code wiki / _hdl_build / nx_bite_sweep.nx

nx_bite_sweep.nx source

↩ module page · 231 lines · 10997 B

1// nx_bite_sweep.nx -- run the non-vacuity proof across every declared gate of a domain (closes seq1366). 2// 3// nx_gate_bite answers "can THIS gate fail?" for one gate. This is the orchestration around it: walk a 4// domain's .gates, take each row's declared SUBJECT (field 3), and require every gate to kill a mutant. 5// Single responsibility kept separate on purpose (rule 9) -- measuring one gate and driving a fleet are 6// different jobs, and folding them into one organ is how a measurement tool grows a scheduler. 7// 8// ★NO SILENT CAPS. A row with no declared subject is reported as NO-SUBJECT and counted against the 9// domain, never skipped quietly. That distinction is the whole point: a gate we did not test and a gate 10// that cannot fail must not look the same in the output, or the sweep becomes the very thing it audits. 11// 12// ★WHY THE SUBJECT IS DECLARED, NOT DERIVED: the obvious convention (nx_X_gate.elf -> runtime/nx_X.nx) is 13// wrong often enough to matter -- nx_raci_gate's subject is runtime/_hdl_build/nx_raci.nx. A guessed path 14// that fails to open produces "no mutant killed", which reads identically to a vacuous gate. Guessing here 15// would manufacture false accusations against working gates. 16// 17// usage: nx_bite_sweep <domain> [max_sites] (CWD = nxc2 root) 18// exit 0 = every declared gate BITES · 1 = at least one vacuous or untestable · 2 = usage/no gates 19// license_tier: ORIGINAL 20import "nx_syscalls.nx" 21import "nx_artifact_root.nx" 22const BS_MAGIC_65536: i64 = 65536 23const BS_MAGIC_65535: i64 = 65535 24 25const BS_MAXROW: i64 = 2048 26 27func w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 28func wn(v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 } 29func wf(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 30func wnf(fd: i64, v: i64) -> i64 { let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let b: *u8=sys_mmap(28); var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(fd,b,k); return 0 } 31 32func bs_read(path: *u8, buf: *u8, cap: i64) -> i64 { 33 let fd: i64 = sys_openat_rd(path) 34 if fd < 0 { return 0 - 1 } 35 var tot: i64 = 0 36 var go: i64 = 1 37 while go == 1 { 38 let n: i64 = sys_read(fd, ((buf as i64)+tot) as *u8, cap - tot) 39 if n <= 0 { go = 0 } else { tot = tot + n; if tot >= cap { go = 0 } } 40 } 41 sys_close(fd) 42 return tot 43} 44 45// copy field `want` (0-based, '|' separated) of buf[s..e) into out; returns its length (0 if absent) 46func bs_field(buf: *u8, s: i64, e: i64, want: i64, out: *u8, cap: i64) -> i64 { 47 var f: i64 = 0 48 var i: i64 = s 49 var fs: i64 = s 50 while i <= e { 51 var cut: i64 = 0 52 if i == e { cut = 1 } else { if buf[i] == (124 as u8) { cut = 1 } } 53 if cut == 1 { 54 if f == want { 55 var n: i64 = i - fs 56 if n >= cap { n = cap - 1 } 57 var k: i64 = 0 58 while k < n { out[k] = buf[fs+k]; k = k + 1 } 59 out[n] = 0 as u8 60 return n 61 } 62 f = f + 1 63 fs = i + 1 64 } 65 i = i + 1 66 } 67 out[0] = 0 as u8 68 return 0 69} 70 71// gate TARGET name from an elf path: strip directory, strip a trailing ".elf" 72func bs_target(elf: *u8, out: *u8) -> i64 { 73 var n: i64 = 0 74 while elf[n] != (0 as u8) { n = n + 1 } 75 var s: i64 = 0 76 var i: i64 = 0 77 while i < n { if elf[i] == (47 as u8) { s = i + 1 } i = i + 1 } 78 var e: i64 = n 79 if n >= 4 { if elf[n-4] == (46 as u8) { e = n - 4 } } 80 var o: i64 = 0 81 var k: i64 = s 82 while k < e { out[o] = elf[k]; o = o + 1; k = k + 1 } 83 out[o] = 0 as u8 84 return o 85} 86 87// fork nx_gate_bite <target> <subject> <sites>; return its exit code (0 = BITES) 88func bs_run(bite: *u8, target: *u8, subject: *u8, sites: *u8, outpath: *u8) -> i64 { 89 let pid: i64 = sys_fork() 90 if pid == 0 { 91 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 92 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 93 let argv: *i64 = sys_mmap(48) as *i64 94 argv[0] = bite as i64 95 argv[1] = target as i64 96 argv[2] = subject as i64 97 argv[3] = sites as i64 98 argv[4] = 0 99 let envp: *i64 = sys_mmap(16) as *i64 100 envp[0] = 0 101 sys_execve(bite, argv, envp) 102 sys_exit(127) 103 } 104 let stp: *i64 = sys_mmap(16) as *i64 105 sys_wait4(pid, stp, 0) 106 let sig: i64 = stp[0] & 0x7f 107 if sig != 0 { return 128 + sig } 108 return (stp[0] >> 8) & 0xff 109} 110 111func main(argc: i64, argv: *i64) -> i64 { 112 if argc < 2 { w("usage: nx_bite_sweep <domain> [max_sites]\n" as *u8); sys_exit(2); return 2 } 113 let domain: *u8 = argv[1] as *u8 114 let sites: *u8 = "4\x00" as *u8 115 var sitesp: *u8 = sites 116 if argc > 2 { sitesp = argv[2] as *u8 } 117 118 w("=== nx_bite_sweep -- every declared gate must be proven able to FAIL ===\n" as *u8) 119 w(" domain=" as *u8); w(domain); w(" max_sites_per_gate=" as *u8); w(sitesp); w("\n" as *u8) 120 121 let gp: *u8 = sys_mmap(256) 122 var o: i64 = 0 123 let pre: *u8 = "knowledge/compare/" 124 var q: i64 = 0 125 while pre[q] != (0 as u8) { gp[o] = pre[q]; o = o + 1; q = q + 1 } 126 q = 0 127 while domain[q] != (0 as u8) { gp[o] = domain[q]; o = o + 1; q = q + 1 } 128 let sfx: *u8 = ".gates" 129 q = 0 130 while sfx[q] != (0 as u8) { gp[o] = sfx[q]; o = o + 1; q = q + 1 } 131 gp[o] = 0 as u8 132 133 let gbuf: *u8 = sys_mmap(BS_MAGIC_65536) 134 let gn: i64 = bs_read(gp, gbuf, BS_MAGIC_65535) 135 if gn <= 0 { w(" NO GATES FILE for this domain\n" as *u8); sys_exit(2); return 2 } 136 137 // Resolve the bite organ itself through the shared root table -- it is `_offc/` on a dev tree and flat 138 // at the serving root after a promote, exactly like every other artifact. 139 let bite: *u8 = sys_mmap(512) 140 if ar_resolve("_offc/nx_gate_bite.elf" as *u8, bite) == 0 { 141 w(" CANNOT RESOLVE nx_gate_bite.elf -- build/promote it first\n" as *u8); sys_exit(2); return 2 142 } 143 144 let elf: *u8 = sys_mmap(512) 145 let subj: *u8 = sys_mmap(512) 146 let tgt: *u8 = sys_mmap(512) 147 let outp: *u8 = "knowledge/status/bite_sweep_run.out\x00" as *u8 148 var declared: i64 = 0 149 var bites: i64 = 0 150 var vacuous: i64 = 0 151 var nosubj: i64 = 0 152 153 var ls: i64 = 0 154 var p: i64 = 0 155 while p <= gn { 156 var eol: i64 = 0 157 if p == gn { eol = 1 } else { if gbuf[p] == (10 as u8) { eol = 1 } } 158 if eol == 1 { 159 if p > ls { if gbuf[ls] != (35 as u8) { 160 let el: i64 = bs_field(gbuf, ls, p, 0, elf, 512) 161 if el > 0 { 162 declared = declared + 1 163 let sl: i64 = bs_field(gbuf, ls, p, 3, subj, 512) 164 bs_target(elf, tgt) 165 w(" " as *u8); w(tgt); w(": " as *u8) 166 if sl <= 0 { 167 nosubj = nosubj + 1 168 w("NO-SUBJECT (row declares no source to mutate -- counted, not skipped)\n" as *u8) 169 } else { 170 // Name the three non-BITES outcomes separately. They demand different work: 171 // INCONCLUSIVE = widen the site budget or pick better mutation targets; 172 // UNCONTROLLED = fix the gate's baseline first, nothing is attributable until then; 173 // RESTORE-FAILED = stop everything, the corpus may be damaged. 174 let rc: i64 = bs_run(bite, tgt, subj, sitesp, outp) 175 if rc == 0 { bites = bites + 1; w("BITES" as *u8) } else { 176 vacuous = vacuous + 1 177 if rc == 1 { w("INCONCLUSIVE (no kill in budget -- not proof of vacuity)" as *u8) } else { 178 if rc == 2 { w("UNCONTROLLED (gate not green at baseline)" as *u8) } else { 179 if rc == 3 { w("RESTORE-FAILED (CORPUS AT RISK)" as *u8) } else { 180 // rc 4 = the row NAMES a subject we cannot open. Distinct from the 181 // sl<=0 branch above (no field at all) and emphatically distinct from 182 // UNCONTROLLED: the gate is not accused, the CONFIG is. Counted as 183 // no_subject so the tally points at the .gates file, not the fleet. 184 if rc == 4 { vacuous = vacuous - 1; nosubj = nosubj + 1 185 w("SUBJECT-UNREADABLE (.gates 4th field names a file that cannot be opened -- CONFIG fault, gate NOT implicated)" as *u8) 186 } else { w("ERROR (exit " as *u8); wn(rc); w(")" as *u8) } 187 } 188 } 189 } 190 } 191 w(" subject=" as *u8); w(subj); w("\n" as *u8) 192 } 193 } 194 } } 195 ls = p + 1 196 } 197 p = p + 1 198 } 199 200 w(" declared=" as *u8); wn(declared); w(" bites=" as *u8); wn(bites) 201 w(" not_proven=" as *u8); wn(vacuous); w(" no_subject=" as *u8); wn(nosubj); w("\n" as *u8) 202 203 let lp: *u8 = sys_mmap(256) 204 o = 0 205 let lpre: *u8 = "knowledge/status/bite_sweep_" 206 q = 0 207 while lpre[q] != (0 as u8) { lp[o] = lpre[q]; o = o + 1; q = q + 1 } 208 q = 0 209 while domain[q] != (0 as u8) { lp[o] = domain[q]; o = o + 1; q = q + 1 } 210 let lsfx: *u8 = ".log" 211 q = 0 212 while lsfx[q] != (0 as u8) { lp[o] = lsfx[q]; o = o + 1; q = q + 1 } 213 lp[o] = 0 as u8 214 let lfd: i64 = sys_openat_wr(lp, 0x1a4) 215 if lfd >= 0 { 216 wf(lfd, "NX-BITE-SWEEP domain=" as *u8); wf(lfd, domain) 217 wf(lfd, " declared=" as *u8); wnf(lfd, declared) 218 wf(lfd, " bites=" as *u8); wnf(lfd, bites) 219 wf(lfd, " not_proven=" as *u8); wnf(lfd, vacuous) 220 wf(lfd, " no_subject=" as *u8); wnf(lfd, nosubj) 221 wf(lfd, " epoch=" as *u8); wnf(lfd, sys_now_realtime_sec()) 222 wf(lfd, "\n" as *u8) 223 if declared > 0 { if bites == declared { wf(lfd, "VERDICT=GREEN every declared gate proven able to fail\n" as *u8) } else { wf(lfd, "VERDICT=RED a declared gate is not proven able to fail (inconclusive, uncontrolled, or no declared subject)\n" as *u8) } } else { wf(lfd, "VERDICT=RED no declared gates\n" as *u8) } 224 sys_close(lfd) 225 } 226 227 if declared > 0 { if bites == declared { w("VERDICT: verdict=GREEN (every declared gate BITES)\n" as *u8); sys_exit(0); return 0 } } 228 w("VERDICT: verdict=RED (a declared gate is NOT PROVEN ABLE TO FAIL -- inconclusive, uncontrolled, or no declared subject; none of these is a proof of vacuity)\n" as *u8) 229 sys_exit(1) 230 return 1 231}