code wiki / _hdl_build / nx_envelope_audit_gate.nx
nx_envelope_audit_gate.nx source
↩ module page · 306 lines · 17355 B
1// nx_envelope_audit_gate.nx -- TEETH FOR THE SILENT-CAP DETECTOR, because on 2026-08-20 it HAD ONE.
2//
3// WHY THIS GATE EXISTS. nx_envelope_audit is the estate's enforcer of the scale-law ("every tool DECLARES
4// its envelope IN ITS OUTPUT -- silent capping is forbidden BY CONSTRUCTION"). It shipped for weeks with a
5// row-cap gate wrapping its whole per-row body and a row counter that only incremented INSIDE that gate, so
6// every allowlist row past the cap was dropped with no counter and no marker -- and its dogfood line then
7// printed the cap as a HAND-TYPED literal, which reads as a population. Measured: it reported rows=512
8// against a tool_allowlist.conf whose true data-row count is over a thousand.
9// ***THE ENFORCER COMMITTED THE DEFECT IT ENFORCES, AND ITS OWN OUTPUT WAS THE ALIBI.***
10// A green that never had a corresponding red is unverified, so every tooth below is paired with the input
11// that must make it fail.
12//
13// HERMETIC BY CONSTRUCTION. The subject resolves its probe dirs (buildroot/runtime/_hdl_build, then
14// buildroot/runtime) RELATIVE TO CWD, so this gate builds a complete throwaway probe tree under
15// /tmp/nx_envelope_audit_gate/ and chdirs into it. Nothing here touches a production path, nothing shares a
16// fixture with a beat, and the fixtures are rebuilt every run so the gate is idempotent -- a gate that is
17// not idempotent reports on its first run and lies about every run after.
18// The fixture SOURCES are assembled at RUNTIME, never stored as files in the tree, because a detector that
19// scans source will otherwise find its own test fixture -- and writing the pattern in a comment re-arms
20// that trap, since prose is source bytes too.
21//
22// SUBJECT: the DEPLOYED nx_envelope_audit elf (serving root, then _offc, then a local _build). If none
23// resolves the gate SKIPs via gv_need -- "I could not look" is not "it is broken".
24// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
25import "nx_syscalls.nx"
26import "nx_gate_verdict.nx"
27import "nx_gatekit_lib.nx"
28
29const EG_DIR: *u8 = "/tmp/nx_envelope_audit_gate"
30const EG_BR: *u8 = "/tmp/nx_envelope_audit_gate/buildroot"
31const EG_RT: *u8 = "/tmp/nx_envelope_audit_gate/buildroot/runtime"
32const EG_HDL: *u8 = "/tmp/nx_envelope_audit_gate/buildroot/runtime/_hdl_build"
33const EG_CONF: *u8 = "/tmp/nx_envelope_audit_gate/f.conf"
34const EG_SMALL: *u8 = "/tmp/nx_envelope_audit_gate/small.conf"
35const EG_HUGE: *u8 = "/tmp/nx_envelope_audit_gate/huge.conf"
36const EG_O1: *u8 = "/tmp/nx_envelope_audit_gate/o1.log"
37const EG_O2: *u8 = "/tmp/nx_envelope_audit_gate/o2.log"
38const EG_O3: *u8 = "/tmp/nx_envelope_audit_gate/o3.log"
39
40const EG_S1: *u8 = "/tmp/nx_envelope_audit_gate/buildroot/runtime/_hdl_build/egsilent.nx"
41const EG_S2: *u8 = "/tmp/nx_envelope_audit_gate/buildroot/runtime/_hdl_build/egdecl.nx"
42const EG_S3: *u8 = "/tmp/nx_envelope_audit_gate/buildroot/runtime/_hdl_build/egcmt.nx"
43const EG_S4: *u8 = "/tmp/nx_envelope_audit_gate/buildroot/runtime/_hdl_build/egplain.nx"
44
45const EG_SUBJ1: *u8 = "/volume1/homes/elderwesto/nishihost/nx_envelope_audit.elf"
46const EG_SUBJ2: *u8 = "/volume1/homes/elderwesto/nishihost/_offc/nx_envelope_audit.elf"
47const EG_SUBJ3: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/_build/nx_envelope_audit.sov.elf"
48
49// FIXTURE SHAPE -- the expected counts are DERIVED from these, never re-typed beside them, because a
50// hand-counted expectation beside a generator is a second copy of the generator's shape and the two drift.
51// ⚠ THE FIXTURE SIZE *IS* THE STRENGTH OF THE ROW-CAP TOOTH, AND IT WAS WRONG ON THE FIRST TRY.
52// Measured 2026-08-20: with 100 silent rows this gate went GREEN 12/12 against a mutant that had the row
53// cap RESTORED -- because 117 rows never reached a cap of 512. A fixture the defect cannot fail is not a
54// test, and the green it produces is indistinguishable from a green earned. The count below is therefore
55// larger than the LIVE tool_allowlist.conf row count, so the tooth proves "no fixed row cap at or below
56// this fixture's size binds" -- which is a BOUND, and it is stated here rather than implied.
57// It is deliberately NOT written as "512 + margin": a hand-typed copy of a cap that has been DELETED is
58// still a second copy of that cap's shape, and it would silently stop covering a smaller future cap.
59const EG_N_SILENT: i64 = 1200
60const EG_N_DECL: i64 = 7
61const EG_N_CMT: i64 = 5
62const EG_N_PLAIN: i64 = 3
63const EG_N_MISS: i64 = 2
64// Rows in the SMALL conf: deliberately fewer than the subject's list cap so the prefix marker must be
65// ABSENT -- the good half of the bite. Two, so the tooth is not testing an empty set.
66const EG_N_SMALL: i64 = 2
67// Enough rows to push the allowlist past the subject's own EA_ALLOWCAP and force its PARTIAL path.
68const EG_N_HUGE: i64 = 14000
69
70const EG_CAPBUF: i64 = 1048576
71const EG_CONFBUF: i64 = 2097152
72const EG_PATHB: i64 = 512
73const EG_TAB: i64 = 9
74const EG_NL: i64 = 10
75const EG_HASH: i64 = 35
76
77func eg_wr(path: *u8, buf: *u8, n: i64) -> i64 {
78 let fd: i64 = sys_openat_wr(path, GV_MODE_644)
79 if fd < 0 { return 0 - 1 }
80 gk_write_all(fd, buf, n)
81 sys_close(fd)
82 return n
83}
84// one allowlist row: <name><TAB>/x/<base>.elf<TAB>GREEN<NL>. TAB and NL are CONSTRUCTED as bytes: a bare
85// control character inside a string literal is ambiguous to the nx lexer, and the '#' below cannot appear
86// in a literal at all.
87func eg_row(b: *u8, o: i64, nm: *u8, idx: i64, base: *u8) -> i64 {
88 var p: i64 = gk_cat(b, o, nm)
89 p = gk_catn(b, p, idx)
90 b[p] = EG_TAB as u8; p = p + 1
91 p = gk_cat(b, p, "/x/" as *u8)
92 p = gk_cat(b, p, base)
93 p = gk_cat(b, p, ".elf" as *u8)
94 b[p] = EG_TAB as u8; p = p + 1
95 p = gk_cat(b, p, "GREEN" as *u8)
96 b[p] = EG_NL as u8; p = p + 1
97 return p
98}
99func eg_rows(b: *u8, o: i64, nm: *u8, base: *u8, cnt: i64) -> i64 {
100 var p: i64 = o
101 var i: i64 = 0
102 while i < cnt { p = eg_row(b, p, nm, i + 1, base); i = i + 1 }
103 return p
104}
105// a comment row the subject must NOT count
106func eg_hashrow(b: *u8, o: i64) -> i64 {
107 var p: i64 = o
108 b[p] = EG_HASH as u8; p = p + 1
109 p = gk_cat(b, p, " a comment row that must never be counted" as *u8)
110 b[p] = EG_NL as u8; p = p + 1
111 return p
112}
113// first integer following an ANCHORED needle. Anchors carry their punctuation so a field name repeated in
114// prose or in the partition line cannot be read as the answer -- a parser that matches the DATA instead of
115// the REPORT LINE is how a census reports verdicts its own organ cannot emit.
116func eg_num_after(buf: *u8, n: i64, needle: *u8) -> i64 {
117 let p: i64 = gk_out_pos(buf, n, needle)
118 if p < 0 { return 0 - 1 }
119 var i: i64 = p + gk_len(needle)
120 var v: i64 = 0
121 var got: i64 = 0
122 while i < n {
123 let c: i64 = buf[i] as i64
124 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); got = 1; i = i + 1 } else { i = n } } else { i = n }
125 }
126 if got == 0 { return 0 - 1 }
127 return v
128}
129// LAST non-empty line, by POSITION. Positional anchoring beats textual matching wherever the output is
130// untrusted: the subject quotes field names in its own prose, so any textual anchor can be matched by data.
131// Separate cursor, explicit flag: a loop that exits by writing a sentinel INTO the variable it is
132// searching for erases the answer, and that idiom is exactly what nx_srclint hunts.
133func eg_last_line_is(buf: *u8, n: i64, want: *u8) -> i64 {
134 var e: i64 = n
135 var go: i64 = 1
136 while go == 1 {
137 if e <= 0 { go = 0 } else { if buf[e-1] == (EG_NL as u8) { e = e - 1 } else { go = 0 } }
138 }
139 if e <= 0 { return 0 }
140 var s: i64 = e
141 var go2: i64 = 1
142 while go2 == 1 {
143 if s <= 0 { go2 = 0 } else { if buf[s-1] == (EG_NL as u8) { go2 = 0 } else { s = s - 1 } }
144 }
145 let m: i64 = gk_len(want)
146 if e - s < m { return 0 }
147 var j: i64 = 0
148 var ok: i64 = 1
149 while j < m { if buf[s+j] != want[j] { ok = 0; j = m } else { j = j + 1 } }
150 return ok
151}
152func main(argc: i64, argv: *i64) -> i64 {
153 let ctr: *i64 = gv_ctr()
154 gv_head("=== nx_envelope_audit_gate -- the silent-cap detector must not have a silent cap ===" as *u8)
155
156 // ---- SUBJECT RESOLUTION (probe, never assume; an absent artifact is indistinguishable from a dead
157 // server unless you stat the binary you are about to fork)
158 let subj: *u8 = sys_mmap(EG_PATHB)
159 var have: i64 = 0
160 if gk_exists(EG_SUBJ1) == 1 { gk_cat(subj, 0, EG_SUBJ1); have = 1 }
161 if have == 0 { if gk_exists(EG_SUBJ2) == 1 { gk_cat(subj, 0, EG_SUBJ2); have = 1 } }
162 if have == 0 { if gk_exists(EG_SUBJ3) == 1 { gk_cat(subj, 0, EG_SUBJ3); have = 1 } }
163 if gv_need("a deployed nx_envelope_audit elf to fork" as *u8, have, ctr) == 0 {
164 return gv_verdict("nx_envelope_audit_gate" as *u8, ctr, "SKIPPED: no deployed subject to fork -- I could not look, which is not a finding about the subject" as *u8)
165 }
166
167 // ---- FIXTURE TREE (rebuilt every run: idempotent by construction)
168 gk_mkdir(EG_DIR); gk_mkdir(EG_BR); gk_mkdir(EG_RT); gk_mkdir(EG_HDL)
169 // a BOUNDED source with no declaration marker anywhere -> SILENT-CAP CANDIDATE
170 gk_write(EG_S1, "const Z_CAP: i64 = 4096\nfunc f() -> i64 { return Z_CAP }\n" as *u8)
171 // a BOUNDED source that EMITS a declaration marker in code -> DECLARING
172 gk_write(EG_S2, "const Z_CAP: i64 = 4096\nfunc f() -> i64 { puts(\"scanned=\") return Z_CAP }\n" as *u8)
173 // a BOUNDED source whose ONLY declaration marker sits in a COMMENT -> must stay a CANDIDATE
174 gk_write(EG_S3, "const Z_CAP: i64 = 4096\n// envelope: prose documents a bound, it does not emit one\nfunc f() -> i64 { return Z_CAP }\n" as *u8)
175 // no bound consts at all -> UNBOUNDED-OR-NA
176 gk_write(EG_S4, "func f() -> i64 { return 1 }\n" as *u8)
177
178 let cb: *u8 = sys_mmap(EG_CONFBUF)
179 var p: i64 = eg_hashrow(cb, 0)
180 p = eg_rows(cb, p, "s" as *u8, "egsilent" as *u8, EG_N_SILENT)
181 p = eg_rows(cb, p, "d" as *u8, "egdecl" as *u8, EG_N_DECL)
182 p = eg_rows(cb, p, "c" as *u8, "egcmt" as *u8, EG_N_CMT)
183 p = eg_rows(cb, p, "p" as *u8, "egplain" as *u8, EG_N_PLAIN)
184 p = eg_rows(cb, p, "m" as *u8, "egnosuch" as *u8, EG_N_MISS)
185 eg_wr(EG_CONF, cb, p)
186 let ps: i64 = eg_rows(cb, 0, "s" as *u8, "egsilent" as *u8, EG_N_SMALL)
187 eg_wr(EG_SMALL, cb, ps)
188 let ph: i64 = eg_rows(cb, 0, "z" as *u8, "egplain" as *u8, EG_N_HUGE)
189 eg_wr(EG_HUGE, cb, ph)
190
191 // The subject resolves its probe dirs relative to CWD, so become the fixture tree.
192 sys_chdir(EG_DIR)
193
194 let o1: *u8 = sys_mmap(EG_CAPBUF)
195 let o2: *u8 = sys_mmap(EG_CAPBUF)
196 let o3: *u8 = sys_mmap(EG_CAPBUF)
197 let n1: *i64 = sys_mmap(GV_CTR_BYTES)
198 let n2: *i64 = sys_mmap(GV_CTR_BYTES)
199 let n3: *i64 = sys_mmap(GV_CTR_BYTES)
200 // gk_run tests each optional arg against NULL, not against an empty string -- passing "" would hand
201 // the subject two empty argv elements it never asked for.
202 let rc1: i64 = gk_run_capture(subj, EG_CONF, EG_O1, 0 as *u8, 0 as *u8, o1, EG_CAPBUF, n1)
203 let rc2: i64 = gk_run_capture(subj, EG_SMALL, EG_O2, 0 as *u8, 0 as *u8, o2, EG_CAPBUF, n2)
204 let rc3: i64 = gk_run_capture(subj, EG_HUGE, EG_O3, 0 as *u8, 0 as *u8, o3, EG_CAPBUF, n3)
205 let c1: i64 = n1[0]
206 let c2: i64 = n2[0]
207 let c3: i64 = n3[0]
208
209 // ---- T1 ANTI-VACUITY, FIRST. A census that produced nothing has failed, not passed -- and every
210 // assertion below is read out of this capture, so a green here is the precondition for the rest
211 // meaning anything at all.
212 var t1: i64 = 0
213 if c1 > 0 { if gk_out_has(o1, c1, "ENVELOPE-AUDIT (F227 scale-law sweep) rows=" as *u8) == 1 { t1 = 1 } }
214 gv_check("anti-vacuity-subject-ran-and-emitted-its-report-header" as *u8, t1, ctr)
215
216 let rows: i64 = eg_num_after(o1, c1, ") rows=" as *u8)
217 let decl: i64 = eg_num_after(o1, c1, " declaring=" as *u8)
218 let sil: i64 = eg_num_after(o1, c1, " silent_cap_candidates=" as *u8)
219 let una: i64 = eg_num_after(o1, c1, " unbounded_or_na=" as *u8)
220 let mis: i64 = eg_num_after(o1, c1, " name_probe_miss=" as *u8)
221
222 // PRINT THE VALUES, NOT JUST PASS/FAIL: a gate that reports a boolean cannot say why, and both
223 // vacuous teeth ever found in this estate were caught by a diagnostic dump, never by the verdict
224 // vector. The fixture expectation is printed beside the observation so the BOUND of the row-cap
225 // claim is visible to the reader without opening this source.
226 gv_puts(" [diag] fixture rows=" as *u8); gv_num(EG_N_SILENT + EG_N_DECL + EG_N_CMT + EG_N_PLAIN + EG_N_MISS)
227 gv_puts(" observed rows=" as *u8); gv_num(rows)
228 gv_puts(" declaring=" as *u8); gv_num(decl)
229 gv_puts(" silent=" as *u8); gv_num(sil)
230 gv_puts(" unbounded=" as *u8); gv_num(una)
231 gv_puts(" miss=" as *u8); gv_num(mis)
232 gv_puts(" rc1=" as *u8); gv_num(rc1)
233 gv_puts(" rc3=" as *u8); gv_num(rc3)
234 gv_puts("\n" as *u8)
235
236 // ---- T2 THE ROW-CAP REGRESSION TOOTH. The fixture is deliberately larger than the cap that used to
237 // bind, so a reinstated row cap reports its own cap here instead of the population.
238 let want_rows: i64 = EG_N_SILENT + EG_N_DECL + EG_N_CMT + EG_N_PLAIN + EG_N_MISS
239 var t2: i64 = 0
240 if rows == want_rows { t2 = 1 }
241 gv_check("every-data-row-is-scanned--rows-equals-the-population-not-a-cap" as *u8, t2, ctr)
242
243 // ---- T3 the hash row must not be counted. The conf carries exactly one, so a subject that counted
244 // comment rows would read one too many and this tooth alone would catch it.
245 var t3: i64 = 0
246 if rows == want_rows { if c2 > 0 { if eg_num_after(o2, c2, ") rows=" as *u8) == EG_N_SMALL { t3 = 1 } } }
247 gv_check("neg-control-a-hash-comment-row-is-NOT-counted-as-a-tool" as *u8, t3, ctr)
248
249 // ---- T4 the partition must sum, and the subject must SAY it sums. A partition you cannot reconcile
250 // is a leak, not a measurement.
251 var t4: i64 = 0
252 if decl + sil + una + mis == rows { if gk_out_has(o1, c1, "RECONCILES" as *u8) == 1 { t4 = 1 } }
253 gv_check("partition-sums-to-rows-and-the-subject-declares-it" as *u8, t4, ctr)
254
255 // ---- T5 the comment-only-marker source must land in CANDIDATES, not DECLARING. This is the tooth
256 // that keeps ea_has_code honest: a marker in a comment DOCUMENTS an envelope, it does not EMIT one.
257 var t5: i64 = 0
258 if decl == EG_N_DECL { if sil == EG_N_SILENT + EG_N_CMT { t5 = 1 } }
259 gv_check("neg-control-a-declaration-marker-inside-a-COMMENT-does-NOT-count-as-declaring" as *u8, t5, ctr)
260
261 // ---- T6 the unbounded and missing classes are not swept into a neighbour
262 var t6: i64 = 0
263 if una == EG_N_PLAIN { if mis == EG_N_MISS { t6 = 1 } }
264 gv_check("unbounded-and-name-probe-miss-are-their-own-buckets" as *u8, t6, ctr)
265
266 // ---- T7 BITE on the prefix marker: it must FIRE when the list is a prefix of its count, and stay
267 // SILENT when the list is complete. A marker that fires on everything discriminates nothing.
268 let pm: *u8 = "PREFIX OF ITS OWN COUNT" as *u8
269 var fired_bad: i64 = 0
270 var fired_good: i64 = 0
271 if gk_out_has(o1, c1, pm) == 1 { fired_bad = 1 }
272 if c2 > 0 { if gk_out_has(o2, c2, pm) == 1 { fired_good = 1 } }
273 gv_bite("prefix-of-its-own-count-marker" as *u8, fired_bad, fired_good, ctr)
274
275 // ---- T8 an allowlist larger than the subject's own read cap must REFUSE to publish a confident
276 // distribution: non-zero exit AND the word PARTIAL. A zero from an incomplete scan is still a floor.
277 var t8: i64 = 0
278 if rc3 != 0 { if gk_out_has(o3, c3, "verdict=PARTIAL" as *u8) == 1 { t8 = 1 } }
279 gv_check("oversize-allowlist-exits-NON-ZERO-and-declares-PARTIAL" as *u8, t8, ctr)
280
281 // ---- T9 the positive control for T8. Without it, a subject that refused EVERYTHING would score full
282 // marks on T8: a guard that refuses everything passes every negative test.
283 var t9: i64 = 0
284 if rc1 == 0 { if gk_out_has(o1, c1, "verdict=COMPLETE" as *u8) == 1 { t9 = 1 } }
285 gv_check("positive-control-a-COVERED-run-exits-ZERO-and-declares-COMPLETE" as *u8, t9, ctr)
286
287 // ---- T10 the coverage verdict must be the LAST line, because every positional reader in the estate
288 // takes the final line and the subject quotes its own field names in prose above it.
289 var t10: i64 = 0
290 if eg_last_line_is(o1, c1, "ENVELOPE-AUDIT COVERAGE" as *u8) == 1 { t10 = 1 }
291 gv_check("coverage-verdict-is-the-LAST-line-by-position" as *u8, t10, ctr)
292
293 // ---- T11 the declared caps must be DERIVED from the consts they bound. A hand-typed copy of a cap is
294 // a second copy of that cap's shape, and the two drift silently.
295 var t11: i64 = 0
296 if gk_out_has(o1, c1, "allow_cap=" as *u8) == 1 { if gk_out_has(o1, c1, "coverage_complete=" as *u8) == 1 { if gk_out_has(o1, c1, "list_cap=" as *u8) == 1 { t11 = 1 } } }
297 gv_check("envelope-declares-allow_cap-coverage_complete-and-list_cap" as *u8, t11, ctr)
298
299 // ---- T12 rc2 is the small-conf control: it must also run clean, so T3 and T7's good half rest on a
300 // run that actually happened rather than on an empty capture.
301 var t12: i64 = 0
302 if rc2 == 0 { if c2 > 0 { t12 = 1 } }
303 gv_check("fixture-reached-its-condition-the-small-conf-run-produced-output" as *u8, t12, ctr)
304
305 return gv_verdict("nx_envelope_audit_gate" as *u8, ctr, "hermetic probe tree under /tmp; every expected count DERIVED from the fixture constants that generate it" as *u8)
306}