nx_organ_ground_lib.nx source
↩ module page · 85 lines · 4545 B
1// nx_organ_ground_lib.nx -- IS THIS SYMBOL ACTUALLY IN THE ORGAN ITS ROW NAMES?
2//
3// The second half of the compare-matrix row question. nx_matrix_sym_lib owns the SYMBOL FIELD's
4// format (bare _ABSENT_ vs the _ABSENT_:<watch> contract) and deliberately performs NO file IO, so
5// that purely lexical consumers can use it. This lib owns the MEASUREMENT: open the organ the row
6// declares, and answer whether the symbol occurs in it.
7//
8// WHY IT EXISTS (measured 2026-08-16). FOUR organs each carried their own copy of this, and the copies
9// did not agree, so the estate published four different answers about the same 25 rows of mangagen:
10// nx_swcompare_evidence 18 present / 7 absent (correct)
11// nx_compare_unified 0 present / 25 absent (read organ paths BARE -> everything missed)
12// nx_swarm_maturity every row L0, 0/1000 (same bare read, same confident zero)
13// nx_sota_status 25 present / 0 gaps (lexical only, never opened anything)
14// ★★★★★★FOUR PRIVATE COPIES OF ONE MEASUREMENT ARE FOUR DIFFERENT NUMBERS, AND EACH ONE LOOKS
15// AUTHORITATIVE ON ITS OWN PAGE. Nothing compared them, so nothing could notice.
16//
17// PATH RESOLUTION IS THE WHOLE DEFECT AND IT IS NOT OPTIONAL. Matrix rows name organs BUILDROOT-
18// relative ("runtime/nx_gen.nx") while these organs run from the serving root, so a bare open misses
19// EVERY row and reports it as absent -- a confident zero that is indistinguishable from an honest
20// "not built". Composes nx_estate_path's ep_open_rd, the estate's ONE resolver, whose own header
21// states the law: A VERDICT THAT CHANGES WITH THE CALLER'S WORKING DIRECTORY IS NOT A MEASUREMENT.
22//
23// THREE STATES, NEVER TWO. "I read the organ and the symbol is not there" and "I could not read the
24// organ" are OPPOSITE facts; collapsing them into 0 is exactly what let a resolution bug masquerade
25// as a fleet of honestly-unbuilt capabilities. Callers that only branch on ==1 keep their behaviour;
26// callers that want to abstain can now see the difference.
27//
28// LAYER: runtime/ primitive, importable by runtime/ and _hdl_build/. Library only: NO main().
29// license_tier: ORIGINAL
30// module: nishi-core.compare.ground
31// capability: MATRIX_ROW_SYMBOL_GROUNDING
32import "nx_syscalls.nx"
33import "nx_estate_path.nx"
34
35// Organ sources are ordinary text; this bound is the READ WINDOW, and it announces rather than
36// silently truncating, because a symbol missed past a silent cap reads exactly like a symbol absent.
37const OG_READ_CAP: i64 = 1 << 20
38
39const OG_PRESENT: i64 = 1
40const OG_ABSENT: i64 = 0
41const OG_UNREADABLE: i64 = 0 - 1
42const OG_TRUNCATED: i64 = 0 - 2
43
44// Substring search over buf[0..n) for ned[0..nl). Plain scan: organ sources are small enough that a
45// smarter matcher would be complexity nobody asked for, and the brute force is the one everyone can
46// verify by reading it.
47func og_find(buf: *u8, n: i64, ned: *u8, na: i64, nl: i64) -> i64 {
48 if nl <= 0 { return 0 - 1 }
49 if nl > n { return 0 - 1 }
50 var i: i64 = 0
51 let last: i64 = n - nl
52 while i <= last {
53 var j: i64 = 0
54 var ok: i64 = 1
55 while j < nl {
56 if buf[i + j] != ned[na + j] { ok = 0; j = nl } else { j = j + 1 }
57 }
58 if ok == 1 { return i }
59 i = i + 1
60 }
61 return 0 - 1
62}
63
64// Read the organ at <path> into <scratch> (caller-owned, capacity <cap>) and report whether
65// ned[na..na+nl) occurs in it.
66// RETURNS OG_PRESENT · OG_ABSENT · OG_UNREADABLE · OG_TRUNCATED.
67// ★NEVER ALLOCATE IN A HOT LOOP: the scratch buffer is passed IN, because these callers run this
68// once per matrix row across every domain and a per-row mmap is how a census turns into a memory bug.
69func og_symbol_in_organ(path: *u8, scratch: *u8, cap: i64, ned: *u8, na: i64, nl: i64) -> i64 {
70 let fd: i64 = ep_open_rd(path)
71 if fd < 0 { return OG_UNREADABLE }
72 var tot: i64 = 0
73 var go: i64 = 1
74 while go == 1 {
75 let r: i64 = sys_read(fd, ((scratch as i64) + tot) as *u8, cap - tot)
76 if r <= 0 { go = 0 } else { tot = tot + r; if tot >= cap { go = 0 } }
77 }
78 sys_close(fd)
79 if tot <= 0 { return OG_UNREADABLE }
80 // A FULL BUFFER IS NOT A COMPLETE READ. If the organ filled the window exactly, the tail was not
81 // examined, so ABSENT would be a claim about bytes nobody looked at.
82 if tot >= cap { if og_find(scratch, tot, ned, na, nl) >= 0 { return OG_PRESENT } return OG_TRUNCATED }
83 if og_find(scratch, tot, ned, na, nl) >= 0 { return OG_PRESENT }
84 return OG_ABSENT
85}