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}