code wiki / _hdl_build / nx_anchorsweep.nx

nx_anchorsweep.nx source

↩ module page · 358 lines · 18101 B

1// nx_anchorsweep.nx -- DRIVE THE ANCHOR RUNG OVER THE 860-GATE NOANCHOR FAMILY. 2// 3// ★WHY THIS EXISTS AND WHY IT IS NOT A DESIGN DECISION. I reported the NOANCHOR family as blocked on 4// human judgement -- "establishing a verdict= tail where none exists" -- and filed that as the reason the 5// D001 lane could not be finished. TWO CALLS REFUTED IT (debt 1786239110): on nx_aa_gate, 6// nx_gate_anchor_edit proposed a candidate and nx_gate_migrate anchor answered 7// exit-code IDENTICAL / PASS-FAIL vector IDENTICAL / before anchor-free YES / after emits anchor YES / 8// verdict==exit AGREES -> GREEN ANCHORED. 9// The judge supplies the judgement, and it checks verdict==exit so it REFUSES A LYING ANCHOR rather than 10// blessing a wrong verdict. ★A CLAIM THAT SOMETHING NEEDS HUMAN AUTHORITY MUST BE EARNED BY TRYING THE 11// TOOL FIRST -- the cheapest experiment was two calls and I declared a blocker without running them. 12// 13// ★COMPOSES TWO RULERS, RE-IMPLEMENTS NEITHER: worklist from knowledge/status/drysweep.log (the census is 14// the single source of truth), judgement from nx_gate_anchor_edit + nx_gate_migrate anchor. This TALLIES. 15// 16// ★ALL FOUR DEFECTS FOUND IN nx_adoptsweep ARE FIXED HERE FROM THE START, not rediscovered: 17// 1. GENERATION SCAN -- drysweep.log is append-only with one block per census, each ended by 18// DRYSWEEP-TOTAL. Reading the whole file sums generations (measured: 605+586=1191 reported as the 19// population). Read between the SECOND-TO-LAST and LAST totals; that also picks up reclassification. 20// 2. EMPTY-WORKLIST REFUSAL -- a sweep that processes nothing must NOT report a clean run. The broken 21// v1 scan printed `partition: 0 of 0 -- SUMS` with no errors. A tooth that passes on the empty set 22// is not a tooth. 23// 3. PER-RUN CANDIDATE PATH -- a fixed /tmp path lets two concurrent sweeps hand each other's candidate 24// to the judge. Suffixed by <skip> so batches are disjoint BY CONSTRUCTION, not by luck. 25// 4. ALREADY-ANCHORED IS A SUCCESS, NOT AN ERROR -- and it is excluded from the rate's denominator. 26// 27// ⚠MUTATES SOURCE: nx_gate_migrate anchor COMMITS on acceptance (.premigrate kept, rule 13) and RESTORES 28// on divergence. <max> is mandatory; measure a batch, read it, then size the next one. 29// 30// nx_anchorsweep <max> [skip] 31// exit: 0 all anchored | 1 any REFUSED/ERROR | 2 usage | 3 NO-CONCLUSION (empty worklist / ruler missing) 32// license_tier: ORIGINAL No hw writes (Rule 26). 33import "nx_syscalls.nx" 34import "nx_artifact_root.nx" 35import "nx_tool_run.nx" 36const AN_MAGIC_20000: i64 = 20000 37const AN_MAGIC_4096: i64 = 4096 38const AN_MAGIC_4095: i64 = 4095 39 40const AN_CENSUS: *u8 = "knowledge/status/drysweep.log" 41const AN_LOG: *u8 = "knowledge/status/anchorsweep.log" 42const AN_SRCCAP: i64 = 4194304 43const AN_OUTCAP: i64 = 65536 44const AN_TIMEOUT: i64 = 120000 45const AN_NAMECAP: i64 = 512 46 47func an_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 48func an_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 49func an_n(fd: i64, v: i64) -> i64 { 50 if v == 0 { sys_write(fd, "0" as *u8, 1); return 0 } 51 var m: i64 = v 52 if m < 0 { sys_write(fd, "-" as *u8, 1); m = 0 - m } 53 let t: *u8 = sys_mmap(32); var k: i64 = 0 54 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 55 let o: *u8 = sys_mmap(32); var i: i64 = 0 56 while i < k { o[i] = t[k-1-i]; i = i + 1 } 57 sys_write(fd, o, k) 58 return 0 59} 60func an_has(buf: *u8, n: i64, pat: *u8) -> i64 { 61 var pl: i64 = 0 62 while pat[pl] != (0 as u8) { pl = pl + 1 } 63 if pl == 0 { return 0 } 64 var i: i64 = 0 65 while i + pl <= n { 66 var k: i64 = 0 67 var ok: i64 = 1 68 while k < pl { if buf[i+k] != pat[k] { ok = 0; k = pl } else { k = k + 1 } } 69 if ok == 1 { return 1 } 70 i = i + 1 71 } 72 return 0 73} 74func an_lastidx(buf: *u8, n: i64, pat: *u8) -> i64 { 75 var pl: i64 = 0 76 while pat[pl] != (0 as u8) { pl = pl + 1 } 77 if pl == 0 { return 0 - 1 } 78 var best: i64 = 0 - 1 79 var i: i64 = 0 80 while i + pl <= n { 81 var k: i64 = 0 82 var ok: i64 = 1 83 while k < pl { if buf[i+k] != pat[k] { ok = 0; k = pl } else { k = k + 1 } } 84 if ok == 1 { best = i } 85 i = i + 1 86 } 87 return best 88} 89func an_atoi(s: *u8) -> i64 { 90 var n: i64 = 0 91 var i: i64 = 0 92 while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { n = n*10 + (c-48) } } i = i + 1 } 93 return n 94} 95func an_cat(dst: *u8, o: i64, s: *u8) -> i64 { 96 var i: i64 = 0 97 var w: i64 = o 98 while s[i] != (0 as u8) { dst[w] = s[i]; w = w + 1; i = i + 1 } 99 dst[w] = 0 as u8 100 return w 101} 102 103// ★RESOLVE THE GATE'S SOURCE, DO NOT ASSUME ONE DIRECTORY. Gates live in BOTH runtime/_hdl_build/ and 104// runtime/ (nx_security_census_gate is in the latter). Guessing one and reporting ERROR for the other 105// would slander half the family as unprocessable. Try both through the estate's ONE resolver. 106func an_srcpath(gname: *u8, out: *u8) -> i64 { 107 let probe: *u8 = sys_mmap(AN_NAMECAP) 108 var o: i64 = an_cat(probe, 0, "runtime/_hdl_build/" as *u8) 109 o = an_cat(probe, o, gname) 110 o = an_cat(probe, o, ".nx" as *u8) 111 if ar_resolve(probe, out) == 1 { return 1 } 112 o = an_cat(probe, 0, "runtime/" as *u8) 113 o = an_cat(probe, o, gname) 114 o = an_cat(probe, o, ".nx" as *u8) 115 if ar_resolve(probe, out) == 1 { return 1 } 116 return 0 117} 118 119func main(argc: i64, argv: *i64) -> i64 { 120 if argc < 2 { an_puts("usage: nx_anchorsweep <max> [skip] -- MUTATES SOURCE via nx_gate_migrate anchor; max is mandatory\n" as *u8); sys_exit(2); return 2 } 121 let maxn: i64 = an_atoi(argv[1] as *u8) 122 var skipn: i64 = 0 123 if argc >= 3 { skipn = an_atoi(argv[2] as *u8) } 124 if maxn <= 0 { an_puts("nx_anchorsweep: max must be > 0 -- refusing an unbounded batch\n" as *u8); sys_exit(2); return 2 } 125 126 let aelf: *u8 = sys_mmap(AN_NAMECAP) 127 let melf: *u8 = sys_mmap(AN_NAMECAP) 128 if ar_resolve("nx_gate_anchor_edit.elf" as *u8, aelf) == 0 { an_puts("nx_anchorsweep: nx_gate_anchor_edit.elf unresolvable -- NO CONCLUSION\n" as *u8); sys_exit(3); return 3 } 129 if ar_resolve("nx_gate_migrate.elf" as *u8, melf) == 0 { an_puts("nx_anchorsweep: nx_gate_migrate.elf unresolvable -- NO CONCLUSION\n" as *u8); sys_exit(3); return 3 } 130 131 let cpath: *u8 = sys_mmap(AN_NAMECAP) 132 if ar_resolve(AN_CENSUS, cpath) == 0 { an_puts("nx_anchorsweep: drysweep.log not found -- run nx_drysweep first. NO CONCLUSION\n" as *u8); sys_exit(3); return 3 } 133 let src: *u8 = sys_mmap(AN_SRCCAP) 134 let n: i64 = ar_read(cpath, src, AN_SRCCAP - 1) 135 if n <= 0 { an_puts("nx_anchorsweep: census unreadable -- NO CONCLUSION\n" as *u8); sys_exit(3); return 3 } 136 137 // per-run candidate path (fix 3) 138 let candp: *u8 = sys_mmap(AN_NAMECAP) 139 var co: i64 = an_cat(candp, 0, "/tmp/anchorsweep_cand_" as *u8) 140 if skipn == 0 { candp[co] = 48 as u8; co = co + 1; candp[co] = 0 as u8 } 141 if skipn > 0 { 142 let ct: *u8 = sys_mmap(32) 143 var ck: i64 = 0 144 var cm: i64 = skipn 145 while cm > 0 { ct[ck] = (48 + (cm % 10)) as u8; cm = cm / 10; ck = ck + 1 } 146 var cj: i64 = 0 147 while cj < ck { candp[co] = ct[ck - 1 - cj]; co = co + 1; cj = cj + 1 } 148 candp[co] = 0 as u8 149 } 150 co = an_cat(candp, co, ".nx" as *u8) 151 an_puts(" candidate path: " as *u8); an_puts(candp); an_puts("\n" as *u8) 152 153 // ★ADMISSION CONTROL -- SHARES THE SAME 3 LEASES AS nx_adoptsweep ON PURPOSE. The saturating 154 // resource is CONCURRENT SOVEREIGN BUILDS across ALL sweeps, not per-organ; separate lease pools 155 // per organ would let 3 adopter + 3 anchor sweeps run and reproduce the outage exactly. 156 // Proven contract: LS-ACQUIRED / LS-BUSY <holder> / LS-RELEASED. 157 let lelf: *u8 = sys_mmap(AN_NAMECAP) 158 var gotlease: i64 = 0 159 if ar_resolve("nx_lease.elf" as *u8, lelf) == 1 { 160 let lout: *u8 = sys_mmap(AN_OUTCAP) 161 let llen: *i64 = sys_mmap(16) as *i64 162 let lav: *i64 = sys_mmap(64) as *i64 163 let s1: *u8 = "gatesweep_1" 164 let s2: *u8 = "gatesweep_2" 165 let s3: *u8 = "gatesweep_3" 166 var slot: i64 = 1 167 while slot <= 3 { 168 var lname: *u8 = s1 169 if slot == 2 { lname = s2 } 170 if slot == 3 { lname = s3 } 171 lout[0] = 0 as u8; llen[0] = 0 172 lav[0] = lelf as i64; lav[1] = "acquire" as *u8 as i64; lav[2] = lname as i64 173 lav[3] = candp as i64; lav[4] = "7200" as *u8 as i64; lav[5] = 0 174 tr_run_capture_to(lelf, lav, lout, AN_OUTCAP - 1, llen, AN_MAGIC_20000) 175 if llen[0] > 0 { if an_has(lout, llen[0], "LS-ACQUIRED" as *u8) == 1 { 176 gotlease = 1 177 an_puts(" lease: " as *u8); an_puts(lname); an_puts("\n" as *u8) 178 slot = 4 179 } } 180 if gotlease == 0 { slot = slot + 1 } 181 } 182 if gotlease == 0 { 183 an_puts(" ★ALL 3 SWEEP LEASES HELD -- refusing to start another concurrent sweep.\n" as *u8) 184 an_puts(" verdict=NO-CONCLUSION\n" as *u8) 185 sys_exit(3); return 3 186 } 187 } 188 if ar_resolve("nx_lease.elf" as *u8, lelf) == 0 { 189 an_puts(" ⚠nx_lease.elf unresolvable -- running WITHOUT concurrency admission control.\n" as *u8) 190 } 191 192 let lf: i64 = sys_openat_append(AN_LOG, 0x1a4) 193 let out: *u8 = sys_mmap(AN_OUTCAP) 194 let olen: *i64 = sys_mmap(16) as *i64 195 let gname: *u8 = sys_mmap(AN_NAMECAP) 196 let spath: *u8 = sys_mmap(AN_NAMECAP) 197 let av: *i64 = sys_mmap(64) as *i64 198 199 var seen: i64 = 0 200 var done: i64 = 0 201 var anch: i64 = 0 202 var refu: i64 = 0 203 var alrdy: i64 = 0 204 var errn: i64 = 0 205 an_puts("=== nx_anchorsweep -- anchoring the NOANCHOR family; nx_gate_migrate anchor is the judge ===\n" as *u8) 206 207 // newest generation only (fix 1) 208 var i: i64 = 0 209 let l1: i64 = an_lastidx(src, n, "DRYSWEEP-TOTAL" as *u8) 210 if l1 > 0 { 211 let l2: i64 = an_lastidx(src, l1, "DRYSWEEP-TOTAL" as *u8) 212 if l2 >= 0 { i = l2 } 213 } 214 while i < n { 215 var e: i64 = i 216 var eol: i64 = 0 217 while eol == 0 { if e >= n { eol = 1 } else { if src[e] == (10 as u8) { eol = 1 } else { e = e + 1 } } } 218 let ll: i64 = e - i 219 if ll > 20 { 220 let line: *u8 = (src as i64 + i) as *u8 221 if an_has(line, ll, "class=SKIP-NOANCHOR" as *u8) == 1 { 222 seen = seen + 1 223 if seen > skipn { if done < maxn { 224 var p: i64 = 0 225 var gs: i64 = 0 - 1 226 while p + 5 <= ll { 227 if line[p] == (103 as u8) { if line[p+1] == (97 as u8) { if line[p+2] == (116 as u8) { if line[p+3] == (101 as u8) { if line[p+4] == (61 as u8) { if gs < 0 { gs = p + 5 } } } } } } 228 p = p + 1 229 } 230 if gs >= 0 { 231 var k: i64 = 0 232 var stop: i64 = 0 233 while stop == 0 { 234 if gs + k >= ll { stop = 1 } 235 if gs + k < ll { 236 let c: i64 = line[gs+k] as i64 237 if c == 32 { stop = 1 } 238 if c != 32 { 239 if k >= AN_NAMECAP - 1 { stop = 1 } 240 if k < AN_NAMECAP - 1 { gname[k] = line[gs+k]; k = k + 1 } 241 } 242 } 243 } 244 gname[k] = 0 as u8 245 var cls: *u8 = "ERROR-NOSRC" as *u8 246 if an_srcpath(gname, spath) == 1 { 247 out[0] = 0 as u8; olen[0] = 0 248 av[0] = aelf as i64; av[1] = spath as i64; av[2] = candp as i64; av[3] = 0 249 tr_run_capture_to(aelf, av, out, AN_OUTCAP - 1, olen, AN_TIMEOUT) 250 cls = "ERROR-EDIT" as *u8 251 if olen[0] > 0 { 252 if an_has(out, olen[0], "NOEDIT" as *u8) == 1 { cls = "ALREADY-ANCHORED" as *u8 } 253 if an_has(out, olen[0], "CANDIDATE-WRITTEN" as *u8) == 1 { 254 out[0] = 0 as u8; olen[0] = 0 255 av[0] = melf as i64; av[1] = "anchor" as *u8 as i64; av[2] = gname as i64; av[3] = candp as i64; av[4] = 0 256 tr_run_capture_to(melf, av, out, AN_OUTCAP - 1, olen, AN_TIMEOUT) 257 cls = "ERROR-JUDGE" as *u8 258 if olen[0] > 0 { 259 if an_has(out, olen[0], "ALREADY-ANCHORED" as *u8) == 1 { cls = "ALREADY-ANCHORED" as *u8 } 260 if an_has(out, olen[0], "ANCHORED" as *u8) == 1 { if an_has(out, olen[0], "ALREADY-ANCHORED" as *u8) == 0 { cls = "ANCHORED" as *u8 } } 261 if an_has(out, olen[0], "ANCHORED" as *u8) == 0 { cls = "REFUSED" as *u8 } 262 } 263 } 264 } 265 } 266 if an_has(cls, 8, "ANCHORED" as *u8) == 1 { if an_has(cls, 16, "ALREADY-ANCHORED" as *u8) == 0 { anch = anch + 1 } } 267 if an_has(cls, 16, "ALREADY-ANCHORED" as *u8) == 1 { alrdy = alrdy + 1 } 268 if an_has(cls, 7, "REFUSED" as *u8) == 1 { refu = refu + 1 } 269 if an_has(cls, 5, "ERROR" as *u8) == 1 { errn = errn + 1 } 270 an_puts(" " as *u8); an_puts(cls); an_puts(" " as *u8); an_puts(gname); an_puts("\n" as *u8) 271 if lf >= 0 { 272 an_w(lf, "ANCHORSWEEP gate=" as *u8); an_w(lf, gname) 273 an_w(lf, " class=" as *u8); an_w(lf, cls); an_w(lf, "\n" as *u8) 274 } 275 done = done + 1 276 } 277 } } 278 } 279 } 280 i = e + 1 281 } 282 283 // ★RELEASE THE LEASE (same defect fixed in nx_adoptsweep -- acquire-without-release turns the guard 284 // into a 7200s lockout after three completed runs; it fails looking exactly like the guard working). 285 // Safe to try all three: nx_lease release is OWNER-CHECKED (wrong owner -> LS-REFUSED not-holder). 286 if gotlease == 1 { 287 let rout: *u8 = sys_mmap(AN_MAGIC_4096) 288 let rlen: *i64 = sys_mmap(16) as *i64 289 let rav: *i64 = sys_mmap(64) as *i64 290 let r1: *u8 = "gatesweep_1" 291 let r2: *u8 = "gatesweep_2" 292 let r3: *u8 = "gatesweep_3" 293 var rs: i64 = 1 294 while rs <= 3 { 295 var rname: *u8 = r1 296 if rs == 2 { rname = r2 } 297 if rs == 3 { rname = r3 } 298 rout[0] = 0 as u8; rlen[0] = 0 299 rav[0] = lelf as i64; rav[1] = "release" as *u8 as i64; rav[2] = rname as i64 300 rav[3] = candp as i64; rav[4] = 0 301 tr_run_capture_to(lelf, rav, rout, AN_MAGIC_4095, rlen, AN_MAGIC_20000) 302 if rlen[0] > 0 { if an_has(rout, rlen[0], "LS-RELEASED" as *u8) == 1 { 303 an_puts(" lease released: " as *u8); an_puts(rname); an_puts("\n" as *u8) 304 } } 305 rs = rs + 1 306 } 307 } 308 309 // empty-worklist refusal (fix 2) 310 if seen == 0 { 311 an_puts("\n ★EMPTY WORKLIST -- no SKIP-NOANCHOR rows in the newest census generation.\n" as *u8) 312 an_puts(" REFUSING to report a clean run over zero gates. verdict=NO-CONCLUSION\n" as *u8) 313 sys_exit(3); return 3 314 } 315 // ★ATTEMPTED NOTHING IS NOT A CLEAN RUN (same defect fixed in nx_adoptsweep): skip beyond the 316 // population slips past the seen==0 guard and yields zero work plus a NEGATIVE deferred, reported 317 // GREEN. Refuse before printing a summary that reads as a result. 318 if done == 0 { 319 an_puts("\n ★ATTEMPTED NOTHING -- skip is at or beyond the population (" as *u8); an_n(1, seen) 320 an_puts(" NOANCHOR rows in the newest census generation).\n" as *u8) 321 an_puts(" REFUSING to report a verdict over zero attempted gates. verdict=NO-CONCLUSION\n" as *u8) 322 sys_exit(3); return 3 323 } 324 let sum: i64 = anch + refu + alrdy + errn 325 an_puts("\n noanchor_in_census=" as *u8); an_n(1, seen) 326 an_puts(" attempted=" as *u8); an_n(1, done) 327 an_puts("\n ANCHORED=" as *u8); an_n(1, anch) 328 an_puts(" REFUSED=" as *u8); an_n(1, refu) 329 an_puts(" ALREADY-ANCHORED=" as *u8); an_n(1, alrdy) 330 an_puts(" ERROR=" as *u8); an_n(1, errn) 331 let genuine: i64 = anch + refu 332 an_puts("\n genuine_attempts=" as *u8); an_n(1, genuine) 333 if genuine > 0 { an_puts(" anchor_permil=" as *u8); an_n(1, (anch * 1000) / genuine) } 334 an_puts(" partition: " as *u8); an_n(1, sum); an_puts(" of " as *u8); an_n(1, done) 335 if sum == done { an_puts(" -- SUMS\n" as *u8) } 336 if sum != done { an_puts(" -- ⚠DOES NOT SUM\n" as *u8) } 337 var deferred: i64 = seen - skipn - done 338 if deferred < 0 { deferred = 0 } 339 if deferred > 0 { 340 an_puts(" ⚠DEFERRED " as *u8); an_n(1, deferred) 341 an_puts(" gate(s) -- BOUNDED BATCH, NOT THE CLASS. resume with skip=" as *u8); an_n(1, skipn + done); an_puts("\n" as *u8) 342 } 343 if lf >= 0 { 344 an_w(lf, "ANCHORSWEEP-TOTAL noanchor=" as *u8); an_n(lf, seen) 345 an_w(lf, " attempted=" as *u8); an_n(lf, done) 346 an_w(lf, " anchored=" as *u8); an_n(lf, anch) 347 an_w(lf, " refused=" as *u8); an_n(lf, refu) 348 an_w(lf, " already=" as *u8); an_n(lf, alrdy) 349 an_w(lf, " genuine=" as *u8); an_n(lf, genuine) 350 an_w(lf, " error=" as *u8); an_n(lf, errn) 351 an_w(lf, " deferred=" as *u8); an_n(lf, deferred) 352 an_w(lf, " verdict=" as *u8) 353 if refu + errn == 0 { an_w(lf, "GREEN\n" as *u8) } else { an_w(lf, "RED\n" as *u8) } 354 sys_close(lf) 355 } 356 if refu + errn > 0 { sys_exit(1); return 1 } 357 sys_exit(0); return 0 358}