code wiki / _hdl_build / nx_bld_cache_cas_gate.nx
nx_bld_cache_cas_gate.nx source
↩ module page · 682 lines · 39257 B
1// nx_bld_cache_cas_gate.nx -- VERDICT gate for rung B2 of /compare/toolchain: the content-addressed
2// build cache in nx_sov_build_run (watch symbol bld_cache_cas). Runs the REAL builder binary end to end
3// inside an ISOLATED fixture tree under <buildroot>/_build/nx_bld_cache_cas_gate/ (its own runtime/, its own _offc/
4// copy of the live toolchain, its own _build/cache) so nothing here touches the estate's cache, its
5// toolchain, or its knowledge/ confs -- and so the gate is idempotent: the fixture is wiped at SETUP,
6// never at teardown (a teardown does not run when a run crashes).
7//
8// DONE-RULE UNDER TEST (toolchain.plan B2, verbatim): an unchanged rebuild returns byte-identical bytes
9// with ZERO compiler invocation, and a one-byte source edit MISSES; a hit is byte-verified before use; a
10// key miss on any input change is the tooth; determinism re-proven by byte-identical cold rebuilds.
11//
12// THE ZERO-INVOCATION WITNESS IS STATE, NOT A MESSAGE: the builder writes _build/<t>.s ONLY inside its
13// compile loop (sys_openat_wr(spath) immediately before it forks nx_cc). The gate deletes that file
14// before a rebuild; if the artifact comes back and the .s is still ABSENT, the compiler was not forked.
15// A tooth asserts the .s IS present after a real build, so the absence witness cannot pass vacuously.
16//
17// Subject: argv[1] = builder elf (absolute or cwd-relative), else the first of
18// <nishihost>/nx_sov_build_run.sov.elf.new (STAGED -- what the next promote installs)
19// <buildroot>/_build/nx_sov_build_run.sov.elf (the last build)
20// <buildroot>/_offc/nx_sov_build_run.elf (LIVE)
21// and the chosen path + its sha256 are PRINTED, so the reader knows which binary was judged.
22// Bounded by the subject's OWN declared per-step deadline (it time-boxes compile and assemble); the
23// gate passes ms=0 so that bound is inherited rather than copied. license_tier: ORIGINAL
24import "nx_syscalls.nx"
25import "nx_sha256.nx"
26import "nx_gate_verdict.nx"
27import "nx_gatekit_lib.nx"
28
29// FIXTURE ROOT IS DERIVED, NOT /tmp (measured 2026-08-23 on the NAS: a byte-identical copy of the live
30// compiler placed under /tmp/ returned execve 127 -- the mount refuses execution -- so every builder run
31// failed with an empty .s and an empty stderr, which READS as a compiler defect). The fixture therefore
32// lives under <buildroot>/_build/nx_bld_cache_cas_gate/, build-artifact territory that is executable by
33// construction and never the serving root. Created and wiped at SETUP. The law "gate scratch lives in
34// /tmp/<gate>/" is followed for everything that is not executed; an executable fixture cannot live there.
35const CG_SHA_HEX: i64 = 64
36const CG_PATH: i64 = 4096
37const CG_OUT: i64 = 1048576 // one builder run prints well under this; = GK_BUF
38const CG_DIRBUF: i64 = 65536
39const CG_DENT_RECLEN_OFF: i64 = 16 // linux_dirent64: d_reclen u16 at +16, d_name at +19 (gk_dirscan uses the same)
40const CG_DENT_NAME_OFF: i64 = 19
41const CG_MODE_X: i64 = 493 // 0755
42const CG_FX_EXIT_A: i64 = 42 // fixture v1 exit code
43const CG_FX_EXIT_B: i64 = 43 // fixture v2 exit code (ONE byte differs: '2' -> '3')
44const CG_MAXOUT_SHOW: i64 = 4096 // how much of a captured run to echo into the report on a failure
45
46const CG_FX: *u8 = "casfx"
47const CG_FXREL: *u8 = "_build/nx_bld_cache_cas_gate"
48static cgp_root_p: i64
49static cgp_tree_p: i64
50static cgp_know_p: i64
51static cgp_conf_p: i64
52static cgp_fxsrc_p: i64
53static cgp_fxs_p: i64
54static cgp_fxelf_p: i64
55static cgp_cache_p: i64
56static cgp_cc_p: i64
57static cgp_asm_p: i64
58static cgp_lock_p: i64
59static cgp_rt_p: i64
60static cgp_hdl_p: i64
61static cgp_offc_p: i64
62static cgp_build_p: i64
63func cgp_mk(base: *u8, tail: *u8) -> i64 {
64 let b: *u8 = sys_mmap(CG_PATH)
65 var o: i64 = gk_cat(b, 0, base)
66 o = gk_cat(b, o, tail)
67 b[o] = 0 as u8
68 return b as i64
69}
70func cgp_init(buildroot: *u8) -> i64 {
71 cgp_root_p = cgp_mk(buildroot, CG_FXREL)
72 cgp_tree_p = cgp_mk(cgp_root_p as *u8, "/tree" as *u8)
73 cgp_know_p = cgp_mk(cgp_root_p as *u8, "/knowledge" as *u8)
74 cgp_conf_p = cgp_mk(cgp_know_p as *u8, "/buildcache.conf" as *u8)
75 cgp_rt_p = cgp_mk(cgp_tree_p as *u8, "/runtime" as *u8)
76 cgp_hdl_p = cgp_mk(cgp_rt_p as *u8, "/_hdl_build" as *u8)
77 cgp_offc_p = cgp_mk(cgp_tree_p as *u8, "/_offc" as *u8)
78 cgp_build_p = cgp_mk(cgp_tree_p as *u8, "/_build" as *u8)
79 cgp_fxsrc_p = cgp_mk(cgp_hdl_p as *u8, "/casfx.nx" as *u8)
80 cgp_fxs_p = cgp_mk(cgp_build_p as *u8, "/casfx.s" as *u8)
81 cgp_fxelf_p = cgp_mk(cgp_build_p as *u8, "/casfx.sov.elf" as *u8)
82 cgp_lock_p = cgp_mk(cgp_build_p as *u8, "/casfx.lock" as *u8)
83 cgp_cache_p = cgp_mk(cgp_build_p as *u8, "/cache" as *u8)
84 cgp_cc_p = cgp_mk(cgp_offc_p as *u8, "/nx_cc_sovereign.elf" as *u8)
85 cgp_asm_p = cgp_mk(cgp_offc_p as *u8, "/nxasm_x86_main.elf" as *u8)
86 return 0
87}
88func cgp_root() -> *u8 { return cgp_root_p as *u8 }
89func cgp_tree() -> *u8 { return cgp_tree_p as *u8 }
90func cgp_know() -> *u8 { return cgp_know_p as *u8 }
91func cgp_conf() -> *u8 { return cgp_conf_p as *u8 }
92func cgp_fxsrc() -> *u8 { return cgp_fxsrc_p as *u8 }
93func cgp_fxs() -> *u8 { return cgp_fxs_p as *u8 }
94func cgp_fxelf() -> *u8 { return cgp_fxelf_p as *u8 }
95func cgp_cache() -> *u8 { return cgp_cache_p as *u8 }
96func cgp_cc() -> *u8 { return cgp_cc_p as *u8 }
97func cgp_asm() -> *u8 { return cgp_asm_p as *u8 }
98func cgp_lock() -> *u8 { return cgp_lock_p as *u8 }
99func cgp_rt() -> *u8 { return cgp_rt_p as *u8 }
100func cgp_hdl() -> *u8 { return cgp_hdl_p as *u8 }
101func cgp_offc() -> *u8 { return cgp_offc_p as *u8 }
102func cgp_build() -> *u8 { return cgp_build_p as *u8 }
103
104
105func cg_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
106func cg_p(s: *u8) -> i64 { sys_write(1, s, cg_len(s)); return 0 }
107func cg_nl() -> i64 { let b: *u8 = sys_mmap(2); b[0] = 10 as u8; sys_write(1, b, 1); sys_munmap(b, 2); return 0 }
108func cg_pn(v: i64) -> i64 { gv_num(v); return 0 }
109
110// sha256 hex of a file; 1 ok (out[0..64] + NUL), 0 unreadable
111func cg_sha(path: *u8, out: *u8) -> i64 {
112 let ln: *i64 = sys_mmap(16) as *i64
113 ln[0] = 0
114 let buf: *u8 = sys_read_file(path, ln)
115 if (buf as i64) == 0 { return 0 }
116 let n: i64 = ln[0]
117 let d: *u8 = sys_mmap(48)
118 sha256_digest(buf, n, d)
119 var i: i64 = 0
120 while i < 32 {
121 let v: i64 = d[i] as i64
122 let hi: i64 = (v >> 4) & 15
123 let lo: i64 = v & 15
124 if hi < 10 { out[i*2] = (48+hi) as u8 } else { out[i*2] = (87+hi) as u8 }
125 if lo < 10 { out[i*2+1] = (48+lo) as u8 } else { out[i*2+1] = (87+lo) as u8 }
126 i = i + 1
127 }
128 out[CG_SHA_HEX] = 0 as u8
129 return 1
130}
131func cg_hexeq(a: *u8, b: *u8) -> i64 {
132 var i: i64 = 0
133 while i < CG_SHA_HEX { if a[i] != b[i] { return 0 } i = i + 1 }
134 return 1
135}
136
137// copy whole file src -> dst, mode applied; 1 ok, 0 fail
138func cg_copy(src: *u8, dst: *u8, mode: i64) -> i64 {
139 let ln: *i64 = sys_mmap(16) as *i64
140 ln[0] = 0
141 let buf: *u8 = sys_read_file(src, ln)
142 if (buf as i64) == 0 { return 0 }
143 let n: i64 = ln[0]
144 sys_unlinkat(dst)
145 let fd: i64 = sys_openat_wr(dst, mode)
146 if fd < 0 { return 0 }
147 let w: i64 = gk_write_all(fd, buf, n)
148 sys_close(fd)
149 if w != n { return 0 }
150 nx_chmod(dst, mode)
151 return 1
152}
153
154// unlink every regular file directly inside dir (no recursion; the fixture cache is flat). Returns the
155// number removed, -1 if the dir could not be opened.
156func cg_clear_dir(dir: *u8) -> i64 {
157 let fd: i64 = sys_openat_rd(dir)
158 if fd < 0 { return 0 - 1 }
159 let gbuf: *u8 = sys_mmap(CG_DIRBUF)
160 let path: *u8 = sys_mmap(CG_PATH)
161 var removed: i64 = 0
162 var nread: i64 = sys_getdents64(fd, gbuf, CG_DIRBUF)
163 while nread > 0 {
164 var off: i64 = 0
165 while off < nread {
166 let reclen: i64 = (gbuf[off + CG_DENT_RECLEN_OFF] as i64) | ((gbuf[off + CG_DENT_RECLEN_OFF + 1] as i64) << 8)
167 if reclen <= 0 { off = nread }
168 if reclen > 0 {
169 let nm: *u8 = ((gbuf as i64) + off + CG_DENT_NAME_OFF) as *u8
170 var isdot: i64 = 0
171 if nm[0] == (46 as u8) { if nm[1] == (0 as u8) { isdot = 1 } }
172 if nm[0] == (46 as u8) { if nm[1] == (46 as u8) { if nm[2] == (0 as u8) { isdot = 1 } } }
173 if isdot == 0 {
174 var o: i64 = gk_cat(path, 0, dir)
175 path[o] = 47 as u8; o = o + 1
176 o = gk_cat(path, o, nm); path[o] = 0 as u8
177 if sys_unlinkat(path) == 0 { removed = removed + 1 }
178 }
179 off = off + reclen
180 }
181 }
182 nread = sys_getdents64(fd, gbuf, CG_DIRBUF)
183 }
184 sys_close(fd)
185 return removed
186}
187// count entries in dir whose name ends with `suffix`; -1 if unopenable
188func cg_count_suffix(dir: *u8, suffix: *u8) -> i64 {
189 let fd: i64 = sys_openat_rd(dir)
190 if fd < 0 { return 0 - 1 }
191 let gbuf: *u8 = sys_mmap(CG_DIRBUF)
192 let sl: i64 = cg_len(suffix)
193 var cnt: i64 = 0
194 var nread: i64 = sys_getdents64(fd, gbuf, CG_DIRBUF)
195 while nread > 0 {
196 var off: i64 = 0
197 while off < nread {
198 let reclen: i64 = (gbuf[off + CG_DENT_RECLEN_OFF] as i64) | ((gbuf[off + CG_DENT_RECLEN_OFF + 1] as i64) << 8)
199 if reclen <= 0 { off = nread }
200 if reclen > 0 {
201 let nm: *u8 = ((gbuf as i64) + off + CG_DENT_NAME_OFF) as *u8
202 let nl: i64 = cg_len(nm)
203 if nl >= sl {
204 var j: i64 = 0
205 var ok: i64 = 1
206 while j < sl { if nm[nl - sl + j] != suffix[j] { ok = 0; j = sl } else { j = j + 1 } }
207 if ok == 1 { cnt = cnt + 1 }
208 }
209 off = off + reclen
210 }
211 }
212 nread = sys_getdents64(fd, gbuf, CG_DIRBUF)
213 }
214 sys_close(fd)
215 return cnt
216}
217
218// write the fixture program with the given exit code (the ONE byte that differs between v1 and v2)
219func cg_write_fixture(exit_code: i64) -> i64 {
220 let txt: *u8 = sys_mmap(CG_PATH)
221 var o: i64 = gk_cat(txt, 0, "import \"nx_syscalls.nx\"" as *u8)
222 txt[o] = 10 as u8; o = o + 1
223 o = gk_cat(txt, o, "func main(argc: i64, argv: *i64) -> i64 {" as *u8)
224 txt[o] = 10 as u8; o = o + 1
225 o = gk_cat(txt, o, " sys_write(1, \"casfx\" as *u8, 5)" as *u8)
226 txt[o] = 10 as u8; o = o + 1
227 o = gk_cat(txt, o, " return " as *u8)
228 o = gk_catn(txt, o, exit_code)
229 txt[o] = 10 as u8; o = o + 1
230 o = gk_cat(txt, o, "}" as *u8)
231 txt[o] = 10 as u8; o = o + 1
232 txt[o] = 0 as u8
233 if gk_write(cgp_fxsrc(), txt) < 0 { return 0 }
234 // Fixture source changes and their identity evidence are one authoring operation.
235 let status_dir: *u8 = cgp_mk(cgp_know(), "/status" as *u8) as *u8
236 gk_mkdir(status_dir)
237 let rule_path: *u8 = cgp_mk(cgp_know(), "/tree_canon.conf" as *u8) as *u8
238 if gk_write(rule_path, "_hdl_build/casfx.nx\n" as *u8) < 0 { return 0 }
239 let digest: *u8 = sys_mmap(CG_SHA_HEX + 2)
240 if cg_sha(cgp_fxsrc(), digest) != 1 { return 0 }
241 let row: *u8 = sys_mmap(CG_PATH)
242 var ro: i64 = gk_cat(row, 0, digest)
243 ro = gk_cat(row, ro, " " as *u8)
244 ro = gk_catn(row, ro, gk_size(cgp_fxsrc()))
245 ro = gk_cat(row, ro, " _hdl_build/casfx.nx\n" as *u8)
246 row[ro] = 0 as u8
247 let manifest: *u8 = cgp_mk(status_dir, "/treecanon_laptop_hash.mf" as *u8) as *u8
248 if gk_write(manifest, row) < 0 { return 0 }
249 return 1
250}
251
252// run the subject builder on the fixture INSIDE the fixture tree; output captured into out; returns rc.
253// extra = an optional lane flag (e.g. "--no-cache") or 0.
254func cg_build(subject: *u8, extra: *u8, out: *u8, outlen: *i64, ctr: *i64) -> i64 {
255 let here: *u8 = sys_mmap(CG_PATH)
256 sys_getcwd(here, CG_PATH)
257 sys_chdir(cgp_tree())
258 var rc: i64 = 0
259 if extra == (0 as *u8) { rc = gk_run_capture_ms(subject, CG_FX, "--build-only" as *u8, 0 as *u8, 0 as *u8, 0, out, CG_OUT, outlen) }
260 if extra != (0 as *u8) { rc = gk_run_capture_ms(subject, CG_FX, extra, "--build-only" as *u8, 0 as *u8, 0, out, CG_OUT, outlen) }
261 sys_chdir(here)
262 if rc != 0 {
263 cg_show_on_fail(0, out, outlen[0])
264 var blocked: i64 = gk_out_has(out, outlen[0], "REFUSED-BUILD-ADMIT" as *u8)
265 if gk_out_has(out, outlen[0], "REFUSED-TREE-CANON" as *u8) == 1 { blocked = 1 }
266 if blocked == 1 { gv_need("build prerequisites admitted; dependent cache checks stopped" as *u8, 0, ctr) }
267 else { gv_check("fixture build completed; dependent cache checks stopped" as *u8, 0, ctr) }
268 let verdict: i64 = gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "see failed build receipt above" as *u8)
269 sys_exit(verdict)
270 }
271 return rc
272}
273// run the BUILT fixture; returns its exit code
274func cg_run_fx() -> i64 { return gk_run(cgp_fxelf(), 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8) }
275
276// copy the 64-hex key after the first "key=" in out into keyout (NUL-terminated); 1 ok / 0 absent
277func cg_key_of(out: *u8, n: i64, keyout: *u8) -> i64 {
278 let p: i64 = gk_out_pos(out, n, " key=" as *u8)
279 if p < 0 { return 0 }
280 var i: i64 = 0
281 while i < CG_SHA_HEX {
282 if p + 5 + i >= n { return 0 }
283 keyout[i] = out[p + 5 + i]
284 i = i + 1
285 }
286 keyout[CG_SHA_HEX] = 0 as u8
287 return 1
288}
289// Does a FILE contain <needle>? 1 yes / 0 no / -1 unreadable. Used only to ask whether the subject binary
290// carries the vocabulary for a refusal -- i.e. whether the failure has a NAME at all.
291func cg_file_has(path: *u8, needle: *u8) -> i64 {
292 let ln: *i64 = sys_mmap(16) as *i64
293 ln[0] = 0
294 let buf: *u8 = sys_read_file(path, ln)
295 if (buf as i64) == 0 { return 0 - 1 }
296 return gk_out_has(buf, ln[0], needle)
297}
298// THE NEEDLE IS ASSEMBLED, NEVER WRITTEN CONTIGUOUSLY. A detector that spells its own pattern in one
299// literal appears in every grep for that pattern beside the organs that actually emit it, and matches
300// itself the moment anyone points it at its own binary -- the estate has paid for that twice. Two halves,
301// joined at run time, so this gate's elf does not contain the string it hunts.
302func cg_needle_anm(out: *u8) -> *u8 {
303 var o: i64 = gk_cat(out, 0, "artifact-not-mat" as *u8)
304 o = gk_cat(out, o, "erialised" as *u8)
305 out[o] = 0 as u8
306 return out
307}
308func cg_show_on_fail(cond: i64, out: *u8, n: i64) -> i64 {
309 if cond == 1 { return 0 }
310 var m: i64 = n
311 if m > CG_MAXOUT_SHOW { m = CG_MAXOUT_SHOW }
312 cg_p(" ---- subject output (head) ----" as *u8); cg_nl()
313 sys_write(1, out, m)
314 cg_nl()
315 return 0
316}
317// append ONE byte to a file (the toolchain-change fixture); returns new size or -1
318func cg_append_byte(path: *u8) -> i64 {
319 let fd: i64 = sys_openat_rdwr(path, CG_MODE_X)
320 if fd < 0 { return 0 - 1 }
321 let end: i64 = sys_lseek(fd, 0, 2)
322 let b: *u8 = sys_mmap(2)
323 b[0] = 0 as u8
324 let w: i64 = sys_write(fd, b, 1)
325 sys_close(fd)
326 if w != 1 { return 0 - 1 }
327 return end + 1
328}
329// flip the LAST byte of a file in place (size preserved); 1 ok
330func cg_flip_last(path: *u8) -> i64 {
331 let fd: i64 = sys_openat_rdwr(path, CG_MODE_X)
332 if fd < 0 { return 0 }
333 let end: i64 = sys_lseek(fd, 0, 2)
334 if end <= 0 { sys_close(fd); return 0 }
335 sys_lseek(fd, end - 1, 0)
336 let b: *u8 = sys_mmap(2)
337 if sys_read(fd, b, 1) != 1 { sys_close(fd); return 0 }
338 b[0] = (b[0] as i64 ^ 255) as u8
339 sys_lseek(fd, end - 1, 0)
340 let w: i64 = sys_write(fd, b, 1)
341 sys_close(fd)
342 if w != 1 { return 0 }
343 return 1
344}
345
346func main(argc: i64, argv: *i64) -> i64 {
347 gv_head("nx_bld_cache_cas_gate -- B2 content-addressed build cache: hit=verified+zero-compile, miss on any input change, corruption refused" as *u8)
348 let ctr: *i64 = gv_ctr()
349
350 // ---- resolve the tree and the subject, and SAY which ----
351 let rt: *u8 = sys_mmap(CG_PATH)
352 if gv_need("source tree resolvable (gk_corpus_root)" as *u8, gk_corpus_root(rt), ctr) == 0 {
353 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "no tree" as *u8)
354 }
355 // buildroot = rt minus trailing "runtime/"; nishihost = buildroot minus trailing "buildroot/"
356 let rtl: i64 = cg_len(rt)
357 let buildroot: *u8 = sys_mmap(CG_PATH)
358 var bo: i64 = 0
359 while bo < rtl - 8 { buildroot[bo] = rt[bo]; bo = bo + 1 }
360 buildroot[bo] = 0 as u8
361 let nishihost: *u8 = sys_mmap(CG_PATH)
362 var ho: i64 = 0
363 if bo > 10 { while ho < bo - 10 { nishihost[ho] = buildroot[ho]; ho = ho + 1 } }
364 nishihost[ho] = 0 as u8
365 let subject: *u8 = sys_mmap(CG_PATH)
366 var chosen: *u8 = "argv" as *u8
367 if argc >= 2 {
368 let a1: *u8 = argv[1] as *u8
369 var so: i64 = 0
370 if a1[0] != (47 as u8) {
371 let here: *u8 = sys_mmap(CG_PATH)
372 sys_getcwd(here, CG_PATH)
373 so = gk_cat(subject, 0, here); subject[so] = 47 as u8; so = so + 1
374 }
375 so = gk_cat(subject, so, a1); subject[so] = 0 as u8
376 }
377 if argc < 2 {
378 var so: i64 = gk_cat(subject, 0, nishihost); so = gk_cat(subject, so, "nx_sov_build_run.sov.elf.new" as *u8); subject[so] = 0 as u8
379 chosen = "staged(.sov.elf.new)" as *u8
380 if gk_exists(subject) == 0 {
381 so = gk_cat(subject, 0, buildroot); so = gk_cat(subject, so, "_build/nx_sov_build_run.sov.elf" as *u8); subject[so] = 0 as u8
382 chosen = "built(_build)" as *u8
383 }
384 if gk_exists(subject) == 0 {
385 so = gk_cat(subject, 0, buildroot); so = gk_cat(subject, so, "_offc/nx_sov_build_run.elf" as *u8); subject[so] = 0 as u8
386 chosen = "live(_offc)" as *u8
387 }
388 }
389 let subj_sha: *u8 = sys_mmap(CG_SHA_HEX + 2)
390 let have_subj: i64 = cg_sha(subject, subj_sha)
391 cg_p(" subject=" as *u8); cg_p(subject); cg_p(" [" as *u8); cg_p(chosen); cg_p("] sha256=" as *u8)
392 if have_subj == 1 { cg_p(subj_sha) } else { cg_p("UNREADABLE" as *u8) }
393 cg_nl()
394 if gv_need("subject builder readable" as *u8, have_subj, ctr) == 0 {
395 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "no subject" as *u8)
396 }
397
398 // ---- fixture tree: created/wiped at SETUP (idempotent across runs) ----
399 cgp_init(buildroot)
400 cg_p(" fixture=" as *u8); cg_p(cgp_root()); cg_nl()
401 gk_mkdir(cgp_root()); gk_mkdir(cgp_tree()); gk_mkdir(cgp_know())
402 gk_mkdir(cgp_rt()); gk_mkdir(cgp_hdl()); gk_mkdir(cgp_offc()); gk_mkdir(cgp_build())
403 gk_mkdir(cgp_cache())
404 cg_clear_dir(cgp_cache())
405 sys_unlinkat(cgp_fxs()); sys_unlinkat(cgp_fxelf()); sys_unlinkat(cgp_conf())
406 sys_unlinkat(cgp_lock())
407 let p1: *u8 = sys_mmap(CG_PATH)
408 let p2: *u8 = sys_mmap(CG_PATH)
409 var ok_src: i64 = 1
410 var o1: i64 = gk_cat(p1, 0, rt); o1 = gk_cat(p1, o1, "nx_syscalls.nx" as *u8); p1[o1] = 0 as u8
411 if cg_copy(p1, cgp_mk(cgp_rt(), "/nx_syscalls.nx" as *u8) as *u8, 420) == 0 { ok_src = 0 }
412 o1 = gk_cat(p1, 0, rt); o1 = gk_cat(p1, o1, "nx_tier.nx" as *u8); p1[o1] = 0 as u8
413 if cg_copy(p1, cgp_mk(cgp_rt(), "/nx_tier.nx" as *u8) as *u8, 420) == 0 { ok_src = 0 }
414 o1 = gk_cat(p1, 0, rt); o1 = gk_cat(p1, o1, "nx_crash.nx" as *u8); p1[o1] = 0 as u8
415 if cg_copy(p1, cgp_mk(cgp_rt(), "/nx_crash.nx" as *u8) as *u8, 420) == 0 { ok_src = 0 }
416 var o2: i64 = gk_cat(p2, 0, buildroot); o2 = gk_cat(p2, o2, "_offc/nx_cc_sovereign.elf" as *u8); p2[o2] = 0 as u8
417 var ok_tc: i64 = 1
418 if cg_copy(p2, cgp_cc(), CG_MODE_X) == 0 { ok_tc = 0 }
419 let cc_real_sha: *u8 = sys_mmap(CG_SHA_HEX + 2)
420 let cc_copy_sha: *u8 = sys_mmap(CG_SHA_HEX + 2)
421 if cg_sha(p2, cc_real_sha) == 0 { ok_tc = 0 }
422 o2 = gk_cat(p2, 0, buildroot); o2 = gk_cat(p2, o2, "_offc/nxasm_x86_main.elf" as *u8); p2[o2] = 0 as u8
423 if cg_copy(p2, cgp_asm(), CG_MODE_X) == 0 { ok_tc = 0 }
424 if gv_need("fixture closure sources copied (nx_syscalls, nx_tier, nx_crash)" as *u8, ok_src, ctr) == 0 {
425 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "fixture" as *u8)
426 }
427 if gv_need("live toolchain copied into the fixture _offc (nx_cc_sovereign + nxasm_x86_main)" as *u8, ok_tc, ctr) == 0 {
428 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "fixture" as *u8)
429 }
430 // The real runner requires explicit admission; fixtures must provision that dependency too.
431 o2 = gk_cat(p2, 0, buildroot); o2 = gk_cat(p2, o2, "_build/nx_build_admit.sov.elf" as *u8); p2[o2] = 0 as u8
432 if gk_exists(p2) == 0 {
433 o2 = gk_cat(p2, 0, nishihost); o2 = gk_cat(p2, o2, "nx_build_admit.elf" as *u8); p2[o2] = 0 as u8
434 }
435 let admit_dest: *u8 = cgp_mk(cgp_build(), "/nx_build_admit.sov.elf" as *u8) as *u8
436 if gv_need("fixture admission executable copied from real tree", cg_copy(p2, admit_dest, CG_MODE_X), ctr) == 0 {
437 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "fixture admission unavailable; cache not exercised" as *u8)
438 }
439 let admit_source_sha: *u8 = sys_mmap(CG_SHA_HEX + 2)
440 let admit_copy_sha: *u8 = sys_mmap(CG_SHA_HEX + 2)
441 var admit_same: i64 = 0
442 if cg_sha(p2, admit_source_sha) == 1 { if cg_sha(admit_dest, admit_copy_sha) == 1 { admit_same = cg_hexeq(admit_source_sha, admit_copy_sha) } }
443 if gv_need("fixture admission copy matches real executable bytes", admit_same, ctr) == 0 {
444 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "fixture admission identity mismatch; cache not exercised" as *u8)
445 }
446 // Keep the host policy, including confirmation timestamps; never relax thresholds for a test.
447 var host_policy: *u8 = cgp_mk(buildroot, "knowledge/build_admit.conf" as *u8) as *u8
448 if gk_exists(host_policy) == 0 { host_policy = cgp_mk(nishihost, "knowledge/build_admit.conf" as *u8) as *u8 }
449 let fixture_policy: *u8 = cgp_mk(cgp_know(), "/build_admit.conf" as *u8) as *u8
450 if gk_exists(host_policy) == 1 {
451 if gv_need("host admission policy copied unchanged", cg_copy(host_policy, fixture_policy, 420), ctr) == 0 { return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "policy copy failed" as *u8) }
452 cg_p(" admission_policy=" as *u8); cg_p(host_policy); cg_nl()
453 } else {
454 sys_unlinkat(fixture_policy)
455 cg_p(" admission_policy=host-derived (no host policy file)\n" as *u8)
456 }
457 var host_confirm: *u8 = cgp_mk(buildroot, "knowledge/status/ioconfirm.status" as *u8) as *u8
458 if gk_exists(host_confirm) == 0 { host_confirm = cgp_mk(nishihost, "knowledge/status/ioconfirm.status" as *u8) as *u8 }
459 let fixture_status: *u8 = cgp_mk(cgp_know(), "/status" as *u8) as *u8
460 gk_mkdir(fixture_status)
461 let fixture_confirm: *u8 = cgp_mk(fixture_status, "/ioconfirm.status" as *u8) as *u8
462 if gk_exists(host_confirm) == 1 {
463 if gv_need("confirmation snapshot copied with original timestamp", cg_copy(host_confirm, fixture_confirm, 420), ctr) == 0 { return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "confirmation copy failed" as *u8) }
464 } else { sys_unlinkat(fixture_confirm) }
465 var cc_same: i64 = 0
466 if cg_sha(cgp_cc(), cc_copy_sha) == 1 { cc_same = cg_hexeq(cc_real_sha, cc_copy_sha) }
467 gv_check("fixture-reached: fixture compiler copy re-hashes to the live compiler" as *u8, cc_same, ctr)
468 gv_check("fixture-reached: fixture cache dir empty at setup" as *u8, (cg_count_suffix(cgp_cache(), ".sov.elf" as *u8) == 0) as i64, ctr)
469 cg_write_fixture(CG_FX_EXIT_A)
470 // The fixture toolchain must EXECUTE from where it was copied (a noexec mount or a lost mode bit
471 // would make every builder run below fail with an empty .s and an empty stderr -- which reads as a
472 // compiler defect). Run the copied compiler directly on the fixture source, inside the tree.
473 let cco: *u8 = sys_mmap(CG_OUT)
474 let ccl: *i64 = sys_mmap(16) as *i64
475 let here0: *u8 = sys_mmap(CG_PATH)
476 sys_getcwd(here0, CG_PATH)
477 sys_chdir(cgp_tree())
478 let ccrc: i64 = gk_run_capture_ms(cgp_cc(), "runtime/_hdl_build/casfx.nx" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0, cco, CG_OUT, ccl)
479 sys_chdir(here0)
480 cg_p(" fixture compiler direct run: rc=" as *u8); cg_pn(ccrc); cg_p(" out_bytes=" as *u8); cg_pn(ccl[0]); cg_nl()
481 let ccok: i64 = ((ccrc == 0) as i64) * ((ccl[0] > 0) as i64)
482 if gv_need("fixture-reached: the copied compiler EXECUTES in the fixture tree and emits asm (rc 0, bytes > 0)" as *u8, ccok, ctr) == 0 {
483 cg_show_on_fail(0, cco, ccl[0])
484 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "fixture toolchain cannot run here (noexec /tmp? mode?) -- no evidence about the builder" as *u8)
485 }
486
487 let out: *u8 = sys_mmap(CG_OUT)
488 let ol: *i64 = sys_mmap(16) as *i64
489 let sha1: *u8 = sys_mmap(CG_SHA_HEX + 2)
490 let shax: *u8 = sys_mmap(CG_SHA_HEX + 2)
491 let key1: *u8 = sys_mmap(CG_SHA_HEX + 2)
492 let keyx: *u8 = sys_mmap(CG_SHA_HEX + 2)
493
494 // ---- T1: first build MISSES (no entry), compiles, stores entry + sidecar ----
495 var rc: i64 = cg_build(subject, 0 as *u8, out, ol, ctr)
496 var c: i64 = (rc == 0) as i64
497 if gv_need("T1 first build: builder exit 0" as *u8, c, ctr) == 0 {
498 cg_show_on_fail(c, out, ol[0])
499 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "first build failed; dependent cache assertions not run" as *u8)
500 }
501 gv_check("T1 first build: announces BUILD-CACHE MISS reason=no-entry" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=no-entry" as *u8), ctr)
502 gv_check("T1 first build: announces BUILD-CACHE STORE" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE STORE" as *u8), ctr)
503 gv_check("T1 first build: compiler RAN (_build/casfx.s present -- the witness the hit tooth relies on)" as *u8, gk_exists(cgp_fxs()), ctr)
504 gv_check("T1 first build: artifact present" as *u8, gk_exists(cgp_fxelf()), ctr)
505 gv_check("T1 first build: cache holds exactly one entry" as *u8, (cg_count_suffix(cgp_cache(), ".sov.elf" as *u8) == 1) as i64, ctr)
506 gv_check("T1 first build: cache holds exactly one sidecar" as *u8, (cg_count_suffix(cgp_cache(), ".sha" as *u8) == 1) as i64, ctr)
507 let have1: i64 = cg_sha(cgp_fxelf(), sha1)
508 let t1size: i64 = gk_size(cgp_fxelf())
509 gv_check("T1 first build: artifact hashable" as *u8, have1, ctr)
510 gv_check("T1 first build: key printed" as *u8, cg_key_of(out, ol[0], key1), ctr)
511 gv_check("T1 first build: built fixture runs with its declared exit code" as *u8, (cg_run_fx() == CG_FX_EXIT_A) as i64, ctr)
512
513 // ---- T2: unchanged rebuild HITS, compiler NOT forked, bytes identical, artifact executable ----
514 sys_unlinkat(cgp_fxs())
515 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
516 c = (rc == 0) as i64
517 gv_check("T2 unchanged rebuild: builder exit 0" as *u8, c, ctr); cg_show_on_fail(c, out, ol[0])
518 gv_check("T2 unchanged rebuild: announces BUILD-CACHE HIT" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE HIT" as *u8), ctr)
519 gv_check("T2 unchanged rebuild: ZERO compiler invocations (_build/casfx.s stays ABSENT)" as *u8, (gk_exists(cgp_fxs()) == 0) as i64, ctr)
520 var eq: i64 = 0
521 if cg_sha(cgp_fxelf(), shax) == 1 { eq = cg_hexeq(sha1, shax) }
522 gv_check("T2 unchanged rebuild: artifact byte-identical to the compiled one" as *u8, eq, ctr)
523 gv_check("T2 unchanged rebuild: served artifact is EXECUTABLE (mode preserved) and exits as declared" as *u8, (cg_run_fx() == CG_FX_EXIT_A) as i64, ctr)
524 gv_check("T2 unchanged rebuild: same key as T1" as *u8, (cg_key_of(out, ol[0], keyx) == 1) as i64 * cg_hexeq(key1, keyx), ctr)
525
526 // ---- T10: THE REFUSAL'S FOOTPRINT -- A HIT MUST MATERIALISE THE ARTIFACT (2026-09-04) ----------
527 // A build refused by admission UNLINKS _build/<t>.sov.elf (nx_sov_build_run does that before it
528 // consults the admitter) and leaves the cache entry and its sidecar untouched. That is the exact
529 // state the 2026-09-04 incident was reported in -- and NO tooth above exercises it: T2's rebuild runs
530 // with T1's artifact already on disk, so every T2 assertion about the served file is about a file the
531 // hit path never had to produce. MEASURED that day on a copy of the builder with the copy-back chain
532 // removed: it printed BUILD-CACHE HIT ... byte-identical artifact reused, exited 0, and left NO FILE.
533 // The two T2 teeth that happened to notice named the WRONG SUBJECT (wrong bytes, wrong mode) rather
534 // than "the builder claimed reuse and produced nothing", which is the sentence a reader needs.
535 sys_unlinkat(cgp_fxelf())
536 sys_unlinkat(cgp_fxs())
537 gv_check("fixture-reached-T10: artifact AND .s both ABSENT before the rebuild (the refusal's footprint)" as *u8, ((gk_exists(cgp_fxelf()) == 0) as i64) * ((gk_exists(cgp_fxs()) == 0) as i64), ctr)
538 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
539 c = (rc == 0) as i64
540 gv_check("T10 artifact deleted, entry+sidecar intact: builder exit 0" as *u8, c, ctr); cg_show_on_fail(c, out, ol[0])
541 gv_check("T10 artifact deleted, entry+sidecar intact: still announces BUILD-CACHE HIT" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE HIT" as *u8), ctr)
542 let t10_present: i64 = gk_exists(cgp_fxelf())
543 gv_check("T10 A HIT MUST MATERIALISE THE ARTIFACT -- a verified HIT that leaves no file on disk is the 2026-09-04 incident" as *u8, t10_present, ctr)
544 cg_show_on_fail(t10_present, out, ol[0])
545 gv_check_eq("T10 materialised artifact size equals the compiled one" as *u8, gk_size(cgp_fxelf()), t1size, ctr)
546 var eq10: i64 = 0
547 if cg_sha(cgp_fxelf(), shax) == 1 { eq10 = cg_hexeq(sha1, shax) }
548 gv_check("T10 materialised artifact is byte-identical to the compiled one" as *u8, eq10, ctr)
549 gv_check("T10 materialised artifact is EXECUTABLE and exits as declared" as *u8, (cg_run_fx() == CG_FX_EXIT_A) as i64, ctr)
550 gv_check("T10 ZERO compiler invocations (.s stays ABSENT -- a hit, not a silent recompile)" as *u8, (gk_exists(cgp_fxs()) == 0) as i64, ctr)
551 // ANTI-VACUITY, AND ITS LIMIT STATED IN ITS OWN NAME. The refusal this rung adds cannot be made to
552 // FIRE from outside the builder: with the copy-back chain intact the invariant it guards is not
553 // breakable by any arrangement of the cache, the sidecar or the artifact (all six such states were
554 // swept on 2026-09-04 and every one behaved correctly). Only a MUTANT builder makes it fire, and that
555 // is where its bite proof lives. What a gate CAN check from here is that the failure has a NAME at
556 // all -- a builder that cannot say "artifact-not-materialised" can only say HIT.
557 let anm: *u8 = sys_mmap(CG_PATH)
558 cg_needle_anm(anm)
559 gv_check("neg-control-T10-vocabulary: subject can NAME the artifact-not-materialised refusal (tests that the failure HAS a name, NOT that it fires -- only a mutant builder can make it fire)" as *u8, (cg_file_has(subject, anm) == 1) as i64, ctr)
560
561 // ---- T3: ONE-BYTE source edit MISSES (new key), compiles, new bytes, new behaviour ----
562 cg_write_fixture(CG_FX_EXIT_B)
563 sys_unlinkat(cgp_fxs())
564 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
565 c = (rc == 0) as i64
566 gv_check("T3 one-byte source edit: builder exit 0" as *u8, c, ctr); cg_show_on_fail(c, out, ol[0])
567 gv_check("T3 one-byte source edit: MISS reason=no-entry" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=no-entry" as *u8), ctr)
568 gv_check("neg-control-T3: the HIT detector stays silent on a real miss" as *u8, (gk_out_has(out, ol[0], "BUILD-CACHE HIT" as *u8) == 0) as i64, ctr)
569 gv_check("T3 one-byte source edit: compiler ran (.s present)" as *u8, gk_exists(cgp_fxs()), ctr)
570 var keydiff: i64 = 0
571 if cg_key_of(out, ol[0], keyx) == 1 { keydiff = (cg_hexeq(key1, keyx) == 0) as i64 }
572 gv_check("T3 one-byte source edit: key DIFFERS from T1" as *u8, keydiff, ctr)
573 var diff3: i64 = 0
574 if cg_sha(cgp_fxelf(), shax) == 1 { diff3 = (cg_hexeq(sha1, shax) == 0) as i64 }
575 gv_check("T3 one-byte source edit: artifact bytes differ" as *u8, diff3, ctr)
576 gv_check("T3 one-byte source edit: new artifact runs with the NEW exit code" as *u8, (cg_run_fx() == CG_FX_EXIT_B) as i64, ctr)
577 gv_check("T3: cache now holds two entries (both closures)" as *u8, (cg_count_suffix(cgp_cache(), ".sov.elf" as *u8) == 2) as i64, ctr)
578
579 // ---- T4: toolchain artifact change (one byte appended to the fixture compiler) MISSES on identical source ----
580 cg_write_fixture(CG_FX_EXIT_A)
581 let cc_size_before: i64 = gk_size(cgp_cc())
582 let cc_size_after: i64 = cg_append_byte(cgp_cc())
583 gv_check("fixture-reached-T4: fixture compiler is one byte longer" as *u8, (cc_size_after == cc_size_before + 1) as i64, ctr)
584 sys_unlinkat(cgp_fxs())
585 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
586 c = (rc == 0) as i64
587 gv_check("T4 toolchain sha change: builder exit 0 (appended compiler still compiles)" as *u8, c, ctr); cg_show_on_fail(c, out, ol[0])
588 gv_check("T4 toolchain sha change: MISS reason=no-entry on UNCHANGED source" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=no-entry" as *u8), ctr)
589 gv_check("T4 toolchain sha change: compiler ran (.s present)" as *u8, gk_exists(cgp_fxs()), ctr)
590 let key4: *u8 = sys_mmap(CG_SHA_HEX + 2)
591 var key4diff: i64 = 0
592 if cg_key_of(out, ol[0], key4) == 1 { key4diff = (cg_hexeq(key1, key4) == 0) as i64 }
593 gv_check("T4 toolchain sha change: key DIFFERS from T1 (toolchain bytes are in the key)" as *u8, key4diff, ctr)
594 var same4: i64 = 0
595 if cg_sha(cgp_fxelf(), shax) == 1 { same4 = cg_hexeq(sha1, shax) }
596 gv_check("T4 toolchain sha change: artifact bytes equal T1 (appended byte changes identity, not codegen)" as *u8, same4, ctr)
597
598 // ---- T5: corrupted cache entry is REFUSED (sha-mismatch), evicted, rebuilt, re-stored ----
599 let ent: *u8 = sys_mmap(CG_PATH)
600 var eo: i64 = gk_cat(ent, 0, cgp_cache()); ent[eo] = 47 as u8; eo = eo + 1
601 eo = gk_cat(ent, eo, key4); eo = gk_cat(ent, eo, ".sov.elf" as *u8); ent[eo] = 0 as u8
602 let side: *u8 = sys_mmap(CG_PATH)
603 var sdo: i64 = gk_cat(side, 0, ent); sdo = gk_cat(side, sdo, ".sha" as *u8); side[sdo] = 0 as u8
604 gv_check("fixture-reached-T5: T4's entry and sidecar exist at the printed key" as *u8, gk_exists(ent) * gk_exists(side), ctr)
605 let esha_before: *u8 = sys_mmap(CG_SHA_HEX + 2)
606 let esha_after: *u8 = sys_mmap(CG_SHA_HEX + 2)
607 cg_sha(ent, esha_before)
608 let flipped: i64 = cg_flip_last(ent)
609 var changed5: i64 = 0
610 if flipped == 1 { if cg_sha(ent, esha_after) == 1 { changed5 = (cg_hexeq(esha_before, esha_after) == 0) as i64 } }
611 gv_check("fixture-reached-T5: cached entry bytes were corrupted in place (size preserved, sha changed)" as *u8, changed5, ctr)
612 sys_unlinkat(cgp_fxs())
613 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
614 c = (rc == 0) as i64
615 gv_check("T5 corrupt entry: builder exit 0" as *u8, c, ctr); cg_show_on_fail(c, out, ol[0])
616 gv_check("neg-control-T5: corrupt entry REFUSED -- MISS reason=sha-mismatch" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=sha-mismatch" as *u8), ctr)
617 gv_check("neg-control-T5: corrupt entry not served as a HIT" as *u8, (gk_out_has(out, ol[0], "BUILD-CACHE HIT" as *u8) == 0) as i64, ctr)
618 gv_check("T5 corrupt entry: compiler ran (.s present)" as *u8, gk_exists(cgp_fxs()), ctr)
619 gv_check("T5 corrupt entry: re-stored (BUILD-CACHE STORE)" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE STORE" as *u8), ctr)
620 var good5: i64 = 0
621 if cg_sha(cgp_fxelf(), shax) == 1 { good5 = cg_hexeq(sha1, shax) }
622 gv_check("T5 corrupt entry: delivered artifact is the CORRECT bytes (equal T1)" as *u8, good5, ctr)
623 var repaired5: i64 = 0
624 if cg_sha(ent, shax) == 1 { repaired5 = cg_hexeq(sha1, shax) }
625 gv_check("T5 corrupt entry: cache entry repaired to the correct bytes" as *u8, repaired5, ctr)
626
627 // ---- T6: sidecar absent -> MISS (not served), rebuilt, repopulated; then a HIT follows ----
628 sys_unlinkat(side)
629 sys_unlinkat(cgp_fxs())
630 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
631 c = (rc == 0) as i64
632 gv_check("T6 sidecar absent: builder exit 0" as *u8, c, ctr); cg_show_on_fail(c, out, ol[0])
633 gv_check("neg-control-T6: entry without sidecar is NOT served -- MISS reason=sidecar-absent" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=sidecar-absent" as *u8), ctr)
634 gv_check("T6 sidecar absent: compiler ran (.s present)" as *u8, gk_exists(cgp_fxs()), ctr)
635 gv_check("T6 sidecar absent: sidecar re-written" as *u8, gk_exists(side), ctr)
636 sys_unlinkat(cgp_fxs())
637 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
638 gv_check("T6 after repopulate: next rebuild HITS with zero compiler invocations" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE HIT" as *u8) * ((gk_exists(cgp_fxs()) == 0) as i64), ctr)
639
640 // ---- T7: kill switches -- conf row and lane flag both bypass the store, loudly ----
641 gk_write(cgp_conf(), "cache_enabled=0\n" as *u8)
642 sys_unlinkat(cgp_fxs())
643 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
644 gv_check("T7 conf cache_enabled=0: MISS reason=disabled-by-conf and the compiler ran" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=disabled-by-conf" as *u8) * gk_exists(cgp_fxs()), ctr)
645 gk_write(cgp_conf(), "cache_enabled=1\n" as *u8)
646 sys_unlinkat(cgp_fxs())
647 rc = cg_build(subject, "--no-cache" as *u8, out, ol, ctr)
648 gv_check("T7 --no-cache: MISS reason=disabled-by-flag and the compiler ran" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=disabled-by-flag" as *u8) * gk_exists(cgp_fxs()), ctr)
649 sys_unlinkat(cgp_fxs())
650 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
651 gv_check("T7 switches off again: plain rebuild HITS" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE HIT" as *u8) * ((gk_exists(cgp_fxs()) == 0) as i64), ctr)
652
653 // ---- T8: determinism -- two COLD builds (cache wiped) are byte-identical ----
654 cg_clear_dir(cgp_cache())
655 sys_unlinkat(cgp_fxs())
656 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
657 let sha_a: *u8 = sys_mmap(CG_SHA_HEX + 2)
658 let ha: i64 = cg_sha(cgp_fxelf(), sha_a)
659 gv_check("T8 cold build A: MISS (cache was wiped) and compiled" as *u8, gk_out_has(out, ol[0], "BUILD-CACHE MISS reason=no-entry" as *u8) * gk_exists(cgp_fxs()), ctr)
660 cg_clear_dir(cgp_cache())
661 sys_unlinkat(cgp_fxs())
662 rc = cg_build(subject, 0 as *u8, out, ol, ctr)
663 let sha_b: *u8 = sys_mmap(CG_SHA_HEX + 2)
664 let hb: i64 = cg_sha(cgp_fxelf(), sha_b)
665 var det: i64 = 0
666 if ha == 1 { if hb == 1 { det = cg_hexeq(sha_a, sha_b) } }
667 gv_check("T8 determinism: two cold builds are byte-identical" as *u8, det, ctr)
668 var det1: i64 = 0
669 if ha == 1 { det1 = cg_hexeq(sha_a, sha1) }
670 gv_check("T8 determinism: cold builds equal the T1 artifact (same source, same codegen)" as *u8, det1, ctr)
671
672 // ---- T9: store hygiene -- no tmp residue left behind ----
673 gv_check("T9 store hygiene: no .tmp- residue in the cache dir" as *u8, (cg_count_suffix(cgp_cache(), ".tmp-casfx" as *u8) == 0) as i64, ctr)
674
675 gv_values_head()
676 gv_kv("t1_compiled_artifact_bytes" as *u8, t1size)
677 gv_kv("t10_delivered_after_hit_bytes" as *u8, gk_size(cgp_fxelf()))
678 gv_kv("cache_entries_at_end" as *u8, cg_count_suffix(cgp_cache(), ".sov.elf" as *u8))
679 gv_kv("cache_sidecars_at_end" as *u8, cg_count_suffix(cgp_cache(), ".sha" as *u8))
680 gv_kv("cache_tmp_residue_at_end" as *u8, cg_count_suffix(cgp_cache(), ".tmp-casfx" as *u8))
681 return gv_verdict("nx_bld_cache_cas_gate" as *u8, ctr, "subject builder judged end to end in an isolated fixture tree" as *u8)
682}