code wiki / (root) / nx_nxa_texm_gate.nx

nx_nxa_texm_gate.nx source

↩ module page · 342 lines · 15578 B

1// nx_nxa_texm_gate.nx -- THE GATE FOR THE TEXM WRITER. 2// 3// SUBJECT: the nx_nxa_texm ELF, forked for real. The organ's contract is an EXIT CODE plus an 4// ADDITIVE container rewrite, and /api/gate_run derives its verdict from the exit code -- so a 5// gate that only read stdout would test the least load-bearing half. Every tooth asserts either an 6// exit code or a byte read back out of the rewritten container. 7// 8// THE DANGEROUS FAILURE THIS GATE EXISTS TO CATCH is not "TEXM missing". It is TEXM PRESENT AND A 9// PRE-EXISTING SECTION GONE. The floor score would RISE while the asset silently lost its rig, 10// garments or hair -- a regression wearing a win, and exactly what an unverified section-append 11// produces. T3 therefore enumerates ALL THIRTEEN pre-existing tags by name rather than spot- 12// checking, and asserts the section count arithmetic closes. 13// 14// FIXTURES AT RUNTIME, IN /tmp/nx_nxa_texm_gate/, and every subject-created output is UNLINKED at 15// SETUP. A gate that is not idempotent reports on its first run and lies about every run after -- 16// a sibling gate hit exactly that today, where a conf left by an earlier run made correct 17// behaviour read as FAIL. Setup also asserts the unlink WORKED before anything is measured. 18// 19// THE REAL ASSET IS READ, NEVER WRITTEN. Input is the shipped character; every output goes to 20// /tmp. The organ never modifies its input, which is what makes an end-to-end gate on production 21// data safe here. 22// 23// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 24import "nx_syscalls.nx" 25import "nx_gate_verdict.nx" 26import "nx_tool_run.nx" 27 28const TG_SUBJECT_DEFAULT: *u8 = "_offc/nx_nxa_texm.elf" 29// ABSOLUTE ON PURPOSE. nx_sov_build_run anchors CWD to buildroot/ before forking, so a 30// nishihost-relative path resolves to buildroot/sites/... and the read returns nothing -- which 31// this gate reported as sections=-1 and a RED across every content tooth, blaming the subject for 32// a harness path error. A gate's own working directory is part of its fixture. 33// AND IT IS THE BANKED PRE-TEXM ARTIFACT, NOT THE SERVED ONE. This gate used to read the LIVE 34// shipped asset, which worked exactly until the capability it tests SHIPPED: once TEXM was written 35// into the served character, "TEXM absent before" could never be true again, and the bite pair 36// honestly reported FALSE-POSITIVE (fired on good input) -- the gate declaring it could no longer 37// discriminate. A gate whose fixture is the production artifact measures its own success into 38// vacuity. The banked pre-TEXM asset is a real artifact (13 sections, TEXC present, TEXM absent), 39// so the ABSENT half of the bite is testable forever. 40const TG_ASSET: *u8 = "/volume1/homes/elderwesto/nishihost/knowledge/bank/ref9d.nxa.pretexm-20260823" 41 42// the organ's exit contract, restated so a change to it BREAKS THIS GATE loudly 43const TG_EXIT_OK: i64 = 0 44const TG_EXIT_BAD: i64 = 3 45const TG_EXIT_NOSEC: i64 = 4 46 47// NXA layout 48const TG_HDR: i64 = 32 49const TG_TOCE: i64 = 32 50const TG_OFF_FIELD: i64 = 8 51const TG_LEN_FIELD: i64 = 16 52const TG_NSEC: i64 = 16 53const TG_TAGB: i64 = 4 54const TG_WORD: i64 = 8 55const TG_RADIX: i64 = 256 56const TG_MASK: i64 = 255 57const TG_NXA_VER: i64 = 1 58 59// THE SECTION COUNTS ARE DERIVED FROM THE INPUT, NEVER DECLARED. This gate used to assert 60// "13 carried + 1 appended = 14" as two literals. That is a picked count describing the subject's 61// SHAPE, and it went RED the moment the asset legitimately GREW: the FACE and MORF sections landed 62// (a capability RISE) and the gate reported a failure. An instrument that cannot tell growth from 63// regression will call every improvement a defect, and raising the literal to 16 would only move 64// the breakage to whoever lands section 17. 65// carried = the input's own section count, read from its header 66// appended = 1 when the input lacks TEXM, 0 when it already has one (replace, not duplicate) 67// so the arithmetic closes for ANY input, and the tooth still catches a dropped or doubled section. 68 69// a resolution small enough that the gate finishes inside a caller deadline. This is a GATE 70// RUNTIME budget, not a quality bar -- the shipping default is read from 71// knowledge/asset_texture_floor.conf by the organ itself and is deliberately NOT restated here, 72// because a threshold copied into a second file is a duplicate ruler that drifts. 73const TG_GATE_RES: *u8 = "128" 74const TG_MIN_TEXM_WORDS: i64 = 8 // a TEXM smaller than its own header cannot carry a map 75 76const TG_CAPCAP: i64 = 262144 77const TG_ARGVN: i64 = 8 78const TG_MODEDIR: i64 = 493 79 80const TG_DIR: *u8 = "/tmp/nx_nxa_texm_gate" 81const TG_OUT1: *u8 = "/tmp/nx_nxa_texm_gate/o1.nxa" 82const TG_OUT2: *u8 = "/tmp/nx_nxa_texm_gate/o2.nxa" 83const TG_NOTEXC: *u8 = "/tmp/nx_nxa_texm_gate/notexc.nxa" 84const TG_OUT3: *u8 = "/tmp/nx_nxa_texm_gate/o3.nxa" 85 86func tg_rd64(b: *u8, off: i64) -> i64 { 87 var v: i64 = 0 88 var i: i64 = TG_WORD - 1 89 while i >= 0 { v = v*TG_RADIX + ((b[off + i] & TG_MASK) as i64); i = i - 1 } 90 return v 91} 92func tg_wr64(b: *u8, off: i64, v: i64) -> i64 { 93 var n: i64 = v 94 var i: i64 = 0 95 while i < TG_WORD { let q: i64 = n / TG_RADIX; b[off + i] = (n - q*TG_RADIX) as u8; n = q; i = i + 1 } 96 return 0 97} 98func tg_tageq(b: *u8, off: i64, t: *u8) -> i64 { 99 var i: i64 = 0 100 while i < TG_TAGB { if b[off + i] != t[i] { return 0 } i = i + 1 } 101 return 1 102} 103// section wordlen by tag, or -1 when absent. Walks the WHOLE table. 104func tg_find_len(b: *u8, ns: i64, t: *u8) -> i64 { 105 var s: i64 = 0 106 while s < ns { 107 let e: i64 = TG_HDR + s*TG_TOCE 108 if tg_tageq(b, e, t) == 1 { return tg_rd64(b, e + TG_LEN_FIELD) } 109 s = s + 1 110 } 111 return 0 - 1 112} 113func tg_nsec(path: *u8, lenout: *i64) -> i64 { 114 let lp: *i64 = sys_mmap(TG_WORD*2) as *i64 115 let b: *u8 = sys_read_file(path, lp) 116 if (b as i64) == 0 { lenout[0] = 0; return 0 - 1 } 117 lenout[0] = lp[0] 118 lenout[1] = b as i64 119 return tg_rd64(b, TG_NSEC) 120} 121func tg_run(subject: *u8, a1: *u8, a2: *u8, a3: *u8, out: *u8, olen: *i64) -> i64 { 122 let av: *i64 = sys_mmap(TG_WORD*TG_ARGVN) as *i64 123 av[0] = subject as i64 124 av[1] = a1 as i64 125 av[2] = a2 as i64 126 av[3] = a3 as i64 127 av[4] = 0 128 return tr_run_capture(subject, av, out, TG_CAPCAP, olen) 129} 130func tg_exists(path: *u8) -> i64 { 131 let lp: *i64 = sys_mmap(TG_WORD*2) as *i64 132 let b: *u8 = sys_read_file(path, lp) 133 if (b as i64) == 0 { return 0 } 134 return 1 135} 136// a structurally valid NXA carrying VERT+SKEL but NO TEXC -- the negative control for the 137// prerequisite check. Built at RUNTIME so no detector can find this pattern in source. 138func tg_write_notexc(path: *u8) -> i64 { 139 let nsec: i64 = 2 140 let total: i64 = TG_HDR + nsec*TG_TOCE + nsec*TG_WORD 141 let b: *u8 = sys_mmap(total + 64) 142 var i: i64 = 0 143 while i < total { b[i] = 0 as u8; i = i + 1 } 144 let mg: *u8 = "NXANIM01" as *u8 145 var k: i64 = 0 146 while k < TG_WORD { b[k] = mg[k]; k = k + 1 } 147 tg_wr64(b, TG_WORD, TG_NXA_VER) 148 tg_wr64(b, TG_NSEC, nsec) 149 let data: i64 = TG_HDR + nsec*TG_TOCE 150 let h0: i64 = TG_HDR 151 let h1: i64 = TG_HDR + TG_TOCE 152 var c: i64 = 0 153 let tv: *u8 = "VERT" as *u8 154 while c < TG_TAGB { b[h0 + c] = tv[c]; c = c + 1 } 155 tg_wr64(b, h0 + TG_OFF_FIELD, data) 156 tg_wr64(b, h0 + TG_LEN_FIELD, 1) 157 var c2: i64 = 0 158 let ts: *u8 = "SKEL" as *u8 159 while c2 < TG_TAGB { b[h1 + c2] = ts[c2]; c2 = c2 + 1 } 160 tg_wr64(b, h1 + TG_OFF_FIELD, data + TG_WORD) 161 tg_wr64(b, h1 + TG_LEN_FIELD, 1) 162 tg_wr64(b, data, 1) 163 tg_wr64(b, data + TG_WORD, 1) 164 let fd: i64 = sys_openat_wr(path, MODE_0644) 165 if fd < 0 { return 0 - 1 } 166 let wr: i64 = sys_write(fd, b, total) 167 sys_close(fd) 168 if wr != total { return 0 - 1 } 169 return total 170} 171 172func main(argc: i64, argv: *i64) -> i64 { 173 let ctr: *i64 = gv_ctr() 174 gv_head("nx_nxa_texm gate -- the PBR map set is written INTO the asset, additively" as *u8) 175 var subject: *u8 = TG_SUBJECT_DEFAULT 176 if argc >= 2 { subject = argv[1] as *u8 } 177 gv_puts(" subject: " as *u8) 178 gv_puts(subject) 179 gv_puts("\n\n" as *u8) 180 181 // ---- SETUP: create scratch, then REMOVE every output the subject might create. 182 sys_mkdir(TG_DIR, TG_MODEDIR) 183 sys_unlinkat(TG_OUT1) 184 sys_unlinkat(TG_OUT2) 185 sys_unlinkat(TG_OUT3) 186 sys_unlinkat(TG_NOTEXC) 187 var clean: i64 = 0 188 if tg_exists(TG_OUT1) == 0 { if tg_exists(TG_OUT2) == 0 { if tg_exists(TG_OUT3) == 0 { clean = 1 } } } 189 gv_check("setup-outputs-absent-before-measuring (gate is idempotent)" as *u8, clean, ctr) 190 191 let cap: *u8 = sys_mmap(TG_CAPCAP) 192 let olen: *i64 = sys_mmap(TG_WORD*2) as *i64 193 let meta: *i64 = sys_mmap(TG_WORD*4) as *i64 194 195 // ---- BEFORE: the shipped asset must NOT already carry TEXM, or every tooth below is vacuous. 196 let ns_in: i64 = tg_nsec(TG_ASSET, meta) 197 let bin: *u8 = meta[1] as *u8 198 gv_puts(" input sections=" as *u8) 199 gv_num(ns_in) 200 gv_puts(" bytes=" as *u8) 201 gv_num(meta[0]) 202 gv_puts("\n" as *u8) 203 var pre_ok: i64 = 0 204 if ns_in > 0 { pre_ok = 1 } 205 gv_check("input-carries-sections-to-carry (count bound in the condition, an empty input cannot pass)" as *u8, pre_ok, ctr) 206 var texm_before: i64 = 0 207 if tg_find_len(bin, ns_in, "TEXM" as *u8) >= 0 { texm_before = 1 } 208 209 // ---- T1: write TEXM ---- 210 let rc1: i64 = tg_run(subject, TG_ASSET, TG_OUT1, TG_GATE_RES, cap, olen) 211 gv_puts(" [T1] write rc=" as *u8) 212 gv_num(rc1) 213 gv_puts("\n" as *u8) 214 var t1: i64 = 0 215 if rc1 == TG_EXIT_OK { t1 = 1 } 216 gv_check("texm-write-exits-OK" as *u8, t1, ctr) 217 218 let ns_out: i64 = tg_nsec(TG_OUT1, meta) 219 let bout: *u8 = meta[1] as *u8 220 gv_puts(" output sections=" as *u8) 221 gv_num(ns_out) 222 gv_puts(" bytes=" as *u8) 223 gv_num(meta[0]) 224 gv_puts("\n" as *u8) 225 226 // ---- T2: ANTI-VACUITY. A TEXM whose length is header-only would still be "PRESENT". Assert 227 // the fixture reached the condition: a real map set was baked and carries real bytes. 228 let tl: i64 = tg_find_len(bout, ns_out, "TEXM" as *u8) 229 gv_puts(" [T2] TEXM wordlen=" as *u8) 230 gv_num(tl) 231 gv_puts("\n" as *u8) 232 var t2: i64 = 0 233 if tl > TG_MIN_TEXM_WORDS { t2 = 1 } 234 gv_check("anti-vacuity-TEXM-carries-more-than-its-own-header" as *u8, t2, ctr) 235 236 // ---- T3: EVERY pre-existing tag survives. THE REGRESSION TOOTH. 237 // Enumerated from the INPUT'S OWN TOC, not from a hand-written tag list: the old version named 238 // thirteen tags, so it could only ever notice a regression among those thirteen and was blind 239 // to any section added later (it would have carried FACE and MORF away silently). Reading the 240 // input's table means the tooth covers whatever the asset actually holds, forever. 241 var kept: i64 = 0 242 var ki: i64 = 0 243 while ki < ns_in { 244 let ke: i64 = TG_HDR + ki*TG_TOCE 245 if tg_find_len(bout, ns_out, ((bin as i64) + ke) as *u8) >= 0 { kept = kept + 1 } 246 ki = ki + 1 247 } 248 gv_puts(" [T3] pre-existing tags surviving=" as *u8) 249 gv_num(kept) 250 gv_puts(" of " as *u8) 251 gv_num(ns_in) 252 gv_puts("\n" as *u8) 253 var t3: i64 = 0 254 if ns_in > 0 { if kept == ns_in { t3 = 1 } } 255 gv_check("additive-only-every-pre-existing-section-survives (denominator is the input's own count)" as *u8, t3, ctr) 256 257 // ---- T4: the count arithmetic closes, DERIVED. carried = the input's own count; appended = 1 258 // only when the input lacked TEXM (a second apply REPLACES). Nothing dropped, nothing doubled, 259 // and the tooth holds for an asset of any size. 260 var expect_after: i64 = ns_in + 1 261 if texm_before == 1 { expect_after = ns_in } 262 gv_puts(" [T4] carried=" as *u8) 263 gv_num(ns_in) 264 gv_puts(" texm_already_present=" as *u8) 265 gv_num(texm_before) 266 gv_puts(" expected=" as *u8) 267 gv_num(expect_after) 268 gv_puts(" got=" as *u8) 269 gv_num(ns_out) 270 gv_puts("\n" as *u8) 271 var t4: i64 = 0 272 if ns_in > 0 { if ns_out == expect_after { t4 = 1 } } 273 gv_check("section-count-arithmetic-closes (carried + appended, both derived from the input)" as *u8, t4, ctr) 274 275 // ---- T5: SECTION LENGTHS ARE UNCHANGED, not merely present. A section can survive by name 276 // and be truncated; only comparing its wordlen catches that. 277 // BIND THE ASSERTION TO ITS DENOMINATOR. The first version of this tooth passed on ns_in=-1, 278 // i.e. it compared ZERO sections and reported success -- a tooth that passes on the empty set 279 // is not a tooth, and it passed in the same run where every other content tooth went RED. 280 var samelen: i64 = 0 281 var compared: i64 = 0 282 var si: i64 = 0 283 while si < ns_in { 284 let e: i64 = TG_HDR + si*TG_TOCE 285 let want: i64 = tg_rd64(bin, e + TG_LEN_FIELD) 286 let got: i64 = tg_find_len(bout, ns_out, ((bin as i64) + e) as *u8) 287 if got == want { compared = compared + 1 } 288 si = si + 1 289 } 290 gv_puts(" [T5] sections compared with identical wordlen=" as *u8) 291 gv_num(compared) 292 gv_puts(" of " as *u8) 293 gv_num(ns_in) 294 gv_puts("\n" as *u8) 295 if ns_in > 0 { if compared == ns_in { samelen = 1 } } 296 gv_check("every-carried-section-keeps-its-exact-wordlen (denominator is the input's own count)" as *u8, samelen, ctr) 297 298 // ---- T6/T7: THE BITE PAIR. TEXM absent before, present after. A writer that reported success 299 // for everything would pass a present-test alone; the ABSENT half is what catches it. 300 var fired_bad: i64 = 0 301 if tl >= 0 { fired_bad = 1 } 302 var fired_good: i64 = 0 303 if texm_before == 1 { fired_good = 1 } 304 gv_bite("neg-control-TEXM-absent-before-and-present-after" as *u8, fired_bad, fired_good, ctr) 305 306 // ---- T8: IDEMPOTENCY. A second apply must REPLACE, never append a second TEXM. 307 let rc2: i64 = tg_run(subject, TG_OUT1, TG_OUT2, TG_GATE_RES, cap, olen) 308 let ns2: i64 = tg_nsec(TG_OUT2, meta) 309 gv_puts(" [T8] second-apply rc=" as *u8) 310 gv_num(rc2) 311 gv_puts(" sections=" as *u8) 312 gv_num(ns2) 313 gv_puts("\n" as *u8) 314 // the second apply runs on an output that ALREADY carries TEXM, so a correct writer replaces it 315 // and the count must not move at all: expected == the first output's own count, derived. 316 var t8: i64 = 0 317 if rc2 == TG_EXIT_OK { if ns_out > 0 { if ns2 == ns_out { t8 = 1 } } } 318 gv_check("idempotent-second-apply-replaces-rather-than-appends (count must not move)" as *u8, t8, ctr) 319 320 // ---- T9: the TEXC PREREQUISITE is enforced. An asset with no UVs has nothing to bake into, 321 // and fabricating a map for it would be inventing data. 322 let wn: i64 = tg_write_notexc(TG_NOTEXC) 323 gv_check("setup-no-texc-fixture-written" as *u8, tg_exists(TG_NOTEXC), ctr) 324 let rc3: i64 = tg_run(subject, TG_NOTEXC, TG_OUT3, TG_GATE_RES, cap, olen) 325 gv_puts(" [T9] no-TEXC input rc=" as *u8) 326 gv_num(rc3) 327 gv_puts("\n" as *u8) 328 var t9: i64 = 0 329 if rc3 == TG_EXIT_NOSEC { if tg_exists(TG_OUT3) == 0 { t9 = 1 } } 330 gv_check("missing-TEXC-refused-by-name-AND-writes-no-output" as *u8, t9, ctr) 331 332 // ---- T10: the subject actually RAN. A negative sentinel or 127 would make every exit-code 333 // tooth above compare against a number the subject never produced. 334 var ran: i64 = 1 335 if rc1 < 0 { ran = 0 } 336 if rc1 == 127 { ran = 0 } 337 gv_check("neg-control-subject-actually-executed (not 127, not a harness sentinel)" as *u8, ran, ctr) 338 339 let rc: i64 = gv_verdict("NXA-TEXM" as *u8, ctr, "the map set is carried inside the asset and every prior section survives byte-for-byte" as *u8) 340 sys_exit(rc) 341 return rc 342}