nx_asset_status_gate.nx source
↩ module page · 233 lines · 12499 B
1// nx_asset_status_gate.nx -- KAT + TEETH for nx_asset_status (R5 dashboard stats).
2//
3// Builds a FIXTURE catalog with a KNOWN composition and proves st_compute reports the EXACT stats:
4// totals by type, by provenance class, freshness, and the R4 signal totals by code. Then the TEETH:
5// an EMPTY catalog must yield ALL ZEROS (no fabricated counts), and the reported total must EQUAL
6// cat_count over the same prefix (the aggregator agrees with the SSOT count).
7//
8// record1 doc, machine, is_current=1, tagged, relations present -> only signal: MISSING_PROVENANCE
9// record2 doc, machine, is_current=1, tagged, relations present -> only signal: MISSING_PROVENANCE
10// record3 image, machine, is_current=1, full w/h, tagged, relations-> only signal: MISSING_PROVENANCE
11// record4 image, human, is_current=1, full w/h, tagged, relations-> only signal: MISSING_PROVENANCE
12// record5 image, machine, is_current=0 (STALE), full w/h, tagged, relations -> MISSING_PROVENANCE + STALE
13//
14// (no credentials are minted -> deny-by-default => every record reads MISSING_PROVENANCE; phashes=0 =>
15// no NEAR_DUP; tags+relations present => no UNTAGGED/ORPHANED; images carry w/h => no MISSING_METADATA;
16// no video/audio => no UNTRANSCODED. So the signal set is exactly { 5x MISSING_PROVENANCE, 1x STALE }.)
17//
18// EXPECTED stats: TOTAL=5; T_DOC=2 T_IMAGE=3; P_MACHINE=4 P_HUMAN=1; CURRENT=4 NOTCURRENT=1;
19// SIG_TOTAL=6 SIG_PROV=5 SIG_STALE=1 (all other code totals 0).
20//
21// Verdict appended to knowledge/status/asset_status_gate.log (additive law #13).
22// expect_exit: 0 license_tier: ORIGINAL
23import "nx_syscalls.nx"
24import "nx_canon_cid.nx"
25import "nx_seg_store.nx"
26import "nx_asset_record.nx"
27import "nx_asset_catalog.nx"
28import "nx_asset_signals.nx"
29import "nx_asset_status.nx"
30import "nx_gate_verdict.nx"
31
32func g_puts(logfd: i64, s: *u8) -> i64 {
33 var n: i64 = 0
34 while s[n] != (0 as u8) { n = n + 1 }
35 sys_write(1, s, n)
36 if logfd > 0 { sys_write(logfd, s, n) }
37 return 0
38}
39func g_putn(logfd: i64, v: i64) -> i64 {
40 let bb: *u8 = sys_mmap(28)
41 var m: i64 = v
42 if m < 0 { g_puts(logfd, "-\x00" as *u8); m = 0 - m }
43 let t: *u8 = sys_mmap(28)
44 var k: i64 = 0
45 if m == 0 { t[0] = 48 as u8; k = 1 }
46 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
47 var i: i64 = 0
48 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
49 sys_write(1, bb, k)
50 if logfd > 0 { sys_write(logfd, bb, k) }
51 return 0
52}
53
54func E() -> *u8 { return "\x00" as *u8 }
55func sset(a: *i64, i: i64, s: *u8) -> i64 { a[i] = s as i64; return 0 }
56
57func mk_rec(core: *i64, prov: *i64, media: *i64, org: *i64, out: *u8) -> i64 {
58 let keys: *i64 = sys_mmap(8 * 48) as *i64
59 let vals: *i64 = sys_mmap(8 * 48) as *i64
60 let n: i64 = ar_fields(core, prov, media, org, keys, vals)
61 return ar_encode(keys, vals, n, out)
62}
63
64// fresh unique store prefix "<base><stamp>-" so each run is clean + idempotent (matches the R4 gate).
65func mk_prefix(prefix: *u8, base: *u8, salt: i64) -> 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() + salt
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
80// build one record's grouped arrays inline: type, prov_class, is_current. tags+relations always present;
81// images carry w/h. Ingests into the catalog at `prefix`.
82func mk_and_ingest(prefix: *u8, typ: *u8, provclass: *u8, current: *u8, is_image: i64, idtag: *u8) -> i64 {
83 let core: *i64 = sys_mmap(8 * 8) as *i64
84 sset(core, 0, typ); sset(core, 1, idtag); sset(core, 2, E()); sset(core, 3, "2026-06-16\x00" as *u8)
85 sset(core, 4, idtag); sset(core, 5, E()); sset(core, 6, E())
86 let prov: *i64 = sys_mmap(8 * 8) as *i64
87 sset(prov, 0, provclass); sset(prov, 1, "agent\x00" as *u8); sset(prov, 2, E()); sset(prov, 3, E())
88 sset(prov, 4, E()); sset(prov, 5, E())
89 let media: *i64 = sys_mmap(8 * 8) as *i64
90 if is_image == 1 {
91 sset(media, 0, "1024\x00" as *u8); sset(media, 1, "768\x00" as *u8); sset(media, 2, E()); sset(media, 3, "image/png\x00" as *u8)
92 } else {
93 sset(media, 0, E()); sset(media, 1, E()); sset(media, 2, E()); sset(media, 3, "text/html\x00" as *u8)
94 }
95 let org: *i64 = sys_mmap(8 * 8) as *i64
96 sset(org, 0, "tag1,tag2\x00" as *u8); sset(org, 1, "/path\x00" as *u8); sset(org, 2, "manage\x00" as *u8)
97 sset(org, 3, current); sset(org, 4, "professional\x00" as *u8); sset(org, 5, "nxc1-rel\x00" as *u8)
98 let rec: *u8 = sys_mmap(8192)
99 let rlen: i64 = mk_rec(core, prov, media, org, rec)
100 let st: *i64 = sys_mmap(16) as *i64
101 return cat_ingest(prefix, rec, rlen, st)
102}
103
104func main() -> i64 {
105 let logfd: i64 = sys_openat_append("knowledge/status/asset_status_gate.log\x00" as *u8, 0x1a4)
106 g_puts(logfd, "=== ASSET-STATUS-GATE (R5: dashboard stats by type/provenance/freshness/signal) ===\n\x00" as *u8)
107
108 var pass: i64 = 0
109 var total: i64 = 0
110
111 let prefix: *u8 = sys_mmap(256)
112 mk_prefix(prefix, "/tmp/stat-\x00" as *u8, 0)
113 g_puts(logfd, " fixture catalog prefix=\x00" as *u8); g_puts(logfd, prefix); g_puts(logfd, "\n\x00" as *u8)
114
115 // ---- ingest the 5 fixture records (KNOWN composition) ----
116 mk_and_ingest(prefix, "doc\x00" as *u8, "machine\x00" as *u8, "1\x00" as *u8, 0, "rec1\x00" as *u8)
117 mk_and_ingest(prefix, "doc\x00" as *u8, "machine\x00" as *u8, "1\x00" as *u8, 0, "rec2\x00" as *u8)
118 mk_and_ingest(prefix, "image\x00" as *u8, "machine\x00" as *u8, "1\x00" as *u8, 1, "rec3\x00" as *u8)
119 mk_and_ingest(prefix, "image\x00" as *u8, "human\x00" as *u8, "1\x00" as *u8, 1, "rec4\x00" as *u8)
120 mk_and_ingest(prefix, "image\x00" as *u8, "machine\x00" as *u8, "0\x00" as *u8, 1, "rec5\x00" as *u8)
121
122 // ---- compute stats (production-style: zero aux arrays) ----
123 let st: *i64 = sys_mmap(8 * st_cap()) as *i64
124 let n: i64 = st_compute_live(prefix, st)
125
126 // dump the full stats array (RAW evidence)
127 g_puts(logfd, " STATS total=\x00" as *u8); g_putn(logfd, st[ST_TOTAL()])
128 g_puts(logfd, " doc=\x00" as *u8); g_putn(logfd, st[ST_T_DOC()])
129 g_puts(logfd, " image=\x00" as *u8); g_putn(logfd, st[ST_T_IMAGE()])
130 g_puts(logfd, " | machine=\x00" as *u8); g_putn(logfd, st[ST_P_MACHINE()])
131 g_puts(logfd, " human=\x00" as *u8); g_putn(logfd, st[ST_P_HUMAN()])
132 g_puts(logfd, " | current=\x00" as *u8); g_putn(logfd, st[ST_CURRENT()])
133 g_puts(logfd, " notcurrent=\x00" as *u8); g_putn(logfd, st[ST_NOTCURRENT()])
134 g_puts(logfd, " | sigtotal=\x00" as *u8); g_putn(logfd, st[ST_SIG_TOTAL()])
135 g_puts(logfd, " prov=\x00" as *u8); g_putn(logfd, st[ST_SIG_PROV()])
136 g_puts(logfd, " stale=\x00" as *u8); g_putn(logfd, st[ST_SIG_STALE()])
137 g_puts(logfd, " untag=\x00" as *u8); g_putn(logfd, st[ST_SIG_UNTAG()])
138 g_puts(logfd, " meta=\x00" as *u8); g_putn(logfd, st[ST_SIG_META()])
139 g_puts(logfd, " neardup=\x00" as *u8); g_putn(logfd, st[ST_SIG_NEARDUP()])
140 g_puts(logfd, " orphan=\x00" as *u8); g_putn(logfd, st[ST_SIG_ORPHAN()])
141 g_puts(logfd, " untrans=\x00" as *u8); g_putn(logfd, st[ST_SIG_UNTRANS()])
142 g_puts(logfd, "\n\x00" as *u8)
143
144 // (a) total == 5
145 total = total + 1
146 g_puts(logfd, " (a) total==5: \x00" as *u8)
147 if st[ST_TOTAL()] == 5 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
148
149 // (b) type counts: doc==2, image==3 (and no other type)
150 total = total + 1
151 g_puts(logfd, " (b) type doc==2 && image==3 (rest 0): \x00" as *u8)
152 var b_ok: i64 = 1
153 if st[ST_T_DOC()] != 2 { b_ok = 0 }
154 if st[ST_T_IMAGE()] != 3 { b_ok = 0 }
155 if st[ST_T_VIDEO()] != 0 { b_ok = 0 }
156 if st[ST_T_AUDIO()] != 0 { b_ok = 0 }
157 if st[ST_T_DATASET()] != 0 { b_ok = 0 }
158 if st[ST_T_PRODUCT()] != 0 { b_ok = 0 }
159 if st[ST_T_OTHER()] != 0 { b_ok = 0 }
160 if b_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
161
162 // (c) provenance counts: machine==4, human==1 (no downloaded/none)
163 total = total + 1
164 g_puts(logfd, " (c) prov machine==4 && human==1 (rest 0): \x00" as *u8)
165 var c_ok: i64 = 1
166 if st[ST_P_MACHINE()] != 4 { c_ok = 0 }
167 if st[ST_P_HUMAN()] != 1 { c_ok = 0 }
168 if st[ST_P_DOWNLOAD()] != 0 { c_ok = 0 }
169 if st[ST_P_NONE()] != 0 { c_ok = 0 }
170 if c_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
171
172 // (d) freshness: current==4, notcurrent==1
173 total = total + 1
174 g_puts(logfd, " (d) freshness current==4 && notcurrent==1: \x00" as *u8)
175 var d_ok: i64 = 1
176 if st[ST_CURRENT()] != 4 { d_ok = 0 }
177 if st[ST_NOTCURRENT()] != 1 { d_ok = 0 }
178 if d_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
179
180 // (e) signals: total==6, MISSING_PROVENANCE==5, STALE==1, rest 0 (exact-set)
181 total = total + 1
182 g_puts(logfd, " (e) signals total==6 prov==5 stale==1 (rest 0): \x00" as *u8)
183 var e_ok: i64 = 1
184 if st[ST_SIG_TOTAL()] != 6 { e_ok = 0 }
185 if st[ST_SIG_PROV()] != 5 { e_ok = 0 }
186 if st[ST_SIG_STALE()] != 1 { e_ok = 0 }
187 if st[ST_SIG_UNTAG()] != 0 { e_ok = 0 }
188 if st[ST_SIG_META()] != 0 { e_ok = 0 }
189 if st[ST_SIG_NEARDUP()] != 0 { e_ok = 0 }
190 if st[ST_SIG_ORPHAN()] != 0 { e_ok = 0 }
191 if st[ST_SIG_UNTRANS()] != 0 { e_ok = 0 }
192 if e_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
193
194 // (f) AGREEMENT: st_compute total == cat_count over the same prefix (aggregator == SSOT count)
195 let cc: i64 = cat_count(prefix)
196 total = total + 1
197 g_puts(logfd, " (f) total==cat_count (got total=\x00" as *u8); g_putn(logfd, n); g_puts(logfd, " cat_count=\x00" as *u8); g_putn(logfd, cc); g_puts(logfd, "): \x00" as *u8)
198 if n == cc { if n == 5 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) } } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
199
200 // ============================================================================================
201 // (g) TEETH: an EMPTY catalog -> ALL ZEROS (no fabricated counts).
202 let eprefix: *u8 = sys_mmap(256)
203 mk_prefix(eprefix, "/tmp/stat-empty-\x00" as *u8, 777)
204 let est: *i64 = sys_mmap(8 * st_cap()) as *i64
205 let en: i64 = st_compute_live(eprefix, est)
206 g_puts(logfd, " EMPTY stats total=\x00" as *u8); g_putn(logfd, est[ST_TOTAL()])
207 g_puts(logfd, " sigtotal=\x00" as *u8); g_putn(logfd, est[ST_SIG_TOTAL()]); g_puts(logfd, "\n\x00" as *u8)
208 total = total + 1
209 g_puts(logfd, " (g) TEETH empty catalog -> ALL ZEROS: \x00" as *u8)
210 var g_ok: i64 = 1
211 if en != 0 { g_ok = 0 }
212 var zi: i64 = 0
213 while zi < st_cap() { if est[zi] != 0 { g_ok = 0 } zi = zi + 1 }
214 if g_ok == 1 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
215
216 // (h) TEETH: empty total == cat_count(empty) == 0
217 let ecc: i64 = cat_count(eprefix)
218 total = total + 1
219 g_puts(logfd, " (h) TEETH empty total==cat_count==0 (got total=\x00" as *u8); g_putn(logfd, en); g_puts(logfd, " cat_count=\x00" as *u8); g_putn(logfd, ecc); g_puts(logfd, "): \x00" as *u8)
220 if en == 0 { if ecc == 0 { pass = pass + 1; g_puts(logfd, "PASS\n\x00" as *u8) } else { g_puts(logfd, "FAIL\n\x00" as *u8) } } else { g_puts(logfd, "FAIL\n\x00" as *u8) }
221
222 // ============================================================================================
223 g_puts(logfd, "ASSET-STATUS-GATE passed \x00" as *u8); g_putn(logfd, pass); g_puts(logfd, "/\x00" as *u8); g_putn(logfd, total)
224 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
225 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
226 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
227 let ctr__dry: *i64 = gv_ctr()
228 ctr__dry[0] = pass
229 ctr__dry[1] = total
230 let rc__dry: i64 = gv_verdict("ASSET-STATUS-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
231 sys_exit(rc__dry)
232 return rc__dry
233}