nx_langdiag_gate.nx source
↩ module page · 167 lines · 11035 B
1// nx_langdiag_gate.nx -- THE LANGUAGE-DIAGNOSTIC PROBE CORPUS, RUN NATIVELY (2026-08-14).
2//
3// WHY THIS EXISTS. Every language probe shipped 2026-08-13 was driven by a hand-written shell
4// script under _ops/ -- build, run, grep, eyeball. That is the break-glass shape the estate's own
5// law forbids (NishiLang for everything; shell only to LAUNCH a sovereign ELF), and it carried a
6// measured weakness the shell could not fix:
7//
8// THE BASH GAUNTLET'S CCFAIL CELLS ASSERT ONLY *THAT* A PROBE WAS REFUSED, NEVER *WHY*.
9// They check the emitted .s is empty. A refusal for a COMPLETELY DIFFERENT reason -- a typo in
10// the probe, an unrelated regression, a parser desync -- passes them silently. That is the
11// "a suite that only asks 'was it refused?' is blind by construction" failure this estate
12// already paid for once on the SSRF deny-tests.
13//
14// This gate fixes it by composing the INCUMBENT base class rather than adding a second ruler:
15// nx_gate_lib's gl_case forks a real organ and asserts BOTH the exit code AND a required output
16// substring. Here the forked organ is the LIVE sovereign compiler and the substring is the
17// DISTINCTIVE PHRASE of the rule under test -- usually its capability= slug. So a refusal now has
18// to be the RIGHT refusal, and a compiler that refused everything generically fails this gate.
19// BITE-PROVEN 2026-08-14: planting a slug the rule never prints yields
20// FAIL const-overshift-refused-by-name exit=2 want_exit=2 want=<planted>
21// -- the EXIT CODE MATCHED and the REASON DID NOT, which is exactly the case a CCFAIL cell passes.
22//
23// ACCEPT cases are equally load-bearing: they assert exit 0 AND a real assembly marker, because a
24// compiler that emitted NOTHING and exited 0 would pass an exit-code-only check. And they are the
25// discrimination control -- without them, a compiler that refuses every input passes every
26// refusal row above (bite-proven: pointing an accept row at a refusing probe goes RED).
27//
28// SUBJECT: the compiler at _offc/nx_cc_sovereign.elf, i.e. the artifact that actually ships.
29//
30// 2026-09-02 (debt 1788309098 adjudicated): the gate read RED 9/11 from 2026-08-25 to 2026-09-02 on a
31// compiler that was CORRECT -- LN15 turned its two multi-line refusal witnesses into valid programs.
32// The two rules survive on irreducible witnesses (nx_probe_opstart_live, nx_probe_lone_operator) and
33// the joined forms moved to the acceptance side. A fixture that stops reaching its condition is the
34// quietest way a conformance case goes vacuous; the receipt for this repair is in lang.gates.
35//
36// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
37import "nx_syscalls.nx"
38import "nx_gate_lib.nx"
39// D001 (refused this gate's first promote, correctly): a gate must inherit the SANCTIONED verdict
40// emitter or nothing downstream can judge it -- nx_gate_green cannot read it and it records no
41// harness frame, so flake and erosion stay invisible. The override (allow_own_verdict=yes) ships an
42// unreadable gate, so it is not taken. Instead BOTH incumbents compose: gl_case keeps the
43// fork-and-assert mechanics (exit code AND required substring, with rich FAIL rows), and gv_*
44// owns adjudication + the verdict anchor. Neither is re-implemented.
45import "nx_gate_verdict.nx"
46
47const LDG_PB: i64 = 65536
48const LDG_EXIT_UNRESOLVED: i64 = 3
49
50// Does this path exist and open for reading?
51func ldg_have(p: *u8) -> i64 {
52 let fd: i64 = sys_openat_rd(p)
53 if fd < 0 { return 0 }
54 sys_close(fd)
55 return 1
56}
57
58// RESOLVE THE SUBJECT, NEVER ASSUME IT (2026-08-14, caught on this gate's FIRST run).
59// The first version chdir'd to "buildroot" unconditionally, matching the API gate-runner's cwd.
60// On the laptop tree a buildroot/ directory EXISTS but holds no toolchain, so the chdir SUCCEEDED,
61// walked away from the real subject, and every row failed with exit=127 -- eleven confident RED
62// rows describing a compiler that was never executed. Uniform 127 across rows that cannot all
63// share a cause is the exec-fail signature, not a regression.
64// So: probe for the subject where we stand, then one level down, and if it is genuinely absent
65// REFUSE WITH A THIRD STATE. "I could not look" is not "it is broken", and a gate that reports
66// RED when its subject is missing teaches everyone to ignore it.
67func ldg_resolve_subject(cc: *u8) -> i64 {
68 if ldg_have(cc) == 1 { return 1 }
69 sys_chdir("buildroot" as *u8)
70 if ldg_have(cc) == 1 { return 1 }
71 return 0
72}
73
74// ONE ROW, adjudicated twice over on purpose: gl_case does the forking and the two assertions and
75// buffers a rich FAIL line (exit + want_exit + want); gv_check then records the SAME outcome on the
76// sanctioned counter so D001's judge can read the result. gl_case increments counts[1] only on a
77// pass, so the delta IS the boolean -- declared, rather than re-deriving the verdict a second way.
78func ldg_row(nm: *u8, src: *u8, want_exit: i64, want: *u8,
79 counts: *i64, ctr: *i64, pb: *u8, po: i64) -> i64 {
80 let cc: *u8 = "_offc/nx_cc_sovereign.elf" as *u8
81 let before: i64 = counts[1]
82 let np: i64 = gl_case(nm, cc, gl_av1(cc, src), want_exit, want, counts, pb, po)
83 gv_check(nm, counts[1] - before, ctr)
84 return np
85}
86// one refusal row: the probe must be REFUSED (exit 2) *and* the output must name the rule.
87func ldg_refuse(nm: *u8, src: *u8, want: *u8, counts: *i64, ctr: *i64, pb: *u8, po: i64) -> i64 {
88 return ldg_row(nm, src, 2, want, counts, ctr, pb, po)
89}
90// one acceptance row: the probe must COMPILE (exit 0) and emit real assembly.
91func ldg_accept(nm: *u8, src: *u8, counts: *i64, ctr: *i64, pb: *u8, po: i64) -> i64 {
92 return ldg_row(nm, src, 0, ".att_syntax" as *u8, counts, ctr, pb, po)
93}
94
95func main() -> i64 {
96 if ldg_resolve_subject("_offc/nx_cc_sovereign.elf" as *u8) == 0 {
97 gl_puts("NX-LANGDIAG-GATE\nverdict=UNRESOLVED subject=_offc/nx_cc_sovereign.elf not found from this cwd or from buildroot/ -- the compiler under test is absent, so nothing was measured. This is NOT a language regression; run from the tree root that holds _offc/ and runtime/.\n" as *u8)
98 return LDG_EXIT_UNRESOLVED
99 }
100 let ctr: *i64 = gv_ctr()
101 gv_head("=== NX-LANGDIAG-GATE -- language diagnostics refuse for the RIGHT reason ===" as *u8)
102 let counts: *i64 = sys_mmap(GL_SCRATCH) as *i64
103 counts[0] = 0
104 counts[1] = 0
105 let pb: *u8 = sys_mmap(LDG_PB)
106 var po: i64 = 0
107
108 // ---- REFUSALS: each asserts the SPECIFIC rule, via its capability slug where it has one ----
109 po = ldg_refuse("float-binding-refused-by-name" as *u8,
110 "runtime/nx_probe_caplim_float.nx" as *u8,
111 "capability=float-int-boundary" as *u8, counts, ctr, pb, po)
112 po = ldg_refuse("float-varinit-and-assign-refused-by-name" as *u8,
113 "runtime/nx_probe_caplim_fassign.nx" as *u8,
114 "capability=float-int-boundary" as *u8, counts, ctr, pb, po)
115 po = ldg_refuse("float-memory-stores-refused-by-name" as *u8,
116 "runtime/nx_probe_caplim_fmem.nx" as *u8,
117 "capability=float-int-boundary" as *u8, counts, ctr, pb, po)
118 po = ldg_refuse("param-cap-refused-by-name" as *u8,
119 "runtime/nx_probe_caplim_args.nx" as *u8,
120 "capability=call-arity-ceiling" as *u8, counts, ctr, pb, po)
121 po = ldg_refuse("const-overshift-refused-by-name" as *u8,
122 "runtime/nx_probe_ub_shift.nx" as *u8,
123 "capability=shift-count-range" as *u8, counts, ctr, pb, po)
124 // statement-break family: these have no slug (not capability limits), so they are pinned to
125 // the phrase their own rule prints -- which is exactly the discrimination a bare CCFAIL lacks.
126 // RE-POINTED 2026-09-02 (debt 1788309098): LN15 tok_line_continuation (2026-08-25) changed the
127 // CONTRACT for the two multi-line witnesses -- a line opening with a binary operator now JOINS
128 // the expression above it, so nx_probe_mlop_live / nx_probe_mlneg_live are CORRECT PROGRAMS and
129 // sit among the acceptances below (their VALUE is proven by nx_linecont_gate; here they are the
130 // control a refusing compiler cannot pass). Neither RULE changed; each keeps a witness that
131 // LN15 cannot join into anything correct. A gate whose fixture stops reaching the condition is
132 // RED about the fixture, not the rule -- this read 9/11 for seven days for exactly that reason.
133 po = ldg_refuse("operator-at-expression-start-refused-by-reason" as *u8,
134 "runtime/nx_probe_opstart_live.nx" as *u8,
135 "an operator starts this expression" as *u8, counts, ctr, pb, po) // `a + + b`: the second + reaches parse_primary
136 po = ldg_refuse("discarded-pure-expression-refused-by-reason" as *u8,
137 "runtime/nx_probe_lone_operator.nx" as *u8,
138 "computes a value and never uses it" as *u8, counts, ctr, pb, po) // `- a` as the FIRST statement of a block: nothing above it to join
139 po = ldg_refuse("let-reassign-speaks-the-voice" as *u8,
140 "runtime/nx_probe_voice_live.nx" as *u8,
141 "was declared with 'let'" as *u8, counts, ctr, pb, po)
142
143 // ---- ACCEPTANCES: the discrimination control ----
144 // Without these a compiler that refused EVERY input would score 8/8 above.
145 po = ldg_accept("paren-cast-index-compiles" as *u8,
146 "runtime/nx_probe_castidx_live.nx" as *u8, counts, ctr, pb, po)
147 po = ldg_accept("chained-casts-compile" as *u8,
148 "runtime/nx_probe_castchain_live.nx" as *u8, counts, ctr, pb, po)
149 po = ldg_accept("crash-guard-witness-compiles" as *u8,
150 "runtime/nx_probe_crash_live.nx" as *u8, counts, ctr, pb, po)
151 // LN15 controls: both former must-refuse witnesses now JOIN and must COMPILE (the value they
152 // compute -- 3 and -1 -- is asserted at run time by nx_linecont_gate, rostered beside this one).
153 po = ldg_accept("leading-plus-continuation-joins-and-compiles" as *u8,
154 "runtime/nx_probe_mlop_live.nx" as *u8, counts, ctr, pb, po)
155 po = ldg_accept("leading-minus-continuation-joins-and-compiles" as *u8,
156 "runtime/nx_probe_mlneg_live.nx" as *u8, counts, ctr, pb, po)
157
158 // Durable evidence first (a gate whose RED lands in a vacuum is not a measurement), then the
159 // buffered FAIL rows with their exit/want detail, then the sanctioned verdict LAST -- gv's
160 // judge anchors BY POSITION, so nothing may print after it.
161 gl_log("knowledge/status/langdiag_gate.log" as *u8,
162 "NX-LANGDIAG-GATE" as *u8, counts)
163 if po > 0 { sys_write(1, pb, po) }
164 return gv_verdict("nx_langdiag_gate" as *u8, ctr,
165 "subject=_offc/nx_cc_sovereign.elf; each refusal pinned to its own rule phrase or capability slug; acceptances are the discrimination control; bite-proven both directions 2026-08-14; statement-break witnesses re-pointed to the LN15 contract 2026-09-02" as *u8)
166}
167