nx_catalog_lib_t75.nx source
↩ module page · 1006 lines · 51266 B
1// nx_catalog_lib.nx -- THE ONE ADOPTION-LADDER CLASSIFIER, extracted from nx_catalog (2026-08-23, compare CE2).
2//
3// WHY A LIB: nx_catalog computed the estate's DEFINITION OF DONE -- the seven-rung ladder SOURCE BUILT STAGED
4// PROMOTED REGISTERED AUTHORISED INVOKED and its weakest-link verdict -- inside a print-interleaved cat_one(),
5// so the answer could only be read by a human off stdout. The /compare generator and the roadmap ranker both
6// needed the same answer PER BOARD ROW, and "done" there was rung ONE of seven (a `func <sym>` line exists in
7// a source file) -- which is exactly why a partial deploy was invisible on every board: a gate compiled and
8// never promoted, an organ promoted and never registered, read identically to LIVE.
9// WHEN TWO ORGANS MUST AGREE, MAKE DISAGREEMENT IMPOSSIBLE BY CONSTRUCTION: one classifier here, imported by
10// nx_catalog (prints it), nx_swcompare_matrix (renders it per row) and nx_compare_rank (ranks on it). The
11// arithmetic moved VERBATIM from nx_catalog; that organ's stdout is byte-identical before and after, and
12// nx_behaveprobe live-vs-staged is the transcription proof, not this comment.
13//
14// cl_ladder(name, registry, consent, actlog, m) -> verdict code (CLV_*); m[CLM_*] carries every measured
15// stage, so a caller prints or renders WHAT WAS MEASURED, never only the verdict (a verdict is not a
16// diagnosis). cl_gap(code) = 1 when the verdict is an adoption gap; LIB and LIVE-DAEMON are NOT gaps (a
17// binary is impossible for one and registration is wrong for the other -- see nx_catalog's header).
18// cl_verdict_name(code) is the short token boards print; cl_verdict_text(code) is the exact sentence
19// nx_catalog has always printed.
20// license_tier: ORIGINAL Read-only. No hw writes (Rule 26).
21import "nx_syscalls.nx"
22// ok_kind_of_path: the estate's ONE reader of the DECLARED organ kind (organ_kind.conf), already what
23// /api/promote consults. Composed, never re-derived from a name suffix.
24import "nx_organkind.nx"
25// EP_ROOT + ep_join: the estate root, so a consumer forked from buildroot/ (the compare regen) or from any
26// other CWD measures the ESTATE and not a stale twin beside it -- buildroot/ carries its own
27// tool_allowlist.conf, so "probe the CWD first" would answer REGISTERED from the wrong registry.
28import "nx_estate_path.nx"
29const CL_BUF: i64 = 4194304 // registry/consent/actlog read cap; the actlog read is TAIL-anchored (cl_slurp_tail)
30const CL_PATH: i64 = 1024
31const CL_SEEK_SET: i64 = 0
32const CL_SEEK_END: i64 = 2
33// measured-stage slots in m[] -- every one a FILE FACT, none a claim read from prose
34const CLM_SRC: i64 = 0 // source bytes, or -1 when no root resolves it
35const CLM_LIB: i64 = 1 // 1 = no top-level main() (a binary is not expected), 0 = program, -1 = unreadable
36const CLM_BUILT: i64 = 2 // buildroot/_build/<n>.sov.elf bytes, or -1
37const CLM_STAGED: i64 = 3 // <n>.sov.elf.new bytes, or -1 (a loaded gun aimed at the next deploy)
38const CLM_PROMOTED: i64 = 4 // <n>.elf | _offc/<n>.elf bytes, or -1
39const CLM_REG: i64 = 5 // 1 = tool_allowlist.conf row "<n><TAB>"
40const CLM_AUTH: i64 = 6 // 1 = cap_consent.log mentions it
41const CLM_INV: i64 = 7 // 1 = actlog.jrnl mentions it (MCP SURFACE ONLY: a direct fork logs the runner)
42const CLM_DKIND: i64 = 8 // declared kind from organ_kind.conf (OK_DAEMON or other)
43const CLM_RESOLVED: i64 = 9 // HOW field 2 of the registry row resolved: one of the CLR_* below
44const CLM_N: i64 = 10
45
46// ---- HOW DID THE REGISTRY ROW RESOLVE? (2026-09-03) ----
47// A resolver that returns a verdict without saying WHERE IT LOOKED reproduces the original defect one
48// layer up, so this travels with every answer INCLUDING the miss.
49const CLR_NAME: i64 = 0 // no registry row at all -- the <name>.nx/<name>.elf convention answered
50const CLR_PATH: i64 = 1 // field 2 STATTED AS GIVEN -- the row is the contract and the contract holds
51const CLR_REGBASE: i64 = 2 // field 2 did NOT stat; its basename answered instead -> the row is MISPOINTED
52const CL_CH_SLASH: i64 = 47
53const CL_CH_DOT: i64 = 46
54// verdict codes, in the weakest-link order nx_catalog prints them
55const CLV_ABSENT: i64 = 0
56const CLV_SOURCE_ONLY: i64 = 1
57const CLV_BUILT_UNPROMOTED: i64 = 2
58const CLV_PROMOTED_SOURCELESS: i64 = 3
59const CLV_PROMOTED_UNREGISTERED: i64 = 4
60const CLV_REGISTERED_UNAUTHORISED: i64 = 5
61const CLV_REGISTERED_DARK: i64 = 6
62const CLV_LIVE: i64 = 7
63const CLV_LIB: i64 = 8
64const CLV_LIVE_DAEMON: i64 = 9
65// FIXTURE (2026-09-02): DECLARED `fixture` in organ_kind.conf -- a runnable witness its gate compiles per run,
66// so no promoted binary is expected. NOT a gap (cl_gap), FULL on the board (clb_classify), and never SOURCE-ONLY.
67const CLV_FIXTURE: i64 = 10
68const CLV_REGISTRY_MISPOINTED: i64 = 11
69const CLV_N: i64 = 12
70
71func cl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
72
73// ---- EVERY PATH THIS LIB OPENS IS ESTATE-RELATIVE, WHEREVER THE PROCESS SITS (2026-08-23) ----
74// MEASURED THE HOUR THIS LIB FIRST SHIPPED: the compare regen forks the matrix generator from buildroot/,
75// every ladder read missed or hit buildroot's stale twins, and 33 of 33 measured graphics rows published
76// as ABSENT with both census stamps -1 -- a confident, complete-looking wrong answer. The marker rule is
77// ep_anchor's (daemons.reg exists ONLY at the estate root) applied per open, without a chdir: an organ
78// that must keep its own CWD for its own relative reads (the generator's knowledge/compare/ tree) can
79// still measure the estate. A verdict that changes with the caller's working directory is not a measurement.
80func cl_estate_path(out: *u8, p: *u8) -> *u8 {
81 let mk: i64 = sys_openat_rd("daemons.reg" as *u8)
82 if mk >= 0 { sys_close(mk); return p }
83 return ep_join(out, EP_ROOT, p)
84}
85func cl_open_estate(p: *u8) -> i64 {
86 let b: *u8 = sys_mmap(CL_PATH)
87 let f: i64 = sys_openat_rd(cl_estate_path(b, p))
88 sys_munmap(b, CL_PATH)
89 return f
90}
91// the WHOLE file (sized from itself by lseek END, cannot short-read), estate-relative; length into lp[0],
92// 0 pointer when absent
93func cl_read_whole(path: *u8, lp: *i64) -> *u8 {
94 lp[0] = 0
95 let fd: i64 = cl_open_estate(path)
96 if fd < 0 { return 0 as *u8 }
97 let sz: i64 = sys_lseek(fd, 0, CL_SEEK_END)
98 if sz < 0 { sys_close(fd); return 0 as *u8 }
99 sys_lseek(fd, 0, CL_SEEK_SET)
100 let buf: *u8 = sys_mmap(sz + 8)
101 var n: i64 = 0
102 var go: i64 = 1
103 while go == 1 {
104 if n >= sz { go = 0 } else {
105 let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, sz - n)
106 if r <= 0 { go = 0 } else { n = n + r }
107 }
108 }
109 sys_close(fd)
110 buf[n] = 0 as u8
111 lp[0] = n
112 return buf
113}
114
115// build "<pre><name><suf>" into dst; returns length
116func cl_cat3(dst: *u8, pre: *u8, name: *u8, suf: *u8) -> i64 {
117 var p: i64 = 0
118 var i: i64 = 0
119 while pre[i] != (0 as u8) { dst[p] = pre[i]; p = p + 1; i = i + 1 }
120 i = 0
121 while name[i] != (0 as u8) { dst[p] = name[i]; p = p + 1; i = i + 1 }
122 i = 0
123 while suf[i] != (0 as u8) { dst[p] = suf[i]; p = p + 1; i = i + 1 }
124 dst[p] = 0 as u8
125 return p
126}
127
128// file exists + size (-1 if absent). Uses a real open, so it cannot be fooled by a stale listing; the size
129// comes from lseek END on that open descriptor (nx_catalog read the whole file to count it -- same number,
130// but a board classifies ~40 rows x ~10 artifacts per emit, and reading every binary end to end to learn
131// its length was the whole cost).
132func cl_fsize(path: *u8) -> i64 {
133 let fd: i64 = cl_open_estate(path)
134 if fd < 0 { return 0 - 1 }
135 let n: i64 = sys_lseek(fd, 0, CL_SEEK_END)
136 sys_close(fd)
137 if n < 0 { return 0 - 1 }
138 return n
139}
140
141// does haystack contain needle? (bounded, byte-exact)
142func cl_has_sub(hay: *u8, hn: i64, ned: *u8) -> i64 {
143 let nn: i64 = cl_slen(ned)
144 if nn == 0 { return 0 }
145 if hn < nn { return 0 }
146 var i: i64 = 0
147 let last: i64 = hn - nn
148 while i <= last {
149 var j: i64 = 0
150 var ok: i64 = 1
151 while j < nn {
152 if hay[i + j] != ned[j] { ok = 0; j = nn } else { j = j + 1 }
153 }
154 if ok == 1 { return 1 }
155 i = i + 1
156 }
157 return 0
158}
159
160// read a whole file (head-anchored, capped at CL_BUF) into a fresh buffer; length into lp[0]
161func cl_slurp(path: *u8, lp: *i64) -> *u8 {
162 lp[0] = 0
163 let fd: i64 = cl_open_estate(path)
164 if fd < 0 { return 0 as *u8 }
165 let buf: *u8 = sys_mmap(CL_BUF + 8)
166 var n: i64 = 0
167 var go: i64 = 1
168 while go == 1 {
169 let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, CL_BUF - n)
170 if r <= 0 { go = 0 } else { n = n + r }
171 if n >= CL_BUF { go = 0 }
172 }
173 sys_close(fd)
174 buf[n] = 0 as u8
175 lp[0] = n
176 return buf
177}
178
179// TAIL-ANCHORED read for APPEND-ONLY ledgers (nx_catalog, 2026-08-07): a head-anchored read of a ledger past
180// the cap keeps the OLDEST bytes and silently drops the NEWEST, and INVOKED is a claim about RECENT activity,
181// so the truncation lands exactly on the evidence. Trade, stated: the first line of the window may be a
182// partial row.
183// Bounded journal evidence describes a byte window, never the whole lifetime.
184const CLC_STATE:i64=0
185const CLC_EXTENT:i64=1
186const CLC_START:i64=2
187const CLC_END:i64=3
188const CLC_READ:i64=4
189const CLC_HEAD:i64=5
190const CLC_TAIL:i64=6
191const CLC_ERRNO:i64=7
192const CLC_FINAL:i64=8
193const CLC_OBSERVED:i64=9
194const CLC_N:i64=10
195const CLC_OK:i64=0
196const CLC_OPEN:i64=1
197const CLC_SEEK:i64=2
198const CLC_ALLOC:i64=3
199const CLC_READ_ERROR:i64=4
200const CLC_CHANGED:i64=5
201const CLC_CLOSE:i64=6
202const CLC_INVALID:i64=7
203func cl_tail_state_name(s:i64)->*u8 {
204 if s==CLC_OK{return "observed"}
205 if s==CLC_OPEN{return "open-failed"}
206 if s==CLC_SEEK{return "seek-failed"}
207 if s==CLC_ALLOC{return "allocation-failed"}
208 if s==CLC_READ_ERROR{return "read-failed"}
209 if s==CLC_CHANGED{return "extent-changed"}
210 if s==CLC_CLOSE{return "close-failed"}
211 return "invalid-capacity"
212}
213func cl_tail_reset(c:*i64)->i64 {
214 var i:i64=0;while i<CLC_N{c[i]=0;i=i+1}
215 c[CLC_EXTENT]=-1;c[CLC_FINAL]=-1;c[CLC_OBSERVED]=sys_now_realtime_sec()
216 return 0
217}
218// Descriptor remains owned by the caller; path wrapper closes its own descriptor.
219func cl_slurp_tail_fd(fd:i64,cap:i64,lp:*i64,c:*i64)->*u8 {
220 cl_tail_reset(c);lp[0]=0
221 if cap<1||cap>CL_BUF {c[CLC_STATE]=CLC_INVALID;return 0 as *u8}
222 let size:i64=sys_lseek(fd,0,CL_SEEK_END)
223 if size<0{c[CLC_STATE]=CLC_SEEK;c[CLC_ERRNO]=size;return 0 as *u8}
224 c[CLC_EXTENT]=size
225 var start:i64=0;if size>cap{start=size-cap}
226 c[CLC_START]=start;c[CLC_END]=start
227 var partial:i64=0
228 let out:*u8=sys_mmap(cap+8)
229 if (out as i64)<=0{c[CLC_STATE]=CLC_ALLOC;c[CLC_ERRNO]=out as i64;return 0 as *u8}
230 if start>0{
231 let seek:i64=sys_lseek(fd,start-1,CL_SEEK_SET)
232 if seek!=start-1{c[CLC_STATE]=CLC_SEEK;c[CLC_ERRNO]=seek;sys_munmap(out,cap+8);return 0 as *u8}
233 let got:i64=sys_read(fd,out,1)
234 if got!=1{c[CLC_STATE]=CLC_READ_ERROR;c[CLC_ERRNO]=got;sys_munmap(out,cap+8);return 0 as *u8}
235 if out[0]!=(10 as u8){partial=1}
236 }
237 let seek:i64=sys_lseek(fd,start,CL_SEEK_SET)
238 if seek!=start{c[CLC_STATE]=CLC_SEEK;c[CLC_ERRNO]=seek;sys_munmap(out,cap+8);return 0 as *u8}
239 let wanted:i64=size-start
240 var n:i64=0;var run:i64=1
241 while n<wanted&&run==1{
242 let got:i64=sys_read(fd,(out as i64+n) as *u8,wanted-n)
243 if got<0{c[CLC_STATE]=CLC_READ_ERROR;c[CLC_ERRNO]=got;run=0}
244 else{if got==0{c[CLC_STATE]=CLC_CHANGED;run=0}else{n=n+got}}
245 }
246 c[CLC_READ]=n;c[CLC_END]=start+n
247 let final:i64=sys_lseek(fd,0,CL_SEEK_END);c[CLC_FINAL]=final
248 if c[CLC_STATE]==CLC_OK{
249 if final<0{c[CLC_STATE]=CLC_SEEK;c[CLC_ERRNO]=final}
250 else{if final!=size{c[CLC_STATE]=CLC_CHANGED}}
251 }
252 var first:i64=0
253 if partial==1{
254 var scanning:i64=1
255 while first<n&&scanning==1{if out[first]==(10 as u8){scanning=0};first=first+1}
256 }
257 var end:i64=n
258 var scanning:i64=1
259 while end>first&&scanning==1{if out[end-1]==(10 as u8){scanning=0}else{end=end-1}}
260 c[CLC_HEAD]=first;c[CLC_TAIL]=n-end
261 var i:i64=first;while i<end{out[i-first]=out[i];i=i+1}
262 out[end-first]=0 as u8
263 if c[CLC_STATE]==CLC_OK{lp[0]=end-first}
264 return out
265}
266func cl_slurp_tail_covered(path:*u8,lp:*i64,c:*i64)->*u8 {
267 cl_tail_reset(c);lp[0]=0
268 let fd:i64=cl_open_estate(path)
269 if fd<0{c[CLC_STATE]=CLC_OPEN;c[CLC_ERRNO]=fd;return 0 as *u8}
270 let out:*u8=cl_slurp_tail_fd(fd,CL_BUF,lp,c)
271 let closed:i64=sys_close(fd)
272 if closed!=0&&c[CLC_STATE]==CLC_OK{c[CLC_STATE]=CLC_CLOSE;c[CLC_ERRNO]=closed;lp[0]=0}
273 return out
274}
275func cl_slurp_tail(path:*u8,lp:*i64)->*u8 {
276 let c:*i64=sys_mmap(CLC_N*8) as *i64
277 let out:*u8=cl_slurp_tail_covered(path,lp,c)
278 sys_munmap(c as *u8,CLC_N*8)
279 return out
280}
281
282// REGISTRY PATH IS AUTHORITATIVE (nx_catalog, 2026-08-07): a registry row may point at a differently-named
283// binary (nishi_compare -> nx_compare_serve.elf). Resolve the ORGAN identity through the row when there is
284// one; fall back to the name convention only when the tool has no row at all. Returns the basename with
285// .elf stripped, length returned, 0 when no row.
286// file exists + size for a path taken EXACTLY AS THE REGISTRY WROTE IT. An absolute path is opened as
287// given -- cl_fsize would send it through cl_estate_path, which prepends EP_ROOT whenever the process is
288// not sitting at the estate root, turning "/volume1/.../x.elf" into a path that cannot exist. Estate-
289// relative rows keep the anchored behaviour.
290func cl_fsize_asgiven(path: *u8) -> i64 {
291 if path[0] != (CL_CH_SLASH as u8) { return cl_fsize(path) }
292 let fd: i64 = sys_openat_rd(path)
293 if fd < 0 { return 0 - 1 }
294 let n: i64 = sys_lseek(fd, 0, CL_SEEK_END)
295 sys_close(fd)
296 if n < 0 { return 0 - 1 }
297 return n
298}
299
300// remove ONE trailing suffix from out[0..o); returns the shortened length, or o unchanged when it is absent
301func cl_strip1(out: *u8, o: i64, sfx: *u8) -> i64 {
302 var L: i64 = 0
303 while sfx[L] != (0 as u8) { L = L + 1 }
304 if o <= L { return o }
305 var k: i64 = 0
306 var same: i64 = 1
307 while k < L { if out[o - L + k] != sfx[k] { same = 0; k = L } else { k = k + 1 } }
308 if same == 1 { return o - L }
309 return o
310}
311
312// remove the WHOLE artifact-suffix chain: "<organ>.sov.elf.new.prev" -> "<organ>". Looping matters: the
313// old code stripped exactly one ".elf" and therefore could not see past ".new" or ".prev" at all.
314func cl_strip_artifact(out: *u8, o0: i64) -> i64 {
315 var o: i64 = o0
316 var go: i64 = 1
317 while go == 1 {
318 let b: i64 = o
319 o = cl_strip1(out, o, ".prev" as *u8)
320 o = cl_strip1(out, o, ".new" as *u8)
321 o = cl_strip1(out, o, ".elf" as *u8)
322 o = cl_strip1(out, o, ".sov" as *u8)
323 if o == b { go = 0 }
324 }
325 out[o] = 0 as u8
326 return o
327}
328
329// ---- RESOLVE THE REGISTRY ROW, AND SAY WHICH WAY IT WENT (rewritten 2026-09-03) ----
330// THE DEFECT THIS REPLACES: the old cl_regorgan was handed a FULLY-QUALIFIED path in field 2 and THREW IT
331// AWAY -- it kept only the basename and stripped only a trailing ".elf". Every rung (source, built, staged,
332// promoted) is then looked up under that mangled name, so a row whose field 2 ends ".elf.new",
333// ".sov.elf.new" or ".sov.elf.new.prev" missed on ALL FOUR and scored "ABSENT -- it does not exist" about
334// organs that are present and byte-verifiable. MEASURED 2026-09-03: nx_comparestale (source 8391B, _build
335// 19705B, promoted 19705B) and nx_nofloat_scale_ffn_ctlprev (registered path present at 53624B) both read
336// ABSENT. nx_catalog is the organ every seat runs BEFORE building something, so a false ABSENT here
337// actively CAUSES duplicate-organ creation.
338// THE FIX IS TO STAT FIELD 2 AS GIVEN FIRST and fall back to the basename convention second.
339// out <- the effective ORGAN identity (basename, artifact-suffix CHAIN stripped) for source/build lookup
340// regp <- field 2 verbatim, NUL-terminated (absolute or estate-relative, exactly as the row wrote it)
341// rb[0]<- size of regp AS GIVEN, or -1 when it does not stat
342// returns CLR_NAME | CLR_PATH | CLR_REGBASE -- never a bare success/failure, because the CALLER has to be
343// able to tell "the row is the contract and it holds" from "the row points at nothing".
344func cl_regresolve(alw: *u8, alwn: i64, name: *u8, out: *u8, regp: *u8, rb: *i64, cap: i64) -> i64 {
345 rb[0] = 0 - 1
346 out[0] = 0 as u8
347 regp[0] = 0 as u8
348 var nl: i64 = 0
349 while name[nl] != (0 as u8) { nl = nl + 1 }
350 var i: i64 = 0
351 var ls: i64 = 0
352 var got: i64 = 0
353 while i <= alwn {
354 var eol: i64 = 0
355 if i == alwn { eol = 1 } else { if alw[i] == (10 as u8) { eol = 1 } }
356 if eol == 1 {
357 if got == 0 { if i - ls > nl {
358 var k: i64 = 0
359 var same: i64 = 1
360 while k < nl { if alw[ls + k] != name[k] { same = 0; k = nl } else { k = k + 1 } }
361 if same == 1 { if alw[ls + nl] == (9 as u8) {
362 let q: i64 = ls + nl + 1
363 // field 2 ends at the NEXT tab, or at end-of-line when the row has no argv column
364 var e2: i64 = q
365 var found: i64 = 0
366 while e2 < i { if alw[e2] == (9 as u8) { found = e2; e2 = i } else { e2 = e2 + 1 } }
367 var pend: i64 = i
368 if found > 0 { pend = found }
369 // (a) field 2 VERBATIM -- the thing we are about to stat as given
370 var w: i64 = q
371 var o: i64 = 0
372 while w < pend { if o < cap - 1 { regp[o] = alw[w]; o = o + 1 } w = w + 1 }
373 regp[o] = 0 as u8
374 // (b) the organ identity: basename, then the WHOLE artifact-suffix chain removed
375 var bs: i64 = q
376 var z: i64 = q
377 while z < pend { if alw[z] == (CL_CH_SLASH as u8) { bs = z + 1 } z = z + 1 }
378 var o2: i64 = 0
379 var w2: i64 = bs
380 while w2 < pend { if o2 < cap - 1 { out[o2] = alw[w2]; o2 = o2 + 1 } w2 = w2 + 1 }
381 out[o2] = 0 as u8
382 cl_strip_artifact(out, o2)
383 got = 1
384 } }
385 } }
386 ls = i + 1
387 }
388 i = i + 1
389 }
390 if got == 0 { return CLR_NAME }
391 rb[0] = cl_fsize_asgiven(regp)
392 if rb[0] >= 0 { return CLR_PATH }
393 return CLR_REGBASE
394}
395
396// the token that travels with every answer, so a reader can tell WHERE the ladder looked
397func cl_resolved_name(code: i64) -> *u8 {
398 if code == CLR_PATH { return "path" as *u8 }
399 if code == CLR_REGBASE { return "registry-basename" as *u8 }
400 return "name" as *u8
401}
402
403// WHERE DOES SOURCE LIVE? The six roots the shipping import resolver probes, in the order nx_catalog banked
404// 2026-08-16 (runtime/ then _hdl_build/ first, so every name that already resolved still resolves the same).
405// p receives the WINNING path; returns its size or -1.
406func cl_src(p: *u8, eff: *u8) -> i64 {
407 cl_cat3(p, "buildroot/runtime/" as *u8, eff, ".nx" as *u8)
408 var s: i64 = cl_fsize(p)
409 if s >= 0 { return s }
410 cl_cat3(p, "buildroot/runtime/_hdl_build/" as *u8, eff, ".nx" as *u8)
411 s = cl_fsize(p)
412 if s >= 0 { return s }
413 cl_cat3(p, "buildroot/runtime/bin/" as *u8, eff, ".nx" as *u8)
414 s = cl_fsize(p)
415 if s >= 0 { return s }
416 cl_cat3(p, "buildroot/runtime/hub/" as *u8, eff, ".nx" as *u8)
417 s = cl_fsize(p)
418 if s >= 0 { return s }
419 cl_cat3(p, "buildroot/runtime/wiki/" as *u8, eff, ".nx" as *u8)
420 s = cl_fsize(p)
421 if s >= 0 { return s }
422 cl_cat3(p, "buildroot/runtime/kernel/" as *u8, eff, ".nx" as *u8)
423 return cl_fsize(p)
424}
425
426// IS THIS SOURCE A LIBRARY? STRUCTURAL, NOT HEURISTIC (nx_catalog, 2026-08-16): a translation unit with no
427// top-level main() CANNOT become an executable, so "no binary" is its CORRECT state. Anchored at column 0 so
428// prose cannot answer for code. Third state on purpose: -1 UNREADABLE -- an axis that cannot see must
429// abstain, never classify an unreadable source as a library.
430func cl_is_lib(path: *u8) -> i64 {
431 let lp2: *i64 = sys_mmap(64) as *i64
432 let b: *u8 = cl_slurp(path, lp2)
433 let n: i64 = lp2[0]
434 if (b as i64) == 0 { return 0 - 1 }
435 if n <= 0 { return 0 - 1 }
436 let pat: *u8 = "func main(" as *u8
437 let pl: i64 = cl_slen(pat)
438 var i: i64 = 0
439 var ls: i64 = 0
440 var found: i64 = 0
441 while i <= n {
442 var eol: i64 = 0
443 if i == n { eol = 1 } else { if b[i] == (10 as u8) { eol = 1 } }
444 if eol == 1 {
445 if i - ls >= pl {
446 var k: i64 = 0
447 var same: i64 = 1
448 while k < pl { if b[ls + k] != pat[k] { same = 0; k = pl } else { k = k + 1 } }
449 if same == 1 { found = 1 }
450 }
451 ls = i + 1
452 }
453 i = i + 1
454 }
455 sys_munmap(b, CL_BUF + 8)
456 if found == 1 { return 0 }
457 return 1
458}
459
460// ---- THE LADDER, measured into m[] and judged weakest-link-first. ----
461// ORDER (nx_catalog, corrected 2026-08-07): PROMOTED is tested before SOURCE/BUILT, because a promoted binary
462// is proof it was built and ABSENT must mean NOTHING exists at all. A LIB with no binary and a DECLARED
463// daemon both return non-gap verdicts: scoring either against a rung it can never occupy invents a backlog
464// row that can never close.
465// A tool name in notes or a startup record is not completed-call evidence.
466func cl_actlog_completed(act: *u8, n: i64, name: *u8) -> i64 {
467 if (act as i64) == 0 { return 0 }
468 let wanted: i64 = cl_slen(name)
469 if wanted <= 0 { return 0 }
470 var start: i64 = 0
471 var i: i64 = 0
472 while i < n {
473 if act[i] == (10 as u8) {
474 var p: i64 = start
475 var col: i64 = 0
476 var field: i64 = start
477 var valid: i64 = 1
478 while p <= i {
479 var sep: i64 = 0
480 if p == i { sep = 1 } else { if act[p] == (9 as u8) { sep = 1 } }
481 if sep == 1 {
482 let len: i64 = p - field
483 if col == 0 {
484 if len <= 0 { valid = 0 }
485 var t: i64 = field
486 while t < p { if act[t] < (48 as u8) { valid = 0 } if act[t] > (57 as u8) { valid = 0 } t = t + 1 }
487 }
488 if col == 1 { if len != 3 { valid = 0 } else {
489 if act[field] != (109 as u8) { valid = 0 }
490 if act[field+1] != (99 as u8) { valid = 0 }
491 if act[field+2] != (112 as u8) { valid = 0 }
492 } }
493 if col == 2 {
494 if len != wanted { valid = 0 } else {
495 var t: i64 = 0
496 while t < wanted { if act[field+t] != name[t] { valid = 0 } t = t + 1 }
497 }
498 }
499 if col == 3 { if len != 4 { valid = 0 } else {
500 if act[field] != (99 as u8) { valid = 0 }
501 if act[field+1] != (97 as u8) { valid = 0 }
502 if act[field+2] != (108 as u8) { valid = 0 }
503 if act[field+3] != (108 as u8) { valid = 0 }
504 } }
505 if col == 4 { if len != 2 { valid = 0 } else {
506 if act[field] != (111 as u8) { valid = 0 }
507 if act[field+1] != (107 as u8) { valid = 0 }
508 } }
509 col = col + 1
510 field = p + 1
511 }
512 p = p + 1
513 }
514 if col == 6 { if valid == 1 { return 1 } }
515 start = i + 1
516 }
517 i = i + 1
518 }
519 return 0
520}
521
522func cl_ladder(name: *u8, alw: *u8, alwn: i64, cns: *u8, cnsn: i64, act: *u8, actn: i64, m: *i64) -> i64 {
523 let organ: *u8 = sys_mmap(CL_PATH)
524 let regp: *u8 = sys_mmap(CL_PATH)
525 let rb: *u8 = sys_mmap(64)
526 let rbi: *i64 = rb as *i64
527 let rcls: i64 = cl_regresolve(alw, alwn, name, organ, regp, rbi, CL_PATH)
528 var eff: *u8 = name
529 if rcls != CLR_NAME { eff = organ }
530 let p: *u8 = sys_mmap(CL_PATH)
531 let tab: *u8 = sys_mmap(64)
532 // ★★★SOURCE, BUILT AND STAGED ARE KEYED ON THE NAME THE CALLER ASKED FOR, NEVER ON THE ALIAS TARGET.
533 // MEASURED 2026-09-03, sev-8 row 1788487164: keying these three on `eff` made the catalogue report
534 // ANOTHER ORGAN'S BYTES under the requested name. Four of four figures were wrong for nx_https_get
535 // (reported 18035/480144/480144 against a real 9605/9808/14880 -- byte-for-byte nx_https_get_cli2's),
536 // and nx_https_get3, which has NO FILES ON ANY OF FIVE CANDIDATE PATHS, was published with a complete
537 // four-rung lifecycle. 99 of 1586 registry rows alias this way and 20 of them own real artifacts that
538 // the report silently replaced -- INCLUDING nx_fs AND nx_fs_write, so the estate's own read and write
539 // tools had never been correctly catalogued. FIVE separate lanes built BUILT-vs-PROMOTED drift tables
540 // on this instrument in one day.
541 // PROMOTED IS DELIBERATELY LEFT ON THE ROW below: field 2 is what the MCP surface actually execs, so it
542 // IS this name's promoted rung. The two identities are now reported SEPARATELY instead of one silently
543 // standing in for the other -- a pure alias honestly reads SOURCE/BUILT/STAGED absent with a real
544 // PROMOTED, which is the true shape of a name that is an entry point onto another organ's artifact.
545 let src: i64 = cl_src(p, name)
546 // classify BEFORE p is reused: it still holds the winning source path here
547 var lib: i64 = 0 - 1
548 if src >= 0 { lib = cl_is_lib(p) }
549 cl_cat3(p, "buildroot/_build/" as *u8, name, ".sov.elf" as *u8)
550 let built: i64 = cl_fsize(p)
551 cl_cat3(p, "" as *u8, name, ".sov.elf.new" as *u8)
552 let staged: i64 = cl_fsize(p)
553 // THE ROW IS THE CONTRACT: when field 2 stats AS GIVEN, that is the artifact the MCP surface actually
554 // execs, so it IS the promoted rung -- not a same-named file the name convention happens to land on.
555 // NO-REGRESSION MEASURED THE DAY THIS SHIPPED: the only rows whose field 2 carries no extension are the
556 // two aliases (nx_status, nx_torstat -> nx_hostctl) and they report 289624B either way, because bare
557 // nx_hostctl and nx_hostctl.elf are the same bytes. The .new/.prev rows are where the two disagree, and
558 // there the ROW is right: nx_nofloat_scale_ffn_ctlprev is the 53624B .prev, not the 60552B .elf beside it.
559 var promoted: i64 = 0 - 1
560 if rcls == CLR_PATH { promoted = rbi[0] }
561 if promoted < 0 {
562 cl_cat3(p, "" as *u8, eff, ".elf" as *u8)
563 promoted = cl_fsize(p)
564 }
565 if promoted < 0 {
566 cl_cat3(p, "_offc/" as *u8, eff, ".elf" as *u8)
567 promoted = cl_fsize(p)
568 }
569 // REGISTERED: the allowlist row is "<name><TAB>" -- the tab stops nx_adopt matching nx_adopt_lib
570 var t: i64 = 0
571 while name[t] != (0 as u8) { tab[t] = name[t]; t = t + 1 }
572 tab[t] = 9 as u8
573 tab[t + 1] = 0 as u8
574 let reg: i64 = cl_has_sub(alw, alwn, tab)
575 let auth: i64 = cl_has_sub(cns, cnsn, name)
576 let inv: i64 = cl_actlog_completed(act, actn, name)
577 let okp: *u8 = sys_mmap(CL_PATH)
578 let dkind: i64 = ok_kind_of_path(cl_estate_path(okp, "knowledge/status/organ_kind.conf" as *u8), name)
579 sys_munmap(okp, CL_PATH)
580 m[CLM_SRC] = src; m[CLM_LIB] = lib; m[CLM_BUILT] = built; m[CLM_STAGED] = staged; m[CLM_PROMOTED] = promoted
581 m[CLM_REG] = reg; m[CLM_AUTH] = auth; m[CLM_INV] = inv; m[CLM_DKIND] = dkind
582 m[CLM_RESOLVED] = rcls
583 sys_munmap(organ, CL_PATH); sys_munmap(p, CL_PATH); sys_munmap(tab, 64)
584 sys_munmap(regp, CL_PATH); sys_munmap(rb, 64)
585
586 // A REGISTRY ROW POINTING AT A DEAD PATH IS ITS OWN DEFECT, AND IT IS NOT ABSENCE (2026-09-03).
587 // Kept DISTINCT from CLV_ABSENT deliberately: ABSENT means "nothing exists, this is a build contract";
588 // MISPOINTED means "the organ IS here and the registered path cannot reach it", which is the one an MCP
589 // caller actually trips over and whose remedy is a RE-REGISTER, never a build. Falls through to the
590 // ordinary ladder when nothing resolved, so a name that genuinely does not exist still reports ABSENT.
591 if rcls == CLR_REGBASE {
592 if src >= 0 { return CLV_REGISTRY_MISPOINTED }
593 if built >= 0 { return CLV_REGISTRY_MISPOINTED }
594 if promoted >= 0 { return CLV_REGISTRY_MISPOINTED }
595 }
596 if promoted < 0 {
597 if src < 0 { if built < 0 { return CLV_ABSENT } }
598 // A DECLARED KIND WINS OVER THE STRUCTURAL READ (2026-09-02, the misread that published five DONE rungs
599 // on /compare/lang as done-but-partially-adopted): a `fixture` has a main BY DESIGN so its gate can
600 // compile it per run under the mode it proves, and a declared `lib` may carry a self-test main the
601 // no-main scan cannot see (nx_thread_pool). Undeclared sources keep the structural rules below.
602 if dkind == OK_FIXTURE { if src >= 0 { return CLV_FIXTURE } }
603 if dkind == OK_LIB { if src >= 0 { return CLV_LIB } }
604 if lib == 1 { if built < 0 { return CLV_LIB } }
605 if built < 0 { return CLV_SOURCE_ONLY }
606 return CLV_BUILT_UNPROMOTED
607 }
608 if src < 0 { return CLV_PROMOTED_SOURCELESS }
609 if dkind == OK_DAEMON { return CLV_LIVE_DAEMON }
610 if reg == 0 { return CLV_PROMOTED_UNREGISTERED }
611 if auth == 0 { return CLV_REGISTERED_UNAUTHORISED }
612 if inv == 0 { return CLV_REGISTERED_DARK }
613 return CLV_LIVE
614}
615
616// 1 = this verdict is an adoption GAP (nx_catalog's with_gaps counts it); 0 = not a gap
617func cl_gap(code: i64) -> i64 {
618 if code == CLV_LIVE { return 0 }
619 if code == CLV_LIB { return 0 }
620 if code == CLV_LIVE_DAEMON { return 0 }
621 if code == CLV_FIXTURE { return 0 }
622 return 1
623}
624
625// the short token a board prints (no spaces, safe in an HTML attribute and a TSV cell)
626func cl_verdict_name(code: i64) -> *u8 {
627 if code == CLV_ABSENT { return "ABSENT" as *u8 }
628 if code == CLV_SOURCE_ONLY { return "SOURCE-ONLY" as *u8 }
629 if code == CLV_BUILT_UNPROMOTED { return "BUILT-UNPROMOTED" as *u8 }
630 if code == CLV_PROMOTED_SOURCELESS { return "PROMOTED-SOURCELESS" as *u8 }
631 if code == CLV_PROMOTED_UNREGISTERED { return "PROMOTED-UNREGISTERED" as *u8 }
632 if code == CLV_REGISTERED_UNAUTHORISED { return "REGISTERED-UNAUTHORISED" as *u8 }
633 if code == CLV_REGISTERED_DARK { return "REGISTERED-DARK" as *u8 }
634 if code == CLV_LIVE { return "LIVE" as *u8 }
635 if code == CLV_LIB { return "LIB" as *u8 }
636 if code == CLV_LIVE_DAEMON { return "LIVE-DAEMON" as *u8 }
637 if code == CLV_FIXTURE { return "FIXTURE" as *u8 }
638 if code == CLV_REGISTRY_MISPOINTED { return "REGISTRY-MISPOINTED" as *u8 }
639 return "UNKNOWN" as *u8
640}
641
642// the one-line remedy a board prints beside a gap (what closes it), empty for non-gaps
643func cl_remedy(code: i64) -> *u8 {
644 if code == CLV_ABSENT { return "no source and no binary: this is a build contract, not a partial deploy" as *u8 }
645 if code == CLV_SOURCE_ONLY { return "source exists, never compiled: /api/build it" as *u8 }
646 if code == CLV_BUILT_UNPROMOTED { return "compiled, never promoted to the serving root: /api/promote it" as *u8 }
647 if code == CLV_PROMOTED_SOURCELESS { return "it runs but cannot be rebuilt: its source is gone from the tree" as *u8 }
648 if code == CLV_PROMOTED_UNREGISTERED { return "a real binary nobody can call over MCP: /api/tools/register it" as *u8 }
649 if code == CLV_REGISTERED_UNAUTHORISED { return "registered, no cap ever minted" as *u8 }
650 if code == CLV_REGISTERED_DARK { return "callable, authorised, no completed MCP invocation in the scanned journal window; lifetime history unknown (a direct fork logs the runner, so this is not proof it never ran)" as *u8 }
651 if code == CLV_REGISTRY_MISPOINTED { return "the organ is present but its registered path does not stat: re-register it at a path that exists" as *u8 }
652 return "" as *u8
653}
654
655// the exact verdict sentence nx_catalog prints, newline included (byte-identity contract with that organ)
656func cl_verdict_text(code: i64) -> *u8 {
657 if code == CLV_ABSENT { return "ABSENT -- no source, no binary, nothing promoted. It does not exist.\n" as *u8 }
658 if code == CLV_LIB { return "LIB -- no top-level main(), so this CANNOT produce a binary and having none is CORRECT, not a gap. For a library the adoption question is IMPORTER COUNT, not binary presence: measure it with nx_absent over the tree for the import line naming this organ.\n" as *u8 }
659 if code == CLV_SOURCE_ONLY { return "SOURCE-ONLY (S2) -- source exists, no shipped binary. Build it.\n" as *u8 }
660 if code == CLV_BUILT_UNPROMOTED { return "BUILT-UNPROMOTED -- compiled but not promoted to the serving root.\n" as *u8 }
661 if code == CLV_PROMOTED_SOURCELESS { return "PROMOTED-SOURCELESS -- it RUNS but CANNOT BE REBUILT: no source in the tree. A fix, a port, or a security patch is impossible until the source is found or rewritten.\n" as *u8 }
662 if code == CLV_LIVE_DAEMON { return "LIVE-DAEMON -- DECLARED `daemon`, so REGISTERED/AUTHORISED are NOT gaps: it serves a port instead of being called as a tool, and registering it would fork a new server per call. Its adoption question is whether the port is SERVED -- ask nx_health, or the portmap.conf row.\n" as *u8 }
663 if code == CLV_FIXTURE { return "FIXTURE -- DECLARED `fixture`: a runnable witness its GATE compiles per run under the mode it proves, so a promoted binary is NOT expected and having none is CORRECT, not a gap. Its adoption question is WHICH GATES compile it -- the roster rows naming its path -- never the MCP ladder (consumer count is not yet censused; nx_absent over the tree for its path answers it).\n" as *u8 }
664 if code == CLV_PROMOTED_UNREGISTERED { return "PROMOTED-UNREGISTERED (S3) -- a real binary NOBODY CAN CALL. Register it.\n" as *u8 }
665 if code == CLV_REGISTERED_UNAUTHORISED { return "REGISTERED-UNAUTHORISED (S4) -- registered, no cap ever minted.\n" as *u8 }
666 if code == CLV_REGISTERED_DARK { return "REGISTERED-DARK (S4) -- callable, authorised, no completed MCP invocation in the scanned journal window; lifetime history unknown. NOTE: actlog sees the MCP surface only; a direct fork (nx_job_run) logs the RUNNER, not this organ, so this is NOT proof it never ran.\n" as *u8 }
667 if code == CLV_REGISTRY_MISPOINTED { return "REGISTRY-MISPOINTED -- the organ IS here (the sizes above are real) but field 2 of its tool_allowlist.conf row does NOT stat, so the MCP surface cannot exec it. This is NOT absence: do not build it, RE-REGISTER it at a path that exists (/api/tools/register name= elf= confirm=yes).\n" as *u8 }
668 return "LIVE -- source, binary, promoted, registered, authorised, invoked.\n" as *u8
669}
670
671// organ NAME from a board's organ-path column: "runtime/_hdl_build/nx_body_gen.nx" -> "nx_body_gen".
672// Returns the name length written into out (NUL-terminated), 0 when the path has no basename.
673func cl_name_of_path(path: *u8, out: *u8, cap: i64) -> i64 {
674 var n: i64 = 0
675 var bs: i64 = 0
676 while path[n] != (0 as u8) { if path[n] == (47 as u8) { bs = n + 1 } n = n + 1 }
677 var e: i64 = n
678 if e >= bs + 3 { if path[e-3] == (46 as u8) { if path[e-2] == (110 as u8) { if path[e-1] == (120 as u8) { e = e - 3 } } } }
679 var o: i64 = 0
680 var i: i64 = bs
681 while i < e { if o < cap - 1 { out[o] = path[i]; o = o + 1 } i = i + 1 }
682 out[o] = 0 as u8
683 return o
684}
685
686// ---- THE ONE SYMBOL RULER (2026-08-23): "the implementing symbol exists in the organ source" ----
687// MEASURED BY A SIBLING SEAT THE SAME DAY: the compare page tested a SUBSTRING (c_file_has) and the ranker
688// tested a top-level DECLARATION (rk_measure), so LN8 read LANDED on the page and OPEN in the ranker at once.
689// Two rulers for one question is the duplicate-ruler defect; this is the one both now call. The rule is the
690// ranker's, because it is the honest reading: a line beginning `func <sym>` followed by '(' or ' ' -- a
691// mention in a comment, a string or a gate's tooth name is documentation, not an implementation.
692// The organ path is estate-relative (runtime/...), resolved through the same anchor as every other read.
693// Returns 1 declared, 0 not declared, -1 when the source cannot be read (abstain, never acquit).
694func cl_symbol_declared(organ_path: *u8, sym: *u8) -> i64 {
695 let pb: *u8 = sys_mmap(cl_slen(organ_path) + 16)
696 var o: i64 = 0
697 if organ_path[0] == (47 as u8) { o = cl_cat3(pb, "" as *u8, organ_path, "" as *u8) }
698 else {
699 let pre: *u8 = "buildroot/" as *u8
700 var pi: i64 = 0
701 var isb: i64 = 1
702 while pre[pi] != (0 as u8) { if organ_path[pi] != pre[pi] { isb = 0; pi = cl_slen(pre) } else { pi = pi + 1 } }
703 if isb == 1 { o = cl_cat3(pb, "" as *u8, organ_path, "" as *u8) } else { o = cl_cat3(pb, "buildroot/" as *u8, organ_path, "" as *u8) }
704 }
705 let lp: *i64 = sys_mmap(16) as *i64
706 let b: *u8 = cl_read_whole(pb, lp)
707 let n: i64 = lp[0]
708 sys_munmap(pb, cl_slen(organ_path) + 16)
709 if (b as i64) == 0 { return 0 - 1 }
710 if n <= 0 { sys_munmap(b, n + 8); return 0 - 1 }
711 let sl: i64 = cl_slen(sym)
712 var found: i64 = 0
713 var i: i64 = 0
714 while i < n {
715 var atbol: i64 = 0
716 if i == 0 { atbol = 1 } else { if b[i-1] == (10 as u8) { atbol = 1 } }
717 if atbol == 1 { if i + 5 + sl < n { if b[i] == (102 as u8) { if b[i+1] == (117 as u8) { if b[i+2] == (110 as u8) { if b[i+3] == (99 as u8) { if b[i+4] == (32 as u8) {
718 var k: i64 = 0
719 var same: i64 = 1
720 while k < sl { if b[i+5+k] != sym[k] { same = 0; k = sl } k = k + 1 }
721 if same == 1 { let nx2: i64 = b[i+5+sl] as i64; if nx2 == 40 { found = 1; i = n } if nx2 == 32 { found = 1; i = n } }
722 } } } } } } }
723 i = i + 1
724 }
725 sys_munmap(b, n + 8)
726 return found
727}
728
729// ==== THE BOARD-LEVEL ADOPTION STATE: one composition of three rulers, by organ kind (2026-08-23, CE2) ====
730// The ladder above is the MCP-surface truth for a PROGRAM. A board also carries LIBRARIES (no binary by
731// design: their question is importer reach) and GATES (run by the roster and the clock, so they read DARK on
732// the MCP-only ladder while executing nightly). Each kind has an incumbent ruler; this composes them so the
733// generator and the ranker cannot classify the same row differently:
734// program cl_ladder (above)
735// library knowledge/status/importers.tsv -- nx_importcensus over the eco-graph store; importers MINUS
736// validation importers (a lib imported only by its gate is BUILT+UNWIRED, not adopted)
737// gate knowledge/status/gateadjudicate.rows -- nx_gateadjudicate's execution-surface census + trial verdict
738// FULL only at the top of the kind's ladder: LIVE, LIVE-DAEMON, LIB-WIRED, GATE:LIVE. Everything short is
739// PARTIAL and carries its remedy. Every census stamps itself (asof), returned so the consumer prints it.
740const CLB_TOK_CAP: i64 = 96
741const CLB_FULL: i64 = 1
742const CLB_PARTIAL: i64 = 0
743const CLB_NA: i64 = 2
744const CLB_TAB: i64 = 9
745const CLB_PIPE: i64 = 124
746const CLB_GA_COL_TRIAL: i64 = 17 // gateadjudicate.rows: name|src|...|ref|first_ref|trial|class
747const CLB_GA_COL_CLASS: i64 = 18
748const CLB_IMP_COL_IMPORTERS: i64 = 1 // importers.tsv: name importers importers_nonval imports first
749const CLB_IMP_COL_NONVAL: i64 = 2
750// ads[] slots filled by clb_load
751const CLB_REG: i64 = 0
752const CLB_REGN: i64 = 1
753const CLB_CNS: i64 = 2
754const CLB_CNSN: i64 = 3
755const CLB_ACT: i64 = 4
756const CLB_ACTN: i64 = 5
757const CLB_IMP: i64 = 6
758const CLB_IMPN: i64 = 7
759const CLB_GA: i64 = 8
760const CLB_GAN: i64 = 9
761const CLB_IMP_ASOF: i64 = 10
762const CLB_GA_ASOF: i64 = 11
763// THE MCP REGISTRY IS NOT THE ONLY DOOR (2026-08-23): knowledge/status/execsurface.tsv (nx_execsurface) names,
764// per promoted organ, the surface that CAUSES its execution -- clock plane, cron, daemon supervisor, gate
765// roster, the MCP tail, or a fork from an organ that is itself on a surface. Without it every beat-run
766// program read REGISTERED-DARK: measured on the graphics board, 12 of 19 PARTIAL rows.
767const CLB_ES: i64 = 12
768const CLB_ESN: i64 = 13
769const CLB_ES_ASOF: i64 = 14
770const CLB_N: i64 = 15
771const CLB_ES_COL_FIRST: i64 = 7 // execsurface.tsv: name clock cron daemon fork roster actlog first_surface
772const CLB_REM_CAP: i64 = 512 // a composed remedy: the ladder's sentence plus the surfaces checked
773
774func clb_eq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 }
775func clb_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } d[p] = 0 as u8; return p }
776func clb_ends(s: *u8, sfx: *u8) -> i64 {
777 let n: i64 = cl_slen(s)
778 let m: i64 = cl_slen(sfx)
779 if n < m { return 0 }
780 var k: i64 = 0
781 while k < m { if s[n - m + k] != sfx[k] { return 0 } k = k + 1 }
782 return 1
783}
784func clb_catn(d: *u8, o: i64, v: i64) -> i64 {
785 var p: i64 = o
786 var m: i64 = v
787 if m < 0 { d[p] = 45 as u8; p = p + 1; m = 0 - m }
788 let t: *u8 = sys_mmap(24)
789 var k: i64 = 0
790 if m == 0 { t[0] = 48 as u8; k = 1 }
791 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
792 var j: i64 = 0
793 while j < k { d[p] = t[k - 1 - j]; p = p + 1; j = j + 1 }
794 d[p] = 0 as u8
795 sys_munmap(t, 24)
796 return p
797}
798// digits at b[i..n); -1 when none
799func clb_digits(b: *u8, i: i64, n: i64) -> i64 {
800 var v: i64 = 0
801 var any: i64 = 0
802 var j: i64 = i
803 while j < n {
804 let c: i64 = b[j] as i64
805 if c < 48 { break }
806 if c > 57 { break }
807 v = v * 10 + (c - 48); any = 1; j = j + 1
808 }
809 if any == 0 { return 0 - 1 }
810 return v
811}
812// offset of the row whose FIRST field (closed by sep) equals name; -1 when absent. b is raw file bytes.
813func clb_row(b: *u8, n: i64, name: *u8, sep: i64) -> i64 {
814 let nl: i64 = cl_slen(name)
815 var i: i64 = 0
816 while i < n {
817 var e: i64 = i
818 while e < n { if b[e] == (10 as u8) { break } e = e + 1 }
819 if e - i > nl { if (b[i + nl] as i64) == sep {
820 var k: i64 = 0
821 var same: i64 = 1
822 while k < nl { if b[i + k] != name[k] { same = 0; k = nl } else { k = k + 1 } }
823 if same == 1 { return i }
824 } }
825 i = e + 1
826 }
827 return 0 - 1
828}
829// start offset of field f (0-based) of the row at r; -1 when the row is shorter
830func clb_field_off(b: *u8, n: i64, r: i64, f: i64, sep: i64) -> i64 {
831 var i: i64 = r
832 var cur: i64 = 0
833 while cur < f {
834 while i < n { if (b[i] as i64) == sep { break } if b[i] == (10 as u8) { return 0 - 1 } i = i + 1 }
835 if i >= n { return 0 - 1 }
836 i = i + 1
837 cur = cur + 1
838 }
839 return i
840}
841func clb_field_str(b: *u8, n: i64, r: i64, f: i64, sep: i64, out: *u8, cap: i64) -> i64 {
842 let st: i64 = clb_field_off(b, n, r, f, sep)
843 if st < 0 { out[0] = 0 as u8; return 0 - 1 }
844 var o: i64 = 0
845 var i: i64 = st
846 while i < n {
847 if (b[i] as i64) == sep { break }
848 if b[i] == (10 as u8) { break }
849 if o < cap - 1 { out[o] = b[i]; o = o + 1 }
850 i = i + 1
851 }
852 out[o] = 0 as u8
853 return o
854}
855func clb_field_int(b: *u8, n: i64, r: i64, f: i64, sep: i64) -> i64 {
856 let st: i64 = clb_field_off(b, n, r, f, sep)
857 if st < 0 { return 0 - 1 }
858 return clb_digits(b, st, n)
859}
860// value of key= on the LAST line of b (anchored BY POSITION: the producer's canonical verdict row); -1 absent
861func clb_last_kv(b: *u8, n: i64, key: *u8) -> i64 {
862 if n <= 0 { return 0 - 1 }
863 var ls: i64 = n - 1
864 if b[ls] == (10 as u8) { ls = ls - 1 }
865 while ls > 0 { if b[ls - 1] == (10 as u8) { break } ls = ls - 1 }
866 let kl: i64 = cl_slen(key)
867 var i: i64 = ls
868 while i + kl <= n {
869 var k: i64 = 0
870 var same: i64 = 1
871 while k < kl { if b[i + k] != key[k] { same = 0; k = kl } else { k = k + 1 } }
872 if same == 1 { return clb_digits(b, i + kl, n) }
873 if b[i] == (10 as u8) { return 0 - 1 }
874 i = i + 1
875 }
876 return 0 - 1
877}
878// load every source the classifier reads, ONCE per run; an absent census reads as length 0 and asof -1,
879// so the consumer prints "-1" rather than inheriting a stale trust it did not measure
880func clb_load(ads: *i64) -> i64 {
881 let lp: *i64 = sys_mmap(16) as *i64
882 ads[CLB_REG] = cl_slurp("tool_allowlist.conf" as *u8, lp) as i64; ads[CLB_REGN] = lp[0]
883 ads[CLB_CNS] = cl_slurp("cap_consent.log" as *u8, lp) as i64; ads[CLB_CNSN] = lp[0]
884 ads[CLB_ACT] = cl_slurp_tail("knowledge/status/actlog.jrnl" as *u8, lp) as i64; ads[CLB_ACTN] = lp[0]
885 let impb: *u8 = cl_read_whole("knowledge/status/importers.tsv" as *u8, lp)
886 ads[CLB_IMP] = impb as i64; ads[CLB_IMPN] = lp[0]
887 if (impb as i64) == 0 { ads[CLB_IMPN] = 0 }
888 let gab: *u8 = cl_read_whole("knowledge/status/gateadjudicate.rows" as *u8, lp)
889 ads[CLB_GA] = gab as i64; ads[CLB_GAN] = lp[0]
890 if (gab as i64) == 0 { ads[CLB_GAN] = 0 }
891 let galog: *u8 = cl_read_whole("knowledge/status/gateadjudicate.log" as *u8, lp)
892 var galogn: i64 = lp[0]
893 if (galog as i64) == 0 { galogn = 0 }
894 ads[CLB_IMP_ASOF] = clb_last_kv(impb, ads[CLB_IMPN], "asof=" as *u8)
895 ads[CLB_GA_ASOF] = clb_last_kv(galog, galogn, "epoch=" as *u8)
896 let esb: *u8 = cl_read_whole("knowledge/status/execsurface.tsv" as *u8, lp)
897 ads[CLB_ES] = esb as i64; ads[CLB_ESN] = lp[0]
898 if (esb as i64) == 0 { ads[CLB_ESN] = 0 }
899 ads[CLB_ES_ASOF] = clb_last_kv(esb, ads[CLB_ESN], "asof=" as *u8)
900 return 0
901}
902// classify one organ NAME (basename, no .nx). tok receives the state token (CLB_TOK_CAP), rem[0] the remedy
903// pointer (empty when FULL). Returns CLB_FULL or CLB_PARTIAL.
904func clb_classify(name: *u8, ads: *i64, tok: *u8, rem: *i64) -> i64 {
905 rem[0] = "" as *u8 as i64
906 if clb_ends(name, "_gate" as *u8) == 1 {
907 let gb: *u8 = ads[CLB_GA] as *u8
908 let gn: i64 = ads[CLB_GAN]
909 if gn > 0 {
910 let r: i64 = clb_row(gb, gn, name, CLB_PIPE)
911 if r >= 0 {
912 let cls: *u8 = sys_mmap(48)
913 let trial: *u8 = sys_mmap(32)
914 clb_field_str(gb, gn, r, CLB_GA_COL_CLASS, CLB_PIPE, cls, 48)
915 clb_field_str(gb, gn, r, CLB_GA_COL_TRIAL, CLB_PIPE, trial, 32)
916 var o: i64 = clb_cat(tok, 0, "GATE:" as *u8)
917 o = clb_cat(tok, o, cls)
918 o = clb_cat(tok, o, " trial=" as *u8)
919 o = clb_cat(tok, o, trial)
920 if clb_eq(cls, "LIVE" as *u8) == 1 { return CLB_FULL }
921 if clb_eq(cls, "DEPLOYED-DARK" as *u8) == 1 { rem[0] = "deployed, no execution surface runs it: admit it to the gate roster" as *u8 as i64 }
922 if clb_eq(cls, "BUILT-UNPROMOTED" as *u8) == 1 { rem[0] = "compiled, never promoted to the serving root: /api/promote it, then roster it" as *u8 as i64 }
923 if clb_eq(cls, "INVOKED-MISSING" as *u8) == 1 { rem[0] = "a surface names it but no binary is promoted: build and promote it" as *u8 as i64 }
924 if clb_eq(cls, "SOURCE-ONLY" as *u8) == 1 { rem[0] = "never built: /api/build it, promote it, roster it" as *u8 as i64 }
925 return CLB_PARTIAL
926 }
927 }
928 // not in the gate census: the MCP ladder answers below, and its token says which ruler spoke
929 }
930 let m: *i64 = sys_mmap(CLM_N * 8) as *i64
931 let code: i64 = cl_ladder(name, ads[CLB_REG] as *u8, ads[CLB_REGN], ads[CLB_CNS] as *u8, ads[CLB_CNSN], ads[CLB_ACT] as *u8, ads[CLB_ACTN], m)
932 if code == CLV_LIB {
933 let ib: *u8 = ads[CLB_IMP] as *u8
934 let inn: i64 = ads[CLB_IMPN]
935 let nm: *u8 = sys_mmap(CLB_TOK_CAP)
936 var q: i64 = clb_cat(nm, 0, name)
937 q = clb_cat(nm, q, ".nx" as *u8)
938 var r2: i64 = 0 - 1
939 if inn > 0 { r2 = clb_row(ib, inn, nm, CLB_TAB) }
940 if r2 < 0 {
941 clb_cat(tok, 0, "LIB-UNCENSUSED" as *u8)
942 rem[0] = "a library absent from the import-graph census (younger than the last eco-graph build, or unreachable from buildroot/runtime)" as *u8 as i64
943 return CLB_PARTIAL
944 }
945 let imp: i64 = clb_field_int(ib, inn, r2, CLB_IMP_COL_IMPORTERS, CLB_TAB)
946 let nv: i64 = clb_field_int(ib, inn, r2, CLB_IMP_COL_NONVAL, CLB_TAB)
947 if nv > 0 {
948 var o3: i64 = clb_cat(tok, 0, "LIB-WIRED importers=" as *u8)
949 o3 = clb_catn(tok, o3, imp)
950 o3 = clb_cat(tok, o3, " nonval=" as *u8)
951 o3 = clb_catn(tok, o3, nv)
952 return CLB_FULL
953 }
954 if imp > 0 {
955 var o4: i64 = clb_cat(tok, 0, "LIB-GATE-ONLY importers=" as *u8)
956 o4 = clb_catn(tok, o4, imp)
957 rem[0] = "imported only by validation organs (gates, tests, benches): wire it into a shipping program" as *u8 as i64
958 return CLB_PARTIAL
959 }
960 clb_cat(tok, 0, "LIB-UNIMPORTED" as *u8)
961 rem[0] = "nothing imports it: wire it into a consumer or retire it" as *u8 as i64
962 return CLB_PARTIAL
963 }
964 if cl_gap(code) == 0 {
965 clb_cat(tok, 0, cl_verdict_name(code))
966 return CLB_FULL
967 }
968 // A PROMOTED program the MCP door never saw: ask the execution-surface census before calling it dark.
969 // Only the door-related verdicts are re-judged; SOURCE-ONLY / BUILT-UNPROMOTED / ABSENT have no binary
970 // a surface could run, and PROMOTED-SOURCELESS is a rebuild hazard whatever runs it.
971 var door: i64 = 0
972 if code == CLV_REGISTERED_DARK { door = 1 }
973 if code == CLV_PROMOTED_UNREGISTERED { door = 1 }
974 if code == CLV_REGISTERED_UNAUTHORISED { door = 1 }
975 if door == 1 {
976 let eb: *u8 = ads[CLB_ES] as *u8
977 let en: i64 = ads[CLB_ESN]
978 if en > 0 {
979 let r3: i64 = clb_row(eb, en, name, CLB_TAB)
980 if r3 >= 0 {
981 let fs: *u8 = sys_mmap(CLB_TOK_CAP)
982 clb_field_str(eb, en, r3, CLB_ES_COL_FIRST, CLB_TAB, fs, CLB_TOK_CAP)
983 var runs: i64 = 0
984 if fs[0] != (0 as u8) { if fs[0] != (45 as u8) { runs = 1 } }
985 if runs == 1 { if fs[0] == (114 as u8) { if fs[1] == (101 as u8) { if fs[2] == (102 as u8) { if fs[3] == (58 as u8) { runs = 0 } } } } }
986 if runs == 1 {
987 var o7: i64 = clb_cat(tok, 0, "RUN-BY:" as *u8)
988 o7 = clb_cat(tok, o7, fs)
989 return CLB_FULL
990 }
991 // not on any surface: keep the ladder's verdict, and say which doors were checked and who merely names it
992 let rb: *u8 = sys_mmap(CLB_REM_CAP)
993 var ro: i64 = clb_cat(rb, 0, cl_remedy(code))
994 ro = clb_cat(rb, ro, "; no execution surface runs it either (clock, cron, daemon, roster, actlog and surfaced forks checked)" as *u8)
995 if fs[0] == (114 as u8) { ro = clb_cat(rb, ro, "; only referenced by " as *u8); ro = clb_cat(rb, ro, (fs as i64 + 4) as *u8); ro = clb_cat(rb, ro, " -- a mention, not a run" as *u8) }
996 clb_cat(tok, 0, cl_verdict_name(code))
997 rem[0] = rb as i64
998 return CLB_PARTIAL
999 }
1000 }
1001 }
1002 clb_cat(tok, 0, cl_verdict_name(code))
1003 rem[0] = cl_remedy(code) as i64
1004 return CLB_PARTIAL
1005}
1006