code wiki / _hdl_build / nx_bless_compiler.nx

nx_bless_compiler.nx source

↩ module page · 297 lines · 14216 B

1// nx_bless_compiler.nx -- TEAM-OWNED self-deploy for the sovereign compiler 2// (GAME arc G2, operator: "keep building the team to handle this 3// autonomously"). The whole win-win-win update gate from 4// [[project-pm-plan-maintainer-winwinwin-2026-06-05]] mechanized: 5// 6// 1. BUILD the candidate SOVEREIGNLY: current _offc compiler compiles 7// runtime/nx_compile_x86.nx (retry-guarded), nxasm_x86_main assembles. 8// nxasm crash/refusal -> REFUSE "BLOCKED-BY-G1" (today's state: the 9// 2.4MB-.s capacity segfault). NO gcc anywhere on this path. 10// 2. MEASURE: nx_game_gate runs twice -- candidate vs live _offc. 11// Verdict is DATA (fails counts), not opinion. 12// 3. BLESS only if candidate is STRICTLY better (fewer fails). The live 13// compiler is backed up to _offc/nx_cc_sovereign.elf.bak first. 14// 4. POST-VERIFY: gate the freshly blessed _offc; if it does not match the 15// candidate's measurement, ROLL BACK from the .bak and re-verify. 16// 5. The gate-loop daemon is STOPPED before measuring and RESTARTED after 17// (two concurrent gates corrupt each other's /tmp artifacts -- learned 18// live 2026-06-09). 19// 20// Exit: 0 blessed+verified, 1 refused (candidate not better), 2 blocked at 21// build (G1), 3 rolled back (post-verify mismatch), 4 internal error. 22// license_tier: ORIGINAL 23import "nx_pm_review_log.nx" 24import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 25import "nx_syscalls.nx" 26const BC_MAGIC_65536: i64 = 65536 27const BC_MAGIC_4095: i64 = 4095 28const BC_MAGIC_4096: i64 = 4096 29 30const BC_MIN_ASM_BYTES: i64 = 128 31const BC_MAX_RETRIES: i64 = 12 32 33func bc_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 34// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 35// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 36// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 37// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 38func bc_putn(v: i64) -> i64 { nxi_out(v); return 0 } 39func bc_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } return off + i } 40func bc_cat_n(dst: *u8, off: i64, v: i64) -> i64 { 41 var o: i64 = off 42 var m: i64 = v 43 if m < 0 { dst[o] = 45; o = o + 1; m = 0 - m } 44 let t: *u8 = sys_mmap(28) 45 var k: i64 = 0 46 if m == 0 { t[0] = 48; k = 1 } 47 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 48 var i: i64 = 0 49 while i < k { dst[o+i] = t[k-1-i]; i = i + 1 } 50 return o + k 51} 52 53func bc_run(path: *u8, argv: *i64, envp: *i64, redir_out: i64, redir_err: i64) -> i64 { 54 let pid: i64 = sys_fork() 55 if pid == 0 { 56 if redir_out >= 0 { sys_dup3(redir_out, 1, 0) } 57 if redir_err >= 0 { sys_dup3(redir_err, 2, 0) } 58 sys_execve(path, argv, envp) 59 sys_exit(127) 60 } 61 let st: *i64 = sys_mmap(16) as *i64 62 sys_wait4(pid, st, 0) 63 let sig: i64 = st[0] & 0x7f 64 if sig != 0 { return 128 + sig } 65 return (st[0] >> 8) & 0xff 66} 67 68func bc_run1(path: *u8, arg1: *u8, envp: *i64, devnull: i64) -> i64 { 69 let argv: *i64 = sys_mmap(32) as *i64 70 argv[0] = path as i64; argv[1] = arg1 as i64; argv[2] = 0 71 return bc_run(path, argv, envp, devnull, devnull) 72} 73 74func bc_filesize(path: *u8) -> i64 { 75 let fd: i64 = sys_openat_rd(path) 76 if fd < 0 { return 0 - 1 } 77 let buf: *u8 = sys_mmap(BC_MAGIC_65536) 78 var total: i64 = 0 79 var n: i64 = sys_read(fd, buf, BC_MAGIC_65536) 80 while n > 0 { total = total + n; n = sys_read(fd, buf, BC_MAGIC_65536) } 81 sys_close(fd) 82 return total 83} 84 85// copy src -> dst with mode 0755 (the dst is an executable tool) 86func bc_copy(src: *u8, dst: *u8) -> i64 { 87 let in_fd: i64 = sys_openat_rd(src) 88 if in_fd < 0 { return 0 - 1 } 89 let out_fd: i64 = sys_openat_wr(dst, 0x1ed) 90 if out_fd < 0 { sys_close(in_fd); return 0 - 1 } 91 let buf: *u8 = sys_mmap(BC_MAGIC_65536) 92 var n: i64 = sys_read(in_fd, buf, BC_MAGIC_65536) 93 while n > 0 { 94 sys_write(out_fd, buf, n) 95 n = sys_read(in_fd, buf, BC_MAGIC_65536) 96 } 97 sys_close(in_fd) 98 sys_close(out_fd) 99 return 0 100} 101 102func bc_read_pidfile(path: *u8) -> i64 { 103 let len_p: *i64 = sys_mmap(8) as *i64 104 let buf: *u8 = sys_read_file(path, len_p) 105 if (buf as i64) == 0 { return 0 - 1 } 106 let n: i64 = len_p[0] 107 var v: i64 = 0 108 var any: i64 = 0 109 var i: i64 = 0 110 while i < n { 111 let c: i64 = buf[i] as i64 112 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1 } } 113 i = i + 1 114 } 115 if any == 0 { return 0 - 1 } 116 return v 117} 118 119// substring search in buf[0,n) 120func bc_substr(buf: *u8, n: i64, needle: *u8) -> i64 { 121 var nl: i64 = 0 122 while needle[nl] != (0 as u8) { nl = nl + 1 } 123 if nl == 0 { return 1 } 124 var i: i64 = 0 125 while i + nl <= n { 126 var k: i64 = 0 127 var ok: i64 = 1 128 while k < nl { if buf[i+k] != needle[k] { ok = 0; k = nl } else { k = k + 1 } } 129 if ok == 1 { return 1 } 130 i = i + 1 131 } 132 return 0 133} 134 135// 1 iff the LAST line of knowledge/status/cc_equiv_gate.log carries selfhost=1 + verdict=GREEN 136// (the most recent cc_equiv run's summary). Used as the pre-deploy guard's verdict reader. 137func bc_equiv_green() -> i64 { 138 let fd: i64 = sys_openat_rd("knowledge/status/cc_equiv_gate.log" as *u8) 139 if fd < 0 { return 0 } 140 let sz: i64 = sys_lseek(fd, 0, 2) 141 var off: i64 = 0 142 if sz > BC_MAGIC_4095 { off = sz - BC_MAGIC_4095 } 143 sys_lseek(fd, off, 0) 144 let buf: *u8 = sys_mmap(BC_MAGIC_4096) 145 var n: i64 = 0 146 var r: i64 = sys_read(fd, buf, BC_MAGIC_4095) 147 while r > 0 { n = n + r; if n >= BC_MAGIC_4095 { r = 0 } else { r = sys_read(fd, buf + n, BC_MAGIC_4095 - n) } } 148 sys_close(fd) 149 var s: i64 = n 150 if s > 0 { if buf[s-1] == (10 as u8) { s = s - 1 } } 151 var ls: i64 = s 152 while ls > 0 { if buf[ls-1] == (10 as u8) { ls = 0 - ls } else { ls = ls - 1 } } 153 if ls < 0 { ls = 0 - ls } 154 let len: i64 = s - ls 155 if len <= 0 { return 0 } 156 if bc_substr(buf + ls, len, "selfhost=1" as *u8) == 1 { if bc_substr(buf + ls, len, "verdict=GREEN" as *u8) == 1 { return 1 } } 157 return 0 158} 159 160func main(argc: i64, argv: *i64) -> i64 { 161 // NEUTRAL mode (opt-in, argv[1]=="NEUTRAL"): bless a behavior-NEUTRAL capability fix (e.g. the 162 // flock syscall-map fix, X-SYSXLATE-FLOCK) on NO-REGRESSION (b_fails <= a_fails) instead of the 163 // default STRICTLY-better (b_fails < a_fails). Default (no arg) is UNCHANGED so the daemon's 164 // automatic bless still requires a genuine improvement. 165 var allow_equal: i64 = 0 166 if argc >= 2 { 167 let av: *u8 = argv[1] as *u8 168 if av[0] == (78 as u8) { if av[1] == (69 as u8) { if av[2] == (85 as u8) { allow_equal = 1 } } } 169 } 170 let envp: *i64 = sys_mmap(8*4) as *i64 171 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 172 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 173 let live: *u8 = "_offc/nx_cc_sovereign.elf" as *u8 174 let bak: *u8 = "_offc/nx_cc_sovereign.elf.bak" as *u8 175 let cand_s: *u8 = "/tmp/nx_cc_candidate.s" as *u8 176 let cand: *u8 = "/tmp/nx_cc_candidate.elf" as *u8 177 let gate: *u8 = "/tmp/nx_game_gate.sov.elf" as *u8 178 179 // ---- 1. sovereign build of the candidate ---- 180 bc_puts("[bless] building candidate: " as *u8); bc_puts(live); bc_puts(" -> nx_compile_x86.nx -> nxasm\n" as *u8) 181 var asmbytes: i64 = 0 182 var tries: i64 = 0 183 while tries < BC_MAX_RETRIES { 184 let sfd: i64 = sys_openat_wr(cand_s, 0x1a4) 185 let cc: *i64 = sys_mmap(8*4) as *i64 186 cc[0] = live as i64; cc[1] = "runtime/nx_compile_x86.nx" as *u8 as i64; cc[2] = 0 187 let rc_c: i64 = bc_run(live, cc, envp, sfd, devnull) 188 sys_close(sfd) 189 asmbytes = bc_filesize(cand_s) 190 if rc_c == 0 { if asmbytes > BC_MIN_ASM_BYTES { tries = BC_MAX_RETRIES } } 191 if tries != BC_MAX_RETRIES { tries = tries + 1 } 192 } 193 if asmbytes <= BC_MIN_ASM_BYTES { 194 bc_puts("[bless] REFUSED: candidate compile produced no usable .s\n" as *u8) 195 return 2 196 } 197 let asm_tool: *u8 = "_offc/nxasm_x86_main.elf" as *u8 198 let aa: *i64 = sys_mmap(8*4) as *i64 199 aa[0] = asm_tool as i64; aa[1] = cand_s as i64; aa[2] = cand as i64; aa[3] = 0 200 let rc_a: i64 = bc_run(asm_tool, aa, envp, devnull, devnull) 201 if rc_a != 0 { 202 bc_puts("[bless] REFUSED: BLOCKED-BY-G1 -- nxasm rc=" as *u8); bc_putn(rc_a) 203 bc_puts(" on the " as *u8); bc_putn(asmbytes) 204 bc_puts("B candidate .s (capacity bug; see GAME arc G1). _offc UNTOUCHED.\n" as *u8) 205 let pm: i64 = pm_open("/tmp/nishi_pm_review.log" as *u8) 206 pm_gap(pm, "toolchain/x86" as *u8, "BLOCKED" as *u8, "compiler self-deploy blocked by G1" as *u8, "nx_bless_compiler: candidate .s built fine but nxasm failed (capacity/encoding); the parser-fixed compiler still cannot be sovereignly blessed; fix GAME-G1 then re-run nx_bless_compiler" as *u8) 207 sys_close(pm) 208 return 2 209 } 210 211 // ---- 1b. pause the gate-loop daemon (concurrent gates corrupt artifacts) ---- 212 let loop_pid: i64 = bc_read_pidfile("/tmp/nishi_game_gate_loop.pid" as *u8) 213 if loop_pid > 0 { 214 nx_kill(loop_pid, 15) 215 bc_puts("[bless] paused gate-loop daemon pid=" as *u8); bc_putn(loop_pid); bc_puts("\n" as *u8) 216 } 217 218 // ---- 2. measure: candidate vs live ---- 219 let b_fails: i64 = bc_run1(gate, cand, envp, devnull) 220 let a_fails: i64 = bc_run1(gate, 0 as *u8, envp, devnull) 221 bc_puts("[bless] gate: candidate fails=" as *u8); bc_putn(b_fails) 222 bc_puts(" live fails=" as *u8); bc_putn(a_fails); bc_puts("\n" as *u8) 223 224 var verdict: i64 = 4 225 var should_bless: i64 = 0 226 if b_fails < a_fails { should_bless = 1 } 227 if allow_equal == 1 { if b_fails == a_fails { should_bless = 1 } } 228 if allow_equal == 1 { bc_puts("[bless] NEUTRAL mode: blessing on NO-REGRESSION (b_fails <= a_fails)\n" as *u8) } 229 if should_bless == 1 { 230 // ---- 2b. PRE-DEPLOY EQUIV GUARD (runs ONLY when a bless is imminent, so it never slows a 231 // refused attempt): the candidate must be byte-behavior-equivalent to the baseline on the 232 // corpus AND self-host -- this catches the deref-cast / gen3 regression CLASS that 233 // nx_game_gate cannot. Point the equiv-gate's default challenger (/tmp/cc_challenger.elf) at 234 // our candidate, run it, require GREEN; a RED REFUSES the bless so a regressing compiler can 235 // never go live. (Folds in nx_cc_promote's equiv validation -> nx_cc_promote can retire.) ---- 236 bc_copy(cand, "/tmp/cc_challenger.elf" as *u8) 237 let eg: *i64 = sys_mmap(8*4) as *i64 238 eg[0] = "./_offc/nx_sov_build_run.elf" as *u8 as i64 239 eg[1] = "nx_cc_equiv_gate" as *u8 as i64 240 eg[2] = 0 241 bc_run("./_offc/nx_sov_build_run.elf" as *u8, eg, envp, devnull, devnull) 242 let eq_green: i64 = bc_equiv_green() 243 bc_puts("[bless] cc_equiv guard (corpus+self-host) green=" as *u8); bc_putn(eq_green); bc_puts("\n" as *u8) 244 if eq_green == 0 { 245 bc_puts("[bless] REFUSED: cc_equiv NOT GREEN -- deref-cast/gen3 guard; _offc UNTOUCHED\n" as *u8) 246 let pmq: i64 = pm_open("/tmp/nishi_pm_review.log" as *u8) 247 pm_gap(pmq, "toolchain/x86" as *u8, "BLOCKED" as *u8, "bless equiv-guard RED" as *u8, "nx_bless_compiler: candidate failed nx_cc_equiv_gate (corpus/self-host differential) -> refused to bless; investigate the compiler-source regression before re-bless" as *u8) 248 sys_close(pmq) 249 verdict = 2 250 } 251 if eq_green == 1 { 252 // ---- 3. bless with backup ---- 253 let rc_bak: i64 = bc_copy(live, bak) 254 if rc_bak < 0 { bc_puts("[bless] ERROR: backup copy failed; ABORT (no bless)\n" as *u8); verdict = 4 } 255 if rc_bak >= 0 { 256 let rc_bls: i64 = bc_copy(cand, live) 257 if rc_bls < 0 { bc_puts("[bless] ERROR: bless copy failed\n" as *u8); verdict = 4 } 258 if rc_bls >= 0 { 259 // ---- 4. post-verify the blessed live tool ---- 260 let c_fails: i64 = bc_run1(gate, 0 as *u8, envp, devnull) 261 bc_puts("[bless] post-verify: blessed-live fails=" as *u8); bc_putn(c_fails) 262 bc_puts(" (need ==" as *u8); bc_putn(b_fails); bc_puts(")\n" as *u8) 263 if c_fails == b_fails { 264 bc_puts("[bless] BLESSED + VERIFIED\n" as *u8) 265 let pm2: i64 = pm_open("/tmp/nishi_pm_review.log" as *u8) 266 pm_deliverable(pm2, "toolchain/x86" as *u8, "compiler-blessed" as *u8, "nx_bless_compiler: candidate gated strictly better than live, blessed to _offc/nx_cc_sovereign.elf (backup at .bak), post-verify matched; GAME-G2 satisfied by the team" as *u8) 267 sys_close(pm2) 268 verdict = 0 269 } 270 if c_fails != b_fails { 271 bc_copy(bak, live) 272 let r_fails: i64 = bc_run1(gate, 0 as *u8, envp, devnull) 273 bc_puts("[bless] POST-VERIFY MISMATCH -> ROLLED BACK; live fails now=" as *u8); bc_putn(r_fails); bc_puts("\n" as *u8) 274 let pm3: i64 = pm_open("/tmp/nishi_pm_review.log" as *u8) 275 pm_gap(pm3, "toolchain/x86" as *u8, "NEEDS-FIX" as *u8, "bless post-verify mismatch" as *u8, "nx_bless_compiler: blessed tool gated differently than the candidate binary (nondeterminism or copy fault); ROLLED BACK from .bak; investigate before re-bless" as *u8) 276 sys_close(pm3) 277 verdict = 3 278 } 279 } 280 } 281 } 282 } 283 if should_bless == 0 { 284 bc_puts("[bless] REFUSED: candidate not better (neutral mode allows ==); _offc UNTOUCHED\n" as *u8) 285 verdict = 1 286 } 287 288 // ---- 5. restart the gate-loop daemon ---- 289 let loop_elf: *u8 = "/tmp/nx_gate_loop.sov.elf" as *u8 290 let chk: i64 = sys_openat_rd(loop_elf) 291 if chk >= 0 { 292 sys_close(chk) 293 bc_run1(loop_elf, 0 as *u8, envp, devnull) 294 bc_puts("[bless] gate-loop daemon restarted\n" as *u8) 295 } 296 return verdict 297}