nx_provcensus_lib.nx source
↩ module page · 296 lines · 12732 B
1// nx_provcensus_lib.nx -- the classification and reconciliation half of the fleet provenance-drift
2// census (2026-08-26).
3//
4// WHY THIS IS A SEPARATE FILE. The census program must fork nx_provcheck once per gate, and a gate that
5// fork/execs a deployed elf CANNOT be mutation-proven: every mutant reads NOT-REACHED, so the harness
6// reports the gate's own fault rather than the subject's. A lib compiled INTO the gate's build closure
7// can be bitten. So all the judgement lives here and all the walking and forking lives in
8// nx_provcensus.nx -- the split is what makes the load-bearing half provable.
9//
10// DELIBERATELY IMPORTS NOTHING. Every function here is pure byte arithmetic over a caller-supplied
11// buffer: no syscalls, no allocation, no clock. That keeps it linkable from both the program (which
12// pulls in nx_dir.nx via the syscalls.nx alias stub) and the gate (which pulls in nx_gate_verdict.nx via
13// nx_syscalls.nx) with no chance of a duplicate-symbol collision between the two spellings.
14//
15// license_tier: ORIGINAL No hw writes (Rule 26).
16
17// ---- Buckets ---------------------------------------------------------------------------------------
18// UNKNOWN IS ITS OWN BUCKET. An unrecognised verdict must never fall into a known one: the bucket it
19// lands in becomes the number somebody plans against. UNREADABLE is that bucket here, and it is
20// deliberately NOT merged with UNRECORDED -- "nx_provcheck could not speak" and "the sidecar predates
21// closure recording" have completely different remedies (fix the instrument vs rebuild the artifact).
22const PCX_CURRENT: i64 = 0
23const PCX_DRIFTED: i64 = 1
24const PCX_UNRECORDED: i64 = 2
25const PCX_NOSIDECAR: i64 = 3
26const PCX_UNREADABLE: i64 = 4
27const PCX_NBUCKET: i64 = 5
28
29func pcx_bucket_name(b: i64) -> *u8 {
30 if b == PCX_CURRENT { return "CURRENT" as *u8 }
31 if b == PCX_DRIFTED { return "DRIFTED" as *u8 }
32 if b == PCX_UNRECORDED { return "UNRECORDED" as *u8 }
33 if b == PCX_NOSIDECAR { return "NOSIDECAR" as *u8 }
34 if b == PCX_UNREADABLE { return "UNREADABLE" as *u8 }
35 return "UNKNOWN" as *u8
36}
37
38// Every non-CURRENT bucket carries a different remedy, and a count without a worklist is not
39// actionable -- so the reason travels with the count, at the point the count is printed.
40func pcx_bucket_remedy(b: i64) -> *u8 {
41 if b == PCX_CURRENT { return "the artifact IS its sources; nothing to do" as *u8 }
42 if b == PCX_DRIFTED { return "HAZARD, not a recorded incident: a ship that used this artifact as-is would prove the WRONG SUBJECT. nx_organ_ship now rebuilds on drift; nx_closurehash names which source moved" as *u8 }
43 if b == PCX_UNRECORDED { return "I could not look: sidecar predates closure recording; one rebuild records one" as *u8 }
44 if b == PCX_NOSIDECAR { return "no .provenance at all; this artifact was never built through a lane that records one" as *u8 }
45 if b == PCX_UNREADABLE { return "nx_provcheck emitted no verdict token; the INSTRUMENT is the subject here, not the gate" as *u8 }
46 return "unclassified" as *u8
47}
48
49// ---- Byte helpers ----------------------------------------------------------------------------------
50
51func pcx_slen(s: *u8) -> i64 {
52 var n: i64 = 0
53 while s[n] != (0 as u8) { n = n + 1 }
54 return n
55}
56
57// Returns the offset just PAST the first occurrence of s at or after `start`, or -1.
58func pcx_find(b: *u8, n: i64, s: *u8, start: i64) -> i64 {
59 let sl: i64 = pcx_slen(s)
60 if sl == 0 { return 0 - 1 }
61 if start < 0 { return 0 - 1 }
62 var i: i64 = start
63 while i + sl <= n {
64 var j: i64 = 0
65 var ok: i64 = 1
66 while j < sl {
67 if (b[i+j]&0xff) != (s[j]&0xff) { ok = 0; j = sl } else { j = j + 1 }
68 }
69 if ok == 1 { return i + sl }
70 i = i + 1
71 }
72 return 0 - 1
73}
74
75// Returns the offset just past the LAST occurrence, or -1.
76//
77// LAST, not first, and on purpose. nx_provcheck prints its verdict as the final token of its final
78// line, so anchoring on the last occurrence is positional anchoring -- the same discipline gv_last_line
79// uses, and the reason it is safe over untrusted output. An unanchored first-match parse reads the DATA
80// as the ANSWER the moment anything upstream echoes the word (a path, a quoted message, a diagnostic).
81// The loop is bounded by the buffer length: there cannot be more hits than bytes.
82func pcx_find_last(b: *u8, n: i64, s: *u8) -> i64 {
83 var best: i64 = 0 - 1
84 var from: i64 = 0
85 var more: i64 = 1
86 var guard: i64 = 0
87 while more == 1 {
88 if guard > n { more = 0 }
89 if more == 1 {
90 let hit: i64 = pcx_find(b, n, s, from)
91 if hit < 0 { more = 0 } else { best = hit; from = hit }
92 guard = guard + 1
93 }
94 }
95 return best
96}
97
98// Does s appear EXACTLY at offset o?
99func pcx_at(b: *u8, n: i64, o: i64, s: *u8) -> i64 {
100 let sl: i64 = pcx_slen(s)
101 if o < 0 { return 0 }
102 if o + sl > n { return 0 }
103 var j: i64 = 0
104 while j < sl {
105 if (b[o+j]&0xff) != (s[j]&0xff) { return 0 }
106 j = j + 1
107 }
108 return 1
109}
110
111// ---- The classifier --------------------------------------------------------------------------------
112// Reads nx_provcheck's captured stdout and returns exactly one bucket. An empty capture, a capture with
113// no verdict token, and a capture carrying a token this build has never heard of ALL land in
114// UNREADABLE: three ways of failing to observe, none of them permitted to read as CURRENT.
115func pcx_classify(b: *u8, n: i64) -> i64 {
116 if n <= 0 { return PCX_UNREADABLE }
117 let o: i64 = pcx_find_last(b, n, "verdict=" as *u8)
118 if o < 0 { return PCX_UNREADABLE }
119 if pcx_at(b, n, o, "CURRENT" as *u8) == 1 { return PCX_CURRENT }
120 if pcx_at(b, n, o, "DRIFTED" as *u8) == 1 { return PCX_DRIFTED }
121 if pcx_at(b, n, o, "UNRECORDED" as *u8) == 1 { return PCX_UNRECORDED }
122 if pcx_at(b, n, o, "NOSIDECAR" as *u8) == 1 { return PCX_NOSIDECAR }
123 return PCX_UNREADABLE
124}
125
126// ---- Population membership -------------------------------------------------------------------------
127// Suffix test, kept here rather than at the call site so the gate can bite it directly.
128func pcx_ends_with(name: *u8, name_len: i64, suffix: *u8) -> i64 {
129 let sl: i64 = pcx_slen(suffix)
130 if name_len < sl { return 0 }
131 if sl <= 0 { return 0 }
132 let start: i64 = name_len - sl
133 var i: i64 = 0
134 while i < sl {
135 if (name[start+i]&0xff) != (suffix[i]&0xff) { return 0 }
136 i = i + 1
137 }
138 return 1
139}
140
141// ---- Reconciliation --------------------------------------------------------------------------------
142// A PARTITION IS A CLAIM: the parts must sum to the population. This returns the sum so the caller can
143// PRINT it beside the population rather than assert agreement it never checked -- an unexplained
144// residual is a leak, an explained one is a decision, and a partition nobody reconciled is neither.
145func pcx_total(counts: *i64) -> i64 {
146 var t: i64 = 0
147 var i: i64 = 0
148 while i < PCX_NBUCKET {
149 t = t + counts[i]
150 i = i + 1
151 }
152 return t
153}
154
155func pcx_reconciles(counts: *i64, population: i64) -> i64 {
156 if pcx_total(counts) == population { return 1 }
157 return 0
158}
159
160// ---- Roster membership: is this gate actually INVOKED? ---------------------------------------------
161// THE INTERSECTION IS THE REAL WORKLIST. A DRIFTED artifact nothing runs is a hazard sitting still; a
162// DRIFTED artifact the roster beat fires every beat is publishing a verdict about code that is not the
163// tree. Same bucket, completely different urgency -- and a bare DRIFTED count cannot separate them, so
164// it sizes a campaign nobody can act on.
165//
166// THE ESTATE HAS TWO ROSTER SURFACES -- gateroster.conf and gateroster_slow.conf -- and reading only one
167// would report half the invoked population as uninvoked. That is the count-execution-surfaces-first law,
168// which has already cost this estate two censuses that disagreed while both were true of what they read.
169//
170// Every parsing rule below is earned by something in the REAL confs, not imagined:
171// - a ';' row is a COMMENT and never a member. Load-bearing, not cosmetic: gateroster.conf carries
172// commented re-homing notes that LIST DOZENS OF GATE NAMES IN PROSE, so a substring search over the
173// file would report those gates as rostered when the beat will never fire them.
174// - a row may carry a path prefix ("_offc/nx_entropy_gate"), so the comparison is against the basename.
175// - the comparison is EXACT over the whole span, never a prefix: nx_softtissue_gate and
176// nx_softtissue_mr_gate are different gates, and a prefix test would silently conflate them.
177
178const PCX_WS_SPACE: i64 = 32
179const PCX_WS_TAB: i64 = 9
180const PCX_WS_CR: i64 = 13
181const PCX_NL: i64 = 10
182const PCX_SEMI: i64 = 59
183const PCX_SLASH: i64 = 47
184
185func pcx_is_ws(c: i64) -> i64 {
186 if c == PCX_WS_SPACE { return 1 }
187 if c == PCX_WS_TAB { return 1 }
188 if c == PCX_WS_CR { return 1 }
189 return 0
190}
191
192// First non-whitespace index in [s,e), or e when the span is entirely whitespace.
193func pcx_row_begin(b: *u8, s: i64, e: i64) -> i64 {
194 var i: i64 = s
195 while i < e {
196 if pcx_is_ws(b[i]&0xff) == 0 { return i }
197 i = i + 1
198 }
199 return e
200}
201
202// Index just past the last non-whitespace byte in [s,e), or s when the span is entirely whitespace.
203// The trailing-CR case is why this exists: a conf written CRLF would otherwise make every row compare
204// unequal by one invisible byte, and the entire roster would read as absent -- a confident, total,
205// silent false negative in the flattering direction.
206func pcx_row_end(b: *u8, s: i64, e: i64) -> i64 {
207 var i: i64 = e
208 while i > s {
209 if pcx_is_ws(b[i-1]&0xff) == 0 { return i }
210 i = i - 1
211 }
212 return s
213}
214
215// Index just past the last '/' in [s,e) -- the start of the basename; s when there is no slash.
216func pcx_basename_off(b: *u8, s: i64, e: i64) -> i64 {
217 var off: i64 = s
218 var i: i64 = s
219 while i < e {
220 if (b[i]&0xff) == PCX_SLASH { off = i + 1 }
221 i = i + 1
222 }
223 return off
224}
225
226// EXACT equality of the span [s,e) with a NUL-terminated name, LENGTH INCLUDED. An empty span never
227// matches, so a blank row cannot be mistaken for a member of anything.
228func pcx_span_eq(b: *u8, s: i64, e: i64, name: *u8) -> i64 {
229 let nl: i64 = pcx_slen(name)
230 if nl <= 0 { return 0 }
231 if e - s != nl { return 0 }
232 var i: i64 = 0
233 while i < nl {
234 if (b[s+i]&0xff) != (name[i]&0xff) { return 0 }
235 i = i + 1
236 }
237 return 1
238}
239
240// Is `name` a LIVE row of this roster buffer? The line walk keeps a SEPARATE end cursor: writing the
241// loop-exit sentinel into the scan cursor is this estate's own recorded defect -- it erases the answer
242// the loop was computing -- so the line end is found with a flag and the cursor is left intact.
243func pcx_roster_has(b: *u8, n: i64, name: *u8) -> i64 {
244 if n <= 0 { return 0 }
245 if pcx_slen(name) <= 0 { return 0 }
246 var s: i64 = 0
247 while s < n {
248 var e: i64 = s
249 var scanning: i64 = 1
250 while scanning == 1 {
251 if e >= n { scanning = 0 }
252 if scanning == 1 {
253 if (b[e]&0xff) == PCX_NL { scanning = 0 } else { e = e + 1 }
254 }
255 }
256 let rbeg: i64 = pcx_row_begin(b, s, e)
257 let rend: i64 = pcx_row_end(b, rbeg, e)
258 var usable: i64 = 0
259 if rbeg < rend {
260 if (b[rbeg]&0xff) != PCX_SEMI { usable = 1 }
261 }
262 if usable == 1 {
263 let bo: i64 = pcx_basename_off(b, rbeg, rend)
264 if pcx_span_eq(b, bo, rend, name) == 1 { return 1 }
265 }
266 s = e + 1
267 }
268 return 0
269}
270
271// Counts the LIVE (non-comment, non-blank) rows of a roster buffer. The census prints this beside the
272// membership split so a roster that failed to load, or loaded empty, ANNOUNCES itself as 0 rows instead
273// of silently making every gate read OFF-ROSTER. That is the flattering direction -- it would shrink the
274// actionable worklist to nothing and look like good news -- and it is the one nobody audits.
275func pcx_roster_rows(b: *u8, n: i64) -> i64 {
276 if n <= 0 { return 0 }
277 var rows: i64 = 0
278 var s: i64 = 0
279 while s < n {
280 var e: i64 = s
281 var scanning: i64 = 1
282 while scanning == 1 {
283 if e >= n { scanning = 0 }
284 if scanning == 1 {
285 if (b[e]&0xff) == PCX_NL { scanning = 0 } else { e = e + 1 }
286 }
287 }
288 let rbeg: i64 = pcx_row_begin(b, s, e)
289 let rend: i64 = pcx_row_end(b, rbeg, e)
290 if rbeg < rend {
291 if (b[rbeg]&0xff) != PCX_SEMI { rows = rows + 1 }
292 }
293 s = e + 1
294 }
295 return rows
296}