code wiki / (root) / nx_artifactdrift.nx

nx_artifactdrift.nx source

↩ module page · 1487 lines · 96790 B

1// nx_artifactdrift.nx -- IS THE BINARY WE ARE SERVING THE ONE THE LAST BUILD PRODUCED? 2// 3// ⚠THIS ORGAN WAS NAMED WRONG TWICE, AND BOTH GUARDS WERE RIGHT. It shipped as `nx_promotestale` and 4// nx_job_run's launch guard refused it: that guard splits the name on '_' and denies any SEGMENT 5// STARTING WITH a control-plane stem, so "promotestale" reads as promote. Renamed to `nx_servedrift`, 6// /api/promote then refused it as a DAEMON and nx_job_run refused it again -- "servedrift" starts with 7// "serve", and that guard's header states it chose stem-prefix DELIBERATELY so `nx_server` could never 8// escape, calling an escaped server "the brick". 9// -- BOTH REFUSALS WERE CORRECT. A launch guard must be wrong in the direction of REFUSING, and a name 10// that starts with `serve` genuinely looks like a server. The tempting fix -- patch an allow-path into a 11// never-brick guard so it consults organ_kind.conf -- would trade a real safety property for a bad name. 12// -- SO THE NAME MOVED, NOT THE GUARD: this measures DRIFT BETWEEN THE BUILT AND SERVED ARTIFACT, which 13// `artifactdrift` says exactly and claims to be no kind of server. 14// ★★AN ORGAN'S NAME IS PART OF ITS INTERFACE, BECAUSE THE ESTATE'S OWN SAFETY RULES READ IT -- and when a 15// guard and a name disagree, the guard is the thing with a proof behind it. 16// 17// WHY IT EXISTS, MEASURED 2026-08-14: two organs were found SERVING STALE CODE purely because a human 18// happened to notice nx_catalog's BUILT and PROMOTED columns disagree -- nx_vizsla_digest (47,402 served 19// vs 47,596 built) and nx_vizsla_plan (176,882 served vs 217,561 built: ~40 KB, a FIFTH of the organ, 20// missing from the running binary). Both were invisible to every health check the estate runs. 21// -- A RUNNING BINARY THAT IS NOT WHAT ITS SOURCE BUILT IS A SILENT CORRECTNESS AND SECURITY DEFECT: 22// every fix, every audit and every gate verdict then describes code that is not the code being executed. 23// -- SPOTTING IT BY EYE DOES NOT SCALE. nx_catalog answers this one NAME at a time; this sweeps. 24// 25// nx_artifactdrift [judge] [registry] [buildroot] [srcroot_primary] [srcroot_secondary] [declare_conf] [trend_log] 26// 27// THE OWNER-SIGNAL AXIS (DM5 ps_owner_scan, 2026-08-20). Every BEHIND row carries an OWNER SIGNAL, so a 28// promote list built from this census can never omit the check. BEHIND alone is NECESSARY BUT NOT 29// SUFFICIENT for "promote me": a BEHIND row can be ANOTHER SEAT'S WORK IN FLIGHT -- measured live 30// 2026-08-15 on nx_oo_extract_gate, where the only thing that stopped the promote was a human looking. 31// STATES, a partition over the BEHIND rows and NOTHING ELSE: 32// DECLARED a row in the declaration conf claims the target -- a STATEMENT, so it outranks the 33// inferences below and is the mechanism for the standing "declare any build you do 34// not promote" law 35// IN-FLIGHT-SUSPECT scratch siblings <target>.nx.* beside the source, or a same-day source touch 36// SRC-UNRESOLVED no source under either root -- the axis ABSTAINS; it does not acquit 37// UNDECLARED no claim and no signal: the ONLY class eligible to be CONSIDERED, never an order 38// ⚠IT IS A SEPARATE AXIS, exactly like the INERT exec-bit axis and for the same reason -- folding owner 39// states into the IDENTICAL/STALE/NO-BUILD/NO-SERVED/STAGED-POINTER partition would break the 40// reconciliation that makes that partition worth trusting. It reconciles against BEHIND on its own, and 41// prints its own coverage so a table that filled can never be read as a total. 42// ⚠THE LAST FOUR ARGUMENTS EXIST SO A GATE CAN POINT THIS ORGAN AT A FIXTURE TREE -- including the trend 43// log, because a gate that shares its fixture with a production beat corrupts the trend it measures. 44// 45// THE UNIT IS THE BINARY, NOT THE REGISTRY ROW. Several names legitimately share one elf (nx_status and 46// nx_torstat both point at nx_hostctl; nx_services/nx_health/nx_mgmt all at nx_mgmt_call.elf), so 47// counting rows would INFLATE the population and report one stale binary as three. 48// 49// CLASSES -- a PARTITION whose parts are printed and MUST sum: 50// IDENTICAL served bytes == built bytes -> what we run is what we built 51// STALE both exist and DIFFER -> THE WORKLIST; the served code is not the build 52// NO-BUILD no build artifact to compare against -> CANNOT JUDGE, never folded into IDENTICAL 53// NO-SERVED the registry points at a missing elf -> a dangling row, a different defect entirely 54// -- "I COULD NOT LOOK" GETS ITS OWN BUCKET. Folding NO-BUILD into IDENTICAL would report the fleet 55// healthy in exactly the state this organ exists to catch -- the defect nx_offc_install already made 56// once when it read "no twin to judge" as "not stale". 57// 58// ⚠⚠THIS ORGAN IS A CHEAP PRE-FILTER, NOT THE ADJUDICATOR. `nx_stale_check <target>` is the incumbent 59// judge and it is STRICTLY BETTER per row: it REBUILDS the target, byte-compares against the deployed 60// elf, and runs a real capability check -- `capability_check=OK strings_checked=N coverage_complete=1`, 61// with a distinct CAPLOSS exit (4) and a DEPLOYED-AHEAD verdict. Use THIS organ to find candidates over 62// the whole registry with two stats each (cheap); use THAT one to decide any single promote (a rebuild 63// each, expensive). ★★★★★A CHEAP CENSUS AND AN EXPENSIVE ADJUDICATOR ARE NOT RIVALS -- NAMING WHICH IS 64// WHICH IS WHAT STOPS THE CHEAP ONE FROM BEING READ AS A VERDICT. 65// ⚠SCOPE, STATED PLAINLY SO THE NAME CANNOT OVERPROMISE: this compares SERVED against THE LAST BUILD 66// ARTIFACT -- not against SOURCE, and buildroot/_build/<name>.sov.elf is WHATEVER WAS BUILT LAST BY 67// ANYONE AT ANY TIME. MEASURED 2026-08-15: nx_verify's _build artifact was 49,085 B while a FRESH build 68// of the same source was 58,828 -- so a row can appear here purely because the _build file is old. 69// That is a third false-positive mode on top of the two already named, and only a rebuild settles it. A STALE row proves an unpromoted build exists and that the served copy 70// is BEHIND it; it does NOT prove the served binary disagrees with its own source, which would need a 71// rebuild per organ (thousands of compiles). The name is `artifactdrift`, not `sourcedrift`, for exactly 72// this reason, and the STALE header says "the last build produced" rather than "its source". 73// ★★AN INSTRUMENT WHOSE NAME PROMISES A WIDER SUBJECT THAN IT MEASURES IS THE MOST COMMON DEFECT IN THIS 74// ESTATE, AND A NEW INSTRUMENT IS THE EASIEST PLACE TO COMMIT IT AGAIN. 75// 76// CHEAP BY CONSTRUCTION: size comes from sys_fstatat (a stat, NOT a read), so the common case costs two 77// stats per binary and reads NOTHING. A full byte compare runs ONLY when the sizes match, which is the 78// only case where size cannot decide. Equal size with different bytes is real, so it is never assumed away. 79// exit 0 census printed | 2 usage | 3 cannot read registry | 4 no rows | 5 capacity exceeded (REFUSES) 80// license_tier: ORIGINAL. Read-only. No hw writes (Rule 26). 81import "nx_syscalls.nx" 82import "nx_heavyio_lib.nx" // the estate-wide heavy-I/O concurrency bound (2026-09-02): a census asks BEFORE it walks 83import "nx_stubmain_lib.nx" // the STUB-MAIN ruler (2026-09-03). Composed, never re-rolled: this organ already 84 // walks the serving root and already resolves sources through PS_SRCROOT_A then 85 // PS_SRCROOT_B in builder order, so the ARMED axis is one predicate call here and 86 // NOT a second tree walker. The estate has one drift census and must keep having one. 87 88const PS_MAXROW: i64 = 4096 89const PS_NAMEMAX: i64 = 256 90const PS_STAT_SIZE_OFF: i64 = 48 91// st_mode sits at byte 24 of x86-64 struct stat (dev 0, ino 8, nlink 16, mode 24). Named, not inlined, 92// because a bare 24 beside a bare 48 is two magic numbers that look like each other. 93const PS_STAT_MODE_OFF: i64 = 24 94const PS_MODE_OWNER_X: i64 = 64 95// Named because `nx_verify magic` now NAMES its offenders, and these were mine. Each is a fact about a 96// wire format or an ABI, not a tunable -- which is exactly why it deserves a name rather than a bare 97// literal the next reader has to decode from context. 98const PS_ASCII_v: i64 = 118 // 'v' -- first byte of the ruler's `verdict=` token, a cheap prefilter 99const PS_BYTE_RADIX: i64 = 256 // combining two little-endian bytes of st_mode 100const PS_BIT_SET: i64 = 2 // `% 2` on a shifted mode = is that permission bit set 101const PS_I64_BYTES: i64 = 8 // sizeof(i64) -- the row tables hold i64 handles, not bytes 102const PS_MODE_0644: i64 = 420 // 0644 in decimal, the estate's standard file mode 103const PS_EXIT_NOTFOUND: i64 = 127 // exec convention: command not found 104const PS_ASCII_SLASH: i64 = 47 // '/' -- path separator, for finding a basename 105const PS_ASCII_HASH: i64 = 35 // the comment byte that opens a skipped line in every conf this organ reads 106const PS_STATBUF_BYTES: i64 = 160 // struct stat is 144 B on x86-64; 160 is the rounded buffer three stat helpers share 107const PS_DEFAULT_REG: *u8 = "tool_allowlist.conf" 108const PS_DEFAULT_BROOT: *u8 = "buildroot/_build/" 109// ONE NAME FOR THE SCRATCH FILE. The judge WRITES it and the explainer READS it back; two spellings 110// of the same path is how a reader and a writer end up honestly describing different files. 111const PS_JUDGE_TMP: *u8 = "/tmp/nx_artifactdrift_judge.tmp" 112const PS_TAB: i64 = 9 113const PS_NL: i64 = 10 114const PS_LOGLINE_CAP: i64 = 1536 // the durable trend row's buffer -- named because it grew when the owner axis landed, and RAISED AGAIN when the fork-root axis added five fields. Raised BEFORE those fields were appended, deliberately: a trend row that overruns its buffer corrupts the one durable record this census leaves behind. 115 116// --- OWNER-SIGNAL AXIS (DM5, ps_owner_scan) ------------------------------------------------------- 117// The builder probes runtime/_hdl_build FIRST and runtime SECOND, so the SOURCE resolver probes in the 118// SAME order or it reports about a file that is not the one that compiles. 119// ★★★★★RESOLVING A NAME IS NOT RESOLVING A PATH -- and a resolver that disagrees with the builder is a 120// second resolver, which is the duplicate-ruler defect wearing a path. 121const PS_SRCROOT_A: *u8 = "buildroot/runtime/_hdl_build/" 122const PS_SRCROOT_B: *u8 = "buildroot/runtime/" 123const PS_SRC_EXT: *u8 = ".nx" 124// A seat that BUILDS WITHOUT PROMOTING declares it here, one row per target, TAB-separated 125// `<target> <owner> <why>`, lines beginning with the comment byte ignored. This is the only owner signal 126// that is a STATEMENT rather than an inference, which is why it outranks both mechanical ones. 127const PS_DECLARE_CONF: *u8 = "knowledge/status/drift_owner_declare.conf" 128const PS_DRIFT_LOG: *u8 = "knowledge/status/artifactdrift.log" 129 130// ---- FORK-ROOT AXIS (2026-08-31) -- A THIRD TWIN NOBODY WAS CENSUSING ------------------------ 131// /api/promote writes the SERVING ROOT and nishihost/_offc. The TOOLCHAIN lane writes buildroot/_offc. 132// NOTHING refreshes buildroot/_offc on an ordinary promote -- and nx_compare_regen chdirs INTO buildroot 133// and then forks the BARE path `_offc/nx_swcompare_*.elf`, so buildroot/_offc IS the copy the compare 134// publisher actually executes. 135// MEASURED 2026-08-31: nx_swcompare_hub was served at 111,236 B while buildroot/_offc still held 81,227 B 136// -- EXACTLY the pre-fix binary -- and a full regen returned `published=201 fails=0 verdict=GREEN` having 137// published NOTHING: every one of the 201 lines reported prev= EQUAL to its new byte count. 138// FOUR INDEPENDENT AGENTS EACH VERIFIED THEIR PROMOTE AGAINST THE SERVING ROOT AND/OR nishihost/_offc, 139// AND ALL FOUR MISSED THIS TWIN -- because nx_catalog enumerates SOURCE/BUILT/STAGED/PROMOTED/_offc and 140// NOT buildroot/_offc, so every row read BUILT==PROMOTED and looked clean. 141// **A CANARY PROVES THE BINARY RUNS, NOT THAT THE CALLERS REACH IT. "PROMOTED + GREEN" IS A CLAIM ABOUT 142// ONE PATH, AND THE PATH THE PUBLISHER FORKS WAS THE ONE NOBODY MEASURED.** 143// SEPARATE AXIS, NOT A PARTITION MEMBER -- the same call this organ already made for INERT, and for the 144// same reason: a binary can be IDENTICAL on the build axis and FORKED on this one. nx_swcompare_matrix 145// was exactly that (_build 210,325 == PROMOTED 210,325 while buildroot/_offc held 208,570), so folding 146// this into `sum` would silently break the reconciliation that makes the partition worth having. 147// REFERENCE IS THE SERVING ROOT, AND THAT IS STATED RATHER THAN ASSUMED: it is what /api/promote writes 148// and what nx_restage restores this twin to agree with. 149// COST: two stats and a byte compare per entry, NO BUILD. That is why this can sweep the whole fork root 150// where nx_stale_check -- one compile per target, and admission-gated -- can only ever answer for one. 151// TWO ADJUDICATORS ARE NOT RIVALS WHEN THEY ANSWER DIFFERENT QUESTIONS AT DIFFERENT COSTS. 152const PS_FORKROOT: *u8 = "buildroot/_offc/" 153// The fork root held 119 entries when this landed, all of them enumerable in one pass; 1024 is >8x that 154// and the loader ANNOUNCES if it ever fills, so this is a bound that cannot become a silent cap. 155const PS_FORK_MAX: i64 = 1024 156// A SCRATCH SIBLING IS THE SOURCE NAME PLUS A SUFFIX -- `<name>.nx.nxw12057`, `<name>.nx.laneFprobe.nxw8847` 157// -- the artifact a live editor session leaves beside the file it is holding open. MEASURED whole-tree 158// 2026-08-20: 762 such files over 23,574, corpus_complete=1. That is ~3%, so the signal DISCRIMINATES 159// rather than saturates; a signal that fires on everything discriminates nothing and must be removed. 160// The marker is bound ONCE here; the per-row test then requires the entry to START with `<name>.nx.`, 161// and the trailing dot is what stops nx_seat.nx.nxw1 from answering for nx_seatresume. 162const PS_SCRATCH_MARK: *u8 = ".nx." 163const PS_SCRATCH_MAX: i64 = 8192 // >10x the measured 762; the loader ANNOUNCES if it ever fills (no silent cap) 164const PS_OWN_DIRBUF: i64 = 65536 // getdents read window, the estate's standard directory buffer 165const PS_OWN_NAMES_SHOWN: i64 = 4 // scratch names printed per row; the COUNT is always exact and says PREFIX above this 166const PS_SECS_PER_DAY: i64 = 86400 // a DEFINITION, not a tunable: the UTC day the mtime is bucketed into 167const PS_STAT_MTIME_OFF: i64 = 88 // st_mtime.tv_sec at byte 88 of x86-64 struct stat (size 48, blksize 56, blocks 64, atime 72) 168// Owner states: a PARTITION over the BEHIND rows AND NOTHING ELSE. Kept as its own axis for the same 169// reason ps_execbit is -- see the section header. 170const PS_OWN_DECLARED: i64 = 0 171const PS_OWN_INFLIGHT: i64 = 1 172const PS_OWN_UNDECLARED: i64 = 2 173const PS_OWN_UNRESOLVED: i64 = 3 174// REF-FRESHNESS states. ★★★★★★THE REFERENCE IS PART OF THE CLAIM: this census compares the served 175// binary against buildroot/_build/<name>.sov.elf, which is THE LAST BUILD ANYBODY RAN AT ANY TIME. If 176// that artifact PREDATES the source, the delta is not evidence about today's source at all -- and the 177// direction can be exactly INVERTED. MEASURED BY A SIBLING SEAT 2026-08-20: of 8 BEHIND subjects 178// rebuilt from source, 5 came out SMALLER than the served binary (AHEAD-on-rebuild) while this worklist 179// said "promote the fix"; worst case nx_schema_backfill served 698,235 vs fresh 102,655, and 180// nx_contentdiff called that promote RED with 14 lost runs. FOUR held subjects flipped BEHIND->AHEAD 181// the instant their _build fossil was refreshed -- nothing about either binary changed, ONLY THE 182// REFERENCE. (That was 8 of 155 under a stated selection rule: a WITNESS THAT THE DEFECT EXISTS, never 183// a population rate.) ★★★★★AN INSTRUMENT WHOSE SUBJECT DOES NOT MATCH WHAT IT CLAIMS TO JUDGE IS THE 184// DEFECT CLASS THIS ESTATE EXISTS TO CURE, AND THE MOST DANGEROUS FORM OF IT POINTS AT THE ONE ACTION 185// THAT DESTROYS CAPABILITY. 186// The predicate needs NO threshold: an artifact built BEFORE its source cannot describe that source. 187// ⚠Equality (built and source stamped in the SAME SECOND) is counted FRESH -- that is the imprecision 188// chosen and it is named here rather than left for a reader to discover: a builder that finishes inside 189// the second its source was written is the common case, and calling it FOSSIL would saturate the axis. 190const PS_REF_FRESH: i64 = 0 191const PS_REF_FOSSIL: i64 = 1 192const PS_REF_UNKNOWN: i64 = 2 193 194func ps_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 195// ★★★★★★A STRING LITERAL SPELLED OUT AS CHARACTER CODES IS THE SAME DEFECT AS A HAND-COUNTED 196// LENGTH, AND WORSE TO READ: `46,101,108,102` is ".elf" written so that no reader recognises it and no 197// search can find it. Two blocks below did exactly that -- and the SECOND exists only because the first 198// could not see ".elf.new", a bug whose own comment sits three lines above it. Compare to the literal. 199func ps_endswith(s: *u8, slen: i64, sfx: *u8) -> i64 { 200 let n: i64 = ps_len(sfx) 201 if slen < n { return 0 } 202 return ps_streq_n(((s as i64) + slen - n) as *u8, sfx, n) 203} 204func ps_puts(s: *u8) -> i64 { sys_write(1, s, ps_len(s)); return 0 } 205func ps_pn(v: i64) -> i64 { 206 var m: i64 = v 207 if m < 0 { ps_puts("-" as *u8); m = 0 - m } 208 let t: *u8 = sys_mmap(32) 209 var k: i64 = 0 210 if m == 0 { t[0] = 48 as u8; k = 1 } 211 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 212 let o: *u8 = sys_mmap(32) 213 var i: i64 = 0 214 while i < k { o[i] = t[k - 1 - i]; i = i + 1 } 215 sys_write(1, o, k) 216 return 0 217} 218// file size via stat -- NOT a read. -1 if it cannot be stat'd (absent/unreadable). 219func ps_size(path: *u8) -> i64 { 220 let sb: *u8 = sys_mmap(PS_STATBUF_BYTES) 221 if sys_fstatat(path, sb) < 0 { return 0 - 1 } 222 let sp: *i64 = (sb as i64 + PS_STAT_SIZE_OFF) as *i64 223 return sp[0] 224} 225// ★★★★★★A BYTE-FOR-BYTE VERIFY IS STRUCTURALLY BLIND TO MODE: an installed binary WITHOUT THE 226// EXECUTE BIT is byte-perfect, passes every size and content comparison this organ makes, and CANNOT 227// RUN. MEASURED 2026-08-16 and it cost an outage: nx_daemon_supervisor.elf was installed 0644 on Aug 10, 228// the running instance kept serving from a now-DELETED inode for six days, and the estate only found out 229// when that process was killed -- at which point the fleet supervisor could not be restarted AT ALL. 230// ★★★★★★A DAEMON RUNNING FROM AN OLD INODE MASKS AN UNRUNNABLE BINARY ON DISK; THE DEFECT IS 231// INVISIBLE UNTIL THE NEXT RESTART, WHICH IS EXACTLY WHEN YOU NEED IT. 232// The mode is in the SAME stat this organ already performs (st_mode at byte 24 of struct stat on x86-64), 233// so this costs no extra syscall -- it was free information being discarded. Read as 4 bytes: taking an 234// i64 there would swallow st_uid in the high half. 235// Owner-execute is octal 0100 = 64; tested arithmetically because that needs no bitwise operator. 236func ps_execbit(path: *u8) -> i64 { 237 let sb: *u8 = sys_mmap(PS_STATBUF_BYTES) 238 if sys_fstatat(path, sb) < 0 { return 0 - 1 } 239 let mo: i64 = (sb as i64 + PS_STAT_MODE_OFF) as *u8 as i64 240 let b0: i64 = (mo as *u8)[0] as i64 241 let b1: i64 = (mo as *u8)[1] as i64 242 let mode: i64 = b0 + b1 * PS_BYTE_RADIX 243 if (mode / PS_MODE_OWNER_X) % PS_BIT_SET == 1 { return 1 } 244 return 0 245} 246// THE ARMED AXIS (2026-09-03). Build `<root><basename>.nx` from a served elf path, using the SAME 247// basename extent [bs,te) the build path bp is already built from -- so the source this asks about is by 248// construction the source the builder compiles, not a second guess at the name. 249func ps_srcpath(root: *u8, elf: *u8, bs: i64, te: i64, out: *u8) -> i64 { 250 var o: i64 = 0 251 var i: i64 = 0 252 while root[i] != (0 as u8) { out[o] = root[i]; o = o + 1; i = i + 1 } 253 var m: i64 = bs 254 while m < te { out[o] = elf[m]; o = o + 1; m = m + 1 } 255 let x: *u8 = ".nx" as *u8 256 var j: i64 = 0 257 while x[j] != (0 as u8) { out[o] = x[j]; o = o + 1; j = j + 1 } 258 out[o] = 0 as u8 259 return o 260} 261 262// Classify the SOURCE behind a served elf, probing _hdl_build FIRST then runtime -- the builder's own 263// order, so a shadowed twin is classified as the twin that actually compiles. UNREADABLE from BOTH roots 264// stays UNREADABLE and is NOT read as safe: an axis that cannot see must abstain, never acquit. 265func ps_srcclass(srca: *u8, srcb: *u8, elf: *u8, bs: i64, te: i64) -> i64 { 266 let sp: *u8 = sys_mmap(PS_NAMEMAX) 267 ps_srcpath(srca, elf, bs, te, sp) 268 let c1: i64 = sm_classify_path(sp) 269 if c1 != SM_UNREADABLE { return c1 } 270 ps_srcpath(srcb, elf, bs, te, sp) 271 return sm_classify_path(sp) 272} 273 274// append helpers for the durable trend row (no allocation per call; caller owns the buffer). 275func ad_cat(d: *u8, o: i64, s: *u8) -> i64 { var p: i64 = o; var i: i64 = 0; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p } 276func ad_catn(d: *u8, o: i64, v: i64) -> i64 { 277 var m: i64 = v 278 var p: i64 = o 279 if m < 0 { d[p] = 45 as u8; p = p + 1; m = 0 - m } 280 let t: *u8 = sys_mmap(32) 281 var k: i64 = 0 282 if m == 0 { t[0] = 48 as u8; k = 1 } 283 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 284 var i: i64 = 0 285 while i < k { d[p] = t[k - 1 - i]; p = p + 1; i = i + 1 } 286 return p 287} 288func ps_streq(a: *u8, b: *u8) -> i64 { 289 var i: i64 = 0 290 var eq: i64 = 1 291 var go: i64 = 1 292 while go == 1 { 293 let ca: i64 = a[i] as i64 294 let cb: i64 = b[i] as i64 295 if ca != cb { eq = 0; go = 0 } else { if ca == 0 { go = 0 } else { i = i + 1 } } 296 } 297 return eq 298} 299// byte-compare two files. 1 identical, 0 differ, 0-1 unreadable (which must NOT read as identical). 300func ps_same(a: *u8, b: *u8) -> i64 { 301 let la: *i64 = sys_mmap(16) as *i64 302 let lb: *i64 = sys_mmap(16) as *i64 303 let ba: *u8 = sys_read_file(a, la) 304 if (ba as i64) == 0 { return 0 - 1 } 305 let bb: *u8 = sys_read_file(b, lb) 306 if (bb as i64) == 0 { return 0 - 1 } 307 if la[0] != lb[0] { return 0 } 308 var i: i64 = 0 309 var same: i64 = 1 310 var go: i64 = 1 311 while go == 1 { 312 if i >= la[0] { go = 0 } else { 313 if ba[i] != bb[i] { same = 0; go = 0 } else { i = i + 1 } 314 } 315 } 316 return same 317} 318 319// fork nx_contentdiff on (live, built) and return 1 iff it reports verdict=GREEN, 0 if RED, -1 if the 320// ruler could not be run at all. COMPOSES THE INCUMBENT RULER -- there is exactly one content-differ in 321// this estate and this is not a second one. ★★★★★A SWEEP THAT RE-IMPLEMENTS ITS RULER IS TWO RULERS THAT 322// WILL DISAGREE; forking it keeps the arithmetic in one place and this organ only TALLIES. 323// --- READING THE RULER'S REPORT --------------------------------------------------------------- 324// ★★★★★★ANCHOR ON THE LINE, NEVER ON A BARE KEY. nx_contentdiff prints `lost_from_live=` MID-LINE, 325// on the line that STARTS with `runs_scanned=`. A whole-buffer search for the bare key would also 326// match that key echoed in a banner, in prose, or in some future field named after it -- which is 327// exactly how a parser ends up reading the documentation as the answer. 328func ps_line_at(b: *u8, n: i64, key: *u8, klen: i64) -> i64 { 329 var i: i64 = 0 330 var hit: i64 = 0 - 1 331 var go: i64 = 1 332 while go == 1 { 333 if i + klen > n { go = 0 } else { 334 var starts: i64 = 0 335 if i == 0 { starts = 1 } else { if b[i - 1] == (PS_NL as u8) { starts = 1 } } 336 if starts == 1 { 337 if ps_streq_n(((b as i64) + i) as *u8, key, klen) == 1 { hit = i; go = 0 } 338 } 339 if go == 1 { i = i + 1 } 340 } 341 } 342 return hit 343} 344 345// Read the integer following `key` WITHIN the line beginning at `ls`. Bounded by the newline, so a 346// later line carrying the same key can never answer for this one. -1 = the key is not on this line, 347// which is a THIRD STATE and must not be printed as a zero. 348func ps_val_in_line(b: *u8, n: i64, ls: i64, key: *u8, klen: i64) -> i64 { 349 var i: i64 = ls 350 var v: i64 = 0 - 1 351 var go: i64 = 1 352 while go == 1 { 353 if i + klen > n { go = 0 } else { 354 if b[i] == (PS_NL as u8) { go = 0 } else { 355 if ps_streq_n(((b as i64) + i) as *u8, key, klen) == 1 { 356 var j: i64 = i + klen 357 var acc: i64 = 0 358 var any: i64 = 0 359 var d: i64 = 1 360 while d == 1 { 361 if j >= n { d = 0 } else { 362 if b[j] < (48 as u8) { d = 0 } else { 363 if b[j] > (57 as u8) { d = 0 } else { 364 acc = acc * 10 + ((b[j] as i64) - 48); any = 1; j = j + 1 365 } 366 } 367 } 368 } 369 if any == 1 { v = acc } 370 go = 0 371 } else { i = i + 1 } 372 } 373 } 374 } 375 return v 376} 377 378// NAME THE RUNS UNDER THE ROW THAT LOST THEM, and hand back the ruler's own numbers. 379// ★★★★★A CAP YOU DO NOT OWN IS STILL A CAP: nx_contentdiff PRINTS a bounded list of lost runs while 380// COUNTING every occurrence, so echoing its list without its count republishes a prefix as the 381// population -- the very defect this organ exists to find, committed one layer down. When the two 382// disagree this says PREFIX out loud rather than letting the shorter list read as the whole answer. 383func ps_explain(tmp: *u8, out: *i64) -> i64 { 384 out[0] = 0 - 1 385 out[1] = 0 - 1 386 out[2] = 0 - 1 387 let rl: *i64 = sys_mmap(16) as *i64 388 let b: *u8 = sys_read_file(tmp, rl) 389 if (b as i64) == 0 { return 0 - 1 } 390 let n: i64 = rl[0] 391 if n <= 0 { return 0 - 1 } 392 // ★★★★★★A HAND-COUNTED LENGTH BESIDE A STRING LITERAL IS A SECOND COPY OF THAT LITERAL'S SHAPE, AND 393 // THE TWO DRIFT SILENTLY: change the string, forget the number, and the parser reads the wrong window 394 // while still compiling and still appearing to work. These were 13 / 15 / 12, hand-counted -- and 395 // `ps_len` was already defined 100 lines above, so this file counted by hand beside its own helper. 396 // Each key is now bound ONCE and its length DERIVED from that binding: one source of truth. 397 let k_runs: *u8 = "runs_scanned=" as *u8 398 let k_lost: *u8 = "lost_from_live=" as *u8 399 let k_perm: *u8 = "lost_permil=" as *u8 400 let ls: i64 = ps_line_at(b, n, k_runs, ps_len(k_runs)) 401 if ls >= 0 { 402 out[0] = ps_val_in_line(b, n, ls, k_lost, ps_len(k_lost)) 403 out[1] = ps_val_in_line(b, n, ls, k_perm, ps_len(k_perm)) 404 out[2] = ps_val_in_line(b, n, ls, k_runs, ps_len(k_runs)) 405 } 406 var i: i64 = 0 407 var printed: i64 = 0 408 var go: i64 = 1 409 // Same rule as the keys above: the marker is bound ONCE and its width DERIVED. It appeared as a bare 410 // `8` in FOUR places here (bound test, skip, slice start, slice length) -- four copies of one string's 411 // length, any of which a one-character edit to the marker would silently falsify. 412 let k_lostpfx: *u8 = " LOST: " as *u8 413 let nlost: i64 = ps_len(k_lostpfx) 414 while go == 1 { 415 if i + nlost > n { go = 0 } else { 416 var starts: i64 = 0 417 if i == 0 { starts = 1 } else { if b[i - 1] == (PS_NL as u8) { starts = 1 } } 418 var adv: i64 = 1 419 if starts == 1 { 420 if ps_streq_n(((b as i64) + i) as *u8, k_lostpfx, nlost) == 1 { 421 var e: i64 = i + nlost 422 var seek: i64 = 1 423 while seek == 1 { 424 if e >= n { seek = 0 } else { 425 if b[e] == (PS_NL as u8) { seek = 0 } else { e = e + 1 } 426 } 427 } 428 ps_puts(" lost-run: " as *u8) 429 sys_write(1, ((b as i64) + i + nlost) as *u8, e - i - nlost) 430 ps_puts("\n" as *u8) 431 printed = printed + 1 432 i = e 433 adv = 0 434 } 435 } 436 if adv == 1 { i = i + 1 } 437 } 438 } 439 ps_puts(" ruler_says lost_runs=" as *u8); ps_pn(out[0]) 440 ps_puts(" permil=" as *u8); ps_pn(out[1]) 441 ps_puts(" of_runs_scanned=" as *u8); ps_pn(out[2]) 442 ps_puts(" named_here=" as *u8); ps_pn(printed) 443 if printed < out[0] { ps_puts(" <== THIS LIST IS A PREFIX OF ITS OWN COUNT, NOT THE POPULATION" as *u8) } 444 ps_puts("\n" as *u8) 445 return printed 446} 447 448func ps_judge(live: *u8, built: *u8, tmp: *u8) -> i64 { 449 let pid: i64 = sys_fork() 450 if pid == 0 { 451 let ofd: i64 = sys_openat_wr(tmp, PS_MODE_0644) 452 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 453 let av: *i64 = sys_mmap(64) as *i64 454 av[0] = "_offc/nx_contentdiff.elf" as *u8 as i64 455 av[1] = live as i64 456 av[2] = built as i64 457 av[3] = 0 458 let ev: *i64 = sys_mmap(16) as *i64 459 ev[0] = "PATH=/usr/bin:/bin" as *u8 as i64 460 ev[1] = 0 461 sys_execve("_offc/nx_contentdiff.elf" as *u8, av, ev) 462 sys_exit(PS_EXIT_NOTFOUND) 463 } 464 let st: *i64 = sys_mmap(16) as *i64 465 sys_wait4(pid, st, 0) 466 let rl: *i64 = sys_mmap(16) as *i64 467 let rb: *u8 = sys_read_file(tmp, rl) 468 if (rb as i64) == 0 { return 0 - 1 } 469 if rl[0] <= 0 { return 0 - 1 } 470 // ANCHOR ON THE RULER'S OWN VERDICT TOKEN, and treat an unreadable run as UNJUDGED rather than as a 471 // pass -- "I could not look" is never "it is safe". 472 var i: i64 = 0 473 var green: i64 = 0 474 // The ruler's verdict token, bound once and measured -- it was a hand-counted 13 in TWO places. 475 let k_green: *u8 = "verdict=GREEN" as *u8 476 let ngreen: i64 = ps_len(k_green) 477 while i + ngreen <= rl[0] { 478 if rb[i] == (PS_ASCII_v as u8) { 479 if ps_streq_n(((rb as i64) + i) as *u8, k_green, ngreen) == 1 { green = 1; i = rl[0] } 480 } 481 i = i + 1 482 } 483 return green 484} 485// compare exactly n bytes (no NUL needed on either side) 486func ps_streq_n(a: *u8, b: *u8, n: i64) -> i64 { 487 var i: i64 = 0 488 while i < n { if a[i] != b[i] { return 0 } i = i + 1 } 489 return 1 490} 491 492// --- OWNER-SIGNAL AXIS: the measurement primitives ------------------------------------------------ 493// does NUL-terminated `s` contain `sub`? No allocation; bounded by the NUL. 494func ps_contains(s: *u8, sub: *u8) -> i64 { 495 let n: i64 = ps_len(s) 496 let m: i64 = ps_len(sub) 497 if m > n { return 0 } 498 var i: i64 = 0 499 while i + m <= n { 500 if ps_streq_n(((s as i64) + i) as *u8, sub, m) == 1 { return 1 } 501 i = i + 1 502 } 503 return 0 504} 505func ps_startswith(s: *u8, pfx: *u8) -> i64 { 506 let m: i64 = ps_len(pfx) 507 if ps_len(s) < m { return 0 } 508 return ps_streq_n(s, pfx, m) 509} 510 511// LOAD THE SCRATCH SIBLINGS ONCE PER SOURCE ROOT, NEVER ONCE PER ROW. 512// ★COUNT SYSCALLS PER UNIT OF OUTPUT -- THAT IS THE REAL COMPLEXITY: a getdents sweep per BEHIND row is 513// hundreds of walks of the same two directories. One pass each fills a small table (762 entries measured 514// estate-wide) and every row after that is a table scan. 515// ⚠ONE getdents64 CALL IS NOT A DIRECTORY LISTING -- loop until it returns <= 0, or a big directory is 516// silently read as a PREFIX and its total published as a fact. 517// Sets full[0]=1 if the table filled. A table that quietly stopped counting yields FEWER flags, and 518// fewer flags is the UNSAFE direction on this axis, so it can never be allowed to fill in silence. 519func ps_load_scratch(dir: *u8, tab: *i64, cap: i64, full: *i64) -> i64 { 520 var n: i64 = 0 521 if cap <= 0 { full[0] = 1; return 0 } 522 let fd: i64 = sys_openat_rd(dir) 523 if fd < 0 { return 0 } 524 let dbuf: *u8 = sys_mmap(PS_OWN_DIRBUF) 525 var go: i64 = 1 526 while go == 1 { 527 let nr: i64 = sys_getdents64(fd, dbuf, PS_OWN_DIRBUF) 528 if nr <= 0 { go = 0 } else { 529 var off: i64 = 0 530 while off < nr { 531 let rec: *u8 = (dbuf as i64 + off) as *u8 532 let nm: *u8 = dirent_name(rec) 533 if ps_contains(nm, PS_SCRATCH_MARK) == 1 { 534 if n < cap { 535 let cp: *u8 = sys_mmap(PS_NAMEMAX) 536 var k: i64 = 0 537 while nm[k] != (0 as u8) { if k < PS_NAMEMAX - 1 { cp[k] = nm[k] } k = k + 1 } 538 if k > PS_NAMEMAX - 1 { k = PS_NAMEMAX - 1 } 539 cp[k] = 0 as u8 540 tab[n] = cp as i64 541 n = n + 1 542 } else { full[0] = 1 } 543 } 544 let rl2: i64 = dirent_reclen(rec) 545 if rl2 <= 0 { off = nr } else { off = off + rl2 } 546 } 547 } 548 } 549 sys_close(fd) 550 return n 551} 552 553// Every `<name>.elf` in `dir`, as a table of heap-copied basenames. Returns the count, or -1 if the 554// DIRECTORY ITSELF cannot be opened -- a THIRD STATE, deliberately distinct from "the directory is 555// empty", because "I could not look" must never be reported as "they agree". 556// THE `.elf` SUFFIX TEST IS THE WHOLE FILTER, AND IT IS MECHANICAL RATHER THAN A HAND-MAINTAINED 557// BLOCKLIST. The fork root is full of backup fossils -- .elf.bak0719, .elf.prev, .elf.prev2, 558// .elf.stale0706, .elf.KNOWNGOOD-1785561900, .elf.REGRESSED-20260801-0126, .elf.pre-bracefix-20260804 -- 559// and every one of them carries a FURTHER extension, so NONE of them ends in `.elf`. Non-ELF payloads 560// sharing the directory (.efi, .img, .txt, .py, .csv, .md, .html, KERNEL.NXE) fall out of the same test. 561// A blocklist would need extending every time somebody invents a new backup suffix; this cannot rot. 562// ONE getdents64 CALL IS NOT A DIRECTORY LISTING -- the loop runs until the syscall returns 0, or a big 563// directory is silently read as a prefix and its total published as a fact. 564func ps_dir_elfs(dir: *u8, tab: *i64, cap: i64, full: *i64) -> i64 { 565 var n: i64 = 0 566 if cap <= 0 { full[0] = 1; return 0 } 567 let fd: i64 = sys_openat_rd(dir) 568 if fd < 0 { return 0 - 1 } 569 let dbuf: *u8 = sys_mmap(PS_OWN_DIRBUF) 570 var go: i64 = 1 571 while go == 1 { 572 let nr: i64 = sys_getdents64(fd, dbuf, PS_OWN_DIRBUF) 573 if nr <= 0 { go = 0 } else { 574 var off: i64 = 0 575 while off < nr { 576 let rec: *u8 = (dbuf as i64 + off) as *u8 577 let nm: *u8 = dirent_name(rec) 578 if ps_endswith(nm, ps_len(nm), ".elf" as *u8) == 1 { 579 if n < cap { 580 let cp: *u8 = sys_mmap(PS_NAMEMAX) 581 var k: i64 = 0 582 while nm[k] != (0 as u8) { if k < PS_NAMEMAX - 1 { cp[k] = nm[k] } k = k + 1 } 583 if k > PS_NAMEMAX - 1 { k = PS_NAMEMAX - 1 } 584 cp[k] = 0 as u8 585 tab[n] = cp as i64 586 n = n + 1 587 } else { full[0] = 1 } 588 } 589 let rl2: i64 = dirent_reclen(rec) 590 if rl2 <= 0 { off = nr } else { off = off + rl2 } 591 } 592 } 593 } 594 sys_close(fd) 595 return n 596} 597 598// st_mtime seconds, from the SAME stat this organ already knows how to take. -1 = cannot stat, which is 599// a THIRD STATE and must never be printed or compared as a zero. 600func ps_mtime(path: *u8) -> i64 { 601 let sb: *u8 = sys_mmap(PS_STATBUF_BYTES) 602 if sys_fstatat(path, sb) < 0 { return 0 - 1 } 603 let mp: *i64 = (sb as i64 + PS_STAT_MTIME_OFF) as *i64 604 return mp[0] 605} 606 607// Is `name` declared in the ownership conf? FIELD 0 of a non-comment line, terminated by TAB or newline. 608// ★★★★★★ANCHOR ON THE LINE, NEVER ON A BARE KEY: a whole-buffer substring search would match the name 609// inside somebody else's free-text REASON and report a row as claimed that nobody claimed. 610func ps_decl_has(b: *u8, n: i64, name: *u8) -> i64 { 611 if n <= 0 { return 0 } 612 let m: i64 = ps_len(name) 613 var i: i64 = 0 614 var hit: i64 = 0 615 while i < n { 616 var e: i64 = i 617 var seek: i64 = 1 618 while seek == 1 { 619 if e >= n { seek = 0 } else { 620 if b[e] == (PS_NL as u8) { seek = 0 } else { e = e + 1 } 621 } 622 } 623 if e > i { 624 if (b[i] as i64) != PS_ASCII_HASH { 625 if i + m <= e { 626 if ps_streq_n(((b as i64) + i) as *u8, name, m) == 1 { 627 var term: i64 = 0 628 if i + m == e { term = 1 } else { 629 if (b[i + m] as i64) == PS_TAB { term = 1 } 630 } 631 if term == 1 { hit = 1 } 632 } 633 } 634 } 635 } 636 i = e + 1 637 } 638 return hit 639} 640 641// count (and on demand NAME) the scratch siblings whose entry starts with `<stem>.nx.`. 642func ps_scratch_count(tab: *i64, ntab: i64, pfx: *u8, show: i64) -> i64 { 643 var c: i64 = 0 644 var i: i64 = 0 645 while i < ntab { 646 let nm: *u8 = tab[i] as *u8 647 if ps_startswith(nm, pfx) == 1 { 648 if show == 1 { if c < PS_OWN_NAMES_SHOWN { ps_puts(" scratch-sibling: " as *u8); ps_puts(nm); ps_puts("\n" as *u8) } } 649 c = c + 1 650 } 651 i = i + 1 652 } 653 if show == 1 { if c > PS_OWN_NAMES_SHOWN { ps_puts(" <== THIS LIST IS A PREFIX OF ITS OWN COUNT, NOT THE POPULATION\n" as *u8) } } 654 return c 655} 656 657// THE OWNER-SIGNAL COLLECTOR -- the DM5 contract symbol, and the single entry point for the axis. 658// One BEHIND row in; the three measured signals out, into `out` = [declared, srcpath-or-0, scratch, day]. 659// Returns 1 when the source RESOLVED and 0 when it did not, because a caller must be able to tell 660// "measured zero" from "could not look" without inspecting the payload. 661// SOURCE PROBE ORDER MIRRORS THE BUILDER'S (_hdl_build first, runtime second). A resolver that disagrees 662// with the builder reports about a file that is not the one that compiles. 663func ps_owner_scan(stm: *u8, srca: *u8, srcb: *u8, tab: *i64, ntab: i64, declb: *u8, decln: i64, now: i64, out: *i64) -> i64 { 664 out[0] = ps_decl_has(declb, decln, stm) 665 let spa: *u8 = sys_mmap(PS_NAMEMAX) 666 var po: i64 = ad_cat(spa, 0, srca) 667 po = ad_cat(spa, po, stm) 668 po = ad_cat(spa, po, PS_SRC_EXT) 669 spa[po] = 0 as u8 670 var mt: i64 = ps_mtime(spa) 671 if mt < 0 { 672 po = ad_cat(spa, 0, srcb) 673 po = ad_cat(spa, po, stm) 674 po = ad_cat(spa, po, PS_SRC_EXT) 675 spa[po] = 0 as u8 676 mt = ps_mtime(spa) 677 } 678 // NO SOURCE UNDER EITHER ROOT: the axis ABSTAINS. -1 is a THIRD STATE, never a measured zero. 679 if mt < 0 { out[1] = 0; out[2] = 0 - 1; out[3] = 0 - 1; out[4] = 0 - 1; return 0 } 680 out[1] = spa as i64 681 let pfx: *u8 = sys_mmap(PS_NAMEMAX) 682 var xo: i64 = ad_cat(pfx, 0, stm) 683 xo = ad_cat(pfx, xo, PS_SCRATCH_MARK) 684 pfx[xo] = 0 as u8 685 out[2] = ps_scratch_count(tab, ntab, pfx, 0) 686 // SAME-DAY TOUCH ONLY, NEVER STALENESS. A future stamp (clock skew) counts as same-day too: erring 687 // toward flagging is the direction that cannot cost a sibling seat their work. 688 var sd: i64 = 0 689 if mt / PS_SECS_PER_DAY >= now / PS_SECS_PER_DAY { sd = 1 } 690 out[3] = sd 691 // THE SOURCE'S OWN STAMP TRAVELS OUT TOO: the caller needs it to ask whether the _build artifact it 692 // is about to call "the fix" was even produced AFTER this source was last written. 693 out[4] = mt 694 return 1 695} 696 697func main(argc: i64, argv: *i64) -> i64 { 698 var reg: *u8 = PS_DEFAULT_REG 699 var broot: *u8 = PS_DEFAULT_BROOT 700 // JUDGE MODE: after the size census, ask the CONTENT question on every STALE row. 701 // WHY THIS IS NOT nx_stale_check's JOB: that organ REBUILDS each target and compares against a FRESH 702 // build -- authoritative, and one compile per row, which is why it is a per-promote adjudicator and 703 // not a population sweep. This mode asks the CHEAPER and DIFFERENT question that the promote decision 704 // actually turns on: would installing THE ARTIFACT THAT ALREADY EXISTS lose capability? For that, the 705 // `_build` artifact IS the thing that would be installed, so comparing against it is exact, and it 706 // costs two file reads instead of a compile. ★★★★★★TWO ADJUDICATORS ARE NOT RIVALS WHEN THEY ANSWER 707 // DIFFERENT QUESTIONS AT DIFFERENT COSTS -- SAYING WHICH IS WHICH IS WHAT STOPS THE CHEAP ONE BEING 708 // MISTAKEN FOR THE AUTHORITATIVE ONE. 709 var judge: i64 = 0 710 if argc >= 2 { if ps_streq(argv[1] as *u8, "judge" as *u8) == 1 { judge = 1 } } 711 // ⚠ARG SHIFT: in judge mode argv[1] is the VERB, so the optional paths move up one. Without this the 712 // registry path would silently become the literal "judge" and the census would report NO ROWS -- a 713 // confident empty answer, which is the worst failure shape a census has. 714 // OWNER-SIGNAL AXIS inputs. All optional, all overridable, so a GATE can point this organ at a 715 // FIXTURE tree instead of the live one. ⚠THE TREND LOG IS DELIBERATELY ONE OF THEM: a gate that 716 // shares its fixture with a production beat writes bogus rows into the trend everyone plans against, 717 // and that is a measured defect class in this estate, not a hypothetical. 718 var srca: *u8 = PS_SRCROOT_A 719 var srcb: *u8 = PS_SRCROOT_B 720 var declp: *u8 = PS_DECLARE_CONF 721 var logp: *u8 = PS_DRIFT_LOG 722 // THE FORK ROOT IS OVERRIDABLE FOR THE SAME REASON EVERY OTHER PATH ABOVE IS: so a GATE can point 723 // this axis at a FIXTURE tree instead of the live one. It shipped hard-coded for exactly one edit, 724 // and that is recorded rather than quietly fixed -- a hard-coded subject would have forced its own 725 // bite proof to MUTATE buildroot/_offc, which is the directory nx_compare_regen forks. A gate that 726 // must perturb a live shared artifact to prove itself is a gate that can take the estate down to 727 // report on it, and this organ already refuses that trade everywhere else. 728 var forkp: *u8 = PS_FORKROOT 729 if judge == 1 { 730 if argc >= 3 { reg = argv[2] as *u8 } 731 if argc >= 4 { broot = argv[3] as *u8 } 732 if argc >= 5 { srca = argv[4] as *u8 } 733 if argc >= 6 { srcb = argv[5] as *u8 } 734 if argc >= 7 { declp = argv[6] as *u8 } 735 if argc >= 8 { logp = argv[7] as *u8 } 736 if argc >= 9 { forkp = argv[8] as *u8 } 737 } else { 738 if argc >= 2 { reg = argv[1] as *u8 } 739 if argc >= 3 { broot = argv[2] as *u8 } 740 if argc >= 4 { srca = argv[3] as *u8 } 741 if argc >= 5 { srcb = argv[4] as *u8 } 742 if argc >= 6 { declp = argv[5] as *u8 } 743 if argc >= 7 { logp = argv[6] as *u8 } 744 if argc >= 8 { forkp = argv[7] as *u8 } 745 } 746 747 // HEAVY-I/O BOUND (2026-09-02): a whole-registry census asks the estate-wide concurrency bound BEFORE it walks. 748 // Governs the PRODUCTION run only (no fixture paths passed): a gate pointing this organ at a fixture tree is 749 // small and must never read DEFER for the wrong reason (a busy box). DEFER exits 4 (the estate's refused- 750 // admission code) and the beat re-fires; UNOBSERVABLE proceeds, ANNOUNCED, so a missing conf can never 751 // silence the drift census. 752 var prod_run: i64 = 1 753 if judge == 1 { if argc >= 3 { prod_run = 0 } } else { if argc >= 2 { prod_run = 0 } } 754 if prod_run == 1 { 755 let hio: *i64 = sys_mmap(32) as *i64 756 let hv: i64 = hio_admit(hio) 757 hio_announce(1, hv, hio) 758 if hv == HIO_DEFER { ps_puts("ARTIFACTDRIFT DEFERRED: heavy-I/O bound reached; the beat re-fires\n" as *u8); sys_exit(4); return 4 } 759 } else { ps_puts("HEAVYIO fixture-run: bound not consulted\n" as *u8) } 760 ps_puts("=== nx_artifactdrift registry=" as *u8); ps_puts(reg) 761 ps_puts(" buildroot=" as *u8); ps_puts(broot); ps_puts(" ===\n" as *u8) 762 763 let rl: *i64 = sys_mmap(16) as *i64 764 let rb: *u8 = sys_read_file(reg, rl) 765 if (rb as i64) == 0 { 766 ps_puts("ARTIFACTDRIFT REFUSE: cannot read the registry\n" as *u8) 767 sys_exit(3) 768 return 3 769 } 770 771 let seen: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 772 var nseen: i64 = 0 773 // WORKLISTS, NOT JUST COUNTERS. A class that is counted but never named cannot be acted on -- the 774 // reader is told a number and given no way to start. STALE already printed its rows; NO-SERVED and 775 // NO-BUILD did not, so two thirds of this census was unactionable by construction. 776 // Each list is a SUBSET of the distinct binaries, so PS_MAXROW already bounds it and the existing 777 // capacity REFUSAL already covers it -- no second cap, and no second number anyone has to guess. 778 let lsv: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 779 let lbd: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 780 let lsp: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 781 // AHEAD is the DANGEROUS class -- the one row type where the obvious action (promote) DESTROYS 782 // capability -- and it was the one class still reported as a bare count. Same "count without a 783 // worklist" defect I had already fixed for NO-SERVED / NO-BUILD, missed here because the STALE 784 // sub-split was added later. ★★★★★FIXING A DEFECT CLASS ONCE DOES NOT FIX THE INSTANCES ADDED AFTER. 785 let lah: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 786 // ⚠FOURTH TIME. I have added four classifications to this organ (NO-SERVED, NO-BUILD, AHEAD, 787 // WOULD-LOSE) and forgotten the worklist on THREE of them, fixing each as a separate lesson. 788 // ★★★★★★THE DEFECT IS NOT THE MISSING LIST, IT IS THAT A COUNTER IS THE DEFAULT AND A LIST IS AN 789 // AFTERTHOUGHT -- SO EVERY NEW BUCKET STARTS OUT UNACTIONABLE AND STAYS THAT WAY UNTIL SOMEBODY 790 // TRIES TO USE IT. If you add a counter to this organ, add its array in the same edit; the count 791 // tells a reader how bad it is and ONLY the list lets them start. 792 let ljl: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 793 // ...and the REASON travels with the row. A worklist of 24 paths answers "which rows" and leaves 794 // "why" to 24 hand re-runs of a ruler this organ ALREADY RAN once per row. 795 // INERT: served, byte-perfect, and NOT EXECUTABLE. ⚠THIS IS A SEPARATE AXIS, NOT A NEW MEMBER OF THE 796 // IDENTICAL/STALE/NO-BUILD/NO-SERVED/STAGED-POINTER PARTITION -- a binary can be IDENTICAL *and* 797 // INERT at the same time, so folding it in would break the partition that must sum. It is counted 798 // and listed on its own, and its total is deliberately NOT added to `sum`. 799 // ★★★★★A NEW BUCKET THAT OVERLAPS AN EXISTING PARTITION MUST BE DECLARED A SEPARATE AXIS, OR THE 800 // RECONCILIATION THAT MADE THE PARTITION TRUSTWORTHY QUIETLY STOPS BEING TRUE. 801 let lin: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 802 var inert: i64 = 0 803 // ARMED: a SERVED binary whose SOURCE has a stub main -- `func main() -> i64 { return 0 }`, the 804 // estate's `compile-only smoke` convention for libraries. Nothing is reachable from that main, so a 805 // rebuild DEAD-STRIPS the whole closure and /api/build stages a do-nothing binary with NO error. 806 // ANY ordinary build-then-promote on such a target replaces a working tool with one that returns 0, 807 // silently, off a GREEN receipt. MEASURED 2026-09-03 on nx_https_get: staged 14,880 B against a 808 // 468,929 B live binary, while its closure-sharing sibling nx_research_fetch builds to 566,096. 809 // ⚠SEPARATE AXIS, NOT A PARTITION MEMBER -- same call this organ already makes for INERT and for the 810 // same structural reason: a row can be IDENTICAL *and* ARMED at once, so folding it into the sum 811 // would break the reconciliation that makes the partition worth trusting. Deliberately NOT added. 812 // ⚠AND IT IS NOT A SIZE RULE. The tempting form is "refuse a candidate far smaller than live", but 813 // that is a magic number that fails BOTH ways: a legitimate toolchain shrink of 304 permil is on 814 // record, and a stub of a SMALL program is barely smaller than the real thing. The structural fact 815 // (main calls nothing) is the signal; size is at most a triage hint. 816 let larm: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 817 var armed: i64 = 0 818 // Sources unreadable from BOTH roots. An axis that cannot see must ABSTAIN, never acquit, and the 819 // abstention needs its own counter or a blind census reads as a clean one. 820 var armunproven: i64 = 0 821 let ljlost: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 822 let ljpm: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 823 let jout: *i64 = sys_mmap(64) as *i64 824 // --- OWNER-SIGNAL AXIS: per-BEHIND-row signals are RECORDED during the sweep and ADJUDICATED AFTER 825 // it. The day signal can only be trusted once its rate over the WHOLE BEHIND population is known -- 826 // a signal that is TRUE FOR EVERY ROW IT COULD MEASURE carries no information. 827 // ★★★★★A SIGNAL THAT FIRES ON EVERYTHING DISCRIMINATES NOTHING, so the rate is MEASURED, never assumed. 828 let lbh: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 829 let lbsrc: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 830 let lbscr: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 831 let lbday: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 832 let lbdec: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 833 let oout: *i64 = sys_mmap(64) as *i64 834 // REF-FRESHNESS per BEHIND row: the state, and the AGE of the reference in seconds. A row that cannot 835 // say how old its evidence is invites the reader to assume it is current. 836 let lbref: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 837 let lbrage: *i64 = sys_mmap(PS_MAXROW*PS_I64_BYTES) as *i64 838 var nbeh: i64 = 0 839 // BOTH source roots are loaded into ONE table on purpose: a stem that exists in both trees then 840 // counts scratch from either, which OVER-flags. That is the safe direction on this axis and is 841 // stated rather than left for a reader to discover. 842 let sctab: *i64 = sys_mmap(PS_SCRATCH_MAX*PS_I64_BYTES) as *i64 843 let scfull: *i64 = sys_mmap(16) as *i64 844 scfull[0] = 0 845 var nsc: i64 = ps_load_scratch(srca, sctab, PS_SCRATCH_MAX, scfull) 846 nsc = nsc + ps_load_scratch(srcb, ((sctab as i64) + nsc * PS_I64_BYTES) as *i64, PS_SCRATCH_MAX - nsc, scfull) 847 let dcl: *i64 = sys_mmap(16) as *i64 848 let dcb: *u8 = sys_read_file(declp, dcl) 849 var dcn: i64 = 0 850 if (dcb as i64) != 0 { dcn = dcl[0] } 851 let nowsec: i64 = sys_now_realtime_sec() 852 var over: i64 = 0 853 var identical: i64 = 0 854 var stale: i64 = 0 855 var nobuild: i64 = 0 856 var noserved: i64 = 0 857 var stagedptr: i64 = 0 858 var behind: i64 = 0 859 var ahead: i64 = 0 860 var resized: i64 = 0 861 var jgreen: i64 = 0 862 var jred: i64 = 0 863 var junjudged: i64 = 0 864 var rows: i64 = 0 865 866 ps_puts("\n-- STALE (the served binary is NOT the one the last build produced) --\n" as *u8) 867 868 var i: i64 = 0 869 while i < rl[0] { 870 var e: i64 = i 871 var seek: i64 = 1 872 while seek == 1 { 873 if e >= rl[0] { seek = 0 } else { 874 if (rb[e] as i64) == PS_NL { seek = 0 } else { e = e + 1 } 875 } 876 } 877 if e > i { 878 if (rb[i] as i64) != PS_ASCII_HASH { 879 var t1: i64 = i 880 var s2: i64 = 1 881 while s2 == 1 { if t1 >= e { s2 = 0 } else { if (rb[t1] as i64) == PS_TAB { s2 = 0 } else { t1 = t1 + 1 } } } 882 if t1 < e { 883 var t2: i64 = t1 + 1 884 var s3: i64 = 1 885 while s3 == 1 { if t2 >= e { s3 = 0 } else { if (rb[t2] as i64) == PS_TAB { s3 = 0 } else { t2 = t2 + 1 } } } 886 let elf: *u8 = sys_mmap(PS_NAMEMAX) 887 var eo: i64 = 0 888 var k: i64 = t1 + 1 889 while k < t2 { if eo + 1 < PS_NAMEMAX { elf[eo] = rb[k]; eo = eo + 1 } k = k + 1 } 890 elf[eo] = 0 as u8 891 if eo > 0 { 892 var dup: i64 = 0 893 var d: i64 = 0 894 while d < nseen { if ps_streq(seen[d] as *u8, elf) == 1 { dup = 1 } d = d + 1 } 895 if dup == 0 { 896 if nseen < PS_MAXROW { seen[nseen] = elf as i64; nseen = nseen + 1 } else { over = 1 } 897 rows = rows + 1 898 var bs: i64 = 0 899 var q: i64 = 0 900 while q < eo { if (elf[q] as i64) == PS_ASCII_SLASH { bs = q + 1 } q = q + 1 } 901 var te: i64 = eo 902 let k_elf: *u8 = ".elf" as *u8 903 if ps_endswith(elf, eo, k_elf) == 1 { te = eo - ps_len(k_elf) } 904 let bp: *u8 = sys_mmap(PS_NAMEMAX) 905 var bo: i64 = 0 906 var bi: i64 = 0 907 while broot[bi] != (0 as u8) { bp[bo] = broot[bi]; bo = bo + 1; bi = bi + 1 } 908 var m: i64 = bs 909 while m < te { bp[bo] = elf[m]; bo = bo + 1; m = m + 1 } 910 let sfx: *u8 = ".sov.elf" as *u8 911 var si: i64 = 0 912 while sfx[si] != (0 as u8) { bp[bo] = sfx[si]; bo = bo + 1; si = si + 1 } 913 bp[bo] = 0 as u8 914 915 // A REGISTRY ROW POINTING AT A STAGED `.elf.new` IS ITS OWN DEFECT WITH ITS OWN 916 // REMEDY AND MUST NOT SHARE A COUNTER WITH "no build artifact". PROMOTION IS THE 917 // DELETION EVENT for the staged file, so such a row carries an expiry date nobody 918 // recorded: it resolves until the next promote of that target and dangles forever 919 // after. Remedy = RE-REGISTER at the promoted path, or reap the row. Remedy for 920 // NO-BUILD = BUILD IT. ★★TWO OPPOSITE ACTIONS MUST NEVER BE ONE NUMBER -- whichever 921 // bucket they land in becomes the plan somebody works from. 922 // (Before this split these rows also produced nonsense compare paths like 923 // `nx_skullsdf.sov.elf.new.sov.elf`, because the `.elf` stripper cannot see `.elf.new`.) 924 var isnew: i64 = 0 925 if ps_endswith(elf, eo, ".new" as *u8) == 1 { isnew = 1 } 926 if isnew == 1 { lsp[stagedptr] = elf as i64; stagedptr = stagedptr + 1 } else { 927 let ssz: i64 = ps_size(elf) 928 let bsz: i64 = ps_size(bp) 929 if ssz < 0 { lsv[noserved] = elf as i64; noserved = noserved + 1 } else { 930 // The served file EXISTS. Ask the question a size compare cannot: can it RUN? 931 if ps_execbit(elf) == 0 { if inert < PS_MAXROW { lin[inert] = elf as i64; inert = inert + 1 } } 932 // ARMED AXIS. We are INSIDE the ssz >= 0 branch, so the served binary 933 // provably EXISTS -- that is the `promoted_exists` half of the conjunction, 934 // established by this organ's own stat rather than assumed. The other half is 935 // the source class. Stub main ALONE is a legitimate convention (a census over 936 // 12,067 sources found 114 of them, and every one checked was correctly 937 // unpromoted); it is the CONJUNCTION that is armed. 938 let scls: i64 = ps_srcclass(srca, srcb, elf, bs, te) 939 if scls == SM_UNREADABLE { armunproven = armunproven + 1 } else { 940 if sm_is_armed(scls, 1) == 1 { if armed < PS_MAXROW { larm[armed] = elf as i64; armed = armed + 1 } } 941 } 942 if bsz < 0 { lbd[nobuild] = bp as i64; nobuild = nobuild + 1 } else { 943 var differ: i64 = 0 944 if ssz != bsz { differ = 1 } else { 945 if ps_same(elf, bp) == 0 { differ = 1 } 946 } 947 if differ == 1 { 948 stale = stale + 1 949 // ★★★★★★TWO CAUSES WITH OPPOSITE REMEDIES MUST NOT SHARE ONE COUNTER. 950 // A single STALE bucket said "235 rows differ" and hid THREE 951 // populations that need three different actions: 952 // BEHIND built > served -- code is BUILT AND NOT DEPLOYED. 953 // PROVEN COSTLY 2026-08-15: nx_drv_proto_emit sat 954 // +3,249 B BEHIND while the fix inside it was the 955 // root cause of TWO standing RED gates. Remedy: promote 956 // -- BUT ONLY AFTER nx_contentdiff SAYS lost=0. 957 // ★★★★★★SIZE DIRECTION AND CAPABILITY DIRECTION CAN POINT 958 // OPPOSITE WAYS. MEASURED 2026-08-15 on nx_verify: a FRESH build 959 // is 58,828 B vs served 51,445 -- squarely BEHIND, i.e. "promote 960 // the fix" -- yet nx_contentdiff shows the served binary holds 31 961 // runs (258 permil: PARITY / EXCEED / UNIQUE / BENCH-COVERAGE) 962 // that the BIGGER build does NOT contain. Promoting would DELETE 963 // a whole reporting lane. The build grew in other directions while 964 // that lane went missing, so the byte total says nothing about it. 965 // ⇒ THIS COLUMN IS A DIFFERENCE DETECTOR, NOT A DIRECTION OF SAFETY. 966 // Neither BEHIND nor AHEAD licenses a promote on its own. 967 // AHEAD served > built -- the RUNNING binary carries more 968 // than today's source compiles. That is the alarming 969 // direction: source loss, or a build from a different 970 // tree. Remedy: INVESTIGATE, never blind-promote -- 971 // promoting AHEAD is how capability gets deleted. 972 // RESIZED-EQUAL same size, different bytes -- a real content 973 // change no size check can see. Remedy: contentdiff. 974 var dir: *u8 = "RESIZED-EQUAL" as *u8 975 if bsz > ssz { dir = "BEHIND" as *u8; behind = behind + 1 976 // OWNER SIGNALS, taken HERE where the row's identity is in hand. 977 // The stem is the TARGET NAME /api/build takes: basename minus `.elf`. 978 if nbeh < PS_MAXROW { 979 let stm: *u8 = sys_mmap(PS_NAMEMAX) 980 var so: i64 = 0 981 var sm: i64 = bs 982 while sm < te { if so + 1 < PS_NAMEMAX { stm[so] = elf[sm]; so = so + 1 } sm = sm + 1 } 983 stm[so] = 0 as u8 984 lbh[nbeh] = elf as i64 985 ps_owner_scan(stm, srca, srcb, sctab, nsc, dcb, dcn, nowsec, oout) 986 lbdec[nbeh] = oout[0] 987 lbsrc[nbeh] = oout[1] 988 lbscr[nbeh] = oout[2] 989 lbday[nbeh] = oout[3] 990 // IS THE REFERENCE EVEN ELIGIBLE TO BE EVIDENCE? The _build 991 // artifact must postdate the source it claims to represent. 992 // No threshold: an artifact built BEFORE its source cannot 993 // describe that source, and the comparison is two stats the 994 // organ already takes. 995 let bmt: i64 = ps_mtime(bp) 996 lbrage[nbeh] = nowsec - bmt 997 if oout[4] < 0 { lbref[nbeh] = PS_REF_UNKNOWN } else { 998 if bmt < 0 { lbref[nbeh] = PS_REF_UNKNOWN } else { 999 if bmt >= oout[4] { lbref[nbeh] = PS_REF_FRESH } else { lbref[nbeh] = PS_REF_FOSSIL } 1000 } 1001 } 1002 nbeh = nbeh + 1 1003 } 1004 } else { 1005 if ssz > bsz { dir = "AHEAD" as *u8; lah[ahead] = elf as i64; ahead = ahead + 1 } else { resized = resized + 1 } 1006 } 1007 ps_puts(" " as *u8); ps_puts(dir) 1008 ps_puts(" " as *u8); ps_puts(elf) 1009 ps_puts(" served=" as *u8); ps_pn(ssz) 1010 ps_puts(" built=" as *u8); ps_pn(bsz) 1011 ps_puts(" delta=" as *u8); ps_pn(bsz - ssz) 1012 var jv: i64 = 0 - 2 1013 if judge == 1 { 1014 jv = ps_judge(elf, bp, PS_JUDGE_TMP) 1015 if jv == 1 { jgreen = jgreen + 1; ps_puts(" JUDGE=SAFE(no printable run lost)" as *u8) } 1016 if jv == 0 { ps_puts(" JUDGE=WOULD-LOSE-CAPABILITY -- the runs it would drop are named below" as *u8) } 1017 if jv < 0 { junjudged = junjudged + 1; ps_puts(" JUDGE=UNJUDGED(the ruler could not be run -- NOT a pass)" as *u8) } 1018 } 1019 ps_puts("\n" as *u8) 1020 // The evidence goes UNDER the row that lost it, while the ruler's 1021 // report is still on disk. Deferring it to a hand re-run is how a 1022 // census ends up publishing a count nobody can act on. 1023 if jv == 0 { 1024 ps_explain(PS_JUDGE_TMP, jout) 1025 ljl[jred] = elf as i64 1026 ljlost[jred] = jout[0] 1027 ljpm[jred] = jout[1] 1028 jred = jred + 1 1029 } 1030 } else { identical = identical + 1 } 1031 } 1032 } 1033 } 1034 } 1035 } 1036 } 1037 } 1038 } 1039 i = e + 1 1040 } 1041 1042 if over == 1 { 1043 ps_puts("ARTIFACTDRIFT REFUSE: distinct-binary table exceeded capacity -- a partial census published\n" as *u8) 1044 ps_puts("as a total is the defect this organ exists to find. Raise PS_MAXROW and re-run.\n" as *u8) 1045 sys_exit(5) 1046 return 5 1047 } 1048 if rows == 0 { ps_puts("ARTIFACTDRIFT: no registry rows matched\n" as *u8); sys_exit(4); return 4 } 1049 if stale == 0 { ps_puts(" (none)\n" as *u8) } 1050 1051 ps_puts("\n-- NO-SERVED (a registry row names a binary that does not exist -- a DANGLING ROW) --\n" as *u8) 1052 if noserved == 0 { ps_puts(" (none)\n" as *u8) } 1053 var z: i64 = 0 1054 while z < noserved { ps_puts(" " as *u8); ps_puts(lsv[z] as *u8); ps_puts("\n" as *u8); z = z + 1 } 1055 1056 ps_puts("\n-- NO-BUILD (no artifact to compare against -- CANNOT-JUDGE, never a pass) --\n" as *u8) 1057 if nobuild == 0 { ps_puts(" (none)\n" as *u8) } 1058 var y: i64 = 0 1059 while y < nobuild { ps_puts(" " as *u8); ps_puts(lbd[y] as *u8); ps_puts("\n" as *u8); y = y + 1 } 1060 1061 ps_puts("\n-- INERT (SERVED, BYTE-PERFECT, AND NOT EXECUTABLE -- a separate axis, NOT part of the sum) --\n" as *u8) 1062 ps_puts(" An installed binary without the execute bit passes every size and content check made above\n" as *u8) 1063 ps_puts(" and CANNOT RUN. It fails as exit 127 at the caller, which reads as 'the organ is missing'.\n" as *u8) 1064 ps_puts(" ★★★★★★MEASURED 2026-08-16: nx_daemon_supervisor.elf sat 0644 since Aug 10 while the running\n" as *u8) 1065 ps_puts(" instance served from a DELETED inode -- so the fleet supervisor was unrestartable for six days\n" as *u8) 1066 ps_puts(" and nobody could know until it was killed. Remedy: chmod 0755, or reinstall via the organ that\n" as *u8) 1067 ps_puts(" preserves mode (nx_offc_install for _offc). NEVER a raw copy -- that is how these are made.\n" as *u8) 1068 ps_puts(" count=" as *u8); ps_pn(inert); ps_puts("\n" as *u8) 1069 if inert == 0 { ps_puts(" (none)\n" as *u8) } 1070 var iw: i64 = 0 1071 while iw < inert { ps_puts(" " as *u8); ps_puts(lin[iw] as *u8); ps_puts("\n" as *u8); iw = iw + 1 } 1072 1073 ps_puts("\n-- ARMED (SERVED, AND ITS SOURCE HAS A STUB MAIN -- a separate axis, NOT part of the sum) --\n" as *u8) 1074 ps_puts(" `func main() -> i64 { return 0 }` is the estate's `compile-only smoke` convention so a LIBRARY\n" as *u8) 1075 ps_puts(" compiles standalone. It is correct for a library and LETHAL for a name that also ships a binary:\n" as *u8) 1076 ps_puts(" nothing is reachable from that main, so a rebuild DEAD-STRIPS the whole closure and /api/build\n" as *u8) 1077 ps_puts(" stages a do-nothing artifact with NO error and a GREEN receipt. The ordinary build-then-promote\n" as *u8) 1078 ps_puts(" loop then replaces a working tool with a binary that returns 0, silently.\n" as *u8) 1079 ps_puts(" MEASURED 2026-09-03 on nx_https_get: staged 14,880 B against a 468,929 B live binary, while its\n" as *u8) 1080 ps_puts(" closure-sharing sibling nx_research_fetch builds to 566,096. Control: nx_gunzip rebuilt\n" as *u8) 1081 ps_puts(" 35,007 -> 35,661, so the toolchain does NOT shrink and the collapse is target-specific.\n" as *u8) 1082 ps_puts(" WHY nx_catalog CANNOT SEE IT: its library detector keys on `no top-level main()`, and a STUB\n" as *u8) 1083 ps_puts(" main defeats that check PRECISELY BY BEING A MAIN -- the lib detector is beaten by the very\n" as *u8) 1084 ps_puts(" convention that lets a library compile. Remedy: declare the target in organ_kind.conf so the\n" as *u8) 1085 ps_puts(" promote lane refuses it by kind, or give the source a real main. NEVER a size threshold.\n" as *u8) 1086 ps_puts(" count=" as *u8); ps_pn(armed); ps_puts(" source_unreadable=" as *u8); ps_pn(armunproven); ps_puts("\n" as *u8) 1087 if armed == 0 { ps_puts(" (none)\n" as *u8) } 1088 var aw: i64 = 0 1089 while aw < armed { ps_puts(" " as *u8); ps_puts(larm[aw] as *u8); ps_puts("\n" as *u8); aw = aw + 1 } 1090 1091 ps_puts("\n-- WHAT \"built\" MEANS HERE (the envelope on every delta and every JUDGE verdict above) --\n" as *u8) 1092 ps_puts(" built = buildroot/_build/<name>.sov.elf -- THE LAST BUILD ANYBODY RAN OF THAT TARGET. Nothing\n" as *u8) 1093 ps_puts(" rebuilds it on a beat, so it lags the source by an UNBOUNDED amount.\n" as *u8) 1094 ps_puts(" ★★★★★★MEASURED 2026-08-16: nx_lmexport read served=18079 built=18177 delta=98; ONE /api/build of\n" as *u8) 1095 ps_puts(" that same source then produced 30,379 -- the real gap was +12,300, or 125x the reported delta.\n" as *u8) 1096 ps_puts(" ⇒ EVERY delta HERE IS A FLOOR, NOT A VALUE, and every JUDGE verdict is about the LAST-BUILT\n" as *u8) 1097 ps_puts(" ARTIFACT, NOT about what the source compiles to today. ★AN INSTRUMENT THAT NAMES A STALE\n" as *u8) 1098 ps_puts(" ARTIFACT AS 'built' IS ANSWERING A NARROWER QUESTION THAN ITS COLUMN HEADING PROMISES.\n" as *u8) 1099 ps_puts(" ⇒ For the SOURCE question, rebuild first: nx_stale_check <target> rebuilds and byte-compares.\n" as *u8) 1100 1101 ps_puts("\n-- AHEAD CANDIDATES (served BIGGER than built -- a SIZE signal, NOT a capability verdict) --\n" as *u8) 1102 ps_puts(" DO NOT PROMOTE THESE TO 'fix' them until judged: promoting installs a SMALLER build and can\n" as *u8) 1103 ps_puts(" DELETE whatever the source no longer reproduces.\n" as *u8) 1104 ps_puts(" ⚠AND 'AHEAD' IS RELATIVE TO THAT LAST BUILD, NOT TO THE SOURCE: a small negative delta is what\n" as *u8) 1105 ps_puts(" a merely-OLDER build looks like. Rebuild the target before reading it as source loss.\n" as *u8) 1106 ps_puts(" ★A SIZE COMPARISON CANNOT ANSWER A CAPABILITY QUESTION. Run the ruler that can:\n" as *u8) 1107 ps_puts(" nx_contentdiff <name>.elf buildroot/_build/<name>.sov.elf\n" as *u8) 1108 ps_puts(" GREEN/lost_from_live=0 => size-only, SAFE to promote. RED => it NAMES each lost run.\n" as *u8) 1109 ps_puts(" MEASURED over the whole class 2026-08-15: 4 candidates, 2 real, 2 size-only false alarms --\n" as *u8) 1110 ps_puts(" so this list is a WORKLIST TO JUDGE, and publishing it as a verdict would be half wrong.\n" as *u8) 1111 if ahead == 0 { ps_puts(" (none)\n" as *u8) } 1112 var q: i64 = 0 1113 while q < ahead { ps_puts(" " as *u8); ps_puts(lah[q] as *u8); ps_puts("\n" as *u8); q = q + 1 } 1114 1115 ps_puts("\n-- OWNER-SIGNAL on every BEHIND row (a SEPARATE AXIS, NOT a member of the sum above) --\n" as *u8) 1116 ps_puts(" ★★★★★★BEHIND IS NECESSARY BUT NOT SUFFICIENT FOR \"PROMOTE ME\": a BEHIND row can be ANOTHER\n" as *u8) 1117 ps_puts(" SEAT'S WORK IN FLIGHT. Caught live 2026-08-15 on nx_oo_extract_gate -- BEHIND 872 B with .nxw\n" as *u8) 1118 ps_puts(" scratch files beside its source and a same-day header edit -- and the only thing that stopped\n" as *u8) 1119 ps_puts(" that promote was a human happening to look. ★A LAW THAT MUST BE RECALLED AT THE MOMENT OF\n" as *u8) 1120 ps_puts(" TEMPTATION IS NOT A CONTROL, ONLY A MECHANISM IN THE PATH IS -- so the check runs HERE, and no\n" as *u8) 1121 ps_puts(" promote list built from this census can omit it.\n" as *u8) 1122 ps_puts(" SIGNALS, all three printed on every row: decl= an explicit declaration row (a STATEMENT, so it\n" as *u8) 1123 ps_puts(" outranks the inferences) | scratch= sibling files named <target>.nx.* that a live editor\n" as *u8) 1124 ps_puts(" session leaves behind | day= the source mtime falls on this census run's UTC day or later.\n" as *u8) 1125 ps_puts(" ⚠day= IS A SAME-DAY TOUCH SIGNAL AND NOTHING ELSE. IN A BULK-SYNCED TREE MTIME IS NOT EDIT\n" as *u8) 1126 ps_puts(" HISTORY -- 7,047 of 7,133 .nx share an mtime inside ONE 5-MINUTE WINDOW -- so it can never be\n" as *u8) 1127 ps_puts(" read as staleness, and if it is TRUE FOR EVERY ROW IT COULD MEASURE it carries no information\n" as *u8) 1128 ps_puts(" and ABSTAINS from voting below. The rate is printed either way, so the decision is auditable.\n" as *u8) 1129 ps_puts(" FAILURE DIRECTION, STATED: THIS AXIS OVER-FLAGS. A wrongly-flagged row costs one adjudication;\n" as *u8) 1130 ps_puts(" a wrongly-cleared row costs a sibling seat their work. ★A HEURISTIC THAT GATES A DESTRUCTIVE\n" as *u8) 1131 ps_puts(" ACTION MUST BE WRONG IN THE DIRECTION OF DOING NOTHING.\n" as *u8) 1132 var srcok: i64 = 0 1133 var dayraw: i64 = 0 1134 var ob: i64 = 0 1135 while ob < nbeh { 1136 if lbday[ob] >= 0 { srcok = srcok + 1 1137 if lbday[ob] == 1 { dayraw = dayraw + 1 } 1138 } 1139 ob = ob + 1 1140 } 1141 var dayvotes: i64 = 1 1142 if srcok > 0 { if dayraw == srcok { dayvotes = 0 } } 1143 ps_puts(" day_signal same_day=" as *u8); ps_pn(dayraw) 1144 ps_puts(" of_source_resolved=" as *u8); ps_pn(srcok) 1145 if dayvotes == 1 { ps_puts(" day_signal=VOTES\n" as *u8) } else { ps_puts(" day_signal=ABSTAINS(unanimous over every row it could measure, so it carries no information)\n" as *u8) } 1146 ps_puts(" scratch_siblings_loaded=" as *u8); ps_pn(nsc) 1147 ps_puts(" declare_conf=" as *u8); ps_puts(declp) 1148 ps_puts(" bytes=" as *u8); ps_pn(dcn) 1149 if dcn == 0 { ps_puts(" <== NO DECLARATION FILE READ: every row below is judged on mechanical signals alone" as *u8) } 1150 ps_puts("\n" as *u8) 1151 if scfull[0] == 1 { 1152 ps_puts(" ⚠SCRATCH TABLE FILLED -- the scratch counts below are a FLOOR, not a total, and a floor here\n" as *u8) 1153 ps_puts(" means FEWER rows flagged, which is the UNSAFE direction. Raise PS_SCRATCH_MAX and re-run.\n" as *u8) 1154 } 1155 1156 var odecl: i64 = 0 1157 var oinfl: i64 = 0 1158 var oundec: i64 = 0 1159 var ounres: i64 = 0 1160 var rfresh: i64 = 0 1161 var rfossil: i64 = 0 1162 var runk: i64 = 0 1163 // THE ONLY NUMBER A DRAIN CAMPAIGN MAY WORK FROM: unclaimed by any seat AND judged against a 1164 // reference that actually postdates its source. Both conjuncts are necessary and neither is 1165 // sufficient, which is exactly why they are counted together instead of being left to a reader. 1166 var oconsider: i64 = 0 1167 if nbeh == 0 { ps_puts(" (none -- there are no BEHIND rows to own)\n" as *u8) } 1168 var oc: i64 = 0 1169 while oc < nbeh { 1170 var ost: i64 = PS_OWN_UNDECLARED 1171 if lbdec[oc] == 1 { ost = PS_OWN_DECLARED } else { 1172 if lbday[oc] < 0 { ost = PS_OWN_UNRESOLVED } else { 1173 if lbscr[oc] > 0 { ost = PS_OWN_INFLIGHT } else { 1174 if dayvotes == 1 { if lbday[oc] == 1 { ost = PS_OWN_INFLIGHT } } 1175 } 1176 } 1177 } 1178 ps_puts(" OWNER=" as *u8) 1179 if ost == PS_OWN_DECLARED { ps_puts("DECLARED" as *u8); odecl = odecl + 1 } 1180 if ost == PS_OWN_INFLIGHT { ps_puts("IN-FLIGHT-SUSPECT" as *u8); oinfl = oinfl + 1 } 1181 if ost == PS_OWN_UNDECLARED { ps_puts("UNDECLARED" as *u8); oundec = oundec + 1 } 1182 if ost == PS_OWN_UNRESOLVED { ps_puts("SRC-UNRESOLVED" as *u8); ounres = ounres + 1 } 1183 if lbref[oc] == PS_REF_FRESH { rfresh = rfresh + 1 } 1184 if lbref[oc] == PS_REF_FOSSIL { rfossil = rfossil + 1 } 1185 if lbref[oc] == PS_REF_UNKNOWN { runk = runk + 1 } 1186 if ost == PS_OWN_UNDECLARED { if lbref[oc] == PS_REF_FRESH { oconsider = oconsider + 1 } } 1187 ps_puts(" " as *u8); ps_puts(lbh[oc] as *u8) 1188 ps_puts(" decl=" as *u8); ps_pn(lbdec[oc]) 1189 ps_puts(" scratch=" as *u8); ps_pn(lbscr[oc]) 1190 ps_puts(" day=" as *u8); ps_pn(lbday[oc]) 1191 ps_puts(" ref=" as *u8) 1192 if lbref[oc] == PS_REF_FRESH { ps_puts("FRESH" as *u8) } 1193 if lbref[oc] == PS_REF_FOSSIL { ps_puts("FOSSIL" as *u8) } 1194 if lbref[oc] == PS_REF_UNKNOWN { ps_puts("UNKNOWN" as *u8) } 1195 ps_puts(" ref_age_s=" as *u8); ps_pn(lbrage[oc]) 1196 ps_puts(" src=" as *u8) 1197 if lbsrc[oc] == 0 { ps_puts("(unresolved -- the axis ABSTAINS, it does not acquit)" as *u8) } else { ps_puts(lbsrc[oc] as *u8) } 1198 ps_puts("\n" as *u8) 1199 // THE REASON TRAVELS WITH THE COUNT: name the scratch siblings UNDER the row they flag, while 1200 // the table is still in hand. Deferring it to a hand `ls` is how a census publishes a number 1201 // nobody can act on. 1202 if lbscr[oc] > 0 { 1203 let sp2: *u8 = lbsrc[oc] as *u8 1204 let sl2: i64 = ps_len(sp2) 1205 var b2: i64 = 0 1206 var q2: i64 = 0 1207 while q2 < sl2 { if (sp2[q2] as i64) == PS_ASCII_SLASH { b2 = q2 + 1 } q2 = q2 + 1 } 1208 let pf2: *u8 = sys_mmap(PS_NAMEMAX) 1209 var w2: i64 = 0 1210 var r2: i64 = b2 1211 while r2 < sl2 { if w2 + 2 < PS_NAMEMAX { pf2[w2] = sp2[r2]; w2 = w2 + 1 } r2 = r2 + 1 } 1212 w2 = ad_cat(pf2, w2, "." as *u8) 1213 pf2[w2] = 0 as u8 1214 ps_scratch_count(sctab, nsc, pf2, 1) 1215 } 1216 // THE REASON TRAVELS WITH THE STATE, AND SO DOES THE REMEDY. A FOSSIL row names the exact 1217 // incumbent call that settles it: nx_stale_check REBUILDS the target and byte-compares, which is 1218 // the expensive question this cheap census deliberately does not ask. Naming it is COMPOSITION, 1219 // not a second ruler, and it keeps every rebuild on the build-admission path where it belongs. 1220 if lbref[oc] == PS_REF_FOSSIL { 1221 ps_puts(" REF-FOSSIL: the reference PREDATES this source, so the delta above is NOT evidence\n" as *u8) 1222 ps_puts(" about today's source and its DIRECTION CAN BE INVERTED. Do not promote from this row.\n" as *u8) 1223 ps_puts(" RESOLVE WITH THE ADJUDICATOR THAT REBUILDS: nx_stale_check " as *u8) 1224 if lbsrc[oc] == 0 { ps_puts("<target>" as *u8) } else { 1225 let s3: *u8 = lbsrc[oc] as *u8 1226 let l3: i64 = ps_len(s3) 1227 var b3: i64 = 0 1228 var q3: i64 = 0 1229 while q3 < l3 { if (s3[q3] as i64) == PS_ASCII_SLASH { b3 = q3 + 1 } q3 = q3 + 1 } 1230 var e3: i64 = l3 1231 if ps_endswith(s3, l3, PS_SRC_EXT) == 1 { e3 = l3 - ps_len(PS_SRC_EXT) } 1232 let sb3: *u8 = sys_mmap(PS_NAMEMAX) 1233 var w3: i64 = 0 1234 var r3: i64 = b3 1235 while r3 < e3 { if w3 + 1 < PS_NAMEMAX { sb3[w3] = s3[r3]; w3 = w3 + 1 } r3 = r3 + 1 } 1236 sb3[w3] = 0 as u8 1237 ps_puts(sb3) 1238 } 1239 ps_puts("\n" as *u8) 1240 } 1241 oc = oc + 1 1242 } 1243 ps_puts(" owner_axis BEHIND=" as *u8); ps_pn(nbeh) 1244 ps_puts(" DECLARED=" as *u8); ps_pn(odecl) 1245 ps_puts(" IN-FLIGHT-SUSPECT=" as *u8); ps_pn(oinfl) 1246 ps_puts(" UNDECLARED=" as *u8); ps_pn(oundec) 1247 ps_puts(" SRC-UNRESOLVED=" as *u8); ps_pn(ounres) 1248 ps_puts(" sum=" as *u8); ps_pn(odecl + oinfl + oundec + ounres) 1249 if odecl + oinfl + oundec + ounres == nbeh { ps_puts(" owner_partition=RECONCILES\n" as *u8) } else { ps_puts(" owner_partition=LEAK\n" as *u8) } 1250 ps_puts(" owner_axis_covered=" as *u8); ps_pn(nbeh) 1251 ps_puts(" of_BEHIND=" as *u8); ps_pn(behind) 1252 if nbeh == behind { ps_puts(" owner_coverage=COMPLETE\n" as *u8) } else { 1253 ps_puts(" owner_coverage=PARTIAL <== THE PER-ROW TABLE HIT PS_MAXROW. A PARTIAL AXIS PUBLISHED AS A\n" as *u8) 1254 ps_puts(" TOTAL IS THE DEFECT THIS ORGAN EXISTS TO FIND: raise PS_MAXROW and re-run before using it.\n" as *u8) 1255 } 1256 ps_puts("\n-- REF-FRESHNESS on every BEHIND row (a SEPARATE AXIS; it qualifies the EVIDENCE, not the row) --\n" as *u8) 1257 ps_puts(" ★★★★★★THE REFERENCE IS PART OF THE CLAIM. `built` here is the LAST BUILD ANYBODY RAN, so a\n" as *u8) 1258 ps_puts(" BEHIND delta measured against an artifact OLDER THAN ITS SOURCE is not weak evidence -- it can\n" as *u8) 1259 ps_puts(" be EXACTLY INVERTED. MEASURED BY A SIBLING SEAT 2026-08-20: rebuilding 8 BEHIND subjects turned\n" as *u8) 1260 ps_puts(" 5 of them AHEAD-on-rebuild while this worklist said promote; nx_schema_backfill read served\n" as *u8) 1261 ps_puts(" 698235 vs a FRESH build of 102655, and nx_contentdiff called that promote RED with 14 lost runs.\n" as *u8) 1262 ps_puts(" Four subjects flipped BEHIND to AHEAD the instant their _build fossil was refreshed: NOTHING\n" as *u8) 1263 ps_puts(" ABOUT EITHER BINARY CHANGED, ONLY THE REFERENCE. (8 of 155 under a stated selection rule -- a\n" as *u8) 1264 ps_puts(" WITNESS THAT THE DEFECT EXISTS, never a population rate.)\n" as *u8) 1265 ps_puts(" ref_axis BEHIND=" as *u8); ps_pn(nbeh) 1266 ps_puts(" REF-FRESH=" as *u8); ps_pn(rfresh) 1267 ps_puts(" REF-FOSSIL=" as *u8); ps_pn(rfossil) 1268 ps_puts(" REF-UNKNOWN=" as *u8); ps_pn(runk) 1269 ps_puts(" sum=" as *u8); ps_pn(rfresh + rfossil + runk) 1270 if rfresh + rfossil + runk == nbeh { ps_puts(" ref_partition=RECONCILES\n" as *u8) } else { ps_puts(" ref_partition=LEAK\n" as *u8) } 1271 ps_puts(" promote_considerable=" as *u8); ps_pn(oconsider) 1272 ps_puts(" of_BEHIND=" as *u8); ps_pn(nbeh) 1273 ps_puts(" <== UNDECLARED *AND* REF-FRESH: the only rows a drain campaign may even look at\n" as *u8) 1274 ps_puts(" ⛔NEITHER AXIS ALONE LICENSES A PROMOTE, AND THIS CENSUS NO LONGER ISSUES ONE. UNDECLARED means\n" as *u8) 1275 ps_puts(" no claim and no in-flight signal; REF-FRESH means the artifact being compared postdates the\n" as *u8) 1276 ps_puts(" source. Both are NECESSARY, neither is SUFFICIENT. Sufficiency still belongs to nx_contentdiff\n" as *u8) 1277 ps_puts(" (lost=0) and nx_behaveprobe, and SRC-UNRESOLVED ABSTAINS rather than acquits, because\n" as *u8) 1278 ps_puts(" \"I could not look\" is never \"nobody owns it\".\n" as *u8) 1279 ps_puts(" TO CLAIM A ROW, append a TAB-separated line <target> <owner> <why> to " as *u8); ps_puts(declp); ps_puts("\n" as *u8) 1280 1281 ps_puts("\n-- STAGED-POINTER (the registry names a `.elf.new`, which promotion DELETES) --\n" as *u8) 1282 if stagedptr == 0 { ps_puts(" (none)\n" as *u8) } 1283 var w: i64 = 0 1284 while w < stagedptr { ps_puts(" " as *u8); ps_puts(lsp[w] as *u8); ps_puts("\n" as *u8); w = w + 1 } 1285 1286 // ---- FORK-ROOT AXIS: buildroot/_offc, the twin the compare publisher actually forks ---- 1287 // DELIBERATELY NOT ADDED TO `sum`. This is the INERT precedent, for the same structural reason: a 1288 // binary can be IDENTICAL on the build axis and FORKED on this one AT THE SAME TIME, so folding it 1289 // into the partition would quietly stop the reconciliation from being true. 1290 ps_puts("\n-- FORK-ROOT (buildroot/_offc -- the twin the compare publisher actually forks) --\n" as *u8) 1291 ps_puts(" REFERENCE = the SERVING ROOT, stated rather than assumed: that is what /api/promote writes\n" as *u8) 1292 ps_puts(" and what nx_restage restores this twin to agree with. SEPARATE AXIS, not part of the\n" as *u8) 1293 ps_puts(" partition above -- a row can be IDENTICAL there and FORK-STALE here, which is how a whole\n" as *u8) 1294 ps_puts(" compare publish surface went stale while every catalogue row read BUILT==PROMOTED.\n" as *u8) 1295 let fktab: *i64 = sys_mmap(PS_FORK_MAX*PS_I64_BYTES) as *i64 1296 let fkfull: *i64 = sys_mmap(16) as *i64 1297 fkfull[0] = 0 1298 let lfk: *i64 = sys_mmap(PS_FORK_MAX*PS_I64_BYTES) as *i64 1299 let lfka: *i64 = sys_mmap(PS_FORK_MAX*PS_I64_BYTES) as *i64 1300 let lfkb: *i64 = sys_mmap(PS_FORK_MAX*PS_I64_BYTES) as *i64 1301 let lfo: *i64 = sys_mmap(PS_FORK_MAX*PS_I64_BYTES) as *i64 1302 var fkident: i64 = 0 1303 var fkstale: i64 = 0 1304 var fkonly: i64 = 0 1305 var fkunread: i64 = 0 1306 let fkn: i64 = ps_dir_elfs(forkp, fktab, PS_FORK_MAX, fkfull) 1307 if fkn < 0 { 1308 ps_puts(" FORK-ROOT UNPROVEN: cannot open " as *u8); ps_puts(forkp) 1309 ps_puts(" -- this axis ABSTAINS rather than acquits. An axis that cannot see must never report agreement.\n" as *u8) 1310 } else { 1311 var fki: i64 = 0 1312 while fki < fkn { 1313 let fknm: *u8 = fktab[fki] as *u8 1314 let fkpath: *u8 = sys_mmap(PS_NAMEMAX) 1315 var fkoff: i64 = ad_cat(fkpath, 0, forkp) 1316 fkoff = ad_cat(fkpath, fkoff, fknm) 1317 fkpath[fkoff] = 0 as u8 1318 let fksz: i64 = ps_size(fkpath) 1319 let fkvsz: i64 = ps_size(fknm) 1320 if fkvsz < 0 { 1321 if fkonly < PS_FORK_MAX { lfo[fkonly] = fknm as i64 } 1322 fkonly = fkonly + 1 1323 } else { 1324 // SIZE FIRST because it is a stat and settles most rows; ps_same only where sizes agree. 1325 // ps_same returns -1 when a file cannot be READ even though it STAT'd -- that is UNREADABLE, 1326 // its own bucket, never folded into IDENTICAL. An unreadable pair is not an agreeing pair. 1327 var fksm: i64 = 1 1328 if fksz != fkvsz { fksm = 0 } else { fksm = ps_same(fkpath, fknm) } 1329 if fksm == 0 { 1330 if fkstale < PS_FORK_MAX { lfk[fkstale] = fknm as i64; lfka[fkstale] = fksz; lfkb[fkstale] = fkvsz } 1331 fkstale = fkstale + 1 1332 } else { 1333 if fksm < 0 { fkunread = fkunread + 1 } else { fkident = fkident + 1 } 1334 } 1335 } 1336 fki = fki + 1 1337 } 1338 if fkfull[0] == 1 { ps_puts(" WARNING: the fork table FILLED -- every count below is a FLOOR, not a total\n" as *u8) } 1339 // THE COUNT TRAVELS WITH ITS WORKLIST *AND* WITH BOTH BYTE COUNTS. A bare `FORK-STALE=3` sends the 1340 // reader to re-stat three roots by hand to learn what this loop already had in registers. 1341 ps_puts(" FORK-STALE (forkroot = the bytes the publisher forks; served = the bytes the estate serves):\n" as *u8) 1342 if fkstale == 0 { ps_puts(" (none)\n" as *u8) } 1343 var fkw: i64 = 0 1344 while fkw < fkstale { 1345 ps_puts(" FORK-STALE " as *u8); ps_puts(lfk[fkw] as *u8) 1346 ps_puts(" forkroot=" as *u8); ps_pn(lfka[fkw]) 1347 ps_puts(" served=" as *u8); ps_pn(lfkb[fkw]) 1348 ps_puts(" delta=" as *u8); ps_pn(lfkb[fkw] - lfka[fkw]) 1349 ps_puts("\n" as *u8) 1350 fkw = fkw + 1 1351 } 1352 if fkstale > 0 { 1353 ps_puts(" REMEDY: nx_restage <target>. /api/promote will NOT close these -- it writes the serving\n" as *u8) 1354 ps_puts(" root and nishihost/_offc and leaves this twin exactly where it was. That asymmetry IS\n" as *u8) 1355 ps_puts(" the defect: an ordinary promote can never refresh the copy the publisher forks.\n" as *u8) 1356 } 1357 ps_puts(" FORK-ONLY (here but no serving-root counterpart -- REPORTED, not an offender):\n" as *u8) 1358 if fkonly == 0 { ps_puts(" (none)\n" as *u8) } 1359 var fkz: i64 = 0 1360 while fkz < fkonly { ps_puts(" FORK-ONLY " as *u8); ps_puts(lfo[fkz] as *u8); ps_puts("\n" as *u8); fkz = fkz + 1 } 1361 ps_puts(" fork_rows=" as *u8); ps_pn(fkn) 1362 ps_puts(" FORK-IDENTICAL=" as *u8); ps_pn(fkident) 1363 ps_puts(" FORK-STALE=" as *u8); ps_pn(fkstale) 1364 ps_puts(" FORK-ONLY=" as *u8); ps_pn(fkonly) 1365 ps_puts(" FORK-UNREADABLE=" as *u8); ps_pn(fkunread) 1366 ps_puts(" sum=" as *u8); ps_pn(fkident + fkstale + fkonly + fkunread) 1367 if fkident + fkstale + fkonly + fkunread == fkn { ps_puts(" fork_partition=RECONCILES\n" as *u8) } else { ps_puts(" fork_partition=LEAK\n" as *u8) } 1368 } 1369 1370 let sum: i64 = identical + stale + nobuild + noserved + stagedptr 1371 ps_puts("\ndistinct_binaries=" as *u8); ps_pn(rows) 1372 ps_puts(" IDENTICAL=" as *u8); ps_pn(identical) 1373 ps_puts(" STALE=" as *u8); ps_pn(stale) 1374 ps_puts(" NO-BUILD=" as *u8); ps_pn(nobuild) 1375 ps_puts(" NO-SERVED=" as *u8); ps_pn(noserved) 1376 ps_puts(" STAGED-POINTER=" as *u8); ps_pn(stagedptr) 1377 ps_puts(" sum=" as *u8); ps_pn(sum) 1378 // STALE split by REMEDY, and the sub-partition is checked too -- a bucket whose parts do not sum 1379 // is a bucket somebody will plan against and be wrong. 1380 ps_puts("\n STALE breakdown: BEHIND(built>served -- A SIZE FACT ABOUT THE LAST BUILD, NOT A PROMOTE ORDER; read OWNER= and ref= per row)=" as *u8); ps_pn(behind) 1381 ps_puts(" AHEAD(served>built, INVESTIGATE -- promoting this DELETES capability)=" as *u8); ps_pn(ahead) 1382 ps_puts(" RESIZED-EQUAL(same size, different bytes)=" as *u8); ps_pn(resized) 1383 ps_puts(" sub_sum=" as *u8); ps_pn(behind + ahead + resized) 1384 if behind + ahead + resized == stale { ps_puts(" sub_partition=RECONCILES" as *u8) } else { ps_puts(" sub_partition=LEAK" as *u8) } 1385 if judge == 1 { 1386 ps_puts("\n JUDGED (content, via a forked nx_contentdiff per STALE row -- no rebuild): SAFE=" as *u8); ps_pn(jgreen) 1387 ps_puts(" WOULD-LOSE-CAPABILITY=" as *u8); ps_pn(jred) 1388 ps_puts(" UNJUDGED=" as *u8); ps_pn(junjudged) 1389 ps_puts(" sum=" as *u8); ps_pn(jgreen + jred + junjudged) 1390 if jgreen + jred + junjudged == stale { ps_puts(" judge_partition=RECONCILES" as *u8) } else { ps_puts(" judge_partition=LEAK" as *u8) } 1391 ps_puts("\n SAFE means no printable run is lost by installing the EXISTING build artifact. It is NOT\n" as *u8) 1392 ps_puts(" a promote order: nx_behaveprobe still owns SUFFICIENCY, and a concurrent seat may own the row.\n" as *u8) 1393 ps_puts(" ★AND IT IS A STATEMENT ABOUT THE LAST-BUILT ARTIFACT, NOT ABOUT TODAY'S SOURCE -- see the\n" as *u8) 1394 ps_puts(" 'WHAT built MEANS' note above. Rebuild first if the question is about the source.\n" as *u8) 1395 ps_puts("\n-- WOULD-LOSE-CAPABILITY (THE WORKLIST: promoting the existing artifact DROPS printable runs) --\n" as *u8) 1396 ps_puts(" These look like ordinary catch-up promotes from the outside and are NOT. Diagnose each with\n" as *u8) 1397 ps_puts(" nx_contentdiff <live>.elf buildroot/_build/<name>.sov.elf -- it NAMES every lost run.\n" as *u8) 1398 ps_puts(" Each row carries the ruler's own permil (lost printable bytes per 1000) so the list can be\n" as *u8) 1399 ps_puts(" TRIAGED without re-running anything -- it is AN ORDER TO READ IN, NOT A VERDICT. /api/promote's\n" as *u8) 1400 ps_puts(" calibrated guard measured ordinary edits at 8-38 permil and every real regression at 49+, so a\n" as *u8) 1401 ps_puts(" low row is usually a reworded message and a high row usually a deleted lane. The run NAMES\n" as *u8) 1402 ps_puts(" printed under each row above are the evidence; this number only says which to read first.\n" as *u8) 1403 if jred == 0 { ps_puts(" (none)\n" as *u8) } 1404 var jw: i64 = 0 1405 while jw < jred { 1406 ps_puts(" permil=" as *u8); ps_pn(ljpm[jw]) 1407 ps_puts(" lost_runs=" as *u8); ps_pn(ljlost[jw]) 1408 ps_puts(" " as *u8); ps_puts(ljl[jw] as *u8); ps_puts("\n" as *u8) 1409 jw = jw + 1 1410 } 1411 } 1412 if sum == rows { ps_puts(" partition=RECONCILES\n" as *u8) } else { ps_puts(" partition=LEAK\n" as *u8) } 1413 ps_puts(" (NO-BUILD is CANNOT-JUDGE, never a pass: no build artifact exists to compare against.)\n" as *u8) 1414 1415 // DURABLE SUMMARY, appended on every run. WRITTEN BEFORE THIS ORGAN WAS PUT ON A BEAT, DELIBERATELY: 1416 // a scheduled census whose only output is stdout is a job that RUNS and leaves NO EVIDENCE, and where 1417 // a clock beat's stdout actually goes was not something I had verified. **SCHEDULING A PRODUCER WHOSE 1418 // OUTPUT MIGHT BE DISCARDED BUYS THE COST OF THE RUN AND NONE OF THE MEASUREMENT** -- and the failure 1419 // is silent, because the job exits 0 either way. 1420 // One line per run so the counts become a TREND: a single census answers "how much drift today", a 1421 // series answers "is it growing", and only the second can tell a campaign that works from one that 1422 // treads water. *A LEVEL CANNOT EXPRESS A TRAJECTORY -- THAT NEEDS TWO SAMPLES IN TIME. 1423 // Fail-soft: if the log cannot be opened the census still reports in full. An evidence-write failure 1424 // must never suppress the measurement it was meant to preserve. 1425 let lfd: i64 = sys_openat_append(logp, PS_MODE_0644) 1426 if lfd >= 0 { 1427 let ln: *u8 = sys_mmap(PS_LOGLINE_CAP) 1428 var lo: i64 = 0 1429 lo = ad_cat(ln, lo, "epoch=" as *u8); lo = ad_catn(ln, lo, sys_now_realtime_sec()) 1430 // WHICH REGISTRY PRODUCED THIS ROW. ★★★★★★AN UNSTAMPED REPORT IS INDISTINGUISHABLE FROM A 1431 // REGISTRY, AND EVERY READER OF THIS TREND WILL SILENTLY CONSUME IT AS ONE. MEASURED 2026-08-20: 1432 // a gate's neg-control run of the PREVIOUS binary -- which predates the [trend_log] argument and 1433 // therefore ignored it -- appended two SIX-ROW FIXTURE censuses into this production log, and 1434 // nothing in the row said so. Reconciling parts do not make a row a population. 1435 lo = ad_cat(ln, lo, " reg=" as *u8); lo = ad_cat(ln, lo, reg) 1436 lo = ad_cat(ln, lo, " distinct=" as *u8); lo = ad_catn(ln, lo, rows) 1437 lo = ad_cat(ln, lo, " identical=" as *u8); lo = ad_catn(ln, lo, identical) 1438 lo = ad_cat(ln, lo, " stale=" as *u8); lo = ad_catn(ln, lo, stale) 1439 lo = ad_cat(ln, lo, " behind=" as *u8); lo = ad_catn(ln, lo, behind) 1440 lo = ad_cat(ln, lo, " ahead=" as *u8); lo = ad_catn(ln, lo, ahead) 1441 lo = ad_cat(ln, lo, " resized=" as *u8); lo = ad_catn(ln, lo, resized) 1442 lo = ad_cat(ln, lo, " nobuild=" as *u8); lo = ad_catn(ln, lo, nobuild) 1443 lo = ad_cat(ln, lo, " noserved=" as *u8); lo = ad_catn(ln, lo, noserved) 1444 lo = ad_cat(ln, lo, " stagedptr=" as *u8); lo = ad_catn(ln, lo, stagedptr) 1445 lo = ad_cat(ln, lo, " sum=" as *u8); lo = ad_catn(ln, lo, sum) 1446 // THE OWNER AXIS TRAVELS IN THE TREND ROW TOO. own_undeclared is the only class a drain campaign 1447 // may even CONSIDER, so a series of these rows answers "is the promotable backlog shrinking, or 1448 // is it only changing hands" -- a question the raw behind= column cannot express. 1449 lo = ad_cat(ln, lo, " own_declared=" as *u8); lo = ad_catn(ln, lo, odecl) 1450 lo = ad_cat(ln, lo, " own_inflight=" as *u8); lo = ad_catn(ln, lo, oinfl) 1451 lo = ad_cat(ln, lo, " own_undeclared=" as *u8); lo = ad_catn(ln, lo, oundec) 1452 lo = ad_cat(ln, lo, " own_unresolved=" as *u8); lo = ad_catn(ln, lo, ounres) 1453 lo = ad_cat(ln, lo, " own_covered=" as *u8); lo = ad_catn(ln, lo, nbeh) 1454 // THE EVIDENCE-QUALITY AXIS TRAVELS TOO. Without ref_fossil in the row, a trend of `behind=` is a 1455 // trend of a number whose reference nobody can date, and a falling behind= could be a campaign 1456 // working or a fossil quietly ageing into the wrong direction. 1457 lo = ad_cat(ln, lo, " ref_fresh=" as *u8); lo = ad_catn(ln, lo, rfresh) 1458 lo = ad_cat(ln, lo, " ref_fossil=" as *u8); lo = ad_catn(ln, lo, rfossil) 1459 lo = ad_cat(ln, lo, " ref_unknown=" as *u8); lo = ad_catn(ln, lo, runk) 1460 lo = ad_cat(ln, lo, " considerable=" as *u8); lo = ad_catn(ln, lo, oconsider) 1461 if rfresh + rfossil + runk == nbeh { lo = ad_cat(ln, lo, " ref_partition=RECONCILES" as *u8) } else { lo = ad_cat(ln, lo, " ref_partition=LEAK" as *u8) } 1462 if odecl + oinfl + oundec + ounres == nbeh { lo = ad_cat(ln, lo, " own_partition=RECONCILES" as *u8) } else { lo = ad_cat(ln, lo, " own_partition=LEAK" as *u8) } 1463 // the partition verdict travels WITH the row: a reader must never have to recompute whether the 1464 // parts summed, and a row that cannot reconcile is a row nobody should plan against. 1465 // THE FORK AXIS TRAVELS IN THE TREND ROW TOO, or its trajectory stays invisible: a level says 1466 // "3 forked today", a series says "and nobody is restaging them". fork_rows is published beside 1467 // the counts as the DENOMINATOR, because a falling fork_stale next to a falling fork_rows is a 1468 // directory being emptied, not a backlog being drained -- and only the pair can tell them apart. 1469 // fork_rows=-1 with fork_partition=UNPROVEN is the ABSTENTION, and it must stay distinguishable 1470 // from a genuine clean sweep: a row that could not look must never read as a row that agreed. 1471 lo = ad_cat(ln, lo, " fork_rows=" as *u8); lo = ad_catn(ln, lo, fkn) 1472 lo = ad_cat(ln, lo, " fork_identical=" as *u8); lo = ad_catn(ln, lo, fkident) 1473 lo = ad_cat(ln, lo, " fork_stale=" as *u8); lo = ad_catn(ln, lo, fkstale) 1474 lo = ad_cat(ln, lo, " fork_only=" as *u8); lo = ad_catn(ln, lo, fkonly) 1475 lo = ad_cat(ln, lo, " fork_unreadable=" as *u8); lo = ad_catn(ln, lo, fkunread) 1476 if fkn < 0 { lo = ad_cat(ln, lo, " fork_partition=UNPROVEN" as *u8) } else { if fkident + fkstale + fkonly + fkunread == fkn { lo = ad_cat(ln, lo, " fork_partition=RECONCILES" as *u8) } else { lo = ad_cat(ln, lo, " fork_partition=LEAK" as *u8) } } 1477 if sum == rows { lo = ad_cat(ln, lo, " partition=RECONCILES" as *u8) } else { lo = ad_cat(ln, lo, " partition=LEAK" as *u8) } 1478 ln[lo] = 10 as u8; lo = lo + 1 1479 sys_write(lfd, ln, lo) 1480 sys_close(lfd) 1481 ps_puts(" durable summary appended -> " as *u8); ps_puts(logp); ps_puts(" bytes=" as *u8); ps_pn(lo); ps_puts("\n" as *u8) 1482 } else { 1483 ps_puts(" WARNING: could not append the durable summary -- this run measured correctly but left no trend row\n" as *u8) 1484 } 1485 sys_exit(0) 1486 return 0 1487}