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}