@forgeax/engine-runtime 0.1.4 → 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,202 @@
1
+ // scene-mount-wrapper-roundtrip.test.ts — regression for the editor "Add to
2
+ // Scene" ghost-node accretion bug.
3
+ //
4
+ // The editor's whole-GLB Add-to-Scene (spawnGlbSceneAsMount) produces a scene
5
+ // pack shaped like:
6
+ // entities: [ ..., { localId: W, Name:"bed.glb", Transform, Children:[M] } ]
7
+ // mounts: [ { localId: M, source: <bedGUID>, memberCount: N, parent: W } ]
8
+ // i.e. an OWNED wrapper entity whose child is a nested mount. This is the exact
9
+ // on-disk shape after the first add+save.
10
+ //
11
+ // On RELOAD, world.instantiateScene re-materialises the mount as a plain "mount
12
+ // entity" (no Name, no SceneInstance — just Transform/ChildOf/Children) sitting
13
+ // BETWEEN the wrapper and the child SceneInstance root. On the NEXT collect that
14
+ // plain mount entity carries no SceneInstance, so rootsToSceneAsset emitted it
15
+ // as an OWNED (nameless) entity + a fresh mount — one extra ghost node per
16
+ // save→reload cycle. This test asserts collect is a FIXED POINT across two
17
+ // reload cycles.
18
+
19
+ import type { Asset } from '@forgeax/engine-assets-runtime';
20
+ import { AssetRegistry } from '@forgeax/engine-assets-runtime';
21
+ import { World } from '@forgeax/engine-ecs';
22
+ import { AssetGuid } from '@forgeax/engine-pack/guid';
23
+ import { Children, Name, Transform } from '@forgeax/engine-scene';
24
+ import type { Handle, SceneAsset } from '@forgeax/engine-types';
25
+ import { describe, expect, it } from 'vitest';
26
+ import { rootsToSceneAsset, serializeSceneAssetToPack } from '../collect-scene-asset';
27
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
28
+ import { registerSceneComponents } from './helpers/register-scene-components';
29
+
30
+ const G_CHILD = '11111111-1111-4111-8111-111111111111';
31
+ const G_TOP = '22222222-2222-4222-8222-222222222222';
32
+
33
+ function mkReg(): AssetRegistry {
34
+ return new AssetRegistry(makeMockShaderRegistry());
35
+ }
36
+ function pg(s: string): AssetGuid {
37
+ const r = AssetGuid.parse(s);
38
+ if (!r.ok) throw new Error(`bad GUID: ${s}`);
39
+ return r.value;
40
+ }
41
+ function cat(reg: AssetRegistry, g: string, p: SceneAsset): void {
42
+ reg.catalog(pg(g), p as Asset);
43
+ }
44
+ function rs(w: World, a: SceneAsset): Handle<'SceneAsset', 'shared'> {
45
+ registerSceneComponents(w, [Name]);
46
+ return w.allocSharedRef('SceneAsset', a);
47
+ }
48
+ function accessParse(reg: AssetRegistry) {
49
+ const internal = reg as unknown as {
50
+ parseAssetPayload(kind: string, payload: Record<string, unknown>, refs?: string[]): unknown;
51
+ };
52
+ return (payload: Record<string, unknown>, refs?: readonly string[]): SceneAsset =>
53
+ internal.parseAssetPayload('scene', payload, refs as string[] | undefined) as SceneAsset;
54
+ }
55
+ function unpack(pack: Record<string, unknown>): {
56
+ payload: Record<string, unknown>;
57
+ refs: readonly string[] | undefined;
58
+ } {
59
+ const a = (pack.assets as Record<string, unknown>[])[0] as Record<string, unknown>;
60
+ return { payload: a.payload as Record<string, unknown>, refs: a.refs as string[] | undefined };
61
+ }
62
+
63
+ describe('editor Add-to-Scene wrapper+mount round-trip (ghost accretion regression)', () => {
64
+ it('collect is a fixed point across reload cycles (no nameless ghost accretes)', () => {
65
+ const reg = mkReg();
66
+ const w = new World();
67
+
68
+ // Child scene = the "bed": one owned mesh entity.
69
+ const child: SceneAsset = {
70
+ kind: 'scene',
71
+ entities: [
72
+ {
73
+ localId: 0 as never,
74
+ components: { Name: { value: 'bed-mesh' }, Transform: { pos: [0, 0, 0] } },
75
+ },
76
+ ],
77
+ };
78
+ cat(reg, G_CHILD, child);
79
+
80
+ // Plain top scene with ONE owned entity (like spin-cube's Ground). The
81
+ // editor adds the mount live below via a wrapper (no mounts[] on disk yet).
82
+ const top: SceneAsset = {
83
+ kind: 'scene',
84
+ entities: [
85
+ {
86
+ localId: 0 as never,
87
+ components: { Name: { value: 'Ground' }, Transform: { pos: [0, 0, 0] } },
88
+ },
89
+ ],
90
+ };
91
+ cat(reg, G_TOP, top);
92
+
93
+ const parse = accessParse(reg);
94
+
95
+ const runCycle = (roots: number[]): { owned: number; mounts: number; pack: SceneAsset } => {
96
+ const c = rootsToSceneAsset(reg, w, roots as never);
97
+ if (!c.ok) throw new Error(`collect failed: ${JSON.stringify(c.error)}`);
98
+ return {
99
+ owned: c.value.entities.length,
100
+ mounts: (c.value.mounts ?? []).length,
101
+ pack: c.value,
102
+ };
103
+ };
104
+
105
+ // The editor's owned top-level roots after a reload = the named entities the
106
+ // session tracks (store.ts _e2h owned-set: the scene asset's entities[], not
107
+ // mount internals). Mirror that here by taking the NAMED entities reachable
108
+ // from the scene (Ground + the bed.glb wrapper), excluding the nameless
109
+ // mount carrier — exactly what the editor collects via entRootHandles.
110
+ const namedTopEntities = (syntheticRoot: number): number[] => {
111
+ const wr = w as unknown as {
112
+ get(
113
+ e: number,
114
+ c: unknown,
115
+ ): {
116
+ ok: boolean;
117
+ value?: { entities?: ArrayLike<number>; value?: string; parent?: number };
118
+ };
119
+ };
120
+ // BFS from the synthetic root over Children; keep NAMED entities whose
121
+ // parent is not itself a named-tracked entity (i.e. top-level owned roots).
122
+ const named: number[] = [];
123
+ const queue = [syntheticRoot];
124
+ const seen = new Set<number>([syntheticRoot]);
125
+ while (queue.length) {
126
+ const cur = queue.shift() as number;
127
+ const ch = wr.get(cur, Children);
128
+ if (ch.ok && ch.value?.entities) {
129
+ for (const k of Array.from(ch.value.entities)) {
130
+ if (seen.has(k)) continue;
131
+ seen.add(k);
132
+ queue.push(k);
133
+ if (wr.get(k, Name).ok) named.push(k);
134
+ }
135
+ }
136
+ }
137
+ return named;
138
+ };
139
+
140
+ // Instantiate the top scene.
141
+ const i0 = reg.instantiate(rs(w, top), w);
142
+ expect(i0.ok).toBe(true);
143
+ if (!i0.ok) return;
144
+
145
+ // ── Editor "Add to Scene": spawn a NAMED wrapper parented under the top
146
+ // scene, then mount the child scene UNDER the wrapper (instantiate with
147
+ // parent=wrapper). Mirrors spawnGlbSceneAsMount +
148
+ // instantiateSceneRefUnderWorld. ──
149
+ const wrapperRes = w.spawn(
150
+ { component: Name, data: { value: 'bed.glb' } },
151
+ { component: Transform, data: { pos: [0, 0, 0] } },
152
+ );
153
+ expect(wrapperRes.ok).toBe(true);
154
+ if (!wrapperRes.ok) return;
155
+ const mountRes = reg.instantiate(rs(w, child), w, wrapperRes.value);
156
+ expect(mountRes.ok).toBe(true);
157
+ if (!mountRes.ok) return;
158
+
159
+ // Cycle 1: collect from the owned roots (Ground + wrapper).
160
+ // Ground is a child of the synthetic root; the wrapper is a free root we
161
+ // just spawned. Collect from both (the editor's entRootHandles set).
162
+ const groundRoots = namedTopEntities(i0.value as unknown as number);
163
+ const c1 = runCycle([...groundRoots, wrapperRes.value as unknown as number]);
164
+
165
+ // Cycle 2: serialize → parse → reload → collect.
166
+ const s1 = serializeSceneAssetToPack(c1.pack, w.components.entries(), G_TOP);
167
+ expect(s1.ok).toBe(true);
168
+ if (!s1.ok) return;
169
+ const u1 = unpack(s1.value);
170
+ const p1 = parse(u1.payload, u1.refs);
171
+ cat(reg, G_TOP, p1);
172
+ const i1 = reg.instantiate(rs(w, p1), w);
173
+ expect(i1.ok).toBe(true);
174
+ if (!i1.ok) return;
175
+ const c2 = runCycle(namedTopEntities(i1.value as unknown as number));
176
+
177
+ // Cycle 3: reload + collect once more (the ghost-accretion point).
178
+ const s2 = serializeSceneAssetToPack(c2.pack, w.components.entries(), G_TOP);
179
+ expect(s2.ok).toBe(true);
180
+ if (!s2.ok) return;
181
+ const u2 = unpack(s2.value);
182
+ const p2 = parse(u2.payload, u2.refs);
183
+ cat(reg, G_TOP, p2);
184
+ const i2 = reg.instantiate(rs(w, p2), w);
185
+ expect(i2.ok).toBe(true);
186
+ if (!i2.ok) return;
187
+ const c3 = runCycle(namedTopEntities(i2.value as unknown as number));
188
+
189
+ // ACCEPTANCE: owned + mount counts are a FIXED POINT across reloads (before
190
+ // the fix this grew unboundedly: owned 2 → 3 → 5, one nameless ghost per
191
+ // cycle). Ground + bed.glb wrapper = 2 owned; the bed = 1 mount.
192
+ expect({ owned: c1.owned, mounts: c1.mounts }).toEqual({ owned: 2, mounts: 1 });
193
+ expect({ owned: c2.owned, mounts: c2.mounts }).toEqual({ owned: 2, mounts: 1 });
194
+ expect({ owned: c3.owned, mounts: c3.mounts }).toEqual({ owned: 2, mounts: 1 });
195
+
196
+ // No owned entity is nameless (the ghost signature).
197
+ for (const e of c3.pack.entities) {
198
+ const comps = e.components as Record<string, Record<string, unknown>>;
199
+ expect(comps.Name, `owned entity localId ${e.localId} must have a Name`).toBeDefined();
200
+ }
201
+ });
202
+ });
@@ -0,0 +1,324 @@
1
+ import * as SceneOwner from '@forgeax/engine-scene';
2
+ // scene-sugar-instantiate.test - engine.assets.instantiate sugar wrapper
3
+ // runtime equivalence (feat-20260514-scene-as-world-blueprint w30; M3 rewrite
4
+ // from old SceneInstanceId returns to new Entity returns).
5
+ //
6
+ // Coverage:
7
+ // (a) sugar entry runs the same pipeline as the main entry: a 2-node
8
+ // SceneAsset goes through `engine.assets.instantiate(handle, world)`
9
+ // and yields the same Entity root / mapping / overrides as the
10
+ // direct `SceneOwner.worldInstantiateScene(world, handle)` call (AC-03 +
11
+ // requirements §IN-3 sugar contract).
12
+ // (b) `parent?` passthrough: passing a parent through the sugar wrapper
13
+ // attaches `ChildOf { parent }` to the root nodes byte-for-byte the
14
+ // same way the main entry does.
15
+ // (c) error passthrough: when the underlying SceneAssetResolver returns
16
+ // Err, the sugar surface returns the same Err verbatim — no wrap, no
17
+ // rename, no message rewrite (research §error-model + plan-strategy
18
+ // §3.3 closed-union transparency).
19
+
20
+ import { AssetRegistry } from '@forgeax/engine-assets-runtime';
21
+ import { defineComponent, type EntityHandle, World } from '@forgeax/engine-ecs';
22
+ import { SceneInstance } from '@forgeax/engine-render';
23
+ import { ChildOf } from '@forgeax/engine-scene';
24
+ import type { Handle, LocalEntityId, SceneAsset, SceneEntity } from '@forgeax/engine-types';
25
+ import { toShared } from '@forgeax/engine-types';
26
+ import { describe, expect, it } from 'vitest';
27
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
28
+ import { registerRuntimeComponents } from './helpers/register-runtime-components';
29
+
30
+ function localId(n: number): LocalEntityId {
31
+ return n as LocalEntityId;
32
+ }
33
+
34
+ function buildScene(): SceneAsset {
35
+ const Transform = defineComponent('Transform', { pos: 'array<f32, 3>' });
36
+ void Transform;
37
+ const nodes: SceneEntity[] = [
38
+ { localId: localId(0), components: { Transform: { pos: [1, 0, 0] } } },
39
+ { localId: localId(1), components: { Transform: { pos: [2, 0, 0] } } },
40
+ ];
41
+ return { kind: 'scene', entities: nodes };
42
+ }
43
+
44
+ function registerSceneAsset(world: World, asset: SceneAsset): Handle<'SceneAsset', 'shared'> {
45
+ return world.allocSharedRef('SceneAsset', asset);
46
+ }
47
+
48
+ describe('w30 - engine.assets.instantiate sugar wrapper equivalence (AC-03)', () => {
49
+ it('(a) sugar entry produces the same Entity root / mapping shape as the main entry', () => {
50
+ defineComponent('Transform', { pos: 'array<f32, 3>' });
51
+ const reg = new AssetRegistry(makeMockShaderRegistry());
52
+ const asset = buildScene();
53
+ // Direct path baseline.
54
+ const worldA = new World();
55
+ registerRuntimeComponents(worldA);
56
+ const handleA = registerSceneAsset(worldA, asset);
57
+ const directRes = SceneOwner.worldInstantiateScene(worldA, handleA);
58
+ expect(directRes.ok).toBe(true);
59
+ if (!directRes.ok) return;
60
+ const directRoot = directRes.value.root;
61
+ const directInst = worldA.get(directRoot, SceneInstance);
62
+ expect(directInst.ok).toBe(true);
63
+ if (!directInst.ok) return;
64
+ const directState = SceneOwner.worldGetSceneInstanceState(worldA, directRoot);
65
+ expect(directState.ok).toBe(true);
66
+ if (!directState.ok) return;
67
+ // Sugar path.
68
+ const worldB = new World();
69
+ registerRuntimeComponents(worldB);
70
+ const handleB = registerSceneAsset(worldB, asset);
71
+ const sugarRes = reg.instantiate<SceneAsset>(handleB, worldB);
72
+ expect(sugarRes.ok).toBe(true);
73
+ if (!sugarRes.ok) return;
74
+ const sugarRoot: EntityHandle = sugarRes.value;
75
+ const sugarInst = worldB.get(sugarRoot, SceneInstance);
76
+ expect(sugarInst.ok).toBe(true);
77
+ if (!sugarInst.ok) return;
78
+ const sugarState = SceneOwner.worldGetSceneInstanceState(worldB, sugarRoot);
79
+ expect(sugarState.ok).toBe(true);
80
+ if (!sugarState.ok) return;
81
+ // Mapping length parity (2 nodes -> 2 slots).
82
+ expect(sugarInst.value.mapping.length).toBe(directInst.value.mapping.length);
83
+ expect(sugarState.value.overrides.size).toBe(directState.value.overrides.size);
84
+ expect(sugarState.value.overrides.size).toBe(0);
85
+ });
86
+
87
+ it('(b) parent? passthrough attaches ChildOf via the sugar entry', () => {
88
+ const Transform = defineComponent('Transform', { pos: 'array<f32, 3>' });
89
+ const reg = new AssetRegistry(makeMockShaderRegistry());
90
+ const asset = buildScene();
91
+ const world = new World();
92
+ registerRuntimeComponents(world);
93
+ const handle = registerSceneAsset(world, asset);
94
+ const parentSpawn = world.spawn({
95
+ component: Transform,
96
+ data: { pos: [0, 0, 0] },
97
+ });
98
+ expect(parentSpawn.ok).toBe(true);
99
+ if (!parentSpawn.ok) return;
100
+ const parentEntity: EntityHandle = parentSpawn.value;
101
+ const sugarRes = reg.instantiate<SceneAsset>(handle, world, parentEntity);
102
+ expect(sugarRes.ok).toBe(true);
103
+ if (!sugarRes.ok) return;
104
+ const sugarRoot: EntityHandle = sugarRes.value;
105
+ const sugarState = SceneOwner.worldGetSceneInstanceState(world, sugarRoot);
106
+ expect(sugarState.ok).toBe(true);
107
+ if (!sugarState.ok) return;
108
+ // The synthetic root now carries a ChildOf component pointing at the
109
+ // caller-supplied parent entity (root entities are children of the
110
+ // synthetic root, not of the caller-supplied parent directly).
111
+ const childOf = world.get(sugarRoot, ChildOf);
112
+ expect(childOf.ok).toBe(true);
113
+ if (!childOf.ok) return;
114
+ expect(childOf.value.parent).toBe(parentEntity);
115
+ });
116
+
117
+ it('(c) error passthrough: invalid handle -> sugar returns Err verbatim', () => {
118
+ const reg = new AssetRegistry(makeMockShaderRegistry());
119
+ const world = new World();
120
+ registerRuntimeComponents(world);
121
+ // Use a handle that is not a managed ref -> instantiateScene returns Err.
122
+ const bogusHandle = toShared<'SceneAsset'>(9999);
123
+ const r = reg.instantiate<SceneAsset>(bogusHandle, world);
124
+ expect(r.ok).toBe(false);
125
+ if (r.ok) return;
126
+ expect(typeof r.error).toBe('object');
127
+ });
128
+ });
129
+
130
+ // ── M5 post-instantiate component injection (w13) ──
131
+ // feat-20260528-scene-asset-guid-refs-and-post-instantiate M5 / w13 TDD red.
132
+ //
133
+ // Coverage:
134
+ // (d) AC-09: rootEntities() + addComponent -> hasComponent=true (query-after pattern);
135
+ // canonical post-instantiate workflow for attaching custom components to
136
+ // the top-level nodes of a prefab instance without a per-instance
137
+ // instantiate(overrides) API.
138
+ // (e) AC-10: mapping[localId] + addComponent -> hasComponent=true;
139
+ // verifies that an AI user can reach any specific node by its Scene-authored
140
+ // localId and attach a component after instantiation.
141
+ // (f) rootEntities() snapshot stays stable after addComponent -- the returned
142
+ // array is a snapshot at call time, not a live view (SceneInstance contract).
143
+
144
+ function buildPostScene(): SceneAsset {
145
+ const nodes: SceneEntity[] = [
146
+ { localId: localId(0), components: { Transform: { pos: [0, 0, 0] } } },
147
+ { localId: localId(1), components: { Transform: { pos: [1, 0, 0] }, ChildOf: { parent: 0 } } },
148
+ ];
149
+ return { kind: 'scene', entities: nodes };
150
+ }
151
+
152
+ // A lightweight component for post-instantiate injection testing.
153
+ const Enemy = defineComponent('Enemy', { speed: 'f32', hp: 'u32' });
154
+
155
+ // A second component so we can test per-localId injection independently.
156
+ const Waypoint = defineComponent('Waypoint', { index: 'u32' });
157
+
158
+ function postInstantiateEntity(entity: EntityHandle | number | undefined): EntityHandle {
159
+ if (typeof entity === 'number') return entity as EntityHandle;
160
+ throw new Error('rootEntities returned non-Entity entry');
161
+ }
162
+
163
+ describe('M5 post-instantiate component injection (w13 / AC-09 + AC-10)', () => {
164
+ it('(d) AC-09: rootEntities() + world.addComponent -> hasComponent is true', () => {
165
+ defineComponent('Transform', { pos: 'array<f32, 3>' });
166
+ const reg = new AssetRegistry(makeMockShaderRegistry());
167
+ const asset = buildPostScene();
168
+ const world = new World();
169
+ registerRuntimeComponents(world, [Enemy, Waypoint]);
170
+ const handle = registerSceneAsset(world, asset);
171
+ const r = reg.instantiate<SceneAsset>(handle, world);
172
+ expect(r.ok).toBe(true);
173
+ if (!r.ok) return;
174
+ const root: EntityHandle = r.value;
175
+ const state = SceneOwner.worldGetSceneInstanceState(world, root);
176
+ expect(state.ok).toBe(true);
177
+ if (!state.ok) return;
178
+ const roots = state.value.rootEntities;
179
+ expect(roots.length).toBe(1);
180
+ const rootEntity = postInstantiateEntity(roots[0]);
181
+ // Attach Enemy component via the query-after pattern.
182
+ const addRes = world.addComponent(rootEntity, {
183
+ component: Enemy,
184
+ data: { speed: 4.5, hp: 2 },
185
+ });
186
+ expect(addRes.ok).toBe(true);
187
+ if (!addRes.ok) return;
188
+ const enemyCheck = world.get(rootEntity, Enemy);
189
+ expect(enemyCheck.ok).toBe(true);
190
+ if (!enemyCheck.ok) return;
191
+ expect(enemyCheck.value.speed).toBe(4.5);
192
+ expect(enemyCheck.value.hp).toBe(2);
193
+ });
194
+
195
+ it('(e) AC-10: mapping[localId] + world.addComponent -> hasComponent is true', () => {
196
+ defineComponent('Transform', { pos: 'array<f32, 3>' });
197
+ const reg = new AssetRegistry(makeMockShaderRegistry());
198
+ const asset = buildPostScene();
199
+ const world = new World();
200
+ registerRuntimeComponents(world, [Enemy, Waypoint]);
201
+ const handle = registerSceneAsset(world, asset);
202
+ const r = reg.instantiate<SceneAsset>(handle, world);
203
+ expect(r.ok).toBe(true);
204
+ if (!r.ok) return;
205
+ const root: EntityHandle = r.value;
206
+ const inst = world.get(root, SceneInstance);
207
+ expect(inst.ok).toBe(true);
208
+ if (!inst.ok) return;
209
+ // Reach node 1 (child) by its localId via mapping array.
210
+ const mapping = inst.value.mapping;
211
+ const childEntity = mapping[1] as unknown as EntityHandle | undefined;
212
+ expect(childEntity).toBeDefined();
213
+ if (childEntity === undefined) return;
214
+ const addRes = world.addComponent(childEntity, {
215
+ component: Waypoint,
216
+ data: { index: 3 },
217
+ });
218
+ expect(addRes.ok).toBe(true);
219
+ if (!addRes.ok) return;
220
+ const wpCheck = world.get(childEntity, Waypoint);
221
+ expect(wpCheck.ok).toBe(true);
222
+ if (!wpCheck.ok) return;
223
+ expect(wpCheck.value.index).toBe(3);
224
+ });
225
+
226
+ it('(d-ii) AC-09: addComponent on a second root entity (multi-root scene)', () => {
227
+ // Two root nodes, each gets a different component via query-after.
228
+ defineComponent('Transform', { pos: 'array<f32, 3>' });
229
+ const multiRoot: SceneEntity[] = [
230
+ { localId: localId(0), components: { Transform: { pos: [0, 0, 0] } } },
231
+ { localId: localId(1), components: { Transform: { pos: [10, 0, 0] } } },
232
+ ];
233
+ const reg = new AssetRegistry(makeMockShaderRegistry());
234
+ const world = new World();
235
+ registerRuntimeComponents(world, [Enemy, Waypoint]);
236
+ const asset: SceneAsset = { kind: 'scene', entities: multiRoot };
237
+ const handle = registerSceneAsset(world, asset);
238
+ const r = reg.instantiate<SceneAsset>(handle, world);
239
+ expect(r.ok).toBe(true);
240
+ if (!r.ok) return;
241
+ const root: EntityHandle = r.value;
242
+ const state = SceneOwner.worldGetSceneInstanceState(world, root);
243
+ expect(state.ok).toBe(true);
244
+ if (!state.ok) return;
245
+ const roots = state.value.rootEntities;
246
+ expect(roots.length).toBe(2);
247
+ // Attach Enemy to root 0, Waypoint to root 1.
248
+ const e0 = postInstantiateEntity(roots[0]);
249
+ const e1 = postInstantiateEntity(roots[1]);
250
+ const add0 = world.addComponent(e0, {
251
+ component: Enemy,
252
+ data: { speed: 3, hp: 1 },
253
+ });
254
+ expect(add0.ok).toBe(true);
255
+ expect(world.get(e0, Enemy).ok).toBe(true);
256
+ const add1 = world.addComponent(e1, {
257
+ component: Waypoint,
258
+ data: { index: 7 },
259
+ });
260
+ expect(add1.ok).toBe(true);
261
+ expect(world.get(e1, Waypoint).ok).toBe(true);
262
+ });
263
+
264
+ it('rootEntities snapshot is stable (not a live view)', () => {
265
+ defineComponent('Transform', { pos: 'array<f32, 3>' });
266
+ const reg = new AssetRegistry(makeMockShaderRegistry());
267
+ const world = new World();
268
+ registerRuntimeComponents(world, [Enemy, Waypoint]);
269
+ const singleRoot: SceneEntity[] = [
270
+ { localId: localId(0), components: { Transform: { pos: [0, 0, 0] } } },
271
+ ];
272
+ const asset: SceneAsset = { kind: 'scene', entities: singleRoot };
273
+ const handle = registerSceneAsset(world, asset);
274
+ const r = reg.instantiate<SceneAsset>(handle, world);
275
+ if (!r.ok) throw new Error(`instantiate failed: ${JSON.stringify(r.error)}`);
276
+ expect(r.ok).toBe(true);
277
+ if (!r.ok) return;
278
+ const root: EntityHandle = r.value;
279
+ const state = SceneOwner.worldGetSceneInstanceState(world, root);
280
+ expect(state.ok).toBe(true);
281
+ if (!state.ok) return;
282
+ const roots1 = state.value.rootEntities;
283
+ // Add a component to the root entity and re-query.
284
+ const e = postInstantiateEntity(roots1[0]);
285
+ const addRes = world.addComponent(e, {
286
+ component: Enemy,
287
+ data: { speed: 1, hp: 10 },
288
+ });
289
+ expect(addRes.ok).toBe(true);
290
+ const state2 = SceneOwner.worldGetSceneInstanceState(world, root);
291
+ expect(state2.ok).toBe(true);
292
+ if (!state2.ok) return;
293
+ const roots2 = state2.value.rootEntities;
294
+ expect(roots1).toEqual(roots2);
295
+ });
296
+
297
+ it('mapping identity: mapping[localId] returns the same Entity across calls', () => {
298
+ defineComponent('Transform', { pos: 'array<f32, 3>' });
299
+ const reg = new AssetRegistry(makeMockShaderRegistry());
300
+ const world = new World();
301
+ registerRuntimeComponents(world);
302
+ const asset = buildPostScene();
303
+ const handle = registerSceneAsset(world, asset);
304
+ const r = reg.instantiate<SceneAsset>(handle, world);
305
+ expect(r.ok).toBe(true);
306
+ if (!r.ok) return;
307
+ const root: EntityHandle = r.value;
308
+ const inst = world.get(root, SceneInstance);
309
+ expect(inst.ok).toBe(true);
310
+ if (!inst.ok) return;
311
+ const mapping1 = inst.value.mapping;
312
+ const inst2 = world.get(root, SceneInstance);
313
+ expect(inst2.ok).toBe(true);
314
+ if (!inst2.ok) return;
315
+ const mapping2 = inst2.value.mapping;
316
+ for (const lid of [0, 1]) {
317
+ const e1 = mapping1[lid];
318
+ const e2 = mapping2[lid];
319
+ expect(e1).toBeDefined();
320
+ expect(e2).toBeDefined();
321
+ expect(e1).toBe(e2);
322
+ }
323
+ });
324
+ });