code wiki / _hdl_build / nx_minerhub.nx
nx_minerhub.nx source
↩ module page · 508 lines · 24396 B
1// nx_minerhub.nx -- MINER SYNTHESIS HUB (miner-sota, 2026-07-23). The measurement layer's FRONT DOOR.
2// The 8 miners each emit JSON; nobody COMPOSED them. This forks each declared miner (allowlist-resolved
3// via the SHARED sj_allow_path), extracts its ONE headline metric, classifies it against DATA-DRIVEN
4// thresholds (GOOD/WATCH/BAD), and emits a single ecosystem-health index + a page. OO by construction:
5// it READS the miners, duplicates none of them; a new miner = ONE conf row, zero code. now-free/pure at
6// the parser (gate); the fork-compose path runs live. Composes nx_sovjson_lib. Read-only. Rule 26.
7// mine <sourceconf> -> JSON: per-source value+status + health_index_permil
8// page <sourceconf> <outfile> -> HTML board
9// selftest <scratch-prefix> -> gate T1..T9 (metric extract + classify + index math, deterministic)
10// conf cols: id TAB dir(hi|lo) TAB good TAB warn TAB metric TAB miner TAB arg1 TAB arg2 ...
11// dir hi = higher is better (coverage, green, done); lo = lower is better (unowned, eroded, dangling)
12// license_tier: ORIGINAL
13import "nx_sovjson_lib.nx"
14import "nx_syscalls.nx"
15import "nx_gate_verdict.nx"
16import "nx_tool_run.nx"
17const MH_MAGIC_1024: i64 = 1024
18
19const MH_CONF: i64 = 65536
20const MH_CAP: i64 = 262144
21const MH_OUT: i64 = 65536
22const MH_PATH: i64 = 512
23const MH_ARENA: i64 = 8192
24const MH_ARGS: i64 = 24
25const MH_ROWS: i64 = 64
26const MH_PERMIL: i64 = 1000
27const MH_NAME_MAX: i64 = 120
28const MH_MODE_644: i64 = 420
29const MH_SENT: i64 = -999999
30
31func mh_read(path: *u8, buf: *u8, cap: i64) -> i64 {
32 let fd: i64 = sys_openat_rd(path)
33 if fd < 0 { return -1 }
34 var n: i64 = 0
35 var go: i64 = 1
36 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 } }
37 sys_close(fd)
38 return n
39}
40func mh_find_from(q: *u8, from: i64, n: i64, lit: *u8) -> i64 {
41 let ll: i64 = sj_vlen(lit)
42 if ll == 0 { return -1 }
43 var i: i64 = from
44 while i + ll <= n {
45 var k: i64 = 0
46 var ok: i64 = 1
47 while k < ll { if q[i+k] != lit[k] { ok = 0; k = ll } else { k = k + 1 } }
48 if ok == 1 { return i }
49 i = i + 1
50 }
51 return -1
52}
53func mh_find(q: *u8, n: i64, lit: *u8) -> i64 {
54 if mh_find_from(q, 0, n, lit) >= 0 { return 1 }
55 return 0
56}
57// extract the integer value of "<key>": from q. foundp[0]=1 if the key is present. MH_SENT if absent.
58func mh_extract(q: *u8, n: i64, key: *u8, foundp: *i64) -> i64 {
59 let tok: *u8 = sys_mmap(256)
60 var t: i64 = 0
61 tok[t] = 34 as u8; t = t + 1
62 t = sj_cat(tok, t, key)
63 tok[t] = 34 as u8; t = t + 1
64 tok[t] = 58 as u8; t = t + 1
65 tok[t] = 0 as u8
66 let p: i64 = mh_find_from(q, 0, n, tok)
67 if p < 0 { foundp[0] = 0; return MH_SENT }
68 foundp[0] = 1
69 // skip spaces after the token, then optional minus, then digits
70 var s: i64 = p + t
71 var go: i64 = 1
72 while go == 1 { if s >= n { go = 0 } else { if q[s] == (32 as u8) { s = s + 1 } else { go = 0 } } }
73 var neg: i64 = 0
74 if s < n { if q[s] == (45 as u8) { neg = 1; s = s + 1 } }
75 var v: i64 = 0
76 var g2: i64 = 1
77 while g2 == 1 { if s >= n { g2 = 0 } else { let c: i64 = q[s] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); s = s + 1 } else { g2 = 0 } } else { g2 = 0 } } }
78 if neg == 1 { v = 0 - v }
79 return v
80}
81// 2 GOOD, 1 WATCH, 0 BAD. dir 0 = higher-better, dir 1 = lower-better.
82func mh_class(val: i64, dir: i64, good: i64, warn: i64) -> i64 {
83 if dir == 0 { if val >= good { return 2 } if val >= warn { return 1 } return 0 }
84 if val <= good { return 2 } if val <= warn { return 1 } return 0
85}
86func mh_key(d: *u8, o: i64, name: *u8) -> i64 {
87 d[o] = 34 as u8
88 var p: i64 = o + 1
89 p = sj_cat(d, p, name)
90 d[p] = 34 as u8
91 p = p + 1
92 d[p] = 58 as u8
93 p = p + 1
94 return p
95}
96func mh_status_str(d: *u8, o: i64, score: i64) -> i64 {
97 var p: i64 = o
98 d[p] = 34 as u8; p = p + 1
99 if score == 2 { p = sj_cat(d, p, "GOOD" as *u8) } else { if score == 1 { p = sj_cat(d, p, "WATCH" as *u8) } else { p = sj_cat(d, p, "BAD" as *u8) } }
100 d[p] = 34 as u8; p = p + 1
101 return p
102}
103// fork one miner row (cols 5.. = miner + args), capture, extract its metric (col 4). ran=0 on fork fail.
104func mh_run(cq: *u8, ls: i64, le: i64, valp: *i64, ranp: *i64) -> i64 {
105 ranp[0] = 0
106 valp[0] = MH_SENT
107 let sp: *i64 = sys_mmap(16) as *i64
108 if sj_col(cq, ls, le, 5, sp) == 0 { return 0 }
109 let mname: *u8 = sys_mmap(MH_PATH)
110 var k: i64 = 0
111 while sp[0]+k < sp[1] { if k < MH_PATH - 2 { mname[k] = cq[sp[0]+k] } k = k + 1 }
112 mname[k] = 0 as u8
113 let mpath: *u8 = sys_mmap(MH_PATH)
114 if sj_allow_path(mname, mpath) == 0 { return 0 }
115 let arena: *u8 = sys_mmap(MH_ARENA)
116 let av: *i64 = sys_mmap(8 * MH_ARGS) as *i64
117 av[0] = mpath as i64
118 var ac: i64 = 1
119 var ao: i64 = 0
120 var c: i64 = 6
121 var more: i64 = 1
122 while more == 1 {
123 if sj_col(cq, ls, le, c, sp) == 0 { more = 0 } else {
124 if ac >= MH_ARGS - 1 { more = 0 } else {
125 av[ac] = ((arena as i64) + ao) as i64
126 var z: i64 = sp[0]
127 while z < sp[1] { if ao < MH_ARENA - 2 { arena[ao] = cq[z]; ao = ao + 1 } z = z + 1 }
128 arena[ao] = 0 as u8; ao = ao + 1
129 ac = ac + 1
130 c = c + 1
131 }
132 }
133 }
134 av[ac] = 0
135 let cout: *u8 = sys_mmap(MH_CAP)
136 let clen: *i64 = sys_mmap(16) as *i64
137 let ex: i64 = tr_run_capture(mpath, av, cout, MH_CAP - 8, clen)
138 if ex != 0 { return 0 }
139 ranp[0] = 1
140 let metric: *u8 = sys_mmap(128)
141 if sj_col(cq, ls, le, 4, sp) == 1 {
142 var m: i64 = 0
143 while sp[0]+m < sp[1] { if m < 120 { metric[m] = cq[sp[0]+m] } m = m + 1 }
144 metric[m] = 0 as u8
145 }
146 let fnd: *i64 = sys_mmap(16) as *i64
147 valp[0] = mh_extract(cout, clen[0], metric, fnd)
148 return 1
149}
150func mh_emit(conf: *u8, wantpage: i64, outp: *u8, d: *u8) -> i64 {
151 let cb: *u8 = sys_mmap(MH_CONF)
152 let cn: i64 = mh_read(conf, cb, MH_CONF - 8)
153 if cn <= 0 { return -1 }
154 let sp: *i64 = sys_mmap(16) as *i64
155 let valp: *i64 = sys_mmap(16) as *i64
156 let ranp: *i64 = sys_mmap(16) as *i64
157 var p: i64 = 0
158 if wantpage == 0 {
159 d[p] = 123 as u8; p = p + 1
160 p = mh_key(d, p, "v" as *u8); p = sj_catn(d, p, 1); d[p] = 44 as u8; p = p + 1
161 p = mh_key(d, p, "tool" as *u8)
162 d[p] = 34 as u8; p = p + 1
163 p = sj_cat(d, p, "nx_minerhub" as *u8)
164 d[p] = 34 as u8; p = p + 1
165 d[p] = 44 as u8; p = p + 1
166 p = mh_key(d, p, "sources" as *u8)
167 d[p] = 91 as u8; p = p + 1
168 } else {
169 d[p] = 60 as u8; p = p + 1
170 d[p] = 33 as u8; p = p + 1
171 p = sj_cat(d, p, "doctype html><html><head><meta charset=\"utf-8\"><title>Miner Hub</title></head><body><h1>Ecosystem Health — Miner Hub</h1><p>each row = one class-miner's headline metric, classified GOOD/WATCH/BAD; the index is the composed health of the measurement layer.</p><table border=\"1\" cellpadding=\"5\"><tr><th>source</th><th>metric</th><th>value</th><th>status</th></tr>" as *u8)
172 }
173 var nsrc: i64 = 0
174 var ran: i64 = 0
175 var scoresum: i64 = 0
176 var good: i64 = 0
177 var watch: i64 = 0
178 var bad: i64 = 0
179 var efirst: i64 = 1
180 var i: i64 = 0
181 while i < cn {
182 let le: i64 = sj_le(cb, i, cn)
183 var ok: i64 = 0
184 if le > i { if cb[i] != (35 as u8) { if sj_col(cb, i, le, 5, sp) == 1 { ok = 1 } } }
185 if ok == 1 {
186 nsrc = nsrc + 1
187 let dir: *i64 = sys_mmap(16) as *i64
188 sj_col(cb, i, le, 1, dir)
189 var dv: i64 = 0
190 if sj_lit_eq(cb, dir[0], dir[1], "lo" as *u8) == 1 { dv = 1 }
191 let gd: *i64 = sys_mmap(16) as *i64
192 sj_col(cb, i, le, 2, gd)
193 let good_t: i64 = sj_atoi_span(cb, gd[0], gd[1])
194 sj_col(cb, i, le, 3, gd)
195 let warn_t: i64 = sj_atoi_span(cb, gd[0], gd[1])
196 mh_run(cb, i, le, valp, ranp)
197 var score: i64 = 0
198 if ranp[0] == 1 { if valp[0] != MH_SENT { score = mh_class(valp[0], dv, good_t, warn_t); ran = ran + 1 } }
199 if ranp[0] == 1 { if valp[0] != MH_SENT {
200 scoresum = scoresum + score
201 if score == 2 { good = good + 1 } else { if score == 1 { watch = watch + 1 } else { bad = bad + 1 } }
202 } }
203 if wantpage == 0 {
204 if efirst == 0 { d[p] = 44 as u8; p = p + 1 }
205 efirst = 0
206 d[p] = 123 as u8; p = p + 1
207 p = mh_key(d, p, "id" as *u8)
208 sj_col(cb, i, le, 0, sp)
209 d[p] = 34 as u8; p = p + 1
210 p = sj_cat_esc(d, p, cb, sp[0], sp[1], MH_NAME_MAX)
211 d[p] = 34 as u8; p = p + 1
212 d[p] = 44 as u8; p = p + 1
213 p = mh_key(d, p, "metric" as *u8)
214 sj_col(cb, i, le, 4, sp)
215 d[p] = 34 as u8; p = p + 1
216 p = sj_cat_esc(d, p, cb, sp[0], sp[1], MH_NAME_MAX)
217 d[p] = 34 as u8; p = p + 1
218 d[p] = 44 as u8; p = p + 1
219 p = mh_key(d, p, "value" as *u8)
220 if valp[0] == MH_SENT { p = sj_cat(d, p, "null" as *u8) } else { p = sj_catn(d, p, valp[0]) }
221 d[p] = 44 as u8; p = p + 1
222 p = mh_key(d, p, "ran" as *u8); p = sj_catn(d, p, ranp[0]); d[p] = 44 as u8; p = p + 1
223 p = mh_key(d, p, "status" as *u8)
224 p = mh_status_str(d, p, score)
225 d[p] = 125 as u8; p = p + 1
226 } else {
227 p = sj_cat(d, p, "<tr><td>" as *u8)
228 sj_col(cb, i, le, 0, sp)
229 p = sj_cat_esc(d, p, cb, sp[0], sp[1], MH_NAME_MAX)
230 p = sj_cat(d, p, "</td><td>" as *u8)
231 sj_col(cb, i, le, 4, sp)
232 p = sj_cat_esc(d, p, cb, sp[0], sp[1], MH_NAME_MAX)
233 p = sj_cat(d, p, "</td><td>" as *u8)
234 if valp[0] == MH_SENT { p = sj_cat(d, p, "n/a" as *u8) } else { p = sj_catn(d, p, valp[0]) }
235 p = sj_cat(d, p, "</td><td>" as *u8)
236 if score == 2 { p = sj_cat(d, p, "GOOD" as *u8) } else { if score == 1 { p = sj_cat(d, p, "WATCH" as *u8) } else { p = sj_cat(d, p, "BAD" as *u8) } }
237 p = sj_cat(d, p, "</td></tr>" as *u8)
238 }
239 }
240 i = le + 1
241 }
242 var idx: i64 = 0 - 1
243 if nsrc > 0 { idx = scoresum * MH_PERMIL / (2 * nsrc) }
244 if wantpage == 0 {
245 d[p] = 93 as u8; p = p + 1
246 d[p] = 44 as u8; p = p + 1
247 p = mh_key(d, p, "sources_total" as *u8); p = sj_catn(d, p, nsrc); d[p] = 44 as u8; p = p + 1
248 p = mh_key(d, p, "ran" as *u8); p = sj_catn(d, p, ran); d[p] = 44 as u8; p = p + 1
249 p = mh_key(d, p, "good" as *u8); p = sj_catn(d, p, good); d[p] = 44 as u8; p = p + 1
250 p = mh_key(d, p, "watch" as *u8); p = sj_catn(d, p, watch); d[p] = 44 as u8; p = p + 1
251 p = mh_key(d, p, "bad" as *u8); p = sj_catn(d, p, bad); d[p] = 44 as u8; p = p + 1
252 p = mh_key(d, p, "health_index_permil" as *u8); p = sj_catn(d, p, idx)
253 d[p] = 125 as u8; p = p + 1
254 d[p] = 10 as u8; p = p + 1
255 } else {
256 p = sj_cat(d, p, "</table><p style=\"font-size:48px\">health_index=" as *u8)
257 p = sj_catn(d, p, idx)
258 p = sj_cat(d, p, "‰</p><p>good=" as *u8)
259 p = sj_catn(d, p, good)
260 p = sj_cat(d, p, " watch=" as *u8)
261 p = sj_catn(d, p, watch)
262 p = sj_cat(d, p, " bad=" as *u8)
263 p = sj_catn(d, p, bad)
264 p = sj_cat(d, p, " ran=" as *u8)
265 p = sj_catn(d, p, ran)
266 p = sj_cat(d, p, "/" as *u8)
267 p = sj_catn(d, p, nsrc)
268 p = sj_cat(d, p, "</p><p><a href=\"/outsidegap\">outsidegap</a> <a href=\"/wsmine\">wsmine</a> <a href=\"/frontier\">frontier</a></p></body></html>" as *u8)
269 let fd: i64 = sys_openat_wr(outp, MH_MODE_644)
270 if fd < 0 { return -3 }
271 sys_write(fd, d, p)
272 sys_close(fd)
273 }
274 return p
275}
276// flag: each BAD source auto-files ONE intake REQ through the ALLOWLIST-RESOLVED filer. Shares mh_run +
277// mh_class with mine (the DECISION logic is DRY -- a flag can never disagree with the board). Marker
278// [HUB:<id>] makes it idempotent: one open ticket per source, no spam while it stays BAD (re-file after
279// triage-close is a declared v-next, matching the nx_feeder discipline). Filer INJECTABLE (argecho in gate).
280func mh_flag(conf: *u8, ipath: *u8, filer: *u8, d: *u8) -> i64 {
281 let cb: *u8 = sys_mmap(MH_CONF)
282 let cn: i64 = mh_read(conf, cb, MH_CONF - 8)
283 if cn <= 0 { return -1 }
284 let ib: *u8 = sys_mmap(MH_CAP)
285 let ibn: i64 = mh_read(ipath, ib, MH_CAP - 8)
286 var iblen: i64 = ibn
287 if iblen < 0 { iblen = 0 }
288 let fpath: *u8 = sys_mmap(MH_PATH)
289 let fok: i64 = sj_allow_path(filer, fpath)
290 let sp: *i64 = sys_mmap(16) as *i64
291 let valp: *i64 = sys_mmap(16) as *i64
292 let ranp: *i64 = sys_mmap(16) as *i64
293 var bad: i64 = 0
294 var flagged: i64 = 0
295 var skipped: i64 = 0
296 var i: i64 = 0
297 while i < cn {
298 let le: i64 = sj_le(cb, i, cn)
299 var ok: i64 = 0
300 if le > i { if cb[i] != (35 as u8) { if sj_col(cb, i, le, 5, sp) == 1 { ok = 1 } } }
301 if ok == 1 {
302 let dir: *i64 = sys_mmap(16) as *i64
303 sj_col(cb, i, le, 1, dir)
304 var dv: i64 = 0
305 if sj_lit_eq(cb, dir[0], dir[1], "lo" as *u8) == 1 { dv = 1 }
306 let gd: *i64 = sys_mmap(16) as *i64
307 sj_col(cb, i, le, 2, gd)
308 let good_t: i64 = sj_atoi_span(cb, gd[0], gd[1])
309 sj_col(cb, i, le, 3, gd)
310 let warn_t: i64 = sj_atoi_span(cb, gd[0], gd[1])
311 mh_run(cb, i, le, valp, ranp)
312 if ranp[0] == 1 { if valp[0] != MH_SENT {
313 let score: i64 = mh_class(valp[0], dv, good_t, warn_t)
314 if score == 0 {
315 bad = bad + 1
316 // marker [HUB:<id>]
317 let mk: *u8 = sys_mmap(256)
318 var mo: i64 = sj_cat(mk, 0, "[HUB:" as *u8)
319 sj_col(cb, i, le, 0, sp)
320 var z: i64 = sp[0]
321 while z < sp[1] { if mo < 200 { mk[mo] = cb[z]; mo = mo + 1 } z = z + 1 }
322 mk[mo] = 93 as u8; mo = mo + 1
323 mk[mo] = 0 as u8
324 var already: i64 = 0
325 if iblen > 0 { if mh_find(ib, iblen, mk) == 1 { already = 1 } }
326 if already == 1 { skipped = skipped + 1 } else { if fok == 1 {
327 let txt: *u8 = sys_mmap(MH_MAGIC_1024)
328 var to: i64 = sj_cat(txt, 0, mk)
329 to = sj_cat(txt, to, " " as *u8)
330 sj_col(cb, i, le, 4, sp)
331 var z2: i64 = sp[0]
332 while z2 < sp[1] { if to < 900 { txt[to] = cb[z2]; to = to + 1 } z2 = z2 + 1 }
333 to = sj_cat(txt, to, "=" as *u8)
334 to = sj_catn(txt, to, valp[0])
335 to = sj_cat(txt, to, " classified BAD by nx_minerhub - triage the owning class-miner's finding (see /minerhub)" as *u8)
336 txt[to] = 0 as u8
337 let av: *i64 = sys_mmap(64) as *i64
338 av[0] = fpath as i64
339 av[1] = "ask" as *u8 as i64
340 av[2] = ipath as i64
341 av[3] = "nx_minerhub" as *u8 as i64
342 av[4] = txt as i64
343 av[5] = 0
344 let cout: *u8 = sys_mmap(MH_OUT)
345 let clen: *i64 = sys_mmap(16) as *i64
346 let ex: i64 = tr_run_capture(fpath, av, cout, MH_OUT - 8, clen)
347 if ex == 0 { flagged = flagged + 1 }
348 } }
349 }
350 } }
351 }
352 i = le + 1
353 }
354 var p: i64 = 0
355 d[p] = 123 as u8; p = p + 1
356 p = mh_key(d, p, "v" as *u8); p = sj_catn(d, p, 1); d[p] = 44 as u8; p = p + 1
357 p = mh_key(d, p, "tool" as *u8)
358 d[p] = 34 as u8; p = p + 1
359 p = sj_cat(d, p, "nx_minerhub" as *u8)
360 d[p] = 34 as u8; p = p + 1
361 d[p] = 44 as u8; p = p + 1
362 p = mh_key(d, p, "averb" as *u8)
363 d[p] = 34 as u8; p = p + 1
364 p = sj_cat(d, p, "flag" as *u8)
365 d[p] = 34 as u8; p = p + 1
366 d[p] = 44 as u8; p = p + 1
367 p = mh_key(d, p, "filer_resolved" as *u8); p = sj_catn(d, p, fok); d[p] = 44 as u8; p = p + 1
368 p = mh_key(d, p, "bad" as *u8); p = sj_catn(d, p, bad); d[p] = 44 as u8; p = p + 1
369 p = mh_key(d, p, "flagged" as *u8); p = sj_catn(d, p, flagged); d[p] = 44 as u8; p = p + 1
370 p = mh_key(d, p, "skipped_already" as *u8); p = sj_catn(d, p, skipped)
371 d[p] = 125 as u8; p = p + 1
372 d[p] = 10 as u8; p = p + 1
373 return p
374}
375func mh_selftest(prefix: *u8) -> i64 {
376 let ctr: *i64 = gv_ctr()
377 gv_head("nx_minerhub selftest -- metric extract + classify + index math (deterministic, no fork)" as *u8)
378 let js: *u8 = sys_mmap(MH_MAGIC_1024)
379 var o: i64 = sj_cat(js, 0, "{\"v\":1,\"coverage_permil\":1000,\"eat_permil\":283,\"avg_hold_s\":-1,\"eroded\":0}\n" as *u8)
380 let jn: i64 = o
381 let fnd: *i64 = sys_mmap(16) as *i64
382 // T1 extract a present positive key
383 var ok1: i64 = 0
384 if mh_extract(js, jn, "coverage_permil" as *u8, fnd) == 1000 { if fnd[0] == 1 { ok1 = 1 } }
385 gv_check("T1 extract exact value of a present key (1000)" as *u8, ok1, ctr)
386 // T2 a substring key must NOT match a longer key (permil vs coverage_permil)
387 var ok2: i64 = 0
388 if mh_extract(js, jn, "eat_permil" as *u8, fnd) == 283 { ok2 = 1 }
389 gv_check("T2 key match is exact-boundary (eat_permil=283, not confused with coverage_permil)" as *u8, ok2, ctr)
390 // T3 negative value parsed as negative (refusal sentinel from a miner)
391 var ok3: i64 = 0
392 if mh_extract(js, jn, "avg_hold_s" as *u8, fnd) == (0 - 1) { ok3 = 1 }
393 gv_check("T3 negative value parsed as -1 (a miner refusal survives synthesis)" as *u8, ok3, ctr)
394 // T4 absent key -> found=0 + sentinel, never fabricated as 0
395 var ok4: i64 = 0
396 let av4: i64 = mh_extract(js, jn, "nonexistent_key" as *u8, fnd)
397 if fnd[0] == 0 { if av4 == MH_SENT { ok4 = 1 } }
398 gv_check("T4 absent key -> found=0 + sentinel, never a fabricated zero" as *u8, ok4, ctr)
399 // T5 hi-is-good classification
400 var ok5: i64 = 0
401 if mh_class(1000, 0, 900, 700) == 2 { if mh_class(800, 0, 900, 700) == 1 { if mh_class(500, 0, 900, 700) == 0 { ok5 = 1 } } }
402 gv_check("T5 higher-is-better: 1000 GOOD, 800 WATCH, 500 BAD" as *u8, ok5, ctr)
403 // T6 lo-is-good classification
404 var ok6: i64 = 0
405 if mh_class(0, 1, 0, 5) == 2 { if mh_class(3, 1, 0, 5) == 1 { if mh_class(20, 1, 0, 5) == 0 { ok6 = 1 } } }
406 gv_check("T6 lower-is-better: 0 GOOD, 3 WATCH, 20 BAD" as *u8, ok6, ctr)
407 // T7 boundary is inclusive (val==good is GOOD, val==warn is WATCH)
408 var ok7: i64 = 0
409 if mh_class(900, 0, 900, 700) == 2 { if mh_class(700, 0, 900, 700) == 1 { ok7 = 1 } }
410 gv_check("T7 thresholds inclusive at the boundary" as *u8, ok7, ctr)
411 // T8 index math: 2 GOOD + 1 WATCH + 1 BAD over 4 = (2+2+1+0)/8 = 625 permil
412 var ok8: i64 = 0
413 let ssum: i64 = 2 + 2 + 1 + 0
414 if ssum * MH_PERMIL / (2 * 4) == 625 { ok8 = 1 }
415 gv_check("T8 health_index math exact: 2G/1W/1B of 4 = 625 permil" as *u8, ok8, ctr)
416 // T9 live compose over a real conf that forks nx_minecov -> the hub actually runs the suite
417 let cf: *u8 = sys_mmap(MH_PATH)
418 o = sj_cat(cf, 0, prefix)
419 o = sj_catn(cf, o, sys_now_realtime_sec())
420 o = sj_cat(cf, o, ".conf" as *u8)
421 cf[o] = 0 as u8
422 let fd: i64 = sys_openat_wr(cf, MH_MODE_644)
423 let lb: *u8 = sys_mmap(MH_MAGIC_1024)
424 var lo: i64 = sj_cat(lb, 0, "cov\thi\t900\t700\tcoverage_permil\tnx_minecov\tcensus\tknowledge/status/minecov_classes.conf\n" as *u8)
425 sys_write(fd, lb, lo)
426 sys_close(fd)
427 let d: *u8 = sys_mmap(MH_OUT)
428 let dl: i64 = mh_emit(cf, 0, "-" as *u8, d)
429 var ok9: i64 = 0
430 if dl > 0 { if mh_find(d, dl, "\"id\":\"cov\"" as *u8) == 1 { if mh_find(d, dl, "\"ran\":1" as *u8) == 1 { if mh_find(d, dl, "\"status\":\"GOOD\"" as *u8) == 1 { ok9 = 1 } } } }
431 gv_check("T9 LIVE compose: forks nx_minecov, extracts coverage_permil, classifies GOOD" as *u8, ok9, ctr)
432 // T10/T11 flag: a BAD source auto-files ONE ticket through the injected argecho filer, idempotent.
433 // conf forks nx_minecov census reading mined_permil(=1000) with dir=lo good=100 warn=500 => 1000>500
434 // => BAD by construction (inverted thresholds; the tooth is the FILING mechanism, not the threshold).
435 let bc: *u8 = sys_mmap(MH_PATH)
436 o = sj_cat(bc, 0, prefix)
437 o = sj_catn(bc, o, sys_now_realtime_sec())
438 o = sj_cat(bc, o, ".bad" as *u8)
439 bc[o] = 0 as u8
440 let bfd: i64 = sys_openat_wr(bc, MH_MODE_644)
441 var blo: i64 = sj_cat(lb, 0, "cov\tlo\t100\t500\tmined_permil\tnx_minecov\tcensus\tknowledge/status/minecov_classes.conf\n" as *u8)
442 sys_write(bfd, lb, blo)
443 sys_close(bfd)
444 let ij: *u8 = sys_mmap(MH_PATH)
445 o = sj_cat(ij, 0, prefix)
446 o = sj_catn(ij, o, sys_now_realtime_sec())
447 o = sj_cat(ij, o, ".ij" as *u8)
448 ij[o] = 0 as u8
449 let fr1: i64 = mh_flag(bc, ij, "argecho" as *u8, d)
450 var ok10: i64 = 0
451 if fr1 > 0 { if mh_find(d, fr1, "\"bad\":1" as *u8) == 1 { if mh_find(d, fr1, "\"flagged\":1" as *u8) == 1 { if mh_find(d, fr1, "\"skipped_already\":0" as *u8) == 1 { ok10 = 1 } } } }
452 gv_check("T10 a BAD source files exactly one ticket through the injected filer" as *u8, ok10, ctr)
453 // seed the marker the argecho filer would have written (argecho does not persist), then re-flag
454 let sfd: i64 = sys_openat_append(ij, MH_MODE_644)
455 var slo: i64 = sj_cat(lb, 0, "REQ seeded [HUB:cov] marker\n" as *u8)
456 sys_write(sfd, lb, slo)
457 sys_close(sfd)
458 let fr2: i64 = mh_flag(bc, ij, "argecho" as *u8, d)
459 var ok11: i64 = 0
460 if fr2 > 0 { if mh_find(d, fr2, "\"bad\":1" as *u8) == 1 { if mh_find(d, fr2, "\"flagged\":0" as *u8) == 1 { if mh_find(d, fr2, "\"skipped_already\":1" as *u8) == 1 { ok11 = 1 } } } }
461 gv_check("T11 marker present -> re-flag files NOTHING (idempotent, no ticket spam)" as *u8, ok11, ctr)
462 let rc: i64 = gv_verdict("MINERHUB-GATE" as *u8, ctr, "synthesis + flag: exact extract, boundary classify, honest sentinel, index math, live compose, idempotent auto-file" as *u8)
463 return rc
464}
465
466func main(argc: i64, argv: *i64) -> i64 {
467 if argc < 3 { sj_puts("usage: nx_minerhub {mine <sourceconf> | page <sourceconf> <outfile> | flag <sourceconf> <intake_jrnl> [filer] | selftest <scratch-prefix>}\n" as *u8); sys_exit(2); return 2 }
468 let verb: *u8 = argv[1] as *u8
469 let vl: i64 = sj_vlen(verb)
470 if sj_lit_eq(verb, 0, vl, "selftest" as *u8) == 1 {
471 let rc: i64 = mh_selftest(argv[2] as *u8)
472 sys_exit(rc)
473 return rc
474 }
475 if sj_lit_eq(verb, 0, vl, "mine" as *u8) == 1 {
476 let d: *u8 = sys_mmap(MH_OUT)
477 let dl: i64 = mh_emit(argv[2] as *u8, 0, "-" as *u8, d)
478 if dl < 0 { sj_puts("REFUSED source conf missing or empty\n" as *u8); sys_exit(3); return 3 }
479 sys_write(1, d, dl)
480 sys_exit(0)
481 return 0
482 }
483 if sj_lit_eq(verb, 0, vl, "page" as *u8) == 1 {
484 if argc < 4 { sj_puts("page needs <sourceconf> <outfile>\n" as *u8); sys_exit(2); return 2 }
485 let d: *u8 = sys_mmap(MH_OUT)
486 let dl: i64 = mh_emit(argv[2] as *u8, 1, argv[3] as *u8, d)
487 if dl < 0 { sj_puts("PAGE FAIL\n" as *u8); sys_exit(1); return 1 }
488 sj_puts("PAGE OK\n" as *u8)
489 sys_exit(0)
490 return 0
491 }
492 if sj_lit_eq(verb, 0, vl, "flag" as *u8) == 1 {
493 if argc < 4 { sj_puts("flag needs <sourceconf> <intake_jrnl> [filer]\n" as *u8); sys_exit(2); return 2 }
494 let filer: *u8 = sys_mmap(128)
495 var fo: i64 = 0
496 if argc >= 5 { fo = sj_cat(filer, 0, argv[4] as *u8) } else { fo = sj_cat(filer, 0, "nx_pm_intake" as *u8) }
497 filer[fo] = 0 as u8
498 let d: *u8 = sys_mmap(MH_OUT)
499 let dl: i64 = mh_flag(argv[2] as *u8, argv[3] as *u8, filer, d)
500 if dl < 0 { sj_puts("REFUSED source conf missing or empty\n" as *u8); sys_exit(3); return 3 }
501 sys_write(1, d, dl)
502 sys_exit(0)
503 return 0
504 }
505 sj_puts("unknown verb\n" as *u8)
506 sys_exit(2)
507 return 2
508}