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}