@volter/editor-game 0.5.65

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 (302) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +23 -0
  3. package/contributions/asset-budget-asset.menu.ts +26 -0
  4. package/contributions/asset-budget.action.ts +18 -0
  5. package/contributions/asset-budget.document.tsx +21 -0
  6. package/contributions/asset-budget.menu.ts +22 -0
  7. package/contributions/audio-unlock.service.ts +17 -0
  8. package/contributions/audio.utility.tsx +15 -0
  9. package/contributions/autoplay.service.ts +48 -0
  10. package/contributions/bridge.command.ts +172 -0
  11. package/contributions/build-profiles.document.tsx +21 -0
  12. package/contributions/build-progress.status.tsx +45 -0
  13. package/contributions/build.action.ts +26 -0
  14. package/contributions/build.command.ts +27 -0
  15. package/contributions/build.header.tsx +37 -0
  16. package/contributions/build.menu.ts +31 -0
  17. package/contributions/build.service.ts +31 -0
  18. package/contributions/connection.status.tsx +43 -0
  19. package/contributions/coverage.service.ts +118 -0
  20. package/contributions/edit-mode-audio.service.ts +23 -0
  21. package/contributions/edit-mode-networking.service.ts +30 -0
  22. package/contributions/game-document.service.ts +25 -0
  23. package/contributions/game-eval.command.ts +210 -0
  24. package/contributions/game.layout.ts +19 -0
  25. package/contributions/gameplay.command.ts +255 -0
  26. package/contributions/generation.service.ts +96 -0
  27. package/contributions/generations.status.tsx +53 -0
  28. package/contributions/ingest.service.ts +80 -0
  29. package/contributions/instances.command.ts +75 -0
  30. package/contributions/navmesh.menu.ts +39 -0
  31. package/contributions/navmesh.service.ts +19 -0
  32. package/contributions/network.utility.tsx +17 -0
  33. package/contributions/play.command.ts +355 -0
  34. package/contributions/profiler.action.ts +16 -0
  35. package/contributions/profiler.menu.ts +22 -0
  36. package/contributions/profiler.utility.tsx +17 -0
  37. package/contributions/react/component-board.service.ts +21 -0
  38. package/contributions/react/design-time-mount.service.ts +60 -0
  39. package/contributions/react/pasteboard.action.ts +41 -0
  40. package/contributions/react/react-inspector.service.ts +85 -0
  41. package/contributions/react/story-documents.service.ts +44 -0
  42. package/contributions/scene-document.service.ts +32 -0
  43. package/contributions/state-watch.action.ts +17 -0
  44. package/contributions/state-watch.menu.ts +23 -0
  45. package/contributions/state-watch.utility.tsx +20 -0
  46. package/contributions/team-playtest.service.ts +124 -0
  47. package/contributions/three/camera-runtime.inspector.tsx +34 -0
  48. package/contributions/three/component-board.service.ts +24 -0
  49. package/contributions/three/component-verbs.command.ts +110 -0
  50. package/contributions/three/component-verbs.service.ts +92 -0
  51. package/contributions/three/constraints.inspector.tsx +34 -0
  52. package/contributions/three/model-asset-sections.service.ts +26 -0
  53. package/contributions/three/reflection-probe-capture.inspector.tsx +32 -0
  54. package/contributions/three/story-documents.service.ts +31 -0
  55. package/contributions/three/three-authoring.service.ts +66 -0
  56. package/contributions/transport.header.tsx +19 -0
  57. package/contributions/xstate-behavior.action.ts +42 -0
  58. package/contributions/xstate-behavior.document.tsx +73 -0
  59. package/contributions/xstate-behavior.inspector.tsx +28 -0
  60. package/contributions/xstate-behavior.menu.ts +23 -0
  61. package/package.json +144 -0
  62. package/src/asset-budget/AssetBudgetPanel.tsx +1172 -0
  63. package/src/asset-budget/asset-budget-model.ts +799 -0
  64. package/src/asset-budget/basis-encoder.ts +165 -0
  65. package/src/asset-budget/gltf-io.ts +154 -0
  66. package/src/asset-budget/gltf-optimize.ts +384 -0
  67. package/src/asset-budget/image-dims.ts +78 -0
  68. package/src/asset-budget/optimize-apply.ts +221 -0
  69. package/src/audio/AudioDebuggerPanel.tsx +457 -0
  70. package/src/audio/audio-debugger-model.ts +87 -0
  71. package/src/bridge/call.ts +60 -0
  72. package/src/bridge/dispatch.ts +459 -0
  73. package/src/bridge/live-frames.ts +25 -0
  74. package/src/bridge/screenshot.ts +316 -0
  75. package/src/build/BuildProfilesPanel.tsx +476 -0
  76. package/src/build/build-session.ts +247 -0
  77. package/src/build/format-bytes.ts +14 -0
  78. package/src/command-results.ts +36 -0
  79. package/src/coverage/live-authoring-surface.ts +30 -0
  80. package/src/coverage/live-project-verbs.ts +162 -0
  81. package/src/coverage/native-system-coverage.ts +143 -0
  82. package/src/coverage/root-coverage.ts +79 -0
  83. package/src/coverage/session-coverage.ts +193 -0
  84. package/src/design-system-stories/ApplicationChrome.stories.tsx +100 -0
  85. package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +406 -0
  86. package/src/edit-mode/edit-mode-audio.ts +56 -0
  87. package/src/edit-mode/edit-mode-networking.ts +112 -0
  88. package/src/game-document/DevicePresetPicker.tsx +84 -0
  89. package/src/game-document/GameCaptureFrameButton.tsx +45 -0
  90. package/src/game-document/GameDocument.tsx +215 -0
  91. package/src/game-document/GamePanel.tsx +662 -0
  92. package/src/game-document/InstanceInspectorPicker.tsx +183 -0
  93. package/src/game-document/crowd-debug.ts +183 -0
  94. package/src/game-document/device-preview.ts +336 -0
  95. package/src/game-document/game-view-store.ts +107 -0
  96. package/src/game-document/physics-debug.ts +187 -0
  97. package/src/generation/GenerationActivity.tsx +421 -0
  98. package/src/generation/GenerationGallery.css +231 -0
  99. package/src/generation/generation-documents.tsx +338 -0
  100. package/src/generation/generation-jobs.ts +128 -0
  101. package/src/generation/generation-presentation.ts +257 -0
  102. package/src/host/adapter-reach.ts +445 -0
  103. package/src/host/adapter-runtime-bindings.ts +303 -0
  104. package/src/host/after-paint.ts +112 -0
  105. package/src/host/api/configurations.ts +66 -0
  106. package/src/host/authoring/babylon-authoring-adapter.ts +703 -0
  107. package/src/host/authoring/canvas-runtime-recognition.ts +50 -0
  108. package/src/host/authoring/contract-hierarchy-authoring.ts +144 -0
  109. package/src/host/authoring/contract-scenes-stories.ts +204 -0
  110. package/src/host/authoring/creation-site-related.ts +55 -0
  111. package/src/host/authoring/ephemeral-persistence.ts +29 -0
  112. package/src/host/authoring/gesture-persist.ts +84 -0
  113. package/src/host/authoring/ingest-data-writer.ts +232 -0
  114. package/src/host/authoring/ingest-source-persistence.ts +826 -0
  115. package/src/host/authoring/mount-isolated-pixi-screen.ts +250 -0
  116. package/src/host/authoring/mounted-authoring.ts +41 -0
  117. package/src/host/authoring/owned-pixi-ticker-listeners.ts +96 -0
  118. package/src/host/authoring/phaser-live-authoring-adapter.ts +265 -0
  119. package/src/host/authoring/pixi-authoring-adapter.ts +1554 -0
  120. package/src/host/authoring/pixi-creation-site-write-target.ts +60 -0
  121. package/src/host/authoring/pixi-isolation-assets.ts +25 -0
  122. package/src/host/authoring/pixi-live-write-target.ts +979 -0
  123. package/src/host/authoring/pixi-source-identity.ts +141 -0
  124. package/src/host/authoring/pixi-still-presentation.ts +71 -0
  125. package/src/host/authoring/pixi-structure-history.ts +237 -0
  126. package/src/host/authoring/pixi-transform-channels.ts +205 -0
  127. package/src/host/authoring/selection-remount-handoff.ts +23 -0
  128. package/src/host/authoring/source-persistence-backend.ts +373 -0
  129. package/src/host/authoring/source-refresh-revisions.ts +81 -0
  130. package/src/host/authoring/struct-write-pipe.ts +143 -0
  131. package/src/host/auto-frame-window.ts +89 -0
  132. package/src/host/binding-resolver.ts +393 -0
  133. package/src/host/browser-transpile.ts +631 -0
  134. package/src/host/canvas-entry-runtime.ts +95 -0
  135. package/src/host/components/CameraAuthoringOverlay.tsx +216 -0
  136. package/src/host/components/HeaderTelemetry.tsx +341 -0
  137. package/src/host/components/PixiIsolationSceneContent.tsx +280 -0
  138. package/src/host/components/ResolutionPicker.tsx +89 -0
  139. package/src/host/components/ThreeIsolationSceneContent.tsx +180 -0
  140. package/src/host/components/frame-debugger-model.ts +579 -0
  141. package/src/host/components/header-telemetry-model.ts +74 -0
  142. package/src/host/components/scene-document.tsx +447 -0
  143. package/src/host/components/utility-view-state.ts +87 -0
  144. package/src/host/components/world-root-stage-binding.tsx +133 -0
  145. package/src/host/components/world-root-stage.ts +1046 -0
  146. package/src/host/coverage/authoring-read-probe.ts +583 -0
  147. package/src/host/coverage/capability-coverage.ts +1587 -0
  148. package/src/host/coverage/coverage-accounting.ts +261 -0
  149. package/src/host/coverage/game-contract-seam-evidence.ts +82 -0
  150. package/src/host/coverage/project-verb-coverage.ts +148 -0
  151. package/src/host/coverage/system-adapter-coverage.ts +373 -0
  152. package/src/host/design-system-stories/StoryLayout.tsx +104 -0
  153. package/src/host/design-system-stories/fixtures/authoring.ts +247 -0
  154. package/src/host/design-system-stories/fixtures/editor-runtime.tsx +115 -0
  155. package/src/host/document-preview-three.ts +110 -0
  156. package/src/host/entry-adjudication.ts +89 -0
  157. package/src/host/game-location-guard.ts +150 -0
  158. package/src/host/game-module-access.ts +196 -0
  159. package/src/host/game-realm-page.ts +358 -0
  160. package/src/host/game-realm-reclaim.ts +55 -0
  161. package/src/host/game-realm-storage.ts +104 -0
  162. package/src/host/gameplay-export.ts +288 -0
  163. package/src/host/gameplay-recording.ts +717 -0
  164. package/src/host/gated-globals.ts +1511 -0
  165. package/src/host/history/json-history-resource.ts +254 -0
  166. package/src/host/ingest/registry.ts +261 -0
  167. package/src/host/instance-extract-actions.ts +120 -0
  168. package/src/host/instance-fork-actions.ts +120 -0
  169. package/src/host/play-control-hook.ts +26 -0
  170. package/src/host/playwright-shim.ts +479 -0
  171. package/src/host/projection/dom.ts +295 -0
  172. package/src/host/projection/pixi.ts +288 -0
  173. package/src/host/r3f-entry-runtime.ts +77 -0
  174. package/src/host/react-mount-runtime.ts +162 -0
  175. package/src/host/realm-services.ts +148 -0
  176. package/src/host/recording-preview.ts +106 -0
  177. package/src/host/roots/module-root.ts +203 -0
  178. package/src/host/roots/react-root.ts +181 -0
  179. package/src/host/same-realm-loop-gate.ts +544 -0
  180. package/src/host/scene-view-drawability.ts +69 -0
  181. package/src/host/sdk/tools.ts +31 -0
  182. package/src/host/served-bundle-runtime-modules.ts +331 -0
  183. package/src/host/server-log-bridge.ts +60 -0
  184. package/src/host/staged-projects.ts +24 -0
  185. package/src/host/stories/mounted-story-viewport-source.ts +64 -0
  186. package/src/host/stories/story-arg-descriptors.ts +50 -0
  187. package/src/host/stories/story-media-presence.ts +152 -0
  188. package/src/host/surface-content.ts +87 -0
  189. package/src/host/take-named-export.ts +23 -0
  190. package/src/host/three-ingest-runtime.ts +76 -0
  191. package/src/host/types-fastnoise-lite.d.ts +7 -0
  192. package/src/host/types-mikktspace.d.ts +20 -0
  193. package/src/host/types-troika-three-text.d.ts +7 -0
  194. package/src/host/use-active-performance-source.ts +53 -0
  195. package/src/host/viewport-pose-memory.ts +48 -0
  196. package/src/host/viewport-root-presentation.ts +40 -0
  197. package/src/ingest/active-ingest.ts +251 -0
  198. package/src/ingest/active-scene-navigation.ts +43 -0
  199. package/src/ingest/authoring/ingest-dom-surface-authoring.ts +191 -0
  200. package/src/ingest/authoring/ingest-root-adapter.ts +897 -0
  201. package/src/ingest/capture-wait-report.ts +122 -0
  202. package/src/ingest/deferred-ingest-play.ts +216 -0
  203. package/src/ingest/deferred-ingest-session.ts +23 -0
  204. package/src/ingest/discovery-public-ingest.ts +242 -0
  205. package/src/ingest/dom-stub-mark.ts +7 -0
  206. package/src/ingest/entry-load.ts +56 -0
  207. package/src/ingest/game-contract-realm.ts +34 -0
  208. package/src/ingest/game-pointer-lock.ts +89 -0
  209. package/src/ingest/held-scene-repaint.ts +73 -0
  210. package/src/ingest/host-surface-box.ts +174 -0
  211. package/src/ingest/ingest-boot-viewport.ts +54 -0
  212. package/src/ingest/ingest-canvas-scene-document.tsx +177 -0
  213. package/src/ingest/ingest-canvas-scene.ts +50 -0
  214. package/src/ingest/ingest-evidence-hook.ts +131 -0
  215. package/src/ingest/ingest-frame-snapshot.ts +183 -0
  216. package/src/ingest/ingest-play-commands.ts +134 -0
  217. package/src/ingest/ingest-play-control.ts +299 -0
  218. package/src/ingest/ingest-render-debug.ts +320 -0
  219. package/src/ingest/ingest-siblings.ts +487 -0
  220. package/src/ingest/ingest-status.ts +62 -0
  221. package/src/ingest/live-ingest-facet.ts +46 -0
  222. package/src/ingest/module-mode.ts +229 -0
  223. package/src/ingest/mount-canvas-ingest-root.ts +899 -0
  224. package/src/ingest/mount-coverage.ts +296 -0
  225. package/src/ingest/mount-dom-ingest-root.ts +282 -0
  226. package/src/ingest/mount-ingest-root.ts +744 -0
  227. package/src/ingest/mount-three-ingest-root.ts +366 -0
  228. package/src/ingest/resolve-canvas.ts +47 -0
  229. package/src/ingest/resolve-three.ts +123 -0
  230. package/src/ingest/served-bundle.ts +109 -0
  231. package/src/ingest/served-html-boot.ts +292 -0
  232. package/src/ingest/surface-canvas.ts +84 -0
  233. package/src/ingest/surface-dom.ts +84 -0
  234. package/src/ingest/surface-three.ts +128 -0
  235. package/src/ingest/types.ts +76 -0
  236. package/src/ingest/unmount-ingest-root.ts +224 -0
  237. package/src/navmesh/navmesh-actions.ts +27 -0
  238. package/src/navmesh/navmesh-handler.ts +237 -0
  239. package/src/navmesh/navmesh-workflow-store.ts +78 -0
  240. package/src/network/NetworkInspectorPanel.tsx +644 -0
  241. package/src/network/network-inspector-model.ts +225 -0
  242. package/src/play/play-boot-stall.ts +118 -0
  243. package/src/play/play-log-events.ts +26 -0
  244. package/src/play/play-mode.ts +2553 -0
  245. package/src/play/play-recording.ts +335 -0
  246. package/src/play/react-play-live-authoring.ts +165 -0
  247. package/src/play-bar/PlayBar.tsx +488 -0
  248. package/src/play-bar/PlayerCountPicker.tsx +100 -0
  249. package/src/profiler/FrameDebuggerPanel.tsx +458 -0
  250. package/src/profiler/PerformancePanel.tsx +1068 -0
  251. package/src/profiler/ProfilerPanel.tsx +53 -0
  252. package/src/profiler/frame-debugger-store.ts +97 -0
  253. package/src/profiler/main-thread-busy.ts +90 -0
  254. package/src/react/design-time-react-mount.ts +782 -0
  255. package/src/react/dom-authoring-adapter.ts +764 -0
  256. package/src/react/pasteboard-materialize.ts +154 -0
  257. package/src/react/react-inspector-section.tsx +2496 -0
  258. package/src/react/react-world-authoring-adapter.ts +3795 -0
  259. package/src/react/story-documents/story-args-section.ts +19 -0
  260. package/src/react/story-documents/story-documents.tsx +1380 -0
  261. package/src/react/story-paint-bounds.ts +94 -0
  262. package/src/react/ui-board-document.tsx +101 -0
  263. package/src/react/ui-board-title.ts +9 -0
  264. package/src/react/ui-component-board.ts +72 -0
  265. package/src/services/audio-pose-guard.ts +81 -0
  266. package/src/services/game-audio-unlock.ts +48 -0
  267. package/src/state-watch/StateWatchPanel.tsx +535 -0
  268. package/src/three/authoring/camera-runtime-inspector-section.tsx +135 -0
  269. package/src/three/authoring/constraint-inspector-section.tsx +189 -0
  270. package/src/three/authoring/design-time-renderer.ts +189 -0
  271. package/src/three/authoring/model-asset-inspector-section.css +41 -0
  272. package/src/three/authoring/model-asset-inspector-section.tsx +869 -0
  273. package/src/three/authoring/oid-source-persistence.ts +557 -0
  274. package/src/three/authoring/r3f-design-session.ts +1174 -0
  275. package/src/three/authoring/r3f-source-authoring-adapter.ts +5949 -0
  276. package/src/three/authoring/reflection-probe-inspector-section.tsx +76 -0
  277. package/src/three/authoring/spatial-audio-handles.ts +215 -0
  278. package/src/three/authoring/spatial-collider-handles.ts +229 -0
  279. package/src/three/authoring/spatial-joint-handles.ts +114 -0
  280. package/src/three/authoring/spatial-light-handles.ts +178 -0
  281. package/src/three/authoring/spatial-lod-handles.ts +93 -0
  282. package/src/three/authoring/spatial-particle-handles.ts +368 -0
  283. package/src/three/authoring/three-authoring-adapter.ts +1953 -0
  284. package/src/three/authoring/three-scene-identity.ts +19 -0
  285. package/src/three/authoring/three-spatial-handles.ts +161 -0
  286. package/src/three/authoring/typed-three-inspector.ts +528 -0
  287. package/src/three/component-verbs/extract-menu.ts +71 -0
  288. package/src/three/component-verbs/fork-menu.ts +78 -0
  289. package/src/three/component-verbs/internals-menu.ts +91 -0
  290. package/src/three/story-documents/three-story-documents.tsx +607 -0
  291. package/src/three/three-board/ThreeBoardDocument.tsx +888 -0
  292. package/src/three/three-board/board-framing.ts +412 -0
  293. package/src/three/three-board/board-layout.ts +401 -0
  294. package/src/three/three-board/board-scene.ts +901 -0
  295. package/src/three/three-board/three-component-board.ts +62 -0
  296. package/src/xstate/XStateBehaviorSection.tsx +130 -0
  297. package/src/xstate/XStateMachineInspector.tsx +566 -0
  298. package/src/xstate/character-animation-machine.fixture.ts +74 -0
  299. package/src/xstate/live-behaviors.ts +106 -0
  300. package/src/xstate/use-live-actor-state.ts +44 -0
  301. package/src/xstate/xstate-graph.ts +235 -0
  302. package/src/xstate/xstate-layout.ts +76 -0
@@ -0,0 +1,118 @@
1
+ /**
2
+ * CAPABILITY COVERAGE (`@volter/editor-sdk/services`, a `workspace.service`
3
+ * contribution): the four derived families that GRADE a mounted game's
4
+ * adapters, and the union headline the editor console says out loud.
5
+ *
6
+ * ## Why this is the game skew's and not the host's
7
+ *
8
+ * Every row here is a question about a GAME — which providers this root's
9
+ * `AuthoringAdapter` exposes, which `SystemAdapters` slots the running game
10
+ * bound, whether the open project can build and prove itself, whether its
11
+ * adapter table became real Edit documents. A host with no game skew loaded
12
+ * (the models build) has no adapters to grade and asked none of it; it kept
13
+ * paying for the derivation anyway, because the families were host fields on
14
+ * `collectState` and a direct call in the host's vitals tick.
15
+ *
16
+ * ## The two doors, both the host's own, neither of them new vocabulary
17
+ *
18
+ * - `session.reportFacet(collect, { reusableKeys })` — the four `vgai status`
19
+ * facets. The keys are declared REUSABLE because grading a root re-walks
20
+ * its tree (76ms–1.3s, measured), which is exactly the cost
21
+ * `command-listener.ts`'s `REUSABLE_DERIVED_FACETS` exists to keep off the
22
+ * interaction path: a collect handed a `reuse` snapshot copies them, and
23
+ * the host strips them from an interaction PATCH by name.
24
+ * - `session.onSample(fn)` — the host's own five-second vitals sample
25
+ * (`coverage/session-vitals.ts`), which `reportSessionCoverage` used to be
26
+ * a direct call inside. Subscribing keeps the promise that module's header
27
+ * makes: ONE watcher, one instant, one answer per cadence. A second
28
+ * interval here would sample the same session a fraction of a second later
29
+ * and publish a second story about one moment.
30
+ *
31
+ * A `restart` says "my project's files changed", so the project family's file
32
+ * cache is dropped on it — through `session.onCommandDispatched`, the door
33
+ * that already reports every relayed command, rather than a line in the
34
+ * host's dispatch naming this package.
35
+ */
36
+ import { editorHost } from '@volter/editor-sdk/host';
37
+ import { authoringSurfaceCoverage } from '../src/coverage/live-authoring-surface';
38
+ import {
39
+ invalidateProjectFileFacts,
40
+ projectVerbCoverage,
41
+ } from '../src/coverage/live-project-verbs';
42
+ import { nativeSystemCoverage } from '../src/coverage/native-system-coverage';
43
+ import { rootCoverageFacet } from '../src/coverage/root-coverage';
44
+ import { reportSessionCoverage } from '../src/coverage/session-coverage';
45
+
46
+ export const point = 'workspace.service';
47
+
48
+ /** The four keys this facet serves, and the ones the host strips from an
49
+ * interaction patch. Named once. */
50
+ const REUSABLE_KEYS = [
51
+ 'rootCoverage',
52
+ 'systemCoverage',
53
+ 'projectCoverage',
54
+ 'authoringCoverage',
55
+ ] as const;
56
+
57
+ function coverageFacets(reuse: Record<string, unknown> | null): Record<string, unknown> {
58
+ if (reuse)
59
+ return {
60
+ rootCoverage: reuse['rootCoverage'] ?? [],
61
+ systemCoverage: reuse['systemCoverage'] ?? null,
62
+ projectCoverage: reuse['projectCoverage'] ?? null,
63
+ authoringCoverage: reuse['authoringCoverage'] ?? null,
64
+ };
65
+ const systems = nativeSystemCoverage();
66
+ const project = projectVerbCoverage();
67
+ const authoring = authoringSurfaceCoverage();
68
+ return {
69
+ // THE DERIVED COVERAGE, per mounted root — native and ingested alike. The
70
+ // row vocabulary is generated from the `AuthoringAdapter` contract itself
71
+ // (`src/coverage/root-coverage.ts`), so a capability nobody remembered to
72
+ // enumerate still appears here as a standing row. `[]` when nothing is
73
+ // mounted, which is not the same as "no gaps".
74
+ rootCoverage: rootCoverageFacet().map((entry) => ({
75
+ worldId: entry.worldId,
76
+ surface: entry.surface,
77
+ summary: entry.report.summary,
78
+ rows: entry.report.rows.map((row) => ({ ...row })),
79
+ })),
80
+ // The GAME-scoped companion to `rootCoverage`: one row per
81
+ // `SystemAdapters` slot, read off the editor's own live registry. `null`
82
+ // for an ingested mount, whose declared-carrier measurement in
83
+ // `ingest.coverage` is stronger, and for a session with no open project.
84
+ systemCoverage: systems
85
+ ? { summary: systems.summary, rows: systems.rows.map((row) => ({ ...row })) }
86
+ : null,
87
+ // The THIRD derived family, and the one that lives outside both adapter
88
+ // contracts: the native verbs whose subject is the PROJECT rather than a
89
+ // mounted root — its committed proof route, whether `vgai add` can land a
90
+ // capability here, and whether it can produce a standalone build at all
91
+ // (`@editor/coverage/project-verb-coverage`). Without it a project could
92
+ // be green in the other two families and silently have none of the three.
93
+ // `null` only when no project is open.
94
+ projectCoverage: project
95
+ ? { summary: project.summary, rows: project.rows.map((row) => ({ ...row })) }
96
+ : null,
97
+ // The PROJECT-level authoring surface: whether the resolved adapter table
98
+ // became real Edit documents and Content pieces. Runtime/root coverage can
99
+ // be green while both are absent, so this family has its own status facet.
100
+ authoringCoverage: authoring
101
+ ? { summary: authoring.summary, rows: authoring.rows.map((row) => ({ ...row })) }
102
+ : null,
103
+ };
104
+ }
105
+
106
+ export function start(): () => void {
107
+ const session = editorHost().session;
108
+ const stopFacet = session.reportFacet(coverageFacets, { reusableKeys: REUSABLE_KEYS });
109
+ const stopSample = session.onSample(reportSessionCoverage);
110
+ const stopCommands = session.onCommandDispatched((type) => {
111
+ if (type === 'restart') invalidateProjectFileFacts();
112
+ });
113
+ return () => {
114
+ stopFacet();
115
+ stopSample();
116
+ stopCommands();
117
+ };
118
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * EDIT-TIME AUDIO (`@volter/editor-sdk/services`, a `workspace.service`
3
+ * contribution): the first-party Three/Web Audio graph the editor inspects
4
+ * while nothing is playing, so Stop falls back to a real adapter instead of
5
+ * making audio disappear.
6
+ *
7
+ * Install-once and project-independent, like `audio-unlock.service.ts` beside
8
+ * it — the graph is the page's, not the open project's — so this has no
9
+ * `onProjectChange` re-install, unlike edit-time networking.
10
+ *
11
+ * It was `components/EditModeAudioBootstrap.tsx`, a component that rendered
12
+ * `null` so the shell's layout could run an effect, and through it the host
13
+ * imported `@volter/game-runtime/setup/setup-audio`, `@volter/game-runtime/audio/bus-mixer` and
14
+ * `@volter/game-runtime/audio/pose-guard` — the engine's audio RUNTIME — into every editor
15
+ * boot (WORK.md §The open-source launch, phase 1 unit 7).
16
+ */
17
+ import { installEditModeAudio } from '../src/edit-mode/edit-mode-audio';
18
+
19
+ export const point = 'workspace.service';
20
+
21
+ export function start(): () => void {
22
+ return installEditModeAudio();
23
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * EDIT-TIME NETWORKING (`@volter/editor-sdk/services`, a `workspace.service`
3
+ * contribution): the networking adapter the editor inspects while nothing is
4
+ * playing, bound to the open project's own Colyseus client/room exports.
5
+ *
6
+ * Unlike audio (universal, install-once), it is project-dependent — it
7
+ * installs only when the open project declares a server — so it re-installs
8
+ * on every project change.
9
+ *
10
+ * It was `components/EditModeNetworkingBootstrap.tsx`, a component that
11
+ * rendered `null` so the shell's layout could run an effect. A service is what
12
+ * that always was, and the shell no longer names it (WORK.md §The workbench,
13
+ * P3b).
14
+ */
15
+ import { onProjectChange } from '@volter/editor-core/project-manager';
16
+ import { installEditModeNetworking } from '../src/edit-mode/edit-mode-networking';
17
+
18
+ export const point = 'workspace.service';
19
+
20
+ export function start(): () => void {
21
+ let dispose = installEditModeNetworking();
22
+ const stop = onProjectChange(() => {
23
+ dispose();
24
+ dispose = installEditModeNetworking();
25
+ });
26
+ return () => {
27
+ stop();
28
+ dispose();
29
+ };
30
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * THE GAME DOCUMENT's content, registered (`@volter/editor-sdk/services`, a
3
+ * `workspace.service` contribution). The host owns the live document's
4
+ * LIFETIME — `workspace:game` opens when a lane acquires it and closes on the
5
+ * playing → stopped edge (`live-document.ts`) — and this package owns what it
6
+ * DRAWS: the panel a runtime mounts into and the document-local toolbar
7
+ * (resolution, device emulation, instance inspection, debug draw, frame
8
+ * capture).
9
+ *
10
+ * A service rather than a module-load side effect, so the registration is
11
+ * paired with an unregistration the host runs before the next contribution
12
+ * pass — a build that drops `@volter/editor-game` leaves the host with no live content
13
+ * and the door's own `NoLiveContent` placeholder, which is the honest state.
14
+ */
15
+ import { editorHost } from '@volter/editor-sdk/host';
16
+ import { GameDocumentContent, GameDocumentToolbar } from '../src/game-document/GameDocument';
17
+
18
+ export const point = 'workspace.service';
19
+
20
+ export function start(): () => void {
21
+ return editorHost().workspace.liveDocument.register({
22
+ Content: GameDocumentContent,
23
+ Toolbar: GameDocumentToolbar,
24
+ });
25
+ }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * The STEP verbs of the session wire (`@volter/editor-sdk/commands`, a
3
+ * `workspace.command` contribution): `game-eval`, the module lane behind
4
+ * `vgai eval`'s `game.run(...)`, and `page-script`, the in-page Playwright
5
+ * shim behind `page(...)`. Both carry a step function's own SOURCE over the
6
+ * wire and reconstruct it here — closures do not survive the trip — so both
7
+ * are gated on a live game surface (a play session or an ingest mount) and
8
+ * rooted at the game container, never editor chrome.
9
+ *
10
+ * The module lane's page-side door (`window.__vgaiGameEval`) and the two
11
+ * providers it needs are installed when this module loads, which is when the
12
+ * verbs themselves become available: one handler, two doors, registered
13
+ * together.
14
+ *
15
+ * Play mode, the module resolver and the shim are the game skew's own
16
+ * modules, still housed in the editor until Play leaves the host (WORK.md
17
+ * §The workbench, G); they are reached through the `@editor/*` alias the
18
+ * editor's Vite serves to every contribution, and become this package's own
19
+ * imports when they move. Nothing here is host API.
20
+ */
21
+
22
+ import { createGameModuleResolver, setFocusedInstanceProvider } from '../src/host/game-module-access';
23
+ import { createPageShim, PageShimUnsupportedError } from '../src/host/playwright-shim';
24
+ import type {
25
+ CommandContribution,
26
+ EditorCommandMessage,
27
+ EditorCommandResult,
28
+ } from '@volter/editor-sdk/commands';
29
+ import { notPlayingResult } from '../src/command-results';
30
+ import { isIngestActive } from '../src/ingest/active-ingest';
31
+ import { focusedInstanceId, getGameContainer, isPlayModeActive } from '../src/play/play-mode';
32
+
33
+ export const point = 'workspace.command';
34
+
35
+ /**
36
+ * `game-eval` relay op — THE MODULE LANE. Reconstructs a step function's
37
+ * source in the editor page (same wire contract as `page-script`: closures do
38
+ * not survive) and runs it against a scope of { page, modules, instanceId } —
39
+ * `modules(path)` importing the RUNNING mount's own module instances
40
+ * (`game-module-access.ts`). This is what makes `vgai eval` able to touch the
41
+ * game's exported modules directly, in the browser, with no registry: the
42
+ * step is literal JS against the game's real functions.
43
+ *
44
+ * The result must survive the wire: anything unserializable is refused BY
45
+ * NAME rather than mangled — return plain data, not live objects.
46
+ */
47
+ /**
48
+ * The Playwright-host door to the SAME handler: a real `page.evaluate` cannot
49
+ * reach relay ops, so the hook exposes `game-eval` inside the page itself.
50
+ * One handler, two doors — the lanes cannot drift.
51
+ */
52
+ declare global {
53
+ interface Window {
54
+ __vgaiGameEval?: (src: string, instance?: string) => Promise<unknown>;
55
+ }
56
+ }
57
+ if (typeof window !== 'undefined') {
58
+ setFocusedInstanceProvider(focusedInstanceId);
59
+ window.__vgaiGameEval = async (src: string, instance?: string) => {
60
+ const result = await handleGameEval({
61
+ type: 'game-eval',
62
+ src,
63
+ ...(instance === undefined ? {} : { instance }),
64
+ } as unknown as EditorCommandMessage);
65
+ if (!result.ok) throw new Error(result.error ?? 'game-eval failed');
66
+ return (result.data as { result?: unknown } | undefined)?.result ?? null;
67
+ };
68
+ }
69
+
70
+ async function handleGameEval(cmd: EditorCommandMessage): Promise<EditorCommandResult> {
71
+ if (!isPlayModeActive() && !isIngestActive()) return notPlayingResult();
72
+ const src = cmd['src'];
73
+ if (typeof src !== 'string') {
74
+ return { ok: false, error: 'game-eval requires a string "src" (the step\'s toString())' };
75
+ }
76
+ const container = getGameContainer();
77
+ if (!container) {
78
+ return {
79
+ ok: false,
80
+ error: 'game-eval: no play-mode game container is mounted yet',
81
+ data: { code: 'GAME_EVAL_ERROR' },
82
+ };
83
+ }
84
+ const instanceRaw = cmd['instance'];
85
+ const instanceId = typeof instanceRaw === 'string' ? instanceRaw : undefined;
86
+ let step: (scope: unknown) => unknown;
87
+ try {
88
+ step = new Function('scope', `return (${src})(scope)`) as (scope: unknown) => unknown;
89
+ } catch (err) {
90
+ return {
91
+ ok: false,
92
+ error: `game-eval: failed to reconstruct the step function from source — ${
93
+ err instanceof Error ? err.message : String(err)
94
+ }`,
95
+ data: { code: 'GAME_EVAL_ERROR' },
96
+ };
97
+ }
98
+ const scope = {
99
+ page: createPageShim(container),
100
+ modules: createGameModuleResolver(instanceId),
101
+ instanceId: instanceId ?? focusedInstanceId(),
102
+ };
103
+ try {
104
+ const result = await step(scope);
105
+ const value = result === undefined ? null : result;
106
+ try {
107
+ JSON.stringify(value);
108
+ } catch {
109
+ return {
110
+ ok: false,
111
+ error:
112
+ 'game-eval: the step returned an unserializable value ' +
113
+ `(${Object.prototype.toString.call(value)}) — return plain data (numbers, strings, ` +
114
+ 'arrays, plain objects), not live module objects.',
115
+ data: { code: 'GAME_EVAL_UNSERIALIZABLE' },
116
+ };
117
+ }
118
+ return { ok: true, data: { result: value } };
119
+ } catch (err) {
120
+ return {
121
+ ok: false,
122
+ error: `game-eval step failed: ${err instanceof Error ? (err.stack ?? err.message) : String(err)}`,
123
+ data: { code: 'GAME_EVAL_ERROR' },
124
+ };
125
+ }
126
+ }
127
+
128
+ /**
129
+ * `page-script` relay op handler — "the playwright shim in the editor
130
+ * page + script-mode wire op". Standalone command (like `bridge-screenshot`,
131
+ * its sibling in `bridge.command.ts`),
132
+ * NOT a `bridge-call` method: this is editor-page UI automation, not the
133
+ * game-debug seam, so it deliberately stays outside `dispatchBridgeMethod`'s
134
+ * switch — the bridge↔wire parity gate (`bridge-wire-parity.test.ts`) only
135
+ * walks THAT switch, and must never need to know about this op.
136
+ *
137
+ * `cmd['src']` is a UI-automation step's `Function.prototype.toString()`
138
+ * source (`@volter/editor-live`'s `RelayTransport.runPageScript` — see that file's
139
+ * doc comment for the client-facing half of the wire contract). Reconstructed
140
+ * here with `new Function` and run against a fresh `createPageShim` rooted at
141
+ * the SAME game container `bridge-screenshot`'s composite capture uses
142
+ * (`getGameContainer` — never editor chrome). `PageShimUnsupportedError`
143
+ * (thrown the instant the step touches an unimplemented `Page`/`Locator`
144
+ * member) is distinguished from any other step failure so a caller can tell
145
+ * "this shim doesn't support that yet" apart from "the step's own assertion
146
+ * failed" — both are structured failures, never a hang or a silent
147
+ * mis-report.
148
+ */
149
+ async function handlePageScript(cmd: EditorCommandMessage): Promise<EditorCommandResult> {
150
+ // An ingest mount IS the live game surface even though it never creates a
151
+ // first-party `play-mode.ts` session. Keep the Playwright-style page door on
152
+ // the same reachability rule as bridge calls/screenshots: a real ingest
153
+ // container is sufficient, while the genuinely-unmounted case still
154
+ // refuses below. Without this, `vgai play` could start an ingested game and
155
+ // `game.commands()` would work, yet `page(...)` answered "not in play mode"
156
+ // against that very same visible game.
157
+ if (!isPlayModeActive() && !isIngestActive()) return notPlayingResult();
158
+ const src = cmd['src'];
159
+ if (typeof src !== 'string') {
160
+ return { ok: false, error: 'page-script requires a string "src" (the step\'s toString())' };
161
+ }
162
+ const container = getGameContainer();
163
+ if (!container) {
164
+ return {
165
+ ok: false,
166
+ error: 'page-script: no play-mode game container is mounted yet',
167
+ data: { code: 'PAGE_SCRIPT_ERROR' },
168
+ };
169
+ }
170
+ let step: (page: unknown) => unknown;
171
+ try {
172
+ // Reconstructing a wire-carried step's source is the documented wire
173
+ // contract (decision 2) — the same limitation class as
174
+ // Playwright's own evaluate serialization: closures over anything
175
+ // outside the step's own body do NOT survive the trip.
176
+ step = new Function('page', `return (${src})(page)`) as (page: unknown) => unknown;
177
+ } catch (err) {
178
+ return {
179
+ ok: false,
180
+ error: `page-script: failed to reconstruct the step function from source — ${
181
+ err instanceof Error ? err.message : String(err)
182
+ }`,
183
+ data: { code: 'PAGE_SCRIPT_ERROR' },
184
+ };
185
+ }
186
+ const page = createPageShim(container);
187
+ try {
188
+ const result = await step(page);
189
+ return { ok: true, data: { result: result === undefined ? null : result } };
190
+ } catch (err) {
191
+ if (err instanceof PageShimUnsupportedError) {
192
+ return {
193
+ ok: false,
194
+ error: err.message,
195
+ data: { code: 'PAGE_SHIM_UNSUPPORTED', member: err.member, supported: [...err.supported] },
196
+ };
197
+ }
198
+ return {
199
+ ok: false,
200
+ error: `page-script: step threw — ${err instanceof Error ? err.message : String(err)}`,
201
+ data: { code: 'PAGE_SCRIPT_ERROR' },
202
+ };
203
+ }
204
+ }
205
+
206
+ export const commands: CommandContribution['commands'] = {
207
+ // THE MODULE LANE: an in-page step over { page, modules, instanceId }.
208
+ 'game-eval': { timeoutMs: 60_000, derivedRefresh: 'always', handle: handleGameEval },
209
+ 'page-script': { timeoutMs: 60_000, derivedRefresh: 'always', handle: handlePageScript },
210
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The GAME workspace — building and playing the game: the editor's standing
3
+ * arrangement, unchanged (`@volter/editor-sdk/looks`, a `workspace.layout`
4
+ * contribution). It applies to every project the game editor opens: a
5
+ * project with no root yet is a game not yet begun, and the Game workspace is
6
+ * where its first root is added. No captured state: the dock's own reconcile
7
+ * builds the standing arrangement from nothing.
8
+ */
9
+ import type { WorkspaceLayoutContribution } from '@volter/editor-sdk/looks';
10
+
11
+ export const point = 'workspace.layout';
12
+ export const layout: WorkspaceLayoutContribution = {
13
+ id: 'game',
14
+ title: 'Game',
15
+ description:
16
+ "Building and playing the game: the editor's standing arrangement, unchanged. The default.",
17
+ // Game authoring uses the viewport's floating controls; Blender owns its header row.
18
+ regions: { header: 'hidden' },
19
+ };