code wiki / _hdl_build / nx_gate_roster_run.nx
nx_gate_roster_run.nx
buildroot/runtime/_hdl_build/nx_gate_roster_run.nx
about
nx_gate_roster_run.nx -- THE DATA-DRIVEN GATE ROSTER BEAT: run every gate named in a conf, on the
clock, with a deadline, and journal each verdict -- so a promoted gate nobody runs becomes a gate
whose verdict is COLLECTED, by adding ONE LINE OF DATA rather than a rebuild.
WHY (campaign lane B, 2026-08-18): nx_gateadjudicate measured 3,235 gate sources on the NAS,
919 promoted, and 780 DEPLOYED-DARK -- promoted binaries that no clock row, roster organ, .gates map,
gatereg row or MCP call ever runs. The estate's law: "a gate nobody runs does not degrade to
neutral -- it degrades to a false sense of coverage, because its existence is counted and its
verdict is not." The wiring vehicle that already exists, nx_gfx_gates_beat, is CORRECT in shape
(bounded runner, per-gate journal line, ABSENT reported never skipped) but its roster is EIGHT
NAMES IN CODE, so admitting a ninth gate is a rebuild. Rule 11/17: rosters are DATA. This organ is
that beat with the roster moved to a conf; nx_gfx_gates_beat is the precedent, not a duplicate --
its eight rows can migrate here whenever its owner chooses.
ROSTER CONF (default knowledge/gateroster.conf), one gate per line:
<gate-name> runs ./<gate-name>.elf from the estate root
; comment / blank ignored (also lines whose first byte is the hash mark)
A gate is ADMITTED to the conf only after a TRIAL run has come back GREEN or SKIP -- adoption is not
blind wiring, and this organ has a `trial` verb for exactly that:
nx_gate_roster_run REFUSED (exit 2): argless mutates NOTHING and prints
usage. The beat must NAME its verb -- every proof tool
in the estate probes an organ argless, so an argless
default that runs the beat makes this organ unprovable
and lets a staged binary write production state.
nx_gate_roster_run beat [conf] [journal] [ms] the beat. A conf OR journal other than the
production defaults writes its heartbeat BESIDE its own
journal (<journal>.stamp, announced) and never to the
cron-watched production stamp.
nx_gate_roster_run trial <listfile> [journal] [ms] run every gate in <listfile> ONCE, journal
under tag "trial"; exit 0 always (a trial
reports, it does not judge the fleet)
nx_gate_roster_run admit <journal> <deadline_ms> [conf] [suspectlist=<conf>.suspect]
The journal->conf bridge, so admission is MECHANICAL, never hand-filtered: take the LATEST
row per gate; GREEN/SKIP with ms < deadline_ms -> merge-ADD into the conf (additive, rule 13:
admission never removes -- a beat RED is an alarm to read, not a row to erase); GREEN with
ms >= deadline_ms -> SUSPECT, written to [suspectlist] and NOT admitted. The suspect class
exists because journals written before 2026-08-18 came from a runner that returned exit 0
for a watchdog-KILLED child, so a legacy at-deadline GREEN is a timeout wearing a pass; the
fixed runner reports 137 and those rows say TIMEOUT, making this class empty going forward.
deadline_ms is REQUIRED (it is the value the trial ran with, from its own header line) --
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_gatekit_lib.nxnx_estate_path.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 61 | const GRR_MS_DEFAULT: i64 = 60000 |
| 62 | const GRR_CAP: i64 = 65536 |
| 63 | const GRR_MODE: i64 = 420 // 0644 |
| 64 | const GRR_NICE: i64 = 10 |
| 65 | const GRR_SIGKILL_RC: i64 = 137 // 128+SIGKILL: what gk_run_capture_ms returns for a child its watchdog killed |
| 66 | const GRR_MAXG: i64 = 4096 |
| 67 | const GRR_SLOT: i64 = 128 |
| 68 | const GRR_LINE: i64 = 1400 // one journal line (epoch/tag/gate/verdict/exit/ms/reason) |
| 69 | const GRR_REASON_MAX: i64 = 240 // reason field cap; a truncated reason still names the cause |
| 70 | const GRR_MSG: i64 = 8192 // report buffers (admit summary, beat header/footer) |
| 71 | const GRR_CONF: *u8 = "knowledge/gateroster.conf" |
| 72 | const GRR_JRNL: *u8 = "knowledge/status/gateroster.jrnl" |
| 76 | const GRR_STAMP: *u8 = "knowledge/status/gateroster.stamp" |
| 94 | const GRR_DIRECTIVE_DISPATCH: *u8 = "@dispatch_deadline_ms" |
| 95 | const GRR_TAG_BEAT: *u8 = "roster" |
functions
| 97 | func grr_isid(c: i64) -> i64 called by 1: grr_load |
| 108 | func grr_slot(t: *u8, i: i64) -> *u8 { return ((t as i64) + i * GRR_SLOT) as *u8 } |
| 111 | func grr_load(path: *u8, tbl: *u8) -> i64 |
| 154 | func grr_directive_ms(path: *u8) -> i64 |
| 179 | func grr_lastrun(jrnl: *u8, tag: *u8, tbl: *u8, n: i64, last: *i64) -> i64 |
| 215 | func grr_order(last: *i64, n: i64, ord: *i64) -> i64 called by 1: main |
| 227 | func grr_one(name: *u8, tag: *u8, jfd: i64, ms: i64) -> i64 |
| 307 | func grr_num(s: *u8, off: i64, endp: *i64) -> i64 |
| 321 | func grr_runeq(b: *u8, rs: i64, re: i64, lit: *u8) -> i64 |
| 330 | func grr_admit(jrnl: *u8, dls: *u8, argc: i64, argv: *i64) -> i64 |
| 524 | func main(argc: i64, argv: *i64) -> i64 |