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}