nx_forge_req_gate.nx source
↩ module page · 288 lines · 9670 B
1// nx_forge_req_gate.nx -- FORGE requirements dossier gate (the adversary/critic tooth).
2// Walks knowledge/forge/forge_requirements_v1.txt: every REQ| row must carry EV= paths that
3// exist NON-EMPTY on disk (evidence fork, census doctrine) and a non-empty ADV= adversary test.
4// NEG-CONTROL: knowledge/forge/forge_req_negctl.txt holds a planted row whose EV file is absent;
5// verdict GREEN only if every real row PASSES and the planted row FAILS (liar-kill: a
6// rubber-stamp checker cannot go GREEN). CR-tolerant by field order (ADV last, EV mid-row).
7// license_tier: ORIGINAL expect_exit: 0
8import "nx_syscalls.nx"
9import "nx_lib_std.nx"
10import "nx_gate_verdict.nx"
11import "nx_artifact_root.nx"
12
13func rq_read(path: *u8, buf: *u8, cap: i64) -> i64 {
14 let fd: i64 = sys_openat_rd(path)
15 if fd < 0 {
16 let neg: i64 = 0 - 1
17 return neg
18 }
19 var total: i64 = 0
20 var going: i64 = 1
21 while going == 1 {
22 let lim: i64 = cap - 1
23 let room: i64 = lim - total
24 if room <= 0 { going = 0 }
25 if going == 1 {
26 let p: *u8 = buf + total
27 let n: i64 = sys_read(fd, p, room)
28 if n <= 0 { going = 0 }
29 if n > 0 { total = total + n }
30 }
31 }
32 sys_close(fd)
33 buf[total] = 0 as u8
34 return total
35}
36
37// HOST-BOUND FIX 2026-08-02 (debt 1785689846, recipe proven on nx_sclass_dispatch_gate): EV rows name
38// artifacts by CONVENTION (`runtime/nx_forge.nx`), and that convention differs per host -- on the NAS the
39// same source lives at `buildroot/runtime/nx_forge.nx`. Opening the literal made every row read EV-MISS
40// off-laptop, i.e. the gate graded the MACHINE, not the dossier. ar_resolve walks the host's roots table
41// (nx_artifact_root -- the 9-of-9-UNGROUNDED law) and tries the raw path FIRST, so dev behaviour is
42// unchanged and a genuine absence still reports the path the caller actually asked for.
43func rq_ev_ok(path: *u8, scratch: *u8) -> i64 {
44 let rp: *u8 = sys_mmap(4096)
45 ar_resolve(path, rp)
46 let fd: i64 = sys_openat_rd(rp)
47 if fd < 0 { return 0 }
48 let n: i64 = sys_read(fd, scratch, 4)
49 sys_close(fd)
50 if n > 0 { return 1 }
51 return 0
52}
53
54// find "|EV=" inside [ls,le); return index just after '=', or -1
55func rq_find_ev(buf: *u8, ls: i64, le: i64) -> i64 {
56 var i: i64 = ls
57 let stop: i64 = le - 3
58 while i < stop {
59 let c0: i64 = buf[i] as i64
60 if c0 == 124 {
61 let i1: i64 = i + 1
62 let c1: i64 = buf[i1] as i64
63 if c1 == 69 {
64 let i2: i64 = i + 2
65 let c2: i64 = buf[i2] as i64
66 if c2 == 86 {
67 let i3: i64 = i + 3
68 let c3: i64 = buf[i3] as i64
69 if c3 == 61 {
70 let r: i64 = i + 4
71 return r
72 }
73 }
74 }
75 }
76 i = i + 1
77 }
78 let neg: i64 = 0 - 1
79 return neg
80}
81
82// find "|ADV=" inside [ls,le); return index just after '=', or -1
83func rq_find_adv(buf: *u8, ls: i64, le: i64) -> i64 {
84 var i: i64 = ls
85 let stop: i64 = le - 4
86 while i < stop {
87 let c0: i64 = buf[i] as i64
88 if c0 == 124 {
89 let i1: i64 = i + 1
90 let c1: i64 = buf[i1] as i64
91 if c1 == 65 {
92 let i2: i64 = i + 2
93 let c2: i64 = buf[i2] as i64
94 if c2 == 68 {
95 let i3: i64 = i + 3
96 let c3: i64 = buf[i3] as i64
97 if c3 == 86 {
98 let i4: i64 = i + 4
99 let c4: i64 = buf[i4] as i64
100 if c4 == 61 {
101 let r: i64 = i + 5
102 return r
103 }
104 }
105 }
106 }
107 }
108 i = i + 1
109 }
110 let neg: i64 = 0 - 1
111 return neg
112}
113
114// validate one REQ row [ls,le); mode 0 = must pass, mode 1 = negctl must fail.
115// returns 1 if the row is BAD for its mode, else 0.
116func rq_row(buf: *u8, ls: i64, le: i64, mode: i64, pbuf: *u8, scratch: *u8) -> i64 {
117 std_puts("ROW " as *u8)
118 let idoff: i64 = ls + 4
119 var idend: i64 = idoff
120 var s: i64 = 1
121 while s == 1 {
122 if idend >= le { s = 0 }
123 if s == 1 {
124 let c: i64 = buf[idend] as i64
125 if c == 124 { s = 0 }
126 if c != 124 { idend = idend + 1 }
127 }
128 }
129 let idp: *u8 = buf + idoff
130 let idl: i64 = idend - idoff
131 sys_write(1, idp, idl)
132 var rowok: i64 = 1
133 let evs: i64 = rq_find_ev(buf, ls, le)
134 if evs < 0 { rowok = 0 }
135 if evs >= 0 {
136 var j: i64 = evs
137 var npaths: i64 = 0
138 var going: i64 = 1
139 while going == 1 {
140 var k: i64 = j
141 var t: i64 = 1
142 while t == 1 {
143 if k >= le { t = 0 }
144 if t == 1 {
145 let c: i64 = buf[k] as i64
146 if c == 44 { t = 0 }
147 if c == 124 { t = 0 }
148 if c != 44 { if c != 124 { k = k + 1 } }
149 }
150 }
151 let tl: i64 = k - j
152 if tl > 0 {
153 if tl < 4000 {
154 let srcp: *u8 = buf + j
155 std_memcpy(pbuf, srcp, tl)
156 pbuf[tl] = 0 as u8
157 let ok: i64 = rq_ev_ok(pbuf, scratch)
158 npaths = npaths + 1
159 if ok == 0 {
160 rowok = 0
161 std_puts(" EV-MISS:" as *u8)
162 std_puts(pbuf)
163 }
164 }
165 }
166 if k >= le { going = 0 }
167 if k < le {
168 let c2: i64 = buf[k] as i64
169 if c2 == 124 { going = 0 }
170 if c2 == 44 { j = k + 1 }
171 }
172 }
173 if npaths == 0 { rowok = 0 }
174 }
175 let ads: i64 = rq_find_adv(buf, ls, le)
176 if ads < 0 { rowok = 0 }
177 if ads >= 0 {
178 if ads >= le { rowok = 0 }
179 if ads < le {
180 let c: i64 = buf[ads] as i64
181 if c == 124 { rowok = 0 }
182 if c == 13 { rowok = 0 }
183 if c == 10 { rowok = 0 }
184 }
185 }
186 if mode == 0 {
187 if rowok == 1 {
188 std_putln(" PASS" as *u8)
189 return 0
190 }
191 std_putln(" FAIL" as *u8)
192 return 1
193 }
194 if rowok == 1 {
195 std_putln(" NEGCTL-NOT-CAUGHT" as *u8)
196 return 1
197 }
198 std_putln(" NEGCTL-CAUGHT" as *u8)
199 return 0
200}
201
202// walk all lines; validate REQ rows; return count of BAD rows for the mode. nrows via nout[0].
203func rq_walk(buf: *u8, len: i64, mode: i64, pbuf: *u8, scratch: *u8, nout: *i64) -> i64 {
204 var bad: i64 = 0
205 var nrows: i64 = 0
206 var i: i64 = 0
207 while i < len {
208 var e: i64 = i
209 var scan: i64 = 1
210 while scan == 1 {
211 if e >= len { scan = 0 }
212 if scan == 1 {
213 let c: i64 = buf[e] as i64
214 if c == 10 { scan = 0 }
215 if c != 10 { e = e + 1 }
216 }
217 }
218 let ll: i64 = e - i
219 var isreq: i64 = 0
220 if ll > 4 {
221 let c0: i64 = buf[i] as i64
222 if c0 == 82 {
223 let i1: i64 = i + 1
224 let c1: i64 = buf[i1] as i64
225 if c1 == 69 {
226 let i2: i64 = i + 2
227 let c2: i64 = buf[i2] as i64
228 if c2 == 81 {
229 let i3: i64 = i + 3
230 let c3: i64 = buf[i3] as i64
231 if c3 == 124 { isreq = 1 }
232 }
233 }
234 }
235 }
236 if isreq == 1 {
237 nrows = nrows + 1
238 let r: i64 = rq_row(buf, i, e, mode, pbuf, scratch)
239 bad = bad + r
240 }
241 i = e + 1
242 }
243 nout[0] = nrows
244 return bad
245}
246
247func main(argc: i64, argv: *i64) -> i64 {
248 let buf: *u8 = sys_mmap(262144) as *u8
249 let nbuf: *u8 = sys_mmap(65536) as *u8
250 let pbuf: *u8 = sys_mmap(4096) as *u8
251 let scratch: *u8 = sys_mmap(64) as *u8
252 let cnt: *i64 = sys_mmap(64) as *i64
253 let n: i64 = rq_read("knowledge/forge/forge_requirements_v1.txt" as *u8, buf, 262144)
254 if n <= 0 {
255 std_putln("FORGE-REQ-GATE verdict=RED no-dossier" as *u8)
256 sys_exit(1)
257 return 1
258 }
259 let bad: i64 = rq_walk(buf, n, 0, pbuf, scratch, cnt)
260 let nrows: i64 = cnt[0]
261 let n2: i64 = rq_read("knowledge/forge/forge_req_negctl.txt" as *u8, nbuf, 65536)
262 var nbad: i64 = 1
263 var nneg: i64 = 0
264 if n2 > 0 {
265 nbad = rq_walk(nbuf, n2, 1, pbuf, scratch, cnt)
266 nneg = cnt[0]
267 }
268 if nneg == 0 { nbad = 1 }
269 std_puts("FORGE-REQ-GATE rows=" as *u8)
270 std_pdec(nrows)
271 std_puts(" rows-bad=" as *u8)
272 std_pdec(bad)
273 std_puts(" negctl-rows=" as *u8)
274 std_pdec(nneg)
275 std_puts(" negctl-bad=" as *u8)
276 std_pdec(nbad)
277 var allok: i64 = 0
278 if nrows > 0 { if bad == 0 { if nbad == 0 { allok = 1 } } }
279 if allok == 1 { std_putln(" verdict=GREEN" as *u8) } else { std_putln(" verdict=RED" as *u8) }
280 let ctr: *i64 = gv_ctr()
281 var t1: i64 = 0
282 if nrows > 0 { if bad == 0 { t1 = 1 } }
283 gv_check("T1 every REQ row carries EV= paths NON-EMPTY on disk (evidence fork)" as *u8, t1, ctr)
284 var t2: i64 = 0
285 if nneg > 0 { if nbad == 0 { t2 = 1 } }
286 gv_check("T2 LIAR-KILL: the planted absent-evidence row is CAUGHT (a rubber stamp cannot go green)" as *u8, t2, ctr)
287 return gv_verdict("FORGE-REQ-GATE" as *u8, ctr, "requirements dossier evidence-forked on disk with the planted negative control caught" as *u8)
288}