nx_gltf2mesh_rig_gate.nx source
↩ module page · 582 lines · 32415 B
1// nx_gltf2mesh_rig_gate.nx -- THE GATE FOR R22, RIG-CARRYING glTF INGEST (contract g2_skin_weights).
2//
3// SUBJECT: the nx_gltf2mesh ELF, forked for real, asked for an .nxa output. The claim under test is
4// that a rigged glTF donor's SKELETON AND SKIN SURVIVE INGEST -- the exact thing nx_roundtrip measured
5// as lost on 2026-08-22 (9 named parts -> 1, 192 bytes = 8 x 24 dropped layer records, on every
6// rigged donor). So the load-bearing teeth read the emitted NXANIM01 back through INDEPENDENT
7// readers, not through the subject's own status line:
8// - nx_asset_floor_gate (a shipped, separately-written NXA reader) reports verts/tris/joints;
9// - nxa_find from nx_nxa.nx (the ONE checksum definition every NXA reader imports) verifies the
10// TOC and every section's payload checksum;
11// - this gate's own minimal TOC walk checks the SKIN/SKEL word lengths against what the donor's
12// vertex and joint counts REQUIRE (computed, never eyeballed) and sums every vertex's weights.
13//
14// FIXTURES ARE THE REAL DONORS, BY ABSOLUTE PATH, PLUS ONE FIXTURE ASSEMBLED AT RUNTIME: the
15// count-mismatch donor is nishi_being_walk.glb with ONE accessor's count patched (8180 -> 8189, same
16// text length so the glb stays well-formed). A hand-authored glb would test the fixture's authoring;
17// a patched real donor tests the subject. Outputs are UNLINKED AT SETUP -- a gate that is not
18// idempotent reports on its first run and lies about every run after (measured on this estate today).
19//
20// DERIVED EXPECTATIONS, QUOTED FROM THE DONORS' OWN JSON (read 2026-08-22, offset 20 of each glb):
21// nishi_being_walk.glb: POSITION count 8180, indices count 49080 (-> 16360 index triples), skins
22// [{"joints":[1..11]}], node 2 "Lsh" translation [-185,520,15] under node 1 "root" (no
23// translation) -> joint 1 binds at (-185, 520, 15) mm and joint 0 is the root (parent -1).
24// ⚠JOINT COUNT IS NO LONGER QUOTED FROM THIS DONOR -- see RG_WALK_JOINTS. Quoting a published
25// artifact freezes ITS vintage as the spec, and on 2026-08-26 the donor was republished with the
26// spec-correct FLOAT normals AND the emitter's current 11-joint rig, turning two teeth RED for a
27// reason that was never about the subject. The other expectations here (vertex/index counts, the
28// Lsh bind) are STRUCTURAL and unchanged by that republish; only the rig grew.
29// nishi-in-seedsan-proportions.glb: POSITION 6728, indices 40332 (-> 13444), joints [1..11],
30// node 2 "Lsh" translation [-65,520,15].
31// synth/elf.glb: skins ABSENT (skin_joints=0) -- the unskinned control.
32// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
33import "nx_syscalls.nx"
34import "nx_gate_verdict.nx"
35import "nx_tool_run.nx"
36import "nx_nxa.nx"
37
38const RG_SUBJECT_DEFAULT: *u8 = "/volume1/homes/elderwesto/nishihost/nx_gltf2mesh.elf"
39const RG_FLOOR_GATE: *u8 = "/volume1/homes/elderwesto/nishihost/nx_asset_floor_gate.elf"
40const RG_WALK: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/compare/vam/nishi_being_walk.glb"
41const RG_SEED: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/exceed/vrm/nishi-in-seedsan-proportions.glb"
42const RG_ELF: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/synth/elf.glb"
43
44const RG_DIR: *u8 = "/tmp/nx_gltf2mesh_rig_gate"
45const RG_WALK_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/walk.nxa"
46const RG_SEED_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/seed.nxa"
47const RG_ELF_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/elf.nxa"
48const RG_ELF_MSH: *u8 = "/tmp/nx_gltf2mesh_rig_gate/elf.nxmesh"
49const RG_MIS_GLB: *u8 = "/tmp/nx_gltf2mesh_rig_gate/mismatch.glb"
50const RG_MIS_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/mismatch.nxa"
51
52// donor-derived expectations (see header)
53const RG_WALK_VERTS: i64 = 8180
54const RG_WALK_TRIS: i64 = 16360
55// 2026-08-26 CORRECTED 9 -> 11, and the AUTHORITY CHANGED WITH IT. This was quoted from the PUBLISHED
56// donor on 2026-08-22; that donor was already behind its own emitter, so this gate had frozen a stale
57// artifact's vintage into a specification. The authority is nx_gltf_anim.nx's GA_NJ (11: root + L/R
58// shoulder,elbow,hip,knee + L/R ankle, debt 1785900993), corroborated by the sibling donor, which has
59// carried RG_SEED_JOINTS=11 and passed all along. A GATE THAT DERIVES ITS EXPECTATION FROM A MUTABLE
60// PUBLISHED ARTIFACT MEASURES THAT ARTIFACT'S AGE, NOT THE SUBJECT -- re-derive from the emitter.
61const RG_WALK_JOINTS: i64 = 11
62const RG_WALK_LSH_X: i64 = 0 - 185
63const RG_WALK_LSH_Y: i64 = 520
64const RG_WALK_LSH_Z: i64 = 15
65const RG_SEED_VERTS: i64 = 6728
66const RG_SEED_TRIS: i64 = 13444
67const RG_SEED_JOINTS: i64 = 11
68const RG_SEED_LSH_X: i64 = 0 - 65
69const RG_SEED_LSH_Y: i64 = 520
70const RG_SEED_LSH_Z: i64 = 15
71const RG_LSH_JOINT: i64 = 1 // joints[1] == node 2 == "Lsh" in both donors
72const RG_BIND_TOL_MM: i64 = 1 // f32 -> mm decode truncates below one unit; the donor values are whole mm
73
74// the count-mismatch patch: this substring is UNIQUE in nishi_being_walk.glb (bufferView 4 is WEIGHTS_0)
75const RG_MIS_ANCHOR: *u8 = "\x22bufferView\x22:4,\x22componentType\x22:5121,\x22normalized\x22:true,\x22count\x22:8180"
76const RG_MIS_FROM: i64 = 48 // '0' -- the last digit of 8180 ...
77const RG_MIS_TO: i64 = 57 // '9' -- ... becomes 8189: same length, a different count
78
79// ---- R22b (multi-skin union) fixtures ----
80const RG_VRM: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/exceed/vrm/seed-san.vrm"
81const RG_VRM_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/vrm.nxa"
82const RG_DIS_GLB: *u8 = "/tmp/nx_gltf2mesh_rig_gate/disjoint.glb"
83const RG_DIS_NXA: *u8 = "/tmp/nx_gltf2mesh_rig_gate/disjoint.nxa"
84// a structurally VALID glTF whose two skins share ZERO joints -- two characters in one file. It
85// must pass every per-primitive validation and reach the UNION connectivity check, or the tooth
86// would pass for the wrong reason; setup asserts the written size equals the computed total.
87const RG_DIS_JSON: *u8 = "{\x22asset\x22:{\x22version\x22:\x222.0\x22},\x22scene\x22:0,\x22scenes\x22:[{\x22nodes\x22:[0]}],\x22nodes\x22:[{\x22children\x22:[1,2,3,4,5,6]},{\x22name\x22:\x22jA0\x22},{\x22name\x22:\x22jA1\x22},{\x22name\x22:\x22jB0\x22},{\x22name\x22:\x22jB1\x22},{\x22mesh\x22:0,\x22skin\x22:0},{\x22mesh\x22:1,\x22skin\x22:1}],\x22meshes\x22:[{\x22primitives\x22:[{\x22attributes\x22:{\x22POSITION\x22:0,\x22JOINTS_0\x22:1,\x22WEIGHTS_0\x22:2},\x22indices\x22:3}]},{\x22primitives\x22:[{\x22attributes\x22:{\x22POSITION\x22:4,\x22JOINTS_0\x22:5,\x22WEIGHTS_0\x22:6},\x22indices\x22:7}]}],\x22skins\x22:[{\x22joints\x22:[1,2],\x22inverseBindMatrices\x22:8},{\x22joints\x22:[3,4],\x22inverseBindMatrices\x22:9}],\x22accessors\x22:[{\x22bufferView\x22:0,\x22componentType\x22:5126,\x22count\x22:3,\x22type\x22:\x22VEC3\x22},{\x22bufferView\x22:1,\x22componentType\x22:5121,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:2,\x22componentType\x22:5121,\x22normalized\x22:true,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:3,\x22componentType\x22:5123,\x22count\x22:3,\x22type\x22:\x22SCALAR\x22},{\x22bufferView\x22:4,\x22componentType\x22:5126,\x22count\x22:3,\x22type\x22:\x22VEC3\x22},{\x22bufferView\x22:5,\x22componentType\x22:5121,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:6,\x22componentType\x22:5121,\x22normalized\x22:true,\x22count\x22:3,\x22type\x22:\x22VEC4\x22},{\x22bufferView\x22:7,\x22componentType\x22:5123,\x22count\x22:3,\x22type\x22:\x22SCALAR\x22},{\x22bufferView\x22:8,\x22componentType\x22:5126,\x22count\x22:2,\x22type\x22:\x22MAT4\x22},{\x22bufferView\x22:9,\x22componentType\x22:5126,\x22count\x22:2,\x22type\x22:\x22MAT4\x22}],\x22bufferViews\x22:[{\x22buffer\x22:0,\x22byteOffset\x22:0,\x22byteLength\x22:36},{\x22buffer\x22:0,\x22byteOffset\x22:36,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:48,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:60,\x22byteLength\x22:6},{\x22buffer\x22:0,\x22byteOffset\x22:68,\x22byteLength\x22:36},{\x22buffer\x22:0,\x22byteOffset\x22:104,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:116,\x22byteLength\x22:12},{\x22buffer\x22:0,\x22byteOffset\x22:128,\x22byteLength\x22:6},{\x22buffer\x22:0,\x22byteOffset\x22:136,\x22byteLength\x22:128},{\x22buffer\x22:0,\x22byteOffset\x22:264,\x22byteLength\x22:128}],\x22buffers\x22:[{\x22byteLength\x22:392}]}"
88const RG_GLB_MAGIC: i64 = 1179937895 // 'g''l''T''F' little-endian
89const RG_GLB_VER: i64 = 2
90const RG_CH_JSON: i64 = 1313821514 // 'J''S''O''N'
91const RG_CH_BIN: i64 = 5130562 // 'B''I''N'0
92const RG_F32_ONE: i64 = 1065353216 // 1.0f bit pattern
93const RG_U8_FULL: i64 = 255 // normalized u8 weight 1.0
94const RG_DIS_BINLEN: i64 = 392
95const RG_GLB_HDR: i64 = 12
96const RG_CHUNK_HDR: i64 = 8
97const RG_ASCII_SP: i64 = 32
98const RG_ALIGN4: i64 = 4
99const RG_MAT4_BYTES_G: i64 = 64
100
101// NXA layout as read by EVERY shipping reader (nx_asset_floor_gate, nx_nxa_rig_emit, nx_nxa_check)
102const RG_NXA_NSEC_OFF: i64 = 16
103const RG_NXA_TOC_OFF: i64 = 32
104const RG_NXA_TOC_ROW: i64 = 32
105const RG_NXA_TOC_OFF_FIELD: i64 = 8
106const RG_NXA_TOC_WL_FIELD: i64 = 16
107const RG_TAG_BYTES: i64 = 4
108const RG_WORD: i64 = 8
109const RG_SKIN_WORDS: i64 = 8
110const RG_SKEL_WORDS: i64 = 8
111const RG_VEC4: i64 = 4
112const RG_Q12: i64 = 4096
113const RG_BYTE_RADIX: i64 = 256
114const RG_BYTE_MASK: i64 = 255
115const RG_MSH_HDR: i64 = 16
116const RG_MSH_LAYROW: i64 = 24
117const RG_MSH_TRIREC_PLUS_ID: i64 = 88 // 84-byte record + 4-byte per-tri layer id, as nx_gltf2mesh writes it
118const RG_MSH_NLAY_OFF: i64 = 8
119const RG_MSH_NTRI_OFF: i64 = 12
120const RG_U32: i64 = 4
121
122const RG_CAPTURE_CAP: i64 = 262144
123const RG_ARGV_SLOTS: i64 = 8
124const RG_MODE_DIR: i64 = 493
125const RG_ASCII_ZERO: i64 = 48
126const RG_ASCII_NINE: i64 = 57
127const RG_DECIMAL: i64 = 10
128const RG_EXEC_FAIL: i64 = 127
129
130func rg_rd64(b: *u8, off: i64) -> i64 {
131 var v: i64 = 0
132 var i: i64 = RG_WORD - 1
133 while i >= 0 { v = v*RG_BYTE_RADIX + ((b[off + i] & RG_BYTE_MASK) as i64); i = i - 1 }
134 return v
135}
136func rg_rd32(b: *u8, off: i64) -> i64 {
137 var v: i64 = 0
138 var i: i64 = RG_U32 - 1
139 while i >= 0 { v = v*RG_BYTE_RADIX + ((b[off + i] & RG_BYTE_MASK) as i64); i = i - 1 }
140 return v
141}
142func rg_tag_eq(b: *u8, off: i64, t: *u8) -> i64 {
143 var i: i64 = 0
144 while i < RG_TAG_BYTES { if b[off + i] != t[i] { return 0 } i = i + 1 }
145 return 1
146}
147// gate-side TOC walk: BYTE offset of a section's payload, and its declared wordlen via wl[0]; -1 absent
148func rg_sec(b: *u8, t: *u8, wl: *i64) -> i64 {
149 let ns: i64 = rg_rd64(b, RG_NXA_NSEC_OFF)
150 var s: i64 = 0
151 while s < ns {
152 let e: i64 = RG_NXA_TOC_OFF + s*RG_NXA_TOC_ROW
153 if rg_tag_eq(b, e, t) == 1 { wl[0] = rg_rd64(b, e + RG_NXA_TOC_WL_FIELD); return rg_rd64(b, e + RG_NXA_TOC_OFF_FIELD) }
154 s = s + 1
155 }
156 wl[0] = 0 - 1
157 return 0 - 1
158}
159func rg_exists(path: *u8) -> i64 {
160 let lp: *i64 = sys_mmap(RG_WORD*2) as *i64
161 let b: *u8 = sys_read_file(path, lp)
162 if (b as i64) == 0 { return 0 }
163 return 1
164}
165func rg_run(subject: *u8, a1: *u8, a2: *u8, out: *u8, outlen: *i64) -> i64 {
166 let av: *i64 = sys_mmap(RG_WORD*RG_ARGV_SLOTS) as *i64
167 av[0] = subject as i64
168 av[1] = a1 as i64
169 av[2] = a2 as i64
170 av[3] = 0
171 return tr_run_capture(subject, av, out, RG_CAPTURE_CAP, outlen)
172}
173// first decimal number following `key` in buf[0..n); -1 when absent
174func rg_num_after(buf: *u8, n: i64, key: *u8) -> i64 {
175 var kl: i64 = 0
176 while key[kl] != (0 as u8) { kl = kl + 1 }
177 var i: i64 = 0
178 while i + kl <= n {
179 var m: i64 = 1
180 var k: i64 = 0
181 while k < kl { if buf[i + k] != key[k] { m = 0; k = kl } k = k + 1 }
182 if m == 1 {
183 var o: i64 = i + kl
184 var v: i64 = 0
185 var d: i64 = 0
186 var go: i64 = 1
187 while go == 1 {
188 if o >= n { go = 0 } else {
189 let c: i64 = (buf[o] & RG_BYTE_MASK) as i64
190 if c < RG_ASCII_ZERO { go = 0 }
191 if c > RG_ASCII_NINE { go = 0 }
192 if go == 1 { v = v*RG_DECIMAL + (c - RG_ASCII_ZERO); d = d + 1; o = o + 1 }
193 }
194 }
195 if d > 0 { return v }
196 return 0 - 1
197 }
198 i = i + 1
199 }
200 return 0 - 1
201}
202// find `lit` in b[0..n); returns offset or -1, and counts occurrences via cnt[0]
203func rg_find_all(b: *u8, n: i64, lit: *u8, cnt: *i64) -> i64 {
204 var ll: i64 = 0
205 while lit[ll] != (0 as u8) { ll = ll + 1 }
206 var first: i64 = 0 - 1
207 cnt[0] = 0
208 var i: i64 = 0
209 while i + ll <= n {
210 var m: i64 = 1
211 var k: i64 = 0
212 while k < ll { if b[i + k] != lit[k] { m = 0; k = ll } k = k + 1 }
213 if m == 1 { cnt[0] = cnt[0] + 1; if first < 0 { first = i } }
214 i = i + 1
215 }
216 return first
217}
218func rg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
219func rg_wr32le(b: *u8, o: i64, v: i64) -> i64 {
220 b[o] = (v & RG_BYTE_MASK) as u8
221 b[o+1] = ((v >> 8) & RG_BYTE_MASK) as u8
222 b[o+2] = ((v >> 16) & RG_BYTE_MASK) as u8
223 b[o+3] = ((v >> 24) & RG_BYTE_MASK) as u8
224 return 0
225}
226// assemble the disjoint-skins GLB at runtime (a fixture in SOURCE would arm every source scanner).
227// BIN layout, hand-summed and asserted by the caller: POS0@0(36) J0@36(12) W0@48(12) IDX0@60(6)+pad
228// POS1@68(36) J1@104(12) W1@116(12) IDX1@128(6)+pad IBM0@136(128) IBM1@264(128) = 392.
229func rg_write_disjoint(path: *u8) -> i64 {
230 var jlen: i64 = 0
231 while RG_DIS_JSON[jlen] != (0 as u8) { jlen = jlen + 1 }
232 let jpad: i64 = (jlen + RG_ALIGN4 - 1)/RG_ALIGN4*RG_ALIGN4
233 let total: i64 = RG_GLB_HDR + RG_CHUNK_HDR + jpad + RG_CHUNK_HDR + RG_DIS_BINLEN
234 let b: *u8 = sys_mmap(total)
235 var z: i64 = 0
236 while z < total { b[z] = 0; z = z + 1 }
237 rg_wr32le(b, 0, RG_GLB_MAGIC)
238 rg_wr32le(b, 4, RG_GLB_VER)
239 rg_wr32le(b, 8, total)
240 rg_wr32le(b, RG_GLB_HDR, jpad)
241 rg_wr32le(b, RG_GLB_HDR + 4, RG_CH_JSON)
242 var i: i64 = 0
243 while i < jlen { b[RG_GLB_HDR + RG_CHUNK_HDR + i] = RG_DIS_JSON[i]; i = i + 1 }
244 while i < jpad { b[RG_GLB_HDR + RG_CHUNK_HDR + i] = RG_ASCII_SP as u8; i = i + 1 }
245 let bh: i64 = RG_GLB_HDR + RG_CHUNK_HDR + jpad
246 rg_wr32le(b, bh, RG_DIS_BINLEN)
247 rg_wr32le(b, bh + 4, RG_CH_BIN)
248 let bb: i64 = bh + RG_CHUNK_HDR
249 // two triangles, height 1.0 m along y (the unit sniffer needs 100..99999 mm)
250 rg_wr32le(b, bb + 16, RG_F32_ONE)
251 rg_wr32le(b, bb + 24, RG_F32_ONE)
252 rg_wr32le(b, bb + 68 + 16, RG_F32_ONE)
253 rg_wr32le(b, bb + 68 + 24, RG_F32_ONE)
254 // weights: slot0 = 1.0 for each of 3 verts, both meshes
255 b[bb + 48] = RG_U8_FULL as u8
256 b[bb + 52] = RG_U8_FULL as u8
257 b[bb + 56] = RG_U8_FULL as u8
258 b[bb + 116] = RG_U8_FULL as u8
259 b[bb + 120] = RG_U8_FULL as u8
260 b[bb + 124] = RG_U8_FULL as u8
261 // indices u16 0,1,2 both meshes
262 b[bb + 62] = 1 as u8
263 b[bb + 64] = 2 as u8
264 b[bb + 130] = 1 as u8
265 b[bb + 132] = 2 as u8
266 // four identity IBMs at 136,200,264,328
267 var m: i64 = 0
268 while m < 4 {
269 let mb: i64 = bb + 136 + m*RG_MAT4_BYTES_G
270 rg_wr32le(b, mb, RG_F32_ONE)
271 rg_wr32le(b, mb + 20, RG_F32_ONE)
272 rg_wr32le(b, mb + 40, RG_F32_ONE)
273 rg_wr32le(b, mb + 60, RG_F32_ONE)
274 m = m + 1
275 }
276 let fd: i64 = sys_openat_wr(path, MODE_0644)
277 if fd < 0 { return 0 - 1 }
278 let wr: i64 = sys_write(fd, b, total)
279 sys_close(fd)
280 if wr != total { return 0 - 1 }
281 return total
282}
283// run the independent reader (nx_asset_floor_gate) on an NXA and harvest verts/tris/joints into r[0..2]
284func rg_floor_read(path: *u8, r: *i64, cap: *u8, olen: *i64) -> i64 {
285 let av: *i64 = sys_mmap(RG_WORD*RG_ARGV_SLOTS) as *i64
286 av[0] = RG_FLOOR_GATE as i64
287 av[1] = path as i64
288 av[2] = 0
289 let rc: i64 = tr_run_capture(RG_FLOOR_GATE, av, cap, RG_CAPTURE_CAP, olen)
290 r[0] = rg_num_after(cap, olen[0], "verts=" as *u8)
291 r[1] = rg_num_after(cap, olen[0], "tris=" as *u8)
292 r[2] = rg_num_after(cap, olen[0], "joints=" as *u8)
293 return rc
294}
295// every vertex's four weights sum to exactly 4096 and name a joint below nj; st[0]=worst dev st[1]=bad
296func rg_skin_audit(b: *u8, ko: i64, nv: i64, nj: i64, st: *i64) -> i64 {
297 st[0] = 0
298 st[1] = 0
299 let cnt: i64 = rg_rd64(b, ko)
300 if cnt != nv { st[1] = nv; return 0 }
301 var v: i64 = 0
302 while v < nv {
303 let rec: i64 = ko + RG_WORD + v*RG_SKIN_WORDS*RG_WORD
304 var sum: i64 = 0
305 var s: i64 = 0
306 var ok: i64 = 1
307 while s < RG_VEC4 {
308 let j: i64 = rg_rd64(b, rec + s*RG_WORD)
309 if j < 0 { ok = 0 }
310 if j >= nj { ok = 0 }
311 sum = sum + rg_rd64(b, rec + (RG_VEC4 + s)*RG_WORD)
312 s = s + 1
313 }
314 let dev: i64 = rg_abs(sum - RG_Q12)
315 if dev > st[0] { st[0] = dev }
316 if dev != 0 { ok = 0 }
317 if ok == 0 { st[1] = st[1] + 1 }
318 v = v + 1
319 }
320 if st[1] == 0 { return 1 }
321 return 0
322}
323
324func main(argc: i64, argv: *i64) -> i64 {
325 let ctr: *i64 = gv_ctr()
326 gv_head("nx_gltf2mesh_rig gate -- a rigged glTF donor's skeleton and skin SURVIVE ingest into NXANIM01" as *u8)
327 var subject: *u8 = RG_SUBJECT_DEFAULT
328 if argc >= 2 { subject = argv[1] as *u8 }
329 gv_puts(" subject: " as *u8); gv_puts(subject); gv_puts("\n" as *u8)
330 gv_puts(" independent reader: " as *u8); gv_puts(RG_FLOOR_GATE); gv_puts("\n\n" as *u8)
331
332 // ---- SETUP: mkdir at setup (a teardown does not run when a run crashes); unlink every output
333 sys_mkdir(RG_DIR, RG_MODE_DIR)
334 sys_unlinkat(RG_WALK_NXA)
335 sys_unlinkat(RG_SEED_NXA)
336 sys_unlinkat(RG_ELF_NXA)
337 sys_unlinkat(RG_ELF_MSH)
338 sys_unlinkat(RG_MIS_GLB)
339 sys_unlinkat(RG_MIS_NXA)
340 sys_unlinkat(RG_VRM_NXA)
341 sys_unlinkat(RG_DIS_NXA)
342 sys_unlinkat(RG_DIS_GLB)
343 var clean: i64 = 0
344 if rg_exists(RG_WALK_NXA) == 0 { if rg_exists(RG_ELF_NXA) == 0 { if rg_exists(RG_MIS_NXA) == 0 { clean = 1 } } }
345 gv_check("setup-outputs-absent-before-measuring (gate is idempotent)" as *u8, clean, ctr)
346 var donors: i64 = 0
347 if rg_exists(RG_WALK) == 1 { if rg_exists(RG_SEED) == 1 { if rg_exists(RG_ELF) == 1 { donors = 1 } } }
348 gv_check("setup-real-donors-readable (walk, seedsan, elf)" as *u8, donors, ctr)
349 // the count-mismatch fixture: patch ONE accessor count in a copy of the real donor
350 let lp: *i64 = sys_mmap(RG_WORD*2) as *i64
351 let gb: *u8 = sys_read_file(RG_WALK, lp)
352 let gn: i64 = lp[0]
353 let cnt: *i64 = sys_mmap(RG_WORD*2) as *i64
354 var fixture_ok: i64 = 0
355 if (gb as i64) != 0 {
356 let at: i64 = rg_find_all(gb, gn, RG_MIS_ANCHOR, cnt)
357 if at >= 0 { if cnt[0] == 1 {
358 var al: i64 = 0
359 while RG_MIS_ANCHOR[al] != (0 as u8) { al = al + 1 }
360 let digit: i64 = at + al - 1
361 if (gb[digit] as i64) == RG_MIS_FROM {
362 gb[digit] = RG_MIS_TO as u8
363 let fd: i64 = sys_openat_wr(RG_MIS_GLB, MODE_0644)
364 if fd >= 0 {
365 let wr: i64 = sys_write(fd, gb, gn)
366 sys_close(fd)
367 if wr == gn { fixture_ok = 1 }
368 }
369 }
370 } }
371 }
372 // ASSERT THE FIXTURE REACHED THE CONDITION: the anchor was unique, the byte flipped, the copy landed
373 gv_check("setup-count-mismatch-fixture-assembled (WEIGHTS_0 count 8180 -> 8189, same length, unique anchor)" as *u8, fixture_ok, ctr)
374
375 let cap: *u8 = sys_mmap(RG_CAPTURE_CAP)
376 let olen: *i64 = sys_mmap(RG_WORD*2) as *i64
377 let r: *i64 = sys_mmap(RG_WORD*4) as *i64
378 let wl: *i64 = sys_mmap(RG_WORD*2) as *i64
379 let st: *i64 = sys_mmap(RG_WORD*4) as *i64
380
381 // ---- T1: the rigged donor converts to .nxa
382 let rc1: i64 = rg_run(subject, RG_WALK, RG_WALK_NXA, cap, olen)
383 gv_puts(" [T1] walk.glb -> walk.nxa rc=" as *u8); gv_num(rc1); gv_puts("\n" as *u8)
384 var t1: i64 = 0
385 if rc1 == 0 { if rg_exists(RG_WALK_NXA) == 1 { t1 = 1 } }
386 gv_check("rigged-donor-converts-to-nxa" as *u8, t1, ctr)
387
388 // ---- T2: the INDEPENDENT reader sees the rig: joints == the donor's skins[].joints count
389 let frc: i64 = rg_floor_read(RG_WALK_NXA, r, cap, olen)
390 gv_puts(" [T2] nx_asset_floor_gate read: verts=" as *u8); gv_num(r[0]); gv_puts(" tris=" as *u8); gv_num(r[1]); gv_puts(" joints=" as *u8); gv_num(r[2]); gv_puts(" (reader rc=" as *u8); gv_num(frc); gv_puts(")\n" as *u8)
391 var t2: i64 = 0
392 if r[2] == RG_WALK_JOINTS { t2 = 1 }
393 gv_check("independent-reader-sees-11-joints (the rig SURVIVED ingest)" as *u8, t2, ctr)
394 var t2b: i64 = 0
395 if r[0] == RG_WALK_VERTS { if r[1] == RG_WALK_TRIS { t2b = 1 } }
396 gv_check("independent-reader-sees-donor-vertex-and-index-triple-counts (8180 / 16360)" as *u8, t2b, ctr)
397
398 // ---- T3: second rigged donor, 11 joints
399 let rc3: i64 = rg_run(subject, RG_SEED, RG_SEED_NXA, cap, olen)
400 let frc3: i64 = rg_floor_read(RG_SEED_NXA, r, cap, olen)
401 gv_puts(" [T3] seedsan rc=" as *u8); gv_num(rc3); gv_puts(" reader: verts=" as *u8); gv_num(r[0]); gv_puts(" tris=" as *u8); gv_num(r[1]); gv_puts(" joints=" as *u8); gv_num(r[2]); gv_puts(" (reader rc=" as *u8); gv_num(frc3); gv_puts(")\n" as *u8)
402 var t3: i64 = 0
403 if rc3 == 0 { if r[2] == RG_SEED_JOINTS { if r[0] == RG_SEED_VERTS { if r[1] == RG_SEED_TRIS { t3 = 1 } } } }
404 gv_check("second-rigged-donor-11-joints-6728-verts-13444-triples" as *u8, t3, ctr)
405
406 // ---- T4..T7: read walk.nxa back with this gate's own TOC walk and with nxa_find (checksums)
407 let nb: *u8 = sys_read_file(RG_WALK_NXA, lp)
408 let nn: i64 = lp[0]
409 var ko: i64 = 0 - 1
410 var so: i64 = 0 - 1
411 var kwl: i64 = 0
412 var swl: i64 = 0
413 if (nb as i64) != 0 {
414 ko = rg_sec(nb, "SKIN" as *u8, wl); kwl = wl[0]
415 so = rg_sec(nb, "SKEL" as *u8, wl); swl = wl[0]
416 }
417 let need_kwl: i64 = 1 + RG_WALK_VERTS*RG_SKIN_WORDS
418 let need_swl: i64 = 1 + RG_WALK_JOINTS*RG_SKEL_WORDS
419 gv_puts(" [T4] SKIN wordlen=" as *u8); gv_num(kwl); gv_puts(" required=" as *u8); gv_num(need_kwl)
420 gv_puts(" | SKEL wordlen=" as *u8); gv_num(swl); gv_puts(" required=" as *u8); gv_num(need_swl); gv_puts("\n" as *u8)
421 var t4: i64 = 0
422 if kwl == need_kwl { if swl == need_swl { t4 = 1 } }
423 gv_check("anti-vacuity-SKIN-and-SKEL-wordlens-equal-what-the-donor-counts-REQUIRE (computed)" as *u8, t4, ctr)
424
425 var t5: i64 = 0
426 if ko >= 0 { t5 = rg_skin_audit(nb, ko, RG_WALK_VERTS, RG_WALK_JOINTS, st) }
427 gv_puts(" [T5] weights audited over ALL " as *u8); gv_num(RG_WALK_VERTS); gv_puts(" vertices: worst |sum-4096|=" as *u8); gv_num(st[0]); gv_puts(" bad_vertices=" as *u8); gv_num(st[1]); gv_puts("\n" as *u8)
428 gv_check("every-vertex-weights-sum-exactly-4096-and-name-a-joint-below-11 (full population, no sampling)" as *u8, t5, ctr)
429
430 // T6: parent column was READ from the hierarchy: joint 0 is the root (-1), every other parent in range
431 var t6: i64 = 0
432 if so >= 0 {
433 let p0: i64 = rg_rd64(nb, so + RG_WORD)
434 var okp: i64 = 1
435 var roots: i64 = 0
436 var j: i64 = 0
437 while j < RG_WALK_JOINTS {
438 let pj: i64 = rg_rd64(nb, so + RG_WORD + j*RG_SKEL_WORDS*RG_WORD)
439 if pj < 0 { roots = roots + 1 } else { if pj >= RG_WALK_JOINTS { okp = 0 } if pj == j { okp = 0 } }
440 j = j + 1
441 }
442 gv_puts(" [T6] SKEL parent[0]=" as *u8); gv_num(p0); gv_puts(" roots=" as *u8); gv_num(roots); gv_puts("\n" as *u8)
443 if p0 < 0 { if roots == 1 { if okp == 1 { t6 = 1 } } }
444 }
445 gv_check("skel-parents-read-from-node-hierarchy (one root, every other parent in range, none its own)" as *u8, t6, ctr)
446
447 // T7: bind position came from inverseBindMatrices: joint 1 ("Lsh") sits at (-185,520,15) mm
448 var t7: i64 = 0
449 if so >= 0 {
450 let e1: i64 = so + RG_WORD + RG_LSH_JOINT*RG_SKEL_WORDS*RG_WORD
451 let bx: i64 = rg_rd64(nb, e1 + RG_WORD)
452 let by: i64 = rg_rd64(nb, e1 + 2*RG_WORD)
453 let bz: i64 = rg_rd64(nb, e1 + 3*RG_WORD)
454 gv_puts(" [T7] SKEL joint1 bind=(" as *u8); gv_num(bx); gv_puts("," as *u8); gv_num(by); gv_puts("," as *u8); gv_num(bz); gv_puts(") mm, donor Lsh translation (-185,520,15)\n" as *u8)
455 if rg_abs(bx - RG_WALK_LSH_X) <= RG_BIND_TOL_MM { if rg_abs(by - RG_WALK_LSH_Y) <= RG_BIND_TOL_MM { if rg_abs(bz - RG_WALK_LSH_Z) <= RG_BIND_TOL_MM { t7 = 1 } } }
456 }
457 gv_check("bind-position-from-inverseBindMatrices-matches-the-donor-hierarchy (two witnesses agree)" as *u8, t7, ctr)
458 // same on the second donor -- a coincidence on one file is not a derivation
459 var t7b: i64 = 0
460 let sb: *u8 = sys_read_file(RG_SEED_NXA, lp)
461 if (sb as i64) != 0 {
462 let so2: i64 = rg_sec(sb, "SKEL" as *u8, wl)
463 if so2 >= 0 {
464 let e2: i64 = so2 + RG_WORD + RG_LSH_JOINT*RG_SKEL_WORDS*RG_WORD
465 let bx2: i64 = rg_rd64(sb, e2 + RG_WORD)
466 let by2: i64 = rg_rd64(sb, e2 + 2*RG_WORD)
467 let bz2: i64 = rg_rd64(sb, e2 + 3*RG_WORD)
468 gv_puts(" [T7b] seedsan joint1 bind=(" as *u8); gv_num(bx2); gv_puts("," as *u8); gv_num(by2); gv_puts("," as *u8); gv_num(bz2); gv_puts(") mm, donor Lsh translation (-65,520,15)\n" as *u8)
469 if rg_abs(bx2 - RG_SEED_LSH_X) <= RG_BIND_TOL_MM { if rg_abs(by2 - RG_SEED_LSH_Y) <= RG_BIND_TOL_MM { if rg_abs(bz2 - RG_SEED_LSH_Z) <= RG_BIND_TOL_MM { t7b = 1 } } }
470 }
471 }
472 gv_check("bind-position-derivation-holds-on-the-second-donor-too" as *u8, t7b, ctr)
473
474 // T8: checksums -- nxa_find (the shared definition) verifies TOC + every payload before answering
475 var t8: i64 = 0
476 if (nb as i64) != 0 {
477 let fv: i64 = nxa_find(nb, nn, nxa_tag4("VERT" as *u8))
478 let ft: i64 = nxa_find(nb, nn, nxa_tag4("TRIS" as *u8))
479 let fs: i64 = nxa_find(nb, nn, nxa_tag4("SKEL" as *u8))
480 let fk: i64 = nxa_find(nb, nn, nxa_tag4("SKIN" as *u8))
481 gv_puts(" [T8] nxa_find word offsets: VERT=" as *u8); gv_num(fv); gv_puts(" TRIS=" as *u8); gv_num(ft); gv_puts(" SKEL=" as *u8); gv_num(fs); gv_puts(" SKIN=" as *u8); gv_num(fk); gv_puts(" (negative = missing/corrupt)\n" as *u8)
482 if fv >= 0 { if ft >= 0 { if fs >= 0 { if fk >= 0 { t8 = 1 } } } }
483 }
484 gv_check("toc-and-every-section-checksum-verify-via-the-shared-nxa_find" as *u8, t8, ctr)
485
486 // ---- T9/T10: THE BITE PAIR. Unskinned donor asked for .nxa must be REFUSED and write nothing;
487 // the same donor asked for .nxmesh must still produce a valid NXMSH2 (the legacy path intact).
488 let rc9: i64 = rg_run(subject, RG_ELF, RG_ELF_NXA, cap, olen)
489 gv_puts(" [T9] elf.glb -> elf.nxa rc=" as *u8); gv_num(rc9); gv_puts("\n" as *u8)
490 var refused: i64 = 0
491 if rc9 != 0 { if rg_exists(RG_ELF_NXA) == 0 { refused = 1 } }
492 gv_check("unskinned-donor-refused-for-nxa-AND-writes-no-output" as *u8, refused, ctr)
493 let rc10: i64 = rg_run(subject, RG_ELF, RG_ELF_MSH, cap, olen)
494 var t10: i64 = 0
495 let mb: *u8 = sys_read_file(RG_ELF_MSH, lp)
496 let mn: i64 = lp[0]
497 if rc10 == 0 { if (mb as i64) != 0 {
498 let nlay: i64 = rg_rd32(mb, RG_MSH_NLAY_OFF)
499 let ntri: i64 = rg_rd32(mb, RG_MSH_NTRI_OFF)
500 let need: i64 = RG_MSH_HDR + nlay*RG_MSH_LAYROW + ntri*RG_MSH_TRIREC_PLUS_ID
501 gv_puts(" [T10] elf.nxmesh rc=" as *u8); gv_num(rc10); gv_puts(" layers=" as *u8); gv_num(nlay); gv_puts(" tris=" as *u8); gv_num(ntri); gv_puts(" bytes=" as *u8); gv_num(mn); gv_puts(" arithmetic=" as *u8); gv_num(need); gv_puts("\n" as *u8)
502 if nlay == 1 { if ntri > 0 { if mn == need { t10 = 1 } } }
503 } }
504 gv_check("unskinned-donor-still-produces-a-consistent-single-layer-NXMSH2 (legacy path intact)" as *u8, t10, ctr)
505 var good_fired: i64 = 1
506 if rc1 == 0 { good_fired = 0 }
507 gv_bite("neg-control-nxa-refused-for-unskinned-donor-and-produced-for-rigged-donor" as *u8, refused, good_fired, ctr)
508
509 // ---- T11: WEIGHTS_0 count disagreeing with POSITION count is REFUSED by name, no output
510 let rc11: i64 = rg_run(subject, RG_MIS_GLB, RG_MIS_NXA, cap, olen)
511 gv_puts(" [T11] mismatch.glb -> .nxa rc=" as *u8); gv_num(rc11); gv_puts("\n" as *u8)
512 var t11: i64 = 0
513 if rc11 != 0 { if rg_exists(RG_MIS_NXA) == 0 {
514 // BY NAME: the refusal text must name the actual conjunct, not merely exit nonzero
515 let hit: i64 = rg_find_all(cap, olen[0], "WEIGHTS_0 count differs from POSITION count" as *u8, cnt)
516 if hit >= 0 { t11 = 1 }
517 } }
518 gv_check("weights-count-mismatch-refused-BY-NAME-and-writes-no-output" as *u8, t11, ctr)
519
520 // ---- T13: THE VROID CASE (R22b). A VRM's skins (one per mesh) UNION into one SKEL; the
521 // independent reader must see exactly the union count the subject claims. Anti-vacuity: the
522 // fixture must actually be multi-skin (skins_used >= 2) or the union was never exercised.
523 let rc13: i64 = rg_run(subject, RG_VRM, RG_VRM_NXA, cap, olen)
524 let su: i64 = rg_num_after(cap, olen[0], "\x22skins_used\x22:" as *u8)
525 let uj: i64 = rg_num_after(cap, olen[0], "\x22skin_joints_union\x22:" as *u8)
526 let jr: i64 = rg_num_after(cap, olen[0], "\x22joints_remapped\x22:" as *u8)
527 let rdrop: i64 = rg_num_after(cap, olen[0], "\x22bind_rot_dropped_joints\x22:" as *u8)
528 gv_puts(" [T13] seed-san.vrm rc=" as *u8); gv_num(rc13)
529 gv_puts(" skins_used=" as *u8); gv_num(su)
530 gv_puts(" union=" as *u8); gv_num(uj)
531 gv_puts(" remapped=" as *u8); gv_num(jr)
532 gv_puts(" rot_dropped=" as *u8); gv_num(rdrop); gv_puts("\n" as *u8)
533 var t13a: i64 = 0
534 if rc13 == 0 { if su >= 2 { t13a = 1 } }
535 gv_check("vrm-multi-skin-donor-converts-AND-fixture-is-really-multi-skin (skins_used >= 2)" as *u8, t13a, ctr)
536 let frc13: i64 = rg_floor_read(RG_VRM_NXA, r, cap, olen)
537 gv_puts(" [T13b] reader: verts=" as *u8); gv_num(r[0]); gv_puts(" tris=" as *u8); gv_num(r[1]); gv_puts(" joints=" as *u8); gv_num(r[2]); gv_puts(" (reader rc=" as *u8); gv_num(frc13); gv_puts(")\n" as *u8)
538 var t13b: i64 = 0
539 if uj > 0 { if r[2] == uj { t13b = 1 } }
540 gv_check("independent-reader-joints-equal-the-declared-union (measured, not assumed)" as *u8, t13b, ctr)
541
542 // ---- T14: FULL-POPULATION audit of the union SKIN: every vertex sums to exactly 4096 and
543 // every stored joint index is below the union count -- the remap cannot have leaked a local
544 // index past the SKEL.
545 var t14: i64 = 0
546 let vb2: *u8 = sys_read_file(RG_VRM_NXA, lp)
547 if (vb2 as i64) != 0 {
548 let ko2: i64 = rg_sec(vb2, "SKIN" as *u8, wl)
549 if ko2 >= 0 { t14 = rg_skin_audit(vb2, ko2, r[0], r[2], st) }
550 }
551 gv_puts(" [T14] union skin audited over ALL " as *u8); gv_num(r[0]); gv_puts(" vertices: worst |sum-4096|=" as *u8); gv_num(st[0]); gv_puts(" bad=" as *u8); gv_num(st[1]); gv_puts("\n" as *u8)
552 gv_check("union-skin-full-population-weights-4096-and-indices-below-union-count" as *u8, t14, ctr)
553
554 // ---- T15: THE DISJOINT BITE. Two skins sharing ZERO joints are two characters, not one; the
555 // subject must refuse BY NAME and write nothing, while the genuine multi-skin VRM converts.
556 let dw: i64 = rg_write_disjoint(RG_DIS_GLB)
557 gv_puts(" [T15] disjoint fixture bytes=" as *u8); gv_num(dw); gv_puts("\n" as *u8)
558 var fix15: i64 = 0
559 if dw > 0 { fix15 = 1 }
560 gv_check("setup-disjoint-two-skin-glb-assembled-at-runtime" as *u8, fix15, ctr)
561 let rc15: i64 = rg_run(subject, RG_DIS_GLB, RG_DIS_NXA, cap, olen)
562 gv_puts(" [T15] disjoint.glb -> .nxa rc=" as *u8); gv_num(rc15); gv_puts("\n" as *u8)
563 var dis_refused: i64 = 0
564 if rc15 != 0 { if rg_exists(RG_DIS_NXA) == 0 {
565 let hit15: i64 = rg_find_all(cap, olen[0], "do not share a skeleton" as *u8, cnt)
566 if hit15 >= 0 { dis_refused = 1 }
567 } }
568 gv_check("disjoint-skins-refused-BY-NAME-and-writes-no-output" as *u8, dis_refused, ctr)
569 var vrm_missed: i64 = 1
570 if rc13 == 0 { vrm_missed = 0 }
571 gv_bite("neg-control-disjoint-skeletons-refused-and-shared-skeleton-union-accepted" as *u8, dis_refused, vrm_missed, ctr)
572
573 // ---- T12: the subject actually executed (not 127, not a harness sentinel)
574 var ran: i64 = 1
575 if rc1 < 0 { ran = 0 }
576 if rc1 == RG_EXEC_FAIL { ran = 0 }
577 gv_check("neg-control-subject-actually-executed (not 127, not a harness sentinel)" as *u8, ran, ctr)
578
579 let rc: i64 = gv_verdict("GLTF2MESH-RIG" as *u8, ctr, "the donor's skeleton and skin survive ingest, read back by an independent reader, bitten both ways" as *u8)
580 sys_exit(rc)
581 return rc
582}