code wiki / _hdl_build / nx_gatesubj.nx

nx_gatesubj.nx source

↩ module page · 318 lines · 14716 B

1// nx_gatesubj.nx -- RESOLVE EVERY GATE'S SUBJECT FROM THE GATE'S OWN SOURCE. 2// 3// THE PROBLEM THIS SIZES 4// ---------------------- 5// Non-vacuity (can this gate ever fail?) is measured by nx_gate_bite, driven in bulk by nx_bite_sweep 6// over rows declared in `knowledge/compare/*.gates`. Measured 2026-08-07: 7// 8// 2,316 `*_gate.nx` in the tree 9// 19 declared in the registry = 8 permil coverage 10// 855 resolvable by NAME convention = 369 permil (nx_X_gate.nx -> nx_X.nx) 11// 12// So 99.2% of the estate's gates have never been asked whether they can fail, and the obvious 13// convention reaches only a third of them. nx_bite_sweep's header is right to refuse NAME guessing -- 14// "a guessed path that fails to open produces 'no mutant killed', which reads identically to a vacuous 15// gate" -- but it drew the wrong conclusion from it, that the subject must be hand-declared. 16// 17// ★★★★★★ THE GATE ALREADY NAMES ITS SUBJECT -- IN THE PATH IT EXECUTES OR THE MODULE IT IMPORTS. 18// DERIVING FROM THE FILENAME IS GUESSING WHILE THE ANSWER IS SITTING IN THE FILE. 19// 20// An END-TO-END gate contains the literal `_offc/<organ>.elf` it fork/execs. An IN-PROCESS gate 21// contains `import "<organ>.nx"`. Neither is a heuristic: both are the gate's own statement of what it 22// tests, and both are exact. A gate with neither is honestly reported UNRESOLVED rather than guessed. 23// ★ REPORTING "I COULD NOT DETERMINE THIS" IS A RESULT; GUESSING AND BEING WRONG IS A FALSE ACCUSATION 24// AGAINST A WORKING GATE. 25// 26// usage: nx_gatesubj [--dir D] [--rows] --rows emits `gate|subject.nx|target|mode` for a sweep 27// license_tier: ORIGINAL 28import "nx_memplane_lib.nx" 29import "nx_gatekit_lib.nx" 30const GS_MAGIC_8192: i64 = 8192 31const GS_MAGIC_4096: i64 = 4096 32 33const GS_DIR: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/runtime/_hdl_build" 34const GS_MAXF: i64 = 32768 // holds the WHOLE corpus pre-filter (18,563), not just gates 35const GS_FBUF: i64 = 4194304 36 37func gs_isid(c: i64) -> i64 { 38 if c >= 97 { if c <= 122 { return 1 } } 39 if c >= 65 { if c <= 90 { return 1 } } 40 if c >= 48 { if c <= 57 { return 1 } } 41 if c == 95 { return 1 } 42 return 0 43} 44 45// (gs_isnx was written here, then superseded by gs_isgate before it ever had a caller. Removed the 46// moment nx_unwired named it, rather than accepted into the baseline -- the ratchet is only worth 47// having if its own author fixes what it finds instead of acknowledging it away.) 48 49// does `name` end with "_gate.nx"? 50func gs_isgate(name: *u8) -> i64 { 51 let l: i64 = mp_len(name) 52 if l < 9 { return 0 } 53 let suf: *u8 = "_gate.nx" as *u8 54 var i: i64 = 0 55 while i < 8 { if name[l - 8 + i] != suf[i] { return 0 } i = i + 1 } 56 return 1 57} 58 59 60 61// find `_offc/<ident>.elf` and copy <ident> to out. Returns 1 on success. 62// ⚠ Skips the gate's OWN name and the shared builder, which every gate mentions. 63func gs_execsubj(buf: *u8, n: i64, self: *u8, out: *u8) -> i64 { 64 let pat: *u8 = "_offc/" as *u8 65 var i: i64 = 0 66 while i + 6 < n { 67 var ok: i64 = 1 68 var j: i64 = 0 69 while j < 6 { if buf[i + j] != pat[j] { ok = 0; j = 6 } else { j = j + 1 } } 70 if ok == 1 { 71 var p: i64 = i + 6 72 var k: i64 = 0 73 // FLAG-TERMINATED. `p = n + 9` writes the exit marker into the cursor and the restore lands 74 // on `n`, so the character AFTER the identifier -- the one that decides `.elf` vs `.nx` -- 75 // is read from the wrong place. FIFTH occurrence of this idiom in one session. 76 // ★★★★★★ THE FIFTH TIME YOU FIX A BUG BY HAND IS PROOF THE FIX BELONGS IN A LINTER. 77 var fin: i64 = 0 78 while fin == 0 { 79 if p >= n { fin = 1 } 80 if fin == 0 { 81 if gs_isid(buf[p] as i64) == 1 { if k < 120 { out[k] = buf[p]; k = k + 1 } p = p + 1 } 82 if gs_isid(buf[p] as i64) == 0 { fin = 1 } 83 } 84 } 85 out[k] = 0 as u8 86 if k > 2 { 87 // must be followed by ".elf" 88 if buf[p] == (46 as u8) { 89 if buf[p + 1] == (101 as u8) { 90 if buf[p + 2] == (108 as u8) { 91 if buf[p + 3] == (102 as u8) { 92 var skip: i64 = 0 93 if mp_streq(out, self) == 1 { skip = 1 } 94 if mp_streq(out, "nx_sov_build_run" as *u8) == 1 { skip = 1 } 95 if skip == 0 { return 1 } 96 } 97 } 98 } 99 } 100 } 101 } 102 i = i + 1 103 } 104 return 0 105} 106 107// find `import "<ident>.nx"` and copy <ident> to out, skipping the shared libraries. 108func gs_impsubj(buf: *u8, n: i64, out: *u8) -> i64 { 109 let pat: *u8 = "import \"" as *u8 110 var i: i64 = 0 111 while i + 8 < n { 112 var ok: i64 = 1 113 var j: i64 = 0 114 while j < 8 { if buf[i + j] != pat[j] { ok = 0; j = 8 } else { j = j + 1 } } 115 if ok == 1 { 116 var p: i64 = i + 8 117 var k: i64 = 0 118 // FLAG-TERMINATED. `p = n + 9` writes the exit marker into the cursor and the restore lands 119 // on `n`, so the character AFTER the identifier -- the one that decides `.elf` vs `.nx` -- 120 // is read from the wrong place. FIFTH occurrence of this idiom in one session. 121 // ★★★★★★ THE FIFTH TIME YOU FIX A BUG BY HAND IS PROOF THE FIX BELONGS IN A LINTER. 122 var fin: i64 = 0 123 while fin == 0 { 124 if p >= n { fin = 1 } 125 if fin == 0 { 126 if gs_isid(buf[p] as i64) == 1 { if k < 120 { out[k] = buf[p]; k = k + 1 } p = p + 1 } 127 if gs_isid(buf[p] as i64) == 0 { fin = 1 } 128 } 129 } 130 out[k] = 0 as u8 131 if k > 2 { 132 var skip: i64 = 0 133 if mp_streq(out, "nx_syscalls" as *u8) == 1 { skip = 1 } 134 if mp_streq(out, "nx_memplane_lib" as *u8) == 1 { skip = 1 } 135 if mp_streq(out, "nx_gatekit_lib" as *u8) == 1 { skip = 1 } 136 if mp_streq(out, "nx_artifact_root" as *u8) == 1 { skip = 1 } 137 if skip == 0 { return 1 } 138 } 139 } 140 i = i + 1 141 } 142 return 0 143} 144 145func main(argc: i64, argv: *i64) -> i64 { 146 var dir: *u8 = GS_DIR 147 var rows: i64 = 0 148 var dirset: i64 = 0 149 var a: i64 = 1 150 while a < argc { 151 let s: *u8 = argv[a] as *u8 152 if mp_streq(s, "--dir" as *u8) == 1 { if a + 1 < argc { dir = argv[a + 1] as *u8; dirset = 1; a = a + 1 } } 153 if mp_streq(s, "--rows" as *u8) == 1 { rows = 1 } 154 a = a + 1 155 } 156 157 let msg: *u8 = sys_mmap(GS_MAGIC_8192) 158 let names: *u8 = sys_mmap(GS_MAXF * 128) 159 let fbuf: *u8 = sys_mmap(GS_FBUF) 160 let path: *u8 = sys_mmap(GS_MAGIC_4096) 161 let subj: *u8 = sys_mmap(256) 162 let self: *u8 = sys_mmap(256) 163 let spath: *u8 = sys_mmap(GS_MAGIC_4096) 164 let alt: *u8 = sys_mmap(GS_MAGIC_4096) 165 let probe: *u8 = sys_mmap(256) 166 let hdlp: *u8 = sys_mmap(GS_MAGIC_4096) 167 let rtp: *u8 = sys_mmap(GS_MAGIC_4096) 168 gk_corpus_hdl(hdlp) 169 gk_corpus_root(rtp) 170 171 // THIS ORGAN FIXED THE HARDCODED-DIRECTORY BUG IN THE THING IT LOOKS AT AND LEFT IT IN THE LIST 172 // OF THINGS IT LOOKS THROUGH. The comment below (★ RESOLVING A NAME IS NOT RESOLVING A PATH) 173 // taught the subject resolver to stat BOTH source directories -- and 40 lines above it, the 174 // enumerator that decides WHICH GATES EXIST still read one. So the census correctly resolved the 175 // subject of every gate it had heard of, having heard of 38.6% of them. 176 // ★★★★★★ FIXING A HARDCODED PATH WHERE IT IS READ, BUT NOT WHERE THE POPULATION IS ENUMERATED, 177 // LEAVES A CENSUS THAT IS PRECISE ABOUT A SUBSET AND SILENT ABOUT THE REST. 178 var scanned: i64 = 0 179 if dirset == 0 { scanned = gk_corpus_scan(names, MP_SLOT, GS_MAXF) } 180 if dirset == 1 { scanned = gk_dirscan(dir, 0 as *u8, names, MP_SLOT, GS_MAXF, 0) } 181 if scanned == (0 - 2) { 182 var mq: i64 = mp_cat(msg, 0, "*** nx_gatesubj: REFUSED -- corpus exceeds GS_MAXF; a truncated census is not a census. ***\n" as *u8) 183 mp_say(msg, mq) 184 return 1 185 } 186 if scanned == (0 - 3) { 187 var mr: i64 = mp_cat(msg, 0, "*** nx_gatesubj: REFUSED -- a source path exceeds the name slot. ***\n" as *u8) 188 mp_say(msg, mr) 189 return 1 190 } 191 if scanned <= 0 { 192 var me: i64 = mp_cat(msg, 0, "*** nx_gatesubj: REFUSED -- could not scan the source tree. ***\n" as *u8) 193 mp_say(msg, me) 194 return 1 195 } 196 // Compact in place to the gates only, so every count below keeps its old meaning. 197 // gs_isgate tests the LAST 8 bytes, so it works on an absolute path unchanged. 198 var cnt: i64 = 0 199 var ci: i64 = 0 200 while ci < scanned { 201 let cp: *u8 = mp_nameptr(names, ci) 202 if gs_isgate(cp) == 1 { 203 let dp: *u8 = mp_nameptr(names, cnt) 204 var cz: i64 = 0 205 while cp[cz] != (0 as u8) { if cz < MP_SLOT - 1 { dp[cz] = cp[cz] } cz = cz + 1 } 206 dp[cz] = 0 as u8 207 cnt = cnt + 1 208 } 209 ci = ci + 1 210 } 211 var mgc: i64 = mp_cat(msg, 0, " corpus=" as *u8) 212 mgc = mp_catn(msg, mgc, scanned) 213 mgc = mp_cat(msg, mgc, " files scanned, gate_sources=" as *u8) 214 mgc = mp_catn(msg, mgc, cnt) 215 if dirset == 0 { mgc = mp_cat(msg, mgc, " (WHOLE compile corpus)\n" as *u8) } 216 if dirset == 1 { mgc = mp_cat(msg, mgc, " (NARROWED by --dir; NOT the whole tree)\n" as *u8) } 217 mp_say(msg, mgc) 218 if cnt <= 0 { 219 var m0: i64 = mp_cat(msg, 0, "*** nx_gatesubj: REFUSED -- no *_gate.nx found. ***\n" as *u8) 220 mp_say(msg, m0) 221 return 1 222 } 223 224 var n_e2e: i64 = 0 225 var n_inproc: i64 = 0 226 var n_unres: i64 = 0 227 var m: i64 = 0 228 229 var i: i64 = 0 230 while i < cnt { 231 let nm: *u8 = mp_nameptr(names, i) 232 // the gate's own target name, so it does not resolve to itself. 233 // nm is now an ABSOLUTE PATH, so take the basename first -- otherwise `self` would carry the 234 // directory and could never match a subject name. 235 var bo: i64 = 0 236 var bz: i64 = 0 237 while nm[bz] != (0 as u8) { if nm[bz] == (47 as u8) { bo = bz + 1 } bz = bz + 1 } 238 let base: *u8 = ((nm as i64) + bo) as *u8 239 var q: i64 = 0 240 while base[q] != (0 as u8) { if q < 250 { self[q] = base[q] } q = q + 1 } 241 if q > 3 { q = q - 3 } 242 self[q] = 0 as u8 243 244 let n: i64 = mp_readf(nm, fbuf, GS_FBUF) 245 var mode: i64 = 0 246 if n > 0 { 247 if gs_execsubj(fbuf, n, self, subj) == 1 { mode = 1 } 248 if mode == 0 { if gs_impsubj(fbuf, n, subj) == 1 { mode = 2 } } 249 } 250 // (counters moved INTO the path-verification block below -- leaving them here counted every 251 // gate twice and produced "coverage 1835 permil". 252 // ★★★★★ A PERCENTAGE OVER 100% IS A COUNTING BUG ANNOUNCING ITSELF; A RATIO THAT CANNOT EXCEED 253 // ITS DENOMINATOR IS A FREE SELF-CHECK, SO ALWAYS PRINT ONE.) 254 255 // ★★★★★ RESOLVING A NAME IS NOT RESOLVING A PATH. Modules live in BOTH `runtime/_hdl_build/` 256 // and `runtime/`; hardcoding one directory emitted rows whose subject could not be opened, and 257 // a path that fails to open is precisely the "guessed path" failure nx_bite_sweep's header 258 // warns about -- it produces "no mutant killed", indistinguishable from a vacuous gate. 259 // I reintroduced the very defect I had just quoted, by assuming a directory instead of 260 // checking one. STAT BOTH, EMIT WHAT OPENS, COUNT THE REST AS UNRESOLVED. 261 if mode > 0 { 262 // ⚠ BOTH DIRECTORIES ARE HOST-RESOLVED. This block previously joined against GS_DIR and a 263 // second hardcoded literal. Fixing only the ENUMERATOR left this resolver still pointing at 264 // the laptop tree, and on the NAS that path EXISTS as a directory of .elf artifacts -- so 265 // every subject failed to open and the organ reported 3,194 gates, 0 resolved, coverage 0 266 // permil, having been 910 permil one host earlier. 267 // ★★★★★★ A SECOND HARDCODED PATH IN THE SAME FILE IS NOT A SECOND BUG, IT IS THE SAME BUG 268 // SURVIVING IN THE HALF YOU DID NOT LOOK AT. 269 var sp1: i64 = gk_cat(spath, 0, hdlp) 270 sp1 = gk_cat(spath, sp1, subj) 271 sp1 = gk_cat(spath, sp1, ".nx" as *u8) 272 spath[sp1] = 0 as u8 273 var where: i64 = 0 274 if mp_readf(spath, probe, 64) > 0 { where = 1 } 275 if where == 0 { 276 var o2: i64 = gk_cat(alt, 0, rtp) 277 o2 = gk_cat(alt, o2, subj) 278 o2 = gk_cat(alt, o2, ".nx" as *u8) 279 alt[o2] = 0 as u8 280 if mp_readf(alt, probe, 64) > 0 { where = 2 } 281 } 282 if where == 0 { mode = 0 } 283 if where > 0 { 284 if mode == 1 { n_e2e = n_e2e + 1 } 285 if mode == 2 { n_inproc = n_inproc + 1 } 286 if rows == 1 { 287 m = mp_cat(msg, 0, self) 288 m = mp_cat(msg, m, "|" as *u8) 289 if where == 1 { m = mp_cat(msg, m, "runtime/_hdl_build/" as *u8) } 290 if where == 2 { m = mp_cat(msg, m, "runtime/" as *u8) } 291 m = mp_cat(msg, m, subj) 292 m = mp_cat(msg, m, ".nx|" as *u8) 293 m = mp_cat(msg, m, subj) 294 if mode == 1 { m = mp_cat(msg, m, "|e2e\n" as *u8) } 295 if mode == 2 { m = mp_cat(msg, m, "|inproc\n" as *u8) } 296 mp_say(msg, m) 297 } 298 } 299 } 300 if mode == 0 { n_unres = n_unres + 1 } 301 i = i + 1 302 } 303 304 m = mp_cat(msg, 0, "nx_gatesubj: " as *u8) 305 m = mp_catn(msg, m, cnt) 306 m = mp_cat(msg, m, " gates -- resolved from the gate's OWN source: " as *u8) 307 m = mp_catn(msg, m, n_e2e) 308 m = mp_cat(msg, m, " end-to-end (execs _offc/<organ>.elf), " as *u8) 309 m = mp_catn(msg, m, n_inproc) 310 m = mp_cat(msg, m, " in-process (imports the module), " as *u8) 311 m = mp_catn(msg, m, n_unres) 312 m = mp_cat(msg, m, " UNRESOLVED (honestly reported, never guessed).\n" as *u8) 313 m = mp_cat(msg, m, " coverage " as *u8) 314 m = mp_catn(msg, m, 1000 * (n_e2e + n_inproc) / cnt) 315 m = mp_cat(msg, m, " permil, against 8 permil declared in knowledge/compare/*.gates and 369 permil reachable by name convention.\n" as *u8) 316 mp_say(msg, m) 317 return 0 318}