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}