@vgai/engine 0.5.22 → 0.5.24

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 (303) hide show
  1. package/README.md +6 -3
  2. package/dist/adapter/adapter-module.d.ts.map +1 -1
  3. package/dist/adapter/adapter-module.js +2 -4
  4. package/dist/adapter/adapter-surface.d.ts +1 -1
  5. package/dist/adapter/adapter-surface.js +1 -1
  6. package/dist/adapter/authoring.d.ts +19 -21
  7. package/dist/adapter/authoring.d.ts.map +1 -1
  8. package/dist/adapter/authoring.js +2 -2
  9. package/dist/adapter/binding.d.ts +341 -0
  10. package/dist/adapter/binding.d.ts.map +1 -0
  11. package/dist/adapter/binding.js +148 -0
  12. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -1
  13. package/dist/adapter/colyseus-networking-adapter.js +23 -4
  14. package/dist/adapter/entrypoint-selection-readers.d.ts +24 -0
  15. package/dist/adapter/entrypoint-selection-readers.d.ts.map +1 -0
  16. package/dist/adapter/entrypoint-selection-readers.js +63 -0
  17. package/dist/adapter/entrypoint-selection-source.d.ts.map +1 -1
  18. package/dist/adapter/entrypoint-selection-source.js +1 -44
  19. package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -1
  20. package/dist/adapter/finders/scenes-from-entrypoint-selection.js +1 -52
  21. package/dist/adapter/host-context.d.ts +46 -15
  22. package/dist/adapter/host-context.d.ts.map +1 -1
  23. package/dist/adapter/host-context.js +2 -9
  24. package/dist/adapter/index.d.ts +11 -12
  25. package/dist/adapter/index.d.ts.map +1 -1
  26. package/dist/adapter/index.js +9 -10
  27. package/dist/adapter/ingest/game-contract-seams.d.ts +5 -0
  28. package/dist/adapter/ingest/game-contract-seams.d.ts.map +1 -1
  29. package/dist/adapter/ingest/game-contract-seams.js +1 -0
  30. package/dist/adapter/ingest/game-contract.d.ts +22 -3
  31. package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
  32. package/dist/adapter/ingest/game-contract.js +0 -3
  33. package/dist/adapter/ingest/scene-capture.d.ts +19 -23
  34. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
  35. package/dist/adapter/ingest/scene-capture.js +143 -17
  36. package/dist/adapter/ingest/visible-capture-window.d.ts +34 -0
  37. package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -1
  38. package/dist/adapter/native-debug-module.d.ts +40 -5
  39. package/dist/adapter/native-debug-module.d.ts.map +1 -1
  40. package/dist/adapter/native-debug-module.js +36 -9
  41. package/dist/adapter/rapier-physics-adapter.d.ts +31 -1
  42. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -1
  43. package/dist/adapter/rapier-physics-adapter.js +50 -36
  44. package/dist/adapter/renderer-config.d.ts +2 -2
  45. package/dist/adapter/renderer-config.js +2 -2
  46. package/dist/adapter/root-adapter.d.ts +7 -7
  47. package/dist/adapter/root-adapter.js +4 -4
  48. package/dist/adapter/system-adapter.d.ts +45 -7
  49. package/dist/adapter/system-adapter.d.ts.map +1 -1
  50. package/dist/adapter/system-seam-contract.d.ts +3 -3
  51. package/dist/adapter/system-seam-contract.js +3 -3
  52. package/dist/adapter/system-slot.d.ts +168 -0
  53. package/dist/adapter/system-slot.d.ts.map +1 -0
  54. package/dist/adapter/system-slot.js +229 -0
  55. package/dist/adapter/transform.d.ts +11 -1
  56. package/dist/adapter/transform.d.ts.map +1 -1
  57. package/dist/ai/navigation.d.ts +17 -1
  58. package/dist/ai/navigation.d.ts.map +1 -1
  59. package/dist/ai/navigation.js +26 -5
  60. package/dist/animation/anim-graph-types.d.ts +11 -3
  61. package/dist/animation/anim-graph-types.d.ts.map +1 -1
  62. package/dist/animation/theatre-clock-binding.d.ts +4 -4
  63. package/dist/animation/theatre-clock-binding.js +4 -4
  64. package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
  65. package/dist/animation/xstate-animation-binding.js +2 -2
  66. package/dist/animation/xstate-animation-meta.d.ts +13 -0
  67. package/dist/animation/xstate-animation-meta.d.ts.map +1 -1
  68. package/dist/animation/xstate-animation-meta.js +14 -0
  69. package/dist/asset-formats/index.d.ts +4 -7
  70. package/dist/asset-formats/index.d.ts.map +1 -1
  71. package/dist/asset-formats/index.js +4 -7
  72. package/dist/asset-formats/render-env.d.ts +5 -8
  73. package/dist/asset-formats/render-env.d.ts.map +1 -1
  74. package/dist/asset-formats/render-env.js +3 -6
  75. package/dist/asset-parse-error.d.ts +2 -5
  76. package/dist/asset-parse-error.d.ts.map +1 -1
  77. package/dist/asset-parse-error.js +2 -5
  78. package/dist/audio/bus-mixer.d.ts +101 -0
  79. package/dist/audio/bus-mixer.d.ts.map +1 -0
  80. package/dist/audio/bus-mixer.js +115 -0
  81. package/dist/core/frame-pacing.d.ts +1 -1
  82. package/dist/core/frame-pacing.js +2 -2
  83. package/dist/core/game-loop.d.ts +1 -3
  84. package/dist/core/game-loop.d.ts.map +1 -1
  85. package/dist/core/game-loop.js +1 -3
  86. package/dist/core/seeded-random.d.ts +1 -1
  87. package/dist/core/sim-clock.d.ts +5 -6
  88. package/dist/core/sim-clock.d.ts.map +1 -1
  89. package/dist/core/sim-clock.js +4 -5
  90. package/dist/core/types.d.ts +1 -3
  91. package/dist/core/types.d.ts.map +1 -1
  92. package/dist/defaults.d.ts +6 -14
  93. package/dist/defaults.d.ts.map +1 -1
  94. package/dist/defaults.js +6 -14
  95. package/dist/dev/register-render-vitals.d.ts +1 -4
  96. package/dist/dev/register-render-vitals.d.ts.map +1 -1
  97. package/dist/dev/register-render-vitals.js +1 -4
  98. package/dist/dev/render-debug-adapter.d.ts +2 -3
  99. package/dist/dev/render-debug-adapter.d.ts.map +1 -1
  100. package/dist/dev/render-debug-adapter.js +2 -3
  101. package/dist/dev/render-vitals.d.ts +3 -3
  102. package/dist/dev/render-vitals.js +3 -3
  103. package/dist/dev/webgl-frame-capture.d.ts +1 -1
  104. package/dist/dev/webgl-frame-capture.js +1 -1
  105. package/dist/index.d.ts +2 -5
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +2 -4
  108. package/dist/input/host-pointer.d.ts +122 -0
  109. package/dist/input/host-pointer.d.ts.map +1 -0
  110. package/dist/input/host-pointer.js +160 -0
  111. package/dist/input/input-manager.d.ts +18 -5
  112. package/dist/input/input-manager.d.ts.map +1 -1
  113. package/dist/input/input-manager.js +33 -13
  114. package/dist/input/rebind-controller.d.ts.map +1 -1
  115. package/dist/input/rebind-controller.js +6 -8
  116. package/dist/input/schema.d.ts.map +1 -1
  117. package/dist/input/schema.js +56 -28
  118. package/dist/manifest/filename.d.ts.map +1 -1
  119. package/dist/manifest/filename.js +8 -12
  120. package/dist/manifest/load.d.ts +10 -10
  121. package/dist/manifest/load.d.ts.map +1 -1
  122. package/dist/manifest/load.js +9 -6
  123. package/dist/manifest/schema.d.ts +17 -21
  124. package/dist/manifest/schema.d.ts.map +1 -1
  125. package/dist/manifest/schema.js +45 -35
  126. package/dist/physics/collider-dimensions.d.ts +8 -12
  127. package/dist/physics/collider-dimensions.d.ts.map +1 -1
  128. package/dist/physics/collider-dimensions.js +8 -12
  129. package/dist/pixi/scene-capture.d.ts +11 -13
  130. package/dist/pixi/scene-capture.d.ts.map +1 -1
  131. package/dist/react/world-state.d.ts +1 -1
  132. package/dist/react/world-state.d.ts.map +1 -1
  133. package/dist/render/light-camera-factory.d.ts +5 -7
  134. package/dist/render/light-camera-factory.d.ts.map +1 -1
  135. package/dist/render/light-camera-factory.js +8 -11
  136. package/dist/render/material-factory.js +1 -1
  137. package/dist/render/render-batch-system.d.ts.map +1 -1
  138. package/dist/render/render-features.d.ts +17 -6
  139. package/dist/render/render-features.d.ts.map +1 -1
  140. package/dist/render/render-features.js +0 -28
  141. package/dist/runtime/create-runtime.d.ts +34 -25
  142. package/dist/runtime/create-runtime.d.ts.map +1 -1
  143. package/dist/runtime/create-runtime.js +218 -93
  144. package/dist/runtime/debug-bridge.d.ts +12 -0
  145. package/dist/runtime/debug-bridge.d.ts.map +1 -1
  146. package/dist/runtime/debug-bridge.js +4 -0
  147. package/dist/runtime/debug-registry.d.ts +95 -8
  148. package/dist/runtime/debug-registry.d.ts.map +1 -1
  149. package/dist/runtime/debug-registry.js +24 -3
  150. package/dist/runtime/dev-build.d.ts +2 -2
  151. package/dist/runtime/dev-build.js +2 -2
  152. package/dist/runtime/game-input-seams.d.ts +2 -2
  153. package/dist/runtime/game-input-seams.d.ts.map +1 -1
  154. package/dist/runtime/game.d.ts +102 -41
  155. package/dist/runtime/game.d.ts.map +1 -1
  156. package/dist/runtime/game.js +80 -54
  157. package/dist/runtime/mount-game.d.ts +0 -16
  158. package/dist/runtime/mount-game.d.ts.map +1 -1
  159. package/dist/runtime/mount-game.js +8 -39
  160. package/dist/runtime/mount-manifest.d.ts +22 -14
  161. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  162. package/dist/runtime/mount-manifest.js +18 -18
  163. package/dist/runtime/playtest.d.ts +22 -0
  164. package/dist/runtime/playtest.d.ts.map +1 -0
  165. package/dist/runtime/playtest.js +12 -0
  166. package/dist/runtime/run-ticks-settled.d.ts +34 -0
  167. package/dist/runtime/run-ticks-settled.d.ts.map +1 -0
  168. package/dist/runtime/run-ticks-settled.js +59 -0
  169. package/dist/runtime/state-bridge.d.ts +2 -3
  170. package/dist/runtime/state-bridge.d.ts.map +1 -1
  171. package/dist/runtime/state-bridge.js +1 -0
  172. package/dist/setup/setup-audio.d.ts +12 -0
  173. package/dist/setup/setup-audio.d.ts.map +1 -1
  174. package/dist/setup/setup-audio.js +9 -10
  175. package/dist/setup/setup-renderer.d.ts +2 -25
  176. package/dist/setup/setup-renderer.d.ts.map +1 -1
  177. package/dist/setup/setup-renderer.js +2 -31
  178. package/dist/world3d-react/r3f-root-factory.d.ts +7 -7
  179. package/dist/world3d-react/r3f-root-factory.js +7 -7
  180. package/dist/world3d-react/rapier-physics-bridge.d.ts +9 -8
  181. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
  182. package/dist/world3d-react/rapier-physics-bridge.js +100 -48
  183. package/package.json +1 -1
  184. package/schemas/engine-capabilities.json +16 -14
  185. package/schemas/vgai-project.schema.json +35 -26
  186. package/src/adapter/adapter-module.ts +2 -4
  187. package/src/adapter/adapter-surface.ts +1 -1
  188. package/src/adapter/authoring.ts +19 -21
  189. package/src/adapter/binding.ts +468 -0
  190. package/src/adapter/colyseus-networking-adapter.ts +20 -5
  191. package/src/adapter/entrypoint-selection-readers.ts +66 -0
  192. package/src/adapter/entrypoint-selection-source.ts +1 -40
  193. package/src/adapter/finders/scenes-from-entrypoint-selection.ts +1 -48
  194. package/src/adapter/host-context.ts +45 -15
  195. package/src/adapter/index.ts +23 -11
  196. package/src/adapter/ingest/game-contract-seams.ts +1 -0
  197. package/src/adapter/ingest/game-contract.ts +22 -3
  198. package/src/adapter/ingest/scene-capture.ts +190 -39
  199. package/src/adapter/ingest/visible-capture-window.ts +35 -0
  200. package/src/adapter/native-debug-module.ts +66 -9
  201. package/src/adapter/rapier-physics-adapter.ts +76 -20
  202. package/src/adapter/renderer-config.ts +2 -2
  203. package/src/adapter/root-adapter.ts +7 -7
  204. package/src/adapter/system-adapter.ts +43 -8
  205. package/src/adapter/system-seam-contract.ts +3 -3
  206. package/src/adapter/system-slot.ts +291 -0
  207. package/src/adapter/transform.ts +18 -1
  208. package/src/ai/navigation.ts +30 -3
  209. package/src/animation/anim-graph-types.ts +11 -3
  210. package/src/animation/theatre-clock-binding.ts +4 -4
  211. package/src/animation/xstate-animation-binding.ts +2 -2
  212. package/src/animation/xstate-animation-meta.ts +16 -0
  213. package/src/asset-formats/index.ts +4 -7
  214. package/src/asset-formats/render-env.ts +3 -6
  215. package/src/asset-parse-error.ts +2 -5
  216. package/src/audio/bus-mixer.ts +161 -0
  217. package/src/core/frame-pacing.ts +2 -2
  218. package/src/core/game-loop.ts +1 -3
  219. package/src/core/seeded-random.ts +1 -1
  220. package/src/core/sim-clock.ts +5 -6
  221. package/src/core/types.ts +1 -3
  222. package/src/defaults.ts +6 -14
  223. package/src/dev/register-render-vitals.ts +1 -4
  224. package/src/dev/render-debug-adapter.ts +2 -3
  225. package/src/dev/render-vitals.ts +3 -3
  226. package/src/dev/webgl-frame-capture.ts +1 -1
  227. package/src/index.ts +2 -5
  228. package/src/input/host-pointer.ts +230 -0
  229. package/src/input/input-manager.ts +34 -13
  230. package/src/input/input-types.ts +1 -1
  231. package/src/input/rebind-controller.ts +6 -8
  232. package/src/input/schema.ts +216 -188
  233. package/src/manifest/filename.ts +8 -12
  234. package/src/manifest/load.ts +17 -13
  235. package/src/manifest/schema.ts +55 -47
  236. package/src/physics/collider-dimensions.ts +8 -12
  237. package/src/pixi/scene-capture.ts +12 -15
  238. package/src/react/world-state.tsx +1 -1
  239. package/src/render/light-camera-factory.ts +8 -11
  240. package/src/render/material-factory.ts +1 -1
  241. package/src/render/render-batch-system.ts +14 -6
  242. package/src/render/render-features.ts +17 -35
  243. package/src/runtime/create-runtime.ts +270 -108
  244. package/src/runtime/debug-bridge.ts +16 -0
  245. package/src/runtime/debug-registry.ts +121 -8
  246. package/src/runtime/dev-build.ts +2 -2
  247. package/src/runtime/game-input-seams.ts +2 -2
  248. package/src/runtime/game.ts +180 -80
  249. package/src/runtime/mount-game.ts +8 -56
  250. package/src/runtime/mount-manifest.ts +43 -34
  251. package/src/runtime/playtest.ts +22 -0
  252. package/src/runtime/run-ticks-settled.ts +72 -0
  253. package/src/runtime/state-bridge.ts +3 -3
  254. package/src/setup/setup-audio.ts +21 -11
  255. package/src/setup/setup-renderer.ts +2 -61
  256. package/src/world3d-react/r3f-root-factory.tsx +7 -7
  257. package/src/world3d-react/rapier-physics-bridge.tsx +107 -50
  258. package/dist/adapter/setup-three-root-adapter.d.ts +0 -86
  259. package/dist/adapter/setup-three-root-adapter.d.ts.map +0 -1
  260. package/dist/adapter/setup-three-root-adapter.js +0 -908
  261. package/dist/animation/clip-map.d.ts +0 -12
  262. package/dist/animation/clip-map.d.ts.map +0 -1
  263. package/dist/animation/clip-map.js +0 -31
  264. package/dist/asset-registry.d.ts +0 -38
  265. package/dist/asset-registry.d.ts.map +0 -1
  266. package/dist/asset-registry.js +0 -66
  267. package/dist/canvas-react/engine-bridge.d.ts +0 -45
  268. package/dist/canvas-react/engine-bridge.d.ts.map +0 -1
  269. package/dist/canvas-react/engine-bridge.js +0 -45
  270. package/dist/canvas-react/pixi-react-adapter.d.ts +0 -77
  271. package/dist/canvas-react/pixi-react-adapter.d.ts.map +0 -1
  272. package/dist/canvas-react/pixi-react-adapter.js +0 -294
  273. package/dist/canvas-react/world-context.d.ts +0 -98
  274. package/dist/canvas-react/world-context.d.ts.map +0 -1
  275. package/dist/canvas-react/world-context.js +0 -173
  276. package/dist/dev/debug-draw.d.ts +0 -24
  277. package/dist/dev/debug-draw.d.ts.map +0 -1
  278. package/dist/dev/debug-draw.js +0 -73
  279. package/dist/render/auto-batcher.d.ts +0 -34
  280. package/dist/render/auto-batcher.d.ts.map +0 -1
  281. package/dist/render/auto-batcher.js +0 -140
  282. package/dist/render/lod.d.ts +0 -13
  283. package/dist/render/lod.d.ts.map +0 -1
  284. package/dist/render/lod.js +0 -16
  285. package/dist/runtime/types.d.ts +0 -303
  286. package/dist/runtime/types.d.ts.map +0 -1
  287. package/dist/runtime/types.js +0 -1
  288. package/dist/world3d-react/engine-bridge.d.ts +0 -47
  289. package/dist/world3d-react/engine-bridge.d.ts.map +0 -1
  290. package/dist/world3d-react/engine-bridge.js +0 -73
  291. package/dist/world3d-react/r3f-adapter.d.ts +0 -58
  292. package/dist/world3d-react/r3f-adapter.d.ts.map +0 -1
  293. package/dist/world3d-react/r3f-adapter.js +0 -634
  294. package/dist/world3d-react/world-context.d.ts +0 -182
  295. package/dist/world3d-react/world-context.d.ts.map +0 -1
  296. package/dist/world3d-react/world-context.js +0 -235
  297. package/src/adapter/setup-three-root-adapter.ts +0 -1032
  298. package/src/animation/clip-map.ts +0 -34
  299. package/src/asset-registry.ts +0 -89
  300. package/src/dev/debug-draw.ts +0 -80
  301. package/src/render/auto-batcher.ts +0 -168
  302. package/src/render/lod.ts +0 -17
  303. package/src/runtime/types.ts +0 -328
@@ -7,14 +7,9 @@
7
7
  // has a `.describe()` (repo policy — powers `scripts/generate-schema.ts` and
8
8
  // the T4.1 schema-walk coverage test).
9
9
  //
10
- // Naming: this file follows the repo's `XxxSchema` (Zod schema) / `Xxx`
11
- // (inferred type) convention used throughout `scene/schema/` the design
12
- // doc's §3 sketch names the bare consts (`AdapterRoot`) without the
13
- // `Schema` suffix; that sketch is explicitly a
14
- // "Zod sketch" the doc tells implementers to adapt to real code style
15
- // ("mirror the style in scene/schema/scene-file.ts" per CLAUDE.md), so the
16
- // schema consts here are suffixed and the bare names are reserved for the
17
- // inferred types, matching every other schema file in the repo.
10
+ // Naming: `XxxSchema` is the Zod schema, `Xxx` the inferred type. Every schema
11
+ // file in this repo reads that way, so the bare names stay reserved for the
12
+ // types.
18
13
  //
19
14
  // Adapter surface values mirror `AdapterSurface` in
20
15
  // `packages/engine/src/runtime/game.ts` (`'three' | 'canvas' | 'dom'`)
@@ -53,7 +48,7 @@ export const GAME_MANIFEST_VERSION = 2;
53
48
  // which is exactly why react is a `dom` root rather than its own kind.
54
49
  //
55
50
  // The pre-rename spellings `threejs`/`pixijs`/`react` are REMOVED, not
56
- // normalized (WO-LR1 item 2, the legacy-removal doctrine at
51
+ // normalized (the legacy-removal doctrine at
57
52
  // ARCHITECTURE-CORE §Vocabulary). Normalization was a second way to say the
58
53
  // same thing: two spellings both parsed, so both kept being written, and
59
54
  // SECOND readers grew (the dev server's surface probe, the hosted-editor
@@ -75,8 +70,8 @@ const REMOVED_BARE_ADAPTER_SPELLING = {
75
70
  };
76
71
  function removedSpellingMessage(bad, where) {
77
72
  const canonical = where === 'adapter' ? REMOVED_BARE_ADAPTER_SPELLING[bad] : REMOVED_SURFACE_SPELLING[bad];
78
- return (`Game manifest: \`${where}\`: "${bad}" — that spelling was REMOVED (WO-LR1; ` +
79
- 'ARCHITECTURE-CORE §Vocabulary). The surface vocabulary is ' +
73
+ return (`Game manifest: \`${where}\`: "${bad}" — that spelling was REMOVED ` +
74
+ '(ARCHITECTURE-CORE §Vocabulary). The surface vocabulary is ' +
80
75
  "'three' | 'canvas' | 'dom' — what the HOST HANDS the root, never which " +
81
76
  `library it uses.\nFix: change \`${where}\` to "${canonical}".`);
82
77
  }
@@ -194,28 +189,6 @@ export const RootAdapterSchema = z
194
189
  .describe("How long the host waits for this game's first captured frame before the mount " +
195
190
  'FAILS by name. A game that needs a long boot (streamed world assets, a menu ' +
196
191
  'the player must clear) raises it; the default is 10s.'),
197
- world: z
198
- .object({
199
- entry: z
200
- .string()
201
- .describe("Project-relative path to the game's OWN module exporting that component"),
202
- export: z
203
- .string()
204
- .optional()
205
- .describe('Named export to read from that module; omit when the module default-exports it'),
206
- })
207
- .strict()
208
- .optional()
209
- .describe("The component this root's WORLD is, in the game's own source — a three root " +
210
- 'whose scene is a React/R3F component tree names it here. Two readers, and ' +
211
- 'they mount different things: the editor mounts THIS component alone as the ' +
212
- "root's design-time document (a still scene — its frameloop runs ONE bounded " +
213
- 'settle at mount, so physics-owned bodies rest at their authored spawn, and ' +
214
- 'is then frozen forever; nothing moves in Edit), while `entry` ' +
215
- 'above stays what PLAY mounts (the whole game, its own composition, its own ' +
216
- 'HUD and loop). Declaring it is what lets a scene be a scene in Edit rather ' +
217
- "than the running game's mount surfaces. A game whose world is not a " +
218
- 'component omits it and keeps mounting through `entry` in both modes.'),
219
192
  })
220
193
  .strict()
221
194
  .describe('Ingest adapter configuration for an unmodified game (a repo-vendored game or your ' +
@@ -257,6 +230,33 @@ export const AdapterRootSchema = z
257
230
  "mounts the root's DOM in (`@scope`; packages/editor/server/scoped-game-css.ts), so " +
258
231
  "the HUD is styled on the UI board's story cards and on the game surface without the " +
259
232
  'editor seeing a single one of those rules. The files themselves are never modified.'),
233
+ world: z
234
+ .object({
235
+ entry: z
236
+ .string()
237
+ .describe("Project-relative path to the game's OWN module exporting that component"),
238
+ export: z
239
+ .string()
240
+ .optional()
241
+ .describe('Named export to read from that module; omit when the module default-exports it'),
242
+ })
243
+ .strict()
244
+ .optional()
245
+ .describe("The component this root's WORLD is, in the game's own source. Two readers, and they " +
246
+ "mount different things: the EDITOR mounts THIS component alone as the root's " +
247
+ 'design-time document, while `entry` above stays what PLAY mounts (the whole game — ' +
248
+ 'its own composition, its own HUD, its own loop). It sits on the ROOT rather than ' +
249
+ 'inside any one adapter because the split it names is not about ingest: a game whose ' +
250
+ 'runtime entry is a SHELL over the thing an author actually edits has this shape ' +
251
+ 'whether the source is vendored or first-party. Two shipped cases, one field: an ' +
252
+ 'ingested game whose `entry` mounts game+HUD+loop while the named export is the world ' +
253
+ 'alone; and a translated Unity/Godot port, whose `entry` is a scene HOST that mounts ' +
254
+ 'the scene the built player starts on (`EditorBuildSettings` index 0 — routinely a ' +
255
+ 'menu with no 3D content at all) while the named export opens the scene an author ' +
256
+ "edits. That is Unity's own split: build settings say where the PLAYER starts; the " +
257
+ 'Scene view opens a scene, and Unity keeps that fact somewhere else entirely. A game ' +
258
+ 'whose world is not a separate component omits this and keeps mounting through ' +
259
+ '`entry` in both modes.'),
260
260
  zOrder: z
261
261
  .number()
262
262
  .int()
@@ -350,6 +350,7 @@ export const GameManifestSchema = z
350
350
  .describe('Exact @vgai/engine semver this game was scaffolded/last upgraded against — an ' +
351
351
  'identity pin, not a range'),
352
352
  })
353
+ .strict()
353
354
  .describe('Engine version pin'),
354
355
  roots: z
355
356
  .array(AdapterRootSchema)
@@ -422,20 +423,24 @@ export const GameManifestSchema = z
422
423
  .optional()
423
424
  .describe('Optional editor labels keyed by adapter-root id'),
424
425
  groups: z
425
- .array(z.object({
426
+ .array(z
427
+ .object({
426
428
  id: z.string().describe('Unique editor-only group id'),
427
429
  label: z.string().describe('Editor-only group label'),
428
430
  roots: z
429
431
  .array(z.string())
430
432
  .min(1)
431
433
  .describe('Adapter-root ids shown under this editor-only group'),
432
- }))
434
+ })
435
+ .strict())
433
436
  .optional()
434
437
  .describe('Optional editor-only hierarchy groups'),
435
438
  })
439
+ .strict()
436
440
  .optional()
437
441
  .describe('Editor projection for native adapter roots'),
438
442
  })
443
+ .strict()
439
444
  .optional()
440
445
  .describe('Editor-only authoring metadata; never runtime ownership'),
441
446
  server: z
@@ -469,6 +474,7 @@ export const GameManifestSchema = z
469
474
  .optional()
470
475
  .describe('Deploy-baked managed-relay credentials. NEVER hand-authored in source — written only into the staged manifest by `vgai deploy` and fetched at runtime by the standalone client'),
471
476
  })
477
+ .strict()
472
478
  .optional()
473
479
  .describe('Multiplayer server config (Colyseus), if this game registers a room'),
474
480
  resolution: z
@@ -476,6 +482,7 @@ export const GameManifestSchema = z
476
482
  width: z.number().describe('Canvas width in pixels'),
477
483
  height: z.number().describe('Canvas height in pixels'),
478
484
  })
485
+ .strict()
479
486
  .optional()
480
487
  .describe('Canvas resolution'),
481
488
  rendering: z
@@ -504,6 +511,7 @@ export const GameManifestSchema = z
504
511
  'production builds. Default false: the bridge only installs in dev builds. The ' +
505
512
  'runtime reader is the debug-bridge installer (D18).'),
506
513
  })
514
+ .strict()
507
515
  .optional()
508
516
  .describe('Debug-bridge production gating (D18) — governs whether ?vgai-debug=1 installs ' +
509
517
  'window.__vgai outside dev builds.'),
@@ -530,6 +538,7 @@ export const GameManifestSchema = z
530
538
  'even higher-precedence explicit config value a host passes directly. Optional — ' +
531
539
  "omit to fall back to the runtime's own fixed default seed."),
532
540
  })
541
+ .strict()
533
542
  .optional()
534
543
  .describe('Seeded-RNG determinism contract (D15) — governs ' +
535
544
  'whether ctx.random is boot-seeded from a reproducible seed and whether the ' +
@@ -576,6 +585,7 @@ export const GameManifestSchema = z
576
585
  "(the profiler's per-frame render.triangles, from renderer.info). Exact and " +
577
586
  'deterministic under a seed.'),
578
587
  })
588
+ .strict()
579
589
  .refine((budget) => Object.values(budget).some((value) => value !== undefined), {
580
590
  message: 'Game manifest: `budget` must set at least one metric (frameCpuMsP95, physicsMsP95, ' +
581
591
  'maxEntities, maxDrawCalls, maxTriangles) — an empty budget block gates nothing ' +
@@ -5,17 +5,13 @@
5
5
  * shape is defined in absolute world units at creation time. Three.js meshes,
6
6
  * by contrast, scale visually for free via the normal Object3D hierarchy. To
7
7
  * keep the physical collider matching what's on screen, the LOADER must bake
8
- * the entity's composed WORLD scale (self × every transformed ancestor — see
9
- * T1.1's world-transform composition) into the collider's dimensions at
10
- * creation time.
8
+ * the entity's composed WORLD scale (self × every transformed ancestor) into
9
+ * the collider's dimensions at creation time.
11
10
  *
12
- * This is the ONE place that does that math, so both the runtime loader
13
- * (scene-loader.ts `createPhysicsBody`) and the editor's collider gizmo
14
- * (gizmo-registry.ts) agree on exactly the same numbers previously the
15
- * editor gizmo only rendered the entity's own live Object3D scale (via normal
16
- * Three.js parenting) while the Rapier body ignored scale entirely, so the
17
- * two silently agreed by coincidence for uniform scale and disagreed for
18
- * everything else.
11
+ * This is the ONE place that does that math, so every caller — the physics
12
+ * body creation path and the editor's collider gizmo alike — agrees on
13
+ * exactly the same numbers. Two copies silently agree by coincidence for
14
+ * uniform scale and disagree for everything else.
19
15
  *
20
16
  * Round colliders (ball/capsule) can only represent a uniform radius — Rapier
21
17
  * has no ellipsoid/elliptical-capsule shape. A non-uniform world scale on a
@@ -33,8 +29,8 @@ export interface ColliderWorldDimensions {
33
29
  }
34
30
  /**
35
31
  * Compute a collider's WORLD-space dimensions given the entity's composed
36
- * world scale (self × ancestors, per-axis, in the entity's own local frame
37
- * X/Y/Z order matches `SceneEntity.transform.scale`).
32
+ * world scale (self × ancestors, per-axis, in the entity's own local frame,
33
+ * in X/Y/Z order).
38
34
  *
39
35
  * @param collider - the entity's authored (unscaled) collider definition.
40
36
  * @param worldScale - composed world scale `[x, y, z]`.
@@ -1 +1 @@
1
- {"version":3,"file":"collider-dimensions.d.ts","sourceRoot":"","sources":["../../src/physics/collider-dimensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMpE,MAAM,WAAW,uBAAuB;IACtC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,kBAAkB,EAC5B,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC7C,WAAW,EAAE,MAAM,GAClB,uBAAuB,CA4CzB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACrD,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC5C,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAItC"}
1
+ {"version":3,"file":"collider-dimensions.d.ts","sourceRoot":"","sources":["../../src/physics/collider-dimensions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMpE,MAAM,WAAW,uBAAuB;IACtC,+DAA+D;IAC/D,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,kBAAkB,EAC5B,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC7C,WAAW,EAAE,MAAM,GAClB,uBAAuB,CA4CzB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACrD,UAAU,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC5C,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAItC"}
@@ -5,17 +5,13 @@
5
5
  * shape is defined in absolute world units at creation time. Three.js meshes,
6
6
  * by contrast, scale visually for free via the normal Object3D hierarchy. To
7
7
  * keep the physical collider matching what's on screen, the LOADER must bake
8
- * the entity's composed WORLD scale (self × every transformed ancestor — see
9
- * T1.1's world-transform composition) into the collider's dimensions at
10
- * creation time.
8
+ * the entity's composed WORLD scale (self × every transformed ancestor) into
9
+ * the collider's dimensions at creation time.
11
10
  *
12
- * This is the ONE place that does that math, so both the runtime loader
13
- * (scene-loader.ts `createPhysicsBody`) and the editor's collider gizmo
14
- * (gizmo-registry.ts) agree on exactly the same numbers previously the
15
- * editor gizmo only rendered the entity's own live Object3D scale (via normal
16
- * Three.js parenting) while the Rapier body ignored scale entirely, so the
17
- * two silently agreed by coincidence for uniform scale and disagreed for
18
- * everything else.
11
+ * This is the ONE place that does that math, so every caller — the physics
12
+ * body creation path and the editor's collider gizmo alike — agrees on
13
+ * exactly the same numbers. Two copies silently agree by coincidence for
14
+ * uniform scale and disagree for everything else.
19
15
  *
20
16
  * Round colliders (ball/capsule) can only represent a uniform radius — Rapier
21
17
  * has no ellipsoid/elliptical-capsule shape. A non-uniform world scale on a
@@ -27,8 +23,8 @@ import { DEFAULTS } from '../defaults';
27
23
  const UNIFORM_SCALE_EPSILON = 1e-4;
28
24
  /**
29
25
  * Compute a collider's WORLD-space dimensions given the entity's composed
30
- * world scale (self × ancestors, per-axis, in the entity's own local frame
31
- * X/Y/Z order matches `SceneEntity.transform.scale`).
26
+ * world scale (self × ancestors, per-axis, in the entity's own local frame,
27
+ * in X/Y/Z order).
32
28
  *
33
29
  * @param collider - the entity's authored (unscaled) collider definition.
34
30
  * @param worldScale - composed world scale `[x, y, z]`.
@@ -17,20 +17,18 @@
17
17
  * instance, so it is trapped; a game bundling its own pixi cannot be captured at
18
18
  * all, and its mount fails by name.
19
19
  */
20
- import { type VisibilityClock, type VisibleCaptureWindow } from '../adapter/ingest/visible-capture-window';
20
+ import { type CaptureWaitOptions } from '../adapter/ingest/visible-capture-window';
21
21
  /**
22
- * Options for {@link SceneCapture2DHandle.waitForCapture} — the same shape the
23
- * three lane's `CaptureWaitOptions` has, because it is the same wait. Passing a
24
- * bare number is `{ timeoutMs }`, which is what every existing caller does.
22
+ * Options for {@link SceneCapture2DHandle.waitForCapture} — the WAIT's options,
23
+ * not this lane's, so they carry no `2D` suffix and are not declared here.
24
+ * They configure `visible-capture-window.ts`'s window, which both surfaces
25
+ * share; this lane used to restate them field-for-field under a `2D` name.
26
+ * The suffix marks what a surface genuinely owns
27
+ * ({@link CapturedRuntime2D} is a Pixi stage/renderer/app, and stays), and a
28
+ * budget of visible milliseconds is not that. Passing a bare number is
29
+ * `{ timeoutMs }`, which is what every existing caller does.
25
30
  */
26
- export interface CaptureWait2DOptions {
27
- /** The capture window, in VISIBLE milliseconds (default 10s). */
28
- timeoutMs?: number | undefined;
29
- /** Injected in tests; defaults to the document's own visibility. */
30
- visibility?: VisibilityClock | undefined;
31
- /** Live view of the wait while it runs, `null` the moment it ends. */
32
- onWait?: ((wait: VisibleCaptureWindow | null) => void) | undefined;
33
- }
31
+ export type { CaptureWaitOptions };
34
32
  /** A live Pixi runtime captured from an external PixiJS game. */
35
33
  export interface CapturedRuntime2D {
36
34
  /** The game's root stage Container. */
@@ -59,7 +57,7 @@ export interface SceneCapture2DHandle {
59
57
  * frame the tab draws after it comes forward is trapped exactly as it would
60
58
  * have been at boot. Rejects only when the window is spent while VISIBLE.
61
59
  */
62
- waitForCapture(options?: number | CaptureWait2DOptions): Promise<CapturedRuntime2D>;
60
+ waitForCapture(options?: number | CaptureWaitOptions): Promise<CapturedRuntime2D>;
63
61
  getDrawCount(): number;
64
62
  /** Pause/resume the captured game's own ticker (loop-host gating). */
65
63
  setPaused(paused: boolean): void;
@@ -1 +1 @@
1
- {"version":3,"file":"scene-capture.d.ts","sourceRoot":"","sources":["../../src/pixi/scene-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,oBAAoB,EAC1B,MAAM,0CAA0C,CAAC;AAElD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACzC,sEAAsE;IACtE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACpE;AAED,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,kCAAkC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpF,YAAY,IAAI,MAAM,CAAC;IACvB,sEAAsE;IACtE,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,SAAS,IAAI,IAAI,CAAC;CACnB;AAMD,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAChE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,OAAO,EACtB,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAmFtB"}
1
+ {"version":3,"file":"scene-capture.d.ts","sourceRoot":"","sources":["../../src/pixi/scene-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,0CAA0C,CAAC;AAElD;;;;;;;;;GASG;AACH,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAEnC,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,kCAAkC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C;;;;;;;;;;;;;;;;OAgBG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClF,YAAY,IAAI,MAAM,CAAC;IACvB,sEAAsE;IACtE,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,SAAS,IAAI,IAAI,CAAC;CACnB;AAMD,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAChE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,OAAO,EACtB,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAmFtB"}
@@ -18,9 +18,9 @@
18
18
  import { type PropsWithChildren } from 'react';
19
19
  import type { z } from 'zod';
20
20
  import type { RootStateObserver } from '../adapter';
21
+ import type { DebugCommandArgs } from '../runtime/debug-registry';
21
22
  import { type Equals, shallow } from '../runtime/frame-selector-cache';
22
23
  import type { Game } from '../runtime/game';
23
- import type { DebugCommandArgs } from '../runtime/types';
24
24
  /** Re-exported for convenience — the opt-in equality for selectors that
25
25
  * return a fresh object/array/tuple every call (default is `Object.is`). */
26
26
  export { shallow };
@@ -1 +1 @@
1
- {"version":3,"file":"world-state.d.ts","sourceRoot":"","sources":["../../src/react/world-state.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAEL,KAAK,iBAAiB,EAMvB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,EAA4B,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD;6EAC6E;AAC7E,OAAO,EAAE,OAAO,EAAE,CAAC;AAInB;;;;;;;;;;;;;;oFAcoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,iBAAiB,CAAC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,+BAElF;AAED;;mDAEmD;AACnD,wBAAgB,OAAO,IAAI,IAAI,CAQ9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,IAAI,GAAG,IAAI,CAE7C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,MAAM,GAAE,MAAM,CAAC,CAAC,CAAa,GAAG,CAAC,CAW9F;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAiBlF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,CAAC,EAClC,MAAM,GAAE,MAAM,CAAC,CAAC,CAAa,GAC5B,CAAC,CAoBH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,OAAO,EACjB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;CAAE,GAC1C,IAAI,CAaN;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,GAAG,SAAS,GAAG,SAAS,EAC1E,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,EACrE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAC/D,IAAI,CAeN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CASxE"}
1
+ {"version":3,"file":"world-state.d.ts","sourceRoot":"","sources":["../../src/react/world-state.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAEL,KAAK,iBAAiB,EAMvB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAA4B,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C;6EAC6E;AAC7E,OAAO,EAAE,OAAO,EAAE,CAAC;AAInB;;;;;;;;;;;;;;oFAcoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,iBAAiB,CAAC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,+BAElF;AAED;;mDAEmD;AACnD,wBAAgB,OAAO,IAAI,IAAI,CAQ9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,IAAI,IAAI,GAAG,IAAI,CAE7C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,MAAM,GAAE,MAAM,CAAC,CAAC,CAAa,GAAG,CAAC,CAW9F;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAiBlF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,CAAC,EAClC,MAAM,GAAE,MAAM,CAAC,CAAC,CAAa,GAC5B,CAAC,CAoBH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,OAAO,EACjB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;CAAE,GAC1C,IAAI,CAaN;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,GAAG,SAAS,GAAG,SAAS,EAC1E,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,EACrE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAC/D,IAAI,CAeN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CASxE"}
@@ -1,12 +1,10 @@
1
1
  /**
2
- * Shared light + camera factory (T1.13 DEFAULTS truth).
2
+ * Shared light + camera factory — the ONE place light/camera fallbacks are
3
+ * decided, and it decides them by READING `DEFAULTS.light`/`DEFAULTS.camera`.
3
4
  *
4
- * `createLight`/`createCamera` used to be duplicated verbatim between the
5
- * runtime loader (`scene-loader.ts`) and the editor preview
6
- * (`entity-factory.ts`)both hardcoded the same fallback literals (color
7
- * '#ffffff', fov 60, near 0.1, far 1000, etc.) that happened to agree with
8
- * `DEFAULTS.light`/`DEFAULTS.camera` by luck rather than by reading them. Any
9
- * edit to one copy (or to `DEFAULTS`) could silently diverge from the other.
5
+ * A second copy hardcoding the same literals (color '#ffffff', fov 60, near
6
+ * 0.1, far 1000) would agree by luck rather than by construction, and any
7
+ * edit to either copy or to `DEFAULTS` would silently diverge.
10
8
  *
11
9
  * This module is now the ONE place that builds a `THREE.Light`/`THREE.Camera`
12
10
  * from a `LightDescriptor`/`CameraDescriptor` descriptor, reading its fallbacks from
@@ -1 +1 @@
1
- {"version":3,"file":"light-camera-factory.d.ts","sourceRoot":"","sources":["../../src/render/light-camera-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9D,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,KAAK,CAAC,KAAK,CA8C7D;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAoBhE"}
1
+ {"version":3,"file":"light-camera-factory.d.ts","sourceRoot":"","sources":["../../src/render/light-camera-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9D,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,KAAK,CAAC,KAAK,CA8C7D;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAoBhE"}
@@ -1,12 +1,10 @@
1
1
  /**
2
- * Shared light + camera factory (T1.13 DEFAULTS truth).
2
+ * Shared light + camera factory — the ONE place light/camera fallbacks are
3
+ * decided, and it decides them by READING `DEFAULTS.light`/`DEFAULTS.camera`.
3
4
  *
4
- * `createLight`/`createCamera` used to be duplicated verbatim between the
5
- * runtime loader (`scene-loader.ts`) and the editor preview
6
- * (`entity-factory.ts`)both hardcoded the same fallback literals (color
7
- * '#ffffff', fov 60, near 0.1, far 1000, etc.) that happened to agree with
8
- * `DEFAULTS.light`/`DEFAULTS.camera` by luck rather than by reading them. Any
9
- * edit to one copy (or to `DEFAULTS`) could silently diverge from the other.
5
+ * A second copy hardcoding the same literals (color '#ffffff', fov 60, near
6
+ * 0.1, far 1000) would agree by luck rather than by construction, and any
7
+ * edit to either copy or to `DEFAULTS` would silently diverge.
10
8
  *
11
9
  * This module is now the ONE place that builds a `THREE.Light`/`THREE.Camera`
12
10
  * from a `LightDescriptor`/`CameraDescriptor` descriptor, reading its fallbacks from
@@ -21,10 +19,9 @@ import * as THREE from 'three';
21
19
  // `three/addons/*` alias (package.json `exports`: `"./addons/*":
22
20
  // "./examples/jsm/*"` — the identical file as
23
21
  // `three/examples/jsm/lights/RectAreaLightUniformsLib.js`) because a literal
24
- // `/examples/` specifier trips `engine-host-no-game-imports.test.ts`'s
25
- // game/editor-example guard (a same-substring false positive against this
26
- // repo's OWN `packages/editor/template/src/examples/` convention, unrelated
27
- // to three.js's addon folder naming).
22
+ // `/examples/` specifier trips this repo's game/editor-example import guard —
23
+ // a same-substring false positive against our own `src/examples/` convention,
24
+ // unrelated to three.js's addon folder naming.
28
25
  import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';
29
26
  import { DEFAULTS } from '../defaults';
30
27
  let rectAreaLightUniformsInitialized = false;
@@ -54,7 +54,7 @@ export function createMaterial(mat) {
54
54
  // R1c — every fallback below reads DEFAULTS.material.* instead of
55
55
  // duplicating its value as a bare literal, so DEFAULTS stays the single
56
56
  // source of truth for what an omitted field renders as (see
57
- // defaults-out-of-scope-consistency.test.ts / material-factory.test.ts's
57
+ // `material-factory.test.ts`'s
58
58
  // "omitted-field" locks, which fail if either copy drifts from the other).
59
59
  const dMat = DEFAULTS.material;
60
60
  const sideValue = mat.side ?? dMat.side;
@@ -1 +1 @@
1
- {"version":3,"file":"render-batch-system.d.ts","sourceRoot":"","sources":["../../src/render/render-batch-system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AA6FhE,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAVlB,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAe;IAEpC,OAAO,CAAC,QAAQ,CAA6C;IAE7D,OAAO,CAAC,SAAS,CAAoD;gBAG3D,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,sBAAsB;IAM1C,wEAAwE;IACxE,KAAK,IAAI,IAAI;IA0Bb,OAAO,CAAC,SAAS;IAyCjB;;;;;OAKG;IACH,MAAM,IAAI,IAAI;IAyBd;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,GAAG,IAAI;IAStD,kEAAkE;IAClE,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,4DAA4D;IAC5D,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,QAAQ,IAAI,IAAI;CAiBjB"}
1
+ {"version":3,"file":"render-batch-system.d.ts","sourceRoot":"","sources":["../../src/render/render-batch-system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAqGhE,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;IAVlB,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAe;IAEpC,OAAO,CAAC,QAAQ,CAA6C;IAE7D,OAAO,CAAC,SAAS,CAAoD;gBAG3D,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,QAAQ,EAAE,sBAAsB;IAM1C,wEAAwE;IACxE,KAAK,IAAI,IAAI;IA0Bb,OAAO,CAAC,SAAS;IAyCjB;;;;;OAKG;IACH,MAAM,IAAI,IAAI;IAyBd;;;OAGG;IACH,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,GAAG,IAAI;IAStD,kEAAkE;IAClE,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,4DAA4D;IAC5D,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,QAAQ,IAAI,IAAI;CAiBjB"}
@@ -1,12 +1,23 @@
1
1
  import { z } from 'zod';
2
2
  /**
3
3
  * The render-feature registry — single source of truth for every togglable render
4
- * setting. The scene schema (`SceneEnvironment.rendering`, `SceneEntity.render`),
5
- * the cascade resolver (`resolveRenderSettings`), the editor UI, and the stats
6
- * overlay are all derived from this list, so "everything togglable" stays
7
- * consistent by construction (same posture as the component/material/instancer
8
- * registries). Adding a feature here gives it a schema field + cascade entry for
9
- * free..
4
+ * setting. The render-env schema (`asset-formats/render-env.ts`) and the cascade
5
+ * resolver (`resolveRenderSettings`) are both derived from this list, so
6
+ * "everything togglable" stays consistent by construction (same posture as the
7
+ * component/material/instancer registries).
8
+ *
9
+ * EVERY ENTRY HERE MUST HAVE A RUNTIME READER of its resolved value, and that is
10
+ * now enforced: `schema-reader-coverage.test.ts` derives its walk from this
11
+ * array, so adding a feature adds a described schema path that fails coverage
12
+ * until `schema-consumption-map.ts` names the file that reads it.
13
+ *
14
+ * Three entries were deleted when that enforcement first ran, having reached it
15
+ * with no reader at all: `autoBatch` (its only mention was a COMMENT in
16
+ * `render-batch-system.ts`, a class whose own header says nothing calls it),
17
+ * `lod`, and `backend` (which offered a `webgpu` option while
18
+ * `setup-renderer.ts` unconditionally constructs a `THREE.WebGLRenderer`). A
19
+ * toggle that changes nothing is worse than a missing one — it tells an author
20
+ * the engine has a dial it does not have.
10
21
  */
11
22
  export type RenderFeatureValue = boolean | number | string;
12
23
  export interface RenderFeature {
@@ -1 +1 @@
1
- {"version":3,"file":"render-features.d.ts","sourceRoot":"","sources":["../../src/render/render-features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,uDAAuD;IACvD,OAAO,EAAE,kBAAkB,CAAC;IAC5B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,oFAAoF;IACpF,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,oCAAoC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EA6EnD,CAAC;AAEF,kCAAkC;AAClC,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAEpE,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAAC,UAAU,CAiBtF"}
1
+ {"version":3,"file":"render-features.d.ts","sourceRoot":"","sources":["../../src/render/render-features.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,uDAAuD;IACvD,OAAO,EAAE,kBAAkB,CAAC;IAC5B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,oFAAoF;IACpF,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,oCAAoC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAgDnD,CAAC;AAEF,kCAAkC;AAClC,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAEpE,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAAC,UAAU,CAiBtF"}
@@ -1,14 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  export const RENDER_FEATURES = [
3
- {
4
- key: 'autoBatch',
5
- label: 'Auto-batching',
6
- description: 'Automatically batch entities sharing geometry+material into one draw call (InstancedMesh/BatchedMesh) while keeping each Object3D as the handle. The headline perf win; opt out per-entity for custom-shader/skinned meshes.',
7
- kind: 'toggle',
8
- default: true,
9
- apply: 'live',
10
- perEntity: true,
11
- },
12
3
  {
13
4
  key: 'frustumCulling',
14
5
  label: 'Frustum culling',
@@ -18,15 +9,6 @@ export const RENDER_FEATURES = [
18
9
  apply: 'live',
19
10
  perEntity: true,
20
11
  },
21
- {
22
- key: 'lod',
23
- label: 'Level of detail',
24
- description: 'Distance-based geometry swap (LOD) for eligible entities.',
25
- kind: 'toggle',
26
- default: true,
27
- apply: 'live',
28
- perEntity: true,
29
- },
30
12
  {
31
13
  key: 'shadows',
32
14
  label: 'Shadows',
@@ -64,16 +46,6 @@ export const RENDER_FEATURES = [
64
46
  apply: 'reload',
65
47
  perEntity: false,
66
48
  },
67
- {
68
- key: 'backend',
69
- label: 'Renderer backend',
70
- description: 'GPU backend: auto picks WebGPU when available, else WebGL2. Applies on reload.',
71
- kind: 'enum',
72
- default: 'auto',
73
- apply: 'reload',
74
- perEntity: false,
75
- options: ['auto', 'webgl', 'webgpu'],
76
- },
77
49
  ];
78
50
  /** Map for O(1) lookup by key. */
79
51
  export const RENDER_FEATURE_BY_KEY = new Map(RENDER_FEATURES.map((f) => [f.key, f]));
@@ -1,16 +1,27 @@
1
+ import { type RootDeclaration } from '../adapter/binding';
1
2
  import type { DomHostContext } from '../adapter/host-context';
2
3
  import type { MountedPixiRoot, MountedReactRoot, MountedThreeRoot, RootAdapter } from '../adapter/root-adapter';
3
4
  import { type Game, type GameInternal, type RootInstance } from './game';
4
- import type { PlaytestContext } from './types';
5
+ import type { PlaytestContext } from './playtest';
5
6
  /**
6
7
  * Register a three world onto the Game shell. `opts.id` defaults to
7
8
  * `'main'`; multi-root callers pass an explicit id. This is the one
8
9
  * registration path for a three world, whatever its id.
9
10
  */
10
- export declare function registerThreeRoot(game: GameInternal, adapter: RootAdapter, mounted: MountedThreeRoot, opts?: {
11
- id?: string | undefined;
12
- pausable?: boolean | undefined;
13
- }): RootInstance;
11
+ export declare function registerThreeRoot(game: GameInternal, adapter: RootAdapter, mounted: MountedThreeRoot, opts?: RegisterRootOptions): RootInstance;
12
+ /** What every `register<Surface>Root` takes beyond the mount itself. */
13
+ export interface RegisterRootOptions {
14
+ readonly id?: string | undefined;
15
+ readonly pausable?: boolean | undefined;
16
+ /**
17
+ * The DECLARATION half of this root's binding, from the resolver that
18
+ * produced `adapter` (`adapter/binding.ts`). Absent for a bare harness
19
+ * registration or a `mountManifestRoots` caller who supplied an
20
+ * already-constructed adapter — see `RootInstance.binding` for why that
21
+ * legitimately yields `null` rather than a fabricated binding.
22
+ */
23
+ readonly declaration?: RootDeclaration | undefined;
24
+ }
14
25
  /**
15
26
  * Register a canvas world onto the Game shell — the pixi analog of
16
27
  * {@link registerThreeRoot}. `adapter` is the seam's own
@@ -18,10 +29,7 @@ export declare function registerThreeRoot(game: GameInternal, adapter: RootAdapt
18
29
  * (`AdapterHandle`, `runtime/game.ts`), so this passes through with zero cast.
19
30
  * `stage` is the one field every `MountedPixiRoot` actually carries.
20
31
  */
21
- export declare function registerPixiRoot(game: GameInternal, adapter: RootAdapter<'canvas'>, mounted: MountedPixiRoot, opts?: {
22
- id?: string | undefined;
23
- pausable?: boolean | undefined;
24
- }): RootInstance;
32
+ export declare function registerPixiRoot(game: GameInternal, adapter: RootAdapter<'canvas'>, mounted: MountedPixiRoot, opts?: RegisterRootOptions): RootInstance;
25
33
  /**
26
34
  * Register a React world onto the Game shell — the DOM
27
35
  * analog of {@link registerThreeRoot}/{@link registerPixiRoot}. A react
@@ -33,10 +41,7 @@ export declare function registerPixiRoot(game: GameInternal, adapter: RootAdapte
33
41
  * `registerPixiRoot`'s doc comment above) — `RootInstance.adapter` only
34
42
  * needs `.id`, so this passes through with zero cast.
35
43
  */
36
- export declare function registerReactRoot(game: GameInternal, adapter: RootAdapter<'dom'>, mounted: MountedReactRoot, container: HTMLElement, opts?: {
37
- id?: string | undefined;
38
- pausable?: boolean | undefined;
39
- }): RootInstance;
44
+ export declare function registerReactRoot(game: GameInternal, adapter: RootAdapter<'dom'>, mounted: MountedReactRoot, container: HTMLElement, opts?: RegisterRootOptions): RootInstance;
40
45
  /**
41
46
  * One world to mount in the universal host — the host-facing mirror of
42
47
  * `manifest/load.ts`'s `ResolvedAdapterRoot` (same identity and presentation
@@ -63,6 +68,14 @@ export interface RootMountSpecBase {
63
68
  * `input-router.ts`'s `resolveClaimingRoot`.
64
69
  */
65
70
  readonly hitTest?: ((x: number, y: number) => boolean) | undefined;
71
+ /**
72
+ * The DECLARATION half of this root's binding, from whoever resolved
73
+ * `adapter` — see `adapter/binding.ts`'s {@link RootDeclaration}. Carried on
74
+ * the spec because the resolver knows it and the host is the only one who
75
+ * can complete the binding (it needs `mounted`, which does not exist until
76
+ * this spec is mounted).
77
+ */
78
+ readonly declaration?: RootDeclaration | undefined;
66
79
  }
67
80
  export interface ThreeRootMountSpec extends RootMountSpecBase {
68
81
  readonly kind: 'three';
@@ -89,9 +102,8 @@ export interface PixiRootMountSpec extends RootMountSpecBase {
89
102
  * opaque mount with nothing to tick).
90
103
  *
91
104
  * Deliberately carries NO `firstParty: true` brand: that brand specifically
92
- * means "has a `.ctx: GameContext`" (`isFirstPartyMounted`,
93
- * `runtime/game.ts`) a react world has no Rapier/ComponentManager/
94
- * GameContext at all, so branding it first-party would be a type lie.
105
+ * a react world has no physics or component runtime at all, so branding it
106
+ * first-party would be a type lie.
95
107
  * `Game.registerRoot`'s "no state bridge" console warning explicitly exempts
96
108
  * `kind: 'dom'` (§7.1-15): a react world has no `observe` BY DESIGN — that
97
109
  * hook is scoped to `useRootObservation` (the ingested/foreign-world case),
@@ -125,7 +137,7 @@ export interface ReactRootAdapter extends RootAdapter<'dom'> {
125
137
  readonly id: string;
126
138
  mount(host: DomHostContext): Promise<MountedReactGame>;
127
139
  }
128
- /** WO-34, same reasoning as {@link PixiRootMountSpec} above: the seam's
140
+ /** Same reasoning as {@link PixiRootMountSpec} above: the seam's
129
141
  * `RootAdapter<'dom'>` is what a DOM root actually guarantees. */
130
142
  export interface ReactRootMountSpec extends RootMountSpecBase {
131
143
  readonly kind: 'dom';
@@ -149,9 +161,8 @@ export interface RootsRuntimeConfig {
149
161
  /**
150
162
  * Mirrors `ThreeHostContext.headless` (Node conformance tests — no GPU): skips
151
163
  * real `WebGLRenderer` construction for every three world in this
152
- * session (a stand-in renderer is used instead, exactly as
153
- * `SetupThreeRootAdapter.mount` already special-cases `host.headless`
154
- * internally). Pixijs roots are unaffected — Pixi already falls back to
164
+ * session (a stand-in renderer is used instead; adapters special-case
165
+ * `host.headless` themselves). Pixijs roots are unaffected — Pixi already falls back to
155
166
  * a 2D canvas renderer with no GPU. Never set `true` in a real host.
156
167
  */
157
168
  headless?: boolean | undefined;
@@ -200,11 +211,9 @@ export interface RootsRuntimeConfig {
200
211
  /**
201
212
  * Handle returned by createGameRuntime() for controlling the running game.
202
213
  *
203
- * This is the GENERIC host handle — it has no first-party concepts (no
204
- * `GameContext`, no `GameSetupFn`). First-party features (the live `GameContext`,
205
- * warm-restart hot reload) are reached through `game.defaultRoot.mounted`
206
- * and narrowed to `MountedSetupThreeRoot`
207
- * (the editor does this for HMR/physics-sync — those are inherently first-party).
214
+ * This is the GENERIC host handle — it has no first-party concepts. A
215
+ * root's own surface is reached through `game.defaultRoot.mounted`, typed
216
+ * as the mounted-root contract (`MountedRoot`).
208
217
  *
209
218
  * Root access is explicit through `game.roots`, `game.world(id)`, and
210
219
  * `game.defaultRoot`; the session does not project a surface-specific alias.