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}