code wiki / _hdl_build / nx_debt_plane_check.nx
nx_debt_plane_check.nx source
↩ module page · 62 lines · 3455 B
1// nx_debt_plane_check.nx -- READ-ONLY damage report for the debt- plane.
2//
3// WHY THIS EXISTS AS A SEPARATE, ARGLESS ORGAN: nx_plane_repair takes a <prefix> argument, /api/gate_run is
4// argless (seq1384), and a newly-registered MCP tool is unreachable until a reconnect (seq1349). So the one
5// number an operator needs before deciding whether to accept permanent loss -- HOW MANY ROWS -- could not be
6// obtained on the NAS at all. This closes that: no arguments, no writes, no confirm, nothing to get wrong.
7//
8// ★IT CANNOT REPAIR. It shares the loader with nx_plane_repair but has no write path whatsoever, so running
9// it can never accept the loss by accident. Accepting permanent loss stays an explicit operator act with an
10// explicit confirm, on a tool that records a receipt. This one only tells you the size of the decision.
11//
12// usage: nx_debt_plane_check (CWD = the store root)
13// exit 0 = plane healthy · 1 = LOSSY (declared > reachable) · 2 = read truncated, numbers untrustworthy
14// license_tier: ORIGINAL expect_exit: 0
15import "nx_syscalls.nx"
16import "nx_store_seed_lib.nx"
17
18const DC_CAP: i64 = 33554432
19
20func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
21func wn(v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; 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} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
22
23func main() -> i64 {
24 let prefix: *u8 = "knowledge/store/debt-\x00" as *u8
25 let buf: *u8 = sys_mmap(DC_CAP)
26 let f: *i64 = sys_mmap(64) as *i64
27 let n: i64 = sts_load_honest(prefix, buf, DC_CAP, f)
28 var inbuf: i64 = 0
29 var i: i64 = 0
30 while i < n { if buf[i] == (10 as u8) { inbuf = inbuf + 1 } i = i + 1 }
31
32 w("=== nx_debt_plane_check -- read-only damage report for the debt ledger ===\n")
33 w(" declared_qn="); wn(f[0])
34 w(" reachable="); wn(f[1])
35 w(" rows_in_buffer="); wn(inbuf)
36 w(" beyond_qn="); wn(f[2])
37 w(" bytes="); wn(n); w("\n")
38
39 // The same lethal check nx_plane_repair makes: a cap-bounded emit drops rows the counter still counted,
40 // so if these disagree every other number here is untrustworthy and no decision should be made on them.
41 if inbuf != f[1] {
42 w(" READ-TRUNCATED: found "); wn(f[1]); w(" rows but only "); wn(inbuf)
43 w(" reached the buffer -- these numbers are NOT trustworthy, raise DC_CAP.\n")
44 w("VERDICT: verdict=RED (measurement itself is truncated)\n")
45 sys_exit(2); return 2
46 }
47 if f[2] > 0 {
48 w(" ROWS-BEYOND-QN: "); wn(f[2]); w(" rows are reachable PAST the declared count (an older seeding\n")
49 w(" generation). That is a DIFFERENT defect from loss and needs a generation diff, not a reconcile.\n")
50 }
51 if f[0] > f[1] {
52 let lost: i64 = f[0] - f[1]
53 w(" LOSSY: "); wn(lost); w(" row(s) declared but UNREACHABLE. Writes to this plane are refused until\n")
54 w(" reconciled. Those rows are NOT recoverable -- their keys are absent from every segment.\n")
55 w(" TO REPAIR (operator act, records a receipt): nx_plane_repair knowledge/store/debt- confirm=yes\n")
56 w("VERDICT: verdict=RED (ledger write-blocked, "); wn(lost); w(" rows lost)\n")
57 sys_exit(1); return 1
58 }
59 w("VERDICT: verdict=GREEN (debt ledger self-consistent, writes accepted)\n")
60 sys_exit(0)
61 return 0
62}