nx_asset_signals_gate.nx source
↩ module page · 412 lines · 22171 B
1// nx_asset_signals_gate.nx -- KAT + TEETH for nx_asset_signals (R4 "what we need to do" pillar).
2//
3// Builds a FIXTURE catalog with KNOWN issues and proves the EXACT task signals are derived, that a
4// fully-clean record yields ZERO signals (TEETH: no false positives), and that the derived signals can
5// be EMITTED to a DEDICATED namespace and READ BACK (emission is verifiable end-to-end):
6//
7// record1 image, width+height present, has relations, is_current=1, HAS a phash, NO credential,
8// tags EMPTY -> EXPECT exactly { MISSING_PROVENANCE, UNTAGGED }
9// record2 image, width/height ABSENT, tagged, valid credential, has relations, is_current=1
10// -> EXPECT exactly { MISSING_METADATA }
11// record3 image, full metadata, tagged, valid credential, has relations, is_current=1, phash = P
12// record4 image, full metadata, tagged, valid credential, has relations, is_current=1, phash = P
13// (record3 & record4 share an IDENTICAL perceptual fingerprint = a near-dup pair)
14// -> EXPECT exactly { NEAR_DUP } for EACH of record3, record4
15// record5 image, full metadata, tagged, valid credential, has relations, is_current=1, UNIQUE phash
16// -> EXPECT ZERO signals (the TEETH: a clean record triggers nothing)
17//
18// Assertions:
19// (a) every EXPECTED (cid, code) signal is present in as_scan's output
20// (b) NO UNEXPECTED signal exists (exact-set: total derived count == expected count)
21// (c) record5 contributes ZERO signals (clean-record teeth, checked explicitly by cid)
22// (d) as_emit writes them into the DEDICATED asset-signals namespace and as_list reads them ALL back,
23// and as_get on one key returns its TAB record with the right signal_code+cid fields (verifiable)
24// (e) ISOLATION: the production board store (knowledge/store/ws-) is NEVER touched (the gate uses a
25// fresh /tmp catalog AND the dedicated namespace prefix is a different store by construction).
26//
27// Verdict appended to knowledge/status/asset_signals_gate.log (additive law #13).
28// expect_exit: 0 license_tier: ORIGINAL
29import "nx_syscalls.nx"
30import "nx_canon_cid.nx"
31import "nx_seg_store.nx"
32import "nx_ed25519_signature.nx"
33import "nx_asset_record.nx"
34import "nx_asset_catalog.nx"
35import "nx_asset_provenance.nx"
36import "nx_asset_autotag.nx"
37import "nx_asset_signals.nx"
38import "nx_gate_verdict.nx"
39
40// ---- gate IO (logfd threaded as a parameter -- no module-level mutable var; matches the R1 gate) ----
41func g_puts(logfd: i64, s: *u8) -> i64 {
42 var n: i64 = 0
43 while s[n] != (0 as u8) { n = n + 1 }
44 sys_write(1, s, n)
45 if logfd > 0 { sys_write(logfd, s, n) }
46 return 0
47}
48func g_putn(logfd: i64, v: i64) -> i64 {
49 let bb: *u8 = sys_mmap(28)
50 var m: i64 = v
51 if m < 0 { g_puts(logfd, "-\x00" as *u8); m = 0 - m }
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(1, bb, k)
59 if logfd > 0 { sys_write(logfd, bb, k) }
60 return 0
61}
62func g_streq(a: *u8, b: *u8) -> i64 {
63 var i: i64 = 0
64 while 1 == 1 {
65 if a[i] != b[i] { return 0 }
66 if a[i] == (0 as u8) { return 1 }
67 i = i + 1
68 }
69 return 1
70}
71
72func E() -> *u8 { return "\x00" as *u8 }
73func sset(a: *i64, i: i64, s: *u8) -> i64 { a[i] = s as i64; return 0 }
74
75// append src at dst[off] (NUL-terminated result), returns new offset.
76func g_cat(dst: *u8, off: i64, src: *u8) -> i64 {
77 var i: i64 = 0
78 while src[i] != (0 as u8) { dst[off + i] = src[i]; i = i + 1 }
79 dst[off + i] = 0 as u8
80 return off + i
81}
82
83// build a record from grouped core/prov/media/org arrays -> canonical bytes into out; returns length.
84func mk_rec(core: *i64, prov: *i64, media: *i64, org: *i64, out: *u8) -> i64 {
85 let keys: *i64 = sys_mmap(8 * 48) as *i64
86 let vals: *i64 = sys_mmap(8 * 48) as *i64
87 let n: i64 = ar_fields(core, prov, media, org, keys, vals)
88 return ar_encode(keys, vals, n, out)
89}
90
91// fresh unique store prefix "<base><stamp>-" so each run is clean + idempotent (matches the R1 gate).
92func mk_prefix(prefix: *u8, base: *u8, salt: i64) -> i64 {
93 var po: i64 = 0
94 while base[po] != (0 as u8) { prefix[po] = base[po]; po = po + 1 }
95 var m: i64 = sys_now_ms() + salt
96 let ds: *u8 = sys_mmap(28)
97 var k: i64 = 0
98 if m == 0 { ds[0] = 48 as u8; k = 1 }
99 while m > 0 { ds[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
100 var j: i64 = 0
101 while j < k { prefix[po] = ds[k - 1 - j]; po = po + 1; j = j + 1 }
102 prefix[po] = 45 as u8; po = po + 1 // '-'
103 prefix[po] = 0 as u8
104 return po
105}
106
107// search the signal table for a (cid, code) pair -> 1 present / 0 absent.
108func sig_has(out_signals: *i64, cap: i64, count: i64, cid: *u8, code: *u8) -> i64 {
109 var k: i64 = 0
110 while k < count {
111 if g_streq(as_sig_cid(out_signals, cap, k), cid) == 1 {
112 if g_streq(as_sig_code(out_signals, cap, k), code) == 1 { return 1 }
113 }
114 k = k + 1
115 }
116 return 0
117}
118// count how many signals in the table belong to a given cid.
119func sig_count_for(out_signals: *i64, cap: i64, count: i64, cid: *u8) -> i64 {
120 var c: i64 = 0
121 var k: i64 = 0
122 while k < count {
123 if g_streq(as_sig_cid(out_signals, cap, k), cid) == 1 { c = c + 1 }
124 k = k + 1
125 }
126 return c
127}
128
129// fill an n-byte grayscale buffer with a deterministic gradient seeded by `seed` (distinct seeds ->
130// visually distinct images -> distinct dHashes; identical seeds -> identical pixels -> identical dHash).
131func fill_gray(buf: *u8, w: i64, h: i64, seed: i64) -> i64 {
132 var y: i64 = 0
133 while y < h {
134 var x: i64 = 0
135 while x < w {
136 buf[y * w + x] = ((x * 13 + y * 7 + seed * 53) % 256) as u8
137 x = x + 1
138 }
139 y = y + 1
140 }
141 return 0
142}
143
144func main() -> i64 {
145 let logfd: i64 = sys_openat_append("knowledge/status/asset_signals_gate.log\x00" as *u8, 0x1a4)
146 g_puts(logfd, "=== ASSET-SIGNALS-GATE (R4: task signals derived from catalog state + emit to WMS namespace) ===\n\x00" as *u8)
147
148 var pass: i64 = 0
149 var total: i64 = 0
150
151 let prefix: *u8 = sys_mmap(256)
152 mk_prefix(prefix, "/tmp/sig-\x00" as *u8, 0)
153 g_puts(logfd, " catalog prefix=\x00" as *u8); g_puts(logfd, prefix); g_puts(logfd, "\n\x00" as *u8)
154 g_puts(logfd, " signals namespace=\x00" as *u8); g_puts(logfd, AS_PREFIX()); g_puts(logfd, " (DEDICATED; production board knowledge/store/ws- untouched)\n\x00" as *u8)
155
156 // shared empty prov/media/org buffers for fixtures that omit a group.
157 let pz: *i64 = sys_mmap(8 * 8) as *i64
158 sset(pz, 0, E()); sset(pz, 1, E()); sset(pz, 2, E()); sset(pz, 3, E()); sset(pz, 4, E()); sset(pz, 5, E())
159
160 // ============================================================================================
161 // record1: image, width+height present (so NOT missing-metadata), has relations, is_current=1,
162 // tags EMPTY (untagged), NO credential (missing-provenance). Expect { MISSING_PROVENANCE, UNTAGGED }.
163 let core1: *i64 = sys_mmap(8 * 8) as *i64
164 sset(core1, 0, "image\x00" as *u8); sset(core1, 1, "Rec one\x00" as *u8)
165 sset(core1, 2, E()); sset(core1, 3, E()); sset(core1, 4, "id-1\x00" as *u8); sset(core1, 5, E()); sset(core1, 6, E())
166 let med1: *i64 = sys_mmap(8 * 8) as *i64
167 sset(med1, 0, "800\x00" as *u8); sset(med1, 1, "600\x00" as *u8); sset(med1, 2, E()); sset(med1, 3, "image/png\x00" as *u8)
168 let org1: *i64 = sys_mmap(8 * 8) as *i64
169 sset(org1, 0, E()); sset(org1, 1, E()); sset(org1, 2, "manage\x00" as *u8) // tags EMPTY
170 sset(org1, 3, "1\x00" as *u8); sset(org1, 4, E()); sset(org1, 5, "nxc1-deadbeef\x00" as *u8) // is_current=1, relations present
171 let rec1: *u8 = sys_mmap(8192)
172 let len1: i64 = mk_rec(core1, pz, med1, org1, rec1)
173
174 // record2: image, width/height ABSENT (missing-metadata), tagged, valid cred, relations, is_current=1.
175 let core2: *i64 = sys_mmap(8 * 8) as *i64
176 sset(core2, 0, "image\x00" as *u8); sset(core2, 1, "Rec two\x00" as *u8)
177 sset(core2, 2, E()); sset(core2, 3, E()); sset(core2, 4, "id-2\x00" as *u8); sset(core2, 5, E()); sset(core2, 6, E())
178 let med2: *i64 = sys_mmap(8 * 8) as *i64
179 sset(med2, 0, E()); sset(med2, 1, E()); sset(med2, 2, E()); sset(med2, 3, "image/png\x00" as *u8) // NO width/height
180 let org2: *i64 = sys_mmap(8 * 8) as *i64
181 sset(org2, 0, "sunset,beach\x00" as *u8); sset(org2, 1, E()); sset(org2, 2, "manage\x00" as *u8)
182 sset(org2, 3, "1\x00" as *u8); sset(org2, 4, E()); sset(org2, 5, "nxc1-deadbeef\x00" as *u8)
183 let rec2: *u8 = sys_mmap(8192)
184 let len2: i64 = mk_rec(core2, pz, med2, org2, rec2)
185
186 // record3 & record4: image, FULL metadata, tagged, valid cred, relations, is_current=1. CLEAN on
187 // every field-predicate -> the ONLY signal they can earn is NEAR_DUP (from an identical phash).
188 let core3: *i64 = sys_mmap(8 * 8) as *i64
189 sset(core3, 0, "image\x00" as *u8); sset(core3, 1, "Rec three\x00" as *u8)
190 sset(core3, 2, E()); sset(core3, 3, E()); sset(core3, 4, "id-3\x00" as *u8); sset(core3, 5, E()); sset(core3, 6, E())
191 let med3: *i64 = sys_mmap(8 * 8) as *i64
192 sset(med3, 0, "1024\x00" as *u8); sset(med3, 1, "768\x00" as *u8); sset(med3, 2, E()); sset(med3, 3, "image/png\x00" as *u8)
193 let org3: *i64 = sys_mmap(8 * 8) as *i64
194 sset(org3, 0, "dup\x00" as *u8); sset(org3, 1, E()); sset(org3, 2, "manage\x00" as *u8)
195 sset(org3, 3, "1\x00" as *u8); sset(org3, 4, E()); sset(org3, 5, "nxc1-deadbeef\x00" as *u8)
196 let rec3: *u8 = sys_mmap(8192)
197 let len3: i64 = mk_rec(core3, pz, med3, org3, rec3)
198
199 let core4: *i64 = sys_mmap(8 * 8) as *i64
200 sset(core4, 0, "image\x00" as *u8); sset(core4, 1, "Rec four\x00" as *u8)
201 sset(core4, 2, E()); sset(core4, 3, E()); sset(core4, 4, "id-4\x00" as *u8); sset(core4, 5, E()); sset(core4, 6, E())
202 let med4: *i64 = sys_mmap(8 * 8) as *i64
203 sset(med4, 0, "1024\x00" as *u8); sset(med4, 1, "768\x00" as *u8); sset(med4, 2, E()); sset(med4, 3, "image/png\x00" as *u8)
204 let org4: *i64 = sys_mmap(8 * 8) as *i64
205 sset(org4, 0, "dup\x00" as *u8); sset(org4, 1, E()); sset(org4, 2, "manage\x00" as *u8)
206 sset(org4, 3, "1\x00" as *u8); sset(org4, 4, E()); sset(org4, 5, "nxc1-deadbeef\x00" as *u8)
207 let rec4: *u8 = sys_mmap(8192)
208 let len4: i64 = mk_rec(core4, pz, med4, org4, rec4)
209
210 // record5: CLEAN on every axis + a UNIQUE phash -> EXPECT ZERO signals (the teeth).
211 let core5: *i64 = sys_mmap(8 * 8) as *i64
212 sset(core5, 0, "image\x00" as *u8); sset(core5, 1, "Rec five\x00" as *u8)
213 sset(core5, 2, E()); sset(core5, 3, E()); sset(core5, 4, "id-5\x00" as *u8); sset(core5, 5, E()); sset(core5, 6, E())
214 let med5: *i64 = sys_mmap(8 * 8) as *i64
215 sset(med5, 0, "1920\x00" as *u8); sset(med5, 1, "1080\x00" as *u8); sset(med5, 2, E()); sset(med5, 3, "image/png\x00" as *u8)
216 let org5: *i64 = sys_mmap(8 * 8) as *i64
217 sset(org5, 0, "clean\x00" as *u8); sset(org5, 1, E()); sset(org5, 2, "manage\x00" as *u8)
218 sset(org5, 3, "1\x00" as *u8); sset(org5, 4, E()); sset(org5, 5, "nxc1-deadbeef\x00" as *u8)
219 let rec5: *u8 = sys_mmap(8192)
220 let len5: i64 = mk_rec(core5, pz, med5, org5, rec5)
221
222 // ---- ingest all 5 into the catalog (cat_list order is the aux-array index order) ----
223 let st: *i64 = sys_mmap(16) as *i64
224 cat_ingest(prefix, rec1, len1, st)
225 cat_ingest(prefix, rec2, len2, st)
226 cat_ingest(prefix, rec3, len3, st)
227 cat_ingest(prefix, rec4, len4, st)
228 cat_ingest(prefix, rec5, len5, st)
229
230 // CIDs (the catalog keys; the signal table reports by CID).
231 let cid1: *u8 = sys_mmap(128); ar_cid(rec1, len1, cid1)
232 let cid2: *u8 = sys_mmap(128); ar_cid(rec2, len2, cid2)
233 let cid3: *u8 = sys_mmap(128); ar_cid(rec3, len3, cid3)
234 let cid4: *u8 = sys_mmap(128); ar_cid(rec4, len4, cid4)
235 let cid5: *u8 = sys_mmap(128); ar_cid(rec5, len5, cid5)
236
237 // ---- AUX 1: per-record perceptual phashes, indexed by cat_list order ----
238 // We must align aux[i] to the catalog's snapshot order, NOT our insertion order. Read cat_list,
239 // then for each listed cid pick the phash for the matching record (records 3 & 4 share P; 5 unique;
240 // 1 has its own; 2 has none -> 0). This keeps as_scan PURE over (snapshot, aux).
241 let gray: *u8 = sys_mmap(64 * 64)
242 fill_gray(gray, 32, 32, 1); let p1: i64 = at_phash(gray, 32, 32) // record1 fingerprint
243 fill_gray(gray, 32, 32, 99); let pDUP: i64 = at_phash(gray, 32, 32) // shared by record3+record4
244 fill_gray(gray, 32, 32, 200); let p5: i64 = at_phash(gray, 32, 32) // record5 unique
245
246 let lcap: i64 = 64
247 let lcids: *i64 = sys_mmap(8 * lcap) as *i64
248 let nlist: i64 = cat_list(prefix, lcids, lcap)
249 let phashes: *i64 = sys_mmap(8 * lcap) as *i64
250 let cred_ptr: *i64 = sys_mmap(8 * lcap) as *i64
251 let cred_len: *i64 = sys_mmap(8 * lcap) as *i64
252
253 // ---- AUX 2: mint REAL ed25519 provenance credentials (records 2,3,4,5); record1 gets NONE ----
254 let priv: *u8 = sys_mmap(32)
255 var z: i64 = 0
256 while z < 32 { priv[z] = (z + 7) as u8; z = z + 1 } // deterministic test secret
257 let pub: *u8 = sys_mmap(32)
258 ed25519_pub_from_priv(priv, pub)
259
260 // build+sign one credential bound to `cid` -> (ptr,len). class human, agent test.
261 // (we use the human class so no tool/model/source needed; entity binds it to the record.)
262 var li: i64 = 0
263 while li < nlist {
264 let c: *u8 = lcids[li] as *u8
265 // default: no phash, no credential.
266 phashes[li] = 0
267 cred_ptr[li] = 0
268 cred_len[li] = 0
269 // phash assignment by identity
270 if g_streq(c, cid1) == 1 { phashes[li] = p1 }
271 if g_streq(c, cid3) == 1 { phashes[li] = pDUP }
272 if g_streq(c, cid4) == 1 { phashes[li] = pDUP }
273 if g_streq(c, cid5) == 1 { phashes[li] = p5 }
274 // credential for everyone EXCEPT record1 (which must read MISSING_PROVENANCE)
275 var wantcred: i64 = 1
276 if g_streq(c, cid1) == 1 { wantcred = 0 }
277 if wantcred == 1 {
278 let assertion: *u8 = sys_mmap(4096)
279 let an: i64 = prov_make(c, prov_class_human(), "tester\x00" as *u8, E(), E(), E(), E(), assertion)
280 let cred: *u8 = sys_mmap(an + 256)
281 let cn: i64 = prov_sign(assertion, an, priv, cred)
282 cred_ptr[li] = cred as i64
283 cred_len[li] = cn
284 }
285 li = li + 1
286 }
287
288 // ============================================================================================
289 // RUN as_scan over the snapshot + aux.
290 let cap: i64 = 256
291 let out_signals: *i64 = sys_mmap(8 * 3 * cap) as *i64
292 let nsig: i64 = as_scan(prefix, phashes, cred_ptr, cred_len, pub, out_signals, cap)
293 g_puts(logfd, " as_scan derived \x00" as *u8); g_putn(logfd, nsig); g_puts(logfd, " signals from \x00" as *u8); g_putn(logfd, nlist); g_puts(logfd, " records\n\x00" as *u8)
294 // dump every derived signal (RAW evidence)
295 var dd: i64 = 0
296 while dd < nsig {
297 g_puts(logfd, " SIG \x00" as *u8); g_puts(logfd, as_sig_code(out_signals, cap, dd))
298 g_puts(logfd, " cid=\x00" as *u8); g_puts(logfd, as_sig_cid(out_signals, cap, dd)); g_puts(logfd, "\n\x00" as *u8)
299 dd = dd + 1
300 }
301
302 // (a) record1 -> exactly { MISSING_PROVENANCE, UNTAGGED }
303 total = total + 1
304 g_puts(logfd, " (a) record1 == {MISSING_PROVENANCE,UNTAGGED} exactly: \x00" as *u8)
305 var a_ok: i64 = 1
306 if sig_has(out_signals, cap, nsig, cid1, SIG_MISSING_PROVENANCE()) == 0 { a_ok = 0 }
307 if sig_has(out_signals, cap, nsig, cid1, SIG_UNTAGGED()) == 0 { a_ok = 0 }
308 if sig_count_for(out_signals, cap, nsig, cid1) != 2 { a_ok = 0 }
309 if a_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
310
311 // (b) record2 -> exactly { MISSING_METADATA }
312 total = total + 1
313 g_puts(logfd, " (b) record2 == {MISSING_METADATA} exactly: \x00" as *u8)
314 var b_ok: i64 = 1
315 if sig_has(out_signals, cap, nsig, cid2, SIG_MISSING_METADATA()) == 0 { b_ok = 0 }
316 if sig_count_for(out_signals, cap, nsig, cid2) != 1 { b_ok = 0 }
317 if b_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
318
319 // (c) record3 & record4 -> each exactly { NEAR_DUP }
320 total = total + 1
321 g_puts(logfd, " (c) record3 & record4 == {NEAR_DUP} each exactly: \x00" as *u8)
322 var c_ok: i64 = 1
323 if sig_has(out_signals, cap, nsig, cid3, SIG_NEAR_DUP()) == 0 { c_ok = 0 }
324 if sig_has(out_signals, cap, nsig, cid4, SIG_NEAR_DUP()) == 0 { c_ok = 0 }
325 if sig_count_for(out_signals, cap, nsig, cid3) != 1 { c_ok = 0 }
326 if sig_count_for(out_signals, cap, nsig, cid4) != 1 { c_ok = 0 }
327 if c_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
328
329 // (d) TEETH: record5 (fully clean) -> ZERO signals.
330 total = total + 1
331 let n5: i64 = sig_count_for(out_signals, cap, nsig, cid5)
332 g_puts(logfd, " (d) TEETH record5 clean -> ZERO signals (got \x00" as *u8); g_putn(logfd, n5); g_puts(logfd, "): \x00" as *u8)
333 if n5 == 0 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
334
335 // (e) EXACT-SET: total derived == 2 + 1 + 1 + 1 + 0 == 5 (no extra false positives anywhere).
336 total = total + 1
337 g_puts(logfd, " (e) exact total signal count == 5 (got \x00" as *u8); g_putn(logfd, nsig); g_puts(logfd, "): \x00" as *u8)
338 if nsig == 5 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
339
340 // ============================================================================================
341 // (f) EMISSION: as_emit -> dedicated namespace; as_list reads ALL back; as_get returns a TAB record.
342 let wrote: i64 = as_emit(out_signals, cap, nsig)
343 g_puts(logfd, " as_emit wrote \x00" as *u8); g_putn(logfd, wrote); g_puts(logfd, " work items to \x00" as *u8); g_puts(logfd, AS_PREFIX()); g_puts(logfd, "\n\x00" as *u8)
344 let keys: *i64 = sys_mmap(8 * 64) as *i64
345 let nkeys: i64 = as_list(keys, 64)
346 g_puts(logfd, " as_list read back \x00" as *u8); g_putn(logfd, nkeys); g_puts(logfd, " work-item keys:\n\x00" as *u8)
347 var kk: i64 = 0
348 while kk < nkeys {
349 g_puts(logfd, " KEY \x00" as *u8); g_puts(logfd, keys[kk] as *u8); g_puts(logfd, "\n\x00" as *u8)
350 kk = kk + 1
351 }
352 total = total + 1
353 g_puts(logfd, " (f) as_emit wrote 5 && as_list read back 5: \x00" as *u8)
354 var f_ok: i64 = 1
355 if wrote != 5 { f_ok = 0 }
356 if nkeys != 5 { f_ok = 0 }
357 if f_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
358
359 // (g) READBACK FIDELITY: as_get one known key ("sig:<cid2>:MISSING_METADATA") and check fields.
360 let qkey: *u8 = sys_mmap(256)
361 var qo: i64 = g_cat(qkey, 0, "sig:\x00" as *u8)
362 qo = g_cat(qkey, qo, cid2)
363 qo = g_cat(qkey, qo, ":\x00" as *u8)
364 qo = g_cat(qkey, qo, SIG_MISSING_METADATA())
365 let gp: *i64 = sys_mmap(16) as *i64
366 let gl: *i64 = sys_mmap(16) as *i64
367 let gr: i64 = as_get(qkey, gp, gl)
368 let f0: *u8 = sys_mmap(64) // field 0 = signal_code
369 let f1: *u8 = sys_mmap(128) // field 1 = cid
370 let f3: *u8 = sys_mmap(32) // field 3 = state
371 if gr == 1 {
372 as_field(gp[0] as *u8, gl[0], 0, f0)
373 as_field(gp[0] as *u8, gl[0], 1, f1)
374 as_field(gp[0] as *u8, gl[0], 3, f3)
375 }
376 g_puts(logfd, " as_get(\x00" as *u8); g_puts(logfd, qkey); g_puts(logfd, ") rc=\x00" as *u8); g_putn(logfd, gr)
377 g_puts(logfd, " field0=\x00" as *u8); g_puts(logfd, f0); g_puts(logfd, " field1=\x00" as *u8); g_puts(logfd, f1)
378 g_puts(logfd, " field3=\x00" as *u8); g_puts(logfd, f3); g_puts(logfd, "\n\x00" as *u8)
379 total = total + 1
380 g_puts(logfd, " (g) as_get readback fields match (code=MISSING_METADATA cid=cid2 state=ACTIVE): \x00" as *u8)
381 var g_ok: i64 = 1
382 if gr != 1 { g_ok = 0 }
383 if g_streq(f0, SIG_MISSING_METADATA()) == 0 { g_ok = 0 }
384 if g_streq(f1, cid2) == 0 { g_ok = 0 }
385 if g_streq(f3, "ACTIVE\x00" as *u8) == 0 { g_ok = 0 }
386 if g_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
387
388 // (h) IDEMPOTENT emit: re-emit the same signals -> as_list count STAYS 5 (no duplicate work items).
389 as_emit(out_signals, cap, nsig)
390 let nkeys2: i64 = as_list(keys, 64)
391 total = total + 1
392 g_puts(logfd, " (h) re-emit idempotent -> as_list STAYS 5 (got \x00" as *u8); g_putn(logfd, nkeys2); g_puts(logfd, "): \x00" as *u8)
393 if nkeys2 == 5 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
394
395 // (i) ISOLATION teeth: the PRODUCTION board prefix is a different store; assert AS_PREFIX != WS prefix
396 // by byte-compare, and that the live board prefix is never used by this organ.
397 total = total + 1
398 g_puts(logfd, " (i) ISOLATION: signals namespace != production board prefix: \x00" as *u8)
399 if g_streq(AS_PREFIX(), "knowledge/store/ws-\x00" as *u8) == 0 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
400
401 // ============================================================================================
402 g_puts(logfd, "ASSET-SIGNALS-GATE passed \x00" as *u8); g_putn(logfd, pass); g_puts(logfd, "/\x00" as *u8); g_putn(logfd, total)
403 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
404 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
405 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
406 let ctr__dry: *i64 = gv_ctr()
407 ctr__dry[0] = pass
408 ctr__dry[1] = total
409 let rc__dry: i64 = gv_verdict("ASSET-SIGNALS-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
410 sys_exit(rc__dry)
411 return rc__dry
412}