code wiki / _hdl_build / nx_gate_rollup.nx

nx_gate_rollup.nx source

↩ module page · 171 lines · 9348 B

1// nx_gate_rollup.nx -- ONE ANSWER TO "ARE ALL THE GATES GREEN?" (eats debt seq986). 2// 3// WHY THIS EXISTS (measured 2026-07-25): the tickless clock daemon dispatches gate jobs on schedule, but 4// clk_dispatch_run counts a job as dispatched whenever it merely RAN -- it never distinguishes exit 0 from 5// exit 1 and discards the child's stdout. So each gate now appends its own verdict to knowledge/status/ 6// <gate>.log. That made a RED DURABLE, but durable is not the same as SURFACED: a line in a file nobody 7// reads still fails silently. This organ is the reader. 8// 9// SURVEYED FIRST (operator standing instruction, don't duplicate): nx_ecosystem_maturity_rollup exists but 10// answers a DIFFERENT question from a DIFFERENT source (maturity depth x breadth from the ecomat seg_store 11// + autonomy ledger). nx_deploy_ready is a pre-deploy safety gate. Neither reads gate verdict logs. There 12// are 91 knowledge/status/*.log files and nothing rolls up their verdicts -- this is genuinely net-new. 13// 14// DATA-DRIVEN (rule 11): the roster lives in the plane `knowledge/store/gatereg-` as 15// id | gate-banner | log-path 16// so registering a new gate is a STORE ROW, not a rebuild of this organ. 17// 18// FAIL-CLOSED: a log that is MISSING, EMPTY, or whose newest line carries no verdict= is reported as 19// UNKNOWN and counted RED. "I could not tell" must never read as "fine" -- that is the whole failure mode 20// this organ exists to remove. 21// 22// D001: emits a `verdict=` anchor. license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 23import "nx_gate_lib.nx" 24import "nx_gate_verdict_lib.nx" 25import "nx_syscalls.nx" 26const GR_MAGIC_65536: i64 = 65536 27const GR_MAGIC_4096: i64 = 4096 28const GR_MAGIC_1024: i64 = 1024 29 30const GR_CONF: *u8 = "knowledge/gatereg.conf" 31const GR_LOGCAP: i64 = 262144 32const GR_EXIT_RED: i64 = 1 33 34// THE FOLD, COMPLETED (2026-07-31). gr_slurp/gr_last_line lived here as byte-identical twins of 35// nx_gate_verdict_lib's gv_slurp/gv_last_line while that lib was ALREADY imported above -- imported but 36// NOT ADOPTED, which is the worse half of a duplicate: it reads as done. The shared reader's fixes (both 37// anchor cases, the GREEN|PASS|VALID vocabulary) reached gv_is_pass here and could never reach the two 38// private copies, so this organ was 1/3 shared and 2/3 frozen -- a reader that disagrees with itself. 39// Deleted outright rather than aliased; all three call sites now route through the lib. 40 41func main(argc: i64, argv: *i64) -> i64 { 42 var conf: *u8 = GR_CONF 43 if argc >= 2 { conf = argv[1] as *u8 } 44 45 let counts: *i64 = sys_mmap(GL_SCRATCH) as *i64 46 counts[0] = 0 47 counts[1] = 0 48 let pb: *u8 = sys_mmap(GL_BUF) 49 var po: i64 = 0 50 51 let cbuf: *u8 = sys_mmap(GR_MAGIC_65536) 52 let cn: i64 = gv_slurp(conf, cbuf, GR_MAGIC_65536) 53 if cn <= 0 { 54 gl_puts("NX-GATE-ROLLUP\nverdict=RED pass=0/0 rule=gate-roster-absent conf=" as *u8) 55 gl_puts(conf) 56 gl_puts("\n" as *u8) 57 sys_exit(GR_EXIT_RED) 58 return GR_EXIT_RED 59 } 60 61 let lbuf: *u8 = sys_mmap(GR_LOGCAP) 62 let line: *u8 = sys_mmap(GR_MAGIC_4096) 63 let gname: *u8 = sys_mmap(256) 64 let lpath: *u8 = sys_mmap(GR_MAGIC_1024) 65 66 var p: i64 = 0 67 while p < cn { 68 // locate end of this conf line 69 var e: i64 = p 70 var scan: i64 = 1 71 while scan == 1 { 72 if e >= cn { scan = 0 } else { if cbuf[e] == (10 as u8) { scan = 0 } else { e = e + 1 } } 73 } 74 // skip comments and blanks 75 var use: i64 = 1 76 if e <= p { use = 0 } 77 if use == 1 { if cbuf[p] == (35 as u8) { use = 0 } } 78 if use == 1 { 79 // field 1 = gate banner, field 2 = log path, TAB separated 80 var t1: i64 = p 81 var s1: i64 = 1 82 while s1 == 1 { 83 if t1 >= e { s1 = 0 } else { if cbuf[t1] == (9 as u8) { s1 = 0 } else { t1 = t1 + 1 } } 84 } 85 if t1 < e { 86 var gi: i64 = 0 87 while p + gi < t1 { gname[gi] = cbuf[p+gi]; gi = gi + 1 } 88 gname[gi] = 0 as u8 89 var li: i64 = 0 90 while t1 + 1 + li < e { lpath[li] = cbuf[t1+1+li]; li = li + 1 } 91 lpath[li] = 0 as u8 92 93 // AN AGGREGATOR MUST NOT BE A MEMBER OF THE SET IT AGGREGATES (2026-07-30). 94 // This organ WRITES knowledge/status/gate_rollup.log, and nx_gatereg_derive registers ANY 95 // anchored log as a gate -- so the roster came to hold this organ's OWN previous output 96 // ('RED GATE-ROLLUP ... NX-GATE-ROLLUP verdict=RED pass=72/105' appeared inside a live run). 97 // Once RED, that row was itself one of the failing gates, so pass could NEVER reach total: 98 // a self-sustaining RED that survives fixing every real gate, and whose own row would be the 99 // last one standing. Excluded BY CONSTRUCTION here rather than by editing the roster, 100 // because the deriver would simply re-add it on the next sweep. 101 var selfrow: i64 = 0 102 let selfpath: *u8 = "knowledge/status/gate_rollup.log" as *u8 103 var sq: i64 = 0 104 var smatch: i64 = 1 105 while selfpath[sq] != (0 as u8) { 106 if lpath[sq] != selfpath[sq] { smatch = 0 } 107 sq = sq + 1 108 } 109 if smatch == 1 { if lpath[sq] == (0 as u8) { selfrow = 1 } } 110 if selfrow == 0 { 111 112 let ln: i64 = gv_slurp(lpath, lbuf, GR_LOGCAP) 113 let vn: i64 = gv_last_line(lbuf, ln, line, GR_MAGIC_4096) 114 counts[0] = counts[0] + 1 115 var ok: i64 = 0 116 // BOTH anchor cases. The ecosystem emits verdict= AND VERDICT= (deploy_ready, 117 // fin_spine_gate, coordination_gate, pm_dashboard_gate all use uppercase). Matching 118 // only lowercase made every uppercase-emitting gate read RED the instant it was 119 // registered -- and this organ AUTO-FILES a debt on RED, so the roster could not be 120 // grown without manufacturing false alarms. Case is a spelling detail, not a verdict. 121 // ONE reader for the pass vocabulary (nx_gate_verdict_lib.gv_is_pass): GREEN|PASS|VALID, 122 // either case. Keeping a private inline check here is what let this organ and the ecomat 123 // deriver disagree -- 73/105 vs 75/105 on the same logs, because spirv-style verdict=VALID 124 // gates read RED here and GREEN there. A shared vocabulary cannot drift; two cannot agree. 125 if vn > 0 { if gv_is_pass(line, vn) == 1 { ok = 1 } } 126 if ok == 1 { counts[1] = counts[1] + 1 } else { 127 po = gl_bcat(pb, po, "RED " as *u8) 128 po = gl_bcat(pb, po, gname) 129 po = gl_bcat(pb, po, " " as *u8) 130 if vn <= 0 { 131 po = gl_bcat(pb, po, "UNKNOWN-no-verdict-line " as *u8) 132 po = gl_bcat(pb, po, lpath) 133 } else { po = gl_bcat(pb, po, line) } 134 po = gl_bcat(pb, po, "\n" as *u8) 135 } 136 } 137 } 138 } 139 p = e + 1 140 } 141 142 gl_log("knowledge/status/gate_rollup.log" as *u8, "NX-GATE-ROLLUP" as *u8, counts) 143 144 // ---- THE ALERT LAYER (the 4th and last: dispatched -> recorded -> surfaced -> ALERTED) ---- 145 // Surfacing only helps someone who RUNS this. On RED, file a debt: `nx_seat boot` ALREADY reports 146 // open_debts + top_sev + top_debt at the start of every session, so the alert channel EXISTS and no new 147 // surface is invented (zero duplication -- the standing instruction). 148 // IDEMPOTENT BY CONSTRUCTION: nx_debt does exact-description dedup (DUPLICATE-SKIPPED, exit 0), so the 149 // description below is deliberately CONSTANT -- a persistent RED files ONCE, not once per hour. That is 150 // also why the description names WHERE to look rather than WHICH gate: embedding the failing gate would 151 // make the text vary, defeating the dedup and spamming the board every beat. 152 if counts[1] != counts[0] { 153 let dav: *i64 = sys_mmap(GL_AVCAP) as *i64 154 let dpath: *u8 = "/volume1/homes/elderwesto/nishihost/nx_debt.elf" as *u8 155 dav[0] = dpath as i64 156 dav[1] = "add" as *u8 as i64 157 dav[2] = "6" as *u8 as i64 158 dav[3] = "gate-red" as *u8 as i64 159 dav[4] = "NX-GATE-ROLLUP is RED: at least one regression gate is failing or has no recent verdict. Read knowledge/status/gate_rollup.log for the roll-up and the per-gate knowledge/status/*.log named in knowledge/gatereg.conf for which one. Filed automatically by the hourly gate-rollup beat; description is intentionally constant so nx_debt exact-desc dedup files it ONCE per outage rather than every hour. EAT THIS ROW once the gate is green again." as *u8 as i64 160 dav[5] = 0 161 let dout: *u8 = sys_mmap(GL_OUTCAP) 162 let dol: *i64 = sys_mmap(GL_SCRATCH) as *i64 163 let drc: i64 = tr_run_capture(dpath, dav, dout, GL_OUTCAP, dol) 164 gl_puts("alert=debt-filed rc=" as *u8) 165 gl_putn(drc) 166 gl_puts("\n" as *u8) 167 } 168 let rc: i64 = gl_verdict("NX-GATE-ROLLUP" as *u8, counts, "" as *u8, pb, po) 169 sys_exit(rc) 170 return rc 171}