nx_forkfresh_gate.nx source
↩ module page · 222 lines · 13983 B
1// nx_forkfresh_gate.nx -- THE REFEREE FOR FORK FRESHNESS (nx_forkfresh_lib), 2026-08-31.
2//
3// IN-PROCESS over nx_forkfresh_lib.nx, deliberately. Nothing can import a main(), and a gate that
4// fork/execs the deployed nx_compare_regen.elf reports NOT-REACHED for every mutant -- its GREEN would
5// prove nothing about the code under test. organ_gate.conf carries that reasoning five times over.
6//
7// SCOPE, STATED SO IT CANNOT BE OVER-READ: this proves the DECISION CORE -- path derivation, the digest
8// ruler, the four-state classification and the abstention contract. It does NOT prove the nx_compare_regen
9// emit loop, its watchlist pass or its census; those stay unreferee'd and are the next rung, not a claim
10// being made here.
11//
12// FIXTURES LIVE IN /tmp/nx_forkfresh_gate/ AND NEVER IN knowledge/store/: a gate that shares its fixture
13// with a production beat reports on the fixture, not on the code (measured estate-wide, ratcheted).
14// Setup truncate-writes every fixture it needs on every run, and the two ABSENT fixtures are absent BY
15// CONSTRUCTION -- they are paths this gate never creates -- so the run is idempotent without a teardown.
16// A gate that is not idempotent reports on its first run and lies about every run after.
17// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
18import "nx_gate_verdict.nx"
19import "nx_forkfresh_lib.nx"
20
21const FG_DIR: *u8 = "/tmp/nx_forkfresh_gate"
22const FG_MODE_DIR: i64 = 493 // 0755
23const FG_MODE_FILE: i64 = 420 // 0644
24const FG_BODY_BYTES: i64 = 4096
25const FG_SUBJECTS: i64 = 5 // the five fixture pairs this gate classifies
26const FG_ABC_LEN: i64 = 3
27const FG_FILLER: i64 = 65 // ASCII A -- fixture body filler
28const FG_MUTANT: i64 = 66 // ASCII B -- the ONE byte that differs at equal size
29const FG_MUT_AT: i64 = 2048 // mid-body, so neither a header nor a tail special case
30const FG_SETUP_FILES: i64 = 7
31// Two DISTINCT sizes for the direction teeth. Their only property that matters is SMALL < LARGE, so they
32// are named for the role they play rather than left as bare numbers a reader would have to compare.
33const FG_DIR_SMALL: i64 = 1024
34const FG_DIR_LARGE: i64 = 4096
35
36func fg_write(path: *u8, buf: *u8, n: i64) -> i64 {
37 let fd: i64 = sys_openat_wr(path, FG_MODE_FILE)
38 if fd < 0 { return 0 }
39 var w: i64 = 0
40 while w < n {
41 let k: i64 = sys_write(fd, ((buf as i64) + w) as *u8, n - w)
42 if k <= 0 { w = n } else { w = w + k }
43 }
44 sys_close(fd)
45 return 1
46}
47
48func fg_streq(a: *u8, b: *u8) -> i64 {
49 var i: i64 = 0
50 while a[i] != (0 as u8) {
51 if a[i] != b[i] { return 0 }
52 i = i + 1
53 }
54 if b[i] != (0 as u8) { return 0 }
55 return 1
56}
57
58func main(argc: i64, argv: *i64) -> i64 {
59 gv_head("nx_forkfresh_gate -- the fork-freshness decision core, in-process" as *u8)
60 let ctr: *i64 = gv_ctr()
61 gv_subjects("fixture pairs classified" as *u8, FG_SUBJECTS, ctr)
62
63 sys_mkdir(FG_DIR, FG_MODE_DIR)
64 sys_mkdir("/tmp/nx_forkfresh_gate/_offc" as *u8, FG_MODE_DIR)
65
66 let body: *u8 = sys_mmap(FG_BODY_BYTES)
67 var i: i64 = 0
68 while i < FG_BODY_BYTES { body[i] = FG_FILLER as u8; i = i + 1 }
69 let mutant: *u8 = sys_mmap(FG_BODY_BYTES)
70 i = 0
71 while i < FG_BODY_BYTES { mutant[i] = FG_FILLER as u8; i = i + 1 }
72 mutant[FG_MUT_AT] = FG_MUTANT as u8
73
74 let f_same: *u8 = "/tmp/nx_forkfresh_gate/_offc/gen_same.elf"
75 let r_same: *u8 = "/tmp/nx_forkfresh_gate/gen_same.elf"
76 let f_diff: *u8 = "/tmp/nx_forkfresh_gate/_offc/gen_diff.elf"
77 let r_diff: *u8 = "/tmp/nx_forkfresh_gate/gen_diff.elf"
78 let f_noref: *u8 = "/tmp/nx_forkfresh_gate/_offc/gen_noref.elf"
79 let r_noref: *u8 = "/tmp/nx_forkfresh_gate/gen_noref_NEVER_CREATED.elf"
80 let f_gone: *u8 = "/tmp/nx_forkfresh_gate/_offc/gen_NEVER_CREATED.elf"
81 let f_empty: *u8 = "/tmp/nx_forkfresh_gate/_offc/gen_empty.elf"
82 let r_empty: *u8 = "/tmp/nx_forkfresh_gate/gen_empty.elf"
83
84 var wrote: i64 = 0
85 wrote = wrote + fg_write(f_same, body, FG_BODY_BYTES)
86 wrote = wrote + fg_write(r_same, body, FG_BODY_BYTES)
87 wrote = wrote + fg_write(f_diff, mutant, FG_BODY_BYTES)
88 wrote = wrote + fg_write(r_diff, body, FG_BODY_BYTES)
89 wrote = wrote + fg_write(f_noref, body, FG_BODY_BYTES)
90 wrote = wrote + fg_write(f_empty, body, 0)
91 wrote = wrote + fg_write(r_empty, body, 0)
92
93 // ASSERT THE FIXTURE REACHED THE CONDITION BEFORE ASSERTING THE OUTCOME. Every tooth below is a
94 // claim about files this run wrote; if setup silently failed, each one would pass or fail for a
95 // reason that has nothing to do with the code under test.
96 gv_check("fixture-setup-wrote-every-declared-file" as *u8, wrote == FG_SETUP_FILES, ctr)
97
98 let fd0: *u8 = sys_mmap(FF_DIGEST_BYTES)
99 let rd0: *u8 = sys_mmap(FF_DIGEST_BYTES)
100 let sz: *i64 = sys_mmap(FF_SIZES_SLOTS * 8) as *i64
101 var classified: i64 = 0
102
103 let s_same: i64 = ff_classify(f_same, r_same, fd0, rd0, sz)
104 classified = classified + 1
105 gv_check("identical-bytes-read-FORK-FRESH" as *u8, s_same == FF_FRESH, ctr)
106 gv_check("fresh-reports-both-sizes-measured" as *u8, sz[0] == FG_BODY_BYTES, ctr)
107
108 // THE LOAD-BEARING TOOTH: same size, one byte apart -> STALE.
109 // A SIZE COMPARISON CANNOT SEE THIS, AND A SIZE COMPARISON IS WHAT THE ESTATE KEPT REACHING FOR.
110 // The equal-size assertion runs FIRST and on the SAME classification, so this can never pass by
111 // accidentally comparing two differently-sized files.
112 let s_diff: i64 = ff_classify(f_diff, r_diff, fd0, rd0, sz)
113 classified = classified + 1
114 gv_check("fixture-reached-condition-equal-sizes" as *u8, sz[0] == sz[1], ctr)
115 gv_check("fixture-reached-condition-sizes-nonzero" as *u8, sz[0] == FG_BODY_BYTES, ctr)
116 gv_check("same-size-differing-content-reads-FORK-STALE" as *u8, s_diff == FF_STALE, ctr)
117
118 let s_nr: i64 = ff_classify(f_noref, r_noref, fd0, rd0, sz)
119 classified = classified + 1
120 gv_check("absent-reference-reads-FORK-UNPROVEN" as *u8, s_nr == FF_UNPROVEN, ctr)
121 gv_check("neg-control-absent-reference-is-not-STALE" as *u8, s_nr != FF_STALE, ctr)
122 gv_check("neg-control-absent-reference-is-not-FRESH" as *u8, s_nr != FF_FRESH, ctr)
123 // NEVER PRINT A FABRICATED SIZE BESIDE AN ABSTENTION.
124 gv_check("unmeasured-reference-size-stays-minus-one" as *u8, sz[1] == (0 - 1), ctr)
125
126 let s_gone: i64 = ff_classify(f_gone, r_same, fd0, rd0, sz)
127 classified = classified + 1
128 gv_check("absent-fork-target-reads-FORK-ABSENT" as *u8, s_gone == FF_NOFORK, ctr)
129 gv_check("neg-control-two-absences-are-distinguishable" as *u8, s_gone != s_nr, ctr)
130
131 // Two zero-byte files digest IDENTICALLY. A classifier that trusted the digest alone would call a
132 // pair of empty stubs FRESH and clear a build tree that contains nothing at all.
133 let s_empty: i64 = ff_classify(f_empty, r_empty, fd0, rd0, sz)
134 classified = classified + 1
135 gv_check("neg-control-empty-pair-does-not-read-FRESH" as *u8, s_empty != FF_FRESH, ctr)
136 gv_check("empty-pair-reads-FORK-ABSENT" as *u8, s_empty == FF_NOFORK, ctr)
137
138 // BIND THE AGGREGATE TO ITS DENOMINATOR: a tooth that passes because it examined zero subjects is
139 // not a tooth. This asserts the classifier was actually driven FG_SUBJECTS times.
140 gv_check("denominator-every-declared-subject-was-classified" as *u8, classified == FG_SUBJECTS, ctr)
141
142 gv_check("only-STALE-is-actionable" as *u8, ff_is_actionable(FF_STALE) == 1, ctr)
143 gv_check("neg-control-UNPROVEN-is-not-actionable" as *u8, ff_is_actionable(FF_UNPROVEN) == 0, ctr)
144 gv_check("neg-control-ABSENT-is-not-actionable" as *u8, ff_is_actionable(FF_NOFORK) == 0, ctr)
145 gv_check("neg-control-FRESH-is-not-actionable" as *u8, ff_is_actionable(FF_FRESH) == 0, ctr)
146
147 let pbuf: *u8 = sys_mmap(FF_PATH_BYTES)
148 ff_promoted_path("_offc/nx_swcompare_matrix.elf" as *u8, pbuf, "../" as *u8)
149 gv_check("promoted-path-derives-parent-plus-basename" as *u8, fg_streq(pbuf, "../nx_swcompare_matrix.elf" as *u8), ctr)
150 ff_promoted_path("nx_gen.elf" as *u8, pbuf, "../" as *u8)
151 gv_check("promoted-path-handles-a-bare-basename" as *u8, fg_streq(pbuf, "../nx_gen.elf" as *u8), ctr)
152 ff_promoted_path("a/b/c/deep.elf" as *u8, pbuf, "" as *u8)
153 gv_check("promoted-path-flattens-every-segment" as *u8, fg_streq(pbuf, "deep.elf" as *u8), ctr)
154 // neg-control: a derivation that simply echoed its input would pass a laxer test than the ones above.
155 ff_promoted_path("_offc/nx_swcompare_matrix.elf" as *u8, pbuf, "../" as *u8)
156 gv_check("neg-control-derivation-is-not-an-echo" as *u8, fg_streq(pbuf, "_offc/nx_swcompare_matrix.elf" as *u8) == 0, ctr)
157
158 // THE RULER ITSELF, against a PUBLISHED external vector (FIPS 180-4 NIST SHA-256 of abc).
159 // This is the tooth that makes the digest field cross-checkable: the same value nx_filehash prints.
160 let kd: *u8 = sys_mmap(FF_DIGEST_BYTES)
161 let kh: *u8 = sys_mmap(FF_HEX_BYTES)
162 sha256_digest("abc" as *u8, FG_ABC_LEN, kd)
163 ff_hex(kd, kh, FF_DIGEST_BYTES)
164 gv_check("sha256-hex-matches-the-published-NIST-abc-vector" as *u8, fg_streq(kh, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" as *u8), ctr)
165 // neg-control: a renderer that returned a constant would pass the vector tooth above forever.
166 let kd2: *u8 = sys_mmap(FF_DIGEST_BYTES)
167 let kh2: *u8 = sys_mmap(FF_HEX_BYTES)
168 sha256_digest("abd" as *u8, FG_ABC_LEN, kd2)
169 ff_hex(kd2, kh2, FF_DIGEST_BYTES)
170 gv_check("neg-control-hex-of-a-different-input-differs" as *u8, fg_streq(kh, kh2) == 0, ctr)
171 gv_check("hex-renders-full-digest-width" as *u8, ff_hex(kd, kh, FF_DIGEST_BYTES) == (FF_DIGEST_BYTES * 2), ctr)
172
173 gv_check("state-words-are-distinct-per-state" as *u8, fg_streq(ff_state_word(FF_FRESH), ff_state_word(FF_STALE)) == 0, ctr)
174
175 // ===== THE STALE DIRECTION, AND WHICH REMEDY IT MAKES SAFE =====================================
176 // A fork can differ from the promoted artifact in two directions that want OPPOSITE actions, and the
177 // consumer printed ONE remedy for both. These teeth pin the direction AND the safety predicate,
178 // because the failure that motivated them was not a wrong classification -- it was a CORRECT
179 // classification followed by the destructive remedy.
180 let dsz: *i64 = sys_mmap(FF_SIZES_SLOTS * 8) as *i64
181 dsz[0] = FG_DIR_SMALL; dsz[1] = FG_DIR_LARGE
182 gv_check("smaller-fork-reads-FORK-BEHIND" as *u8, ff_direction(FF_STALE, dsz) == FF_DIR_BEHIND, ctr)
183 dsz[0] = FG_DIR_LARGE; dsz[1] = FG_DIR_SMALL
184 gv_check("larger-fork-reads-FORK-AHEAD" as *u8, ff_direction(FF_STALE, dsz) == FF_DIR_AHEAD, ctr)
185 dsz[0] = FG_DIR_LARGE; dsz[1] = FG_DIR_LARGE
186 gv_check("equal-sizes-read-FORK-DIVERGED-SAME-SIZE" as *u8, ff_direction(FF_STALE, dsz) == FF_DIR_UNDECIDED, ctr)
187
188 // A DIRECTION ONLY EXISTS FOR A PAIR ALREADY PROVEN TO DIFFER. Deriving one for a FRESH pair would
189 // invent a remedy for an artifact that needs none, and for an ABSTENTION it would fabricate a finding.
190 dsz[0] = FG_DIR_SMALL; dsz[1] = FG_DIR_LARGE
191 gv_check("neg-control-a-FRESH-pair-has-no-direction" as *u8, ff_direction(FF_FRESH, dsz) == FF_DIR_NA, ctr)
192 gv_check("neg-control-an-UNPROVEN-pair-has-no-direction" as *u8, ff_direction(FF_UNPROVEN, dsz) == FF_DIR_NA, ctr)
193 gv_check("neg-control-an-ABSENT-pair-has-no-direction" as *u8, ff_direction(FF_NOFORK, dsz) == FF_DIR_NA, ctr)
194
195 // NEVER FABRICATE A DIRECTION FROM AN UNMEASURED SIZE -- the same law the -1 size slots already carry.
196 dsz[0] = 0 - 1; dsz[1] = FG_DIR_LARGE
197 gv_check("neg-control-unmeasured-fork-size-yields-no-direction" as *u8, ff_direction(FF_STALE, dsz) == FF_DIR_NA, ctr)
198 dsz[0] = FG_DIR_LARGE; dsz[1] = 0 - 1
199 gv_check("neg-control-unmeasured-promoted-size-yields-no-direction" as *u8, ff_direction(FF_STALE, dsz) == FF_DIR_NA, ctr)
200
201 // THE LOAD-BEARING TEETH: restage is safe for exactly ONE direction. The shipped defect answered YES
202 // for all of them, so a predicate that returned 1 everywhere would still pass the BEHIND tooth alone --
203 // the three refusals below are what make this a test rather than a restatement.
204 gv_check("restage-is-safe-for-a-fork-that-is-BEHIND" as *u8, ff_restage_is_safe(FF_DIR_BEHIND) == 1, ctr)
205 gv_check("neg-control-restage-is-NOT-safe-for-a-fork-that-is-AHEAD" as *u8, ff_restage_is_safe(FF_DIR_AHEAD) == 0, ctr)
206 gv_check("neg-control-restage-is-NOT-safe-when-UNDECIDED" as *u8, ff_restage_is_safe(FF_DIR_UNDECIDED) == 0, ctr)
207 gv_check("neg-control-restage-is-NOT-safe-with-no-direction" as *u8, ff_restage_is_safe(FF_DIR_NA) == 0, ctr)
208
209 // BIND THE DIRECTION TO THE REAL CLASSIFIER, NOT ONLY TO HAND-BUILT ARRAYS. The equal-size differing
210 // pair is the estate's own blind spot; re-classifying it here proves the two functions compose on a
211 // REAL measurement rather than on numbers this gate typed for itself.
212 let s_dir: i64 = ff_classify(f_diff, r_diff, fd0, rd0, sz)
213 gv_check("fixture-reached-condition-real-pair-is-STALE" as *u8, s_dir == FF_STALE, ctr)
214 gv_check("fixture-reached-condition-real-pair-sizes-equal" as *u8, sz[0] == sz[1], ctr)
215 gv_check("real-same-size-stale-pair-is-UNDECIDED-not-a-guess" as *u8, ff_direction(s_dir, sz) == FF_DIR_UNDECIDED, ctr)
216 gv_check("real-same-size-stale-pair-does-NOT-authorise-restage" as *u8, ff_restage_is_safe(ff_direction(s_dir, sz)) == 0, ctr)
217
218 gv_check("direction-words-are-distinct-per-direction" as *u8, fg_streq(ff_direction_word(FF_DIR_BEHIND), ff_direction_word(FF_DIR_AHEAD)) == 0, ctr)
219 gv_check("neg-control-a-direction-word-is-not-a-state-word" as *u8, fg_streq(ff_direction_word(FF_DIR_AHEAD), ff_state_word(FF_STALE)) == 0, ctr)
220
221 return gv_verdict("nx_forkfresh_gate" as *u8, ctr, "in-process over nx_forkfresh_lib: derivation, the digest ruler against a published vector, the four-state classification and the abstention contract" as *u8)
222}