code wiki / _hdl_build / nx_gate_triage.nx

nx_gate_triage.nx source

↩ module page · 213 lines · 9314 B

1// nx_gate_triage.nx -- TEAM-OWNED failure LOCALIZER for the game gate 2// (operator: "keep building the team to handle this autonomously"). 3// Mechanizes the oracle-differential diagnosis ladder Claude ran by hand on 4// 2026-06-09 (the tictactoe draw-detect hunt): for every gated module, build 5// the SAME compiler-emitted .s twice -- once with the sovereign assembler, 6// once with gcc (ORACLE USE ONLY, per the C-is-for-benchmarking law; gcc 7// never lands on a deploy path here) -- run both, and classify: 8// 9// PASS : sovereign build exits 0 10// ASM-GAP : nxasm refuses the .s (encoding gap) or crashes 11// TOOLCHAIN-NXASM : sovereign build fails BUT gcc build of the SAME .s 12// passes -> the assembler mis-encoded something 13// COMPILER-OR-SOURCE : BOTH builds fail the same way -> the .s itself is 14// wrong (compiler bug) or the module's source is 15// COMPILE-FAIL : no usable .s after retries 16// 17// One TRIAGE line per module -> stdout + /tmp/nishi_game_gate_triage.log. 18// The sentinel forks this automatically on REGRESSION, so a red beat arrives 19// pre-localized: the Engineer reads WHERE the bug lives, not just that one 20// exists. Usage: nx_gate_triage.elf [compiler] (default _offc, repo root). 21// 22// license_tier: ORIGINAL Reuses the gg_ spine from nx_game_gate. 23import "nx_syscalls.nx" 24const GT_MAGIC_4096: i64 = 4096 25 26const GT_MIN_ASM_BYTES: i64 = 128 27const GT_MAX_RETRIES: i64 = 12 28 29func gt_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 } 30func gt_cat_n(dst: *u8, off: i64, v: i64) -> i64 { 31 var o: i64 = off 32 var m: i64 = v 33 if m < 0 { dst[o] = 45; o = o + 1; m = 0 - m } 34 let t: *u8 = sys_mmap(28) 35 var k: i64 = 0 36 if m == 0 { t[0] = 48; k = 1 } 37 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 38 var i: i64 = 0 39 while i < k { dst[o+i] = t[k-1-i]; i = i + 1 } 40 return o + k 41} 42 43func gt_run(path: *u8, argv: *i64, envp: *i64, redir_out: i64, redir_err: i64) -> i64 { 44 let pid: i64 = sys_fork() 45 if pid == 0 { 46 if redir_out >= 0 { sys_dup3(redir_out, 1, 0) } 47 if redir_err >= 0 { sys_dup3(redir_err, 2, 0) } 48 sys_execve(path, argv, envp) 49 sys_exit(127) 50 } 51 let st: *i64 = sys_mmap(16) as *i64 52 sys_wait4(pid, st, 0) 53 let sig: i64 = st[0] & 0x7f 54 if sig != 0 { return 128 + sig } 55 return (st[0] >> 8) & 0xff 56} 57 58func gt_filesize(path: *u8) -> i64 { 59 let fd: i64 = sys_openat_rd(path) 60 if fd < 0 { return 0 } 61 let buf: *u8 = sys_mmap(GT_MAGIC_4096) 62 var total: i64 = 0 63 var n: i64 = sys_read(fd, buf, GT_MAGIC_4096) 64 while n > 0 { total = total + n; n = sys_read(fd, buf, GT_MAGIC_4096) } 65 sys_close(fd) 66 return total 67} 68 69// Same module list as nx_game_gate (keep in sync; gate owns the canon). 70func gt_module(i: i64) -> *u8 { 71 if i == 0 { return "nx_term_kat" as *u8 } 72 if i == 1 { return "nx_tictactoe_test" as *u8 } 73 if i == 2 { return "nx_checkers_test" as *u8 } 74 if i == 3 { return "nx_raycast_voxel_test" as *u8 } 75 if i == 4 { return "nx_game_engine_compose_test" as *u8 } 76 if i == 5 { return "nx_game_runtime_compose_test" as *u8 } 77 if i == 6 { return "nx_fab_slice_test" as *u8 } 78 if i == 7 { return "nx_text_render_test" as *u8 } 79 if i == 8 { return "nx_html_render_test" as *u8 } 80 if i == 9 { return "nx_render_target_match_test" as *u8 } 81 if i == 10 { return "nx_perceptual_render_test" as *u8 } 82 if i == 11 { return "nx_pitwall_render_test" as *u8 } 83 if i == 12 { return "nx_math_games_test" as *u8 } 84 if i == 13 { return "nx_actor_role_game_logic_test" as *u8 } 85 if i == 14 { return "nx_user_sim_games" as *u8 } 86 if i == 15 { return "nx_worldgen_refine" as *u8 } 87 if i == 16 { return "nx_visual_novel_test" as *u8 } 88 return 0 as *u8 89} 90 91// classification codes 92const GT_PASS: i64 = 0 93const GT_ASM_GAP: i64 = 1 94const GT_TOOLCHAIN_NXASM: i64 = 2 95const GT_COMPILER_OR_SOURCE: i64 = 3 96const GT_COMPILE_FAIL: i64 = 4 97 98func gt_triage_one(name: *u8, compiler: *u8, envp: *i64, devnull: i64, sov_exit: *i64, ora_exit: *i64) -> i64 { 99 let src: *u8 = sys_mmap(512) 100 var o: i64 = 0 101 o = gt_cat(src, o, "runtime/_hdl_build/" as *u8); o = gt_cat(src, o, name); o = gt_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 102 let chk: i64 = sys_openat_rd(src) 103 if chk < 0 { 104 o = 0 105 o = gt_cat(src, o, "runtime/" as *u8); o = gt_cat(src, o, name); o = gt_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 106 } 107 if chk >= 0 { sys_close(chk) } 108 109 let spath: *u8 = sys_mmap(256); o = 0 110 o = gt_cat(spath, o, "/tmp/" as *u8); o = gt_cat(spath, o, name); o = gt_cat(spath, o, ".tri.s" as *u8); spath[o] = 0 as u8 111 let sovelf: *u8 = sys_mmap(256); o = 0 112 o = gt_cat(sovelf, o, "/tmp/" as *u8); o = gt_cat(sovelf, o, name); o = gt_cat(sovelf, o, ".tri.sov" as *u8); sovelf[o] = 0 as u8 113 let oraelf: *u8 = sys_mmap(256); o = 0 114 o = gt_cat(oraelf, o, "/tmp/" as *u8); o = gt_cat(oraelf, o, name); o = gt_cat(oraelf, o, ".tri.ora" as *u8); oraelf[o] = 0 as u8 115 116 // compile (retry guard) 117 var asmbytes: i64 = 0 118 var tries: i64 = 0 119 while tries < GT_MAX_RETRIES { 120 let sfd: i64 = sys_openat_wr(spath, 0x1a4) 121 let cc: *i64 = sys_mmap(8*4) as *i64 122 cc[0] = compiler as i64; cc[1] = src as i64; cc[2] = 0 123 let rc_c: i64 = gt_run(compiler, cc, envp, sfd, devnull) 124 sys_close(sfd) 125 asmbytes = gt_filesize(spath) 126 if rc_c == 0 { if asmbytes > GT_MIN_ASM_BYTES { tries = GT_MAX_RETRIES } } 127 if tries != GT_MAX_RETRIES { tries = tries + 1 } 128 } 129 if asmbytes <= GT_MIN_ASM_BYTES { return GT_COMPILE_FAIL } 130 131 // lane A: sovereign assembler 132 let asm_tool: *u8 = "_offc/nxasm_x86_main.elf" as *u8 133 let aa: *i64 = sys_mmap(8*4) as *i64 134 aa[0] = asm_tool as i64; aa[1] = spath as i64; aa[2] = sovelf as i64; aa[3] = 0 135 let rc_a: i64 = gt_run(asm_tool, aa, envp, devnull, devnull) 136 if rc_a != 0 { return GT_ASM_GAP } 137 let rr: *i64 = sys_mmap(8*4) as *i64 138 rr[0] = sovelf as i64; rr[1] = 0 139 let rc_sov: i64 = gt_run(sovelf, rr, envp, devnull, devnull) 140 sov_exit[0] = rc_sov 141 if rc_sov == 0 { return GT_PASS } 142 143 // lane B: gcc ORACLE of the SAME .s (diagnosis only, never a deploy path) 144 let gcc_path: *u8 = "/usr/bin/gcc" as *u8 145 let ga: *i64 = sys_mmap(8*8) as *i64 146 ga[0] = gcc_path as i64 147 ga[1] = "-no-pie" as *u8 as i64 148 ga[2] = "-nostartfiles" as *u8 as i64 149 ga[3] = "-o" as *u8 as i64 150 ga[4] = oraelf as i64 151 ga[5] = spath as i64 152 ga[6] = 0 153 let rc_g: i64 = gt_run(gcc_path, ga, envp, devnull, devnull) 154 if rc_g != 0 { return GT_COMPILER_OR_SOURCE } // .s gcc won't even assemble -> emitted asm broken 155 let rr2: *i64 = sys_mmap(8*4) as *i64 156 rr2[0] = oraelf as i64; rr2[1] = 0 157 let rc_ora: i64 = gt_run(oraelf, rr2, envp, devnull, devnull) 158 ora_exit[0] = rc_ora 159 if rc_ora == 0 { return GT_TOOLCHAIN_NXASM } 160 return GT_COMPILER_OR_SOURCE 161} 162 163func gt_report(logfd: i64, name: *u8, cls: i64, sov: i64, ora: i64, ts: i64) -> i64 { 164 let line: *u8 = sys_mmap(512) 165 var o: i64 = 0 166 o = gt_cat(line, o, "TRIAGE ts=" as *u8) 167 o = gt_cat_n(line, o, ts) 168 o = gt_cat(line, o, " module=" as *u8) 169 o = gt_cat(line, o, name) 170 o = gt_cat(line, o, " class=" as *u8) 171 if cls == GT_PASS { o = gt_cat(line, o, "PASS" as *u8) } 172 if cls == GT_ASM_GAP { o = gt_cat(line, o, "ASM-GAP (nxasm refuses/crashes on the .s)" as *u8) } 173 if cls == GT_TOOLCHAIN_NXASM { o = gt_cat(line, o, "TOOLCHAIN-NXASM (gcc build of SAME .s passes; assembler mis-encodes)" as *u8) } 174 if cls == GT_COMPILER_OR_SOURCE { o = gt_cat(line, o, "COMPILER-OR-SOURCE (both lanes fail; the .s itself is wrong)" as *u8) } 175 if cls == GT_COMPILE_FAIL { o = gt_cat(line, o, "COMPILE-FAIL (no usable .s)" as *u8) } 176 if cls != GT_PASS { 177 o = gt_cat(line, o, " sov-exit=" as *u8) 178 o = gt_cat_n(line, o, sov) 179 o = gt_cat(line, o, " oracle-exit=" as *u8) 180 o = gt_cat_n(line, o, ora) 181 } 182 o = gt_cat(line, o, "\n" as *u8) 183 sys_write(1, line, o) 184 if logfd >= 0 { sys_write(logfd, line, o) } 185 return 0 186} 187 188func main(argc: i64, argv: *i64) -> i64 { 189 var compiler: *u8 = "_offc/nx_cc_sovereign.elf" as *u8 190 if argc >= 2 { compiler = argv[1] as *u8 } 191 let envp: *i64 = sys_mmap(8*4) as *i64 192 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 193 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 194 let logfd: i64 = sys_openat_append("/tmp/nishi_game_gate_triage.log" as *u8, 0x1a4) 195 let ts: i64 = sys_now_realtime_sec() 196 197 var nonpass: i64 = 0 198 var i: i64 = 0 199 var name: *u8 = gt_module(0) 200 while name != (0 as *u8) { 201 let sov_exit: *i64 = sys_mmap(8) as *i64 202 let ora_exit: *i64 = sys_mmap(8) as *i64 203 sov_exit[0] = 0 - 1 204 ora_exit[0] = 0 - 1 205 let cls: i64 = gt_triage_one(name, compiler, envp, devnull, sov_exit, ora_exit) 206 gt_report(logfd, name, cls, sov_exit[0], ora_exit[0], ts) 207 if cls != GT_PASS { nonpass = nonpass + 1 } 208 i = i + 1 209 name = gt_module(i) 210 } 211 if logfd >= 0 { sys_close(logfd) } 212 return nonpass 213}