code wiki / _hdl_build / nx_gate_fixture_ratchet_gate.nx
nx_gate_fixture_ratchet_gate.nx source
↩ module page · 357 lines · 15397 B
1// nx_gate_fixture_ratchet_gate.nx -- A GATE MUST NOT SHARE ITS FIXTURE WITH A PRODUCTION BEAT.
2// 2026-08-07, ws=segstore. SIBLING OF nx_gate_dry_ratchet_gate, deliberately built to the same shape:
3// same corpus, same baseline-file convention, same first-run honesty, same gv_bite non-vacuity cell.
4// Only the TOOTH differs. Matching the known good was the point -- a second ratchet that behaved
5// differently would be a second thing to remember, and the whole value of a ratchet is that nobody
6// has to remember it.
7//
8// WHAT IT RATCHETS. A gate that keeps its scratch planes under knowledge/store/ is sharing a
9// directory with the nx_segguard beat, which sweeps every 600s and folds any plane at or above its
10// threshold. MEASURED 2026-08-07T10:01:56: segguard folded `segracegate-real 23 -> 1` WHILE
11// nx_segrace_gate was mid-run, and the gate then reported "COMPACTION STILL ERASES COMMITTED
12// SEGMENTS -- lost 1". A controlled comparison settled it: the SAME code on a /tmp fixture went
13// GREEN 24/24, the pre-change baseline on the knowledge/store fixture went RED. The RED tracked the
14// FIXTURE, not the code.
15// ★★★★★★A GATE THAT SHARES ITS FIXTURE WITH A PRODUCTION BEAT IS MEASURING THE BEAT.
16// ★A RED THAT A THIRD PARTY CAN CAUSE IS NOT A MEASUREMENT OF THE CODE UNDER TEST.
17//
18// WHY A RATCHET AND NOT A LINT-AND-FIX PASS: fixing the 9 gates that carry this today is O(LEAVES)
19// and does nothing about the tenth someone writes tomorrow. The sibling gate says it best -- "a rule
20// nothing must remember beats a list". This fails if they forget.
21//
22// SCOPE -- CORRECTED 2026-08-07, AND THE CORRECTION IS THE POINT. This header first claimed the
23// defect was LATENT: "segguard has folded ZERO of them". That was measured over NINE planes I
24// happened to have to hand, and all nine came back clean. Re-measured over the FULL population of
25// thirty, the sweeper has touched TEN of them -- 57 logged COMPACT/FAIL/DEFER events, `ledgergate`
26// alone 17 and `citatorgate` 9. So the defect is ACTIVE for a third of the population, not latent.
27// ★★★★★★A SAMPLE THAT RETURNS ZERO IS THE EASIEST KIND TO BELIEVE AND THE MOST LIKELY TO BE
28// UNREPRESENTATIVE -- 0/9 read as "no problem", the true rate was 33%.
29// ★★★★★A LATENT DEFECT AND AN ACTIVE ONE ARE DIFFERENT FACTS -- AND YOU DO NOT KNOW WHICH YOU HAVE
30// UNTIL YOU HAVE ASKED THE WHOLE POPULATION.
31//
32// THE TOOTH: count *_gate.nx sources that name a TEST-FIXTURE plane under knowledge/store/.
33// current > baseline -> RED. Someone added a gate whose fixture the sweeper can rewrite.
34// current < baseline -> GREEN, baseline TIGHTENS. The ratchet only ever closes.
35// current == baseline -> GREEN, no change.
36//
37// DETECTOR, and why it is narrow ON PURPOSE: it fires only when the plane NAME following
38// knowledge/store/ contains gate|test|probe|scratch|fixture. A gate that READS a real production
39// plane is legitimate and must not be flagged; a raw "does the source mention knowledge/store/"
40// check counts 124 gate files, of which only 9 are fixtures. The narrow form is the difference
41// between a worklist and a wall of noise.
42// ★A DETECTOR THAT CANNOT TELL A FIXTURE FROM A LEGITIMATE READ PRODUCES A NUMBER NOBODY ACTS ON.
43//
44// ENVELOPE, declared in-band: FLAT scan of runtime + runtime/_hdl_build under the discovered
45// buildroot -- the same corpus as nx_gate_dry_ratchet_gate, so the two numbers compose.
46// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
47import "nx_syscalls.nx"
48import "nx_gate_verdict.nx"
49
50const FX_DIRBUF: i64 = 262144
51const FX_PATH: i64 = 512
52const FX_SRC: i64 = 262144
53const FX_NAME: i64 = 128
54const FX_RECLEN_OFF: i64 = 16
55const FX_NAME_OFF: i64 = 19
56const FX_MODE: i64 = 420
57const FX_NUM: i64 = 32
58const FX_ZERO: i64 = 48
59const FX_B10: i64 = 10
60const FX_LC_A: i64 = 97
61const FX_LC_Z: i64 = 122
62const FX_D0: i64 = 48
63const FX_D9: i64 = 57
64const FX_DASH: i64 = 45
65const FX_USCORE: i64 = 95
66const FX_BASELINE: *u8 = "knowledge/status/gate_fixture_ratchet.conf"
67
68func fx_exists(path: *u8) -> i64 {
69 let fd: i64 = sys_openat_rd(path)
70 if fd < 0 { return 0 }
71 sys_close(fd)
72 return 1
73}
74
75func fx_enter_buildroot() -> i64 {
76 if fx_exists("runtime/nx_gate_verdict.nx" as *u8) == 1 { return 1 }
77 if sys_chdir("buildroot" as *u8) == 0 {
78 if fx_exists("runtime/nx_gate_verdict.nx" as *u8) == 1 { return 1 }
79 }
80 return 0
81}
82
83func fx_cat(dst: *u8, o: i64, s: *u8) -> i64 {
84 var i: i64 = 0
85 var p: i64 = o
86 while s[i] != (0 as u8) { dst[p] = s[i]; p = p + 1; i = i + 1 }
87 dst[p] = 0 as u8
88 return p
89}
90
91func fx_slurp(path: *u8, buf: *u8, cap: i64) -> i64 {
92 let fd: i64 = sys_openat_rd(path)
93 if fd < 0 { return 0 - 1 }
94 var total: i64 = 0
95 var run: i64 = 1
96 while run == 1 {
97 if total >= cap { run = 0 } else {
98 let r: i64 = sys_read(fd, ((buf as i64) + total) as *u8, cap - total)
99 if r <= 0 { run = 0 } else { total = total + r }
100 }
101 }
102 sys_close(fd)
103 return total
104}
105
106// substring test over a bounded region
107func fx_has(hay: *u8, hn: i64, needle: *u8) -> i64 {
108 var nl: i64 = 0
109 while needle[nl] != (0 as u8) { nl = nl + 1 }
110 if nl == 0 { return 1 }
111 if hn < nl { return 0 }
112 var i: i64 = 0
113 while i <= hn - nl {
114 var m: i64 = 1
115 var c: i64 = 0
116 while c < nl {
117 if hay[i + c] != needle[c] { m = 0; c = nl } else { c = c + 1 }
118 }
119 if m == 1 { return 1 }
120 i = i + 1
121 }
122 return 0
123}
124
125// does this plane NAME mark it as test scaffolding rather than production data?
126func fx_marks_fixture(nm: *u8, n: i64) -> i64 {
127 if fx_has(nm, n, "gate" as *u8) == 1 { return 1 }
128 if fx_has(nm, n, "test" as *u8) == 1 { return 1 }
129 if fx_has(nm, n, "probe" as *u8) == 1 { return 1 }
130 if fx_has(nm, n, "scratch" as *u8) == 1 { return 1 }
131 if fx_has(nm, n, "fixture" as *u8) == 1 { return 1 }
132 return 0
133}
134
135// 1 iff the source names a TEST-FIXTURE plane under knowledge/store/
136func fx_fixture_in_store(buf: *u8, n: i64, nm: *u8) -> i64 {
137 let key: *u8 = "knowledge/store/" as *u8
138 var kl: i64 = 0
139 while key[kl] != (0 as u8) { kl = kl + 1 }
140 if n < kl { return 0 }
141 var i: i64 = 0
142 while i <= n - kl {
143 var m: i64 = 1
144 var c: i64 = 0
145 while c < kl {
146 if buf[i + c] != key[c] { m = 0; c = kl } else { c = c + 1 }
147 }
148 if m == 1 {
149 var j: i64 = i + kl
150 var w: i64 = 0
151 var go: i64 = 1
152 while go == 1 {
153 if j >= n { go = 0 } else {
154 if w >= FX_NAME - 1 { go = 0 } else {
155 let ch: i64 = buf[j] as i64
156 var ok: i64 = 0
157 if ch >= FX_LC_A { if ch <= FX_LC_Z { ok = 1 } }
158 if ch >= FX_D0 { if ch <= FX_D9 { ok = 1 } }
159 if ch == FX_DASH { ok = 1 }
160 if ch == FX_USCORE { ok = 1 }
161 if ok == 1 { nm[w] = buf[j] as u8; w = w + 1; j = j + 1 } else { go = 0 }
162 }
163 }
164 }
165 nm[w] = 0 as u8
166 if fx_marks_fixture(nm, w) == 1 { return 1 }
167 }
168 i = i + 1
169 }
170 return 0
171}
172
173func fx_is_gate_src(nm: *u8, n: i64) -> i64 {
174 if n < 8 { return 0 }
175 let t: *u8 = "_gate.nx" as *u8
176 var k: i64 = 0
177 while k < 8 {
178 if nm[n - 8 + k] != t[k] { return 0 }
179 k = k + 1
180 }
181 return 1
182}
183
184// -1 if the dir cannot be read: a census that cannot read its corpus must REFUSE, never report zero.
185// A zero here would read as "no gate keeps a fixture in the swept store" and TIGHTEN the ratchet to 0,
186// permanently breaking every future run -- the same trap the sibling gate calls out.
187func fx_count_dir(dir: *u8) -> i64 {
188 let fd: i64 = sys_openat_rd(dir)
189 if fd < 0 { return 0 - 1 }
190 let dbuf: *u8 = sys_mmap(FX_DIRBUF)
191 let path: *u8 = sys_mmap(FX_PATH)
192 let src: *u8 = sys_mmap(FX_SRC)
193 let nmb: *u8 = sys_mmap(FX_NAME)
194 var cnt: i64 = 0
195 var n: i64 = sys_getdents64(fd, dbuf, FX_DIRBUF)
196 while n > 0 {
197 var p: i64 = 0
198 while p < n {
199 let reclen: i64 = (dbuf[p + FX_RECLEN_OFF] as i64) + ((dbuf[p + FX_RECLEN_OFF + 1] as i64) * 256)
200 if reclen <= 0 { p = n }
201 else {
202 let nm: *u8 = ((dbuf as i64) + p + FX_NAME_OFF) as *u8
203 var ln: i64 = 0
204 while nm[ln] != (0 as u8) { ln = ln + 1 }
205 if fx_is_gate_src(nm, ln) == 1 {
206 var o: i64 = fx_cat(path, 0, dir)
207 path[o] = 47 as u8
208 o = o + 1
209 var w: i64 = 0
210 while w < ln { path[o + w] = nm[w]; w = w + 1 }
211 path[o + ln] = 0 as u8
212 let sn: i64 = fx_slurp(path, src, FX_SRC)
213 if sn > 0 {
214 if fx_fixture_in_store(src, sn, nmb) == 1 {
215 cnt = cnt + 1
216 // NAME the offender. A count without a worklist is not actionable: the
217 // first version of this organ printed 31 and named none of them, which
218 // tells an operator that work exists but not where.
219 // ★A COUNT WITHOUT A WORKLIST IS NOT ACTIONABLE.
220 // Uncapped ON PURPOSE -- a "first 12 shown" list is a SAMPLE, and a
221 // sample must never stand in for the population it was drawn from.
222 gv_puts(" FIXTURE-IN-SWEPT-STORE: " as *u8)
223 gv_puts(path)
224 gv_puts(" plane=knowledge/store/" as *u8)
225 gv_puts(nmb)
226 gv_puts("\
227" as *u8)
228 }
229 }
230 }
231 p = p + reclen
232 }
233 }
234 n = sys_getdents64(fd, dbuf, FX_DIRBUF)
235 }
236 sys_close(fd)
237 return cnt
238}
239
240func fx_atoi(s: *u8, n: i64) -> i64 {
241 var v: i64 = 0
242 var i: i64 = 0
243 var seen: i64 = 0
244 while i < n {
245 let c: i64 = s[i] as i64
246 if c >= FX_ZERO {
247 if c <= FX_ZERO + 9 { v = v * FX_B10 + (c - FX_ZERO); seen = 1; i = i + 1 }
248 else { i = n }
249 } else { i = n }
250 }
251 if seen == 0 { return 0 - 1 }
252 return v
253}
254
255func fx_write_baseline(v: i64) -> i64 {
256 let b: *u8 = sys_mmap(FX_NUM)
257 var m: i64 = v
258 let t: *u8 = sys_mmap(FX_NUM)
259 var k: i64 = 0
260 if m == 0 { t[0] = FX_ZERO as u8; k = 1 }
261 while m > 0 { t[k] = (FX_ZERO + (m % FX_B10)) as u8; m = m / FX_B10; k = k + 1 }
262 var i: i64 = 0
263 while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
264 b[k] = 10 as u8
265 let fd: i64 = sys_openat_wr(FX_BASELINE, FX_MODE)
266 if fd < 0 { return 0 - 1 }
267 sys_write(fd, b, k + 1)
268 sys_close(fd)
269 return 0
270}
271
272func main(argc: i64, argv: *i64) -> i64 {
273 let ctr: *i64 = gv_ctr()
274 gv_head("=== nx_gate_fixture_ratchet_gate -- no gate may share its fixture with a production beat ===" as *u8)
275
276 if fx_enter_buildroot() == 0 {
277 gv_puts(" no corpus root -- refusing (a ratchet that cannot see its corpus must never tighten)\
278" as *u8)
279 gv_check("T0 corpus root resolved" as *u8, 0, ctr)
280 return gv_verdict("GATE-FIXTURE-RATCHET" as *u8, ctr, "no corpus root" as *u8)
281 }
282 gv_check("T0 corpus root resolved" as *u8, 1, ctr)
283
284 let c1: i64 = fx_count_dir("runtime" as *u8)
285 let c2: i64 = fx_count_dir("runtime/_hdl_build" as *u8)
286 var readable: i64 = 0
287 if c1 >= 0 { if c2 >= 0 { readable = 1 } }
288 gv_check("T1 both corpus dirs readable (a zero from an unreadable dir would tighten the ratchet to 0)" as *u8, readable, ctr)
289 if readable == 0 {
290 return gv_verdict("GATE-FIXTURE-RATCHET" as *u8, ctr, "corpus unreadable" as *u8)
291 }
292 let cur: i64 = c1 + c2
293
294 // DETECTOR NON-VACUITY, on real corpus bytes rather than an arithmetic tautology: a crafted
295 // source naming a fixture plane MUST fire, and one naming a legitimate production plane MUST NOT.
296 // This is the cell that separates "the detector works" from "the detector never says anything".
297 // THE BITE FIXTURES ARE ASSEMBLED AT RUNTIME, NOT WRITTEN AS LITERALS. Written literally, this
298 // gate's own source carries the swept-store prefix followed by a fixture-marked plane name, and
299 // the scan therefore FLAGS ITSELF -- it did, and reported 31 when the truth was 30. The first fix
300 // split the code literal but left the pattern spelled out IN THIS COMMENT, so the count did not
301 // move: prose is source bytes too. Worse than the off-by-one: the next reader sees this
302 // gate on its own worklist, "fixes" it, and silently destroys the bite test that makes the whole
303 // organ non-vacuous. Splitting the literal means the source never carries the pattern contiguously.
304 // ★★★★★A DETECTOR THAT SCANS SOURCE WILL FIND ITS OWN TEST FIXTURE -- ASSEMBLE ITS FIXTURES AT RUNTIME.
305 let nmb: *u8 = sys_mmap(FX_NAME)
306 let badsrc: *u8 = sys_mmap(FX_NAME)
307 var bl: i64 = fx_cat(badsrc, 0, "knowledge/" as *u8)
308 bl = fx_cat(badsrc, bl, "store/" as *u8)
309 bl = fx_cat(badsrc, bl, "wsgate-" as *u8)
310 let goodsrc: *u8 = sys_mmap(FX_NAME)
311 var gl: i64 = fx_cat(goodsrc, 0, "knowledge/" as *u8)
312 gl = fx_cat(goodsrc, gl, "store/" as *u8)
313 gl = fx_cat(goodsrc, gl, "dp-web-pub-" as *u8)
314 let fired: i64 = fx_fixture_in_store(badsrc, bl, nmb)
315 let quiet: i64 = fx_fixture_in_store(goodsrc, gl, nmb)
316 gv_bite("T2 detector fires on a FIXTURE plane and stays silent on a real production plane" as *u8, fired, quiet, ctr)
317
318 let bbuf: *u8 = sys_mmap(FX_NUM)
319 let bn: i64 = fx_slurp(FX_BASELINE, bbuf, FX_NUM)
320 var base: i64 = 0 - 1
321 if bn > 0 { base = fx_atoi(bbuf, bn) }
322
323 gv_puts(" gates with a fixture in the swept store now = " as *u8)
324 gv_num(cur)
325 gv_puts(" baseline = " as *u8)
326 if base < 0 { gv_puts("(none)" as *u8) } else { gv_num(base) }
327 gv_puts("\
328" as *u8)
329
330 if base < 0 {
331 fx_write_baseline(cur)
332 gv_check("T3 baseline INITIALISED -- this run compared NOTHING and is not evidence of health" as *u8, 1, ctr)
333 return gv_verdict("GATE-FIXTURE-RATCHET" as *u8, ctr, "baseline initialised; the NEXT run is the first real comparison" as *u8)
334 }
335
336 var held: i64 = 0
337 if cur <= base { held = 1 }
338 gv_check("T3 fixture-in-swept-store count did not increase since the baseline" as *u8, held, ctr)
339
340 if held == 1 {
341 if cur < base {
342 fx_write_baseline(cur)
343 gv_puts(" ratchet TIGHTENED to " as *u8)
344 gv_num(cur)
345 gv_puts("\
346" as *u8)
347 }
348 return gv_verdict("GATE-FIXTURE-RATCHET" as *u8, ctr, "no gate newly shares its fixture with the segguard beat" as *u8)
349 }
350 gv_puts(" REGRESSION: a gate was added whose scratch planes live under knowledge/store/, where the\
351" as *u8)
352 gv_puts(" 600s nx_segguard beat can fold them mid-run. Move the fixture to /tmp/<gatename>/ and\
353" as *u8)
354 gv_puts(" create it with sys_mkdir at SETUP -- see nx_segrace_gate for the worked fix.\
355" as *u8)
356 return gv_verdict("GATE-FIXTURE-RATCHET" as *u8, ctr, "a gate now shares its fixture with a production beat" as *u8)
357}