code wiki / _hdl_build / nx_oo_extract.nx
nx_oo_extract.nx source
↩ module page · 653 lines · 37236 B
1// nx_oo_extract.nx -- BYTE-PROVEN OO DUP-FUNCTION EXTRACTOR (the real "object-oriented without losing
2// functionality" operation, unblocked by the 2026-07-21 byte-equiv proof). Moves functions that are
3// DUPLICATED byte-identically across N consumers into a shared base lib, repoints each consumer to
4// import it, and COMMITS only if EVERY consumer's rebuild is BYTE-IDENTICAL to before (else REVERTS all).
5// never-brick + rule-13 (originals backed up). Every refusal carries verdict+reason+fix (operator law).
6// argv: <funcname[,funcname...]> <baselib-srcpath> <buildonly-elf> <consumer-srcpath1> [consumer-srcpath2 ...]
7// [--proof=bytes|behave] [--workload=<path>]
8// exit: 0 EXTRACTED | 1 REFUSED(reverted) | 2 usage/precondition | 3 io/build error(reverted)
9//
10// v2 (2026-08-18, the /compare generator dedup): TWO capabilities the single-function v1 could not do.
11// (1) N FUNCTIONS IN ONE PASS. A comma-separated funcname list moves the whole shared set at once with ONE
12// import line and ONE proof cycle. v1 needed N runs and each run left the consumer importing a lib that
13// the NEXT run would rewrite -- and a base lib holding one function is not a base class, it is a shard.
14// (2) BEHAVIOURAL PROOF. `--proof=behave` proves the extraction by the consumer's OUTPUT, not its image:
15// each consumer is run BEFORE and AFTER over every argv line in --workload that names it, and the
16// captured stdout must be byte-identical. Needed because an added `import` line legitimately reorders
17// the compiled image (functions are laid out in source order), so `--proof=bytes` REFUSES a correct
18// extraction; the byte proof stays the default because it is the stronger claim when it holds.
19// Workload format: one line per run, `<consumer-target> <argv1> <argv2> ...`; a consumer with no
20// workload line has NO proof and the run REFUSES (a proof over an empty set is not a proof).
21// A function is extracted only if its body is byte-identical across EVERY consumer; a divergent body is
22// REFUSED by name -- resolve by rename or by making them equal first, never by picking one.
23// license_tier: ORIGINAL No hw writes (Rule 26).
24import "nx_seat_drive_lib.nx"
25import "nx_seg_store.nx"
26import "nx_deploy_lib.nx"
27import "nx_syscalls.nx"
28
29const OE_CAP: i64 = 2097152
30const OE_MAXC: i64 = 128
31const OE_MAXF: i64 = 64 // functions per extraction (argv[1] list); a REFUSED-by-count if exceeded
32const OE_NAME: i64 = 128 // one function-name slot
33const OE_MAXW: i64 = 256 // workload lines
34const OE_WARGV: i64 = 32 // argv tokens per workload line
35const OE_ABSPATH: i64 = 1024 // an absolute path buffer: start-cwd + /buildroot/_build/<target>.sov.elf
36
37func oe_read(path: *u8, buf: *u8, cap: i64) -> i64 {
38 let fd: i64 = sys_openat_rd(path)
39 if fd < 0 { return 0 - 1 }
40 var n: i64 = 0
41 var r: i64 = sys_read(fd, buf, cap - 1)
42 while r > 0 { n = n + r; if n >= cap - 1 { r = 0 } else { r = sys_read(fd, buf + n, cap - 1 - n) } }
43 sys_close(fd)
44 return n
45}
46func oe_isid(c: i64) -> i64 {
47 if c >= 97 { if c <= 122 { return 1 } }
48 if c >= 65 { if c <= 90 { return 1 } }
49 if c >= 48 { if c <= 57 { return 1 } }
50 if c == 95 { return 1 }
51 return 0
52}
53func oe_eq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 { if an != bn { return 0 } var i: i64 = 0; while i < an { if a[i] != b[i] { return 0 } i = i + 1 } return 1 }
54func oe_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
55func oe_starts(s: *u8, p: *u8) -> i64 { var i: i64 = 0; while p[i] != (0 as u8) { if s[i] != p[i] { return 0 } i = i + 1 } return 1 }
56// find func <fname>( at a line start; out[0]=body-start(the 'f'), out[1]=body-end(next func or n); ret 1/0
57func oe_find_func(buf: *u8, n: i64, fname: *u8, out: *i64) -> i64 {
58 var nl: i64 = 0
59 while fname[nl] != (0 as u8) { nl = nl + 1 }
60 var i: i64 = 0
61 var bol: i64 = 1
62 var fstart: i64 = 0 - 1
63 while i < n {
64 if bol == 1 {
65 var m: i64 = 1
66 if i + 5 + nl + 1 > n { m = 0 }
67 if m == 1 { if buf[i] != (102 as u8) { m = 0 } }
68 if m == 1 { if buf[i+1] != (117 as u8) { m = 0 } }
69 if m == 1 { if buf[i+2] != (110 as u8) { m = 0 } }
70 if m == 1 { if buf[i+3] != (99 as u8) { m = 0 } }
71 if m == 1 { if buf[i+4] != (32 as u8) { m = 0 } }
72 if m == 1 {
73 var k: i64 = 0
74 while k < nl { if buf[i+5+k] != fname[k] { m = 0; k = nl } else { k = k + 1 } }
75 }
76 if m == 1 { if buf[i+5+nl] != (40 as u8) { m = 0 } }
77 if m == 1 {
78 if fstart < 0 {
79 fstart = i
80 } else {
81 out[0] = fstart; out[1] = i; return 1
82 }
83 } else {
84 // any OTHER top-level declaration after we found ours ends the range: `func `, `const `,
85 // `struct `, `import ` (2026-08-18: a `const` between two functions was being swallowed
86 // into the earlier body, so two consumers differing only by a const's PLACEMENT read as
87 // divergent functions).
88 var isdecl: i64 = 0
89 if i + 5 <= n { if buf[i] == (102 as u8) { if buf[i+1] == (117 as u8) { if buf[i+2] == (110 as u8) { if buf[i+3] == (99 as u8) { if buf[i+4] == (32 as u8) { isdecl = 1 } } } } } }
90 if i + 6 <= n { if buf[i] == (99 as u8) { if buf[i+1] == (111 as u8) { if buf[i+2] == (110 as u8) { if buf[i+3] == (115 as u8) { if buf[i+4] == (116 as u8) { if buf[i+5] == (32 as u8) { isdecl = 1 } } } } } } }
91 if i + 7 <= n { if buf[i] == (115 as u8) { if buf[i+1] == (116 as u8) { if buf[i+2] == (114 as u8) { if buf[i+3] == (117 as u8) { if buf[i+4] == (99 as u8) { if buf[i+5] == (116 as u8) { if buf[i+6] == (32 as u8) { isdecl = 1 } } } } } } } }
92 if i + 7 <= n { if buf[i] == (105 as u8) { if buf[i+1] == (109 as u8) { if buf[i+2] == (112 as u8) { if buf[i+3] == (111 as u8) { if buf[i+4] == (114 as u8) { if buf[i+5] == (116 as u8) { if buf[i+6] == (32 as u8) { isdecl = 1 } } } } } } } }
93 if isdecl == 1 { if fstart >= 0 { out[0] = fstart; out[1] = i; return 1 } }
94 }
95 }
96 let c: i64 = buf[i] as i64
97 if c == 10 { bol = 1 } else { bol = 0 }
98 i = i + 1
99 }
100 if fstart >= 0 { out[0] = fstart; out[1] = n; return 1 }
101 return 0
102}
103// TRIM TRAILING BLANK LINES from a found body (2026-08-18): the extent above runs to the next `func`
104// line, so it swallows the blank lines BETWEEN functions -- and two consumers that differ only by
105// "one blank line after kv_n" read as DIVERGENT. Blank lines are not part of a function; the move
106// carries the body up to its last non-blank line and the byte-identity test judges the code.
107func oe_trim_body_end(buf: *u8, out: *i64) -> i64 {
108 // Walk back WHOLE LINES: a trailing line that is blank or begins with `//` (after indentation) is
109 // not the function's -- it is whitespace, or the header comment of the NEXT declaration (the estate
110 // documents a function in the lines ABOVE it). Stop at the first trailing line holding code.
111 var e: i64 = out[1]
112 let s: i64 = out[0]
113 var go: i64 = 1
114 while go == 1 {
115 if e <= s { go = 0 } else {
116 // find start of the last line ending at e (buf[e-1] is its last byte, or the '\n' before it)
117 var le: i64 = e
118 if le > s { if buf[le-1] == (10 as u8) { le = le - 1 } }
119 var ls: i64 = le
120 while ls > s { if buf[ls-1] == (10 as u8) { break } ls = ls - 1 }
121 // classify the line buf[ls..le)
122 var i: i64 = ls
123 while i < le { if buf[i] != (32 as u8) { if buf[i] != (9 as u8) { break } } i = i + 1 }
124 var drop: i64 = 0
125 if i >= le { drop = 1 }
126 if drop == 0 { if i + 1 < le { if buf[i] == (47 as u8) { if buf[i+1] == (47 as u8) { drop = 1 } } } }
127 if ls == s { drop = 0 } // never eat the function's own first line
128 if drop == 1 { e = ls } else { go = 0 }
129 }
130 }
131 out[1] = e
132 return e
133}
134func oe_find_func_trim(buf: *u8, n: i64, fname: *u8, out: *i64) -> i64 {
135 let r: i64 = oe_find_func(buf, n, fname, out)
136 if r == 1 { oe_trim_body_end(buf, out) }
137 return r
138}
139// build target (basename of srcpath minus .nx) via buildonly; snapshot buildroot/_build/<target>.sov.elf -> snappath
140func oe_build_snap(buildelf: *u8, target: *u8, snappath: *u8, buf: *u8) -> i64 {
141 let art: *u8 = sys_mmap(512)
142 // buildroot/_build/, NOT /tmp/: nx_sov_build_run has written _build/ (anchoring its own CWD to
143 // buildroot/) since 2026-07-30. Reading /tmp here meant the baseline artifact was NEVER found, so
144 // oe_build_snap returned 0 and every extraction ABORTED with no-baseline-artifact -- the byte-proof
145 // that makes this extractor safe has been inoperative, and it reported the fault as the CONSUMER's
146 // ("does-not-build-standalone") rather than its own.
147 var o: i64 = sd_cat(art, 0, "buildroot/_build/" as *u8)
148 o = sd_cat(art, o, target)
149 o = sd_cat(art, o, ".sov.elf" as *u8)
150 sys_unlinkat(art)
151 let av: *i64 = sys_mmap(16) as *i64
152 av[0] = target as i64
153 dep_run_capture(buildelf, av, 1, "/tmp/oe_build.log" as *u8)
154 let n: i64 = oe_read(art, buf, OE_CAP)
155 if n > 0 {
156 // the builder writes _build/<t>.sov.elf WITHOUT +x on this host, so a behavioural run's execve
157 // failed EACCES -> silent exit 127 -> an empty capture that read as "the consumer emits nothing"
158 // (the estate's inert-artifact landmine, measured 2026-08-19 on this very organ's first behave
159 // run). The extractor owns this baseline artifact's lifecycle, so it makes it runnable itself.
160 nx_chmod(art, MODE_0755)
161 if (snappath as i64) != 0 { ss_writefile(snappath, buf, n) }
162 }
163 return n
164}
165// basename of a path (after last '/') into out; returns len
166func oe_base(path: *u8, out: *u8) -> i64 {
167 var last: i64 = 0 - 1
168 var i: i64 = 0
169 while path[i] != (0 as u8) { if path[i] == (47 as u8) { last = i } i = i + 1 }
170 var o: i64 = 0
171 var j: i64 = last + 1
172 while path[j] != (0 as u8) { out[o] = path[j]; o = o + 1; j = j + 1 }
173 out[o] = 0 as u8
174 return o
175}
176// target = basename minus ".nx"
177func oe_target(path: *u8, out: *u8) -> i64 {
178 let bl: i64 = oe_base(path, out)
179 if bl >= 3 { if out[bl-3] == (46 as u8) { out[bl-3] = 0 as u8; return bl - 3 } }
180 return bl
181}
182// CONSUMER-CONST DEPENDENCY CHECK (2026-08-18, first real run): a moved body that reads a `const` the
183// CONSUMER declares compiles into a lib the parser reads BEFORE that const -- nx_parse: "module const
184// used before its declaration -- it would silently read 0". The extractor must see this in pass 1 and
185// refuse BY NAME, never discover it as a broken build in pass 5. Scans the consumer's `const NAME`
186// declarations and asks whether the body mentions NAME as a whole identifier. Returns 1 + prints the
187// name on the first hit, 0 when clean.
188func oe_body_uses_consumer_const(body: *u8, bn: i64, src: *u8, sn: i64, fname: *u8, cp: *u8) -> i64 {
189 var i: i64 = 0
190 var bol: i64 = 1
191 while i + 6 < sn {
192 if bol == 1 { if src[i] == (99 as u8) { if src[i+1] == (111 as u8) { if src[i+2] == (110 as u8) { if src[i+3] == (115 as u8) { if src[i+4] == (116 as u8) { if src[i+5] == (32 as u8) {
193 // const NAME ... -> NAME = identifier run after "const "
194 var ns: i64 = i + 6
195 var ne: i64 = ns
196 while ne < sn { if oe_isid(src[ne] as i64) == 0 { break } ne = ne + 1 }
197 let nl: i64 = ne - ns
198 if nl > 0 {
199 // whole-identifier search of NAME inside body
200 var j: i64 = 0
201 while j + nl <= bn {
202 var m: i64 = 1
203 var k: i64 = 0
204 while k < nl { if body[j+k] != src[ns+k] { m = 0; k = nl } else { k = k + 1 } }
205 if m == 1 {
206 var lb: i64 = 0
207 if j > 0 { lb = oe_isid(body[j-1] as i64) }
208 var rb: i64 = 0
209 if j + nl < bn { rb = oe_isid(body[j+nl] as i64) }
210 if lb == 0 { if rb == 0 {
211 sd_w("NX-OO-EXTRACT verdict=REFUSED reason=function-" as *u8); sd_w(fname); sd_w("-reads-consumer-const-" as *u8)
212 let nm: *u8 = sys_mmap(nl + 1); var q: i64 = 0; while q < nl { nm[q] = src[ns+q]; q = q + 1 } nm[nl] = 0 as u8
213 sd_w(nm); sd_w("-declared-in:" as *u8); sd_w(cp)
214 sd_w(" fix=a-lib-is-parsed-BEFORE-the-consumer,-so-that-const-would-read-0;-either-move-the-const-into-the-lib-too,-pass-it-as-a-parameter,-or-leave-this-function-out-of-the-list. no-changes-made\n" as *u8)
215 return 1
216 } }
217 }
218 j = j + 1
219 }
220 }
221 } } } } } } }
222 if src[i] == (10 as u8) { bol = 1 } else { bol = 0 }
223 i = i + 1
224 }
225 return 0
226}
227// LIB-IMPORT PLACEMENT (2026-08-18): the import goes AFTER the consumer's leading block of comments,
228// imports and consts -- never at byte 0. Placed first, the lib's bodies were parsed before the
229// consumer's own `import "nx_syscalls.nx"` and every MODE_*/K_MAGIC_* const they read "would silently
230// read 0" (measured). Returns the byte offset of the first line that is none of: blank, //, import, const.
231func oe_import_insert_at(src: *u8, sn: i64) -> i64 {
232 var p: i64 = 0
233 var last_ok: i64 = 0
234 var go: i64 = 1
235 while go == 1 {
236 if p >= sn { go = 0 } else {
237 var e: i64 = p
238 while e < sn { if src[e] == (10 as u8) { break } e = e + 1 }
239 var i: i64 = p
240 while i < e { if src[i] != (32 as u8) { break } i = i + 1 }
241 var ok: i64 = 0
242 if i >= e { ok = 1 }
243 if ok == 0 { if i + 1 < e { if src[i] == (47 as u8) { if src[i+1] == (47 as u8) { ok = 1 } } } }
244 if ok == 0 { if oe_starts(((src as i64) + i) as *u8, "import " as *u8) == 1 { ok = 1 } }
245 if ok == 0 { if oe_starts(((src as i64) + i) as *u8, "const " as *u8) == 1 { ok = 1 } }
246 if ok == 1 { last_ok = e + 1; p = e + 1 } else { go = 0 }
247 }
248 }
249 if last_ok > sn { last_ok = sn }
250 return last_ok
251}
252// split argv[1] "a,b,c" into the names table (OE_NAME stride, NUL-terminated); returns count (0 = empty/overflow)
253func oe_split_names(s: *u8, names: *u8) -> i64 {
254 var cnt: i64 = 0
255 var i: i64 = 0
256 var o: i64 = 0
257 var go: i64 = 1
258 while go == 1 {
259 let c: i64 = s[i] as i64
260 if c == 44 { names[cnt*OE_NAME + o] = 0 as u8; if o > 0 { cnt = cnt + 1 } o = 0; if cnt >= OE_MAXF { return 0 } }
261 else { if c == 0 { names[cnt*OE_NAME + o] = 0 as u8; if o > 0 { cnt = cnt + 1 } go = 0 } else { if o < OE_NAME - 1 { names[cnt*OE_NAME + o] = c as u8; o = o + 1 } } }
262 i = i + 1
263 }
264 return cnt
265}
266// BEHAVIOURAL RUN: execute buildroot/_build/<target>.sov.elf with the workload line's argv, stdout -> outfile.
267// Workload lines: "<target> <a1> <a2> ..." ; only lines whose first token equals target are run; returns runs done.
268// Every run's capture is a separate file (outprefix + index) so a mismatch names the exact argv line.
269// WORKLOAD CWD (2026-08-18, first real run): consumers that read relative data paths (the /compare
270// generators open knowledge/compare/<dom>.matrix from CWD=buildroot) captured EMPTY when forked from the
271// extractor's own CWD -- an empty proof the organ correctly refused. A workload line `@cwd <dir>` sets
272// the directory every FOLLOWING run's child chdirs into before exec; the elf path is made absolute from
273// the extractor's start directory first, so the chdir cannot break the exec.
274func oe_run_in(elf_abs: *u8, av: *i64, na: i64, outfile: *u8, cwd: *u8) -> i64 {
275 let pid: i64 = sys_fork()
276 if pid == 0 {
277 if (cwd as i64) != 0 { if cwd[0] != (0 as u8) { sys_chdir(cwd) } }
278 let fd: i64 = sys_openat_wr(outfile, MODE_0644)
279 if fd >= 0 { sys_dup3(fd, 1, 0); sys_dup3(fd, 2, 0) }
280 let argv: *i64 = sys_mmap(8 * (na + 2)) as *i64
281 let envp: *i64 = sys_mmap(16) as *i64; envp[0] = 0
282 argv[0] = elf_abs as i64
283 var i: i64 = 0
284 while i < na { argv[i+1] = av[i]; i = i + 1 }
285 argv[na+1] = 0
286 sys_execve_clean(elf_abs, argv, envp)
287 sys_exit(127)
288 }
289 let st: *i64 = sys_mmap(16) as *i64
290 sys_wait4(pid, st, 0)
291 return (st[0] >> 8) & 0xff
292}
293func oe_behave(target: *u8, wl: *u8, wn: i64, outprefix: *u8, tokbuf: *u8) -> i64 {
294 let elf: *u8 = sys_mmap(OE_ABSPATH)
295 let here: *u8 = sys_mmap(OE_ABSPATH)
296 sys_getcwd(here, OE_ABSPATH)
297 var eo: i64 = sd_cat(elf, 0, here); eo = sd_cat(elf, eo, "/buildroot/_build/" as *u8); eo = sd_cat(elf, eo, target); eo = sd_cat(elf, eo, ".sov.elf" as *u8)
298 let cwd: *u8 = sys_mmap(512)
299 cwd[0] = 0 as u8
300 let av: *i64 = sys_mmap(8 * OE_WARGV) as *i64
301 let outp: *u8 = sys_mmap(512)
302 var runs: i64 = 0
303 var p: i64 = 0
304 var line: i64 = 0
305 while p < wn {
306 var e: i64 = p
307 while e < wn { if wl[e] == (10 as u8) { break } e = e + 1 }
308 // tokenize wl[p..e) by spaces into tokbuf (NUL-separated), av[] points at each
309 var na: i64 = 0
310 var i: i64 = p
311 var to: i64 = 0
312 while i < e {
313 while i < e { if wl[i] != (32 as u8) { break } i = i + 1 }
314 if i < e {
315 if na < OE_WARGV { av[na] = ((tokbuf as i64) + to) as i64; na = na + 1 }
316 while i < e { if wl[i] == (32 as u8) { break } tokbuf[to] = wl[i]; to = to + 1; i = i + 1 }
317 tokbuf[to] = 0 as u8; to = to + 1
318 }
319 }
320 // `@cwd <dir>` directive: applies to every following run line
321 if na >= 2 { if oe_streq(av[0] as *u8, "@cwd" as *u8) == 1 {
322 var ci: i64 = 0
323 let cd: *u8 = av[1] as *u8
324 while cd[ci] != (0 as u8) { cwd[ci] = cd[ci]; ci = ci + 1 }
325 cwd[ci] = 0 as u8
326 na = 0
327 } }
328 if na >= 1 { if oe_streq(av[0] as *u8, target) == 1 {
329 var oo: i64 = sd_cat(outp, 0, outprefix); oo = sd_cat(outp, oo, "." as *u8); oo = sd_num(outp, oo, line); outp[oo] = 0 as u8
330 // pass argv[1..] to the elf (av[0] is the target name, the elf is argv[0] itself); the
331 // capture path is made absolute too, since the child may chdir before it opens it.
332 // UNBOUNDED BY CONTRACT, NOT BY OVERSIGHT: this tree's nx_deploy_lib twin carries no
333 // deadline runner (dep_run_capture_bounded lives only in runtime/, the two trees have
334 // diverged -- named here, not silently duplicated). A workload line must therefore be a
335 // TERMINATING CLI run (a generator emit, a census, a probe), never a daemon or a serve verb.
336 let rrc: i64 = oe_run_in(elf, ((av as i64) + 8) as *i64, na - 1, outp, cwd)
337 if rrc == 127 {
338 // exec itself failed (inert artifact / wrong path) -- say so, or the empty capture
339 // reads as "the consumer emits nothing" and the wrong subject gets investigated.
340 sd_w("OO-EXEC-FAIL elf=" as *u8); sd_w(elf); sd_w(" (rc=127: not-executable-or-absent; the capture for this line is meaningless)\n" as *u8)
341 }
342 runs = runs + 1
343 } }
344 line = line + 1
345 p = e + 1
346 }
347 return runs
348}
349// VOLATILE-FIELD MASK (2026-08-19, first run on the /compare generators): their json carries
350// `"generated_unix":<epoch>` -- two byte-equal captures taken seconds apart differ ONLY there, so a
351// perfect extraction read as OO-CHANGED. Which fields are volatile is a property of the CONSUMER, so it
352// is DATA: a workload line `@volatile <token>` masks every digit-run following `"<token>":` in BOTH
353// captures before the compare (digits -> '0'; nothing else touched, so any other drift still fails).
354func oe_mask_volatile(b: *u8, n: i64, tok: *u8) -> i64 {
355 var tl: i64 = 0
356 while tok[tl] != (0 as u8) { tl = tl + 1 }
357 if tl == 0 { return 0 }
358 var i: i64 = 0
359 while i + tl < n {
360 var m: i64 = 1
361 var k: i64 = 0
362 while k < tl { if b[i+k] != tok[k] { m = 0; k = tl } else { k = k + 1 } }
363 if m == 1 {
364 var j: i64 = i + tl
365 while j < n { let c: i64 = b[j] as i64; if c == 34 { j = j + 1 } else { if c == 58 { j = j + 1 } else { if c == 32 { j = j + 1 } else { break } } } }
366 while j < n { let d: i64 = b[j] as i64; if d >= 48 { if d <= 57 { b[j] = 48 as u8; j = j + 1 } else { break } } else { break } }
367 i = j
368 } else { i = i + 1 }
369 }
370 return 0
371}
372// compare every "<prefix>.<i>" capture pair (before vs after) for lines naming target; returns mismatches
373func oe_behave_cmp(target: *u8, wl: *u8, wn: i64, prefa: *u8, prefb: *u8, ba: *u8, bb: *u8) -> i64 {
374 let pa: *u8 = sys_mmap(512)
375 let pb: *u8 = sys_mmap(512)
376 var bad: i64 = 0
377 var p: i64 = 0
378 var line: i64 = 0
379 while p < wn {
380 var e: i64 = p
381 while e < wn { if wl[e] == (10 as u8) { break } e = e + 1 }
382 // first token
383 var i: i64 = p
384 while i < e { if wl[i] != (32 as u8) { break } i = i + 1 }
385 var j: i64 = i
386 while j < e { if wl[j] == (32 as u8) { break } j = j + 1 }
387 var same: i64 = 1
388 var k: i64 = 0
389 while i + k < j { if target[k] == (0 as u8) { same = 0; k = j } else { if wl[i+k] != target[k] { same = 0; k = j } else { k = k + 1 } } }
390 if same == 1 { if target[k] != (0 as u8) { same = 0 } }
391 if same == 1 { if j > i {
392 var oa: i64 = sd_cat(pa, 0, prefa); oa = sd_cat(pa, oa, "." as *u8); oa = sd_num(pa, oa, line); pa[oa] = 0 as u8
393 var ob: i64 = sd_cat(pb, 0, prefb); ob = sd_cat(pb, ob, "." as *u8); ob = sd_num(pb, ob, line); pb[ob] = 0 as u8
394 let na: i64 = oe_read(pa, ba, OE_CAP)
395 let nb: i64 = oe_read(pb, bb, OE_CAP)
396 // apply every @volatile mask declared in the workload to BOTH captures
397 var vp: i64 = 0
398 while vp < wn {
399 var ve: i64 = vp
400 while ve < wn { if wl[ve] == (10 as u8) { break } ve = ve + 1 }
401 if oe_starts(((wl as i64) + vp) as *u8, "@volatile " as *u8) == 1 {
402 let tk: *u8 = sys_mmap(128)
403 var to3: i64 = 0
404 var vs: i64 = vp + 10
405 while vs < ve { if wl[vs] == (32 as u8) { break } if to3 < 127 { tk[to3] = wl[vs]; to3 = to3 + 1 } vs = vs + 1 }
406 tk[to3] = 0 as u8
407 if na > 0 { oe_mask_volatile(ba, na, tk) }
408 if nb > 0 { oe_mask_volatile(bb, nb, tk) }
409 }
410 vp = ve + 1
411 }
412 if na <= 0 { bad = bad + 1; sd_w("OO-BEHAVE-EMPTY(before) " as *u8); sd_w(target); sd_w(" line=" as *u8); let t0: *u8 = sys_mmap(32); sd_num(t0, 0, line); sd_w(t0); sd_w("\n" as *u8) }
413 else { if oe_eq(ba, na, bb, nb) == 0 { bad = bad + 1; sd_w("OO-CHANGED(output) " as *u8); sd_w(target); sd_w(" line=" as *u8); let t1: *u8 = sys_mmap(32); sd_num(t1, 0, line); sd_w(t1); sd_w(" before=" as *u8); let t2: *u8 = sys_mmap(32); sd_num(t2, 0, na); sd_w(t2); sd_w("B after=" as *u8); let t3: *u8 = sys_mmap(32); sd_num(t3, 0, nb); sd_w(t3); sd_w("B\n" as *u8) } }
414 } }
415 line = line + 1
416 p = e + 1
417 }
418 return bad
419}
420
421func main(argc: i64, argv: *i64) -> i64 {
422 if argc < 5 { sd_w("usage: nx_oo_extract <funcname[,f2,...]> <baselib-srcpath> <buildonly-elf> <consumer-src...> [--proof=bytes|behave] [--workload=<path>]\n" as *u8); sys_exit(2); return 2 }
423 let basepath: *u8 = argv[2] as *u8
424 let buildelf: *u8 = argv[3] as *u8
425 // options are trailing "--" args; consumers are everything between argv[4] and the first option
426 var proof_behave: i64 = 0
427 var wlpath: *u8 = 0 as *u8
428 var nc: i64 = 0
429 var ai: i64 = 4
430 while ai < argc {
431 let a: *u8 = argv[ai] as *u8
432 if oe_starts(a, "--proof=" as *u8) == 1 {
433 if oe_streq(((a as i64) + 8) as *u8, "behave" as *u8) == 1 { proof_behave = 1 }
434 else { if oe_streq(((a as i64) + 8) as *u8, "bytes" as *u8) == 0 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=unknown-proof-mode fix=--proof=bytes|behave\n" as *u8); sys_exit(2); return 2 } }
435 } else { if oe_starts(a, "--workload=" as *u8) == 1 { wlpath = ((a as i64) + 11) as *u8 }
436 else { if oe_starts(a, "--" as *u8) == 1 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=unknown-option:" as *u8); sd_w(a); sd_w(" fix=see-usage\n" as *u8); sys_exit(2); return 2 }
437 else { nc = nc + 1 } } }
438 ai = ai + 1
439 }
440 if nc < 1 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=no-consumers fix=pass-at-least-one-consumer-src\n" as *u8); sys_exit(2); return 2 }
441 if nc > OE_MAXC { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=too-many-consumers fix=split-the-run\n" as *u8); sys_exit(2); return 2 }
442 let names: *u8 = sys_mmap(OE_MAXF * OE_NAME)
443 let nf: i64 = oe_split_names(argv[1] as *u8, names)
444 if nf < 1 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=funcname-list-empty-or-over-limit fix=comma-separated,-at-most-64\n" as *u8); sys_exit(2); return 2 }
445 if proof_behave == 1 { if (wlpath as i64) == 0 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=proof=behave-needs---workload fix=pass---workload=<path>-with-one-'<target> <argv...>'-line-per-run\n" as *u8); sys_exit(2); return 2 } }
446 let basebn: *u8 = sys_mmap(256)
447 oe_base(basepath, basebn)
448
449 let cbuf: *u8 = sys_mmap(OE_CAP)
450 let rng: *i64 = sys_mmap(16) as *i64
451 // PASS 1: every function must exist in every consumer with a byte-identical body. bodies[] holds the
452 // reference copy of each (from consumer 0) for the lib; bl[] their lengths.
453 let bodies: *u8 = sys_mmap(OE_CAP)
454 let boff: *i64 = sys_mmap(8 * OE_MAXF) as *i64
455 let blen: *i64 = sys_mmap(8 * OE_MAXF) as *i64
456 var bused: i64 = 0
457 var fi: i64 = 0
458 while fi < nf {
459 let fname: *u8 = ((names as i64) + fi*OE_NAME) as *u8
460 var ci: i64 = 0
461 var first: i64 = 1
462 while ci < nc {
463 let cp: *u8 = argv[4 + ci] as *u8
464 let cn: i64 = oe_read(cp, cbuf, OE_CAP)
465 if cn <= 0 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=consumer-unreadable:" as *u8); sd_w(cp); sd_w(" fix=verify-the-consumer-source-path\n" as *u8); sys_exit(2); return 2 }
466 if oe_find_func_trim(cbuf, cn, fname, rng) != 1 {
467 sd_w("NX-OO-EXTRACT verdict=ABORTED reason=function-" as *u8); sd_w(fname); sd_w("-not-defined-in:" as *u8); sd_w(cp)
468 sd_w(" fix=only-pass-consumers-that-DEFINE-every-listed-function(check-funcmine-output)\n" as *u8); sys_exit(2); return 2
469 }
470 let bs: i64 = rng[0]
471 let be: i64 = rng[1]
472 if oe_body_uses_consumer_const(((cbuf as i64) + bs) as *u8, be - bs, cbuf, cn, fname, cp) == 1 { sys_exit(1); return 1 }
473 if first == 1 {
474 boff[fi] = bused; blen[fi] = be - bs
475 var t: i64 = 0
476 while t < be - bs { bodies[bused + t] = cbuf[bs + t]; t = t + 1 }
477 bused = bused + (be - bs)
478 first = 0
479 } else {
480 if oe_eq(((cbuf as i64) + bs) as *u8, be - bs, ((bodies as i64) + boff[fi]) as *u8, blen[fi]) == 0 {
481 sd_w("NX-OO-EXTRACT verdict=REFUSED reason=the-" as *u8); sd_w(fname); sd_w("-bodies-are-NOT-byte-identical-across-consumers(differs-in:" as *u8); sd_w(cp); sd_w(")" as *u8)
482 sd_w(" fix=only-byte-identical-duplicates-can-be-safely-extracted;-if-they-differ-they-are-DIVERGENT-resolve-by-rename-or-make-equal-first,-never-by-picking-one. no-changes-made\n" as *u8)
483 sys_exit(1); return 1
484 }
485 }
486 ci = ci + 1
487 }
488 fi = fi + 1
489 }
490
491 // PASS 2: baseline every consumer (build snapshot; behavioural captures if asked) + backup its source
492 let tgt: *u8 = sys_mmap(256)
493 let snap: *u8 = sys_mmap(512)
494 let bak: *u8 = sys_mmap(512)
495 let wl: *u8 = sys_mmap(OE_CAP)
496 var wn: i64 = 0
497 if proof_behave == 1 {
498 wn = oe_read(wlpath, wl, OE_CAP)
499 if wn <= 0 { sd_w("NX-OO-EXTRACT verdict=ABORTED reason=workload-unreadable-or-empty:" as *u8); sd_w(wlpath); sd_w(" fix=one-'<target> <argv...>'-line-per-run\n" as *u8); sys_exit(2); return 2 }
500 }
501 let tokbuf: *u8 = sys_mmap(OE_CAP)
502 let pref: *u8 = sys_mmap(512)
503 var ci: i64 = 0
504 while ci < nc {
505 let cp: *u8 = argv[4 + ci] as *u8
506 oe_target(cp, tgt)
507 var so: i64 = sd_cat(snap, 0, "/tmp/oo_" as *u8); so = sd_cat(snap, so, tgt); so = sd_cat(snap, so, ".before" as *u8)
508 let bn: i64 = oe_build_snap(buildelf, tgt, snap, cbuf)
509 if bn <= 0 {
510 // NAME THE RIGHT SUBJECT (2026-08-18, first real run): a missing baseline artifact was reported
511 // as "consumer does not build standalone" when the builder had REFUSED ADMISSION under an I/O
512 // storm (procs_blocked>=blocked_max) -- the box, not the consumer. Read the builder's own log
513 // for its admission verdict and say which it was.
514 let lg: *u8 = sys_mmap(OE_CAP)
515 let ln: i64 = oe_read("/tmp/oe_build.log" as *u8, lg, OE_CAP)
516 var admit_refused: i64 = 0
517 if ln > 0 { if dp_contains(lg, ln, "REFUSED-BUILD-ADMIT" as *u8) == 1 { admit_refused = 1 } }
518 if admit_refused == 1 {
519 sd_w("NX-OO-EXTRACT verdict=ABORTED reason=builder-REFUSED-ADMISSION-under-load(box-saturated,-not-the-consumer:" as *u8); sd_w(tgt); sd_w(")" as *u8)
520 sd_w(" fix=re-issue-when-/proc/loadavg-clears;-nothing-was-changed. no-changes-made\n" as *u8)
521 } else {
522 sd_w("NX-OO-EXTRACT verdict=ABORTED reason=consumer-" as *u8); sd_w(tgt); sd_w("-does-not-build-standalone(no-baseline-artifact)" as *u8)
523 sd_w(" fix=byte-proof-needs-a-buildable-holder;-see-/tmp/oe_build.log. no-changes-made\n" as *u8)
524 }
525 sys_exit(3); return 3
526 }
527 if proof_behave == 1 {
528 var po: i64 = sd_cat(pref, 0, "/tmp/oo_" as *u8); po = sd_cat(pref, po, tgt); po = sd_cat(pref, po, ".before" as *u8); pref[po] = 0 as u8
529 let runs: i64 = oe_behave(tgt, wl, wn, pref, tokbuf)
530 if runs == 0 {
531 sd_w("NX-OO-EXTRACT verdict=ABORTED reason=consumer-" as *u8); sd_w(tgt); sd_w("-has-NO-workload-line(a-proof-over-the-empty-set-is-not-a-proof)" as *u8)
532 sd_w(" fix=add-'<target> <argv...>'-lines-to-the-workload-for-every-consumer. no-changes-made\n" as *u8)
533 sys_exit(2); return 2
534 }
535 sd_w("OO-BASELINE " as *u8); sd_w(tgt); sd_w(" runs=" as *u8); let rb: *u8 = sys_mmap(32); sd_num(rb, 0, runs); sd_w(rb); sd_w("\n" as *u8)
536 }
537 let cn: i64 = oe_read(cp, cbuf, OE_CAP)
538 var bo: i64 = sd_cat(bak, 0, cp); bo = sd_cat(bak, bo, ".oobak" as *u8)
539 ss_writefile(bak, cbuf, cn)
540 ci = ci + 1
541 }
542
543 // PASS 3: write the base lib (header + every extracted body, in list order)
544 let lib: *u8 = sys_mmap(OE_CAP)
545 var lo: i64 = sd_cat(lib, 0, "// AUTO-EXTRACTED shared base (nx_oo_extract). license_tier: ORIGINAL No hw writes (Rule 26).\n" as *u8)
546 lo = sd_cat(lib, lo, "// functions: " as *u8); lo = sd_cat(lib, lo, argv[1] as *u8); lo = sd_cat(lib, lo, "\n" as *u8)
547 // the lib declares its own foundation import so it reads standalone; the flattener dedups repeats
548 lo = sd_cat(lib, lo, "import \"nx_syscalls.nx\"\n" as *u8)
549 fi = 0
550 while fi < nf {
551 var t2: i64 = 0
552 while t2 < blen[fi] { lib[lo] = bodies[boff[fi] + t2]; lo = lo + 1; t2 = t2 + 1 }
553 if lo > 0 { if lib[lo-1] != (10 as u8) { lib[lo] = 10 as u8; lo = lo + 1 } }
554 fi = fi + 1
555 }
556 ss_writefile(basepath, lib, lo)
557
558 // PASS 4: edit each consumer (prepend ONE import, remove EVERY listed func def)
559 let nfb: *u8 = sys_mmap(OE_CAP)
560 ci = 0
561 while ci < nc {
562 let cp: *u8 = argv[4 + ci] as *u8
563 var cn: i64 = oe_read(cp, cbuf, OE_CAP)
564 fi = 0
565 while fi < nf {
566 let fname: *u8 = ((names as i64) + fi*OE_NAME) as *u8
567 oe_find_func_trim(cbuf, cn, fname, rng)
568 let bs: i64 = rng[0]
569 let be: i64 = rng[1]
570 var no: i64 = 0
571 var t3: i64 = 0
572 while t3 < bs { nfb[no] = cbuf[t3]; no = no + 1; t3 = t3 + 1 }
573 t3 = be
574 while t3 < cn { nfb[no] = cbuf[t3]; no = no + 1; t3 = t3 + 1 }
575 // swap: cbuf <- nfb
576 var t4: i64 = 0
577 while t4 < no { cbuf[t4] = nfb[t4]; t4 = t4 + 1 }
578 cn = no
579 fi = fi + 1
580 }
581 // insert the ONE lib import after the consumer's leading comment/import/const block (see oe_import_insert_at)
582 let at: i64 = oe_import_insert_at(cbuf, cn)
583 var no2: i64 = 0
584 var t5: i64 = 0
585 while t5 < at { nfb[no2] = cbuf[t5]; no2 = no2 + 1; t5 = t5 + 1 }
586 no2 = sd_cat(nfb, no2, "import \"" as *u8); no2 = sd_cat(nfb, no2, basebn); no2 = sd_cat(nfb, no2, "\"\n" as *u8)
587 while t5 < cn { nfb[no2] = cbuf[t5]; no2 = no2 + 1; t5 = t5 + 1 }
588 ss_writefile(cp, nfb, no2)
589 ci = ci + 1
590 }
591
592 // PASS 5: rebuild each consumer and prove (bytes, or behaviour over the workload)
593 var changed: i64 = 0
594 let bufb: *u8 = sys_mmap(OE_CAP)
595 let prefb: *u8 = sys_mmap(512)
596 ci = 0
597 while ci < nc {
598 let cp: *u8 = argv[4 + ci] as *u8
599 oe_target(cp, tgt)
600 var so: i64 = sd_cat(snap, 0, "/tmp/oo_" as *u8); so = sd_cat(snap, so, tgt); so = sd_cat(snap, so, ".before" as *u8)
601 let an: i64 = oe_build_snap(buildelf, tgt, 0 as *u8, cbuf)
602 if an <= 0 {
603 changed = changed + 1
604 // same attribution as the pass-2 abort (a fix in one path and not its sibling is half a fix):
605 // an admission-refused rebuild is the BOX, not the change -- it still counts as unverifiable
606 // (so the revert below is correct), but the message must not indict the extraction.
607 let lg2: *u8 = sys_mmap(OE_CAP)
608 let ln2: i64 = oe_read("/tmp/oe_build.log" as *u8, lg2, OE_CAP)
609 var adm2: i64 = 0
610 if ln2 > 0 { if dp_contains(lg2, ln2, "REFUSED-BUILD-ADMIT" as *u8) == 1 { adm2 = 1 } }
611 if adm2 == 1 { sd_w("OO-BUILD-ADMIT-REFUSED(box-saturated,-unverifiable-this-run) " as *u8); sd_w(tgt); sd_w(" fix=re-issue-when-load-clears\n" as *u8) }
612 else { sd_w("OO-CHANGED(build-broke) " as *u8); sd_w(tgt); sd_w(" see=/tmp/oe_build.log\n" as *u8) }
613 } else {
614 if proof_behave == 0 {
615 let sn: i64 = oe_read(snap, bufb, OE_CAP)
616 if oe_eq(cbuf, an, bufb, sn) == 0 { changed = changed + 1; sd_w("OO-CHANGED(bytes) " as *u8); sd_w(tgt); sd_w("\n" as *u8) }
617 } else {
618 var po: i64 = sd_cat(pref, 0, "/tmp/oo_" as *u8); po = sd_cat(pref, po, tgt); po = sd_cat(pref, po, ".before" as *u8); pref[po] = 0 as u8
619 var pb: i64 = sd_cat(prefb, 0, "/tmp/oo_" as *u8); pb = sd_cat(prefb, pb, tgt); pb = sd_cat(prefb, pb, ".after" as *u8); prefb[pb] = 0 as u8
620 oe_behave(tgt, wl, wn, prefb, tokbuf)
621 let bad: i64 = oe_behave_cmp(tgt, wl, wn, pref, prefb, cbuf, bufb)
622 if bad > 0 { changed = changed + 1 }
623 }
624 }
625 ci = ci + 1
626 }
627
628 if changed == 0 {
629 sd_w("NX-OO-EXTRACT verdict=EXTRACTED reason=" as *u8); sd_w(argv[1] as *u8)
630 sd_w("-moved-to-" as *u8); sd_w(basebn)
631 sd_w("-and-all-" as *u8)
632 let ob: *u8 = sys_mmap(32); sd_num(ob, 0, nc); sd_w(ob)
633 if proof_behave == 0 { sd_w("-consumers-rebuilt-BYTE-IDENTICAL(behaviour-preserved)" as *u8) }
634 else { sd_w("-consumers-rebuilt-and-every-workload-run-OUTPUT-IDENTICAL(behaviour-preserved-over-the-declared-workload)" as *u8) }
635 sd_w(" fix=none-committed;-remove-the-.oobak-backups-when-satisfied\n" as *u8)
636 sys_exit(0); return 0
637 }
638 // any consumer changed -> REVERT everything
639 ci = 0
640 while ci < nc {
641 let cp: *u8 = argv[4 + ci] as *u8
642 var bo: i64 = sd_cat(bak, 0, cp); bo = sd_cat(bak, bo, ".oobak" as *u8)
643 let cn: i64 = oe_read(bak, cbuf, OE_CAP)
644 if cn > 0 { ss_writefile(cp, cbuf, cn) }
645 ci = ci + 1
646 }
647 sys_unlinkat(basepath)
648 sd_w("NX-OO-EXTRACT verdict=REFUSED reason=" as *u8)
649 let ob2: *u8 = sys_mmap(32); sd_num(ob2, 0, changed); sd_w(ob2)
650 sd_w("-consumer(s)-changed-after-extraction(behaviour-NOT-preserved) fix=extraction-not-safe-here-see-OO-CHANGED-lines;-all-consumers-RESTORED-from-.oobak-and-the-base-lib-removed(safe)\n" as *u8)
651 sys_exit(1)
652 return 1
653}