code wiki / (root) / nx_comparetree_lib_gate.nx

nx_comparetree_lib_gate.nx source

↩ module page · 1014 lines · 52151 B

1// nx_comparetree_lib_gate.nx -- the referee for the two-tree /compare resolver (nx_comparetree_lib). 2// 3// WHAT MAKES THIS GATE REAL RATHER THAN DECORATIVE: 4// * IN-PROCESS. It imports the lib and calls it directly, so nx_gate_bite can mutate the lib and 5// watch this go RED. A gate that fork/execs a deployed elf reports NOT-REACHED for every mutant and 6// its GREEN proves nothing about the code under test. 7// * REAL FILES, NOT A SIMULATION. The three resolution cases are exercised against actual fixture 8// files under /tmp/<gate>/, because the defect being guarded is a FILESYSTEM LOOKUP. A gate that 9// only tested the pure decision would pass while the resolver read the wrong path. 10// * THE FIXTURE IS ASSERTED BEFORE THE OUTCOME. If the fixture write failed, every "resolves to 11// secondary" tooth below would pass for the wrong reason -- an absent file resolves nowhere. 12// * ANTI-VACUITY BY CONTENT. Each case checks the BYTES RETURNED, not just the which-tree flag. A 13// trivial implementation that always sets the flag to PRIMARY and reads nothing cannot pass, and 14// that implementation is kept here as cg_wrong_pick so the claim is demonstrated, not asserted. 15// * cwd-INDEPENDENT. Fixtures are absolute and the production-order teeth compare constants, so this 16// gate cannot pass or fail because of where a runner happened to start it. 17// license_tier: ORIGINAL 18import "nx_syscalls.nx" 19import "nx_gate_verdict.nx" 20import "nx_comparetree_lib.nx" 21 22const CG_MODE_755: i64 = 493 23const CG_MODE_644: i64 = 420 24const CG_BUF: i64 = 4096 25const CG_PATH: i64 = 512 26 27const CG_ROOT: *u8 = "/tmp/nx_comparetree_lib_gate" 28const CG_MK_P: *u8 = "/tmp/nx_comparetree_lib_gate/p" 29const CG_MK_S: *u8 = "/tmp/nx_comparetree_lib_gate/s" 30// the same two dirs WITH the trailing slash, which is what ct_build_path concatenates against 31const CG_DIR_P: *u8 = "/tmp/nx_comparetree_lib_gate/p/" 32const CG_DIR_S: *u8 = "/tmp/nx_comparetree_lib_gate/s/" 33// a directory that does not exist -- the control that proves the secondary lookup is load-bearing 34const CG_DIR_NONE: *u8 = "/tmp/nx_comparetree_lib_gate/no_such_dir/" 35const CG_SUF: *u8 = ".matrix" 36 37// Bodies differ in BOTH content and LENGTH, so which tree answered is provable from the bytes rather 38// than from the flag the resolver sets about itself. 39const CG_BODY_P_BOTH: *u8 = "PRIMARY-TREE-BOTH\n" 40const CG_BODY_S_BOTH: *u8 = "SECONDARY-TREE-BOTH-AND-LONGER\n" 41const CG_BODY_P_ONLY: *u8 = "PRIMARY-ONLY\n" 42const CG_BODY_S_ONLY: *u8 = "SECONDARY-ONLY-LONGER\n" 43 44func cg_zlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 45func eq(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 } 46func ne(a: i64, b: i64) -> i64 { if a == b { return 0 } return 1 } 47 48func cg_say(s: *u8) -> i64 { 49 var n: i64 = 0 50 while s[n] != (0 as u8) { n = n + 1 } 51 sys_write(1, s, n) 52 return 0 53} 54func cg_num(v: i64) -> i64 { 55 let t: *u8 = sys_mmap(32) 56 var m: i64 = v 57 if m == 0 { sys_write(1, "0" as *u8, 1); return 0 } 58 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 59 var k: i64 = 0 60 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 61 let o: *u8 = sys_mmap(32) 62 var j: i64 = 0 63 while k > 0 { k = k - 1; o[j] = t[k]; j = j + 1 } 64 sys_write(1, o, j) 65 return 0 66} 67 68func cg_write(path: *u8, body: *u8) -> i64 { 69 let fd: i64 = sys_openat_wr(path, CG_MODE_644) 70 if fd < 0 { return 0 } 71 let n: i64 = cg_zlen(body) 72 let wr: i64 = sys_write(fd, body, n) 73 sys_close(fd) 74 if wr == n { return 1 } 75 return 0 76} 77 78func cg_streq(a: *u8, b: *u8) -> i64 { 79 var i: i64 = 0 80 while a[i] != (0 as u8) { 81 if a[i] != b[i] { return 0 } 82 i = i + 1 83 } 84 if b[i] != (0 as u8) { return 0 } 85 return 1 86} 87 88// buf[0..n) against a NUL-terminated expected body -- LENGTH INCLUDED, so a short read cannot pass. 89func cg_bufeq(buf: *u8, n: i64, exp: *u8) -> i64 { 90 let m: i64 = cg_zlen(exp) 91 if n != m { return 0 } 92 var i: i64 = 0 93 while i < m { 94 if buf[i] != exp[i] { return 0 } 95 i = i + 1 96 } 97 return 1 98} 99 100// THE WRONG IMPLEMENTATION, kept in the gate as the thing the teeth must be able to catch. This is 101// precisely what a single-hard-coded-prefix reader does: it concludes PRIMARY no matter what it found. 102func cg_wrong_pick(n1: i64, n2: i64) -> i64 { return CT_TREE_PRIMARY } 103 104// ================================================================================================ 105// THE OVERSIZE FIXTURE -- a file BIGGER than the read cap that was removed on 2026-09-01. 106// 107// CG_OLD_CAP is not a number this gate chose. It is the exact reserve nx_swcompare_evidence used to 108// hand ct_read for a .matrix, so a fixture of CG_OLD_CAP + pad + tail straddles PRECISELY the boundary 109// the silent truncation lived on. charsim.matrix measures 67,965 B against that 65,536 B reserve: the 110// referee graded a prefix, dropped five rows including that board's own LIAR-KILL row and its 111// operator-acceptance row, and published "grounded 25/25 | unsupported 0" anyway. 112// 113// CG_BIG_TAIL IS WRITTEN LAST AND ITS BYTES APPEAR NOWHERE IN THE FILLER, so "the reader reached the 114// end of the file" is decidable BY CONTENT. A reader that reported the right byte COUNT while holding 115// only a 65,536-byte prefix would pass a length check and fails the tail check -- which is the whole 116// difference between a tooth and a decoration here. 117// ================================================================================================ 118const CG_OLD_CAP: i64 = 65536 119const CG_BIG_PAD: i64 = 3000 120const CG_BIG_FILL: i64 = 46 121const CG_BIG_TAIL: *u8 = "TAIL-PAST-THE-OLD-CAP\n" 122const CG_BIG_DOM: *u8 = "big" 123 124func cg_gt(a: i64, b: i64) -> i64 { if a > b { return 1 } return 0 } 125 126// Writes the fixture and returns its EXACT byte count, or 0 if any part of the write failed. The write 127// LOOPS: a short write on a 68 KB body would leave a smaller fixture that still looked written, and a 128// fixture that quietly stopped straddling the boundary is the vacuous-test defect wearing a green. 129func cg_write_big(path: *u8) -> i64 { 130 let tn: i64 = cg_zlen(CG_BIG_TAIL) 131 let head: i64 = CG_OLD_CAP + CG_BIG_PAD 132 let total: i64 = head + tn 133 let body: *u8 = sys_mmap(total + 16) 134 var i: i64 = 0 135 while i < head { body[i] = CG_BIG_FILL as u8; i = i + 1 } 136 var k: i64 = 0 137 while k < tn { body[head + k] = CG_BIG_TAIL[k]; k = k + 1 } 138 let fd: i64 = sys_openat_wr(path, CG_MODE_644) 139 if fd < 0 { return 0 } 140 var off: i64 = 0 141 var okw: i64 = 1 142 var go: i64 = 1 143 while go == 1 { 144 if off >= total { go = 0 } else { 145 let n: i64 = sys_write(fd, ((body as i64) + off) as *u8, total - off) 146 if n <= 0 { okw = 0; go = 0 } else { off = off + n } 147 } 148 } 149 sys_close(fd) 150 if okw == 0 { return 0 } 151 if off != total { return 0 } 152 return total 153} 154 155// does buf[0..n) END with exp? The anti-vacuity check for a full read: a byte COUNT can be reported 156// without having been read, a TAIL cannot. 157func cg_tail_is(buf: *u8, n: i64, exp: *u8) -> i64 { 158 let m: i64 = cg_zlen(exp) 159 if n < m { return 0 } 160 var i: i64 = 0 161 while i < m { 162 if buf[n - m + i] != exp[i] { return 0 } 163 i = i + 1 164 } 165 return 1 166} 167 168// ================================================================================================ 169// THE ADOPTION CENSUS -- THE PART THAT MAKES THIS GATE'S SUBJECT THE FLEET AND NOT ONLY THE LIB. 170// 171// EVERY TOOTH ABOVE HAS THE LIB ITSELF AS ITS SUBJECT. They prove the resolver WORKS; not one of them 172// measures whether anybody CALLS it -- so this gate would have stayed GREEN through every recurrence of 173// the very defect it was written for. Measured 2026-08-31: the resolver has ONE production consumer 174// (nx_swcompare_evidence) while dozens of organs still name a compare tree by hand, and the two-tree 175// blindness has now been independently rediscovered FOUR times (2026-08-20, 2026-08-25, 2026-08-26/27, 176// 2026-08-31), each rediscovery costing a seat the same investigation from scratch. 177// 178// THE REMEDY SO FAR WAS "TEACH EACH NEW READER ABOUT BOTH TREES", WHICH IS O(READERS) FOREVER AND FAILS 179// FOR EVERY READER NOBODY TAUGHT -- including every organ not yet written. This census is the mechanism 180// in the path instead: it counts sources that name a compare tree in CODE, holds the floor as a SET OF 181// NAMES, and goes RED when that set GROWS. 182// 183// WHY A NAMED-SET RATCHET AND NOT A VERDICT ON EACH SITE. A bare compare path is CORRECT in 184// nx_compare_regen (which chdirs to buildroot) and a latent defect in nx_evidence_beat -- THE SAME 185// LITERAL, and only the caller's CWD tells them apart. Judging the standing population would need a 186// per-organ CWD provenance nobody has measured, and a detector that fires on organs that are already 187// right is a false-positive generator, which is worse than no detector at all. The ratchet needs no such 188// judgement: every current site is baselined BY NAME and only a NEW one has to answer for itself. The 189// baseline file doubles as the CWD-triage worklist that the adjudication will need. 190// 191// A COUNT WOULD NOT DO. On a tree several lanes write at once, a count-only ratchet reports a rise 192// without saying whose, so the seat that must answer for it cannot be found. The floor is a SET. 193// ================================================================================================ 194 195const CG_ST_CODE: i64 = 0 196const CG_ST_STR: i64 = 1 197const CG_ST_COMMENT: i64 = 2 198 199const CG_DQ: i64 = 34 200const CG_BSL: i64 = 92 201const CG_FSL: i64 = 47 202const CG_NLB: i64 = 10 203 204// THE NEEDLE, DELIBERATELY WITHOUT A TRAILING SLASH. It must match all four spellings in the estate: 205// the bare "knowledge/compare/", the "buildroot/knowledge/compare/" prefixed form, and both of those 206// written with no trailing slash (nx_evidence_audit's EA_DIR and nx_evidence_fleet's EF_DIR are). 207// A needle carrying the slash would silently miss the last two -- a floor published as a population. 208const CG_NEEDLE: *u8 = "knowledge/compare" 209const CG_IMPORTMARK: *u8 = "nx_comparetree_lib" 210 211// TWO ROOTS FOR THE SCAN, FOR THE SAME REASON THE LIB HAS TWO TREES: this gate's own corpus path is 212// CWD-relative, and a census pointed at the wrong root returns a confident, complete-looking zero. The 213// first root that OPENS wins and the choice is PRINTED, so the census says where it looked rather than 214// asserting a property of the fleet it may never have read. 215const CG_SCAN_A1: *u8 = "buildroot/runtime" 216const CG_SCAN_A2: *u8 = "runtime" 217const CG_SCAN_B1: *u8 = "buildroot/runtime/_hdl_build" 218const CG_SCAN_B2: *u8 = "runtime/_hdl_build" 219const CG_NXEXT: *u8 = ".nx" 220 221// THE BASELINE IS ANCHORED TO ONE TREE REGARDLESS OF CWD. If the scan resolved at the nishihost root the 222// status dir is plain; if it resolved inside buildroot the parent hop puts it back on the SAME file. 223// Two CWDs writing two baselines would fork the ratchet, and a forked ratchet is no ratchet. 224const CG_STATUS_1: *u8 = "knowledge/status/" 225const CG_STATUS_2: *u8 = "../knowledge/status/" 226const CG_BASE_FILE: *u8 = "comparetree_adoption.baseline" 227const CG_STAMP_FILE: *u8 = "comparetree_adoption.stamp" 228 229// THE ONLY TWO FILES THAT MAY NAME A COMPARE TREE BY HAND: the resolver that owns the constants, and 230// the tooth that pins them. Exemption is BY NAME and nothing else -- see the narrowness control below. 231const CG_EXEMPT_1: *u8 = "nx_comparetree_lib.nx" 232const CG_EXEMPT_2: *u8 = "nx_comparetree_lib_gate.nx" 233 234// A NAMED, ANNOUNCING WORK BUDGET, DERIVED FROM THE MEASURED CORPUS AND NOT GUESSED. Over-budget files 235// are COUNTED and force coverage_complete=0, so a partial scan is LOUD; a census that quietly stops 236// counting returns a SMALLER number that reads like better news, and this one may not tighten its floor 237// on a partial read. 238// MEASURED 2026-08-31 BY THE FIRST RUN OF THIS VERY TOOTH, which is the whole argument for announcing a 239// budget instead of trusting one: it was set to 12000 from an outside estimate, hit that cap EXACTLY, 240// reported over_budget=7109, and went RED rather than seeding its floor from a prefix. So the corpus is 241// 19109 .nx files across the two organ dirs -- 59 percent larger than the estimate -- and a silent cap 242// would have banked 47 offenders as though they were the population. 243// This figure is that measurement plus headroom for growth. The budget exists to bound a RUNAWAY, never 244// to sample: if it is ever hit again the gate says so in the same breath as its verdict. 245const CG_FILE_BUDGET: i64 = 32000 246const CG_DENT_BUF: i64 = 262144 247const CG_NAME_CAP: i64 = 256 248const CG_SET_CAP: i64 = 262144 249const CG_FX_CAP: i64 = 512 250 251const CG_O_SCANNED: i64 = 0 252const CG_O_OFFENDERS: i64 = 1 253const CG_O_ADOPTERS: i64 = 2 254const CG_O_EXEMPTED: i64 = 3 255const CG_O_UNREAD: i64 = 4 256const CG_O_OVER: i64 = 5 257const CG_O_SETLEN: i64 = 6 258const CG_OUT_SLOTS: i64 = 8 259const CG_OUT_BYTES: i64 = 64 260 261func cg_put(d: *u8, o: i64, b: i64) -> i64 { d[o] = b as u8; return o + 1 } 262 263func cg_at(src: *u8, n: i64, i: i64, ned: *u8, nl: i64) -> i64 { 264 if i + nl > n { return 0 } 265 var k: i64 = 0 266 while k < nl { 267 if src[i + k] != ned[k] { return 0 } 268 k = k + 1 269 } 270 return 1 271} 272 273// THE RULER. Does this SOURCE name the needle in CODE (bare or inside a string literal), as opposed to 274// in PROSE? A scanner that does not skip comments measures the documentation and not the code -- and 275// this file's own header would be its loudest hit. String state is tracked because a line comment may 276// not begin inside a string literal: every organ that fetches anything carries a "https:" URL whose 277// double slash would otherwise swallow the rest of its line, hiding a real site as a false negative. 278func cg_code_has(src: *u8, n: i64, ned: *u8) -> i64 { 279 let nl: i64 = cg_zlen(ned) 280 if nl <= 0 { return 0 } 281 var i: i64 = 0 282 var st: i64 = CG_ST_CODE 283 var hit: i64 = 0 284 while i < n { 285 let c: i64 = src[i] as i64 286 if st == CG_ST_COMMENT { 287 if c == CG_NLB { st = CG_ST_CODE } 288 i = i + 1 289 } else { 290 if st == CG_ST_STR { 291 if c == CG_BSL { i = i + 2 } else { 292 if c == CG_DQ { st = CG_ST_CODE; i = i + 1 } else { 293 if cg_at(src, n, i, ned, nl) == 1 { hit = 1 } 294 i = i + 1 295 } 296 } 297 } else { 298 if c == CG_DQ { st = CG_ST_STR; i = i + 1 } else { 299 var adv: i64 = 1 300 if c == CG_FSL { 301 if i + 1 < n { if src[i + 1] == (CG_FSL as u8) { st = CG_ST_COMMENT; adv = 2 } } 302 } 303 if st == CG_ST_CODE { if cg_at(src, n, i, ned, nl) == 1 { hit = 1 } } 304 i = i + adv 305 } 306 } 307 } 308 } 309 return hit 310} 311 312// WRONG IMPLEMENTATION 1, kept so the comment-skipping can be shown to matter: a plain substring search, 313// blind to comments. It is what a grep does, and it is why the hand census counted prose as code. 314func cg_naive_has(src: *u8, n: i64, ned: *u8) -> i64 { 315 let nl: i64 = cg_zlen(ned) 316 if nl <= 0 { return 0 } 317 var i: i64 = 0 318 while i + nl <= n { 319 if cg_at(src, n, i, ned, nl) == 1 { return 1 } 320 i = i + 1 321 } 322 return 0 323} 324 325// WRONG IMPLEMENTATION 2: strips at ANY double slash, ignoring string state. It fails in the quiet 326// direction -- it MISSES real sites -- which is the failure nobody audits. 327func cg_slashstrip_has(src: *u8, n: i64, ned: *u8) -> i64 { 328 let nl: i64 = cg_zlen(ned) 329 if nl <= 0 { return 0 } 330 var i: i64 = 0 331 var st: i64 = CG_ST_CODE 332 var hit: i64 = 0 333 while i < n { 334 let c: i64 = src[i] as i64 335 if st == CG_ST_COMMENT { 336 if c == CG_NLB { st = CG_ST_CODE } 337 i = i + 1 338 } else { 339 var adv: i64 = 1 340 if c == CG_FSL { 341 if i + 1 < n { if src[i + 1] == (CG_FSL as u8) { st = CG_ST_COMMENT; adv = 2 } } 342 } 343 if st == CG_ST_CODE { if cg_at(src, n, i, ned, nl) == 1 { hit = 1 } } 344 i = i + adv 345 } 346 } 347 return hit 348} 349 350func cg_exempt(name: *u8) -> i64 { 351 if cg_streq(name, CG_EXEMPT_1) == 1 { return 1 } 352 if cg_streq(name, CG_EXEMPT_2) == 1 { return 1 } 353 return 0 354} 355 356// ONE CLASSIFIER, called by the fixtures AND by the fleet walk. A sweep that re-implements the check is 357// a second opinion, not a wider one. 358func cg_is_offender(name: *u8, src: *u8, n: i64) -> i64 { 359 if cg_code_has(src, n, CG_NEEDLE) == 0 { return 0 } 360 if cg_exempt(name) == 1 { return 0 } 361 return 1 362} 363 364func cg_ends_with(name: *u8, suf: *u8) -> i64 { 365 let n: i64 = cg_zlen(name) 366 let m: i64 = cg_zlen(suf) 367 if n < m { return 0 } 368 var i: i64 = 0 369 while i < m { 370 if name[n - m + i] != suf[i] { return 0 } 371 i = i + 1 372 } 373 return 1 374} 375 376func cg_eol(b: *u8, n: i64, i: i64) -> i64 { 377 var e: i64 = i 378 while e < n { 379 if b[e] == (CG_NLB as u8) { return e } 380 e = e + 1 381 } 382 return n 383} 384 385// WHOLE-LINE membership. A prefix must NOT match: fixing one offender must never silently amnesty a 386// differently-named one whose name happens to start the same way. 387func cg_hasline(hay: *u8, hn: i64, name: *u8) -> i64 { 388 let len: i64 = cg_zlen(name) 389 var i: i64 = 0 390 var found: i64 = 0 391 while i < hn { 392 let e: i64 = cg_eol(hay, hn, i) 393 if e - i == len { 394 var k: i64 = 0 395 var same: i64 = 1 396 while k < len { 397 if hay[i + k] != name[k] { same = 0 } 398 k = k + 1 399 } 400 if same == 1 { found = 1 } 401 } 402 i = e + 1 403 } 404 return found 405} 406 407// THE RATCHET DECISION, PURE AND EXHAUSTIVELY TESTABLE. It is the function the production path calls, so 408// the teeth below measure the shipped behaviour and not a paraphrase of it. 409// cov=0 -> NEVER write. A partial scan finds FEWER offenders, and tightening on it would launder 410// a blind run into a smaller floor -- the failure that reads like an improvement. 411// no baseline -> SEED. Self-baselining on first sight is what makes adoption non-breaking by 412// construction; a ratchet that starts RED for everyone is one everybody learns to mute. 413// rises > 0 -> REFUSE. Rewriting here would amnesty the very regression being reported. 414// falls > 0 -> TIGHTEN, so a fix is banked and cannot silently regress later. 415func cg_should_write(have_base: i64, rises: i64, falls: i64, cov: i64) -> i64 { 416 if cov == 0 { return 0 } 417 if have_base == 0 { return 1 } 418 if rises > 0 { return 0 } 419 if falls > 0 { return 1 } 420 return 0 421} 422 423// THE LAUNDERING RATCHET, kept as the thing the decision above must be able to refuse. 424func cg_launder_write(have_base: i64, rises: i64, falls: i64, cov: i64) -> i64 { return 1 } 425 426// ---- fixtures, BUILT BYTE-WISE. The double slash and the quote are constructed rather than typed into 427// a literal, so no lexer question about what a string may contain can make a tooth vacuous. 428func cg_fx_clean(d: *u8) -> i64 { 429 let o: i64 = gv_cat(d, 0, "const K: *u8 = knowledge/status/roster.log" as *u8) 430 d[o] = 0 as u8 431 return o 432} 433func cg_fx_code(d: *u8) -> i64 { 434 var o: i64 = gv_cat(d, 0, "const D: *u8 = " as *u8) 435 o = gv_cat(d, o, CG_NEEDLE) 436 o = gv_cat(d, o, "/ ;" as *u8) 437 d[o] = 0 as u8 438 return o 439} 440func cg_fx_str(d: *u8) -> i64 { 441 var o: i64 = gv_cat(d, 0, "const D: *u8 = " as *u8) 442 o = cg_put(d, o, CG_DQ) 443 o = gv_cat(d, o, CG_NEEDLE) 444 o = cg_put(d, o, CG_FSL) 445 o = cg_put(d, o, CG_DQ) 446 d[o] = 0 as u8 447 return o 448} 449func cg_fx_cmt(d: *u8) -> i64 { 450 var o: i64 = cg_put(d, 0, CG_FSL) 451 o = cg_put(d, o, CG_FSL) 452 o = gv_cat(d, o, " the publishing twin is " as *u8) 453 o = gv_cat(d, o, CG_NEEDLE) 454 o = gv_cat(d, o, "/ -- this line is PROSE, not code" as *u8) 455 d[o] = 0 as u8 456 return o 457} 458func cg_fx_url(d: *u8) -> i64 { 459 var o: i64 = gv_cat(d, 0, "let u: *u8 = " as *u8) 460 o = cg_put(d, o, CG_DQ) 461 o = gv_cat(d, o, "https:" as *u8) 462 o = cg_put(d, o, CG_FSL) 463 o = cg_put(d, o, CG_FSL) 464 o = gv_cat(d, o, "example.invalid/p" as *u8) 465 o = cg_put(d, o, CG_DQ) 466 o = gv_cat(d, o, " let v: *u8 = " as *u8) 467 o = cg_put(d, o, CG_DQ) 468 o = gv_cat(d, o, CG_NEEDLE) 469 o = cg_put(d, o, CG_DQ) 470 d[o] = 0 as u8 471 return o 472} 473 474// ONE DIRECTORY, NON-RECURSIVE, .nx ONLY -- the declared corpus is the ORGAN population, which is where 475// every site the hand census named actually lives. Returns -1 if the directory could not be opened, so 476// an unreadable root ABSTAINS instead of reporting a clean fleet. 477func cg_scan_dir(dir: *u8, set: *u8, setcap: i64, out: *i64) -> i64 { 478 let fd: i64 = sys_openat_rd(dir) 479 if fd < 0 { return 0 - 1 } 480 let db: *u8 = sys_mmap(CG_DENT_BUF) 481 let path: *u8 = sys_mmap(CG_PATH) 482 let lenp: *i64 = sys_mmap(16) as *i64 483 var go: i64 = 1 484 while go == 1 { 485 let nb: i64 = sys_getdents64(fd, db, CG_DENT_BUF) 486 if nb <= 0 { go = 0 } else { 487 var off: i64 = 0 488 var walking: i64 = 1 489 while walking == 1 { 490 if off >= nb { walking = 0 } else { 491 let rec: *u8 = ((db as i64) + off) as *u8 492 let rl: i64 = dirent_reclen(rec) 493 let ty: i64 = dirent_type(rec) 494 var isfile: i64 = 0 495 if ty == DT_REG { isfile = 1 } 496 if ty == DT_UNKNOWN { isfile = 1 } 497 if isfile == 1 { 498 let nm: *u8 = dirent_name(rec) 499 if cg_ends_with(nm, CG_NXEXT) == 1 { 500 if out[CG_O_SCANNED] >= CG_FILE_BUDGET { 501 out[CG_O_OVER] = out[CG_O_OVER] + 1 502 } else { 503 out[CG_O_SCANNED] = out[CG_O_SCANNED] + 1 504 var p: i64 = gv_cat(path, 0, dir) 505 p = cg_put(path, p, CG_FSL) 506 p = gv_cat(path, p, nm) 507 path[p] = 0 as u8 508 lenp[0] = 0 509 let src: *u8 = sys_read_file(path, lenp) 510 let sn: i64 = lenp[0] 511 if sn <= 0 { out[CG_O_UNREAD] = out[CG_O_UNREAD] + 1 } else { 512 if cg_code_has(src, sn, CG_IMPORTMARK) == 1 { 513 out[CG_O_ADOPTERS] = out[CG_O_ADOPTERS] + 1 514 } 515 if cg_code_has(src, sn, CG_NEEDLE) == 1 { 516 if cg_exempt(nm) == 1 { 517 out[CG_O_EXEMPTED] = out[CG_O_EXEMPTED] + 1 518 } else { 519 out[CG_O_OFFENDERS] = out[CG_O_OFFENDERS] + 1 520 var so: i64 = out[CG_O_SETLEN] 521 if so + cg_zlen(nm) + 2 < setcap { 522 so = gv_cat(set, so, nm) 523 so = cg_put(set, so, CG_NLB) 524 set[so] = 0 as u8 525 out[CG_O_SETLEN] = so 526 } else { out[CG_O_OVER] = out[CG_O_OVER] + 1 } 527 } 528 } 529 } 530 sys_free_file(src, sn) 531 } 532 } 533 } 534 if rl <= 0 { walking = 0 } else { off = off + rl } 535 } 536 } 537 } 538 } 539 sys_close(fd) 540 return 0 541} 542 543func main(argc: i64, argv: *i64) -> i64 { 544 gv_head("NX-COMPARETREE-LIB-GATE -- the two-tree resolver under every /compare reader" as *u8) 545 let ctr: *i64 = gv_ctr() 546 547 // ---------------- SETUP: rebuilt every run, so nothing depends on a previous run's leftovers. 548 sys_mkdir(CG_ROOT, CG_MODE_755) 549 sys_mkdir(CG_MK_P, CG_MODE_755) 550 sys_mkdir(CG_MK_S, CG_MODE_755) 551 552 let pp: *u8 = sys_mmap(CG_PATH) 553 let sp: *u8 = sys_mmap(CG_PATH) 554 var fx: i64 = 1 555 ct_build_path(CG_DIR_P, "both" as *u8, CG_SUF, pp) 556 if cg_write(pp, CG_BODY_P_BOTH) == 0 { fx = 0 } 557 ct_build_path(CG_DIR_S, "both" as *u8, CG_SUF, sp) 558 if cg_write(sp, CG_BODY_S_BOTH) == 0 { fx = 0 } 559 ct_build_path(CG_DIR_P, "onlyp" as *u8, CG_SUF, pp) 560 if cg_write(pp, CG_BODY_P_ONLY) == 0 { fx = 0 } 561 ct_build_path(CG_DIR_S, "onlys" as *u8, CG_SUF, sp) 562 if cg_write(sp, CG_BODY_S_ONLY) == 0 { fx = 0 } 563 564 // ---------------- THE FIXTURE REACHED ITS CONDITION. Asserted BEFORE any outcome: with no files 565 // written, every resolution tooth below would report a miss and read as a real finding. 566 gv_check("fixture-all-four-files-written" as *u8, eq(fx, 1), ctr) 567 gv_check("fixture-both-tree-bodies-actually-differ" as *u8, 568 eq(cg_streq(CG_BODY_P_BOTH, CG_BODY_S_BOTH), 0), ctr) 569 570 // ---------------- PATH CONSTRUCTION 571 let bp: *u8 = sys_mmap(CG_PATH) 572 ct_build_path(CG_DIR_P, "dcc" as *u8, CG_SUF, bp) 573 gv_check("path-primary-dir-domain-suffix-is-exact" as *u8, 574 cg_streq(bp, "/tmp/nx_comparetree_lib_gate/p/dcc.matrix" as *u8), ctr) 575 ct_build_path(CG_DIR_S, "dcc" as *u8, CG_SUF, bp) 576 gv_check("path-secondary-dir-domain-suffix-is-exact" as *u8, 577 cg_streq(bp, "/tmp/nx_comparetree_lib_gate/s/dcc.matrix" as *u8), ctr) 578 gv_check("path-returned-length-equals-string-length" as *u8, 579 eq(ct_build_path(CG_DIR_S, "dcc" as *u8, CG_SUF, bp), cg_zlen(bp)), ctr) 580 581 // ---------------- WHICH TREE EACH CONSTANT NAMES, GATED AS A FACT. 582 // RENAMED 2026-09-01 from "order-*" because the old names were not true of what these test. They 583 // pin the VALUE of each tree constant; they say nothing about the ORDER a class tries them in, so 584 // the old comment here -- "flipping the order fails HERE, loudly" -- was FALSE: a per-class order 585 // flip passed both of these untouched. That is precisely how a silent flip would have happened, 586 // and it is why the order teeth below now exist. A tooth named for a stronger claim than it makes 587 // is worse than an absent one, because its green is counted as coverage of the claim in its name. 588 gv_check("treeconst-primary-is-knowledge-compare" as *u8, 589 cg_streq(CT_DIR_PRIMARY, "knowledge/compare/" as *u8), ctr) 590 gv_check("treeconst-secondary-is-buildroot-knowledge-compare" as *u8, 591 cg_streq(CT_DIR_SECONDARY, "buildroot/knowledge/compare/" as *u8), ctr) 592 593 // ---------------- THE PER-CLASS ORDER, ADJUDICATED 2026-09-01, PINNED IN BOTH POSITIONS. 594 // .matrix resolves PUBLISHED-first (buildroot, the tree nx_compare_regen renders) and .gates 595 // resolves AUTHORED-first (knowledge, where 58 of its 63 maps exist and which no page renders). 596 // The next flip of either must therefore fail HERE, loudly -- which is what the previous author 597 // intended and what the constant-only teeth above could not deliver. 598 // BOTH POSITIONS ARE ASSERTED DELIBERATELY: an edit that changed only the first would aim both 599 // probes at one tree, silently deleting the fallback that keeps every board resolvable, and a 600 // first-position-only tooth would still read green while boards went dark. 601 gv_check("order-published-tries-the-PUBLISHING-tree-first" as *u8, 602 cg_streq(ct_first_published(), "buildroot/knowledge/compare/" as *u8), ctr) 603 gv_check("order-published-falls-back-to-the-authoring-tree" as *u8, 604 cg_streq(ct_second_published(), "knowledge/compare/" as *u8), ctr) 605 gv_check("order-authored-tries-the-AUTHORING-tree-first" as *u8, 606 cg_streq(ct_first_authored(), "knowledge/compare/" as *u8), ctr) 607 gv_check("order-authored-falls-back-to-the-publishing-tree" as *u8, 608 cg_streq(ct_second_authored(), "buildroot/knowledge/compare/" as *u8), ctr) 609 gv_check("order-published-probes-two-DISTINCT-trees" as *u8, 610 eq(cg_streq(ct_first_published(), ct_second_published()), 0), ctr) 611 gv_check("order-authored-probes-two-DISTINCT-trees" as *u8, 612 eq(cg_streq(ct_first_authored(), ct_second_authored()), 0), ctr) 613 // If someone "repairs" a failing order tooth by making both orders agree, the per-class 614 // adjudication is gone and every tooth above still passes. This is the one that notices. 615 gv_check("neg-control-the-two-orders-are-INVERSES-not-copies" as *u8, 616 eq(cg_streq(ct_first_published(), ct_first_authored()), 0), ctr) 617 618 // ---------------- POSITION -> TREE TRANSLATION, EXHAUSTIVE. 619 // ct_read_2dir reports WHICH POSITION answered (it is handed arbitrary dirs and cannot know more), 620 // writing CT_TREE_PRIMARY whenever argument one won. Under the published order argument one IS the 621 // secondary tree, so without ct_swap_tree every buildroot read would stamp mroot=PRIMARY -- the 622 // referee would grade the right document and MISNAME it, rebuilding the same defect one field over. 623 gv_check("swap-primary-position-reports-the-secondary-tree" as *u8, 624 eq(ct_swap_tree(CT_TREE_PRIMARY), CT_TREE_SECONDARY), ctr) 625 gv_check("swap-secondary-position-reports-the-primary-tree" as *u8, 626 eq(ct_swap_tree(CT_TREE_SECONDARY), CT_TREE_PRIMARY), ctr) 627 // A MISS MUST STAY A MISS. Inventing a tree for NONE would report a document that was never read. 628 gv_check("swap-none-stays-none-a-miss-is-never-a-tree" as *u8, 629 eq(ct_swap_tree(CT_TREE_NONE), CT_TREE_NONE), ctr) 630 gv_check("swap-an-unknown-token-passes-through-unchanged" as *u8, 631 eq(ct_swap_tree(99), 99), ctr) 632 gv_check("swap-is-its-own-inverse-so-it-cannot-drift-one-way" as *u8, 633 eq(ct_swap_tree(ct_swap_tree(CT_TREE_PRIMARY)), CT_TREE_PRIMARY), ctr) 634 // The shipped defect is the ABSENT translation -- stamping the raw position token. If this stops 635 // firing, the swap teeth above have stopped discriminating. 636 gv_bite("neg-control-an-untranslated-position-token-is-caught" as *u8, 637 eq(CT_TREE_PRIMARY, CT_TREE_PRIMARY), 638 eq(ct_swap_tree(CT_TREE_PRIMARY), CT_TREE_PRIMARY), ctr) 639 640 // ---------------- RESOLUTION, THE THREE CASES, AGAINST REAL FILES 641 let buf: *u8 = sys_mmap(CG_BUF) 642 let wh: *i64 = sys_mmap(16) as *i64 643 644 // (a) present only in the PRIMARY tree 645 wh[0] = 0 - 1 646 let na: i64 = ct_read_2dir(CG_DIR_P, CG_DIR_S, "onlyp" as *u8, CG_SUF, buf, CG_BUF, wh) 647 let wa: i64 = wh[0] 648 gv_check("onlyp-resolves-to-the-primary-tree" as *u8, eq(wa, CT_TREE_PRIMARY), ctr) 649 gv_check("onlyp-returns-the-primary-bytes" as *u8, cg_bufeq(buf, na, CG_BODY_P_ONLY), ctr) 650 651 // (b) present only in the SECONDARY tree -- THE 40 DARK DOMAINS. Before the fallback existed this 652 // read returned nothing and the referee printed "matrix file missing" without examining a row. 653 wh[0] = 0 - 1 654 let nb: i64 = ct_read_2dir(CG_DIR_P, CG_DIR_S, "onlys" as *u8, CG_SUF, buf, CG_BUF, wh) 655 let wb: i64 = wh[0] 656 gv_check("onlys-resolves-to-the-secondary-tree" as *u8, eq(wb, CT_TREE_SECONDARY), ctr) 657 gv_check("onlys-returns-the-secondary-bytes" as *u8, cg_bufeq(buf, nb, CG_BODY_S_ONLY), ctr) 658 659 // (c) present in BOTH -- must resolve to PRIMARY, by flag AND by bytes. 660 wh[0] = 0 - 1 661 let nc: i64 = ct_read_2dir(CG_DIR_P, CG_DIR_S, "both" as *u8, CG_SUF, buf, CG_BUF, wh) 662 let wc2: i64 = wh[0] 663 gv_check("both-present-resolves-to-the-primary-tree" as *u8, eq(wc2, CT_TREE_PRIMARY), ctr) 664 gv_check("both-present-returns-the-PRIMARY-bytes-not-the-secondary" as *u8, 665 cg_bufeq(buf, nc, CG_BODY_P_BOTH), ctr) 666 gv_check("both-present-did-not-return-the-secondary-bytes" as *u8, 667 eq(cg_bufeq(buf, nc, CG_BODY_S_BOTH), 0), ctr) 668 669 // (c2) THE SAME TWO FILES, THE REVERSED ORDER -- the published order's MECHANISM, proven against 670 // real files. Without this, every order tooth above is a string compare on a constant and nothing 671 // demonstrates that reversing the arguments actually selects the other tree; a resolver that 672 // ignored its own argument order would pass all of them. 673 wh[0] = 0 - 1 674 let nc2: i64 = ct_read_2dir(CG_DIR_S, CG_DIR_P, "both" as *u8, CG_SUF, buf, CG_BUF, wh) 675 let wc3: i64 = wh[0] 676 gv_check("reversed-order-returns-the-OTHER-trees-bytes" as *u8, 677 cg_bufeq(buf, nc2, CG_BODY_S_BOTH), ctr) 678 gv_check("reversed-order-did-not-return-the-first-orders-bytes" as *u8, 679 eq(cg_bufeq(buf, nc2, CG_BODY_P_BOTH), 0), ctr) 680 // THE TOKEN IS POSITION, NOT TREE: whichever dir is passed first reports CT_TREE_PRIMARY. Asserted 681 // right here, at its source, so the fact ct_swap_tree exists to correct is visible to the next 682 // reader instead of being a surprise waiting in a wrapper. 683 gv_check("reversed-order-still-reports-the-FIRST-POSITION-as-primary" as *u8, 684 eq(wc3, CT_TREE_PRIMARY), ctr) 685 gv_check("swap-turns-that-position-token-into-the-tree-actually-read" as *u8, 686 eq(ct_swap_tree(wc3), CT_TREE_SECONDARY), ctr) 687 688 // AND THE REVERSAL MUST NOT COST THE FALLBACK. A domain present in ONE tree only must still resolve 689 // under the reversed order. This is the "no board goes dark" guarantee that makes the .matrix flip 690 // safe to ship -- gated here rather than asserted in a comment. 691 wh[0] = 0 - 1 692 let nc4: i64 = ct_read_2dir(CG_DIR_S, CG_DIR_P, "onlyp" as *u8, CG_SUF, buf, CG_BUF, wh) 693 gv_check("reversed-order-still-finds-a-first-tree-only-domain-NO-BOARD-GOES-DARK" as *u8, 694 cg_bufeq(buf, nc4, CG_BODY_P_ONLY), ctr) 695 696 // (d) present in NEITHER -- a miss must be reported as a miss, never as a tree. 697 wh[0] = 0 - 1 698 let nd: i64 = ct_read_2dir(CG_DIR_P, CG_DIR_S, "nosuchdomain" as *u8, CG_SUF, buf, CG_BUF, wh) 699 let wd: i64 = wh[0] 700 var nd_empty: i64 = 0 701 if nd <= 0 { nd_empty = 1 } 702 gv_check("missing-in-both-reports-tree-none" as *u8, eq(wd, CT_TREE_NONE), ctr) 703 gv_check("missing-in-both-returns-no-bytes" as *u8, nd_empty, ctr) 704 705 // ---------------- THE READ CAP, REMOVED 2026-09-01 -- RESOLVING A FILE BIGGER THAN THE OLD RESERVE 706 // ct_read fills a caller-supplied buffer and STOPS AT ITS CAP WITH NO SIGNAL. nx_swcompare_evidence 707 // handed it 65,536 B for a .matrix; charsim.matrix measures 67,965 B, so the referee graded a PREFIX 708 // and published "grounded 25/25 | unsupported 0" while the five dropped rows included that board's 709 // own LIAR-KILL row and its operator-acceptance watch row. THE TWO SYMBOL NAMES ARE DELIBERATELY 710 // NOT SPELLED HERE: the referee's grounding scanner does not strip comments, so an identifier 711 // written in prose is a live grounding site -- a detector that scans source will ground a claim on 712 // its own documentation. 713 // ct_readall_2dir composes sys_read_file, which sizes its buffer from the file itself (lseek END) 714 // and cannot short-read, so there is no longer a number here to get wrong. 715 // 716 // THE FIXTURE IS ASSERTED BEFORE THE OUTCOME, and THE NEGATIVE CONTROL IS THE OLD READER ITSELF: 717 // ct_read is run on the very same file and must still stop dead at 65,536 with the tail unseen. If 718 // that stops firing, the fixture no longer straddles the boundary and every tooth below is vacuous. 719 let bigp: *u8 = sys_mmap(CG_PATH) 720 ct_build_path(CG_DIR_S, CG_BIG_DOM, CG_SUF, bigp) 721 let bigw: i64 = cg_write_big(bigp) 722 gv_check("bigfixture-oversize-file-was-written" as *u8, ne(bigw, 0), ctr) 723 gv_check("bigfixture-is-LARGER-than-the-cap-that-was-removed" as *u8, 724 cg_gt(bigw, CG_OLD_CAP), ctr) 725 726 let cbuf: *u8 = sys_mmap(CG_OLD_CAP + 16) 727 let ccn: i64 = ct_read(bigp, cbuf, CG_OLD_CAP) 728 gv_check("neg-control-the-capped-reader-stops-EXACTLY-at-its-cap-on-this-file" as *u8, 729 eq(ccn, CG_OLD_CAP), ctr) 730 gv_check("neg-control-the-capped-reader-CANNOT-see-the-tail-past-the-cap" as *u8, 731 eq(cg_tail_is(cbuf, ccn, CG_BIG_TAIL), 0), ctr) 732 733 // THE SUBJECT. Resolved from the SECOND position deliberately, so this one call proves the uncapped 734 // path reads whole AND keeps the fallback that stops a board going dark. 735 let bign: *i64 = sys_mmap(16) as *i64 736 wh[0] = 0 - 1 737 let bigb: *u8 = ct_readall_2dir(CG_DIR_NONE, CG_DIR_S, CG_BIG_DOM, CG_SUF, bign, wh) 738 var big_ptr: i64 = 0 739 if (bigb as i64) != 0 { big_ptr = 1 } 740 gv_check("readall-returned-a-buffer-for-an-oversize-file" as *u8, big_ptr, ctr) 741 gv_check("readall-returns-EVERY-byte-of-a-file-larger-than-the-old-cap" as *u8, 742 eq(bign[0], bigw), ctr) 743 // ANTI-VACUITY: a reader that reported the right COUNT while holding only a 65,536-byte prefix 744 // passes the tooth above. Only the TAIL proves the bytes past the old cap are really in the buffer. 745 gv_check("readall-the-bytes-PAST-the-old-cap-are-really-in-the-buffer" as *u8, 746 cg_tail_is(bigb, bign[0], CG_BIG_TAIL), ctr) 747 gv_check("readall-still-falls-back-to-the-second-position-NO-BOARD-GOES-DARK" as *u8, 748 eq(wh[0], CT_TREE_SECONDARY), ctr) 749 750 // A MISS MUST STAY A MISS on the uncapped path too, or "absent" starts reading as "empty" -- and an 751 // empty matrix and a missing one take different remedies. 752 let missn: *i64 = sys_mmap(16) as *i64 753 wh[0] = 0 - 1 754 let missb: *u8 = ct_readall_2dir(CG_DIR_P, CG_DIR_S, "nosuchdomain" as *u8, CG_SUF, missn, wh) 755 var miss_null: i64 = 0 756 if (missb as i64) == 0 { miss_null = 1 } 757 gv_check("readall-missing-in-both-returns-a-null-buffer" as *u8, miss_null, ctr) 758 gv_check("readall-missing-in-both-returns-no-bytes" as *u8, eq(missn[0], 0), ctr) 759 gv_check("readall-missing-in-both-reports-tree-none" as *u8, eq(wh[0], CT_TREE_NONE), ctr) 760 761 // AND THE UNCAPPED READER MUST AGREE WITH THE CAPPED ONE WHEREVER THE CAPPED ONE WAS CORRECT -- 762 // a second reader that resolved differently would be the duplicate-ruler defect, not a fix. 763 let smalln: *i64 = sys_mmap(16) as *i64 764 wh[0] = 0 - 1 765 let smallb: *u8 = ct_readall_2dir(CG_DIR_P, CG_DIR_S, "both" as *u8, CG_SUF, smalln, wh) 766 gv_check("readall-agrees-with-the-capped-reader-on-which-tree-wins" as *u8, 767 eq(wh[0], CT_TREE_PRIMARY), ctr) 768 gv_check("readall-agrees-with-the-capped-reader-on-the-bytes-returned" as *u8, 769 cg_bufeq(smallb, smalln[0], CG_BODY_P_BOTH), ctr) 770 771 // SCOPE, NAMED SO NOBODY MISTAKES IT FOR MORE THAN IT IS. ct_compare_readall_published hard-codes 772 // the production trees, so it cannot be aimed at a fixture and is NOT exercised end-to-end here; 773 // what is checkable is that it composes the SAME order facts as its capped sibling rather than 774 // introducing a third order. That nx_swcompare_evidence actually CALLS it is proven by that 775 // organ's own run -- mbytes equal to the matrix's size on disk, mcapped=0 -- and not by this gate. 776 gv_check("readall-published-wrapper-shares-the-published-order-first-position" as *u8, 777 cg_streq(ct_first_published(), CT_DIR_SECONDARY), ctr) 778 779 // ---------------- THE PURE DECISION, EXHAUSTIVE OVER ITS CLASSES 780 gv_check("pick-both-readable-prefers-primary" as *u8, eq(ct_pick(5, 7), CT_TREE_PRIMARY), ctr) 781 gv_check("pick-primary-only-is-primary" as *u8, eq(ct_pick(5, 0), CT_TREE_PRIMARY), ctr) 782 gv_check("pick-secondary-only-is-secondary" as *u8, eq(ct_pick(0, 7), CT_TREE_SECONDARY), ctr) 783 gv_check("pick-neither-is-none" as *u8, eq(ct_pick(0, 0), CT_TREE_NONE), ctr) 784 // an unopenable path returns 0-1 and an EMPTY file returns 0; both must fall through, because an 785 // empty matrix grades exactly as badly as a missing one and would otherwise mask the fallback. 786 gv_check("pick-unreadable-primary-falls-through" as *u8, 787 eq(ct_pick(0 - 1, 7), CT_TREE_SECONDARY), ctr) 788 gv_check("pick-empty-primary-falls-through" as *u8, eq(ct_pick(0, 9), CT_TREE_SECONDARY), ctr) 789 gv_check("pick-unreadable-both-is-none" as *u8, eq(ct_pick(0 - 1, 0 - 1), CT_TREE_NONE), ctr) 790 791 // ---------------- NEGATIVE CONTROLS 792 // The always-primary picker IS the shipped defect. If this bite ever stops firing, the tooth above 793 // has stopped discriminating and every resolution tooth is decoration. 794 gv_bite("neg-control-an-always-primary-picker-is-caught" as *u8, 795 eq(cg_wrong_pick(0, 9), CT_TREE_PRIMARY), 796 eq(ct_pick(0, 9), CT_TREE_PRIMARY), ctr) 797 798 // The secondary lookup must actually happen. Point d2 at a directory that does not exist: if the 799 // resolver were still finding "onlys", it would be reading something other than what it was told to. 800 wh[0] = 0 - 1 801 ct_read_2dir(CG_DIR_P, CG_DIR_NONE, "onlys" as *u8, CG_SUF, buf, CG_BUF, wh) 802 let w_bogus: i64 = wh[0] 803 wh[0] = 0 - 1 804 ct_read_2dir(CG_DIR_P, CG_DIR_S, "onlys" as *u8, CG_SUF, buf, CG_BUF, wh) 805 let w_real: i64 = wh[0] 806 gv_bite("neg-control-the-secondary-lookup-is-load-bearing" as *u8, 807 ne(w_bogus, CT_TREE_SECONDARY), 808 ne(w_real, CT_TREE_SECONDARY), ctr) 809 810 // ================= THE ADOPTION CENSUS: THE RULER FIRST, THEN THE FLEET ================= 811 // The fixtures come first on purpose. If the ruler cannot tell code from prose, every number the 812 // fleet walk prints below is noise wearing a population's clothes. 813 let fxb: *u8 = sys_mmap(CG_FX_CAP) 814 let f1: i64 = cg_fx_code(fxb) 815 let r_code: i64 = cg_code_has(fxb, f1, CG_NEEDLE) 816 let f2: i64 = cg_fx_str(fxb) 817 let r_str: i64 = cg_code_has(fxb, f2, CG_NEEDLE) 818 let f3: i64 = cg_fx_clean(fxb) 819 let r_clean: i64 = cg_code_has(fxb, f3, CG_NEEDLE) 820 let f4: i64 = cg_fx_cmt(fxb) 821 let r_cmt_real: i64 = cg_code_has(fxb, f4, CG_NEEDLE) 822 let r_cmt_naive: i64 = cg_naive_has(fxb, f4, CG_NEEDLE) 823 let f5: i64 = cg_fx_url(fxb) 824 let r_url_real: i64 = cg_code_has(fxb, f5, CG_NEEDLE) 825 let r_url_strip: i64 = cg_slashstrip_has(fxb, f5, CG_NEEDLE) 826 827 gv_check("ruler-a-compare-path-written-as-bare-code-is-detected" as *u8, eq(r_code, 1), ctr) 828 gv_check("ruler-a-compare-path-inside-a-string-literal-is-detected" as *u8, eq(r_str, 1), ctr) 829 gv_check("ruler-a-source-that-names-no-compare-tree-stays-clean" as *u8, eq(r_clean, 0), ctr) 830 831 // A DETECTOR THAT CANNOT TELL CODE FROM THE COMMENT DESCRIBING IT WILL FLAG EVERY EXPLANATION OF THE 832 // BUG IT HUNTS -- starting with this file's own header, which names both trees a dozen times. 833 gv_bite("neg-control-a-comment-only-mention-must-not-be-counted-as-a-site" as *u8, 834 r_cmt_naive, r_cmt_real, ctr) 835 // ...and the opposite error, which fails SILENTLY: a stripper that honours a double slash inside a 836 // string literal swallows the rest of the line after any URL and MISSES real sites. 837 gv_bite("neg-control-the-string-aware-lexer-is-load-bearing" as *u8, 838 eq(r_url_strip, 0), eq(r_url_real, 0), ctr) 839 // THE EXEMPTION IS BY NAME AND MUST NOT LEAK: identical content is an offender under an ordinary 840 // organ's name and is not one under the resolver's. 841 let f6: i64 = cg_fx_str(fxb) 842 gv_bite("neg-control-the-name-exemption-is-narrow-not-a-blanket" as *u8, 843 cg_is_offender("nx_evidence_beat.nx" as *u8, fxb, f6), 844 cg_is_offender(CG_EXEMPT_1, fxb, f6), ctr) 845 846 // THE RATCHET DECISION, EXHAUSTIVE OVER ITS CLASSES. 847 gv_check("ratchet-seeds-on-first-sight-so-adoption-is-non-breaking" as *u8, 848 eq(cg_should_write(0, 0, 0, 1), 1), ctr) 849 gv_check("ratchet-tightens-when-an-offender-is-actually-fixed" as *u8, 850 eq(cg_should_write(1, 0, 3, 1), 1), ctr) 851 gv_check("ratchet-holds-when-nothing-moved" as *u8, 852 eq(cg_should_write(1, 0, 0, 1), 0), ctr) 853 gv_check("ratchet-refuses-to-tighten-from-a-partial-scan" as *u8, 854 eq(cg_should_write(1, 0, 3, 0), 0), ctr) 855 gv_bite("neg-control-a-laundering-ratchet-rewrites-its-floor-on-a-rise-and-this-one-refuses" as *u8, 856 cg_launder_write(1, 1, 0, 1), cg_should_write(1, 1, 0, 1), ctr) 857 858 // ---------------- THE FLEET. Scan root resolved by probe, never assumed -- see CG_SCAN_A1. 859 let cout: *i64 = sys_mmap(CG_OUT_BYTES) as *i64 860 var oi: i64 = 0 861 while oi < CG_OUT_SLOTS { cout[oi] = 0; oi = oi + 1 } 862 let cset: *u8 = sys_mmap(CG_SET_CAP) 863 cset[0] = 0 as u8 864 865 var rootA: *u8 = CG_SCAN_A1 866 var rootB: *u8 = CG_SCAN_B1 867 var atroot: i64 = 1 868 let probe: i64 = sys_openat_rd(CG_SCAN_A1) 869 if probe < 0 { rootA = CG_SCAN_A2; rootB = CG_SCAN_B2; atroot = 0 } else { sys_close(probe) } 870 871 let ra: i64 = cg_scan_dir(rootA, cset, CG_SET_CAP, cout) 872 let rb: i64 = cg_scan_dir(rootB, cset, CG_SET_CAP, cout) 873 var covok: i64 = 1 874 if ra != 0 { covok = 0 } 875 if rb != 0 { covok = 0 } 876 if cout[CG_O_OVER] > 0 { covok = 0 } 877 878 // A ROOT THAT WOULD NOT OPEN IS NOT A CLEAN FLEET. Precondition, so this ends SKIP and never a RED 879 // about organs the census never read. 880 var rootok: i64 = 0 881 if ra == 0 { rootok = 1 } 882 gv_need("census-scan-root-opened-and-was-walked" as *u8, rootok, ctr) 883 // BIND THE AGGREGATE TO ITS DENOMINATOR: ten teeth over zero files would otherwise read GREEN. 884 gv_subjects("nx sources examined by the adoption census" as *u8, cout[CG_O_SCANNED], ctr) 885 gv_check("census-coverage-complete-this-is-a-value-not-a-floor" as *u8, eq(covok, 1), ctr) 886 887 // ---------------- THE FLOOR, HELD AS A SET OF NAMES 888 let bpath: *u8 = sys_mmap(CG_PATH) 889 var bo: i64 = 0 890 if atroot == 1 { bo = gv_cat(bpath, 0, CG_STATUS_1) } else { bo = gv_cat(bpath, 0, CG_STATUS_2) } 891 bo = gv_cat(bpath, bo, CG_BASE_FILE) 892 bpath[bo] = 0 as u8 893 894 let bbuf: *u8 = sys_mmap(CG_SET_CAP) 895 let bnum: i64 = ct_read(bpath, bbuf, CG_SET_CAP - 2) 896 var have_base: i64 = 0 897 if bnum > 0 { have_base = 1; bbuf[bnum] = 0 as u8 } 898 899 let nmb: *u8 = sys_mmap(CG_NAME_CAP) 900 let sl: i64 = cout[CG_O_SETLEN] 901 var rises: i64 = 0 902 var ci: i64 = 0 903 while ci < sl { 904 let e: i64 = cg_eol(cset, sl, ci) 905 if e > ci { 906 var ln: i64 = e - ci 907 if ln > CG_NAME_CAP - 1 { ln = CG_NAME_CAP - 1 } 908 var k: i64 = 0 909 while k < ln { nmb[k] = cset[ci + k]; k = k + 1 } 910 nmb[ln] = 0 as u8 911 if have_base == 1 { 912 if cg_hasline(bbuf, bnum, nmb) == 0 { 913 rises = rises + 1 914 gv_puts(" RISE new-hardcoded-compare-path file=" as *u8) 915 gv_puts(nmb) 916 gv_puts(" (it names a /compare tree in CODE and is not in the baseline -- compose ct_compare_read_published from nx_comparetree_lib when a page RENDERS the class, ct_compare_read_authored when none does, or adjudicate it into the baseline naming the CWD that makes the bare path correct)\n" as *u8) 917 } 918 } 919 } 920 ci = e + 1 921 } 922 923 var falls: i64 = 0 924 var bi: i64 = 0 925 while bi < bnum { 926 let be: i64 = cg_eol(bbuf, bnum, bi) 927 if be > bi { 928 var bl: i64 = be - bi 929 if bl > CG_NAME_CAP - 1 { bl = CG_NAME_CAP - 1 } 930 var q: i64 = 0 931 while q < bl { nmb[q] = bbuf[bi + q]; q = q + 1 } 932 nmb[bl] = 0 as u8 933 if cg_hasline(cset, sl, nmb) == 0 { 934 falls = falls + 1 935 gv_puts(" FIXED no-longer-hardcodes-a-compare-path file=" as *u8) 936 gv_puts(nmb) 937 gv_puts("\n" as *u8) 938 } 939 } 940 bi = be + 1 941 } 942 943 var wrote: i64 = 0 944 if cg_should_write(have_base, rises, falls, covok) == 1 { 945 if cg_write(bpath, cset) == 1 { wrote = 1 } 946 } 947 var ok_norewrite: i64 = 1 948 if rises > 0 { if wrote == 1 { ok_norewrite = 0 } } 949 950 // THE TOOTH THIS WHOLE FILE EXISTS FOR. Every other tooth in this gate has the LIB as its subject; 951 // this one has the FLEET, and it is the only thing here that can fire on the FIFTH rediscovery. 952 gv_check("adoption-no-new-source-hardcodes-a-compare-tree-path" as *u8, eq(rises, 0), ctr) 953 gv_check("adoption-the-floor-was-not-rewritten-while-a-rise-was-being-reported" as *u8, 954 ok_norewrite, ctr) 955 956 // A FORGEABLE STAMP PROVES SOMETHING RAN SOMEWHERE, NEVER THAT THE WATCHED WORK RAN -- so it carries 957 // the SCALE fields, and a run that examined one file cannot masquerade as a run that examined them all. 958 let stb: *u8 = sys_mmap(CG_SET_CAP) 959 var sp2: i64 = gv_cat(stb, 0, "ts=" as *u8) 960 sp2 = gv_catn(stb, sp2, sys_now_realtime_sec()) 961 sp2 = gv_cat(stb, sp2, " scanned=" as *u8); sp2 = gv_catn(stb, sp2, cout[CG_O_SCANNED]) 962 sp2 = gv_cat(stb, sp2, " offenders=" as *u8); sp2 = gv_catn(stb, sp2, cout[CG_O_OFFENDERS]) 963 sp2 = gv_cat(stb, sp2, " adopters=" as *u8); sp2 = gv_catn(stb, sp2, cout[CG_O_ADOPTERS]) 964 sp2 = gv_cat(stb, sp2, " exempted=" as *u8); sp2 = gv_catn(stb, sp2, cout[CG_O_EXEMPTED]) 965 sp2 = gv_cat(stb, sp2, " unreadable=" as *u8); sp2 = gv_catn(stb, sp2, cout[CG_O_UNREAD]) 966 sp2 = gv_cat(stb, sp2, " over_budget=" as *u8); sp2 = gv_catn(stb, sp2, cout[CG_O_OVER]) 967 sp2 = gv_cat(stb, sp2, " coverage_complete=" as *u8); sp2 = gv_catn(stb, sp2, covok) 968 sp2 = gv_cat(stb, sp2, " rises=" as *u8); sp2 = gv_catn(stb, sp2, rises) 969 sp2 = gv_cat(stb, sp2, " fixed=" as *u8); sp2 = gv_catn(stb, sp2, falls) 970 sp2 = gv_cat(stb, sp2, " baseline_written=" as *u8); sp2 = gv_catn(stb, sp2, wrote) 971 sp2 = cg_put(stb, sp2, CG_NLB) 972 stb[sp2] = 0 as u8 973 let spath: *u8 = sys_mmap(CG_PATH) 974 var so3: i64 = 0 975 if atroot == 1 { so3 = gv_cat(spath, 0, CG_STATUS_1) } else { so3 = gv_cat(spath, 0, CG_STATUS_2) } 976 so3 = gv_cat(spath, so3, CG_STAMP_FILE) 977 spath[so3] = 0 as u8 978 let stamped: i64 = cg_write(spath, stb) 979 980 // ---------------- VALUES, NOT JUST VERDICTS. Both vacuous-tooth classes this estate has measured 981 // were caught by a diagnostic dump and never by the pass/fail vector. 982 cg_say(" census_root=" as *u8); cg_say(rootA) 983 cg_say(" hdl_root=" as *u8); cg_say(rootB) 984 cg_say(" walk_rc_a=" as *u8); cg_num(ra) 985 cg_say(" walk_rc_b=" as *u8); cg_num(rb) 986 cg_say("\n" as *u8) 987 cg_say(" scanned=" as *u8); cg_num(cout[CG_O_SCANNED]) 988 cg_say(" offenders=" as *u8); cg_num(cout[CG_O_OFFENDERS]) 989 cg_say(" adopters=" as *u8); cg_num(cout[CG_O_ADOPTERS]) 990 cg_say(" exempted=" as *u8); cg_num(cout[CG_O_EXEMPTED]) 991 cg_say(" unreadable=" as *u8); cg_num(cout[CG_O_UNREAD]) 992 cg_say(" over_budget=" as *u8); cg_num(cout[CG_O_OVER]) 993 cg_say(" coverage_complete=" as *u8); cg_num(covok) 994 cg_say("\n" as *u8) 995 cg_say(" baseline=" as *u8); cg_say(bpath) 996 cg_say(" had_baseline=" as *u8); cg_num(have_base) 997 cg_say(" baseline_bytes=" as *u8); cg_num(bnum) 998 cg_say(" rises=" as *u8); cg_num(rises) 999 cg_say(" fixed=" as *u8); cg_num(falls) 1000 cg_say(" written=" as *u8); cg_num(wrote) 1001 cg_say(" stamped=" as *u8); cg_num(stamped) 1002 cg_say("\n" as *u8) 1003 cg_say(" THE BASELINE FILE IS THE WORKLIST: each name in it is an organ that resolves a /compare path by hand and has not been triaged for the CWD that would make it correct.\n" as *u8) 1004 cg_say(" fixture_ok=" as *u8); cg_num(fx) 1005 cg_say(" onlyp: which=" as *u8); cg_num(wa); cg_say(" bytes=" as *u8); cg_num(na) 1006 cg_say(" onlys: which=" as *u8); cg_num(wb); cg_say(" bytes=" as *u8); cg_num(nb) 1007 cg_say(" both: which=" as *u8); cg_num(wc2); cg_say(" bytes=" as *u8); cg_num(nc) 1008 cg_say(" miss: which=" as *u8); cg_num(wd); cg_say(" bytes=" as *u8); cg_num(nd) 1009 cg_say(" bogus_d2_which=" as *u8); cg_num(w_bogus) 1010 cg_say("\n" as *u8) 1011 1012 return gv_verdict("nx_comparetree_lib_gate" as *u8, ctr, 1013 "primary-first resolution over real fixture files in both trees" as *u8) 1014}