@forgeax/engine-runtime 0.1.3 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (606) hide show
  1. package/README.md +49 -83
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts +2 -0
  4. package/dist/__tests__/animation-graph-collect-roundtrip.test.d.ts.map +1 -0
  5. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts +2 -0
  6. package/dist/__tests__/animation-graph-serialize.unit.test.d.ts.map +1 -0
  7. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts +2 -0
  8. package/dist/__tests__/asset-brand-and-name-retirement.test.d.ts.map +1 -0
  9. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts +11 -0
  10. package/dist/__tests__/asset-error-exhaustive.test-d.d.ts.map +1 -0
  11. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts +2 -0
  12. package/dist/__tests__/asset-registry-guid-reverse.test.d.ts.map +1 -0
  13. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts +2 -0
  14. package/dist/__tests__/asset-registry-hdr-equirect.test.d.ts.map +1 -0
  15. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts +2 -0
  16. package/dist/__tests__/asset-registry-mesh-pack-payload.dawn.test.d.ts.map +1 -0
  17. package/dist/__tests__/asset-registry-mounts.test.d.ts +2 -0
  18. package/dist/__tests__/asset-registry-mounts.test.d.ts.map +1 -0
  19. package/dist/__tests__/asset-registry.browser.test.d.ts +2 -0
  20. package/dist/__tests__/asset-registry.browser.test.d.ts.map +1 -0
  21. package/dist/__tests__/asset-registry.dawn.test.d.ts +2 -0
  22. package/dist/__tests__/asset-registry.dawn.test.d.ts.map +1 -0
  23. package/dist/__tests__/asset-registry.listCatalog.test.d.ts +2 -0
  24. package/dist/__tests__/asset-registry.listCatalog.test.d.ts.map +1 -0
  25. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts +2 -0
  26. package/dist/__tests__/asset-registry.mesh-bin.test.d.ts.map +1 -0
  27. package/dist/__tests__/asset-registry.pack-cache.test.d.ts +2 -0
  28. package/dist/__tests__/asset-registry.pack-cache.test.d.ts.map +1 -0
  29. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts +2 -0
  30. package/dist/__tests__/asset-registry.raw-container-failfast.test.d.ts.map +1 -0
  31. package/dist/__tests__/asset-registry.recursive.spec.d.ts +2 -0
  32. package/dist/__tests__/asset-registry.recursive.spec.d.ts.map +1 -0
  33. package/dist/__tests__/asset-registry.unit.test.d.ts +2 -0
  34. package/dist/__tests__/asset-registry.unit.test.d.ts.map +1 -0
  35. package/dist/__tests__/asset.unit.test.d.ts +2 -0
  36. package/dist/__tests__/asset.unit.test.d.ts.map +1 -0
  37. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts +2 -0
  38. package/dist/__tests__/audio-load-by-guid.unit.test.d.ts.map +1 -0
  39. package/dist/__tests__/backend-selection.integration.test.d.ts +2 -0
  40. package/dist/__tests__/backend-selection.integration.test.d.ts.map +1 -0
  41. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts +2 -0
  42. package/dist/__tests__/basis-catalog-dispatch.integration.test.d.ts.map +1 -0
  43. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts +2 -0
  44. package/dist/__tests__/builtin-asset-registry.unit.test.d.ts.map +1 -0
  45. package/dist/__tests__/collect-scene-asset.test.d.ts +1 -2
  46. package/dist/__tests__/collect-scene-asset.test.d.ts.map +1 -1
  47. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts +2 -0
  48. package/dist/__tests__/collect-scene-mount-collapse.test.d.ts.map +1 -0
  49. package/dist/__tests__/collect-transient-roundtrip.test.d.ts +1 -1
  50. package/dist/__tests__/collect-transient-roundtrip.test.d.ts.map +1 -1
  51. package/dist/__tests__/collect-transient-skip.test.d.ts +1 -2
  52. package/dist/__tests__/collect-transient-skip.test.d.ts.map +1 -1
  53. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts +2 -0
  54. package/dist/__tests__/compressed-texture-physical-extent.integration.test.d.ts.map +1 -0
  55. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts +2 -0
  56. package/dist/__tests__/dawn/mesh-update-dawn.test.d.ts.map +1 -0
  57. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts +2 -0
  58. package/dist/__tests__/dawn/upload-texture.dawn.test.d.ts.map +1 -0
  59. package/dist/__tests__/draw-published.d.ts +2 -2
  60. package/dist/__tests__/draw-published.d.ts.map +1 -1
  61. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts +2 -0
  62. package/dist/__tests__/dynamic-texture-store.unit.test.d.ts.map +1 -0
  63. package/dist/__tests__/errors.unit.test.d.ts +2 -0
  64. package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
  65. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts +2 -0
  66. package/dist/__tests__/extract-skin-mismatch.unit.test.d.ts.map +1 -0
  67. package/dist/__tests__/fetch-binary-decompress.test.d.ts +2 -0
  68. package/dist/__tests__/fetch-binary-decompress.test.d.ts.map +1 -0
  69. package/dist/__tests__/four-path-compression.integration.test.d.ts +2 -0
  70. package/dist/__tests__/four-path-compression.integration.test.d.ts.map +1 -0
  71. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts +2 -0
  72. package/dist/__tests__/fullscreen-feature-host.dawn.test.d.ts.map +1 -0
  73. package/dist/__tests__/guid-for-asset.unit.test.d.ts +2 -0
  74. package/dist/__tests__/guid-for-asset.unit.test.d.ts.map +1 -0
  75. package/dist/__tests__/handle-migration.test.d.ts +2 -0
  76. package/dist/__tests__/handle-migration.test.d.ts.map +1 -0
  77. package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
  78. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts +2 -0
  79. package/dist/__tests__/host-custom-kind-contract.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/host-custom-kind-contract.test.d.ts +2 -0
  81. package/dist/__tests__/host-custom-kind-contract.test.d.ts.map +1 -0
  82. package/dist/__tests__/inspect-name.test.d.ts +2 -0
  83. package/dist/__tests__/inspect-name.test.d.ts.map +1 -0
  84. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts +2 -0
  85. package/dist/__tests__/instantiate-mount-deferred-wiring.test.d.ts.map +1 -0
  86. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts +2 -0
  87. package/dist/__tests__/loadbyguid-payload.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts +2 -0
  89. package/dist/__tests__/loadbyguid-texture-intern.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/loader-extract-graceful.test.d.ts +2 -0
  91. package/dist/__tests__/loader-extract-graceful.test.d.ts.map +1 -0
  92. package/dist/__tests__/loader-name-survival.test.d.ts +2 -0
  93. package/dist/__tests__/loader-name-survival.test.d.ts.map +1 -0
  94. package/dist/__tests__/mesh-bin-contract.test.d.ts +2 -0
  95. package/dist/__tests__/mesh-bin-contract.test.d.ts.map +1 -0
  96. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts +2 -0
  97. package/dist/__tests__/mesh-bin-skin-roundtrip.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/mesh-bin.test.d.ts +2 -0
  99. package/dist/__tests__/mesh-bin.test.d.ts.map +1 -0
  100. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts +2 -0
  101. package/dist/__tests__/mesh-loader-skin-contract.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/new-kind-refs-contract.test.d.ts +2 -0
  103. package/dist/__tests__/new-kind-refs-contract.test.d.ts.map +1 -0
  104. package/dist/__tests__/package-promotion.test.d.ts +2 -0
  105. package/dist/__tests__/package-promotion.test.d.ts.map +1 -0
  106. package/dist/__tests__/package-rename.test.d.ts +2 -0
  107. package/dist/__tests__/package-rename.test.d.ts.map +1 -0
  108. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts +1 -1
  109. package/dist/__tests__/recover-error-exhaustive.test-d.d.ts.map +1 -1
  110. package/dist/__tests__/render-error-exhaustive.test-d.d.ts +1 -1
  111. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
  112. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts +10 -0
  113. package/dist/__tests__/render-feature-prepared-graphics.fixture.d.ts.map +1 -0
  114. package/dist/__tests__/render-system-extract.unit.test.d.ts +2 -0
  115. package/dist/__tests__/render-system-extract.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/renderer-test-utils.d.ts +10 -0
  117. package/dist/__tests__/renderer-test-utils.d.ts.map +1 -0
  118. package/dist/__tests__/renderer.test-d.d.ts +2 -0
  119. package/dist/__tests__/renderer.test-d.d.ts.map +1 -0
  120. package/dist/__tests__/resolve-asset-handle-err.test.d.ts +2 -0
  121. package/dist/__tests__/resolve-asset-handle-err.test.d.ts.map +1 -0
  122. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts +2 -0
  123. package/dist/__tests__/resolve-asset-handle.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/resolveName-fallback.test.d.ts +2 -0
  125. package/dist/__tests__/resolveName-fallback.test.d.ts.map +1 -0
  126. package/dist/__tests__/resolveName-null-package.test.d.ts +2 -0
  127. package/dist/__tests__/resolveName-null-package.test.d.ts.map +1 -0
  128. package/dist/__tests__/resolveName-unified-entry.test.d.ts +2 -0
  129. package/dist/__tests__/resolveName-unified-entry.test.d.ts.map +1 -0
  130. package/dist/__tests__/resolveName.test.d.ts +2 -0
  131. package/dist/__tests__/resolveName.test.d.ts.map +1 -0
  132. package/dist/__tests__/roots-to-scene-asset.test.d.ts +1 -1
  133. package/dist/__tests__/roots-to-scene-asset.test.d.ts.map +1 -1
  134. package/dist/__tests__/roundtrip-primitive.test.d.ts +2 -0
  135. package/dist/__tests__/roundtrip-primitive.test.d.ts.map +1 -0
  136. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts +2 -0
  137. package/dist/__tests__/scene-bare-guid-refs-instantiate.test.d.ts.map +1 -0
  138. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts +2 -0
  139. package/dist/__tests__/scene-instance-authoring.integration.test.d.ts.map +1 -0
  140. package/dist/__tests__/scene-mount-fixed-point.test.d.ts +2 -0
  141. package/dist/__tests__/scene-mount-fixed-point.test.d.ts.map +1 -0
  142. package/dist/__tests__/scene-mount-roundtrip.test.d.ts +2 -0
  143. package/dist/__tests__/scene-mount-roundtrip.test.d.ts.map +1 -0
  144. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts +2 -0
  145. package/dist/__tests__/scene-mount-wrapper-roundtrip.test.d.ts.map +1 -0
  146. package/dist/__tests__/scene-sugar-instantiate.test.d.ts +2 -0
  147. package/dist/__tests__/scene-sugar-instantiate.test.d.ts.map +1 -0
  148. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts +2 -0
  149. package/dist/__tests__/serialize-mounts-roundtrip.test.d.ts.map +1 -0
  150. package/dist/__tests__/serialize-scene-asset.test.d.ts +1 -1
  151. package/dist/__tests__/serialize-scene-asset.test.d.ts.map +1 -1
  152. package/dist/__tests__/template-game-default-api-contract.test.d.ts +2 -0
  153. package/dist/__tests__/template-game-default-api-contract.test.d.ts.map +1 -0
  154. package/dist/__tests__/tileset-asset-validate.test.d.ts +2 -0
  155. package/dist/__tests__/tileset-asset-validate.test.d.ts.map +1 -0
  156. package/dist/__tests__/transcode-fallback.unit.test.d.ts +2 -0
  157. package/dist/__tests__/transcode-fallback.unit.test.d.ts.map +1 -0
  158. package/dist/__tests__/transient-runtime-behavior.test.d.ts +2 -0
  159. package/dist/__tests__/transient-runtime-behavior.test.d.ts.map +1 -0
  160. package/dist/__tests__/video-loader-consumption.test.d.ts +2 -0
  161. package/dist/__tests__/video-loader-consumption.test.d.ts.map +1 -0
  162. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts +2 -0
  163. package/dist/__tests__/video-loader-smoke.dawn.test.d.ts.map +1 -0
  164. package/dist/backend-selection.d.ts +13 -0
  165. package/dist/backend-selection.d.ts.map +1 -0
  166. package/dist/collect-scene-asset.d.ts +3 -3
  167. package/dist/collect-scene-asset.d.ts.map +1 -1
  168. package/dist/createRenderer.d.ts +14 -2
  169. package/dist/createRenderer.d.ts.map +1 -1
  170. package/dist/errors/environment.d.ts +1 -1
  171. package/dist/errors/environment.d.ts.map +1 -1
  172. package/dist/index.d.ts +19 -81
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.mjs +105 -108
  175. package/dist/index.mjs.map +1 -1
  176. package/dist/renderer-host.d.ts +9 -0
  177. package/dist/renderer-host.d.ts.map +1 -0
  178. package/dist/renderer-host.mjs +62 -0
  179. package/dist/renderer-host.mjs.map +1 -0
  180. package/dist/scene-instances/index.d.ts +2 -0
  181. package/dist/scene-instances/index.d.ts.map +1 -0
  182. package/dist/scene-utils/mount-override-fold.d.ts +1 -2
  183. package/dist/scene-utils/mount-override-fold.d.ts.map +1 -1
  184. package/dist/systems/sprite-animation-tick.d.ts +1 -1
  185. package/dist/systems/sprite-animation-tick.d.ts.map +1 -1
  186. package/dist/systems/transparent-sort.d.ts +1 -2
  187. package/dist/systems/transparent-sort.d.ts.map +1 -1
  188. package/dist/tilemap-register-validate.d.ts.map +1 -1
  189. package/package.json +34 -33
  190. package/src/__tests__/active-camera.unit.test.ts +19 -9
  191. package/src/__tests__/animation-graph-collect-roundtrip.test.ts +213 -0
  192. package/src/__tests__/animation-graph-serialize.unit.test.ts +171 -0
  193. package/src/__tests__/append-injection.test.ts +1 -1
  194. package/src/__tests__/asset-brand-and-name-retirement.test.ts +102 -0
  195. package/src/__tests__/asset-error-exhaustive.test-d.ts +62 -0
  196. package/src/__tests__/asset-registry-guid-reverse.test.ts +575 -0
  197. package/src/__tests__/asset-registry-hdr-equirect.test.ts +78 -0
  198. package/src/__tests__/asset-registry-mesh-pack-payload.dawn.test.ts +232 -0
  199. package/src/__tests__/asset-registry-mounts.test.ts +806 -0
  200. package/src/__tests__/asset-registry.browser.test.ts +81 -0
  201. package/src/__tests__/asset-registry.dawn.test.ts +94 -0
  202. package/src/__tests__/asset-registry.listCatalog.test.ts +170 -0
  203. package/src/__tests__/asset-registry.mesh-bin.test.ts +316 -0
  204. package/src/__tests__/asset-registry.pack-cache.test.ts +969 -0
  205. package/src/__tests__/asset-registry.raw-container-failfast.test.ts +225 -0
  206. package/src/__tests__/asset-registry.recursive.spec.ts +1397 -0
  207. package/src/__tests__/asset-registry.unit.test.ts +1030 -0
  208. package/src/__tests__/asset.unit.test.ts +7107 -0
  209. package/src/__tests__/audio-load-by-guid.unit.test.ts +126 -0
  210. package/src/__tests__/backend-selection.integration.test.ts +11 -0
  211. package/src/__tests__/basis-catalog-dispatch.integration.test.ts +320 -0
  212. package/src/__tests__/bind-group-cache-keying.test.ts +4 -4
  213. package/src/__tests__/block-upload-math.unit.test.ts +2 -2
  214. package/src/__tests__/builtin-asset-registry.unit.test.ts +112 -0
  215. package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
  216. package/src/__tests__/cache-false-eviction.test.ts +2 -1
  217. package/src/__tests__/cache-isolation-matrix.test.ts +2 -1
  218. package/src/__tests__/camera-clear-snapshot-equivalence.unit.test.ts +5 -6
  219. package/src/__tests__/clamp-to-last.e2e.browser.test.ts +29 -19
  220. package/src/__tests__/collect-scene-asset.test.ts +49 -52
  221. package/src/__tests__/collect-scene-mount-collapse.test.ts +391 -0
  222. package/src/__tests__/collect-subtree.unit.test.ts +1 -2
  223. package/src/__tests__/collect-transient-children-absent.test.ts +24 -10
  224. package/src/__tests__/collect-transient-roundtrip.test.ts +44 -20
  225. package/src/__tests__/collect-transient-skip.test.ts +24 -13
  226. package/src/__tests__/components.test-d.ts +1 -6
  227. package/src/__tests__/components.unit.test.ts +20 -19
  228. package/src/__tests__/composite-skybox-cross-world.browser.test.ts +59 -27
  229. package/src/__tests__/compressed-texture-physical-extent.integration.test.ts +139 -0
  230. package/src/__tests__/create-renderer-assembly.integration.test.ts +42 -29
  231. package/src/__tests__/createRenderer-dispose.test.ts +35 -402
  232. package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +25 -30
  233. package/src/__tests__/createRenderer.unit.test.ts +1 -1
  234. package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +27 -63
  235. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +56 -47
  236. package/src/__tests__/dawn/instances-per-instance-pbr.dawn.test.ts +49 -29
  237. package/src/__tests__/dawn/instances-shadow.dawn.test.ts +26 -15
  238. package/src/__tests__/dawn/instances-uniform-fallback.dawn.test.ts +13 -14
  239. package/src/__tests__/dawn/material-alpha.dawn.test.ts +23 -31
  240. package/src/__tests__/dawn/material-cooked-fixture.dawn.test.ts +0 -18
  241. package/src/__tests__/dawn/{mesh-update.dawn.test.ts → mesh-update-dawn.test.ts} +42 -134
  242. package/src/__tests__/dawn/mipmap-srgb-linear.dawn.test.ts +14 -7
  243. package/src/__tests__/dawn/per-entity-material-texture-isolation.dawn.test.ts +16 -28
  244. package/src/__tests__/dawn/sprite-nineslice-mesh-bind.dawn.test.ts +23 -39
  245. package/src/__tests__/dawn/upload-texture.dawn.test.ts +198 -0
  246. package/src/__tests__/dawn/user-handle-mesh-render.dawn.test.ts +12 -14
  247. package/src/__tests__/dawn/user-mesh-upload.dawn.test.ts +27 -22
  248. package/src/__tests__/dawn/zero-manifest-mesh-fail.dawn.test.ts +25 -28
  249. package/src/__tests__/dawn/zero-manifest-ready.dawn.test.ts +10 -11
  250. package/src/__tests__/demo-sortscope-migration.unit.test.ts +5 -5
  251. package/src/__tests__/derive-bgl-integration.test.ts +34 -44
  252. package/src/__tests__/derive-render-data-skin.unit.test.ts +1 -1
  253. package/src/__tests__/draw-published.ts +11 -4
  254. package/src/__tests__/dynamic-texture-store.unit.test.ts +190 -0
  255. package/src/__tests__/equirect-bc6h.integration.test.ts +144 -21
  256. package/src/__tests__/errors.unit.test.ts +1203 -0
  257. package/src/__tests__/extract-frames-graceful-degradation.test.ts +3 -7
  258. package/src/__tests__/extract-frames-merge.test.ts +35 -22
  259. package/src/__tests__/extract-record-no-hardcoded-texture-fields.test.ts +5 -16
  260. package/src/__tests__/extract-skin-mismatch.unit.test.ts +322 -0
  261. package/src/__tests__/fetch-binary-decompress.test.ts +356 -0
  262. package/src/__tests__/four-path-compression.integration.test.ts +395 -0
  263. package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +1 -1
  264. package/src/__tests__/fullscreen-feature-host.dawn.test.ts +80 -0
  265. package/src/__tests__/fullscreen-post-bgl-depth.test.ts +4 -2
  266. package/src/__tests__/fullscreen-post-depth-params-arity.test.ts +3 -3
  267. package/src/__tests__/fullscreen-post-process-pass.dawn.test.ts +39 -23
  268. package/src/__tests__/fullscreen-post-process-pass.unit.test.ts +4 -2
  269. package/src/__tests__/fxaa-pixel-diff.dawn.test.ts +28 -17
  270. package/src/__tests__/fxaa-validation-and-resize.dawn.test.ts +29 -18
  271. package/src/__tests__/fxaa-zero-overhead.dawn.test.ts +16 -12
  272. package/src/__tests__/geometry.unit.test.ts +525 -159
  273. package/src/__tests__/glyph-tilemap-worldid.test.ts +1 -1
  274. package/src/__tests__/gpu-resource-cow-survivor.test.ts +6 -4
  275. package/src/__tests__/guid-for-asset.unit.test.ts +102 -0
  276. package/src/__tests__/handle-migration.test.ts +136 -0
  277. package/src/__tests__/helpers/register-runtime-components.ts +4 -2
  278. package/src/__tests__/helpers/register-scene-components.ts +1 -1
  279. package/src/__tests__/host-custom-kind-contract.test-d.ts +47 -0
  280. package/src/__tests__/host-custom-kind-contract.test.ts +578 -0
  281. package/src/__tests__/inspect-name.test.ts +139 -0
  282. package/src/__tests__/instances.test-d.ts +1 -1
  283. package/src/__tests__/instantiate-mount-deferred-wiring.test.ts +112 -0
  284. package/src/__tests__/light-casters-9-light.browser.test.ts +73 -76
  285. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +7 -10
  286. package/src/__tests__/light-snapshot.test-d.ts +2 -2
  287. package/src/__tests__/lights-vec-negative.unit.test.ts +1 -1
  288. package/src/__tests__/lights.unit.test.ts +16 -500
  289. package/src/__tests__/loadbyguid-payload.unit.test.ts +117 -0
  290. package/src/__tests__/loadbyguid-texture-intern.unit.test.ts +213 -0
  291. package/src/__tests__/loader-extract-graceful.test.ts +146 -0
  292. package/src/__tests__/loader-name-survival.test.ts +213 -0
  293. package/src/__tests__/m3-vec-negative.unit.test.ts +3 -2
  294. package/src/__tests__/material-texture-uv-scale.unit.test.ts +101 -31
  295. package/src/__tests__/materials.unit.test.ts +10 -27
  296. package/src/__tests__/mesh-bin-contract.test.ts +28 -0
  297. package/src/__tests__/mesh-bin-skin-roundtrip.unit.test.ts +149 -0
  298. package/src/__tests__/mesh-bin.test.ts +38 -0
  299. package/src/__tests__/mesh-loader-skin-contract.unit.test.ts +120 -0
  300. package/src/__tests__/mesh-ssbo-grow.unit.test.ts +3 -3
  301. package/src/__tests__/mip-gate.unit.test.ts +1 -1
  302. package/src/__tests__/msaa-sprite-pixel-diff.dawn.test.ts +29 -68
  303. package/src/__tests__/new-kind-refs-contract.test.ts +132 -0
  304. package/src/__tests__/node-shims.d.ts +4 -6
  305. package/src/__tests__/package-promotion.test.ts +88 -0
  306. package/src/__tests__/package-rename.test.ts +103 -0
  307. package/src/__tests__/pass-selector.unit.test.ts +2 -2
  308. package/src/__tests__/pbr-pipeline.unit.test.ts +14 -21
  309. package/src/__tests__/pipeline-builder-msaa.unit.test.ts +6 -9
  310. package/src/__tests__/pipeline-cache-keying.unit.test.ts +6 -9
  311. package/src/__tests__/pipeline-spec.test.ts +16 -177
  312. package/src/__tests__/pipeline.unit.test.ts +154 -1693
  313. package/src/__tests__/point-light-shadow.dawn.test.ts +33 -42
  314. package/src/__tests__/point-light-shadow.unit.test.ts +19 -60
  315. package/src/__tests__/post-process-error-codes.unit.test.ts +4 -1
  316. package/src/__tests__/post-process-params-component.unit.test.ts +1 -1
  317. package/src/__tests__/post-process-params-extract.unit.test.ts +2 -5
  318. package/src/__tests__/postprocess-camera-consistency.test.ts +4 -7
  319. package/src/__tests__/profiler-assembly.integration.test.ts +1 -1
  320. package/src/__tests__/propagate-transforms.dawn.test.ts +12 -11
  321. package/src/__tests__/record-worldid-isolation.test.ts +7 -29
  322. package/src/__tests__/recover-error-exhaustive.test-d.ts +1 -1
  323. package/src/__tests__/render-error-exhaustive.test-d.ts +81 -71
  324. package/src/__tests__/render-feature-assembly.test-d.ts +20 -9
  325. package/src/__tests__/render-feature-prepared-graphics-docs.unit.test.ts +8 -6
  326. package/src/__tests__/render-feature-prepared-graphics.browser.test.ts +60 -558
  327. package/src/__tests__/render-feature-prepared-graphics.dawn.test.ts +57 -544
  328. package/src/__tests__/render-feature-prepared-graphics.fixture.ts +104 -0
  329. package/src/__tests__/render-feature-prepared-graphics.integration.test.ts +40 -248
  330. package/src/__tests__/render-feature-prepared-graphics.regression.integration.test.ts +83 -340
  331. package/src/__tests__/render-feature-recover.integration.test.ts +9 -49
  332. package/src/__tests__/render-feature-runtime-surface.test-d.ts +17 -20
  333. package/src/__tests__/render-schema-consumer.integration.test.ts +20 -13
  334. package/src/__tests__/render-schema-owner-boundary.unit.test.ts +2 -6
  335. package/src/__tests__/render-system-cross-world-overlay-queue.test.ts +5 -5
  336. package/src/__tests__/render-system-extract-dispatch-ordering.test.ts +16 -31
  337. package/src/__tests__/render-system-extract.test.ts +36 -51
  338. package/src/__tests__/render-system-extract.unit.test.ts +360 -0
  339. package/src/__tests__/render-system-fold-bucket.unit.test.ts +3 -5
  340. package/src/__tests__/render-system-fold-fallback.unit.test.ts +6 -3
  341. package/src/__tests__/render-system-fold-material.unit.test.ts +3 -5
  342. package/src/__tests__/render-system-fold-metrics.unit.test.ts +5 -5
  343. package/src/__tests__/render-system-fold-modegate.unit.test.ts +6 -6
  344. package/src/__tests__/render-system-fold.dawn.test.ts +7 -5
  345. package/src/__tests__/render-system-mega.test.ts +292 -190
  346. package/src/__tests__/render-system-owner-split-contract.test.ts +10 -32
  347. package/src/__tests__/render-system-record-multi-material-textureview.test.ts +59 -45
  348. package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +23 -29
  349. package/src/__tests__/render-system-record.test.ts +398 -235
  350. package/src/__tests__/render-system-record.unit.test.ts +25 -26
  351. package/src/__tests__/render-system-skin-bg.unit.test.ts +8 -12
  352. package/src/__tests__/renderer-consumer.test-d.ts +16 -3
  353. package/src/__tests__/renderer-health.unit.test.ts +26 -916
  354. package/src/__tests__/renderer-lifecycle.integration.test.ts +19 -6
  355. package/src/__tests__/renderer-recover.unit.test.ts +49 -1069
  356. package/src/__tests__/renderer-result.test-d.ts +19 -9
  357. package/src/__tests__/renderer-surface.unit.test.ts +3 -5
  358. package/src/__tests__/renderer-test-utils.ts +56 -0
  359. package/src/__tests__/renderer.test-d.ts +59 -0
  360. package/src/__tests__/resolve-asset-handle-err.test.ts +111 -0
  361. package/src/__tests__/resolve-asset-handle.unit.test.ts +64 -0
  362. package/src/__tests__/resolve-depth-only-view.test.ts +1 -1
  363. package/src/__tests__/resolveName-fallback.test.ts +64 -0
  364. package/src/__tests__/resolveName-null-package.test.ts +38 -0
  365. package/src/__tests__/resolveName-unified-entry.test.ts +65 -0
  366. package/src/__tests__/resolveName.test.ts +64 -0
  367. package/src/__tests__/rhi-null-command-flow.unit.test.ts +43 -261
  368. package/src/__tests__/rhi-null-renderer-lifecycle.unit.test.ts +41 -169
  369. package/src/__tests__/roots-to-scene-asset.test.ts +199 -93
  370. package/src/__tests__/roundtrip-primitive.test.ts +351 -0
  371. package/src/__tests__/scene-bare-guid-refs-instantiate.test.ts +123 -0
  372. package/src/__tests__/scene-equirect-roundtrip.test.ts +103 -16
  373. package/src/__tests__/scene-instance-authoring.integration.test.ts +8 -0
  374. package/src/__tests__/scene-instance-bridge.integration.test.ts +1 -1
  375. package/src/__tests__/scene-instance-component.test.ts +1 -1
  376. package/src/__tests__/scene-mount-fixed-point.test.ts +257 -0
  377. package/src/__tests__/scene-mount-roundtrip.test.ts +987 -0
  378. package/src/__tests__/scene-mount-wrapper-roundtrip.test.ts +202 -0
  379. package/src/__tests__/scene-sugar-instantiate.test.ts +324 -0
  380. package/src/__tests__/serialize-mounts-roundtrip.test.ts +533 -0
  381. package/src/__tests__/serialize-scene-asset.test.ts +219 -22
  382. package/src/__tests__/shadow-caster-empty-schema.test.ts +3 -3
  383. package/src/__tests__/shadow-csm-cascade-loadop.test.ts +37 -17
  384. package/src/__tests__/shadow-csm-component.test.ts +3 -5
  385. package/src/__tests__/shadow-csm-extract.test.ts +2 -100
  386. package/src/__tests__/shadow-csm-orthoz.test.ts +2 -16
  387. package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +19 -14
  388. package/src/__tests__/shadow-csm-tile-consistency.test.ts +32 -26
  389. package/src/__tests__/shadow-csm-ubo.dawn.test.ts +8 -49
  390. package/src/__tests__/shadow-csm-ubo.test.ts +3 -25
  391. package/src/__tests__/shadow-csm-viewport.browser.test.ts +1 -1
  392. package/src/__tests__/shadow-fields-observable.dawn.test.ts +67 -56
  393. package/src/__tests__/shadow-m1.dawn.test.ts +8 -9
  394. package/src/__tests__/shadow-mesh-ssbo-order.test.ts +11 -27
  395. package/src/__tests__/skin-errors.unit.test.ts +1 -1
  396. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +7 -5
  397. package/src/__tests__/skylight-lazy-projection.test.ts +36 -15
  398. package/src/__tests__/sparse-tag-scene-roundtrip.test.ts +5 -5
  399. package/src/__tests__/sprite-cullmode-flip.dawn.test.ts +47 -64
  400. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +12 -11
  401. package/src/__tests__/sprite-lit-extract-branch.test.ts +1 -1
  402. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
  403. package/src/__tests__/ssao-bgl.test.ts +16 -9
  404. package/src/__tests__/ssao-buffers.test.ts +2 -2
  405. package/src/__tests__/ssao-data.test.ts +2 -2
  406. package/src/__tests__/ssao-errors.test.ts +1 -1
  407. package/src/__tests__/ssao-passes.test.ts +64 -392
  408. package/src/__tests__/ssao-pipelines.test.ts +1 -1
  409. package/src/__tests__/ssao-uniform-layout.test.ts +8 -6
  410. package/src/__tests__/stencil-outline-pixel.dawn.test.ts +25 -17
  411. package/src/__tests__/swap-chain-format.unit.test.ts +5 -7
  412. package/src/__tests__/systems.unit.test.ts +536 -1326
  413. package/src/__tests__/template-game-default-api-contract.test.ts +362 -0
  414. package/src/__tests__/text.unit.test.ts +56 -33
  415. package/src/__tests__/tilemap-childed-despawn.test.ts +8 -14
  416. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +8 -12
  417. package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +2 -1
  418. package/src/__tests__/tilemap-chunk-extract.test.ts +13 -17
  419. package/src/__tests__/tilemap-dirty-rebuild.test.ts +7 -11
  420. package/src/__tests__/tilemap-material-cache.test.ts +8 -13
  421. package/src/__tests__/tilemap-multi-atlas.test.ts +12 -32
  422. package/src/__tests__/tilemap-owner-boundary.unit.test.ts +5 -2
  423. package/src/__tests__/tilemap-region-pack.test.ts +8 -12
  424. package/src/__tests__/tilemap-spawn-flip-pivot.test.ts +8 -12
  425. package/src/__tests__/tilemap-uv-inset.test.ts +11 -14
  426. package/src/__tests__/tilemap-validate.test.ts +1 -1
  427. package/src/__tests__/tileset-asset-validate.test.ts +638 -0
  428. package/src/__tests__/transcode-fallback.unit.test.ts +207 -0
  429. package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +36 -28
  430. package/src/__tests__/transient-fields-collect.test.ts +28 -21
  431. package/src/__tests__/transient-runtime-behavior.test.ts +227 -0
  432. package/src/__tests__/transparent-sort-tilemap-sprite-interleave.test.ts +4 -4
  433. package/src/__tests__/variant-selection.unit.test.ts +1 -1
  434. package/src/__tests__/video-extract-bindgroup.dawn.test.ts +89 -136
  435. package/src/__tests__/video-loader-consumption.test.ts +86 -0
  436. package/src/__tests__/video-loader-smoke.dawn.test.ts +60 -0
  437. package/src/__tests__/view-ubo-layout.browser.test.ts +0 -22
  438. package/src/__tests__/world-entity-key.test.ts +1 -1
  439. package/src/__tests__/world-scene-despawn.test.ts +1 -1
  440. package/src/__tests__/world-scene-instantiate.test.ts +2 -36
  441. package/src/__tests__/world-scene-nested.test.ts +1 -1
  442. package/src/__tests__/world-scene-override.test.ts +1 -1
  443. package/src/backend-selection.ts +69 -0
  444. package/src/collect-scene-asset.ts +28 -23
  445. package/src/components/__tests__/camera.test-d.ts +1 -1
  446. package/src/components/__tests__/camera.test.ts +1 -1
  447. package/src/components/__tests__/sprite-animation.test-d.ts +2 -2
  448. package/src/components/__tests__/tile-layer.test-d.ts +1 -1
  449. package/src/components/__tests__/tile-layer.unit.test.ts +2 -2
  450. package/src/createRenderer.ts +24 -36
  451. package/src/errors/environment.ts +1 -1
  452. package/src/index.ts +47 -113
  453. package/src/renderer-host.ts +33 -0
  454. package/src/scene-instances/__tests__/post-spawn-resolve-joints.unit.test.ts +1 -1
  455. package/src/scene-instances/index.ts +4 -0
  456. package/src/scene-utils/mount-override-fold.ts +3 -7
  457. package/src/systems/__tests__/transparent-sort.bench.ts +3 -3
  458. package/src/systems/sprite-animation-tick.ts +1 -1
  459. package/src/systems/transparent-sort.ts +38 -38
  460. package/src/tilemap-register-validate.ts +4 -4
  461. package/dist/__tests__/bind-group-cache-binding.test.d.ts +0 -2
  462. package/dist/__tests__/bind-group-cache-binding.test.d.ts.map +0 -1
  463. package/dist/__tests__/bind-group-cache-frame.test.d.ts +0 -2
  464. package/dist/__tests__/bind-group-cache-frame.test.d.ts.map +0 -1
  465. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts +0 -2
  466. package/dist/__tests__/dawn/mesh-update.dawn.test.d.ts.map +0 -1
  467. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts +0 -2
  468. package/dist/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.d.ts.map +0 -1
  469. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts +0 -2
  470. package/dist/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.d.ts.map +0 -1
  471. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts +0 -2
  472. package/dist/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.d.ts.map +0 -1
  473. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts +0 -2
  474. package/dist/__tests__/dispatch-fullscreen-pass-params.unit.test.d.ts.map +0 -1
  475. package/dist/__tests__/fog-producer-manifest.d.ts +0 -131
  476. package/dist/__tests__/fog-producer-manifest.d.ts.map +0 -1
  477. package/dist/__tests__/fog-producer-pixel-probe.d.ts +0 -42
  478. package/dist/__tests__/fog-producer-pixel-probe.d.ts.map +0 -1
  479. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts +0 -2
  480. package/dist/__tests__/fog-producer-pixel.browser.test.d.ts.map +0 -1
  481. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts +0 -2
  482. package/dist/__tests__/fog-producer-pixel.dawn.test.d.ts.map +0 -1
  483. package/dist/__tests__/fog-producer-real-fixture.d.ts +0 -5
  484. package/dist/__tests__/fog-producer-real-fixture.d.ts.map +0 -1
  485. package/dist/__tests__/fog-producer-vfx-effect.d.ts +0 -3
  486. package/dist/__tests__/fog-producer-vfx-effect.d.ts.map +0 -1
  487. package/dist/__tests__/fog-scene-asset.integration.test.d.ts +0 -2
  488. package/dist/__tests__/fog-scene-asset.integration.test.d.ts.map +0 -1
  489. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts +0 -2
  490. package/dist/__tests__/gpu-resource-store-cubemap-status.test.d.ts.map +0 -1
  491. package/dist/__tests__/gpu-resource.test.d.ts +0 -2
  492. package/dist/__tests__/gpu-resource.test.d.ts.map +0 -1
  493. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts +0 -2
  494. package/dist/__tests__/hdrp-bgl-slots.browser.test.d.ts.map +0 -1
  495. package/dist/__tests__/hdrp-buffers.unit.test.d.ts +0 -2
  496. package/dist/__tests__/hdrp-buffers.unit.test.d.ts.map +0 -1
  497. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts +0 -2
  498. package/dist/__tests__/hdrp-execute-filter.unit.test.d.ts.map +0 -1
  499. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts +0 -2
  500. package/dist/__tests__/hdrp-gbuffer-attachments.browser.test.d.ts.map +0 -1
  501. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts +0 -2
  502. package/dist/__tests__/hdrp-pipeline-asset-type.test-d.d.ts.map +0 -1
  503. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts +0 -2
  504. package/dist/__tests__/hdrp-ssao-boundary.test.d.ts.map +0 -1
  505. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts +0 -2
  506. package/dist/__tests__/hdrp-ssao-falsification.test.d.ts.map +0 -1
  507. package/dist/__tests__/helpers/primitive-world.d.ts +0 -8
  508. package/dist/__tests__/helpers/primitive-world.d.ts.map +0 -1
  509. package/dist/__tests__/helpers/render-asset-port.d.ts +0 -15
  510. package/dist/__tests__/helpers/render-asset-port.d.ts.map +0 -1
  511. package/dist/__tests__/helpers/scene-asset-port.d.ts +0 -9
  512. package/dist/__tests__/helpers/scene-asset-port.d.ts.map +0 -1
  513. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts +0 -2
  514. package/dist/__tests__/material-derived-coordinates.integration.test.d.ts.map +0 -1
  515. package/dist/__tests__/pipeline-layout-selection.test.d.ts +0 -2
  516. package/dist/__tests__/pipeline-layout-selection.test.d.ts.map +0 -1
  517. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts +0 -2
  518. package/dist/__tests__/post-process-reads-narrowing.test-d.d.ts.map +0 -1
  519. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts +0 -2
  520. package/dist/__tests__/post-process-register-roundtrip.dawn.test.d.ts.map +0 -1
  521. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts +0 -2
  522. package/dist/__tests__/render-feature-zero-feature.browser.test.d.ts.map +0 -1
  523. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts +0 -2
  524. package/dist/__tests__/render-pipeline-trivial.dawn.test.d.ts.map +0 -1
  525. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts +0 -2
  526. package/dist/__tests__/shadow-csm-caster-membership.test.d.ts.map +0 -1
  527. package/dist/__tests__/shadow-csm-pssm.test.d.ts +0 -2
  528. package/dist/__tests__/shadow-csm-pssm.test.d.ts.map +0 -1
  529. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts +0 -2
  530. package/dist/__tests__/shadow-csm-temporal.browser.test.d.ts.map +0 -1
  531. package/dist/__tests__/shadow-csm-viewport.test.d.ts +0 -2
  532. package/dist/__tests__/shadow-csm-viewport.test.d.ts.map +0 -1
  533. package/dist/__tests__/shadow-m2.dawn.test.d.ts +0 -2
  534. package/dist/__tests__/shadow-m2.dawn.test.d.ts.map +0 -1
  535. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts +0 -2
  536. package/dist/__tests__/shadow-m3-calibrate-run.dawn.test.d.ts.map +0 -1
  537. package/dist/__tests__/shadow-m3-calibrate.d.ts +0 -83
  538. package/dist/__tests__/shadow-m3-calibrate.d.ts.map +0 -1
  539. package/dist/__tests__/shadow-m3.dawn.test.d.ts +0 -2
  540. package/dist/__tests__/shadow-m3.dawn.test.d.ts.map +0 -1
  541. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts +0 -2
  542. package/dist/__tests__/shadow-probe-control-flow.dawn.test.d.ts.map +0 -1
  543. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts +0 -2
  544. package/dist/__tests__/shadow-quality-metrics.dawn.test.d.ts.map +0 -1
  545. package/dist/__tests__/temporal-off-path.unit.test.d.ts +0 -2
  546. package/dist/__tests__/temporal-off-path.unit.test.d.ts.map +0 -1
  547. package/dist/__tests__/video-cache-regression.unit.test.d.ts +0 -2
  548. package/dist/__tests__/video-cache-regression.unit.test.d.ts.map +0 -1
  549. package/dist/asset-kind.d.ts +0 -4
  550. package/dist/asset-kind.d.ts.map +0 -1
  551. package/dist/errors/sprite-animation.d.ts +0 -3
  552. package/dist/errors/sprite-animation.d.ts.map +0 -1
  553. package/dist/scene-asset-port.d.ts +0 -17
  554. package/dist/scene-asset-port.d.ts.map +0 -1
  555. package/dist/scene-collect-errors.d.ts +0 -22
  556. package/dist/scene-collect-errors.d.ts.map +0 -1
  557. package/dist/shadow-m3-calibrate.d.ts +0 -40
  558. package/dist/shadow-m3-calibrate.d.ts.map +0 -1
  559. package/src/__tests__/bind-group-cache-binding.test.ts +0 -2513
  560. package/src/__tests__/bind-group-cache-frame.test.ts +0 -1511
  561. package/src/__tests__/dispatch-fullscreen-pass-composite-swapchain.dawn.test.ts +0 -204
  562. package/src/__tests__/dispatch-fullscreen-pass-custom-reads.dawn.test.ts +0 -297
  563. package/src/__tests__/dispatch-fullscreen-pass-depth-composite.dawn.test.ts +0 -271
  564. package/src/__tests__/dispatch-fullscreen-pass-params.unit.test.ts +0 -321
  565. package/src/__tests__/fog-producer-manifest.ts +0 -162
  566. package/src/__tests__/fog-producer-pixel-probe.ts +0 -263
  567. package/src/__tests__/fog-producer-pixel.browser.test.ts +0 -26
  568. package/src/__tests__/fog-producer-pixel.dawn.test.ts +0 -55
  569. package/src/__tests__/fog-producer-real-fixture.ts +0 -805
  570. package/src/__tests__/fog-producer-vfx-effect.ts +0 -272
  571. package/src/__tests__/fog-scene-asset.integration.test.ts +0 -123
  572. package/src/__tests__/gpu-resource-store-cubemap-status.test.ts +0 -207
  573. package/src/__tests__/gpu-resource.test.ts +0 -1206
  574. package/src/__tests__/hdrp-bgl-slots.browser.test.ts +0 -50
  575. package/src/__tests__/hdrp-buffers.unit.test.ts +0 -70
  576. package/src/__tests__/hdrp-execute-filter.unit.test.ts +0 -200
  577. package/src/__tests__/hdrp-gbuffer-attachments.browser.test.ts +0 -64
  578. package/src/__tests__/hdrp-pipeline-asset-type.test-d.ts +0 -139
  579. package/src/__tests__/hdrp-ssao-boundary.test.ts +0 -237
  580. package/src/__tests__/hdrp-ssao-falsification.test.ts +0 -289
  581. package/src/__tests__/helpers/primitive-world.ts +0 -91
  582. package/src/__tests__/helpers/render-asset-port.ts +0 -65
  583. package/src/__tests__/helpers/scene-asset-port.ts +0 -23
  584. package/src/__tests__/material-derived-coordinates.integration.test.ts +0 -100
  585. package/src/__tests__/pipeline-layout-selection.test.ts +0 -298
  586. package/src/__tests__/post-process-reads-narrowing.test-d.ts +0 -52
  587. package/src/__tests__/post-process-register-roundtrip.dawn.test.ts +0 -230
  588. package/src/__tests__/render-feature-zero-feature.browser.test.ts +0 -152
  589. package/src/__tests__/render-pipeline-trivial.dawn.test.ts +0 -525
  590. package/src/__tests__/shadow-csm-caster-membership.test.ts +0 -232
  591. package/src/__tests__/shadow-csm-pssm.test.ts +0 -142
  592. package/src/__tests__/shadow-csm-temporal.browser.test.ts +0 -145
  593. package/src/__tests__/shadow-csm-viewport.test.ts +0 -74
  594. package/src/__tests__/shadow-m2.dawn.test.ts +0 -394
  595. package/src/__tests__/shadow-m3-calibrate-run.dawn.test.ts +0 -248
  596. package/src/__tests__/shadow-m3-calibrate.ts +0 -203
  597. package/src/__tests__/shadow-m3.dawn.test.ts +0 -288
  598. package/src/__tests__/shadow-probe-control-flow.dawn.test.ts +0 -264
  599. package/src/__tests__/shadow-quality-metrics.dawn.test.ts +0 -324
  600. package/src/__tests__/temporal-off-path.unit.test.ts +0 -69
  601. package/src/__tests__/video-cache-regression.unit.test.ts +0 -186
  602. package/src/asset-kind.ts +0 -7
  603. package/src/errors/sprite-animation.ts +0 -5
  604. package/src/scene-asset-port.ts +0 -32
  605. package/src/scene-collect-errors.ts +0 -30
  606. package/src/shadow-m3-calibrate.ts +0 -171
@@ -0,0 +1,351 @@
1
+ // M3 test -- full schema primitive round-trip (AC-18)
2
+ // (plan-strategy: cover f32/f64/i32/u32/bool/string + entity + shared<>
3
+ // combination + TypedArray->Array normalization).
4
+ //
5
+ // The round-trip path is: spawn live entities → rootsToSceneAsset collect → verify
6
+ // value equivalence. We use live entity spawning rather than instantiateScene because
7
+ // instantiateScene creates internal shared<> refs back to the SceneAsset itself,
8
+ // which would require cataloguing the scene asset.
9
+
10
+ import type { Asset } from '@forgeax/engine-assets-runtime';
11
+ import { AssetRegistry } from '@forgeax/engine-assets-runtime';
12
+ import { defineComponent, type EntityHandle, World } from '@forgeax/engine-ecs';
13
+ import { AssetGuid } from '@forgeax/engine-pack/guid';
14
+ import { ChildOf } from '@forgeax/engine-scene';
15
+ import { describe, expect, it } from 'vitest';
16
+ import { rootsToSceneAsset } from '../collect-scene-asset';
17
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
18
+
19
+ function linkChildren(
20
+ world: World,
21
+ parent: EntityHandle,
22
+ children: readonly (EntityHandle | number)[],
23
+ ): void {
24
+ for (const child of children) {
25
+ const result = world.addComponent(child as EntityHandle, {
26
+ component: ChildOf,
27
+ data: { parent },
28
+ });
29
+ if (!result.ok) throw new Error(result.error.code);
30
+ }
31
+ }
32
+
33
+ // ═══════════════════════════════════════════════════════════════════════════════
34
+ // Helpers
35
+ // ═══════════════════════════════════════════════════════════════════════════════
36
+
37
+ function makeRegistry(): AssetRegistry {
38
+ return new AssetRegistry(makeMockShaderRegistry());
39
+ }
40
+
41
+ function makePayload(kind: Asset['kind']): Asset {
42
+ return { kind } as Asset;
43
+ }
44
+
45
+ function registerComponents(
46
+ world: World,
47
+ ...components: readonly Parameters<World['components']['register']>[0][]
48
+ ): void {
49
+ for (const component of components) world.components.register(component).unwrap();
50
+ }
51
+
52
+ // biome-ignore lint/suspicious/noExplicitAny: test helper bridging typed component tokens to World.spawn
53
+ function s(w: World, compToken: any, data: any): number {
54
+ // biome-ignore lint/suspicious/noExplicitAny: test helper adapter for World.spawn overload
55
+ const r = w.spawn({ component: compToken, data } as any);
56
+ if (!r.ok) throw new Error('spawn failed');
57
+ return r.value as number;
58
+ }
59
+
60
+ // ═══════════════════════════════════════════════════════════════════════════════
61
+ // m3-t3(a): individual primitive field round-trip value equivalence
62
+ // ═══════════════════════════════════════════════════════════════════════════════
63
+
64
+ describe('m3-t3(a): individual primitive field round-trip', () => {
65
+ it('f32 field round-trips with value equivalence', () => {
66
+ const Test_F32 = defineComponent('Test_RT_F32', { val: 'f32' });
67
+
68
+ const world = new World();
69
+ registerComponents(world, Test_F32);
70
+ const reg = makeRegistry();
71
+ // 1.5 is exactly representable in f32.
72
+ const r0 = s(world, Test_F32, { val: 1.5 });
73
+
74
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
75
+ expect(collected.ok).toBe(true);
76
+ if (!collected.ok) return;
77
+ const scene = collected.value;
78
+ expect(scene.entities).toHaveLength(1);
79
+
80
+ const ent0 = scene.entities[0];
81
+ if (!ent0) throw new Error('entity 0 missing');
82
+ const comps = ent0.components as Record<string, Record<string, unknown>>;
83
+ const cf = comps.Test_RT_F32;
84
+ expect(cf).toBeDefined();
85
+ if (!cf) throw new Error('Test_RT_F32 missing');
86
+ expect(cf.val).toBe(1.5);
87
+ });
88
+
89
+ it('f64 field round-trips with value equivalence', () => {
90
+ const Test_F64 = defineComponent('Test_RT_F64', { val: 'f64' });
91
+
92
+ const world = new World();
93
+ registerComponents(world, Test_F64);
94
+ const reg = makeRegistry();
95
+ const r0 = s(world, Test_F64, { val: 1.7976931348623157e308 });
96
+
97
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
98
+ expect(collected.ok).toBe(true);
99
+ if (!collected.ok) return;
100
+ const scene = collected.value;
101
+ expect(scene.entities).toHaveLength(1);
102
+
103
+ const ent0 = scene.entities[0];
104
+ if (!ent0) throw new Error('entity 0 missing');
105
+ const comps = ent0.components as Record<string, Record<string, unknown>>;
106
+ const cf = comps.Test_RT_F64;
107
+ expect(cf).toBeDefined();
108
+ if (!cf) throw new Error('Test_RT_F64 missing');
109
+ const v = cf.val as number;
110
+ expect(v).toBeGreaterThan(1e308);
111
+ });
112
+
113
+ it('i32 field round-trips with value equivalence', () => {
114
+ const Test_I32 = defineComponent('Test_RT_I32', { val: 'i32' });
115
+
116
+ const world = new World();
117
+ registerComponents(world, Test_I32);
118
+ const reg = makeRegistry();
119
+ const r0 = s(world, Test_I32, { val: -42 });
120
+
121
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
122
+ expect(collected.ok).toBe(true);
123
+ if (!collected.ok) return;
124
+ const scene = collected.value;
125
+ expect(scene.entities).toHaveLength(1);
126
+
127
+ const ent0 = scene.entities[0];
128
+ if (!ent0) throw new Error('entity 0 missing');
129
+ const comps = ent0.components as Record<string, Record<string, unknown>>;
130
+ const cf = comps.Test_RT_I32;
131
+ expect(cf).toBeDefined();
132
+ if (!cf) throw new Error('Test_RT_I32 missing');
133
+ expect(cf.val).toBe(-42);
134
+ });
135
+
136
+ it('u32 field round-trips with value equivalence', () => {
137
+ const Test_U32 = defineComponent('Test_RT_U32', { val: 'u32' });
138
+
139
+ const world = new World();
140
+ registerComponents(world, Test_U32);
141
+ const reg = makeRegistry();
142
+ const r0 = s(world, Test_U32, { val: 4294967295 });
143
+
144
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
145
+ expect(collected.ok).toBe(true);
146
+ if (!collected.ok) return;
147
+ const scene = collected.value;
148
+ expect(scene.entities).toHaveLength(1);
149
+
150
+ const ent0 = scene.entities[0];
151
+ if (!ent0) throw new Error('entity 0 missing');
152
+ const comps = ent0.components as Record<string, Record<string, unknown>>;
153
+ const cf = comps.Test_RT_U32;
154
+ expect(cf).toBeDefined();
155
+ if (!cf) throw new Error('Test_RT_U32 missing');
156
+ expect(cf.val).toBe(4294967295);
157
+ });
158
+
159
+ it('bool field round-trips with value equivalence', () => {
160
+ const Test_Bool = defineComponent('Test_RT_BOOL', { flag: 'bool' });
161
+
162
+ const world = new World();
163
+ registerComponents(world, Test_Bool, ChildOf);
164
+ const reg = makeRegistry();
165
+ const r0 = s(world, Test_Bool, { flag: true });
166
+ const r1 = s(world, Test_Bool, { flag: false });
167
+ linkChildren(world, r0 as EntityHandle, [r1 as EntityHandle]);
168
+
169
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
170
+ expect(collected.ok).toBe(true);
171
+ if (!collected.ok) return;
172
+ const scene = collected.value;
173
+ expect(scene.entities).toHaveLength(2);
174
+
175
+ const comps0 = (scene.entities[0]?.components as Record<string, Record<string, unknown>>)
176
+ .Test_RT_BOOL;
177
+ expect(comps0).toBeDefined();
178
+ if (!comps0) throw new Error('Test_RT_BOOL missing on e0');
179
+ expect(comps0.flag).toBe(true);
180
+
181
+ const comps1 = (scene.entities[1]?.components as Record<string, Record<string, unknown>>)
182
+ .Test_RT_BOOL;
183
+ expect(comps1).toBeDefined();
184
+ if (!comps1) throw new Error('Test_RT_BOOL missing on e1');
185
+ expect(comps1.flag).toBe(false);
186
+ });
187
+
188
+ it('string field round-trips with value equivalence', () => {
189
+ const Test_Str = defineComponent('Test_RT_STR', { label: 'string' });
190
+
191
+ const world = new World();
192
+ registerComponents(world, Test_Str);
193
+ const reg = makeRegistry();
194
+ const r0 = s(world, Test_Str, { label: 'hello-primitive-test' });
195
+
196
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
197
+ expect(collected.ok).toBe(true);
198
+ if (!collected.ok) return;
199
+ const scene = collected.value;
200
+ expect(scene.entities).toHaveLength(1);
201
+
202
+ const ent0 = scene.entities[0];
203
+ if (!ent0) throw new Error('entity 0 missing');
204
+ const comps = ent0.components as Record<string, Record<string, unknown>>;
205
+ const cf = comps.Test_RT_STR;
206
+ expect(cf).toBeDefined();
207
+ if (!cf) throw new Error('Test_RT_STR missing');
208
+ expect(cf.label).toBe('hello-primitive-test');
209
+ });
210
+ });
211
+
212
+ // ═══════════════════════════════════════════════════════════════════════════════
213
+ // m3-t3(b): entity + shared<> + primitive mixed entity full-chain value equivalence
214
+ // ═══════════════════════════════════════════════════════════════════════════════
215
+
216
+ describe('m3-t3(b): mixed entity+shared+primitive round-trip', () => {
217
+ it('entity with all primitive types + entity ref + shared ref survives round-trip', () => {
218
+ // Primitive component.
219
+ const Test_MixedPrim = defineComponent('Test_RT_MixedPrim', {
220
+ posX: 'f32',
221
+ posY: 'f32',
222
+ count: 'i32',
223
+ flags: 'u32',
224
+ active: 'bool',
225
+ name: 'string',
226
+ });
227
+
228
+ // Entity ref component.
229
+ const Test_EntityRef = defineComponent('Test_EntityRef', { target: 'entity' });
230
+
231
+ // Shared ref component.
232
+ const Test_HasShared = defineComponent('Test_HasShared', {
233
+ ref: { type: 'shared<TestAsset>' },
234
+ // biome-ignore lint/suspicious/noExplicitAny: defineComponent constraint too strict for shared<> schema
235
+ } as any);
236
+
237
+ // Register a catalogued asset.
238
+ const assetPayload = makePayload('skeleton');
239
+ const reg = makeRegistry();
240
+ const guid = AssetGuid.parse('d0000000-d000-0000-0000-000000000001');
241
+ if (!guid.ok) throw new Error('guid parse failed');
242
+ reg.catalog(guid.value, assetPayload);
243
+
244
+ const world = new World();
245
+ const handle = world.allocSharedRef('', assetPayload);
246
+ registerComponents(world, Test_MixedPrim, Test_EntityRef, Test_HasShared, ChildOf);
247
+
248
+ // Spawn entity A (primitive holder) as root.
249
+ const r0 = s(world, Test_MixedPrim, {
250
+ posX: 1.5,
251
+ posY: 2.5,
252
+ count: 7,
253
+ flags: 42,
254
+ active: true,
255
+ name: 'mixed-entity',
256
+ });
257
+
258
+ // Spawn entity B (with entity ref to A + shared ref).
259
+ const r1 = s(world, Test_EntityRef, { target: r0 as EntityHandle });
260
+ world.addComponent(r1 as EntityHandle, {
261
+ component: Test_HasShared,
262
+ // biome-ignore lint/suspicious/noExplicitAny: Handle branded type not assignable to component data for shared<> schema
263
+ data: { ref: handle as any },
264
+ });
265
+
266
+ // Link r0 → r1 via Children so both are in the BFS closure.
267
+ linkChildren(world, r0 as EntityHandle, [r1 as EntityHandle]);
268
+
269
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
270
+ expect(collected.ok).toBe(true);
271
+ if (!collected.ok) return;
272
+ const scene = collected.value;
273
+ expect(scene.entities).toHaveLength(2);
274
+
275
+ // Entity 0 (r0): primitives
276
+ const ent0 = scene.entities[0];
277
+ if (!ent0) throw new Error('e0 missing');
278
+ const mp = (ent0.components as Record<string, Record<string, unknown>>).Test_RT_MixedPrim;
279
+ expect(mp).toBeDefined();
280
+ if (!mp) throw new Error('Test_RT_MixedPrim missing');
281
+ expect(mp.posX).toBe(1.5);
282
+ expect(mp.posY).toBe(2.5);
283
+ expect(mp.count).toBe(7);
284
+ expect(mp.flags).toBe(42);
285
+ expect(mp.active).toBe(true);
286
+ expect(mp.name).toBe('mixed-entity');
287
+
288
+ // Entity 1 (r1): entity ref + shared ref
289
+ const ent1 = scene.entities[1];
290
+ if (!ent1) throw new Error('e1 missing');
291
+ const er = (ent1.components as Record<string, Record<string, unknown>>).Test_EntityRef;
292
+ expect(er).toBeDefined();
293
+ if (!er) throw new Error('Test_EntityRef missing');
294
+ // After localId renumbering, the target should be a valid localId number.
295
+ expect(typeof er.target).toBe('number');
296
+ expect(er.target as number).toBeGreaterThanOrEqual(0);
297
+
298
+ // shared<> field must resolve to GUID string.
299
+ const hs = (ent1.components as Record<string, Record<string, unknown>>).Test_HasShared;
300
+ expect(hs).toBeDefined();
301
+ if (!hs) throw new Error('Test_HasShared missing');
302
+ expect(typeof hs.ref).toBe('string');
303
+ });
304
+ });
305
+
306
+ // ═══════════════════════════════════════════════════════════════════════════════
307
+ // m3-t3(c): Float32Array field round-trip as plain Array + value equivalence
308
+ // ═══════════════════════════════════════════════════════════════════════════════
309
+
310
+ describe('m3-t3(c): TypedArray->Array round-trip normalization', () => {
311
+ it('Float32Array field round-trips to plain Array with value equivalence', () => {
312
+ const Test_ArrF32 = defineComponent('Test_RT_ArrF32', {
313
+ data: 'array<f32>',
314
+ });
315
+
316
+ const world = new World();
317
+ registerComponents(world, Test_ArrF32);
318
+ const reg = makeRegistry();
319
+ const arr = new Float32Array([1.0, 2.5, 3.75, 4.0, 5.125]);
320
+ const r0 = s(world, Test_ArrF32, {
321
+ // biome-ignore lint/suspicious/noExplicitAny: Float32Array not directly assignable to component data field
322
+ data: arr as any,
323
+ });
324
+
325
+ const collected = rootsToSceneAsset(reg, world, [r0 as EntityHandle]);
326
+ expect(collected.ok).toBe(true);
327
+ if (!collected.ok) return;
328
+ const scene = collected.value;
329
+ expect(scene.entities).toHaveLength(1);
330
+
331
+ const ent0 = scene.entities[0];
332
+ if (!ent0) throw new Error('entity 0 missing');
333
+ const comps = ent0.components as Record<string, Record<string, unknown>>;
334
+ const cf = comps.Test_RT_ArrF32;
335
+ expect(cf).toBeDefined();
336
+ if (!cf) throw new Error('Test_RT_ArrF32 missing');
337
+ const data = cf.data as unknown[];
338
+
339
+ // Round-trip output must be a plain Array.
340
+ expect(Array.isArray(data)).toBe(true);
341
+ expect(data).not.toBeInstanceOf(Float32Array);
342
+
343
+ // Values must be equivalent.
344
+ expect(data).toHaveLength(5);
345
+ expect(data[0]).toBe(1.0);
346
+ expect(data[1]).toBe(2.5);
347
+ expect(data[2]).toBe(3.75);
348
+ expect(data[3]).toBe(4.0);
349
+ expect(data[4]).toBeCloseTo(5.125, 5);
350
+ });
351
+ });
@@ -0,0 +1,123 @@
1
+ // scene-bare-guid-refs-instantiate.test — regression for the prod Play
2
+ // instantiate crash (feedback 2026-06-23, root cause corrected 2026-06-24).
3
+ //
4
+ // Reproduces the production on-disk pack shape that in-process / unit tests
5
+ // never exercised: a catalogued scene envelope whose `refs[]` are *bare GUID
6
+ // edges* (`sceneEntityId` / `sourceField` stripped at the w7 D-10
7
+ // serialization boundary), with multiple entities referencing the same mesh
8
+ // GUID through `MeshFilter.assetHandle`.
9
+ //
10
+ // Before the fix, `_resolveSceneGuids` took Branch A (envelope.refs.length>0)
11
+ // but `continue`-skipped every bare edge (no sceneEntityId/sourceField) →
12
+ // `resolvedMap` stayed empty → the entity-walk fallback (only reachable on the
13
+ // `else` / no-refs branch) never ran → the GUID *string* passed through to
14
+ // spawn. There `col.view[row] = (guidString as number)` coerced to 0 and
15
+ // `retainSharedScalarHandle(guidString)` skipped the `< BUILTIN_BASE` guard
16
+ // (NaN compare is false) → `SharedRefStore.retain` routed `shared-ref-released`
17
+ // to the World error handler, and the field read back as the sentinel 0 (the
18
+ // per-frame `asset-not-registered` flood in the studio report).
19
+ //
20
+ // The fix falls through to the entity-walk fallback whenever the structured
21
+ // edges resolved nothing, so GUID strings resolve to live user-tier handles
22
+ // before spawn.
23
+
24
+ import { AssetRegistry } from '@forgeax/engine-assets-runtime';
25
+ import { World } from '@forgeax/engine-ecs';
26
+ import { createBoxGeometry } from '@forgeax/engine-geometry';
27
+ import { AssetGuid } from '@forgeax/engine-pack/guid';
28
+ import { MeshFilter, SceneInstance } from '@forgeax/engine-render';
29
+ import type { LocalEntityId, MeshAsset, SceneAsset, SceneEntity } from '@forgeax/engine-types';
30
+ import { BUILTIN_BASE } from '@forgeax/engine-types';
31
+ import { describe, expect, it } from 'vitest';
32
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
33
+ import { registerSceneComponents } from './helpers/register-scene-components';
34
+
35
+ function localId(n: number): LocalEntityId {
36
+ return n as LocalEntityId;
37
+ }
38
+
39
+ function cubeMesh(): MeshAsset {
40
+ const res = createBoxGeometry(1, 1, 1);
41
+ if (!res.ok) throw new Error('createBoxGeometry(1,1,1) failed');
42
+ return res.value;
43
+ }
44
+
45
+ // Two distinct mesh GUIDs referenced from N entities each — mirrors the studio
46
+ // report where engine builtin cube/sphere were among the unresolved handles.
47
+ const MESH_GUID_A = '00d274da-e863-41d8-bafe-10b97d1468d4';
48
+ const MESH_GUID_B = '95730fd2-1111-4222-8333-444455556666';
49
+
50
+ describe('regression — prod bare-GUID scene envelope.refs resolve before retain', () => {
51
+ it('instantiate resolves bare-GUID MeshFilter.assetHandle across N entities (no shared-ref-released)', () => {
52
+ const reg = new AssetRegistry(makeMockShaderRegistry());
53
+ const world = new World();
54
+ registerSceneComponents(world, [MeshFilter]);
55
+
56
+ // Catalogue the two mesh payloads (as loadByGuid would on the prod path).
57
+ const guidA = AssetGuid.parse(MESH_GUID_A);
58
+ const guidB = AssetGuid.parse(MESH_GUID_B);
59
+ if (!guidA.ok || !guidB.ok) throw new Error('GUID parse failed');
60
+ expect(reg.catalog(guidA.value, cubeMesh()).ok).toBe(true);
61
+ expect(reg.catalog(guidB.value, cubeMesh()).ok).toBe(true);
62
+
63
+ // Build a scene whose entities reference the meshes by GUID *string* —
64
+ // exactly the post-parseScenePayload intermediate state. Several entities
65
+ // share each GUID to exercise the dedup (one allocSharedRef per GUID).
66
+ const entities: SceneEntity[] = [];
67
+ for (let i = 0; i < 4; i++) {
68
+ entities.push({
69
+ localId: localId(i),
70
+ components: {
71
+ MeshFilter: { assetHandle: i % 2 === 0 ? MESH_GUID_A : MESH_GUID_B },
72
+ },
73
+ } as unknown as SceneEntity);
74
+ }
75
+ const scene: SceneAsset = { kind: 'scene', entities };
76
+
77
+ // Catalogue the scene as an envelope carrying BARE-GUID refs[] — no
78
+ // sceneEntityId / sourceField (the prod serialization shape). This forces
79
+ // Branch A of _resolveSceneGuids while leaving every edge unresolvable.
80
+ const SCENE_GUID = 'c1111111-2222-4333-8444-555566667777';
81
+ const sceneGuid = AssetGuid.parse(SCENE_GUID);
82
+ if (!sceneGuid.ok) throw new Error('scene GUID parse failed');
83
+ expect(
84
+ reg.catalog(sceneGuid.value, scene, [{ guid: MESH_GUID_A }, { guid: MESH_GUID_B }]).ok,
85
+ ).toBe(true);
86
+
87
+ // Mint the scene handle and instantiate through the public sugar entry.
88
+ const sceneHandle = world.allocSharedRef('SceneAsset', scene);
89
+ const res = reg.instantiate<SceneAsset>(sceneHandle, world);
90
+
91
+ expect(res.ok).toBe(true);
92
+ if (!res.ok) return;
93
+
94
+ // Every spawned member's MeshFilter.assetHandle is a resolved
95
+ // user-tier slot (>= BUILTIN_BASE) — not the sentinel 0 a coerced GUID
96
+ // string would leave behind.
97
+ const inst = world.get(res.value, SceneInstance);
98
+ expect(inst.ok).toBe(true);
99
+ if (!inst.ok) return;
100
+ let seen = 0;
101
+ for (let i = 0; i < 4; i++) {
102
+ const member = inst.value.mapping[i] as unknown as number;
103
+ const mf = world.get(member as never, MeshFilter);
104
+ expect(mf.ok).toBe(true);
105
+ if (!mf.ok) continue;
106
+ const handle = mf.value.assetHandle as unknown as number;
107
+ expect(typeof handle).toBe('number');
108
+ expect(handle).toBeGreaterThanOrEqual(BUILTIN_BASE);
109
+ seen++;
110
+ }
111
+ expect(seen).toBe(4);
112
+
113
+ // Dedup: the two distinct GUIDs mint exactly two user-tier handles,
114
+ // shared across the four members (one allocSharedRef per unique GUID).
115
+ const handles = new Set<number>();
116
+ for (let i = 0; i < 4; i++) {
117
+ const member = inst.value.mapping[i] as unknown as number;
118
+ const mf = world.get(member as never, MeshFilter);
119
+ if (mf.ok) handles.add(mf.value.assetHandle as unknown as number);
120
+ }
121
+ expect(handles.size).toBe(2);
122
+ });
123
+ });
@@ -1,8 +1,48 @@
1
+ // feat-20260630-equirect-kind-internalized-ibl-declarative-skyligh M3 / w15 —
2
+ // scene roundtrip + instantiate handle resolution for the declarative skylight
3
+ // (plan-strategy §5.3 key test point (4); requirements AC-07 / AC-04;
4
+ // research R-1 — scene-handle-fields generic `shared<` extraction auto-covers
5
+ // the equirect field, no per-field whitelist).
6
+ //
7
+ // Two assertions, both on the CONSUMER path (not `.test-d.ts`):
8
+ // (1) A SceneAsset whose Skylight references an equirect source by GUID
9
+ // string round-trips through instantiate: the GUID resolves to a live
10
+ // user-tier shared handle on the spawned Skylight column (AC-07). This
11
+ // exercises BOTH scene-resolution paths the equirect field rides:
12
+ // - extractSceneEntityHandleGuids (generic `shared<` detection, R-1)
13
+ // - parseScenePayload HANDLE_FIELD_NAMES allowlist (w27, second path)
14
+ // (2) `world.spawn(Skylight{equirect}).data.equirect` is typed
15
+ // `Handle<'EquirectAsset','shared'>` — verified by assigning a branded
16
+ // EquirectAsset handle into the spawn data and reading it back (a wrong
17
+ // field type would fail typecheck on this consumer path, AC-04).
18
+ //
19
+ // TDD red phase: the equirect field lands in w16 (Skylight component) +
20
+ // w27 (HANDLE_FIELD_NAMES). Until then the `shared<EquirectAsset>` field name
21
+ // is `cubemap` and this file fails to compile / resolve — that is the red.
22
+
23
+ import { AssetRegistry } from '@forgeax/engine-assets-runtime';
24
+ import type { EntityHandle } from '@forgeax/engine-ecs';
1
25
  import { World } from '@forgeax/engine-ecs';
2
- import { Skylight } from '@forgeax/engine-render/internal';
3
- import type { EquirectAsset, Handle } from '@forgeax/engine-types';
26
+ import { Skylight } from '@forgeax/engine-render';
27
+ import type {
28
+ EquirectAsset,
29
+ Handle,
30
+ LocalEntityId,
31
+ SceneAsset,
32
+ SceneEntity,
33
+ } from '@forgeax/engine-types';
34
+ import { BUILTIN_BASE } from '@forgeax/engine-types';
4
35
  import { describe, expect, it } from 'vitest';
36
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
37
+ import { registerSceneComponents } from './helpers/register-scene-components';
38
+
39
+ function localId(n: number): LocalEntityId {
40
+ return n as LocalEntityId;
41
+ }
5
42
 
43
+ // A minimal valid EquirectAsset POD (kind:'equirect', single 2D rgba16float
44
+ // image). The roundtrip never decodes the bytes; a tiny tight-packed buffer is
45
+ // enough to catalogue + resolve the handle.
6
46
  function equirectPod(width = 4, height = 2): EquirectAsset {
7
47
  return {
8
48
  kind: 'equirect',
@@ -14,20 +54,67 @@ function equirectPod(width = 4, height = 2): EquirectAsset {
14
54
  };
15
55
  }
16
56
 
17
- describe('Skylight equirect shared-reference ownership', () => {
18
- it('stores a World.sharedRefs-owned EquirectAsset handle on the consumer path', () => {
57
+ const EQUIRECT_GUID = '019e4a26-3c29-7420-af5d-20f2724a16b0';
58
+
59
+ describe('scene equirect roundtrip + instantiate handle resolution (M3 / w15)', () => {
60
+ it('(1) Skylight{equirect: GUID} round-trips: instantiate resolves the GUID to a live user-tier shared handle (AC-07)', async () => {
61
+ const reg = new AssetRegistry(makeMockShaderRegistry());
62
+ const world = new World();
63
+ registerSceneComponents(world, [Skylight]);
64
+
65
+ // Catalogue the equirect payload exactly as loadByGuid would on the prod
66
+ // path, so the GUID string in the scene resolves to a real handle.
67
+ const { AssetGuid } = await import('@forgeax/engine-pack/guid');
68
+ const guid = AssetGuid.parse(EQUIRECT_GUID);
69
+ if (!guid.ok) throw new Error('equirect GUID parse failed');
70
+ expect(reg.catalog(guid.value, equirectPod()).ok).toBe(true);
71
+
72
+ // A scene whose single Skylight references the equirect source by GUID
73
+ // string — the post-parseScenePayload intermediate state where handle
74
+ // fields hold GUID strings awaiting resolution.
75
+ const entities: SceneEntity[] = [
76
+ {
77
+ localId: localId(0),
78
+ components: {
79
+ Skylight: { equirect: EQUIRECT_GUID, intensity: 1.0 },
80
+ },
81
+ } as unknown as SceneEntity,
82
+ ];
83
+ const scene: SceneAsset = { kind: 'scene', entities };
84
+
85
+ const sceneHandle = world.allocSharedRef('SceneAsset', scene);
86
+ const res = reg.instantiate<SceneAsset>(sceneHandle, world);
87
+ expect(res.ok).toBe(true);
88
+ if (!res.ok) return;
89
+
90
+ // The spawned Skylight's equirect field must be a resolved user-tier slot
91
+ // (>= BUILTIN_BASE), not the sentinel 0 a coerced GUID string would leave.
92
+ const root = res.value as EntityHandle;
93
+ const { SceneInstance } = await import('@forgeax/engine-render');
94
+ const inst = world.get(root, SceneInstance);
95
+ expect(inst.ok).toBe(true);
96
+ if (!inst.ok) return;
97
+ const member = inst.value.mapping[0] as unknown as EntityHandle;
98
+ const sky = world.get(member, Skylight);
99
+ expect(sky.ok).toBe(true);
100
+ if (!sky.ok) return;
101
+ const equirectHandle = sky.value.equirect as unknown as number;
102
+ expect(typeof equirectHandle).toBe('number');
103
+ expect(equirectHandle).toBeGreaterThanOrEqual(BUILTIN_BASE);
104
+ });
105
+
106
+ it('(2) world.spawn(Skylight{equirect}).data.equirect is typed Handle<EquirectAsset,shared> on the consumer path (AC-04)', () => {
19
107
  const world = new World();
20
- const equirect: Handle<'EquirectAsset', 'shared'> = world.allocSharedRef(
21
- 'EquirectAsset',
22
- equirectPod(),
23
- );
24
- const entity = world.spawn({ component: Skylight, data: { equirect } }).unwrap();
25
-
26
- const stored = world.get(entity, Skylight).unwrap().equirect;
27
- const resolved = world.sharedRefs.resolve<string, EquirectAsset>(stored);
28
-
29
- expect(stored).toBe(equirect);
30
- expect(resolved.ok).toBe(true);
31
- if (resolved.ok) expect(resolved.value.kind).toBe('equirect');
108
+ registerSceneComponents(world, [Skylight]);
109
+ // Branded EquirectAsset handle — assigning it into the spawn `equirect`
110
+ // field is the consumer-path type assertion: a wrong field type (e.g. the
111
+ // retired CubeTextureAsset, or a non-handle column) would fail typecheck
112
+ // here, not in a separate .test-d.ts.
113
+ const equirect: Handle<'EquirectAsset', 'shared'> = 1024 as Handle<'EquirectAsset', 'shared'>;
114
+ const e = world.spawn({ component: Skylight, data: { equirect } }).unwrap();
115
+ const r = world.get(e, Skylight).unwrap();
116
+ // The read-back value carries the same handle (runtime confirms the column
117
+ // stored the shared handle, complementing the compile-time field type).
118
+ expect(r.equirect as unknown as number).toBe(1024);
32
119
  });
33
120
  });
@@ -0,0 +1,8 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { instantiateFlat } from '../../../assets-runtime/src/registry/instantiate';
3
+
4
+ describe('scene authoring bridge', () => {
5
+ it('exposes the flat authoring entry without a runtime duplicate', () => {
6
+ expect(typeof instantiateFlat).toBe('function');
7
+ });
8
+ });
@@ -1,5 +1,5 @@
1
- import { postSpawnResolveJoints } from '@forgeax/engine-render/internal';
2
1
  import { describe, expect, it } from 'vitest';
2
+ import { postSpawnResolveJoints } from '../../../render/src/scene-instances/post-spawn-resolve-joints';
3
3
 
4
4
  describe('scene instance skin bridge', () => {
5
5
  it('exports a post-spawn resolver for nested mounts', () => {
@@ -14,7 +14,7 @@
14
14
  // dynamic structure); plan-tasks §M2 / w15.
15
15
 
16
16
  import { componentSchema } from '@forgeax/engine-ecs/internal';
17
- import { SceneInstance } from '@forgeax/engine-render/internal';
17
+ import { SceneInstance } from '@forgeax/engine-render';
18
18
  import { describe, expect, it } from 'vitest';
19
19
 
20
20
  describe('SceneInstance component (w15)', () => {