code wiki / (root) / nx_asset_search_gate.nx

nx_asset_search_gate.nx source

↩ module page · 137 lines · 7759 B

1// nx_asset_search_gate.nx -- KAT + TEETH for nx_asset_search (faceted findability over the catalog). 2// 3// Ingests 4 known records into a fresh catalog then proves the facet filters return EXACTLY the right 4// sets (and the right CIDs): 5// A image / professional / tags="gallery,generated" 6// B image / private / tags="gallery,private" 7// C doc / professional / tags="wiki,doctrine" 8// D video / professional / tags="clip" 9// (a) by type=image -> 2 (b) by type=doc -> 1 (c) by type=video -> 1 10// (d) by classification=private -> 1 (e) by classification=professional -> 3 11// (f) by tag=gallery -> 2 (g) by tag=doctrine -> 1 12// (h) membership: the type=doc result actually contains C's CID 13// TEETH (must be empty): (i) type=audio -> 0 (j) tag=nonexistent -> 0 14// 15// Verdict appended to knowledge/status/asset_search_gate.log (additive law #13). 16// expect_exit: 0 license_tier: ORIGINAL 17import "nx_syscalls.nx" 18import "nx_canon_cid.nx" 19import "nx_asset_record.nx" 20import "nx_asset_catalog.nx" 21import "nx_asset_search.nx" 22import "nx_gate_verdict.nx" 23 24func g_puts(logfd: i64, s: *u8) -> i64 { 25 var n: i64 = 0 26 while s[n] != (0 as u8) { n = n + 1 } 27 sys_write(1, s, n) 28 if logfd > 0 { sys_write(logfd, s, n) } 29 return 0 30} 31func g_putn(logfd: i64, v: i64) -> i64 { 32 let bb: *u8 = sys_mmap(28) 33 var m: i64 = v 34 if m < 0 { g_puts(logfd, "-\x00" as *u8); m = 0 - m } 35 let t: *u8 = sys_mmap(28) 36 var k: i64 = 0 37 if m == 0 { t[0] = 48 as u8; k = 1 } 38 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 39 var i: i64 = 0 40 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 41 sys_write(1, bb, k) 42 if logfd > 0 { sys_write(logfd, bb, k) } 43 return 0 44} 45func E() -> *u8 { return "\x00" as *u8 } 46func sset(a: *i64, i: i64, s: *u8) -> i64 { a[i] = s as i64; return 0 } 47 48// build an asset record: type / classification / tags / id (others empty). returns byte length. 49func mk_asset(typ: *u8, cls: *u8, tags: *u8, id: *u8, out: *u8) -> i64 { 50 let core: *i64 = sys_mmap(8 * 8) as *i64 51 sset(core, 0, typ); sset(core, 1, "Asset\x00" as *u8); sset(core, 2, E()) 52 sset(core, 3, "2026-06-20\x00" as *u8); sset(core, 4, id); sset(core, 5, E()); sset(core, 6, E()) 53 let pz: *i64 = sys_mmap(8 * 8) as *i64 54 sset(pz, 0, E()); sset(pz, 1, E()); sset(pz, 2, E()); sset(pz, 3, E()); sset(pz, 4, E()); sset(pz, 5, E()) 55 let mz: *i64 = sys_mmap(8 * 8) as *i64 56 sset(mz, 0, E()); sset(mz, 1, E()); sset(mz, 2, E()); sset(mz, 3, E()) 57 let oz: *i64 = sys_mmap(8 * 8) as *i64 58 sset(oz, 0, tags); sset(oz, 1, E()); sset(oz, 2, E()); sset(oz, 3, "1\x00" as *u8); sset(oz, 4, cls); sset(oz, 5, E()) 59 let keys: *i64 = sys_mmap(8 * 48) as *i64 60 let vals: *i64 = sys_mmap(8 * 48) as *i64 61 let n: i64 = ar_fields(core, pz, mz, oz, keys, vals) 62 return ar_encode(keys, vals, n, out) 63} 64 65func gt_prefix(prefix: *u8, base: *u8) -> i64 { 66 var po: i64 = 0 67 while base[po] != (0 as u8) { prefix[po] = base[po]; po = po + 1 } 68 var m: i64 = sys_now_ms() 69 let ds: *u8 = sys_mmap(28) 70 var k: i64 = 0 71 if m == 0 { ds[0] = 48 as u8; k = 1 } 72 while m > 0 { ds[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 73 var j: i64 = 0 74 while j < k { prefix[po] = ds[k - 1 - j]; po = po + 1; j = j + 1 } 75 prefix[po] = 45 as u8; po = po + 1 76 prefix[po] = 0 as u8 77 return po 78} 79 80func expect_count(logfd: i64, label: *u8, got: i64, want: i64) -> i64 { 81 g_puts(logfd, label); g_puts(logfd, " got=\x00" as *u8); g_putn(logfd, got); g_puts(logfd, " want=\x00" as *u8); g_putn(logfd, want); g_puts(logfd, ": \x00" as *u8) 82 if got == want { g_puts(logfd, "PASS\n\x00" as *u8); return 1 } 83 g_puts(logfd, "FAIL\n\x00" as *u8); return 0 84} 85 86func main() -> i64 { 87 let logfd: i64 = sys_openat_append("knowledge/status/asset_search_gate.log\x00" as *u8, 0x1a4) 88 g_puts(logfd, "=== ASSET-SEARCH-GATE (faceted findability over the catalog) ===\n\x00" as *u8) 89 90 let prefix: *u8 = sys_mmap(256); gt_prefix(prefix, "/tmp/assrch-\x00" as *u8) 91 let rA: *u8 = sys_mmap(8192); let nA: i64 = mk_asset("image\x00" as *u8, "professional\x00" as *u8, "gallery,generated\x00" as *u8, "s-a\x00" as *u8, rA) 92 let rB: *u8 = sys_mmap(8192); let nB: i64 = mk_asset("image\x00" as *u8, "private\x00" as *u8, "gallery,private\x00" as *u8, "s-b\x00" as *u8, rB) 93 let rC: *u8 = sys_mmap(8192); let nC: i64 = mk_asset("doc\x00" as *u8, "professional\x00" as *u8, "wiki,doctrine\x00" as *u8, "s-c\x00" as *u8, rC) 94 let rD: *u8 = sys_mmap(8192); let nD: i64 = mk_asset("video\x00" as *u8, "professional\x00" as *u8, "clip\x00" as *u8, "s-d\x00" as *u8, rD) 95 96 let st: *i64 = sys_mmap(16) as *i64 97 let cidC: *u8 = sys_mmap(128) 98 let junk: *u8 = sys_mmap(128) 99 cat_ingest_cid(prefix, rA, nA, junk, st) 100 cat_ingest_cid(prefix, rB, nB, junk, st) 101 cat_ingest_cid(prefix, rC, nC, cidC, st) 102 cat_ingest_cid(prefix, rD, nD, junk, st) 103 g_puts(logfd, " ingested 4 records, catalog count=\x00" as *u8); g_putn(logfd, cat_count(prefix)); g_puts(logfd, "\n\x00" as *u8) 104 105 let out: *i64 = sys_mmap(8 * 64) as *i64 106 var pass: i64 = 0 107 var total: i64 = 0 108 109 total = total + 1; pass = pass + expect_count(logfd, " (a) type=image\x00" as *u8, as_by_field(prefix, "type\x00" as *u8, "image\x00" as *u8, out, 64), 2) 110 total = total + 1; pass = pass + expect_count(logfd, " (b) type=doc\x00" as *u8, as_by_field(prefix, "type\x00" as *u8, "doc\x00" as *u8, out, 64), 1) 111 total = total + 1; pass = pass + expect_count(logfd, " (c) type=video\x00" as *u8, as_by_field(prefix, "type\x00" as *u8, "video\x00" as *u8, out, 64), 1) 112 total = total + 1; pass = pass + expect_count(logfd, " (d) classification=private\x00" as *u8, as_by_field(prefix, "classification\x00" as *u8, "private\x00" as *u8, out, 64), 1) 113 total = total + 1; pass = pass + expect_count(logfd, " (e) classification=professional\x00" as *u8, as_by_field(prefix, "classification\x00" as *u8, "professional\x00" as *u8, out, 64), 3) 114 total = total + 1; pass = pass + expect_count(logfd, " (f) tag=gallery\x00" as *u8, as_by_tag(prefix, "gallery\x00" as *u8, out, 64), 2) 115 total = total + 1; pass = pass + expect_count(logfd, " (g) tag=doctrine\x00" as *u8, as_by_tag(prefix, "doctrine\x00" as *u8, out, 64), 1) 116 117 // (h) membership: the type=doc result actually contains C's CID 118 let ndoc: i64 = as_by_field(prefix, "type\x00" as *u8, "doc\x00" as *u8, out, 64) 119 var memok: i64 = 0 120 if cat_idx_has(out, ndoc, cidC) == 1 { memok = 1 } 121 total = total + 1; pass = pass + expect_count(logfd, " (h) doc result contains C's CID\x00" as *u8, memok, 1) 122 123 // TEETH: empty results for absent facets (no false matches) 124 total = total + 1; pass = pass + expect_count(logfd, " (i TEETH) type=audio (none)\x00" as *u8, as_by_field(prefix, "type\x00" as *u8, "audio\x00" as *u8, out, 64), 0) 125 total = total + 1; pass = pass + expect_count(logfd, " (j TEETH) tag=nonexistent (none)\x00" as *u8, as_by_tag(prefix, "nonexistent\x00" as *u8, out, 64), 0) 126 127 g_puts(logfd, "ASSET-SEARCH-GATE passed \x00" as *u8); g_putn(logfd, pass); g_puts(logfd, "/\x00" as *u8); g_putn(logfd, total) 128 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 129 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 130 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 131 let ctr__dry: *i64 = gv_ctr() 132 ctr__dry[0] = pass 133 ctr__dry[1] = total 134 let rc__dry: i64 = gv_verdict("ASSET-SEARCH-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 135 sys_exit(rc__dry) 136 return rc__dry 137}