code wiki / _hdl_build / nx_rebuild_drain.nx

nx_rebuild_drain.nx source

↩ module page · 1307 lines · 79056 B

1// nx_rebuild_drain.nx -- THE ACTING HALF of dependency-aware staleness (debt 1785447998). 2// 3// nx_rebuild_plan DIAGNOSES: 662 of 696 deployed organs run binaries predating their own dependencies, 4// 638 of them traceable to just two shared runtimes carrying real behavioural root-fixes (SIGPIPE in 5// nx_syscalls.nx, the ss_get O(whole-store) fix in nx_seg_store.nx). But a census nobody is OBLIGED to 6// read is the same shape of defect as a fix nobody is OBLIGED to rebuild against -- both are capability 7// that exists and does not reach the place it matters. This organ is the obligation. 8// 9// ★★★WHY AN ORGAN AND NOT THE SHELL SCRIPT IT REPLACES: a shell batch is something a human remembers to 10// run. An organ can be SUPERVISED -- put on a beat, it turns "someone should rebuild the dependents" 11// into a property of the system. That is the whole difference between a workaround and a fix. 12// 13// GUARDS, every one of them learned by being bitten today: 14// • _cli/STUB TRAP: a fresh build far SMALLER than the deployed elf means the same-basename .nx is a 15// smoke stub and the real tool came from another source. nx_https_get rebuilds 443KB vs 633KB 16// deployed -- installing that BREAKS a working tool. REFUSED, never installed. 17// • ETXTBSY: cp over a RUNNING elf fails; the daemon holds that inode. Install is write-to-.new then 18// RENAME, which swaps the directory entry and leaves the live inode alone. 19// • BUILD FAILURE IS NOT INSTALLABLE: a non-zero build rc or a missing artifact skips the target. 20// • BOUNDED + SERIAL: today's saturation incident (load 63, mgmt+tools+sshd dead) came from wide 21// fan-out. This drains a batch at a time, one build at a time, and stops. Idempotent: re-running 22// simply picks up whatever is still stale, so a partial drain is always safe to resume. 23// • IDENTICAL-BYTES IS A NO-OP: if the fresh build matches what is deployed, nothing is written. 24// 25// nx_rebuild_drain beat [batch] [buildroot] [elfdir] SELF-CONTAINED for a clock row: regenerates the list, then drains a bounded batch 26// nx_rebuild_drain classify <listfile> [buildroot] [elfdir] PARTITION ONLY, spends no compile: buildable vs lib-basename vs no-elf 27// nx_rebuild_drain <listfile> [batch] [buildroot] [elfdir] 28// listfile = output of `nx_rebuild_plan list` (one target name per line) 29// -> per-target rows + summary. Exit 0 always; a drain reports, it does not refuse. 30// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 31import "nx_syscalls.nx" 32import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 33 34const RD_AT_FDCWD: i64 = 0 - 100 35const RD_SYS_NEWFSTATAT: i64 = 262 36const RD_STATBUF: i64 = 256 37const RD_OFF_SIZE: i64 = 48 38const RD_PATHCAP: i64 = 512 39const RD_LISTCAP: i64 = 262144 40// derived: measured 8 serial targets ran clean with zero saturation; 8 is the proven-safe default and is 41// overridable per invocation rather than baked in. 42const RD_DEFAULT_BATCH: i64 = 8 43// the stub-trap ratio: a fresh build under HALF the deployed size is a wrong-source signal, not a 44// shrink. Same discriminator nx_stale_check documents. 45const RD_STUB_NUM: i64 = 2 46// ⚠NO BUILD TIMEOUT IS ENFORCED HERE. A wedged nx_sov_build_run will block this drain indefinitely. 47// Stating it rather than declaring an unused RD_BUILD_TIMEOUT_S const -- a threshold nothing reads is 48// a guard that exists only in the reader's imagination, which is worse than an honestly absent one. 49// Mitigated for now by BOUNDED batches: a hang stalls one batch, never an unattended sweep. 50const RD_COPYBUF: i64 = 1048576 51 52func rd_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 53// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 54// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 55// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 56// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 57func rd_n(v: i64) -> i64 { nxi_out(v); return 0 } 58func rd_len(a: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { i = i + 1 } return i } 59func rd_cpy(dst: *u8, src: *u8) -> i64 { var i: i64 = 0; while src[i] != (0 as u8) { dst[i] = src[i]; i = i + 1 } dst[i] = 0 as u8; return i } 60func rd_cat(dst: *u8, o: i64, src: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while src[i] != (0 as u8) { dst[p] = src[i]; p = p + 1; i = i + 1 } dst[p] = 0 as u8; return p } 61 62// ALIAS RESOLUTION (2026-08-15). Some deployed artifacts carry a basename that is NOT their build 63// target -- nx_opaque_login.elf is byte-identical to the nx_opaque_login_daemon build. Without this the 64// row resolves to a LIBRARY, never links, and blocks the queue forever. 65// ★DATA, NOT CODE: the mapping lives in a conf so a new case is a row, not a rebuild of this organ. 66// ⚠ONLY `proven` ROWS RESOLVE. An `unresolved` row keeps its recorded evidence and is NOT built under a 67// guessed target -- installing a different program under a live service's name is worse than the stale 68// binary it would replace. ★WRONG IN THE DIRECTION OF DOING NOTHING. 69const RD_ALIAS_CONF: *u8 = "knowledge/registry/elf_source_alias.conf" 70const RD_TAB_C: i64 = 9 71const RD_HASH_C: i64 = 35 72// Writes the resolved build target for `name` into out; returns 1 if a PROVEN alias applied, else 0 73// (and out is left holding `name` unchanged). 74func rd_alias(name: *u8, out: *u8) -> i64 { 75 rd_cpy(out, name) 76 let lenp: *i64 = sys_mmap(8) 77 let b: *u8 = sys_read_file(RD_ALIAS_CONF, lenp) 78 let n: i64 = lenp[0] 79 sys_munmap(lenp as *u8, 8) 80 if n <= 0 { return 0 } 81 var applied: i64 = 0 82 var i: i64 = 0 83 while i < n { 84 var le: i64 = i 85 var sc: i64 = 1 86 while sc == 1 { if le >= n { sc = 0 } else { if b[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 87 if le > i { 88 if (b[i] as i64) != RD_HASH_C { 89 let e1: i64 = rd_find_byte(b, i, le, RD_TAB_C) 90 if e1 >= 0 { 91 let nlen: i64 = e1 - i 92 var k: i64 = 0 93 var same: i64 = 1 94 var cmp: i64 = 1 95 while cmp == 1 { 96 if k >= nlen { cmp = 0 } else { 97 if name[k] != b[i+k] { same = 0; cmp = 0 } else { k = k + 1 } 98 } 99 } 100 if same == 1 { if name[nlen] == (0 as u8) { 101 let f2s: i64 = e1 + 1 102 let t2: i64 = rd_find_byte(b, f2s, le, RD_TAB_C) 103 if t2 >= 0 { 104 // ★WIDENED 2026-08-17 to accept `equivalent` as well as `proven`, and the scope is 105 // ONE ROW: of the three equivalent aliases, two are DECLARED DAEMONS that the 106 // portmap guard defers regardless, so only nx_project -> nx_project_gate becomes 107 // buildable. Its evidence is the STRICT oracle (nx_contentdiff runs_scanned=470 108 // lost_from_live=0 verdict=GREEN 3/3), and four independent guards still stand 109 // between this and the serving root: the daemon deferral, the content-loss 110 // threshold, the .prev rollback, and the install ledger. 111 // ⚠`unresolved` is STILL refused. A guessed alias installs a different program 112 // under a deployed name, which is worse than the stale binary it replaces. 113 var okstat: i64 = 0 114 if rd_starts_at(b, t2 + 1, le, "proven" as *u8) == 1 { okstat = 1 } 115 if rd_starts_at(b, t2 + 1, le, "equivalent" as *u8) == 1 { okstat = 1 } 116 if okstat == 1 { 117 var w: i64 = 0 118 while f2s + w < t2 { out[w] = b[f2s + w]; w = w + 1 } 119 out[w] = 0 as u8 120 applied = 1 121 } 122 } 123 } } 124 } 125 } 126 } 127 i = le + 1 128 } 129 sys_munmap(b, n) 130 return applied 131} 132 133// ★★★★★★THE CALLABLE HOME FOR "WHERE IS THIS BYTE". I wrote the cursor-clobber exit THREE TIMES in 134// one session -- mb_loop_allocs, rd_has_main, and rd_alias -- each time AFTER banking the law that 135// forbids it. A rule I have to remember is a rule I will skip; the only thing that stops it is a 136// function that cannot express the defect. Returns the index of `c` in [s,e), or -1. The scan cursor 137// and the ANSWER are separate variables, so the exit can never destroy the position. 138func rd_find_byte(b: *u8, s: i64, e: i64, c: i64) -> i64 { 139 var i: i64 = s 140 var at: i64 = 0 - 1 141 var scanning: i64 = 1 142 while scanning == 1 { 143 if i >= e { scanning = 0 } else { 144 if (b[i] as i64) == c { at = i; scanning = 0 } else { i = i + 1 } 145 } 146 } 147 return at 148} 149 150func rd_starts_at(b: *u8, s: i64, e: i64, pre: *u8) -> i64 { 151 var k: i64 = 0 152 while pre[k] != (0 as u8) { 153 if s + k >= e { return 0 } 154 if b[s+k] != pre[k] { return 0 } 155 k = k + 1 156 } 157 return 1 158} 159 160func rd_streq(a: *u8, b: *u8) -> i64 { 161 var i: i64 = 0 162 var r: i64 = 2 163 while r == 2 { 164 if a[i] != b[i] { r = 0 } else { 165 if a[i] == (0 as u8) { r = 1 } else { i = i + 1 } 166 } 167 } 168 return r 169} 170 171func rd_size(path: *u8) -> i64 { 172 let sb: *u8 = sys_mmap(RD_STATBUF) 173 if __syscall(RD_SYS_NEWFSTATAT, RD_AT_FDCWD, path as i64, sb as i64, 0, 0, 0) != 0 { return 0 - 1 } 174 let sp: *i64 = ((sb as i64) + RD_OFF_SIZE) as *i64 175 return sp[0] 176} 177 178// name must be [A-Za-z0-9_] -- this string is handed to execve, so anything else is refused outright 179// rather than sanitised. A target name is not user prose; if it does not look like one, it is not one. 180func rd_safe(name: *u8) -> i64 { 181 var i: i64 = 0 182 while name[i] != (0 as u8) { 183 let c: i64 = name[i] as i64 184 var ok: i64 = 0 185 if c >= 48 { if c <= 57 { ok = 1 } } 186 if c >= 65 { if c <= 90 { ok = 1 } } 187 if c >= 97 { if c <= 122 { ok = 1 } } 188 if c == 95 { ok = 1 } 189 if ok == 0 { return 0 } 190 i = i + 1 191 if i >= 64 { return 0 } 192 } 193 if i == 0 { return 0 } 194 return 1 195} 196 197// byte-identical? 1 = same, 0 = differ/unreadable 198func rd_same(a: *u8, b: *u8) -> i64 { 199 let sa: i64 = rd_size(a) 200 let sb2: i64 = rd_size(b) 201 if sa < 0 { return 0 } 202 if sa != sb2 { return 0 } 203 let fa: i64 = sys_openat_rd(a) 204 if fa < 0 { return 0 } 205 let fb: i64 = sys_openat_rd(b) 206 if fb < 0 { sys_close(fa); return 0 } 207 let ba: *u8 = sys_mmap(RD_COPYBUF) 208 let bb: *u8 = sys_mmap(RD_COPYBUF) 209 var same: i64 = 1 210 var go: i64 = 1 211 while go == 1 { 212 let ra: i64 = sys_read(fa, ba, RD_COPYBUF) 213 let rb: i64 = sys_read(fb, bb, RD_COPYBUF) 214 if ra != rb { same = 0; go = 0 } else { 215 if ra <= 0 { go = 0 } else { 216 var k: i64 = 0 217 while k < ra { if ba[k] != bb[k] { same = 0; k = ra; go = 0 } else { k = k + 1 } } 218 } 219 } 220 } 221 sys_close(fa) 222 sys_close(fb) 223 return same 224} 225 226// copy src -> dst (truncating). 1 ok, 0 fail. 227func rd_copy(src: *u8, dst: *u8) -> i64 { 228 let fs: i64 = sys_openat_rd(src) 229 if fs < 0 { return 0 } 230 let fd: i64 = sys_openat_wr(dst, 493) 231 if fd < 0 { sys_close(fs); return 0 } 232 let buf: *u8 = sys_mmap(RD_COPYBUF) 233 var ok: i64 = 1 234 var go: i64 = 1 235 while go == 1 { 236 let r: i64 = sys_read(fs, buf, RD_COPYBUF) 237 if r < 0 { ok = 0; go = 0 } else { 238 if r == 0 { go = 0 } else { 239 let wn: i64 = sys_write(fd, buf, r) 240 if wn != r { ok = 0; go = 0 } 241 } 242 } 243 } 244 sys_fsync(fd) 245 sys_close(fd) 246 sys_close(fs) 247 return ok 248} 249 250// ---- CONTENT CONTAINMENT (root fix 2026-07-30, ws=sev-eater) --------------------------------- 251// THE SIZE RATIO ABOVE CANNOT SEE THE DIFFERENCE BETWEEN THE TWO THINGS IT MUST SEPARATE. 252// MEASURED TODAY, both directions, which is why this exists: 253// * A BETTER TOOLCHAIN SHRINKS A BINARY WITHOUT LOSING ANYTHING. Rebuilding nx_fin_serve / 254// nx_mp_serve / nx_torrent_mkinfo produced 12-22pc SMALLER elfs whose printable-string sets were 255// IDENTICAL to the deployed ones (only_in_deployed=0 AND only_in_fresh=0). seq1464 restored 11712 256// bytes of optimiser passes, so EVERY organ built by an older compiler now looks suspicious to a 257// size ruler. Judged by size alone the whole 700-organ queue is unreachable. 258// * REAL SOURCE LOSS ALSO SHRINKS A BINARY -- and by LESS. A supervised drain of 40 found 9 organs 259// whose fresh build was missing runs the deployed binary had (nx_warden -48, nx_conductor -46, 260// nx_https_get -12, +6 more). Every one of them PASSED the 50pc stub ratio; refused_stub_source 261// was 0. The ratio would have installed all nine. 262// So size correlates with the thing we fear and does not measure it. CONTENT does: a run of printable 263// bytes in the deployed binary is something that binary can emit, and if the fresh build cannot emit 264// it, capability was lost. An optimiser cannot trip this -- it changes instruction encoding, not the 265// strings the program can print. 266// LAW: A GUARD MUST MEASURE THE PROPERTY YOU CARE ABOUT (capability retained), NOT A PROXY THAT 267// CORRELATES WITH IT (size). Same shape as nx_srcguard v2's symbol-set containment for SOURCE. 268// THE MEASUREMENT ITSELF IS NOT MADE HERE. This organ carried its own printable-run differ until 269// 2026-08-16; see the rd_lost_runs tombstone below for why a second one was a defect rather than an 270// optimisation. The reasoning above is retained because it is WHY the guard exists at all -- it is the 271// case for measuring content instead of size, and that case is unchanged by which organ does the counting. 272 273// ⛔rd_slurp DELETED 2026-08-16 -- a hand-rolled CAPPED whole-file reader that sat beside the estate's 274// proven cap-free `sys_read_file`, which sizes its buffer from the file (lseek END) and cannot 275// short-read. Its own source records DEBT-EATEN 2026-07-15 for precisely this class: "the old fixed cap 276// SILENTLY TRUNCATED bigger files ... the worst failure class". I reproduced that eaten debt here as 277// three guessed ceilings (65536 alias conf / 65536 live-service table / 8388608 elf compare), one of 278// them feeding a SAFETY GUARD that fails OPEN on truncation and one feeding the content-loss verdict 279// that can corrupt in BOTH directions. 280// ★★★★★★A DUPLICATE RULER WEARING A CONSTANT IS STILL A DUPLICATE RULER, AND ITS CONSTANT IS THE PART 281// THAT ROTS. Compose the proven reader; never re-implement it. 282 283 284// ⛔rd_lost_runs DELETED 2026-08-16, with its private rd_runs / rd_h_ins / rd_h_has hash set and the six 285// constants that tuned it (RD_RUNMIN RD_HSLOTS RD_HMASK RD_HBYTES RD_FNVP RD_LENMIX RD_PROBE_CAP). 286// It was a SECOND printable-run differ living beside nx_contentdiff, and the two disagreed on a SAFETY 287// verdict: 267 vs 334 on identical inputs, because this one's RD_RUNMIN was 8 and the incumbent's minlen 288// is 6. The count now comes from rd_cdiff_lost, which forks the incumbent and parses its report, so the 289// drain and /api/promote decide on the SAME number and the calibrated 10-run floor finally means what it 290// was calibrated to mean. ★★★★★★DELETING THE DUPLICATE IS THE FIX; RETUNING 8 TO 6 WOULD HAVE LEFT TWO 291// RULERS THAT AGREE TODAY AND DRIFT TOMORROW. 292 293// run the sovereign builder for <target> under buildroot; returns its exit code, or -1 on spawn failure. 294// REBUILD LIKE FOR LIKE (2026-08-19): does the DEPLOYED elf carry a .debug_line section? If it does, 295// the drain must rebuild with --debug, or the content ruler reads the disappearance of the debug NAME 296// TABLE as capability loss and the row is refused forever. MEASURED on the two rows that sat at the 297// head of every regenerated list: nx_conductor "lost 52 runs" / nx_warden "lost 55" -- every single 298// lost run was a FUNCTION NAME (sys_socket, sys_recvfrom, w_is_build_artifact...) from .debug_line/ 299// .debug_info of an 08-15 dbgflag-era debug build; rebuilt with --debug the loss collapses to the 300// names of functions the compiler's whole-program DCE genuinely removed (dead code, not capability). 301// The probe is the section-name STRING in the elf bytes -- the same channel the section header table 302// uses, present exactly when nxasm emitted the section, and absent from a stripped build. Fail-open: 303// an unreadable elf probes 0 and the row builds exactly as before. 304const RD_DEBUG_MARK: *u8 = ".debug_line" 305func rd_live_has_debug(dep: *u8) -> i64 { 306 let lenp: *i64 = sys_mmap(16) as *i64 307 let b: *u8 = sys_read_file(dep, lenp) 308 if (b as i64) == 0 { return 0 } 309 let n: i64 = lenp[0] 310 var m: i64 = 0 311 while RD_DEBUG_MARK[m] != (0 as u8) { m = m + 1 } 312 var i: i64 = 0 313 var hit: i64 = 0 314 while i + m <= n { 315 var k: i64 = 0 316 var ok: i64 = 1 317 while k < m { if b[i+k] != RD_DEBUG_MARK[k] { ok = 0; k = m } else { k = k + 1 } } 318 if ok == 1 { hit = 1; i = n } 319 i = i + 1 320 } 321 if n > 0 { sys_munmap(b, n + 16) } 322 sys_munmap(lenp as *u8, 16) 323 return hit 324} 325func rd_build(broot: *u8, target: *u8, want_debug: i64) -> i64 { 326 let pid: i64 = sys_fork() 327 if pid < 0 { return 0 - 1 } 328 if pid == 0 { 329 sys_chdir(broot) 330 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 420) 331 if devnull >= 0 { sys_dup3(devnull, 1, 0); sys_dup3(devnull, 2, 0) } 332 let av: *i64 = sys_mmap(64) as *i64 333 av[0] = "./_offc/nx_sov_build_run.elf" as i64 334 av[1] = target as i64 335 av[2] = "--build-only" as i64 336 var na: i64 = 3 337 if want_debug == 1 { av[na] = "--debug" as i64; na = na + 1 } 338 av[na] = 0 339 let ev: *i64 = sys_mmap(16) as *i64 340 ev[0] = 0 341 sys_execve("./_offc/nx_sov_build_run.elf" as *u8, av, ev) 342 sys_exit(127) 343 } 344 let st: *i64 = sys_mmap(16) as *i64 345 sys_wait4(pid, st, 0) 346 return wait_exit_code(st[0]) 347} 348 349// ★★★★★★THE BEAT VERB IS THE WHOLE POINT OF THIS ORGAN, AND IT WAS THE ONE THING MISSING. This 350// file's own header says it: "an organ can be SUPERVISED -- put on a beat, it turns 'someone should 351// rebuild the dependents' into a property of the system. That is the whole difference between a 352// workaround and a fix." It shipped without one, so it stayed a tool somebody had to remember to run -- 353// which is the same adoption defect it exists to cure, one level up. 354// A clock row forks ONE command, but the pipeline is plan-list THEN drain, and the drain's own note says 355// the list must be regenerated first because installing changes who is stale. So the loop closes HERE, 356// inside the incumbent, rather than in a new beat organ that would be a second thing to keep correct. 357// ★EXTEND THE INCUMBENT, NEVER ADD A SECOND RULER. 358// ⚠BOUNDED BY CONSTRUCTION: the batch is an argument with a small default, the drain is serial, every 359// install is content-loss-refused and rollback-snapshotted, and identical bytes are a no-op. The header 360// records why that matters -- "today's saturation incident (load 63, mgmt+tools+sshd dead) came from 361// wide fan-out." 362// Deliberately SMALL. A beat is unattended, so its blast radius per firing is the thing that must be 363// bounded, not its throughput -- 1,849 rows drain over many quiet firings rather than one wide one. 364// ★★★★★★THE BATCH IS A SAFETY CEILING, NOT THE OPERATING POINT. A guessed count is a defect 365// generator in both directions -- too small is a trickle (at 4/day, 1,834 rows is ~458 days), too large 366// saturates the host. The real limit is HEADROOM, and the estate already measures it: nx_build_admit 367// reads /proc live and nx_sov_build_run turns a denial into SBR_ADMIT_REFUSED(6). So the drain runs 368// until the BOX says stop, and this number only bounds the worst case for one unattended firing. 369// ★COMPOSE THE INCUMBENT'S MEASUREMENT INSTEAD OF INVENTING A SECOND ONE: reading /proc here would be a 370// duplicate ruler that drifts from the admitter the builds actually obey. 371// ★★★★★★A COUNT WITHOUT A WORKLIST IS NOT ACTIONABLE, AND `lost_runs=2` IS A COUNT. A refusal that 372// says only HOW MANY capabilities the fresh build drops leaves the reader with no way to decide whether 373// the loss is a real regression or a deliberate reword -- so the row is re-attempted and re-refused on 374// every firing, forever. That is the head-of-line block again, one level down. 375// The estate already has the differ that NAMES them (nx_contentdiff prints `LOST: <run>`), so this forks 376// it ON REFUSAL ONLY rather than teaching rd_lost_runs to print. ★COMPOSE THE RULER, NEVER RE-IMPLEMENT 377// IT -- and the fork cost is paid only on the rare refusal, never on the common path. 378// ⚠Output goes to a DURABLE log, not stdout: this organ emits a JSON row stream, and interleaving the 379// differ's prose would corrupt it for every consumer. The JSON keeps the count; the log keeps the names. 380const RD_INSTALLLOG: *u8 = "knowledge/status/rebuild_installs.log" 381// ⛔THE LEDGER OF WHAT THIS ORGAN ACTUALLY SWAPPED. The trend journal records `installed=3` and NOT 382// WHICH -- so after the beat ran unattended, "did it replace a declared daemon?" was UNANSWERABLE, and I 383// hit exactly that wall auditing my own runs. ★★★★★★A COUNT WITHOUT A WORKLIST IS NOT ACTIONABLE, AND 384// FOR AN ORGAN THAT MUTATES THE SERVING ROOT THE WORKLIST IS THE AUDIT TRAIL. An unattended installer 385// whose actions cannot be enumerated afterwards is asking to be trusted rather than checked. 386// Append-only; the rollback path rides on the row so a reversal needs no archaeology. 387func rd_install_log(organ: *u8, was: i64, now: i64, prevn: *u8) -> i64 { 388 let fd: i64 = sys_openat_append(RD_INSTALLLOG, MODE_0644) 389 if fd < 0 { 390 rd_w("{\"organ\":\"nx_rebuild_drain\",\"install_ledger\":\"UNWRITABLE\"}\n" as *u8) 391 return 0 - 1 392 } 393 let b: *u8 = sys_mmap(RD_PATHCAP) 394 var o: i64 = 0 395 o = rd_catn(b, o, sys_now_realtime_sec()) 396 o = rd_cat(b, o, "\t" as *u8); o = rd_cat(b, o, organ) 397 o = rd_cat(b, o, "\twas=" as *u8); o = rd_catn(b, o, was) 398 o = rd_cat(b, o, "\tnow=" as *u8); o = rd_catn(b, o, now) 399 o = rd_cat(b, o, "\trollback=" as *u8); o = rd_cat(b, o, prevn) 400 b[o] = 10 as u8 401 o = o + 1 402 sys_write(fd, b, o) 403 sys_close(fd) 404 sys_munmap(b, RD_PATHCAP) 405 return 0 406} 407const RD_FAILLOG: *u8 = "knowledge/status/rebuild_buildfail.log" 408// ⛔THE OTHER PERMANENTLY-STUCK CLASS, AND IT BURNS A BUILD SLOT EVERY FIRING. MEASURED on the live beat 409// series: `failed=2` on EVERY scheduled firing since 1786932213 -- the SAME two organs re-attempted and 410// re-failing, consuming half a batch of 4 for ever. That is the head-of-line block already fixed for LIB 411// rows, in a new costume: a row that cannot compile is retried by an unattended beat until someone 412// notices, and `failed=2` is a COUNT WITH NO WORKLIST so nobody can. 413// ★★★★★A COUNTER TELLS YOU A CLASS EXISTS; ONLY A LEDGER TELLS YOU IT IS THE SAME ROW EVERY TIME. 414// ⚠DELIBERATELY NOT AN AUTO-SKIP: a BUILDFAIL can be TRANSIENT (a sibling mid-edit, headroom, a lease), 415// so refusing the row for ever would be wrong in the destructive direction. Recording it makes the 416// repeat offender VISIBLE and adjudicable; suppressing it would hide a defect that may have healed. 417func rd_fail_log(organ: *u8, tgt: *u8, rc: i64) -> i64 { 418 let fd: i64 = sys_openat_append(RD_FAILLOG, MODE_0644) 419 if fd < 0 { rd_w("{\"organ\":\"nx_rebuild_drain\",\"buildfail_ledger\":\"UNWRITABLE\"}\n" as *u8); return 0 - 1 } 420 let b: *u8 = sys_mmap(RD_PATHCAP) 421 var o: i64 = 0 422 o = rd_catn(b, o, sys_now_realtime_sec()) 423 o = rd_cat(b, o, "\t" as *u8); o = rd_cat(b, o, organ) 424 o = rd_cat(b, o, "\tbuilt_target=" as *u8); o = rd_cat(b, o, tgt) 425 o = rd_cat(b, o, "\trc=" as *u8); o = rd_catn(b, o, rc) 426 b[o] = 10 as u8 427 o = o + 1 428 sys_write(fd, b, o) 429 sys_close(fd) 430 sys_munmap(b, RD_PATHCAP) 431 return 0 432} 433const RD_LOSSLOG: *u8 = "knowledge/status/rebuild_contentloss.log" 434const RD_CDIFF_ELF: *u8 = "./_offc/nx_contentdiff.elf" 435const RD_CDIFF_TMPA: *u8 = "/tmp/nx_rd_cdiff_" 436const RD_CDIFF_TMPB: *u8 = ".txt" 437const RD_STATLINE: *u8 = "runs_scanned=" 438const RD_LOSTFIELD: *u8 = "lost_from_live=" 439// ⛔THE ONE CONTENT RULER. This organ used to CARRY ITS OWN printable-run differ (rd_runs + an FNV hash 440// set) whose shortest counted run was RD_RUNMIN=8, while nx_contentdiff -- the ruler /api/promote's guard 441// shares arithmetic with -- uses minlen=6. MEASURED 2026-08-16 on nx_clean_serve_daemon, identical inputs 442// (deployed 1255501 B, fresh 715779 B): mine said 267 lost, the incumbent said 334 of 592 scanned. FOUR 443// of the six runs it NAMED as lost were shorter than 8 (`default` `delete` `typeof` `finally`) and were 444// structurally invisible to mine. ★★★★★★I ADOPTED PROMOTE'S CALIBRATED FLOOR (10 runs / 49 permil) AND 445// APPLIED IT TO A DIFFERENT MEASURE WITH A DIFFERENT DENOMINATOR -- A THRESHOLD CALIBRATED ON ONE RULER 446// IS MEANINGLESS ON ANOTHER, and the drift is toward UNDER-reporting loss, i.e. toward installing a 447// regression. The comment directly below already forbade exactly this and I built it anyway. 448// Returns lost_from_live, or -1 when the report cannot be read or parsed -- and an unverifiable compare 449// is refused by the caller, because a guard that cannot answer must never wave through. 450func rd_cdiff_lost(organ: *u8, dep: *u8, fresh: *u8, logit: i64) -> i64 { 451 // ⚠Per-organ temp path: a single shared scratch file would make two concurrent drains read each 452 // other's report. Concurrency on the SAME organ is already excluded by the per-target lease. 453 let tp: *u8 = sys_mmap(RD_PATHCAP) 454 var tc: i64 = rd_cpy(tp, RD_CDIFF_TMPA) 455 tc = rd_cat(tp, tc, organ) 456 tc = rd_cat(tp, tc, RD_CDIFF_TMPB) 457 sys_unlinkat(tp) 458 let of: i64 = sys_openat_wr(tp, MODE_0644) 459 if of < 0 { sys_munmap(tp, RD_PATHCAP); return 0 - 1 } 460 let pid: i64 = sys_fork() 461 if pid < 0 { sys_close(of); sys_munmap(tp, RD_PATHCAP); return 0 - 1 } 462 if pid == 0 { 463 sys_dup3(of, 1, 0) 464 sys_dup3(of, 2, 0) 465 let av: *i64 = sys_mmap(64) as *i64 466 av[0] = RD_CDIFF_ELF as i64 467 av[1] = dep as i64 468 av[2] = fresh as i64 469 av[3] = 0 470 let ev: *i64 = sys_mmap(16) as *i64 471 ev[0] = 0 472 sys_execve(RD_CDIFF_ELF, av, ev) 473 sys_exit(127) 474 } 475 let st: *i64 = sys_mmap(16) as *i64 476 sys_wait4(pid, st, 0) 477 sys_close(of) 478 sys_munmap(st as *u8, 16) 479 let lenp: *i64 = sys_mmap(8) 480 let b: *u8 = sys_read_file(tp, lenp) 481 let n: i64 = lenp[0] 482 sys_munmap(lenp as *u8, 8) 483 sys_munmap(tp, RD_PATHCAP) 484 if n <= 0 { return 0 - 1 } 485 if logit == 1 { 486 let fd: i64 = sys_openat_append(RD_LOSSLOG, MODE_0644) 487 if fd >= 0 { 488 let hb: *u8 = sys_mmap(RD_PATHCAP) 489 var o: i64 = rd_cpy(hb, "\n=== " as *u8) 490 o = rd_cat(hb, o, organ) 491 o = rd_cat(hb, o, " epoch=" as *u8) 492 o = rd_catn(hb, o, sys_now_realtime_sec()) 493 o = rd_cat(hb, o, " (capabilities the DEPLOYED binary has and the FRESH build does not)\n" as *u8) 494 sys_write(fd, hb, o) 495 sys_write(fd, b, n) 496 sys_munmap(hb, RD_PATHCAP) 497 sys_close(fd) 498 } 499 } 500 // ★ANCHOR BY POSITION, NEVER BY TEXT. `lost_from_live=` is itself a printable run inside any binary 501 // that embeds nx_contentdiff's strings, so it can appear on a `LOST:` line -- an unanchored search 502 // would read the DATA as the ANSWER. Only the stats line STARTS with `runs_scanned=`. 503 var flen: i64 = 0 504 while RD_LOSTFIELD[flen] != (0 as u8) { flen = flen + 1 } 505 var out: i64 = 0 - 1 506 var i: i64 = 0 507 var walking: i64 = 1 508 while walking == 1 { 509 if i >= n { walking = 0 } else { 510 var le: i64 = i 511 var sc: i64 = 1 512 while sc == 1 { if le >= n { sc = 0 } else { if b[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 513 if rd_starts_at(b, i, le, RD_STATLINE) == 1 { 514 var k: i64 = i 515 var fnd: i64 = 0 - 1 516 var scan: i64 = 1 517 while scan == 1 { 518 if k >= le { scan = 0 } else { 519 if rd_starts_at(b, k, le, RD_LOSTFIELD) == 1 { fnd = k; scan = 0 } else { k = k + 1 } 520 } 521 } 522 if fnd >= 0 { 523 var p: i64 = fnd + flen 524 var v: i64 = 0 525 var any: i64 = 0 526 var dig: i64 = 1 527 while dig == 1 { 528 if p >= le { dig = 0 } else { 529 let c: i64 = b[p] as i64 530 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1; p = p + 1 } else { dig = 0 } } else { dig = 0 } 531 } 532 } 533 if any == 1 { out = v } 534 } 535 walking = 0 536 } else { i = le + 1 } 537 } 538 } 539 sys_munmap(b, n) 540 return out 541} 542func rd_name_losses(organ: *u8, dep: *u8, fresh: *u8) -> i64 { 543 let fd: i64 = sys_openat_append(RD_LOSSLOG, MODE_0644) 544 if fd < 0 { return 0 - 1 } 545 let hb: *u8 = sys_mmap(RD_PATHCAP) 546 var o: i64 = rd_cpy(hb, "\n=== " as *u8) 547 o = rd_cat(hb, o, organ) 548 o = rd_cat(hb, o, " epoch=" as *u8) 549 o = rd_catn(hb, o, sys_now_realtime_sec()) 550 o = rd_cat(hb, o, " (capabilities the DEPLOYED binary has and the FRESH build does not)\n" as *u8) 551 sys_write(fd, hb, o) 552 sys_munmap(hb, RD_PATHCAP) 553 let pid: i64 = sys_fork() 554 if pid < 0 { sys_close(fd); return 0 - 1 } 555 if pid == 0 { 556 sys_dup3(fd, 1, 0) 557 sys_dup3(fd, 2, 0) 558 let av: *i64 = sys_mmap(64) as *i64 559 av[0] = RD_CDIFF_ELF as i64 560 av[1] = dep as i64 561 av[2] = fresh as i64 562 av[3] = 0 563 let ev: *i64 = sys_mmap(16) as *i64 564 ev[0] = 0 565 sys_execve(RD_CDIFF_ELF, av, ev) 566 sys_exit(127) 567 } 568 let st: *i64 = sys_mmap(16) as *i64 569 sys_wait4(pid, st, 0) 570 sys_close(fd) 571 return wait_exit_code(st[0]) 572} 573// ★★★★★★A GUARD THAT MEASURES ONLY LOSS WILL BLOCK EVERY UPGRADE THAT RENAMES ANYTHING. MEASURED 574// 2026-08-15 on nx_archive_daemon: the fresh build LOSES 2 runs (an old `User-Agent: NishiReader/2.0` + 575// its Accept twin, replaced by the Chrome header set nx_polite_browser now emits) and GAINS 139 -- 576// including ARENA-OVERRUN, ring_sizes and the fail-loud ENOMEM messages, i.e. the arena safety work the 577// deployed binary predates. Refusing that install keeps the OLDER, LESS SAFE binary in production, and 578// re-refuses it on every firing forever. 579// ★A ONE-DIRECTION DIFF CANNOT TELL A REGRESSION FROM A REWORD -- the gain is half the evidence and the 580// guard was reading neither. 581// THE THRESHOLD IS NOT INVENTED HERE. /api/promote's calibrated guard already permits 1-2 absent runs: 582// ordinary edits measure 8-38 permil, and EVERY real regression cleared 49+ permil / 10+ runs. This 583// adopts that measured floor in the unit available (run count), so the drain DECIDES LIKE PROMOTE 584// DECIDES -- ★TWO GUARDS FOR ONE INVARIANT WITH DIFFERENT THRESHOLDS IS THE DUPLICATE-RULER DEFECT. 585// ⚠A loss below the floor is never silent: it is still NAMED in the loss log and reported in the row. 586// ★★★★★★A DRAIN THAT CANNOT TELL A LIVE SERVICE FROM A ONE-SHOT WILL EVENTUALLY DEPLOY ONE WITHOUT 587// A HEALTH CHECK. Every install so far landed on a NON-running binary -- verified against the live table, 588// not assumed -- but that was the luck of the queue order, not a property of this organ. The backlog 589// holds nx_opaque_login, nx_gallery_serve and nx_mgmt_api among its 1,828 rows, and this organ's guards 590// are all STATIC (content, size, rollback): none of them asks "does it still serve after the swap?". 591// The estate already states the rule -- /api/promote REFUSES daemons with "A DAEMON must use the 592// health-checked /api/deploy (validate -> promote -> http-health -> auto-rollback), not /api/promote -- 593// that is the correct path, not a workaround." This organ was bypassing that lane entirely. 594// ★READ THE LIVE TABLE, NEVER HARDCODE A SERVICE LIST: the supervisor writes mgmt_snap.json every poll, 595// so the set is DATA that stays current on its own. A baked-in list would rot into a guard that waves 596// through whatever was added after it was written. 597// ⚠Refusing is the SAFE direction: a deferred upgrade leaves the estate exactly as it is, while an 598// unchecked daemon swap can take a service down and only the NEXT restart would reveal it (the rename 599// leaves the running inode alone, so the damage is silent until then -- the worst shape a failure can 600// have). 601const RD_SNAP: *u8 = "mgmt_snap.json" 602// ⛔NO CAP HERE, AND THE REASON IS THE GUARD'S OWN SAFETY. This read used a hand-picked 65536 ceiling. 603// mgmt_snap.json measures 662 B today -- 99x headroom, which is exactly why the defect was invisible -- 604// but a capped read TRUNCATES IN SILENCE, and a truncated live-service table reads as `not live` for 605// every service past the cut. The guard would then wave an unchecked daemon swap through, and the rename 606// leaves the running inode alone so nothing would surface until the next restart. 607// ★★★★★★A SAFETY GUARD WHOSE INPUT CAN TRUNCATE SILENTLY FAILS OPEN, AND ITS HEADROOM TODAY IS NOT A 608// PROPERTY OF TOMORROW'S DATA. sys_read_file sizes from the file and cannot short-read. 609func rd_is_live_service(name: *u8) -> i64 { 610 let lenp: *i64 = sys_mmap(8) 611 let b: *u8 = sys_read_file(RD_SNAP, lenp) 612 let n: i64 = lenp[0] 613 sys_munmap(lenp as *u8, 8) 614 if n <= 0 { 615 // ★A GUARD THAT CANNOT MEASURE MUST REFUSE, NEVER WAVE THROUGH. No snapshot means we cannot tell 616 // whether this target is live, and installing on that basis is exactly the gamble to avoid. 617 return 0 - 1 618 } 619 let pat: *u8 = sys_mmap(RD_PATHCAP) 620 var p: i64 = rd_cpy(pat, "SVC " as *u8) 621 p = rd_cat(pat, p, name) 622 p = rd_cat(pat, p, ".elf " as *u8) 623 var found: i64 = 0 624 var i: i64 = 0 625 while i < n { 626 var le: i64 = i 627 var sc: i64 = 1 628 while sc == 1 { if le >= n { sc = 0 } else { if b[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 629 if rd_starts_at(b, i, le, pat) == 1 { found = 1; i = n } else { i = le + 1 } 630 } 631 sys_munmap(pat, RD_PATHCAP) 632 sys_munmap(b, n) 633 return found 634} 635const RD_PORTMAP: *u8 = "knowledge/status/portmap.conf" 636// ⛔A DAEMON THAT HAPPENS TO BE DOWN IS STILL A DAEMON. rd_is_live_service reads mgmt_snap, which lists 637// only what is RUNNING -- so a declared service that is currently stopped sails past it and gets its 638// binary swapped by a rename, bypassing the health-checked /api/deploy lane. ★★★★★A GUARD KEYED ON 639// CURRENT STATE MISSES EVERY SUBJECT THAT IS BETWEEN STATES, AND `stopped` IS EXACTLY WHEN A BAD BINARY 640// LANDS UNNOTICED: nothing fails until the next start. portmap.conf is the CANONICAL port registry and 641// its own header states the rule -- "A listener absent here is UNDECLARED." Owning a port IS the 642// declaration. 1 = declared owner, 0 = not, -1 = unreadable (caller refuses, never waves through). 643func rd_owns_port(name: *u8) -> i64 { 644 let lenp: *i64 = sys_mmap(8) 645 let b: *u8 = sys_read_file(RD_PORTMAP, lenp) 646 let n: i64 = lenp[0] 647 sys_munmap(lenp as *u8, 8) 648 if n <= 0 { return 0 - 1 } 649 let pat: *u8 = sys_mmap(RD_PATHCAP) 650 var p: i64 = rd_cpy(pat, name) 651 p = rd_cat(pat, p, ".elf" as *u8) 652 var found: i64 = 0 653 var i: i64 = 0 654 var walking: i64 = 1 655 while walking == 1 { 656 if i >= n { walking = 0 } else { 657 var le: i64 = i 658 var sc: i64 = 1 659 while sc == 1 { if le >= n { sc = 0 } else { if b[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 660 if le > i { if b[i] != (35 as u8) { 661 let t: i64 = rd_find_byte(b, i, le, RD_TAB_C) 662 if t >= 0 { if rd_starts_at(b, t + 1, le, pat) == 1 { 663 // ★rd_starts_at IS A PREFIX TEST, so the field must also END here or `nx_foo.elf` 664 // matches a row owning `nx_foo.elf.bak`. A PREFIX TEST STANDING IN FOR AN EXACT ONE. 665 if t + 1 + p >= le { found = 1; walking = 0 } 666 } } 667 } } 668 if walking == 1 { i = le + 1 } 669 } 670 } 671 sys_munmap(pat, RD_PATHCAP) 672 sys_munmap(b, n) 673 return found 674} 675const RD_LOSS_REGRESSION_RUNS: i64 = 10 676const RD_ADMIT_REFUSED: i64 = 6 677// BUILD SLOTS PER FIRING -- not rows per firing; rows we decline to build cost no slot (see the 678// work-done-not-work-offered note in the drain loop). ★A CONSTANT MUST CARRY THE ARITHMETIC THAT CHOSE 679// IT, OR THE NEXT READER CAN ONLY GUESS WHETHER RAISING IT IS SAFE. MEASURED 2026-08-16 from this 680// organ's own elapsed_s column: fixed cost per firing ~9 s (plan regeneration + lib skips), marginal 681// cost ~10 s per build, so 4 slots = ~48 s. Against the 1800 s period adopted from the estate's 682// established queue-drain beat (ddqbeat, nx_dedup_migrate queue 2) that is a 2.7% duty cycle. 683// ⚠The REAL governor is not this number: nx_sov_build_run's admission controller refuses per-build 684// when the box lacks headroom and the drain STOPS on SBR_ADMIT_REFUSED, so a loaded box drains slower 685// by measurement rather than by anything guessed here. Raise this only with a fresh elapsed_s reading. 686const RD_BEAT_BATCH: i64 = 4 687// The durable series. Append-only, TAB-separated, one line per run of the `beat` VERB -- which is NOT 688// the same as one line per SCHEDULED firing, and conflating the two is what made this series unreadable: 689// read `src=scheduled` rows for cadence and backlog trend, `src=manual` rows for operator-driven drains. 690// The schedule itself is NEVER inferable from this file; the clocksched- plane is its only authority. nx_sizeguard already exists 691// to watch a status journal's growth and its sibling calibration is knowledge/status/procchurn.jrnl at 692// 1048576 B / 20000 lines -- REUSE THAT BUDGET rather than inventing one when this is wired to a guard. 693const RD_TREND: *u8 = "knowledge/status/rebuild_drain.jrnl" 694func rd_trend(backlog: i64, attempted: i64, installed: i64, notprog: i64, failed: i64, src: *u8, elapsed: i64, ddaemon: i64, dlive: i64, current: i64, hstop: i64) -> i64 { 695 let fd: i64 = sys_openat_append(RD_TREND, MODE_0644) 696 if fd < 0 { 697 // ★AN UNWRITABLE TREND MUST ANNOUNCE, NOT VANISH: a silently missing row reads later as "the 698 // beat did not fire", which is the exact confusion this series exists to remove. 699 rd_w("{\"organ\":\"nx_rebuild_drain\",\"trend\":\"UNWRITABLE\",\"path\":\"" as *u8) 700 rd_w(RD_TREND); rd_w("\"}\n" as *u8) 701 return 0 - 1 702 } 703 let b: *u8 = sys_mmap(RD_PATHCAP) 704 var o: i64 = 0 705 o = rd_catn(b, o, sys_now_realtime_sec()) 706 o = rd_cat(b, o, "\tbacklog=" as *u8); o = rd_catn(b, o, backlog) 707 o = rd_cat(b, o, "\tattempted=" as *u8); o = rd_catn(b, o, attempted) 708 o = rd_cat(b, o, "\tinstalled=" as *u8); o = rd_catn(b, o, installed) 709 o = rd_cat(b, o, "\tnot_a_program=" as *u8); o = rd_catn(b, o, notprog) 710 o = rd_cat(b, o, "\tfailed=" as *u8); o = rd_catn(b, o, failed) 711 o = rd_cat(b, o, "\tsrc=" as *u8); o = rd_cat(b, o, src) 712 // ★★★★★A BEAT THAT DOES NOT REPORT ITS OWN DURATION CANNOT BE SCHEDULED FROM EVIDENCE -- the period is 713 // then chosen by taste, and the only feedback is a queue that visibly never drains. With elapsed in 714 // the series the duty cycle (elapsed/period) is arithmetic any later reader can redo. 715 o = rd_cat(b, o, "\telapsed_s=" as *u8); o = rd_catn(b, o, elapsed) 716 // REASON TRAVELS WITH THE COUNT (2026-08-29): these buckets were COMPUTED on every beat and then 717 // thrown away by this row, so `backlog=2301 installed=0` read for 15 hours as a broken drain when 718 // it is mostly DAEMONS this organ CORRECTLY defers to the health-checked /api/deploy lane, plus a 719 // program tail starved by build admission on a loaded box. Additive columns, appended LAST. 720 o = rd_cat(b, o, "\tdeferred_daemon=" as *u8); o = rd_catn(b, o, ddaemon) 721 o = rd_cat(b, o, "\tdeferred_live=" as *u8); o = rd_catn(b, o, dlive) 722 o = rd_cat(b, o, "\talready_current=" as *u8); o = rd_catn(b, o, current) 723 o = rd_cat(b, o, "\theadroom_stopped=" as *u8); o = rd_catn(b, o, hstop) 724 b[o] = 10 as u8 725 o = o + 1 726 sys_write(fd, b, o) 727 sys_close(fd) 728 sys_munmap(b, RD_PATHCAP) 729 return 0 730} 731// decimal append into dst at o, returns new offset (MSB-first, no allocation) 732func rd_catn(dst: *u8, o: i64, v: i64) -> i64 { 733 var m: i64 = v 734 if m < 0 { dst[o] = 45 as u8; return rd_catn(dst, o + 1, 0 - m) } 735 if m == 0 { dst[o] = 48 as u8; return o + 1 } 736 let t: *u8 = sys_mmap(32) 737 var k: i64 = 0 738 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 739 var p: i64 = o 740 while k > 0 { k = k - 1; dst[p] = t[k]; p = p + 1 } 741 sys_munmap(t, 32) 742 return p 743} 744const RD_PLAN_ELF: *u8 = "./_offc/nx_rebuild_plan.elf" 745const RD_BEAT_LIST: *u8 = "/tmp/nx_rebuild_beat.list" 746func rd_plan_list(elfdir: *u8, srcroot: *u8, outpath: *u8) -> i64 { 747 let pid: i64 = sys_fork() 748 if pid < 0 { return 0 - 1 } 749 if pid == 0 { 750 let ofd: i64 = sys_openat_wr(outpath, MODE_0644) 751 if ofd < 0 { sys_exit(126) } 752 sys_dup3(ofd, 1, 0) 753 let av: *i64 = sys_mmap(64) as *i64 754 av[0] = RD_PLAN_ELF as i64 755 av[1] = "list" as i64 756 av[2] = elfdir as i64 757 av[3] = srcroot as i64 758 av[4] = 0 759 let ev: *i64 = sys_mmap(16) as *i64 760 ev[0] = 0 761 sys_execve(RD_PLAN_ELF, av, ev) 762 sys_exit(127) 763 } 764 let st: *i64 = sys_mmap(16) as *i64 765 sys_wait4(pid, st, 0) 766 return wait_exit_code(st[0]) 767} 768 769// 1 iff <broot>/runtime/**/<name>.nx declares a main(). A source without one is a LIBRARY and can never 770// link standalone -- `nxasm_x86: UNDEFINED label: main` is the toolchain saying "not a program", not 771// "broken code". Checked BEFORE spending a compile, because the compile is the expensive part and its 772// failure is indistinguishable from a real one once you only have an rc. 773// ⚠Both source roots are probed in the builder's own order (_hdl_build first, then runtime), so this 774// reports on the file that actually compiles rather than the first one that happens to exist. 775const RD_MAINDECL: *u8 = "func main(" 776// ⚠⚠READS THE WHOLE SOURCE, NOT A HEAD WINDOW. In this corpus main() is conventionally the LAST 777// function in the file, so a head-capped read would have found it in almost nothing and reported every 778// program as NOT-A-PROGRAM -- vacuous by construction, and it would have silently emptied the drain's 779// work queue while looking like a clean classification. ★A HEAD READ CANNOT ANSWER A QUESTION ABOUT THE 780// TAIL. rd_slurp is the organ's existing whole-file reader; composing it keeps one reader, not two. 781func rd_has_main(broot: *u8, name: *u8) -> i64 { 782 let p: *u8 = sys_mmap(RD_PATHCAP) 783 let lenp: *i64 = sys_mmap(8) 784 var c: i64 = rd_cpy(p, broot) 785 c = rd_cat(p, c, "/runtime/_hdl_build/" as *u8) 786 c = rd_cat(p, c, name) 787 c = rd_cat(p, c, ".nx" as *u8) 788 var buf: *u8 = sys_read_file(p, lenp) 789 var n: i64 = lenp[0] 790 if n <= 0 { 791 c = rd_cpy(p, broot) 792 c = rd_cat(p, c, "/runtime/" as *u8) 793 c = rd_cat(p, c, name) 794 c = rd_cat(p, c, ".nx" as *u8) 795 buf = sys_read_file(p, lenp) 796 n = lenp[0] 797 } 798 var found: i64 = 0 799 if n > 0 { 800 var i: i64 = 0 801 while i < n { 802 // ⚠⚠EXIT BY FLAG, NEVER BY CLOBBERING THE CURSOR. The first cut of this wrote `k = 9` to 803 // break out -- but the needle is 10 bytes, so RD_MAINDECL[9] is '(' and NOT the terminator: 804 // on a mismatch it reset k to 9 and span forever at 100% CPU. ★★★★★★A LOOP THAT BREAKS BY 805 // CLOBBERING ITS OWN CURSOR IS THE DEFECT THIS ESTATE HAS ALREADY PAID FOR FOUR TIMES IN A 806 // DAY, AND I WROTE IT AGAIN -- the fix is a separate flag, which cannot be off-by-one. 807 var k: i64 = 0 808 var ok: i64 = 1 809 var scanning: i64 = 1 810 while scanning == 1 { 811 if RD_MAINDECL[k] == (0 as u8) { scanning = 0 } else { 812 if i + k >= n { ok = 0; scanning = 0 } else { 813 if buf[i+k] != RD_MAINDECL[k] { ok = 0; scanning = 0 } else { k = k + 1 } 814 } 815 } 816 } 817 if ok == 1 { found = 1; i = n } else { i = i + 1 } 818 } 819 } 820 if n > 0 { sys_munmap(buf, n) } 821 sys_munmap(lenp as *u8, 8) 822 sys_munmap(p, RD_PATHCAP) 823 return found 824} 825 826// ★★★★★★DEDUPE TO SUBJECTS, THEN SPLIT BY REMEDY, BEFORE PUBLISHING ANY BACKLOG NUMBER. `1,852 827// stale organs` is a MIXED POPULATION, not a work queue: some rows are libraries whose basename happens 828// to match a deployed elf and can NEVER be built, some have no deployed elf at all, and only the 829// remainder is work. Reporting the total as a backlog sends the next reader on a campaign that cannot 830// finish. This verb answers the partition WITHOUT SPENDING A SINGLE COMPILE -- the classification is a 831// file read per row, and the compile is the expensive part -- so the honest number is cheap to have and 832// there is no excuse for quoting the mixed one. 833// ⚠Walks the WHOLE list, never a batch: a partition measured over a prefix is a sample wearing a 834// population's name. 835func rd_classify(listp: *u8, broot: *u8, elfdir: *u8) -> i64 { 836 let lb: *u8 = sys_mmap(RD_LISTCAP) 837 let lfd: i64 = sys_openat_rd(listp) 838 if lfd < 0 { rd_w("{\"organ\":\"nx_rebuild_drain\",\"refused\":\"listfile unreadable\"}\n" as *u8); return 2 } 839 let ln: i64 = sys_read(lfd, lb, RD_LISTCAP - 1) 840 sys_close(lfd) 841 if ln <= 0 { rd_w("{\"organ\":\"nx_rebuild_drain\",\"refused\":\"list EMPTY\"}\n" as *u8); return 2 } 842 lb[ln] = 0 as u8 843 let name: *u8 = sys_mmap(RD_PATHCAP) 844 let dep: *u8 = sys_mmap(RD_PATHCAP) 845 var rows: i64 = 0 846 var notprog: i64 = 0 847 var noelf: i64 = 0 848 var daemonrow: i64 = 0 849 var unsafe_name: i64 = 0 850 var buildable: i64 = 0 851 var i: i64 = 0 852 while i < ln { 853 var le: i64 = i 854 var sc: i64 = 1 855 while sc == 1 { if le >= ln { sc = 0 } else { if lb[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 856 if le > i { 857 var o: i64 = 0 858 var k: i64 = i 859 while k < le { if o < RD_PATHCAP - 1 { name[o] = lb[k]; o = o + 1 } k = k + 1 } 860 name[o] = 0 as u8 861 rows = rows + 1 862 if rd_safe(name) == 0 { unsafe_name = unsafe_name + 1 } else { 863 var c: i64 = rd_cpy(dep, elfdir) 864 c = rd_cat(dep, c, "/" as *u8) 865 c = rd_cat(dep, c, name) 866 c = rd_cat(dep, c, ".elf" as *u8) 867 if rd_size(dep) < 0 { noelf = noelf + 1 } else { 868 let tgt: *u8 = sys_mmap(RD_PATHCAP) 869 let aliased: i64 = rd_alias(name, tgt) 870 // ★★★★★SPLIT BY REMEDY BEFORE PUBLISHING A BACKLOG NUMBER. A DECLARED DAEMON belongs to the 871 // health-checked /api/deploy lane and can NEVER be drained by this one, so counting it 872 // as `buildable` makes the work queue permanently unreachable -- a backlog that cannot 873 // reach zero reads as failure when it is actually correct. Checked FIRST because it is 874 // the most specific fact: nx_project_serve is BOTH a declared daemon and a lib basename, 875 // and `daemon` is the one that names its remedy. 876 if rd_owns_port(name) == 1 { 877 daemonrow = daemonrow + 1 878 rd_w("DECLARED-DAEMON " as *u8); rd_w(name); rd_w(" -- /api/deploy lane, not this one\n" as *u8) 879 } else { 880 if rd_has_main(broot, tgt) == 0 { 881 notprog = notprog + 1 882 rd_w("LIB-BASENAME " as *u8); rd_w(name); rd_w("\n" as *u8) 883 } else { 884 buildable = buildable + 1 885 if aliased == 1 { rd_w("ALIASED " as *u8); rd_w(name); rd_w(" -> " as *u8); rd_w(tgt); rd_w("\n" as *u8) } 886 } 887 } 888 sys_munmap(tgt, RD_PATHCAP) 889 } 890 } 891 } 892 i = le + 1 893 } 894 rd_w("{\"organ\":\"nx_rebuild_drain\",\"verb\":\"classify\",\"rows\":" as *u8); rd_n(rows) 895 rd_w(",\"buildable\":" as *u8); rd_n(buildable) 896 rd_w(",\"lib_basename_never_buildable\":" as *u8); rd_n(notprog) 897 rd_w(",\"no_deployed_elf\":" as *u8); rd_n(noelf) 898 rd_w(",\"declared_daemon_other_lane\":" as *u8); rd_n(daemonrow) 899 rd_w(",\"unsafe_name\":" as *u8); rd_n(unsafe_name) 900 let sum: i64 = buildable + notprog + noelf + unsafe_name + daemonrow 901 rd_w(",\"partition_sum\":" as *u8); rd_n(sum) 902 if sum == rows { rd_w(",\"reconciles\":1" as *u8) } else { rd_w(",\"reconciles\":0" as *u8) } 903 rd_w(",\"note\":\"buildable is the ONLY row count that is a work queue; the rest need adjudication, not compiles\"}\n" as *u8) 904 return 0 905} 906 907func main(argc: i64, argv: *i64) -> i64 { 908 if argc < 2 { rd_w("usage: nx_rebuild_drain <listfile> [batch] [buildroot] [elfdir]\n nx_rebuild_drain classify <listfile> [buildroot] [elfdir]\n" as *u8); sys_exit(2); return 2 } 909 // beat sets these and falls through into the ONE drain body below -- a second copy of the drain 910 // loop would be a second thing to keep correct, and the two would silently disagree the first time 911 // either changed. 912 var is_beat: i64 = 0 913 let t_start: i64 = sys_now_realtime_sec() 914 var beat_list: *u8 = "" as *u8 915 var beat_batch: i64 = 0 916 // ★★★★★★A GUARD THAT KEYS ON THE VERB CANNOT SEE WHO TYPED IT. `is_beat` was meant to keep hand-runs 917 // out of the durable series, and it could not: invoking the `beat` verb by hand mints rows that are 918 // byte-identical to the scheduler's. I then read three of my OWN rows as evidence of a 5-minute 919 // cadence and published a 6-day drain estimate for a job that fires DAILY. Only the CLOCK ROW passes 920 // `scheduled`, so an operator can never mint a scheduled row by accident. 921 var beat_src: *u8 = "manual" as *u8 922 var beat_broot: *u8 = "buildroot" as *u8 923 var beat_elfdir: *u8 = "." as *u8 924 if rd_streq(argv[1] as *u8, "beat" as *u8) == 1 { 925 var bb: i64 = RD_BEAT_BATCH 926 var bbr: *u8 = "buildroot" as *u8 927 var bed: *u8 = "." as *u8 928 if argc >= 3 { 929 let bs: *u8 = argv[2] as *u8 930 var v: i64 = 0 931 var q: i64 = 0 932 while bs[q] != (0 as u8) { let c: i64 = bs[q] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } q = q + 1 } 933 if v > 0 { bb = v } 934 } 935 if argc >= 4 { bbr = argv[3] as *u8 } 936 if argc >= 5 { bed = argv[4] as *u8 } 937 // ★A FLAG THAT ACCEPTS ANY SPELLING CANNOT REPORT A TYPO -- exact token or refuse, so a clock row 938 // with a mistyped marker fails LOUDLY instead of silently logging every scheduled firing as manual. 939 var bsrc: *u8 = "manual" as *u8 940 if argc >= 6 { 941 if rd_streq(argv[5] as *u8, "scheduled" as *u8) == 1 { bsrc = "scheduled" as *u8 } else { 942 rd_w("{\"organ\":\"nx_rebuild_drain\",\"verb\":\"beat\",\"refused\":\"unrecognised source marker -- the only accepted token is `scheduled`, and only the clock row passes it\"}\n" as *u8) 943 sys_exit(2) 944 return 2 945 } 946 } 947 // ★REGENERATE FIRST. Installing changes who is stale, so a beat that reuses yesterday's list 948 // re-attempts work already done and misses work newly created. 949 let prc: i64 = rd_plan_list(bed, "buildroot/runtime" as *u8, RD_BEAT_LIST) 950 if prc != 0 { 951 rd_w("{\"organ\":\"nx_rebuild_drain\",\"verb\":\"beat\",\"refused\":\"plan list failed\",\"rc\":" as *u8) 952 rd_n(prc); rd_w("}\n" as *u8) 953 sys_exit(0) 954 return 0 955 } 956 rd_w("{\"organ\":\"nx_rebuild_drain\",\"verb\":\"beat\",\"list\":\"" as *u8) 957 rd_w(RD_BEAT_LIST); rd_w("\",\"batch\":" as *u8); rd_n(bb); rd_w(",\"src\":\"" as *u8); rd_w(bsrc); rd_w("\"}\n" as *u8) 958 beat_list = RD_BEAT_LIST 959 beat_batch = bb 960 beat_src = bsrc 961 beat_broot = bbr 962 beat_elfdir = bed 963 is_beat = 1 964 } 965 if rd_streq(argv[1] as *u8, "classify" as *u8) == 1 { 966 if argc < 3 { rd_w("usage: nx_rebuild_drain classify <listfile> [buildroot] [elfdir]\n" as *u8); sys_exit(2); return 2 } 967 var cb: *u8 = "buildroot" as *u8 968 var ce: *u8 = "." as *u8 969 if argc >= 4 { cb = argv[3] as *u8 } 970 if argc >= 5 { ce = argv[4] as *u8 } 971 let rcc: i64 = rd_classify(argv[2] as *u8, cb, ce) 972 sys_exit(rcc) 973 return rcc 974 } 975 var listp: *u8 = argv[1] as *u8 976 var batch: i64 = RD_DEFAULT_BATCH 977 var broot: *u8 = "buildroot" as *u8 978 var elfdir: *u8 = "." as *u8 979 if argc >= 3 { 980 let bs: *u8 = argv[2] as *u8 981 var v: i64 = 0 982 var i: i64 = 0 983 while bs[i] != (0 as u8) { let c: i64 = bs[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } 984 if v > 0 { batch = v } 985 } 986 if argc >= 4 { broot = argv[3] as *u8 } 987 if argc >= 5 { elfdir = argv[4] as *u8 } 988 if is_beat == 1 { listp = beat_list; batch = beat_batch; broot = beat_broot; elfdir = beat_elfdir } 989 990 let lb: *u8 = sys_mmap(RD_LISTCAP) 991 let lfd: i64 = sys_openat_rd(listp) 992 if lfd < 0 { rd_w("{\"organ\":\"nx_rebuild_drain\",\"refused\":\"listfile unreadable\"}\n" as *u8); sys_exit(2); return 2 } 993 let ln: i64 = sys_read(lfd, lb, RD_LISTCAP - 1) 994 sys_close(lfd) 995 if ln <= 0 { rd_w("{\"organ\":\"nx_rebuild_drain\",\"drained\":0,\"note\":\"list EMPTY -- nothing stale, or the plan was never run\"}\n" as *u8); return 0 } 996 lb[ln] = 0 as u8 997 998 let name: *u8 = sys_mmap(RD_PATHCAP) 999 let fresh: *u8 = sys_mmap(RD_PATHCAP) 1000 let dep: *u8 = sys_mmap(RD_PATHCAP) 1001 let tmpn: *u8 = sys_mmap(RD_PATHCAP) 1002 let prevn: *u8 = sys_mmap(RD_PATHCAP) 1003 var installed: i64 = 0 1004 var notprog: i64 = 0 1005 // ★★★★★★COUNTED BEFORE THE BATCH BOUND, NOT INSIDE IT. The first cut incremented this in the drain 1006 // loop -- which stops after `batch` rows -- so the trend recorded `backlog=2` for a 1,852-row queue: 1007 // A COUNTER INSIDE A BOUNDED LOOP MEASURES THE BOUND, NOT THE POPULATION. Worse, the line carried a 1008 // comment asserting it counted every row, so the wrong number arrived CERTIFIED. 1009 // ★A COMMENT THAT STATES AN INTENT THE CODE DOES NOT IMPLEMENT IS WORSE THAN NO COMMENT. 1010 var total_rows: i64 = 0 1011 var stopped_headroom: i64 = 0 1012 var livedefer: i64 = 0 1013 var tr_i: i64 = 0 1014 while tr_i < ln { 1015 var tr_e: i64 = tr_i 1016 var tr_s: i64 = 1 1017 while tr_s == 1 { if tr_e >= ln { tr_s = 0 } else { if lb[tr_e] == (10 as u8) { tr_s = 0 } else { tr_e = tr_e + 1 } } } 1018 if tr_e > tr_i { total_rows = total_rows + 1 } 1019 tr_i = tr_e + 1 1020 } 1021 var nochange: i64 = 0 1022 var refused: i64 = 0 1023 var refusedc: i64 = 0 1024 var failed: i64 = 0 1025 // ★SPLIT OUT OF `failed` 2026-08-17: no-deployed-elf spends NO build slot, a BUILDFAIL spends one, and 1026 // the partition identity needs only the former. `failed` is KEPT as the union so the existing summary 1027 // field does not change meaning for any consumer (rule 19: add, never repurpose). 1028 var skipped_no_elf: i64 = 0 1029 var portdefer: i64 = 0 1030 // `done` = build slots SPENT (the batch bound). `examined` = rows the loop looked at, which is 1031 // larger whenever a row is declined without a compile. ★PUBLISH BOTH OR THE PARTITION CANNOT BE 1032 // CHECKED: examined == done + not_a_program + deferred_live_service + no-deployed-elf, and a 1033 // residual there is a row class nobody named. 1034 var done: i64 = 0 1035 var examined: i64 = 0 1036 1037 rd_w("{\"organ\":\"nx_rebuild_drain\",\"rows\":[" as *u8) 1038 var first: i64 = 1 1039 var i: i64 = 0 1040 while i < ln { 1041 if done >= batch { i = ln } else { 1042 var le: i64 = i 1043 var sc: i64 = 1 1044 while sc == 1 { if le >= ln { sc = 0 } else { if lb[le] == (10 as u8) { sc = 0 } else { le = le + 1 } } } 1045 if le > i { 1046 var o: i64 = 0 1047 var k: i64 = i 1048 while k < le { if o < RD_PATHCAP - 1 { name[o] = lb[k]; o = o + 1 } k = k + 1 } 1049 name[o] = 0 as u8 1050 if rd_safe(name) == 1 { 1051 // ★★★★★★A LIMIT MUST COUNT WORK DONE, NOT WORK OFFERED. This counter used to advance HERE, 1052 // before the outcome was known, so a row we DECLINE to build spent a build slot. 1053 // MEASURED 2026-08-16: three permanently-unbuildable lib sources sit at the head of 1054 // every regenerated list, so a batch of 4 performed ONE build per firing and the 1055 // other three slots re-derived the same three refusals for ever. The comment forty 1056 // lines below already named this head-of-line block and cited the banked remedy -- 1057 // the diagnosis was written and the arithmetic was never changed to match it. 1058 // ★A DIAGNOSIS IN A COMMENT IS NOT A FIX; THE QUEUE OBEYS THE COUNTER, NOT THE PROSE. 1059 examined = examined + 1 1060 var c: i64 = rd_cpy(dep, elfdir) 1061 c = rd_cat(dep, c, "/" as *u8) 1062 c = rd_cat(dep, c, name) 1063 c = rd_cat(dep, c, ".elf" as *u8) 1064 let ds: i64 = rd_size(dep) 1065 var f: i64 = rd_cpy(fresh, broot) 1066 f = rd_cat(fresh, f, "/_build/" as *u8) 1067 f = rd_cat(fresh, f, name) 1068 f = rd_cat(fresh, f, ".sov.elf" as *u8) 1069 if first == 0 { rd_w("," as *u8) } 1070 first = 0 1071 rd_w("{\"organ\":\"" as *u8); rd_w(name); rd_w("\",\"result\":\"" as *u8) 1072 // ★★★★★★"IT DOES NOT COMPILE" AND "IT IS NOT A PROGRAM" ARE DIFFERENT FACTS WITH 1073 // OPPOSITE REMEDIES. MEASURED 2026-08-15: the first two rows of the backlog reported 1074 // BUILDFAIL rc=4, and the real error is `nxasm_x86: UNDEFINED label: main` -- 1075 // nx_gen_gateway.nx is a LIBRARY (its runnable twin is nx_gen_gateway_daemon.nx, which 1076 // has its own built elf). A lib can NEVER link standalone, so this row fails on every 1077 // run, never stops being stale, and sits at the head of every regenerated list. 1078 // ★★★★★★A PERMANENTLY-FAILING ROW AT THE HEAD OF AN ALWAYS-RE-SORTED QUEUE IS A 1079 // HEAD-OF-LINE BLOCK THAT NEVER CLEARS, and the estate already banked the remedy: 1080 // HIDING AN UNBUILDABLE SET INSIDE A BUILD QUEUE GUARANTEES THE QUEUE NEVER FINISHES -- 1081 // dedupe to SUBJECTS, then SPLIT BY REMEDY, before publishing any backlog number. 1082 // Detected the only way that is not a guess: the source either declares main or it does 1083 // not. Reported as its own row so the two never share a counter -- a lib here needs 1084 // ADJUDICATION (whose elf is that, really?), never a compile fix. 1085 let livesvc: i64 = rd_is_live_service(name) 1086 if ds < 0 { rd_w("SKIP-NO-DEPLOYED-ELF\"}" as *u8); failed = failed + 1; skipped_no_elf = skipped_no_elf + 1 } else { 1087 // ★ONE DECISION, ONE BRANCH -- the brace shape here is UNCHANGED on purpose. A nested 1088 // else would mean hand-balancing a 13-deep cascade, and a mis-closed brace in a live 1089 // installer is a worse defect than the one being fixed. 1090 // ★NAME WHICH REASON: a RUNNING service and a DECLARED-but-stopped one take the same 1091 // remedy but are not the same fact, and two skip-causes sharing one counter is how a 1092 // population stops being adjudicable. 1093 let portown: i64 = rd_owns_port(name) 1094 var deferany: i64 = 0 1095 if livesvc != 0 { deferany = 1 } 1096 if portown != 0 { deferany = 1 } 1097 if deferany != 0 { 1098 if livesvc < 0 { rd_w("REFUSED-CANNOT-READ-LIVE-TABLE\"}" as *u8) } else { 1099 if livesvc != 0 { rd_w("DEFERRED-LIVE-SERVICE-USE-API-DEPLOY\"}" as *u8) } else { 1100 if portown < 0 { rd_w("REFUSED-CANNOT-READ-PORTMAP\"}" as *u8) } else { rd_w("DEFERRED-DECLARED-DAEMON-USE-API-DEPLOY\"}" as *u8) } } } 1101 if livesvc != 0 { livedefer = livedefer + 1 } else { portdefer = portdefer + 1 } 1102 } else { 1103 // ⛔RESOLVE THE ALIAS BEFORE THE GATE THAT REJECTS ON IT. The first wiring put this 1104 // AFTER rd_has_main, which tests the DEPLOYED BASENAME -- so an aliased row was 1105 // rejected as a library before the alias was ever consulted, and the change was a 1106 // no-op that still compiled and still passed neutrality. 1107 // ★★★★★A LOOKUP PLACED AFTER THE TEST IT EXISTS TO SATISFY CANNOT CHANGE ANY OUTCOME, 1108 // AND NOTHING IN THE BUILD OR THE TEST SUITE SAYS SO -- only running the aliased row 1109 // and seeing the OLD verdict does. rd_classify already had this order right; the 1110 // drain path did not, which is exactly how the two halves drifted. 1111 let btgt: *u8 = sys_mmap(RD_PATHCAP) 1112 let usedalias: i64 = rd_alias(name, btgt) 1113 if rd_has_main(broot, btgt) == 0 { 1114 rd_w("NOT-A-PROGRAM-LIB-SOURCE\"}" as *u8) 1115 notprog = notprog + 1 1116 sys_munmap(btgt, RD_PATHCAP) 1117 } else { 1118 // The slot is spent HERE -- at the first action that costs the box a compile. 1119 // STOPPED-NO-HEADROOM counts too: the box was asked, and asking is the work. 1120 done = done + 1 1121 // ⛔THE ALIAS WAS RESOLVED FOR THE CLASSIFIER AND NEVER FOR THE BUILDER. rd_alias had 1122 // exactly two call sites -- its definition and rd_classify -- so the conf could 1123 // REPORT a resolved provenance while the drain still compiled the deployed basename, 1124 // which for an aliased row is a LIBRARY that can never link. 1125 // ★★★★★★A REGISTRY WIRED INTO THE REPORT BUT NOT INTO THE ACTION IS BUILT+UNWIRED 1126 // WEARING THE COSTUME OF A FEATURE: every reader sees the mapping and nothing obeys it. 1127 // BUILD the alias target and read ITS artifact; COMPARE against the DEPLOYED basename. 1128 // Non-aliased rows are unaffected BY CONSTRUCTION -- rd_alias copies `name` through 1129 // unchanged when no proven/equivalent row matches. 1130 if usedalias == 1 { 1131 var af: i64 = rd_cpy(fresh, broot) 1132 af = rd_cat(fresh, af, "/_build/" as *u8) 1133 af = rd_cat(fresh, af, btgt) 1134 af = rd_cat(fresh, af, ".sov.elf" as *u8) 1135 } 1136 let rc: i64 = rd_build(broot, btgt, rd_live_has_debug(dep)) 1137 // ⛔LOG BEFORE THE FREE. The first cut called rd_fail_log(name, btgt, rc) at the JSON 1138 // emit site far below -- AFTER this munmap -- a USE-AFTER-FREE that SIGSEGV'd the live 1139 // drain on its very first BUILDFAIL. The ledger file was created at 0 bytes, so the 1140 // open succeeded and the crash landed writing the freed pointer. 1141 // ★★★★★★A LEDGER ADDED TO RECORD FAILURES BECAME THE FAILURE: I extended the LIFETIME of 1142 // a borrowed buffer by adding a reader, and nothing in the build or the neutrality 1143 // test could see it -- only running the exact row that fails. 1144 // ★AN ARGUMENT THAT OUTLIVES ITS OWNER'S munmap IS A DANGLING POINTER NO MATTER HOW 1145 // OBVIOUSLY CORRECT THE CALL LOOKS AT THE CALL SITE. 1146 let fs: i64 = rd_size(fresh) 1147 // ⛔BACKPRESSURE IS NOT A FAILURE, AND AN APPEND-ONLY LEDGER MUST NOT SAY IT IS. 1148 // rc == RD_ADMIT_REFUSED is the BOX saying "stop", not the TARGET saying "broken". 1149 // The emit logic below already earned that exclusion (see its note); the ledger I 1150 // added would have bypassed it and permanently recorded healthy organs as failures -- 1151 // the exact regression that note exists to prevent, re-entered through a new door. 1152 // ★★★★★★A NEW RECORDER MUST INHERIT EVERY EXCLUSION THE EXISTING REPORTER ALREADY 1153 // EARNED; ADDING AN OUTPUT IS NOT NEUTRAL JUST BECAUSE IT ONLY WRITES. 1154 // ⚠Both calls sit BEFORE the munmap so btgt is still owned -- fs is hoisted above the 1155 // free for the same reason, which also lets NO-ARTIFACT record the real built target 1156 // instead of the deployed basename. 1157 if rc != 0 { if rc != RD_ADMIT_REFUSED { rd_fail_log(name, btgt, rc) } } 1158 if rc == 0 { if fs < 0 { rd_fail_log(name, btgt, 0 - 1) } } 1159 sys_munmap(btgt, RD_PATHCAP) 1160 // ★★★★★★BACKPRESSURE IS NOT A FAILURE. nx_sov_build_run returns SBR_ADMIT_REFUSED(6) 1161 // for all three admission denials -- DENY-MEM, QUEUE, CANNOT-MEASURE -- and its 1162 // source says why that code is distinct: the NAS branch once returned the raw 1163 // 3/4/5 which COLLIDE with COMPILE_FAIL/ASM_FAIL, so "a wait-and-retry signal 1164 // decoded as a broken build". My drain counted every rc!=0 as BUILDFAIL and would 1165 // have reproduced that regression from the other side -- recording a HEALTHY 1166 // target as broken, permanently, in an append-only trend. 1167 // ★A WAIT-AND-RETRY SIGNAL RECORDED AS A FAILURE TEACHES THE OPERATOR THAT HEALTHY 1168 // TARGETS ARE BROKEN. It STOPS the batch instead: the box is telling us to stop, 1169 // and the drain is idempotent so the remainder is simply the next firing's work. 1170 if rc == RD_ADMIT_REFUSED { 1171 rd_w("STOPPED-NO-HEADROOM\"}" as *u8) 1172 // The FLAG is what stops the loop (read at the loop tail). The old `i = ln` 1173 // written here was OVERWRITTEN by the tail's `i = le + 1` one screen down, so 1174 // "STOPS the batch" was true in prose and false in code: MEASURED 2026-08-18, 1175 // a 16-slot round printed STOPPED-NO-HEADROOM at slot 4 and went on to spend 1176 // the other 12 -- a loop-exit sentinel written into the cursor and erased, the 1177 // estate's own banked gotcha. A stop is a flag; the cursor is not a flag. 1178 stopped_headroom = 1 1179 } else { 1180 if rc != 0 { rd_w("BUILDFAIL\",\"rc\":" as *u8); rd_n(rc); rd_w("}" as *u8); failed = failed + 1 } else { 1181 if fs < 0 { rd_w("BUILDFAIL-NO-ARTIFACT\"}" as *u8); failed = failed + 1 } else { 1182 // ONE RULER: the count now comes from nx_contentdiff itself, so the drain 1183 // decides on the SAME number /api/promote's guard was calibrated against. 1184 // THE RULER SPEAKS BEFORE THE SIZE SCREEN (2026-08-18). The stub trap below 1185 // ("fresh under HALF the deployed size is a wrong-source signal") used to fire 1186 // FIRST and alone, so the content ruler never got to vouch for a small build. 1187 // Then nx_cc gained whole-program DCE and every honest rebuild became 24-72% 1188 // smaller: MEASURED on the live beat -- 11 of 16 slots per round went to 1189 // REFUSED-AMBIGUOUS-STUB-SOURCE for binaries that had lost NOTHING, the drain 1190 // tapered from 12 installs a round to 0-2, and the same 11 rows re-occupied 1191 // the head of every regenerated list. A stub source (main returns 0) is still 1192 // refused: it loses every printable run, so lostr>0 and the trap fires as 1193 // before -- but now on EVIDENCE, and an unverifiable ruler (-1) refuses too. 1194 // Same shape as the promote guard's SHRINK fix the same day: size alone 1195 // escalates only when the ruler could not vouch. 1196 let lostr: i64 = rd_cdiff_lost(name, dep, fresh, 0) 1197 var stubref: i64 = 0 1198 if fs * RD_STUB_NUM < ds { if lostr != 0 { stubref = 1 } } 1199 if stubref == 1 { 1200 rd_w("REFUSED-AMBIGUOUS-STUB-SOURCE\",\"lost_runs\":" as *u8); rd_n(lostr) 1201 rd_w(",\"fresh\":" as *u8); rd_n(fs) 1202 rd_w(",\"deployed\":" as *u8); rd_n(ds); rd_w("}" as *u8) 1203 refused = refused + 1 1204 } else { 1205 // The OTHER half of the evidence: what the fresh build adds. A rename shows 1206 // as a small loss beside a large gain; a true regression does not. 1207 var gained: i64 = 0 1208 if lostr > 0 { gained = rd_cdiff_lost(name, fresh, dep, 0) } 1209 var block: i64 = 0 1210 if lostr < 0 { block = 1 } 1211 if lostr >= RD_LOSS_REGRESSION_RUNS { block = 1 } 1212 if block == 0 { if lostr > 0 { 1213 // Below the measured regression floor: PROCEED, but never silently. 1214 rd_cdiff_lost(name, dep, fresh, 1) 1215 } } 1216 if block == 1 { 1217 // Capability the deployed binary can express and the fresh one cannot. 1218 // -1 means we could not read one of them: refuse that too, because a 1219 // guard that cannot answer must not wave things through. 1220 if lostr < 0 { rd_w("REFUSED-UNVERIFIABLE-CONTENT\",\"fresh\":" as *u8) } else { rd_w("REFUSED-CONTENT-LOSS\",\"lost_runs\":" as *u8) } 1221 if lostr > 0 { rd_n(lostr); rd_w(",\"gained_runs\":" as *u8); rd_n(gained); rd_w(",\"fresh\":" as *u8) } 1222 rd_n(fs); rd_w(",\"deployed\":" as *u8); rd_n(ds) 1223 // Name them, so the refusal is adjudicable instead of merely counted. 1224 if lostr > 0 { rd_cdiff_lost(name, dep, fresh, 1); rd_w(",\"named_in\":\"" as *u8); rd_w(RD_LOSSLOG); rd_w("\"" as *u8) } 1225 rd_w("}" as *u8) 1226 refusedc = refusedc + 1 1227 } else { 1228 if rd_same(fresh, dep) == 1 { 1229 rd_w("ALREADY-CURRENT\",\"bytes\":" as *u8); rd_n(fs); rd_w("}" as *u8) 1230 nochange = nochange + 1 1231 } else { 1232 // ★★★KEEP A WAY BACK BEFORE YOU NEED ONE. The first real drain installed 9 1233 // binaries that had SHRUNK 24-42%; the 50% stub ratio passed them and only 1234 // post-hoc probing proved they were sound. They were -- but that was LUCK, 1235 // and luck is not a guard. Rename is atomic and therefore IRREVERSIBLE: the 1236 // previous inode has no name left and cannot be rebuilt, because it came 1237 // from an older toolchain that no longer exists. So snapshot the deployed 1238 // elf to .prev FIRST; if the snapshot cannot be taken, DO NOT INSTALL. 1239 // Rule 26's shape applied to software: reversible BY CONSTRUCTION, never by 1240 // the hope that the new artifact is fine. 1241 var pv: i64 = rd_cpy(prevn, dep) 1242 pv = rd_cat(prevn, pv, ".prev" as *u8) 1243 if rd_copy(dep, prevn) == 0 { rd_w("REFUSED-NO-ROLLBACK-SNAPSHOT\"}" as *u8); failed = failed + 1 } else { 1244 var t: i64 = rd_cpy(tmpn, dep) 1245 t = rd_cat(tmpn, t, ".new" as *u8) 1246 if rd_copy(fresh, tmpn) == 0 { rd_w("COPYFAIL\"}" as *u8); failed = failed + 1 } else { 1247 nx_chmod(tmpn, 493) 1248 if sys_renameat(tmpn, dep) != 0 { 1249 rd_w("RENAMEFAIL\"}" as *u8); failed = failed + 1 1250 } else { 1251 rd_w("INSTALLED\",\"was\":" as *u8); rd_n(ds) 1252 rd_w(",\"now\":" as *u8); rd_n(rd_size(dep)) 1253 rd_w(",\"rollback\":\"" as *u8); rd_w(prevn); rd_w("\"}" as *u8) 1254 installed = installed + 1 1255 rd_install_log(name, ds, fs, prevn) 1256 } 1257 } 1258 } 1259 } 1260 } 1261 } 1262 } 1263 } 1264 } 1265 } 1266 } 1267 } 1268 } 1269 } 1270 if stopped_headroom == 1 { i = ln } else { i = le + 1 } 1271 } 1272 } 1273 rd_w("],\"attempted\":" as *u8); rd_n(done) 1274 rd_w(",\"installed\":" as *u8); rd_n(installed) 1275 rd_w(",\"already_current\":" as *u8); rd_n(nochange) 1276 rd_w(",\"refused_stub_source\":" as *u8); rd_n(refused) 1277 rd_w(",\"refused_content_loss\":" as *u8); rd_n(refusedc) 1278 rd_w(",\"not_a_program\":" as *u8); rd_n(notprog) 1279 rd_w(",\"failed\":" as *u8); rd_n(failed) 1280 rd_w(",\"skipped_no_deployed_elf\":" as *u8); rd_n(skipped_no_elf) 1281 rd_w(",\"buildfail\":" as *u8); rd_n(failed - skipped_no_elf) 1282 rd_w(",\"batch\":" as *u8); rd_n(batch) 1283 rd_w(",\"examined\":" as *u8); rd_n(examined) 1284 rd_w(",\"partition_reconciles\":" as *u8) 1285 // 🔴FIXED 2026-08-17, AND MY OWN CHECK IS WHAT CAUGHT IT. This read `+ failed`, which DOUBLE-COUNTS: 1286 // a BUILDFAIL row already spent a build slot, so it is inside `done`. It reconciled in every earlier 1287 // test only because those runs contained no real build failures -- the first run that hit two 1288 // printed `partition_reconciles:0` and named the defect for me. 1289 // ★★★★★★`failed` IS A BUCKET NAMED FOR HOW THE READER FAILED, HOLDING TWO FACTS WITH OPPOSITE SLOT 1290 // ACCOUNTING: SKIP-NO-DEPLOYED-ELF spends NO slot, BUILDFAIL spends one. Only the no-elf class is an 1291 // addend here. ★A PARTITION CHECK EARNS ITS KEEP THE FIRST TIME THE POPULATION CHANGES SHAPE. 1292 if examined == done + notprog + livedefer + portdefer + skipped_no_elf { rd_n(1) } else { rd_n(0) } 1293 rd_w(",\"deferred_live_service\":" as *u8); rd_n(livedefer) 1294 rd_w(",\"deferred_declared_daemon\":" as *u8); rd_n(portdefer) 1295 rd_w(",\"stopped_for_headroom\":" as *u8); rd_n(stopped_headroom) 1296 rd_w(",\"note\":\"IDEMPOTENT: re-run to continue draining -- regenerate the list with `nx_rebuild_plan list` first, since installing changes who is stale. VERIFY BY RE-RUNNING THE CENSUS, not by trusting this summary.\"}\n" as *u8) 1297 // ★★★★★★A BEAT THAT LEAVES NO TREND IS INDISTINGUISHABLE FROM ONE THAT NEVER FIRED. The summary 1298 // above goes to a job artifact nobody keeps; unattended firings need a DURABLE series or the only 1299 // answerable question is "did it run just now", never "is the backlog shrinking". 1300 // The load-bearing column is `backlog` -- the row count of the list the beat REGENERATED this 1301 // firing. A LEVEL CANNOT EXPRESS PROGRESS: one row says nothing, two rows say whether the drain is 1302 // outpacing the staleness that shared runtimes keep creating. Append-only, one line per firing. 1303 // ⚠Written only for the `beat` VERB -- but the verb is typeable by hand, so the row carries `src=` 1304 // to say which. This comment previously claimed the two could not mix; they did, on the same day. 1305 if is_beat == 1 { rd_trend(total_rows, done, installed, notprog, failed, beat_src, sys_now_realtime_sec() - t_start, portdefer, livedefer, nochange, stopped_headroom) } 1306 return 0 1307}