code wiki / _hdl_build / nx_staghyg.nx
nx_staghyg.nx source
↩ module page · 642 lines · 33655 B
1// nx_staghyg.nx -- STAGING-AREA HYGIENE: census, verdict, and expiry for the deploy queue.
2//
3// THE MEASURED PROBLEM (debt 1785531571, sev-9): the staging area has no expiry, so a .new file that
4// PREDATES the live binary it would replace sits there looking deployable forever. Promoting it is a
5// ROLLBACK WEARING AN UPGRADE FILENAME. Nothing in the tree measured this per-artifact, and nothing
6// refused it at the moment of promote.
7//
8// FOUR VERBS, DELIBERATELY SEPARATED (Rule 9 -- each does ONE thing):
9// census [root] report size+mtime for BOTH sides and DECIDE NOTHING. This is the rung-0
10// instrument, modelled verbatim on nx_tree_diff, whose banked lesson is that a
11// tool which picks a direction is the clobber bug with a friendlier face.
12// scan [root] the classified verdict: every staged artifact bucketed, counts that SUM.
13// check <livepath> one target. exit 0 = promotable, exit 3 = refused. The gate/promote surface.
14// expire [root] apply disarm artifacts past the expiry window.
15//
16// *EXPIRY RENAMES, IT NEVER DELETES. An expired artifact becomes <name>.new.expired-<epoch>, which
17// md_promote_staged can no longer see (it opens exactly <name>.new) -- so the queue is disarmed while
18// every byte is kept and the act is reversible with a single rename back (Rule 13 additive-only,
19// Rule 26 fail-safe by construction). Without `apply` it only reports.
20//
21// *THE CENSUS COUNTS THE HEALTHY ROWS TOO. An instrument blind to the common case only ever sees
22// crises -- the banked crawler lesson. FORWARD and ORPHAN are reported beside every refusal, and the
23// class counts are printed so a reader can check they SUM to the number scanned (a partition is a
24// claim).
25// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
26import "nx_syscalls.nx"
27import "nx_staging_guard.nx"
28
29const SH_STDOUT: i64 = 1
30const SH_DIRBUF: i64 = 262144
31const SH_PATHCAP: i64 = 1024
32const SH_DIR_TYPE: i64 = 4
33const SH_ALLOWCAP: i64 = 1048576
34
35func sh_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(SH_STDOUT, s, n); return 0 }
36func sh_num(v: i64) -> i64 {
37 var m: i64 = v
38 if m < 0 { m = 0 - m; sys_write(SH_STDOUT, "-" as *u8, 1) }
39 let t: *u8 = sys_mmap(32)
40 var k: i64 = 0
41 if m == 0 { t[0] = 48 as u8; k = 1 }
42 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
43 let o: *u8 = sys_mmap(32)
44 var i: i64 = 0
45 while i < k { o[i] = t[k - 1 - i]; i = i + 1 }
46 sys_write(SH_STDOUT, o, k)
47 sys_munmap(t, 32)
48 sys_munmap(o, 32)
49 return 0
50}
51
52func sh_ends_new(nm: *u8) -> i64 {
53 let n: i64 = sg_strlen(nm)
54 if n < 5 { return 0 }
55 if nm[n - 4] != (46 as u8) { return 0 }
56 if nm[n - 3] != (110 as u8) { return 0 }
57 if nm[n - 2] != (101 as u8) { return 0 }
58 if nm[n - 1] != (119 as u8) { return 0 }
59 return 1
60}
61
62// join dir + name, dropping `strip` trailing bytes of name (4 strips a .new suffix)
63func sh_join(dir: *u8, nm: *u8, out: *u8, strip: i64) -> i64 {
64 var o: i64 = 0
65 var i: i64 = 0
66 while dir[i] != (0 as u8) { out[o] = dir[i]; o = o + 1; i = i + 1 }
67 out[o] = 47 as u8; o = o + 1
68 let nl: i64 = sg_strlen(nm) - strip
69 i = 0
70 while i < nl { out[o] = nm[i]; o = o + 1; i = i + 1 }
71 out[o] = 0 as u8
72 return o
73}
74
75// Build the LIVE path a staged artifact would overwrite. THE MAPPING IS NOT A PLAIN SUFFIX STRIP:
76// /api/build stages <t>.sov.elf.new and /api/promote installs it as <t>.elf, so the live counterpart
77// of X.sov.elf.new is X.elf -- X.sov.elf NEVER EXISTS. Measured 2026-08-06: the naive strip reported
78// live=-1 for essentially every build-staged artifact, which would have classed them all ORPHAN
79// (nothing to lose) and made this entire guard VACUOUS. A pairing rule is a claim about the deploy
80// path; read the deploy path, do not guess it.
81func sh_live_path(dir: *u8, nm: *u8, out: *u8) -> i64 {
82 let n: i64 = sg_strlen(nm)
83 let keep: i64 = n - 4
84 var sov: i64 = 0
85 if keep >= 8 { if sg_eq_at(nm, keep - 8, ".sov.elf" as *u8, 8) == 1 { sov = 1 } }
86 var lim: i64 = keep
87 if sov == 1 { lim = keep - 8 }
88 var o: i64 = 0
89 var i: i64 = 0
90 while dir[i] != (0 as u8) { out[o] = dir[i]; o = o + 1; i = i + 1 }
91 out[o] = 47 as u8; o = o + 1
92 i = 0
93 while i < lim { out[o] = nm[i]; o = o + 1; i = i + 1 }
94 out[o] = 0 as u8
95 if sov == 1 {
96 out[o] = 46 as u8; o = o + 1
97 out[o] = 101 as u8; o = o + 1
98 out[o] = 108 as u8; o = o + 1
99 out[o] = 102 as u8; o = o + 1
100 out[o] = 0 as u8
101 }
102 return o
103}
104
105// 1 when `s` ends with `suf`.
106func sh_ends(s: *u8, suf: *u8) -> i64 {
107 let n: i64 = sg_strlen(s)
108 let m: i64 = sg_strlen(suf)
109 if m > n { return 0 }
110 var i: i64 = 0
111 while i < m {
112 if s[n - m + i] != suf[i] { return 0 }
113 i = i + 1
114 }
115 return 1
116}
117
118// copy the tab-separated field `idx` of the line [ls,le) into out (NUL-terminated); returns its length.
119// tool_allowlist.conf rows are name<TAB>abs-elf<TAB>GREEN[<TAB>pinned-args].
120func sh_field(buf: *u8, ls: i64, le: i64, idx: i64, out: *u8, cap: i64) -> i64 {
121 var f: i64 = 0
122 var o: i64 = 0
123 var i: i64 = ls
124 while i < le {
125 let c: u8 = buf[i]
126 if c == (9 as u8) { f = f + 1 }
127 if c != (9 as u8) {
128 if f == idx { if o < (cap - 1) { out[o] = c; o = o + 1 } }
129 }
130 i = i + 1
131 }
132 out[o] = 0 as u8
133 return o
134}
135
136// ABSOLUTE staged path -> the live path a promote would install. Same mapping sh_live_path applies to a
137// basename, but on a full path and with no directory join: /x/nx_foo.sov.elf.new -> /x/nx_foo.elf.
138// The .sov.elf rewrite matters -- /x/nx_foo.sov.elf never exists, so getting it wrong would report every
139// ARMED row as DANGLING.
140func sh_abs_live(p: *u8, out: *u8) -> i64 {
141 let n: i64 = sg_strlen(p)
142 var keep: i64 = n
143 if sh_ends(p, ".new" as *u8) == 1 { keep = n - 4 }
144 var sov: i64 = 0
145 if keep >= 8 { if sg_eq_at(p, keep - 8, ".sov.elf" as *u8, 8) == 1 { sov = 1 } }
146 var lim: i64 = keep
147 if sov == 1 { lim = keep - 8 }
148 var o: i64 = 0
149 while o < lim { out[o] = p[o]; o = o + 1 }
150 out[o] = 0 as u8
151 if sov == 1 {
152 out[o] = 46 as u8; o = o + 1
153 out[o] = 101 as u8; o = o + 1
154 out[o] = 108 as u8; o = o + 1
155 out[o] = 102 as u8; o = o + 1
156 out[o] = 0 as u8
157 }
158 return o
159}
160
161func sh_append_num(out: *u8, pos: i64, v: i64) -> i64 {
162 var m: i64 = v
163 let t: *u8 = sys_mmap(32)
164 var k: i64 = 0
165 if m == 0 { t[0] = 48 as u8; k = 1 }
166 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
167 var o: i64 = pos
168 var i: i64 = 0
169 while i < k { out[o] = t[k - 1 - i]; o = o + 1; i = i + 1 }
170 out[o] = 0 as u8
171 sys_munmap(t, 32)
172 return o
173}
174
175func sh_append_str(out: *u8, pos: i64, s: *u8) -> i64 {
176 var o: i64 = pos
177 var i: i64 = 0
178 while s[i] != (0 as u8) { out[o] = s[i]; o = o + 1; i = i + 1 }
179 out[o] = 0 as u8
180 return o
181}
182
183func sh_row(nm: *u8, cls: i64, out: *i64) -> i64 {
184 sh_puts(" " as *u8)
185 sh_puts(sg_class_name(cls))
186 sh_puts("\t" as *u8)
187 sh_puts(nm)
188 sh_puts(" live=" as *u8); sh_num(out[SG_O_LIVESZ])
189 sh_puts("b/mt=" as *u8); sh_num(out[SG_O_LIVEMT])
190 sh_puts(" staged=" as *u8); sh_num(out[SG_O_NEWSZ])
191 sh_puts("b/mt=" as *u8); sh_num(out[SG_O_NEWMT])
192 sh_puts(" age=" as *u8); sh_num(out[SG_O_AGEDAYS])
193 sh_puts("d shrink=" as *u8); sh_num(out[SG_O_SHRINKPERMIL])
194 sh_puts("permil caploss=" as *u8); sh_num(out[SG_O_LOSTPERMIL])
195 sh_puts("permil (" as *u8); sh_num(out[SG_O_MISSING])
196 sh_puts("/" as *u8); sh_num(out[SG_O_CHECKED])
197 sh_puts(" live tokens absent)\n" as *u8)
198 return 0
199}
200
201func main(argc: i64, argv: *i64) -> i64 {
202 var verb: *u8 = "scan" as *u8
203 if argc >= 2 { verb = argv[1] as *u8 }
204 var root: *u8 = "." as *u8
205
206 let cfg: *i64 = sys_mmap(8 * SG_C_SLOTS) as *i64
207 let hadconf: i64 = sg_conf_load(cfg)
208 // The reference set for expiry's PROVE-UNREFERENCED half. Loaded ONCE, not per artifact: this is the
209 // registry that decides whether renaming a staged file would break a live tool.
210 let allowbuf: *u8 = sys_mmap(SH_ALLOWCAP)
211 let allown: i64 = sg_slurp("tool_allowlist.conf" as *u8, allowbuf, SH_ALLOWCAP - 2)
212 let now: i64 = sys_now_realtime_sec()
213 let out: *i64 = sys_mmap(8 * SG_OUT_SLOTS) as *i64
214
215 // ---- check <livepath>: ONE target, exit code is the answer ----
216 if sg_contains(verb, sg_strlen(verb), "check" as *u8, 5) == 1 {
217 if argc < 3 {
218 sh_puts("usage: nx_staghyg check <live-path>\nverdict=RED rule=usage\n" as *u8)
219 sys_exit(2); return 2
220 }
221 let lp: *u8 = argv[2] as *u8
222 // TWO NAMES FOR ONE ARTIFACT, and this verb only ever built one of them (debt 1786067334).
223 // /api/build stages <t>.sov.elf.new -- 553 such files on this root -- while the legacy upload path
224 // stages <artifact>.new (35). `check` appended ONLY ".new", so for every target carrying both it
225 // judged an artifact the promoter will never consume.
226 // MEASURED 2026-08-06: for nx_law_warden.elf it read nx_law_warden.elf.new (191901b, SIX DAYS OLD)
227 // and answered class=BACKDATE promotable=NO REFUSED -- while nx_contentdiff on the artifact
228 // /api/build had produced minutes earlier (nx_law_warden.sov.elf.new, 216596b) returned
229 // lost_from_live=0, 3/3 GREEN. A clean upgrade reported as a refused backdate.
230 // PRECEDENCE LIFTED VERBATIM FROM nx_hostctl.hc_deploy_one, WHICH LEARNED IT THE EXPENSIVE WAY:
231 // "prefer the SANCTIONED BUILD artifact (.sov.elf.new). Preferring the legacy upload name let ONE
232 // stale leftover permanently shadow every fresh build -- a promote that reported success and shipped
233 // the wrong binary." Same trap, second organ, and the second one is an ADVISOR rather than a
234 // promoter -- which is why it went unnoticed: nothing it says takes effect, so nothing contradicts it.
235 // The classifier (nx_staging_guard) is shared and CORRECT; only the path RESOLUTION here was wrong.
236 // Existence is probed via the classifier itself (SG_NONE == nothing staged) so this needs no new
237 // stat helper and cannot disagree with the classifier about what "staged" means.
238 let npA: *u8 = sys_mmap(SH_PATHCAP)
239 let npB: *u8 = sys_mmap(SH_PATHCAP)
240 let eA: i64 = sh_append_str(npA, 0, lp)
241 sh_append_str(npA, eA, ".new" as *u8)
242 let lpn: i64 = sg_strlen(lp)
243 var cut: i64 = lpn
244 if lpn > 4 { if lp[lpn-4] == (46 as u8) { if lp[lpn-3] == (101 as u8) { if lp[lpn-2] == (108 as u8) { if lp[lpn-1] == (102 as u8) { cut = lpn - 4 } } } } }
245 var bo: i64 = 0
246 while bo < cut { npB[bo] = lp[bo]; bo = bo + 1 }
247 let eB: i64 = sh_append_str(npB, cut, ".sov.elf.new" as *u8)
248 npB[eB] = 0 as u8
249 let outB: *i64 = sys_mmap(8 * SG_OUT_SLOTS) as *i64
250 let cB: i64 = sg_classify(lp, npB, now, cfg, outB)
251 let cA: i64 = sg_classify(lp, npA, now, cfg, out)
252 var c: i64 = cA
253 var np: *u8 = npA
254 if cB != SG_NONE {
255 c = cB
256 np = npB
257 var oi: i64 = 0
258 while oi < SG_OUT_SLOTS { out[oi] = outB[oi]; oi = oi + 1 }
259 }
260 var bothstaged: i64 = 0
261 if cA != SG_NONE { if cB != SG_NONE { bothstaged = 1 } }
262 sh_row(lp, c, out)
263 // DECLARE WHICH FILE WAS JUDGED. An advisory verdict that does not name its subject cannot be
264 // checked against the promoter, which is exactly how this stayed wrong.
265 sh_puts(" judged=" as *u8); sh_puts(np)
266 if bothstaged == 1 {
267 // AMBIGUITY IS ITS OWN HAZARD, not something to resolve silently: with two staged artifacts for
268 // one target the question "is it safe to promote?" has TWO answers, and picking one quietly is
269 // how the wrong binary ships. Say both facts out loud and name which one actually ships.
270 sh_puts(" BOTH-STAGED=1 other=" as *u8); sh_puts(npA)
271 sh_puts(" (two staged artifacts for one target; /api/promote consumes the .sov.elf.new, so the other will NOT ship -- delete it or promote deliberately)" as *u8)
272 }
273 sh_puts("\n" as *u8)
274 if c == SG_NONE {
275 sh_puts("NX-STAGHYG check target=" as *u8); sh_puts(lp)
276 sh_puts(" class=NONE nothing-staged verdict=GREEN\n" as *u8)
277 sys_exit(0); return 0
278 }
279 if sg_allows(c) == 1 {
280 sh_puts("NX-STAGHYG check target=" as *u8); sh_puts(lp)
281 sh_puts(" class=" as *u8); sh_puts(sg_class_name(c))
282 sh_puts(" promotable=YES verdict=GREEN\n" as *u8)
283 sys_exit(0); return 0
284 }
285 sh_puts("NX-STAGHYG check target=" as *u8); sh_puts(lp)
286 sh_puts(" class=" as *u8); sh_puts(sg_class_name(c))
287 sh_puts(" promotable=NO REFUSED verdict=GREEN\n" as *u8)
288 sys_exit(3); return 3
289 }
290
291 // ---- stagedref: TURN A COUNT INTO A WORK ORDER ------------------------------------------------
292 // nx_shipcheck counts registry rows whose binary path is a staging artifact and NEVER NAMES THEM --
293 // its log carries totals only. The number sat at EXACTLY 45 from 2026-08-01 to 2026-08-06, looking
294 // perfectly well-instrumented, because nobody could act on it. A METRIC THAT CANNOT NAME ITS MEMBERS
295 // IS A SCOREBOARD, NOT A WORK ORDER.
296 // And the rows are NOT homogeneous, which is the second reason a bare count could never drive this:
297 // BY-DESIGN a *_staged alias whose whole purpose IS to run the staged build. Repairing it
298 // DESTROYS working tooling. Five of the 46 are these.
299 // REPOINT-ONLY a live <name>.elf already exists -- no build needed, just re-point the row.
300 // ARMED the staged artifact still exists; a promote would CONSUME it and strand the row,
301 // so promote and re-point must happen together.
302 // DANGLING the staged artifact is already gone: the tool is ALREADY DEAD (exit 127).
303 // Remedy for every non-BY-DESIGN row: /api/build -> /api/promote with expect_sha256 ->
304 // /api/tools/register name=&elf=<name>.elf&update=yes&confirm=yes (update=yes does an atomic row
305 // replace and PRESERVES pinned args when args= is omitted).
306 if sg_contains(verb, sg_strlen(verb), "stagedref" as *u8, 9) == 1 {
307 let ab: *u8 = sys_mmap(SH_ALLOWCAP)
308 let an2: i64 = sg_slurp("tool_allowlist.conf" as *u8, ab, SH_ALLOWCAP - 2)
309 if an2 <= 0 {
310 sh_puts("NX-STAGHYG stagedref verdict=RED rule=allowlist-unreadable\n" as *u8)
311 sys_exit(1); return 1
312 }
313 let fname: *u8 = sys_mmap(SH_PATHCAP)
314 let fpath: *u8 = sys_mmap(SH_PATHCAP)
315 let livep2: *u8 = sys_mmap(SH_PATHCAP)
316 var nrows: i64 = 0
317 var nsr: i64 = 0
318 var nbydesign: i64 = 0
319 var nrepoint: i64 = 0
320 var narmed: i64 = 0
321 var ndangling: i64 = 0
322 sh_puts("=== NX-STAGHYG stagedref -- every row NAMED with its remedy ===\n" as *u8)
323 var ls: i64 = 0
324 while ls < an2 {
325 // walk to the newline; `le` lands ON it (or on an2). The first cut of this loop set
326 // le = an2 + 1 on a hit, which jumped straight to EOF and parsed the WHOLE FILE as one row --
327 // and it still printed partition=OK, because a partition check is VACUOUSLY TRUE over an
328 // empty set. rows=1 against an 849-row file was the only tell.
329 var le: i64 = ls
330 var eol: i64 = 0
331 while eol == 0 {
332 if le >= an2 { eol = 1 }
333 if eol == 0 {
334 if ab[le] == (10 as u8) { eol = 1 }
335 if eol == 0 { le = le + 1 }
336 }
337 }
338 let lend: i64 = le
339 if lend > ls {
340 if ab[ls] != (35 as u8) {
341 nrows = nrows + 1
342 sh_field(ab, ls, lend, 0, fname, SH_PATHCAP)
343 sh_field(ab, ls, lend, 1, fpath, SH_PATHCAP)
344 if sh_ends(fpath, ".new" as *u8) == 1 {
345 nsr = nsr + 1
346 sh_abs_live(fpath, livep2)
347 let stagedsz: i64 = sg_size(fpath)
348 let livesz: i64 = sg_size(livep2)
349 if sh_ends(fname, "_staged" as *u8) == 1 {
350 nbydesign = nbydesign + 1
351 sh_puts(" BY-DESIGN " as *u8); sh_puts(fname)
352 sh_puts(" points at its STAGED build on purpose -- do NOT repair\n" as *u8)
353 }
354 if sh_ends(fname, "_staged" as *u8) == 0 {
355 if livesz >= 0 {
356 nrepoint = nrepoint + 1
357 sh_puts(" REPOINT-ONLY " as *u8); sh_puts(fname)
358 sh_puts(" live exists " as *u8); sh_num(livesz)
359 sh_puts("b -- no build needed, register update=yes\n" as *u8)
360 }
361 if livesz < 0 {
362 if stagedsz >= 0 {
363 narmed = narmed + 1
364 sh_puts(" ARMED " as *u8); sh_puts(fname)
365 sh_puts(" staged " as *u8); sh_num(stagedsz)
366 sh_puts("b exists -- a promote CONSUMES it, so promote+repoint together\n" as *u8)
367 }
368 if stagedsz < 0 {
369 ndangling = ndangling + 1
370 sh_puts(" DANGLING " as *u8); sh_puts(fname)
371 sh_puts(" staged artifact GONE -- this tool is ALREADY DEAD (exit 127)\n" as *u8)
372 }
373 }
374 }
375 }
376 }
377 }
378 ls = le + 1
379 }
380 // NON-VACUITY FLOOR: this file has hundreds of rows. A parse that yields almost nothing must SAY SO
381 // rather than emit a confident GREEN over an empty set -- which is exactly what the first cut did.
382 if nrows < 10 { sh_puts(" PARSE-SUSPECT: only " as *u8); sh_num(nrows); sh_puts(" rows parsed from a file this size -- treat the counts below as UNTRUSTWORTHY
383" as *u8) }
384 sh_puts("NX-STAGHYG stagedref rows=" as *u8); sh_num(nrows)
385 sh_puts(" stagedref=" as *u8); sh_num(nsr)
386 sh_puts(" BY-DESIGN=" as *u8); sh_num(nbydesign)
387 sh_puts(" REPOINT-ONLY=" as *u8); sh_num(nrepoint)
388 sh_puts(" ARMED=" as *u8); sh_num(narmed)
389 sh_puts(" DANGLING=" as *u8); sh_num(ndangling)
390 let srsum: i64 = nbydesign + nrepoint + narmed + ndangling
391 sh_puts(" classes_sum=" as *u8); sh_num(srsum)
392 if srsum != nsr { sh_puts(" PARTITION-BROKEN" as *u8) }
393 if srsum == nsr { sh_puts(" partition=OK" as *u8) }
394 sh_puts(" actionable=" as *u8); sh_num(nsr - nbydesign)
395 sh_puts(" verdict=GREEN\n" as *u8)
396 sys_exit(0)
397 return 0
398 }
399
400 if argc >= 3 { root = argv[2] as *u8 }
401 var doapply: i64 = 0
402 if argc >= 4 { if sg_contains(argv[3] as *u8, sg_strlen(argv[3] as *u8), "apply" as *u8, 5) == 1 { doapply = 1 } }
403
404 let iscensus: i64 = sg_contains(verb, sg_strlen(verb), "census" as *u8, 6)
405 let isexpire: i64 = sg_contains(verb, sg_strlen(verb), "expire" as *u8, 6)
406
407 let fd: i64 = sys_openat_rd(root)
408 if fd < 0 {
409 sh_puts("NX-STAGHYG verdict=RED rule=root-absent root=" as *u8); sh_puts(root); sh_puts("\n" as *u8)
410 sys_exit(1); return 1
411 }
412
413 let dbuf: *u8 = sys_mmap(SH_DIRBUF)
414 let lp: *u8 = sys_mmap(SH_PATHCAP)
415 let np: *u8 = sys_mmap(SH_PATHCAP)
416 let xp: *u8 = sys_mmap(SH_PATHCAP)
417
418 var nstaged: i64 = 0
419 var cNONE: i64 = 0
420 var cFWD: i64 = 0
421 var cORPH: i64 = 0
422 var cBACK: i64 = 0
423 var cEXP: i64 = 0
424 var cSHR: i64 = 0
425 var cCAP: i64 = 0
426 var nrefused: i64 = 0
427 var npaired: i64 = 0
428 var nolder: i64 = 0
429 var nsmaller: i64 = 0
430 var nexpired_applied: i64 = 0
431 var nwould_expire: i64 = 0
432 var nstale_orphan: i64 = 0
433 var nblindspot: i64 = 0
434 var nrestage: i64 = 0
435 var nref_blocked: i64 = 0
436 // FLAG TALLIES, reported BESIDE the class partition. The class is the FIRST refusal reason in a fixed
437 // precedence, so class counts alone under-report: a 16-day-old ORPHAN returns ORPHAN and never shows
438 // up as EXPIRED, and a backdated artifact that ALSO loses tokens is only counted once. These tallies
439 // OVERLAP by design and deliberately do NOT sum to `staged` -- that is the honest shape of the data.
440 var fBACK: i64 = 0
441 var fEXP: i64 = 0
442 var fSHR: i64 = 0
443 var fCAP: i64 = 0
444
445 if iscensus == 1 { sh_puts("=== NX-STAGHYG census -- size+mtime BOTH sides; DECIDES NOTHING ===\n" as *u8) }
446 if iscensus == 0 { sh_puts("=== NX-STAGHYG scan -- classified staging verdict ===\n" as *u8) }
447
448 var go: i64 = 1
449 while go == 1 {
450 let nr: i64 = sys_getdents64(fd, dbuf, SH_DIRBUF)
451 if nr <= 0 { go = 0 }
452 if go == 1 {
453 var off: i64 = 0
454 while off < nr {
455 let rec: *u8 = ((dbuf as i64) + off) as *u8
456 let ty: i64 = dirent_type(rec)
457 let nm: *u8 = dirent_name(rec)
458 if ty != SH_DIR_TYPE {
459 if sh_ends_new(nm) == 1 {
460 nstaged = nstaged + 1
461 sh_join(root, nm, np, 0)
462 sh_live_path(root, nm, lp)
463
464 if iscensus == 1 {
465 // RUNG 0: report both sides, mark which is newer, decide nothing.
466 let ls: i64 = sg_size(lp)
467 let ns: i64 = sg_size(np)
468 let lm: i64 = sg_mtime(lp)
469 let nmt: i64 = sg_mtime(np)
470 sh_puts(" " as *u8); sh_puts(nm)
471 sh_puts(" live=" as *u8); sh_num(ls); sh_puts("b/" as *u8); sh_num(lm)
472 sh_puts(" staged=" as *u8); sh_num(ns); sh_puts("b/" as *u8); sh_num(nmt)
473 if ls < 0 { sh_puts(" newer=NO-LIVE" as *u8) }
474 if ls >= 0 {
475 npaired = npaired + 1
476 if nmt > lm { sh_puts(" newer=STAGED" as *u8) }
477 if nmt < lm { sh_puts(" newer=LIVE" as *u8); nolder = nolder + 1 }
478 if nmt == lm { sh_puts(" newer=SAME-MTIME" as *u8) }
479 if ns < ls { sh_puts(" smaller=STAGED" as *u8); nsmaller = nsmaller + 1 }
480 }
481 sh_puts("\n" as *u8)
482 }
483
484 if iscensus == 0 {
485 let c: i64 = sg_classify(lp, np, now, cfg, out)
486 if c == SG_NONE { cNONE = cNONE + 1 }
487 if c == SG_FORWARD { cFWD = cFWD + 1 }
488 if c == SG_ORPHAN { cORPH = cORPH + 1 }
489 if c == SG_BACKDATE { cBACK = cBACK + 1 }
490 if c == SG_EXPIRED { cEXP = cEXP + 1 }
491 if c == SG_SHRINK { cSHR = cSHR + 1 }
492 if c == SG_CAPLOSS { cCAP = cCAP + 1 }
493 if out[SG_O_LIVESZ] >= 0 { npaired = npaired + 1 }
494 // THE BLIND SPOT, COUNTED. A staged artifact that is NEWER, the SAME SIZE, and
495 // shows ZERO capability change is exactly the signature of a MUTATION-CLASS
496 // defect (an ==/!= operator swap is size-preserving AND string-preserving by
497 // construction), and this guard ALLOWS it. Two such mutants have already escaped
498 // into this tree. Measured 2026-08-06 by a sibling seat: 5 of 18,060 files
499 // differed at equal size and 1 of those 5 was a mutant -- a 20pct hit rate INSIDE
500 // the blind spot against a 33pct base divergence rate. An instrument that cannot
501 // count its own blind spot cannot tell you whether to care about it.
502 if sg_allows(c) == 1 {
503 if out[SG_O_IDENTICAL] == 1 { nrestage = nrestage + 1 }
504 if out[SG_O_LIVESZ] > 0 {
505 if out[SG_O_NEWSZ] == out[SG_O_LIVESZ] {
506 if out[SG_O_LOSTPERMIL] == 0 {
507 // ONLY a DIFFERING same-size artifact is the blind spot. A
508 // byte-identical re-stage is harmless, and counting it here
509 // would inflate the number that argues for the fix -- which is
510 // the one number that must not be inflated.
511 if out[SG_O_IDENTICAL] == 0 {
512 nblindspot = nblindspot + 1
513 sh_puts(" BLIND-SPOT " as *u8); sh_puts(nm)
514 sh_puts(" same size " as *u8); sh_num(out[SG_O_NEWSZ])
515 sh_puts("b, content DIFFERS, zero capability delta -- nothing in this guard can see what changed\n" as *u8)
516 }
517 }
518 }
519 }
520 }
521 let fl: i64 = out[SG_O_FLAGS]
522 if (fl % 2) == 1 { fBACK = fBACK + 1 }
523 if ((fl / 2) % 2) == 1 { fEXP = fEXP + 1 }
524 if ((fl / 4) % 2) == 1 { fSHR = fSHR + 1 }
525 if ((fl / 8) % 2) == 1 { fCAP = fCAP + 1 }
526 if sg_allows(c) == 0 {
527 if c != SG_NONE {
528 nrefused = nrefused + 1
529 sh_row(nm, c, out)
530 }
531 }
532 // EXPIRY. Scope is deliberate: it disarms only artifacts that are past the
533 // window AND would be REFUSED -- i.e. actually armed to overwrite a live
534 // binary with something worse. A stale ORPHAN is staging-area rot, not a
535 // hazard (there is no live binary for it to destroy), so it is COUNTED and
536 // REPORTED but never touched: silently renaming hundreds of other seats'
537 // unpromoted builds would be its own act of destruction.
538 if out[SG_O_AGEDAYS] > cfg[SG_C_MAXAGE] {
539 if sg_allows(c) == 1 { nstale_orphan = nstale_orphan + 1 }
540 if sg_allows(c) == 0 { nwould_expire = nwould_expire + 1 }
541 }
542 if isexpire == 1 {
543 if out[SG_O_AGEDAYS] > cfg[SG_C_MAXAGE] {
544 if sg_allows(c) == 0 {
545 // PROVE UNREFERENCED BEFORE YOU MOVE. This verb RENAMES a staged
546 // artifact -- and tool_allowlist.conf can point a REGISTERED tool
547 // straight at a <name>.sov.elf.new. nx_shipcheck counts 45 such rows
548 // (stagedref), unchanged for five days. Renaming one of those turns a
549 // live tool into exit 127 NOT-FOUND. The estate's rule is RETIRE =
550 // MOVE + PROVE UNREFERENCED; the first cut of this verb did the MOVE
551 // and skipped the PROVE, and only luck kept it from breaking a tool
552 // (the single artifact it disarmed was referenced by its .elf, not its
553 // .new -- verified, not assumed).
554 // FAIL-CLOSED: an unreadable allowlist means nothing can be PROVEN
555 // unreferenced, so nothing is disarmed. A stale artifact left armed is
556 // the cheaper failure -- the promote guard already refuses it -- while
557 // a tool broken by its own janitor is a live outage.
558 var referenced: i64 = 1
559 if allown > 0 { referenced = sg_contains(allowbuf, allown, nm, sg_strlen(nm)) }
560 if referenced == 1 {
561 nref_blocked = nref_blocked + 1
562 sh_puts(" REFERENCED-NOT-DISARMED " as *u8); sh_puts(nm)
563 sh_puts(" -- tool_allowlist.conf points a REGISTERED tool at this exact staged artifact; renaming it would make that tool exit 127\n" as *u8)
564 }
565 if referenced == 0 {
566 if doapply == 0 {
567 sh_puts(" WOULD-DISARM " as *u8); sh_puts(nm)
568 sh_puts(" (age=" as *u8); sh_num(out[SG_O_AGEDAYS])
569 sh_puts("d class=" as *u8); sh_puts(sg_class_name(c)); sh_puts(")\n" as *u8)
570 }
571 if doapply == 1 {
572 var xo: i64 = sh_append_str(xp, 0, np)
573 xo = sh_append_str(xp, xo, ".expired-" as *u8)
574 sh_append_num(xp, xo, now)
575 if sys_renameat(np, xp) == 0 {
576 nexpired_applied = nexpired_applied + 1
577 sh_puts(" DISARMED " as *u8); sh_puts(nm)
578 sh_puts(" -> " as *u8); sh_puts(xp); sh_puts("\n" as *u8)
579 }
580 }
581 }
582 }
583 }
584 }
585 }
586 }
587 }
588 off = off + dirent_reclen(rec)
589 }
590 }
591 }
592 sys_close(fd)
593
594 if iscensus == 1 {
595 sh_puts("NX-STAGHYG census root=" as *u8); sh_puts(root)
596 sh_puts(" staged=" as *u8); sh_num(nstaged)
597 sh_puts(" paired=" as *u8); sh_num(npaired)
598 sh_puts(" staged-OLDER-than-live=" as *u8); sh_num(nolder)
599 sh_puts(" staged-SMALLER-than-live=" as *u8); sh_num(nsmaller)
600 sh_puts(" verdict=GREEN\n" as *u8)
601 sys_exit(0); return 0
602 }
603
604 sh_puts("NX-STAGHYG scan root=" as *u8); sh_puts(root)
605 sh_puts(" staged=" as *u8); sh_num(nstaged)
606 sh_puts(" FORWARD=" as *u8); sh_num(cFWD)
607 sh_puts(" ORPHAN=" as *u8); sh_num(cORPH)
608 sh_puts(" BACKDATE=" as *u8); sh_num(cBACK)
609 sh_puts(" EXPIRED=" as *u8); sh_num(cEXP)
610 sh_puts(" SHRINK=" as *u8); sh_num(cSHR)
611 sh_puts(" CAPLOSS=" as *u8); sh_num(cCAP)
612 sh_puts(" NONE=" as *u8); sh_num(cNONE)
613 sh_puts(" refused=" as *u8); sh_num(nrefused)
614 let summed: i64 = cFWD + cORPH + cBACK + cEXP + cSHR + cCAP + cNONE
615 sh_puts(" classes_sum=" as *u8); sh_num(summed)
616 if summed != nstaged { sh_puts(" PARTITION-BROKEN" as *u8) }
617 if summed == nstaged { sh_puts(" partition=OK" as *u8) }
618 sh_puts(" paired=" as *u8); sh_num(npaired)
619 sh_puts(" | OVERLAPPING FLAGS (do not sum): backdate=" as *u8); sh_num(fBACK)
620 sh_puts(" expired=" as *u8); sh_num(fEXP)
621 sh_puts(" shrink=" as *u8); sh_num(fSHR)
622 sh_puts(" caploss=" as *u8); sh_num(fCAP)
623 sh_puts(" | conf=" as *u8); sh_num(hadconf)
624 sh_puts(" maxage=" as *u8); sh_num(cfg[SG_C_MAXAGE])
625 sh_puts("d shrinktol=" as *u8); sh_num(cfg[SG_C_SHRINKTOL])
626 sh_puts("permil caplosstol=" as *u8); sh_num(cfg[SG_C_CAPLOSS])
627 sh_puts("permil" as *u8)
628 sh_puts(" | BLIND SPOT (allowed, same size, content DIFFERS, zero capability delta = the mutation-class signature this guard CANNOT see): " as *u8); sh_num(nblindspot)
629 sh_puts(" harmless_identical_restage=" as *u8); sh_num(nrestage)
630 sh_puts(" | EXPIRY past " as *u8); sh_num(cfg[SG_C_MAXAGE])
631 sh_puts("d: armed_and_stale=" as *u8); sh_num(nwould_expire)
632 sh_puts(" stale_orphans_left_alone=" as *u8); sh_num(nstale_orphan)
633 if isexpire == 1 {
634 sh_puts(" disarmed=" as *u8); sh_num(nexpired_applied)
635 sh_puts(" referenced_NOT_disarmed=" as *u8); sh_num(nref_blocked)
636 sh_puts(" allowlist_rows_read=" as *u8); sh_num(allown)
637 if allown <= 0 { sh_puts(" ALLOWLIST-UNREADABLE-SO-NOTHING-DISARMED" as *u8) }
638 }
639 sh_puts(" verdict=GREEN\n" as *u8)
640 sys_exit(0)
641 return 0
642}