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}