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}