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}