@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,79 @@
1
+ /**
2
+ * PER-ROOT COVERAGE — the generated capability report for EVERY root the editor
3
+ * currently has mounted, native and ingested alike.
4
+ *
5
+ * ## The defect this closes
6
+ *
7
+ * Coverage used to be an ingest-only instrument: `ingest/mount-coverage.ts`
8
+ * assembled facts for the one ingested world and nothing said anything about a
9
+ * native root at all. So a per-root gap on a first-party root — the measured
10
+ * case was a project's HUD (`dom`) root whose inspector was dead — surfaced
11
+ * only as a one-off session error, never as a standing row, and closing it
12
+ * depended on somebody remembering it existed.
13
+ *
14
+ * The generator does not care which lane produced a root. It asks each mounted
15
+ * root's own `AuthoringAdapter` which providers it exposes
16
+ * (`measureAuthoringProviders`, whose vocabulary the compiler pins to the
17
+ * contract), diffs that against the full contract minus what the root's SURFACE
18
+ * kind cannot have, and every delta is a standing row. Nothing here consults a
19
+ * game's id, its route, or its manifest.
20
+ *
21
+ * ## Where the rows go
22
+ *
23
+ * Two doors, one derivation — the same shape `ingest/mount-coverage.ts` already
24
+ * uses:
25
+ *
26
+ * - `vgai status`, through {@link rootCoverageFacet}, so an agent reads the
27
+ * same answer without opening the editor;
28
+ * - the editor console, through `coverage/session-coverage.ts`, which unions
29
+ * this family with the game- and project-scoped ones so the warning's
30
+ * headline counts every seam rather than this family's 21. The console
31
+ * ledger turns that into a standing unresolved condition, loud on every
32
+ * `vgai` command until it is closed.
33
+ */
34
+
35
+ import { measureAdapter } from '../host/adapter-reach';
36
+ import {
37
+ type MountedRootSubject,
38
+ mountedRootSubjects,
39
+ } from '@volter/editor-core/authoring/mounted-root-subjects';
40
+ import {
41
+ type CapabilityCoverageReport,
42
+ deriveCapabilityCoverage,
43
+ } from '../host/coverage/capability-coverage';
44
+ import type { AdapterSurface } from '@volter/editor-project/adapter/adapter-surface';
45
+
46
+ /** One root's report. `surface` rides along because it is what decides which
47
+ * absences were excused, and a reader must be able to check that. */
48
+ export interface RootCoverageReport {
49
+ readonly worldId: string;
50
+ readonly surface: AdapterSurface | null;
51
+ readonly report: CapabilityCoverageReport;
52
+ }
53
+
54
+ /**
55
+ * The generated report for one root.
56
+ *
57
+ * A root owns only authoring reach. Runtime, system-registry, and project facts
58
+ * are omitted, so the universal derivation produces no rows for those families.
59
+ */
60
+ export function deriveRootCoverage(subject: MountedRootSubject): RootCoverageReport {
61
+ const report = deriveCapabilityCoverage({
62
+ worldId: subject.worldId,
63
+ reach: measureAdapter(subject.adapter, subject.worldId),
64
+ surface: subject.surface,
65
+ reachMechanism: null,
66
+ });
67
+ return {
68
+ worldId: subject.worldId,
69
+ surface: subject.surface,
70
+ report,
71
+ };
72
+ }
73
+
74
+ /** Every mounted root's report, re-derived on read — a root's adapter gains and
75
+ * loses providers during a session (a design session swaps itself in), so a
76
+ * cached answer would start lying. */
77
+ export function rootCoverageFacet(): readonly RootCoverageReport[] {
78
+ return mountedRootSubjects().map(deriveRootCoverage);
79
+ }
@@ -0,0 +1,193 @@
1
+ /**
2
+ * ONE COVERAGE HEADLINE PER SESSION — the union of every derived family.
3
+ *
4
+ * ## The defect this closes
5
+ *
6
+ * Coverage grew a family at a time, and each family kept its own console door:
7
+ * `coverage/root-coverage.ts` printed the `editor.*` rows per mounted root,
8
+ * `coverage/native-system-coverage.ts` printed the `system.*` rows, and each
9
+ * one's headline counted only its own rows. So the loudest sentence the product
10
+ * says about its own completeness read "N of 21 seams are MISSING" — 21 being
11
+ * the `AuthoringAdapter` provider vocabulary plus `editor.capture`, and nothing
12
+ * else. A session could print "0 of 21" while an entire family of native verbs
13
+ * (`coverage/project-verb-coverage.ts`) was absent, because no surface anywhere
14
+ * summed the families.
15
+ *
16
+ * A count that names one family's total "seams" is the clean-answer failure the
17
+ * whole derivation exists to end: it is crisp, always available, correlated
18
+ * with the truth, and wrong in exactly the cases worth investigating. So the
19
+ * families are UNIONED before anything is said, the headline counts the union,
20
+ * and the per-family split rides in the same sentence — a reader sees both the
21
+ * total and which family it is short in, and cannot mistake one for the other.
22
+ *
23
+ * ## What this owns, and what it does not
24
+ *
25
+ * It owns assembly and the console door. Every family still derives itself, in
26
+ * its own file, from its own facts; nothing here decides a verdict. The
27
+ * per-family facets on `vgai status` (`command-listener.ts`) stay separate for
28
+ * the same reason they always were — a machine reader wants the rows keyed by
29
+ * subject, and it is the HUMAN-facing sentence that has to be a union.
30
+ */
31
+
32
+ import { mountedRootSubjects } from '@volter/editor-core/authoring/mounted-root-subjects';
33
+ import {
34
+ type CoveragePart,
35
+ formatCapabilityCoverageBlocks,
36
+ unionCoverageReport,
37
+ } from '../host/coverage/capability-coverage';
38
+ import { editorConsole } from '@volter/editor-core/editor-console';
39
+ import { editorIsPlaying } from '@volter/editor-core/editor-session-mode';
40
+ import { projectAdapterFacet } from '@volter/editor-core/project-adapter';
41
+ import { getCurrentProject } from '@volter/editor-core/project-manager';
42
+ import { authoringSurfaceCoverage } from './live-authoring-surface';
43
+ import { projectVerbCoverage } from './live-project-verbs';
44
+ import { nativeSystemCoverage } from './native-system-coverage';
45
+ import { type RootCoverageReport, rootCoverageFacet } from './root-coverage';
46
+
47
+ /**
48
+ * Every family that has something to say about this session, in report order:
49
+ * the per-root `editor.*` families first (cheapest to reason about), then the
50
+ * game-scoped `system.*`, then the project-scoped `project.*`.
51
+ *
52
+ * A root's part carries its worldId as the label because the same seam
53
+ * legitimately appears once per mounted root; the game- and project-scoped
54
+ * families appear once and carry none.
55
+ */
56
+ export function sessionCoverageParts(
57
+ /** The per-root family, already derived. Grading a root is the expensive
58
+ * half of this whole file (it re-walks the root's tree through the
59
+ * conformance probe), and `reportSessionCoverage` needs the same rows for
60
+ * its mount-in-progress guard — deriving them twice per five-second sample
61
+ * was pure duplication, measured at ~175ms a copy on a 1822-node canvas
62
+ * world. */
63
+ roots: readonly RootCoverageReport[] = rootCoverageFacet(),
64
+ ): readonly CoveragePart[] {
65
+ const parts: CoveragePart[] = roots.map((entry) => ({
66
+ label: entry.worldId,
67
+ report: entry.report,
68
+ }));
69
+ const systems = nativeSystemCoverage();
70
+ if (systems) parts.push({ label: null, report: systems });
71
+ const project = projectVerbCoverage();
72
+ if (project) parts.push({ label: null, report: project });
73
+ const authoring = authoringSurfaceCoverage();
74
+ if (authoring) parts.push({ label: null, report: authoring });
75
+ return parts;
76
+ }
77
+
78
+ /** The session's whole coverage answer as ONE report, or `null` when no family
79
+ * had anything to measure (nothing mounted, no project open). */
80
+ export function sessionCoverageReport(
81
+ roots?: readonly RootCoverageReport[],
82
+ ): ReturnType<typeof unionCoverageReport> | null {
83
+ const parts = sessionCoverageParts(roots ?? rootCoverageFacet());
84
+ if (parts.length === 0) return null;
85
+ return unionCoverageReport(getCurrentProject()?.config.name ?? 'session', parts);
86
+ }
87
+
88
+ /**
89
+ * Say it out loud, once per distinct gap set.
90
+ *
91
+ * Keyed on the rendered TEXT rather than a mount or project token, because the
92
+ * union's inputs come and go inside one session (a root mounts, a design
93
+ * session attaches, `vgai add` lands a script) and the honest rule is "say it
94
+ * when the answer changes". A recurrence after a real change is a new condition
95
+ * and gets said again; the server ledger sums repeats of an unchanged one.
96
+ */
97
+ const _said = new Set<string>();
98
+ let _pendingSignature: string | null = null;
99
+ let _pendingSamples = 0;
100
+
101
+ function clearPendingCoverage(): void {
102
+ _pendingSignature = null;
103
+ _pendingSamples = 0;
104
+ }
105
+
106
+ export function reportSessionCoverage(): void {
107
+ // Edit-time source authoring is the subject of the per-root provider rows.
108
+ // Play temporarily swaps those adapters for runtime/live projections with a
109
+ // deliberately smaller vocabulary. Recording that temporary projection in
110
+ // the unresolved ledger makes a successful Play look like a standing Edit
111
+ // defect after Play has ended, so the report waits for Edit's adapters.
112
+ if (editorIsPlaying()) {
113
+ clearPendingCoverage();
114
+ return;
115
+ }
116
+ // ONE grading pass per sample. Every guard below and the report itself read
117
+ // these same rows.
118
+ const roots = rootCoverageFacet();
119
+ const report = sessionCoverageReport(roots);
120
+ if (!report || report.summary.gaps === 0) {
121
+ clearPendingCoverage();
122
+ return;
123
+ }
124
+ // Say nothing while nothing is MOUNTED. The families each stand down for
125
+ // states they cannot measure, but the project family legitimately has
126
+ // manifest-fact rows pre-mount — and a pre-mount headline is still a
127
+ // transient the ledger would hold forever (measured: a boot-time "N of N
128
+ // seams MISSING" snapshot stood beside the real post-mount report as a
129
+ // second unresolved warning). The mount is the moment the session becomes
130
+ // the thing coverage describes; until then, silence is the honest report.
131
+ //
132
+ // "Mounted" is what `mountedRootSubjects()` means by it, and a root the
133
+ // editor has merely DISCLOSED does not count — see that function's
134
+ // `isBoundaryDisclosure`. A declared world wears the boundary disclosure
135
+ // adapter for the whole of its mount's assembly, so a session mid-assembly
136
+ // has subjects that are not yet the thing coverage describes. The guard lives
137
+ // HERE, in the one report path, precisely so no caller's timing can plant a
138
+ // transient: the vitals sampler is periodic and lands wherever it lands.
139
+ const mounted = mountedRootSubjects();
140
+ if (mounted.length === 0) {
141
+ clearPendingCoverage();
142
+ return;
143
+ }
144
+ // A multi-root project assembles its composite incrementally. The first live
145
+ // child is not yet the declared authoring surface, and the ledger cannot
146
+ // retract the partial-root warning after the remaining children attach.
147
+ // Wait for every shipped region by source-owned id; a single-root/bare
148
+ // adapter keeps its historical `root` identity and is already atomic.
149
+ const declared = projectAdapterFacet()?.regions ?? [];
150
+ if (declared.length > 1) {
151
+ const mountedIds = new Set(mounted.map((subject) => subject.worldId));
152
+ if (declared.some((region) => !mountedIds.has(region.id))) {
153
+ clearPendingCoverage();
154
+ return;
155
+ }
156
+ }
157
+ // A root whose hierarchy has not completed one valid operation is not yet a
158
+ // stable authoring subject. Provider gaps observed before that point are an
159
+ // assembly snapshot: the adapter object exists, but the tree every provider
160
+ // addresses does not. Do not make that snapshot permanent in the server
161
+ // ledger. The live status facet and Doctor's final coverage phase still
162
+ // report a hierarchy that genuinely never becomes valid; this guard only
163
+ // keeps the periodic console reporter from treating "mount in progress" as
164
+ // a completed session.
165
+ if (
166
+ roots.some(
167
+ (root) => root.report.rows.find((row) => row.seam === 'editor.capture')?.status !== 'ok',
168
+ )
169
+ ) {
170
+ clearPendingCoverage();
171
+ return;
172
+ }
173
+ const head = `session coverage "${report.summary.worldId}"`;
174
+ const warnings = formatCapabilityCoverageBlocks(report, head).filter(
175
+ (block) => block.level === 'warn',
176
+ );
177
+ const signature = warnings.map((block) => block.message).join('\n---\n');
178
+ if (_pendingSignature === signature) _pendingSamples++;
179
+ else {
180
+ _pendingSignature = signature;
181
+ _pendingSamples = 1;
182
+ }
183
+ // HMR and cold-remount replace an adapter between two snapshots. A single
184
+ // conformance failure during that handoff is not a standing condition; the
185
+ // next five-second sample must reproduce the exact gap set before it enters
186
+ // the unresolved ledger. Genuine gaps remain loud one sample later.
187
+ if (_pendingSamples < 2) return;
188
+ for (const block of warnings) {
189
+ if (_said.has(block.message)) continue;
190
+ _said.add(block.message);
191
+ editorConsole.warn(block.message, 'coverage');
192
+ }
193
+ }
@@ -0,0 +1,100 @@
1
+ import { ensureCoreUtilitiesRegistered } from '@volter/editor-core/components/core-utilities';
2
+ import { ProjectHeader } from '@volter/editor-core/components/ProjectHeader';
3
+ import { ensureCoreStatusContributionsRegistered } from '@volter/editor-core/components/status-contributions';
4
+ import {
5
+ installStoryWorkspaceUtilityController,
6
+ StoryEditorRuntime,
7
+ } from '../host/design-system-stories/fixtures/editor-runtime';
8
+ import { DesignSystemPage, StorySection } from '../host/design-system-stories/StoryLayout';
9
+ import { useEditorStore } from '@volter/editor-core/editor-runtime';
10
+ import { getCurrentProject, setActiveProject } from '@volter/editor-core/project-manager';
11
+ import type { Meta, StoryObj } from '@storybook/react';
12
+ import { useLayoutEffect, useState } from 'react';
13
+ // The transport is `@volter/editor-game`'s; this gallery story shows its view over
14
+ // the design system (a story, not the shell, so no host closure pin counts it).
15
+ import { PlayBarView } from '../play-bar/PlayBar';
16
+
17
+ const meta = {
18
+ title: 'Design System/Application Chrome/Production Shell',
19
+ parameters: { controls: { disable: true } },
20
+ } satisfies Meta;
21
+
22
+ export default meta;
23
+ type Story = StoryObj<typeof meta>;
24
+
25
+ function ProductionApplicationChrome() {
26
+ const store = useEditorStore();
27
+ const [, ready] = useState(0);
28
+ const [playState, setPlayState] = useState<'stopped' | 'playing' | 'paused'>('stopped');
29
+ const updatePlayState = (next: 'stopped' | 'playing' | 'paused') => {
30
+ store.setPlayState(next);
31
+ setPlayState(next);
32
+ };
33
+ useLayoutEffect(() => {
34
+ const previousProject = getCurrentProject();
35
+ setActiveProject({
36
+ rootPath: '/projects/orbit-workshop',
37
+ config: {
38
+ manifestVersion: 2,
39
+ name: 'Orbit Workshop',
40
+ version: '0.8.0',
41
+ engine: { version: '0.24.0' },
42
+ hasThreeRoot: true,
43
+ // A three root has no scene-file document — its TSX/R3F source IS the
44
+ // document — so `openProject` derives `null` here for every
45
+ // three-root project. Mirror that instead of inventing a scene path.
46
+ defaultScene: null,
47
+ },
48
+ });
49
+ ensureCoreUtilitiesRegistered();
50
+ ensureCoreStatusContributionsRegistered();
51
+ const uninstallWorkspaceController = installStoryWorkspaceUtilityController();
52
+ ready((value) => value + 1);
53
+ return () => {
54
+ uninstallWorkspaceController();
55
+ setActiveProject(previousProject);
56
+ };
57
+ }, []);
58
+
59
+ return (
60
+ <DesignSystemPage
61
+ eyebrow="Production application shell"
62
+ title="Global commands and passive status stay global"
63
+ summary="This story renders the same connected project header, runtime telemetry, application menus, transport, status registry, and coding-conversation tray as the editor. Document, panel, and viewport-local chrome remain with their owning production surfaces."
64
+ testId="application-chrome-production"
65
+ >
66
+ <StorySection title="Global command header">
67
+ <div className="ds-production-chrome-stage">
68
+ <ProjectHeader
69
+ transport={
70
+ <PlayBarView
71
+ state={playState}
72
+ playEditRegime={playState === 'stopped' ? null : 'ephemeral'}
73
+ onPlay={() => updatePlayState(playState === 'stopped' ? 'playing' : 'stopped')}
74
+ onPause={() => updatePlayState(playState === 'paused' ? 'playing' : 'paused')}
75
+ onStep={() => undefined}
76
+ onRestart={() => updatePlayState('playing')}
77
+ onStop={() => updatePlayState('stopped')}
78
+ />
79
+ }
80
+ />
81
+ </div>
82
+ </StorySection>
83
+ </DesignSystemPage>
84
+ );
85
+ }
86
+
87
+ function chromeStory(style: 'classic' | 'glass', backdrop: 'dark' | 'light'): Story {
88
+ return {
89
+ globals: { material: style, backdrop },
90
+ render: () => (
91
+ <StoryEditorRuntime>
92
+ <ProductionApplicationChrome />
93
+ </StoryEditorRuntime>
94
+ ),
95
+ };
96
+ }
97
+
98
+ export const Classic: Story = chromeStory('classic', 'dark');
99
+ export const GlassDark: Story = chromeStory('glass', 'dark');
100
+ export const GlassLight: Story = chromeStory('glass', 'light');