code wiki / _hdl_build / nx_info_registry.nx
nx_info_registry.nx source
↩ module page · 891 lines · 39198 B
1// nx_info_registry.nx -- NATIVE FEATURES + RISK REGISTRIES on the information plane (operator
2// 2026-07-20: workstreams pay a detective-work tax re-deriving what exists and what can bite;
3// the features registry + risk register become NATIVE planes, queryable by any seat/agent).
4// READS the seg-store planes seeded via nx_store_put (compose, never re-implement the store):
5// knowledge/store/featreg- 9-col id title status owner scope entry surface evidence note
6// knowledge/store/riskreg- 10-col id title likelihood impact status owner scope mitigation trigger note
7// Exposure = likelihood*impact is DERIVED here, never stored (same law as frontier float).
8// Verbs:
9// nx_info_registry features [query] -> JSON rows (value-substring filter, values only)
10// nx_info_registry risks [query] -> JSON rows + derived exposure per row
11// nx_info_registry board -> JSON counts by status + top OPEN risk by exposure
12// nx_info_registry page -> writes registries_stage.html (publish via nx_site_publish)
13// nx_info_registry selftest -> 6 structural teeth, VERDICT GREEN/RED, exit 0/3
14// FAIL-CLOSED: an unseeded plane exits 4 with a loud message -- a missing registry is a defect,
15// never an empty list. Malformed rows are SKIPPED but COUNTED in the declared envelope.
16// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
17import "nx_store_seed_lib.nx"
18import "nx_seg_store.nx"
19import "nx_syscalls.nx"
20const IRX_MAGIC_4096: i64 = 4096
21
22const IRX_CAP: i64 = 1048576
23const IRX_OUT: i64 = 4194304
24const IRX_NL: i64 = 10
25const IRX_TAB: i64 = 9
26const IRX_QU: i64 = 34
27const IRX_COLON: i64 = 58
28const IRX_COMMA: i64 = 44
29const IRX_LB: i64 = 123
30const IRX_RB: i64 = 125
31const IRX_LSQ: i64 = 91
32const IRX_RSQ: i64 = 93
33const IRX_BANG: i64 = 33
34const IRX_MAXCOL: i64 = 16
35const IRX_PAIR: i64 = 2
36const IRX_SP2: i64 = 256
37const IRX_FEAT_NCOL: i64 = 9
38const IRX_RISK_NCOL: i64 = 10
39const IRX_DEC_NCOL: i64 = 9
40const IRX_STDERR: i64 = 2
41const IRX_EXIT_USAGE: i64 = 2
42const IRX_EXIT_RED: i64 = 3
43const IRX_EXIT_ABSENT: i64 = 4
44const IRX_FMODE: i64 = 420
45
46func irx_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
47func irx_werr(s: *u8) -> i64 { sys_write(IRX_STDERR, s, irx_slen(s)); return 0 }
48func irx_eqs(a: *u8, b: *u8) -> i64 {
49 var i: i64 = 0
50 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
51 if b[i] != (0 as u8) { return 0 }
52 return 1
53}
54func irx_slice_eqs(q: *u8, a: i64, b: i64, s: *u8) -> i64 {
55 let sn: i64 = irx_slen(s)
56 if b - a != sn { return 0 }
57 var i: i64 = 0
58 while i < sn { if q[a+i] != s[i] { return 0 } i = i + 1 }
59 return 1
60}
61// compare slice [a1,b1) of q against slice [a2,b2) of r (byte-exact)
62func irx_slice_eq_slice(q: *u8, a1: i64, b1: i64, r: *u8, a2: i64, b2: i64) -> i64 {
63 if b1 - a1 != b2 - a2 { return 0 }
64 let ln: i64 = b1 - a1
65 var i: i64 = 0
66 while i < ln { if q[a1+i] != r[a2+i] { return 0 } i = i + 1 }
67 return 1
68}
69func irx_cols(q: *u8, ls: i64, le: i64, sp: *i64) -> i64 {
70 var c: i64 = 0
71 var p: i64 = ls
72 while c < IRX_MAXCOL {
73 var e: i64 = p
74 var s: i64 = 1
75 while s == 1 { if e >= le { s = 0 } else { if q[e] == (IRX_TAB as u8) { s = 0 } else { e = e + 1 } } }
76 sp[c*IRX_PAIR] = p
77 sp[c*IRX_PAIR+1] = e
78 c = c + 1
79 if e >= le { return c }
80 p = e + 1
81 }
82 return c
83}
84func irx_b(d: *u8, o: i64, c: i64) -> i64 { d[o] = c as u8; return o + 1 }
85// copy slice sanitized for JSON string context: quote->apostrophe-ish, backslash->slash, ctl->space
86func irx_cat_slice_json(d: *u8, o: i64, q: *u8, a: i64, b: i64) -> i64 {
87 var oo: i64 = o
88 var i: i64 = a
89 while i < b {
90 var c: i64 = q[i]
91 if c == 34 { c = 39 }
92 if c == 92 { c = 47 }
93 if c < 32 { c = 32 }
94 d[oo] = c as u8
95 oo = oo + 1
96 i = i + 1
97 }
98 return oo
99}
100// copy slice sanitized for HTML text context: angle brackets -> parens (rows may carry <arg> shapes)
101func irx_cat_slice_html(d: *u8, o: i64, q: *u8, a: i64, b: i64) -> i64 {
102 var oo: i64 = o
103 var i: i64 = a
104 while i < b {
105 var c: i64 = q[i]
106 if c == 60 { c = 40 }
107 if c == 62 { c = 41 }
108 if c < 32 { c = 32 }
109 d[oo] = c as u8
110 oo = oo + 1
111 i = i + 1
112 }
113 return oo
114}
115func irx_atoi_slice(q: *u8, a: i64, b: i64) -> i64 {
116 var v: i64 = 0
117 var i: i64 = a
118 while i < b {
119 let c: i64 = q[i]
120 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } }
121 i = i + 1
122 }
123 return v
124}
125// substring search of C-string s within [ls,le) -- sound flag exits only, no break
126func irx_find_sub(q: *u8, ls: i64, le: i64, s: *u8) -> i64 {
127 let sn: i64 = irx_slen(s)
128 if sn == 0 { return 1 }
129 var i: i64 = ls
130 var found: i64 = 0
131 while found == 0 {
132 if i + sn > le { found = 2 } else {
133 var j: i64 = 0
134 var ok: i64 = 1
135 while j < sn { if q[i+j] != s[j] { ok = 0; j = sn } else { j = j + 1 } }
136 if ok == 1 { found = 1 } else { i = i + 1 }
137 }
138 }
139 if found == 1 { return 1 }
140 return 0
141}
142func irx_jkey(d: *u8, o: i64, k: *u8) -> i64 {
143 var oo: i64 = irx_b(d, o, IRX_QU)
144 oo = ss_cat(d, oo, k)
145 oo = irx_b(d, oo, IRX_QU)
146 oo = irx_b(d, oo, IRX_COLON)
147 return oo
148}
149func irx_jcstr(d: *u8, o: i64, k: *u8, v: *u8) -> i64 {
150 var oo: i64 = irx_jkey(d, o, k)
151 oo = irx_b(d, oo, IRX_QU)
152 oo = ss_cat(d, oo, v)
153 oo = irx_b(d, oo, IRX_QU)
154 return oo
155}
156func irx_jslice(d: *u8, o: i64, k: *u8, q: *u8, a: i64, b: i64) -> i64 {
157 var oo: i64 = irx_jkey(d, o, k)
158 oo = irx_b(d, oo, IRX_QU)
159 oo = irx_cat_slice_json(d, oo, q, a, b)
160 oo = irx_b(d, oo, IRX_QU)
161 return oo
162}
163func irx_jint(d: *u8, o: i64, k: *u8, v: i64) -> i64 {
164 var oo: i64 = irx_jkey(d, o, k)
165 oo = ss_catn(d, oo, v)
166 return oo
167}
168func irx_load_or_die(prefix: *u8, b: *u8) -> i64 {
169 let n: i64 = sts_load(prefix, b, IRX_CAP - IRX_MAGIC_4096)
170 if n <= 0 { irx_werr("REGISTRY PLANE ABSENT/EMPTY (fail-closed): " as *u8); irx_werr(prefix); irx_werr("\n" as *u8); sys_exit(IRX_EXIT_ABSENT) }
171 return n
172}
173// emit one registry as JSON. kindfeat=1 -> featreg 9-col; kindfeat=0 -> riskreg 10-col w/ exposure.
174func irx_emit_registry(kindfeat: i64, query: *u8, hasq: i64) -> i64 {
175 let b: *u8 = sys_mmap(IRX_CAP)
176 var n: i64 = 0
177 if kindfeat == 1 { n = irx_load_or_die("knowledge/store/featreg-" as *u8, b) } else { n = irx_load_or_die("knowledge/store/riskreg-" as *u8, b) }
178 let out: *u8 = sys_mmap(IRX_OUT)
179 let sp: *i64 = sys_mmap(IRX_SP2) as *i64
180 var wantcols: i64 = IRX_RISK_NCOL
181 if kindfeat == 1 { wantcols = IRX_FEAT_NCOL }
182 var total: i64 = 0
183 var matched: i64 = 0
184 var malformed: i64 = 0
185 var o: i64 = 0
186 o = irx_b(out, o, IRX_LB)
187 if kindfeat == 1 { o = irx_jcstr(out, o, "registry" as *u8, "features" as *u8) } else { o = irx_jcstr(out, o, "registry" as *u8, "risks" as *u8) }
188 o = irx_b(out, o, IRX_COMMA)
189 if hasq == 1 { o = irx_jcstr(out, o, "query" as *u8, query) } else { o = irx_jcstr(out, o, "query" as *u8, "none" as *u8) }
190 o = irx_b(out, o, IRX_COMMA)
191 o = irx_jkey(out, o, "rows" as *u8)
192 o = irx_b(out, o, IRX_LSQ)
193 var first: i64 = 1
194 var i: i64 = 0
195 while i < n {
196 var le: i64 = i
197 var s: i64 = 1
198 while s == 1 { if le >= n { s = 0 } else { if b[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
199 if le > i {
200 total = total + 1
201 let nc: i64 = irx_cols(b, i, le, sp)
202 if nc != wantcols { malformed = malformed + 1 } else {
203 var inc: i64 = 1
204 if hasq == 1 { inc = irx_find_sub(b, i, le, query) }
205 if inc == 1 {
206 matched = matched + 1
207 if first == 0 { o = irx_b(out, o, IRX_COMMA) }
208 first = 0
209 o = irx_b(out, o, IRX_LB)
210 o = irx_jslice(out, o, "id" as *u8, b, sp[0], sp[1])
211 o = irx_b(out, o, IRX_COMMA)
212 o = irx_jslice(out, o, "title" as *u8, b, sp[2], sp[3])
213 o = irx_b(out, o, IRX_COMMA)
214 if kindfeat == 1 {
215 o = irx_jslice(out, o, "status" as *u8, b, sp[4], sp[5])
216 o = irx_b(out, o, IRX_COMMA)
217 o = irx_jslice(out, o, "owner" as *u8, b, sp[6], sp[7])
218 o = irx_b(out, o, IRX_COMMA)
219 o = irx_jslice(out, o, "scope" as *u8, b, sp[8], sp[9])
220 o = irx_b(out, o, IRX_COMMA)
221 o = irx_jslice(out, o, "entry" as *u8, b, sp[10], sp[11])
222 o = irx_b(out, o, IRX_COMMA)
223 o = irx_jslice(out, o, "surface" as *u8, b, sp[12], sp[13])
224 o = irx_b(out, o, IRX_COMMA)
225 o = irx_jslice(out, o, "evidence" as *u8, b, sp[14], sp[15])
226 o = irx_b(out, o, IRX_COMMA)
227 o = irx_jslice(out, o, "note" as *u8, b, sp[16], sp[17])
228 } else {
229 let lik: i64 = irx_atoi_slice(b, sp[4], sp[5])
230 let imp: i64 = irx_atoi_slice(b, sp[6], sp[7])
231 let expo: i64 = lik * imp
232 o = irx_jint(out, o, "likelihood" as *u8, lik)
233 o = irx_b(out, o, IRX_COMMA)
234 o = irx_jint(out, o, "impact" as *u8, imp)
235 o = irx_b(out, o, IRX_COMMA)
236 o = irx_jint(out, o, "exposure" as *u8, expo)
237 o = irx_b(out, o, IRX_COMMA)
238 o = irx_jslice(out, o, "status" as *u8, b, sp[8], sp[9])
239 o = irx_b(out, o, IRX_COMMA)
240 o = irx_jslice(out, o, "owner" as *u8, b, sp[10], sp[11])
241 o = irx_b(out, o, IRX_COMMA)
242 o = irx_jslice(out, o, "scope" as *u8, b, sp[12], sp[13])
243 o = irx_b(out, o, IRX_COMMA)
244 o = irx_jslice(out, o, "mitigation" as *u8, b, sp[14], sp[15])
245 o = irx_b(out, o, IRX_COMMA)
246 o = irx_jslice(out, o, "trigger" as *u8, b, sp[16], sp[17])
247 o = irx_b(out, o, IRX_COMMA)
248 o = irx_jslice(out, o, "note" as *u8, b, sp[18], sp[19])
249 }
250 o = irx_b(out, o, IRX_RB)
251 }
252 }
253 }
254 i = le + 1
255 }
256 o = irx_b(out, o, IRX_RSQ)
257 o = irx_b(out, o, IRX_COMMA)
258 o = irx_jint(out, o, "total" as *u8, total)
259 o = irx_b(out, o, IRX_COMMA)
260 o = irx_jint(out, o, "matched" as *u8, matched)
261 o = irx_b(out, o, IRX_COMMA)
262 o = irx_jkey(out, o, "envelope" as *u8)
263 o = irx_b(out, o, IRX_LB)
264 o = irx_jint(out, o, "plane_cap" as *u8, IRX_CAP)
265 o = irx_b(out, o, IRX_COMMA)
266 o = irx_jint(out, o, "malformed" as *u8, malformed)
267 o = irx_b(out, o, IRX_COMMA)
268 var trunc: i64 = 0
269 if n >= IRX_CAP - IRX_MAGIC_4096 { trunc = 1 }
270 o = irx_jint(out, o, "truncated" as *u8, trunc)
271 o = irx_b(out, o, IRX_RB)
272 o = irx_b(out, o, IRX_RB)
273 o = irx_b(out, o, IRX_NL)
274 sys_write(1, out, o)
275 return 0
276}
277// count decreg rows whose supersedes(col7) is not "-" but references a NON-existent id
278// = a dangling decision chain (the ADL integrity signal; 0 = sound graph).
279func irx_dec_dangling(b: *u8, n: i64) -> i64 {
280 let sp: *i64 = sys_mmap(IRX_SP2) as *i64
281 let sp2: *i64 = sys_mmap(IRX_SP2) as *i64
282 var dangling: i64 = 0
283 var i: i64 = 0
284 while i < n {
285 var le: i64 = i
286 var s: i64 = 1
287 while s == 1 { if le >= n { s = 0 } else { if b[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
288 if le > i {
289 let nc: i64 = irx_cols(b, i, le, sp)
290 if nc == IRX_DEC_NCOL {
291 var isnone: i64 = 0
292 if sp[15] - sp[14] == 1 { if b[sp[14]] == (45 as u8) { isnone = 1 } }
293 if isnone == 0 {
294 var found: i64 = 0
295 var j: i64 = 0
296 while j < n {
297 var le2: i64 = j
298 var s2: i64 = 1
299 while s2 == 1 { if le2 >= n { s2 = 0 } else { if b[le2] == (IRX_NL as u8) { s2 = 0 } else { le2 = le2 + 1 } } }
300 if le2 > j {
301 let nc2: i64 = irx_cols(b, j, le2, sp2)
302 if nc2 == IRX_DEC_NCOL { if irx_slice_eq_slice(b, sp2[0], sp2[1], b, sp[14], sp[15]) == 1 { found = 1 } }
303 }
304 j = le2 + 1
305 }
306 if found == 0 { dangling = dangling + 1 }
307 }
308 }
309 }
310 i = le + 1
311 }
312 return dangling
313}
314// write "superseded_by":"<id or ->" -- scan for any row whose supersedes(col7) == this id [ida,idb)
315func irx_superseded_by(b: *u8, n: i64, ida: i64, idb: i64, sp2: *i64, out: *u8, o: i64) -> i64 {
316 var oo: i64 = irx_jkey(out, o, "superseded_by" as *u8)
317 oo = irx_b(out, oo, IRX_QU)
318 var foundq: i64 = 0
319 var j: i64 = 0
320 while j < n {
321 var le: i64 = j
322 var s: i64 = 1
323 while s == 1 { if le >= n { s = 0 } else { if b[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
324 if le > j {
325 let nc: i64 = irx_cols(b, j, le, sp2)
326 if nc == IRX_DEC_NCOL {
327 if irx_slice_eq_slice(b, sp2[14], sp2[15], b, ida, idb) == 1 {
328 if foundq == 0 { oo = irx_cat_slice_json(out, oo, b, sp2[0], sp2[1]); foundq = 1 }
329 }
330 }
331 }
332 j = le + 1
333 }
334 if foundq == 0 { oo = irx_b(out, oo, 45) }
335 oo = irx_b(out, oo, IRX_QU)
336 return oo
337}
338func irx_emit_decisions(query: *u8, hasq: i64) -> i64 {
339 let b: *u8 = sys_mmap(IRX_CAP)
340 let n: i64 = irx_load_or_die("knowledge/store/decreg-" as *u8, b)
341 let out: *u8 = sys_mmap(IRX_OUT)
342 let sp: *i64 = sys_mmap(IRX_SP2) as *i64
343 let sp2: *i64 = sys_mmap(IRX_SP2) as *i64
344 var total: i64 = 0
345 var matched: i64 = 0
346 var malformed: i64 = 0
347 var o: i64 = 0
348 o = irx_b(out, o, IRX_LB)
349 o = irx_jcstr(out, o, "registry" as *u8, "decisions" as *u8)
350 o = irx_b(out, o, IRX_COMMA)
351 if hasq == 1 { o = irx_jcstr(out, o, "query" as *u8, query) } else { o = irx_jcstr(out, o, "query" as *u8, "none" as *u8) }
352 o = irx_b(out, o, IRX_COMMA)
353 o = irx_jkey(out, o, "rows" as *u8)
354 o = irx_b(out, o, IRX_LSQ)
355 var first: i64 = 1
356 var i: i64 = 0
357 while i < n {
358 var le: i64 = i
359 var s: i64 = 1
360 while s == 1 { if le >= n { s = 0 } else { if b[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
361 if le > i {
362 total = total + 1
363 let nc: i64 = irx_cols(b, i, le, sp)
364 if nc != IRX_DEC_NCOL { malformed = malformed + 1 } else {
365 var inc: i64 = 1
366 if hasq == 1 { inc = irx_find_sub(b, i, le, query) }
367 if inc == 1 {
368 matched = matched + 1
369 if first == 0 { o = irx_b(out, o, IRX_COMMA) }
370 first = 0
371 o = irx_b(out, o, IRX_LB)
372 o = irx_jslice(out, o, "id" as *u8, b, sp[0], sp[1])
373 o = irx_b(out, o, IRX_COMMA)
374 o = irx_jslice(out, o, "title" as *u8, b, sp[2], sp[3])
375 o = irx_b(out, o, IRX_COMMA)
376 o = irx_jslice(out, o, "status" as *u8, b, sp[4], sp[5])
377 o = irx_b(out, o, IRX_COMMA)
378 o = irx_jslice(out, o, "driver" as *u8, b, sp[6], sp[7])
379 o = irx_b(out, o, IRX_COMMA)
380 o = irx_jslice(out, o, "date" as *u8, b, sp[8], sp[9])
381 o = irx_b(out, o, IRX_COMMA)
382 o = irx_jslice(out, o, "context" as *u8, b, sp[10], sp[11])
383 o = irx_b(out, o, IRX_COMMA)
384 o = irx_jslice(out, o, "decision" as *u8, b, sp[12], sp[13])
385 o = irx_b(out, o, IRX_COMMA)
386 o = irx_jslice(out, o, "supersedes" as *u8, b, sp[14], sp[15])
387 o = irx_b(out, o, IRX_COMMA)
388 o = irx_jslice(out, o, "note" as *u8, b, sp[16], sp[17])
389 o = irx_b(out, o, IRX_COMMA)
390 o = irx_superseded_by(b, n, sp[0], sp[1], sp2, out, o)
391 o = irx_b(out, o, IRX_RB)
392 }
393 }
394 }
395 i = le + 1
396 }
397 o = irx_b(out, o, IRX_RSQ)
398 o = irx_b(out, o, IRX_COMMA)
399 o = irx_jint(out, o, "total" as *u8, total)
400 o = irx_b(out, o, IRX_COMMA)
401 o = irx_jint(out, o, "matched" as *u8, matched)
402 o = irx_b(out, o, IRX_COMMA)
403 o = irx_jkey(out, o, "envelope" as *u8)
404 o = irx_b(out, o, IRX_LB)
405 o = irx_jint(out, o, "plane_cap" as *u8, IRX_CAP)
406 o = irx_b(out, o, IRX_COMMA)
407 o = irx_jint(out, o, "malformed" as *u8, malformed)
408 o = irx_b(out, o, IRX_COMMA)
409 o = irx_jint(out, o, "dangling_supersedes" as *u8, irx_dec_dangling(b, n))
410 o = irx_b(out, o, IRX_COMMA)
411 var trunc: i64 = 0
412 if n >= IRX_CAP - IRX_MAGIC_4096 { trunc = 1 }
413 o = irx_jint(out, o, "truncated" as *u8, trunc)
414 o = irx_b(out, o, IRX_RB)
415 o = irx_b(out, o, IRX_RB)
416 o = irx_b(out, o, IRX_NL)
417 sys_write(1, out, o)
418 return 0
419}
420func irx_do_board() -> i64 {
421 let fb: *u8 = sys_mmap(IRX_CAP)
422 let fn2: i64 = irx_load_or_die("knowledge/store/featreg-" as *u8, fb)
423 let rb: *u8 = sys_mmap(IRX_CAP)
424 let rn: i64 = irx_load_or_die("knowledge/store/riskreg-" as *u8, rb)
425 let db: *u8 = sys_mmap(IRX_CAP)
426 let dn: i64 = irx_load_or_die("knowledge/store/decreg-" as *u8, db)
427 let sp: *i64 = sys_mmap(IRX_SP2) as *i64
428 let out: *u8 = sys_mmap(IRX_OUT)
429 var ftot: i64 = 0
430 var flive: i64 = 0
431 var fbuild: i64 = 0
432 var fdesign: i64 = 0
433 var i: i64 = 0
434 while i < fn2 {
435 var le: i64 = i
436 var s: i64 = 1
437 while s == 1 { if le >= fn2 { s = 0 } else { if fb[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
438 if le > i {
439 let nc: i64 = irx_cols(fb, i, le, sp)
440 if nc == IRX_FEAT_NCOL {
441 ftot = ftot + 1
442 if irx_slice_eqs(fb, sp[4], sp[5], "live" as *u8) == 1 { flive = flive + 1 }
443 if irx_slice_eqs(fb, sp[4], sp[5], "building" as *u8) == 1 { fbuild = fbuild + 1 }
444 if irx_slice_eqs(fb, sp[4], sp[5], "design" as *u8) == 1 { fdesign = fdesign + 1 }
445 }
446 }
447 i = le + 1
448 }
449 var rtot: i64 = 0
450 var ropen: i64 = 0
451 var rmit: i64 = 0
452 var racc: i64 = 0
453 var rclosed: i64 = 0
454 var topexpo: i64 = 0
455 var topa: i64 = 0
456 var topb: i64 = 0
457 var j: i64 = 0
458 while j < rn {
459 var le2: i64 = j
460 var s2: i64 = 1
461 while s2 == 1 { if le2 >= rn { s2 = 0 } else { if rb[le2] == (IRX_NL as u8) { s2 = 0 } else { le2 = le2 + 1 } } }
462 if le2 > j {
463 let nc2: i64 = irx_cols(rb, j, le2, sp)
464 if nc2 == IRX_RISK_NCOL {
465 rtot = rtot + 1
466 let isclosed: i64 = irx_slice_eqs(rb, sp[8], sp[9], "closed" as *u8)
467 if irx_slice_eqs(rb, sp[8], sp[9], "open" as *u8) == 1 { ropen = ropen + 1 }
468 if irx_slice_eqs(rb, sp[8], sp[9], "mitigating" as *u8) == 1 { rmit = rmit + 1 }
469 if irx_slice_eqs(rb, sp[8], sp[9], "accepted" as *u8) == 1 { racc = racc + 1 }
470 if isclosed == 1 { rclosed = rclosed + 1 }
471 if isclosed == 0 {
472 let lik: i64 = irx_atoi_slice(rb, sp[4], sp[5])
473 let imp: i64 = irx_atoi_slice(rb, sp[6], sp[7])
474 let expo: i64 = lik * imp
475 if expo > topexpo { topexpo = expo; topa = sp[0]; topb = sp[1] }
476 }
477 }
478 }
479 j = le2 + 1
480 }
481 var dtot: i64 = 0
482 var dacc: i64 = 0
483 var dsup: i64 = 0
484 var dprop: i64 = 0
485 var dlinks: i64 = 0
486 var k: i64 = 0
487 while k < dn {
488 var le3: i64 = k
489 var s3: i64 = 1
490 while s3 == 1 { if le3 >= dn { s3 = 0 } else { if db[le3] == (IRX_NL as u8) { s3 = 0 } else { le3 = le3 + 1 } } }
491 if le3 > k {
492 let nc3: i64 = irx_cols(db, k, le3, sp)
493 if nc3 == IRX_DEC_NCOL {
494 dtot = dtot + 1
495 if irx_slice_eqs(db, sp[4], sp[5], "accepted" as *u8) == 1 { dacc = dacc + 1 }
496 if irx_slice_eqs(db, sp[4], sp[5], "superseded" as *u8) == 1 { dsup = dsup + 1 }
497 if irx_slice_eqs(db, sp[4], sp[5], "proposed" as *u8) == 1 { dprop = dprop + 1 }
498 var isnone: i64 = 0
499 if sp[15] - sp[14] == 1 { if db[sp[14]] == (45 as u8) { isnone = 1 } }
500 if isnone == 0 { dlinks = dlinks + 1 }
501 }
502 }
503 k = le3 + 1
504 }
505 let ddangle: i64 = irx_dec_dangling(db, dn)
506 var o: i64 = 0
507 o = irx_b(out, o, IRX_LB)
508 o = irx_jcstr(out, o, "board" as *u8, "info-registries" as *u8)
509 o = irx_b(out, o, IRX_COMMA)
510 o = irx_jkey(out, o, "features" as *u8)
511 o = irx_b(out, o, IRX_LB)
512 o = irx_jint(out, o, "total" as *u8, ftot)
513 o = irx_b(out, o, IRX_COMMA)
514 o = irx_jint(out, o, "live" as *u8, flive)
515 o = irx_b(out, o, IRX_COMMA)
516 o = irx_jint(out, o, "building" as *u8, fbuild)
517 o = irx_b(out, o, IRX_COMMA)
518 o = irx_jint(out, o, "design" as *u8, fdesign)
519 o = irx_b(out, o, IRX_RB)
520 o = irx_b(out, o, IRX_COMMA)
521 o = irx_jkey(out, o, "risks" as *u8)
522 o = irx_b(out, o, IRX_LB)
523 o = irx_jint(out, o, "total" as *u8, rtot)
524 o = irx_b(out, o, IRX_COMMA)
525 o = irx_jint(out, o, "open" as *u8, ropen)
526 o = irx_b(out, o, IRX_COMMA)
527 o = irx_jint(out, o, "mitigating" as *u8, rmit)
528 o = irx_b(out, o, IRX_COMMA)
529 o = irx_jint(out, o, "accepted" as *u8, racc)
530 o = irx_b(out, o, IRX_COMMA)
531 o = irx_jint(out, o, "closed" as *u8, rclosed)
532 o = irx_b(out, o, IRX_RB)
533 o = irx_b(out, o, IRX_COMMA)
534 o = irx_jkey(out, o, "top_open_risk" as *u8)
535 o = irx_b(out, o, IRX_LB)
536 if topb > topa { o = irx_jslice(out, o, "id" as *u8, rb, topa, topb) } else { o = irx_jcstr(out, o, "id" as *u8, "none" as *u8) }
537 o = irx_b(out, o, IRX_COMMA)
538 o = irx_jint(out, o, "exposure" as *u8, topexpo)
539 o = irx_b(out, o, IRX_RB)
540 o = irx_b(out, o, IRX_COMMA)
541 o = irx_jkey(out, o, "decisions" as *u8)
542 o = irx_b(out, o, IRX_LB)
543 o = irx_jint(out, o, "total" as *u8, dtot)
544 o = irx_b(out, o, IRX_COMMA)
545 o = irx_jint(out, o, "accepted" as *u8, dacc)
546 o = irx_b(out, o, IRX_COMMA)
547 o = irx_jint(out, o, "superseded" as *u8, dsup)
548 o = irx_b(out, o, IRX_COMMA)
549 o = irx_jint(out, o, "proposed" as *u8, dprop)
550 o = irx_b(out, o, IRX_COMMA)
551 o = irx_jint(out, o, "supersede_links" as *u8, dlinks)
552 o = irx_b(out, o, IRX_COMMA)
553 o = irx_jint(out, o, "dangling_supersedes" as *u8, ddangle)
554 o = irx_b(out, o, IRX_RB)
555 o = irx_b(out, o, IRX_COMMA)
556 let ep: i64 = sys_now_realtime_sec()
557 o = irx_jint(out, o, "generated_epoch" as *u8, ep)
558 o = irx_b(out, o, IRX_RB)
559 o = irx_b(out, o, IRX_NL)
560 sys_write(1, out, o)
561 // also bank the board to a verifiable out-file (nx_prim_query/nx_prim_gap precedent):
562 // readable evidence + consumable by cron/other organs without re-running the organ.
563 let bfd: i64 = sys_openat_wr("knowledge/status/registries_board.json" as *u8, IRX_FMODE)
564 if bfd >= 0 { sys_write(bfd, out, o); sys_close(bfd) }
565 return 0
566}
567// emit a full-width table row: every col of the row as one td, html-sanitized
568func irx_page_row(out: *u8, o: i64, q: *u8, sp: *i64, nc: i64) -> i64 {
569 var oo: i64 = ss_cat(out, o, "<tr>" as *u8)
570 var c: i64 = 0
571 while c < nc {
572 oo = ss_cat(out, oo, "<td>" as *u8)
573 oo = irx_cat_slice_html(out, oo, q, sp[c*IRX_PAIR], sp[c*IRX_PAIR+1])
574 oo = ss_cat(out, oo, "</td>" as *u8)
575 c = c + 1
576 }
577 oo = ss_cat(out, oo, "</tr>" as *u8)
578 return oo
579}
580// html-safe superseded_by cell: scan for any row whose supersedes(col7) == this id, else "-"
581func irx_page_superseded_by_html(out: *u8, o: i64, b: *u8, n: i64, ida: i64, idb: i64) -> i64 {
582 let sp2: *i64 = sys_mmap(IRX_SP2) as *i64
583 var oo: i64 = o
584 var foundq: i64 = 0
585 var j: i64 = 0
586 while j < n {
587 var le: i64 = j
588 var s: i64 = 1
589 while s == 1 { if le >= n { s = 0 } else { if b[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
590 if le > j {
591 let nc: i64 = irx_cols(b, j, le, sp2)
592 if nc == IRX_DEC_NCOL {
593 if irx_slice_eq_slice(b, sp2[14], sp2[15], b, ida, idb) == 1 {
594 if foundq == 0 { oo = irx_cat_slice_html(out, oo, b, sp2[0], sp2[1]); foundq = 1 }
595 }
596 }
597 }
598 j = le + 1
599 }
600 if foundq == 0 { oo = irx_b(out, oo, 45) }
601 return oo
602}
603func irx_do_page() -> i64 {
604 let fb: *u8 = sys_mmap(IRX_CAP)
605 let fn2: i64 = irx_load_or_die("knowledge/store/featreg-" as *u8, fb)
606 let rb: *u8 = sys_mmap(IRX_CAP)
607 let rn: i64 = irx_load_or_die("knowledge/store/riskreg-" as *u8, rb)
608 let db: *u8 = sys_mmap(IRX_CAP)
609 let dn: i64 = irx_load_or_die("knowledge/store/decreg-" as *u8, db)
610 let sp: *i64 = sys_mmap(IRX_SP2) as *i64
611 let out: *u8 = sys_mmap(IRX_OUT)
612 var o: i64 = 0
613 o = ss_cat(out, o, "<" as *u8)
614 o = irx_b(out, o, IRX_BANG)
615 o = ss_cat(out, o, "doctype html><html><head><meta charset=utf-8><title>Nishi Registries</title><style>body" as *u8)
616 o = irx_b(out, o, IRX_LB)
617 o = ss_cat(out, o, "font-family:monospace;background:rgb(16,16,20);color:rgb(226,226,220);margin:24px" as *u8)
618 o = irx_b(out, o, IRX_RB)
619 o = ss_cat(out, o, "table" as *u8)
620 o = irx_b(out, o, IRX_LB)
621 o = ss_cat(out, o, "border-collapse:collapse;margin:12px 0 28px 0" as *u8)
622 o = irx_b(out, o, IRX_RB)
623 o = ss_cat(out, o, "td,th" as *u8)
624 o = irx_b(out, o, IRX_LB)
625 o = ss_cat(out, o, "border:1px solid rgb(80,80,95);padding:4px 8px;font-size:13px;text-align:left;vertical-align:top" as *u8)
626 o = irx_b(out, o, IRX_RB)
627 o = ss_cat(out, o, "th" as *u8)
628 o = irx_b(out, o, IRX_LB)
629 o = ss_cat(out, o, "background:rgb(38,38,50)" as *u8)
630 o = irx_b(out, o, IRX_RB)
631 o = ss_cat(out, o, "h1,h2" as *u8)
632 o = irx_b(out, o, IRX_LB)
633 o = ss_cat(out, o, "color:rgb(140,200,255)" as *u8)
634 o = irx_b(out, o, IRX_RB)
635 o = ss_cat(out, o, "</style></head><body><h1>Nishi Information Plane Registries</h1><p>Native features registry + risk register + decision/ADL log. Source planes: knowledge/store/featreg-, riskreg-, decreg- (provenanced via nx_store_put hist). Exposure (likelihood x impact) and superseded_by are DERIVED at render, never stored. Query via MCP: nx_info_registry features|risks|decisions|board.</p>" as *u8)
636 o = ss_cat(out, o, "<h2>Features registry</h2><table><tr><th>id</th><th>title</th><th>status</th><th>owner</th><th>scope</th><th>entry</th><th>surface</th><th>evidence</th><th>note</th></tr>" as *u8)
637 var i: i64 = 0
638 while i < fn2 {
639 var le: i64 = i
640 var s: i64 = 1
641 while s == 1 { if le >= fn2 { s = 0 } else { if fb[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
642 if le > i {
643 let nc: i64 = irx_cols(fb, i, le, sp)
644 if nc == IRX_FEAT_NCOL { o = irx_page_row(out, o, fb, sp, nc) }
645 }
646 i = le + 1
647 }
648 o = ss_cat(out, o, "</table><h2>Risk register</h2><table><tr><th>id</th><th>title</th><th>L</th><th>I</th><th>LxI</th><th>status</th><th>owner</th><th>scope</th><th>mitigation</th><th>trigger</th><th>note</th></tr>" as *u8)
649 var j: i64 = 0
650 while j < rn {
651 var le2: i64 = j
652 var s2: i64 = 1
653 while s2 == 1 { if le2 >= rn { s2 = 0 } else { if rb[le2] == (IRX_NL as u8) { s2 = 0 } else { le2 = le2 + 1 } } }
654 if le2 > j {
655 let nc2: i64 = irx_cols(rb, j, le2, sp)
656 if nc2 == IRX_RISK_NCOL {
657 let lik: i64 = irx_atoi_slice(rb, sp[4], sp[5])
658 let imp: i64 = irx_atoi_slice(rb, sp[6], sp[7])
659 let expo: i64 = lik * imp
660 o = ss_cat(out, o, "<tr><td>" as *u8)
661 o = irx_cat_slice_html(out, o, rb, sp[0], sp[1])
662 o = ss_cat(out, o, "</td><td>" as *u8)
663 o = irx_cat_slice_html(out, o, rb, sp[2], sp[3])
664 o = ss_cat(out, o, "</td><td>" as *u8)
665 o = ss_catn(out, o, lik)
666 o = ss_cat(out, o, "</td><td>" as *u8)
667 o = ss_catn(out, o, imp)
668 o = ss_cat(out, o, "</td><td><b>" as *u8)
669 o = ss_catn(out, o, expo)
670 o = ss_cat(out, o, "</b></td><td>" as *u8)
671 o = irx_cat_slice_html(out, o, rb, sp[8], sp[9])
672 o = ss_cat(out, o, "</td><td>" as *u8)
673 o = irx_cat_slice_html(out, o, rb, sp[10], sp[11])
674 o = ss_cat(out, o, "</td><td>" as *u8)
675 o = irx_cat_slice_html(out, o, rb, sp[12], sp[13])
676 o = ss_cat(out, o, "</td><td>" as *u8)
677 o = irx_cat_slice_html(out, o, rb, sp[14], sp[15])
678 o = ss_cat(out, o, "</td><td>" as *u8)
679 o = irx_cat_slice_html(out, o, rb, sp[16], sp[17])
680 o = ss_cat(out, o, "</td><td>" as *u8)
681 o = irx_cat_slice_html(out, o, rb, sp[18], sp[19])
682 o = ss_cat(out, o, "</td></tr>" as *u8)
683 }
684 }
685 j = le2 + 1
686 }
687 o = ss_cat(out, o, "</table><h2>Decision / ADL registry</h2><p>Architecture Decision Log -- query before proposing, so a settled decision is never re-litigated. superseded_by is DERIVED (any decision whose supersedes points here); a dangling supersedes reference fails selftest T8.</p><table><tr><th>id</th><th>status</th><th>driver</th><th>date</th><th>title</th><th>context</th><th>decision</th><th>supersedes</th><th>superseded_by</th><th>note</th></tr>" as *u8)
688 var di: i64 = 0
689 while di < dn {
690 var dle: i64 = di
691 var ds: i64 = 1
692 while ds == 1 { if dle >= dn { ds = 0 } else { if db[dle] == (IRX_NL as u8) { ds = 0 } else { dle = dle + 1 } } }
693 if dle > di {
694 let dnc: i64 = irx_cols(db, di, dle, sp)
695 if dnc == IRX_DEC_NCOL {
696 o = ss_cat(out, o, "<tr><td>" as *u8)
697 o = irx_cat_slice_html(out, o, db, sp[0], sp[1])
698 o = ss_cat(out, o, "</td><td>" as *u8)
699 o = irx_cat_slice_html(out, o, db, sp[4], sp[5])
700 o = ss_cat(out, o, "</td><td>" as *u8)
701 o = irx_cat_slice_html(out, o, db, sp[6], sp[7])
702 o = ss_cat(out, o, "</td><td>" as *u8)
703 o = irx_cat_slice_html(out, o, db, sp[8], sp[9])
704 o = ss_cat(out, o, "</td><td>" as *u8)
705 o = irx_cat_slice_html(out, o, db, sp[2], sp[3])
706 o = ss_cat(out, o, "</td><td>" as *u8)
707 o = irx_cat_slice_html(out, o, db, sp[10], sp[11])
708 o = ss_cat(out, o, "</td><td>" as *u8)
709 o = irx_cat_slice_html(out, o, db, sp[12], sp[13])
710 o = ss_cat(out, o, "</td><td>" as *u8)
711 o = irx_cat_slice_html(out, o, db, sp[14], sp[15])
712 o = ss_cat(out, o, "</td><td><b>" as *u8)
713 o = irx_page_superseded_by_html(out, o, db, dn, sp[0], sp[1])
714 o = ss_cat(out, o, "</b></td><td>" as *u8)
715 o = irx_cat_slice_html(out, o, db, sp[16], sp[17])
716 o = ss_cat(out, o, "</td></tr>" as *u8)
717 }
718 }
719 di = dle + 1
720 }
721 o = ss_cat(out, o, "</table><p>generated_epoch=" as *u8)
722 let ep: i64 = sys_now_realtime_sec()
723 o = ss_catn(out, o, ep)
724 o = ss_cat(out, o, " by nx_info_registry page</p></body></html>" as *u8)
725 let fd: i64 = sys_openat_wr("registries_stage.html" as *u8, IRX_FMODE)
726 if fd < 0 { irx_werr("page: cannot open registries_stage.html\n" as *u8); sys_exit(1) }
727 sys_write(fd, out, o)
728 sys_close(fd)
729 let m: *u8 = sys_mmap(IRX_MAGIC_4096)
730 var mo: i64 = ss_cat(m, 0, "PAGE-EMITTED registries_stage.html bytes=" as *u8)
731 mo = ss_catn(m, mo, o)
732 mo = irx_b(m, mo, IRX_NL)
733 sys_write(1, m, mo)
734 return 0
735}
736func irx_do_selftest() -> i64 {
737 let fb: *u8 = sys_mmap(IRX_CAP)
738 let fn2: i64 = sts_load("knowledge/store/featreg-" as *u8, fb, IRX_CAP - IRX_MAGIC_4096)
739 let rb: *u8 = sys_mmap(IRX_CAP)
740 let rn: i64 = sts_load("knowledge/store/riskreg-" as *u8, rb, IRX_CAP - IRX_MAGIC_4096)
741 let db: *u8 = sys_mmap(IRX_CAP)
742 let dn: i64 = sts_load("knowledge/store/decreg-" as *u8, db, IRX_CAP - IRX_MAGIC_4096)
743 let sp: *i64 = sys_mmap(IRX_SP2) as *i64
744 var frows: i64 = 0
745 var fmal: i64 = 0
746 var neghits: i64 = 0
747 var poshits: i64 = 0
748 if fn2 > 0 {
749 var i: i64 = 0
750 while i < fn2 {
751 var le: i64 = i
752 var s: i64 = 1
753 while s == 1 { if le >= fn2 { s = 0 } else { if fb[le] == (IRX_NL as u8) { s = 0 } else { le = le + 1 } } }
754 if le > i {
755 frows = frows + 1
756 let nc: i64 = irx_cols(fb, i, le, sp)
757 if nc != IRX_FEAT_NCOL { fmal = fmal + 1 }
758 let hneg: i64 = irx_find_sub(fb, i, le, "zqxnegcontrolzqx" as *u8)
759 if hneg == 1 { neghits = neghits + 1 }
760 let hpos: i64 = irx_find_sub(fb, i, le, "FR" as *u8)
761 if hpos == 1 { poshits = poshits + 1 }
762 }
763 i = le + 1
764 }
765 }
766 var rrows: i64 = 0
767 var rmal: i64 = 0
768 var numbad: i64 = 0
769 var maxexpo: i64 = 0
770 if rn > 0 {
771 var j: i64 = 0
772 while j < rn {
773 var le2: i64 = j
774 var s2: i64 = 1
775 while s2 == 1 { if le2 >= rn { s2 = 0 } else { if rb[le2] == (IRX_NL as u8) { s2 = 0 } else { le2 = le2 + 1 } } }
776 if le2 > j {
777 rrows = rrows + 1
778 let nc2: i64 = irx_cols(rb, j, le2, sp)
779 if nc2 != IRX_RISK_NCOL { rmal = rmal + 1 } else {
780 let lik: i64 = irx_atoi_slice(rb, sp[4], sp[5])
781 let imp: i64 = irx_atoi_slice(rb, sp[6], sp[7])
782 if lik < 1 { numbad = numbad + 1 }
783 if lik > 9 { numbad = numbad + 1 }
784 if imp < 1 { numbad = numbad + 1 }
785 if imp > 9 { numbad = numbad + 1 }
786 let expo: i64 = lik * imp
787 if expo > maxexpo { maxexpo = expo }
788 }
789 }
790 j = le2 + 1
791 }
792 }
793 var pass: i64 = 0
794 if fn2 > 0 { if frows > 0 { if fmal == 0 { pass = pass + 1; irx_werr("T1 featreg loads, all rows 9-col: PASS\n" as *u8) } } }
795 if pass < 1 { irx_werr("T1 featreg structural: FAIL\n" as *u8) }
796 var p2: i64 = 0
797 if rn > 0 { if rrows > 0 { if rmal == 0 { p2 = 1; irx_werr("T2 riskreg loads, all rows 10-col: PASS\n" as *u8) } } }
798 if p2 == 0 { irx_werr("T2 riskreg structural: FAIL\n" as *u8) }
799 pass = pass + p2
800 var p3: i64 = 0
801 if rrows > 0 { if numbad == 0 { p3 = 1; irx_werr("T3 likelihood+impact all 1..9: PASS\n" as *u8) } }
802 if p3 == 0 { irx_werr("T3 likelihood+impact range: FAIL\n" as *u8) }
803 pass = pass + p3
804 var p4: i64 = 0
805 if neghits == 0 { p4 = 1; irx_werr("T4 negative-control query matches 0: PASS\n" as *u8) }
806 if p4 == 0 { irx_werr("T4 negative-control: FAIL\n" as *u8) }
807 pass = pass + p4
808 var p5: i64 = 0
809 if poshits > 0 { p5 = 1; irx_werr("T5 positive query FR matches: PASS\n" as *u8) }
810 if p5 == 0 { irx_werr("T5 positive query: FAIL\n" as *u8) }
811 pass = pass + p5
812 var p6: i64 = 0
813 if maxexpo > 0 { p6 = 1; irx_werr("T6 derived exposure nonzero: PASS\n" as *u8) }
814 if p6 == 0 { irx_werr("T6 derived exposure: FAIL\n" as *u8) }
815 pass = pass + p6
816 var drows: i64 = 0
817 var dmal: i64 = 0
818 var dlinks: i64 = 0
819 if dn > 0 {
820 var kk: i64 = 0
821 while kk < dn {
822 var dle: i64 = kk
823 var dss: i64 = 1
824 while dss == 1 { if dle >= dn { dss = 0 } else { if db[dle] == (IRX_NL as u8) { dss = 0 } else { dle = dle + 1 } } }
825 if dle > kk {
826 drows = drows + 1
827 let dnc: i64 = irx_cols(db, kk, dle, sp)
828 if dnc != IRX_DEC_NCOL { dmal = dmal + 1 } else {
829 var isnone: i64 = 0
830 if sp[15] - sp[14] == 1 { if db[sp[14]] == (45 as u8) { isnone = 1 } }
831 if isnone == 0 { dlinks = dlinks + 1 }
832 }
833 }
834 kk = dle + 1
835 }
836 }
837 let ddangle: i64 = irx_dec_dangling(db, dn)
838 var p7: i64 = 0
839 if dn > 0 { if drows > 0 { if dmal == 0 { p7 = 1; irx_werr("T7 decreg loads, all rows 9-col: PASS\n" as *u8) } } }
840 if p7 == 0 { irx_werr("T7 decreg structural: FAIL\n" as *u8) }
841 pass = pass + p7
842 var p8: i64 = 0
843 if dlinks > 0 { if ddangle == 0 { p8 = 1; irx_werr("T8 supersedes chain sound (links>0 AND dangling=0): PASS\n" as *u8) } }
844 if p8 == 0 { irx_werr("T8 supersedes chain integrity: FAIL\n" as *u8) }
845 pass = pass + p8
846 let m: *u8 = sys_mmap(IRX_MAGIC_4096)
847 var mo: i64 = ss_cat(m, 0, "SELFTEST " as *u8)
848 mo = ss_catn(m, mo, pass)
849 mo = ss_cat(m, mo, "/8 VERDICT=" as *u8)
850 if pass == 8 { mo = ss_cat(m, mo, "GREEN" as *u8) } else { mo = ss_cat(m, mo, "RED" as *u8) }
851 mo = irx_b(m, mo, IRX_NL)
852 sys_write(1, m, mo)
853 if pass == 8 { sys_exit(0) }
854 sys_exit(IRX_EXIT_RED)
855 return 0
856}
857
858func main(argc: i64, argv: *i64) -> i64 {
859 if argc < 2 { irx_werr("usage: nx_info_registry features|risks|decisions [query] | board | page | selftest\n" as *u8); sys_exit(IRX_EXIT_USAGE); return IRX_EXIT_USAGE }
860 let verb: *u8 = argv[1] as *u8
861 if irx_eqs("features" as *u8, verb) == 1 {
862 var hasq: i64 = 0
863 var q: *u8 = "none" as *u8
864 if argc > 2 { hasq = 1; q = argv[2] as *u8 }
865 irx_emit_registry(1, q, hasq)
866 sys_exit(0)
867 return 0
868 }
869 if irx_eqs("risks" as *u8, verb) == 1 {
870 var hasq2: i64 = 0
871 var q2: *u8 = "none" as *u8
872 if argc > 2 { hasq2 = 1; q2 = argv[2] as *u8 }
873 irx_emit_registry(0, q2, hasq2)
874 sys_exit(0)
875 return 0
876 }
877 if irx_eqs("decisions" as *u8, verb) == 1 {
878 var hasq3: i64 = 0
879 var q3: *u8 = "none" as *u8
880 if argc > 2 { hasq3 = 1; q3 = argv[2] as *u8 }
881 irx_emit_decisions(q3, hasq3)
882 sys_exit(0)
883 return 0
884 }
885 if irx_eqs("board" as *u8, verb) == 1 { irx_do_board(); sys_exit(0); return 0 }
886 if irx_eqs("page" as *u8, verb) == 1 { irx_do_page(); sys_exit(0); return 0 }
887 if irx_eqs("selftest" as *u8, verb) == 1 { irx_do_selftest(); sys_exit(0); return 0 }
888 irx_werr("usage: nx_info_registry features|risks|decisions [query] | board | page | selftest\n" as *u8)
889 sys_exit(IRX_EXIT_USAGE)
890 return IRX_EXIT_USAGE
891}