code wiki / _hdl_build / nx_gateadjudicate.nx
nx_gateadjudicate.nx source
↩ module page · 1329 lines · 70748 B
1// nx_gateadjudicate.nx -- THE GATE ADJUDICATION CENSUS: every gate source in the compile corpus, its
2// adoption ladder (file facts), the execution surfaces that name it, and the ONE remedy bucket it
3// falls in. Built for campaign lane B (2026-08-18): "2,287 uninvoked gate sources wire-or-retire,
4// 105 deployed-dark, 2,182 undeployed" -- numbers measured once on 2026-08-07 over ONE source
5// directory (2,317 gates) and later shown to understate the population by ~880 (nx_gatesubj on the
6// whole corpus: 3,194). A campaign that works a stale list re-investigates what is already fixed, so
7// step 0 of the lane is this instrument, re-runnable, full population, partition summed.
8//
9// WHAT ALREADY EXISTED (asked first -- nx_spendgate/nx_capsearch, 2026-08-18):
10// nx_gatesubj every gate's SUBJECT from its own source (the population enumerator; composed here
11// through the same gk_corpus_scan so the denominator cannot disagree)
12// nx_catalog PER-NAME adoption ladder (SOURCE.BUILT.STAGED.PROMOTED.REGISTERED.AUTHORISED.INVOKED)
13// -- its INVOKED axis is the MCP actlog only, and gates are mostly run by beats, so a
14// gate reads DARK there while a clock row runs it nightly
15// nx_wirecensus registered-but-never-called over the MCP surface (S4)
16// nx_gate_rollup reads knowledge/gatereg.conf rows -> knowledge/status/<gate>.log verdicts
17// nx_gatebuilt_gate authored-vs-compiled census (prints a bounded list, no partition)
18// None joins the GATE population to the surfaces that CAUSE EXECUTION. That join is this organ.
19//
20// THE EDGE DEFINITION IS THE QUESTION (measured 08-07: four definitions gave 75 / 0 / 2,043 / 30).
21// A gate counts as INVOKED only through a surface that runs it or collects its verdict:
22// CLOCK its own .elf is the organ of a clock row, OR its name appears in that row's ARGUMENTS
23// (clocksched- live, clockjobs- desired; measured: rows like `nx_sov_build_run.elf <gate>`
24// and `nx_law_warden.elf scan` carry args, so the organ column is split at its first space)
25// ROSTER its name is MENTIONED inside the source of an organ that IS on the clock (2-hop, e.g.
26// nx_estate_census_run -> nx_gatesubj.elf; nx_gfx_gates_beat -> "nx_gltf_load_gate"+".elf",
27// so the match is the identifier, not the .elf literal), or inside an organ listed in
28// knowledge/gateadjudicate_rosters.conf (off-host rosters such as the laptop's
29// nx_memplane_run, declared as DATA -- never a name baked in here)
30// GATES a knowledge/compare/*.gates row (the executed-evidence map nx_swcompare_evidence runs)
31// GATEREG a knowledge/gatereg.conf row (nx_gate_rollup collects its verdict)
32// GROSTER a knowledge/gateroster.conf row -- the data-driven roster nx_gate_roster_run runs on the
33// clock; counted as a surface ONLY while nx_gate_roster_run itself is a roster organ (on the
34// clock or in the rosters conf), otherwise the conf is a list nothing executes and is NOT
35// credited (printed as groster_inert=1 so the reader sees the missing clock row)
36// ACTLOG an MCP invocation on record in knowledge/status/actlog.jrnl (tail window, declared)
37// A mere MENTION of <gate>.elf in some other source is recorded as REF (something wants it) but is
38// NOT invocation -- report generators name their findings, and that class contaminated three
39// measurements in one hour on 08-07. ★ AN UNSTAMPED REPORT IS INDISTINGUISHABLE FROM A REGISTRY.
40// TRIAL the LATEST row for the gate in knowledge/status/gateroster.jrnl (nx_gate_roster_run's journal:
41// trial or beat). NOT a surface -- it is the REASON that travels with DEPLOYED-DARK: a dark gate
42// that has been trialed and FAILED (RED/ABSENT/TIMEOUT) is a defect worklist, not a wiring
43// worklist, and a dark gate that trialed GREEN/SKIP is one `admit` away from LIVE. The bucket
44// stays DEPLOYED-DARK (the partition does not change); the sub-counts split it by remedy.
45// BTRIAL same, from knowledge/status/gatebuild.jrnl -- the BUILT-ARTIFACT sweep lane: trials run the
46// gate's buildroot/_build/<n>.sov.elf IN PLACE (no promote, nothing deployed), so the
47// 2,181-strong BUILT-UNPROMOTED class can be adjudicated on EVIDENCE (passing = a promote
48// candidate, failing = fix-or-retire) instead of by a mass action the record forbids.
49// LOG (a knowledge/status/*.log the gate writes, with its age) is EVIDENCE it once ran, not a surface.
50// ⚠ LOG NAMES DROP THE ORGAN PREFIX: nx_p384_ecdh_gate writes p384_ecdh_gate.log, _mmu_gate writes
51// mmu.log (measured 2026-08-18 against knowledge/gatereg.conf, which is DERIVED from those logs). So a
52// log/gatereg row matches gate <n> when its basename equals <n> minus a leading "nx_" or "_" (STEM),
53// (or the full name), or -- only when no gate matches exactly AND no non-gate ORGAN of that stem exists in
54// the corpus -- STEM minus a trailing "_gate". Measured 2026-08-18 without that second guard: resmon.log,
55// shipcheck.log, asset_access.log (ORGAN status logs, whose verdict= lines the rollup collects on the
56// organ's behalf) were credited to nx_resmon_gate / nx_shipcheck_gate / nx_asset_access_gate and made
57// 50+ dark gates read as "ran today". ★ A LOG NAMED FOR THE SUBJECT IS THE SUBJECT'S LOG, NOT ITS GATE'S.
58// A log that then matches more than one gate is counted AMBIGUOUS and printed, not silently credited to both.
59//
60// LADDER (file facts, the same paths nx_catalog stats):
61// SRC hdl|rt . BUILT buildroot/_build/<n>.sov.elf . STAGED <n>.sov.elf.new .
62// PROMOTED <n>.elf | _offc/<n>.elf | buildroot/_offc/<n>.elf . REG tool_allowlist.conf field 0
63//
64// THE PARTITION (one bucket per gate, remedies differ, sum printed and checked):
65// LIVE invoked AND promoted -> nothing to do (verdict is collected)
66// INVOKED-MISSING invoked AND NOT promoted -> an invocation GAP: build+promote
67// DEPLOYED-DARK promoted, NOT invoked -> wire to a roster (or retire the binary)
68// BUILT-UNPROMOTED built, not promoted, not invoked -> promote or retire the build
69// SOURCE-ONLY no artifact, not invoked -> REFERENCED (ref>0: something names it,
70// adjudicate) | UNREFERENCED (nothing in the corpus names it: retire candidate)
71// ★★★★★ "94% NOT DEPLOYED" IS A HEADLINE; A SUMMED PARTITION BY REMEDY IS A DECISION.
72//
73// DECLARED BLIND SPOTS (printed every run, so a reader never mistakes them for zero):
74// - laptop hooks / laptop rosters are not on this host; declare them in the rosters conf.
75// - ACTLOG is a tail window of GA_ACT_TAIL bytes; older invocations are invisible.
76// - a ROSTER edge is 2-hop and static: the organ names the .elf; whether that code path runs is
77// the organ's business. It is still a surface that CAN cause execution, unlike a report.
78//
79// usage: nx_gateadjudicate [--rows <path>] [--list <CLASS> <path>] [--estate <dir>]
80// --list <CLASS> <path> (repeatable, up to GA_MAXLISTS per run) write the gate NAMES of one bucket, one per line, in nx_gate_roster_run's
81// roster/trial format -- path-qualified when the binary is not at the estate
82// root (`_offc/<n>`, `buildroot/_offc/<n>`), because the runner execs
83// ./<row>.elf and a bare name for an _offc-only gate journals ABSENT (measured
84// on trial 1: promoted gates reported ABSENT purely from the row's spelling).
85// roster/trial format (CLASS = LIVE | INVOKED-MISSING | DEPLOYED-DARK |
86// BUILT-UNPROMOTED | SOURCE-ONLY | DARK-UNTRIED | DARK-PASSING | DARK-FAILING) --
87// the last three are DEPLOYED-DARK split by its TRIAL axis, and LIVE-FAILING is the
88// LIVE gates whose latest roster/trial row is RED/ABSENT/TIMEOUT -- collected AND read,
89// which is the whole point of wiring; a trial list is emitted by the census
90// itself, never hand-filtered from its rows. A SOURCE-ONLY list WITHHOLDS
91// gates whose source was modified today (src_age_d == 0) and prints how many:
92// that list feeds a reversible-retire campaign, and the estate's measured law
93// is that a fresh artifact can be ANOTHER SEAT'S WORK IN FLIGHT -- the guard
94// belongs in the emitter, not in the operator's memory
95// --rows <path> write one row per gate: name|src|src_age_d|built|staged|prom|reg|clock|roster|gates|gatereg|groster|act|log|logage_d|ref|first_ref|trial|class
96// (always) a CLUSTER table: gates grouped by their first name token after the prefix, one line per
97// cluster with its bucket counts, sorted by UNINVOKED desc -- the campaign is worked per cluster,
98// never per row, because a shared cause reports once per consumer.
99// --estate <dir> chdir here instead of ep_anchor() (laptop smoke; the census is about the NAS estate)
100// exit: 0 census printed . 1 REFUSED (corpus/table cap or unreadable tree -- never a truncated census)
101// 3 UNOBSERVABLE (no estate root on this host)
102// Appends ONE line per run to knowledge/status/gateadjudicate.log (a level cannot express a trend).
103// license_tier: ORIGINAL Read-only over the estate except its own two artifacts. No hw writes (Rule 26).
104import "nx_gatekit_lib.nx"
105import "nx_estate_path.nx"
106import "nx_clock_sched.nx"
107
108const GA_MAXF: i64 = 32768 // corpus files (gk_corpus_scan REFUSES past this, never truncates)
109const GA_SLOT: i64 = 192 // bytes per corpus path slot
110const GA_MAXG: i64 = 6144 // gates the table holds (REFUSE past it -- a silent cap is a smaller number that reads as better news)
111const GA_GSLOT: i64 = 128 // bytes per gate name
112const GA_MSG: i64 = 65536
113const GA_ROWCAP: i64 = 4194304 // rows artifact; refuse if exceeded
114const GA_ACT_TAIL: i64 = 4194304 // actlog tail window (DECLARED: older invocations invisible)
115const GA_STATBUF: i64 = 256
116const GA_MTIME_OFF: i64 = 88 // x86_64 struct stat: st_mtim.tv_sec
117const GA_SEC_PER_DAY: i64 = 86400
118const GA_MAXCLK: i64 = 512 // clock/roster organ basenames (live + desired planes + conf)
119const GA_MAXCLU: i64 = 4096 // distinct cluster keys (a full table prints FLOOR, never silently stops counting)
120const GA_MAXLISTS: i64 = 8 // --list specs accepted per run (a clock row emits several worklists in one pass)
121const GA_CLUSHOW: i64 = 60 // cluster lines printed (the rest are in the rows artifact; the count of hidden clusters is printed)
122const GA_LOG: *u8 = "knowledge/status/gateadjudicate.log"
123const GA_ROSTERS: *u8 = "knowledge/gateadjudicate_rosters.conf"
124const GA_ALLOW: *u8 = "tool_allowlist.conf"
125const GA_GATEREG: *u8 = "knowledge/gatereg.conf"
126const GA_GROSTER: *u8 = "knowledge/gateroster.conf"
127const GA_ROSTJRNL: *u8 = "knowledge/status/gateroster.jrnl"
128const GA_BUILDJRNL: *u8 = "knowledge/status/gatebuild.jrnl"
129const GA_BUILT_PREFIX: *u8 = "buildroot/_build/"
130const GA_BUILT_SUFFIX: *u8 = ".sov"
131const GA_ACTLOG: *u8 = "knowledge/status/actlog.jrnl"
132const GA_STATUS: *u8 = "knowledge/status/"
133const GA_CMP1: *u8 = "knowledge/compare/"
134const GA_CMP2: *u8 = "buildroot/knowledge/compare/"
135const GA_CLK_LIVE: *u8 = "knowledge/store/clocksched-"
136const GA_CLK_WANT: *u8 = "knowledge/store/clockjobs-"
137
138// ---- small helpers -------------------------------------------------------------------------------
139
140func ga_isid(c: i64) -> i64 {
141 if c >= 97 { if c <= 122 { return 1 } }
142 if c >= 65 { if c <= 90 { return 1 } }
143 if c >= 48 { if c <= 57 { return 1 } }
144 if c == 95 { return 1 }
145 return 0
146}
147
148// does NUL-terminated s end with NUL-terminated suf?
149func ga_endswith(s: *u8, suf: *u8) -> i64 {
150 let l: i64 = gk_len(s)
151 let k: i64 = gk_len(suf)
152 if k > l { return 0 }
153 var i: i64 = 0
154 while i < k { if s[l - k + i] != suf[i] { return 0 } i = i + 1 }
155 return 1
156}
157
158// pointer to the basename of a NUL-terminated path
159func ga_base(p: *u8) -> *u8 {
160 var bo: i64 = 0
161 var i: i64 = 0
162 while p[i] != (0 as u8) { if p[i] == (47 as u8) { bo = i + 1 } i = i + 1 }
163 return ((p as i64) + bo) as *u8
164}
165
166func ga_gslot(g: *u8, i: i64) -> *u8 { return ((g as i64) + i * GA_GSLOT) as *u8 }
167func ga_cslot(names: *u8, i: i64) -> *u8 { return ((names as i64) + i * GA_SLOT) as *u8 }
168
169// compare a byte run [p, p+n) against NUL-terminated s
170func ga_eqrun(s: *u8, p: *u8, n: i64) -> i64 {
171 var i: i64 = 0
172 while i < n { if s[i] == (0 as u8) { return 0 } if s[i] != p[i] { return 0 } i = i + 1 }
173 if s[i] != (0 as u8) { return 0 }
174 return 1
175}
176
177// linear lookup of a byte run in the gate table; -1 if absent. (3k names x few hits per file --
178// the scan is dominated by bytes read, not by this loop.)
179func ga_find(gn: *u8, ng: i64, p: *u8, n: i64) -> i64 {
180 var i: i64 = 0
181 while i < ng { if ga_eqrun(ga_gslot(gn, i), p, n) == 1 { return i } i = i + 1 }
182 return 0 - 1
183}
184
185// mtime (epoch seconds) of a path, or -1
186func ga_mtime(path: *u8, sb: *u8) -> i64 {
187 if sys_fstatat(path, sb) != 0 { return 0 - 1 }
188 var v: i64 = 0
189 var i: i64 = 7
190 while i >= 0 { v = (v << 8) | (sb[GA_MTIME_OFF + i] as i64); i = i - 1 }
191 return v
192}
193
194// append one NUL-terminated line to a file (create 0644 if absent)
195func ga_appendline(path: *u8, line: *u8) -> i64 {
196 let fd: i64 = sys_openat_append(path, 420)
197 if fd < 0 { return 0 - 1 }
198 let n: i64 = gk_len(line)
199 let w: i64 = gk_write_all(fd, line, n)
200 sys_close(fd)
201 return w
202}
203
204// Scan a byte buffer for identifier runs that end in "_gate" and are followed by `after` (".elf",
205// or NUL for "any delimiter"); each hit resolves against the gate table and marks flag[g] (and
206// counts into cnt[g] when cnt is non-null, recording the first referrer index in first[g]).
207// `self` (may be -1) is never marked -- an organ naming its own basename is not a reference.
208func ga_scan_buf(buf: *u8, n: i64, gn: *u8, ng: i64, flag: *i64, cnt: *i64, first: *i64, refidx: i64, self: i64, want_elf: i64) -> i64 {
209 var hits: i64 = 0
210 var i: i64 = 0
211 while i < n {
212 // find the end of an identifier run
213 if ga_isid(buf[i] as i64) == 1 {
214 var e: i64 = i
215 var fin: i64 = 0
216 while fin == 0 {
217 if e >= n { fin = 1 }
218 if fin == 0 { if ga_isid(buf[e] as i64) == 1 { e = e + 1 } else { fin = 1 } }
219 }
220 // run is [i, e)
221 var take: i64 = 0
222 if e - i >= 6 {
223 if buf[e - 5] == (95 as u8) { if buf[e - 4] == (103 as u8) { if buf[e - 3] == (97 as u8) { if buf[e - 2] == (116 as u8) { if buf[e - 1] == (101 as u8) { take = 1 } } } } }
224 }
225 if take == 1 {
226 if want_elf == 1 {
227 take = 0
228 if e + 4 <= n {
229 if buf[e] == (46 as u8) { if buf[e + 1] == (101 as u8) { if buf[e + 2] == (108 as u8) { if buf[e + 3] == (102 as u8) { take = 1 } } } }
230 }
231 }
232 }
233 if take == 1 {
234 let g: i64 = ga_find(gn, ng, ((buf as i64) + i) as *u8, e - i)
235 if g >= 0 {
236 if g != self {
237 flag[g] = 1
238 if cnt != (0 as *i64) {
239 if cnt[g] == 0 { first[g] = refidx }
240 cnt[g] = cnt[g] + 1
241 }
242 hits = hits + 1
243 }
244 }
245 }
246 i = e
247 }
248 i = i + 1
249 }
250 return hits
251}
252
253// STEM of a gate name: minus a leading "nx_" or "_". Returns the offset into the name.
254func ga_stemoff(nm: *u8) -> i64 {
255 if nm[0] == (110 as u8) { if nm[1] == (120 as u8) { if nm[2] == (95 as u8) { return 3 } } }
256 if nm[0] == (95 as u8) { return 1 }
257 return 0
258}
259
260// Match a log/gatereg basename run [p,p+n) against the gate table by STEM, then by STEM minus "_gate"
261// (fallback only when no exact stem matched). Marks flag[g] for every match; returns the number of
262// gates matched (0, 1, or >1 = ambiguous).
263// compare cb[off .. off+n) with p[0..n) (no terminator requirement on cb beyond the run)
264func ga_eqrun_n(cb: *u8, off: i64, p: *u8, n: i64) -> i64 {
265 var k: i64 = 0
266 while k < n { if cb[off + k] != p[k] { return 0 } k = k + 1 }
267 return 1
268}
269
270// does the compile corpus hold a source whose basename is <pre><run>.nx, for pre in {nx_, _, ""}?
271func ga_organ_exists(names: *u8, scanned: i64, p: *u8, n: i64) -> i64 {
272 var i: i64 = 0
273 while i < scanned {
274 let cb: *u8 = ga_base(ga_cslot(names, i))
275 let bl: i64 = gk_len(cb) - 3 // minus ".nx"
276 var hit: i64 = 0
277 if bl == n { if ga_eqrun_n(cb, 0, p, n) == 1 { hit = 1 } }
278 if hit == 0 { if bl == n + 3 { if cb[0] == (110 as u8) { if cb[1] == (120 as u8) { if cb[2] == (95 as u8) { if ga_eqrun_n(cb, 3, p, n) == 1 { hit = 1 } } } } } }
279 if hit == 0 { if bl == n + 1 { if cb[0] == (95 as u8) { if ga_eqrun_n(cb, 1, p, n) == 1 { hit = 1 } } } }
280 if hit == 1 { return 1 }
281 i = i + 1
282 }
283 return 0
284}
285
286func ga_logmatch(gn: *u8, ng: i64, p: *u8, n: i64, flag: *i64, lastg: *i64, names: *u8, scanned: i64) -> i64 {
287 var matched: i64 = 0
288 var i: i64 = 0
289 while i < ng {
290 let nm: *u8 = ga_gslot(gn, i)
291 let so: i64 = ga_stemoff(nm)
292 var hit: i64 = 0
293 if ga_eqrun(((nm as i64) + so) as *u8, p, n) == 1 { hit = 1 }
294 if hit == 0 { if ga_eqrun(nm, p, n) == 1 { hit = 1 } }
295 if hit == 1 { flag[i] = 1; lastg[0] = i; matched = matched + 1 }
296 i = i + 1
297 }
298 if matched > 0 { return matched }
299 // fallback: stem minus trailing "_gate" (5 bytes) -- ONLY when no non-gate organ owns that stem
300 if ga_organ_exists(names, scanned, p, n) == 1 { return 0 }
301 i = 0
302 while i < ng {
303 let nm: *u8 = ga_gslot(gn, i)
304 let so: i64 = ga_stemoff(nm)
305 let sl: i64 = gk_len(nm) - so
306 if sl > 5 {
307 if ga_endswith(nm, "_gate" as *u8) == 1 {
308 if sl - 5 == n {
309 var eq: i64 = 1
310 var k: i64 = 0
311 while k < n { if nm[so + k] != p[k] { eq = 0; k = n } else { k = k + 1 } }
312 if eq == 1 { flag[i] = 1; lastg[0] = i; matched = matched + 1 }
313 }
314 }
315 }
316 i = i + 1
317 }
318 return matched
319}
320
321// Walk one directory; for every regular entry whose name ends with `ext`, mark the gate named by the
322// entry (mode 1: entry basename minus ext IS the gate name -> flag + age) or scan the file's rows for
323// <gate>.elf literals (mode 2: .gates maps). Returns entries examined, or -1 if the dir is unopenable.
324func ga_dirpass(dir: *u8, ext: *u8, mode: i64, gn: *u8, ng: i64, flag: *i64, age: *i64, now: i64, sb: *u8, ambig: *i64, names: *u8, scanned: i64) -> i64 {
325 let fd: i64 = sys_openat_rd(dir)
326 if fd < 0 { return 0 - 1 }
327 let gbuf: *u8 = sys_mmap(65536)
328 let path: *u8 = sys_mmap(4096)
329 let nm2: *u8 = sys_mmap(512)
330 let lenp: *i64 = sys_mmap(16) as *i64
331 var seen: i64 = 0
332 var nread: i64 = __syscall(217, fd, gbuf, 65536, 0, 0, 0)
333 while nread > 0 {
334 var off: i64 = 0
335 while off < nread {
336 let reclen: i64 = (gbuf[off + 16] as i64) | ((gbuf[off + 17] as i64) << 8)
337 if reclen <= 0 { off = nread }
338 if reclen > 0 {
339 let nm: *u8 = ((gbuf as i64) + off + 19) as *u8
340 if ga_endswith(nm, ext) == 1 {
341 seen = seen + 1
342 var po: i64 = gk_cat(path, 0, dir)
343 po = gk_cat(path, po, nm)
344 path[po] = 0 as u8
345 if mode == 1 {
346 // knowledge/status/<stem>.log -> evidence + age (stem rule, see header)
347 let l: i64 = gk_len(nm)
348 let k: i64 = gk_len(ext)
349 var q: i64 = 0
350 while q < l - k { nm2[q] = nm[q]; q = q + 1 }
351 nm2[q] = 0 as u8
352 let lastg: *i64 = sys_mmap(8) as *i64
353 lastg[0] = 0 - 1
354 let m: i64 = ga_logmatch(gn, ng, nm2, l - k, flag, lastg, names, scanned)
355 if m > 1 { ambig[0] = ambig[0] + 1 }
356 if m >= 1 {
357 let mt: i64 = ga_mtime(path, sb)
358 // age is recorded on the last matched gate; an ambiguous log's age is
359 // still a real mtime, so record it rather than -1
360 if mt > 0 { age[lastg[0]] = (now - mt) / GA_SEC_PER_DAY }
361 if mt <= 0 { age[lastg[0]] = 0 - 1 }
362 }
363 }
364 if mode == 2 {
365 let b: *u8 = sys_read_file(path, lenp)
366 if lenp[0] > 0 {
367 ga_scan_buf(b, lenp[0], gn, ng, flag, 0 as *i64, 0 as *i64, 0, 0 - 1, 1)
368 sys_free_file(b, lenp[0])
369 }
370 }
371 }
372 off = off + reclen
373 }
374 }
375 nread = __syscall(217, fd, gbuf, 65536, 0, 0, 0)
376 }
377 sys_close(fd)
378 return seen
379}
380
381// Load one clock plane and (a) mark gates whose own .elf is an organ column, (b) append every organ
382// basename (minus .elf) to the roster table. Returns rows loaded (0 if the plane is empty/absent).
383func ga_clockpass(prefix: *u8, gn: *u8, ng: i64, g_clock: *i64, ros: *u8, nros: *i64) -> i64 {
384 let names: *u8 = sys_mmap(CLK_MAXJOBS * CLK_NAMEW)
385 let orgs: *u8 = sys_mmap(CLK_MAXJOBS * CLK_NAMEW)
386 let iv: *i64 = sys_mmap(CLK_MAXJOBS * 8) as *i64
387 let nd: *i64 = sys_mmap(CLK_MAXJOBS * 8) as *i64
388 let np: *i64 = sys_mmap(8) as *i64
389 np[0] = 0
390 let r: i64 = clk_load_plane(prefix, names, orgs, iv, nd, np)
391 if r <= 0 { return 0 }
392 let first: *u8 = sys_mmap(CLK_NAMEW + 8)
393 var i: i64 = 0
394 while i < np[0] {
395 let org: *u8 = clk_slot(orgs, i)
396 // the organ column is "<path> [args...]": the FIRST TOKEN is the organ, the rest are its args
397 var fl: i64 = 0
398 var ff: i64 = 0
399 while ff == 0 {
400 if org[fl] == (0 as u8) { ff = 1 }
401 if ff == 0 { if org[fl] == (32 as u8) { ff = 1 } else { if fl < CLK_NAMEW { first[fl] = org[fl] } fl = fl + 1 } }
402 }
403 first[fl] = 0 as u8
404 let base: *u8 = ga_base(first)
405 // strip a trailing ".elf" and then a trailing ".sov" for the name comparison
406 let l: i64 = gk_len(base)
407 var nl: i64 = l
408 if ga_endswith(base, ".elf" as *u8) == 1 { nl = l - 4 }
409 if nl > 4 { if base[nl - 4] == (46 as u8) { if base[nl - 3] == (115 as u8) { if base[nl - 2] == (111 as u8) { if base[nl - 1] == (118 as u8) { nl = nl - 4 } } } } }
410 // (a) direct: the gate's own elf is scheduled, or a gate is named in the row's ARGUMENTS
411 let g: i64 = ga_find(gn, ng, base, nl)
412 if g >= 0 { g_clock[g] = 1 }
413 if org[fl] == (32 as u8) { ga_scan_buf(((org as i64) + fl) as *u8, gk_len(org) - fl, gn, ng, g_clock, 0 as *i64, 0 as *i64, 0, 0 - 1, 0) }
414 // (b) roster table entry (dedup by exact name)
415 var dup: i64 = 0
416 var j: i64 = 0
417 while j < nros[0] { if ga_eqrun(ga_gslot(ros, j), base, nl) == 1 { dup = 1 } j = j + 1 }
418 if dup == 0 {
419 if nros[0] < GA_MAXCLK {
420 let dst: *u8 = ga_gslot(ros, nros[0])
421 var q: i64 = 0
422 while q < nl { if q < GA_GSLOT - 1 { dst[q] = base[q] } q = q + 1 }
423 if q > GA_GSLOT - 1 { q = GA_GSLOT - 1 }
424 dst[q] = 0 as u8
425 nros[0] = nros[0] + 1
426 }
427 }
428 i = i + 1
429 }
430 return np[0]
431}
432
433// Read the off-host roster conf (one organ basename per line, comments with a leading semicolon or
434// blank lines ignored) into the roster table. Returns lines adopted, or -1 if the conf is absent.
435func ga_rosterconf(path: *u8, ros: *u8, nros: *i64) -> i64 {
436 let lenp: *i64 = sys_mmap(16) as *i64
437 let b: *u8 = sys_read_file(path, lenp)
438 if lenp[0] <= 0 { return 0 - 1 }
439 let n: i64 = lenp[0]
440 var adopted: i64 = 0
441 var i: i64 = 0
442 while i < n {
443 let e: i64 = gk_eol(b, i, n)
444 // a line whose first non-blank byte is ';' (59) or the hash mark (35) is a comment: skip it,
445 // else the first word of the comment would be adopted as a roster organ (measured on the
446 // laptop smoke: "; off-host rosters" adopted `off`).
447 var c0: i64 = i
448 var fc: i64 = 0
449 while fc == 0 {
450 if c0 >= e { fc = 1 }
451 if fc == 0 { if b[c0] == (32 as u8) { c0 = c0 + 1 } else { fc = 1 } }
452 }
453 var skip: i64 = 0
454 if c0 < e { if b[c0] == (59 as u8) { skip = 1 } }
455 if c0 < e { if b[c0] == (35 as u8) { skip = 1 } }
456 if skip == 1 { c0 = e }
457 // trim: identifier run only
458 var s: i64 = c0
459 var f1: i64 = 0
460 while f1 == 0 {
461 if s >= e { f1 = 1 }
462 if f1 == 0 { if ga_isid(b[s] as i64) == 1 { f1 = 1 } else { s = s + 1 } }
463 }
464 var t: i64 = s
465 var f2: i64 = 0
466 while f2 == 0 {
467 if t >= e { f2 = 1 }
468 if f2 == 0 { if ga_isid(b[t] as i64) == 1 { t = t + 1 } else { f2 = 1 } }
469 }
470 if t > s {
471 if nros[0] < GA_MAXCLK {
472 let dst: *u8 = ga_gslot(ros, nros[0])
473 var q: i64 = 0
474 while q < t - s { if q < GA_GSLOT - 1 { dst[q] = b[s + q] } q = q + 1 }
475 if q > GA_GSLOT - 1 { q = GA_GSLOT - 1 }
476 dst[q] = 0 as u8
477 nros[0] = nros[0] + 1
478 adopted = adopted + 1
479 }
480 }
481 i = e + 1
482 }
483 sys_free_file(b, n)
484 return adopted
485}
486
487// roster-journal pass: knowledge/status/gateroster.jrnl rows are `epoch TAB tag TAB gate TAB verdict TAB
488// exit=N TAB ms=N`; the LATEST row per gate wins (append-only journal). Writes trial[g] = 1 GREEN . 2 SKIP
489// . 3 RED . 4 ABSENT . 5 TIMEOUT (0 = never trialed). The gate field may be path-qualified
490// (`_offc/<n>`): only the basename is matched. Returns rows read, or -1 if the journal is absent.
491func ga_jrnleq(b: *u8, rs: i64, re: i64, lit: *u8) -> i64 {
492 let l: i64 = gk_len(lit)
493 if re - rs != l { return 0 }
494 var k: i64 = 0
495 while k < l { if b[rs + k] != lit[k] { return 0 } k = k + 1 }
496 return 1
497}
498func ga_jrnlpass(path: *u8, gn: *u8, ng: i64, trial: *i64) -> i64 {
499 let lenp: *i64 = sys_mmap(16) as *i64
500 let b: *u8 = sys_read_file(path, lenp)
501 if lenp[0] <= 0 { return 0 - 1 }
502 let n: i64 = lenp[0]
503 var rows: i64 = 0
504 var i: i64 = 0
505 while i < n {
506 let e: i64 = gk_eol(b, i, n)
507 var f: i64 = 0
508 var fs: i64 = i
509 var gs: i64 = 0
510 var ge: i64 = 0
511 var vs: i64 = 0
512 var ve: i64 = 0
513 var t: i64 = i
514 while t <= e {
515 var atend: i64 = 0
516 if t == e { atend = 1 }
517 if atend == 0 { if b[t] == (9 as u8) { atend = 1 } }
518 if atend == 1 {
519 if f == 2 { gs = fs; ge = t }
520 if f == 3 { vs = fs; ve = t }
521 f = f + 1
522 fs = t + 1
523 }
524 t = t + 1
525 }
526 if ge > gs { if ve > vs {
527 rows = rows + 1
528 // basename of the gate field, minus a trailing .elf
529 var bs: i64 = gs
530 var q: i64 = gs
531 while q < ge { if b[q] == (47 as u8) { bs = q + 1 } q = q + 1 }
532 var be: i64 = ge
533 if be - bs > 4 { if b[be - 4] == (46 as u8) { if b[be - 3] == (101 as u8) { if b[be - 2] == (108 as u8) { if b[be - 1] == (102 as u8) { be = be - 4 } } } } }
534 // built-sweep rows are spelled `buildroot/_build/<n>.sov` -- strip the .sov the same way
535 if be - bs > 4 { if b[be - 4] == (46 as u8) { if b[be - 3] == (115 as u8) { if b[be - 2] == (111 as u8) { if b[be - 1] == (118 as u8) { be = be - 4 } } } } }
536 let g: i64 = ga_find(gn, ng, ((b as i64) + bs) as *u8, be - bs)
537 if g >= 0 {
538 var v: i64 = 0
539 if ga_jrnleq(b, vs, ve, "GREEN" as *u8) == 1 { v = 1 }
540 if ga_jrnleq(b, vs, ve, "SKIP" as *u8) == 1 { v = 2 }
541 if ga_jrnleq(b, vs, ve, "RED" as *u8) == 1 { v = 3 }
542 if ga_jrnleq(b, vs, ve, "ABSENT" as *u8) == 1 { v = 4 }
543 if ga_jrnleq(b, vs, ve, "TIMEOUT" as *u8) == 1 { v = 5 }
544 trial[g] = v
545 }
546 } }
547 i = e + 1
548 }
549 sys_free_file(b, n)
550 return rows
551}
552
553// gateroster pass: every non-comment first-word of knowledge/gateroster.conf that names a gate marks
554// GROSTER (rows may carry a trailing ".elf" or an "_offc/" prefix, both stripped). Returns rows matched,
555// or -1 if the conf is absent.
556func ga_grosterpass(path: *u8, gn: *u8, ng: i64, flag: *i64) -> i64 {
557 let lenp: *i64 = sys_mmap(16) as *i64
558 let b: *u8 = sys_read_file(path, lenp)
559 if lenp[0] <= 0 { return 0 - 1 }
560 let n: i64 = lenp[0]
561 var hits: i64 = 0
562 var i: i64 = 0
563 while i < n {
564 let e: i64 = gk_eol(b, i, n)
565 var c0: i64 = i
566 var fc: i64 = 0
567 while fc == 0 {
568 if c0 >= e { fc = 1 }
569 if fc == 0 { if b[c0] == (32 as u8) { c0 = c0 + 1 } else { fc = 1 } }
570 }
571 var skip: i64 = 0
572 if c0 >= e { skip = 1 }
573 if skip == 0 { if b[c0] == (59 as u8) { skip = 1 } }
574 if skip == 0 { if b[c0] == (35 as u8) { skip = 1 } }
575 if skip == 0 {
576 // token: up to space or eol; then strip a leading path (after last '/') and a trailing .elf
577 var t: i64 = c0
578 var ft: i64 = 0
579 while ft == 0 {
580 if t >= e { ft = 1 }
581 if ft == 0 { if b[t] == (32 as u8) { ft = 1 } else { t = t + 1 } }
582 }
583 var bs: i64 = c0
584 var q: i64 = c0
585 while q < t { if b[q] == (47 as u8) { bs = q + 1 } q = q + 1 }
586 var be: i64 = t
587 if be - bs > 4 { if b[be - 4] == (46 as u8) { if b[be - 3] == (101 as u8) { if b[be - 2] == (108 as u8) { if b[be - 1] == (102 as u8) { be = be - 4 } } } } }
588 if be > bs {
589 let g: i64 = ga_find(gn, ng, ((b as i64) + bs) as *u8, be - bs)
590 if g >= 0 { flag[g] = 1; hits = hits + 1 }
591 }
592 }
593 i = e + 1
594 }
595 sys_free_file(b, n)
596 return hits
597}
598
599// registry pass: every line of tool_allowlist.conf whose field 0 (up to TAB) names a gate marks REG.
600func ga_regpass(path: *u8, gn: *u8, ng: i64, g_reg: *i64) -> i64 {
601 let lenp: *i64 = sys_mmap(16) as *i64
602 let b: *u8 = sys_read_file(path, lenp)
603 if lenp[0] <= 0 { return 0 - 1 }
604 let n: i64 = lenp[0]
605 var rows: i64 = 0
606 var i: i64 = 0
607 while i < n {
608 let e: i64 = gk_eol(b, i, n)
609 var t: i64 = i
610 var f3: i64 = 0
611 while f3 == 0 {
612 if t >= e { f3 = 1 }
613 if f3 == 0 { if b[t] == (9 as u8) { f3 = 1 } else { t = t + 1 } }
614 }
615 if t > i {
616 let g: i64 = ga_find(gn, ng, ((b as i64) + i) as *u8, t - i)
617 if g >= 0 { g_reg[g] = 1 }
618 }
619 rows = rows + 1
620 i = e + 1
621 }
622 sys_free_file(b, n)
623 return rows
624}
625
626// gatereg pass: every non-comment row of knowledge/gatereg.conf is `<banner>TAB<log-path>`; the log
627// path's basename minus ".log" is stem-matched against the gate table (same rule as the LOG axis,
628// because gatereg IS derived from those logs). Returns rows that matched a gate, or -1 if absent.
629func ga_gateregpass(path: *u8, gn: *u8, ng: i64, flag: *i64, ambig: *i64, names: *u8, scanned: i64) -> i64 {
630 let lenp: *i64 = sys_mmap(16) as *i64
631 let b: *u8 = sys_read_file(path, lenp)
632 if lenp[0] <= 0 { return 0 - 1 }
633 let n: i64 = lenp[0]
634 let lastg: *i64 = sys_mmap(8) as *i64
635 var hits: i64 = 0
636 var i: i64 = 0
637 while i < n {
638 let e: i64 = gk_eol(b, i, n)
639 var comment: i64 = 0
640 if b[i] == (35 as u8) { comment = 1 }
641 if comment == 0 {
642 // last field: from after the last TAB (or line start) to e; then basename; then strip .log
643 var f: i64 = i
644 var t: i64 = i
645 while t < e { if b[t] == (9 as u8) { f = t + 1 } t = t + 1 }
646 var bs: i64 = f
647 t = f
648 while t < e { if b[t] == (47 as u8) { bs = t + 1 } t = t + 1 }
649 var be: i64 = e
650 if be - bs > 4 {
651 if b[be - 4] == (46 as u8) { if b[be - 3] == (108 as u8) { if b[be - 2] == (111 as u8) { if b[be - 1] == (103 as u8) { be = be - 4 } } } }
652 }
653 if be > bs {
654 let m: i64 = ga_logmatch(gn, ng, ((b as i64) + bs) as *u8, be - bs, flag, lastg, names, scanned)
655 if m > 1 { ambig[0] = ambig[0] + 1 }
656 if m >= 1 { hits = hits + 1 }
657 }
658 }
659 i = e + 1
660 }
661 sys_free_file(b, n)
662 return hits
663}
664
665// actlog pass: TAIL window of the MCP invocation journal; identifier runs ending in _gate mark ACT.
666func ga_actpass(path: *u8, gn: *u8, ng: i64, flag: *i64, winout: *i64) -> i64 {
667 let fd: i64 = sys_openat_rd(path)
668 if fd < 0 { winout[0] = 0 - 1; return 0 - 1 }
669 let sz: i64 = sys_lseek(fd, 0, 2)
670 var start: i64 = 0
671 if sz > GA_ACT_TAIL { start = sz - GA_ACT_TAIL }
672 sys_lseek(fd, start, 0)
673 let cap: i64 = sz - start
674 let b: *u8 = sys_mmap(cap + 16)
675 var total: i64 = 0
676 var go: i64 = 1
677 while go == 1 {
678 let r: i64 = sys_read(fd, ((b as i64) + total) as *u8, cap - total)
679 if r <= 0 { go = 0 } else { total = total + r; if total >= cap { go = 0 } }
680 }
681 sys_close(fd)
682 winout[0] = total
683 if total <= 0 { return 0 }
684 return ga_scan_buf(b, total, gn, ng, flag, 0 as *i64, 0 as *i64, 0, 0 - 1, 0)
685}
686
687func ga_yn(msg: *u8, o: i64, v: i64) -> i64 {
688 if v > 0 { return gk_cat(msg, o, "1|" as *u8) }
689 return gk_cat(msg, o, "0|" as *u8)
690}
691
692func main(argc: i64, argv: *i64) -> i64 {
693 let msg: *u8 = sys_mmap(GA_MSG)
694 var o: i64 = 0
695 var rowsp: *u8 = 0 as *u8
696 let listcls_a: *i64 = sys_mmap(GA_MAXLISTS * 8) as *i64
697 let listp_a: *i64 = sys_mmap(GA_MAXLISTS * 8) as *i64
698 var nlists: i64 = 0
699 var lists_dropped: i64 = 0
700 var estate: *u8 = 0 as *u8
701 var a: i64 = 1
702 while a < argc {
703 let s: *u8 = argv[a] as *u8
704 if gk_streq(s, "--rows" as *u8) == 1 { if a + 1 < argc { rowsp = argv[a + 1] as *u8; a = a + 1 } }
705 if gk_streq(s, "--list" as *u8) == 1 { if a + 2 < argc {
706 var room: i64 = 0
707 if nlists < GA_MAXLISTS { room = 1 }
708 if room == 1 { listcls_a[nlists] = argv[a + 1]; listp_a[nlists] = argv[a + 2]; nlists = nlists + 1 }
709 if room == 0 { lists_dropped = lists_dropped + 1 }
710 a = a + 2 } }
711 if gk_streq(s, "--estate" as *u8) == 1 { if a + 1 < argc { estate = argv[a + 1] as *u8; a = a + 1 } }
712 a = a + 1
713 }
714
715 // ---- P0 anchor: a verdict that changes with the caller's cwd is not a measurement ----------
716 if estate != (0 as *u8) {
717 if sys_chdir(estate) != 0 {
718 o = gk_cat(msg, 0, "nx_gateadjudicate: UNOBSERVABLE -- cannot chdir to --estate\nverdict=UNOBSERVABLE\n" as *u8)
719 gk_say(msg, o)
720 return 3
721 }
722 }
723 if estate == (0 as *u8) {
724 if ep_anchor() < 0 {
725 o = gk_cat(msg, 0, "nx_gateadjudicate: UNOBSERVABLE -- no estate root on this host (ep_anchor failed; pass --estate <dir> for a smoke run)\nverdict=UNOBSERVABLE\n" as *u8)
726 gk_say(msg, o)
727 return 3
728 }
729 }
730 let now: i64 = sys_now_realtime_sec()
731 let sb: *u8 = sys_mmap(GA_STATBUF)
732
733 // ---- P1 corpus: the ONE denominator (REFUSES, never truncates) --------------------------------
734 let names: *u8 = sys_mmap(GA_MAXF * GA_SLOT)
735 let scanned: i64 = gk_corpus_scan(names, GA_SLOT, GA_MAXF)
736 if scanned == (0 - 2) { o = gk_cat(msg, 0, "nx_gateadjudicate: REFUSED -- corpus exceeds GA_MAXF; a truncated census is not a census.\nverdict=REFUSED\n" as *u8); gk_say(msg, o); return 1 }
737 if scanned == (0 - 3) { o = gk_cat(msg, 0, "nx_gateadjudicate: REFUSED -- a source path exceeds GA_SLOT.\nverdict=REFUSED\n" as *u8); gk_say(msg, o); return 1 }
738 if scanned <= 0 { o = gk_cat(msg, 0, "nx_gateadjudicate: REFUSED -- could not scan the compile corpus.\nverdict=REFUSED\n" as *u8); gk_say(msg, o); return 1 }
739
740 // ---- P2 gate table -----------------------------------------------------------------------
741 let gn: *u8 = sys_mmap(GA_MAXG * GA_GSLOT)
742 let g_src: *i64 = sys_mmap(GA_MAXG * 8) as *i64 // 1 hdl, 2 rt
743 let g_cidx: *i64 = sys_mmap(GA_MAXG * 8) as *i64 // corpus index of the gate source
744 let g_built: *i64 = sys_mmap(GA_MAXG * 8) as *i64
745 let g_staged: *i64 = sys_mmap(GA_MAXG * 8) as *i64
746 let g_proot: *i64 = sys_mmap(GA_MAXG * 8) as *i64
747 let g_poffc: *i64 = sys_mmap(GA_MAXG * 8) as *i64
748 let g_pbro: *i64 = sys_mmap(GA_MAXG * 8) as *i64
749 let g_reg: *i64 = sys_mmap(GA_MAXG * 8) as *i64
750 let g_clock: *i64 = sys_mmap(GA_MAXG * 8) as *i64
751 let g_roster: *i64 = sys_mmap(GA_MAXG * 8) as *i64
752 let g_gates: *i64 = sys_mmap(GA_MAXG * 8) as *i64
753 let g_greg: *i64 = sys_mmap(GA_MAXG * 8) as *i64
754 let g_gros: *i64 = sys_mmap(GA_MAXG * 8) as *i64
755 let g_trial: *i64 = sys_mmap(GA_MAXG * 8) as *i64
756 let g_btrial: *i64 = sys_mmap(GA_MAXG * 8) as *i64
757 let g_act: *i64 = sys_mmap(GA_MAXG * 8) as *i64
758 let g_log: *i64 = sys_mmap(GA_MAXG * 8) as *i64
759 let g_logage: *i64 = sys_mmap(GA_MAXG * 8) as *i64
760 let g_srcage: *i64 = sys_mmap(GA_MAXG * 8) as *i64
761 let g_ref: *i64 = sys_mmap(GA_MAXG * 8) as *i64
762 let g_ref1: *i64 = sys_mmap(GA_MAXG * 8) as *i64
763 let g_refflag: *i64 = sys_mmap(GA_MAXG * 8) as *i64 // scratch: ga_scan_buf's flag slot when the counter is g_ref
764 let g_class: *i64 = sys_mmap(GA_MAXG * 8) as *i64
765 let c_isgate: *i64 = sys_mmap(GA_MAXF * 8) as *i64 // corpus idx -> gate idx or -1
766 var ng: i64 = 0
767 var ci: i64 = 0
768 while ci < scanned {
769 let cp: *u8 = ga_cslot(names, ci)
770 c_isgate[ci] = 0 - 1
771 if ga_endswith(cp, "_gate.nx" as *u8) == 1 {
772 if ng >= GA_MAXG {
773 o = gk_cat(msg, 0, "nx_gateadjudicate: REFUSED -- more gates than GA_MAXG; raise the table, do not sample.\nverdict=REFUSED\n" as *u8)
774 gk_say(msg, o)
775 return 1
776 }
777 let base: *u8 = ga_base(cp)
778 let l: i64 = gk_len(base)
779 let dst: *u8 = ga_gslot(gn, ng)
780 var q: i64 = 0
781 while q < l - 3 { if q < GA_GSLOT - 1 { dst[q] = base[q] } q = q + 1 }
782 if q > GA_GSLOT - 1 { q = GA_GSLOT - 1 }
783 dst[q] = 0 as u8
784 g_src[ng] = 2
785 if gk_has(cp, "/_hdl_build/" as *u8) == 1 { g_src[ng] = 1 }
786 g_cidx[ng] = ci
787 g_logage[ng] = 0 - 1
788 g_srcage[ng] = 0 - 1
789 let smt: i64 = ga_mtime(cp, sb)
790 if smt > 0 { g_srcage[ng] = (now - smt) / GA_SEC_PER_DAY }
791 g_ref1[ng] = 0 - 1
792 c_isgate[ci] = ng
793 ng = ng + 1
794 }
795 ci = ci + 1
796 }
797 if ng <= 0 { o = gk_cat(msg, 0, "nx_gateadjudicate: REFUSED -- no *_gate.nx in the corpus.\nverdict=REFUSED\n" as *u8); gk_say(msg, o); return 1 }
798
799 // ---- P3 clock planes + off-host roster conf -> roster table ----------------------------------
800 let ros: *u8 = sys_mmap(GA_MAXCLK * GA_GSLOT)
801 let nros: *i64 = sys_mmap(8) as *i64
802 nros[0] = 0
803 let clk_live: i64 = ga_clockpass(GA_CLK_LIVE, gn, ng, g_clock, ros, nros)
804 let clk_want: i64 = ga_clockpass(GA_CLK_WANT, gn, ng, g_clock, ros, nros)
805 let ros_conf: i64 = ga_rosterconf(GA_ROSTERS, ros, nros)
806
807 // ---- P4 exec-literal scan over the WHOLE corpus (REF everywhere, ROSTER when the referrer is a roster organ)
808 let lenp: *i64 = sys_mmap(16) as *i64
809 var files_read: i64 = 0
810 var files_unreadable: i64 = 0
811 var bytes_read: i64 = 0
812 var ros_referrers: i64 = 0
813 ci = 0
814 while ci < scanned {
815 let cp: *u8 = ga_cslot(names, ci)
816 let b: *u8 = sys_read_file(cp, lenp)
817 if lenp[0] <= 0 { files_unreadable = files_unreadable + 1 }
818 if lenp[0] > 0 {
819 files_read = files_read + 1
820 bytes_read = bytes_read + lenp[0]
821 let self: i64 = c_isgate[ci]
822 // is this file a roster organ? (its basename minus .nx is in the roster table)
823 let base: *u8 = ga_base(cp)
824 let bl: i64 = gk_len(base)
825 var isros: i64 = 0
826 var j: i64 = 0
827 while j < nros[0] { if ga_eqrun(ga_gslot(ros, j), base, bl - 3) == 1 { isros = 1 } j = j + 1 }
828 if isros == 1 { ros_referrers = ros_referrers + 1 }
829 ga_scan_buf(b, lenp[0], gn, ng, g_refflag, g_ref, g_ref1, ci, self, 1)
830 // A ROSTER organ exists to run things, and it commonly builds the elf path at runtime
831 // ("nx_x_gate" as *u8 + ".elf" -- measured: nx_gfx_gates_beat names its 8 gates that way),
832 // so for roster organs ANY identifier mention counts as the edge (want_elf=0). This can
833 // only over-credit LIVE, i.e. it errs toward NOT retiring -- the safe direction for a
834 // signal that feeds a destructive remedy.
835 if isros == 1 { ga_scan_buf(b, lenp[0], gn, ng, g_roster, 0 as *i64, 0 as *i64, ci, self, 0) }
836 sys_free_file(b, lenp[0])
837 }
838 ci = ci + 1
839 }
840 var gi: i64 = 0
841
842 // ---- P5..P8 registries / maps / journal / logs ------------------------------------------------
843 let reg_rows: i64 = ga_regpass(GA_ALLOW, gn, ng, g_reg)
844 let ambig: *i64 = sys_mmap(16) as *i64
845 ambig[0] = 0
846 ambig[1] = 0
847 let greg_hits: i64 = ga_gateregpass(GA_GATEREG, gn, ng, g_greg, ((ambig as i64) + 8) as *i64, names, scanned)
848 let gates1: i64 = ga_dirpass(GA_CMP1, ".gates" as *u8, 2, gn, ng, g_gates, g_logage, now, sb, ambig, names, scanned)
849 let gates2: i64 = ga_dirpass(GA_CMP2, ".gates" as *u8, 2, gn, ng, g_gates, g_logage, now, sb, ambig, names, scanned)
850 // GROSTER counts only while the roster runner is itself a roster organ (on the clock / in the conf)
851 var gros_live: i64 = 0
852 var rq: i64 = 0
853 while rq < nros[0] { if gk_streq(ga_gslot(ros, rq), "nx_gate_roster_run" as *u8) == 1 { gros_live = 1 } rq = rq + 1 }
854 var gros_hits: i64 = 0 - 1
855 if gros_live == 1 { gros_hits = ga_grosterpass(GA_GROSTER, gn, ng, g_gros) }
856 let jrnl_rows: i64 = ga_jrnlpass(GA_ROSTJRNL, gn, ng, g_trial)
857 let bjrnl_rows: i64 = ga_jrnlpass(GA_BUILDJRNL, gn, ng, g_btrial)
858 let actwin: *i64 = sys_mmap(8) as *i64
859 let act_hits: i64 = ga_actpass(GA_ACTLOG, gn, ng, g_act, actwin)
860 let logs_seen: i64 = ga_dirpass(GA_STATUS, ".log" as *u8, 1, gn, ng, g_log, g_logage, now, sb, ambig, names, scanned)
861
862 // ---- P9 ladder stats ------------------------------------------------------------------------
863 let p: *u8 = sys_mmap(4096)
864 gi = 0
865 while gi < ng {
866 let nm: *u8 = ga_gslot(gn, gi)
867 var po: i64 = gk_cat(p, 0, "buildroot/_build/" as *u8); po = gk_cat(p, po, nm); po = gk_cat(p, po, ".sov.elf" as *u8); p[po] = 0 as u8
868 g_built[gi] = gk_exists(p)
869 po = gk_cat(p, 0, nm); po = gk_cat(p, po, ".sov.elf.new" as *u8); p[po] = 0 as u8
870 g_staged[gi] = gk_exists(p)
871 po = gk_cat(p, 0, nm); po = gk_cat(p, po, ".elf" as *u8); p[po] = 0 as u8
872 g_proot[gi] = gk_exists(p)
873 po = gk_cat(p, 0, "_offc/" as *u8); po = gk_cat(p, po, nm); po = gk_cat(p, po, ".elf" as *u8); p[po] = 0 as u8
874 g_poffc[gi] = gk_exists(p)
875 po = gk_cat(p, 0, "buildroot/_offc/" as *u8); po = gk_cat(p, po, nm); po = gk_cat(p, po, ".elf" as *u8); p[po] = 0 as u8
876 g_pbro[gi] = gk_exists(p)
877 gi = gi + 1
878 }
879
880 // ---- P10 classify + partition ---------------------------------------------------------------
881 var n_live: i64 = 0
882 var n_gap: i64 = 0
883 var n_dark: i64 = 0
884 var n_dark_reg: i64 = 0
885 var n_dark_log: i64 = 0
886 var n_dark_ref: i64 = 0
887 var n_live_fail: i64 = 0
888 var n_bup_untried: i64 = 0
889 var n_bup_pass: i64 = 0
890 var n_bup_fail: i64 = 0
891 var n_dark_untried: i64 = 0
892 var n_dark_pass: i64 = 0
893 var n_dark_fail: i64 = 0
894 var n_bup: i64 = 0
895 var n_src: i64 = 0
896 var n_src_ref: i64 = 0
897 var n_src_unref: i64 = 0
898 var n_hdl: i64 = 0
899 var n_rt: i64 = 0
900 var s_clock: i64 = 0
901 var s_roster: i64 = 0
902 var s_gates: i64 = 0
903 var s_greg: i64 = 0
904 var s_gros: i64 = 0
905 var s_act: i64 = 0
906 var s_reg: i64 = 0
907 var s_log: i64 = 0
908 var s_ref: i64 = 0
909 var s_prom: i64 = 0
910 var s_proot: i64 = 0
911 var s_poffc: i64 = 0
912 var s_pbro: i64 = 0
913 var s_built: i64 = 0
914 var s_staged: i64 = 0
915 gi = 0
916 while gi < ng {
917 var invoked: i64 = 0
918 if g_clock[gi] > 0 { invoked = 1 }
919 if g_roster[gi] > 0 { invoked = 1 }
920 if g_gates[gi] > 0 { invoked = 1 }
921 if g_greg[gi] > 0 { invoked = 1 }
922 if g_gros[gi] > 0 { invoked = 1 }
923 if g_act[gi] > 0 { invoked = 1 }
924 var prom: i64 = 0
925 if g_proot[gi] > 0 { prom = 1 }
926 if g_poffc[gi] > 0 { prom = 1 }
927 if g_pbro[gi] > 0 { prom = 1 }
928 var cls: i64 = 0
929 if invoked == 1 { if prom == 1 { cls = 1; n_live = n_live + 1; if g_trial[gi] >= 3 { n_live_fail = n_live_fail + 1 } } }
930 if invoked == 1 { if prom == 0 { cls = 2; n_gap = n_gap + 1 } }
931 if invoked == 0 { if prom == 1 {
932 cls = 3; n_dark = n_dark + 1
933 if g_reg[gi] > 0 { n_dark_reg = n_dark_reg + 1 }
934 if g_log[gi] > 0 { n_dark_log = n_dark_log + 1 }
935 if g_ref[gi] > 0 { n_dark_ref = n_dark_ref + 1 }
936 if g_trial[gi] == 0 { n_dark_untried = n_dark_untried + 1 }
937 if g_trial[gi] == 1 { n_dark_pass = n_dark_pass + 1 }
938 if g_trial[gi] == 2 { n_dark_pass = n_dark_pass + 1 }
939 if g_trial[gi] >= 3 { n_dark_fail = n_dark_fail + 1 }
940 } }
941 if invoked == 0 { if prom == 0 { if g_built[gi] > 0 {
942 cls = 4; n_bup = n_bup + 1
943 if g_btrial[gi] == 0 { n_bup_untried = n_bup_untried + 1 }
944 if g_btrial[gi] == 1 { n_bup_pass = n_bup_pass + 1 }
945 if g_btrial[gi] == 2 { n_bup_pass = n_bup_pass + 1 }
946 if g_btrial[gi] >= 3 { n_bup_fail = n_bup_fail + 1 }
947 } } }
948 if invoked == 0 { if prom == 0 { if g_built[gi] == 0 {
949 cls = 5; n_src = n_src + 1
950 if g_ref[gi] > 0 { n_src_ref = n_src_ref + 1 }
951 if g_ref[gi] == 0 { n_src_unref = n_src_unref + 1 }
952 } } }
953 g_class[gi] = cls
954 if g_src[gi] == 1 { n_hdl = n_hdl + 1 }
955 if g_src[gi] == 2 { n_rt = n_rt + 1 }
956 if g_clock[gi] > 0 { s_clock = s_clock + 1 }
957 if g_roster[gi] > 0 { s_roster = s_roster + 1 }
958 if g_gates[gi] > 0 { s_gates = s_gates + 1 }
959 if g_greg[gi] > 0 { s_greg = s_greg + 1 }
960 if g_gros[gi] > 0 { s_gros = s_gros + 1 }
961 if g_act[gi] > 0 { s_act = s_act + 1 }
962 if g_reg[gi] > 0 { s_reg = s_reg + 1 }
963 if g_log[gi] > 0 { s_log = s_log + 1 }
964 if g_ref[gi] > 0 { s_ref = s_ref + 1 }
965 if prom == 1 { s_prom = s_prom + 1 }
966 if g_proot[gi] > 0 { s_proot = s_proot + 1 }
967 if g_poffc[gi] > 0 { s_poffc = s_poffc + 1 }
968 if g_pbro[gi] > 0 { s_pbro = s_pbro + 1 }
969 if g_built[gi] > 0 { s_built = s_built + 1 }
970 if g_staged[gi] > 0 { s_staged = s_staged + 1 }
971 gi = gi + 1
972 }
973 let part_sum: i64 = n_live + n_gap + n_dark + n_bup + n_src
974
975 // ---- report ---------------------------------------------------------------------------------
976 o = gk_cat(msg, 0, "nx_gateadjudicate: the gate adjudication census, whole compile corpus, one bucket per gate\n" as *u8)
977 o = gk_cat(msg, o, " corpus_files=" as *u8); o = gk_catn(msg, o, scanned)
978 o = gk_cat(msg, o, " gate_sources=" as *u8); o = gk_catn(msg, o, ng)
979 o = gk_cat(msg, o, " (hdl_build=" as *u8); o = gk_catn(msg, o, n_hdl)
980 o = gk_cat(msg, o, " runtime=" as *u8); o = gk_catn(msg, o, n_rt)
981 o = gk_cat(msg, o, ") files_read=" as *u8); o = gk_catn(msg, o, files_read)
982 o = gk_cat(msg, o, " unreadable=" as *u8); o = gk_catn(msg, o, files_unreadable)
983 o = gk_cat(msg, o, " bytes_read=" as *u8); o = gk_catn(msg, o, bytes_read)
984 o = gk_cat(msg, o, "\n surfaces: clock_live_rows=" as *u8); o = gk_catn(msg, o, clk_live)
985 o = gk_cat(msg, o, " clock_desired_rows=" as *u8); o = gk_catn(msg, o, clk_want)
986 o = gk_cat(msg, o, " roster_conf_lines=" as *u8); o = gk_catn(msg, o, ros_conf)
987 o = gk_cat(msg, o, " roster_organs=" as *u8); o = gk_catn(msg, o, nros[0])
988 o = gk_cat(msg, o, " roster_sources_found=" as *u8); o = gk_catn(msg, o, ros_referrers)
989 o = gk_cat(msg, o, " registry_rows=" as *u8); o = gk_catn(msg, o, reg_rows)
990 o = gk_cat(msg, o, " gatereg_hits=" as *u8); o = gk_catn(msg, o, greg_hits)
991 o = gk_cat(msg, o, " gateroster_hits=" as *u8); o = gk_catn(msg, o, gros_hits)
992 if gros_live == 0 { o = gk_cat(msg, o, " groster_inert=1" as *u8) }
993 o = gk_cat(msg, o, " gates_maps=" as *u8); o = gk_catn(msg, o, gates1)
994 o = gk_cat(msg, o, "+" as *u8); o = gk_catn(msg, o, gates2)
995 o = gk_cat(msg, o, " actlog_window_bytes=" as *u8); o = gk_catn(msg, o, actwin[0])
996 o = gk_cat(msg, o, " actlog_hits=" as *u8); o = gk_catn(msg, o, act_hits)
997 o = gk_cat(msg, o, " status_logs=" as *u8); o = gk_catn(msg, o, logs_seen)
998 o = gk_cat(msg, o, " roster_journal_rows=" as *u8); o = gk_catn(msg, o, jrnl_rows)
999 o = gk_cat(msg, o, " build_journal_rows=" as *u8); o = gk_catn(msg, o, bjrnl_rows)
1000 o = gk_cat(msg, o, "\n roster organs (clock live+desired planes + conf; * = source found in corpus):" as *u8)
1001 var ri: i64 = 0
1002 while ri < nros[0] {
1003 o = gk_cat(msg, o, " " as *u8)
1004 o = gk_cat(msg, o, ga_gslot(ros, ri))
1005 var found: i64 = 0
1006 var rj: i64 = 0
1007 while rj < scanned {
1008 let cb: *u8 = ga_base(ga_cslot(names, rj))
1009 if ga_eqrun(ga_gslot(ros, ri), cb, gk_len(cb) - 3) == 1 { found = 1; rj = scanned } else { rj = rj + 1 }
1010 }
1011 if found == 1 { o = gk_cat(msg, o, "*" as *u8) }
1012 ri = ri + 1
1013 }
1014 o = gk_cat(msg, o, "\n axes over gates: BUILT=" as *u8); o = gk_catn(msg, o, s_built)
1015 o = gk_cat(msg, o, " STAGED=" as *u8); o = gk_catn(msg, o, s_staged)
1016 o = gk_cat(msg, o, " PROMOTED=" as *u8); o = gk_catn(msg, o, s_prom)
1017 o = gk_cat(msg, o, " (root=" as *u8); o = gk_catn(msg, o, s_proot)
1018 o = gk_cat(msg, o, " _offc=" as *u8); o = gk_catn(msg, o, s_poffc)
1019 o = gk_cat(msg, o, " buildroot/_offc=" as *u8); o = gk_catn(msg, o, s_pbro); o = gk_cat(msg, o, ")" as *u8)
1020 o = gk_cat(msg, o, " REG=" as *u8); o = gk_catn(msg, o, s_reg)
1021 o = gk_cat(msg, o, " CLOCK=" as *u8); o = gk_catn(msg, o, s_clock)
1022 o = gk_cat(msg, o, " ROSTER=" as *u8); o = gk_catn(msg, o, s_roster)
1023 o = gk_cat(msg, o, " GATES=" as *u8); o = gk_catn(msg, o, s_gates)
1024 o = gk_cat(msg, o, " GATEREG=" as *u8); o = gk_catn(msg, o, s_greg)
1025 o = gk_cat(msg, o, " GROSTER=" as *u8); o = gk_catn(msg, o, s_gros)
1026 o = gk_cat(msg, o, " ACTLOG=" as *u8); o = gk_catn(msg, o, s_act)
1027 o = gk_cat(msg, o, " LOG=" as *u8); o = gk_catn(msg, o, s_log)
1028 o = gk_cat(msg, o, " REF=" as *u8); o = gk_catn(msg, o, s_ref)
1029 o = gk_cat(msg, o, " log_ambiguous=" as *u8); o = gk_catn(msg, o, ambig[0])
1030 o = gk_cat(msg, o, " gatereg_ambiguous=" as *u8); o = gk_catn(msg, o, ambig[1])
1031 o = gk_cat(msg, o, "\n PARTITION (one bucket per gate, by remedy):\n" as *u8)
1032 o = gk_cat(msg, o, " LIVE " as *u8); o = gk_catn(msg, o, n_live); o = gk_cat(msg, o, " invoked+promoted: verdict collected [latest roster/trial row FAILING=" as *u8)
1033 o = gk_catn(msg, o, n_live_fail); o = gk_cat(msg, o, " -- collected AND read: the alarm worklist]\n" as *u8)
1034 o = gk_cat(msg, o, " INVOKED-MISSING " as *u8); o = gk_catn(msg, o, n_gap); o = gk_cat(msg, o, " a surface names it, no binary anywhere: build+promote (a GAP)\n" as *u8)
1035 o = gk_cat(msg, o, " DEPLOYED-DARK " as *u8); o = gk_catn(msg, o, n_dark); o = gk_cat(msg, o, " promoted, no surface runs it: wire to a roster or retire [registered=" as *u8)
1036 o = gk_catn(msg, o, n_dark_reg); o = gk_cat(msg, o, " has_status_log=" as *u8); o = gk_catn(msg, o, n_dark_log); o = gk_cat(msg, o, " named_by_a_source=" as *u8); o = gk_catn(msg, o, n_dark_ref); o = gk_cat(msg, o, "]\n" as *u8)
1037 o = gk_cat(msg, o, " by trial (latest gateroster.jrnl row): untried=" as *u8); o = gk_catn(msg, o, n_dark_untried)
1038 o = gk_cat(msg, o, " passing=" as *u8); o = gk_catn(msg, o, n_dark_pass); o = gk_cat(msg, o, " (one `admit` from LIVE) failing=" as *u8); o = gk_catn(msg, o, n_dark_fail)
1039 o = gk_cat(msg, o, " (RED/ABSENT/TIMEOUT: a defect worklist, not a wiring one) sum=" as *u8); o = gk_catn(msg, o, n_dark_untried + n_dark_pass + n_dark_fail)
1040 if n_dark_untried + n_dark_pass + n_dark_fail == n_dark { o = gk_cat(msg, o, " == dark\n" as *u8) }
1041 if n_dark_untried + n_dark_pass + n_dark_fail != n_dark { o = gk_cat(msg, o, " != dark: LEAK\n" as *u8) }
1042 o = gk_cat(msg, o, " BUILT-UNPROMOTED " as *u8); o = gk_catn(msg, o, n_bup); o = gk_cat(msg, o, " compiled only: promote or retire the build\n" as *u8)
1043 o = gk_cat(msg, o, " by built-artifact trial (gatebuild.jrnl): untried=" as *u8); o = gk_catn(msg, o, n_bup_untried)
1044 o = gk_cat(msg, o, " passing=" as *u8); o = gk_catn(msg, o, n_bup_pass); o = gk_cat(msg, o, " (promote candidates WITH evidence) failing=" as *u8); o = gk_catn(msg, o, n_bup_fail)
1045 o = gk_cat(msg, o, " (fix or retire) sum=" as *u8); o = gk_catn(msg, o, n_bup_untried + n_bup_pass + n_bup_fail)
1046 if n_bup_untried + n_bup_pass + n_bup_fail == n_bup { o = gk_cat(msg, o, " == built_unprom\n" as *u8) }
1047 if n_bup_untried + n_bup_pass + n_bup_fail != n_bup { o = gk_cat(msg, o, " != built_unprom: LEAK\n" as *u8) }
1048 o = gk_cat(msg, o, " SOURCE-ONLY " as *u8); o = gk_catn(msg, o, n_src); o = gk_cat(msg, o, " no artifact: REFERENCED=" as *u8)
1049 o = gk_catn(msg, o, n_src_ref); o = gk_cat(msg, o, " (something names its .elf: adjudicate) UNREFERENCED=" as *u8); o = gk_catn(msg, o, n_src_unref); o = gk_cat(msg, o, " (nothing in the corpus names it: retire candidates)\n" as *u8)
1050 o = gk_cat(msg, o, " SUM " as *u8); o = gk_catn(msg, o, part_sum)
1051 if part_sum == ng { o = gk_cat(msg, o, " == gate_sources: partition RECONCILES\n" as *u8) }
1052 if part_sum != ng { o = gk_cat(msg, o, " != gate_sources: PARTITION LEAK -- do not plan against these numbers\n" as *u8) }
1053 o = gk_cat(msg, o, " BLIND SPOTS (declared): off-host rosters/hooks only via " as *u8); o = gk_cat(msg, o, GA_ROSTERS)
1054 if ros_conf < 0 { o = gk_cat(msg, o, " (ABSENT: laptop-rostered gates read as REF-only here)" as *u8) }
1055 o = gk_cat(msg, o, "; ACTLOG is a tail window; ROSTER edges are static 2-hop.\n" as *u8)
1056 o = gk_cat(msg, o, " UNINVOKED (the lane-B worklist) = DEPLOYED-DARK + BUILT-UNPROMOTED + SOURCE-ONLY = " as *u8)
1057 o = gk_catn(msg, o, n_dark + n_bup + n_src)
1058 o = gk_cat(msg, o, "\n" as *u8)
1059 gk_say(msg, o)
1060
1061 // ---- clusters: first name token after the prefix; counts per bucket; sorted by uninvoked desc ----
1062 let ck: *u8 = sys_mmap(GA_MAXCLU * GA_GSLOT)
1063 let cn: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64 // gates in cluster
1064 let c1: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64 // live
1065 let c3: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64 // dark
1066 let c4: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64 // built-unpromoted
1067 let c5: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64 // source-only
1068 let creg: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64 // registered
1069 var ncl: i64 = 0
1070 var clu_floor: i64 = 0
1071 let tok: *u8 = sys_mmap(GA_GSLOT)
1072 gi = 0
1073 while gi < ng {
1074 let nm: *u8 = ga_gslot(gn, gi)
1075 let so: i64 = ga_stemoff(nm)
1076 var t: i64 = 0
1077 var ft: i64 = 0
1078 while ft == 0 {
1079 if nm[so + t] == (0 as u8) { ft = 1 }
1080 if ft == 0 { if nm[so + t] == (95 as u8) { ft = 1 } else { if t < GA_GSLOT - 2 { tok[t] = nm[so + t] } t = t + 1 } }
1081 }
1082 if t > GA_GSLOT - 2 { t = GA_GSLOT - 2 }
1083 tok[t] = 0 as u8
1084 var idx: i64 = 0 - 1
1085 var j: i64 = 0
1086 while j < ncl { if gk_streq(ga_gslot(ck, j), tok) == 1 { idx = j; j = ncl } else { j = j + 1 } }
1087 if idx < 0 {
1088 if ncl < GA_MAXCLU {
1089 let dst: *u8 = ga_gslot(ck, ncl)
1090 var q: i64 = 0
1091 while q <= t { dst[q] = tok[q]; q = q + 1 }
1092 idx = ncl
1093 ncl = ncl + 1
1094 }
1095 if idx < 0 { clu_floor = 1 }
1096 }
1097 if idx >= 0 {
1098 cn[idx] = cn[idx] + 1
1099 if g_class[gi] == 1 { c1[idx] = c1[idx] + 1 }
1100 if g_class[gi] == 3 { c3[idx] = c3[idx] + 1 }
1101 if g_class[gi] == 4 { c4[idx] = c4[idx] + 1 }
1102 if g_class[gi] == 5 { c5[idx] = c5[idx] + 1 }
1103 if g_reg[gi] > 0 { creg[idx] = creg[idx] + 1 }
1104 }
1105 gi = gi + 1
1106 }
1107 // selection sort of an index permutation by uninvoked = c3+c4+c5, descending
1108 let ord: *i64 = sys_mmap(GA_MAXCLU * 8) as *i64
1109 var oi: i64 = 0
1110 while oi < ncl { ord[oi] = oi; oi = oi + 1 }
1111 oi = 0
1112 while oi < ncl {
1113 var best: i64 = oi
1114 var oj: i64 = oi + 1
1115 while oj < ncl {
1116 let ub: i64 = c3[ord[best]] + c4[ord[best]] + c5[ord[best]]
1117 let uj: i64 = c3[ord[oj]] + c4[ord[oj]] + c5[ord[oj]]
1118 if uj > ub { best = oj }
1119 oj = oj + 1
1120 }
1121 let tmp: i64 = ord[oi]
1122 ord[oi] = ord[best]
1123 ord[best] = tmp
1124 oi = oi + 1
1125 }
1126 var singles: i64 = 0
1127 var sci: i64 = 0
1128 while sci < ncl { if cn[sci] == 1 { singles = singles + 1 } sci = sci + 1 }
1129 o = gk_cat(msg, 0, " CLUSTERS (first name token after the prefix): clusters=" as *u8); o = gk_catn(msg, o, ncl)
1130 o = gk_cat(msg, o, " singletons=" as *u8); o = gk_catn(msg, o, singles)
1131 if clu_floor == 1 { o = gk_cat(msg, o, " (TABLE FULL: cluster count is a FLOOR)" as *u8) }
1132 o = gk_cat(msg, o, " shown=" as *u8)
1133 var show: i64 = ncl
1134 if show > GA_CLUSHOW { show = GA_CLUSHOW }
1135 o = gk_catn(msg, o, show)
1136 o = gk_cat(msg, o, " (sorted by uninvoked desc; hidden clusters carry the remainder, see rows artifact)\n" as *u8)
1137 o = gk_cat(msg, o, " cluster|gates|live|dark|built_unprom|source_only|registered\n" as *u8)
1138 gk_say(msg, o)
1139 oi = 0
1140 var shown_gates: i64 = 0
1141 while oi < show {
1142 let c: i64 = ord[oi]
1143 o = gk_cat(msg, 0, " " as *u8)
1144 o = gk_cat(msg, o, ga_gslot(ck, c)); o = gk_cat(msg, o, "|" as *u8)
1145 o = gk_catn(msg, o, cn[c]); o = gk_cat(msg, o, "|" as *u8)
1146 o = gk_catn(msg, o, c1[c]); o = gk_cat(msg, o, "|" as *u8)
1147 o = gk_catn(msg, o, c3[c]); o = gk_cat(msg, o, "|" as *u8)
1148 o = gk_catn(msg, o, c4[c]); o = gk_cat(msg, o, "|" as *u8)
1149 o = gk_catn(msg, o, c5[c]); o = gk_cat(msg, o, "|" as *u8)
1150 o = gk_catn(msg, o, creg[c]); o = gk_cat(msg, o, "\n" as *u8)
1151 gk_say(msg, o)
1152 shown_gates = shown_gates + cn[c]
1153 oi = oi + 1
1154 }
1155 o = gk_cat(msg, 0, " (shown clusters cover " as *u8); o = gk_catn(msg, o, shown_gates)
1156 o = gk_cat(msg, o, " of " as *u8); o = gk_catn(msg, o, ng); o = gk_cat(msg, o, " gates; hidden clusters=" as *u8); o = gk_catn(msg, o, ncl - show); o = gk_cat(msg, o, ")\n" as *u8)
1157 gk_say(msg, o)
1158
1159 // ---- rows artifact (optional) -----------------------------------------------------------------
1160 if rowsp != (0 as *u8) {
1161 let rb: *u8 = sys_mmap(GA_ROWCAP)
1162 var ro: i64 = gk_cat(rb, 0, "<!-- NX-DERIVED: regenerated artefact, not authored memory -->\n" as *u8)
1163 ro = gk_cat(rb, ro, "name|src|src_age_d|built|staged|prom|reg|clock|roster|gates|gatereg|groster|act|log|logage_d|ref|first_ref|trial|class\n" as *u8)
1164 var over: i64 = 0
1165 gi = 0
1166 while gi < ng {
1167 if ro + 1024 > GA_ROWCAP { over = 1; gi = ng }
1168 if over == 0 {
1169 ro = gk_cat(rb, ro, ga_gslot(gn, gi)); ro = gk_cat(rb, ro, "|" as *u8)
1170 if g_src[gi] == 1 { ro = gk_cat(rb, ro, "hdl|" as *u8) }
1171 if g_src[gi] == 2 { ro = gk_cat(rb, ro, "rt|" as *u8) }
1172 ro = gk_catn(rb, ro, g_srcage[gi]); ro = gk_cat(rb, ro, "|" as *u8)
1173 ro = ga_yn(rb, ro, g_built[gi])
1174 ro = ga_yn(rb, ro, g_staged[gi])
1175 var pm: i64 = 0
1176 if g_proot[gi] > 0 { pm = pm + 1 }
1177 if g_poffc[gi] > 0 { pm = pm + 2 }
1178 if g_pbro[gi] > 0 { pm = pm + 4 }
1179 ro = gk_catn(rb, ro, pm); ro = gk_cat(rb, ro, "|" as *u8)
1180 ro = ga_yn(rb, ro, g_reg[gi])
1181 ro = ga_yn(rb, ro, g_clock[gi])
1182 ro = ga_yn(rb, ro, g_roster[gi])
1183 ro = ga_yn(rb, ro, g_gates[gi])
1184 ro = ga_yn(rb, ro, g_greg[gi])
1185 ro = ga_yn(rb, ro, g_gros[gi])
1186 ro = ga_yn(rb, ro, g_act[gi])
1187 ro = ga_yn(rb, ro, g_log[gi])
1188 ro = gk_catn(rb, ro, g_logage[gi]); ro = gk_cat(rb, ro, "|" as *u8)
1189 ro = gk_catn(rb, ro, g_ref[gi]); ro = gk_cat(rb, ro, "|" as *u8)
1190 if g_ref1[gi] >= 0 { ro = gk_cat(rb, ro, ga_base(ga_cslot(names, g_ref1[gi]))) }
1191 if g_ref1[gi] < 0 { ro = gk_cat(rb, ro, "-" as *u8) }
1192 ro = gk_cat(rb, ro, "|" as *u8)
1193 if g_trial[gi] == 0 { ro = gk_cat(rb, ro, "-" as *u8) }
1194 if g_trial[gi] == 1 { ro = gk_cat(rb, ro, "GREEN" as *u8) }
1195 if g_trial[gi] == 2 { ro = gk_cat(rb, ro, "SKIP" as *u8) }
1196 if g_trial[gi] == 3 { ro = gk_cat(rb, ro, "RED" as *u8) }
1197 if g_trial[gi] == 4 { ro = gk_cat(rb, ro, "ABSENT" as *u8) }
1198 if g_trial[gi] == 5 { ro = gk_cat(rb, ro, "TIMEOUT" as *u8) }
1199 ro = gk_cat(rb, ro, "|" as *u8)
1200 if g_class[gi] == 1 { ro = gk_cat(rb, ro, "LIVE" as *u8) }
1201 if g_class[gi] == 2 { ro = gk_cat(rb, ro, "INVOKED-MISSING" as *u8) }
1202 if g_class[gi] == 3 { ro = gk_cat(rb, ro, "DEPLOYED-DARK" as *u8) }
1203 if g_class[gi] == 4 { ro = gk_cat(rb, ro, "BUILT-UNPROMOTED" as *u8) }
1204 if g_class[gi] == 5 { if g_ref[gi] > 0 { ro = gk_cat(rb, ro, "SOURCE-ONLY-REFERENCED" as *u8) } }
1205 if g_class[gi] == 5 { if g_ref[gi] == 0 { ro = gk_cat(rb, ro, "SOURCE-ONLY-UNREFERENCED" as *u8) } }
1206 ro = gk_cat(rb, ro, "\n" as *u8)
1207 gi = gi + 1
1208 }
1209 }
1210 if over == 1 {
1211 o = gk_cat(msg, 0, " rows: REFUSED -- artifact would exceed GA_ROWCAP; nothing written (a partial rows file reads as a whole one)\n" as *u8)
1212 gk_say(msg, o)
1213 }
1214 if over == 0 {
1215 rb[ro] = 0 as u8
1216 let w: i64 = gk_write(rowsp, rb)
1217 o = gk_cat(msg, 0, " rows: wrote=" as *u8); o = gk_catn(msg, o, w); o = gk_cat(msg, o, " of=" as *u8); o = gk_cat(msg, o, rowsp)
1218 o = gk_cat(msg, o, " rows_written=" as *u8); o = gk_catn(msg, o, ng); o = gk_cat(msg, o, "\n" as *u8)
1219 gk_say(msg, o)
1220 }
1221 }
1222
1223 // ---- class list (optional): the census emits its own worklists ---------------------------------
1224 var li: i64 = 0
1225 while li < nlists {
1226 let listcls: *u8 = listcls_a[li] as *u8
1227 let listp: *u8 = listp_a[li] as *u8
1228 li = li + 1
1229 var want: i64 = 0
1230 if gk_streq(listcls, "LIVE" as *u8) == 1 { want = 1 }
1231 if gk_streq(listcls, "INVOKED-MISSING" as *u8) == 1 { want = 2 }
1232 if gk_streq(listcls, "DEPLOYED-DARK" as *u8) == 1 { want = 3 }
1233 if gk_streq(listcls, "BUILT-UNPROMOTED" as *u8) == 1 { want = 4 }
1234 if gk_streq(listcls, "SOURCE-ONLY" as *u8) == 1 { want = 5 }
1235 // DEPLOYED-DARK sub-lists by trial verdict (the REASON travels with the count; a seat can pull the
1236 // failing worklist without re-deriving it from rows): 6 untried, 7 passing, 8 failing
1237 if gk_streq(listcls, "DARK-UNTRIED" as *u8) == 1 { want = 6 }
1238 if gk_streq(listcls, "DARK-PASSING" as *u8) == 1 { want = 7 }
1239 if gk_streq(listcls, "DARK-FAILING" as *u8) == 1 { want = 8 }
1240 if gk_streq(listcls, "LIVE-FAILING" as *u8) == 1 { want = 9 }
1241 // BUILT-UNPROMOTED by built-artifact trial; rows spelled `buildroot/_build/<n>.sov` so the runner
1242 // execs the built artifact in place (it appends .elf) -- journal these to gatebuild.jrnl, NOT the
1243 // roster journal: admit must never wire an undeployed artifact onto the beat.
1244 if gk_streq(listcls, "BUILT-UNTRIED" as *u8) == 1 { want = 10 }
1245 if gk_streq(listcls, "BUILT-PASSING" as *u8) == 1 { want = 11 }
1246 if gk_streq(listcls, "BUILT-FAILING" as *u8) == 1 { want = 12 }
1247 if want == 0 {
1248 o = gk_cat(msg, 0, " list: REFUSED -- unknown class (LIVE|INVOKED-MISSING|DEPLOYED-DARK|BUILT-UNPROMOTED|SOURCE-ONLY|DARK-UNTRIED|DARK-PASSING|DARK-FAILING|LIVE-FAILING|BUILT-UNTRIED|BUILT-PASSING|BUILT-FAILING)\n" as *u8)
1249 gk_say(msg, o)
1250 }
1251 if want > 0 {
1252 let lb: *u8 = sys_mmap(GA_ROWCAP)
1253 var lo2: i64 = gk_cat(lb, 0, "; NX-DERIVED by nx_gateadjudicate: class=" as *u8)
1254 lo2 = gk_cat(lb, lo2, listcls)
1255 lo2 = gk_cat(lb, lo2, " epoch=" as *u8); lo2 = gk_catn(lb, lo2, now)
1256 lo2 = gk_cat(lb, lo2, " -- one gate per line, nx_gate_roster_run trial/roster format\n" as *u8)
1257 var lcount: i64 = 0
1258 var withheld: i64 = 0
1259 gi = 0
1260 while gi < ng {
1261 var sel: i64 = 0
1262 if g_class[gi] == want { sel = 1 }
1263 if want == 6 { if g_class[gi] == 3 { if g_trial[gi] == 0 { sel = 1 } } }
1264 if want == 7 { if g_class[gi] == 3 { if g_trial[gi] == 1 { sel = 1 } } }
1265 if want == 7 { if g_class[gi] == 3 { if g_trial[gi] == 2 { sel = 1 } } }
1266 if want == 8 { if g_class[gi] == 3 { if g_trial[gi] >= 3 { sel = 1 } } }
1267 if want == 9 { if g_class[gi] == 1 { if g_trial[gi] >= 3 { sel = 1 } } }
1268 if want == 10 { if g_class[gi] == 4 { if g_btrial[gi] == 0 { sel = 1 } } }
1269 if want == 11 { if g_class[gi] == 4 { if g_btrial[gi] == 1 { sel = 1 } } }
1270 if want == 11 { if g_class[gi] == 4 { if g_btrial[gi] == 2 { sel = 1 } } }
1271 if want == 12 { if g_class[gi] == 4 { if g_btrial[gi] >= 3 { sel = 1 } } }
1272 if sel == 1 {
1273 var take: i64 = 1
1274 // SOURCE-ONLY feeds a retire campaign: never emit a source modified TODAY --
1275 // a fresh artifact can be another seat's work in flight (measured law).
1276 if want == 5 { if g_srcage[gi] == 0 { take = 0; withheld = withheld + 1 } }
1277 if take == 1 {
1278 if lo2 + 256 < GA_ROWCAP {
1279 var builtrow: i64 = 0
1280 if want >= 10 { builtrow = 1 }
1281 if builtrow == 1 { lo2 = gk_cat(lb, lo2, GA_BUILT_PREFIX) }
1282 if builtrow == 0 { if g_proot[gi] == 0 { if g_poffc[gi] > 0 { lo2 = gk_cat(lb, lo2, "_offc/" as *u8) } } }
1283 if builtrow == 0 { if g_proot[gi] == 0 { if g_poffc[gi] == 0 { if g_pbro[gi] > 0 { lo2 = gk_cat(lb, lo2, "buildroot/_offc/" as *u8) } } } }
1284 lo2 = gk_cat(lb, lo2, ga_gslot(gn, gi))
1285 if builtrow == 1 { lo2 = gk_cat(lb, lo2, GA_BUILT_SUFFIX) }
1286 lb[lo2] = 10 as u8
1287 lo2 = lo2 + 1
1288 lcount = lcount + 1
1289 }
1290 }
1291 }
1292 gi = gi + 1
1293 }
1294 lb[lo2] = 0 as u8
1295 let lw: i64 = gk_write(listp, lb)
1296 o = gk_cat(msg, 0, " list: class=" as *u8); o = gk_cat(msg, o, listcls)
1297 o = gk_cat(msg, o, " names=" as *u8); o = gk_catn(msg, o, lcount)
1298 if withheld > 0 { o = gk_cat(msg, o, " withheld_same_day=" as *u8); o = gk_catn(msg, o, withheld) }
1299 o = gk_cat(msg, o, " wrote=" as *u8); o = gk_catn(msg, o, lw)
1300 o = gk_cat(msg, o, " of=" as *u8); o = gk_cat(msg, o, listp)
1301 o = gk_cat(msg, o, "\n" as *u8)
1302 gk_say(msg, o)
1303 }
1304 }
1305
1306 if lists_dropped > 0 {
1307 o = gk_cat(msg, 0, " list: DROPPED " as *u8); o = gk_catn(msg, o, lists_dropped)
1308 o = gk_cat(msg, o, " --list spec(s) beyond GA_MAXLISTS -- not emitted, said so\n" as *u8)
1309 gk_say(msg, o)
1310 }
1311
1312 // ---- trend line (append-only; a level cannot express a trajectory) ------------------------------
1313 let ln: *u8 = sys_mmap(1024)
1314 var lo: i64 = gk_cat(ln, 0, "epoch=" as *u8); lo = gk_catn(ln, lo, now)
1315 lo = gk_cat(ln, lo, " gates=" as *u8); lo = gk_catn(ln, lo, ng)
1316 lo = gk_cat(ln, lo, " live=" as *u8); lo = gk_catn(ln, lo, n_live)
1317 lo = gk_cat(ln, lo, " gap=" as *u8); lo = gk_catn(ln, lo, n_gap)
1318 lo = gk_cat(ln, lo, " dark=" as *u8); lo = gk_catn(ln, lo, n_dark)
1319 lo = gk_cat(ln, lo, " built_unprom=" as *u8); lo = gk_catn(ln, lo, n_bup)
1320 lo = gk_cat(ln, lo, " src_ref=" as *u8); lo = gk_catn(ln, lo, n_src_ref)
1321 lo = gk_cat(ln, lo, " src_unref=" as *u8); lo = gk_catn(ln, lo, n_src_unref)
1322 lo = gk_cat(ln, lo, " corpus=" as *u8); lo = gk_catn(ln, lo, scanned)
1323 lo = gk_cat(ln, lo, "\n" as *u8)
1324 ln[lo] = 0 as u8
1325 let ap: i64 = ga_appendline(GA_LOG, ln)
1326 o = gk_cat(msg, 0, " trend: appended=" as *u8); o = gk_catn(msg, o, ap); o = gk_cat(msg, o, " to " as *u8); o = gk_cat(msg, o, GA_LOG); o = gk_cat(msg, o, "\n" as *u8)
1327 gk_say(msg, o)
1328 return 0
1329}