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