code wiki / _hdl_build / nx_infomgmt_gate.nx
nx_infomgmt_gate.nx source
↩ module page · 672 lines · 26571 B
1// nx_infomgmt_gate.nx -- THE INFORMATION-MANAGEMENT GATE: one command re-proves
2// the sovereign storage substrate rung-1 claim set (segment store + canonical
3// CID), evidence-driven + durable. Pure NishiLang, NO SQL, no .sh.
4//
5// Rows (each = a claim; FAIL on any row = RED, never silenced):
6// canon-determinism same logical record, two field insertion orders
7// => IDENTICAL canonical bytes => IDENTICAL CID
8// canon-distinct different record => different CID (no collisions by
9// construction of the encoding)
10// fresh-process-read records written+committed by a CHILD PROCESS that
11// exits; parent reads byte-exact (no shared memory --
12// the bytes came off disk)
13// time-travel v2 shadows v1 on get(); BOTH versions remain readable
14// in history (the additive law as a query surface)
15// tombstone-additive delete = tombstone: get() says GONE, history still
16// serves the old bytes (nothing is ever destroyed)
17// crash-invisibility fault injection: child dies BEFORE the commit point
18// (temp written, no rename/manifest) => key absent,
19// prior data intact, manifest unchanged
20// reopen-determinism all reads repeated from scratch are byte-identical
21// and the canonical CID re-derives identically
22//
23// EXCEED rows vs SQL-class stores: time-travel + tombstone-additive +
24// crash-invisibility are capabilities SQLite does not give by default.
25// Durable verdicts: knowledge/status/infomgmt_gate.log.
26// license_tier: ORIGINAL
27
28import "nx_syscalls.nx"
29import "nx_canon_cid.nx"
30import "nx_seg_store.nx"
31
32const IG_ROWS: i64 = 15
33
34func ig_p(s: *u8) -> i64 {
35 var n: i64 = 0
36 while s[n] != (0 as u8) { n = n + 1 }
37 sys_write(1, s, n)
38 return 0
39}
40
41func ig_fp(fd: i64, s: *u8) -> i64 {
42 var n: i64 = 0
43 while s[n] != (0 as u8) { n = n + 1 }
44 sys_write(fd, s, n)
45 return 0
46}
47
48func ig_fn(fd: i64, v: i64) -> i64 {
49 let bb: *u8 = sys_mmap(28)
50 var m: i64 = v
51 if m < 0 { m = 0 - m; sys_write(fd, "-" as *u8, 1) }
52 let t: *u8 = sys_mmap(28)
53 var k: i64 = 0
54 if m == 0 { t[0] = 48 as u8; k = 1 }
55 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
56 var i: i64 = 0
57 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
58 sys_write(fd, bb, k)
59 return 0
60}
61
62func ig_memeq(a: *u8, b: *u8, n: i64) -> i64 {
63 var i: i64 = 0
64 while i < n {
65 if a[i] != b[i] { return 0 }
66 i = i + 1
67 }
68 return 1
69}
70
71func ig_streq(a: *u8, b: *u8) -> i64 {
72 var i: i64 = 0
73 while 1 == 1 {
74 if a[i] != b[i] { return 0 }
75 if a[i] == (0 as u8) { return 1 }
76 i = i + 1
77 }
78 return 0
79}
80
81func ig_report(logfd: i64, name: *u8, pass: i64) -> i64 {
82 var fdi: i64 = 0
83 while fdi < 2 {
84 var fd: i64 = 1
85 if fdi == 1 { fd = logfd }
86 if fd > 0 {
87 ig_fp(fd, "INFOMGMT-GATE row=" as *u8)
88 ig_fp(fd, name)
89 if pass == 1 { ig_fp(fd, " verdict=PASS\n" as *u8) }
90 if pass != 1 { ig_fp(fd, " verdict=FAIL\n" as *u8) }
91 }
92 fdi = fdi + 1
93 }
94 return 0
95}
96
97// fork a child that writes records into segid then commits (mode 1) or
98// crash-writes only the temp (mode 2); parent waits. Records are passed as
99// (kind,key,val,vlen) quads in q[], nq of them.
100func ig_child_write(prefix: *u8, segid: i64, mode: i64, q: *i64, nq: i64) -> i64 {
101 let pid: i64 = sys_fork()
102 if pid == 0 {
103 let w: *i64 = ss_begin()
104 var i: i64 = 0
105 while i < nq {
106 ss_add(w, q[i * 4], (q[i * 4 + 1]) as *u8, (q[i * 4 + 2]) as *u8, q[i * 4 + 3])
107 i = i + 1
108 }
109 var rc: i64 = 0
110 if mode == 1 { rc = ss_commit(prefix, w, segid) }
111 if mode == 2 { rc = ss_crashwrite(prefix, w, segid) }
112 if rc != 0 { sys_exit(9) }
113 sys_exit(0)
114 }
115 let st: *i64 = sys_mmap(16) as *i64
116 sys_wait4(pid, st, 0)
117 return st[0]
118}
119
120func main() -> i64 {
121 let logfd: i64 = sys_openat_append("knowledge/status/infomgmt_gate.log" as *u8, 0x1a4)
122 if logfd > 0 {
123 ig_fp(logfd, "INFOMGMT-GATE epoch=" as *u8)
124 ig_fn(logfd, sys_now_realtime_sec())
125 ig_fp(logfd, " run-start rung=1 (segment-store + canonical-cid)\n" as *u8)
126 }
127
128 // fresh per-run store prefix (flat files; no mkdir needed)
129 let prefix: *u8 = sys_mmap(128)
130 var po: i64 = 0
131 po = ss_cat(prefix, po, "/tmp/im" as *u8)
132 po = ss_catn(prefix, po, sys_now_us())
133 po = ss_cat(prefix, po, "-" as *u8)
134 prefix[po] = 0 as u8
135
136 var passed: i64 = 0
137
138 // ---- record A: same logical record, two insertion orders ----
139 let k1: *i64 = sys_mmap(8 * 4) as *i64
140 let v1: *i64 = sys_mmap(8 * 4) as *i64
141 k1[0] = "name" as *u8 as i64
142 v1[0] = "diora_baird" as *u8 as i64
143 k1[1] = "layer" as *u8 as i64
144 v1[1] = "L6" as *u8 as i64
145 k1[2] = "maturity" as *u8 as i64
146 v1[2] = "functional" as *u8 as i64
147 let k2: *i64 = sys_mmap(8 * 4) as *i64
148 let v2: *i64 = sys_mmap(8 * 4) as *i64
149 k2[0] = "maturity" as *u8 as i64
150 v2[0] = "functional" as *u8 as i64
151 k2[1] = "name" as *u8 as i64
152 v2[1] = "diora_baird" as *u8 as i64
153 k2[2] = "layer" as *u8 as i64
154 v2[2] = "L6" as *u8 as i64
155
156 let encA: *u8 = sys_mmap(4096)
157 let encA2: *u8 = sys_mmap(4096)
158 let lenA: i64 = canon_encode(k1, v1, 3, encA)
159 let lenA2: i64 = canon_encode(k2, v2, 3, encA2)
160 let cidA: *u8 = sys_mmap(80)
161 let cidA2: *u8 = sys_mmap(80)
162 cid_of(encA, lenA, cidA)
163 cid_of(encA2, lenA2, cidA2)
164 var ok: i64 = 0
165 if lenA == lenA2 { if ig_memeq(encA, encA2, lenA) == 1 { if ig_streq(cidA, cidA2) == 1 { ok = 1 } } }
166 ig_report(logfd, "canon-determinism" as *u8, ok)
167 passed = passed + ok
168
169 // ---- record B: one value differs => different CID ----
170 let v3: *i64 = sys_mmap(8 * 4) as *i64
171 v3[0] = "diora_baird" as *u8 as i64
172 v3[1] = "L6" as *u8 as i64
173 v3[2] = "production" as *u8 as i64
174 let encB: *u8 = sys_mmap(4096)
175 let lenB: i64 = canon_encode(k1, v3, 3, encB)
176 let cidB: *u8 = sys_mmap(80)
177 cid_of(encB, lenB, cidB)
178 ok = 0
179 if ig_streq(cidA, cidB) == 0 { ok = 1 }
180 ig_report(logfd, "canon-distinct" as *u8, ok)
181 passed = passed + ok
182
183 // ---- seg 1 written + committed by a fresh child process ----
184 let q1: *i64 = sys_mmap(8 * 8) as *i64
185 q1[0] = 1
186 q1[1] = "cap:diora" as *u8 as i64
187 q1[2] = encA as i64
188 q1[3] = lenA
189 q1[4] = 1
190 q1[5] = "cap:search" as *u8 as i64
191 q1[6] = encB as i64
192 q1[7] = lenB
193 let st1: i64 = ig_child_write(prefix, 1, 1, q1, 2)
194 let pp: *i64 = sys_mmap(16) as *i64
195 let ll: *i64 = sys_mmap(16) as *i64
196 ok = 0
197 if st1 == 0 {
198 let g1: i64 = ss_get(prefix, "cap:diora" as *u8, pp, ll)
199 if g1 == 1 { if ll[0] == lenA { if ig_memeq(pp[0] as *u8, encA, lenA) == 1 {
200 let g2: i64 = ss_get(prefix, "cap:search" as *u8, pp, ll)
201 if g2 == 1 { if ll[0] == lenB { if ig_memeq(pp[0] as *u8, encB, lenB) == 1 { ok = 1 } } }
202 } } }
203 }
204 ig_report(logfd, "fresh-process-read" as *u8, ok)
205 passed = passed + ok
206
207 // ---- seg 2: v2 of cap:diora (record B bytes) => shadows v1, history keeps both ----
208 let q2: *i64 = sys_mmap(8 * 4) as *i64
209 q2[0] = 1
210 q2[1] = "cap:diora" as *u8 as i64
211 q2[2] = encB as i64
212 q2[3] = lenB
213 let st2: i64 = ig_child_write(prefix, 2, 1, q2, 1)
214 let kinds: *i64 = sys_mmap(8 * 260) as *i64
215 let ptrs: *i64 = sys_mmap(8 * 260) as *i64
216 let lens: *i64 = sys_mmap(8 * 260) as *i64
217 ok = 0
218 if st2 == 0 {
219 let g3: i64 = ss_get(prefix, "cap:diora" as *u8, pp, ll)
220 if g3 == 1 { if ll[0] == lenB { if ig_memeq(pp[0] as *u8, encB, lenB) == 1 {
221 let hn: i64 = ss_scan(prefix, "cap:diora" as *u8, kinds, ptrs, lens)
222 if hn == 2 { if lens[0] == lenA { if ig_memeq(ptrs[0] as *u8, encA, lenA) == 1 { ok = 1 } } }
223 } } }
224 }
225 ig_report(logfd, "time-travel" as *u8, ok)
226 passed = passed + ok
227
228 // ---- seg 3: tombstone cap:search => GONE on get, history additive ----
229 let q3: *i64 = sys_mmap(8 * 4) as *i64
230 q3[0] = 2
231 q3[1] = "cap:search" as *u8 as i64
232 q3[2] = "" as *u8 as i64
233 q3[3] = 0
234 let st3: i64 = ig_child_write(prefix, 3, 1, q3, 1)
235 ok = 0
236 if st3 == 0 {
237 let g4: i64 = ss_get(prefix, "cap:search" as *u8, pp, ll)
238 if g4 == 0 {
239 let hn2: i64 = ss_scan(prefix, "cap:search" as *u8, kinds, ptrs, lens)
240 if hn2 == 2 { if lens[0] == lenB { if ig_memeq(ptrs[0] as *u8, encB, lenB) == 1 { ok = 1 } } }
241 }
242 }
243 ig_report(logfd, "tombstone-additive" as *u8, ok)
244 passed = passed + ok
245
246 // ---- seg 4: FAULT INJECTION -- child dies before the commit point ----
247 let q4: *i64 = sys_mmap(8 * 4) as *i64
248 q4[0] = 1
249 q4[1] = "cap:ghost" as *u8 as i64
250 q4[2] = encB as i64
251 q4[3] = lenB
252 let st4: i64 = ig_child_write(prefix, 4, 2, q4, 1)
253 let segs: *i64 = sys_mmap(8 * 260) as *i64
254 ok = 0
255 if st4 == 0 {
256 let g5: i64 = ss_get(prefix, "cap:ghost" as *u8, pp, ll)
257 if g5 == (0 - 1) {
258 let g6: i64 = ss_get(prefix, "cap:diora" as *u8, pp, ll)
259 if g6 == 1 { if ig_memeq(pp[0] as *u8, encB, lenB) == 1 {
260 let ms: i64 = ss_manifest(prefix, segs)
261 if ms == 3 { ok = 1 }
262 } }
263 }
264 }
265 ig_report(logfd, "crash-invisibility" as *u8, ok)
266 passed = passed + ok
267
268 // ---- reopen-determinism: every read again from scratch + CID re-derives ----
269 ok = 0
270 let g7: i64 = ss_get(prefix, "cap:diora" as *u8, pp, ll)
271 if g7 == 1 { if ig_memeq(pp[0] as *u8, encB, lenB) == 1 {
272 let cidR: *u8 = sys_mmap(80)
273 cid_of(pp[0] as *u8, ll[0], cidR)
274 if ig_streq(cidR, cidB) == 1 {
275 let g8: i64 = ss_get(prefix, "cap:search" as *u8, pp, ll)
276 if g8 == 0 { ok = 1 }
277 }
278 } }
279 ig_report(logfd, "reopen-determinism" as *u8, ok)
280 passed = passed + ok
281
282 // ---- fsync-durability (IM3): wrapper discriminates real fds, commit path green ----
283 // sys_fsync must return 0 on a valid fd and EBADF on a junk fd (proves the
284 // syscall is wired, not a no-op), and a commit through the fsync'd path
285 // must still read back byte-exact.
286 ok = 0
287 let mfp: *u8 = sys_mmap(512)
288 var mo: i64 = 0
289 mo = ss_cat(mfp, mo, prefix)
290 mo = ss_cat(mfp, mo, "manifest.txt" as *u8)
291 mfp[mo] = 0 as u8
292 let ffd: i64 = sys_openat_rd(mfp)
293 if ffd >= 0 {
294 let f1: i64 = sys_fsync(ffd)
295 sys_close(ffd)
296 let f2: i64 = sys_fsync(0 - 1)
297 if f1 == 0 { if f2 == (0 - 9) {
298 let q5: *i64 = sys_mmap(8 * 4) as *i64
299 q5[0] = 1
300 q5[1] = "cap:fsync" as *u8 as i64
301 q5[2] = encA as i64
302 q5[3] = lenA
303 let st5: i64 = ig_child_write(prefix, 5, 1, q5, 1)
304 if st5 == 0 {
305 let g9: i64 = ss_get(prefix, "cap:fsync" as *u8, pp, ll)
306 if g9 == 1 { if ig_memeq(pp[0] as *u8, encA, lenA) == 1 { ok = 1 } }
307 }
308 } }
309 }
310 ig_report(logfd, "fsync-durability" as *u8, ok)
311 passed = passed + ok
312
313 // ---- key-index-oracle (IM2): binary-search reads == chronological scan ----
314 // The scan path is the ORACLE; the index must agree on verdict AND bytes
315 // for every key state: live (cap:diora=v2), tombstoned (cap:search),
316 // never-written (cap:ghost), fresh single-segment (cap:fsync).
317 ok = 1
318 let pp2: *i64 = sys_mmap(16) as *i64
319 let ll2: *i64 = sys_mmap(16) as *i64
320 let names9: *i64 = sys_mmap(8 * 4) as *i64
321 names9[0] = "cap:diora" as *u8 as i64
322 names9[1] = "cap:search" as *u8 as i64
323 names9[2] = "cap:ghost" as *u8 as i64
324 names9[3] = "cap:fsync" as *u8 as i64
325 let hh: *i64 = ss_open(prefix)
326 let pp3: *i64 = sys_mmap(16) as *i64
327 let ll3: *i64 = sys_mmap(16) as *i64
328 var ki: i64 = 0
329 while ki < 4 {
330 let kk: *u8 = names9[ki] as *u8
331 let vs: i64 = ss_get(prefix, kk, pp, ll)
332 let vi: i64 = ss_get_idx(prefix, kk, pp2, ll2)
333 let vh: i64 = ss_hget(hh, kk, pp3, ll3)
334 if vs != vi { ok = 0 }
335 if vs != vh { ok = 0 }
336 if vs == 1 { if vi == 1 {
337 if ll[0] != ll2[0] { ok = 0 }
338 if ok == 1 { if ig_memeq(pp[0] as *u8, pp2[0] as *u8, ll[0]) == 0 { ok = 0 } }
339 if ll[0] != ll3[0] { ok = 0 }
340 if ok == 1 { if ig_memeq(pp[0] as *u8, pp3[0] as *u8, ll[0]) == 0 { ok = 0 } }
341 } }
342 ki = ki + 1
343 }
344 ig_report(logfd, "key-index-oracle" as *u8, ok)
345 passed = passed + ok
346
347 // ---- term-postings-oracle (IM2b): postings path == brute-force tokenize ----
348 // Expectation computed by the ORACLE path (ss_hget + ss_tok_has per key);
349 // ss_term must return the same count AND every returned key's current
350 // record must actually contain the term. Terms chosen to exercise:
351 // multi-hit ("diora": 2 records), shadowed-version + tombstone exclusion
352 // ("production": only cap:diora's v2 -- cap:search had it but is
353 // tombstoned), and the negative ("zzznope": 0).
354 ok = 1
355 let qterms: *i64 = sys_mmap(8 * 4) as *i64
356 qterms[0] = "diora" as *u8 as i64
357 qterms[1] = "production" as *u8 as i64
358 qterms[2] = "zzznope" as *u8 as i64
359 let tkp: *i64 = sys_mmap(8 * 20) as *i64
360 let tkl: *i64 = sys_mmap(8 * 20) as *i64
361 let kcopy: *u8 = sys_mmap(256)
362 var exp_diora: i64 = 0
363 var exp_prod: i64 = 0
364 var qi: i64 = 0
365 while qi < 3 {
366 let qt: *u8 = qterms[qi] as *u8
367 var exp: i64 = 0
368 var oi: i64 = 0
369 while oi < 4 {
370 let g: i64 = ss_hget(hh, names9[oi] as *u8, pp3, ll3)
371 if g == 1 { if ss_tok_has(pp3[0] as *u8, ll3[0], qt) == 1 { exp = exp + 1 } }
372 oi = oi + 1
373 }
374 if qi == 0 { exp_diora = exp }
375 if qi == 1 { exp_prod = exp }
376 let got: i64 = ss_term(hh, qt, tkp, tkl, 16)
377 if got != exp { ok = 0 }
378 // membership: every returned key's current record contains the term
379 var ri: i64 = 0
380 while ri < got {
381 var x: i64 = 0
382 let ks: *u8 = tkp[ri] as *u8
383 while x < tkl[ri] { kcopy[x] = ks[x]; x = x + 1 }
384 kcopy[x] = 0 as u8
385 let g2: i64 = ss_hget(hh, kcopy, pp3, ll3)
386 if g2 != 1 { ok = 0 }
387 if g2 == 1 { if ss_tok_has(pp3[0] as *u8, ll3[0], qt) == 0 { ok = 0 } }
388 ri = ri + 1
389 }
390 qi = qi + 1
391 }
392 // sanity teeth: the multi-hit and single-hit expectations must be real
393 if exp_diora != 2 { ok = 0 }
394 if exp_prod != 1 { ok = 0 }
395 ig_report(logfd, "term-postings-oracle" as *u8, ok)
396 passed = passed + ok
397
398 // ---- multi-term-and-oracle (IM2c): postings intersection == full-scan AND ----
399 // ORACLE = for every known key: current bytes (ss_hget) contain ALL terms
400 // (ss_tok_has, the same single tokenizer). Queries chosen to exercise:
401 // q0 diora+production -> 1 (cap:search ALSO had both but is
402 // tombstoned -- AND must exclude it)
403 // q1 diora+functional -> 1 (cap:diora's v1 had both; its CURRENT
404 // v2 lost "functional" -- the stale
405 // version must NOT answer = currency)
406 // q2 diora+zzznope -> 0 (empty intersection)
407 // q3 diora+layer+production-> 1 (3-term query)
408 // Runs PRE-compaction so shadowed versions still sit in live segments.
409 ok = 1
410 let qn: *i64 = sys_mmap(8 * 8) as *i64
411 let qts: *i64 = sys_mmap(8 * 16) as *i64
412 qn[0] = 2
413 qts[0] = "diora" as *u8 as i64
414 qts[1] = "production" as *u8 as i64
415 qn[1] = 2
416 qts[3] = "diora" as *u8 as i64
417 qts[4] = "functional" as *u8 as i64
418 qn[2] = 2
419 qts[6] = "diora" as *u8 as i64
420 qts[7] = "zzznope" as *u8 as i64
421 qn[3] = 3
422 qts[9] = "diora" as *u8 as i64
423 qts[10] = "layer" as *u8 as i64
424 qts[11] = "production" as *u8 as i64
425 let teeth: *i64 = sys_mmap(8 * 8) as *i64
426 teeth[0] = 1
427 teeth[1] = 1
428 teeth[2] = 0
429 teeth[3] = 1
430 let akp: *i64 = sys_mmap(8 * 20) as *i64
431 let akl: *i64 = sys_mmap(8 * 20) as *i64
432 let aterms: *i64 = sys_mmap(8 * 4) as *i64
433 var aq: i64 = 0
434 while aq < 4 {
435 let nt: i64 = qn[aq]
436 var ti: i64 = 0
437 while ti < nt { aterms[ti] = qts[aq * 3 + ti]; ti = ti + 1 }
438 // oracle expectation: full scan of known keys, ALL terms in current bytes
439 var exp: i64 = 0
440 var oi: i64 = 0
441 while oi < 4 {
442 let g: i64 = ss_hget(hh, names9[oi] as *u8, pp3, ll3)
443 if g == 1 {
444 var all: i64 = 1
445 ti = 0
446 while ti < nt {
447 if ss_tok_has(pp3[0] as *u8, ll3[0], aterms[ti] as *u8) == 0 { all = 0 }
448 ti = ti + 1
449 }
450 if all == 1 { exp = exp + 1 }
451 }
452 oi = oi + 1
453 }
454 if exp != teeth[aq] { ok = 0 }
455 let got: i64 = ss_term_and(hh, aterms, nt, akp, akl, 16)
456 if got != exp { ok = 0 }
457 // membership: every returned key's current record contains EVERY term
458 var ri: i64 = 0
459 while ri < got {
460 var x: i64 = 0
461 let ks: *u8 = akp[ri] as *u8
462 while x < akl[ri] { kcopy[x] = ks[x]; x = x + 1 }
463 kcopy[x] = 0 as u8
464 let g2: i64 = ss_hget(hh, kcopy, pp3, ll3)
465 if g2 != 1 { ok = 0 }
466 if g2 == 1 {
467 ti = 0
468 while ti < nt {
469 if ss_tok_has(pp3[0] as *u8, ll3[0], aterms[ti] as *u8) == 0 { ok = 0 }
470 ti = ti + 1
471 }
472 }
473 ri = ri + 1
474 }
475 aq = aq + 1
476 }
477 // single-term consistency: AND of one term == ss_term exactly
478 aterms[0] = "diora" as *u8 as i64
479 if ss_term_and(hh, aterms, 1, akp, akl, 16) != exp_diora { ok = 0 }
480 ig_report(logfd, "multi-term-and-oracle" as *u8, ok)
481 passed = passed + ok
482
483 // ---- compaction-equivalence (IM4): get() identical across the fold ----
484 // Pre-compaction expectations (proven by earlier rows): cap:diora=encB,
485 // cap:search=GONE(0), cap:ghost=ABSENT(-1), cap:fsync=encA. Compact, then
486 // every key must answer IDENTICALLY on BOTH read paths, and the live
487 // manifest must hold exactly the one merged segment.
488 ok = 0
489 let cseg: i64 = ss_compact(prefix, 9000001)
490 if cseg == 9000001 {
491 ok = 1
492 let gd: i64 = ss_get(prefix, "cap:diora" as *u8, pp, ll)
493 if gd != 1 { ok = 0 }
494 if ok == 1 { if ig_memeq(pp[0] as *u8, encB, lenB) == 0 { ok = 0 } }
495 let gdi: i64 = ss_get_idx(prefix, "cap:diora" as *u8, pp2, ll2)
496 if gdi != 1 { ok = 0 }
497 if ok == 1 { if ig_memeq(pp2[0] as *u8, encB, lenB) == 0 { ok = 0 } }
498 if ss_get(prefix, "cap:search" as *u8, pp, ll) != 0 { ok = 0 }
499 if ss_get_idx(prefix, "cap:search" as *u8, pp2, ll2) != 0 { ok = 0 }
500 if ss_get(prefix, "cap:ghost" as *u8, pp, ll) != (0 - 1) { ok = 0 }
501 if ss_get_idx(prefix, "cap:ghost" as *u8, pp2, ll2) != (0 - 1) { ok = 0 }
502 let gf: i64 = ss_get(prefix, "cap:fsync" as *u8, pp, ll)
503 if gf != 1 { ok = 0 }
504 if ok == 1 { if ig_memeq(pp[0] as *u8, encA, lenA) == 0 { ok = 0 } }
505 let ms2: i64 = ss_manifest(prefix, segs)
506 if ms2 != 1 { ok = 0 }
507 // term search survives the fold with identical answers (fresh handle)
508 let hc: *i64 = ss_open(prefix)
509 let ckp: *i64 = sys_mmap(8 * 20) as *i64
510 let ckl: *i64 = sys_mmap(8 * 20) as *i64
511 if ss_term(hc, "diora" as *u8, ckp, ckl, 16) != exp_diora { ok = 0 }
512 if ss_term(hc, "production" as *u8, ckp, ckl, 16) != exp_prod { ok = 0 }
513 if ss_term(hc, "zzznope" as *u8, ckp, ckl, 16) != 0 { ok = 0 }
514 // AND queries survive the fold with identical answers
515 aterms[0] = "diora" as *u8 as i64
516 aterms[1] = "production" as *u8 as i64
517 if ss_term_and(hc, aterms, 2, ckp, ckl, 16) != 1 { ok = 0 }
518 aterms[1] = "functional" as *u8 as i64
519 if ss_term_and(hc, aterms, 2, ckp, ckl, 16) != 1 { ok = 0 }
520 aterms[1] = "zzznope" as *u8 as i64
521 if ss_term_and(hc, aterms, 2, ckp, ckl, 16) != 0 { ok = 0 }
522 }
523 ig_report(logfd, "compaction-equivalence" as *u8, ok)
524 passed = passed + ok
525
526 // ---- compaction-archive (IM4): history files survive, archive names them ----
527 ok = 1
528 let arcp: *u8 = sys_mmap(512)
529 var aro: i64 = 0
530 aro = ss_cat(arcp, aro, prefix)
531 aro = ss_cat(arcp, aro, "manifest-archive.txt" as *u8)
532 arcp[aro] = 0 as u8
533 let aszp: *i64 = sys_mmap(16) as *i64
534 let ab: *u8 = ss_readall(arcp, aszp)
535 if aszp[0] <= 0 { ok = 0 }
536 // archive must list 4 retired segments (one line each)
537 var alines: i64 = 0
538 var ai: i64 = 0
539 while ai < aszp[0] {
540 if ab[ai] == (10 as u8) { alines = alines + 1 }
541 ai = ai + 1
542 }
543 if alines != 4 { ok = 0 }
544 // every retired segment's .docs file is STILL on disk and readable
545 var sg: i64 = 1
546 while sg < 6 {
547 if sg != 4 {
548 let sp9: *u8 = sys_mmap(512)
549 ss_segname(prefix, sg, 0, sp9)
550 let sfd9: i64 = sys_openat_rd(sp9)
551 if sfd9 < 0 { ok = 0 }
552 if sfd9 >= 0 { sys_close(sfd9) }
553 }
554 sg = sg + 1
555 }
556 ig_report(logfd, "compaction-archive" as *u8, ok)
557 passed = passed + ok
558
559 // ---- archive-time-travel (IM-AR): FULL history readable AFTER the fold ----
560 // ss_scan_all = archived segments (srcs=0, chronological) then live (srcs=1).
561 // Post-compaction expectations derive from the proven fixture history:
562 // cap:diora -> 3 rows: archived v1=encA, archived v2=encB, live fold-copy
563 // =encB (pre-fold history BYTE-EXACT = nothing destroyed)
564 // cap:search -> 3 rows: archived put=encB, archived TOMBSTONE, live
565 // TOMBSTONE (deletes preserved in history)
566 // cap:fsync -> 2 rows: archived encA, live encA
567 // cap:ghost -> 0 rows (crash-written temp never entered ANY manifest)
568 ok = 1
569 let wsrc: *i64 = sys_mmap(8 * 260) as *i64
570 let na1: i64 = ss_scan_all(prefix, "cap:diora" as *u8, kinds, ptrs, lens, wsrc)
571 if na1 != 3 { ok = 0 }
572 if ok == 1 {
573 if kinds[0] != 1 { ok = 0 }
574 if lens[0] != lenA { ok = 0 }
575 if ok == 1 { if ig_memeq(ptrs[0] as *u8, encA, lenA) == 0 { ok = 0 } }
576 if kinds[1] != 1 { ok = 0 }
577 if lens[1] != lenB { ok = 0 }
578 if ok == 1 { if ig_memeq(ptrs[1] as *u8, encB, lenB) == 0 { ok = 0 } }
579 if kinds[2] != 1 { ok = 0 }
580 if lens[2] != lenB { ok = 0 }
581 if ok == 1 { if ig_memeq(ptrs[2] as *u8, encB, lenB) == 0 { ok = 0 } }
582 if wsrc[0] != 0 { ok = 0 }
583 if wsrc[1] != 0 { ok = 0 }
584 if wsrc[2] != 1 { ok = 0 }
585 }
586 let na2: i64 = ss_scan_all(prefix, "cap:search" as *u8, kinds, ptrs, lens, wsrc)
587 if na2 != 3 { ok = 0 }
588 if ok == 1 {
589 if kinds[0] != 1 { ok = 0 }
590 if lens[0] != lenB { ok = 0 }
591 if ok == 1 { if ig_memeq(ptrs[0] as *u8, encB, lenB) == 0 { ok = 0 } }
592 if kinds[1] != 2 { ok = 0 }
593 if kinds[2] != 2 { ok = 0 }
594 if wsrc[1] != 0 { ok = 0 }
595 if wsrc[2] != 1 { ok = 0 }
596 }
597 let na3: i64 = ss_scan_all(prefix, "cap:fsync" as *u8, kinds, ptrs, lens, wsrc)
598 if na3 != 2 { ok = 0 }
599 if ok == 1 {
600 if lens[0] != lenA { ok = 0 }
601 if lens[1] != lenA { ok = 0 }
602 if ig_memeq(ptrs[0] as *u8, encA, lenA) == 0 { ok = 0 }
603 if ig_memeq(ptrs[1] as *u8, encA, lenA) == 0 { ok = 0 }
604 if wsrc[0] != 0 { ok = 0 }
605 if wsrc[1] != 1 { ok = 0 }
606 }
607 if ss_scan_all(prefix, "cap:ghost" as *u8, kinds, ptrs, lens, wsrc) != 0 { ok = 0 }
608 ig_report(logfd, "archive-time-travel" as *u8, ok)
609 passed = passed + ok
610
611 // ---- postings-scale-bulk: a 4097-doc segment commits AND is searchable ----
612 // 4097 docs exceeds the OLD fixed 4096 docs/segment cap (which silently
613 // emitted uninitialized doc offsets and dropped terms/pairs = silent
614 // search misses). Capacities are now DATA-DRIVEN from the writer size:
615 // the bulk commit must SUCCEED, term search must count EXACTLY 4097
616 // (every doc, none silently dropped), keyed reads of first/last bulk doc
617 // and the prior store must answer byte-exact.
618 ok = 0
619 let wbig: *i64 = ss_begin()
620 let kb9: *u8 = sys_mmap(64)
621 var bi: i64 = 0
622 var addrc: i64 = 0
623 while bi < 4097 {
624 var ko9: i64 = 0
625 ko9 = ss_cat(kb9, ko9, "bulk:" as *u8)
626 ko9 = ss_catn(kb9, ko9, bi)
627 kb9[ko9] = 0 as u8
628 if ss_add(wbig, 1, kb9, "vv bulkdoc" as *u8, 10) != 0 { addrc = 1 }
629 bi = bi + 1
630 }
631 let crc: i64 = ss_commit(prefix, wbig, 7777)
632 if addrc == 0 { if crc == 0 {
633 let ms9: i64 = ss_manifest(prefix, segs)
634 if ms9 == 2 {
635 let hb: *i64 = ss_open(prefix)
636 let bkp: *i64 = sys_mmap(8 * 4200) as *i64
637 let bkl: *i64 = sys_mmap(8 * 4200) as *i64
638 let nvv: i64 = ss_term(hb, "bulkdoc" as *u8, bkp, bkl, 4200)
639 if nvv == 4097 {
640 let gf1: i64 = ss_hget(hb, "bulk:0" as *u8, pp3, ll3)
641 let gf2: i64 = ss_hget(hb, "bulk:4096" as *u8, pp3, ll3)
642 if gf1 == 1 { if gf2 == 1 { if ll3[0] == 10 {
643 let g10: i64 = ss_get(prefix, "cap:diora" as *u8, pp, ll)
644 if g10 == 1 { if ig_memeq(pp[0] as *u8, encB, lenB) == 1 { ok = 1 } }
645 } } }
646 }
647 }
648 } }
649 ig_report(logfd, "postings-scale-bulk" as *u8, ok)
650 passed = passed + ok
651
652 let permil: i64 = (passed * 1000) / IG_ROWS
653 var fdi: i64 = 0
654 while fdi < 2 {
655 var fd: i64 = 1
656 if fdi == 1 { fd = logfd }
657 if fd > 0 {
658 ig_fp(fd, "INFOMGMT-GATE rows=" as *u8)
659 ig_fn(fd, IG_ROWS)
660 ig_fp(fd, " passed=" as *u8)
661 ig_fn(fd, passed)
662 ig_fp(fd, " permil=" as *u8)
663 ig_fn(fd, permil)
664 if passed == IG_ROWS { ig_fp(fd, " verdict=GREEN\n" as *u8) }
665 if passed != IG_ROWS { ig_fp(fd, " verdict=RED\n" as *u8) }
666 }
667 fdi = fdi + 1
668 }
669 if logfd > 0 { sys_close(logfd) }
670 if passed == IG_ROWS { return 0 }
671 return 1
672}