nx_gate_verdict.nx source
↩ module page · 906 lines · 44993 B
1// nx_gate_verdict.nx -- THE canonical gate-AUTHORING verdict lib (D001 first rung, 2026-07-18).
2// The debt: 2555 gate organs each hand-roll puts/num/pass/ttl/PASS-FAIL/verdict -- zero DRY.
3// This is the ONE copy gates import instead. Sibling of nx_gate_green.nx (which JUDGES a gate's
4// output from outside; this lib EMITS it from inside). Contract emitted:
5// " <check-name>: PASS\n" | " <check-name>: FAIL\n" per check
6// "\nNX-<GATE-NAME> passed <p>/<t> verdict=GREEN (<note>)\n" | " verdict=RED\n"
7// -- the exact shape nx_gate_green / nx_autograde already judge (anchor "verdict=", pat "GREEN").
8// Usage:
9// let ctr: *i64 = gv_ctr() // [0]=pass [1]=ttl
10// gv_head("my gate -- what it proves")
11// gv_check("T1 the thing holds", t1_ok, ctr) // t1_ok: 1 pass, else fail
12// ...
13// let rc: i64 = gv_verdict("MY-GATE", ctr, "green note") // prints summary; 0 GREEN / 1 RED
14// sys_exit(rc)
15// license_tier: ORIGINAL No hw writes (Rule 26).
16import "nx_syscalls.nx"
17
18const GV_NL: i64 = 10
19
20// Named plans make completeness independent of the number of checks that happened to execute.
21// Layout: header(count, valid, undeclared); entries(name pointer, byte length, executions).
22const GV_PLAN_HEADER: i64 = 3
23const GV_PLAN_ENTRY: i64 = 3
24const GV_I64_BYTES: i64 = 8
25
26func gv_plan_name_eq(a: *u8, an: i64, b: *u8, bn: i64) -> i64 {
27 if an != bn { return 0 }
28 var i: i64 = 0
29 while i < an { if a[i] != b[i] { return 0 }; i = i+1 }
30 return 1
31}
32func gv_plan_new(names: *u8) -> *i64 {
33 var size: i64 = 0
34 var count: i64 = 0
35 while names[size] != (0 as u8) {
36 if names[size] == (GV_NL as u8) { count = count+1 }
37 size = size+1
38 }
39 let plan: *i64 = sys_mmap(GV_I64_BYTES*(GV_PLAN_HEADER+GV_PLAN_ENTRY*count)) as *i64
40 plan[0]=count; plan[1]=1; plan[2]=0
41 if count == 0 { plan[1]=0 }
42 if size > 0 { if names[size-1] != (GV_NL as u8) { plan[1]=0 } }
43 var start: i64 = 0
44 var pos: i64 = 0
45 var row: i64 = 0
46 while pos < size {
47 if names[pos] == (GV_NL as u8) {
48 let cell: i64 = GV_PLAN_HEADER+GV_PLAN_ENTRY*row
49 plan[cell]=(names as i64)+start
50 plan[cell+1]=pos-start
51 plan[cell+2]=0
52 if pos == start { plan[1]=0 }
53 var previous: i64 = 0
54 while previous < row {
55 let old: i64 = GV_PLAN_HEADER+GV_PLAN_ENTRY*previous
56 if gv_plan_name_eq(plan[cell] as *u8,plan[cell+1],plan[old] as *u8,plan[old+1]) == 1 { plan[1]=0 }
57 previous=previous+1
58 }
59 row=row+1; start=pos+1
60 }
61 pos=pos+1
62 }
63 return plan
64}
65func gv_plan_take(plan: *i64, name: *u8) -> i64 {
66 var size: i64 = 0
67 while name[size] != (0 as u8) { size=size+1 }
68 var row: i64 = 0
69 while row < plan[0] {
70 let cell: i64 = GV_PLAN_HEADER+GV_PLAN_ENTRY*row
71 if gv_plan_name_eq(plan[cell] as *u8,plan[cell+1],name,size) == 1 {
72 plan[cell+2]=plan[cell+2]+1
73 return (plan[cell+2] == 1) as i64
74 }
75 row=row+1
76 }
77 plan[2]=plan[2]+1
78 return 0
79}
80func gv_plan_complete(plan: *i64) -> i64 {
81 if plan[1] != 1 { return 0 }
82 if plan[2] != 0 { return 0 }
83 var row: i64 = 0
84 while row < plan[0] {
85 if plan[GV_PLAN_HEADER+GV_PLAN_ENTRY*row+2] != 1 { return 0 }
86 row=row+1
87 }
88 return 1
89}
90func gv_plan_check(plan: *i64, name: *u8, cond: i64, ctr: *i64) -> i64 {
91 let accepted: i64 = gv_plan_take(plan,name)
92 return gv_check(name,((accepted == 1)&&(cond == 1)) as i64,ctr)
93}
94func gv_plan_finish(plan: *i64, ctr: *i64) -> i64 {
95 var row: i64 = 0
96 while row < plan[0] {
97 let cell: i64 = GV_PLAN_HEADER+GV_PLAN_ENTRY*row
98 if plan[cell+2] != 1 {
99 gv_puts(" PLAN case=" as *u8)
100 sys_write(1,plan[cell] as *u8,plan[cell+1])
101 gv_puts(" executions=" as *u8); gv_num(plan[cell+2]); gv_puts("\n" as *u8)
102 }
103 row=row+1
104 }
105 let result: i64 = gv_check("declared-plan-executed-exactly-once" as *u8,gv_plan_complete(plan),ctr)
106 gv_puts(" PLAN declared=" as *u8); gv_num(plan[0])
107 gv_puts(" valid=" as *u8); gv_num(plan[1])
108 gv_puts(" undeclared=" as *u8); gv_num(plan[2]); gv_puts("\n" as *u8)
109 sys_munmap(plan as *u8,GV_I64_BYTES*(GV_PLAN_HEADER+GV_PLAN_ENTRY*plan[0]))
110 return result
111}
112
113const GV_CTR_BYTES: i64 = 24
114const GV_NUM_SCRATCH: i64 = 28
115const GV_ZERO: i64 = 48
116const GV_B10: i64 = 10
117
118func gv_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
119func gv_num(v: i64) -> i64 {
120 let b: *u8 = sys_mmap(GV_NUM_SCRATCH)
121 let t: *u8 = sys_mmap(GV_NUM_SCRATCH)
122 var m: i64 = v
123 if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }
124 var k: i64 = 0
125 if m == 0 { t[0] = GV_ZERO as u8; k = 1 }
126 while m > 0 { t[k] = (GV_ZERO + (m % GV_B10)) as u8; m = m / GV_B10; k = k + 1 }
127 var i: i64 = 0
128 while i < k { b[i] = t[k-1-i]; i = i + 1 }
129 sys_write(1, b, k)
130 sys_munmap(b, GV_NUM_SCRATCH)
131 sys_munmap(t, GV_NUM_SCRATCH)
132 return 0
133}
134// EMIT ONE MEASURED KEY AND ITS VALUE, so a gate's GREEN can be checked from OUTSIDE the estate.
135// ★★★★★★A GATE THAT PRINTS ONLY PASS IS UNFALSIFIABLE FROM THE OUTSIDE: an arithmetic that cannot see a
136// number can never contradict one, so a pass-only gate makes an independent SECOND METHOD CLASS
137// structurally impossible -- and PROVEN requires two independent method classes. The estate already had
138// the law ("PRINT THE VALUES, NOT JUST PASS/FAIL") and no primitive for it, so every gate that obeyed the
139// law hand-rolled its own printer and most gates simply did not obey it. This is that primitive.
140// MEASURED 2026-09-03: nx_appliedmath_gate was 26/26 GREEN while emitting NOT ONE NUMBER; once it emitted
141// the 28 values its teeth rest on, CPython recomputed 24 of them from the declared inputs, AGREED on all
142// 24 with 15 at zero tolerance, and REFUSED two perturbed controls. None of that was possible the hour before.
143// Call it AFTER the teeth and BEFORE gv_verdict: the verdict line must stay LAST for gv_last_line, which
144// anchors by POSITION rather than by text.
145func gv_kv(k: *u8, v: i64) -> i64 {
146 gv_puts(" " as *u8); gv_puts(k); gv_puts("=" as *u8); gv_num(v); gv_puts("\n" as *u8)
147 return 0
148}
149
150// The header a reader (or an outside adjudicator) looks for to find the emitted block.
151// ce_number_envelope -- CE6 (codeeffectiveness): AN EFFECTIVENESS FIGURE PUBLISHES WITH ITS ENVELOPE OR NOT AT ALL.
152// A replay script that never observed the work matched frontier agents on static benchmarks, so a bare percentage
153// is not evidence. ONE ruler for every board: the value, n (observations behind it), the interval [lo, hi] it sits
154// in, and the null-control value (what the same ruler reads on a subject with nothing in it). A figure with n <= 0,
155// no interval (lo > hi), or an interval that excludes its own value is REFUSED BY NAME and never printed as a value
156// -- the refusal line replaces it, so no reader can mistake a bare number for a measured one. Returns
157// CE_ENV_PUBLISHED or the named refusal code so a gate can assert it. Same placement as gv_kv: after the teeth,
158// before gv_verdict, so the verdict line stays LAST.
159const CE_ENV_PUBLISHED: i64 = 0
160const CE_ENV_REFUSED_BARE: i64 = 1
161const CE_ENV_REFUSED_NO_INTERVAL: i64 = 2
162const CE_ENV_REFUSED_EXCLUDES: i64 = 3
163func ce_env_refuse(k: *u8, why: *u8, n: i64, lo: i64, hi: i64, code: i64) -> i64 {
164 gv_puts(" REFUSED-" as *u8); gv_puts(why); gv_puts(" key=" as *u8); gv_puts(k)
165 gv_puts(" rule=ce_number_envelope n=" as *u8); gv_num(n); gv_puts(" lo=" as *u8); gv_num(lo); gv_puts(" hi=" as *u8); gv_num(hi)
166 gv_puts(" -- a figure without n and an interval containing it does not publish\n" as *u8)
167 return code
168}
169func ce_number_envelope(k: *u8, v: i64, n: i64, lo: i64, hi: i64, null_v: i64) -> i64 {
170 if n <= 0 { return ce_env_refuse(k, "BARE-NUMBER" as *u8, n, lo, hi, CE_ENV_REFUSED_BARE) }
171 if lo > hi { return ce_env_refuse(k, "NO-INTERVAL" as *u8, n, lo, hi, CE_ENV_REFUSED_NO_INTERVAL) }
172 if v < lo { return ce_env_refuse(k, "INTERVAL-EXCLUDES-VALUE" as *u8, n, lo, hi, CE_ENV_REFUSED_EXCLUDES) }
173 if v > hi { return ce_env_refuse(k, "INTERVAL-EXCLUDES-VALUE" as *u8, n, lo, hi, CE_ENV_REFUSED_EXCLUDES) }
174 gv_puts(" " as *u8); gv_puts(k); gv_puts("=" as *u8); gv_num(v)
175 gv_puts(" n=" as *u8); gv_num(n); gv_puts(" lo=" as *u8); gv_num(lo); gv_puts(" hi=" as *u8); gv_num(hi)
176 gv_puts(" null=" as *u8); gv_num(null_v); gv_puts("\n" as *u8)
177 return CE_ENV_PUBLISHED
178}
179
180func gv_values_head() -> i64 {
181 gv_puts("\n VALUES emitted for independent adjudication -- recompute each from the declared inputs\n" as *u8)
182 return 0
183}
184
185// ★★★★★★ASSERT AND EMIT IN ONE CALL, SO THE NUMBER PUBLISHED AND THE NUMBER TESTED CANNOT DRIFT APART.
186// gv_kv alone leaves a gate author two jobs -- check a value, then remember to print it -- and the estate
187// has measured what happens to any invariant that depends on two places agreeing by discipline: 666 gates
188// sit on this base class and emit nothing at all. These make emission a SIDE EFFECT of the assertion, so
189// there is exactly ONE expression and disagreement is impossible by construction rather than by care.
190// MIGRATION IS MECHANICAL AND GREPPABLE:
191// gv_check("name", (a == b) as i64, ctr) -> gv_check_eq("name", a, b, ctr)
192// gv_check("name", (am_abs(a-b) <= t) as i64, ctr) -> gv_check_near("name", a, b, t, ctr)
193// The tooth line keeps its exact leading shape, so every existing reader, rollup and last-line judge is
194// unaffected; the values are APPENDED after the verdict word.
195func gv_check_eq(name: *u8, actual: i64, expected: i64, ctr: *i64) -> i64 {
196 let ok: i64 = (actual == expected) as i64
197 gv_check(name, ok, ctr)
198 gv_puts(" actual=" as *u8); gv_num(actual)
199 gv_puts(" expected=" as *u8); gv_num(expected)
200 gv_puts(" delta=" as *u8); gv_num(actual - expected)
201 gv_puts("\n" as *u8)
202 return ok
203}
204
205// The same, for a value the gate can only hold to a DECLARED tolerance. The tolerance is EMITTED beside
206// the delta on purpose: an outside adjudicator must be told what bar it is checking against, or it will
207// invent one -- and a tolerance that lives only in a tooth name cannot be read by a machine.
208func gv_check_near(name: *u8, actual: i64, expected: i64, tol: i64, ctr: *i64) -> i64 {
209 var d: i64 = actual - expected
210 if d < 0 { d = 0 - d }
211 let ok: i64 = (d <= tol) as i64
212 gv_check(name, ok, ctr)
213 gv_puts(" actual=" as *u8); gv_num(actual)
214 gv_puts(" expected=" as *u8); gv_num(expected)
215 gv_puts(" delta=" as *u8); gv_num(d)
216 gv_puts(" tol=" as *u8); gv_num(tol)
217 gv_puts("\n" as *u8)
218 return ok
219}
220
221func gv_ctr() -> *i64 {
222 let c: *i64 = sys_mmap(GV_CTR_BYTES) as *i64
223 c[0] = 0
224 c[1] = 0
225 c[2] = 0
226 return c
227}
228
229// ---- THE THIRD STATE: "I COULD NOT TEST" IS NOT "IT IS BROKEN" --------------------------------
230// ADDED 2026-08-07. Ten service-facing gates were built and run for the first time; SIX came back RED
231// and NOT ONE was a regression: missing fixtures (/tmp/sni_nishi_chain.der, /tmp/mozilla_certdata.txt),
232// missing config+creds (golive_dns.conf, porkbun), or the service under test simply not running.
233// A gate that reports FAIL when its PRECONDITIONS are absent is not reporting on the system at all --
234// it is reporting on its own environment, in the same word.
235// ★★★★★★ A DETECTOR THAT CANNOT DISTINGUISH "I COULD NOT LOOK" FROM "I LOOKED AND IT IS BROKEN"
236// TEACHES EVERYONE TO IGNORE IT, AND THEN IT IS WORSE THAN ABSENT.
237// This estate already learned the law twice: nx_gonogo grew a third state because a two-state verdict
238// WILL fabricate, and nx_commons_price returns UNPRICED rather than inventing a rate. Same rule here.
239// gv_need declares a precondition. If it is absent the gate ends SKIP (evidence=none), never RED.
240// SKIP is NOT a pass: it blocks any claim that the thing works, exactly as missing evidence blocks a
241// GO but never a NO-GO.
242func gv_need(name: *u8, present: i64, ctr: *i64) -> i64 {
243 if present == 1 { return 1 }
244 ctr[2] = ctr[2] + 1
245 gv_puts(" PRECONDITION MISSING: " as *u8)
246 gv_puts(name)
247 gv_puts(" -- cannot test, NOT a failure of the system under test\n" as *u8)
248 return 0
249}
250// ---- gv_subjects: THE EMPTY-SET LAW, MADE STRUCTURAL (2026-08-22) ---------------------------------
251// THE DEFECT: ctr[0]/ctr[1] count TEETH, never SUBJECTS. A gate with ten teeth over ZERO files reports
252// 10/10 GREEN and every consumer reads a pass. This estate has WRITTEN the law repeatedly --
253// "A TOOTH THAT PASSES ON THE EMPTY SET IS NOT A TOOTH", "BIND EVERY AGGREGATE ASSERTION TO ITS
254// DENOMINATOR" -- and never built the mechanism, so the discipline lived per-organ and hand-rolled
255// (nx_plane_check exits 4 EMPTY-not-a-pass; nx_battery_grade returns UNMEASURED on zero answer rows).
256// *A LAW EVERY AUTHOR MUST REMEMBER IS A LAW THAT WILL BE FORGOTTEN; ONLY A PRIMITIVE IN THE PATH HOLDS.
257// MEASURED THE DAY THIS WAS WRITTEN: a ship harness skipped its work behind a load guard, wrote no log,
258// and EXITED 0 -- inconclusive reading as success, inside the tooling built to enforce the opposite.
259//
260// A ZERO POPULATION IS NOT A FAILURE OF THE SUBJECT, IT IS THE ABSENCE OF EVIDENCE ABOUT IT. So this is
261// DELIBERATELY a precondition (SKIP), never a RED -- and it COMPOSES gv_need rather than inventing a
262// fourth state, so it inherits the already-proven ordering: a SKIP co-occurring with a real failure
263// still escalates to RED and can never amnesty it.
264// Fail-CLOSED on a negative count: an unreadable population is not permission to claim coverage.
265// The count PRINTS ALWAYS, pass or not, so coverage is on the record instead of inferred.
266func gv_subjects(name: *u8, n: i64, ctr: *i64) -> i64 {
267 gv_puts(" subjects=" as *u8)
268 gv_num(n)
269 gv_puts(" [" as *u8)
270 gv_puts(name)
271 gv_puts("]\n" as *u8)
272 var present: i64 = 0
273 if n > 0 { present = 1 }
274 return gv_need(name, present, ctr)
275}
276func gv_head(title: *u8) -> i64 { gv_puts(title); gv_puts("\n\n" as *u8); return 0 }
277// one check: prints " <name>: PASS|FAIL", bumps counters, returns cond
278func gv_check(name: *u8, cond: i64, ctr: *i64) -> i64 {
279 ctr[1] = ctr[1] + 1
280 gv_puts(" " as *u8)
281 gv_puts(name)
282 gv_puts(": " as *u8)
283 if cond == 1 { ctr[0] = ctr[0] + 1; gv_puts("PASS\n" as *u8) } else { gv_puts("FAIL\n" as *u8) }
284 return cond
285}
286// ---- HOISTED FROM THE NAS COPY 2026-07-31 (ws=gate-dry-d001). THE BASE CLASS HAD FORKED: the NAS tree
287// carried gv_bite/gv_cat/gv_catn/gv_journal and this tree carried only the original six, so a gate written
288// against one tree would not compile on the other -- and, worse, an identical migration bought DIFFERENT
289// capability depending on where it happened. Converging the ANCESTOR is the fix; every descendant gains
290// these without being touched, including the ones not written yet. That is the whole point of a base class.
291//
292// BITE-PROVEN cell: the non-vacuity law made structural. A detector counts ONLY if it FIRES on the crafted
293// bad input AND stays SILENT on the crafted good one. A cell green before the defect exists is VACUOUS and
294// proves nothing (the gates-green-on-garbage class). Prints the sub-verdict so vacuity is SEEN, not counted.
295func gv_bite(name: *u8, bad: i64, good: i64, ctr: *i64) -> i64 {
296 var ok: i64 = 0
297 if bad == 1 { if good == 0 { ok = 1 } }
298 ctr[1] = ctr[1] + 1
299 gv_puts(" " as *u8)
300 gv_puts(name)
301 if ok == 1 { ctr[0] = ctr[0] + 1; gv_puts(": BITE-PROVEN (fires on bad, silent on good)\n" as *u8) }
302 if ok == 0 {
303 gv_puts(": FAIL " as *u8)
304 if bad != 1 { gv_puts("[VACUOUS: did not fire on the bad input]" as *u8) }
305 if good != 0 { gv_puts("[FALSE-POSITIVE: fired on the good input]" as *u8) }
306 gv_puts("\n" as *u8)
307 }
308 return ok
309}
310
311const GV_MODE_644: i64 = 420
312const GV_LINE: i64 = 512
313const GV_TAB: i64 = 9
314const GV_SLASH: i64 = 47
315const GV_MINUS: i64 = 45
316
317func gv_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p }
318func gv_catn(d: *u8, o: i64, v: i64) -> i64 {
319 let t: *u8 = sys_mmap(GV_NUM_SCRATCH)
320 var m: i64 = v
321 var p: i64 = o
322 if m < 0 { d[p] = GV_MINUS as u8; p = p + 1; m = 0 - m }
323 var k: i64 = 0
324 if m == 0 { t[0] = GV_ZERO as u8; k = 1 }
325 while m > 0 { t[k] = (GV_ZERO + (m % GV_B10)) as u8; m = m / GV_B10; k = k + 1 }
326 var i: i64 = 0
327 while i < k { d[p] = t[k-1-i]; p = p + 1; i = i + 1 }
328 sys_munmap(t, GV_NUM_SCRATCH)
329 return p
330}
331
332// FAIL-SOFT outcome journal: every gate that emits a verdict self-records ONE actlog-grammar frame, so
333// the HARNESS class finally has evidence at all -- flake and EROSION (a banked GREEN later going RED)
334// become derivable, and the frames are minable for free. A write failure NEVER touches the verdict:
335// no permission, no journal, no problem. Append-only, single line, conflict-free (O_APPEND).
336// Deliberately self-contained (no new imports): organs define their own sj_*/cat helpers, so importing a
337// json lib here would collide across hundreds of consumers.
338func gv_journal(name: *u8, passed: i64, total: i64, green: i64) -> i64 {
339 let fd: i64 = sys_openat_append("knowledge/status/harness.jrnl" as *u8, GV_MODE_644)
340 if fd < 0 { return 0 }
341 let ln: *u8 = sys_mmap(GV_LINE)
342 var o: i64 = gv_catn(ln, 0, sys_now_realtime_sec())
343 ln[o] = GV_TAB as u8; o = o + 1
344 o = gv_cat(ln, o, "harness" as *u8)
345 ln[o] = GV_TAB as u8; o = o + 1
346 o = gv_cat(ln, o, name)
347 ln[o] = GV_TAB as u8; o = o + 1
348 o = gv_cat(ln, o, "run" as *u8)
349 ln[o] = GV_TAB as u8; o = o + 1
350 if green == 1 { o = gv_cat(ln, o, "GREEN" as *u8) } else { o = gv_cat(ln, o, "RED" as *u8) }
351 ln[o] = GV_TAB as u8; o = o + 1
352 o = gv_catn(ln, o, passed)
353 ln[o] = GV_SLASH as u8; o = o + 1
354 o = gv_catn(ln, o, total)
355 ln[o] = GV_NL as u8; o = o + 1
356 sys_write(fd, ln, o)
357 sys_close(fd)
358 sys_munmap(ln, GV_LINE)
359 return 0
360}
361
362// summary + verdict; returns exit code (0 GREEN / 1 RED). Caller gv_exit(rc), never the raw thread exit: a gate that
363// created a thread pool (nf_pool, mm_pool_i8, nsv_init, nx_pool_submit) and ends with sys_exit retires only the calling
364// thread; the workers stay parked in futex wait, the verdict is on disk and the process is a runaway with no kill surface
365// (two gates sat twenty minutes with fifteen threads each on 2026-09-17; nx_syscalls.nx had named the class on 2026-07-07
366// and left it to discipline, and this line prescribed the raw exit). gv_exit is exit_group, which is what return-from-main
367// already does, so a single-threaded gate loses nothing by taking it. nx_gatelaw_gate's L5 axis names the stragglers.
368// ============================================================================================
369// AD1's REFUSING HALF, WIRED (2026-09-03, lane K). MEASURED FIRST: gv_bare_rate had sat in this file
370// since 2026-08-27 with ZERO PRODUCTION CALLERS -- a grep for gv_bare_rate over buildroot/runtime
371// returns matches=8 over files=23592 with coverage_complete=1 corpus_complete=1, and every one of
372// those eight is this file's own comment, this file's own definition, or nx_rigor_envelope_gate,
373// which is its own gate. Its sibling gv_envelope_check returns matches=1 on that same corpus: its
374// definition, and nothing else. The rigor-envelope header above argues that a ruler in a sibling lib
375// is adopted at advice rates while a ruler in the base class is adopted by every gate that imports
376// it -- the ruler was duly placed in the base class and then never called from the emitter.
377// ***THE ADOPTION ARGUMENT WAS MADE AND THE WIRING WAS NOT DONE***, so the refusal was built,
378// gate-proven, and unreachable from every production emitter in the estate.
379//
380// SILENT WHEN CLEAN, BY CONSTRUCTION. This prints NOTHING unless the note actually carries a rate
381// with no denominator, so stdout stays BYTE-IDENTICAL for every gate that does not have the defect
382// and no existing judge-equivalence proof is invalidated by wiring it in.
383//
384// IT ANNOUNCES AND COUNTS, IT DOES NOT REFUSE -- CHOSEN, NOT CONCEDED. gv_verdict's return value IS
385// the fleet verdict (/api/gate_run derives GREEN/RED/SKIP from it), so letting a bare rate flip that
386// return would turn every gate whose note quotes a rate RED in one edit to the base class every gate
387// imports: the permanently-red detector everyone learns to ignore, installed at the root. The
388// refusing direction belongs to the QA admission contract, which can weigh it per candidate and
389// abstain when it cannot look.
390//
391// PRINTED ABOVE THE VERDICT LINE ON PURPOSE: gv_last_line and every positional reader in the estate
392// anchor on the FINAL line, so an announcement appended after the verdict would silently break all
393// of them. Emitting before the first verdict byte is what keeps the verdict last.
394func gv_note_bare_rate(note: *u8) -> i64 {
395 if (note as i64) == 0 { return 0 }
396 var n: i64 = 0
397 while note[n] != (0 as u8) { n = n + 1 }
398 let off: i64 = gv_bare_rate(note, n)
399 if off < 0 { return 0 }
400 gv_puts("\nNX-RIGOR bare-rate-in-note byte_offset=" as *u8)
401 gv_num(off)
402 gv_puts(" note_bytes=" as *u8)
403 gv_num(n)
404 gv_puts(" rule=AD1-gv_bare_rate\n" as *u8)
405 gv_puts(" A rate is published here whose enclosing object carries no n. Bind it to its denominator\n" as *u8)
406 gv_puts(" via gv_envelope / gv_envelope_json. ADVISORY: the verdict line below is UNCHANGED by this.\n" as *u8)
407 return 1
408}
409
410func gv_verdict(name: *u8, ctr: *i64, note: *u8) -> i64 {
411 // AD1 REFUSING HALF, WIRED: scan the note we are about to publish BEFORE any verdict byte is
412 // emitted, so this announcement can never displace the verdict line from the tail of the output.
413 gv_note_bare_rate(note)
414 // THIRD STATE FIRST. If any precondition was missing the run produced NO EVIDENCE about the
415 // system under test, so it must not be reported in the same word as a real failure.
416 // The third state IS plumbed, end to end: this returns 3, and nx_mgmt_api maps rc==3 to SKIP and
417 // excludes it from RED. It used to return 1 under a comment admitting that was hand-waving.
418 // A COMMENT THAT OUTLIVES THE DEFECT IT DESCRIBES BECOMES A FALSE CLAIM WITH A TRUSTED BYLINE --
419 // AND OTHERS BUILD WORKAROUNDS AGAINST IT. MEASURED: nx_mcu_ready_gate hand-rolled its own exit
420 // code because this paragraph told it not to trust the return value, and that hand-rolled version
421 // A FAILURE IS EVIDENCE, AND EVIDENCE MUST NOT BE AMNESTIED. The third state answers "I could not
422 // look". It must not also answer "I looked, I found a defect, and something ELSE was missing too".
423 // MEASURED 2026-08-15 on nx_adversarial_sov_gate: three checks RAN, one FAILED, one precondition was
424 // missing -- and this function reported `verdict=SKIP ... proved NOTHING about the system under test`
425 // while holding a real failure. The one failure a gate exists to catch was the one it could not
426 // report. A SKIP THAT CAN SWALLOW A RED IS NOT A THIRD STATE, IT IS AN AMNESTY.
427 // ORDERING IS THE WHOLE FIX, and it is a strict TIGHTENING: the only verdict that moves is
428 // (preconditions missing AND at least one check failed), SKIP -> RED. A clean run cannot become RED,
429 // a RED cannot become GREEN, and a SKIP with nothing failing is still SKIP. This can never bless
430 // anything -- it can only stop something being blessed.
431 // The missing preconditions are still NAMED on the verdict line, because "RED, and also partly
432 // unobservable" is a different situation from "RED, fully measured", and a reader needs both.
433 if ctr[1] > ctr[0] {
434 gv_puts("\nNX-" as *u8)
435 gv_puts(name)
436 gv_puts(" passed " as *u8)
437 gv_num(ctr[0])
438 gv_puts("/" as *u8)
439 gv_num(ctr[1])
440 if ctr[2] > 0 {
441 gv_puts(" (with " as *u8)
442 gv_num(ctr[2])
443 gv_puts(" precondition(s) ALSO missing -- a failed check is evidence, so this is RED, not SKIP)" as *u8)
444 }
445 gv_puts(" verdict=RED\n" as *u8)
446 gv_journal(name, ctr[0], ctr[1], 0)
447 return 1
448 }
449 // silently collapsed SKIP into RED -- the very class of bug it was avoiding.
450 if ctr[2] > 0 {
451 gv_puts("\nNX-" as *u8)
452 gv_puts(name)
453 gv_puts(" verdict=SKIP -- " as *u8)
454 gv_num(ctr[2])
455 gv_puts(" precondition(s) missing; ran " as *u8)
456 gv_num(ctr[1])
457 gv_puts(" checks, proved NOTHING about the system under test.\n" as *u8)
458 gv_puts(" SKIP is not a pass: it blocks any claim that this works, exactly as missing\n" as *u8)
459 gv_puts(" evidence blocks a GO but never a NO-GO.\n" as *u8)
460 gv_journal(name, ctr[0], ctr[1], 0)
461 // EXIT 3 = SKIP, distinct from 1 = RED. This used to return 1 with a comment admitting the
462 // distinction "lives in the output text until gate_run maps a third exit code". That was
463 // hand-waving: a third state that collapses to RED at the transport is not a third state.
464 // /api/gate_run now maps 3 -> SKIP, so "I could not look" is machine-readable fleet-wide.
465 return 3
466 }
467 gv_puts("\nNX-" as *u8)
468 gv_puts(name)
469 gv_puts(" passed " as *u8)
470 gv_num(ctr[0])
471 gv_puts("/" as *u8)
472 gv_num(ctr[1])
473 if ctr[0] == ctr[1] {
474 if ctr[1] > 0 {
475 gv_puts(" verdict=GREEN (" as *u8)
476 gv_puts(note)
477 gv_puts(")\n" as *u8)
478 // The journal write is a FILE side-effect only -- stdout, the PASS/FAIL vector and the
479 // verdict line are byte-unchanged, so every migration already proven judge-equivalent
480 // stays valid. Every inheriting gate now records its own outcome without being touched.
481 gv_journal(name, ctr[0], ctr[1], 1)
482 return 0
483 }
484 }
485 gv_puts(" verdict=RED\n" as *u8)
486 gv_journal(name, ctr[0], ctr[1], 0)
487 return 1
488}
489
490// ============================================================================================
491// THE RIGOR ENVELOPE (AD1, 2026-08-27): A PUBLISHED NUMBER IS A STRUCT, NEVER A BARE RATE.
492// ============================================================================================
493// WHY IT LIVES IN THE BASE CLASS: /compare/autograde published "92 percent resolved" with no
494// denominator (the July record says n=14: 13 of 14); /compare/gen's referee rows publish HPSv2 /
495// PickScore / GenEval values with no n, no interval, no engine hash. Both boards were made to share
496// ONE ruler by the operator's standing order (proven evidence mandatory on BOTH), and the only place
497// every gate already inherits from is this file. A ruler in a sibling lib is adopted at advice
498// rates; a ruler in the base class is adopted at 100 percent of the gates that import it.
499//
500// THE STRUCT (out[GV_ENV_FIELDS], every field an i64, rates in PERMIL):
501// k n rate wilson_lo wilson_hi boot_lo boot_hi env_lo env_hi clusters B seed measured z_micro width target
502// THE METHOD, with its sources named so a reader can refute it rather than trust it:
503// * Wilson score interval (Wilson 1927, JASA 22:209-212), z = Phi^-1(0.975) = 1.959964 for a
504// two-sided 95 percent interval. Chosen over the Wald interval because Wald collapses to zero width
505// at k=0 and k=n, which is exactly where a small benchmark lives (0 of 14, 14 of 14).
506// * A HIERARCHICAL (two-level) bootstrap over the task nesting (Miller et al. 2025, "Statistical
507// Precipice" -- agent benchmarks nest runs inside tasks, and a flat interval under-covers):
508// resample clusters with replacement, then each chosen cluster's outcomes with replacement, B
509// replicates, percentile interval. The envelope is the WIDER of the two -- the bootstrap can only
510// widen Wilson, never narrow it, so a caller cannot launder a small n through clustering.
511// * A Park-Miller minimal-standard generator (Park and Miller 1988, CACM 31(10)): multiply-and-mod
512// only, so no bitwise or shift semantics are relied on, seed-deterministic so two runs of the same
513// ledger publish the same interval.
514// * INTEGER ARITHMETIC THROUGHOUT (this is the no-float estate). Micro-units (1e6) carry z and the
515// radicand; the square root is bisection on i64. The five reference values below were checked by
516// hand against the closed form before this shipped: 7/14 -> [268,732], 13/14 -> [685,987],
517// 0/14 -> [0,215], 14/14 -> [785,1000], 1/1 -> [207,1000] permil.
518// THE REFUSAL: gv_bare_rate scans a text body for digits followed by "%" or " percent" whose enclosing
519// JSON object carries no "n" field, and returns the offender's byte offset. A page emitted through
520// gv_envelope_json never trips it, because that object always carries "n". A hand-typed percent does.
521// THE PARAMETERS are ARGUMENTS, not literals read here: z_micro, B, seed and the width target come
522// from knowledge/rigor.conf through nx_stage_path.sp_rigor_int (this lib deliberately imports nothing
523// new -- `const EP_MAGIC_1024` already exists independently in nx_ecomat_put.nx:12, so importing
524// nx_estate_path here would collide at some gate's next build). The bootstrap defaults below are
525// the fallback when no conf row exists, and every printed line names the values it used.
526// UNMEASURED IS ITS OWN STATE: n=0 returns 0 and prints UNMEASURED; a cluster partition that does not
527// sum to (k,n) returns GV_ENV_REFUSED_PARTITION and prints REFUSED-PARTITION -- a partition is a claim.
528const GV_ENV_FIELDS: i64 = 16
529const GV_ENV_BYTES: i64 = 128 // GV_ENV_FIELDS * 8
530const GV_ENV_K: i64 = 0
531const GV_ENV_N: i64 = 1
532const GV_ENV_RATE: i64 = 2
533const GV_ENV_WLO: i64 = 3
534const GV_ENV_WHI: i64 = 4
535const GV_ENV_BLO: i64 = 5
536const GV_ENV_BHI: i64 = 6
537const GV_ENV_LO: i64 = 7
538const GV_ENV_HI: i64 = 8
539const GV_ENV_CLUSTERS: i64 = 9
540const GV_ENV_B: i64 = 10
541const GV_ENV_SEED: i64 = 11
542const GV_ENV_MEASURED: i64 = 12
543const GV_ENV_Z: i64 = 13
544const GV_ENV_WIDTH: i64 = 14
545const GV_ENV_TARGET: i64 = 15
546const GV_ENV_REFUSED_PARTITION: i64 = 0 - 1
547const GV_MICRO: i64 = 1000000
548const GV_PERMIL: i64 = 1000
549// Phi^-1(0.975) in micro-units: the two-sided 95 percent normal quantile (Wilson 1927).
550const GV_Z95_MICRO: i64 = 1959964
551// the radicand is carried in micro-units; multiplying by 100 before the integer sqrt makes the root
552// come out scaled by 1e4 (sqrt(1e6 * 1e2) = 1e4), i.e. four decimals of the root survive the floor.
553const GV_SQRT_IN_SCALE: i64 = 100
554const GV_SQRT_OUT_SCALE: i64 = 10000
555// B=1000 is the textbook floor for a bootstrap percentile interval (Efron and Tibshirani 1993, ch.13).
556const GV_BOOT_B_DEFAULT: i64 = 1000
557// any fixed seed is reproducible; this one names the day the envelope shipped, so a reader can date it.
558const GV_BOOT_SEED_DEFAULT: i64 = 20260827
559// Park-Miller minimal standard: x' = 16807 * x mod (2^31 - 1). Period 2^31-2, far above B * n here.
560const GV_PM_A: i64 = 16807
561const GV_PM_M: i64 = 2147483647
562// n*n must fit an i64 for the radicand 4k(n-k): the exact limit is 3,037,000,499; floored with headroom.
563const GV_ENV_N_MAX: i64 = 2000000000
564// isqrt bisection upper bound: the largest v with v*v <= 2^63-1 is 3,037,000,499 (no mid*mid overflow).
565const GV_ISQRT_HI: i64 = 3037000499
566// replicate rates are permil, so a 1001-bin histogram makes the percentile walk O(B) with no sort.
567const GV_HIST_BINS: i64 = 1001
568const GV_HIST_BYTES: i64 = 8008 // GV_HIST_BINS * 8
569// the 2.5th and 97.5th percentiles of the replicate distribution bound a two-sided 95 percent interval.
570const GV_PCT_LO_PERMIL: i64 = 25
571const GV_PCT_HI_PERMIL: i64 = 975
572const GV_ENV_UNDECLARED: *u8 = "UNDECLARED"
573
574func gv_isqrt(v: i64) -> i64 {
575 if v <= 0 { return 0 }
576 var lo: i64 = 0
577 var hi: i64 = v
578 if hi > GV_ISQRT_HI { hi = GV_ISQRT_HI }
579 while lo < hi {
580 let mid: i64 = (lo + hi + 1) / 2
581 if mid * mid <= v { lo = mid } else { hi = mid - 1 }
582 }
583 return lo
584}
585
586// Wilson bounds in permil for k of n at z (micro). out[0]=lo out[1]=hi. Returns 1, or 0 UNMEASURED.
587// bounds = (2k + z^2 +- z * sqrt(4k(n-k)/n + z^2)) / (2(n + z^2))
588func gv_wilson_permil(k: i64, n: i64, z_micro: i64, out: *i64) -> i64 {
589 if n <= 0 { return 0 }
590 if n > GV_ENV_N_MAX { return 0 }
591 if k < 0 { return 0 }
592 if k > n { return 0 }
593 let z2: i64 = (z_micro * z_micro) / GV_MICRO
594 let a: i64 = 2 * k * GV_MICRO + z2
595 let d: i64 = 2 * (n * GV_MICRO + z2)
596 let f: i64 = 4 * k * (n - k)
597 let q: i64 = f / n
598 let r: i64 = f - q * n
599 let rad: i64 = q * GV_MICRO + (r * GV_MICRO) / n + z2
600 let s: i64 = gv_isqrt(rad * GV_SQRT_IN_SCALE)
601 let t: i64 = (z_micro * s) / GV_SQRT_OUT_SCALE
602 var lo: i64 = ((a - t) * GV_PERMIL + d / 2) / d
603 var hi: i64 = ((a + t) * GV_PERMIL + d / 2) / d
604 if lo < 0 { lo = 0 }
605 if hi > GV_PERMIL { hi = GV_PERMIL }
606 out[0] = lo
607 out[1] = hi
608 return 1
609}
610
611func gv_rng_next(state: *i64) -> i64 {
612 var x: i64 = state[0]
613 if x <= 0 { x = 1 }
614 if x >= GV_PM_M { x = x % GV_PM_M }
615 if x == 0 { x = 1 }
616 x = (GV_PM_A * x) % GV_PM_M
617 state[0] = x
618 return x
619}
620
621// Two-level bootstrap over clusters (ck[c] successes of cn[c] outcomes). out[0]=lo out[1]=hi permil.
622// Returns 1, or 0 when there is nothing to resample.
623func gv_boot_hier(ck: *i64, cn: *i64, nc: i64, b: i64, seed: i64, out: *i64) -> i64 {
624 if nc <= 0 { return 0 }
625 if b <= 0 { return 0 }
626 var ntot: i64 = 0
627 var c0: i64 = 0
628 while c0 < nc { ntot = ntot + cn[c0]; c0 = c0 + 1 }
629 if ntot <= 0 { return 0 }
630 let hist: *i64 = sys_mmap(GV_HIST_BYTES) as *i64
631 var hz: i64 = 0
632 while hz < GV_HIST_BINS { hist[hz] = 0; hz = hz + 1 }
633 let st: *i64 = sys_mmap(8) as *i64
634 st[0] = seed
635 var rep: i64 = 0
636 while rep < b {
637 var succ: i64 = 0
638 var tot: i64 = 0
639 var pick: i64 = 0
640 while pick < nc {
641 let c: i64 = gv_rng_next(st) % nc
642 let kc: i64 = ck[c]
643 let ncc: i64 = cn[c]
644 var dd: i64 = 0
645 while dd < ncc {
646 if (gv_rng_next(st) % ncc) < kc { succ = succ + 1 }
647 tot = tot + 1
648 dd = dd + 1
649 }
650 pick = pick + 1
651 }
652 var rate: i64 = 0
653 if tot > 0 { rate = (succ * GV_PERMIL + tot / 2) / tot }
654 if rate < 0 { rate = 0 }
655 if rate > GV_PERMIL { rate = GV_PERMIL }
656 hist[rate] = hist[rate] + 1
657 rep = rep + 1
658 }
659 let lo_need: i64 = (b * GV_PCT_LO_PERMIL + GV_PERMIL - 1) / GV_PERMIL
660 let hi_need: i64 = (b * GV_PCT_HI_PERMIL + GV_PERMIL - 1) / GV_PERMIL
661 var cum: i64 = 0
662 var lo: i64 = 0 - 1
663 var hi: i64 = 0 - 1
664 var bin: i64 = 0
665 while bin < GV_HIST_BINS {
666 cum = cum + hist[bin]
667 if lo < 0 { if cum >= lo_need { lo = bin } }
668 if hi < 0 { if cum >= hi_need { hi = bin } }
669 bin = bin + 1
670 }
671 if lo < 0 { lo = 0 }
672 if hi < 0 { hi = GV_PERMIL }
673 sys_munmap(hist as *u8, GV_HIST_BYTES)
674 sys_munmap(st as *u8, 8)
675 out[0] = lo
676 out[1] = hi
677 return 1
678}
679
680// THE ENVELOPE. ck/cn/nc describe the task nesting (pass nc=0 for "no nesting known": the plain
681// bootstrap is the degenerate hierarchy and clusters=1 is printed so the reader can see that).
682// width_target is the conf row (permil); width_ok is derived from it and printed, never decided here.
683// Returns 1 MEASURED, 0 UNMEASURED (n<=0 or k out of range), GV_ENV_REFUSED_PARTITION when the
684// clusters do not sum to (k, n).
685func gv_envelope(k: i64, n: i64, ck: *i64, cn: *i64, nc: i64, z_micro: i64, b: i64, seed: i64, width_target: i64, out: *i64) -> i64 {
686 var i: i64 = 0
687 while i < GV_ENV_FIELDS { out[i] = 0; i = i + 1 }
688 out[GV_ENV_K] = k
689 out[GV_ENV_N] = n
690 out[GV_ENV_Z] = z_micro
691 out[GV_ENV_B] = b
692 out[GV_ENV_SEED] = seed
693 out[GV_ENV_TARGET] = width_target
694 out[GV_ENV_CLUSTERS] = nc
695 if n <= 0 { return 0 }
696 if k < 0 { return 0 }
697 if k > n { return 0 }
698 if nc > 0 {
699 var sk: i64 = 0
700 var sn: i64 = 0
701 var c: i64 = 0
702 while c < nc { sk = sk + ck[c]; sn = sn + cn[c]; c = c + 1 }
703 if sk != k { return GV_ENV_REFUSED_PARTITION }
704 if sn != n { return GV_ENV_REFUSED_PARTITION }
705 }
706 out[GV_ENV_RATE] = (k * GV_PERMIL + n / 2) / n
707 let w: *i64 = sys_mmap(16) as *i64
708 if gv_wilson_permil(k, n, z_micro, w) == 0 { return 0 }
709 out[GV_ENV_WLO] = w[0]
710 out[GV_ENV_WHI] = w[1]
711 var kk: *i64 = ck
712 var nn: *i64 = cn
713 var ncl: i64 = nc
714 if ncl <= 0 {
715 let one: *i64 = sys_mmap(16) as *i64
716 one[0] = k
717 one[1] = n
718 kk = one
719 nn = ((one as i64) + 8) as *i64
720 ncl = 1
721 }
722 out[GV_ENV_CLUSTERS] = ncl
723 let bb: *i64 = sys_mmap(16) as *i64
724 if gv_boot_hier(kk, nn, ncl, b, seed, bb) == 1 {
725 out[GV_ENV_BLO] = bb[0]
726 out[GV_ENV_BHI] = bb[1]
727 } else {
728 out[GV_ENV_BLO] = w[0]
729 out[GV_ENV_BHI] = w[1]
730 }
731 var lo: i64 = w[0]
732 if out[GV_ENV_BLO] < lo { lo = out[GV_ENV_BLO] }
733 var hi: i64 = w[1]
734 if out[GV_ENV_BHI] > hi { hi = out[GV_ENV_BHI] }
735 out[GV_ENV_LO] = lo
736 out[GV_ENV_HI] = hi
737 out[GV_ENV_WIDTH] = hi - lo
738 out[GV_ENV_MEASURED] = 1
739 return 1
740}
741
742// width_ok: 1 when a target was given and the envelope is no wider than it; 0 otherwise. A target of
743// 0 means "none declared" and reads as 0 -- an undeclared bar can never be met.
744func gv_envelope_width_ok(out: *i64) -> i64 {
745 if out[GV_ENV_MEASURED] != 1 { return 0 }
746 if out[GV_ENV_TARGET] <= 0 { return 0 }
747 if out[GV_ENV_WIDTH] <= out[GV_ENV_TARGET] { return 1 }
748 return 0
749}
750
751func gv_env_pair(a: i64, b: i64) -> i64 {
752 gv_puts("[" as *u8); gv_num(a); gv_puts("," as *u8); gv_num(b); gv_puts("]" as *u8)
753 return 0
754}
755
756// the canonical printed line: one row, every parameter on it, so the number can be re-derived.
757func gv_envelope_print(label: *u8, out: *i64, harness: *u8) -> i64 {
758 gv_puts(" ENVELOPE " as *u8)
759 gv_puts(label)
760 gv_puts(" k=" as *u8); gv_num(out[GV_ENV_K])
761 gv_puts(" n=" as *u8); gv_num(out[GV_ENV_N])
762 if out[GV_ENV_MEASURED] == 1 {
763 gv_puts(" rate_permil=" as *u8); gv_num(out[GV_ENV_RATE])
764 gv_puts(" ci_permil=" as *u8); gv_env_pair(out[GV_ENV_LO], out[GV_ENV_HI])
765 gv_puts(" wilson=" as *u8); gv_env_pair(out[GV_ENV_WLO], out[GV_ENV_WHI])
766 gv_puts(" boot=" as *u8); gv_env_pair(out[GV_ENV_BLO], out[GV_ENV_BHI])
767 gv_puts(" width=" as *u8); gv_num(out[GV_ENV_WIDTH])
768 gv_puts(" target=" as *u8); gv_num(out[GV_ENV_TARGET])
769 gv_puts(" width_ok=" as *u8); gv_num(gv_envelope_width_ok(out))
770 } else {
771 gv_puts(" UNMEASURED (no population -- a rate over nothing is not a rate)" as *u8)
772 }
773 gv_puts(" clusters=" as *u8); gv_num(out[GV_ENV_CLUSTERS])
774 gv_puts(" B=" as *u8); gv_num(out[GV_ENV_B])
775 gv_puts(" seed=" as *u8); gv_num(out[GV_ENV_SEED])
776 gv_puts(" z_micro=" as *u8); gv_num(out[GV_ENV_Z])
777 gv_puts(" harness=" as *u8)
778 if (harness as i64) == 0 { gv_puts(GV_ENV_UNDECLARED) } else { if harness[0] == (0 as u8) { gv_puts(GV_ENV_UNDECLARED) } else { gv_puts(harness) } }
779 gv_puts(" method=wilson+hierarchical-bootstrap\n" as *u8)
780 return 0
781}
782
783// JSON object for a published page. Always carries "n" (the field the refusal looks for).
784func gv_envelope_json(d: *u8, o0: i64, out: *i64, harness: *u8) -> i64 {
785 var o: i64 = o0
786 o = gv_cat(d, o, "{\"k\":" as *u8); o = gv_catn(d, o, out[GV_ENV_K])
787 o = gv_cat(d, o, ",\"n\":" as *u8); o = gv_catn(d, o, out[GV_ENV_N])
788 if out[GV_ENV_MEASURED] == 1 {
789 o = gv_cat(d, o, ",\"rate_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_RATE])
790 o = gv_cat(d, o, ",\"ci_lo_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_LO])
791 o = gv_cat(d, o, ",\"ci_hi_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_HI])
792 o = gv_cat(d, o, ",\"wilson_lo_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_WLO])
793 o = gv_cat(d, o, ",\"wilson_hi_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_WHI])
794 o = gv_cat(d, o, ",\"boot_lo_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_BLO])
795 o = gv_cat(d, o, ",\"boot_hi_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_BHI])
796 o = gv_cat(d, o, ",\"width_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_WIDTH])
797 o = gv_cat(d, o, ",\"width_target_permil\":" as *u8); o = gv_catn(d, o, out[GV_ENV_TARGET])
798 o = gv_cat(d, o, ",\"width_ok\":" as *u8); o = gv_catn(d, o, gv_envelope_width_ok(out))
799 o = gv_cat(d, o, ",\"verdict\":\"MEASURED\"" as *u8)
800 } else {
801 o = gv_cat(d, o, ",\"rate_permil\":null,\"ci_lo_permil\":null,\"ci_hi_permil\":null,\"verdict\":\"UNMEASURED\"" as *u8)
802 }
803 o = gv_cat(d, o, ",\"clusters\":" as *u8); o = gv_catn(d, o, out[GV_ENV_CLUSTERS])
804 o = gv_cat(d, o, ",\"boot_reps\":" as *u8); o = gv_catn(d, o, out[GV_ENV_B])
805 o = gv_cat(d, o, ",\"seed\":" as *u8); o = gv_catn(d, o, out[GV_ENV_SEED])
806 o = gv_cat(d, o, ",\"z_micro\":" as *u8); o = gv_catn(d, o, out[GV_ENV_Z])
807 o = gv_cat(d, o, ",\"harness\":\"" as *u8)
808 if (harness as i64) == 0 { o = gv_cat(d, o, GV_ENV_UNDECLARED) } else { if harness[0] == (0 as u8) { o = gv_cat(d, o, GV_ENV_UNDECLARED) } else { o = gv_cat(d, o, harness) } }
809 o = gv_cat(d, o, "\",\"method\":\"wilson+hierarchical-bootstrap\"}" as *u8)
810 return o
811}
812
813// does buf[at..] begin with lit (NUL-terminated), inside n?
814func gv_at(buf: *u8, n: i64, at: i64, lit: *u8) -> i64 {
815 var i: i64 = 0
816 while lit[i] != (0 as u8) {
817 if at + i >= n { return 0 }
818 if buf[at + i] != lit[i] { return 0 }
819 i = i + 1
820 }
821 return 1
822}
823
824// does the JSON object enclosing position `at` (nearest '{' before, nearest '}' after) carry "n":?
825func gv_obj_has_n(buf: *u8, n: i64, at: i64) -> i64 {
826 var s: i64 = at
827 var go: i64 = 1
828 while go == 1 {
829 if s <= 0 { s = 0; go = 0 } else {
830 if buf[s] == (123 as u8) { go = 0 } else { s = s - 1 }
831 }
832 }
833 var e: i64 = at
834 go = 1
835 while go == 1 {
836 if e >= n { e = n; go = 0 } else {
837 if buf[e] == (125 as u8) { go = 0 } else { e = e + 1 }
838 }
839 }
840 var i: i64 = s
841 while i < e {
842 if gv_at(buf, e, i, "\"n\":" as *u8) == 1 { return 1 }
843 i = i + 1
844 }
845 return 0
846}
847
848// THE REFUSAL. Returns the byte offset of the first bare rate (digits + "%" or " percent" with no "n"
849// in the enclosing object), or -1 when the body is clean.
850func gv_bare_rate(buf: *u8, n: i64) -> i64 {
851 var i: i64 = 0
852 while i < n {
853 let c: i64 = buf[i] as i64
854 var isd: i64 = 0
855 if c >= 48 { if c <= 57 { isd = 1 } }
856 if isd == 1 {
857 var j: i64 = i
858 var scan: i64 = 1
859 while scan == 1 {
860 if j >= n { scan = 0 } else {
861 let dch: i64 = buf[j] as i64
862 var dd: i64 = 0
863 if dch >= 48 { if dch <= 57 { dd = 1 } }
864 if dd == 1 { j = j + 1 } else { scan = 0 }
865 }
866 }
867 var hit: i64 = 0
868 if j < n { if buf[j] == (37 as u8) { hit = 1 } }
869 if hit == 0 { if gv_at(buf, n, j, " percent" as *u8) == 1 { hit = 1 } }
870 if hit == 1 { if gv_obj_has_n(buf, n, i) == 0 { return i } }
871 i = j
872 } else { i = i + 1 }
873 }
874 return 0 - 1
875}
876
877// AD2's half of the contract: two envelopes are directly comparable only when their harness manifests
878// are the SAME declared hash. UNDECLARED (or empty) on either side refuses -- an undeclared harness is
879// not a matching one.
880func gv_envelope_comparable(ha: *u8, hb: *u8) -> i64 {
881 if (ha as i64) == 0 { return 0 }
882 if (hb as i64) == 0 { return 0 }
883 if ha[0] == (0 as u8) { return 0 }
884 if hb[0] == (0 as u8) { return 0 }
885 if gv_at(ha, GV_LINE, 0, GV_ENV_UNDECLARED) == 1 { return 0 }
886 if gv_at(hb, GV_LINE, 0, GV_ENV_UNDECLARED) == 1 { return 0 }
887 var i: i64 = 0
888 while ha[i] != (0 as u8) {
889 if ha[i] != hb[i] { return 0 }
890 i = i + 1
891 }
892 if hb[i] != (0 as u8) { return 0 }
893 return 1
894}
895
896// a tooth that binds a published rate to its denominator: passes only when the envelope MEASURED, and
897// prints the envelope line beside the PASS/FAIL so the reader sees the numbers, not a boolean.
898func gv_envelope_check(name: *u8, out: *i64, harness: *u8, ctr: *i64) -> i64 {
899 gv_envelope_print(name, out, harness)
900 var ok: i64 = 0
901 if out[GV_ENV_MEASURED] == 1 { ok = 1 }
902 return gv_check(name, ok, ctr)
903}
904
905// THE EXIT (2026-09-17): exit_group, so a gate takes its pool workers with it -- see the note above gv_verdict.
906func gv_exit(rc: i64) -> i64 { sys_exit_group(rc); return rc }