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}