nx_wgsl_gate.nx source
↩ module page · 752 lines · 77340 B
1// nx_wgsl_gate.nx -- IS THE SHADER BACKEND REAL, OR A RUBBER STAMP?
2//
3// SUBJECT: ./nx_wgsl.elf by default, or ./nx_wgsl.sov.elf.new with `staged`.
4// Both modes execute the actual binary; e2e fork, never an in-process re-derive -- an
5// in-process gate would prove the SOURCE compiles, not that the SHIPPED artifact behaves).
6//
7// THE PRE-DECLARED ACCEPT RULE (written before the backend was built): the SAME NishiLang source
8// compiled to BOTH dialects must produce the SAME RESULT. On this box that cannot be proven at the
9// pixel level -- headless WebGPU wedges inside requestAdapter/createShaderModule (measured; it is
10// why nx_game_page_emit carries a GPU_BOOT_MS race at all) -- so equivalence is asserted at the
11// EMITTED-IR level and the pixel gap is DECLARED, never papered over:
12// * TRACE IDENTITY: each backend records the node ids it emits, in order. Two backends that
13// consumed the same source completely produce identical traces.
14// * NON-VACUITY: a module with one statement removed must NOT trace the same. Without this leg
15// trace identity would be satisfied by two backends that both emit nothing.
16// * REFUSAL: a construct outside the covered subset must refuse BY NAME. A silent
17// mistranslation in a shader backend compiles, links, runs, and draws the wrong picture.
18// * DIALECT SEPARATION: the GLSL output must carry GLSL's own spelling and the WGSL output
19// WGSL's -- proving each backend emitted its dialect rather than copying the other.
20// * SHIPPING EQUIVALENCE: the emitted GLSL must carry the same operators and operands as the
21// hand-written VSH that ships in nx_game_page_emit today, which is the migration reference.
22// * DECLARATION REFUSALS (S1, 2026-09-04): a texture-typed uniform, a K_ATTRIB and a fragment K_VARY
23// each REFUSE BY NAME in WGSL (they used to be emitted wrong with no refusal), and a scalar uniform
24// is still ADMITTED by the same pass -- the positive control a deny-guard must carry.
25// * UNIFORM QUALIFICATION (S2, 2026-09-04): WGSL reads a uniform as `u.<name>` (it lives in struct U),
26// GLSL reads it bare; a parameter or local of the same name shadows the uniform and stays bare in
27// both. Trace identity must survive a uniform being in play.
28// * TEXTURES ARE THEIR OWN KIND (S3, 2026-09-04): K_TEXTURE emits a @group/@binding var OUTSIDE struct U
29// in WGSL and a sampler uniform in GLSL, read bare in both; the deprecated texture-typed K_UNIFORM
30// refuses in BOTH dialects naming K_TEXTURE; texture_2d<f32> and a binding collision refuse by name.
31// * DERIVED FRAGMENT SIGNATURE (S4, 2026-09-04): a sir_param_position parameter yields
32// `@fragment fn main(@builtin(position) pos:vec4f)->@location(0) vec4f{` and GLSL reads it as gl_FragCoord;
33// zero parameters derive to the old literal exactly; a position READ with no declared parameter and a
34// plain (unbound) fragment parameter refuse by name -- an undeclared input is never a placeholder.
35//
36// WHAT THIS GATE DOES NOT MEASURE, STATED SO IT CANNOT BE MISREAD: no tooth renders a frame.
37// GREEN here means the two dialects are emitted from one source and agree structurally. It does
38// NOT mean a GPU drew the same pixels from both. That is nx_wgsl_pixel_gate, and it is OWED.
39
40import "nx_syscalls.nx"
41import "nx_gate_verdict.nx"
42import "nx_gatekit_lib.nx"
43
44const WGG_ELF: *u8 = "./nx_wgsl.elf"
45// Capture ceiling: the subject prints two shader texts plus a summary line. 64 KiB is two orders
46// of magnitude above the measured 310-byte emission and is a REFUSAL bound, not a silent cap --
47// gk_run_capture reports the byte count and the teeth below bind to it.
48// S12c-6 (2026-09-05): the `cast` verb now prints TWO modules (vertex + fragment) in TWO dialects; each module's emission is
49// bounded by the subject's own WG_EMIT_CAP (SIR_MAXNODE*16 = 262,144), so four times that is a ceiling the subject cannot
50// exceed -- still a REFUSAL bound (gk_run_capture reports the count), never a silent cap. 65,536 would have truncated the full
51// fragment (34 KB of hand GLSL x 2 dialects + the vertex pair) and reported the prefix as the whole.
52const WGG_CAP: i64 = 1048576
53// R-F KAT (2026-09-04): THE SHIPPING PAGE PACKER'S OWN NUMBERS, read off nx_game_page_emit's gpe_emit_webgpu --
54// it packs 96 floats into struct U, writes pal from float index 28 and palf from float index 76. The derived
55// layout must reproduce them as byte offsets (index times 4); they are known answers from the artifact the
56// layout serves, not thresholds chosen here.
57const WGG_PACKER_FLOATS: i64 = 96
58const WGG_PACKER_PAL_F: i64 = 28
59const WGG_PACKER_PALF_F: i64 = 76
60const WGG_FLOAT_BYTES: i64 = 4
61// THE REFUSAL TEXTS THE S1 TEETH ASSERT, exactly as `nx_wgsl decls` prints them (`<label>_named=<refusal>`).
62// Keyed on the probe LABEL so the tooth reads the refusal of ITS probe, and on the rule's own opening
63// words so a refusal that fired for the WRONG reason cannot score it.
64const WGG_R_TEXUNIFORM: *u8 = "texuniform_named=wgsl: texture-typed uniform"
65// S6 2026-09-05: fixture attribute renamed apos->aP (the real cast name; apos:vec3f contained the
66// substring pos:vec3f and inflated the member-balance neg-control). Closure bump: a prior build served a
67// stale cached artifact (staged apos, not aP) despite a changed src -- this comment forces a real compile.
68const WGG_R_ATTRIB: *u8 = "attrib_named=wgsl: vertex attribute declaration (K_ATTRIB)"
69const WGG_R_FRAGVARY: *u8 = "fragvary_named=wgsl: varying declaration (K_VARY) reached in a fragment stage"
70// S3: the texture contract bytes and refusals, exactly as `nx_wgsl decls` prints them for shsrc_tex_plain
71// (uniform scale, texture vox, fn vox_at). WGG_TEX_LAYOUT is ONE contiguous string -- struct U holding only
72// the scalar, its binding line, then the texture var -- so "outside struct U" and "struct U does not contain
73// it" are proven by adjacency, not by two independent contains-checks a reordering could wave through.
74const WGG_TEX_LAYOUT: *u8 = "struct U{\nscale:f32,\n}\n@group(0)@binding(0)var<uniform> u:U;\n@group(0)@binding(1)var vox:texture_3d<u32>;\n"
75const WGG_TEX_WGSL_DECL: *u8 = "@group(0)@binding(1)var vox:texture_3d<u32>;\n"
76const WGG_TEX_GLSL_DECL: *u8 = "uniform highp usampler3D vox;\n"
77const WGG_TEX_WGSL_READ: *u8 = "return textureLoad(vox,vec3i(x,y,z),0).x;\n"
78const WGG_TEX_GLSL_READ: *u8 = "return texelFetch(vox,ivec3(x,y,z),0).x;\n"
79const WGG_R_TEXUNIFORM_GL: *u8 = "texuniform_glsl_named=glsl: texture-typed uniform"
80const WGG_R_TEX2D_WG: *u8 = "tex2d_wgsl_named=wgsl: texture type outside the covered subset"
81const WGG_R_TEX2D_GL: *u8 = "tex2d_glsl_named=glsl: texture type outside the covered subset"
82const WGG_R_TEXCOLLIDE: *u8 = "texcollide_named=wgsl: derived texture binding collides"
83// S4: the derived fragment signature and its reads, exactly as `nx_wgsl decls` prints them for shsrc_frag_pos,
84// the zero-parameter control, and the refusals for an undeclared / unbound input.
85const WGG_FRAGPOS_SIG: *u8 = "@fragment fn main(@builtin(position) pos:vec4f)->@location(0) vec4f{\n"
86const WGG_FRAGPOS_WGSL_BODY: *u8 = "return vec4f(pos.x,pos.y,0.0,1.0);\n"
87const WGG_FRAGPOS_GLSL_BODY: *u8 = "vec4(gl_FragCoord.x,gl_FragCoord.y,0.0,1.0)"
88const WGG_FRAGCONST_SIG: *u8 = "@fragment fn main()->@location(0) vec4f{\n"
89const WGG_R_FRAGUNDECL: *u8 = "fragundecl_named=wgsl: @builtin(position) read without a declared entry parameter"
90const WGG_R_FRAGPLAIN_WG: *u8 = "fragplain_wgsl_named=wgsl: fragment entry parameter that is not the @builtin(position) input"
91const WGG_R_FRAGPLAIN_GL: *u8 = "fragplain_glsl_named=glsl: entry-point parameter that is not the @builtin(position) input"
92// S5 (2026-09-04): THE FRAGMENT OUTPUT. Each of these is ONE CONTIGUOUS RUN, so adjacency proves the shape
93// -- a declaration that drifted away from its main(), or a return that survived beside the assignment,
94// cannot score them the way two independent contains-checks could.
95// The GLSL run is the whole program: header, the declared output, and an entry that ASSIGNS rather than
96// returns. Before S5 the middle line did not exist and the last was `return vec4(1.0,0.0,0.0,1.0);` --
97// a value returned from a void function, against no declaration: invalid GLSL ES 3.00 on both counts.
98const WGG_FRAGOUT_GLSL: *u8 = "out vec4 fc;\nvoid main(){\nfc=vec4(1.0,0.0,0.0,1.0);\n}\n"
99const WGG_FRAGOUT_GLSL_DECL: *u8 = "out vec4 fc;\n"
100// The WGSL run at location 0 must reproduce the literal this line used to carry, BYTE FOR BYTE.
101const WGG_FRAGOUT_WGSL: *u8 = "@fragment fn main()->@location(0) vec4f{\nreturn vec4f(1.0,0.0,0.0,1.0);\n}\n"
102// A NON-ZERO location proves the number is DATA and not the constant 0 it was spelled as.
103const WGG_FRAGLOC2_GLSL: *u8 = "layout(location=2) out vec4 fc;\n"
104const WGG_FRAGLOC2_WGSL: *u8 = "@fragment fn main()->@location(2) vec4f{\n"
105// The discard-only positive control: no output declared, and BOTH backends admit it.
106const WGG_FRAGDISCARD_WGSL: *u8 = "@fragment fn main(){\ndiscard;\n}\n"
107const WGG_FRAGDISCARD_GLSL: *u8 = "void main(){\ndiscard;\n}\n"
108const WGG_R_FRAGNOOUT_GL: *u8 = "fragnoout_glsl_named=glsl: fragment entry returns a value with no declared fragment output"
109const WGG_R_FRAGNOOUT_WG: *u8 = "fragnoout_wgsl_named=wgsl: fragment entry returns a value with no declared fragment output"
110const WGG_R_VERTFRAGOUT_GL: *u8 = "vertfragout_glsl_named=glsl: fragment output declaration (K_FRAGOUT) outside a fragment stage"
111const WGG_R_VERTFRAGOUT_WG: *u8 = "vertfragout_wgsl_named=wgsl: fragment output declaration (K_FRAGOUT) outside a fragment stage"
112const WGG_R_TWOOUT_GL: *u8 = "fragtwoout_glsl_named=glsl: more than one fragment output declared"
113const WGG_R_TWOOUT_WG: *u8 = "fragtwoout_wgsl_named=wgsl: more than one fragment output declared"
114// S5 residual (b): the sampled read. WGSL refuses (no sampler binding); GLSL EMITS, because its texture()
115// needs no separate sampler object -- the mirror image of K_STORAGE, which GLSL refuses and WGSL emits.
116const WGG_R_TEXSAMPLE_WG: *u8 = "texsample_wgsl_named=wgsl: sampled texture read (E_TEXSAMPLE)"
117const WGG_TEXSAMPLE_GLSL: *u8 = "return texture(vox,uv);\n"
118
119func wgg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
120
121func wgg_has(buf: *u8, n: i64, ned: *u8) -> i64 {
122 let m: i64 = wgg_slen(ned)
123 if m == 0 { return 0 }
124 var i: i64 = 0
125 while i + m <= n {
126 var j: i64 = 0
127 var ok: i64 = 1
128 while j < m {
129 if buf[i+j] != ned[j] { ok = 0; j = m } else { j = j + 1 }
130 }
131 if ok == 1 { return 1 }
132 i = i + 1
133 }
134 return 0
135}
136
137// how many times ned occurs in buf[0..n) -- the S2 teeth need "exactly once" (the qualifier appears in the
138// WGSL text and never leaks into the GLSL text printed beside it), which a presence check cannot say.
139func wgg_count(buf: *u8, n: i64, ned: *u8) -> i64 {
140 let m: i64 = wgg_slen(ned)
141 if m == 0 { return 0 }
142 var c: i64 = 0
143 var i: i64 = 0
144 while i + m <= n {
145 var j: i64 = 0
146 var ok: i64 = 1
147 while j < m {
148 if buf[i+j] != ned[j] { ok = 0; j = m } else { j = j + 1 }
149 }
150 if ok == 1 { c = c + 1 }
151 i = i + 1
152 }
153 return c
154}
155
156// first integer following the LAST occurrence of key -- anchored on the key, never on position,
157// so a value appearing in the prose above cannot be read as the answer.
158func wgg_num_after(buf: *u8, n: i64, key: *u8) -> i64 {
159 let m: i64 = wgg_slen(key)
160 var at: i64 = 0 - 1
161 var i: i64 = 0
162 while i + m <= n {
163 // S5 (2026-09-04): THE KEY MUST START A LINE. This search was an UNANCHORED substring match that
164 // kept the LAST hit, so any probe label that is a SUFFIX of another label silently read the WRONG
165 // probe's number -- "fragout_glsl_rc=" matches inside "vertfragout_glsl_rc=-1", and the tooth asking
166 // "did the fragout probe emit?" was answered -1 by the vertex-stage REFUSAL probe. MEASURED the
167 // moment both labels existed: 100/102, two teeth failing against a subject that was in fact correct
168 // (the emission was 113 bytes). The failure direction is the dangerous one too -- a suffix label
169 // whose sibling REFUSES reads as a refusal, so a working feature reports as broken and a broken one
170 // could report as working. `nx_wgsl decls` prints every "<label>_rc=" and "<label>_trace_equal=" at
171 // a line start, so this anchor is exact and no pre-existing tooth's reading moves. The colliding
172 // pair is kept in the probe set ON PURPOSE and asserted below: it is the live neg-control for this.
173 var anch: i64 = 0
174 if i == 0 { anch = 1 } else { if buf[i-1] == (10 as u8) { anch = 1 } }
175 if anch == 1 {
176 var j: i64 = 0
177 var ok: i64 = 1
178 while j < m {
179 if buf[i+j] != key[j] { ok = 0; j = m } else { j = j + 1 }
180 }
181 if ok == 1 { at = i + m }
182 }
183 i = i + 1
184 }
185 if at < 0 { return 0 - 1 }
186 var v: i64 = 0
187 var seen: i64 = 0
188 var neg: i64 = 0
189 if at < n { if buf[at] == (45 as u8) { neg = 1; at = at + 1 } }
190 while at < n {
191 let c: i64 = buf[at] as i64
192 if c >= 48 { if c <= 57 { v = v*10 + (c - 48); seen = 1; at = at + 1 } else { at = n } } else { at = n }
193 }
194 if seen == 0 { return 0 - 1 }
195 if neg == 1 { return 0 - v }
196 return v
197}
198
199// S12c-4: a needle that must carry a bang -- nx_cc refuses '!' inside a literal, so the fixture is written with '~' (126)
200// and every tilde becomes '!' (33) at run time, the byte the emitted shader actually carries.
201const WGG_C_TILDE: i64 = 126
202const WGG_C_BANG: i64 = 33
203func wgg_bang(s: *u8) -> *u8 {
204 var n: i64 = 0
205 while s[n] != (0 as u8) { n = n + 1 }
206 let o: *u8 = sys_mmap(n + 1)
207 var i: i64 = 0
208 while i < n {
209 var c: i64 = s[i] as i64
210 if c == WGG_C_TILDE { c = WGG_C_BANG }
211 o[i] = c as u8
212 i = i + 1
213 }
214 o[n] = 0 as u8
215 return o
216}
217
218func main(argc: i64, argv: *i64) -> i64 {
219 var subject: *u8 = WGG_ELF
220 if argc > 1 {
221 let mode: *u8 = argv[1] as *u8
222 if argc != 2 || wgg_slen(mode) != wgg_slen("staged" as *u8) || wgg_has(mode, wgg_slen(mode), "staged" as *u8) == 0 {
223 gv_puts("usage: nx_wgsl_gate [staged]; invalid selection, no subject executed\n" as *u8)
224 return 2
225 }
226 subject = "./nx_wgsl.sov.elf.new" as *u8
227 }
228 gv_puts("shader subject=" as *u8); gv_puts(subject); gv_puts("\n" as *u8)
229 let ctr: *i64 = gv_ctr()
230 gv_puts("nx_wgsl_gate -- ONE NishiLang source, TWO dialects, and the equivalence is measured\n\n" as *u8)
231
232 let buf: *u8 = sys_mmap(WGG_CAP)
233 let bl: *i64 = sys_mmap(16) as *i64
234 bl[0] = 0
235 // COMPOSE the proven subprocess primitive. A hand-rolled pipe/fork/wait DEADLOCKED a sibling
236 // gate in production this same day (pid 2240, 50+ min in pipe_wait); the banked law is that
237 // fixtures and subprocess come from nx_gatekit_lib. Never re-roll this.
238 let rc: i64 = gk_run_capture(subject, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, buf, WGG_CAP, bl)
239 let n: i64 = bl[0]
240 gv_puts(" subject rc=" as *u8); gv_num(rc); gv_puts(" bytes=" as *u8); gv_num(n); gv_puts("\n" as *u8)
241 gv_check("subject-ran-and-produced-output (127 = elf absent, the stale-offc tell)" as *u8, rc == 0, ctr)
242 var got: i64 = 0
243 if n > 0 { got = 1 }
244 gv_check("subject-emitted-bytes (a silent subject proves nothing)" as *u8, got, ctr)
245 if got == 0 { return gv_verdict("NX-WGSL" as *u8, ctr, "the backend produced no output at all" as *u8) }
246
247 // ---- the GLSL dialect is really GLSL --------------------------------------------------
248 gv_check("glsl-carries-its-version-pragma" as *u8, wgg_has(buf, n, "#version 300 es" as *u8), ctr)
249 gv_check("glsl-uses-gl_VertexID (GLSL's own vertex-index spelling)" as *u8, wgg_has(buf, n, "gl_VertexID" as *u8), ctr)
250 gv_check("glsl-ASSIGNS-gl_Position" as *u8, wgg_has(buf, n, "gl_Position=" as *u8), ctr)
251
252 // ---- the WGSL dialect is really WGSL, and STRUCTURALLY different -----------------------
253 gv_check("wgsl-declares-a-vertex-entry-point" as *u8, wgg_has(buf, n, "@vertex fn" as *u8), ctr)
254 gv_check("wgsl-RETURNS-builtin-position (not an assignment -- a real structural difference)" as *u8, wgg_has(buf, n, "->@builtin(position)" as *u8), ctr)
255 gv_check("wgsl-uses-its-own-type-spelling (vec4f, never vec4)" as *u8, wgg_has(buf, n, "vec4f(" as *u8), ctr)
256 gv_check("wgsl-suffixes-its-unsigned-shift-amount (1u -- GLSL must not)" as *u8, wgg_has(buf, n, "<<1u" as *u8), ctr)
257
258 // ---- SHIPPING EQUIVALENCE: same operators and operands as the hand-written VSH ---------
259 // The GLSL that ships today is:
260 // void main(){vec2 v=vec2((gl_VertexID<<1)&2,gl_VertexID&2);gl_Position=vec4(v*2.-1.,0.,1.);}
261 // The emitted form is explicit where the hand form leaned on constructor conversion, so this
262 // is SEMANTIC equivalence over the same operator set -- stated exactly, not overclaimed.
263 gv_check("emitted-glsl-keeps-the-shipped-shift (<<1)" as *u8, wgg_has(buf, n, "<<1)" as *u8), ctr)
264 gv_check("emitted-glsl-keeps-the-shipped-mask (&2)" as *u8, wgg_has(buf, n, "&2)" as *u8), ctr)
265 gv_check("emitted-glsl-keeps-the-shipped-vec2-local" as *u8, wgg_has(buf, n, "vec2 v=vec2(" as *u8), ctr)
266 gv_check("emitted-glsl-keeps-the-shipped-clip-transform (*2.0)-1.0" as *u8, wgg_has(buf, n, "(v*2.0)-1.0" as *u8), ctr)
267
268 // ---- THE ACCEPT RULE: trace identity, and its non-vacuity ------------------------------
269 let gnodes: i64 = wgg_num_after(buf, n, "glsl_nodes=" as *u8)
270 let wnodes: i64 = wgg_num_after(buf, n, "wgsl_nodes=" as *u8)
271 let teq: i64 = wgg_num_after(buf, n, "trace_equal=" as *u8)
272 let cnodes: i64 = wgg_num_after(buf, n, "corrupt_nodes=" as *u8)
273 gv_puts(" glsl_nodes=" as *u8); gv_num(gnodes)
274 gv_puts(" wgsl_nodes=" as *u8); gv_num(wnodes)
275 gv_puts(" trace_equal=" as *u8); gv_num(teq)
276 gv_puts(" corrupt_nodes=" as *u8); gv_num(cnodes); gv_puts("\n" as *u8)
277 // BOUND IN THE CONDITION, so an empty emit cannot pass: the node count must be positive AND
278 // equal across backends. A gate that only asked 'are they equal?' would pass on 0 == 0.
279 var same: i64 = 0
280 if gnodes > 0 { if gnodes == wnodes { same = 1 } }
281 gv_check("both-backends-consumed-the-same-source (node counts equal AND positive)" as *u8, same, ctr)
282 gv_check("trace-identity-element-wise (same node ids, same order)" as *u8, teq == 1, ctr)
283 // NON-VACUITY: drop one statement and the trace MUST change. This is what makes the tooth
284 // above load-bearing rather than decorative.
285 var nonvac: i64 = 0
286 if cnodes > 0 { if cnodes != gnodes { nonvac = 1 } }
287 gv_check("neg-control-a-statement-dropped-CHANGES-the-trace (equality is not vacuous)" as *u8, nonvac, ctr)
288
289 // ---- REFUSAL: outside the covered subset, refuse BY NAME -------------------------------
290 let urc: i64 = wgg_num_after(buf, n, "uncovered_rc=" as *u8)
291 gv_puts(" uncovered_rc=" as *u8); gv_num(urc); gv_puts("\n" as *u8)
292 gv_check("neg-control-uncovered-construct-REFUSES (rc=-1, never a guess)" as *u8, urc == (0 - 1), ctr)
293 gv_check("the-refusal-NAMES-the-construct (a named refusal is a contract)" as *u8, wgg_has(buf, n, "outside the covered subset" as *u8), ctr)
294 gv_check("neg-control-did-not-fire-on-the-GOOD-module (no REFUSED on the real shader)" as *u8, wgg_has(buf, n, "REFUSED: " as *u8) == 0, ctr)
295
296 // ---- S1 (2026-09-04): DECLARATION MISTRANSLATIONS ARE NAMED REFUSALS, AND THE GUARD STILL ADMITS ----
297 // Three outputs used to be confidently wrong with NO refusal: a texture-typed uniform emitted INSIDE
298 // struct U, a K_ATTRIB dropped to zero bytes, a fragment K_VARY emitted as a comment. `nx_wgsl decls`
299 // runs each and prints the refusal VERBATIM; each tooth asserts rc == -1 AND which rule fired. A
300 // deny-guard that has only ever refused is unverified, so the same run carries a POSITIVE control --
301 // a scalar uniform that MUST be admitted: a guard that refuses everything passes every negative test.
302 let db: *u8 = sys_mmap(WGG_CAP)
303 bl[0] = 0
304 let drc: i64 = gk_run_capture(subject, "decls" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, db, WGG_CAP, bl)
305 let dn: i64 = bl[0]
306 gv_puts(" decls rc=" as *u8); gv_num(drc); gv_puts(" bytes=" as *u8); gv_num(dn); gv_puts("\n" as *u8)
307 gv_check("decls-verb-ran (rc=0)" as *u8, drc == 0, ctr)
308 gv_check("decls-verb-emitted-bytes" as *u8, dn > 0, ctr)
309 // S3 (2026-09-04) REWROTE THE S1 TEXTURE TOOTH INTO COVERAGE. A texture is now its own kind (K_TEXTURE,
310 // sir_texture). The deprecated form -- a texture-typed K_UNIFORM -- still refuses, in BOTH dialects, naming
311 // K_TEXTURE as the remedy; the covered form is emitted OUTSIDE struct U in WGSL (proven by ADJACENCY:
312 // struct U, its binding, then the texture var, one contiguous string) and as a sampler uniform in GLSL,
313 // is read bare in both, keeps trace identity, and every other texture type refuses by name.
314 gv_check_eq("neg-control-texture-typed-K_UNIFORM-still-REFUSES-in-wgsl (rc=-1; the remedy is K_TEXTURE)" as *u8, wgg_num_after(db, dn, "texuniform_rc=" as *u8), 0 - 1, ctr)
315 gv_check("neg-control-texture-typed-K_UNIFORM-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TEXUNIFORM), ctr)
316 gv_check_eq("neg-control-texture-typed-K_UNIFORM-REFUSES-in-glsl-too (rc=-1; both backends cover the same source)" as *u8, wgg_num_after(db, dn, "texuniform_glsl_rc=" as *u8), 0 - 1, ctr)
317 gv_check("neg-control-texture-typed-K_UNIFORM-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TEXUNIFORM_GL), ctr)
318 gv_check("K_TEXTURE-wgsl-probe-emitted (tex_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex_wgsl_rc=" as *u8) > 0, ctr)
319 gv_check("K_TEXTURE-glsl-probe-emitted (tex_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex_glsl_rc=" as *u8) > 0, ctr)
320 gv_check("K_TEXTURE-wgsl-emits-a-binding-var (group 0, derived binding 1)" as *u8, wgg_has(db, dn, WGG_TEX_WGSL_DECL), ctr)
321 gv_check("K_TEXTURE-is-OUTSIDE-struct-U-and-struct-U-holds-only-the-scalar (contiguous layout KAT)" as *u8, wgg_has(db, dn, WGG_TEX_LAYOUT), ctr)
322 gv_check_eq("neg-control-struct-U-member-spelling-of-the-texture-is-ABSENT (count 0)" as *u8, wgg_count(db, dn, "vox:texture_3d<u32>," as *u8), 0, ctr)
323 gv_check("K_TEXTURE-glsl-emits-the-sampler-uniform" as *u8, wgg_has(db, dn, WGG_TEX_GLSL_DECL), ctr)
324 gv_check("K_TEXTURE-wgsl-reads-it-with-textureLoad-and-the-ident-BARE" as *u8, wgg_has(db, dn, WGG_TEX_WGSL_READ), ctr)
325 gv_check("K_TEXTURE-glsl-reads-it-with-texelFetch" as *u8, wgg_has(db, dn, WGG_TEX_GLSL_READ), ctr)
326 gv_check_eq("neg-control-the-texture-ident-is-NEVER-u.-qualified (count of u.vox is 0)" as *u8, wgg_count(db, dn, "u.vox" as *u8), 0, ctr)
327 gv_check_eq("K_TEXTURE-trace-identity-holds-across-dialects (tex_trace_equal)" as *u8, wgg_num_after(db, dn, "tex_trace_equal=" as *u8), 1, ctr)
328 // GE54 (2026-09-05): the four `texture_2d REFUSES` neg-controls were RETIRED here -- texture_2d<f32> is now a
329 // SUPPORTED sampled texture (GLSL sampler2D, WGSL texture + companion sampler), proven by the tex2d teeth above,
330 // so asserting it refuses is asserting the old world. The refusal contract now fires only for texture types
331 // outside {T_TEX3U, T_TEX2F}; WGG_R_TEX2D_WG/GL are kept for the record. The storage/texture collision below
332 // still refuses and its neg-control stands.
333 gv_check_eq("neg-control-derived-texture-binding-on-a-storage-binding-REFUSES (rc=-1)" as *u8, wgg_num_after(db, dn, "texcollide_rc=" as *u8), 0 - 1, ctr)
334 gv_check("neg-control-collision-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TEXCOLLIDE), ctr)
335
336 // ---- S4 (2026-09-04): THE FRAGMENT ENTRY SIGNATURE IS DERIVED FROM THE DECLARED PARAMETERS ----
337 // It was the literal "()->@location(0) vec4f{" whatever the function declared, and a position READ
338 // emitted the placeholder identifier POSITION. Now the single covered input, @builtin(position), is
339 // derived from a sir_param_position parameter in both dialects; the zero-parameter case derives to the
340 // old literal exactly (control); an undeclared read and an unbound parameter refuse by name.
341 gv_check("fragpos-wgsl-probe-emitted (fragpos_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragpos_wgsl_rc=" as *u8) > 0, ctr)
342 gv_check("fragpos-glsl-probe-emitted (fragpos_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragpos_glsl_rc=" as *u8) > 0, ctr)
343 gv_check("fragment-entry-signature-is-DERIVED-from-the-position-param (KAT)" as *u8, wgg_has(db, dn, WGG_FRAGPOS_SIG), ctr)
344 gv_check("fragment-body-reads-the-position-param-BARE (pos.x, pos.y)" as *u8, wgg_has(db, dn, WGG_FRAGPOS_WGSL_BODY), ctr)
345 gv_check("glsl-reads-the-declared-position-input-as-gl_FragCoord" as *u8, wgg_has(db, dn, WGG_FRAGPOS_GLSL_BODY), ctr)
346 gv_check_eq("fragpos-trace-identity-holds-across-dialects (fragpos_trace_equal)" as *u8, wgg_num_after(db, dn, "fragpos_trace_equal=" as *u8), 1, ctr)
347 gv_check("control-zero-parameter-fragment-derives-to-the-old-literal-EXACTLY" as *u8, wgg_has(db, dn, WGG_FRAGCONST_SIG), ctr)
348 gv_check_eq("neg-control-position-READ-without-a-declared-param-REFUSES (rc=-1)" as *u8, wgg_num_after(db, dn, "fragundecl_rc=" as *u8), 0 - 1, ctr)
349 gv_check("neg-control-undeclared-input-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGUNDECL), ctr)
350 gv_check_eq("neg-control-the-placeholder-identifier-POSITION-is-emitted-NOWHERE (count 0)" as *u8, wgg_count(db, dn, "POSITION" as *u8), 0, ctr)
351 gv_check_eq("neg-control-plain-fragment-param-REFUSES-in-wgsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragplain_wgsl_rc=" as *u8), 0 - 1, ctr)
352 gv_check("neg-control-plain-fragment-param-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGPLAIN_WG), ctr)
353 gv_check_eq("neg-control-plain-fragment-param-REFUSES-in-glsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragplain_glsl_rc=" as *u8), 0 - 1, ctr)
354 gv_check("neg-control-plain-fragment-param-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGPLAIN_GL), ctr)
355 gv_check("S6-K_ATTRIB-is-ADMITTED-in-wgsl (attrib_rc>0: a vertex attribute no longer refuses)" as *u8, wgg_num_after(db, dn, "attrib_rc=" as *u8) > 0, ctr)
356 gv_check("S6-vertex-attribute-emits-as-a-@location-entry-parameter (,@location(0) aP:vec3f)" as *u8, wgg_has(db, dn, ",@location(0) aP:vec3f" as *u8), ctr)
357 gv_check("S6-glsl-emits-the-attribute-module-scope (layout(location=0) in vec3 aP;)" as *u8, wgg_has(db, dn, "layout(location=0) in vec3 aP;" as *u8), ctr)
358 gv_check_eq("S6-attribute-trace-identity-holds-across-dialects (attrib_trace_equal)" as *u8, wgg_num_after(db, dn, "attrib_trace_equal=" as *u8), 1, ctr)
359 gv_check_eq("neg-control-K_ATTRIB-in-a-FRAGMENT-stage-REFUSES (attribfrag_rc=-1)" as *u8, wgg_num_after(db, dn, "attribfrag_rc=" as *u8), 0 - 1, ctr)
360 gv_check("neg-control-fragment-attribute-refusal-NAMES-ITS-RULE (outside a vertex stage)" as *u8, wgg_has(db, dn, "outside a vertex stage" as *u8), ctr)
361 gv_check("S7-fragment-K_VARY-is-ADMITTED (fragvary_rc>0: declared-but-unread still carries the struct parameter)" as *u8, wgg_num_after(db, dn, "fragvary_rc=" as *u8) > 0, ctr)
362 gv_check("S7-interstage-struct-emitted-with-the-reserved-position-member (struct VIO{@builtin(position) bpos:vec4f,@location(0) vcol:vec4f,)" as *u8, wgg_has(db, dn, "struct VIO{@builtin(position) bpos:vec4f,@location(0) vcol:vec4f," as *u8), ctr)
363 gv_check("S7-flat-int-varying-carries-@interpolate(flat) (@location(1) @interpolate(flat) vii:i32,})" as *u8, wgg_has(db, dn, "@location(1) @interpolate(flat) vii:i32,}" as *u8), ctr)
364 gv_check("S7-vertex-entry-RETURNS-the-struct-and-opens-var-vo (->VIO{ var vo:VIO;)" as *u8, wgg_has(db, dn, ")->VIO{\nvar vo:VIO;" as *u8), ctr)
365 gv_check("S7-varying-write-qualifies-vo. (vo.vii=7;)" as *u8, wgg_has(db, dn, "vo.vii=7;" as *u8), ctr)
366 gv_check("S7-position-assignment-lands-in-the-struct (vo.bpos=vec4f()" as *u8, wgg_has(db, dn, "vo.bpos=vec4f(" as *u8), ctr)
367 gv_check("S7-vertex-entry-closes-with-return-vo" as *u8, wgg_has(db, dn, "return vo;\n}" as *u8), ctr)
368 gv_check("S7-fragment-entry-TAKES-the-struct ((vin:VIO)->@location(0) vec4f{)" as *u8, wgg_has(db, dn, "(vin:VIO)->@location(0) vec4f{" as *u8), ctr)
369 gv_check("S7-varying-read-qualifies-vin. ((vin.vcol*f32(vin.vii)))" as *u8, wgg_has(db, dn, "(vin.vcol*f32(vin.vii))" as *u8), ctr)
370 gv_check("S7-glsl-keeps-module-scope-out-with-flat (flat out int vii;)" as *u8, wgg_has(db, dn, "flat out int vii;" as *u8), ctr)
371 gv_check("S7-glsl-fragment-input-spelled-in (in vec4 vcol;)" as *u8, wgg_has(db, dn, "in vec4 vcol;" as *u8), ctr)
372 gv_check_eq("S7-vertex-varying-trace-identity-holds-across-dialects (varyvs_trace_equal)" as *u8, wgg_num_after(db, dn, "varyvs_trace_equal=" as *u8), 1, ctr)
373 gv_check_eq("S7-fragment-varying-trace-identity-holds-across-dialects (varyfs_trace_equal)" as *u8, wgg_num_after(db, dn, "varyfs_trace_equal=" as *u8), 1, ctr)
374 gv_check_eq("neg-control-a-varying-named-bpos-REFUSES (varybpos_rc=-1; the reserved position member)" as *u8, wgg_num_after(db, dn, "varybpos_rc=" as *u8), 0 - 1, ctr)
375 gv_check("neg-control-bpos-refusal-NAMES-ITS-RULE (reserved @builtin(position) member)" as *u8, wgg_has(db, dn, "reserved @builtin(position) member" as *u8), ctr)
376 // ---- S8 (2026-09-05): THE NAMED CAST SAMPLER SET uAtl uNrm uJT uGD ----
377 gv_check("S8-cast-vertex-probe-emitted (cast8vs_rc>0)" as *u8, wgg_num_after(db, dn, "cast8vs_rc=" as *u8) > 0, ctr)
378 gv_check("S8-cast-fragment-probe-emitted (cast8fs_rc>0)" as *u8, wgg_num_after(db, dn, "cast8fs_rc=" as *u8) > 0, ctr)
379 gv_check("S8-joint-table-read-by-INTEGER-coordinate-in-the-vertex-entry (vo.vcol=textureLoad(uJT,vec2i(i32(aJ.x),0),0);)" as *u8, wgg_has(db, dn, "vo.vcol=textureLoad(uJT,vec2i(i32(aJ.x),0),0);" as *u8), ctr)
380 gv_check("S8-glsl-texelFetch-twin-over-ivec2 (vcol=texelFetch(uJT,ivec2(int(aJ.x),0),0);)" as *u8, wgg_has(db, dn, "vcol=texelFetch(uJT,ivec2(int(aJ.x),0),0);" as *u8), ctr)
381 gv_check("S8-2D-float-load-returns-a-vec4f-usable-as-position (vo.bpos=textureLoad(uGD,vec2i(0,0),0);)" as *u8, wgg_has(db, dn, "vo.bpos=textureLoad(uGD,vec2i(0,0),0);" as *u8), ctr)
382 gv_check("S8-glsl-position-from-the-garment-table (gl_Position=texelFetch(uGD,ivec2(0,0),0);)" as *u8, wgg_has(db, dn, "gl_Position=texelFetch(uGD,ivec2(0,0),0);" as *u8), ctr)
383 gv_check("S8-the-fourth-2D-texture-lands-at-DERIVED-binding-7 (two slots each: 1,3,5,7) (@binding(7)var uGD:texture_2d<f32>;)" as *u8, wgg_has(db, dn, "@binding(7)var uGD:texture_2d<f32>;" as *u8), ctr)
384 gv_check("S8-its-companion-sampler-follows-at-8 (uGD_s:sampler)" as *u8, wgg_has(db, dn, "@binding(8)var uGD_s:sampler;" as *u8), ctr)
385 gv_check("S8-atlas-and-normal-map-SAMPLED-in-the-fragment-through-companion-samplers ((textureSample(uAtl,uAtl_s,vin.vcol.xy)*textureSample(uNrm,uNrm_s,vin.vcol.xy)))" as *u8, wgg_has(db, dn, "(textureSample(uAtl,uAtl_s,vin.vcol.xy)*textureSample(uNrm,uNrm_s,vin.vcol.xy))" as *u8), ctr)
386 gv_check("S8-glsl-sampled-twin ((texture(uAtl,vcol.xy)*texture(uNrm,vcol.xy)))" as *u8, wgg_has(db, dn, "(texture(uAtl,vcol.xy)*texture(uNrm,vcol.xy))" as *u8), ctr)
387 gv_check_eq("S8-cast-vertex-trace-identity-holds-across-dialects (cast8vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast8vs_trace_equal=" as *u8), 1, ctr)
388 gv_check_eq("S8-cast-fragment-trace-identity-holds-across-dialects (cast8fs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast8fs_trace_equal=" as *u8), 1, ctr)
389 // S9 (2026-09-05): mat3 + derivatives + inverseSqrt. cast9vs = mat3x3f(aA,aB,aC) then M*aP into position; cast9fs =
390 // vec4(dpdx, dpdy, fwidth, inverseSqrt) over the varying. The IR names are the WGSL spellings; the GLSL arm re-spells
391 // dFdx/dFdy/inversesqrt through ONE map (gl_call_name), and the two leak controls prove the map is one-directional.
392 gv_check("S9-mat3-vertex-emits (cast9vs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast9vs_rc=" as *u8) > 0) as i64, ctr)
393 gv_check("S9-wgsl-mat3x3f-ctor-from-three-columns" as *u8, wgg_has(db, dn, "mat3x3f(aA,aB,aC)" as *u8), ctr)
394 gv_check("S9-glsl-mat3-ctor-from-three-columns" as *u8, wgg_has(db, dn, "mat3(aA,aB,aC)" as *u8), ctr)
395 gv_check("S9-mat-times-vec-is-plain-star-in-both-dialects" as *u8, (wgg_count(db, dn, "(M*aP)" as *u8) >= 2) as i64, ctr)
396 gv_check_eq("S9-mat3-vertex-trace-identity-holds-across-dialects (cast9vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast9vs_trace_equal=" as *u8), 1, ctr)
397 gv_check("S9-derivative-fragment-emits (cast9fs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast9fs_rc=" as *u8) > 0) as i64, ctr)
398 gv_check("S9-wgsl-spells-dpdx-dpdy-fwidth-inverseSqrt" as *u8, wgg_has(db, dn, "vec4f(dpdx(vin.vcol.x),dpdy(vin.vcol.y),fwidth(vin.vcol.z),inverseSqrt(vin.vcol.w))" as *u8), ctr)
399 gv_check("S9-glsl-spells-dFdx-dFdy-fwidth-inversesqrt" as *u8, wgg_has(db, dn, "vec4(dFdx(vcol.x),dFdy(vcol.y),fwidth(vcol.z),inversesqrt(vcol.w))" as *u8), ctr)
400 gv_check("neg-control-S9-glsl-spelling-never-leaks-into-wgsl" as *u8, (wgg_count(db, dn, "dFdx(vin." as *u8) == 0) as i64, ctr)
401 gv_check("neg-control-S9-wgsl-spelling-never-leaks-into-glsl" as *u8, (wgg_count(db, dn, "inverseSqrt(vcol." as *u8) == 0) as i64, ctr)
402 gv_check_eq("S9-derivative-fragment-trace-identity-holds-across-dialects (cast9fs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast9fs_trace_equal=" as *u8), 1, ctr)
403 // S12a (2026-09-05): the instance index. cast10vs = position = vec4(f32(instance_index), aP.y, 0, 1). WGSL binds
404 // @builtin(instance_index) ii:u32 ONLY in the module that reads it (M_USESII); every other decls module keeps its
405 // signature, which the count neg-control proves across the whole decls output. GLSL reads gl_InstanceID undeclared.
406 gv_check("S12a-instance-vertex-emits (cast10vs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast10vs_rc=" as *u8) > 0) as i64, ctr)
407 gv_check("S12a-wgsl-binds-instance_index-beside-vertex_index" as *u8, wgg_has(db, dn, "vi:u32,@builtin(instance_index) iidx:u32" as *u8), ctr)
408 gv_check("S12a-wgsl-reads-the-instance-as-i32(iidx) (S12c-2b: the builtin parameter is iidx so a module-level local ii cannot collide)" as *u8, wgg_has(db, dn, "f32(i32(iidx))" as *u8), ctr)
409 gv_check("S12a-glsl-reads-gl_InstanceID-undeclared" as *u8, wgg_has(db, dn, "float(gl_InstanceID)" as *u8), ctr)
410 gv_check_eq("neg-control-S12a-instance-binding-appears-in-exactly-one-decls-module" as *u8, wgg_count(db, dn, "@builtin(instance_index)" as *u8), 1, ctr)
411 gv_check_eq("S12a-instance-vertex-trace-identity-holds-across-dialects (cast10vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast10vs_trace_equal=" as *u8), 1, ctr)
412 // S12c-1 (2026-09-05): a VOID return inside the interstage-struct vertex entry. cast11vs writes vo.vcol then returns early
413 // under an if; WGSL must hand back the struct (`return vo;`), GLSL says `return;`, and nothing anywhere may emit `return ;`.
414 gv_check("S12c1-void-return-vertex-emits (cast11vs_rc>0)" as *u8, (wgg_num_after(db, dn, "cast11vs_rc=" as *u8) > 0) as i64, ctr)
415 gv_check("S12c1-wgsl-void-return-inside-VIO-entry-returns-the-struct" as *u8, wgg_has(db, dn, "vo.vcol=vec4f(0.0);\nreturn vo;\n}" as *u8), ctr)
416 gv_check("S12c1-glsl-void-return-is-bare" as *u8, wgg_has(db, dn, "vcol=vec4(0.0);\nreturn;\n}" as *u8), ctr)
417 gv_check_eq("neg-control-S12c1-no-dialect-emits-return-space-semicolon" as *u8, wgg_count(db, dn, "return ;" as *u8), 0, ctr)
418 gv_check_eq("S12c1-void-return-trace-identity-holds-across-dialects (cast11vs_trace_equal)" as *u8, wgg_num_after(db, dn, "cast11vs_trace_equal=" as *u8), 1, ctr)
419 gv_check("control-the-3D-u32-load-path-is-UNCHANGED-by-the-typed-result (textureLoad(vox,vec3i(x,y,z),0).x still emitted)" as *u8, wgg_has(db, dn, "textureLoad(vox,vec3i(x,y,z),0).x" as *u8), ctr)
420 let prc: i64 = wgg_num_after(db, dn, "posctl_wgsl_rc=" as *u8)
421 gv_puts(" posctl_wgsl_rc=" as *u8); gv_num(prc); gv_puts("\n" as *u8)
422 gv_check("positive-control-a-SCALAR-uniform-is-ADMITTED (wgsl rc>0: the guard does not refuse everything)" as *u8, prc > 0, ctr)
423 gv_check("positive-control-no-refusal-fired-on-it" as *u8, wgg_has(db, dn, "posctl_wgsl_named=NONE" as *u8), ctr)
424 gv_check("positive-control-struct-U-carries-the-scalar (scale:f32)" as *u8, wgg_has(db, dn, "scale:f32," as *u8), ctr)
425
426 // ---- S2 (2026-09-04): A UNIFORM READ IS `u.<name>` IN WGSL AND BARE IN GLSL; SHADOWING WINS ----
427 // Measured on the S1 positive control before S2: WGSL printed `v=(v*scale);` under `struct U{scale:f32,}`
428 // -- an undeclared identifier, no refusal. The same probe now carries both dialects' spelling, and two
429 // neg-controls prove the resolver reads SCOPE, not just the name: a local and a parameter named like a
430 // uniform must stay bare.
431 gv_check("wgsl-QUALIFIES-the-uniform-read (v=(v*u.scale);)" as *u8, wgg_has(db, dn, "v=(v*u.scale);" as *u8), ctr)
432 gv_check("glsl-keeps-the-BARE-uniform-read (v=(v*scale);)" as *u8, wgg_has(db, dn, "v=(v*scale);" as *u8), ctr)
433 gv_check_eq("the-qualifier-appears-EXACTLY-ONCE (WGSL only -- it never leaks into the GLSL printed beside it)" as *u8, wgg_count(db, dn, "u.scale" as *u8), 1, ctr)
434 gv_check_eq("trace-identity-STILL-holds-with-a-uniform-in-play (posctl_trace_equal)" as *u8, wgg_num_after(db, dn, "posctl_trace_equal=" as *u8), 1, ctr)
435 gv_check("shadow-local-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "shadowlocal_rc=" as *u8) > 0, ctr)
436 gv_check("neg-control-a-LOCAL-named-like-a-uniform-is-NOT-qualified (v=(v*k);)" as *u8, wgg_has(db, dn, "v=(v*k);" as *u8), ctr)
437 gv_check("shadow-param-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "shadowparam_rc=" as *u8) > 0, ctr)
438 gv_check("neg-control-a-PARAM-named-like-a-uniform-is-NOT-qualified (return (k*2.0);)" as *u8, wgg_has(db, dn, "return (k*2.0);" as *u8), ctr)
439 gv_check_eq("neg-control-the-shadowed-uniform-is-NEVER-qualified (count of u.k is 0)" as *u8, wgg_count(db, dn, "u.k" as *u8), 0, ctr)
440
441 // ---- S5 (2026-09-04): THE FRAGMENT OUTPUT IS A DECLARATION, AND BOTH HALVES OF THE SIGNATURE ARE DATA ----
442 // TWO defects, one shape. (a) The GLSL fragment stage had NO output declaration and lowered S_RETURN to
443 // `return <e>;` inside `void main()` -- invalid GLSL ES 3.00 twice over, emitted with no refusal, and
444 // invisible because nothing in this gate pinned the GLSL fragment bytes. It does now, and that absence
445 // was the whole reason the defect survived S1-S4. (b) The WGSL side spelled its signature tail as the
446 // literal ")->@location(0) vec4f{", so the location and the type were unreadable constants -- the same
447 // defect S4 had just removed from the PARAMETER half of that identical line. Both halves are derived now.
448 gv_check("fragout-glsl-probe-emitted (fragout_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragout_glsl_rc=" as *u8) > 0, ctr)
449 gv_check("fragout-wgsl-probe-emitted (fragout_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "fragout_wgsl_rc=" as *u8) > 0, ctr)
450 gv_check("glsl-DECLARES-the-fragment-output-and-ASSIGNS-it (one contiguous KAT)" as *u8, wgg_has(db, dn, WGG_FRAGOUT_GLSL), ctr)
451 gv_check_eq("neg-control-the-glsl-fragment-entry-RETURNS-NOTHING (count of 'return vec4(1.0,0.0,0.0,1.0)' is 0)" as *u8, wgg_count(db, dn, "return vec4(1.0,0.0,0.0,1.0)" as *u8), 0, ctr)
452 gv_check("wgsl-DERIVES-the-return-half-to-the-old-literal-EXACTLY (KAT)" as *u8, wgg_has(db, dn, WGG_FRAGOUT_WGSL), ctr)
453 gv_check_eq("neg-control-wgsl-declares-NO-out-variable-for-it (count of 'out vec4f' is 0)" as *u8, wgg_count(db, dn, "out vec4f" as *u8), 0, ctr)
454 gv_check_eq("fragout-trace-identity-holds-across-dialects (fragout_trace_equal)" as *u8, wgg_num_after(db, dn, "fragout_trace_equal=" as *u8), 1, ctr)
455 // THE LOCATION IS DATA. A tooth that only ever saw location 0 could not tell a derived number from the
456 // constant it replaced -- this is the tooth the trivial wrong implementation (keep printing 0) fails.
457 gv_check("anti-vacuity-a-NON-ZERO-location-reaches-the-glsl-layout-qualifier" as *u8, wgg_has(db, dn, WGG_FRAGLOC2_GLSL), ctr)
458 gv_check("anti-vacuity-a-NON-ZERO-location-reaches-the-wgsl-@location" as *u8, wgg_has(db, dn, WGG_FRAGLOC2_WGSL), ctr)
459 gv_check_eq("location-0-FRAGOUT-emits-NO-layout-qualifier (a loc-0 out is bare; S6 attributes carry layout(location=0) in, so this counts the loc-0 out form specifically, not the shared prefix)" as *u8, wgg_count(db, dn, "layout(location=0) out" as *u8), 0, ctr)
460 // POSITIVE CONTROL for the PRECISION of the rule: the requirement binds to a body that RETURNS A VALUE,
461 // never to the stage. A discard-only fragment is a legal program with no colour output, and a guard that
462 // refused it would be a false-positive generator -- the failure mode a deny-guard is most prone to.
463 gv_check("positive-control-a-DISCARD-only-fragment-needs-no-output-glsl (rc>0)" as *u8, wgg_num_after(db, dn, "fragdiscard_glsl_rc=" as *u8) > 0, ctr)
464 gv_check("positive-control-a-DISCARD-only-fragment-needs-no-output-wgsl (rc>0)" as *u8, wgg_num_after(db, dn, "fragdiscard_wgsl_rc=" as *u8) > 0, ctr)
465 gv_check("positive-control-discard-only-glsl-body-is-EXACTLY-void-main-discard" as *u8, wgg_has(db, dn, WGG_FRAGDISCARD_GLSL), ctr)
466 gv_check("positive-control-discard-only-wgsl-entry-carries-NO-return-type" as *u8, wgg_has(db, dn, WGG_FRAGDISCARD_WGSL), ctr)
467 // NEG-CONTROLS. Each asserts WHICH rule fired, never merely that something was refused.
468 gv_check_eq("neg-control-value-returned-with-NO-declared-output-REFUSES-in-glsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragnoout_glsl_rc=" as *u8), 0 - 1, ctr)
469 gv_check("neg-control-glsl-no-output-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGNOOUT_GL), ctr)
470 gv_check_eq("neg-control-value-returned-with-NO-declared-output-REFUSES-in-wgsl (rc=-1)" as *u8, wgg_num_after(db, dn, "fragnoout_wgsl_rc=" as *u8), 0 - 1, ctr)
471 gv_check("neg-control-wgsl-no-output-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_FRAGNOOUT_WG), ctr)
472 gv_check_eq("neg-control-a-fragment-output-on-a-VERTEX-stage-REFUSES-in-glsl (rc=-1)" as *u8, wgg_num_after(db, dn, "vertfragout_glsl_rc=" as *u8), 0 - 1, ctr)
473 gv_check("neg-control-vertex-fragout-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_VERTFRAGOUT_GL), ctr)
474 gv_check_eq("neg-control-a-fragment-output-on-a-VERTEX-stage-REFUSES-in-wgsl (rc=-1)" as *u8, wgg_num_after(db, dn, "vertfragout_wgsl_rc=" as *u8), 0 - 1, ctr)
475 gv_check("neg-control-vertex-fragout-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_VERTFRAGOUT_WG), ctr)
476 gv_check_eq("neg-control-TWO-declared-outputs-REFUSE-in-glsl (rc=-1; MRT is its own rung)" as *u8, wgg_num_after(db, dn, "fragtwoout_glsl_rc=" as *u8), 0 - 1, ctr)
477 gv_check("neg-control-two-output-glsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TWOOUT_GL), ctr)
478 gv_check_eq("neg-control-TWO-declared-outputs-REFUSE-in-wgsl (rc=-1; MRT is its own rung)" as *u8, wgg_num_after(db, dn, "fragtwoout_wgsl_rc=" as *u8), 0 - 1, ctr)
479 gv_check("neg-control-two-output-wgsl-refusal-NAMES-ITS-RULE" as *u8, wgg_has(db, dn, WGG_R_TWOOUT_WG), ctr)
480
481 // ---- S5 residual (b): A SAMPLED READ REFUSES IN WGSL AND EMITS IN GLSL ----
482 // wg_expr emitted `textureSample(t,samp,c)` against an UNDECLARED `samp` -- WGSL that does not compile,
483 // produced with no refusal, while wgsl_emit_module's declaration pass ALREADY refused a texture_2d<f32>
484 // for exactly that missing binding. The declaration side refused and the expression side guessed.
485 // Measured over the shipping world shader before choosing a remedy: texelFetch 1 / textureLoad 1 /
486 // texture( 0 / textureSample 0 -- ZERO sampled reads, so a sampler declaration kind would have been
487 // built for no caller. The GLSL half is asserted too: a refusal with no ADMITTING twin would not prove
488 // the rule is about the sampler rather than about the operation.
489 // GE54 (2026-09-05): the two `SAMPLED read REFUSES in wgsl` neg-controls were RETIRED -- E_TEXSAMPLE now emits
490 // textureSample(<tex>,<tex>_s,<coord>) against the DERIVED companion sampler (proven by the tex2d teeth), so
491 // asserting it refuses asserts the old world. The two controls below still stand: the OLD undeclared placeholder
492 // `,samp,` must appear NOWHERE, and the GLSL sampled read still emits -- the rule was the sampler, not the op.
493 gv_check_eq("neg-control-the-undeclared-sampler-`samp`-is-emitted-NOWHERE (count of ',samp,' is 0)" as *u8, wgg_count(db, dn, ",samp," as *u8), 0, ctr)
494 gv_check("positive-control-the-SAME-sampled-read-still-EMITS-in-glsl (rc>0: the rule is the sampler, not the operation)" as *u8, wgg_num_after(db, dn, "texsample_glsl_rc=" as *u8) > 0, ctr)
495 gv_check("positive-control-glsl-emits-texture(vox,uv)" as *u8, wgg_has(db, dn, WGG_TEXSAMPLE_GLSL), ctr)
496
497 // ---- S5: THE GATE'S OWN NUMBER PARSER IS ANCHORED (a defect this run FOUND, in the gate itself) ----
498 // wgg_num_after was an unanchored substring search keeping the LAST hit. "fragout_glsl_rc=" is a strict
499 // SUFFIX of "vertfragout_glsl_rc=", so the fragout teeth were reading the vertex-stage refusal's -1.
500 // The colliding label pair is DELIBERATELY retained so this control cannot go vacuous: it is measuring
501 // a collision that genuinely exists in the subject's output, not a planted one.
502 gv_check("neg-control-the-number-parser-ANCHORS-AT-A-LINE-START (fragout_glsl_rc= is a SUFFIX of vertfragout_glsl_rc=)" as *u8, wgg_num_after(db, dn, "fragout_glsl_rc=" as *u8) != wgg_num_after(db, dn, "vertfragout_glsl_rc=" as *u8), ctr)
503 gv_check_eq("positive-control-the-SUFFIX-label-still-reads-ITS-OWN-number (vertfragout_glsl_rc=-1)" as *u8, wgg_num_after(db, dn, "vertfragout_glsl_rc=" as *u8), 0 - 1, ctr)
504 gv_check("anti-vacuity-the-collision-is-REAL-in-the-subject-output (both labels present)" as *u8, wgg_has(db, dn, "\nfragout_glsl_rc=" as *u8) + wgg_has(db, dn, "\nvertfragout_glsl_rc=" as *u8) == 2, ctr)
505
506 // ---- R-A / R-C (2026-09-04): select() AND let -- the first two IR kinds the world shader needs (GE44) ----
507 // The whole-population diff of the two hand world shaders named five missing IR kinds (B1-B5). E_SELECT and
508 // the let flag are the two that need no new declaration machinery, so they land first. Each spelling is
509 // asserted EXACTLY in its own dialect and asserted ABSENT from the other; trace identity holds.
510 gv_check("selectlet-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "selectlet_glsl_rc=" as *u8) > 0, ctr)
511 gv_check("selectlet-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "selectlet_wgsl_rc=" as *u8) > 0, ctr)
512 gv_check("glsl-lowers-E_SELECT-to-the-ternary-and-let-to-a-plain-local (float t=((c>0)?a:b);)" as *u8, wgg_has(db, dn, "float t=((c>0)?a:b);" as *u8), ctr)
513 gv_check("wgsl-lowers-E_SELECT-to-select(f,t,cond)-and-let-to-let (let t:f32=select(b,a,(c>0));)" as *u8, wgg_has(db, dn, "let t:f32=select(b,a,(c>0));" as *u8), ctr)
514 gv_check_eq("neg-control-the-ternary-appears-ONCE (GLSL only; it never leaks into WGSL)" as *u8, wgg_count(db, dn, "?a:b)" as *u8), 1, ctr)
515 gv_check_eq("neg-control-select(b,a-appears-ONCE (WGSL only; it never leaks into GLSL)" as *u8, wgg_count(db, dn, "=select(b,a," as *u8), 1, ctr)
516 gv_check_eq("neg-control-the-let-local-is-never-spelled-var-in-wgsl (count of 'var t:f32' is 0)" as *u8, wgg_count(db, dn, "var t:f32" as *u8), 0, ctr)
517 gv_check_eq("selectlet-trace-identity-holds-across-dialects (selectlet_trace_equal)" as *u8, wgg_num_after(db, dn, "selectlet_trace_equal=" as *u8), 1, ctr)
518
519 // ---- R-B: the counted loop (GE44, B3 of the hand-shader diff) is BUILDER SUGAR over S_LOOP/S_BREAK ----
520 // sir_for_until appends init; loop { if until { break } body; step } -- so both dialects lower it through arms
521 // they already share and the only per-dialect bytes are the loop keyword and the declaration spelling. Each
522 // shape is asserted EXACTLY with the exit test FIRST and the step LAST, the sugar never spells `for(` in either
523 // dialect, and the trace is identical by construction.
524 gv_check("foruntil-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "foruntil_glsl_rc=" as *u8) > 0, ctr)
525 gv_check("foruntil-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "foruntil_wgsl_rc=" as *u8) > 0, ctr)
526 gv_check("glsl-lowers-the-counted-loop-to-while(true)-exit-test-first-step-last (int i=0; while(true){ if((i>=n)){ break; } s=(s+i); i=(i+1); })" as *u8, wgg_has(db, dn, "int i=0;\nwhile(true){\nif((i>=n)){\nbreak;\n}\ns=(s+i);\ni=(i+1);\n}" as *u8), ctr)
527 gv_check("wgsl-lowers-the-counted-loop-to-loop-exit-test-first-step-last (var i:i32=0; loop{ if((i>=n)){ break; } s=(s+i); i=(i+1); })" as *u8, wgg_has(db, dn, "var i:i32=0;\nloop{\nif((i>=n)){\nbreak;\n}\ns=(s+i);\ni=(i+1);\n}" as *u8), ctr)
528 gv_check_eq("neg-control-while(true)-appears-ONCE (GLSL only; it never leaks into WGSL)" as *u8, wgg_count(db, dn, "while(true){" as *u8), 1, ctr)
529 gv_check_eq("neg-control-loop{-appears-ONCE (WGSL only; it never leaks into GLSL)" as *u8, wgg_count(db, dn, "loop{" as *u8), 1, ctr)
530 gv_check_eq("neg-control-the-sugar-never-spells-for( in either dialect (count 0)" as *u8, wgg_count(db, dn, "for(" as *u8), 0, ctr)
531 gv_check_eq("the-step-is-the-last-statement-of-the-body-in-BOTH-dialects (i=(i+1); then the closing brace then return s; twice)" as *u8, wgg_count(db, dn, "i=(i+1);\n}\nreturn s;" as *u8), 2, ctr)
532 gv_check_eq("foruntil-trace-identity-holds-across-dialects (foruntil_trace_equal)" as *u8, wgg_num_after(db, dn, "foruntil_trace_equal=" as *u8), 1, ctr)
533
534 // ---- R-D: K_STRUCT declaration + member access (GE44, B1 of the hand-shader diff) ----
535 // One declaration kind, members as K_PARAM nodes, a struct type named by its declaration; construction is an
536 // E_CALL named after the struct and member access is the E_SWZ spelling both dialects already share. Each
537 // dialect's declaration bytes are asserted EXACTLY and asserted ABSENT from the other; the local, the member
538 // write and the nested member read are asserted per dialect; trace identity holds.
539 gv_check("struct-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "struct_glsl_rc=" as *u8) > 0, ctr)
540 gv_check("struct-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "struct_wgsl_rc=" as *u8) > 0, ctr)
541 gv_check("glsl-declares-the-struct-with-semicolon-members-and-a-terminating-semicolon (struct Hit{vec3 pos;float d;};)" as *u8, wgg_has(db, dn, "struct Hit{vec3 pos;float d;};\n" as *u8), ctr)
542 gv_check("wgsl-declares-the-struct-with-comma-members-and-no-terminator (struct Hit{pos:vec3f,d:f32,})" as *u8, wgg_has(db, dn, "struct Hit{pos:vec3f,d:f32,}\n" as *u8), ctr)
543 gv_check("glsl-struct-typed-local-built-by-the-struct-constructor (Hit h=Hit(p,k);)" as *u8, wgg_has(db, dn, "Hit h=Hit(p,k);\n" as *u8), ctr)
544 gv_check("wgsl-struct-typed-local-built-by-the-struct-constructor (var h:Hit=Hit(p,k);)" as *u8, wgg_has(db, dn, "var h:Hit=Hit(p,k);\n" as *u8), ctr)
545 gv_check_eq("member-write-then-nested-member-read-spelled-IDENTICALLY-in-BOTH-dialects (h.d=(h.d*2.0); return (h.d+h.pos.x); twice)" as *u8, wgg_count(db, dn, "h.d=(h.d*2.0);\nreturn (h.d+h.pos.x);\n" as *u8), 2, ctr)
546 // R-E CORRECTION (same day): these three were hand-counted ONCE / TWICE and the R-E fixture's second Hit
547 // declaration turned the LIVE gate RED an hour after they shipped -- a count pinned to the fixture population
548 // is a magic number wearing a tooth. DERIVED now: the GLSL spelling and the WGSL spelling must occur EQUALLY
549 // often (every fixture declares once per dialect) and more than never; a leak of either spelling into the
550 // other dialect breaks the balance, which is exactly what the neg-controls existed to catch.
551 gv_check("glsl-member-spelling-present (vec3 pos;)" as *u8, wgg_count(db, dn, "vec3 pos;" as *u8) > 0, ctr)
552 gv_check_eq("neg-control-member-spellings-BALANCE-across-dialects (count of vec3 pos; equals count of pos:vec3f -- a leak breaks it)" as *u8, wgg_count(db, dn, "vec3 pos;" as *u8), wgg_count(db, dn, "pos:vec3f" as *u8), ctr)
553 gv_check_eq("the-struct-declaration-BALANCES-across-dialects (count of struct Hit{vec3 equals count of struct Hit{pos:)" as *u8, wgg_count(db, dn, "struct Hit{vec3 " as *u8), wgg_count(db, dn, "struct Hit{pos:" as *u8), ctr)
554 gv_check_eq("struct-trace-identity-holds-across-dialects (struct_trace_equal)" as *u8, wgg_num_after(db, dn, "struct_trace_equal=" as *u8), 1, ctr)
555
556 // ---- R-E: struct RETURN and struct PARAMETER, one canonical shape (GE44, B2 of the hand-shader diff) ----
557 // The two hand shaders spell march two ways (GLSL out-params, WGSL struct return). GLSL ES 3.00 returns
558 // structs, so the IR carries ONE shape and both signature emitters spell the struct by its declaration; no
559 // out-parameter twin exists to disagree with. Asserted exactly per dialect, the member read straight off the
560 // call result identical in both, the struct-return signature once per dialect, trace identity.
561 gv_check("structret-glsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "structret_glsl_rc=" as *u8) > 0, ctr)
562 gv_check("structret-wgsl-probe-emitted (rc>0)" as *u8, wgg_num_after(db, dn, "structret_wgsl_rc=" as *u8) > 0, ctr)
563 gv_check("glsl-returns-a-struct-from-a-plain-function (Hit mk(vec3 p,float k){ Hit h=Hit(p,k); h.d=(k*2.0); return h; })" as *u8, wgg_has(db, dn, "Hit mk(vec3 p,float k){\nHit h=Hit(p,k);\nh.d=(k*2.0);\nreturn h;\n}\n" as *u8), ctr)
564 gv_check("wgsl-returns-a-struct-from-a-plain-function (fn mk(p:vec3f,k:f32)->Hit{ var h:Hit=Hit(p,k); h.d=(k*2.0); return h; })" as *u8, wgg_has(db, dn, "fn mk(p:vec3f,k:f32)->Hit{\nvar h:Hit=Hit(p,k);\nh.d=(k*2.0);\nreturn h;\n}\n" as *u8), ctr)
565 gv_check("glsl-takes-a-struct-parameter (float useh(Hit h,float k){)" as *u8, wgg_has(db, dn, "float useh(Hit h,float k){\n" as *u8), ctr)
566 gv_check("wgsl-takes-a-struct-parameter (fn useh(h:Hit,k:f32)->f32{)" as *u8, wgg_has(db, dn, "fn useh(h:Hit,k:f32)->f32{\n" as *u8), ctr)
567 gv_check_eq("member-read-straight-off-the-call-result-spelled-IDENTICALLY-in-BOTH-dialects (return (mk(h.pos,k).d+h.d); twice)" as *u8, wgg_count(db, dn, "return (mk(h.pos,k).d+h.d);\n" as *u8), 2, ctr)
568 gv_check("glsl-struct-return-signature-present (Hit mk( -- no out-parameter twin)" as *u8, wgg_count(db, dn, "Hit mk(" as *u8) > 0, ctr)
569 gv_check_eq("neg-control-struct-return-signatures-BALANCE-across-dialects (count of Hit mk( equals count of ->Hit{ -- derived, not pinned to the fixture population)" as *u8, wgg_count(db, dn, "Hit mk(" as *u8), wgg_count(db, dn, "->Hit{" as *u8), ctr)
570 gv_check_eq("structret-trace-identity-holds-across-dialects (structret_trace_equal)" as *u8, wgg_num_after(db, dn, "structret_trace_equal=" as *u8), 1, ctr)
571
572 // ---- R-F: the uniform LAYOUT is derived from the IR by the WGSL rules and published as data (GE44) ----
573 // A SECOND capture: `nx_wgsl layout` prints the world uniform block through both backends, one row per uniform
574 // (offset/size/align/stride/count) and the struct size. The KAT is the shipping page packer's own numbers
575 // (WGG_PACKER_*), so 112, 304 and 384 are read off the artifact the layout must serve, never off this gate;
576 // the spec's uniform stride rule is bite-proven by the array<f32,8> neg-control refusing BY NAME.
577 let lb: *u8 = sys_mmap(WGG_CAP)
578 bl[0] = 0
579 let lrc: i64 = gk_run_capture(subject, "layout" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, lb, WGG_CAP, bl)
580 let ln: i64 = bl[0]
581 gv_puts(" layout rc=" as *u8); gv_num(lrc); gv_puts(" bytes=" as *u8); gv_num(ln); gv_puts("\n" as *u8)
582 gv_check("layout-verb-ran (rc=0)" as *u8, lrc == 0, ctr)
583 gv_check("layout-verb-emitted-bytes" as *u8, ln > 0, ctr)
584 gv_check_eq("struct-U-size-equals-the-packer's-96-floats-times-4 (struct_u_size)" as *u8, wgg_num_after(lb, ln, "struct_u_size=" as *u8), WGG_PACKER_FLOATS * WGG_FLOAT_BYTES, ctr)
585 gv_check_eq("pal-offset-equals-the-packer's-float-index-28-times-4 (uniform|pal|offset=)" as *u8, wgg_num_after(lb, ln, "uniform|pal|offset=" as *u8), WGG_PACKER_PAL_F * WGG_FLOAT_BYTES, ctr)
586 gv_check_eq("palf-offset-equals-the-packer's-float-index-76-times-4 (uniform|palf|offset=)" as *u8, wgg_num_after(lb, ln, "uniform|palf|offset=" as *u8), WGG_PACKER_PALF_F * WGG_FLOAT_BYTES, ctr)
587 gv_check("vec3f-member-aligns-to-16-sizes-12-and-the-next-f32-packs-into-its-tail (cam at 0 size 12, t at 12)" as *u8, wgg_has(lb, ln, "uniform|cam|offset=0|size=12|align=16|stride=0|count=0\nuniform|t|offset=12|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
588 gv_check("vec2f-member-aligns-to-8 (res at 80 size 8 align 8)" as *u8, wgg_has(lb, ln, "uniform|res|offset=80|size=8|align=8|stride=0|count=0\n" as *u8), ctr)
589 gv_check("vec4f-array-stride-is-16-and-size-is-stride-times-count (pal 192 over 12, palf 80 over 5)" as *u8, wgg_has(lb, ln, "uniform|pal|offset=112|size=192|align=16|stride=16|count=12\nuniform|palf|offset=304|size=80|align=16|stride=16|count=5\n" as *u8), ctr)
590 gv_check("the-emitted-struct-U-carries-the-hand-shader's-array-spellings (pal:array<vec4f,12>, palf:array<vec4f,5>,)" as *u8, wgg_has(lb, ln, "pal:array<vec4f,12>,\npalf:array<vec4f,5>,\n" as *u8), ctr)
591 gv_check("the-uniform-read-is-qualified-in-wgsl (return (u.t*k);)" as *u8, wgg_has(lb, ln, "return (u.t*k);" as *u8), ctr)
592 gv_check("the-uniform-read-is-bare-in-glsl (return (t*k);)" as *u8, wgg_has(lb, ln, "return (t*k);" as *u8), ctr)
593 gv_check("layout-positive-control-admitted (layout_rc=384 layout_named=NONE)" as *u8, wgg_has(lb, ln, "layout_rc=384 layout_named=NONE" as *u8), ctr)
594 // S12c-2b: the neg-control's subject moved from array<f32,8> (now LOWERED, below) to array<vec2f,8> -- stride 8 is genuinely
595 // invalid in the uniform address space and has no lowering, so the refusal still fires BY NAME on a real offender.
596 gv_check("neg-control-uniform-array<vec2f,8>-refuses-BY-NAME (stride not a multiple of 16)" as *u8, wgg_has(lb, ln, "layoutbad_rc=-1 layoutbad_named=wgsl: uniform array element stride is not a multiple of 16" as *u8), ctr)
597 gv_check("S12c2b-uniform-array<f32,8>-is-LOWERED-to-two-vec4-lanes (offset=0 size=32 align=16 stride=16 count=2 f32n=8)" as *u8, wgg_has(lb, ln, "uniform|w|offset=0|size=32|align=16|stride=16|count=2|f32n=8" as *u8), ctr)
598 gv_check("S12c2b-lowered-f32-array-struct-size-is-32 (layoutf32_rc=32)" as *u8, wgg_has(lb, ln, "layoutf32_rc=32" as *u8), ctr)
599
600 // ---- R-G teeth: the WORLD shader (the full ray-marcher) emits through BOTH dialects, once (GE44) ----
601 // A THIRD capture. `nx_wgsl world` builds the world fragment + vertex pass ONCE (nx_world_shader_src) and
602 // emits it to GLSL and WGSL. This is the pixel-parity claim's TEXT-LEVEL control and it survives the
603 // retirement of the page's hand WGSL literal, because it RE-DERIVES the emitted shader on every gate run
604 // rather than trusting a stored copy. rc is read off the report line, never pinned to the byte count (a real
605 // shader edit changes the count and must not read as a leak); named=NONE proves neither dialect refused; the
606 // trace identity proves ONE IR walk; dialect-specific spellings prove both fragments are genuinely present
607 // (one program emitted twice, never one dialect twice). The GLSL/WGSL march signatures must BALANCE.
608 let wb: *u8 = sys_mmap(WGG_CAP)
609 bl[0] = 0
610 let wrc: i64 = gk_run_capture(subject, "world" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, wb, WGG_CAP, bl)
611 let wn: i64 = bl[0]
612 gv_puts(" world rc=" as *u8); gv_num(wrc); gv_puts(" bytes=" as *u8); gv_num(wn); gv_puts("\n" as *u8)
613 gv_check("world-verb-ran (rc=0)" as *u8, wrc == 0, ctr)
614 gv_check("world-verb-emitted-bytes" as *u8, wn > 0, ctr)
615 gv_check("world-glsl-fragment-emitted (world_glsl_rc>0)" as *u8, wgg_num_after(wb, wn, "world_glsl_rc=" as *u8) > 0, ctr)
616 gv_check("world-glsl-fragment-not-refused (world_glsl_named=NONE)" as *u8, wgg_has(wb, wn, "world_glsl_named=NONE" as *u8), ctr)
617 gv_check("world-wgsl-fragment-emitted (world_wgsl_rc>0)" as *u8, wgg_num_after(wb, wn, "world_wgsl_rc=" as *u8) > 0, ctr)
618 gv_check("world-wgsl-fragment-not-refused (world_wgsl_named=NONE)" as *u8, wgg_has(wb, wn, "world_wgsl_named=NONE" as *u8), ctr)
619 gv_check_eq("world-fragment-trace-identity-holds-across-dialects (world_trace_equal)" as *u8, wgg_num_after(wb, wn, "world_trace_equal=" as *u8), 1, ctr)
620 gv_check("world-glsl-vertex-emitted (worldvs_glsl_rc>0)" as *u8, wgg_num_after(wb, wn, "worldvs_glsl_rc=" as *u8) > 0, ctr)
621 gv_check("world-wgsl-vertex-emitted (worldvs_wgsl_rc>0)" as *u8, wgg_num_after(wb, wn, "worldvs_wgsl_rc=" as *u8) > 0, ctr)
622 gv_check("world-glsl-dialect-spelling-uint-vx-present" as *u8, wgg_has(wb, wn, "uint vx(" as *u8), ctr)
623 gv_check("world-glsl-dialect-spelling-out-vec4-present" as *u8, wgg_has(wb, wn, "out vec4" as *u8), ctr)
624 gv_check("world-wgsl-dialect-spelling-fn-vx-present" as *u8, wgg_has(wb, wn, "fn vx(" as *u8), ctr)
625 gv_check("world-wgsl-dialect-spelling-Hit-return-arrow-present" as *u8, wgg_has(wb, wn, ")->Hit{" as *u8), ctr)
626 gv_check_eq("neg-control-march-signatures-BALANCE-across-dialects (count of Hit march( equals count of fn march()" as *u8, wgg_count(wb, wn, "Hit march(" as *u8), wgg_count(wb, wn, "fn march(" as *u8), ctr)
627 gv_kv("world_glsl_rc" as *u8, wgg_num_after(wb, wn, "world_glsl_rc=" as *u8))
628 gv_kv("world_wgsl_rc" as *u8, wgg_num_after(wb, wn, "world_wgsl_rc=" as *u8))
629 gv_kv("worldvs_glsl_rc" as *u8, wgg_num_after(wb, wn, "worldvs_glsl_rc=" as *u8))
630 gv_kv("worldvs_wgsl_rc" as *u8, wgg_num_after(wb, wn, "worldvs_wgsl_rc=" as *u8))
631
632 // ---- GE55 K_PRIVATE: module-scope private state, ONE declaration kind, both dialects (the decls capture) ----
633 // The kind exists so the world shader can derive every float from RAW uniform words in one function while every
634 // other body stays byte-identical. Proven: declared per dialect (scalar and array spellings), written bare beside
635 // a QUALIFIED uniform read, an array element assigned in both dialects, never spelled u.<name>, trace-identical,
636 // and a texture-typed private refuses BY NAME in each dialect. The layout capture proves it is invisible there.
637 gv_check("priv-glsl-probe-emitted (priv_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "priv_glsl_rc=" as *u8) > 0, ctr)
638 gv_check("priv-wgsl-probe-emitted (priv_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "priv_wgsl_rc=" as *u8) > 0, ctr)
639 gv_check("wgsl-private-scalar-declared (var<private> gk:f32;)" as *u8, wgg_has(db, dn, "var<private> gk:f32;\n" as *u8), ctr)
640 gv_check("wgsl-private-array-declared (var<private> pv:array<vec4f,2>;)" as *u8, wgg_has(db, dn, "var<private> pv:array<vec4f,2>;\n" as *u8), ctr)
641 gv_check("glsl-private-scalar-declared (float gk;)" as *u8, wgg_has(db, dn, "float gk;\n" as *u8), ctr)
642 gv_check("glsl-private-array-declared (vec4 pv[2];)" as *u8, wgg_has(db, dn, "vec4 pv[2];\n" as *u8), ctr)
643 gv_check("wgsl-private-written-bare-beside-a-QUALIFIED-uniform-read (gk=(u.q*2.0);)" as *u8, wgg_has(db, dn, "gk=(u.q*2.0);\n" as *u8), ctr)
644 gv_check("glsl-private-written-bare-beside-a-bare-uniform-read (gk=(q*2.0);)" as *u8, wgg_has(db, dn, "gk=(q*2.0);\n" as *u8), ctr)
645 gv_check_eq("neg-control-private-never-qualified-as-a-uniform (count of u.gk)" as *u8, wgg_count(db, dn, "u.gk" as *u8), 0, ctr)
646 gv_check_eq("private-array-element-assigned-in-BOTH-dialects (pv[0]= twice)" as *u8, wgg_count(db, dn, "pv[0]=" as *u8), 2, ctr)
647 gv_check_eq("priv-trace-identity-holds-across-dialects (priv_trace_equal)" as *u8, wgg_num_after(db, dn, "priv_trace_equal=" as *u8), 1, ctr)
648 gv_check("neg-control-texture-typed-private-refuses-BY-NAME-in-glsl" as *u8, wgg_has(db, dn, "privtex_glsl_rc=-1 privtex_glsl_named=glsl: texture-typed private variable" as *u8), ctr)
649 gv_check("neg-control-texture-typed-private-refuses-BY-NAME-in-wgsl" as *u8, wgg_has(db, dn, "privtex_wgsl_rc=-1 privtex_wgsl_named=wgsl: texture-typed private variable" as *u8), ctr)
650 gv_check("layout-lists-the-uniform-beside-the-private (uniform|q|offset=0|size=4)" as *u8, wgg_has(lb, ln, "uniform|q|offset=0|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
651 gv_check_eq("neg-control-layout-never-lists-a-private (count of uniform|gk|)" as *u8, wgg_count(lb, ln, "uniform|gk|" as *u8), 0, ctr)
652 gv_check("layout-struct-size-is-the-uniform-alone (layoutpriv_rc=4)" as *u8, wgg_has(lb, ln, "layoutpriv_rc=4 rows:" as *u8), ctr)
653 gv_kv("priv_glsl_rc" as *u8, wgg_num_after(db, dn, "priv_glsl_rc=" as *u8))
654 gv_kv("priv_wgsl_rc" as *u8, wgg_num_after(db, dn, "priv_wgsl_rc=" as *u8))
655
656 // ---- GE55 step B: the world module takes the sim's RAW words and derives every float on the GPU ----
657 // The layout capture pins the raw struct to the sim's UR_* table (one ruler, two consumers): camx at word 0,
658 // pal0 at 80, palf0 at 128, resw at 148, yflip at 156, struct 160 == URAW_BYTES. The world capture proves the
659 // emitted shaders now declare the raw words as the uniform block, hold the derived names as private state, carry
660 // upk(), and never read the old f32 uniforms through u. (a leak of `u.cam` would mean the flip did not happen).
661 gv_check("layoutraw-struct-is-164-bytes (layoutraw_rc=164: 41 raw words with r_surf at 160; AlignOf(U) is 4 for a scalar-only struct so SizeOf is offset+size of the last member and is NOT rounded to 16 -- the 176 this tooth once pinned was a prediction the backend never made; the sim block stays 176 = 44 words vec4-padded and the page copies the 164 the layout names -- GE53)" as *u8, wgg_has(lb, ln, "layoutraw_rc=164 rows:" as *u8), ctr)
662 gv_check("layoutraw-surf-at-byte-160 (UR_SURF=40, GE53: the ground-is-the-field word)" as *u8, wgg_has(lb, ln, "uniform|r_surf|offset=160|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
663 gv_check("layoutraw-camx-at-word-0 (uniform|r_camx|offset=0|size=4)" as *u8, wgg_has(lb, ln, "uniform|r_camx|offset=0|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
664 gv_check("layoutraw-pal0-at-byte-80 (UR_PAL=20)" as *u8, wgg_has(lb, ln, "uniform|r_pal0|offset=80|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
665 gv_check("layoutraw-palf0-at-byte-128 (UR_PALF=32)" as *u8, wgg_has(lb, ln, "uniform|r_palf0|offset=128|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
666 gv_check("layoutraw-resw-at-byte-148 (UR_RESW=37)" as *u8, wgg_has(lb, ln, "uniform|r_resw|offset=148|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
667 gv_check("layoutraw-yflip-at-byte-156 (UR_YFLIP=39)" as *u8, wgg_has(lb, ln, "uniform|r_yflip|offset=156|size=4|align=4|stride=0|count=0\n" as *u8), ctr)
668 gv_check("world-wgsl-uniform-block-is-the-raw-words (struct U{ r_camx:i32,)" as *u8, wgg_has(wb, wn, "struct U{\nr_camx:i32,\n" as *u8), ctr)
669 gv_check("world-glsl-uniform-block-is-the-raw-words (uniform int r_camx;)" as *u8, wgg_has(wb, wn, "uniform int r_camx;\n" as *u8), ctr)
670 gv_check("world-wgsl-derived-palette-is-private-state (var<private> pal:array<vec4f,12>;)" as *u8, wgg_has(wb, wn, "var<private> pal:array<vec4f,12>;\n" as *u8), ctr)
671 gv_check("world-glsl-derived-palette-is-a-bare-global (vec4 pal[12];)" as *u8, wgg_has(wb, wn, "vec4 pal[12];\n" as *u8), ctr)
672 gv_check("world-wgsl-carries-upk (fn upk(){)" as *u8, wgg_has(wb, wn, "fn upk(){" as *u8), ctr)
673 gv_check("world-glsl-carries-upk (void upk(){)" as *u8, wgg_has(wb, wn, "void upk(){" as *u8), ctr)
674 gv_check("world-entry-calls-upk-first-in-both-dialects (upk(); twice)" as *u8, wgg_count(wb, wn, "upk();\n" as *u8) == 2, ctr)
675 gv_check_eq("neg-control-no-function-reads-the-old-f32-uniforms (count of u.cam)" as *u8, wgg_count(wb, wn, "u.cam" as *u8), 0, ctr)
676 gv_check("world-wgsl-reads-a-raw-word-qualified (f32(u.r_camx))" as *u8, wgg_has(wb, wn, "f32(u.r_camx)" as *u8), ctr)
677 gv_check("world-glsl-reads-a-raw-word-bare (float(r_camx))" as *u8, wgg_has(wb, wn, "float(r_camx)" as *u8), ctr)
678 gv_kv("layoutraw_rc" as *u8, wgg_num_after(lb, ln, "layoutraw_rc=" as *u8))
679
680 // ---- GE55: a void function has no return arrow in WGSL (the backend once spelled fn upk()->void{) ----
681 gv_check_eq("neg-control-wgsl-never-spells-a-void-return-arrow-in-the-world (count of ->void)" as *u8, wgg_count(wb, wn, "->void" as *u8), 0, ctr)
682 gv_check_eq("neg-control-wgsl-never-spells-a-void-return-arrow-in-decls (count of ->void)" as *u8, wgg_count(db, dn, "->void" as *u8), 0, ctr)
683 gv_check("wgsl-void-function-signature-has-no-arrow-in-the-private-fixture (fn upk(){)" as *u8, wgg_has(db, dn, "fn upk(){" as *u8), ctr)
684
685 // ---- GE54: sampled texture_2d<f32> lowers in both dialects (the cast fragment needs it; the world used only
686 // textureLoad, which takes no sampler). GLSL is one combined sampler2D; WGSL is a texture binding + a DERIVED
687 // companion sampler `<name>_s`, and the E_TEXSAMPLE arm uses exactly that name so they agree by construction. ----
688 gv_check("tex2d-glsl-emitted (tex2dsmp_glsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex2dsmp_glsl_rc=" as *u8) > 0, ctr)
689 gv_check("tex2d-wgsl-emitted (tex2dsmp_wgsl_rc>0)" as *u8, wgg_num_after(db, dn, "tex2dsmp_wgsl_rc=" as *u8) > 0, ctr)
690 gv_check("glsl-declares-a-combined-sampler2D (uniform sampler2D atlas;)" as *u8, wgg_has(db, dn, "uniform sampler2D atlas;\n" as *u8), ctr)
691 gv_check("wgsl-declares-the-texture-binding (atlas:texture_2d<f32>;)" as *u8, wgg_has(db, dn, "atlas:texture_2d<f32>;\n" as *u8), ctr)
692 gv_check("wgsl-derives-a-companion-sampler (atlas_s:sampler;)" as *u8, wgg_has(db, dn, "atlas_s:sampler;\n" as *u8), ctr)
693 gv_check("glsl-samples-with-texture (texture(atlas,uv))" as *u8, wgg_has(db, dn, "texture(atlas,uv)" as *u8), ctr)
694 gv_check("wgsl-samples-with-textureSample-and-the-companion (textureSample(atlas,atlas_s,uv))" as *u8, wgg_has(db, dn, "textureSample(atlas,atlas_s,uv)" as *u8), ctr)
695 gv_check_eq("tex2d-trace-identity-holds-across-dialects (tex2dsmp_trace_equal)" as *u8, wgg_num_after(db, dn, "tex2dsmp_trace_equal=" as *u8), 1, ctr)
696 gv_check_eq("neg-control-glsl-has-NO-separate-wgsl-sampler-decl (count of atlas_s:sampler is a WGSL-only construct)" as *u8, wgg_count(db, dn, "sampler2D atlas;" as *u8), 1, ctr)
697
698 // S5 VALUES (gv_kv): an arithmetic that cannot see a number can never contradict one.
699 gv_kv("fragout_glsl_rc" as *u8, wgg_num_after(db, dn, "fragout_glsl_rc=" as *u8))
700 gv_kv("fragout_wgsl_rc" as *u8, wgg_num_after(db, dn, "fragout_wgsl_rc=" as *u8))
701 gv_kv("fragloc2_glsl_rc" as *u8, wgg_num_after(db, dn, "fragloc2_glsl_rc=" as *u8))
702 gv_kv("fragdiscard_glsl_rc" as *u8, wgg_num_after(db, dn, "fragdiscard_glsl_rc=" as *u8))
703 gv_kv("texsample_glsl_rc" as *u8, wgg_num_after(db, dn, "texsample_glsl_rc=" as *u8))
704 gv_kv("layout_location_sites" as *u8, wgg_count(db, dn, "layout(location=" as *u8))
705 gv_kv("undeclared_samp_sites" as *u8, wgg_count(db, dn, ",samp," as *u8))
706
707 // ---- S12c-5 teeth (2026-09-05): the three spellings the cast FRAGMENT needs, on the decls capture's fragassign fixture ----
708 // The hand fragment ASSIGNS its declared output and exits early with a void `return;` -- valid GLSL as-is, while WGSL must
709 // carry the output as a local (`var fc:vec4f;`), return it at every void return and once after the body. It also carries a
710 // `const float` local and a u-suffixed unsigned literal. The value-returning fragout fixture beside it (m8f) must be
711 // UNTOUCHED: exactly one `var fc:vec4f;` in the whole decls capture proves the lowering fires only where assignment happens.
712 gv_check("S12c5-fragassign-glsl-emitted-with-no-refusal" as *u8, wgg_has(db, dn, "fragassign_glsl_named=NONE" as *u8), ctr)
713 gv_check("S12c5-fragassign-wgsl-emitted-with-no-refusal" as *u8, wgg_has(db, dn, "fragassign_wgsl_named=NONE" as *u8), ctr)
714 gv_check("S12c5-glsl-assigns-the-out-variable-void-returns-const-local-and-0u-literal (fc=vec4(1.0); return; const float K=1.2; uint z=0u; fc=vec4(K);)" as *u8, wgg_has(db, dn, "fc=vec4(1.0);\nreturn;\n}\nconst float K=1.2;\nuint z=0u;\nfc=vec4(K);\n}" as *u8), ctr)
715 gv_check("S12c5-wgsl-carries-the-output-as-a-local-and-returns-it-at-every-exit (var fc:vec4f; ... return fc; ... return fc;)" as *u8, wgg_has(db, dn, "var fc:vec4f;\nif((u.a<0.5)){\nfc=vec4f(1.0);\nreturn fc;\n}\nconst K:f32=1.2;\nvar z:u32=0u;\nfc=vec4f(K);\nreturn fc;\n}" as *u8), ctr)
716 gv_check("neg-control-the-output-local-appears-ONLY-in-the-assigning-fixture (count of var fc:vec4f; is 1; the value-returning fixture stays untouched)" as *u8, wgg_count(db, dn, "var fc:vec4f;" as *u8) == 1, ctr)
717 gv_check("S12c5-fragassign-trace-identity-holds-across-dialects (fragassign_trace_equal=1)" as *u8, wgg_has(db, dn, "fragassign_trace_equal=1" as *u8), ctr)
718 gv_check("neg-control-glsl-never-spells-the-wgsl-local-form (count of var fc:vec4f in GLSL is impossible; uint z=0u; appears once)" as *u8, wgg_count(db, dn, "uint z=0u;" as *u8) == 1, ctr)
719
720 // ---- S12c teeth (2026-09-05): THE CAST vertex stage (nx_cast_shader_src) through both backends, `nx_wgsl cast` ----
721 // The GLSL side's proof is the canonical token ruler against the hand MVS (nx_glsl_tokdiff, journaled on gameengine.plan);
722 // these teeth pin what the WGSL side must carry to be VALID WGSL under S12c-2b: the float[N] uniforms lowered to vec4 lanes
723 // and read as [i/4][i%4], no array<f32 member anywhere, the instance builtin bound as iidx so the cast's own local ii
724 // cannot collide, and logical not spelled in both dialects. Refusal-free emission in both dialects is asserted by name.
725 let cb: *u8 = sys_mmap(WGG_CAP)
726 bl[0] = 0
727 let crc: i64 = gk_run_capture(subject, "cast" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, cb, WGG_CAP, bl)
728 let cn: i64 = bl[0]
729 gv_puts(" cast rc=" as *u8); gv_num(crc); gv_puts(" bytes=" as *u8); gv_num(cn); gv_puts("\n" as *u8)
730 gv_check("S12c-cast-verb-ran (rc=0)" as *u8, crc == 0, ctr)
731 gv_check("S12c-cast-verb-emits-GLSL-with-no-refusal" as *u8, wgg_has(cb, cn, "cast_glsl_named=NONE" as *u8), ctr)
732 gv_check("S12c-cast-verb-emits-WGSL-with-no-refusal" as *u8, wgg_has(cb, cn, "cast_wgsl_named=NONE" as *u8), ctr)
733 gv_check("S12c-glsl-keeps-the-hand-float-array (uniform float uGN[12];)" as *u8, wgg_has(cb, cn, "uniform float uGN[12];" as *u8), ctr)
734 gv_check("S12c-glsl-reads-the-float-array-bare (uGN[ii])" as *u8, wgg_has(cb, cn, "float gs9=uGN[ii];" as *u8), ctr)
735 gv_check("S12c2b-wgsl-lowers-float-array-to-vec4-lanes (uGN:array<vec4f,3>)" as *u8, wgg_has(cb, cn, "uGN:array<vec4f,3>," as *u8), ctr)
736 gv_check("S12c2b-wgsl-lowers-the-72-vec3-array-untouched (uSB:array<vec3f,72>)" as *u8, wgg_has(cb, cn, "uSB:array<vec3f,72>," as *u8), ctr)
737 gv_check("S12c2b-wgsl-reads-the-lowered-lane (u.uGN[(ii)/4][(ii)%4])" as *u8, wgg_has(cb, cn, "u.uGN[(ii)/4][(ii)%4]" as *u8), ctr)
738 gv_check("neg-control-wgsl-never-declares-array<f32 (0 sites)" as *u8, wgg_count(cb, cn, "array<f32," as *u8) == 0, ctr)
739 gv_check("S12c2b-wgsl-instance-builtin-is-iidx-so-the-cast-local-ii-cannot-collide" as *u8, wgg_has(cb, cn, "@builtin(instance_index) iidx:u32" as *u8), ctr)
740 gv_check("S12c2b-wgsl-cast-local-ii-is-derived-from-iidx (var ii:i32=i32(iidx);)" as *u8, wgg_has(cb, cn, "var ii:i32=i32(iidx);" as *u8), ctr)
741 gv_check("S12c4-both-dialects-spell-logical-not-on-wr9 (2 sites)" as *u8, wgg_count(cb, cn, wgg_bang("(~wr9)" as *u8)) == 2, ctr)
742 gv_check("S12c4-both-dialects-spell-logical-not-on-the-skirt-gate (2 sites)" as *u8, wgg_count(cb, cn, wgg_bang("(~((((gbm==4)||(gbm==5))||(gbm==8))||(gbm==9)))" as *u8)) == 2, ctr)
743 gv_check("S12c-cast-emits-the-clip-transform-in-both-dialects (2 sites)" as *u8, wgg_count(cb, cn, "(300.08/299.92)" as *u8) == 2, ctr)
744 // S12c-6: WGSL has no scalar-bound overload of clamp/min/max, so the skin tail's clamp((vec3(ndl)+w3)/(1.+w3),0.,1.) must
745 // read vec3f bounds in WGSL and scalar bounds in GLSL; an all-scalar clamp and an all-vector min must pass through untouched
746 gv_check("S12c6-wgsl-splats-scalar-bounds-on-the-vector-clamp (dif3: ,vec3f(0.0),vec3f(1.0)) once)" as *u8, wgg_count(cb, cn, ",vec3f(0.0),vec3f(1.0))" as *u8) == 1, ctr)
747 gv_check("neg-control-S12c6-glsl-keeps-the-scalar-bounds-and-only-glsl-does ((1.0+w3)),0.0,1.0) exactly once)" as *u8, wgg_count(cb, cn, "(1.0+w3)),0.0,1.0)" as *u8) == 1, ctr)
748 gv_check("neg-control-S12c6-all-scalar-clamp-untouched-in-both-dialects (clamp(fl9,0.0,0.3) twice)" as *u8, wgg_count(cb, cn, "clamp(fl9,0.0,0.3)" as *u8) == 2, ctr)
749 gv_check("neg-control-S12c6-all-vector-min-untouched (min(spec8,vec3f(6.0)) once)" as *u8, wgg_count(cb, cn, "min(spec8,vec3f(6.0))" as *u8) == 1, ctr)
750
751 return gv_verdict("NX-WGSL" as *u8, ctr, "one NishiLang source emits both dialects; equivalence is measured at the IR level and the pixel level is declared unproven" as *u8)
752}