nx_artifactdrift_gate.nx source
↩ module page · 259 lines · 13869 B
1// nx_artifactdrift_gate.nx -- THE BITE PROOF FOR THE FORK-ROOT AXIS (2026-08-31).
2//
3// WHY THIS GATE EXISTS. On 2026-08-31 a compare regen returned `published=201 fails=0 verdict=GREEN`
4// and published NOTHING: every one of the 201 lines reported prev= EQUAL to its new byte count. The
5// cause was a THIRD TWIN nobody was censusing -- nx_compare_regen chdirs into buildroot and forks the
6// BARE path `_offc/nx_swcompare_*.elf`, so buildroot/_offc is the copy the publisher actually executes,
7// and /api/promote never writes it. FOUR INDEPENDENT AGENTS each verified their promote against the
8// serving root and/or nishihost/_offc and all four missed it, because nx_catalog enumerates
9// SOURCE/BUILT/STAGED/PROMOTED/_offc and NOT buildroot/_offc -- so every row read BUILT==PROMOTED.
10//
11// nx_artifactdrift grew a FORK-ROOT axis for exactly this. That axis had never been proven to go
12// SILENT. A detector that has only ever fired on real data is HALF verified: firing proves it can
13// speak, never that its silence means anything. A GREEN THAT NEVER HAD A CORRESPONDING RED IS
14// UNVERIFIED -- AND SO IS A RED THAT NEVER HAD A CORRESPONDING GREEN.
15//
16// THIS GATE NEVER TOUCHES buildroot/_offc. The subject fork root is argv[7], overridable precisely
17// so a gate can point the axis at a FIXTURE tree. A gate that must perturb the directory the compare
18// publisher forks in order to report on it is a gate that can take the estate down to test itself.
19// Every fixture lives under /tmp/nx_artifactdrift_gate/ and the subject trend log is redirected
20// there too, so this can never append to knowledge/status/artifactdrift.log -- a gate must not share
21// its fixture with a production beat.
22//
23// THREE LEGS, because the axis has three honest answers and all three must be proven:
24// RED a planted twin that differs -> FIRES and NAMES it, carrying BOTH byte counts
25// GREEN a byte-identical twin -> SILENT (FORK-STALE=0 and no offender line at all)
26// ABSTAIN a fork root it cannot open -> UNPROVEN, and must NOT report agreement
27// The GREEN leg additionally asserts the twin was EXAMINED (FORK-IDENTICAL=1): a zero from an EMPTY
28// directory is the gate-passes-on-the-empty-set defect, and would look exactly like a real green.
29//
30// Exit carries the verdict via gv_verdict (0 GREEN / 1 RED / 3 SKIP).
31// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
32import "nx_gate_verdict.nx"
33import "nx_gatekit_lib.nx"
34import "nx_tool_run.nx"
35
36// The subject is the SERVING-ROOT binary, which is what nx_job_run and the roster fork. Measured
37// 2026-08-31: serving root and nishihost/_offc are byte-identical (sha 8b5a4f9f..., 71925 B), and
38// buildroot/_offc holds no twin of this organ at all -- so there is one artifact to prove, not three.
39// The leading ./ is REQUIRED: execve does no PATH lookup, so a bare basename fails ENOENT and the
40// gate would report on a subject it never launched.
41const AG_SUBJECT: *u8 = "./nx_artifactdrift.elf"
42const AG_DIR: *u8 = "/tmp/nx_artifactdrift_gate"
43const AG_A: *u8 = "/tmp/nx_artifactdrift_gate/forkA/"
44const AG_B: *u8 = "/tmp/nx_artifactdrift_gate/forkB/"
45const AG_BLIND: *u8 = "/tmp/nx_artifactdrift_gate/no_such_forkroot/"
46const AG_LOG: *u8 = "/tmp/nx_artifactdrift_gate/drift_fixture.log"
47const AG_ADIR: *u8 = "/tmp/nx_artifactdrift_gate/forkA"
48const AG_BDIR: *u8 = "/tmp/nx_artifactdrift_gate/forkB"
49
50// The subject own defaults, passed through so the MAIN census is unchanged and only the fork root
51// and the trend log move. Holding these fixed is what makes the separateness tooth meaningful.
52const AG_REG: *u8 = "tool_allowlist.conf"
53const AG_BROOT: *u8 = "buildroot/_build/"
54const AG_SRCA: *u8 = "buildroot/runtime/_hdl_build/"
55const AG_SRCB: *u8 = "buildroot/runtime/"
56const AG_DECL: *u8 = "knowledge/status/drift_owner_declare.conf"
57
58// DONOR is copied byte-for-byte to make an IDENTICAL twin. VICTIM is written as short text to make a
59// twin that DIFFERS. ORPHAN has no serving-root counterpart. All three are ordinary serving-root names
60// chosen because they exist; nothing about the proof depends on WHICH files these are, and the expected
61// output strings are DERIVED from the sizes measured at runtime, never written as literals -- a
62// hand-counted size beside a fixture is a second copy of that fixture shape and the two drift.
63const AG_DONOR: *u8 = "nx_magic.elf"
64const AG_VICTIM: *u8 = "nx_debtmine.elf"
65const AG_ORPHAN: *u8 = "nx_zzz_gatefixture.elf"
66const AG_PLANT: *u8 = "NOT-THE-SERVED-BYTES-planted-by-nx_artifactdrift_gate\n"
67
68const AG_CAP: i64 = 1048576 // > 12x the ~82 KB the live census emits; truncation is ASSERTED, not assumed
69const AG_MODE644: i64 = 420
70const AG_PATHBUF: i64 = 256
71const AG_LINEBUF: i64 = 1024
72const AG_NL: i64 = 10
73
74func ag_path(dir: *u8, name: *u8) -> *u8 {
75 let p: *u8 = sys_mmap(AG_PATHBUF)
76 var o: i64 = gv_cat(p, 0, dir)
77 o = gv_cat(p, o, name)
78 p[o] = 0 as u8
79 return p
80}
81
82// Binary-safe copy. gk_write takes a NUL-terminated STRING and would stop at the first zero byte of an
83// ELF, so the copy is done with an explicit length. A full buffer is reported as its own failure:
84// a silently truncated donor would produce a twin that DIFFERS, which is the opposite of what the
85// IDENTICAL fixture is for, and the gate would then pass its RED leg for the wrong reason.
86func ag_copy(src: *u8, dst: *u8, buf: *u8, cap: i64) -> i64 {
87 let n: i64 = gk_read(src, buf, cap)
88 if n < 0 { return 0 - 1 }
89 if n >= cap { return 0 - 2 }
90 let fd: i64 = sys_openat_wr(dst, AG_MODE644)
91 if fd < 0 { return 0 - 1 }
92 let w: i64 = gk_write_all(fd, buf, n)
93 sys_close(fd)
94 if w != n { return 0 - 1 }
95 return n
96}
97
98func ag_same(a: *u8, b: *u8, ba: *u8, bb: *u8, cap: i64) -> i64 {
99 let na: i64 = gk_read(a, ba, cap)
100 let nb: i64 = gk_read(b, bb, cap)
101 if na < 0 { return 0 }
102 if nb < 0 { return 0 }
103 if na != nb { return 0 }
104 var i: i64 = 0
105 var ok: i64 = 1
106 while i < na { if ba[i] != bb[i] { ok = 0; i = na } else { i = i + 1 } }
107 return ok
108}
109
110// Copy the line that STARTS at `key` up to the newline. Used to compare the subject main partition
111// summary across two runs that differ ONLY in their fork root.
112func ag_line_at(buf: *u8, n: i64, key: *u8, dst: *u8, cap: i64) -> i64 {
113 let p: i64 = gk_out_pos(buf, n, key)
114 if p < 0 { return 0 - 1 }
115 var i: i64 = p
116 var k: i64 = 0
117 while i < n {
118 if buf[i] == (AG_NL as u8) { i = n } else {
119 if k < cap - 1 { dst[k] = buf[i]; k = k + 1 }
120 i = i + 1
121 }
122 }
123 dst[k] = 0 as u8
124 return k
125}
126
127// Drive the subject with a full argv. gk_run_capture stops at four arguments and the fork root is the
128// SEVENTH, so the arbitrary-arity runner is the one composed here.
129func ag_run(forkp: *u8, out: *u8, cap: i64, ol: *i64) -> i64 {
130 let av: *i64 = sys_mmap(128) as *i64
131 av[0] = AG_SUBJECT as i64
132 av[1] = AG_REG as i64
133 av[2] = AG_BROOT as i64
134 av[3] = AG_SRCA as i64
135 av[4] = AG_SRCB as i64
136 av[5] = AG_DECL as i64
137 av[6] = AG_LOG as i64
138 av[7] = forkp as i64
139 av[8] = 0
140 return tr_run_capture(AG_SUBJECT, av, out, cap, ol)
141}
142
143func main(argc: i64, argv: *i64) -> i64 {
144 let ctr: *i64 = gv_ctr()
145 gv_head("nx_artifactdrift_gate -- FORK-ROOT AXIS: fires, stays silent, and abstains" as *u8)
146
147 // PRECONDITIONS. An absent subject or registry must ABSTAIN, never fail the axis. A gate that
148 // reports RED because it could not find what it guards indicts the wrong subject.
149 let donor_sz: i64 = gk_size(AG_DONOR)
150 let victim_sz: i64 = gk_size(AG_VICTIM)
151 gv_need("subject-present" as *u8, gk_exists(AG_SUBJECT), ctr)
152 gv_need("registry-present" as *u8, gk_exists(AG_REG), ctr)
153 gv_need("donor-present" as *u8, gk_exists(AG_DONOR), ctr)
154 gv_need("victim-present" as *u8, gk_exists(AG_VICTIM), ctr)
155
156 // SETUP. Fixtures are ASSEMBLED AT RUNTIME, never checked in: a detector that scans a tree would
157 // find its own committed fixture. Directories are created unconditionally and the fixture files are
158 // removed before being rewritten, so a second run cannot inherit the first run tree -- a gate that
159 // is not idempotent reports on its first run and lies on every run after.
160 gk_mkdir(AG_DIR)
161 gk_mkdir(AG_ADIR)
162 gk_mkdir(AG_BDIR)
163 let fa_donor: *u8 = ag_path(AG_A, AG_DONOR)
164 let fa_victim: *u8 = ag_path(AG_A, AG_VICTIM)
165 let fa_orphan: *u8 = ag_path(AG_A, AG_ORPHAN)
166 let fb_donor: *u8 = ag_path(AG_B, AG_DONOR)
167 let fb_victim: *u8 = ag_path(AG_B, AG_VICTIM)
168 let fb_orphan: *u8 = ag_path(AG_B, AG_ORPHAN)
169 gk_rm(fa_donor)
170 gk_rm(fa_victim)
171 gk_rm(fa_orphan)
172 gk_rm(fb_donor)
173 gk_rm(fb_victim)
174 gk_rm(fb_orphan)
175
176 let cpbuf: *u8 = sys_mmap(AG_CAP)
177 let cmpa: *u8 = sys_mmap(AG_CAP)
178 let cmpb: *u8 = sys_mmap(AG_CAP)
179 let ca: i64 = ag_copy(AG_DONOR, fa_donor, cpbuf, AG_CAP)
180 let cb: i64 = ag_copy(AG_DONOR, fb_donor, cpbuf, AG_CAP)
181 gk_write(fa_victim, AG_PLANT)
182 gk_write(fa_orphan, AG_PLANT)
183
184 // FIXTURE-REACHED-THE-CONDITION. Asserted BEFORE any outcome, because a fixture the defect cannot
185 // fail is not a test, and every outcome tooth below is meaningless if these do not hold.
186 var cpok: i64 = 0
187 if ca == donor_sz { if cb == donor_sz { cpok = 1 } }
188 gv_check("fixture-donor-copied-without-truncation" as *u8, cpok, ctr)
189 gv_check("fixture-identical-twin-is-byte-identical" as *u8, ag_same(fa_donor, AG_DONOR, cmpa, cmpb, AG_CAP), ctr)
190 var vdiff: i64 = 0
191 if gk_size(fa_victim) != victim_sz { vdiff = 1 }
192 gv_check("fixture-stale-twin-really-differs-from-served" as *u8, vdiff, ctr)
193 var orph: i64 = 0
194 if gk_exists(AG_ORPHAN) == 0 { orph = 1 }
195 gv_check("fixture-orphan-has-no-serving-root-counterpart" as *u8, orph, ctr)
196
197 let outa: *u8 = sys_mmap(AG_CAP)
198 let outb: *u8 = sys_mmap(AG_CAP)
199 let outc: *u8 = sys_mmap(AG_CAP)
200 let ola: *i64 = sys_mmap(16) as *i64
201 let olb: *i64 = sys_mmap(16) as *i64
202 let olc: *i64 = sys_mmap(16) as *i64
203 ag_run(AG_A, outa, AG_CAP, ola)
204 ag_run(AG_B, outb, AG_CAP, olb)
205 ag_run(AG_BLIND, outc, AG_CAP, olc)
206
207 // A capture that hit its ceiling is a PARTIAL read, and every absence tooth below would then be
208 // measuring the buffer instead of the subject.
209 var nota: i64 = 0
210 if ola[0] < AG_CAP { if olb[0] < AG_CAP { if olc[0] < AG_CAP { nota = 1 } } }
211 gv_check("captures-not-truncated" as *u8, nota, ctr)
212
213 // RED. The expected row is DERIVED from the two sizes this gate just measured, so the tooth proves
214 // the row carries the CORRECT byte counts, not merely that some digits are present.
215 let exp: *u8 = sys_mmap(AG_PATHBUF)
216 var eo: i64 = gv_cat(exp, 0, "FORK-STALE " as *u8)
217 eo = gv_cat(exp, eo, AG_VICTIM)
218 eo = gv_cat(exp, eo, " forkroot=" as *u8)
219 eo = gk_catn(exp, eo, gk_size(fa_victim))
220 eo = gv_cat(exp, eo, " served=" as *u8)
221 eo = gk_catn(exp, eo, victim_sz)
222 exp[eo] = 0 as u8
223 gv_check("red-fires-and-names-the-offender-with-both-byte-counts" as *u8, gk_out_has(outa, ola[0], exp), ctr)
224 gv_check("red-counts-the-identical-twin-as-FORK-IDENTICAL" as *u8, gk_out_has(outa, ola[0], "FORK-IDENTICAL=1" as *u8), ctr)
225 gv_check("red-names-the-orphan-as-FORK-ONLY-not-an-offender" as *u8, gk_out_has(outa, ola[0], "FORK-ONLY nx_zzz_gatefixture.elf" as *u8), ctr)
226 gv_check("red-fork-partition-reconciles" as *u8, gk_out_has(outa, ola[0], "sum=3 fork_partition=RECONCILES" as *u8), ctr)
227 gv_check("red-count-travels-with-its-remedy" as *u8, gk_out_has(outa, ola[0], "REMEDY: nx_restage" as *u8), ctr)
228
229 // GREEN neg-controls. FORK-STALE=0 alone is not silence: the offender line must be ABSENT, and the
230 // twin must have been EXAMINED or the zero came from an empty directory.
231 gv_check("neg-control-green-reports-zero-stale" as *u8, gk_out_has(outb, olb[0], "FORK-STALE=0" as *u8), ctr)
232 var quiet: i64 = 0
233 if gk_out_has(outb, olb[0], "FORK-STALE nx_" as *u8) == 0 { quiet = 1 }
234 gv_check("neg-control-green-names-no-offender-at-all" as *u8, quiet, ctr)
235 gv_check("neg-control-green-actually-examined-the-twin" as *u8, gk_out_has(outb, olb[0], "FORK-IDENTICAL=1" as *u8), ctr)
236
237 // ABSTENTION neg-controls. An axis that cannot see must never report agreement.
238 gv_check("neg-control-blind-axis-abstains-UNPROVEN" as *u8, gk_out_has(outc, olc[0], "FORK-ROOT UNPROVEN" as *u8), ctr)
239 var noacq: i64 = 0
240 if gk_out_has(outc, olc[0], "FORK-STALE=0" as *u8) == 0 { noacq = 1 }
241 gv_check("neg-control-blind-axis-does-not-acquit" as *u8, noacq, ctr)
242
243 // SEPARATENESS. The fork axis is declared a SEPARATE axis rather than a partition member, because a
244 // binary can be IDENTICAL on the build axis and FORK-STALE on this one at the same time. This proves
245 // it empirically: two runs whose fork roots hold DIFFERENT numbers of rows must produce a
246 // byte-identical main partition line. If fork rows ever leaked into that sum, this fails.
247 let la: *u8 = sys_mmap(AG_LINEBUF)
248 let lb: *u8 = sys_mmap(AG_LINEBUF)
249 let na: i64 = ag_line_at(outa, ola[0], "distinct_binaries=" as *u8, la, AG_LINEBUF)
250 let nb: i64 = ag_line_at(outb, olb[0], "distinct_binaries=" as *u8, lb, AG_LINEBUF)
251 var sep: i64 = 0
252 if na > 0 { if nb > 0 { sep = gk_streq(la, lb) } }
253 gv_check("fork-axis-is-separate-main-partition-unchanged" as *u8, sep, ctr)
254
255 // The gate must not be able to pollute the production trend log it is testing around.
256 gv_check("subject-trend-log-redirected-to-the-fixture" as *u8, gk_out_has(outa, ola[0], "appended -> /tmp/nx_artifactdrift_gate/" as *u8), ctr)
257
258 return gv_verdict("nx_artifactdrift_gate" as *u8, ctr, "fork-root axis of the deployed nx_artifactdrift; every fixture under /tmp/nx_artifactdrift_gate/" as *u8)
259}