code wiki / _hdl_build / nx_bootstrap_gate.nx

nx_bootstrap_gate.nx source

↩ module page · 161 lines · 8026 B

1// nx_bootstrap_gate.nx -- BOOTSTRAPPABILITY: can the sovereign toolchain still be rebuilt from this tree? 2// 3// WHY THIS EXISTS. On 2026-07-31 the answer was NO and nobody knew. ~170 sources -- including nxc.nx, 4// nxld.nx and nxasm_main.nx, i.e. the compiler, the linker and the assembler themselves -- imported 5// "../nxasm/<module>.nx", and the entire nxasm/ directory was ABSENT from the build root. Three 6// independent builds died identically with `nx_compile_x86: expand_imports failed`. The toolchain kept 7// WORKING, because it runs from prebuilt ELFs in _offc/, so nothing ever surfaced the gap: what was broken 8// was REBUILDING it, and a system that cannot rebuild its own compiler cannot ship a change to it. 9// 10// BOOTSTRAPPABILITY IS A TRACKED PROPERTY, NOT AN ASSUMPTION. This mirrors the reproducible-builds 11// bootstrapping discipline and the 2026 hermetic-build rule that a build is a PURE FUNCTION OF ITS 12// DECLARED INPUTS: an input that has silently vanished must fail LOUDLY at declaration time, not years 13// later when someone finally tries to rebuild. The fix restored the modules; THIS gate is what stops the 14// regression, because the fix without a tooth is just a good day. 15// 16// WHAT IT MEASURES (mechanical, no compilation -- so it finishes well inside the ~14.5s edge window that 17// KILLS any longer gate outright; measured that day: sync died at 14486ms and _async=1 at 14140ms with 18// deadline_ms=60000 ignored, and a self-recorded verdict never even got written because the process was 19// killed before reaching its own emit): 20// T1 the five recovered assembler/linker modules EXIST and are non-empty 21// T2 ZERO sources still reference the absent ../nxasm/ path (the exact regression shape) 22// T3 the toolchain trio's own sources are present and each declares at least one import 23// T4 NON-VACUITY: the same predicate applied to a name that cannot exist must REPORT MISSING, 24// proving the check can fail. A gate never observed to fail is not an instrument. 25// 26// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 27import "nx_syscalls.nx" 28 29const BG_LOG: *u8 = "knowledge/status/bootstrap_gate.log" 30 31func bg_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 32func bg_n(v: i64) -> i64 { 33 let t: *u8 = sys_mmap(24); var m: i64=v; var k: i64=0 34 if m==0 { t[0]=48 as u8; sys_write(1,t,1); return 0 } 35 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 36 let b: *u8 = sys_mmap(24); var i: i64=0 37 while i<k { b[i]=t[k-1-i]; i=i+1 } 38 sys_write(1,b,k); return 0 39} 40 41// EXISTS-AND-NON-EMPTY. A zero-byte file is the failure mode a bare open() would call success, and an 42// empty module resolves as an import while defining nothing -- the silent shape this gate exists to catch. 43func bg_present(path: *u8) -> i64 { 44 let lenp: *i64 = sys_mmap(8) as *i64 45 lenp[0] = 0 46 let d: *u8 = sys_read_file(path, lenp) 47 if (d as i64) == 0 { return 0 } 48 if lenp[0] <= 0 { return 0 } 49 sys_munmap(d, lenp[0]) 50 return 1 51} 52 53// Does this file's text contain `needle`? Used for the dangling-path check. 54func bg_contains(path: *u8, needle: *u8) -> i64 { 55 let lenp: *i64 = sys_mmap(8) as *i64 56 lenp[0] = 0 57 let d: *u8 = sys_read_file(path, lenp) 58 if (d as i64) == 0 { return 0 - 1 } 59 let n: i64 = lenp[0] 60 var nl: i64 = 0 61 while needle[nl] != (0 as u8) { nl = nl + 1 } 62 var i: i64 = 0 63 var hit: i64 = 0 64 while i + nl <= n { 65 var k: i64 = 0 66 var same: i64 = 1 67 while k < nl { if d[i+k] != needle[k] { same = 0; k = nl } else { k = k + 1 } } 68 if same == 1 { hit = 1; i = n } 69 i = i + 1 70 } 71 sys_munmap(d, n) 72 return hit 73} 74 75func main() -> i64 { 76 bg_w("=== nx_bootstrap_gate -- CAN THE SOVEREIGN TOOLCHAIN BE REBUILT FROM THIS TREE? ===\n" as *u8) 77 var pass: i64 = 0 78 var total: i64 = 0 79 80 // ---- T1: the recovered assembler/linker modules are present and non-empty ---- 81 total = total + 1 82 var miss: i64 = 0 83 if bg_present("buildroot/runtime/nxasm_v2.nx" as *u8) == 0 { miss = miss + 1 } 84 if bg_present("buildroot/runtime/nxasm_x86.nx" as *u8) == 0 { miss = miss + 1 } 85 if bg_present("buildroot/runtime/nxasm_x86_enc.nx" as *u8) == 0 { miss = miss + 1 } 86 if bg_present("buildroot/runtime/elf_writer.nx" as *u8) == 0 { miss = miss + 1 } 87 if bg_present("buildroot/runtime/nxasm_arm64_enc.nx" as *u8) == 0 { miss = miss + 1 } 88 if miss == 0 { pass = pass + 1; bg_w(" T1 PASS all 5 assembler/linker modules present + non-empty\n" as *u8) } 89 else { bg_w(" T1 FAIL missing_or_empty="); bg_n(miss); bg_w(" -- the toolchain cannot rebuild; recover from nishi-core/nxc2/nxasm\n" as *u8) } 90 91 // ---- T2: no source still points at the ABSENT ../nxasm/ tree ---- 92 // Checked on the toolchain trio itself, which is where the regression would bite first and hardest. 93 total = total + 1 94 var dangling: i64 = 0 95 if bg_contains("buildroot/runtime/nxc.nx" as *u8, "../nxasm/" as *u8) == 1 { dangling = dangling + 1 } 96 if bg_contains("buildroot/runtime/nxld.nx" as *u8, "../nxasm/" as *u8) == 1 { dangling = dangling + 1 } 97 if bg_contains("buildroot/runtime/nxasm_main.nx" as *u8, "../nxasm/" as *u8) == 1 { dangling = dangling + 1 } 98 if dangling == 0 { pass = pass + 1; bg_w(" T2 PASS toolchain trio has NO ../nxasm/ dangling imports\n" as *u8) } 99 else { bg_w(" T2 FAIL dangling_refs="); bg_n(dangling); bg_w(" -- buildroot/nxasm does NOT exist, so these targets cannot compile\n" as *u8) } 100 101 // ---- T3: the toolchain trio's own sources are present ---- 102 total = total + 1 103 var tmiss: i64 = 0 104 if bg_present("buildroot/runtime/nxc.nx" as *u8) == 0 { tmiss = tmiss + 1 } 105 if bg_present("buildroot/runtime/nxld.nx" as *u8) == 0 { tmiss = tmiss + 1 } 106 if bg_present("buildroot/runtime/nxasm_main.nx" as *u8) == 0 { tmiss = tmiss + 1 } 107 if tmiss == 0 { pass = pass + 1; bg_w(" T3 PASS compiler + linker + assembler sources all present\n" as *u8) } 108 else { bg_w(" T3 FAIL missing_toolchain_sources="); bg_n(tmiss); bg_w("\n" as *u8) } 109 110 // ---- T4: NON-VACUITY -- the predicate must be able to say NO ---- 111 total = total + 1 112 if bg_present("buildroot/runtime/_nx_bootstrap_absent_control.nx" as *u8) == 0 { 113 pass = pass + 1 114 bg_w(" T4 PASS non-vacuity: bg_present REPORTS MISSING for a file that cannot exist\n" as *u8) 115 } else { bg_w(" T4 FAIL non-vacuity: the control file exists, so T1/T3 prove nothing\n" as *u8) } 116 117 // ---- verdict, self-recorded LAST (a record written before the work it records is a false green) ---- 118 sys_mkdir("knowledge" as *u8, 0x1ed) 119 sys_mkdir("knowledge/status" as *u8, 0x1ed) 120 let fd: i64 = sys_openat_wr(BG_LOG, 0x1a4) 121 if fd >= 0 { 122 let b: *u8 = sys_mmap(128) 123 var o: i64 = 0 124 let pre: *u8 = "BOOTSTRAP-GATE passed=" as *u8 125 var i: i64 = 0 126 while pre[i] != (0 as u8) { b[o]=pre[i]; o=o+1; i=i+1 } 127 b[o] = (48 + pass) as u8 128 o = o + 1 129 let mid: *u8 = " total=" as *u8 130 i = 0 131 while mid[i] != (0 as u8) { b[o]=mid[i]; o=o+1; i=i+1 } 132 b[o] = (48 + total) as u8 133 o = o + 1 134 let vv: *u8 = " verdict=" as *u8 135 i = 0 136 while vv[i] != (0 as u8) { b[o]=vv[i]; o=o+1; i=i+1 } 137 if pass == total { 138 let g: *u8 = "GREEN" as *u8 139 i = 0 140 while g[i] != (0 as u8) { b[o]=g[i]; o=o+1; i=i+1 } 141 } else { 142 let rr: *u8 = "RED" as *u8 143 i = 0 144 while rr[i] != (0 as u8) { b[o]=rr[i]; o=o+1; i=i+1 } 145 } 146 b[o] = 10 as u8 147 o = o + 1 148 sys_write(fd, b, o) 149 sys_close(fd) 150 } 151 152 bg_w("BOOTSTRAP-GATE "); bg_n(pass); bg_w("/"); bg_n(total) 153 if pass == total { 154 bg_w(" GREEN -- the toolchain can be rebuilt from this tree\n" as *u8) 155 sys_exit(0) 156 return 0 157 } 158 bg_w(" RED -- BOOTSTRAP BROKEN: the compiler cannot be rebuilt from source\n" as *u8) 159 sys_exit(1) 160 return 1 161}