code wiki / _hdl_build / nx_eqsat_membership_proof_test.nx
nx_eqsat_membership_proof_test.nx source
↩ module page · 354 lines · 22445 B
1// nx_eqsat_membership_proof_test.nx -- proves the MEMBERSHIP-AS-PROOF
2// CERTIFICATE for (mul x 8) == (shl x 3), and proves the certificate is
3// LOAD-BEARING (it FAILS when a non-sound rule is used or the endpoints are not
4// in the same e-class). FAIL LOUD known-answer; exit 0 iff every check holds.
5//
6// STRUCTURE (each step self-asserts; mismatch => sys_exit(nonzero)):
7// STEP 1 SOUND SET: run the W=8 masked exhaustive battery for the SIX
8// width-trivial unary rules + mul_pow2 in-range. Establishes the
9// proven-sound set this run (total == 1536 + 2048 == 3584, all pass).
10// BOTH witnesses (algebraic Witness A AND triangulated gsim Witness B)
11// must agree on every vector. This is what JUSTIFIES the allow-list.
12// STEP 0 LOCKSTEP: the membership organ's MP_RULE_* ids must equal the
13// engine's NX_EQSAT_RULE_* (single source of truth) so the LIVE log
14// the engine writes is never mislabeled against this allow-list.
15// STEP 2 CERTIFICATE (positive, LIVE): build an e-graph, add (mul x 8) and
16// (shl x 3), ENABLE provenance, run the REAL nx_eqsat_saturate (not a
17// gated driver), and certify STRICTLY FROM THE LOG the engine wrote at
18// its union chokepoint -- mul_pow2 fires at k=3<W, logs RULE_MUL_POW2,
19// find(mul8)==find(shl3), every logged id sound + no overflow ->
20// certified. This PROMOTES mul_pow2 into the proven-sound set, now
21// exercised through the live engine + its k<W guard.
22// STEP 3 LOAD-BEARING NEG-A (non-sound rule): the gated leg cites the BOGUS
23// rule (mul x 3)==(shl x 1) -> recorder REFUSES + certificate FAILS;
24// AND a LIVE leg -- the live engine has no bogus rule, so it never
25// unions (mul x 4) with (shl x 1) => live membership/certificate FAIL.
26// STEP 4 LOAD-BEARING NEG-B (endpoints not in same class): LIVE-certify
27// (mul x 8) against (shl x 2) -- the live engine merges mul8 with
28// (shl x 3), not (shl x 2), so membership FAILS and the certificate
29// FAILS even though the log is sound.
30// STEP 5 LOAD-BEARING NEG-C (k>=W boundary): the membership organ's
31// k<MP_W side-condition (mp_mul_pow2_k_ok==0 at k==W) must REFUSE +
32// FAIL the gated certificate; in the LIVE engine this class is
33// discharged at union time by the k<NX_EQSAT_W guard (never logged).
34// STEP 6 LOAD-BEARING NEG-D (log completeness): an UNDERSIZED prov buffer
35// (cap=0) still lets the real merge happen (membership holds) but the
36// overflow flag must POISON the certificate (FAIL CLOSED) -- a
37// truncated log can never yield a passing-but-incomplete certificate.
38//
39// Known answer (FAIL LOUD): prints "<sound_passed> <sound_total> <cert> " where
40// sound_total==3584, sound_passed==3584, cert==1 (cert is now the LIVE
41// certificate). exit 0 iff all steps hold.
42
43import "nx_gate_verdict.nx"
44import "nx_eqsat_membership_proof.nx"
45
46func _emit_num(v: i64) -> i64 {
47 let b: *u8 = sys_mmap(28); var n: i64 = v; if n < 0 { n = 0 - n }
48 let t2: *u8 = sys_mmap(28); var t: i64 = 0
49 if n == 0 { t2[0] = 48; t = 1 }
50 while n > 0 { t2[t] = 48 + (n % 10); n = n / 10; t = t + 1 }
51 var i: i64 = 0; while i < t { b[i] = t2[t - 1 - i]; i = i + 1 }
52 b[t] = 32; sys_write(1, b, t + 1); return 0
53}
54func _nl() -> i64 { let z: *u8 = sys_mmap(2); z[0] = 10; sys_write(1, z, 1); return 0 }
55
56// Independent cross-check: does (mul x 2^k) == (shl x k) hold for ALL x mod 2^W,
57// evaluated on the gsim (masked) vs the doubling oracle? Returns passed vectors.
58// Used as defense-in-depth for the certified equivalence and for NEG-B failure.
59func _cross_check_pow2(g: *NxGsim, vals: *i64, cells: *NxGsimCell,
60 mul_const: i64, shl_amt: i64, oracle_k: i64,
61 t: *NxTriTally) -> i64 {
62 let hi: i64 = mp_count()
63 var x: i64 = 0
64 while x < hi {
65 let lhs: i64 = _mp_eval_op_const(g, vals, cells, NX_GATE_KIND_MUL, x, mul_const)
66 let rhs: i64 = _mp_eval_op_const(g, vals, cells, NX_GATE_KIND_SHL, x, shl_amt)
67 let oracle: i64 = _mp_oracle_double_k(x, oracle_k)
68 let legs: *i64 = sys_mmap(2 * 8) as *i64
69 legs[0] = lhs
70 legs[1] = rhs
71 let v: *NxTriVerdict = sys_mmap(64) as *NxTriVerdict
72 nx_tri_pass_strict(legs, 2, oracle, 2, v)
73 nx_tri_tally_add(t, v, x)
74 x = x + 1
75 }
76 return t.passed
77}
78
79func main() -> i64 {
80 // MIGRATED OFF A HAND-ROLLED VERDICT 2026-08-14, and NEVER COMPILED BEFORE THAT DAY. This is the
81 // deepest gate in the eqsat family -- four load-bearing negative controls against three positives --
82 // and its exit-code-as-assertion-number protocol meant it stopped at the FIRST failure and reported
83 // one number to a caller that could not read it.
84 gv_head("nx_eqsat membership-as-proof gate -- a certificate that fails closed on every unsound path" as *u8)
85 let ctr: *i64 = gv_ctr()
86 // shared gsim scratch (generous fixed caps; the netlists are tiny)
87 let vals: *i64 = sys_mmap(64 * 8) as *i64
88 let cells: *NxGsimCell = sys_mmap(64 * 48) as *NxGsimCell
89 let g: *NxGsim = sys_mmap(64) as *NxGsim
90
91 // ========================================================================
92 // STEP 0: rule-id LOCKSTEP -- the membership organ's MP_RULE_* must match the
93 // engine's NX_EQSAT_RULE_* exactly, or the live log the engine writes could be
94 // mislabeled against this certifier's allow-list. (Defends the mislabel trap.)
95 // ========================================================================
96 if mp_rule_ids_lockstep() != 1 { sys_exit(70); return 70 }
97
98 // ========================================================================
99 // STEP 1: establish the SOUND SET via the W=8 masked exhaustive battery.
100 // ========================================================================
101 let t: *NxTriTally = sys_mmap(64) as *NxTriTally
102 nx_tri_tally_init(t)
103 var sound_total: i64 = 0
104 sound_total = sound_total + mp_battery_unary(g, vals, cells, MP_RULE_ADD_ZERO, t)
105 sound_total = sound_total + mp_battery_unary(g, vals, cells, MP_RULE_SUB_SELF, t)
106 sound_total = sound_total + mp_battery_unary(g, vals, cells, MP_RULE_ADD_SELF, t)
107 sound_total = sound_total + mp_battery_unary(g, vals, cells, MP_RULE_AND_SELF, t)
108 sound_total = sound_total + mp_battery_unary(g, vals, cells, MP_RULE_OR_ZERO, t)
109 sound_total = sound_total + mp_battery_unary(g, vals, cells, MP_RULE_MUL_ONE, t)
110 let pow2_total: i64 = mp_battery_mul_pow2_inrange(g, vals, cells, t)
111 sound_total = sound_total + pow2_total
112
113 let sound_passed: i64 = t.passed
114 // six unary rules each sweep 2^W = 256 vectors -> 1536; mul_pow2 = 256*8 = 2048
115 let expect_total: i64 = 6 * mp_count() + mp_count() * MP_W
116
117 // ========================================================================
118 // STEP 2: the MEMBERSHIP-AS-PROOF CERTIFICATE (positive) for mul x 8 == shl x 3.
119 // ========================================================================
120 let cap_nodes: i64 = 64
121 let cap_cls: i64 = 64
122 let nodes: *NxENode = sys_mmap(cap_nodes * 64) as *NxENode
123 let classes: *NxEClass = sys_mmap(cap_cls * 32) as *NxEClass
124 let eg: *NxEGraph = sys_mmap(NX_EQSAT_GRAPH_BYTES) as *NxEGraph
125 if nx_eqsat_init(eg, nodes, cap_nodes, classes, cap_cls) != NX_EQSAT_OK { sys_exit(30); return 30 }
126
127 let vx: i64 = nx_eqsat_add_var(eg, 0) // x
128 let c8: i64 = nx_eqsat_add_const(eg, 8) // 8 = 2^3
129 let c3: i64 = nx_eqsat_add_const(eg, 3) // 3
130 let mul8: i64 = nx_eqsat_add_binary(eg, NX_EQ_OP_MUL, vx, c8) // (mul x 8)
131 let shl3: i64 = nx_eqsat_add_binary(eg, NX_EQ_OP_SHL, vx, c3) // (shl x 3)
132
133 // Pre-merge: distinct e-classes (membership must NOT yet hold).
134 if nx_eqsat_find(eg, mul8) == nx_eqsat_find(eg, shl3) { sys_exit(31); return 31 }
135
136 // LIVE saturation: enable provenance, run the REAL engine (NOT a gated driver),
137 // and certify STRICTLY FROM THE LOG the engine wrote at its union chokepoint.
138 // mul_pow2 fires at k=3<W (its k<W guard admits it) and merges mul8 with shl3,
139 // logging RULE_MUL_POW2 -- the ONLY real merge on this graph. This PROMOTES
140 // mul_pow2 into the proven-sound set, exercised through the live engine.
141 let plog: *i64 = sys_mmap(64 * 8) as *i64
142 if nx_eqsat_enable_prov(eg, plog, 64) != NX_EQSAT_OK { sys_exit(32); return 32 }
143 let sat2: i64 = nx_eqsat_saturate(eg, 16)
144 if sat2 != NX_EQSAT_SATURATED { sys_exit(38); return 38 } // engine converged
145
146 let cert: *NxMpCertificate = sys_mmap(64) as *NxMpCertificate
147 let cok: i64 = mp_certify_live(eg, mul8, shl3, cert)
148 if cert.member != 1 { sys_exit(33); return 33 } // MEMBERSHIP holds (live find==find)
149 if cert.sound != 1 { sys_exit(34); return 34 } // PROVENANCE: all logged ids sound
150 if cok != 1 { sys_exit(35); return 35 } // CERTIFIED (live)
151 // The live engine logged at least the mul_pow2 merge, all sound, no overflow.
152 if eg.n_prov < 1 { sys_exit(39); return 39 } // a real merge WAS logged
153 if eg.prov_overflow != 0 { sys_exit(47); return 47 } // log did not overflow
154
155 // Cross-check the SAME equivalence with a fresh triangulation battery.
156 let tc: *NxTriTally = sys_mmap(64) as *NxTriTally
157 nx_tri_tally_init(tc)
158 let cc_passed: i64 = _cross_check_pow2(g, vals, cells, 8, 3, 3, tc)
159 if tc.total != mp_count() { sys_exit(36); return 36 }
160 if cc_passed != tc.total { sys_exit(37); return 37 } // defense in depth agrees
161
162 // ========================================================================
163 // STEP 3: LOAD-BEARING NEG-A -- a NON-sound rule must NOT certify.
164 // ========================================================================
165 // 3a: the bogus identity's own W=8 battery must DISAGREE (so it can never
166 // enter the sound set). (mul x 3) vs (shl x 1): false for almost all x.
167 let tb: *NxTriTally = sys_mmap(64) as *NxTriTally
168 nx_tri_tally_init(tb)
169 // oracle = true (x*3) mod 2^W via doublings is NOT a power-of-two; build it
170 // directly so the oracle is the honest value, and BOTH legs (mul x 3, shl x 1)
171 // are checked against it -- they will diverge.
172 let hi: i64 = mp_count()
173 var bx: i64 = 0
174 while bx < hi {
175 let blhs: i64 = _mp_eval_op_const(g, vals, cells, NX_GATE_KIND_MUL, bx, 3)
176 let brhs: i64 = _mp_eval_op_const(g, vals, cells, NX_GATE_KIND_SHL, bx, 1)
177 let boracle: i64 = ((bx & mp_mask()) * 3) & mp_mask() // honest (x*3) mod 2^W
178 let blegs: *i64 = sys_mmap(2 * 8) as *i64
179 blegs[0] = blhs
180 blegs[1] = brhs
181 let bv: *NxTriVerdict = sys_mmap(64) as *NxTriVerdict
182 nx_tri_pass_strict(blegs, 2, boracle, 2, bv)
183 nx_tri_tally_add(tb, bv, bx)
184 bx = bx + 1
185 }
186 // The bogus identity MUST fail the battery (not all vectors agree).
187 if tb.passed == tb.total { sys_exit(40); return 40 } // bogus must NOT be sound
188 // The bogus rule id must NOT be in the proven-sound allow-list.
189 if mp_is_sound_rule(MP_RULE_BOGUS_MUL3) != 0 { sys_exit(41); return 41 }
190
191 // 3b: a gated saturation citing the bogus rule must REFUSE the merge and the
192 // certificate must FAIL. Use a fresh e-graph with (mul x 4) and (shl x 1).
193 let nodes2: *NxENode = sys_mmap(cap_nodes * 64) as *NxENode
194 let classes2: *NxEClass = sys_mmap(cap_cls * 32) as *NxEClass
195 let eg2: *NxEGraph = sys_mmap(NX_EQSAT_GRAPH_BYTES) as *NxEGraph
196 if nx_eqsat_init(eg2, nodes2, cap_nodes, classes2, cap_cls) != NX_EQSAT_OK { sys_exit(42); return 42 }
197 let vx2: i64 = nx_eqsat_add_var(eg2, 0)
198 let c4b: i64 = nx_eqsat_add_const(eg2, 4)
199 let c1b: i64 = nx_eqsat_add_const(eg2, 1)
200 let mul4: i64 = nx_eqsat_add_binary(eg2, NX_EQ_OP_MUL, vx2, c4b)
201 let shl1: i64 = nx_eqsat_add_binary(eg2, NX_EQ_OP_SHL, vx2, c1b)
202 let prov2: *NxMpProvenance = sys_mmap(64) as *NxMpProvenance
203 mp_prov_init(prov2)
204 // Cite the BOGUS rule -- the recorder must refuse + poison the certificate.
205 let admitted2: i64 = mp_prov_admit_union(prov2, eg2, mul4, shl1, MP_RULE_BOGUS_MUL3, 1)
206 // captured; asserted as teeth at the end so a single run reports ALL of them
207 let cert2: *NxMpCertificate = sys_mmap(64) as *NxMpCertificate
208 let cok2: i64 = mp_certify(eg2, mul4, shl1, prov2, cert2)
209 // cok2 asserted below
210
211 // 3c: LIVE leg (belt-and-suspenders) -- the live engine has NO bogus rule, so
212 // it can NEVER union (mul x 4) with (shl x 1) (the bogus claim is false; the
213 // sound mul_pow2 would merge mul4 with SHL(x,2), not shl1). So live membership
214 // FAILS => the live certificate FAILS, with a clean (all-sound) log.
215 let plog2: *i64 = sys_mmap(64 * 8) as *i64
216 if nx_eqsat_enable_prov(eg2, plog2, 64) != NX_EQSAT_OK { sys_exit(48); return 48 }
217 nx_eqsat_saturate(eg2, 16)
218 let cert2b: *NxMpCertificate = sys_mmap(64) as *NxMpCertificate
219 let cok2b: i64 = mp_certify_live(eg2, mul4, shl1, cert2b)
220 // cert2b.member and cok2b asserted below
221
222 // ========================================================================
223 // STEP 4: LOAD-BEARING NEG-B -- endpoints not in the same e-class.
224 // ========================================================================
225 // Certify (mul x 8) against (shl x 2): genuinely inequivalent (8 != 2^2).
226 let nodes3: *NxENode = sys_mmap(cap_nodes * 64) as *NxENode
227 let classes3: *NxEClass = sys_mmap(cap_cls * 32) as *NxEClass
228 let eg3: *NxEGraph = sys_mmap(NX_EQSAT_GRAPH_BYTES) as *NxEGraph
229 if nx_eqsat_init(eg3, nodes3, cap_nodes, classes3, cap_cls) != NX_EQSAT_OK { sys_exit(50); return 50 }
230 let vx3: i64 = nx_eqsat_add_var(eg3, 0)
231 let c8c: i64 = nx_eqsat_add_const(eg3, 8)
232 let c2c: i64 = nx_eqsat_add_const(eg3, 2)
233 let mul8c: i64 = nx_eqsat_add_binary(eg3, NX_EQ_OP_MUL, vx3, c8c)
234 let shl2c: i64 = nx_eqsat_add_binary(eg3, NX_EQ_OP_SHL, vx3, c2c)
235 // LIVE: enable provenance + run the REAL saturator. mul_pow2 merges (mul x 8)
236 // with (shl x 3), NOT (shl x 2) -- so mul8c and shl2c stay in distinct classes.
237 // Membership FAILS => the live certificate FAILS, even though the log is sound.
238 let plog3: *i64 = sys_mmap(64 * 8) as *i64
239 if nx_eqsat_enable_prov(eg3, plog3, 64) != NX_EQSAT_OK { sys_exit(55); return 55 }
240 nx_eqsat_saturate(eg3, 16)
241 let cert3: *NxMpCertificate = sys_mmap(64) as *NxMpCertificate
242 let cok3: i64 = mp_certify_live(eg3, mul8c, shl2c, cert3)
243 // cert3.member and cok3 asserted below
244 // And the equivalence really is false: cross-check must DISAGREE.
245 let td: *NxTriTally = sys_mmap(64) as *NxTriTally
246 nx_tri_tally_init(td)
247 _cross_check_pow2(g, vals, cells, 8, 2, 3, td) // oracle = x*8, rhs = x<<2
248 // td.passed vs td.total asserted below
249
250 // ========================================================================
251 // STEP 5: LOAD-BEARING NEG-C -- mul_pow2 at k>=W boundary must be REFUSED.
252 // ========================================================================
253 // At k==W the masked equality MUL/SHL coincides (0==0), so an equality sweep
254 // is BLIND to the bug -- but the k<W side-condition is not. The recorder must
255 // refuse the merge and the certificate must fail.
256 let k_at_W_ok: i64 = mp_mul_pow2_k_ok(MP_W)
257 let k_below_W_ok: i64 = mp_mul_pow2_k_ok(MP_W - 1)
258 let nodes4: *NxENode = sys_mmap(cap_nodes * 64) as *NxENode
259 let classes4: *NxEClass = sys_mmap(cap_cls * 32) as *NxEClass
260 let eg4: *NxEGraph = sys_mmap(NX_EQSAT_GRAPH_BYTES) as *NxEGraph
261 if nx_eqsat_init(eg4, nodes4, cap_nodes, classes4, cap_cls) != NX_EQSAT_OK { sys_exit(62); return 62 }
262 let vx4: i64 = nx_eqsat_add_var(eg4, 0)
263 let c256: i64 = nx_eqsat_add_const(eg4, 256) // 2^8 = 2^W
264 let cW: i64 = nx_eqsat_add_const(eg4, MP_W) // shift by W
265 let mul256: i64 = nx_eqsat_add_binary(eg4, NX_EQ_OP_MUL, vx4, c256)
266 let shlW: i64 = nx_eqsat_add_binary(eg4, NX_EQ_OP_SHL, vx4, cW)
267 let prov4: *NxMpProvenance = sys_mmap(64) as *NxMpProvenance
268 mp_prov_init(prov4)
269 // Cite mul_pow2 but at k==W -- the side-condition must REFUSE it.
270 let admitted4: i64 = mp_prov_admit_union(prov4, eg4, mul256, shlW, MP_RULE_MUL_POW2, MP_W)
271 // admitted4 and prov4.all_sound asserted below
272 let cert4: *NxMpCertificate = sys_mmap(64) as *NxMpCertificate
273 let cok4: i64 = mp_certify(eg4, mul256, shlW, prov4, cert4)
274 // cok4 asserted below
275 // Prove the equality sweep alone is BLIND here (masked MUL==SHL==0 at k=W):
276 // x * 256 mod 256 == 0 and x << 8 mod 256 == 0 for all x in [0,256).
277 var wx: i64 = 0
278 var blind_agree: i64 = 0
279 while wx < mp_count() {
280 let wl: i64 = _mp_eval_op_const(g, vals, cells, NX_GATE_KIND_MUL, wx, 256)
281 let wr: i64 = _mp_eval_op_const(g, vals, cells, NX_GATE_KIND_SHL, wx, MP_W)
282 if wl == wr { if wl == 0 { blind_agree = blind_agree + 1 } }
283 wx = wx + 1
284 }
285 // blind_agree asserted below -- this is the subtlest tooth in the file
286
287 // ========================================================================
288 // STEP 6: LOAD-BEARING NEG-D -- log COMPLETENESS. An UNDERSIZED provenance
289 // buffer must FAIL CLOSED: the live engine still performs the real merge (so
290 // membership holds), but the truncated/overflowed log must POISON the
291 // certificate. A log that can silently drop entries would let an unsound
292 // union beyond the cap slip through invisibly; this proves it cannot.
293 // ========================================================================
294 let nodes5: *NxENode = sys_mmap(cap_nodes * 64) as *NxENode
295 let classes5: *NxEClass = sys_mmap(cap_cls * 32) as *NxEClass
296 let eg5: *NxEGraph = sys_mmap(NX_EQSAT_GRAPH_BYTES) as *NxEGraph
297 if nx_eqsat_init(eg5, nodes5, cap_nodes, classes5, cap_cls) != NX_EQSAT_OK { sys_exit(67); return 67 }
298 let vx5: i64 = nx_eqsat_add_var(eg5, 0)
299 let c8e: i64 = nx_eqsat_add_const(eg5, 8)
300 let c3e: i64 = nx_eqsat_add_const(eg5, 3)
301 let mul8e: i64 = nx_eqsat_add_binary(eg5, NX_EQ_OP_MUL, vx5, c8e)
302 let shl3e: i64 = nx_eqsat_add_binary(eg5, NX_EQ_OP_SHL, vx5, c3e)
303 let plog5: *i64 = sys_mmap(8) as *i64
304 // cap_prov = 0 -- the very first real merge cannot be logged -> overflow flag.
305 if nx_eqsat_enable_prov(eg5, plog5, 0) != NX_EQSAT_OK { sys_exit(68); return 68 }
306 nx_eqsat_saturate(eg5, 16)
307 let cert5: *NxMpCertificate = sys_mmap(64) as *NxMpCertificate
308 let cok5: i64 = mp_certify_live(eg5, mul8e, shl3e, cert5)
309 // cert5 / overflow / cok5 asserted below
310
311 // ========================================================================
312 // FINAL known-answer gate (FAIL LOUD).
313 // ========================================================================
314 _emit_num(sound_passed); _emit_num(sound_total); _emit_num(cok); _nl()
315
316 // ---- THE POSITIVE. Every control below asserts a REFUSAL; without these three a certifier that
317 // refused everything would score full marks on the whole file.
318 gv_check("the soundness battery swept its full vector domain" as *u8, sound_total == expect_total, ctr)
319 gv_check("every vector passed on BOTH witnesses" as *u8, sound_passed == sound_total, ctr)
320 gv_check("the positive certificate for mul-by-8 equals shl-by-3 HOLDS" as *u8, cok == 1, ctr)
321
322 // ---- NEG-A: a citation of a rule that was never proven sound.
323 gv_check("neg-control-a-union-citing-an-unproven-rule-is-REFUSED-at-admission" as *u8, admitted2 == 0, ctr)
324 gv_check("neg-control-the-refused-citation-POISONS-the-provenance" as *u8, prov2.all_sound == 0, ctr)
325 gv_check("neg-control-the-poison-NAMES-the-offending-rule" as *u8, prov2.bad_rule == MP_RULE_BOGUS_MUL3, ctr)
326 gv_check("neg-control-the-gated-certificate-FAILS-on-a-poisoned-log" as *u8, cok2 == 0, ctr)
327 gv_check("neg-control-the-LIVE-engine-never-merges-the-falsely-claimed-pair" as *u8, cert2b.member == 0, ctr)
328 gv_check("neg-control-the-live-certificate-FAILS-too" as *u8, cok2b == 0, ctr)
329
330 // ---- NEG-B: endpoints that are genuinely inequivalent.
331 gv_check("neg-control-membership-FAILS-for-inequivalent-endpoints" as *u8, cert3.member == 0, ctr)
332 gv_check("neg-control-the-certificate-FAILS-even-though-the-log-is-clean" as *u8, cok3 == 0, ctr)
333 gv_check("neg-control-the-independent-cross-check-DISAGREES-so-the-claim-really-is-false" as *u8, td.passed != td.total, ctr)
334
335 // ---- NEG-C: the boundary the equality sweep cannot see. THIS IS THE SUBTLEST TOOTH HERE.
336 // At k == W the masked values coincide -- x*2^W and x<<W are BOTH zero for every x -- so an
337 // equality battery agrees on all 256 vectors and is therefore BLIND to the unsoundness. Only the
338 // k < W side-condition catches it. A suite built purely on value comparison would pass this bug.
339 gv_check("neg-control-the-rule-side-condition-REFUSES-k-equal-to-W" as *u8, k_at_W_ok == 0, ctr)
340 gv_check("the same side-condition ACCEPTS k just below W, so it is not refusing everything" as *u8, k_below_W_ok == 1, ctr)
341 gv_check("neg-control-a-boundary-union-is-REFUSED-at-admission" as *u8, admitted4 == 0, ctr)
342 gv_check("neg-control-the-boundary-refusal-poisons-the-provenance" as *u8, prov4.all_sound == 0, ctr)
343 gv_check("neg-control-the-boundary-certificate-FAILS" as *u8, cok4 == 0, ctr)
344 gv_check("PROOF THE EQUALITY SWEEP IS BLIND AT THE BOUNDARY: both sides agree on every vector" as *u8, blind_agree == mp_count(), ctr)
345
346 // ---- NEG-D: an undersized provenance log must fail CLOSED, not silently drop entries.
347 gv_check("neg-control-the-merge-really-did-happen-so-membership-holds" as *u8, cert5.member == 1, ctr)
348 gv_check("neg-control-an-undersized-log-raises-the-overflow-flag" as *u8, eg5.prov_overflow == 1, ctr)
349 gv_check("neg-control-a-truncated-log-is-NOT-sound" as *u8, cert5.sound == 0, ctr)
350 gv_check("neg-control-the-certificate-FAILS-CLOSED-on-a-truncated-log" as *u8, cok5 == 0, ctr)
351
352 return gv_verdict("nx_eqsat_membership_proof_test" as *u8, ctr,
353 "membership-as-proof certificate for mul-to-shl, against four load-bearing controls: an unproven rule id, inequivalent endpoints, the k=W boundary that a pure equality sweep is provably blind to, and an undersized log that must fail closed" as *u8)
354}