code wiki / _hdl_build / nx_tcratchet_lib.nx

nx_tcratchet_lib.nx source

↩ module page · 90 lines · 3771 B

1// nx_tcratchet_lib.nx -- TOOLCHAIN RATCHET: refuse a toolchain artifact that SHRANK against its banked size. 2// 3// WHY (the incident this exists for, measured 2026-07-30, debt 1785440455): buildroot/_offc/nx_cc_sovereign.elf 4// was found LIVE at 520,103 bytes when the known-good build is 543,126 -- a compiler whose optimiser was 5// 11,712 SOURCE-bytes short. **THE HUB WAS COMPILING EVERY ORGAN WITH A REGRESSED COMPILER**, which is why its 6// .s output came out 16,430 bytes larger than the laptop's from identical sources. Nobody knowingly promoted it. 7// 8// WHY THE EXISTING CANARY DID NOT CATCH IT, stated in that debt: nx_tc_canary proves a compiler is CORRECT 9// (8 checks that must RUN), NOT that it optimises well. **A WORSE-BUT-CORRECT COMPILER PASSES IT BY DESIGN.** 10// Correctness and quality are different axes and a gate on one says nothing about the other. 11// 12// THE RULE: a toolchain artifact that SHRINKS is REFUSED until a human re-banks deliberately. This is the 13// ecosystem's own banked law -- 'a byte-count DECREASE after an addition is a REVERT' -- mechanised at the one 14// place where being wrong corrupts every binary the ecosystem produces. 15// 16// ⚠IT WITHHOLDS, IT DOES NOT DIAGNOSE. A legitimate shrinking refactor lands here too (nx_capaxes went 17// 20177->16243 when its selftest moved out, correctly). That is why the verdict is REFUSE-PENDING-REBANK and 18// not 'corrupt': the remedy is an explicit re-bank, so an intentional shrink costs one deliberate act and an 19// accidental one cannot pass silently. Same stance nx_stale_check takes on DEPLOYED-AHEAD. 20// 21// FAIL-CLOSED: an UNBANKED artifact returns its own verdict, never OK. A ratchet that cannot compare must 22// refuse to bless -- a guard that waves through what it cannot measure is not a guard. 23// license_tier: ORIGINAL No hw writes (Rule 26). 24import "nx_syscalls.nx" 25 26const TCR_OK: i64 = 0 27const TCR_REGRESSED: i64 = 1 28const TCR_UNBANKED: i64 = 2 29const TCR_MISSING: i64 = 3 30// Zero tolerance by default: 1000 permil of banked = the artifact may not shrink by even one byte. 31// argv-overridable so a lane can declare a deliberate allowance, never buried (rule 11). 32const TCR_FLOOR_PERMIL: i64 = 1000 33 34// live = size of the artifact on disk now (<=0 means absent/unreadable) 35// banked= the recorded known-good size (<=0 means never banked) 36func tcr_verdict(live: i64, banked: i64, floor_permil: i64) -> i64 { 37 if banked <= 0 { return TCR_UNBANKED } 38 if live <= 0 { return TCR_MISSING } 39 if live * 1000 < banked * floor_permil { return TCR_REGRESSED } 40 return TCR_OK 41} 42 43func tcr_name(v: i64) -> *u8 { 44 if v == TCR_OK { return "OK" as *u8 } 45 if v == TCR_REGRESSED { return "REGRESSED-REFUSE-PENDING-REBANK" as *u8 } 46 if v == TCR_UNBANKED { return "UNBANKED-CANNOT-JUDGE" as *u8 } 47 if v == TCR_MISSING { return "MISSING-ARTIFACT" as *u8 } 48 return "UNKNOWN" as *u8 49} 50 51// Size of a file, or 0-1 if unreadable. Uses the same read path every organ here uses. 52func tcr_size(path: *u8) -> i64 { 53 let ln: *i64 = sys_mmap(16) as *i64 54 ln[0] = 0 55 let b: *u8 = sys_read_file(path, ln) 56 if b as i64 == 0 { return 0 - 1 } 57 return ln[0] 58} 59 60func tcr_puts(s: *u8) { 61 var n: i64 = 0 62 while s[n] != (0 as u8) { n = n + 1 } 63 sys_write(1, s, n) 64} 65 66func tcr_puti(x: i64) { 67 var buf: *u8 = sys_mmap(64) as *u8 68 var v: i64 = x 69 var neg: i64 = 0 70 if v < 0 { 71 neg = 1 72 v = 0 - v 73 } 74 var i: i64 = 40 75 if v == 0 { 76 i = i - 1 77 buf[i] = 48 as u8 78 } 79 while v > 0 { 80 let d: i64 = v - (v / 10) * 10 81 i = i - 1 82 buf[i] = (d + 48) as u8 83 v = v / 10 84 } 85 if neg == 1 { 86 i = i - 1 87 buf[i] = 45 as u8 88 } 89 sys_write(1, ((buf as i64) + i) as *u8, 40 - i) 90}