code wiki / (root) / nx_actlog_gate.nx

nx_actlog_gate.nx source

↩ module page · 95 lines · 5654 B

1// nx_actlog_gate.nx -- END-TO-END gate for the action-journal miner: forks the SUBJECT ARTIFACT and runs 2// its own selftest (15 teeth: journal, sequence, frequency, harden, gap, closed-pattern, confidence), 3// inheriting the exit code as the verdict. Exists because on 2026-09-05 the read-cap fix shipped through 4// nx_organ_ship with prove=NO-GATE-FOUND: the proof existed as a verb and nothing could resolve it. 5// Sibling of nx_claude_harvest_gate; resolvable by the <target>_gate convention, so no organ_gate.conf row. 6// 7// ARTIFACT IDENTITY: the ship loop PROVEs BEFORE it promotes, so the serving root still holds the PREVIOUS 8// binary at PROVE time. The just-built artifact is preferred (buildroot/_build/ on the NAS, _build/ on the 9// laptop farm -- two hosts, two ladders), the promoted copy is the fallback, and the choice is PRINTED. 10// The subject is forked IN PLACE by a relative path from the estate root (no chdir, nothing exec'd from 11// /tmp, which is noexec on the NAS); its scratch journal lives under /tmp where writing is allowed. 12// 13// exit: 0 GREEN / 1 RED (gv_verdict law: the exit code IS the verdict) 14import "nx_syscalls.nx" 15import "nx_gate_verdict.nx" 16import "nx_tool_run.nx" 17 18const ALG_OUT: i64 = 262144 19const ALG_PATH: i64 = 256 20 21func alg_find(q: *u8, n: i64, lit: *u8) -> i64 { 22 var ll: i64 = 0 23 while lit[ll] != (0 as u8) { ll = ll + 1 } 24 if ll == 0 { return 0 } 25 var i: i64 = 0 26 while i + ll <= n { 27 var j: i64 = 0 28 var ok: i64 = 1 29 while j < ll { if q[i + j] != lit[j] { ok = 0; j = ll } else { j = j + 1 } } 30 if ok == 1 { return 1 } 31 i = i + 1 32 } 33 return 0 34} 35 36func alg_exists(path: *u8) -> i64 { 37 let fd: i64 = sys_openat_rd(path) 38 if fd < 0 { return 0 } 39 sys_close(fd) 40 return 1 41} 42 43func main(argc: i64, argv: *i64) -> i64 { 44 let ctr: *i64 = gv_ctr() 45 gv_head("nx_actlog_gate -- forks the subject artifact's own selftest; the exit code carries the verdict" as *u8) 46 let built: *u8 = "buildroot/_build/nx_actlog.sov.elf" as *u8 47 let built_local: *u8 = "_build/nx_actlog.sov.elf" as *u8 48 let promoted: *u8 = "./nx_actlog.elf" as *u8 49 var subject: *u8 = promoted 50 var which: *u8 = "PROMOTED" as *u8 51 if alg_exists(built_local) == 1 { subject = built_local; which = "JUST-BUILT-local" as *u8 } 52 if alg_exists(built) == 1 { subject = built; which = "JUST-BUILT" as *u8 } 53 let have: i64 = alg_exists(subject) 54 gv_puts("SUBJECT " as *u8); gv_puts(which); gv_puts(" " as *u8); gv_puts(subject); gv_puts("\n" as *u8) 55 gv_check("T1 subject artifact resolved and openable" as *u8, have, ctr) 56 if have == 0 { return gv_verdict("nx_actlog_gate" as *u8, ctr, "no subject artifact at any root; nothing was proven" as *u8) } 57 // unique scratch journal so a re-run is idempotent (the selftest truncates it itself) 58 let jr: *u8 = sys_mmap(ALG_PATH) 59 var o: i64 = gv_cat(jr, 0, "/tmp/alg_" as *u8) 60 o = gv_catn(jr, o, sys_now_realtime_sec()) 61 o = gv_cat(jr, o, ".jrnl" as *u8) 62 jr[o] = 0 as u8 63 let av: *i64 = sys_mmap(64) as *i64 64 av[0] = subject as i64 65 av[1] = "selftest" as *u8 as i64 66 av[2] = jr as i64 67 av[3] = 0 68 let cout: *u8 = sys_mmap(ALG_OUT) 69 let colen: *i64 = sys_mmap(16) as *i64 70 colen[0] = 0 71 let ex: i64 = tr_run_capture(subject, av, cout, ALG_OUT - 8, colen) 72 let n: i64 = colen[0] 73 gv_kv("selftest_exit" as *u8, ex) 74 gv_kv("selftest_bytes" as *u8, n) 75 gv_check("T2 subject selftest exit 0 (its own verdict is GREEN)" as *u8, (ex == 0) as i64, ctr) 76 // T3 is anchored to the LAST line by POSITION (gv_last_line law): the subject embeds a BENCH that prints its 77 // own verdict=GREEN mid-stream, so an unanchored substring passed on a RED selftest (measured 2026-09-05, 78 // 16/17 RED with T3 PASS). The verdict line is the final line; nothing printed before it may stand in for it. 79 var ls: i64 = n 80 if ls > 0 { if cout[ls - 1] == (10 as u8) { ls = ls - 1 } } 81 var lb: i64 = ls 82 var scanning: i64 = 1 83 while scanning == 1 { if lb == 0 { scanning = 0 } else { if cout[lb - 1] == (10 as u8) { scanning = 0 } else { lb = lb - 1 } } } 84 gv_check("T3 the LAST line (by position) is the subject's verdict line and reads verdict=GREEN" as *u8, alg_find(((cout as i64) + lb) as *u8, ls - lb, "verdict=GREEN" as *u8), ctr) 85 // T4 ARTIFACT IDENTITY: the confidence tooth exists only in the current miner generation 86 gv_check("T4 artifact identity: the association-rule confidence tooth is present (an older binary cannot pass)" as *u8, alg_find(cout, n, "confidence(M:x->N:y)" as *u8), ctr) 87 // T5 ARTIFACT IDENTITY, THIS GENERATION (2026-09-05): a ship reported SHIPPED with live_sha equal to the 88 // PREVIOUS promote while this gate read 6/6, because T4 pins a string BOTH generations carry. A gate that 89 // cannot tell the generation it was written for from its predecessor certifies the predecessor. The 90 // derived-index tooth exists only from the frame-count-sized build onward. 91 gv_check("T5 artifact identity, this generation: the derived-index tooth (T16 index sized from the frame count) is present" as *u8, alg_find(cout, n, "T16 index sized from the frame count" as *u8), ctr) 92 gv_check("neg-control-no-red: subject output carries no verdict=RED" as *u8, (alg_find(cout, n, "verdict=RED" as *u8) == 0) as i64, ctr) 93 gv_check("T6 non-vacuity: captured output is not empty (a dead fork cannot pass)" as *u8, (n > 0) as i64, ctr) 94 return gv_verdict("nx_actlog_gate" as *u8, ctr, "end-to-end: the subject's own selftest is the proof; T4 pins the tested bytes to the current miner generation" as *u8) 95}