code wiki / (root) / nx_capcliff_recovery_20260912.nx

nx_capcliff_recovery_20260912.nx source

↩ module page · 619 lines · 39953 B

1// nx_capcliff.nx -- READER-CAP CLIFF DETECTOR for append-only ledgers, WITH THE REMEDY CENSUS (DI13). 2// 3// WHY THIS EXISTS (measured 2026-08-06). Several estate readers capture a ledger into a BOUNDED 4// buffer -- 4 MiB is the recurring number (nx_debt_view declares capture_cap=4194304; nx_catalog 5// reports actlog 4194304B exactly). When the ledger grows PAST that cap the reader keeps working and 6// silently returns a TRUNCATED PREFIX. Two were already over on the day this was written: 7// knowledge/status/actlog.jrnl -- read at offset 4194304 returns bytes and 'more remains', while 8// nx_catalog reports exactly 4194304B. The boundary row is epoch 1785966081 (~21h before), so 9// EVERY INVOCATION SINCE THEN IS INVISIBLE and nx_catalog calls freshly-run organs 10// REGISTERED-DARK (S4) 'callable, authorised, NEVER RUN'. The estate's headline ADOPTION signal 11// was being manufactured by a truncated buffer. 12// knowledge/store/debt- -- nx_plane_check says rows=3326 GREEN bytes=4217666, while nx_debt page 13// reports total=3311 and nx_debt show cannot find the ~15 newest rows. 14// 15// ***BECAUSE THESE LEDGERS ARE APPEND-ONLY, A PREFIX CAP ALWAYS EATS THE NEWEST ROWS FIRST.*** The 16// instrument therefore degrades exactly as new work arrives, and every downstream metric drifts 17// toward 'nothing happened lately'. That is the worst possible failure direction for an adoption or 18// debt gauge, and nothing announced it. 19// 20// This organ makes the cliff PREDICTABLE instead of discovered: it measures each rostered ledger 21// against the cap and reports headroom, so a crossing is forecast rather than found by accident. 22// 23// THE REMEDY CENSUS (DI13, 2026-09-06). An OVER row is a SIZE fact, not a proven reader defect: a 24// TAIL-anchored or whole-file reader loses nothing, a HEAD-anchored one loses the newest rows. So every 25// OVER ledger is now judged against knowledge/capcliff_remedy.conf, rows `ledger|kind|target|note`: 26// reader target = <file:line> of the consumer's READ SITE. The organ READS THAT LINE and classifies 27// it -- WHOLE (sys_read_file), TAIL (SEEK_END or a *_tail( helper), HEAD (a bare sys_read), 28// UNVERIFIED (none of those: a declaration that did not point at a read). The conf declares 29// WHERE to look; the classification is measured, never copied from the row. 30// writer target = <file:line> of the appender (verified: the line must append). 31// guard target = sizeguard:<byte-cliff>:<line-cliff>; nx_sizeguard is FORKED on the ledger with that 32// budget and its exit code is the guard's verdict (0 GREEN 1 AMBER 2 RED 3 UNMEASURED). 33// mention target = a file that names the ledger without reading it (comment, fixture); declared, not judged. 34// Remedy states describe the DECLARED ROSTER, not a complete semantic census of all source consumers. 35// GOVERNED: declared readers are WHOLE/TAIL or guarded GREEN/AMBER; BREACHED: a declared guard reads RED; 36// UNGOVERNED: a declared HEAD/UNVERIFIED reader has no working guard. UNREGISTERED: a readable conf has 37// no matching ledger rows. UNMEASURED: conf unreadable or zero declared readers, including writer-only rows. 38// Zero declared readers cannot prove no actual readers. The legacy NO-READER state code/name is retained 39// for compatibility but no current evidence contract establishes it. Output carries the roster truth scope 40// and semantic_coverage=UNMEASURED. Unknown coverage abstains with exit 3 in remedy and OVER-ledger scan; 41// known UNGOVERNED/BREACHED evidence retains exit 6 precedence. No journal rotation is performed. 42// 43// nx_capcliff scan [roster.conf] [cap_bytes] [remedy.conf] 44// nx_capcliff remedy <ledger> [remedy.conf] one ledger's remedy census, on demand 45// nx_capcliff selftest 46// verdicts: OVER (past the cap) | NEAR (>= NEAR_PERMIL of cap) | OK | MISSING (rostered but absent -- reported, 47// NEVER counted as OK). 48// exit: 0 all OK or every OVER ledger governed | 4 NEAR present | 6 an OVER ledger UNGOVERNED or BREACHED | 49// 3 remedy coverage UNREGISTERED/UNMEASURED | 2 usage | 5 empty roster | selftest: 0 GREEN / 1 RED 50// license_tier: ORIGINAL expect_exit: 0 51import "nx_syscalls.nx" 52import "nx_tool_run.nx" 53import "nx_gate_verdict.nx" 54const CC_MAGIC_4096: i64 = 4096 55 56const CC_CAP_DEFAULT: i64 = 4194304 57const CC_NEAR_PERMIL: i64 = 900 58const CC_MAXROWS: i64 = 256 59const CC_CONFCAP: i64 = 65536 60const CC_EXIT_NEAR: i64 = 4 61const CC_EXIT_OVER: i64 = 6 62const CC_EXIT_EMPTY: i64 = 5 63const CC_EXIT_UNMEASURED: i64 = 3 64const CC_SEEK_END: i64 = 2 65const CC_REMEDY_CONF: *u8 = "knowledge/capcliff_remedy.conf" as *u8 66const CC_SIZEGUARD: *u8 = "./nx_sizeguard.elf" as *u8 67const CC_SIZEGUARD_BUILT: *u8 = "_build/nx_sizeguard.sov.elf" as *u8 68const CC_GUARD_OUT: i64 = 4096 69const CC_LINE_CAP: i64 = 4096 70const CC_MODE_644: i64 = 420 71const CC_MODE_755: i64 = 493 72const CC_FIX_DIR: *u8 = "/tmp/nx_capcliff_recovery_20260912" as *u8 73// anchoring classes (a partition of every declared reader) 74const CC_ANCH_UNVERIFIED: i64 = 0 75const CC_ANCH_WHOLE: i64 = 1 76const CC_ANCH_TAIL: i64 = 2 77const CC_ANCH_HEAD: i64 = 3 78// remedy states 79const CC_ST_UNGOVERNED: i64 = 0 80const CC_ST_GOVERNED: i64 = 1 81const CC_ST_BREACHED: i64 = 2 82const CC_ST_NOREADER: i64 = 3 83const CC_ST_UNREGISTERED: i64 = 4 84const CC_ST_UNMEASURED: i64 = 5 85// guard verdicts mirror nx_sizeguard's exit codes; -1 = no guard declared; -2 = guard binary absent 86const CC_GUARD_NONE: i64 = 0 - 1 87const CC_GUARD_NOELF: i64 = 0 - 2 88const CC_SG_GREEN: i64 = 0 89const CC_SG_AMBER: i64 = 1 90const CC_SG_RED: i64 = 2 91// counts[] slots filled by cc_remedy 92const CC_K_READERS: i64 = 0 93const CC_K_WHOLE: i64 = 1 94const CC_K_TAIL: i64 = 2 95const CC_K_HEAD: i64 = 3 96const CC_K_UNVER: i64 = 4 97const CC_K_WRITERS: i64 = 5 98const CC_K_WUNVER: i64 = 6 99const CC_K_GUARD: i64 = 7 100const CC_K_MENTIONS: i64 = 8 101const CC_K_N: i64 = 9 102 103func cw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 104func cwe(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 } 105func cwn(v: i64) -> i64 { var m: i64=v; if m<0{cw("-" as *u8);m=0-m} let t:*u8=sys_mmap(28); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(28); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); sys_munmap(t,28); sys_munmap(o,28); return 0 } 106func cwb(b: *u8, s: i64, e: i64) -> i64 { if e>s { sys_write(1, (b as i64 + s) as *u8, e-s) } return 0 } 107 108func cc_streq(a: *u8, b: *u8) -> i64 { 109 var i: i64 = 0 110 var r: i64 = 2 111 while r == 2 { if a[i] != b[i] { r = 0 } else { if a[i] == (0 as u8) { r = 1 } else { i = i + 1 } } } 112 return r 113} 114func cc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 115func cc_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var oo: i64 = o; while s[i] != (0 as u8) { d[oo] = s[i]; oo = oo + 1; i = i + 1 } d[oo] = 0 as u8; return oo } 116func cc_catn(d: *u8, o: i64, v: i64) -> i64 { 117 var m: i64 = v 118 var oo: i64 = o 119 if m < 0 { d[oo] = 45 as u8; oo = oo + 1; m = 0 - m } 120 let t: *u8 = sys_mmap(32) 121 var k: i64 = 0 122 if m == 0 { t[0] = 48 as u8; k = 1 } 123 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 124 while k > 0 { k = k - 1; d[oo] = t[k]; oo = oo + 1 } 125 d[oo] = 0 as u8 126 return oo 127} 128// substring within buf[s,e) 129func cc_span_has(buf: *u8, s: i64, e: i64, lit: *u8) -> i64 { 130 let m: i64 = cc_slen(lit) 131 if m == 0 { return 0 } 132 var i: i64 = s 133 while i + m <= e { 134 var j: i64 = 0 135 var same: i64 = 1 136 while j < m { if buf[i + j] != lit[j] { same = 0; j = m } else { j = j + 1 } } 137 if same == 1 { return 1 } 138 i = i + 1 139 } 140 return 0 141} 142func cc_has(s: *u8, lit: *u8) -> i64 { return cc_span_has(s, 0, cc_slen(s), lit) } 143func cc_span_eq(buf: *u8, s: i64, e: i64, lit: *u8) -> i64 { let ll: i64 = cc_slen(lit); if e - s != ll { return 0 } var i: i64 = 0; while i < ll { if buf[s + i] != lit[i] { return 0 } i = i + 1 } return 1 } 144 145func cc_atoi(s: *u8) -> i64 { 146 var v: i64 = 0 147 var i: i64 = 0 148 while s[i] != (0 as u8) { let c: i64 = s[i]; if c >= 48 { if c <= 57 { v = v*10 + (c - 48) } } i = i + 1 } 149 return v 150} 151// the decimal at buf[s,e), digits only, or -1 152func cc_span_int(buf: *u8, s: i64, e: i64) -> i64 { 153 var v: i64 = 0 154 var nd: i64 = 0 155 var i: i64 = s 156 while i < e { let c: i64 = buf[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); nd = nd + 1 } } i = i + 1 } 157 if nd == 0 { return 0 - 1 } 158 return v 159} 160 161// SIZE BY lseek(SEEK_END). Returns -1 when the path cannot be opened -- a MISSING ledger must never 162// read as a small one, because 'small' would score OK and hide a roster that points at nothing. 163func cc_size(path: *u8) -> i64 { 164 let fd: i64 = sys_openat_rd(path) 165 if fd < 0 { return 0 - 1 } 166 let sz: i64 = sys_lseek(fd, 0, CC_SEEK_END) 167 sys_close(fd) 168 if sz < 0 { return 0 - 1 } 169 return sz 170} 171 172// copy a NUL-terminated path out of the conf buffer span [s,e) into dst 173func cc_copy(buf: *u8, s: i64, e: i64, dst: *u8) -> i64 { 174 var i: i64 = s 175 var o: i64 = 0 176 while i < e { dst[o] = buf[i]; o = o + 1; i = i + 1 } 177 dst[o] = 0 as u8 178 return o 179} 180// the idx-th '|'-separated field of buf[rs,re): sp[0]=start sp[1]=end; 1 when present 181func cc_field(buf: *u8, rs: i64, re: i64, idx: i64, sp: *i64) -> i64 { 182 var f: i64 = 0 183 var s: i64 = rs 184 var i: i64 = rs 185 while i <= re { 186 var cut: i64 = 0 187 if i == re { cut = 1 } else { if buf[i] == (124 as u8) { cut = 1 } } 188 if cut == 1 { 189 if f == idx { sp[0] = s; sp[1] = i; return 1 } 190 f = f + 1 191 s = i + 1 192 } 193 i = i + 1 194 } 195 return 0 196} 197// index of the newline ending the line that contains p, or n 198func cc_line_end(buf: *u8, n: i64, p: i64) -> i64 { var i: i64 = p; var go: i64 = 1; while go == 1 { if i >= n { go = 0 } else { if buf[i] == (10 as u8) { go = 0 } else { i = i + 1 } } } return i } 199 200// ---- the remedy census (DI13) ------------------------------------------------------------------------------------ 201// line ln (1-based) of the file at path, copied to dst (cut at CC_LINE_CAP); -1 when the file or the line is absent 202func cc_read_line(path: *u8, ln: i64, dst: *u8) -> i64 { 203 dst[0] = 0 as u8 204 let l: *i64 = sys_mmap(16) as *i64 205 let b: *u8 = sys_read_file(path, l) 206 if (b as i64) == 0 { return 0 - 1 } 207 let n: i64 = l[0] 208 var cur: i64 = 1 209 var i: i64 = 0 210 while cur < ln { if i >= n { return 0 - 1 } if b[i] == (10 as u8) { cur = cur + 1 } i = i + 1 } 211 if i >= n { return 0 - 1 } 212 let e: i64 = cc_line_end(b, n, i) 213 var o: i64 = 0 214 var k: i64 = i 215 while k < e { if o + 1 < CC_LINE_CAP { dst[o] = b[k]; o = o + 1 } k = k + 1 } 216 dst[o] = 0 as u8 217 return o 218} 219// the anchoring class of ONE read-site line. Order matters: a whole-file read names sys_read_file; a tail read 220// names SEEK_END or a *_tail( helper; a bare sys_read( is head-anchored; anything else did not point at a read. 221func cc_anchor_class(line: *u8) -> i64 { 222 if cc_has(line, "sys_read_file(" as *u8) == 1 { return CC_ANCH_WHOLE } 223 if cc_has(line, "SEEK_END" as *u8) == 1 { return CC_ANCH_TAIL } 224 // the same constant in two spellings is two constants to every scanner: `sys_lseek(fd, 0, 2)` IS SEEK_END 225 if cc_has(line, "sys_lseek(" as *u8) == 1 { if cc_has(line, ", 2)" as *u8) == 1 { return CC_ANCH_TAIL } } 226 if cc_has(line, "_tail(" as *u8) == 1 { return CC_ANCH_TAIL } 227 if cc_has(line, "sys_read(" as *u8) == 1 { return CC_ANCH_HEAD } 228 return CC_ANCH_UNVERIFIED 229} 230func cc_anchor_name(c: i64) -> *u8 { 231 if c == CC_ANCH_WHOLE { return "WHOLE" as *u8 } 232 if c == CC_ANCH_TAIL { return "TAIL" as *u8 } 233 if c == CC_ANCH_HEAD { return "HEAD" as *u8 } 234 return "UNVERIFIED" as *u8 235} 236// split "<file>:<line>" (the LAST colon) into path (NUL-terminated) and the line number; -1 when malformed 237func cc_split_site(spec: *u8, s: i64, e: i64, path: *u8) -> i64 { 238 var c: i64 = e 239 var seek: i64 = 1 240 while seek == 1 { if c <= s { seek = 0 } else { if spec[c - 1] == (58 as u8) { seek = 0 } else { c = c - 1 } } } 241 if c <= s { return 0 - 1 } 242 cc_copy(spec, s, c - 1, path) 243 return cc_span_int(spec, c, e) 244} 245// the anchoring of a declared reader "<file>:<line>": reads that line and classifies it 246func cc_anchoring(spec: *u8, s: i64, e: i64, path: *u8, line: *u8) -> i64 { 247 let ln: i64 = cc_split_site(spec, s, e, path) 248 if ln < 0 { return CC_ANCH_UNVERIFIED } 249 if cc_read_line(path, ln, line) < 0 { return CC_ANCH_UNVERIFIED } 250 return cc_anchor_class(line) 251} 252func cc_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 253// FORK nx_sizeguard on the ledger with the declared budget "sizeguard:<bytes>:<lines>"; its exit code is the verdict 254func cc_guard(ledger: *u8, spec: *u8, s: i64, e: i64, out: *u8, olen: *i64) -> i64 { 255 olen[0] = 0 256 if cc_span_has(spec, s, e, "sizeguard:" as *u8) == 0 { return CC_GUARD_NONE } 257 // fields after the verb, ':'-separated: the first ':' ends the verb, the second separates the two budgets 258 var c1: i64 = 0 - 1 259 var c2: i64 = 0 - 1 260 var q: i64 = s 261 while q < e { if spec[q] == (58 as u8) { if c1 < 0 { c1 = q } else { if c2 < 0 { c2 = q } } } q = q + 1 } 262 if c1 < 0 { return CC_GUARD_NONE } 263 if c2 < 0 { return CC_GUARD_NONE } 264 let bytes: i64 = cc_span_int(spec, c1 + 1, c2) 265 let lines: i64 = cc_span_int(spec, c2 + 1, e) 266 if bytes <= 0 { return CC_GUARD_NONE } 267 if lines <= 0 { return CC_GUARD_NONE } 268 var elf: *u8 = CC_SIZEGUARD 269 if cc_exists(elf) == 0 { elf = CC_SIZEGUARD_BUILT } 270 if cc_exists(elf) == 0 { return CC_GUARD_NOELF } 271 let bs: *u8 = sys_mmap(32) 272 let ls: *u8 = sys_mmap(32) 273 cc_catn(bs, 0, bytes) 274 cc_catn(ls, 0, lines) 275 let av: *i64 = sys_mmap(48) as *i64 276 av[0] = elf as i64 277 av[1] = ledger as i64 278 av[2] = bs as i64 279 av[3] = ls as i64 280 av[4] = 0 281 return tr_run_capture(elf, av, out, CC_GUARD_OUT - 8, olen) 282} 283func cc_state_name(st: i64) -> *u8 { 284 if st == CC_ST_GOVERNED { return "GOVERNED" as *u8 } 285 if st == CC_ST_BREACHED { return "BREACHED" as *u8 } 286 if st == CC_ST_NOREADER { return "NO-READER" as *u8 } 287 if st == CC_ST_UNREGISTERED { return "UNREGISTERED" as *u8 } 288 if st == CC_ST_UNMEASURED { return "UNMEASURED" as *u8 } 289 return "UNGOVERNED" as *u8 290} 291// THE REMEDY CENSUS for one ledger: walks the conf, verifies every declared reader/writer/guard, prints one line 292// per declaration and one REMEDY line, fills counts[], returns the state. 293func cc_remedy(ledger: *u8, conf: *u8, counts: *i64, quiet: i64) -> i64 { 294 var i: i64 = 0 295 while i < CC_K_N { counts[i] = 0; i = i + 1 } 296 counts[CC_K_GUARD] = CC_GUARD_NONE 297 let l: *i64 = sys_mmap(16) as *i64 298 let b: *u8 = sys_read_file(conf, l) 299 var have: i64 = 0 300 var n: i64 = 0 301 if (b as i64) != 0 { have = 1; n = l[0] } 302 let sp: *i64 = sys_mmap(16) as *i64 303 let path: *u8 = sys_mmap(CC_MAGIC_4096) 304 let line: *u8 = sys_mmap(CC_LINE_CAP) 305 let gout: *u8 = sys_mmap(CC_GUARD_OUT) 306 let gl: *i64 = sys_mmap(16) as *i64 307 var registered: i64 = 0 308 var rs: i64 = 0 309 var scanning: i64 = have 310 while scanning == 1 { 311 if rs >= n { scanning = 0 } else { 312 let re: i64 = cc_line_end(b, n, rs) 313 if re > rs { if b[rs] != (35 as u8) { 314 if cc_field(b, rs, re, 0, sp) == 1 { if cc_span_eq(b, sp[0], sp[1], ledger) == 1 { 315 registered = registered + 1 316 let ks: *i64 = sys_mmap(16) as *i64 317 let ts: *i64 = sys_mmap(16) as *i64 318 if cc_field(b, rs, re, 1, ks) == 1 { if cc_field(b, rs, re, 2, ts) == 1 { 319 if cc_span_eq(b, ks[0], ks[1], "reader" as *u8) == 1 { 320 let ac: i64 = cc_anchoring(b, ts[0], ts[1], path, line) 321 counts[CC_K_READERS] = counts[CC_K_READERS] + 1 322 if ac == CC_ANCH_WHOLE { counts[CC_K_WHOLE] = counts[CC_K_WHOLE] + 1 } 323 if ac == CC_ANCH_TAIL { counts[CC_K_TAIL] = counts[CC_K_TAIL] + 1 } 324 if ac == CC_ANCH_HEAD { counts[CC_K_HEAD] = counts[CC_K_HEAD] + 1 } 325 if ac == CC_ANCH_UNVERIFIED { counts[CC_K_UNVER] = counts[CC_K_UNVER] + 1 } 326 if quiet == 0 { cw(" reader " as *u8); cwb(b, ts[0], ts[1]); cw(" anchoring=" as *u8); cw(cc_anchor_name(ac)); cw("\n" as *u8) } 327 } 328 if cc_span_eq(b, ks[0], ks[1], "writer" as *u8) == 1 { 329 counts[CC_K_WRITERS] = counts[CC_K_WRITERS] + 1 330 let ln: i64 = cc_split_site(b, ts[0], ts[1], path) 331 var ok: i64 = 0 332 if ln >= 0 { if cc_read_line(path, ln, line) >= 0 { if cc_has(line, "append" as *u8) == 1 { ok = 1 } } } 333 if ok == 0 { counts[CC_K_WUNVER] = counts[CC_K_WUNVER] + 1 } 334 if quiet == 0 { cw(" writer " as *u8); cwb(b, ts[0], ts[1]); if ok == 1 { cw(" appends=VERIFIED\n" as *u8) } else { cw(" appends=UNVERIFIED\n" as *u8) } } 335 } 336 if cc_span_eq(b, ks[0], ks[1], "guard" as *u8) == 1 { 337 let gv: i64 = cc_guard(ledger, b, ts[0], ts[1], gout, gl) 338 counts[CC_K_GUARD] = gv 339 if quiet == 0 { 340 cw(" guard " as *u8); cwb(b, ts[0], ts[1]); cw(" verdict=" as *u8) 341 if gv == CC_SG_GREEN { cw("GREEN" as *u8) } 342 if gv == CC_SG_AMBER { cw("AMBER" as *u8) } 343 if gv == CC_SG_RED { cw("RED" as *u8) } 344 if gv == CC_GUARD_NOELF { cw("NO-GUARD-BINARY" as *u8) } 345 if gv == CC_GUARD_NONE { cw("MALFORMED" as *u8) } 346 if gv > CC_SG_RED { cw("UNMEASURED" as *u8) } 347 cw("\n" as *u8) 348 } 349 } 350 if cc_span_eq(b, ks[0], ks[1], "mention" as *u8) == 1 { 351 counts[CC_K_MENTIONS] = counts[CC_K_MENTIONS] + 1 352 if quiet == 0 { cw(" mention " as *u8); cwb(b, ts[0], ts[1]); cw(" (declared, not judged)\n" as *u8) } 353 } 354 } } 355 } } 356 } } 357 rs = re + 1 358 } 359 } 360 // the state 361 var st: i64 = CC_ST_UNGOVERNED 362 let blind: i64 = counts[CC_K_HEAD] + counts[CC_K_UNVER] 363 // A configured writer or mention is not a complete census of consumers. No existing 364 // contract proves zero readers, so preserve that state code but abstain on this input. 365 if counts[CC_K_READERS] == 0 { st = CC_ST_UNMEASURED } else { 366 if blind == 0 { st = CC_ST_GOVERNED } else { 367 let gv: i64 = counts[CC_K_GUARD] 368 if gv == CC_SG_GREEN { st = CC_ST_GOVERNED } 369 if gv == CC_SG_AMBER { st = CC_ST_GOVERNED } 370 if gv == CC_SG_RED { st = CC_ST_BREACHED } 371 } 372 } 373 if have == 0 { st = CC_ST_UNMEASURED } else { if registered == 0 { st = CC_ST_UNREGISTERED } } 374 if quiet == 0 { 375 cw(" REMEDY " as *u8); cw(ledger) 376 cw(" readers=" as *u8); cwn(counts[CC_K_READERS]); cw(" whole=" as *u8); cwn(counts[CC_K_WHOLE]); cw(" tail=" as *u8); cwn(counts[CC_K_TAIL]) 377 cw(" head=" as *u8); cwn(counts[CC_K_HEAD]); cw(" unverified=" as *u8); cwn(counts[CC_K_UNVER]) 378 cw(" writers=" as *u8); cwn(counts[CC_K_WRITERS]); cw(" writers_unverified=" as *u8); cwn(counts[CC_K_WUNVER]) 379 cw(" guard=" as *u8); cwn(counts[CC_K_GUARD]); cw(" mentions=" as *u8); cwn(counts[CC_K_MENTIONS]) 380 cw(" conf=" as *u8); if have == 1 { cw("PRESENT" as *u8) } else { cw("ABSENT" as *u8) } 381 cw(" registered_rows=" as *u8); cwn(registered) 382 cw(" coverage=DECLARED-ROSTER semantic_coverage=UNMEASURED" as *u8) 383 cw(" => " as *u8); cw(cc_state_name(st)); cw("\n" as *u8) 384 if st == CC_ST_UNREGISTERED { cw(" next=register-evidence-backed-consumer-sites; no matching declaration is not proof of no readers\n" as *u8) } 385 if st == CC_ST_UNMEASURED { cw(" next=verify-remedy-config-and-consumer-coverage; zero declared readers is not a complete absence proof\n" as *u8) } 386 } 387 return st 388} 389 390func cc_scan(conf: *u8, cap: i64, remedy: *u8) -> i64 { 391 if cap <= 0 { 392 cwe("NX-CAPCLIFF REFUSED: cap must be > 0 -- a zero cap marks every ledger OVER and the alarm becomes noise\n" as *u8) 393 return 2 394 } 395 let fd: i64 = sys_openat_rd(conf) 396 if fd < 0 { 397 cwe("NX-CAPCLIFF REFUSED: cannot read roster " as *u8); cwe(conf); cwe(" -- refusing to report GREEN over a roster it never read\n" as *u8) 398 return CC_EXIT_EMPTY 399 } 400 // CAP REMOVED 2026-08-23 (nx_capcensus lane): ONE sys_read of CC_CONFCAP silently dropped any 401 // roster tail past 65,536 bytes -- the same shape as nx_cron_reconcile's single 16,383-byte read 402 // of a 24,356-byte registry, which left 11 production jobs inert while printing declared=55 as 403 // if that were the population. sys_read_file sizes its buffer from the file itself (lseek END) 404 // and cannot short-read, so the roster is read WHOLE at any size. The fd check above is kept so 405 // the unreadable-roster refusal is byte-for-byte the behaviour it always had. 406 sys_close(fd) 407 let lenp: *i64 = sys_mmap(8) as *i64 408 *lenp = 0 409 let buf: *u8 = sys_read_file(conf, lenp) 410 let n: i64 = *lenp 411 let pbuf: *u8 = sys_mmap(CC_MAGIC_4096) 412 let counts: *i64 = sys_mmap(8 * CC_K_N) as *i64 413 414 cw("=== nx_capcliff -- append-only ledgers vs the reader capture cap ===\ncap=" as *u8); cwn(cap) 415 cw(" near_at_permil=" as *u8); cwn(CC_NEAR_PERMIL); cw(" roster=" as *u8); cw(conf); cw(" remedy=" as *u8); cw(remedy); cw("\n" as *u8) 416 417 var rows: i64 = 0 418 var over: i64 = 0 419 var near: i64 = 0 420 var missing: i64 = 0 421 var governed: i64 = 0 422 var ungoverned: i64 = 0 423 var breached: i64 = 0 424 var noreader: i64 = 0 425 var unmeasured: i64 = 0 426 var i: i64 = 0 427 while i < n { 428 // Find the line span [i,nl). A break that OVERWRITES THE CURSOR destroys the newline position: 429 // the first draft exited by setting i = n+1, so e collapsed to n and the WHOLE FILE parsed as 430 // one line whose first byte was '#'. Every row vanished and the organ answered 431 // RED-EMPTY-nothing-checked -- which is the ONLY reason the bug was visible at all. A scanner 432 // that had defaulted to GREEN over zero rows would have shipped silently. 433 var nl: i64 = i 434 var brk: i64 = 0 435 while brk == 0 { 436 if nl >= n { brk = 1 } else { if buf[nl] == (10 as u8) { brk = 1 } else { nl = nl + 1 } } 437 } 438 let s: i64 = i 439 var e: i64 = nl 440 // trim trailing CR so a CRLF roster parses identically 441 if e > s { if buf[e-1] == (13 as u8) { e = e - 1 } } 442 if e > s { if buf[s] != (35 as u8) { 443 // CAP REMOVED 2026-08-23 (nx_capcensus lane): `rows` is a COUNTER -- nothing is indexed 444 // by it -- so `rows < CC_MAXROWS` was a PURE SILENT SKIP: ledger 257 and beyond was 445 // never examined and never counted, while the verdict still printed rows=256 as if that 446 // were the population. That is the nx_cron_reconcile declared=55 defect exactly. A cap 447 // is not a number to tune, so it is REMOVED rather than raised. Provably neutral for any 448 // roster of <=256 rows (byte-identical output); strictly more correct above that. 449 if rows >= 0 { 450 cc_copy(buf, s, e, pbuf) 451 let sz: i64 = cc_size(pbuf) 452 rows = rows + 1 453 cw(" " as *u8) 454 if sz < 0 { 455 missing = missing + 1 456 cw("MISSING " as *u8); cwb(buf, s, e); cw(" (rostered but unreadable -- NOT counted OK)\n" as *u8) 457 } else { 458 let permil: i64 = sz * 1000 / cap 459 if sz >= cap { 460 over = over + 1 461 cw("OVER " as *u8); cwb(buf, s, e); cw(" bytes=" as *u8); cwn(sz) 462 cw(" = " as *u8); cwn(permil); cw(" permil of the NOMINAL reader window -- a SIZE fact; the remedy census below says whether any reader is blind\n" as *u8) 463 let st: i64 = cc_remedy(pbuf, remedy, counts, 0) 464 if st == CC_ST_GOVERNED { governed = governed + 1 } 465 if st == CC_ST_UNGOVERNED { ungoverned = ungoverned + 1 } 466 if st == CC_ST_BREACHED { breached = breached + 1 } 467 if st == CC_ST_NOREADER { noreader = noreader + 1 } 468 if st == CC_ST_UNREGISTERED { unmeasured = unmeasured + 1 } 469 if st == CC_ST_UNMEASURED { unmeasured = unmeasured + 1 } 470 } else { if permil >= CC_NEAR_PERMIL { 471 near = near + 1 472 cw("NEAR " as *u8); cwb(buf, s, e); cw(" bytes=" as *u8); cwn(sz) 473 cw(" = " as *u8); cwn(permil); cw(" permil, headroom=" as *u8); cwn(cap - sz); cw(" bytes\n" as *u8) 474 } else { 475 cw("OK " as *u8); cwb(buf, s, e); cw(" bytes=" as *u8); cwn(sz) 476 cw(" = " as *u8); cwn(permil); cw(" permil, headroom=" as *u8); cwn(cap - sz); cw(" bytes\n" as *u8) 477 } } 478 } 479 } 480 } } 481 i = e + 1 482 } 483 484 if rows == 0 { 485 cw("NX-CAPCLIFF verdict=RED-EMPTY-nothing-checked-this-is-not-a-pass (roster had no usable rows)\n" as *u8) 486 return CC_EXIT_EMPTY 487 } 488 cw("NX-CAPCLIFF rows=" as *u8); cwn(rows); cw(" over=" as *u8); cwn(over); cw(" near=" as *u8); cwn(near); cw(" missing=" as *u8); cwn(missing) 489 cw(" over_governed=" as *u8); cwn(governed); cw(" over_noreader=" as *u8); cwn(noreader); cw(" over_ungoverned=" as *u8); cwn(ungoverned); cw(" over_breached=" as *u8); cwn(breached) 490 cw(" over_unmeasured=" as *u8); cwn(unmeasured) 491 if governed + noreader + ungoverned + breached + unmeasured == over { cw(" remedy_partition=RECONCILES" as *u8) } else { cw(" remedy_partition=LEAK" as *u8) } 492 if ungoverned + breached > 0 { cw(" verdict=RED (an OVER ledger has a HEAD-anchored or unverified reader with no working guard, or its guard has already fired: the newest rows are being lost to a reader that cannot see them, or a refusal nobody acted on. Fix the reader's anchoring or declare and arm a guard in " as *u8); cw(remedy); cw(")\n" as *u8); return CC_EXIT_OVER } 493 if unmeasured > 0 { cw(" verdict=UNMEASURED (OVER ledger consumer coverage is unregistered or unmeasured; inspect the remedy declarations)\n" as *u8); return CC_EXIT_UNMEASURED } 494 if near > 0 { cw(" verdict=AMBER (a ledger is approaching the cap -- act before it crosses, because the crossing is SILENT)\n" as *u8); return CC_EXIT_NEAR } 495 if over > 0 { cw(" verdict=GREEN (every OVER ledger is governed: its readers are whole-file or tail-anchored, or a loud guard stands before its cliff; the cap is a declared horizon, not an alarm)\n" as *u8); return 0 } 496 cw(" verdict=GREEN (every rostered ledger fits its readers' capture)\n" as *u8) 497 return 0 498} 499 500// ---- selftest on the base class ------------------------------------------------------------------------------ 501func cc_wfile(path: *u8, s: *u8) -> i64 { 502 let fd: i64 = sys_openat_wr(path, CC_MODE_644) 503 if fd < 0 { return 0 - 1 } 504 let n: i64 = cc_slen(s) 505 sys_write(fd, s, n) 506 sys_close(fd) 507 return n 508} 509func cc_selftest() -> i64 { 510 // The private build runner starts in buildroot; live ledger fixtures belong to the serving root. 511 if cc_exists("knowledge/capcliff_ledgers.conf" as *u8) == 0 { 512 if cc_exists("../knowledge/capcliff_ledgers.conf" as *u8) == 1 { sys_chdir(".." as *u8) } 513 } 514 let ctr: *i64 = gv_ctr() 515 gv_head("nx_capcliff selftest -- each tooth carries its opposite; the remedy census on planted consumers" as *u8) 516 // T1 a file that EXISTS must measure > 0; T2 OPPOSITE: a MISSING file must be -1, NEVER 0 517 let s_ok: i64 = cc_size("knowledge/capcliff_ledgers.conf" as *u8) 518 gv_check("T1 an existing file measures more than zero bytes" as *u8, (s_ok > 0) as i64, ctr) 519 gv_kv("t1_bytes" as *u8, s_ok) 520 gv_check_eq("neg-control-T2 a missing file returns -1, never 0 (0 would score OK and hide a dead roster row)" as *u8, cc_size("knowledge/zzq_no_such_ledger_91827.jrnl" as *u8), 0 - 1, ctr) 521 // T3 the live cliff: actlog must ALREADY be over 4 MiB (this is why the organ exists); T4 OPPOSITE: a ledger under 522 let s_act: i64 = cc_size("knowledge/status/actlog.jrnl" as *u8) 523 gv_check("T3 actlog.jrnl is at or past the nominal window (the measured cliff that motivated this organ)" as *u8, (s_act >= CC_CAP_DEFAULT) as i64, ctr) 524 gv_kv("t3_actlog_bytes" as *u8, s_act) 525 let s_ws: i64 = cc_size("knowledge/status/ws_sync.jrnl" as *u8) 526 var t4: i64 = 0 527 if s_ws > 0 { if s_ws < CC_CAP_DEFAULT { t4 = 1 } } 528 gv_check("T4 ws_sync.jrnl is under the window (the OPPOSITE of T3, so the compare is real)" as *u8, t4, ctr) 529 gv_kv("t4_ws_sync_bytes" as *u8, s_ws) 530 gv_check("neg-control-T5 an unreadable roster does not open (scan REFUSES with exit 5, never GREEN over a roster it never read)" as *u8, (sys_openat_rd("knowledge/zzq_no_such_roster_91827.conf" as *u8) < 0) as i64, ctr) 531 // fixtures under /tmp/nx_capcliff (created at setup; nothing is shared with a production beat) 532 sys_mkdir(CC_FIX_DIR, CC_MODE_755) 533 let csrc: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx" as *u8 534 cc_wfile(csrc, " let b: *u8 = sys_read_file(p, l)\n let t: *u8 = cl_slurp_tail(p, l)\n let n: i64 = sys_read(fd, b, 4096)\n let x: i64 = 1\n let sz: i64 = sys_lseek(fd, 0, SEEK_END)\n" as *u8) 535 let wsrc: *u8 = "/tmp/nx_capcliff_recovery_20260912/w.nx" as *u8 536 cc_wfile(wsrc, " let fd: i64 = sys_openat_append(p, 420)\n" as *u8) 537 let line: *u8 = sys_mmap(CC_LINE_CAP) 538 let path: *u8 = sys_mmap(CC_MAGIC_4096) 539 let spec1: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx:1" as *u8 540 let spec2: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx:2" as *u8 541 let spec3: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx:3" as *u8 542 let spec4: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx:4" as *u8 543 let spec5: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx:5" as *u8 544 let spec9: *u8 = "/tmp/nx_capcliff_recovery_20260912/c.nx:99" as *u8 545 gv_check_eq("T6 a sys_read_file line is WHOLE" as *u8, cc_anchoring(spec1, 0, cc_slen(spec1), path, line), CC_ANCH_WHOLE, ctr) 546 gv_check_eq("T6b a *_tail( helper line is TAIL" as *u8, cc_anchoring(spec2, 0, cc_slen(spec2), path, line), CC_ANCH_TAIL, ctr) 547 gv_check_eq("T6c a bare sys_read( line is HEAD" as *u8, cc_anchoring(spec3, 0, cc_slen(spec3), path, line), CC_ANCH_HEAD, ctr) 548 gv_check_eq("neg-control-T6d a line that reads nothing is UNVERIFIED (a declaration that did not point at a read)" as *u8, cc_anchoring(spec4, 0, cc_slen(spec4), path, line), CC_ANCH_UNVERIFIED, ctr) 549 gv_check_eq("T6e a SEEK_END line is TAIL" as *u8, cc_anchoring(spec5, 0, cc_slen(spec5), path, line), CC_ANCH_TAIL, ctr) 550 gv_check_eq("neg-control-T6f a line past the end of the file is UNVERIFIED, never acquitted" as *u8, cc_anchoring(spec9, 0, cc_slen(spec9), path, line), CC_ANCH_UNVERIFIED, ctr) 551 // five fixture ledgers of 200 bytes and a remedy conf that governs them differently 552 let body: *u8 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n" as *u8 553 cc_wfile("/tmp/nx_capcliff_recovery_20260912/led_a.log" as *u8, body) 554 cc_wfile("/tmp/nx_capcliff_recovery_20260912/led_b.log" as *u8, body) 555 cc_wfile("/tmp/nx_capcliff_recovery_20260912/led_c.log" as *u8, body) 556 cc_wfile("/tmp/nx_capcliff_recovery_20260912/led_d.log" as *u8, body) 557 cc_wfile("/tmp/nx_capcliff_recovery_20260912/led_e.log" as *u8, body) 558 let rconf: *u8 = "/tmp/nx_capcliff_recovery_20260912/remedy.conf" as *u8 559 cc_wfile(rconf, "# fixture remedy conf\n/tmp/nx_capcliff_recovery_20260912/led_a.log|reader|/tmp/nx_capcliff_recovery_20260912/c.nx:1|whole\n/tmp/nx_capcliff_recovery_20260912/led_a.log|reader|/tmp/nx_capcliff_recovery_20260912/c.nx:2|tail\n/tmp/nx_capcliff_recovery_20260912/led_a.log|writer|/tmp/nx_capcliff_recovery_20260912/w.nx:1|append\n/tmp/nx_capcliff_recovery_20260912/led_a.log|mention|/tmp/nx_capcliff_recovery_20260912/c.nx|comment\n/tmp/nx_capcliff_recovery_20260912/led_b.log|reader|/tmp/nx_capcliff_recovery_20260912/c.nx:3|head, no guard\n/tmp/nx_capcliff_recovery_20260912/led_c.log|reader|/tmp/nx_capcliff_recovery_20260912/c.nx:3|head\n/tmp/nx_capcliff_recovery_20260912/led_c.log|guard|sizeguard:1000000:100000|budget far above 200 B\n/tmp/nx_capcliff_recovery_20260912/led_d.log|reader|/tmp/nx_capcliff_recovery_20260912/c.nx:3|head\n/tmp/nx_capcliff_recovery_20260912/led_d.log|guard|sizeguard:10:1|budget below 200 B: the guard has fired\n" as *u8) 560 let counts: *i64 = sys_mmap(8 * CC_K_N) as *i64 561 gv_check_eq("T7 a ledger whose readers are all WHOLE or TAIL is GOVERNED" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_a.log" as *u8, rconf, counts, 1), CC_ST_GOVERNED, ctr) 562 gv_check_eq("T7b its readers partition (readers = whole + tail + head + unverified)" as *u8, counts[CC_K_READERS], counts[CC_K_WHOLE] + counts[CC_K_TAIL] + counts[CC_K_HEAD] + counts[CC_K_UNVER], ctr) 563 gv_check_eq("T7c the writer's append is verified and the mention counted" as *u8, counts[CC_K_WRITERS] * 100 + counts[CC_K_WUNVER] * 10 + counts[CC_K_MENTIONS], 101, ctr) 564 gv_check_eq("neg-control-T8 a HEAD reader with no guard is UNGOVERNED" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_b.log" as *u8, rconf, counts, 1), CC_ST_UNGOVERNED, ctr) 565 gv_check_eq("T9 a HEAD reader behind a sizeguard reading GREEN is GOVERNED (the guard is FORKED, not trusted)" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_c.log" as *u8, rconf, counts, 1), CC_ST_GOVERNED, ctr) 566 gv_check_eq("T9b the forked guard's verdict was GREEN" as *u8, counts[CC_K_GUARD], CC_SG_GREEN, ctr) 567 gv_check_eq("neg-control-T10 a HEAD reader behind a sizeguard reading RED is BREACHED (the refusal fired and nobody acted)" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_d.log" as *u8, rconf, counts, 1), CC_ST_BREACHED, ctr) 568 gv_check_eq("T11 uncovered ledger is UNREGISTERED, never NO-READER" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_e.log" as *u8, rconf, counts, 1), CC_ST_UNREGISTERED, ctr) 569 gv_check_eq("T11b missing config is UNMEASURED" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_a.log" as *u8, "/tmp/nx_capcliff_recovery_20260912/missing-private.conf" as *u8, counts, 1), CC_ST_UNMEASURED, ctr) 570 let zconf: *u8 = "/tmp/nx_capcliff_recovery_20260912/writer-only.conf" as *u8 571 cc_wfile(zconf, "/tmp/nx_capcliff_recovery_20260912/led_e.log|writer|/tmp/nx_capcliff_recovery_20260912/w.nx:1|verified writer, reader census not proven\n" as *u8) 572 gv_check_eq("T11c verified writer alone cannot prove no readers" as *u8, cc_remedy("/tmp/nx_capcliff_recovery_20260912/led_e.log" as *u8, zconf, counts, 1), CC_ST_UNMEASURED, ctr) 573 // T12 the scan's verdict over a fixture roster at a 100-byte cap: b and d make it RED; without them it is GREEN 574 cc_wfile("/tmp/nx_capcliff_recovery_20260912/roster_red.conf" as *u8, "/tmp/nx_capcliff_recovery_20260912/led_a.log\n/tmp/nx_capcliff_recovery_20260912/led_b.log\n/tmp/nx_capcliff_recovery_20260912/led_c.log\n/tmp/nx_capcliff_recovery_20260912/led_d.log\n/tmp/nx_capcliff_recovery_20260912/led_e.log\n" as *u8) 575 cc_wfile("/tmp/nx_capcliff_recovery_20260912/roster_green.conf" as *u8, "/tmp/nx_capcliff_recovery_20260912/led_a.log\n/tmp/nx_capcliff_recovery_20260912/led_c.log\n" as *u8) 576 cc_wfile("/tmp/nx_capcliff_recovery_20260912/roster_unknown.conf" as *u8, "/tmp/nx_capcliff_recovery_20260912/led_e.log\n" as *u8) 577 gv_check_eq("T12c scan uncovered OVER ledger abstains with exit 3" as *u8, cc_scan("/tmp/nx_capcliff_recovery_20260912/roster_unknown.conf" as *u8, 100, rconf), CC_EXIT_UNMEASURED, ctr) 578 gv_check_eq("T12 scan: an ungoverned or breached OVER ledger makes the verdict RED (exit 6)" as *u8, cc_scan("/tmp/nx_capcliff_recovery_20260912/roster_red.conf" as *u8, 100, rconf), CC_EXIT_OVER, ctr) 579 gv_check_eq("T12b scan: registered governed readers preserve GREEN (exit 0)" as *u8, cc_scan("/tmp/nx_capcliff_recovery_20260912/roster_green.conf" as *u8, 100, rconf), 0, ctr) 580 gv_check_eq("neg-control-T13 scan refuses an empty roster with exit 5" as *u8, cc_scan("/tmp/nx_capcliff_recovery_20260912/zzq_absent_roster.conf" as *u8, 100, rconf), CC_EXIT_EMPTY, ctr) 581 return gv_verdict("nx_capcliff" as *u8, ctr, "the size ruler and its opposites, the anchoring classifier on planted read sites, the forked guard in both directions, and the scan verdict that carries RED only for an ungoverned or breached cliff" as *u8) 582} 583 584func main(argc: i64, argv: *i64) -> i64 { 585 // ARGLESS NOW DEFAULTS TO `scan` (2026-08-07). The tickless clock forks scheduled organs ARGLESSLY, 586 // so an organ that REQUIRES a verb can never be put on the clock -- it would print usage and exit 2 587 // every tick, which reads as a running job that never finds anything. That is exactly why THIS 588 // detector was never scheduled while the very cliff it exists to catch was crossed for the THIRD 589 // time: nx_debt's DB_CAP went 4MiB -> 32MiB on 2026-08-06 after the plane silently returned a 590 // truncated prefix and the reader lost its NEWEST rows. `scan` is the only non-selftest verb, so 591 // defaulting to it loses no capability and makes the organ schedulable. 592 // LAW: A TOOL THAT CANNOT RUN ARGLESS CANNOT BE SCHEDULED, AND A DETECTOR THAT CANNOT BE SCHEDULED 593 // ONLY EVER RUNS WHEN SOMEONE ALREADY SUSPECTS THE PROBLEM. 594 var verb: *u8 = "scan" as *u8 595 if argc >= 2 { verb = argv[1] as *u8 } 596 if cc_streq(verb, "selftest" as *u8) == 1 { let rc: i64 = cc_selftest(); sys_exit(rc); return rc } 597 if cc_streq(verb, "remedy" as *u8) == 1 { 598 if argc < 3 { cwe("usage: nx_capcliff remedy <ledger> [remedy.conf]\n" as *u8); sys_exit(2); return 2 } 599 var rconf: *u8 = CC_REMEDY_CONF 600 if argc >= 4 { rconf = argv[3] as *u8 } 601 let counts: *i64 = sys_mmap(8 * CC_K_N) as *i64 602 let st: i64 = cc_remedy(argv[2] as *u8, rconf, counts, 0) 603 if st == CC_ST_UNREGISTERED { sys_exit(CC_EXIT_UNMEASURED); return CC_EXIT_UNMEASURED } 604 if st == CC_ST_UNMEASURED { sys_exit(CC_EXIT_UNMEASURED); return CC_EXIT_UNMEASURED } 605 if st == CC_ST_UNGOVERNED { sys_exit(CC_EXIT_OVER); return CC_EXIT_OVER } 606 if st == CC_ST_BREACHED { sys_exit(CC_EXIT_OVER); return CC_EXIT_OVER } 607 return 0 608 } 609 if cc_streq(verb, "scan" as *u8) == 0 { cwe("usage: nx_capcliff scan [roster.conf] [cap_bytes] [remedy.conf] | remedy <ledger> [remedy.conf] | selftest\n" as *u8); sys_exit(2); return 2 } 610 var conf: *u8 = "knowledge/capcliff_ledgers.conf" as *u8 611 var cap: i64 = CC_CAP_DEFAULT 612 var remedy: *u8 = CC_REMEDY_CONF 613 if argc >= 3 { conf = argv[2] as *u8 } 614 if argc >= 4 { cap = cc_atoi(argv[3] as *u8) } 615 if argc >= 5 { remedy = argv[4] as *u8 } 616 let rc: i64 = cc_scan(conf, cap, remedy) 617 if rc != 0 { sys_exit(rc) } 618 return rc 619}