nx_meshrig_gate.nx source
↩ module page · 266 lines · 12528 B
1// nx_meshrig_gate.nx -- IS THE BIND REAL, OR JUST A SKIN SECTION THAT EXISTS?
2//
3// Subject: ./nx_meshrig.elf (the serving-root binary; e2e fork, never an in-process re-derive).
4//
5// THE DEFECT THIS GATE EXISTS TO CATCH: a RIGID bind -- every vertex nailed to one bone at full
6// weight -- satisfies "the asset has a SKIN section", loads in nx_nxa_play, reports
7// zero_weight_verts=0, and produces candy-wrapper garbage the moment anything poses. It is the
8// trivial wrong implementation, and presence-of-section cannot distinguish it from a real bind.
9// Two numbers can: under a rigid bind EVERY vertex has exactly one influence and the mean dominant
10// weight is 4096 (the q12 whole).
11//
12// THE NEG-CONTROL NEEDS NO CODE MUTATION, WHICH IS WHY IT IS TRUSTWORTHY: a skeleton with ONE bone
13// IS a rigid bind, by construction. So the rigid case runs the SAME promoted binary down the SAME
14// code path with a different fixture -- there is no mutant to restore and no risk of measuring a
15// harness instead of the subject. A 4-joint skeleton must blend; a 2-joint skeleton must not.
16//
17// FIXTURES ARE ASSEMBLED AT RUNTIME under /tmp/nxmeshriggate/ (a gate must not share its fixture
18// with a production beat, and a teardown does not run when a run crashes). The mesh fixture is
19// emitted here as real NXMSH2 bytes, including a real IEEE754 f32 encoder, because a fixture the
20// defect cannot fail is not a test.
21//
22// SUBPROCESS CAPTURE COMPOSES nx_gatekit_lib. This is not a style preference: a hand-rolled
23// pipe/fork/exec in a sibling gate DEADLOCKED IN PRODUCTION today (50+ minutes in pipe_wait, zero
24// CPU, artifact frozen at its header) because an undrained pipe blocks forever. The banked law is
25// that fixtures and subprocess come from that lib; never re-roll them.
26// license_tier: ORIGINAL expect_exit: 0
27import "nx_syscalls.nx"
28import "nx_gate_verdict.nx"
29import "nx_gatekit_lib.nx"
30
31const MG_ELF: *u8 = "./nx_meshrig.elf"
32const MG_DIR: *u8 = "/tmp/nxmeshriggate"
33const MG_MESH: *u8 = "/tmp/nxmeshriggate/col.nxmesh"
34const MG_SKP: *u8 = "/tmp/nxmeshriggate/multi.skel"
35const MG_SKN: *u8 = "/tmp/nxmeshriggate/onebone.skel"
36const MG_OUTP: *u8 = "/tmp/nxmeshriggate/multi.nxa"
37const MG_OUTN: *u8 = "/tmp/nxmeshriggate/onebone.nxa"
38const MG_OUTD: *u8 = "/tmp/nxmeshriggate/determinism.nxa"
39const MG_MODE: i64 = 420
40const MG_Q12: i64 = 4096
41// PROTECTIVE bound on a subprocess's stdout, not a data cap: the subject prints a fixed dozen
42// lines. Truncation is ANNOUNCED (see the cap tooth) rather than silently swallowed.
43const MG_CAP: i64 = 65536
44const MG_TRIB: i64 = 84
45const MG_NTRI: i64 = 24
46const MG_STAT: i64 = 1750
47const MG_M23: i64 = 8388607
48
49func mg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
50
51// IEEE754 f32 ENCODER -- the fixture must be real NXMSH2 bytes, so the gate needs the inverse of
52// the subject's decoder. Exact for magnitudes below 2^24, which every fixture coordinate is.
53func mg_f32enc(v: i64) -> i64 {
54 if v == 0 { return 0 }
55 var sign: i64 = 0
56 var a: i64 = v
57 if a < 0 { sign = 1; a = 0 - a }
58 var e: i64 = 0
59 var t: i64 = a
60 while t > 1 { t = t >> 1; e = e + 1 }
61 var m: i64 = 0
62 if e >= 23 { m = a >> (e - 23) } else { m = a << (23 - e) }
63 m = m & MG_M23
64 let expo: i64 = 127 + e
65 return (sign << 31) | (expo << 23) | m
66}
67func mg_put32(b: *u8, o: i64, w: i64) -> i64 {
68 b[o] = (w & 255) as u8
69 b[o+1] = ((w >> 8) & 255) as u8
70 b[o+2] = ((w >> 16) & 255) as u8
71 b[o+3] = ((w >> 24) & 255) as u8
72 return 0
73}
74
75// A vertical column of triangles from y=0 to y=MG_STAT mm: Y-up, so the subject's derived-up-axis
76// and spec-conformance rotation are both exercised by the positive case.
77func mg_write_mesh(path: *u8) -> i64 {
78 let sz: i64 = 16 + MG_NTRI*MG_TRIB
79 let b: *u8 = sys_mmap(sz + 64)
80 var i: i64 = 0
81 while i < sz { b[i] = 0 as u8; i = i + 1 }
82 b[0] = 78 as u8
83 b[1] = 88 as u8
84 b[2] = 77 as u8
85 b[3] = 83 as u8
86 b[4] = 72 as u8
87 b[5] = 50 as u8
88 mg_put32(b, 8, 0)
89 mg_put32(b, 12, MG_NTRI)
90 var t: i64 = 0
91 while t < MG_NTRI {
92 let y0: i64 = (MG_STAT * t) / MG_NTRI
93 let y1: i64 = (MG_STAT * (t+1)) / MG_NTRI
94 var w: i64 = 0
95 if t % 2 == 1 { w = 60 }
96 if t % 2 == 0 { w = 100 }
97 let o: i64 = 16 + t*MG_TRIB
98 mg_put32(b, o+0, mg_f32enc(0 - w)); mg_put32(b, o+4, mg_f32enc(y0)); mg_put32(b, o+8, mg_f32enc(0))
99 mg_put32(b, o+12, mg_f32enc(w)); mg_put32(b, o+16, mg_f32enc(y0)); mg_put32(b, o+20, mg_f32enc(0))
100 mg_put32(b, o+24, mg_f32enc(0)); mg_put32(b, o+28, mg_f32enc(y1)); mg_put32(b, o+32, mg_f32enc(w))
101 t = t + 1
102 }
103 let fd: i64 = sys_openat_wr(path, MG_MODE)
104 if fd < 0 { return 0 - 1 }
105 sys_write(fd, b, sz)
106 sys_close(fd)
107 return sz
108}
109func mg_write_text(path: *u8, s: *u8) -> i64 {
110 let fd: i64 = sys_openat_wr(path, MG_MODE)
111 if fd < 0 { return 0 - 1 }
112 let n: i64 = mg_slen(s)
113 sys_write(fd, s, n)
114 sys_close(fd)
115 return n
116}
117
118// find "<key>" in buf and read the integer immediately after it; MG_ABSENT when the key is missing
119const MG_ABSENT: i64 = 0 - 999999999
120func mg_after(buf: *u8, blen: i64, key: *u8) -> i64 {
121 let kl: i64 = mg_slen(key)
122 var i: i64 = 0
123 var found: i64 = 0 - 1
124 while i + kl <= blen {
125 if found < 0 {
126 var k: i64 = 0
127 var same: i64 = 1
128 while k < kl {
129 if buf[i+k] != key[k] { same = 0 }
130 k = k + 1
131 }
132 if same == 1 { found = i + kl }
133 }
134 i = i + 1
135 }
136 if found < 0 { return MG_ABSENT }
137 var p: i64 = found
138 var ng: i64 = 0
139 if p < blen { if buf[p] == (45 as u8) { ng = 1; p = p + 1 } }
140 var v: i64 = 0
141 var got: i64 = 0
142 var go: i64 = 1
143 while go == 1 {
144 if p >= blen { go = 0 }
145 if go == 1 {
146 let c: i64 = buf[p] as i64
147 var isd: i64 = 0
148 if c >= 48 { if c <= 57 { isd = 1 } }
149 if isd == 1 { v = v*10 + (c - 48); p = p + 1; got = 1 } else { go = 0 }
150 }
151 }
152 if got == 0 { return MG_ABSENT }
153 if ng == 1 { return 0 - v }
154 return v
155}
156func mg_has(buf: *u8, blen: i64, needle: *u8) -> i64 {
157 let nl: i64 = mg_slen(needle)
158 var i: i64 = 0
159 while i + nl <= blen {
160 var k: i64 = 0
161 var same: i64 = 1
162 while k < nl { if buf[i+k] != needle[k] { same = 0 } k = k + 1 }
163 if same == 1 { return 1 }
164 i = i + 1
165 }
166 return 0
167}
168func mg_filesize(path: *u8) -> i64 {
169 let ln: *i64 = sys_mmap(16) as *i64
170 ln[0] = 0
171 let b: *u8 = sys_read_file(path, ln)
172 if (b as i64) == 0 { return 0 - 1 }
173 return ln[0]
174}
175
176func main(argc: i64, argv: *i64) -> i64 {
177 let ctr: *i64 = gv_ctr()
178 gv_puts("nx_meshrig_gate -- a SKIN section that exists is not a bind; blend is measured, and a rigid bind must FAIL\n\n" as *u8)
179
180 sys_mkdir(MG_DIR, 493)
181 let msz: i64 = mg_write_mesh(MG_MESH)
182 // 4 joints => 3 bone segments => a vertex can carry several influences
183 let np: i64 = mg_write_text(MG_SKP, "B 0 100 0 90\nJ 0 -1 0 0 0 0\nJ 1 0 0 0 583 0\nJ 2 1 0 0 1166 0\nJ 3 2 0 0 1750 0\n" as *u8)
184 // 2 joints => ONE bone segment => every vertex is nailed to it: the rigid bind, by construction
185 let nn: i64 = mg_write_text(MG_SKN, "B 0 100 0 90\nJ 0 -1 0 0 0 0\nJ 1 0 0 0 1750 0\n" as *u8)
186 var setup: i64 = 0
187 if msz > 0 { if np > 0 { if nn > 0 { setup = 1 } } }
188 gv_puts(" fixture mesh_bytes="); gv_num(msz); gv_puts(" skel_multi="); gv_num(np); gv_puts(" skel_onebone="); gv_num(nn); gv_puts("\n" as *u8)
189 gv_check("setup-fixtures-written (a fixture the defect cannot fail is not a test)" as *u8, setup, ctr)
190
191 let buf: *u8 = sys_mmap(MG_CAP + 64)
192 let bl: *i64 = sys_mmap(16) as *i64
193
194 // ---------- POSITIVE: the real, multi-bone bind ----------
195 bl[0] = 0
196 let rcp: i64 = gk_run_capture(MG_ELF, MG_MESH, MG_SKP, MG_OUTP, 0 as *u8, buf, MG_CAP, bl)
197 gv_check("positive-bind-exits-zero" as *u8, rcp == 0, ctr)
198 gv_check("capture-not-truncated (a truncated capture would make every parse below unproven)" as *u8, bl[0] < MG_CAP, ctr)
199 let p_nv: i64 = mg_after(buf, bl[0], "verts=" as *u8)
200 let p_bones: i64 = mg_after(buf, bl[0], "bones=" as *u8)
201 let p_multi: i64 = mg_after(buf, bl[0], "verts_with_multiple_influences=" as *u8)
202 let p_single: i64 = mg_after(buf, bl[0], "verts_with_single_influence=" as *u8)
203 let p_dom: i64 = mg_after(buf, bl[0], "mean_dominant_weight_q12=" as *u8)
204 let p_bad: i64 = mg_after(buf, bl[0], "verts_whose_weights_do_not_sum_to_4096=" as *u8)
205 gv_puts(" positive nv="); gv_num(p_nv); gv_puts(" bones="); gv_num(p_bones)
206 gv_puts(" multi="); gv_num(p_multi); gv_puts(" single="); gv_num(p_single)
207 gv_puts(" mean_dom_q12="); gv_num(p_dom); gv_puts(" bad_sum="); gv_num(p_bad); gv_puts("\n" as *u8)
208
209 // anti-vacuity: the counts are bound IN the condition, so an empty or absent parse cannot pass
210 var reached: i64 = 0
211 if p_nv == MG_NTRI*3 { if p_bones == 3 { reached = 1 } }
212 gv_check("fixture-reached-the-condition (nv == 3*ntris AND bones == joints-1, both parsed)" as *u8, reached, ctr)
213
214 var blend_ok: i64 = 0
215 if p_multi == p_nv { if p_nv > 0 { blend_ok = 1 } }
216 gv_check("every-vertex-carries-MULTIPLE-influences (count bound to nv; empty set cannot pass)" as *u8, blend_ok, ctr)
217 gv_check("no-vertex-is-single-influence (a rigid bind would make this equal nv)" as *u8, p_single == 0, ctr)
218
219 var dom_ok: i64 = 0
220 if p_dom > 0 { if p_dom < MG_Q12 { dom_ok = 1 } }
221 gv_check("mean-dominant-weight-strictly-below-the-q12-whole (4096 is the rigid signature)" as *u8, dom_ok, ctr)
222 gv_check("all-weight-lanes-sum-to-exactly-4096 (the format's own requirement)" as *u8, p_bad == 0, ctr)
223 gv_check("spec-up-rotation-announced-for-a-Y-up-source (bytes must not disagree with the format naming them)" as *u8,
224 mg_has(buf, bl[0], "spec_up=rotX+90" as *u8), ctr)
225
226 let sz1: i64 = mg_filesize(MG_OUTP)
227 gv_puts(" emitted bytes="); gv_num(sz1); gv_puts("\n" as *u8)
228 gv_check("positive-emits-a-nonempty-nxa" as *u8, sz1 > 0, ctr)
229
230 // ---------- DETERMINISM: same inputs, same bytes ----------
231 bl[0] = 0
232 let rcd: i64 = gk_run_capture(MG_ELF, MG_MESH, MG_SKP, MG_OUTD, 0 as *u8, buf, MG_CAP, bl)
233 let sz2: i64 = mg_filesize(MG_OUTD)
234 var det: i64 = 0
235 if rcd == 0 { if sz2 == sz1 { if sz1 > 0 { det = 1 } } }
236 gv_check("determinism-same-inputs-same-output-size" as *u8, det, ctr)
237
238 // ---------- NEG-CONTROL: one bone IS a rigid bind. No mutant, same binary, same path. ----------
239 bl[0] = 0
240 let rcn: i64 = gk_run_capture(MG_ELF, MG_MESH, MG_SKN, MG_OUTN, 0 as *u8, buf, MG_CAP, bl)
241 let n_nv: i64 = mg_after(buf, bl[0], "verts=" as *u8)
242 let n_bones: i64 = mg_after(buf, bl[0], "bones=" as *u8)
243 let n_multi: i64 = mg_after(buf, bl[0], "verts_with_multiple_influences=" as *u8)
244 let n_single: i64 = mg_after(buf, bl[0], "verts_with_single_influence=" as *u8)
245 let n_dom: i64 = mg_after(buf, bl[0], "mean_dominant_weight_q12=" as *u8)
246 gv_puts(" neg-control(one bone) rc="); gv_num(rcn); gv_puts(" bones="); gv_num(n_bones)
247 gv_puts(" multi="); gv_num(n_multi); gv_puts(" single="); gv_num(n_single)
248 gv_puts(" mean_dom_q12="); gv_num(n_dom); gv_puts("\n" as *u8)
249
250 var neg_reached: i64 = 0
251 if rcn == 0 { if n_bones == 1 { if n_nv == MG_NTRI*3 { neg_reached = 1 } } }
252 gv_check("neg-control-fixture-reached-the-condition (it really did bind, with exactly one bone)" as *u8, neg_reached, ctr)
253
254 // the rigid bind must show the rigid signature on BOTH numbers at once -- two independent
255 // signals, so a single accidental match cannot carry it
256 var rigid_sig: i64 = 0
257 if n_single == n_nv { if n_dom == MG_Q12 { if n_multi == 0 { rigid_sig = 1 } } }
258 // gv_bite(fired-on-bad, fired-on-good): the blend teeth must fire on the rigid fixture and stay
259 // silent on the real one. Passing the POSITIVE run's blend result as the good leg is the whole
260 // discrimination -- an inverted leg here would claim the detector fires on healthy input.
261 var good_leg: i64 = 0
262 if p_single == p_nv { good_leg = 1 }
263 gv_bite("neg-control-rigid-one-bone-bind-shows-the-rigid-signature-and-the-real-bind-does-not" as *u8, rigid_sig, good_leg, ctr)
264
265 return gv_verdict("NX-MESHRIG" as *u8, ctr, "blend is measured on both a real and a rigid bind, and only the real one blends" as *u8)
266}