code wiki / _hdl_build / nx_gatereg_derive.nx
nx_gatereg_derive.nx
buildroot/runtime/_hdl_build/nx_gatereg_derive.nx
about
nx_gatereg_derive.nx -- DERIVE the gate roster from the evidence itself.
WHY THIS EXISTS (measured 2026-07-30): knowledge/gatereg.conf listed FOUR gates while the same NAS
held 181 knowledge/status/*.log files. nx_gate_rollup can only roll up what the roster names, so
"verdict=GREEN pass=4/4" was a true statement about a roster that covered ~2% of the evidence -- a
green light with almost nothing behind it. Hand-maintaining that roster is why it never grew.
So: stop typing the roster, DERIVE it. A log whose newest line carries a verdict anchor IS a gate
log, by the gate plane's own contract; anything else (token_spend.log, resources.log, ...) is not
and is deliberately left out rather than registered as a permanent UNKNOWN.
READ-ONLY BY DEFAULT. It prints the split (green / red / no-anchor) and the candidate rows, and
writes a roster ONLY when given an explicit emit path. Registering a RED gate is correct -- that is
the point of surfacing -- but it flips the rollup RED and nx_gate_rollup AUTO-FILES a debt, so the
operator sees the count before that happens instead of after.
nx_gatereg_derive [statusdir] [emitpath]
statusdir default knowledge/status
emitpath if given, write "<BANNER>\t<path>" rows for every anchored log
The banner is a DISPLAY LABEL only -- nx_gate_rollup reads the log's last line and never compares
the banner -- so it is derived from the filename (stem uppercased, '_' -> '-') and cannot be wrong
in a way that changes a verdict.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict_lib.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
| 28 | const GD_STDOUT: i64 = 1 |
| 29 | const GD_MODE: i64 = 420 |
| 30 | const GD_DIRBUF: i64 = 262144 |
| 31 | const GD_ROWCAP: i64 = 262144 |
| 32 | const GD_PATHCAP: i64 = 1024 |
| 33 | const GD_DIR_TYPE: i64 = 4 |
| 38 | const GD_DEFAULT_MAX_AGE_DAYS: i64 = 30 |
| 44 | const GD_NUMBUF: i64 = 28 |
| 45 | const GD_ASCII_0: i64 = 48 |
| 46 | const GD_DEC: i64 = 10 |
functions
| 40 | func gd_puts(s: *u8) -> i64 { let n: i64 = gv_len(s); sys_write(GD_STDOUT, s, n); return 0 } |
| 43 | func gd_fputs(fd: i64, s: *u8) -> i64 { let n: i64 = gv_len(s); sys_write(fd, s, n); return 0 } |
| 48 | func gd_num(fd: i64, v: i64) -> i64 |
| 65 | func gd_is_log(nm: *u8, n: i64) -> i64 |
| 75 | func gd_join(dir: *u8, nm: *u8, out: *u8) -> i64 called by 1: main |
| 87 | func gd_banner(nm: *u8, n: i64, out: *u8) -> i64 |
| 104 | func gd_bcat(buf: *u8, off: i64, s: *u8) -> i64 called by 1: main |
| 111 | func gd_atoi(s: *u8) -> i64 called by 1: main |
| 122 | func main(argc: i64, argv: *i64) -> i64 |