code wiki / (root) / nx_behaveprobe_gate.nx

nx_behaveprobe_gate.nx source

↩ module page · 165 lines · 10721 B

1// nx_behaveprobe_gate.nx -- THE REFEREE FOR THE PROMOTE RULER'S SUFFICIENCY HALF: A LIVE PROBE MUST READ A SIGNAL 2// DEATH AS A SIGNAL DEATH, AND A PLAIN EXIT CODE AS ITSELF. 3// 4// WHY (2026-09-05, measured on the promote path). nx_behaveprobe reported rc=0 for a gate the crash guard 5// had killed with SIGSEGV -- twice -- and that receipt cleared a crashing gate for promote. The rule was 6// not missing: wait_status_rc (2026-08-25) reads a signal death as 128+signal, nx_waitrc_gate proves it, 7// and nx_tool_run composes it. The SERVED probe was simply older than the rule, and nothing in the estate 8// ever asked the live ruler the question. A STALE COPY OF A CORRECT INSTRUMENT IS INDISTINGUISHABLE FROM 9// A BROKEN ONE, and the only cure that survives a promote is a referee that forks the LIVE binary against 10// a subject that really dies by signal. That subject is nx_sigfixture (registered, dies by the named signal 11// on itself; `exit <code>` is its control arm), and the probe's `self` mode compares live against itself 12// so no stage slot is touched. 13// SUBJECT = the DEPLOYED probe at its absolute nishihost path, forked in its own directory (the 08-22 14// lesson: a relative subject and a runner's cwd read as failing teeth about a correct binary). 15// license_tier: ORIGINAL expect_exit: 0 16import "nx_syscalls.nx" 17import "nx_gate_verdict.nx" 18import "nx_tool_run.nx" 19 20const BPG_PROBE: *u8 = "/volume1/homes/elderwesto/nishihost/nx_behaveprobe.elf" 21const BPG_FIXTURE: *u8 = "nx_sigfixture" 22const BPG_SIG_BASE: i64 = 128 // wait_status_rc: a signal death reads 128+signal 23const BPG_SIGTERM: i64 = 15 // no guard catches it: a TRUE signal death 24const BPG_SIGTERM_ARG: *u8 = "15" 25const BPG_CTRL_CODE: i64 = 7 // the control arm: a plain exit code must pass through unchanged 26const BPG_CTRL_ARG: *u8 = "7" 27const BPG_CAPTURE_CAP: i64 = 65536 28const BPG_ARGV_SLOTS: i64 = 8 29const BPG_WORD_BYTES: i64 = 8 30const BPG_CWD_CAP: i64 = 4096 31const BPG_NO_TIMEOUT: i64 = 0 32const BPG_SLASH: i64 = 47 33const BPG_DIGIT_ZERO: i64 = 48 34const BPG_DIGIT_NINE: i64 = 57 35const BPG_DEC_BASE: i64 = 10 36const BPG_MINUS: i64 = 45 37const BPG_ABSENT: i64 = 0 - 999999 // a key the capture does not carry: never a plausible rc 38 39func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 40func pn(v: i64) -> i64 { let t: *u8=sys_mmap(24); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let b: *u8=sys_mmap(24); var j: i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 } 41// substring presence, bounded by the literal's measured length -- never a byte past either buffer 42func bpg_find(b: *u8, n: i64, lit: *u8) -> i64 { 43 var ll: i64 = 0 44 while lit[ll] != (0 as u8) { ll = ll + 1 } 45 if ll == 0 { return 0 - 1 } 46 var i: i64 = 0 47 while i + ll <= n { 48 var k: i64 = 0 49 var ok: i64 = 1 50 while ok == 1 { if k >= ll { break } if b[i+k] != lit[k] { ok = 0 } k = k + 1 } 51 if ok == 1 { return i } 52 i = i + 1 53 } 54 return 0 - 1 55} 56func bpg_has(b: *u8, n: i64, lit: *u8) -> i64 { if bpg_find(b, n, lit) >= 0 { return 1 } return 0 } 57// the integer that follows `key` in the probe's own JSON line; BPG_ABSENT when the key is not there 58func bpg_json_int(b: *u8, n: i64, key: *u8) -> i64 { 59 let at: i64 = bpg_find(b, n, key) 60 if at < 0 { return BPG_ABSENT } 61 var kl: i64 = 0 62 while key[kl] != (0 as u8) { kl = kl + 1 } 63 var i: i64 = at + kl 64 var neg: i64 = 0 65 if i < n { if b[i] == (BPG_MINUS as u8) { neg = 1; i = i + 1 } } 66 var v: i64 = 0 67 var any: i64 = 0 68 while i < n { 69 let c: i64 = b[i] as i64 70 if c < BPG_DIGIT_ZERO { break } 71 if c > BPG_DIGIT_NINE { break } 72 v = v * BPG_DEC_BASE + (c - BPG_DIGIT_ZERO) 73 any = 1 74 i = i + 1 75 } 76 if any == 0 { return BPG_ABSENT } 77 if neg == 1 { return 0 - v } 78 return v 79} 80func bpg_dirname(path: *u8, out: *u8) -> i64 { 81 var last: i64 = 0 - 1 82 var i: i64 = 0 83 while path[i] != (0 as u8) { if path[i] == (BPG_SLASH as u8) { last = i } i = i + 1 } 84 if last <= 0 { out[0] = BPG_SLASH as u8; out[1] = 0 as u8; return 1 } 85 var k: i64 = 0 86 while k < last { if k < BPG_CWD_CAP - 1 { out[k] = path[k] } k = k + 1 } 87 out[last] = 0 as u8 88 return last 89} 90// fork the LIVE probe as `self <fixture> <a3> [a4]` in its own directory, capture stdout, return its exit code 91func bpg_probe(a3: *u8, a4: *u8, out: *u8, olen: *i64) -> i64 { 92 let av: *i64 = sys_mmap(BPG_WORD_BYTES*BPG_ARGV_SLOTS) as *i64 93 av[0] = BPG_PROBE as i64 94 av[1] = "self" as i64 95 av[2] = BPG_FIXTURE as i64 96 av[3] = a3 as i64 97 if (a4 as i64) != 0 { av[4] = a4 as i64; av[5] = 0 } else { av[4] = 0 } 98 let cwd: *u8 = sys_mmap(BPG_CWD_CAP) 99 bpg_dirname(BPG_PROBE, cwd) 100 return tr_run_capture_cwd(BPG_PROBE, av, out, BPG_CAPTURE_CAP, olen, BPG_NO_TIMEOUT, cwd) 101} 102 103// THE PROBE PRINTS ONLY ITS OWN JSON LINE, NEVER THE SUBJECT'S BYTES (measured on the first run: T3/T8 looked for 104// the fixture's text in the probe's capture and read a true absence about the wrong subject). So the fixture is 105// witnessed DIRECTLY through the in-process ruler -- tr_run_capture_cwd over wait_status_rc -- which is a SECOND 106// METHOD CLASS beside the probe: two rulers, one status word, and they must agree. 107const BPG_FIXTURE_ELF: *u8 = "/volume1/homes/elderwesto/nishihost/nx_sigfixture.elf" 108func bpg_fixture(a1: *u8, a2: *u8, out: *u8, olen: *i64) -> i64 { 109 let av: *i64 = sys_mmap(BPG_WORD_BYTES*BPG_ARGV_SLOTS) as *i64 110 av[0] = BPG_FIXTURE_ELF as i64 111 av[1] = a1 as i64 112 if (a2 as i64) != 0 { av[2] = a2 as i64; av[3] = 0 } else { av[2] = 0 } 113 let cwd: *u8 = sys_mmap(BPG_CWD_CAP) 114 bpg_dirname(BPG_FIXTURE_ELF, cwd) 115 return tr_run_capture_cwd(BPG_FIXTURE_ELF, av, out, BPG_CAPTURE_CAP, olen, BPG_NO_TIMEOUT, cwd) 116} 117 118func main() -> i64 { 119 let ctr: *i64 = gv_ctr() 120 gv_head("nx_behaveprobe_gate -- the LIVE promote ruler is asked how it reads a signal death and a plain exit, against a subject that really dies" as *u8) 121 122 // ---- the signal arm: nx_sigfixture 15 dies by SIGTERM on itself ---- 123 let cs: *u8 = sys_mmap(BPG_CAPTURE_CAP) 124 let ls: *i64 = sys_mmap(BPG_WORD_BYTES*2) as *i64 125 let prc: i64 = bpg_probe(BPG_SIGTERM_ARG, 0 as *u8, cs, ls) 126 hw(" probe(self sigfixture 15) exit=" as *u8); pn(prc); hw(" captured=" as *u8); pn(ls[0]); hw("\n" as *u8) 127 gv_check("T1 neg-control-subject-executed: the live probe ran and produced its own JSON line (organ named) -- the exit codes below came from the ruler, not from the fork" as *u8, ((prc >= 0) as i64) * bpg_has(cs, ls[0], "nx_behaveprobe" as *u8), ctr) 128 gv_check("T2 the self direction is honoured: mode reads live-vs-self, so no stage slot and no .prev was needed to ask the question" as *u8, bpg_has(cs, ls[0], "live-vs-self" as *u8), ctr) 129 let fs: *u8 = sys_mmap(BPG_CAPTURE_CAP) 130 let fl: *i64 = sys_mmap(BPG_WORD_BYTES*2) as *i64 131 let frc: i64 = bpg_fixture(BPG_SIGTERM_ARG, 0 as *u8, fs, fl) 132 hw(" fixture(15) direct rc=" as *u8); pn(frc); hw(" captured=" as *u8); pn(fl[0]); hw("\n" as *u8) 133 gv_check("T3 fixture-reached-the-condition: forked DIRECTLY through the in-process ruler the fixture names the signal it died by (dying by signal 15) and its rc reads 143 -- a second method class agreeing with the probe" as *u8, bpg_has(fs, fl[0], "dying by signal 15" as *u8) * ((frc == BPG_SIG_BASE + BPG_SIGTERM) as i64), ctr) 134 let lrc: i64 = bpg_json_int(cs, ls[0], "\"live_rc\":" as *u8) 135 let orc: i64 = bpg_json_int(cs, ls[0], "\"other_rc\":" as *u8) 136 hw(" live_rc=" as *u8); pn(lrc); hw(" other_rc=" as *u8); pn(orc); hw("\n" as *u8) 137 gv_check("T4 a TRUE signal death reads 128+signal on the live side (SIGTERM -> 143): the ruler composes wait_status_rc, never the bare WEXITSTATUS that reads a signalled child as 0" as *u8, (lrc == BPG_SIG_BASE + BPG_SIGTERM) as i64, ctr) 138 gv_check("T5 the other side reads the same 143 (self mode ran the same binary twice) -- one ruler, one answer" as *u8, (orc == BPG_SIG_BASE + BPG_SIGTERM) as i64, ctr) 139 gv_check("T6 neg-control-never-zero-on-signal: the capture carries no live_rc of 0 -- the exact receipt that cleared a crashing gate for promote on 2026-09-05" as *u8, (bpg_has(cs, ls[0], "\"live_rc\":0," as *u8) == 0) as i64, ctr) 140 gv_check("T7 the evidence grade NAMES the death: SIGNALLED is on the line, so a caller reading the receipt is told a signal death is not a verdict" as *u8, bpg_has(cs, ls[0], "SIGNALLED" as *u8), ctr) 141 142 // ---- the control arm: nx_sigfixture exit 7 is a plain exit code and must pass through unchanged ---- 143 let cc: *u8 = sys_mmap(BPG_CAPTURE_CAP) 144 let lc: *i64 = sys_mmap(BPG_WORD_BYTES*2) as *i64 145 let crc: i64 = bpg_probe("exit" as *u8, BPG_CTRL_ARG, cc, lc) 146 hw(" probe(self sigfixture exit 7) exit=" as *u8); pn(crc); hw(" captured=" as *u8); pn(lc[0]); hw("\n" as *u8) 147 let clrc: i64 = bpg_json_int(cc, lc[0], "\"live_rc\":" as *u8) 148 hw(" control live_rc=" as *u8); pn(clrc); hw("\n" as *u8) 149 let fc: *u8 = sys_mmap(BPG_CAPTURE_CAP) 150 let fcl: *i64 = sys_mmap(BPG_WORD_BYTES*2) as *i64 151 let fcrc: i64 = bpg_fixture("exit" as *u8, BPG_CTRL_ARG, fc, fcl) 152 hw(" fixture(exit 7) direct rc=" as *u8); pn(fcrc); hw(" captured=" as *u8); pn(fcl[0]); hw("\n" as *u8) 153 gv_check("T8 fixture-reached-the-condition: forked DIRECTLY through the in-process ruler the control subject printed its control-arm line and exited by code 7, not by signal -- the second method class agrees with the probe here too" as *u8, bpg_has(fc, fcl[0], "control arm" as *u8) * ((fcrc == BPG_CTRL_CODE) as i64), ctr) 154 gv_check("T9 ANTI-VACUITY control arm: a plain exit 7 reads exactly 7 -- a ruler that answered 143 for everything cannot score this" as *u8, (clrc == BPG_CTRL_CODE) as i64, ctr) 155 gv_check("T10 neg-control-control-arm-is-not-SIGNALLED: an ordinary non-zero exit is graded GRADED, never SIGNALLED -- the two axes stay apart" as *u8, ((bpg_has(cc, lc[0], "SIGNALLED" as *u8) == 0) as i64) * bpg_has(cc, lc[0], "GRADED" as *u8), ctr) 156 var bad: i64 = 0 157 if lrc == BPG_SIG_BASE + BPG_SIGTERM { bad = 1 } 158 var good: i64 = 1 159 if clrc == BPG_CTRL_CODE { good = 0 } 160 gv_bite("T11 neg-control-signal-vs-exit-pair: 143 on the signal arm AND 7 on the control arm -- a ruler that could not tell a death from an exit cannot score this" as *u8, bad, good, ctr) 161 162 let rc: i64 = gv_verdict("BEHAVEPROBE-GATE", ctr, "live deployed probe, registered signal fixture, self direction; every tooth states its own strength" as *u8) 163 sys_exit(rc) 164 return rc 165}