nx_shipcheck.nx source
↩ module page · 537 lines · 20060 B
1// nx_shipcheck.nx -- SHIP-COMPLETE integration-orphan detector (POST-submit lane; operator law
2// feedback-ship-complete-lifecycle-standard 2026-07-21, ws=auto-shipcomplete-guards).
3// Counts integration orphans per class over the REAL registry surfaces:
4// noschema tool_allowlist.conf rows with NO schema row in knowledge/tool_schemas.conf
5// staleschema tool_schemas.conf rows whose tool is NOT in tool_allowlist.conf (ghost schema)
6// stagedref registry rows whose binary path contains .new (registered-but-never-promoted)
7// missingbin registry rows whose binary is ABSENT on disk (tools/call would exec-fail)
8// straynew stranded .new artifacts in the deploy root (one-level walk, DECLARED)
9// verb `listnew [root]` PRINTS those names (exit code = the count) -- see sc_scan_new's header for why.
10// noatlas registry tools absent from knowledge/registry/atlas_catalog.tsv col1
11// Composed context (owned elsewhere, echoed for the trend line, NEVER re-scanned or re-filed):
12// dupsrc last count from knowledge/status/dup_source.log (seq207 lane)
13// unreg_l003 last L003 measured from knowledge/status/law_warden.jrnl (warden lane)
14// frowjoin=-1 DECLARED UNMEASURED: frontier rows carry no ws column (F209 evidence gap).
15// verbs: scan [root] | beat [root] | file [root] [filer]
16// scan: sweep + print + O_APPEND one trend line to <root>/knowledge/status/shipcheck.log
17// beat: scan + auto-file debts via the ALLOWLIST-RESOLVED filer (default nx_debt)
18// file: scan + file via an INJECTED filer tool name (the gate passes argecho -- selftest
19// never writes the production debt plane; F872 harden pattern)
20// Descs are CANONICAL and COUNT-FREE so nx_debt content-idempotent add (F868) makes any
21// beat cadence spam-proof BY CONSTRUCTION. Envelope: per-file read caps DECLARED via capped=.
22// license_tier: ORIGINAL Read-only sweep + O_APPEND log + debt filing. No hw writes (Rule 26).
23import "nx_syscalls.nx"
24
25const SC_TAB: i64 = 9
26const SC_NL: i64 = 10
27const SC_HASH: i64 = 35
28const SC_DOT: i64 = 46
29const SC_SLASH: i64 = 47
30const SC_COLON: i64 = 58
31const SC_ZERO: i64 = 48
32const SC_NINE: i64 = 57
33const SC_MINUS: i64 = 45
34const SC_B10: i64 = 10
35const SC_B256: i64 = 256
36const SC_LC_N: i64 = 110
37const SC_LC_E: i64 = 101
38const SC_LC_W: i64 = 119
39const SC_BUFCAP: i64 = 262144
40const SC_LOGCAP: i64 = 1048576
41const SC_PATHCAP: i64 = 1024
42const SC_OUTCAP: i64 = 8192
43const SC_DESCCAP: i64 = 1024
44const SC_DIRCAP: i64 = 262144
45const SC_MODE_F: i64 = 420
46const SC_EXITRED: i64 = 3
47const SC_EXEFAIL: i64 = 127
48const SC_STATBUF: i64 = 160
49const SC_NEWLEN: i64 = 4
50const SC_SEV_MISSINGBIN: i64 = 7
51const SC_SEV_STAGEDREF: i64 = 7
52const SC_SEV_NOSCHEMA: i64 = 6
53const SC_SEV_STALESCHEMA: i64 = 5
54const SC_SEV_STRAYNEW: i64 = 5
55const SC_SEV_NOATLAS: i64 = 4
56
57static g_root: *u8
58static g_allow: *u8
59static g_an: i64
60static g_schema: *u8
61static g_sn: i64
62static g_atlas: *u8
63static g_atn: i64
64static g_scr: *u8
65static g_scr2: *u8
66static g_sp: *i64
67static g_rn: i64
68static g_hitcap: i64
69static g_sev: i64
70static g_c_allow: i64
71static g_c_schema: i64
72static g_c_noschema: i64
73static g_c_staleschema: i64
74static g_c_stagedref: i64
75static g_c_missingbin: i64
76static g_c_straynew: i64
77static g_c_dupsrc: i64
78static g_c_unreg: i64
79static g_c_noatlas: i64
80
81func sc_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
82
83func sc_cat(d: *u8, o: i64, s: *u8) -> i64 {
84 var i: i64 = 0
85 var p: i64 = o
86 while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 }
87 d[p] = 0 as u8
88 return p
89}
90
91func sc_catn(d: *u8, o: i64, v: i64) -> i64 {
92 let t: *u8 = sys_mmap(32)
93 var m: i64 = v
94 var p: i64 = o
95 if m < 0 { d[p] = SC_MINUS as u8; p = p + 1; m = 0 - m }
96 var k: i64 = 0
97 if m == 0 { t[0] = SC_ZERO as u8; k = 1 }
98 while m > 0 { t[k] = (SC_ZERO + (m % SC_B10)) as u8; m = m / SC_B10; k = k + 1 }
99 var i: i64 = 0
100 while i < k { d[p] = t[k-1-i]; p = p + 1; i = i + 1 }
101 d[p] = 0 as u8
102 return p
103}
104
105func sc_path(d: *u8, rel: *u8) -> *u8 {
106 var o: i64 = sc_cat(d, 0, g_root)
107 d[o] = SC_SLASH as u8
108 o = o + 1
109 o = sc_cat(d, o, rel)
110 return d
111}
112
113func sc_readf(rel: *u8, cap: i64) -> *u8 {
114 let pb: *u8 = sys_mmap(SC_PATHCAP)
115 let pp: *u8 = sc_path(pb, rel)
116 let buf: *u8 = sys_mmap(cap)
117 g_rn = 0
118 let fd: i64 = sys_openat_rd(pp)
119 if fd < 0 { return buf }
120 var t: i64 = 0
121 var done: i64 = 0
122 while done == 0 {
123 let want: i64 = cap - 8 - t
124 let r: i64 = sys_read(fd, buf + t, want)
125 if r <= 0 { done = 1 } else { t = t + r; if t >= cap - 8 { done = 1; g_hitcap = 1 } }
126 }
127 sys_close(fd)
128 g_rn = t
129 return buf
130}
131
132func sc_le(b: *u8, i: i64, n: i64) -> i64 {
133 var j: i64 = i
134 var d: i64 = 0
135 while d == 0 {
136 if j >= n { d = 1 } else { if b[j] == (SC_NL as u8) { d = 1 } else { j = j + 1 } }
137 }
138 return j
139}
140
141func sc_col(b: *u8, ls: i64, le: i64, want: i64, sp: *i64) -> i64 {
142 var c: i64 = 0
143 var s: i64 = ls
144 var j: i64 = ls
145 var fnd: i64 = 0
146 var d: i64 = 0
147 while d == 0 {
148 var hit: i64 = 0
149 if j >= le { hit = 1 } else { if b[j] == (SC_TAB as u8) { hit = 1 } }
150 if hit == 1 {
151 if c == want { sp[0] = s; sp[1] = j; fnd = 1; d = 1 } else { c = c + 1; s = j + 1; if j >= le { d = 1 } else { j = j + 1 } }
152 } else { j = j + 1 }
153 }
154 return fnd
155}
156
157func sc_span_lit(b: *u8, s: i64, e: i64, lit: *u8) -> i64 {
158 let n: i64 = sc_len(lit)
159 if e - s != n { return 0 }
160 var i: i64 = 0
161 while i < n { let bi: i64 = s + i; if b[bi] != lit[i] { return 0 } i = i + 1 }
162 return 1
163}
164
165func sc_cpspan(b: *u8, sp: *i64) -> *u8 {
166 var i: i64 = sp[0]
167 var k: i64 = 0
168 while i < sp[1] { g_scr[k] = b[i]; k = k + 1; i = i + 1 }
169 g_scr[k] = 0 as u8
170 return g_scr
171}
172
173func sc_cpspan2(b: *u8, sp: *i64) -> *u8 {
174 var i: i64 = sp[0]
175 var k: i64 = 0
176 while i < sp[1] { g_scr2[k] = b[i]; k = k + 1; i = i + 1 }
177 g_scr2[k] = 0 as u8
178 return g_scr2
179}
180
181func sc_name_in(b: *u8, n: i64, name: *u8, col: i64) -> i64 {
182 var i: i64 = 0
183 var fnd: i64 = 0
184 while i < n {
185 let le: i64 = sc_le(b, i, n)
186 var skip: i64 = 0
187 if le <= i { skip = 1 } else { if b[i] == (SC_HASH as u8) { skip = 1 } }
188 if skip == 0 {
189 if fnd == 0 {
190 if sc_col(b, i, le, col, g_sp) == 1 { if sc_span_lit(b, g_sp[0], g_sp[1], name) == 1 { fnd = 1 } }
191 }
192 }
193 i = le + 1
194 }
195 return fnd
196}
197
198func sc_has_new(b: *u8, sp: *i64) -> i64 {
199 var i: i64 = sp[0]
200 while i + SC_NEWLEN <= sp[1] {
201 if b[i] == (SC_DOT as u8) { if b[i+1] == (SC_LC_N as u8) { if b[i+2] == (SC_LC_E as u8) { if b[i+3] == (SC_LC_W as u8) { return 1 } } } }
202 i = i + 1
203 }
204 return 0
205}
206
207func sc_exists(p: *u8) -> i64 {
208 let sb: *u8 = sys_mmap(SC_STATBUF)
209 let r: i64 = sys_fstatat(p, sb)
210 if r == 0 { return 1 }
211 return 0
212}
213
214// emit=1 prints each offending NAME to stdout instead of only counting it.
215// WHY (2026-08-03, debt 1785773047): this class grew 40 -> 512 in 13 days and the only interface to it was a
216// COUNT. `nx_shelltool glob '*.elf.new' .` BUDGET-EXCEEDS before finishing the root walk, and the log stores
217// counts only -- so the estate could see the number and never the members. A DETECTOR THAT COUNTS A CLASS IT
218// CANNOT ENUMERATE HANDS YOU A NUMBER YOU CANNOT ACT ON. Same one-level walk, same predicate, so the list can
219// never disagree with the count it reports.
220func sc_scan_new(emit: i64) -> i64 {
221 let fd: i64 = sys_openat_rd(g_root)
222 if fd < 0 { return 0 }
223 let db: *u8 = sys_mmap(SC_DIRCAP)
224 var cnt: i64 = 0
225 var done: i64 = 0
226 while done == 0 {
227 let nr: i64 = sys_getdents64(fd, db, SC_DIRCAP)
228 if nr <= 0 { done = 1 } else {
229 var p: i64 = 0
230 while p < nr {
231 let rlo: i64 = db[p+16] as i64
232 let rhi: i64 = db[p+17] as i64
233 let rl: i64 = rlo + rhi * SC_B256
234 let ns: i64 = p + 19
235 var ne: i64 = ns
236 while db[ne] != (0 as u8) { ne = ne + 1 }
237 if ne - ns >= SC_NEWLEN { if db[ne-4] == (SC_DOT as u8) { if db[ne-3] == (SC_LC_N as u8) { if db[ne-2] == (SC_LC_E as u8) { if db[ne-1] == (SC_LC_W as u8) { cnt = cnt + 1; if emit == 1 { sys_write(1, (((db as i64) + ns) as *u8), ne - ns); sys_write(1, "\n" as *u8, 1) } } } } } }
238 if rl <= 0 { p = nr } else { p = p + rl }
239 }
240 }
241 }
242 sys_close(fd)
243 return cnt
244}
245
246func sc_atoi_span(b: *u8, sp: *i64) -> i64 {
247 var v: i64 = 0
248 var i: i64 = sp[0]
249 while i < sp[1] { let ch: i64 = b[i] as i64; if ch >= SC_ZERO { if ch <= SC_NINE { v = v * SC_B10 + (ch - SC_ZERO) } } i = i + 1 }
250 return v
251}
252
253func sc_last_num_after(b: *u8, pat: *u8) -> i64 {
254 let n: i64 = g_rn
255 let pl: i64 = sc_len(pat)
256 var best: i64 = 0 - 1
257 var i: i64 = 0
258 while i + pl <= n {
259 var k: i64 = 0
260 var ok: i64 = 1
261 while k < pl { let bi: i64 = i + k; if b[bi] != pat[k] { ok = 0; k = pl } else { k = k + 1 } }
262 if ok == 1 { best = i + pl }
263 i = i + 1
264 }
265 if best < 0 { return 0 - 1 }
266 var v: i64 = 0
267 var j: i64 = best
268 var any: i64 = 0
269 var d: i64 = 0
270 while d == 0 {
271 let ch: i64 = b[j] as i64
272 var isd: i64 = 0
273 if ch >= SC_ZERO { if ch <= SC_NINE { isd = 1 } }
274 if isd == 1 { v = v * SC_B10 + (ch - SC_ZERO); any = 1; j = j + 1 } else { d = 1 }
275 }
276 if any == 0 { return 0 - 1 }
277 return v
278}
279
280func sc_l003(b: *u8) -> i64 {
281 let n: i64 = g_rn
282 var best: i64 = 0 - 1
283 var i: i64 = 0
284 while i < n {
285 let le: i64 = sc_le(b, i, n)
286 if sc_col(b, i, le, 2, g_sp) == 1 {
287 if sc_span_lit(b, g_sp[0], g_sp[1], "L003") == 1 {
288 if sc_col(b, i, le, 3, g_sp) == 1 {
289 if sc_span_lit(b, g_sp[0], g_sp[1], "unregistered") == 1 {
290 if sc_col(b, i, le, 4, g_sp) == 1 { best = sc_atoi_span(b, g_sp) }
291 }
292 }
293 }
294 }
295 i = le + 1
296 }
297 return best
298}
299
300func sc_scan() -> i64 {
301 g_hitcap = 0
302 g_allow = sc_readf("tool_allowlist.conf", SC_BUFCAP)
303 g_an = g_rn
304 g_schema = sc_readf("knowledge/tool_schemas.conf", SC_BUFCAP)
305 g_sn = g_rn
306 g_atlas = sc_readf("knowledge/registry/atlas_catalog.tsv", SC_BUFCAP)
307 g_atn = g_rn
308 g_c_allow = 0
309 g_c_schema = 0
310 g_c_noschema = 0
311 g_c_staleschema = 0
312 g_c_stagedref = 0
313 g_c_missingbin = 0
314 g_c_straynew = 0
315 g_c_dupsrc = 0
316 g_c_unreg = 0
317 g_c_noatlas = 0
318 var i: i64 = 0
319 while i < g_an {
320 let le: i64 = sc_le(g_allow, i, g_an)
321 var skip: i64 = 0
322 if le <= i { skip = 1 } else { if g_allow[i] == (SC_HASH as u8) { skip = 1 } }
323 if skip == 0 {
324 if sc_col(g_allow, i, le, 0, g_sp) == 1 {
325 if g_sp[1] > g_sp[0] {
326 g_c_allow = g_c_allow + 1
327 let nm: *u8 = sc_cpspan(g_allow, g_sp)
328 if sc_name_in(g_schema, g_sn, nm, 0) == 0 { g_c_noschema = g_c_noschema + 1 }
329 if sc_name_in(g_atlas, g_atn, nm, 1) == 0 { g_c_noatlas = g_c_noatlas + 1 }
330 if sc_col(g_allow, i, le, 1, g_sp) == 1 {
331 if sc_has_new(g_allow, g_sp) == 1 { g_c_stagedref = g_c_stagedref + 1 } else {
332 let pp: *u8 = sc_cpspan2(g_allow, g_sp)
333 if sc_exists(pp) == 0 { g_c_missingbin = g_c_missingbin + 1 }
334 }
335 }
336 }
337 }
338 }
339 i = le + 1
340 }
341 var j: i64 = 0
342 while j < g_sn {
343 let le2: i64 = sc_le(g_schema, j, g_sn)
344 var skip2: i64 = 0
345 if le2 <= j { skip2 = 1 } else { if g_schema[j] == (SC_HASH as u8) { skip2 = 1 } }
346 if skip2 == 0 {
347 if sc_col(g_schema, j, le2, 0, g_sp) == 1 {
348 if g_sp[1] > g_sp[0] {
349 g_c_schema = g_c_schema + 1
350 let nm2: *u8 = sc_cpspan(g_schema, g_sp)
351 if sc_name_in(g_allow, g_an, nm2, 0) == 0 { g_c_staleschema = g_c_staleschema + 1 }
352 }
353 }
354 }
355 j = le2 + 1
356 }
357 g_c_straynew = sc_scan_new(0)
358 let db: *u8 = sc_readf("knowledge/status/dup_source.log", SC_LOGCAP)
359 g_c_dupsrc = sc_last_num_after(db, "basenames found: ")
360 let wb: *u8 = sc_readf("knowledge/status/law_warden.jrnl", SC_LOGCAP)
361 g_c_unreg = sc_l003(wb)
362 return 0
363}
364
365func sc_append(b: *u8, n: i64) -> i64 {
366 let pb: *u8 = sys_mmap(SC_PATHCAP)
367 let lp: *u8 = sc_path(pb, "knowledge/status/shipcheck.log")
368 let fd: i64 = sys_openat_append(lp, SC_MODE_F)
369 if fd < 0 { return 0 }
370 sys_write(fd, b, n)
371 sys_close(fd)
372 return 1
373}
374
375func sc_emit(verb: *u8) -> i64 {
376 let ts: *i64 = sys_mmap(16) as *i64
377 sys_clock_gettime_real(ts)
378 let ep: i64 = ts[0]
379 let ob: *u8 = sys_mmap(SC_OUTCAP)
380 var o: i64 = 0
381 o = sc_cat(ob, o, "SHIPCHECK epoch=" as *u8)
382 o = sc_catn(ob, o, ep)
383 o = sc_cat(ob, o, " verb=" as *u8)
384 o = sc_cat(ob, o, verb)
385 o = sc_cat(ob, o, " allow=" as *u8)
386 o = sc_catn(ob, o, g_c_allow)
387 o = sc_cat(ob, o, " schema=" as *u8)
388 o = sc_catn(ob, o, g_c_schema)
389 o = sc_cat(ob, o, " noschema=" as *u8)
390 o = sc_catn(ob, o, g_c_noschema)
391 o = sc_cat(ob, o, " staleschema=" as *u8)
392 o = sc_catn(ob, o, g_c_staleschema)
393 o = sc_cat(ob, o, " stagedref=" as *u8)
394 o = sc_catn(ob, o, g_c_stagedref)
395 o = sc_cat(ob, o, " missingbin=" as *u8)
396 o = sc_catn(ob, o, g_c_missingbin)
397 o = sc_cat(ob, o, " straynew=" as *u8)
398 o = sc_catn(ob, o, g_c_straynew)
399 o = sc_cat(ob, o, " dupsrc=" as *u8)
400 o = sc_catn(ob, o, g_c_dupsrc)
401 o = sc_cat(ob, o, " unreg_l003=" as *u8)
402 o = sc_catn(ob, o, g_c_unreg)
403 o = sc_cat(ob, o, " noatlas=" as *u8)
404 o = sc_catn(ob, o, g_c_noatlas)
405 o = sc_cat(ob, o, " frowjoin=-1 capped=" as *u8)
406 o = sc_catn(ob, o, g_hitcap)
407 var bad: i64 = 0
408 bad = g_c_noschema + g_c_staleschema + g_c_stagedref + g_c_missingbin + g_c_straynew + g_c_noatlas
409 if bad > 0 { o = sc_cat(ob, o, " verdict=RED" as *u8) } else { o = sc_cat(ob, o, " verdict=GREEN" as *u8) }
410 ob[o] = SC_NL as u8
411 o = o + 1
412 sys_write(1, ob, o)
413 sc_append(ob, o)
414 if bad > 0 { return SC_EXITRED }
415 return 0
416}
417
418func sc_allow_path(name: *u8, outp: *u8) -> i64 {
419 var i: i64 = 0
420 var fnd: i64 = 0
421 while i < g_an {
422 let le: i64 = sc_le(g_allow, i, g_an)
423 var skip: i64 = 0
424 if le <= i { skip = 1 } else { if g_allow[i] == (SC_HASH as u8) { skip = 1 } }
425 if skip == 0 {
426 if fnd == 0 {
427 if sc_col(g_allow, i, le, 0, g_sp) == 1 {
428 if sc_span_lit(g_allow, g_sp[0], g_sp[1], name) == 1 {
429 if sc_col(g_allow, i, le, 1, g_sp) == 1 {
430 var k: i64 = 0
431 var z: i64 = g_sp[0]
432 while z < g_sp[1] { outp[k] = g_allow[z]; k = k + 1; z = z + 1 }
433 outp[k] = 0 as u8
434 fnd = 1
435 }
436 }
437 }
438 }
439 }
440 i = le + 1
441 }
442 return fnd
443}
444
445func sc_spawn_filer(fpath: *u8, desc: *u8) -> i64 {
446 let sevs: *u8 = sys_mmap(8)
447 let so: i64 = sc_catn(sevs, 0, g_sev)
448 let av: *i64 = sys_mmap(64) as *i64
449 av[0] = fpath as i64
450 av[1] = "add" as *u8 as i64
451 av[2] = sevs as i64
452 av[3] = "shipcomplete" as *u8 as i64
453 av[4] = desc as i64
454 av[5] = 0
455 let env: *i64 = sys_mmap(8) as *i64
456 env[0] = 0
457 let pid: i64 = sys_fork()
458 if pid == 0 { sys_execve(fpath, av, env); sys_exit_group(SC_EXEFAIL) }
459 let st: *i64 = sys_mmap(16) as *i64
460 st[0] = 0
461 sys_wait4(pid, st, 0)
462 let raw: i64 = st[0]
463 let code: i64 = (raw / SC_B256) % SC_B256
464 return code
465}
466
467func sc_file_cls(fpath: *u8, tail: *u8) -> i64 {
468 let desc: *u8 = sys_mmap(SC_DESCCAP)
469 var o: i64 = 0
470 o = sc_cat(desc, 0, "SHIPCOMPLETE-ORPHAN " as *u8)
471 o = sc_cat(desc, o, tail)
472 let rc: i64 = sc_spawn_filer(fpath, desc)
473 let rb: *u8 = sys_mmap(SC_PATHCAP)
474 var ro: i64 = 0
475 ro = sc_cat(rb, 0, "FILED class=" as *u8)
476 var i: i64 = 0
477 var d: i64 = 0
478 while d == 0 {
479 let ch: i64 = tail[i] as i64
480 if ch == 0 { d = 1 } else { if ch == SC_COLON { d = 1 } else { rb[ro] = tail[i]; ro = ro + 1; i = i + 1 } }
481 }
482 ro = sc_cat(rb, ro, " exit=" as *u8)
483 ro = sc_catn(rb, ro, rc)
484 rb[ro] = SC_NL as u8
485 ro = ro + 1
486 sys_write(1, rb, ro)
487 sc_append(rb, ro)
488 return rc
489}
490
491func sc_file(filer: *u8) -> i64 {
492 let fpath: *u8 = sys_mmap(SC_PATHCAP)
493 let fok: i64 = sc_allow_path(filer, fpath)
494 if fok == 0 {
495 let eb: *u8 = sys_mmap(SC_PATHCAP)
496 var eo: i64 = 0
497 eo = sc_cat(eb, 0, "SHIPCHECK-FILE filer-unresolved" as *u8)
498 eb[eo] = SC_NL as u8
499 eo = eo + 1
500 sys_write(1, eb, eo)
501 sc_append(eb, eo)
502 return 1
503 }
504 if g_c_stagedref > 0 { g_sev = SC_SEV_STAGEDREF; sc_file_cls(fpath, "stagedref: registered MCP tools whose tool_allowlist.conf binary path points at a staged .new artifact (registered-but-never-promoted) -- promote or withdraw each; live counts in knowledge/status/shipcheck.log (nx_shipcheck)" as *u8) }
505 if g_c_missingbin > 0 { g_sev = SC_SEV_MISSINGBIN; sc_file_cls(fpath, "missingbin: registered MCP tools whose allowlisted binary is ABSENT on disk (tools-call would exec-fail) -- restore or deregister; live counts in knowledge/status/shipcheck.log (nx_shipcheck)" as *u8) }
506 if g_c_noschema > 0 { g_sev = SC_SEV_NOSCHEMA; sc_file_cls(fpath, "noschema: tool registry rows with NO schema row in knowledge/tool_schemas.conf (agents fly blind on safety and verbs) -- add schema-bridge rows; live counts in knowledge/status/shipcheck.log (nx_shipcheck)" as *u8) }
507 if g_c_staleschema > 0 { g_sev = SC_SEV_STALESCHEMA; sc_file_cls(fpath, "staleschema: tool_schemas.conf rows whose tool is NOT in tool_allowlist.conf (ghost schema, nx_seat-class staleness) -- reconcile or retire each row; live counts in knowledge/status/shipcheck.log (nx_shipcheck)" as *u8) }
508 if g_c_straynew > 0 { g_sev = SC_SEV_STRAYNEW; sc_file_cls(fpath, "straynew: stranded staged .new artifacts in the deploy root (never promoted, never cleaned) -- promote or evict via nx_evict; live counts in knowledge/status/shipcheck.log (nx_shipcheck)" as *u8) }
509 if g_c_noatlas > 0 { g_sev = SC_SEV_NOATLAS; sc_file_cls(fpath, "noatlas: registered MCP tools absent from the atlas recombination catalog knowledge/registry/atlas_catalog.tsv (invisible to discovery and recombination) -- register via nx_atlas_catseed; live counts in knowledge/status/shipcheck.log (nx_shipcheck)" as *u8) }
510 return 0
511}
512
513func main(argc: i64, argv: *i64) -> i64 {
514 g_scr = sys_mmap(SC_PATHCAP)
515 g_scr2 = sys_mmap(SC_PATHCAP)
516 g_sp = sys_mmap(16) as *i64
517 g_root = "." as *u8
518 var verb: *u8 = "scan" as *u8
519 if argc >= 2 { verb = argv[1] as *u8 }
520 if argc >= 3 { g_root = argv[2] as *u8 }
521 var filer: *u8 = "nx_debt" as *u8
522 if argc >= 4 { filer = argv[3] as *u8 }
523 // listnew: PRINT the straynew members (the class this organ could previously only count). Deliberately
524 // BEFORE sc_scan() so the listing costs one directory walk and nothing else, and returns the COUNT as its
525 // exit code -- so a caller can pipe the names AND branch on how many there were.
526 if sc_span_lit(verb, 0, sc_len(verb), "listnew" as *u8) == 1 {
527 let ln: i64 = sc_scan_new(1)
528 return ln
529 }
530 sc_scan()
531 let rc: i64 = sc_emit(verb)
532 var dofile: i64 = 0
533 if sc_span_lit(verb, 0, sc_len(verb), "beat" as *u8) == 1 { dofile = 1 }
534 if sc_span_lit(verb, 0, sc_len(verb), "file" as *u8) == 1 { dofile = 1 }
535 if dofile == 1 { sc_file(filer) }
536 return rc
537}