code wiki / _hdl_build / nx_registrymine.nx
nx_registrymine.nx source
↩ module page · 367 lines · 15890 B
1// nx_registrymine.nx -- REGISTRY-PLANE MINER (miner-sota MS06d, 2026-07-23) closing the census's last
2// two uncovered classes in ONE organ: MC07 capabilities (bigrock-) and MC11 residual-catalog (minergap-).
3// Both share the canonical registry row shape, so this is deliberately GENERIC (raci-, commontask-,
4// work- fit it too) rather than two near-identical organs -- rule-15 applied BEFORE the duplication.
5// It answers the question a registry cannot answer about itself: WHO OWNS WHAT, and what is ORPHANED.
6// UNOWNED = owner is "-" or empty (a capability nobody is accountable for -- the real find)
7// UNSCOPED = scope is "-" or empty (a row that cannot be routed to a lane)
8// plus per-owner load (total + open), status distribution, severity distribution, owned_permil.
9// Source is a seg-store plane via the ALLOWLIST-RESOLVED loader, or a FILE when loader is "-"
10// (deterministic gate fixtures). Composes nx_sovjson_lib (sj_*). Read-only. No hw writes (Rule 26).
11// mine <source> [loader|-] [minsup] -> JSON: totals, by_owner ranked, by_status, sev, gaps
12// selftest <scratch-prefix> -> gate T1..T8
13// row cols: id TAB title TAB sev TAB status TAB owner TAB scope TAB note
14// license_tier: ORIGINAL
15import "nx_sovjson_lib.nx"
16import "nx_syscalls.nx"
17import "nx_gate_verdict.nx"
18import "nx_tool_run.nx"
19const RM_MAGIC_4088: i64 = 4088
20
21const RM_CAP: i64 = 1048576
22const RM_OUT: i64 = 65536
23const RM_PATH: i64 = 512
24const RM_SLOTS: i64 = 256
25const RM_TOPN: i64 = 20
26const RM_ALLOW: i64 = 131072
27const RM_PERMIL: i64 = 1000
28const RM_SEVN: i64 = 12
29const RM_NAME_MAX: i64 = 120
30const RM_MODE_644: i64 = 420
31
32func rm_read(path: *u8, buf: *u8, cap: i64) -> i64 {
33 let fd: i64 = sys_openat_rd(path)
34 if fd < 0 { return -1 }
35 var n: i64 = 0
36 var go: i64 = 1
37 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64)+n) as *u8, cap-n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } }
38 sys_close(fd)
39 return n
40}
41func rm_find(q: *u8, n: i64, lit: *u8) -> i64 {
42 let ll: i64 = sj_vlen(lit)
43 if ll == 0 { return 0 }
44 var i: i64 = 0
45 while i + ll <= n {
46 var k: i64 = 0
47 var ok: i64 = 1
48 while k < ll { if q[i+k] != lit[k] { ok = 0; k = ll } else { k = k + 1 } }
49 if ok == 1 { return 1 }
50 i = i + 1
51 }
52 return 0
53}
54// DELEGATES to the shared base (rule-15 extraction 2026-07-23)
55func rm_allow_path(name: *u8, outp: *u8) -> i64 { return sj_allow_path(name, outp) }
56func rm_key(d: *u8, o: i64, name: *u8) -> i64 {
57 d[o] = 34 as u8
58 var p: i64 = o + 1
59 p = sj_cat(d, p, name)
60 d[p] = 34 as u8
61 p = p + 1
62 d[p] = 58 as u8
63 p = p + 1
64 return p
65}
66// a field is ABSENT when it is empty or a bare "-"
67func rm_absent(q: *u8, s: i64, e: i64) -> i64 {
68 if e <= s { return 1 }
69 if e - s == 1 { if q[s] == (45 as u8) { return 1 } }
70 return 0
71}
72// intern a span into a parallel table; returns index or -1 when full
73func rm_intern(q: *u8, cs: i64, ce: i64, ss: *i64, se: *i64, np: *i64) -> i64 {
74 var k: i64 = 0
75 while k < np[0] {
76 if ce - cs == se[k] - ss[k] {
77 var m: i64 = 0
78 var eq: i64 = 1
79 while m < ce - cs { if q[cs+m] != q[ss[k]+m] { eq = 0; m = ce - cs } else { m = m + 1 } }
80 if eq == 1 { return k }
81 }
82 k = k + 1
83 }
84 if np[0] >= RM_SLOTS { return -1 }
85 ss[np[0]] = cs
86 se[np[0]] = ce
87 np[0] = np[0] + 1
88 return np[0] - 1
89}
90func rm_load(src: *u8, loader: *u8, buf: *u8, lcx: *i64) -> i64 {
91 lcx[0] = 0
92 if sj_lit_eq(loader, 0, sj_vlen(loader), "-" as *u8) == 1 {
93 let n: i64 = rm_read(src, buf, RM_CAP - 8)
94 if n <= 0 { return -1 }
95 return n
96 }
97 let lp: *u8 = sys_mmap(RM_PATH)
98 if rm_allow_path(loader, lp) == 0 { return -2 }
99 lcx[0] = 1
100 let av: *i64 = sys_mmap(64) as *i64
101 av[0] = lp as i64
102 av[1] = src as i64
103 av[2] = "load" as *u8 as i64
104 av[3] = 0
105 let cl: *i64 = sys_mmap(16) as *i64
106 let ex: i64 = tr_run_capture(lp, av, buf, RM_CAP - 8, cl)
107 if ex != 0 { return -3 }
108 if cl[0] <= 0 { return -1 }
109 return cl[0]
110}
111func rm_mine_json(src: *u8, loader: *u8, minsup: i64, d: *u8) -> i64 {
112 let q: *u8 = sys_mmap(RM_CAP)
113 let lcx: *i64 = sys_mmap(16) as *i64
114 let n: i64 = rm_load(src, loader, q, lcx)
115 if n < 0 { return n }
116 let ows: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
117 let owe: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
118 let owc: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
119 let owo: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
120 let nown: *i64 = sys_mmap(16) as *i64
121 let sts: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
122 let ste: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
123 let stc: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
124 let nsts: *i64 = sys_mmap(16) as *i64
125 let sevc: *i64 = sys_mmap(8 * RM_SEVN) as *i64
126 let done: *i64 = sys_mmap(8 * RM_SLOTS) as *i64
127 let sp: *i64 = sys_mmap(16) as *i64
128 var rows: i64 = 0
129 var malformed: i64 = 0
130 var unowned: i64 = 0
131 var unscoped: i64 = 0
132 var capped: i64 = 0
133 var i: i64 = 0
134 while i < n {
135 let le: i64 = sj_le(q, i, n)
136 var ok: i64 = 0
137 var cmt: i64 = 0
138 if le > i { if q[i] == (35 as u8) { cmt = 1 } }
139 if le > i { if cmt == 0 { if sj_col(q, i, le, 4, sp) == 1 { ok = 1 } } }
140 if ok == 0 { if le > i { if cmt == 0 { malformed = malformed + 1 } } } else {
141 rows = rows + 1
142 // owner (col 4)
143 let os: i64 = sp[0]
144 let oe: i64 = sp[1]
145 if rm_absent(q, os, oe) == 1 { unowned = unowned + 1 } else {
146 let oi: i64 = rm_intern(q, os, oe, ows, owe, nown)
147 if oi < 0 { capped = 1 } else { owc[oi] = owc[oi] + 1 }
148 }
149 // status (col 3)
150 var isopen: i64 = 0
151 if sj_col(q, i, le, 3, sp) == 1 {
152 if sj_lit_eq(q, sp[0], sp[1], "O" as *u8) == 1 { isopen = 1 }
153 if sj_lit_eq(q, sp[0], sp[1], "open" as *u8) == 1 { isopen = 1 }
154 let si: i64 = rm_intern(q, sp[0], sp[1], sts, ste, nsts)
155 if si < 0 { capped = 1 } else { stc[si] = stc[si] + 1 }
156 }
157 if isopen == 1 { if rm_absent(q, os, oe) == 0 {
158 let oi2: i64 = rm_intern(q, os, oe, ows, owe, nown)
159 if oi2 >= 0 { owo[oi2] = owo[oi2] + 1 }
160 } }
161 // scope (col 5)
162 if sj_col(q, i, le, 5, sp) == 1 {
163 if rm_absent(q, sp[0], sp[1]) == 1 { unscoped = unscoped + 1 }
164 } else { unscoped = unscoped + 1 }
165 // severity (col 2)
166 if sj_col(q, i, le, 2, sp) == 1 {
167 let sv: i64 = sj_atoi_span(q, sp[0], sp[1])
168 if sv >= 0 { if sv < RM_SEVN { sevc[sv] = sevc[sv] + 1 } }
169 }
170 }
171 i = le + 1
172 }
173 var p: i64 = 0
174 d[p] = 123 as u8; p = p + 1
175 p = rm_key(d, p, "v" as *u8); p = sj_catn(d, p, 1); d[p] = 44 as u8; p = p + 1
176 p = rm_key(d, p, "tool" as *u8)
177 d[p] = 34 as u8; p = p + 1
178 p = sj_cat(d, p, "nx_registrymine" as *u8)
179 d[p] = 34 as u8; p = p + 1
180 d[p] = 44 as u8; p = p + 1
181 p = rm_key(d, p, "averb" as *u8)
182 d[p] = 34 as u8; p = p + 1
183 p = sj_cat(d, p, "mine" as *u8)
184 d[p] = 34 as u8; p = p + 1
185 d[p] = 44 as u8; p = p + 1
186 p = rm_key(d, p, "source" as *u8)
187 d[p] = 34 as u8; p = p + 1
188 p = sj_cat_esc(d, p, src, 0, sj_vlen(src), RM_NAME_MAX)
189 d[p] = 34 as u8; p = p + 1
190 d[p] = 44 as u8; p = p + 1
191 p = rm_key(d, p, "loader_resolved" as *u8); p = sj_catn(d, p, lcx[0]); d[p] = 44 as u8; p = p + 1
192 p = rm_key(d, p, "rows" as *u8); p = sj_catn(d, p, rows); d[p] = 44 as u8; p = p + 1
193 p = rm_key(d, p, "malformed" as *u8); p = sj_catn(d, p, malformed); d[p] = 44 as u8; p = p + 1
194 p = rm_key(d, p, "owners" as *u8); p = sj_catn(d, p, nown[0]); d[p] = 44 as u8; p = p + 1
195 p = rm_key(d, p, "unowned" as *u8); p = sj_catn(d, p, unowned); d[p] = 44 as u8; p = p + 1
196 p = rm_key(d, p, "unscoped" as *u8); p = sj_catn(d, p, unscoped); d[p] = 44 as u8; p = p + 1
197 var op: i64 = 0 - 1
198 if rows > 0 { op = (rows - unowned) * RM_PERMIL / rows }
199 p = rm_key(d, p, "owned_permil" as *u8); p = sj_catn(d, p, op); d[p] = 44 as u8; p = p + 1
200 // by_owner ranked by total desc
201 p = rm_key(d, p, "by_owner" as *u8)
202 d[p] = 91 as u8; p = p + 1
203 var shown: i64 = 0
204 var below: i64 = 0
205 var efirst: i64 = 1
206 var pass: i64 = 0
207 while pass < nown[0] {
208 var mi: i64 = 0 - 1
209 var mx: i64 = 0 - 1
210 var k: i64 = 0
211 while k < nown[0] {
212 if done[k] == 0 { if owc[k] > mx { mx = owc[k]; mi = k } }
213 k = k + 1
214 }
215 if mi >= 0 {
216 done[mi] = 1
217 if mx < minsup { below = below + 1 } else {
218 if shown < RM_TOPN {
219 if efirst == 0 { d[p] = 44 as u8; p = p + 1 }
220 efirst = 0
221 d[p] = 123 as u8; p = p + 1
222 p = rm_key(d, p, "owner" as *u8)
223 d[p] = 34 as u8; p = p + 1
224 p = sj_cat_esc(d, p, q, ows[mi], owe[mi], RM_NAME_MAX)
225 d[p] = 34 as u8; p = p + 1
226 d[p] = 44 as u8; p = p + 1
227 p = rm_key(d, p, "rows" as *u8); p = sj_catn(d, p, owc[mi]); d[p] = 44 as u8; p = p + 1
228 p = rm_key(d, p, "open" as *u8); p = sj_catn(d, p, owo[mi])
229 d[p] = 125 as u8; p = p + 1
230 shown = shown + 1
231 }
232 }
233 }
234 pass = pass + 1
235 }
236 d[p] = 93 as u8; p = p + 1
237 d[p] = 44 as u8; p = p + 1
238 p = rm_key(d, p, "owners_shown" as *u8); p = sj_catn(d, p, shown); d[p] = 44 as u8; p = p + 1
239 p = rm_key(d, p, "owners_below_minsup" as *u8); p = sj_catn(d, p, below); d[p] = 44 as u8; p = p + 1
240 // by_status (declaration order)
241 p = rm_key(d, p, "by_status" as *u8)
242 d[p] = 91 as u8; p = p + 1
243 var si2: i64 = 0
244 var sfirst: i64 = 1
245 while si2 < nsts[0] {
246 if sfirst == 0 { d[p] = 44 as u8; p = p + 1 }
247 sfirst = 0
248 d[p] = 123 as u8; p = p + 1
249 p = rm_key(d, p, "status" as *u8)
250 d[p] = 34 as u8; p = p + 1
251 p = sj_cat_esc(d, p, q, sts[si2], ste[si2], RM_NAME_MAX)
252 d[p] = 34 as u8; p = p + 1
253 d[p] = 44 as u8; p = p + 1
254 p = rm_key(d, p, "rows" as *u8); p = sj_catn(d, p, stc[si2])
255 d[p] = 125 as u8; p = p + 1
256 si2 = si2 + 1
257 }
258 d[p] = 93 as u8; p = p + 1
259 d[p] = 44 as u8; p = p + 1
260 p = rm_key(d, p, "sev" as *u8)
261 d[p] = 91 as u8; p = p + 1
262 var sv2: i64 = 0
263 var vfirst: i64 = 1
264 while sv2 < RM_SEVN {
265 if sevc[sv2] > 0 {
266 if vfirst == 0 { d[p] = 44 as u8; p = p + 1 }
267 vfirst = 0
268 d[p] = 123 as u8; p = p + 1
269 p = rm_key(d, p, "sev" as *u8); p = sj_catn(d, p, sv2); d[p] = 44 as u8; p = p + 1
270 p = rm_key(d, p, "rows" as *u8); p = sj_catn(d, p, sevc[sv2])
271 d[p] = 125 as u8; p = p + 1
272 }
273 sv2 = sv2 + 1
274 }
275 d[p] = 93 as u8; p = p + 1
276 d[p] = 44 as u8; p = p + 1
277 p = rm_key(d, p, "slots_capped" as *u8); p = sj_catn(d, p, capped)
278 d[p] = 125 as u8; p = p + 1
279 d[p] = 10 as u8; p = p + 1
280 return p
281}
282func rm_selftest(prefix: *u8) -> i64 {
283 let ctr: *i64 = gv_ctr()
284 gv_head("nx_registrymine selftest -- ownership-gap teeth (a dash owner is UNOWNED, not an owner)" as *u8)
285 let fx: *u8 = sys_mmap(RM_PATH)
286 var o: i64 = sj_cat(fx, 0, prefix)
287 o = sj_catn(fx, o, sys_now_realtime_sec())
288 o = sj_cat(fx, o, ".rm" as *u8)
289 fx[o] = 0 as u8
290 let miss: *u8 = sys_mmap(RM_PATH)
291 o = sj_cat(miss, 0, fx)
292 o = sj_cat(miss, o, ".absent" as *u8)
293 miss[o] = 0 as u8
294 // 6 rows: pm owns 3 (2 open), hr owns 1 open, 1 dash-owner, 1 empty-owner; 2 unscoped; 1 malformed
295 let fd: i64 = sys_openat_wr(fx, RM_MODE_644)
296 let lb: *u8 = sys_mmap(RM_MAGIC_4088)
297 var lo: i64 = sj_cat(lb, 0, "# fixture\n" as *u8)
298 lo = sj_cat(lb, lo, "R1\tcap one\t8\tO\tpm\tlaneA\tnote\n" as *u8)
299 lo = sj_cat(lb, lo, "R2\tcap two\t5\tO\tpm\tlaneA\tnote\n" as *u8)
300 lo = sj_cat(lb, lo, "R3\tcap three\t5\tD\tpm\tlaneB\tnote\n" as *u8)
301 lo = sj_cat(lb, lo, "R4\tcap four\t8\tO\thr\t-\tnote\n" as *u8)
302 lo = sj_cat(lb, lo, "R5\tcap five\t3\tO\t-\tlaneC\tnobody owns this\n" as *u8)
303 lo = sj_cat(lb, lo, "R6\tcap six\t3\tD\t\t\tempty owner and scope\n" as *u8)
304 lo = sj_cat(lb, lo, "junkrow\n" as *u8)
305 sys_write(fd, lb, lo)
306 sys_close(fd)
307 let d: *u8 = sys_mmap(RM_OUT)
308 let r1: i64 = rm_mine_json(miss, "-" as *u8, 1, d)
309 var ok1: i64 = 0
310 if r1 < 0 { ok1 = 1 }
311 gv_check("T1 missing source refused fail closed" as *u8, ok1, ctr)
312 let dl: i64 = rm_mine_json(fx, "-" as *u8, 1, d)
313 var ok2: i64 = 0
314 if dl > 0 { if rm_find(d, dl, "\"rows\":6,\"malformed\":1" as *u8) == 1 { ok2 = 1 } }
315 gv_check("T2 exact rows 6 with the junk row counted malformed (comment skipped)" as *u8, ok2, ctr)
316 var ok3: i64 = 0
317 if rm_find(d, dl, "\"unowned\":2" as *u8) == 1 { if rm_find(d, dl, "\"owners\":2" as *u8) == 1 { ok3 = 1 } }
318 gv_check("T3 BOTH a dash owner and an empty owner count UNOWNED, neither becomes an owner" as *u8, ok3, ctr)
319 var ok4: i64 = 0
320 if rm_find(d, dl, "\"owner\":\"pm\",\"rows\":3,\"open\":2" as *u8) == 1 { ok4 = 1 }
321 gv_check("T4 per-owner load exact: pm 3 rows of which 2 open" as *u8, ok4, ctr)
322 var ok5: i64 = 0
323 if rm_find(d, dl, "\"status\":\"O\",\"rows\":4" as *u8) == 1 { if rm_find(d, dl, "\"status\":\"D\",\"rows\":2" as *u8) == 1 { ok5 = 1 } }
324 gv_check("T5 status distribution exact 4 open 2 done" as *u8, ok5, ctr)
325 var ok6: i64 = 0
326 if rm_find(d, dl, "\"owned_permil\":666" as *u8) == 1 { ok6 = 1 }
327 gv_check("T6 owned_permil exact 666 (4 owned of 6)" as *u8, ok6, ctr)
328 var ok7: i64 = 0
329 if rm_find(d, dl, "\"unscoped\":2" as *u8) == 1 { ok7 = 1 }
330 gv_check("T7 unscoped exact 2 (dash scope AND empty scope)" as *u8, ok7, ctr)
331 let dl8: i64 = rm_mine_json(fx, "-" as *u8, 2, d)
332 var ok8: i64 = 0
333 if dl8 > 0 { if rm_find(d, dl8, "\"owner\":\"hr\"" as *u8) == 0 { if rm_find(d, dl8, "\"owners_below_minsup\":1" as *u8) == 1 { ok8 = 1 } } }
334 gv_check("T8 minsup 2 suppresses the single-row owner and DECLARES it" as *u8, ok8, ctr)
335 let rc: i64 = gv_verdict("REGISTRYMINE-GATE" as *u8, ctr, "registry mining: unowned and unscoped surfaced, per-owner load exact, suppression declared" as *u8)
336 return rc
337}
338
339func main(argc: i64, argv: *i64) -> i64 {
340 if argc < 3 { sj_puts("usage: nx_registrymine {mine <source> [loader|-] [minsup] | selftest <scratch-prefix>}\n" as *u8); sys_exit(2); return 2 }
341 let verb: *u8 = argv[1] as *u8
342 let vl: i64 = sj_vlen(verb)
343 if sj_lit_eq(verb, 0, vl, "selftest" as *u8) == 1 {
344 let rc: i64 = rm_selftest(argv[2] as *u8)
345 sys_exit(rc)
346 return rc
347 }
348 if sj_lit_eq(verb, 0, vl, "mine" as *u8) == 1 {
349 let loader: *u8 = sys_mmap(128)
350 var lo: i64 = 0
351 if argc >= 4 { lo = sj_cat(loader, 0, argv[3] as *u8) } else { lo = sj_cat(loader, 0, "nx_store_put" as *u8) }
352 loader[lo] = 0 as u8
353 var minsup: i64 = 1
354 if argc >= 5 { let mz: i64 = sj_atoi_z(argv[4] as *u8); if mz > 0 { minsup = mz } }
355 let d: *u8 = sys_mmap(RM_OUT)
356 let dl: i64 = rm_mine_json(argv[2] as *u8, loader, minsup, d)
357 if dl == (0 - 2) { sj_puts("REFUSED loader not in the allowlist\n" as *u8); sys_exit(3); return 3 }
358 if dl == (0 - 3) { sj_puts("REFUSED loader exited nonzero\n" as *u8); sys_exit(3); return 3 }
359 if dl < 0 { sj_puts("REFUSED source missing or empty\n" as *u8); sys_exit(3); return 3 }
360 sys_write(1, d, dl)
361 sys_exit(0)
362 return 0
363 }
364 sj_puts("unknown verb\n" as *u8)
365 sys_exit(2)
366 return 2
367}