code wiki / (root) / nx_provcensus_lib.nx

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}