code wiki / _hdl_build / _ss_compact_cap_gate.nx

_ss_compact_cap_gate.nx source

↩ module page · 197 lines · 8483 B

1import "nx_gate_gn.nx" 2// _ss_compact_cap_gate.nx -- NO-FAKE-GREEN gate for ss_compact_cap (LM-028 fix). 3// Proves the cap-aware compaction folds a >256-segment store to ONE segment with ZERO data loss, 4// AND proves the assertion is REAL by a NEGATIVE CONTROL: an IDENTICAL store with its manifest 5// truncated at SS_MANIFEST_LEGACY_CAP (the synthesized legacy OUTCOME -- the lossy ss_compact 6// itself was rewritten data-driven 2026-07-19, so the old code no longer exists to call; a neg 7// arm invoking it can never fail again, proven RED 2026-07-20) MUST show the loss to this gate's 8// verifier. Pos+neg = the gate cannot be fake-green (a vacuous verifier misses the synth loss). 9// scratch1 (FIX) : build 300 distinct keys (one per segment) -> ss_compact_cap -> expect 10// 1 live segment, ALL 300 keys still retrievable, deep key k:299 value byte-exact, 11// 300 retired names archived (history kept). 12// scratch2 (NEGCTL): same 300-key store -> manifest truncated at SS_MANIFEST_LEGACY_CAP -> 13// expect exactly 256 retrievable and the deep key k:299 ABSENT. 14// Scratch lives in /tmp/ccgate, NOT knowledge/store: the production store is swept by the 600s 15// nx_segguard beat, which compacted a half-built 26-seg fixture mid-run (2026-07-20T20:15:32) and the 16// swap ate one concurrent manifest append -> spurious RED before=299. Hermetic beats timing. Tear down 17// with rm -f /tmp/ccgate/_cctest* before each run; the gate LOGIC is pure NishiLang/sovereign. 18// license_tier: ORIGINAL 19import "nx_seg_store.nx" 20import "nx_syscalls.nx" 21 22func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 23 24// "k:NNN" (3-digit, zero-padded); returns key length (5). null-terminated. 25func kbuf(n: i64, out: *u8) -> i64 { 26 out[0] = 107 as u8 27 out[1] = 58 as u8 28 out[2] = (48 + (n / 100) % 10) as u8 29 out[3] = (48 + (n / 10) % 10) as u8 30 out[4] = (48 + n % 10) as u8 31 out[5] = 0 as u8 32 return 5 33} 34// "vNNN"; returns value length (4). null-terminated. 35func vbuf(n: i64, out: *u8) -> i64 { 36 out[0] = 118 as u8 37 out[1] = (48 + (n / 100) % 10) as u8 38 out[2] = (48 + (n / 10) % 10) as u8 39 out[3] = (48 + n % 10) as u8 40 out[4] = 0 as u8 41 return 4 42} 43 44// commit `count` distinct keys, ONE per segment (segid n+1). Returns 0 ok, -1 fail. 45func build_store(prefix: *u8, count: i64) -> i64 { 46 var n: i64 = 0 47 while n < count { 48 let kb: *u8 = sys_mmap(16) 49 let vb: *u8 = sys_mmap(16) 50 kbuf(n, kb) 51 let vl: i64 = vbuf(n, vb) 52 let w: *i64 = ss_begin() 53 ss_add(w, 1, kb, vb, vl) 54 if ss_commit(prefix, w, n + 1) != 0 { return 0 - 1 } 55 n = n + 1 56 } 57 return 0 58} 59 60// how many of keys [0,count) are live-retrievable (ss_get_cap == 1) 61func count_live(prefix: *u8, count: i64, cap: i64) -> i64 { 62 var found: i64 = 0 63 var n: i64 = 0 64 while n < count { 65 let kb: *u8 = sys_mmap(16) 66 kbuf(n, kb) 67 let pp: *i64 = sys_mmap(16) as *i64 68 let ll: *i64 = sys_mmap(16) as *i64 69 if ss_get_cap(prefix, kb, pp, ll, cap) == 1 { found = found + 1 } 70 n = n + 1 71 } 72 return found 73} 74 75// 1 iff key n retrievable AND its value bytes == vbuf(n) 76func check_val(prefix: *u8, n: i64, cap: i64) -> i64 { 77 let kb: *u8 = sys_mmap(16) 78 kbuf(n, kb) 79 let pp: *i64 = sys_mmap(16) as *i64 80 let ll: *i64 = sys_mmap(16) as *i64 81 if ss_get_cap(prefix, kb, pp, ll, cap) != 1 { return 0 } 82 let vb: *u8 = sys_mmap(16) 83 let vl: i64 = vbuf(n, vb) 84 if ll[0] != vl { return 0 } 85 let got: *u8 = pp[0] as *u8 86 var t: i64 = 0 87 while t < vl { if got[t] != vb[t] { return 0 } t = t + 1 } 88 return 1 89} 90 91// HERMETIC SETUP (2026-08-07). This gate was GREEN exactly ONCE -- on a virgin /tmp -- and RED on 92// every run since. Both failures were the SAME root cause: it left state behind, then asserted 93// ABSOLUTE counts against it. 94// (a) ss_commit APPENDS to <prefix>manifest.txt, so the PREVIOUS run's merged segment was still 95// live and each rerun archived 301, not 300 -> `arch != N` -> RED. Observed 300, 601, 902. 96// (b) the neg control TRUNCATES p2's manifest to the legacy cap and LEAVES it, so the next run's 97// build_store appended 300 rows onto 256 -> ns2 = 556 != 300 -> rc2 = -1 -> RED. 98// Cleaning at SETUP, not teardown, is deliberate: a teardown does not run when a run crashes, and 99// this gate's own header already banks "Hermetic beats timing. Tear down" as a lesson learned -- 100// which it then did not apply to its own archive or to p2. 101// Only the two MANIFESTS are removed. Segment .docs/.idx/.pos are left alone: they are reachable 102// ONLY through a manifest, build_store rewrites segids 1..N anyway, and unlinking data files inside 103// a test would be a habit worth not forming. 104// ★A GATE THAT LEAVES STATE BEHIND AND ASSERTS ABSOLUTE COUNTS IS GREEN EXACTLY ONCE. 105func wipe_plane(prefix: *u8) -> i64 { 106 let f: *u8 = sys_mmap(512) 107 var o: i64 = 0 108 o = ss_cat(f, o, prefix) 109 o = ss_cat(f, o, "manifest.txt" as *u8) 110 f[o] = 0 as u8 111 sys_unlinkat(f) 112 let g: *u8 = sys_mmap(512) 113 var o2: i64 = 0 114 o2 = ss_cat(g, o2, prefix) 115 o2 = ss_cat(g, o2, "manifest-archive.txt" as *u8) 116 g[o2] = 0 as u8 117 sys_unlinkat(g) 118 return 0 119} 120 121func main() -> i64 { sys_mkdir("/tmp/ccgate\x00" as *u8, 0x1ed) 122 let p1: *u8 = "/tmp/ccgate/_cctest1-" as *u8 123 let p2: *u8 = "/tmp/ccgate/_cctest2-" as *u8 124 let CAP: i64 = 1024 125 let N: i64 = 300 126 127 // HERMETIC SETUP -- see wipe_plane above. Without this the gate is GREEN exactly once, on a 128 // virgin /tmp, and RED on every run thereafter regardless of whether ss_compact_cap is correct. 129 wipe_plane(p1) 130 wipe_plane(p2) 131 132 if build_store(p1, N) != 0 { gp("BUILD1 FAIL\n" as *u8); sys_exit(1); return 1 } 133 if build_store(p2, N) != 0 { gp("BUILD2 FAIL\n" as *u8); sys_exit(1); return 1 } 134 135 let before: i64 = count_live(p1, N, CAP) 136 137 // ---- FIX: cap-aware compaction ---- 138 let rc1: i64 = ss_compact_cap(p1, 900001, CAP) 139 let s1: *i64 = sys_mmap(8 * CAP) as *i64 140 let seg1: i64 = ss_manifest_cap(p1, s1, CAP) 141 let after1: i64 = count_live(p1, N, CAP) 142 let deep1: i64 = check_val(p1, 299, CAP) 143 let s1a: *i64 = sys_mmap(8 * CAP) as *i64 144 let arch: i64 = ss_manifest_file_cap(p1, "manifest-archive.txt" as *u8, s1a, CAP) 145 146 // ---- NEG CONTROL: synthesize the legacy 256-cap OUTCOME (truncate live manifest at the 147 // legacy cap) and prove THIS GATE'S VERIFIER sees the loss (anti-vacuity). 148 let s2: *i64 = sys_mmap(8 * CAP) as *i64 149 let ns2: i64 = ss_manifest_cap(p2, s2, CAP) 150 var rc2: i64 = 0 - 1 151 if ns2 == N { rc2 = 900002 } 152 let mb: *u8 = sys_mmap(16384) 153 var mo: i64 = 0 154 var si: i64 = 0 155 while si < SS_MANIFEST_LEGACY_CAP { 156 mo = ss_cat(mb, mo, s2[si] as *u8) 157 mb[mo] = 10 as u8 158 mo = mo + 1 159 si = si + 1 160 } 161 let m2: *u8 = sys_mmap(512) 162 var o3: i64 = 0 163 o3 = ss_cat(m2, o3, p2) 164 o3 = ss_cat(m2, o3, "manifest.txt" as *u8) 165 m2[o3] = 0 as u8 166 if ss_writefile(m2, mb, mo) != 0 { rc2 = 0 - 9 } 167 let after2: i64 = count_live(p2, N, CAP) 168 let deep2: i64 = check_val(p2, 299, CAP) 169 170 gp("=== ss_compact_cap gate (LM-028) ===\n" as *u8) 171 gp("before(live)=" as *u8); gn(before); gp(" (expect 300)\n" as *u8) 172 gp("FIX rc=" as *u8); gn(rc1); gp(" segs_after=" as *u8); gn(seg1); gp(" live_after=" as *u8); gn(after1) 173 gp(" deep_k299=" as *u8); gn(deep1); gp(" archived=" as *u8); gn(arch); gp("\n" as *u8) 174 gp("NEGCTL(synth-legacy) rc=" as *u8); gn(rc2); gp(" live_after=" as *u8); gn(after2); gp(" deep_k299=" as *u8); gn(deep2); gp("\n" as *u8) 175 176 var ok: i64 = 1 177 if before != N { ok = 0 } 178 if rc1 != 900001 { ok = 0 } 179 if seg1 != 1 { ok = 0 } 180 if after1 != N { ok = 0 } 181 if deep1 != 1 { ok = 0 } 182 if arch != N { ok = 0 } 183 // neg control MUST show the synthesized loss: exactly the legacy-cap survivors, deep key gone 184 if rc2 != 900002 { ok = 0 } 185 if after2 != SS_MANIFEST_LEGACY_CAP { ok = 0 } 186 if deep2 != 0 { ok = 0 } 187 188 if ok == 1 { 189 gp("GALXCOMPACTGATE 9/9 GREEN -- cap-aware compaction: 300 segs -> 1, ZERO loss, deep key exact, history archived; synth legacy-cap control DROPS " as *u8) 190 gn(N - after2); gp(" keys (verifier non-vacuous)\n" as *u8) 191 sys_exit(0) 192 return 0 193 } 194 gp("GALXCOMPACTGATE RED\n" as *u8) 195 sys_exit(1) 196 return 1 197}