@forgeax/engine-app 0.1.2

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 (354) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +418 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/__tests__/animation-asset-lookup.unit.test.d.ts +2 -0
  5. package/dist/__tests__/animation-asset-lookup.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/app-rebuild.test.d.ts +2 -0
  7. package/dist/__tests__/app-rebuild.test.d.ts.map +1 -0
  8. package/dist/__tests__/asset-registry-types.test-d.d.ts +2 -0
  9. package/dist/__tests__/asset-registry-types.test-d.d.ts.map +1 -0
  10. package/dist/__tests__/assets-runtime-assembly.integration.test.d.ts +2 -0
  11. package/dist/__tests__/assets-runtime-assembly.integration.test.d.ts.map +1 -0
  12. package/dist/__tests__/callback-deletion.unit.test.d.ts +2 -0
  13. package/dist/__tests__/callback-deletion.unit.test.d.ts.map +1 -0
  14. package/dist/__tests__/callback-inference.test-d.d.ts +2 -0
  15. package/dist/__tests__/callback-inference.test-d.d.ts.map +1 -0
  16. package/dist/__tests__/component-introspection.unit.test.d.ts +2 -0
  17. package/dist/__tests__/component-introspection.unit.test.d.ts.map +1 -0
  18. package/dist/__tests__/consumer-migration.unit.test.d.ts +2 -0
  19. package/dist/__tests__/consumer-migration.unit.test.d.ts.map +1 -0
  20. package/dist/__tests__/create-app-features.test.d.ts +2 -0
  21. package/dist/__tests__/create-app-features.test.d.ts.map +1 -0
  22. package/dist/__tests__/create-app-listener-sync.test.d.ts +2 -0
  23. package/dist/__tests__/create-app-listener-sync.test.d.ts.map +1 -0
  24. package/dist/__tests__/create-app-lock-provider.test.d.ts +2 -0
  25. package/dist/__tests__/create-app-lock-provider.test.d.ts.map +1 -0
  26. package/dist/__tests__/create-app-plugin.test.d.ts +2 -0
  27. package/dist/__tests__/create-app-plugin.test.d.ts.map +1 -0
  28. package/dist/__tests__/create-app-stop.test.d.ts +2 -0
  29. package/dist/__tests__/create-app-stop.test.d.ts.map +1 -0
  30. package/dist/__tests__/create-app-time.unit.test.d.ts +2 -0
  31. package/dist/__tests__/create-app-time.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/create-app.test-d.d.ts +2 -0
  33. package/dist/__tests__/create-app.test-d.d.ts.map +1 -0
  34. package/dist/__tests__/create-app.test.d.ts +2 -0
  35. package/dist/__tests__/create-app.test.d.ts.map +1 -0
  36. package/dist/__tests__/create-renderer-error.integration.test.d.ts +2 -0
  37. package/dist/__tests__/create-renderer-error.integration.test.d.ts.map +1 -0
  38. package/dist/__tests__/create-renderer-lifecycle.integration.test.d.ts +2 -0
  39. package/dist/__tests__/create-renderer-lifecycle.integration.test.d.ts.map +1 -0
  40. package/dist/__tests__/docs-gate-green.unit.test.d.ts +2 -0
  41. package/dist/__tests__/docs-gate-green.unit.test.d.ts.map +1 -0
  42. package/dist/__tests__/draw-source-headless-full-chain.test.d.ts +2 -0
  43. package/dist/__tests__/draw-source-headless-full-chain.test.d.ts.map +1 -0
  44. package/dist/__tests__/draw-source-injected-world-update-visibility.test.d.ts +2 -0
  45. package/dist/__tests__/draw-source-injected-world-update-visibility.test.d.ts.map +1 -0
  46. package/dist/__tests__/draw-source-single-world-regression.test.d.ts +2 -0
  47. package/dist/__tests__/draw-source-single-world-regression.test.d.ts.map +1 -0
  48. package/dist/__tests__/ecs-import.unit.test.d.ts +2 -0
  49. package/dist/__tests__/ecs-import.unit.test.d.ts.map +1 -0
  50. package/dist/__tests__/engine-worker-bootstrap-channel.unit.test.d.ts +2 -0
  51. package/dist/__tests__/engine-worker-bootstrap-channel.unit.test.d.ts.map +1 -0
  52. package/dist/__tests__/engine-worker-world-swap.unit.test.d.ts +2 -0
  53. package/dist/__tests__/engine-worker-world-swap.unit.test.d.ts.map +1 -0
  54. package/dist/__tests__/errors-pointer-lock-failed.test.d.ts +2 -0
  55. package/dist/__tests__/errors-pointer-lock-failed.test.d.ts.map +1 -0
  56. package/dist/__tests__/execution-bootstrap-isolation.unit.test.d.ts +2 -0
  57. package/dist/__tests__/execution-bootstrap-isolation.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/execution-error-detail.test-d.d.ts +2 -0
  59. package/dist/__tests__/execution-error-detail.test-d.d.ts.map +1 -0
  60. package/dist/__tests__/execution-error-detail.unit.test.d.ts +2 -0
  61. package/dist/__tests__/execution-error-detail.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/execution-frame-order.unit.test.d.ts +2 -0
  63. package/dist/__tests__/execution-frame-order.unit.test.d.ts.map +1 -0
  64. package/dist/__tests__/execution-frame-protocol.unit.test.d.ts +2 -0
  65. package/dist/__tests__/execution-frame-protocol.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/execution-input-sample.contract.test.d.ts +2 -0
  67. package/dist/__tests__/execution-input-sample.contract.test.d.ts.map +1 -0
  68. package/dist/__tests__/execution-measurement.unit.test.d.ts +2 -0
  69. package/dist/__tests__/execution-measurement.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/execution-public-api.test-d.d.ts +2 -0
  71. package/dist/__tests__/execution-public-api.test-d.d.ts.map +1 -0
  72. package/dist/__tests__/execution-public-api.unit.test.d.ts +2 -0
  73. package/dist/__tests__/execution-public-api.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/execution-rebuild.contract.test.d.ts +2 -0
  75. package/dist/__tests__/execution-rebuild.contract.test.d.ts.map +1 -0
  76. package/dist/__tests__/execution-report.contract.test.d.ts +2 -0
  77. package/dist/__tests__/execution-report.contract.test.d.ts.map +1 -0
  78. package/dist/__tests__/execution-report.types.test-d.d.ts +2 -0
  79. package/dist/__tests__/execution-report.types.test-d.d.ts.map +1 -0
  80. package/dist/__tests__/execution-schema-freshness.unit.test.d.ts +2 -0
  81. package/dist/__tests__/execution-schema-freshness.unit.test.d.ts.map +1 -0
  82. package/dist/__tests__/execution-selector.unit.test.d.ts +2 -0
  83. package/dist/__tests__/execution-selector.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/execution-shared-kernel.unit.test.d.ts +2 -0
  85. package/dist/__tests__/execution-shared-kernel.unit.test.d.ts.map +1 -0
  86. package/dist/__tests__/execution-world-health-owner.test-d.d.ts +2 -0
  87. package/dist/__tests__/execution-world-health-owner.test-d.d.ts.map +1 -0
  88. package/dist/__tests__/fallback-camera.unit.test.d.ts +2 -0
  89. package/dist/__tests__/fallback-camera.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/frame-loop-time-elapsed.test.d.ts +2 -0
  91. package/dist/__tests__/frame-loop-time-elapsed.test.d.ts.map +1 -0
  92. package/dist/__tests__/frame-loop-time.unit.test.d.ts +2 -0
  93. package/dist/__tests__/frame-loop-time.unit.test.d.ts.map +1 -0
  94. package/dist/__tests__/frame-loop-world-array.test.d.ts +2 -0
  95. package/dist/__tests__/frame-loop-world-array.test.d.ts.map +1 -0
  96. package/dist/__tests__/kernel-worker-runtime.unit.test.d.ts +2 -0
  97. package/dist/__tests__/kernel-worker-runtime.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/migration-surface-inventory.unit.test.d.ts +2 -0
  99. package/dist/__tests__/migration-surface-inventory.unit.test.d.ts.map +1 -0
  100. package/dist/__tests__/plugin-policy.integration.test.d.ts +2 -0
  101. package/dist/__tests__/plugin-policy.integration.test.d.ts.map +1 -0
  102. package/dist/__tests__/plugin-profiles.unit.test.d.ts +2 -0
  103. package/dist/__tests__/plugin-profiles.unit.test.d.ts.map +1 -0
  104. package/dist/__tests__/profiler-default-off.test.d.ts +2 -0
  105. package/dist/__tests__/profiler-default-off.test.d.ts.map +1 -0
  106. package/dist/__tests__/profiler-frame-token.test.d.ts +2 -0
  107. package/dist/__tests__/profiler-frame-token.test.d.ts.map +1 -0
  108. package/dist/__tests__/profiler-phase-catalog.test.d.ts +2 -0
  109. package/dist/__tests__/profiler-phase-catalog.test.d.ts.map +1 -0
  110. package/dist/__tests__/profiler-phase-integration.test.d.ts +2 -0
  111. package/dist/__tests__/profiler-phase-integration.test.d.ts.map +1 -0
  112. package/dist/__tests__/profiler-remote-bridge.test.d.ts +2 -0
  113. package/dist/__tests__/profiler-remote-bridge.test.d.ts.map +1 -0
  114. package/dist/__tests__/remote-integration.test.d.ts +2 -0
  115. package/dist/__tests__/remote-integration.test.d.ts.map +1 -0
  116. package/dist/__tests__/remote-serve-flag.test.d.ts +2 -0
  117. package/dist/__tests__/remote-serve-flag.test.d.ts.map +1 -0
  118. package/dist/__tests__/rhi-capture-capability.test-d.d.ts +2 -0
  119. package/dist/__tests__/rhi-capture-capability.test-d.d.ts.map +1 -0
  120. package/dist/__tests__/rhi-capture-host.integration.test.d.ts +2 -0
  121. package/dist/__tests__/rhi-capture-host.integration.test.d.ts.map +1 -0
  122. package/dist/__tests__/rhi-capture.browser.test.d.ts +2 -0
  123. package/dist/__tests__/rhi-capture.browser.test.d.ts.map +1 -0
  124. package/dist/__tests__/surface-handoff.test.d.ts +2 -0
  125. package/dist/__tests__/surface-handoff.test.d.ts.map +1 -0
  126. package/dist/__tests__/types-m2.test-d.d.ts +2 -0
  127. package/dist/__tests__/types-m2.test-d.d.ts.map +1 -0
  128. package/dist/__tests__/visibility-remote.integration.test.d.ts +2 -0
  129. package/dist/__tests__/visibility-remote.integration.test.d.ts.map +1 -0
  130. package/dist/__tests__/worker-execution-stop.test.d.ts +2 -0
  131. package/dist/__tests__/worker-execution-stop.test.d.ts.map +1 -0
  132. package/dist/animation-asset-lookup.d.ts +8 -0
  133. package/dist/animation-asset-lookup.d.ts.map +1 -0
  134. package/dist/assets-runtime-assembly.d.ts +19 -0
  135. package/dist/assets-runtime-assembly.d.ts.map +1 -0
  136. package/dist/canvas-policy.d.ts +4 -0
  137. package/dist/canvas-policy.d.ts.map +1 -0
  138. package/dist/create-app.d.ts +57 -0
  139. package/dist/create-app.d.ts.map +1 -0
  140. package/dist/engine-worker-runtime.mjs +884 -0
  141. package/dist/engine-worker-runtime.mjs.map +1 -0
  142. package/dist/errors.d.ts +263 -0
  143. package/dist/errors.d.ts.map +1 -0
  144. package/dist/execution/attached-world-swap.d.ts +21 -0
  145. package/dist/execution/attached-world-swap.d.ts.map +1 -0
  146. package/dist/execution/bootstrap-entry.d.ts +30 -0
  147. package/dist/execution/bootstrap-entry.d.ts.map +1 -0
  148. package/dist/execution/capabilities.d.ts +5 -0
  149. package/dist/execution/capabilities.d.ts.map +1 -0
  150. package/dist/execution/control.d.ts +14 -0
  151. package/dist/execution/control.d.ts.map +1 -0
  152. package/dist/execution/engine-worker-runtime.d.ts +2 -0
  153. package/dist/execution/engine-worker-runtime.d.ts.map +1 -0
  154. package/dist/execution/engine-worker.d.ts +23 -0
  155. package/dist/execution/engine-worker.d.ts.map +1 -0
  156. package/dist/execution/host-controller.d.ts +16 -0
  157. package/dist/execution/host-controller.d.ts.map +1 -0
  158. package/dist/execution/index.d.ts +10 -0
  159. package/dist/execution/index.d.ts.map +1 -0
  160. package/dist/execution/kernel-pool.d.ts +14 -0
  161. package/dist/execution/kernel-pool.d.ts.map +1 -0
  162. package/dist/execution/kernel-worker-runtime.d.ts +2 -0
  163. package/dist/execution/kernel-worker-runtime.d.ts.map +1 -0
  164. package/dist/execution/measurement.d.ts +7 -0
  165. package/dist/execution/measurement.d.ts.map +1 -0
  166. package/dist/execution/protocol.d.ts +84 -0
  167. package/dist/execution/protocol.d.ts.map +1 -0
  168. package/dist/execution/report.d.ts +5 -0
  169. package/dist/execution/report.d.ts.map +1 -0
  170. package/dist/execution/schema.d.ts +4 -0
  171. package/dist/execution/schema.d.ts.map +1 -0
  172. package/dist/execution/selector.d.ts +10 -0
  173. package/dist/execution/selector.d.ts.map +1 -0
  174. package/dist/execution/types.d.ts +107 -0
  175. package/dist/execution/types.d.ts.map +1 -0
  176. package/dist/fallback-camera.d.ts +8 -0
  177. package/dist/fallback-camera.d.ts.map +1 -0
  178. package/dist/game-context.d.ts +98 -0
  179. package/dist/game-context.d.ts.map +1 -0
  180. package/dist/index.d.ts +24 -0
  181. package/dist/index.d.ts.map +1 -0
  182. package/dist/index.mjs +3985 -0
  183. package/dist/index.mjs.map +1 -0
  184. package/dist/input-map-plugin.d.ts +5 -0
  185. package/dist/input-map-plugin.d.ts.map +1 -0
  186. package/dist/input-plugin.d.ts +4 -0
  187. package/dist/input-plugin.d.ts.map +1 -0
  188. package/dist/internal/assembled-engine-profile.d.ts +5 -0
  189. package/dist/internal/assembled-engine-profile.d.ts.map +1 -0
  190. package/dist/internal/assets-world-plugin.d.ts +21 -0
  191. package/dist/internal/assets-world-plugin.d.ts.map +1 -0
  192. package/dist/internal/browser-remote-bridge.d.ts +25 -0
  193. package/dist/internal/browser-remote-bridge.d.ts.map +1 -0
  194. package/dist/internal/browser-rhi-debug-runtime.d.ts +18 -0
  195. package/dist/internal/browser-rhi-debug-runtime.d.ts.map +1 -0
  196. package/dist/internal/component-introspection.d.ts +24 -0
  197. package/dist/internal/component-introspection.d.ts.map +1 -0
  198. package/dist/internal/ecs-import.d.ts +6 -0
  199. package/dist/internal/ecs-import.d.ts.map +1 -0
  200. package/dist/internal/engine-profile-common.d.ts +9 -0
  201. package/dist/internal/engine-profile-common.d.ts.map +1 -0
  202. package/dist/internal/error-fanout.d.ts +66 -0
  203. package/dist/internal/error-fanout.d.ts.map +1 -0
  204. package/dist/internal/frame-loop.d.ts +35 -0
  205. package/dist/internal/frame-loop.d.ts.map +1 -0
  206. package/dist/internal/input-attach.d.ts +44 -0
  207. package/dist/internal/input-attach.d.ts.map +1 -0
  208. package/dist/internal/main-engine-profile.d.ts +15 -0
  209. package/dist/internal/main-engine-profile.d.ts.map +1 -0
  210. package/dist/internal/remote-serve-flag.d.ts +23 -0
  211. package/dist/internal/remote-serve-flag.d.ts.map +1 -0
  212. package/dist/internal/remote-server-plugin.d.ts +8 -0
  213. package/dist/internal/remote-server-plugin.d.ts.map +1 -0
  214. package/dist/internal/rhi-capture.d.ts +19 -0
  215. package/dist/internal/rhi-capture.d.ts.map +1 -0
  216. package/dist/internal/rhi-debug-flag.d.ts +18 -0
  217. package/dist/internal/rhi-debug-flag.d.ts.map +1 -0
  218. package/dist/internal/worker-engine-profile.d.ts +13 -0
  219. package/dist/internal/worker-engine-profile.d.ts.map +1 -0
  220. package/dist/kernel-worker-runtime.mjs +69 -0
  221. package/dist/kernel-worker-runtime.mjs.map +1 -0
  222. package/dist/load-game-errors.d.ts +131 -0
  223. package/dist/load-game-errors.d.ts.map +1 -0
  224. package/dist/load-game.d.ts +34 -0
  225. package/dist/load-game.d.ts.map +1 -0
  226. package/dist/plugin-factories.d.ts +3 -0
  227. package/dist/plugin-factories.d.ts.map +1 -0
  228. package/dist/tool-preview/bootstrap.d.ts +113 -0
  229. package/dist/tool-preview/bootstrap.d.ts.map +1 -0
  230. package/dist/tool-preview/evidence.d.ts +20 -0
  231. package/dist/tool-preview/evidence.d.ts.map +1 -0
  232. package/dist/tool-preview/framing.d.ts +13 -0
  233. package/dist/tool-preview/framing.d.ts.map +1 -0
  234. package/dist/tool-preview/recipe.d.ts +54 -0
  235. package/dist/tool-preview/recipe.d.ts.map +1 -0
  236. package/dist/types.d.ts +444 -0
  237. package/dist/types.d.ts.map +1 -0
  238. package/package.json +86 -0
  239. package/schema/execution-report.schema.json +168 -0
  240. package/src/__tests__/animation-asset-lookup.unit.test.ts +20 -0
  241. package/src/__tests__/app-rebuild.test.ts +31 -0
  242. package/src/__tests__/asset-registry-types.test-d.ts +16 -0
  243. package/src/__tests__/assets-runtime-assembly.integration.test.ts +68 -0
  244. package/src/__tests__/callback-deletion.unit.test.ts +14 -0
  245. package/src/__tests__/callback-inference.test-d.ts +32 -0
  246. package/src/__tests__/component-introspection.unit.test.ts +56 -0
  247. package/src/__tests__/consumer-migration.unit.test.ts +21 -0
  248. package/src/__tests__/create-app-features.test.ts +40 -0
  249. package/src/__tests__/create-app-listener-sync.test.ts +377 -0
  250. package/src/__tests__/create-app-lock-provider.test.ts +212 -0
  251. package/src/__tests__/create-app-plugin.test.ts +217 -0
  252. package/src/__tests__/create-app-stop.test.ts +617 -0
  253. package/src/__tests__/create-app-time.unit.test.ts +26 -0
  254. package/src/__tests__/create-app.test-d.ts +82 -0
  255. package/src/__tests__/create-app.test.ts +346 -0
  256. package/src/__tests__/create-renderer-error.integration.test.ts +24 -0
  257. package/src/__tests__/create-renderer-lifecycle.integration.test.ts +19 -0
  258. package/src/__tests__/docs-gate-green.unit.test.ts +61 -0
  259. package/src/__tests__/draw-source-headless-full-chain.test.ts +226 -0
  260. package/src/__tests__/draw-source-injected-world-update-visibility.test.ts +182 -0
  261. package/src/__tests__/draw-source-single-world-regression.test.ts +185 -0
  262. package/src/__tests__/ecs-import.unit.test.ts +40 -0
  263. package/src/__tests__/engine-worker-bootstrap-channel.unit.test.ts +74 -0
  264. package/src/__tests__/engine-worker-world-swap.unit.test.ts +76 -0
  265. package/src/__tests__/errors-pointer-lock-failed.test.ts +268 -0
  266. package/src/__tests__/execution-bootstrap-isolation.unit.test.ts +80 -0
  267. package/src/__tests__/execution-error-detail.test-d.ts +13 -0
  268. package/src/__tests__/execution-error-detail.unit.test.ts +35 -0
  269. package/src/__tests__/execution-frame-order.unit.test.ts +38 -0
  270. package/src/__tests__/execution-frame-protocol.unit.test.ts +61 -0
  271. package/src/__tests__/execution-input-sample.contract.test.ts +23 -0
  272. package/src/__tests__/execution-measurement.unit.test.ts +20 -0
  273. package/src/__tests__/execution-public-api.test-d.ts +10 -0
  274. package/src/__tests__/execution-public-api.unit.test.ts +9 -0
  275. package/src/__tests__/execution-rebuild.contract.test.ts +36 -0
  276. package/src/__tests__/execution-report.contract.test.ts +50 -0
  277. package/src/__tests__/execution-report.types.test-d.ts +16 -0
  278. package/src/__tests__/execution-schema-freshness.unit.test.ts +20 -0
  279. package/src/__tests__/execution-selector.unit.test.ts +72 -0
  280. package/src/__tests__/execution-shared-kernel.unit.test.ts +180 -0
  281. package/src/__tests__/execution-world-health-owner.test-d.ts +9 -0
  282. package/src/__tests__/fallback-camera.unit.test.ts +32 -0
  283. package/src/__tests__/frame-loop-time-elapsed.test.ts +115 -0
  284. package/src/__tests__/frame-loop-time.unit.test.ts +61 -0
  285. package/src/__tests__/frame-loop-world-array.test.ts +441 -0
  286. package/src/__tests__/kernel-worker-runtime.unit.test.ts +50 -0
  287. package/src/__tests__/migration-surface-inventory.unit.test.ts +13 -0
  288. package/src/__tests__/plugin-policy.integration.test.ts +15 -0
  289. package/src/__tests__/plugin-profiles.unit.test.ts +190 -0
  290. package/src/__tests__/profiler-default-off.test.ts +53 -0
  291. package/src/__tests__/profiler-frame-token.test.ts +248 -0
  292. package/src/__tests__/profiler-phase-catalog.test.ts +30 -0
  293. package/src/__tests__/profiler-phase-integration.test.ts +129 -0
  294. package/src/__tests__/profiler-remote-bridge.test.ts +31 -0
  295. package/src/__tests__/remote-integration.test.ts +224 -0
  296. package/src/__tests__/remote-serve-flag.test.ts +24 -0
  297. package/src/__tests__/rhi-capture-capability.test-d.ts +22 -0
  298. package/src/__tests__/rhi-capture-host.integration.test.ts +157 -0
  299. package/src/__tests__/rhi-capture.browser.test.ts +51 -0
  300. package/src/__tests__/surface-handoff.test.ts +92 -0
  301. package/src/__tests__/types-m2.test-d.ts +81 -0
  302. package/src/__tests__/visibility-remote.integration.test.ts +119 -0
  303. package/src/__tests__/worker-execution-stop.test.ts +116 -0
  304. package/src/animation-asset-lookup.ts +13 -0
  305. package/src/assets-runtime-assembly.ts +70 -0
  306. package/src/canvas-policy.ts +16 -0
  307. package/src/create-app.ts +1351 -0
  308. package/src/errors.ts +454 -0
  309. package/src/execution/attached-world-swap.ts +67 -0
  310. package/src/execution/bootstrap-entry.ts +122 -0
  311. package/src/execution/capabilities.ts +102 -0
  312. package/src/execution/control.ts +52 -0
  313. package/src/execution/engine-worker-runtime.ts +400 -0
  314. package/src/execution/engine-worker.ts +161 -0
  315. package/src/execution/host-controller.ts +454 -0
  316. package/src/execution/index.ts +43 -0
  317. package/src/execution/kernel-pool.ts +236 -0
  318. package/src/execution/kernel-worker-runtime.ts +103 -0
  319. package/src/execution/measurement.ts +39 -0
  320. package/src/execution/protocol.ts +131 -0
  321. package/src/execution/report.ts +66 -0
  322. package/src/execution/schema.ts +168 -0
  323. package/src/execution/selector.ts +98 -0
  324. package/src/execution/types.ts +146 -0
  325. package/src/fallback-camera.ts +20 -0
  326. package/src/game-context.ts +126 -0
  327. package/src/index.ts +176 -0
  328. package/src/input-map-plugin.ts +21 -0
  329. package/src/input-plugin.ts +26 -0
  330. package/src/internal/assembled-engine-profile.ts +22 -0
  331. package/src/internal/assets-world-plugin.ts +79 -0
  332. package/src/internal/browser-remote-bridge.ts +267 -0
  333. package/src/internal/browser-rhi-debug-runtime.ts +67 -0
  334. package/src/internal/component-introspection.ts +116 -0
  335. package/src/internal/ecs-import.ts +41 -0
  336. package/src/internal/engine-profile-common.ts +10 -0
  337. package/src/internal/error-fanout.ts +129 -0
  338. package/src/internal/frame-loop.ts +525 -0
  339. package/src/internal/input-attach.ts +104 -0
  340. package/src/internal/main-engine-profile.ts +80 -0
  341. package/src/internal/remote-serve-flag.ts +50 -0
  342. package/src/internal/remote-server-plugin.ts +16 -0
  343. package/src/internal/rhi-capture.ts +211 -0
  344. package/src/internal/rhi-debug-flag.ts +40 -0
  345. package/src/internal/worker-engine-profile.ts +47 -0
  346. package/src/load-game-errors.ts +211 -0
  347. package/src/load-game.ts +115 -0
  348. package/src/plugin-factories.ts +2 -0
  349. package/src/tool-preview/bootstrap.ts +848 -0
  350. package/src/tool-preview/evidence.ts +59 -0
  351. package/src/tool-preview/framing.ts +52 -0
  352. package/src/tool-preview/recipe.ts +137 -0
  353. package/src/types.ts +505 -0
  354. package/src/vite-env.d.ts +12 -0
@@ -0,0 +1,441 @@
1
+ // feat-20260708-composited-multi-world-rendering M3 / m3-t3 — AC-03 frame-loop
2
+ // [world] wrapping.
3
+ //
4
+ // The app frame-loop is the single point that shields single-world AI users from
5
+ // the multi-world draw signature: internally it wraps the current World into
6
+ // `[world]` and passes `{ cameraOwner: 0, resourceOwner: 0 }` (plan-strategy §7 M3). Engine.create /
7
+ // createApp public API is unchanged — the user still hands over one World.
8
+ //
9
+ // This test drives createFrameLoop directly (injected now / raf / caf seams) with
10
+ // a spy renderer and asserts the exact call shape:
11
+ // renderer.draw([world], { cameraOwner: 0, resourceOwner: 0 })
12
+ //
13
+ // Test-first (red before m3-i3): the frame-loop currently calls
14
+ // renderer.draw(world). After migration these assertions pass and the single
15
+ // world identity path (worldId 0) is preserved (AC-03 regression guarantee).
16
+
17
+ import { Update, World } from '@forgeax/engine-ecs';
18
+ import type { Renderer } from '@forgeax/engine-render';
19
+ import { describe, expect, it, vi } from 'vitest';
20
+ import { createFrameLoop } from '../internal/frame-loop';
21
+
22
+ interface DrawCall {
23
+ readonly worlds: unknown;
24
+ readonly options: unknown;
25
+ }
26
+
27
+ function makeSpyRenderer(): { renderer: Renderer; calls: DrawCall[] } {
28
+ const calls: DrawCall[] = [];
29
+ const renderer = {
30
+ backend: 'webgpu' as const,
31
+ ready: Promise.resolve({ ok: true, value: undefined }),
32
+ attachWorld(): { ok: true; value: undefined } {
33
+ return { ok: true, value: undefined };
34
+ },
35
+ detachWorld(): void {},
36
+ draw(worlds: unknown, options: unknown): { ok: true; value: undefined } {
37
+ calls.push({ worlds, options });
38
+ return { ok: true, value: undefined };
39
+ },
40
+ onError(): () => void {
41
+ return () => {
42
+ // no-op unsubscribe
43
+ };
44
+ },
45
+ dispose(): void {
46
+ // no-op
47
+ },
48
+ } as unknown as Renderer;
49
+ return { renderer, calls };
50
+ }
51
+
52
+ /**
53
+ * Synchronous rAF driver: fire the scheduled tick exactly `frames` times.
54
+ * The injected `raf` stores the next callback; `pump` invokes it, which in
55
+ * turn schedules the following one, so we can step the loop deterministically.
56
+ */
57
+ function makeSyncScheduler() {
58
+ let pending: ((t: number) => void) | null = null;
59
+ let clock = 0;
60
+ const raf = (cb: (t: number) => void): number => {
61
+ pending = cb;
62
+ return 1;
63
+ };
64
+ const caf = (): void => {
65
+ pending = null;
66
+ };
67
+ const now = (): number => {
68
+ clock += 16;
69
+ return clock;
70
+ };
71
+ const pump = (frames: number): void => {
72
+ for (let i = 0; i < frames; i++) {
73
+ const cb = pending;
74
+ pending = null;
75
+ if (cb === null) break;
76
+ cb(clock);
77
+ }
78
+ };
79
+ return { raf, caf, now, pump };
80
+ }
81
+
82
+ describe('M3 / m3-t3 — frame-loop wraps the single World into [world] with owner 0', () => {
83
+ it('attaches once before the first update without moving drawSource ahead of update', () => {
84
+ const events: string[] = [];
85
+ const world = new World();
86
+ world
87
+ .addSystem(Update, {
88
+ name: 'observeUpdateOrder',
89
+ queries: [],
90
+ fn: () => events.push('update'),
91
+ })
92
+ .unwrap();
93
+ const renderer = {
94
+ backend: 'webgpu' as const,
95
+ ready: Promise.resolve({ ok: true, value: undefined }),
96
+ attachWorld(): { ok: true; value: undefined } {
97
+ events.push('attach');
98
+ return { ok: true, value: undefined };
99
+ },
100
+ detachWorld(): void {},
101
+ draw(): { ok: true; value: undefined } {
102
+ events.push('draw');
103
+ return { ok: true, value: undefined };
104
+ },
105
+ onError: () => () => {},
106
+ dispose: () => {},
107
+ } as unknown as Renderer;
108
+ const { raf, caf, now, pump } = makeSyncScheduler();
109
+ const loop = createFrameLoop({
110
+ world,
111
+ renderer,
112
+ now,
113
+ raf,
114
+ caf,
115
+ drawSource: () => {
116
+ events.push('drawSource');
117
+ return undefined;
118
+ },
119
+ });
120
+
121
+ loop.start().unwrap();
122
+ pump(2);
123
+ loop.stop().unwrap();
124
+
125
+ expect(events).toEqual([
126
+ 'attach',
127
+ 'update',
128
+ 'drawSource',
129
+ 'draw',
130
+ 'update',
131
+ 'drawSource',
132
+ 'draw',
133
+ ]);
134
+ });
135
+
136
+ it('calls renderer.draw([world], { cameraOwner: 0, resourceOwner: 0 }) once per running frame', () => {
137
+ const world = new World();
138
+ const { renderer, calls } = makeSpyRenderer();
139
+ const { raf, caf, now, pump } = makeSyncScheduler();
140
+
141
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
142
+ const started = loop.start();
143
+ expect(started.ok).toBe(true);
144
+
145
+ // start() schedules the first tick via raf (it does not run synchronously);
146
+ // pump three ticks so we observe 3 frames total.
147
+ pump(3);
148
+
149
+ expect(calls.length).toBeGreaterThanOrEqual(3);
150
+ for (const call of calls) {
151
+ // The worlds argument is an array carrying exactly the single world.
152
+ expect(Array.isArray(call.worlds)).toBe(true);
153
+ const arr = call.worlds as unknown[];
154
+ expect(arr.length).toBe(1);
155
+ expect(arr[0]).toBe(world);
156
+ // owner is the required, defaulted-to-0 index (single-world identity).
157
+ expect(call.options).toEqual({ cameraOwner: 0, resourceOwner: 0 });
158
+ }
159
+
160
+ loop.stop();
161
+ });
162
+
163
+ it('does not draw a World whose update did not reach terminal publication', () => {
164
+ const world = new World();
165
+ world
166
+ .addSystem(Update, {
167
+ name: 'fail-update',
168
+ queries: [],
169
+ fn: () => {
170
+ throw new Error('update failed');
171
+ },
172
+ })
173
+ .unwrap();
174
+ const { renderer, calls } = makeSpyRenderer();
175
+ const onError = vi.fn();
176
+ const { raf, caf, now, pump } = makeSyncScheduler();
177
+ const loop = createFrameLoop({ world, renderer, now, raf, caf, onError });
178
+
179
+ loop.start().unwrap();
180
+ pump(1);
181
+
182
+ expect(calls).toHaveLength(0);
183
+ expect(onError).toHaveBeenCalledTimes(1);
184
+ loop.stop().unwrap();
185
+ });
186
+
187
+ it('does not mutate the public frame-loop contract: start/stop return Result.ok', () => {
188
+ const world = new World();
189
+ const { renderer } = makeSpyRenderer();
190
+ const { raf, caf, now } = makeSyncScheduler();
191
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
192
+
193
+ const started = loop.start();
194
+ expect(started.ok).toBe(true);
195
+ const stopped = loop.stop();
196
+ expect(stopped.ok).toBe(true);
197
+ });
198
+
199
+ it('forwards a draw Result.err through onError (single world path unchanged)', () => {
200
+ const world = new World();
201
+ const calls: DrawCall[] = [];
202
+ const rhiErr = { code: 'rhi-not-available' } as const;
203
+ const renderer = {
204
+ backend: 'webgpu' as const,
205
+ ready: Promise.resolve({ ok: true, value: undefined }),
206
+ attachWorld: () => ({ ok: true, value: undefined }),
207
+ detachWorld: () => {},
208
+ draw(worlds: unknown, options: unknown): { ok: false; error: typeof rhiErr } {
209
+ calls.push({ worlds, options });
210
+ return { ok: false, error: rhiErr };
211
+ },
212
+ onError(): () => void {
213
+ return () => {
214
+ // no-op
215
+ };
216
+ },
217
+ dispose(): void {
218
+ // no-op
219
+ },
220
+ } as unknown as Renderer;
221
+ const onError = vi.fn();
222
+ const { raf, caf, now, pump } = makeSyncScheduler();
223
+
224
+ const loop = createFrameLoop({ world, renderer, now, raf, caf, onError });
225
+ loop.start();
226
+ // start() schedules the first tick via raf; pump once to run it.
227
+ pump(1);
228
+
229
+ expect(calls[0]?.worlds).toEqual([world]);
230
+ expect(calls[0]?.options).toEqual({ cameraOwner: 0, resourceOwner: 0 });
231
+ expect(onError).toHaveBeenCalledWith(rhiErr);
232
+
233
+ loop.stop();
234
+ });
235
+
236
+ it('keeps the rAF heartbeat but freezes draw work during device loss', () => {
237
+ const world = new World();
238
+ let reason: 'alive' | 'device-lost' = 'alive';
239
+ const calls: unknown[] = [];
240
+ const renderer = {
241
+ backend: 'webgpu' as const,
242
+ ready: Promise.resolve({ ok: true, value: undefined }),
243
+ attachWorld: () => ({ ok: true, value: undefined }),
244
+ detachWorld: () => {},
245
+ health: () => ({ reason, recoverable: reason === 'device-lost' }),
246
+ draw(): { ok: true; value: undefined } {
247
+ calls.push(undefined);
248
+ return { ok: true, value: undefined };
249
+ },
250
+ onError(): () => void {
251
+ return () => {};
252
+ },
253
+ dispose(): void {},
254
+ } as unknown as Renderer;
255
+ const { raf, caf, now, pump } = makeSyncScheduler();
256
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
257
+ loop.start();
258
+ pump(1);
259
+ expect(calls).toHaveLength(1);
260
+
261
+ reason = 'device-lost';
262
+ pump(3);
263
+ expect(calls).toHaveLength(1);
264
+
265
+ reason = 'alive';
266
+ pump(1);
267
+ expect(calls).toHaveLength(2);
268
+ loop.stop();
269
+ });
270
+
271
+ it('steps one deterministic frame through the same update and draw authority while paused', () => {
272
+ const world = new World();
273
+ const update = vi.spyOn(world, 'update');
274
+ const { renderer, calls } = makeSpyRenderer();
275
+ const { raf, caf, now } = makeSyncScheduler();
276
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
277
+
278
+ expect(loop.start().ok).toBe(true);
279
+ expect(loop.pause().ok).toBe(true);
280
+ const stepped = loop.stepFrame(1 / 60);
281
+
282
+ expect(stepped.ok).toBe(true);
283
+ expect(update).toHaveBeenCalledTimes(1);
284
+ expect(update).toHaveBeenCalledWith(1 / 60);
285
+ expect(calls).toEqual([{ worlds: [world], options: { cameraOwner: 0, resourceOwner: 0 } }]);
286
+
287
+ expect(loop.resume().ok).toBe(true);
288
+ expect(loop.stop().ok).toBe(true);
289
+ });
290
+
291
+ it('rejects deterministic stepping outside paused state and with an invalid delta', () => {
292
+ const world = new World();
293
+ const { renderer } = makeSpyRenderer();
294
+ const { raf, caf, now } = makeSyncScheduler();
295
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
296
+
297
+ const idle = loop.stepFrame(1 / 60);
298
+ expect(idle.ok).toBe(false);
299
+ if (!idle.ok) {
300
+ expect(idle.error.code).toBe('app-frame-step-invalid');
301
+ expect(idle.error.detail).toEqual({ state: 'idle', deltaSeconds: 1 / 60, reason: 'state' });
302
+ }
303
+
304
+ expect(loop.start().ok).toBe(true);
305
+ expect(loop.pause().ok).toBe(true);
306
+ const invalidDelta = loop.stepFrame(Number.NaN);
307
+ expect(invalidDelta.ok).toBe(false);
308
+ if (!invalidDelta.ok) {
309
+ expect(invalidDelta.error).toMatchObject({
310
+ code: 'app-frame-step-invalid',
311
+ detail: { reason: 'delta' },
312
+ });
313
+ }
314
+ expect(loop.resume().ok).toBe(true);
315
+ expect(loop.stop().ok).toBe(true);
316
+ });
317
+
318
+ it('detaches draw-source Worlds as soon as routing stops referencing them', () => {
319
+ const world = new World();
320
+ const overlay = new World();
321
+ const attached: World[] = [];
322
+ const detached: World[] = [];
323
+ const renderer = {
324
+ backend: 'webgpu' as const,
325
+ ready: Promise.resolve({ ok: true, value: undefined }),
326
+ attachWorld(candidate: World) {
327
+ attached.push(candidate);
328
+ return { ok: true as const, value: undefined };
329
+ },
330
+ detachWorld(candidate: World): void {
331
+ detached.push(candidate);
332
+ },
333
+ draw: () => ({ ok: true as const, value: undefined }),
334
+ onError: () => () => {},
335
+ dispose: () => {},
336
+ } as unknown as Renderer;
337
+ const { raf, caf, now, pump } = makeSyncScheduler();
338
+ const loop = createFrameLoop({
339
+ world,
340
+ renderer,
341
+ now,
342
+ raf,
343
+ caf,
344
+ drawSource: () => ({ worlds: [world, overlay], cameraOwner: 0, resourceOwner: 0 }),
345
+ });
346
+
347
+ loop.start().unwrap();
348
+ pump(2);
349
+ expect(attached).toEqual([world, overlay]);
350
+ expect(detached).toEqual([]);
351
+
352
+ loop.setDrawSource(undefined);
353
+ expect(detached).toEqual([overlay]);
354
+ loop.stop().unwrap();
355
+ expect(detached).toEqual([overlay, world]);
356
+ });
357
+
358
+ it('detaches active draw-source Worlds when the loop stops', () => {
359
+ const world = new World();
360
+ const overlay = new World();
361
+ const detached: World[] = [];
362
+ const renderer = {
363
+ backend: 'webgpu' as const,
364
+ ready: Promise.resolve({ ok: true, value: undefined }),
365
+ attachWorld: () => ({ ok: true as const, value: undefined }),
366
+ detachWorld(candidate: World): void {
367
+ detached.push(candidate);
368
+ },
369
+ draw: () => ({ ok: true as const, value: undefined }),
370
+ onError: () => () => {},
371
+ dispose: () => {},
372
+ } as unknown as Renderer;
373
+ const { raf, caf, now, pump } = makeSyncScheduler();
374
+ const loop = createFrameLoop({
375
+ world,
376
+ renderer,
377
+ now,
378
+ raf,
379
+ caf,
380
+ drawSource: () => ({ worlds: [world, overlay], cameraOwner: 0, resourceOwner: 0 }),
381
+ });
382
+
383
+ loop.start().unwrap();
384
+ pump(1);
385
+ loop.stop().unwrap();
386
+
387
+ expect(detached).toEqual([overlay, world]);
388
+ });
389
+
390
+ it('terminates a paused loop and detaches its primary World exactly once', () => {
391
+ const world = new World();
392
+ const detached: World[] = [];
393
+ const renderer = {
394
+ backend: 'webgpu' as const,
395
+ ready: Promise.resolve({ ok: true, value: undefined }),
396
+ attachWorld: () => ({ ok: true as const, value: undefined }),
397
+ detachWorld(candidate: World): void {
398
+ detached.push(candidate);
399
+ },
400
+ draw: () => ({ ok: true as const, value: undefined }),
401
+ onError: () => () => {},
402
+ dispose: () => {},
403
+ } as unknown as Renderer;
404
+ const { raf, caf, now, pump } = makeSyncScheduler();
405
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
406
+
407
+ loop.start().unwrap();
408
+ pump(1);
409
+ loop.pause().unwrap();
410
+ loop.stop().unwrap();
411
+
412
+ expect(loop.getState()).toBe('stopped');
413
+ expect(detached).toEqual([world]);
414
+ });
415
+
416
+ it('terminal setStopped releases attachments once across repeated cleanup', () => {
417
+ const world = new World();
418
+ const detached: World[] = [];
419
+ const renderer = {
420
+ backend: 'webgpu' as const,
421
+ ready: Promise.resolve({ ok: true, value: undefined }),
422
+ attachWorld: () => ({ ok: true as const, value: undefined }),
423
+ detachWorld(candidate: World): void {
424
+ detached.push(candidate);
425
+ },
426
+ draw: () => ({ ok: true as const, value: undefined }),
427
+ onError: () => () => {},
428
+ dispose: () => {},
429
+ } as unknown as Renderer;
430
+ const { raf, caf, now, pump } = makeSyncScheduler();
431
+ const loop = createFrameLoop({ world, renderer, now, raf, caf });
432
+
433
+ loop.start().unwrap();
434
+ pump(1);
435
+ loop.setStopped();
436
+ loop.setStopped();
437
+
438
+ expect(loop.getState()).toBe('stopped');
439
+ expect(detached).toEqual([world]);
440
+ });
441
+ });
@@ -0,0 +1,50 @@
1
+ import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
2
+
3
+ describe('kernel worker runtime', () => {
4
+ let originalOnMessage: typeof globalThis.onmessage;
5
+ let receive: (event: MessageEvent<unknown>) => void;
6
+
7
+ beforeAll(async () => {
8
+ originalOnMessage = globalThis.onmessage;
9
+ await import('../execution/kernel-worker-runtime');
10
+ receive = globalThis.onmessage as unknown as (event: MessageEvent<unknown>) => void;
11
+ });
12
+
13
+ afterAll(() => {
14
+ globalThis.onmessage = originalOnMessage;
15
+ });
16
+
17
+ it('dispatches a preloaded kernel without a per-frame import promise', async () => {
18
+ const moduleUrl = 'data:text/javascript,export default { run() { return undefined; } }';
19
+ const preloadControl = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
20
+ const preloadStatus = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
21
+
22
+ receive({
23
+ data: {
24
+ kind: 'kernel-preload',
25
+ moduleUrl,
26
+ control: preloadControl,
27
+ status: preloadStatus,
28
+ jobIndex: 0,
29
+ },
30
+ } as MessageEvent<unknown>);
31
+ await vi.waitFor(() => expect(Atomics.load(preloadControl, 0)).toBe(1));
32
+ expect(Atomics.load(preloadStatus, 0)).toBe(1);
33
+
34
+ const control = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
35
+ const status = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
36
+ receive({
37
+ data: {
38
+ kind: 'kernel-job',
39
+ moduleUrl,
40
+ binding: { length: 0, read: {}, write: {} },
41
+ control,
42
+ status,
43
+ jobIndex: 0,
44
+ },
45
+ } as MessageEvent<unknown>);
46
+
47
+ expect(Atomics.load(control, 0)).toBe(1);
48
+ expect(Atomics.load(status, 0)).toBe(1);
49
+ });
50
+ });
@@ -0,0 +1,13 @@
1
+ import { Time, World } from '@forgeax/engine-ecs';
2
+ import { describe, expect, it } from 'vitest';
3
+
4
+ describe('M4 time ownership inventory', () => {
5
+ it('advances the protected Time resource only through World.update', () => {
6
+ const world = new World();
7
+ expect(() =>
8
+ world.insertResource(Time, { delta: 1, elapsed: 1, maxDeltaSeconds: 1 }),
9
+ ).toThrow();
10
+ world.update(1 / 60).unwrap();
11
+ expect(world.getResource(Time).delta).toBeCloseTo(1 / 60);
12
+ });
13
+ });
@@ -0,0 +1,15 @@
1
+ import { animationPlugin } from '@forgeax/engine-animation';
2
+ import { createWorldContext, World } from '@forgeax/engine-ecs';
3
+ import { scenePlugin } from '@forgeax/engine-scene';
4
+ import { describe, expect, it } from 'vitest';
5
+
6
+ describe('scene plugin policy', () => {
7
+ it('can be composed on a host-owned world', async () => {
8
+ const world = new World();
9
+ await createWorldContext(world, [scenePlugin()]);
10
+ });
11
+ });
12
+
13
+ it('extracted animation plugin has a stable identity', () => {
14
+ expect(animationPlugin().name).toBe('animation');
15
+ });