code wiki / _hdl_build / nx_game_gate.nx

nx_game_gate.nx source

↩ module page · 220 lines · 9708 B

1// nx_game_gate.nx -- TEAM-OWNED re-runnable evidence gate for the game-engine 2// substrate (operator: "keep building the team to build this"). Builds and 3// runs every game-substrate test module through the SOVEREIGN pipeline 4// (nx_cc -> nxasm_x86_main -> run, no gcc/sh) and emits one structured 5// verdict line per module, judged by RAW wait4 status (signal-aware), so the 6// grade can never come from a lying $? channel (see 7// feedback-wsl-exit-code-judging-2026-06-09) nor from LLM assertion (see 8// feedback-evidence-driven-live-grading). Appends every line to 9// /tmp/nishi_game_gate.log so grades are LIVE + auditable. 10// 11// Usage: 12// nx_game_gate.elf # compiler = _offc/nx_cc_sovereign.elf 13// nx_game_gate.elf /path/to/nx_cc.elf # explicit compiler (e.g. a candidate 14// # build under test, or the gcc-linked 15// # oracle scaffold while the nxasm 16// # capacity fix is pending) 17// Run from the nxc2 repo root (paths are root-relative like nx_sov_build_run). 18// Exit code = number of FAILED modules (0 = substrate green). 19// 20// license_tier: ORIGINAL Reuses the _run spine from nx_sov_build_run. 21import "nx_syscalls.nx" 22 23const GG_MIN_ASM_BYTES: i64 = 128 24const GG_MAX_RETRIES: i64 = 12 25 26func gg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 27func gg_putn(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64=v; if m<0 {m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8 = sys_mmap(28); var k: i64=0; if m==0 {t[0]=48;k=1}; while m>0 {t[k]=48+(m%10); m=m/10; k=k+1}; var i: i64=0; while i<k {bb[i]=t[k-1-i]; i=i+1}; sys_write(1, bb, k); return 0 } 28 29// append NUL-terminated s into dst at off; return new offset (no NUL written) 30func gg_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 } 31 32// append decimal v into dst at off; return new offset 33func gg_cat_n(dst: *u8, off: i64, v: i64) -> i64 { 34 var o: i64 = off 35 var m: i64 = v 36 if m < 0 { dst[o] = 45; o = o + 1; m = 0 - m } 37 let t: *u8 = sys_mmap(28) 38 var k: i64 = 0 39 if m == 0 { t[0] = 48; k = 1 } 40 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 } 41 var i: i64 = 0 42 while i < k { dst[o+i] = t[k-1-i]; i = i + 1 } 43 return o + k 44} 45 46// fork/execve/wait4; returns WEXITSTATUS, or 128+signal on signal death 47// (signal-aware per the nx_sov_build_run 2026-06-09 fix -- a segfaulted 48// tool must NEVER decode as success). 49func gg_run(path: *u8, argv: *i64, envp: *i64, redir_out: i64, redir_err: i64) -> i64 { 50 let pid: i64 = sys_fork() 51 if pid == 0 { 52 if redir_out >= 0 { sys_dup3(redir_out, 1, 0) } 53 if redir_err >= 0 { sys_dup3(redir_err, 2, 0) } 54 sys_execve(path, argv, envp) 55 sys_exit(127) 56 } 57 let st: *i64 = sys_mmap(16) as *i64 58 sys_wait4(pid, st, 0) 59 let sig: i64 = st[0] & 0x7f 60 if sig != 0 { return 128 + sig } 61 return (st[0] >> 8) & 0xff 62} 63 64func gg_filesize(path: *u8) -> i64 { 65 let fd: i64 = sys_openat_rd(path) 66 if fd < 0 { return 0 } 67 let buf: *u8 = sys_mmap(4096) 68 var total: i64 = 0 69 var n: i64 = sys_read(fd, buf, 4096) 70 while n > 0 { total = total + n; n = sys_read(fd, buf, 4096) } 71 sys_close(fd) 72 return total 73} 74 75// The gated module list. Index -> module basename; 0-pointer past the end. 76// KAT first: if the compiler itself regressed the terminator bug class, 77// every later verdict is suspect -- surface that immediately. 78func gg_module(i: i64) -> *u8 { 79 if i == 0 { return "nx_term_kat" as *u8 } 80 if i == 1 { return "nx_tictactoe_test" as *u8 } 81 if i == 2 { return "nx_checkers_test" as *u8 } 82 if i == 3 { return "nx_raycast_voxel_test" as *u8 } 83 if i == 4 { return "nx_game_engine_compose_test" as *u8 } 84 if i == 5 { return "nx_game_runtime_compose_test" as *u8 } 85 if i == 6 { return "nx_fab_slice_test" as *u8 } 86 if i == 7 { return "nx_text_render_test" as *u8 } 87 if i == 8 { return "nx_html_render_test" as *u8 } 88 if i == 9 { return "nx_render_target_match_test" as *u8 } 89 if i == 10 { return "nx_perceptual_render_test" as *u8 } 90 if i == 11 { return "nx_pitwall_render_test" as *u8 } 91 if i == 12 { return "nx_math_games_test" as *u8 } 92 if i == 13 { return "nx_actor_role_game_logic_test" as *u8 } 93 if i == 14 { return "nx_user_sim_games" as *u8 } 94 if i == 15 { return "nx_worldgen_refine" as *u8 } 95 if i == 16 { return "nx_visual_novel_test" as *u8 } 96 if i == 17 { return "nx_procgen_signature_test" as *u8 } 97 if i == 18 { return "nx_scene_contract_test" as *u8 } 98 if i == 19 { return "nx_procgen_biome_test" as *u8 } 99 if i == 20 { return "nx_procgen_features_test" as *u8 } 100 if i == 21 { return "nx_procgen_water_test" as *u8 } 101 if i == 22 { return "nx_worldgen_tuner_test" as *u8 } 102 return 0 as *u8 103} 104 105// Build + run ONE module through the sovereign pipeline. Returns the run 106// verdict code: 0 = PASS; 1..127 = module's own failing assertion exit; 107// 128+sig = signal death; 1001 = compile-fail; 1002 = assemble-fail. 108func gg_gate_one(name: *u8, compiler: *u8, envp: *i64, devnull: i64) -> i64 { 109 // resolve source: runtime/_hdl_build/<name>.nx, else runtime/<name>.nx 110 let src: *u8 = sys_mmap(512) 111 var o: i64 = 0 112 o = gg_cat(src, o, "runtime/_hdl_build/" as *u8); o = gg_cat(src, o, name); o = gg_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 113 let chk: i64 = sys_openat_rd(src) 114 if chk < 0 { 115 o = 0 116 o = gg_cat(src, o, "runtime/" as *u8); o = gg_cat(src, o, name); o = gg_cat(src, o, ".nx" as *u8); src[o] = 0 as u8 117 } 118 if chk >= 0 { sys_close(chk) } 119 120 let spath: *u8 = sys_mmap(256); o = 0 121 o = gg_cat(spath, o, "/tmp/" as *u8); o = gg_cat(spath, o, name); o = gg_cat(spath, o, ".gg.s" as *u8); spath[o] = 0 as u8 122 let elfpath: *u8 = sys_mmap(256); o = 0 123 o = gg_cat(elfpath, o, "/tmp/" as *u8); o = gg_cat(elfpath, o, name); o = gg_cat(elfpath, o, ".gg.elf" as *u8); elfpath[o] = 0 as u8 124 125 // compile with recompile-retry (known compiler empty-.s nondeterminism) 126 var asmbytes: i64 = 0 127 var tries: i64 = 0 128 while tries < GG_MAX_RETRIES { 129 let sfd: i64 = sys_openat_wr(spath, 0x1a4) 130 let cc: *i64 = sys_mmap(8*4) as *i64 131 cc[0] = compiler as i64; cc[1] = src as i64; cc[2] = 0 132 let rc_c: i64 = gg_run(compiler, cc, envp, sfd, devnull) 133 sys_close(sfd) 134 asmbytes = gg_filesize(spath) 135 if rc_c == 0 { if asmbytes > GG_MIN_ASM_BYTES { tries = GG_MAX_RETRIES } } 136 if tries != GG_MAX_RETRIES { tries = tries + 1 } 137 } 138 if asmbytes <= GG_MIN_ASM_BYTES { return 1001 } 139 140 // assemble + link with the sovereign assembler (NO gcc) 141 let asm_tool: *u8 = "_offc/nxasm_x86_main.elf" as *u8 142 let aa: *i64 = sys_mmap(8*4) as *i64 143 aa[0] = asm_tool as i64; aa[1] = spath as i64; aa[2] = elfpath as i64; aa[3] = 0 144 let rc_a: i64 = gg_run(asm_tool, aa, envp, 0 - 1, 0 - 1) 145 if rc_a != 0 { return 1002 } 146 147 // run; mute the module's own stdout (verdict = exit status, not prose) 148 let rr: *i64 = sys_mmap(8*4) as *i64 149 rr[0] = elfpath as i64; rr[1] = 0 150 return gg_run(elfpath, rr, envp, devnull, devnull) 151} 152 153// Emit one verdict line to stdout AND append it to the gate log. 154func gg_report(logfd: i64, name: *u8, code: i64, ts: i64) -> i64 { 155 let line: *u8 = sys_mmap(512) 156 var o: i64 = 0 157 o = gg_cat(line, o, "GAMEGATE ts=" as *u8) 158 o = gg_cat_n(line, o, ts) 159 o = gg_cat(line, o, " module=" as *u8) 160 o = gg_cat(line, o, name) 161 o = gg_cat(line, o, " verdict=" as *u8) 162 if code == 0 { o = gg_cat(line, o, "PASS" as *u8) } 163 if code == 1001 { o = gg_cat(line, o, "COMPILE-FAIL" as *u8) } 164 if code == 1002 { o = gg_cat(line, o, "ASM-FAIL" as *u8) } 165 if code != 0 { 166 if code != 1001 { 167 if code != 1002 { 168 if code > 128 { 169 o = gg_cat(line, o, "SIGNAL sig=" as *u8) 170 o = gg_cat_n(line, o, code - 128) 171 } else { 172 o = gg_cat(line, o, "FAIL exit=" as *u8) 173 o = gg_cat_n(line, o, code) 174 } 175 } 176 } 177 } 178 o = gg_cat(line, o, "\n" as *u8) 179 sys_write(1, line, o) 180 if logfd >= 0 { sys_write(logfd, line, o) } 181 return 0 182} 183 184func main(argc: i64, argv: *i64) -> i64 { 185 var compiler: *u8 = "_offc/nx_cc_sovereign.elf" as *u8 186 if argc >= 2 { compiler = argv[1] as *u8 } 187 188 let envp: *i64 = sys_mmap(8*4) as *i64 189 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 190 let devnull: i64 = sys_openat_wr("/dev/null" as *u8, 0x1a4) 191 let logfd: i64 = sys_openat_append("/tmp/nishi_game_gate.log" as *u8, 0x1a4) 192 let ts: i64 = sys_now_realtime_sec() 193 194 gg_puts("GAMEGATE BEGIN compiler=" as *u8); gg_puts(compiler); gg_puts("\n" as *u8) 195 196 var fails: i64 = 0 197 var i: i64 = 0 198 var name: *u8 = gg_module(0) 199 while name != (0 as *u8) { 200 let code: i64 = gg_gate_one(name, compiler, envp, devnull) 201 gg_report(logfd, name, code, ts) 202 if code != 0 { fails = fails + 1 } 203 i = i + 1 204 name = gg_module(i) 205 } 206 207 let sline: *u8 = sys_mmap(256) 208 var o: i64 = 0 209 o = gg_cat(sline, o, "GAMEGATE SUMMARY ts=" as *u8) 210 o = gg_cat_n(sline, o, ts) 211 o = gg_cat(sline, o, " modules=" as *u8) 212 o = gg_cat_n(sline, o, i) 213 o = gg_cat(sline, o, " fails=" as *u8) 214 o = gg_cat_n(sline, o, fails) 215 o = gg_cat(sline, o, "\n" as *u8) 216 sys_write(1, sline, o) 217 if logfd >= 0 { sys_write(logfd, sline, o) } 218 if logfd >= 0 { sys_close(logfd) } 219 return fails 220}