nx_idemp.nx source
↩ module page · 310 lines · 15874 B
1// nx_idemp.nx -- IS THIS GATE IDEMPOTENT? RUN IT TWICE AND COMPARE. No heuristic, no grep.
2//
3// WHY. Rule 10 says every operation must be safe to run twice, and the estate has been paying for the
4// gates that are not -- three confirmed the same day (debt 1786128761):
5// nx_segstore_uncap_gate 7/9 RED from a stale seg-2106 fixture its header told the RUNNER to clean.
6// nx_law_warden T15 25/26 RED for hours, filed sev-7 as a broken per-plane counter. The counter
7// was always right; /tmp/lwseg held zzlw-seg-2 and zzlw-seg-3 from an older
8// revision of the fixture, so segamp correctly said max=4 and the assertion
9// demanded 2. A capability guarding an OOM class sat indicted by its leftovers.
10// nx_coa_gate THE MONEY PATH -- intermittent, with the FAILING TOOTH MOVING between runs,
11// until 2026-07-31 root-caused as C6 registering a side in a PERSISTENT plane
12// so C5 passed only on a virgin store.
13// ★★★★★★A GATE THAT IS NOT IDEMPOTENT REPORTS ON ITS FIRST RUN AND LIES ABOUT EVERY RUN AFTER.
14// ★★★★★★AN INTERMITTENT FAILURE WHOSE FAILING TOOTH MOVES IS A FIXTURE DEFECT, NOT A RACE -- A RACE
15// USUALLY BREAKS THE SAME ASSERTION. That one distinction would have saved each of the three.
16//
17// WHY MEASURE INSTEAD OF SCAN. The obvious approach is to grep the 140 measured `sys_mkdir("/tmp/...")`
18// sites for a matching cleanup. That is a PROXY: it asks whether the author wrote a pattern, not whether
19// the gate survives a second run. It cannot see a fixture poisoned through a persistent seg-store plane
20// (exactly nx_coa_gate's defect, where no /tmp cleanup would have helped), and it calls a gate SAFE for
21// having an unlink list that is merely incomplete.
22// ★★★★★★RUNNING IT TWICE IS NOT A BETTER HEURISTIC, IT IS THE DEFINITION. Ask the property directly.
23//
24// WHAT IT REPORTS, and the verdict IS the decision:
25// IDEMPOTENT -- run 1 and run 2 agree on exit code AND on the passed/total tally.
26// NON-IDEMPOTENT -- they disagree. The FIRST run's answer is the one everyone has been trusting.
27// UNMEASURED -- the gate could not be executed twice (absent, timeout, spawn failure). NEVER
28// folded into IDEMPOTENT: an unrunnable gate is not a clean one.
29//
30// ⚠DECLARED ENVELOPE, so nobody reads more into a green than it carries:
31// - Two runs prove non-idempotency when they DISAGREE. Agreement is evidence, not proof: a gate whose
32// fixture only poisons on the third run reads clean here. ★TWO RUNS FALSIFY; THEY DO NOT CERTIFY.
33// Use `-n` to raise the run count when a gate is suspected and cheap.
34// - It runs REAL gates with REAL side effects. That is the point -- the second run is the measurement
35// -- but it means this must never be pointed at anything that mutates production beyond its fixture.
36// The roster is verifiers only, matching /api/gate_run's own bound.
37// usage: nx_idemp <gate-elf-path> [runs] default 2 runs
38// license_tier: ORIGINAL Executes verifiers, writes nothing of its own. No hw writes (Rule 26).
39import "nx_syscalls.nx"
40import "nx_guarded_run.nx"
41const ID_MAGIC_100000: i64 = 100000
42
43const ID_DEADLINE_MS: i64 = 180000
44const ID_OUTCAP: i64 = 1048576
45const ID_PATHCAP: i64 = 1024
46const ID_MAXRUNS: i64 = 8
47const ID_DEFRUNS: i64 = 2
48const ID_MODE_TMP: i64 = 384 // 0600
49const ID_ZERO: i64 = 48
50const ID_NINE: i64 = 57
51const ID_SLASH: i64 = 47
52
53func id_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
54func id_puts(s: *u8) -> i64 { sys_write(1, s, id_len(s)); return 0 }
55func id_putn(v: i64) -> i64 {
56 if v == 0 { id_puts("0" as *u8); return 0 }
57 var x: i64 = v
58 if x < 0 { id_puts("-" as *u8); x = 0 - x }
59 let b: *u8 = sys_mmap(32)
60 var i: i64 = 0
61 while x > 0 { b[i] = ((x % 10) + ID_ZERO) as u8; x = x / 10; i = i + 1 }
62 while i > 0 { i = i - 1; sys_write(1, ((b as i64) + i) as *u8, 1) }
63 return 0
64}
65func id_atoi(s: *u8) -> i64 {
66 var v: i64 = 0
67 var i: i64 = 0
68 var go: i64 = 1
69 while go == 1 {
70 let c: i64 = s[i] as i64
71 if c >= ID_ZERO { if c <= ID_NINE { v = v * 10 + (c - ID_ZERO); i = i + 1 } else { go = 0 } } else { go = 0 }
72 }
73 return v
74}
75
76// Extract a comparable (pass,fail) tally, encoded pass*100000+fail; -1 when no format matched.
77//
78// REWRITTEN (rule 3, not patched): v1 handled only gv_verdict's "passed <a>/<b>" and carried a
79// convoluted double-scan. Then nx_coa_gate -- the money path, the first real gate pointed at this --
80// came back "(none found)" on BOTH runs, so the IDEMPOTENT verdict rested on the exit code alone,
81// which this organ's own header calls too coarse to see a moving tooth.
82// ★★★★★★ONE VERDICT FORMAT IS NOT THE ESTATE'S ONLY VERDICT FORMAT. A comparator that silently
83// finds nothing on its second axis is running on ONE axis and still printing a confident verdict.
84// ★★★★★A PARSER THAT RETURNS "NOT FOUND" IS ONLY EVIDENCE ABOUT THE SHAPES IT TRIED.
85// Three shapes, most specific first, and the fallback cannot miss:
86// "passed <a>/<b>" gv_verdict -> pass=a fail=b-a
87// "pass=<a> fail=<b>" nx_coa_gate family -> pass=a fail=b
88// count of "PASS " / "FAIL " line markers -> works for any gate that labels its teeth at all
89// Scan decimal digits at `at`; writes the value to out[0] and RETURNS THE INDEX JUST PAST THEM.
90//
91// ⚠THE BUG THIS FIXES WAS MINE, IN THIS FILE, TODAY. v1 ended its loop by assigning `p = n` and then
92// returned `p` -- so on "passed 0/1" it read the 0 correctly and handed back n instead of the index
93// of the '/'. The caller's `if b[e1] == '/'` could then never be true, shape 1 silently fell through,
94// and the tally axis reported "nothing found" on every gv_verdict gate. It looked fine for hours
95// because the gates I happened to test first used shape 2 ("pass=N fail=M"), which does not need the
96// returned position at all.
97// ★★★★★★A LOOP THAT BREAKS BY OVERSHOOTING ITS INDEX DESTROYS THE POSITION IT WAS SEARCHING FOR.
98// Banked in this estate, written three times in one session by another seat, and I wrote it again.
99// ★★★★★KNOWING A LAW IS NOT HAVING THE HABIT -- USE A DONE FLAG, NEVER THE CURSOR, TO EXIT.
100// ★★★★★THE NEGATIVE CONTROL FOUND WHAT FOUR PASSING RUNS HID: every subject that exercised only the
101// working shape agreed, so the broken axis stayed invisible until a shape-1 gate arrived.
102func id_scan_num(b: *u8, n: i64, at: i64, out: *i64) -> i64 {
103 var p: i64 = at
104 var v: i64 = 0
105 var got: i64 = 0
106 var done: i64 = 0
107 while done == 0 {
108 if p >= n { done = 1 } else {
109 let c: i64 = b[p] as i64
110 if c >= ID_ZERO { if c <= ID_NINE { v = v * 10 + (c - ID_ZERO); got = 1; p = p + 1 } else { done = 1 } } else { done = 1 }
111 }
112 }
113 out[0] = v
114 if got == 1 { return p }
115 return 0 - 1
116}
117func id_find(b: *u8, n: i64, pat: *u8) -> i64 {
118 let pl: i64 = id_len(pat)
119 if pl <= 0 { return 0 - 1 }
120 var i: i64 = 0
121 while i + pl <= n {
122 var j: i64 = 0
123 var ok: i64 = 1
124 while j < pl { if b[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } }
125 if ok == 1 { return i }
126 i = i + 1
127 }
128 return 0 - 1
129}
130func id_count(b: *u8, n: i64, pat: *u8) -> i64 {
131 let pl: i64 = id_len(pat)
132 if pl <= 0 { return 0 }
133 var i: i64 = 0
134 var c: i64 = 0
135 while i + pl <= n {
136 var j: i64 = 0
137 var ok: i64 = 1
138 while j < pl { if b[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } }
139 if ok == 1 { c = c + 1; i = i + pl } else { i = i + 1 }
140 }
141 return c
142}
143func id_tally(b: *u8, n: i64) -> i64 {
144 let box: *i64 = sys_mmap(16) as *i64
145
146 // shape 1: "passed <a>/<b>" -- EVERY occurrence, keeping the LAST that actually parses.
147 //
148 // ⚠v1 took the FIRST match and gave up if it did not parse. Measured on nx_ivvguard_gate, whose
149 // output contains "passed " TWICE: once at offset 1567 inside a TOOTH DESCRIPTION -- "...25 of 26
150 // passing is NOT green even at rc=0 -- passed must equal total..." -- and once at 3349 in the real
151 // verdict line "NX-IVVGUARD passed 34/34". The prose match has no digits after it, so shape 1 bailed,
152 // shape 2 found no "pass=", and shape 3's bracketed "[PASS]" markers do not match "PASS " -- leaving
153 // a lone stray "FAIL " and the absurd tally pass=0 fail=1 for a 34/34 GREEN gate.
154 // ★★★★★★A PARSER THAT TAKES THE FIRST MATCH AND GIVES UP CANNOT SURVIVE PROSE CONTAINING ITS OWN
155 // KEYWORD -- AND A GATE'S TOOTH NAMES ARE PROSE ABOUT GATES, SO THEY ARE THE MOST LIKELY TEXT IN
156 // THE ESTATE TO CONTAIN IT. Scan them all; the verdict is the LAST one that parses.
157 // ★★★★★TWO AXES THAT CONTRADICT EACH OTHER (rc=0 GREEN vs a tally of 0 passed) MEAN ONE IS WRONG --
158 // DO NOT PRINT BOTH AND MOVE ON.
159 var best1: i64 = 0 - 1
160 var sp: i64 = 0
161 var scanning: i64 = 1
162 while scanning == 1 {
163 let rel: i64 = id_find(((b as i64) + sp) as *u8, n - sp, "passed " as *u8)
164 if rel < 0 { scanning = 0 } else {
165 let p1: i64 = sp + rel
166 let e1: i64 = id_scan_num(b, n, p1 + 7, box)
167 if e1 > 0 {
168 let a: i64 = box[0]
169 if e1 < n { if b[e1] == (ID_SLASH as u8) {
170 let e2: i64 = id_scan_num(b, n, e1 + 1, box)
171 if e2 > 0 { let t: i64 = box[0]; best1 = a * ID_MAGIC_100000 + (t - a) }
172 } }
173 }
174 sp = p1 + 7
175 if sp >= n { scanning = 0 }
176 }
177 }
178 if best1 >= 0 { return best1 }
179 // shape 2: "pass=<a> fail=<b>"
180 let p2: i64 = id_find(b, n, "pass=" as *u8)
181 if p2 >= 0 {
182 let e1: i64 = id_scan_num(b, n, p2 + 5, box)
183 if e1 > 0 {
184 let a: i64 = box[0]
185 let p3: i64 = id_find(b, n, "fail=" as *u8)
186 if p3 >= 0 {
187 let e2: i64 = id_scan_num(b, n, p3 + 5, box)
188 if e2 > 0 { return a * ID_MAGIC_100000 + box[0] }
189 }
190 }
191 }
192 // shape 3: count the tooth markers themselves. A gate that labels no tooth in any of these ways
193 // yields 0 pass / 0 fail, which compares equal run-to-run and is reported as (none found) so the
194 // reader knows the tally axis contributed NOTHING rather than agreeing.
195 let np: i64 = id_count(b, n, "PASS " as *u8)
196 let nf: i64 = id_count(b, n, "FAIL " as *u8)
197 if np + nf > 0 { return np * ID_MAGIC_100000 + nf }
198 return 0 - 1
199}
200
201// run the gate once, capturing stdout to a temp file; returns rc, writes tally to out[0]
202func id_run_once(path: *u8, tmpp: *u8, out: *i64) -> i64 {
203 let fd: i64 = sys_openat_wr(tmpp, ID_MODE_TMP)
204 let av: *i64 = sys_mmap(8 * 4) as *i64
205 av[0] = path as i64
206 av[1] = 0
207 let ev: *i64 = sys_mmap(8 * 2) as *i64
208 ev[0] = 0
209 let rc: i64 = nx_guarded_run(path, av, ev, ID_DEADLINE_MS, fd, fd)
210 if fd >= 0 { sys_close(fd) }
211 let lp: *i64 = sys_mmap(16) as *i64
212 lp[0] = 0
213 let buf: *u8 = sys_read_file(tmpp, lp)
214 var t: i64 = 0 - 1
215 if (buf as i64) != 0 { t = id_tally(buf, lp[0]) }
216 out[0] = t
217 return rc
218}
219
220func main(argc: i64, argv: *i64) -> i64 {
221 if argc < 2 {
222 id_puts("usage: nx_idemp <gate-elf-path> [runs]\n" as *u8)
223 id_puts(" runs the gate N times (default 2) and compares exit code AND passed/total tally.\n" as *u8)
224 id_puts(" >>TWO RUNS FALSIFY IDEMPOTENCY; THEY DO NOT CERTIFY IT.<<\n" as *u8)
225 sys_exit(2)
226 }
227 let path: *u8 = argv[1] as *u8
228 var runs: i64 = ID_DEFRUNS
229 if argc >= 3 { runs = id_atoi(argv[2] as *u8) }
230 if runs < 2 { runs = ID_DEFRUNS }
231 if runs > ID_MAXRUNS { runs = ID_MAXRUNS }
232
233 id_puts("nx_idemp -- run it twice and compare. Rule 10 asked directly.\n gate: " as *u8)
234 id_puts(path)
235 id_puts("\n runs: " as *u8); id_putn(runs); id_puts("\n\n" as *u8)
236
237 // NONCED CAPTURE PATH -- and the reason is this organ catching itself.
238 // v1 used the fixed path /tmp/nx_idemp_capture.txt. Two nx_idemp jobs launched concurrently then
239 // wrote the SAME file, and the second subject's tally was read out of the first subject's output:
240 // nx_ivvguard_gate came back rc=0 (GREEN) with pass=0 fail=1, a tally that belonged to the negative
241 // control running beside it.
242 // ★★★★★★A FIXED SCRATCH PATH IN A TOOL THAT CAN RUN CONCURRENTLY IS EXACTLY THE DEFECT THIS TOOL
243 // EXISTS TO FIND. I built a fixture-collision detector on a shared fixture.
244 // The remedy is the one this lane ranked highest over cleaning: NONCE IT. A nonce cannot be
245 // forgotten because it IS the name, whereas a cleanup step is something a future edit can omit.
246 let tmpp: *u8 = sys_mmap(ID_PATHCAP)
247 var tn: i64 = 0
248 let pfx: *u8 = "/tmp/nx_idemp_capture_" as *u8
249 while pfx[tn] != (0 as u8) { tmpp[tn] = pfx[tn]; tn = tn + 1 }
250 var nonce: i64 = sys_now_us()
251 if nonce < 0 { nonce = 0 - nonce }
252 let nb: *u8 = sys_mmap(32)
253 var nl: i64 = 0
254 if nonce == 0 { nb[0] = 48 as u8; nl = 1 }
255 while nonce > 0 { nb[nl] = ((nonce % 10) + ID_ZERO) as u8; nonce = nonce / 10; nl = nl + 1 }
256 while nl > 0 { nl = nl - 1; tmpp[tn] = nb[nl]; tn = tn + 1 }
257 tmpp[tn] = 46 as u8; tn = tn + 1
258 tmpp[tn] = 116 as u8; tn = tn + 1
259 tmpp[tn] = 120 as u8; tn = tn + 1
260 tmpp[tn] = 116 as u8; tn = tn + 1
261 tmpp[tn] = 0 as u8
262 let tb: *i64 = sys_mmap(16) as *i64
263 let rcs: *i64 = sys_mmap(8 * (ID_MAXRUNS + 1)) as *i64
264 let tls: *i64 = sys_mmap(8 * (ID_MAXRUNS + 1)) as *i64
265
266 var i: i64 = 0
267 var unmeasured: i64 = 0
268 while i < runs {
269 let rc: i64 = id_run_once(path, tmpp, tb)
270 rcs[i] = rc
271 tls[i] = tb[0]
272 id_puts(" run " as *u8); id_putn(i + 1)
273 id_puts(": rc=" as *u8); id_putn(rc)
274 id_puts(" tally=" as *u8)
275 if tls[i] < 0 { id_puts("(no tooth markers -- THIS AXIS CONTRIBUTED NOTHING)" as *u8) } else { id_puts("pass=" as *u8); id_putn(tls[i] / ID_MAGIC_100000); id_puts(" fail=" as *u8); id_putn(tls[i] % ID_MAGIC_100000) }
276 if rc == NX_GR_TIMEOUT { id_puts(" TIMEOUT" as *u8); unmeasured = 1 }
277 if rc == NX_GR_SPAWN_FAIL { id_puts(" SPAWN-FAIL" as *u8); unmeasured = 1 }
278 if rc == 127 { id_puts(" NOT-FOUND (execve 127)" as *u8); unmeasured = 1 }
279 id_puts("\n" as *u8)
280 i = i + 1
281 }
282
283 var samerc: i64 = 1
284 var sametally: i64 = 1
285 i = 1
286 while i < runs {
287 if rcs[i] != rcs[0] { samerc = 0 }
288 if tls[i] != tls[0] { sametally = 0 }
289 i = i + 1
290 }
291
292 id_puts("\n" as *u8)
293 if unmeasured == 1 {
294 id_puts("VERDICT=UNMEASURED -- the gate could not be executed cleanly twice.\n" as *u8)
295 id_puts(" >>AN UNRUNNABLE GATE IS NOT A CLEAN ONE. This is never folded into IDEMPOTENT.<<\n" as *u8)
296 sys_exit(2)
297 }
298 if samerc == 1 { if sametally == 1 {
299 id_puts("VERDICT=IDEMPOTENT -- every run agreed on exit code and tally.\n" as *u8)
300 id_puts(" >>EVIDENCE, NOT PROOF: a fixture that only poisons on a later run reads clean here.<<\n" as *u8)
301 sys_exit(0)
302 } }
303 id_puts("VERDICT=NON-IDEMPOTENT -- the runs DISAGREE.\n" as *u8)
304 if samerc == 0 { id_puts(" exit code changed between runs.\n" as *u8) }
305 if sametally == 0 { id_puts(" the passed/total tally changed -- THIS IS THE 'FAILING TOOTH MOVES' SIGNATURE.\n" as *u8) }
306 id_puts(" >>THE FIRST RUN'S ANSWER IS THE ONE EVERYONE HAS BEEN TRUSTING. Diagnose the FIXTURE\n" as *u8)
307 id_puts(" before the code: build it from scratch, or nonce it so it cannot be inherited.<<\n" as *u8)
308 sys_exit(3)
309 return 0
310}