code wiki / _hdl_build / nx_harnessmine.nx

nx_harnessmine.nx source

↩ module page · 324 lines · 15422 B

1// nx_harnessmine.nx -- HARNESS-CLASS MINER over the gate-outcome journal (miner-sota F1012, 2026-07-23). 2// The census (nx_minecov MC09) measured the harness class at ZERO evidence: 953+ gates run constantly 3// and NOTHING recorded an outcome, so flake and erosion were structurally invisible. nx_gate_verdict 4// now self-records one actlog-grammar frame per verdict (fail-soft); this mines that history for the 5// two signals a pass/fail count cannot give: 6// FLAKE = the same gate has produced BOTH outcomes (non-determinism -- the gate cannot be trusted) 7// EROSION = a gate that was GREEN later went RED (a BANKED WIN LOST -- the ratchet law's RED). A gate 8// that went RED then GREEN is a FIX, explicitly NOT erosion; the distinction is the point. 9// Order matters, so frames are walked in journal order per gate. now INJECTABLE for deterministic tests. 10// Composes nx_sovjson_lib (sj_*). Read-only. No hw writes (Rule 26). 11// mine <journal> [minruns] [now] -> JSON per-gate + totals (green_permil, flaky, eroded) 12// selftest <scratch-prefix> -> gate T1..T8 13// frame cols: ts TAB ws TAB gate TAB verb TAB outcome(GREEN|RED) TAB passed/total 14// license_tier: ORIGINAL 15import "nx_sovjson_lib.nx" 16import "nx_syscalls.nx" 17import "nx_gate_verdict.nx" 18const HM_MAGIC_1785000000: i64 = 1785000000 19const HM_MAGIC_4088: i64 = 4088 20 21const HM_WIN: i64 = 4194304 22const HM_OUT: i64 = 65536 23const HM_PATH: i64 = 512 24const HM_GATES: i64 = 512 25const HM_TOPN: i64 = 30 26const HM_PERMIL: i64 = 1000 27const HM_DAY: i64 = 86400 28const HM_NAME_MAX: i64 = 120 29const HM_MODE_644: i64 = 420 30 31func hm_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 hm_find(q: *u8, n: i64, lit: *u8) -> i64 { 41 let ll: i64 = sj_vlen(lit) 42 if ll == 0 { return 0 } 43 var i: i64 = 0 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 1 } 49 i = i + 1 50 } 51 return 0 52} 53func hm_key(d: *u8, o: i64, name: *u8) -> i64 { 54 d[o] = 34 as u8 55 var p: i64 = o + 1 56 p = sj_cat(d, p, name) 57 d[p] = 34 as u8 58 p = p + 1 59 d[p] = 58 as u8 60 p = p + 1 61 return p 62} 63func hm_digits(q: *u8, s: i64, e: i64) -> i64 { 64 if e <= s { return 0 } 65 var i: i64 = s 66 while i < e { let c: i64 = q[i] as i64; if c < 48 { return 0 } if c > 57 { return 0 } i = i + 1 } 67 return 1 68} 69func hm_mine_json(jpath: *u8, minruns: i64, now: i64, d: *u8) -> i64 { 70 let q: *u8 = sys_mmap(HM_WIN) 71 let n: i64 = hm_read(jpath, q, HM_WIN - 8) 72 if n <= 0 { return -1 } 73 var trunc: i64 = 0 74 if n >= HM_WIN - 8 { trunc = 1 } 75 let gs: *i64 = sys_mmap(8 * HM_GATES) as *i64 76 let ge: *i64 = sys_mmap(8 * HM_GATES) as *i64 77 let runs: *i64 = sys_mmap(8 * HM_GATES) as *i64 78 let green: *i64 = sys_mmap(8 * HM_GATES) as *i64 79 let red: *i64 = sys_mmap(8 * HM_GATES) as *i64 80 let eroded: *i64 = sys_mmap(8 * HM_GATES) as *i64 81 let lastg: *i64 = sys_mmap(8 * HM_GATES) as *i64 82 let lastts: *i64 = sys_mmap(8 * HM_GATES) as *i64 83 let done: *i64 = sys_mmap(8 * HM_GATES) as *i64 84 let sp: *i64 = sys_mmap(16) as *i64 85 var ng: i64 = 0 86 var gcapped: i64 = 0 87 var frames: i64 = 0 88 var malformed: i64 = 0 89 var i: i64 = 0 90 while i < n { 91 let le: i64 = sj_le(q, i, n) 92 var ok: i64 = 0 93 var cmt: i64 = 0 94 if le > i { if q[i] == (35 as u8) { cmt = 1 } } 95 if le > i { if cmt == 0 { if sj_col(q, i, le, 4, sp) == 1 { ok = 1 } } } 96 if ok == 0 { if le > i { if cmt == 0 { malformed = malformed + 1 } } } else { 97 var isgreen: i64 = 0 98 var isred: i64 = 0 99 if sj_lit_eq(q, sp[0], sp[1], "GREEN" as *u8) == 1 { isgreen = 1 } 100 if sj_lit_eq(q, sp[0], sp[1], "RED" as *u8) == 1 { isred = 1 } 101 if isgreen + isred == 0 { malformed = malformed + 1 } else { 102 frames = frames + 1 103 sj_col(q, i, le, 2, sp) 104 let cs: i64 = sp[0] 105 let ce: i64 = sp[1] 106 var idx: i64 = 0 - 1 107 var k: i64 = 0 108 while k < ng { 109 if ce - cs == ge[k] - gs[k] { 110 var m: i64 = 0 111 var eq: i64 = 1 112 while m < ce - cs { if q[cs+m] != q[gs[k]+m] { eq = 0; m = ce - cs } else { m = m + 1 } } 113 if eq == 1 { idx = k; k = ng } 114 } 115 k = k + 1 116 } 117 if idx < 0 { 118 if ng >= HM_GATES { gcapped = 1 } else { 119 gs[ng] = cs 120 ge[ng] = ce 121 lastg[ng] = 0 - 1 122 idx = ng 123 ng = ng + 1 124 } 125 } 126 if idx >= 0 { 127 runs[idx] = runs[idx] + 1 128 if isgreen == 1 { green[idx] = green[idx] + 1 } else { red[idx] = red[idx] + 1 } 129 // EROSION: previously GREEN, now RED. A RED->GREEN transition is a FIX, not erosion. 130 if isred == 1 { if lastg[idx] == 1 { eroded[idx] = 1 } } 131 if isgreen == 1 { lastg[idx] = 1 } else { lastg[idx] = 0 } 132 sj_col(q, i, le, 0, sp) 133 if hm_digits(q, sp[0], sp[1]) == 1 { lastts[idx] = sj_atoi_span(q, sp[0], sp[1]) } 134 } 135 } 136 } 137 i = le + 1 138 } 139 var tgreen: i64 = 0 140 var tred: i64 = 0 141 var flaky: i64 = 0 142 var nerod: i64 = 0 143 var k3: i64 = 0 144 while k3 < ng { 145 tgreen = tgreen + green[k3] 146 tred = tred + red[k3] 147 if green[k3] > 0 { if red[k3] > 0 { flaky = flaky + 1 } } 148 nerod = nerod + eroded[k3] 149 k3 = k3 + 1 150 } 151 var p: i64 = 0 152 d[p] = 123 as u8; p = p + 1 153 p = hm_key(d, p, "v" as *u8); p = sj_catn(d, p, 1); d[p] = 44 as u8; p = p + 1 154 p = hm_key(d, p, "tool" as *u8) 155 d[p] = 34 as u8; p = p + 1 156 p = sj_cat(d, p, "nx_harnessmine" as *u8) 157 d[p] = 34 as u8; p = p + 1 158 d[p] = 44 as u8; p = p + 1 159 p = hm_key(d, p, "averb" as *u8) 160 d[p] = 34 as u8; p = p + 1 161 p = sj_cat(d, p, "mine" as *u8) 162 d[p] = 34 as u8; p = p + 1 163 d[p] = 44 as u8; p = p + 1 164 p = hm_key(d, p, "journal" as *u8) 165 d[p] = 34 as u8; p = p + 1 166 p = sj_cat_esc(d, p, jpath, 0, sj_vlen(jpath), HM_NAME_MAX) 167 d[p] = 34 as u8; p = p + 1 168 d[p] = 44 as u8; p = p + 1 169 p = hm_key(d, p, "journal_bytes" as *u8); p = sj_catn(d, p, n); d[p] = 44 as u8; p = p + 1 170 p = hm_key(d, p, "truncated" as *u8); p = sj_catn(d, p, trunc); d[p] = 44 as u8; p = p + 1 171 p = hm_key(d, p, "minruns" as *u8); p = sj_catn(d, p, minruns); d[p] = 44 as u8; p = p + 1 172 p = hm_key(d, p, "frames" as *u8); p = sj_catn(d, p, frames); d[p] = 44 as u8; p = p + 1 173 p = hm_key(d, p, "malformed" as *u8); p = sj_catn(d, p, malformed); d[p] = 44 as u8; p = p + 1 174 p = hm_key(d, p, "gates" as *u8); p = sj_catn(d, p, ng); d[p] = 44 as u8; p = p + 1 175 p = hm_key(d, p, "flaky" as *u8); p = sj_catn(d, p, flaky); d[p] = 44 as u8; p = p + 1 176 p = hm_key(d, p, "eroded" as *u8); p = sj_catn(d, p, nerod); d[p] = 44 as u8; p = p + 1 177 var gperm: i64 = 0 - 1 178 if frames > 0 { gperm = tgreen * HM_PERMIL / frames } 179 p = hm_key(d, p, "green_permil" as *u8); p = sj_catn(d, p, gperm); d[p] = 44 as u8; p = p + 1 180 // per-gate, ranked by RED desc (the ones that need attention first) 181 p = hm_key(d, p, "by_gate" as *u8) 182 d[p] = 91 as u8; p = p + 1 183 var shown: i64 = 0 184 var below: i64 = 0 185 var efirst: i64 = 1 186 var pass: i64 = 0 187 while pass < ng { 188 var mi: i64 = 0 - 1 189 var mx: i64 = 0 - 1 190 var k4: i64 = 0 191 while k4 < ng { 192 if done[k4] == 0 { if red[k4] > mx { mx = red[k4]; mi = k4 } } 193 k4 = k4 + 1 194 } 195 if mi >= 0 { 196 done[mi] = 1 197 if runs[mi] < minruns { below = below + 1 } else { 198 if shown < HM_TOPN { 199 if efirst == 0 { d[p] = 44 as u8; p = p + 1 } 200 efirst = 0 201 d[p] = 123 as u8; p = p + 1 202 p = hm_key(d, p, "gate" as *u8) 203 d[p] = 34 as u8; p = p + 1 204 p = sj_cat_esc(d, p, q, gs[mi], ge[mi], HM_NAME_MAX) 205 d[p] = 34 as u8; p = p + 1 206 d[p] = 44 as u8; p = p + 1 207 p = hm_key(d, p, "runs" as *u8); p = sj_catn(d, p, runs[mi]); d[p] = 44 as u8; p = p + 1 208 p = hm_key(d, p, "green" as *u8); p = sj_catn(d, p, green[mi]); d[p] = 44 as u8; p = p + 1 209 p = hm_key(d, p, "red" as *u8); p = sj_catn(d, p, red[mi]); d[p] = 44 as u8; p = p + 1 210 var fl: i64 = 0 211 if green[mi] > 0 { if red[mi] > 0 { fl = 1 } } 212 p = hm_key(d, p, "flaky" as *u8); p = sj_catn(d, p, fl); d[p] = 44 as u8; p = p + 1 213 p = hm_key(d, p, "eroded" as *u8); p = sj_catn(d, p, eroded[mi]); d[p] = 44 as u8; p = p + 1 214 p = hm_key(d, p, "last" as *u8) 215 d[p] = 34 as u8; p = p + 1 216 if lastg[mi] == 1 { p = sj_cat(d, p, "GREEN" as *u8) } else { p = sj_cat(d, p, "RED" as *u8) } 217 d[p] = 34 as u8; p = p + 1 218 d[p] = 44 as u8; p = p + 1 219 var agd: i64 = 0 - 1 220 if lastts[mi] > 0 { agd = (now - lastts[mi]) / HM_DAY } 221 p = hm_key(d, p, "last_run_days" as *u8); p = sj_catn(d, p, agd) 222 d[p] = 125 as u8; p = p + 1 223 shown = shown + 1 224 } 225 } 226 } 227 pass = pass + 1 228 } 229 d[p] = 93 as u8; p = p + 1 230 d[p] = 44 as u8; p = p + 1 231 p = hm_key(d, p, "gates_shown" as *u8); p = sj_catn(d, p, shown); d[p] = 44 as u8; p = p + 1 232 p = hm_key(d, p, "gates_below_minruns" as *u8); p = sj_catn(d, p, below); d[p] = 44 as u8; p = p + 1 233 p = hm_key(d, p, "gates_capped" as *u8); p = sj_catn(d, p, gcapped) 234 d[p] = 125 as u8; p = p + 1 235 d[p] = 10 as u8; p = p + 1 236 return p 237} 238func hm_selftest(prefix: *u8) -> i64 { 239 let ctr: *i64 = gv_ctr() 240 gv_head("nx_harnessmine selftest -- flake vs EROSION teeth (order matters; a fix is not erosion)" as *u8) 241 let now: i64 = HM_MAGIC_1785000000 242 let fx: *u8 = sys_mmap(HM_PATH) 243 var o: i64 = sj_cat(fx, 0, prefix) 244 o = sj_catn(fx, o, sys_now_realtime_sec()) 245 o = sj_cat(fx, o, ".hm" as *u8) 246 fx[o] = 0 as u8 247 let miss: *u8 = sys_mmap(HM_PATH) 248 o = sj_cat(miss, 0, fx) 249 o = sj_cat(miss, o, ".absent" as *u8) 250 miss[o] = 0 as u8 251 // GA: GREEN then RED = ERODED + flaky. GB: RED then GREEN = a FIX, flaky but NOT eroded. 252 // GC: GREEN x3 = stable. GD: 1 run only (below minruns 2). plus a malformed + a bogus outcome. 253 let fd: i64 = sys_openat_wr(fx, HM_MODE_644) 254 let lb: *u8 = sys_mmap(HM_MAGIC_4088) 255 var lo: i64 = sj_cat(lb, 0, "# fixture\n" as *u8) 256 lo = sj_cat(lb, lo, "1784900000\tharness\tGA-GATE\trun\tGREEN\t8/8\n" as *u8) 257 lo = sj_cat(lb, lo, "1784910000\tharness\tGB-GATE\trun\tRED\t5/8\n" as *u8) 258 lo = sj_cat(lb, lo, "1784920000\tharness\tGA-GATE\trun\tRED\t7/8\n" as *u8) 259 lo = sj_cat(lb, lo, "1784930000\tharness\tGB-GATE\trun\tGREEN\t8/8\n" as *u8) 260 lo = sj_cat(lb, lo, "1784940000\tharness\tGC-GATE\trun\tGREEN\t4/4\n" as *u8) 261 lo = sj_cat(lb, lo, "1784950000\tharness\tGC-GATE\trun\tGREEN\t4/4\n" as *u8) 262 lo = sj_cat(lb, lo, "1784960000\tharness\tGC-GATE\trun\tGREEN\t4/4\n" as *u8) 263 lo = sj_cat(lb, lo, "1784970000\tharness\tGD-GATE\trun\tGREEN\t2/2\n" as *u8) 264 lo = sj_cat(lb, lo, "1784980000\tharness\tGE-GATE\trun\tPURPLE\t1/1\n" as *u8) 265 lo = sj_cat(lb, lo, "nocolumns\n" as *u8) 266 sys_write(fd, lb, lo) 267 sys_close(fd) 268 let d: *u8 = sys_mmap(HM_OUT) 269 let r1: i64 = hm_mine_json(miss, 1, now, d) 270 var ok1: i64 = 0 271 if r1 < 0 { ok1 = 1 } 272 gv_check("T1 missing journal refused fail closed" as *u8, ok1, ctr) 273 let dl: i64 = hm_mine_json(fx, 1, now, d) 274 var ok2: i64 = 0 275 if dl > 0 { if hm_find(d, dl, "\"frames\":8,\"malformed\":2,\"gates\":4" as *u8) == 1 { ok2 = 1 } } 276 gv_check("T2 exact frames 8, BOTH bad lines counted malformed, 4 gates" as *u8, ok2, ctr) 277 var ok3: i64 = 0 278 if hm_find(d, dl, "\"gate\":\"GA-GATE\",\"runs\":2,\"green\":1,\"red\":1,\"flaky\":1,\"eroded\":1,\"last\":\"RED\"" as *u8) == 1 { ok3 = 1 } 279 gv_check("T3 GREEN then RED = ERODED (a banked win lost)" as *u8, ok3, ctr) 280 var ok4: i64 = 0 281 if hm_find(d, dl, "\"gate\":\"GB-GATE\",\"runs\":2,\"green\":1,\"red\":1,\"flaky\":1,\"eroded\":0,\"last\":\"GREEN\"" as *u8) == 1 { ok4 = 1 } 282 gv_check("T4 RED then GREEN is a FIX: flaky yes, eroded NO (order respected)" as *u8, ok4, ctr) 283 var ok5: i64 = 0 284 if hm_find(d, dl, "\"gate\":\"GC-GATE\",\"runs\":3,\"green\":3,\"red\":0,\"flaky\":0,\"eroded\":0" as *u8) == 1 { ok5 = 1 } 285 gv_check("T5 stable gate is neither flaky nor eroded" as *u8, ok5, ctr) 286 var ok6: i64 = 0 287 if hm_find(d, dl, "\"flaky\":2,\"eroded\":1" as *u8) == 1 { if hm_find(d, dl, "\"green_permil\":750" as *u8) == 1 { ok6 = 1 } } 288 gv_check("T6 totals exact: 2 flaky, only 1 eroded, green_permil 750" as *u8, ok6, ctr) 289 var ok7: i64 = 0 290 if hm_find(d, dl, "\"last_run_days\":0" as *u8) == 1 { if hm_find(d, dl, "\"gate\":\"GE-GATE\"" as *u8) == 0 { ok7 = 1 } } 291 gv_check("T7 unknown outcome PURPLE never becomes a gate; recency derived" as *u8, ok7, ctr) 292 let dl8: i64 = hm_mine_json(fx, 2, now, d) 293 var ok8: i64 = 0 294 if dl8 > 0 { if hm_find(d, dl8, "\"gate\":\"GD-GATE\"" as *u8) == 0 { if hm_find(d, dl8, "\"gates_below_minruns\":1" as *u8) == 1 { ok8 = 1 } } } 295 gv_check("T8 minruns 2 suppresses the single-run gate and DECLARES it" as *u8, ok8, ctr) 296 let rc: i64 = gv_verdict("HARNESSMINE-GATE" as *u8, ctr, "harness mining: flake vs erosion distinguished by ORDER, malformed counted, suppression declared" as *u8) 297 return rc 298} 299 300func main(argc: i64, argv: *i64) -> i64 { 301 if argc < 3 { sj_puts("usage: nx_harnessmine {mine <journal> [minruns] [now] | selftest <scratch-prefix>}\n" as *u8); sys_exit(2); return 2 } 302 let verb: *u8 = argv[1] as *u8 303 let vl: i64 = sj_vlen(verb) 304 if sj_lit_eq(verb, 0, vl, "selftest" as *u8) == 1 { 305 let rc: i64 = hm_selftest(argv[2] as *u8) 306 sys_exit(rc) 307 return rc 308 } 309 if sj_lit_eq(verb, 0, vl, "mine" as *u8) == 1 { 310 var minruns: i64 = 1 311 if argc >= 4 { let mz: i64 = sj_atoi_z(argv[3] as *u8); if mz > 0 { minruns = mz } } 312 var now: i64 = sys_now_realtime_sec() 313 if argc >= 5 { let nz: i64 = sj_atoi_z(argv[4] as *u8); if nz > 0 { now = nz } } 314 let d: *u8 = sys_mmap(HM_OUT) 315 let dl: i64 = hm_mine_json(argv[2] as *u8, minruns, now, d) 316 if dl < 0 { sj_puts("REFUSED journal missing or empty (no gate has recorded an outcome yet)\n" as *u8); sys_exit(3); return 3 } 317 sys_write(1, d, dl) 318 sys_exit(0) 319 return 0 320 } 321 sj_puts("unknown verb\n" as *u8) 322 sys_exit(2) 323 return 2 324}