code wiki / _hdl_build / nx_oo_extract_gate.nx
nx_oo_extract_gate.nx source
↩ module page · 293 lines · 18030 B
1// nx_oo_extract_gate.nx -- GATE for the byte-proven OO extractor (5 teeth, REAL builds via nx_buildonly).
2// PREREQ: stage _offc/nx_oo_extract.elf + _offc/nx_buildonly.elf. Fixtures go to buildroot/runtime/_hdl_build/ -- NOT runtime/_hdl_build/, which only exists when CWD is the nxc2 source root; /api/gate_run runs from the SERVING root where no runtime/ tree exists, so ss_writefile wrote nothing, the extractor found no consumer, and T1 reported ABORTED(consumer-ooc1-does-not-build-standalone) -- the gate accusing the EXTRACTOR of its own fixture bug. One extractor fork
3// per tooth (self-exec chain). Fixtures written into runtime/_hdl_build/ (so bare-name build resolves
4// them), cleaned up each tooth.
5// T1 identical oohelp across 2 consumers -> EXTRACTED, base created, consumers import it + no longer
6// define it, each rebuilt BYTE-IDENTICAL | T2 NEG different bodies -> REFUSED + consumers UNCHANGED |
7// T3 the REFUSED carries reason= AND fix= (feedback law) | T4 NEG function-not-defined -> ABORTED |
8// T5 EXTRACTED carries reason= AND fix=.
9// license_tier: ORIGINAL No hw writes (Rule 26).
10import "nx_seat_drive_lib.nx"
11import "nx_seg_store.nx"
12import "nx_deploy_lib.nx"
13import "nx_syscalls.nx"
14import "nx_gate_verdict.nx"
15
16func og_atoi(s: *u8) -> i64 { var v: i64 = 0; var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } return v }
17func og_itoa(dst: *u8, v: i64) -> i64 { var m: i64 = v; let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } var i: i64 = 0; while i < k { dst[i] = t[k - 1 - i]; i = i + 1 } dst[k] = 0 as u8; return k }
18func og_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
19// PRINT THE VALUES, NOT JUST PASS/FAIL -- a gate that reports a boolean cannot say why.
20// Negatives are printed with their sign: og_itoa's loop is `while m > 0`, so a bare -1 would emit
21// NOTHING and read as a blank field rather than a failure, and one nonsense number in a report
22// discredits every honest number standing beside it.
23func og_wnum(v: i64) -> i64 {
24 let b: *u8 = sys_mmap(32)
25 if v < 0 { sd_w("-" as *u8); let n2: i64 = og_itoa(b, 0 - v); sys_write(1, b, n2); return 0 }
26 let n: i64 = og_itoa(b, v)
27 sys_write(1, b, n)
28 return 0
29}
30// COMPOSE THE READER; DO NOT HAND-ROLL ONE BESIDE IT. This was a private og_read doing a SINGLE
31// sys_read into a 65536 buffer -- the same guessed ceiling written twice on one line. Two ways to be
32// wrong: a single read is permitted to return short even when the file is smaller than the cap, and
33// any file over 64 KiB was truncated outright. Either way sd_count would report a literal ABSENT from
34// a file that contains it, and this gate's teeth are built entirely on og_has answering that question
35// -- a false ABSENT here reads as a defect in nx_oo_extract, which is the accusation this gate has
36// already been wrong about once today.
37// sys_read_file (nx_syscalls) sizes its buffer from the file via lseek END and cannot short-read, so
38// there is no ceiling left to guess and og_read has nothing left to do.
39func og_has(p: *u8, lit: *u8) -> i64 {
40 let ln: *i64 = sys_mmap(16) as *i64
41 let b: *u8 = sys_read_file(p, ln)
42 if (b as i64) == 0 { return 0 }
43 let n: i64 = ln[0]
44 if n <= 0 { return 0 }
45 return sd_count(b, n, lit)
46}
47
48// EXCLUSIVE RUN. Every fixture path in this gate is FIXED in the shared source tree, because a
49// bare-name build has to resolve them, and /tmp/oo_t*.out are fixed too. MEASURED 2026-08-15: two
50// concurrent instances make the extractor read the OTHER tooth's fixture and correctly REFUSE
51// ("the-oohelp-bodies-are-NOT-byte-identical") or ABORT ("consumer-ooc2-does-not-build-standalone").
52// Those are TRUE verdicts about FALSE inputs, and this gate was turning them into an accusation
53// against nx_oo_extract, which has no such defect. A gate that cannot guarantee its own inputs must
54// abstain, not convict.
55// O_EXCL create is the estate's proven atomic claim (the g_uniq idiom, nx_research_journal_gate:92).
56// getpid is deliberately NOT used for this: it has no working const __syscall form on this backend --
57// nx_getpid_const_probe witnessed const_fn=-25 next to var_fn=<pid> in the SAME binary, so a
58// pid-stamped name would silently collapse to one shared name and reintroduce the very collision.
59const OG_LOCK: *u8 = "/tmp/nx_oo_extract_gate.lock" as *u8
60func og_lock_acquire() -> i64 {
61 let fd: i64 = __syscall(SYS_OPENAT, AT_FDCWD, OG_LOCK, 0xc1, 0x1a4, 0, 0) // O_CREAT|O_EXCL|O_WRONLY
62 if fd < 0 { return 0 }
63 // A LOCK THAT CANNOT SAY WHEN IT WAS TAKEN CANNOT BE JUDGED STALE -- it is just an opaque refusal.
64 // Stamped with the acquiring microsecond so a reader can tell a live holder from a corpse.
65 let b: *u8 = sys_mmap(64)
66 let n: i64 = og_itoa(b, sys_now_us())
67 sys_write(fd, b, n)
68 sys_close(fd)
69 return 1
70}
71func og_lock_release() -> i64 { return sys_unlinkat(OG_LOCK) }
72
73// A GUARD WHOSE RECOVERY INSTRUCTION CANNOT BE EXECUTED WITH THE ESTATE'S OWN TOOLS IS A GUARD THAT
74// EVENTUALLY BRICKS ITSELF. The first cut of this lock told the reader to "remove the lock file" -- and
75// there is no sovereign delete for a /tmp path, so the only route was the shell this estate forbids.
76// Measured within the hour: a leaked lock made a clean run report SKIP with no way to clear it.
77// So the release is a VERB. The full token is compared, not its first byte: a flag that accepts any
78// spelling cannot report a typo, and silently running the wrong mode is worse than refusing.
79func og_streq(a: *u8, b: *u8) -> i64 {
80 var i: i64 = 0
81 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
82 if b[i] != (0 as u8) { return 0 }
83 return 1
84}
85
86func og_clean() -> i64 {
87 sys_unlinkat("buildroot/runtime/_hdl_build/ooc1.nx" as *u8)
88 sys_unlinkat("buildroot/runtime/_hdl_build/ooc2.nx" as *u8)
89 sys_unlinkat("buildroot/runtime/_hdl_build/oobase.nx" as *u8)
90 sys_unlinkat("buildroot/runtime/_hdl_build/ooc1.nx.oobak" as *u8)
91 sys_unlinkat("buildroot/runtime/_hdl_build/ooc2.nx.oobak" as *u8)
92 return 0
93}
94// run: nx_oo_extract oohelp runtime/_hdl_build/oobase.nx _offc/nx_buildonly.elf <c1> [c2]
95func og_run(c2: i64, outp: *u8) -> i64 {
96 let av: *i64 = sys_mmap(64) as *i64
97 av[0] = "oohelp" as *u8 as i64
98 av[1] = "buildroot/runtime/_hdl_build/oobase.nx" as *u8 as i64
99 av[2] = "_offc/nx_buildonly.elf" as *u8 as i64
100 av[3] = "buildroot/runtime/_hdl_build/ooc1.nx" as *u8 as i64
101 var nn: i64 = 4
102 if c2 == 1 { av[4] = "buildroot/runtime/_hdl_build/ooc2.nx" as *u8 as i64; nn = 5 }
103 return dep_run_capture("_offc/nx_oo_extract.elf" as *u8, av, nn, outp)
104}
105
106func main(argc: i64, argv: *i64) -> i64 {
107 var stage: i64 = 1
108 var pass: i64 = 0
109 // The unlock verb is answered BEFORE stage parsing, because og_atoi("unlock") is 0 and a
110 // non-numeric argument would otherwise be silently read as "stage 0" and clamped to 1 -- running a
111 // full gate when the caller asked to release a lock.
112 if argc >= 2 {
113 if og_streq(argv[1] as *u8, "unlock" as *u8) == 1 {
114 let rcU: i64 = og_lock_release()
115 sd_w("NX-OO-EXTRACT-GATE unlock rc=" as *u8); og_wnum(rcU)
116 sd_w(" -- 0 means a lock was held and is now free; negative means there was none to release.\n" as *u8)
117 sd_w(" Use this only when no instance is running: it does not ask the holder's permission.\n" as *u8)
118 sys_exit(0)
119 return 0
120 }
121 }
122 if argc >= 2 { let ss1: *u8 = argv[1] as *u8; stage = og_atoi(ss1) }
123 if argc >= 3 { let ps: *u8 = argv[2] as *u8; pass = og_atoi(ps) }
124 if stage < 1 { stage = 1 }
125
126 // PRECONDITION (gv_need, 2026-08-11): the teeth fork _offc/nx_oo_extract.elf via _offc/nx_buildonly.elf.
127 // Absent prereqs made every tooth FAIL and the gate report RED about artifacts, not the extractor.
128 if stage == 1 {
129 let pre1: i64 = sys_openat_rd("_offc/nx_oo_extract.elf" as *u8)
130 let pre2: i64 = sys_openat_rd("_offc/nx_buildonly.elf" as *u8)
131 var have: i64 = 1
132 if pre1 < 0 { have = 0 } else { sys_close(pre1) }
133 if pre2 < 0 { have = 0 } else { sys_close(pre2) }
134 if have == 0 {
135 let ctr0: *i64 = gv_ctr()
136 gv_need("_offc/nx_oo_extract.elf + _offc/nx_buildonly.elf staged" as *u8, 0, ctr0)
137 let rc0: i64 = gv_verdict("OO-EXTRACT-GATE" as *u8, ctr0, "byte-proven OO extractor teeth" as *u8)
138 sys_exit(rc0)
139 return rc0
140 }
141 // Claimed ONCE, by stage 1 only, and released by stage 5 -- the teeth self-exec into fresh
142 // processes, so the claim has to outlive the process that made it. unlinkat releases a FILE
143 // regardless of which process created it, which is exactly why the lock is a file and not a
144 // directory (there is no rmdir wrapper in this tree).
145 if og_lock_acquire() == 0 {
146 let ctrL: *i64 = gv_ctr()
147 gv_need("an exclusive run -- another nx_oo_extract_gate instance holds /tmp/nx_oo_extract_gate.lock" as *u8, 0, ctrL)
148 sd_w(" Concurrent instances share these fixtures, so their verdicts describe each other's inputs, not the extractor.\n" as *u8)
149 sd_w(" If NO instance is running, a previous run died holding it: remove /tmp/nx_oo_extract_gate.lock and re-run.\n" as *u8)
150 let rcL: i64 = gv_verdict("OO-EXTRACT-GATE" as *u8, ctrL, "byte-proven OO extractor teeth" as *u8)
151 sys_exit(rcL)
152 return rcL
153 }
154 }
155
156 if stage == 1 {
157 og_clean()
158 let c1: *u8 = "func oohelp(x: i64) -> i64 { return x + 1 }\nfunc main() -> i64 { return oohelp(41) }\n" as *u8
159 ss_writefile("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, c1, og_len(c1))
160 let c2: *u8 = "func oohelp(x: i64) -> i64 { return x + 1 }\nfunc main() -> i64 { return oohelp(7) }\n" as *u8
161 ss_writefile("buildroot/runtime/_hdl_build/ooc2.nx" as *u8, c2, og_len(c2))
162 let rc: i64 = og_run(1, "/tmp/oo_t1.out" as *u8)
163 let out: *u8 = sys_mmap(16384)
164 let n: i64 = dp_read("/tmp/oo_t1.out" as *u8, out, 16384)
165 // DECOMPOSED 2026-08-15. This was four nested conditions collapsing into a single boolean, so
166 // a T1 FAIL could mean any of five unrelated defects: the extractor never ran, it ran and
167 // refused, it refused to write the base, it wrote the base but never rewrote the consumer's
168 // import, or it rewrote the import and left the old definition behind. A compound assertion
169 // that will not name its failing conjunct makes every reader guess, and they guess the
170 // alarming one. Each conjunct is now measured into its own named value and printed.
171 let a_rc: i64 = rc
172 let a_extracted: i64 = sd_count(out, n, "verdict=EXTRACTED" as *u8)
173 let a_base_defines: i64 = og_has("buildroot/runtime/_hdl_build/oobase.nx" as *u8, "func oohelp" as *u8)
174 let a_consumer_imports: i64 = og_has("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, "import \"oobase.nx\"" as *u8)
175 let a_consumer_still_defines: i64 = og_has("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, "func oohelp" as *u8)
176 sd_w(" T1 conjuncts: rc=" as *u8); og_wnum(a_rc)
177 sd_w(" extracted=" as *u8); og_wnum(a_extracted)
178 sd_w(" base_defines=" as *u8); og_wnum(a_base_defines)
179 sd_w(" consumer_imports=" as *u8); og_wnum(a_consumer_imports)
180 sd_w(" consumer_still_defines=" as *u8); og_wnum(a_consumer_still_defines)
181 sd_w(" (want rc=0 extracted=1 base_defines>=1 consumer_imports>=1 consumer_still_defines=0)\n" as *u8)
182 var ok: i64 = 0
183 if a_rc == 0 { if a_extracted == 1 {
184 if a_base_defines >= 1 {
185 if a_consumer_imports >= 1 {
186 if a_consumer_still_defines == 0 { ok = 1 }
187 }
188 }
189 } }
190 // CONCURRENCY, MEASURED 2026-08-15 -- AND MY FIRST EXPLANATION OF IT WAS WRONG, which is why the
191 // measurement is recorded here instead of the story. Two instances run at once BOTH fail T1
192 // (rc=2 on one pair, rc=3 on the next) while a single instance is 5/5 GREEN, so the failure is
193 // real and concurrency-triggered. I assumed a sibling's og_clean() was deleting the fixtures out
194 // from under the extractor. THE DECOMPOSED CONJUNCTS REFUTE THAT: consumer_still_defines=1 means
195 // ooc1.nx was present and intact the whole time. Whatever serialises is inside the extract/build
196 // step -- a per-target build lease is the standing suspect -- not the filesystem.
197 // A detector built on the wrong signature is worse than none: it never fires, and its comment
198 // teaches the next reader a cause that was disproven. So this tooth asserts nothing about WHY and
199 // instead prints what the extractor actually said -- the one piece of evidence that names it.
200 // Already in memory from the dp_read above, so this costs one write, not a re-read.
201 if ok == 0 {
202 sd_w(" T1 extractor output follows (the only thing that can name a nonzero rc):\n " as *u8)
203 var dn: i64 = n
204 if dn > 400 { dn = 400 }
205 if dn > 0 { sys_write(1, out, dn) } else { sd_w("(the extractor produced NO output at all)" as *u8) }
206 sd_w("\n" as *u8)
207 }
208 og_clean()
209 if ok == 1 { sd_w("T1 extracted-byte-identical PASS\n" as *u8); pass = pass + 1 } else { sd_w("T1 extracted-byte-identical FAIL\n" as *u8) }
210 }
211 if stage == 2 {
212 og_clean()
213 let c1: *u8 = "func oohelp(x: i64) -> i64 { return x + 1 }\nfunc main() -> i64 { return oohelp(41) }\n" as *u8
214 ss_writefile("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, c1, og_len(c1))
215 let c2: *u8 = "func oohelp(x: i64) -> i64 { return x + 2 }\nfunc main() -> i64 { return oohelp(7) }\n" as *u8
216 ss_writefile("buildroot/runtime/_hdl_build/ooc2.nx" as *u8, c2, og_len(c2))
217 let rc: i64 = og_run(1, "/tmp/oo_t2.out" as *u8)
218 let out: *u8 = sys_mmap(16384)
219 let n: i64 = dp_read("/tmp/oo_t2.out" as *u8, out, 16384)
220 var ok: i64 = 0
221 // REFUSED + consumers UNCHANGED (ooc1 still defines oohelp, no import)
222 if rc == 1 { if sd_count(out, n, "verdict=REFUSED" as *u8) == 1 {
223 if og_has("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, "func oohelp" as *u8) >= 1 {
224 if og_has("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, "import \"oobase.nx\"" as *u8) == 0 { ok = 1 }
225 }
226 } }
227 og_clean()
228 if ok == 1 { sd_w("T2 neg-different-bodies-refused-unchanged PASS\n" as *u8); pass = pass + 1 } else { sd_w("T2 neg-different-bodies-refused-unchanged FAIL\n" as *u8) }
229 }
230 if stage == 3 {
231 let out: *u8 = sys_mmap(16384)
232 let n: i64 = dp_read("/tmp/oo_t2.out" as *u8, out, 16384)
233 var ok: i64 = 0
234 if sd_count(out, n, "reason=" as *u8) >= 1 { if sd_count(out, n, "fix=" as *u8) >= 1 { ok = 1 } }
235 if ok == 1 { sd_w("T3 refusal-has-reason-and-fix PASS\n" as *u8); pass = pass + 1 } else { sd_w("T3 refusal-has-reason-and-fix FAIL\n" as *u8) }
236 }
237 if stage == 4 {
238 og_clean()
239 let c1: *u8 = "func notit() -> i64 { return 1 }\nfunc main() -> i64 { return notit() }\n" as *u8
240 ss_writefile("buildroot/runtime/_hdl_build/ooc1.nx" as *u8, c1, og_len(c1))
241 let rc: i64 = og_run(0, "/tmp/oo_t4.out" as *u8)
242 let out: *u8 = sys_mmap(16384)
243 let n: i64 = dp_read("/tmp/oo_t4.out" as *u8, out, 16384)
244 var ok: i64 = 0
245 if rc == 2 { if sd_count(out, n, "verdict=ABORTED" as *u8) == 1 { if sd_count(out, n, "not-defined" as *u8) >= 1 { ok = 1 } } }
246 og_clean()
247 if ok == 1 { sd_w("T4 neg-not-defined-aborted PASS\n" as *u8); pass = pass + 1 } else { sd_w("T4 neg-not-defined-aborted FAIL\n" as *u8) }
248 }
249 if stage == 5 {
250 let out: *u8 = sys_mmap(16384)
251 let n: i64 = dp_read("/tmp/oo_t1.out" as *u8, out, 16384)
252 var ok: i64 = 0
253 if sd_count(out, n, "reason=" as *u8) >= 1 { if sd_count(out, n, "fix=" as *u8) >= 1 { ok = 1 } }
254 if ok == 1 { sd_w("T5 extracted-has-reason-and-fix PASS\n" as *u8); pass = pass + 1 } else { sd_w("T5 extracted-has-reason-and-fix FAIL\n" as *u8) }
255 }
256
257 if stage >= 5 {
258 // MIGRATED onto nx_gate_verdict (D001, 2026-08-11). `pass` is the tooth count carried across
259 // the self-exec chain (each tooth already printed its own PASS/FAIL row in its own process),
260 // so ctr[0]=pass/ctr[1]=5 is the faithful counter here -- no conjunct exists outside it.
261 // Released here, at the end of the chain stage 1 claimed for. Held across every tooth on
262 // purpose: releasing per-stage would reopen the window between teeth, which is where the
263 // measured collision actually landed.
264 og_lock_release()
265 // Released here, at the end of the chain stage 1 claimed for. Held across every tooth on
266 // purpose: releasing per-stage would reopen the window between teeth, which is where the
267 // measured collision actually landed.
268 og_lock_release()
269 let ctr: *i64 = gv_ctr()
270 ctr[0] = pass
271 ctr[1] = 5
272 let rc: i64 = gv_verdict("OO-EXTRACT-GATE" as *u8, ctr, "byte-proven OO extractor: extract/refuse/abort + reason+fix" as *u8)
273 sys_exit(rc)
274 return rc
275 }
276
277 let self: *u8 = argv[0] as *u8
278 let sb: *u8 = sys_mmap(24)
279 og_itoa(sb, stage + 1)
280 let pb2: *u8 = sys_mmap(24)
281 og_itoa(pb2, pass)
282 let nav: *i64 = sys_mmap(40) as *i64
283 nav[0] = self as i64
284 nav[1] = sb as i64
285 nav[2] = pb2 as i64
286 nav[3] = 0
287 let envp: *i64 = sys_mmap(16) as *i64
288 envp[0] = 0
289 sys_execve(self, nav, envp)
290 sd_w("OOG-EXEC-FAIL\n" as *u8)
291 sys_exit(1)
292 return 1
293}