code wiki / (root) / nx_d001census.nx

nx_d001census.nx source

↩ module page · 225 lines · 10890 B

1// nx_d001census.nx -- SIZE THE D001 POPULATION INSTEAD OF DISCOVERING IT ONE REFUSED PROMOTE AT A TIME. 2// 3// /api/promote REFUSES a gate that rolls its own verdict (D001): nx_gate_green cannot judge it and it 4// records no harness.jrnl frame, so flake and erosion stay invisible for it. Correct guard. But it fires 5// at PROMOTE time, one gate at a time, so the only way to learn the size of the problem is to keep 6// bouncing off it -- I hit it four times before asking how many there are. 7// *A GUARD THAT ONLY SPEAKS AT THE MOMENT OF ACTION TEACHES YOU THE POPULATION ONE REFUSAL AT A TIME.* 8// 9// This partitions every gate in the tree into the three states that have DIFFERENT REMEDIES, which is the 10// whole point -- "D001" as one bucket is not actionable: 11// OK inherits_base=1 -- nothing to do 12// MIGRATABLE inherits=0, emits_verdict=1 -- nx_gate_dry_apply CAN rewrite it, automatable 13// NEEDS-ANCHOR inherits=0, emits_verdict=0 -- dry_apply SKIPs it ("no verdict=GREEN tail"); 14// needs the anchor rung, a source edit in the 15// gate-owner lane. MEASURED: all 4 I hit are here. 16// PROBE-FAIL is its own bucket: *AN UNPARSED PROBE MUST NEVER FALL INTO A KNOWN STATE*, because the 17// bucket it lands in becomes the number somebody plans a migration campaign against. 18// 19// COMPOSES nx_gate_migrate probe -- never re-derives "is this compliant", because a second implementation 20// of that judgement would drift from the one /api/promote actually enforces, and would disagree exactly 21// when it mattered. 22// ⚠ the probe BUILDS each gate (`builds=1`), so this contends for per-target build leases like any other 23// sweep: bounded by an explicit max, resumable by skip, deadline per probe. 24// 25// nx_d001census <max> [skip] [timeout_ms] [dir] 26// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 27import "nx_tool_run.nx" 28 29const DC_HOST: *u8 = "/volume1/homes/elderwesto/nishihost" 30const DC_PROBE: *u8 = "/volume1/homes/elderwesto/nishihost/nx_gate_migrate.elf" 31const DC_DRY: *u8 = "/volume1/homes/elderwesto/nishihost/nx_gate_dry_apply.elf" 32const DC_DIR: *u8 = "/volume1/homes/elderwesto/nishihost/buildroot/runtime" 33const DC_DIRBUF: i64 = 262144 34const DC_RECLEN_OFF: i64 = 16 35const DC_NAME_OFF: i64 = 19 36const DC_CAP: i64 = 65536 37const DC_DEF_TMO: i64 = 180000 38 39func dcp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 40func dce(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 } 41func dcn(v: i64) -> i64 { 42 var m: i64 = v 43 if m < 0 { dcp("-" as *u8); m = 0 - m } 44 let t: *u8 = sys_mmap(32) 45 var k: i64 = 0 46 if m == 0 { t[0] = 48 as u8; k = 1 } 47 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 48 let b: *u8 = sys_mmap(32) 49 var i: i64 = 0 50 while i < k { b[i] = t[k-1-i]; i = i + 1 } 51 sys_write(1, b, k) 52 return 0 53} 54func dc_atoi(s: *u8) -> i64 { 55 var v: i64 = 0 56 var i: i64 = 0 57 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c < 48 { return 0 - 1 } if c > 57 { return 0 - 1 } v = v*10 + (c-48); i = i + 1 } 58 if i == 0 { return 0 - 1 } 59 return v 60} 61func dc_ends(nm: *u8, sfx: *u8) -> i64 { 62 var ln: i64 = 0 63 while nm[ln] != (0 as u8) { ln = ln + 1 } 64 var ls: i64 = 0 65 while sfx[ls] != (0 as u8) { ls = ls + 1 } 66 if ln < ls { return 0 } 67 var i: i64 = 0 68 while i < ls { if nm[ln-ls+i] != sfx[i] { return 0 } i = i + 1 } 69 return 1 70} 71// find `key` in buf and return the single digit that follows it, or -1. Scans the WHOLE buffer: a merged 72// stdout+stderr capture routinely puts the line you want somewhere other than offset 0. 73func agmig(d: *u8, o: i64, s: *u8) -> i64 { var x: i64=o; var i: i64=0; while s[i]!=(0 as u8){d[x]=s[i];x=x+1;i=i+1} return x } 74// substring present anywhere in the buffer -- never offset 0, a merged capture puts the line elsewhere 75func dc_has(buf: *u8, n: i64, ndl: *u8) -> i64 { 76 var ln: i64 = 0 77 while ndl[ln] != (0 as u8) { ln = ln + 1 } 78 if ln == 0 { return 0 } 79 if n < ln { return 0 } 80 var i: i64 = 0 81 while i <= n - ln { 82 var k: i64 = 0 83 var hit: i64 = 1 84 while k < ln { if buf[i+k] != ndl[k] { hit = 0; k = ln } else { k = k + 1 } } 85 if hit == 1 { return 1 } 86 i = i + 1 87 } 88 return 0 89} 90func dc_flag(buf: *u8, n: i64, key: *u8) -> i64 { 91 var ln: i64 = 0 92 while key[ln] != (0 as u8) { ln = ln + 1 } 93 if n < ln + 1 { return 0 - 1 } 94 var i: i64 = 0 95 while i <= n - ln - 1 { 96 var k: i64 = 0 97 var hit: i64 = 1 98 while k < ln { if buf[i+k] != key[k] { hit = 0; k = ln } else { k = k + 1 } } 99 if hit == 1 { let c: i64 = buf[i+ln] as i64; if c >= 48 { if c <= 57 { return c - 48 } } return 0 - 1 } 100 i = i + 1 101 } 102 return 0 - 1 103} 104 105func main(argc: i64, argv: *i64) -> i64 { 106 if argc < 2 { dce("usage: nx_d001census <max> [skip] [timeout_ms] [dir]\n" as *u8); sys_exit(3); return 3 } 107 let maxn: i64 = dc_atoi(argv[1] as *u8) 108 if maxn <= 0 { dce("nx_d001census: REFUSES an unbounded census; pass max > 0\n" as *u8); sys_exit(3); return 3 } 109 var skip: i64 = 0 110 if argc >= 3 { skip = dc_atoi(argv[2] as *u8) } 111 if skip < 0 { skip = 0 } 112 var tmo: i64 = DC_DEF_TMO 113 if argc >= 4 { tmo = dc_atoi(argv[3] as *u8) } 114 if tmo <= 0 { tmo = DC_DEF_TMO } 115 var dir: *u8 = DC_DIR 116 // an EMPTY positional placeholder means "use the default", never "use nothing" -- passing "" as a 117 // filler silently blanked a path argument earlier today and the organ then failed on an empty file. 118 if argc >= 5 { let d: *u8 = argv[4] as *u8; if d[0] != (0 as u8) { dir = d } } 119 120 let fd: i64 = sys_openat_rd(dir) 121 if fd < 0 { dce("nx_d001census: cannot open dir\n" as *u8); sys_exit(2); return 2 } 122 let db: *u8 = sys_mmap(DC_DIRBUF) 123 let out: *u8 = sys_mmap(DC_CAP) 124 let ol: *i64 = sys_mmap(16) as *i64 125 let tgt: *u8 = sys_mmap(512) 126 let mig: *u8 = sys_mmap(512) 127 let av: *i64 = sys_mmap(64) as *i64 128 129 var idx: i64 = 0 130 var done: i64 = 0 131 var c_ok: i64 = 0 132 var c_mig: i64 = 0 133 var c_anch: i64 = 0 134 var c_bad: i64 = 0 135 136 dcp("# state gate\n" as *u8) 137 var batches: i64 = 0 138 var go: i64 = 1 139 while go == 1 { 140 let n: i64 = sys_getdents64(fd, db, DC_DIRBUF) 141 if n <= 0 { go = 0 } else { 142 batches = batches + 1 143 var p: i64 = 0 144 while p < n { 145 let reclen: i64 = (db[p+DC_RECLEN_OFF] as i64) | ((db[p+DC_RECLEN_OFF+1] as i64) << 8) 146 if reclen <= 0 { p = n } else { 147 let nmo: i64 = p + DC_NAME_OFF 148 let nm: *u8 = ((db as i64) + nmo) as *u8 149 var take: i64 = 0 150 if dc_ends(nm, "_gate.nx" as *u8) == 1 { take = 1 } 151 if (nm[0] as i64) == 46 { take = 0 } 152 if (nm[0] as i64) == 95 { take = 0 } 153 if take == 1 { 154 idx = idx + 1 155 var run: i64 = 1 156 if idx <= skip { run = 0 } 157 if done >= maxn { run = 0 } 158 if run == 1 { 159 var ln: i64 = 0 160 while nm[ln] != (0 as u8) { ln = ln + 1 } 161 var i2: i64 = 0 162 while i2 < ln - 3 { tgt[i2] = nm[i2]; i2 = i2 + 1 } 163 tgt[ln-3] = 0 as u8 164 av[0] = DC_PROBE as i64 165 av[1] = "probe" as *u8 as i64 166 av[2] = tgt as i64 167 av[3] = 0 168 ol[0] = 0 169 tr_run_capture_cwd(DC_PROBE, av, out, DC_CAP, ol, tmo, DC_HOST) 170 let inh: i64 = dc_flag(out, ol[0], "inherits_base=" as *u8) 171 let emi: i64 = dc_flag(out, ol[0], "emits_verdict=" as *u8) 172 // *DO NOT INFER AUTOMATABILITY FROM A PROXY FLAG -- INVOKE THE AUTOMATION AND LOOK. 173 // v1 labelled `emits_verdict=1` as MIGRATABLE. MEASURED AND FALSE: nx_accommodate_gate 174 // probes emits_verdict=1 and dry_apply still SKIPs it ("counter idiom not recognised" 175 // -- it also requires one of 6 known counter shapes). A bucket named after an 176 // automation that has not been ATTEMPTED asserts a capability nobody tested, which is 177 // the exact defect this census exists to prevent, committed inside the census itself. 178 // So the non-inheriting gates now actually run dry_apply and are classified on ITS 179 // outcome, not on a flag that merely correlates with it. 180 if inh < 0 { c_bad = c_bad + 1; dcp("PROBE-FAIL " as *u8) } 181 if inh == 1 { c_ok = c_ok + 1; dcp("OK " as *u8) } 182 if inh == 0 { 183 var mp: i64 = agmig(mig, 0, "/tmp/" as *u8) 184 mp = agmig(mig, mp, tgt) 185 mp = agmig(mig, mp, ".mig.nx" as *u8) 186 mig[mp] = 0 as u8 187 av[0] = DC_DRY as i64 188 av[1] = tgt as i64 189 av[2] = mig as i64 190 av[3] = 0 191 ol[0] = 0 192 tr_run_capture_cwd(DC_DRY, av, out, DC_CAP, ol, tmo, DC_HOST) 193 var skipped: i64 = 0 194 if dc_has(out, ol[0], "SKIP" as *u8) == 1 { skipped = 1 } 195 if skipped == 0 { c_mig = c_mig + 1; dcp("MIGRATABLE " as *u8) } else { 196 c_anch = c_anch + 1 197 if emi == 1 { dcp("BLOCKED-IDIOM " as *u8) } else { dcp("NEEDS-ANCHOR " as *u8) } 198 } 199 } 200 dcp(tgt) 201 dcp("\n" as *u8) 202 done = done + 1 203 } 204 } 205 p = p + reclen 206 } 207 } 208 } 209 } 210 sys_close(fd) 211 if batches == 0 { dce("nx_d001census: not a directory (getdents64 refused)\n" as *u8); sys_exit(2); return 2 } 212 213 dcp("# d001census probed=" as *u8); dcn(done) 214 dcp(" of gates_seen=" as *u8); dcn(idx) 215 dcp(" skip=" as *u8); dcn(skip) 216 dcp(" | OK=" as *u8); dcn(c_ok) 217 dcp(" MIGRATABLE=" as *u8); dcn(c_mig) 218 dcp(" NOT-AUTOMATABLE=" as *u8); dcn(c_anch) 219 dcp(" PROBE-FAIL=" as *u8); dcn(c_bad) 220 dcp("\n# MIGRATABLE = dry_apply WAS RUN and produced a candidate (measured, not inferred) -> nx_gate_migrate verify.\n" as *u8) 221 dcp("# NEEDS-ANCHOR / BLOCKED-IDIOM = dry_apply RAN and SKIPped; the reason differs and so does the remedy:\n" as *u8) 222 dcp("# NEEDS-ANCHOR no verdict=GREEN tail -> anchor rung first (source edit, gate-owner lane)\n" as *u8) 223 dcp("# BLOCKED-IDIOM emits a verdict but its counter shape is none of the 6 dry_apply knows\n" as *u8) 224 return 0 225}