code wiki / (root) / nx_hostctl_buildrun_gate.nx

nx_hostctl_buildrun_gate.nx source

↩ module page · 39 lines · 4683 B

1// nx_hostctl_buildrun_gate.nx -- the RED that the buildrun fix never had (2026-09-05). Drives the ONE rule in 2// nx_buildrun_verdict_lib (the function nx_hostctl cmd_buildrun calls before it stages anything) with captures shaped 3// like the real incident and its controls. The subject is the decision, not the supervisor's filesystem: hostctl's 4// build paths are absolute by design, so a fixture tree cannot stand in for them, and a gate that forked the live 5// supervisor would be a deploy in a test's clothing. 6// Declared for nx_hostctl in knowledge/organ_gate.conf. exit: 0 GREEN / 1 RED (gv_verdict law). 7import "nx_syscalls.nx" 8import "nx_gate_verdict.nx" 9import "nx_buildrun_verdict_lib.nx" 10 11func bg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 12 13func main(argc: i64, argv: *i64) -> i64 { 14 let ctr: *i64 = gv_ctr() 15 gv_head("nx_hostctl_buildrun_gate -- a refused or dead builder can never be read as BUILT; only exit 0 plus the builder's own token stages" as *u8) 16 // T1 THE INCIDENT SHAPE: the builder refused under admission (rc=4) and left the previous artifact on disk 17 let c1: *u8 = "[nx_sov_build_run] CWD anchored to buildroot/ (started in the serving root)\nBUILD-ADMIT mem_available_mb=21917 procs_running=13 procs_blocked=4 blocked_max=8\nVERDICT=QUEUE -- one of: the D-state roster shows an I/O storm ...\n[nx_sov_build_run] REFUSED-BUILD-ADMIT rc=4 QUEUE -- the BUILD-ADMIT report ABOVE names which conjunct fired\n" as *u8 18 gv_check_eq("T1 the measured incident: builder exit 4 with REFUSED-BUILD-ADMIT in the capture reads EXIT_NONZERO, never BUILT" as *u8, bv_verdict(4, c1, bg_len(c1)), BV_EXIT_NONZERO, ctr) 19 // T2 a real compile 20 let c2: *u8 = "[nx_sov_build_run] nx_actlog: BUILD-CACHE MISS reason=no-entry key=1965\n[nx_sov_build_run] nx_actlog: BUILD-CACHE STORE bytes=104983 sha256=0434\n[nx_sov_build_run] nx_actlog: asm=472851B SOVEREIGN build (nx_cc->nxasm_x86, no gcc, no run) elf=_build/nx_actlog.sov.elf\n" as *u8 21 gv_check_eq("T2 a real compile: exit 0 and the SOVEREIGN build token reads OK" as *u8, bv_verdict(0, c2, bg_len(c2)), BV_OK, ctr) 22 // T3 a cache HIT prints asm=0B and the SAME token -- a legitimate reuse must not be refused 23 let c3: *u8 = "[nx_sov_build_run] nx_actlog: BUILD-CACHE HIT key=1965 bytes=117760 sha256=91fb verified against its sidecar, byte-identical artifact reused\n[nx_sov_build_run] nx_actlog: asm=0B SOVEREIGN build (nx_cc->nxasm_x86, no gcc, no run) elf=_build/nx_actlog.sov.elf\n" as *u8 24 gv_check_eq("T3 a cache hit: exit 0 and the token on the asm=0B line reads OK (a reuse is a build this run vouched for)" as *u8, bv_verdict(0, c3, bg_len(c3)), BV_OK, ctr) 25 // neg-controls 26 let c4: *u8 = "[nx_sov_build_run] nx_actlog: BUILD-CACHE HIT key=1965 bytes=117760 verified against its sidecar\n" as *u8 27 gv_check_eq("neg-control-T4 a hit line ALONE without the token reads NO_TOKEN (the sidecar law: a hit that materialised nothing)" as *u8, bv_verdict(0, c4, bg_len(c4)), BV_NO_TOKEN, ctr) 28 let c5: *u8 = "" as *u8 29 gv_check_eq("neg-control-T5 exit 0 with an EMPTY capture reads NO_TOKEN, never OK" as *u8, bv_verdict(0, c5, 0), BV_NO_TOKEN, ctr) 30 gv_check_eq("neg-control-T6 exit 127 (the exec itself failed) reads EXIT_NONZERO even with a stale token in the capture" as *u8, bv_verdict(127, c2, bg_len(c2)), BV_EXIT_NONZERO, ctr) 31 let c7: *u8 = "[nx_sov_build_run] nx_actlog: SOVEREIGN\nbuild elf=_build/nx_actlog.sov.elf\n" as *u8 32 gv_check_eq("neg-control-T7 the token split across a line break is NOT the token (exact, contiguous match)" as *u8, bv_verdict(0, c7, bg_len(c7)), BV_NO_TOKEN, ctr) 33 // T8 the exit conjunct is evaluated FIRST: a refusal that somehow carries the token still fails on exit 34 let c8: *u8 = "REFUSED-BUILD-ADMIT rc=4 -- a previous line said SOVEREIGN build once\n" as *u8 35 gv_check_eq("T8 conjunct order: exit 4 wins over a token in the capture (the exit is the builder's verdict on THIS run)" as *u8, bv_verdict(4, c8, bg_len(c8)), BV_EXIT_NONZERO, ctr) 36 // T9 the receipt names the reason (a message that names the wrong stage costs the reader the investigation) 37 gv_check_eq("T9 every verdict has a reason string that names its conjunct" as *u8, (bg_len(bv_reason(BV_EXIT_NONZERO)) > 0) as i64 * (bg_len(bv_reason(BV_NO_TOKEN)) > 0) as i64 * (bg_len(bv_reason(BV_OK)) > 0) as i64, 1, ctr) 38 return gv_verdict("nx_hostctl_buildrun_gate" as *u8, ctr, "a builder that refused or died can no longer be read as BUILT: exit 0 AND the builder's own token gate the stage, with the cache-hit reuse kept and the split-token and empty-capture controls refused" as *u8) 39}