@volter/editor-game 0.5.68 → 0.5.70

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 (169) hide show
  1. package/NOTICE +7 -7
  2. package/contributions/autoplay.service.ts +1 -1
  3. package/contributions/build-profiles.document.tsx +1 -1
  4. package/contributions/build-progress.status.tsx +2 -2
  5. package/contributions/build.header.tsx +1 -1
  6. package/contributions/connection.status.tsx +1 -1
  7. package/contributions/coverage.service.ts +2 -2
  8. package/contributions/game-eval.command.ts +6 -6
  9. package/contributions/gameplay.command.ts +2 -2
  10. package/contributions/generations.status.tsx +1 -1
  11. package/contributions/ingest.service.ts +2 -2
  12. package/contributions/play.command.ts +6 -6
  13. package/contributions/react/react-inspector.service.ts +2 -2
  14. package/package.json +8 -8
  15. package/serving/index.ts +1 -1
  16. package/src/asset-budget/AssetBudgetPanel.tsx +1 -1
  17. package/src/asset-budget/asset-budget-model.ts +14 -14
  18. package/src/asset-budget/optimize-apply.ts +8 -8
  19. package/src/bridge/call.ts +3 -3
  20. package/src/bridge/dispatch.ts +12 -12
  21. package/src/bridge/screenshot.ts +6 -6
  22. package/src/build/BuildProfilesPanel.tsx +8 -8
  23. package/src/canvas/canvas-board/CanvasBoardDocument.tsx +2 -2
  24. package/src/canvas/canvas-board/canvas-component-board.ts +1 -1
  25. package/src/canvas/canvas-design-mount.ts +1 -1
  26. package/src/coverage/live-project-verbs.ts +3 -3
  27. package/src/coverage/native-system-coverage.ts +3 -3
  28. package/src/coverage/root-coverage.ts +2 -2
  29. package/src/coverage/session-coverage.ts +2 -2
  30. package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +2 -2
  31. package/src/game-document/DevicePresetPicker.tsx +6 -6
  32. package/src/game-document/GameCaptureFrameButton.tsx +1 -1
  33. package/src/game-document/GameDocument.tsx +2 -2
  34. package/src/game-document/GamePanel.tsx +9 -9
  35. package/src/game-document/InstanceInspectorPicker.tsx +1 -1
  36. package/src/game-document/device-preview.ts +4 -4
  37. package/src/game-document/physics-debug.ts +2 -2
  38. package/src/generation/GenerationActivity.tsx +22 -22
  39. package/src/generation/GenerationGallery.css +79 -79
  40. package/src/generation/generation-documents.tsx +25 -25
  41. package/src/generation/generation-presentation.ts +1 -1
  42. package/src/host/adapter-reach.ts +1 -1
  43. package/src/host/adapter-runtime-bindings.ts +5 -5
  44. package/src/host/after-paint.ts +3 -3
  45. package/src/host/api/configurations.ts +1 -1
  46. package/src/host/authoring/canvas-runtime-recognition.ts +2 -2
  47. package/src/host/authoring/contract-hierarchy-authoring.ts +6 -6
  48. package/src/host/authoring/contract-scenes-stories.ts +5 -5
  49. package/src/host/authoring/ingest-data-writer.ts +1 -1
  50. package/src/host/authoring/ingest-source-persistence.ts +2 -2
  51. package/src/host/authoring/mount-isolated-pixi-screen.ts +1 -1
  52. package/src/host/authoring/pixi-authoring-adapter.ts +60 -4
  53. package/src/host/authoring/pixi-creatable-kinds.ts +18 -0
  54. package/src/host/authoring/pixi-live-write-target.ts +6 -5
  55. package/src/host/authoring/pixi-source-write-target.ts +5 -2
  56. package/src/host/authoring/pixi-structure-history.ts +3 -3
  57. package/src/host/binding-resolver.ts +6 -6
  58. package/src/host/browser-transpile.ts +11 -11
  59. package/src/host/canvas-preview-frames.ts +1 -1
  60. package/src/host/components/CameraAuthoringOverlay.tsx +14 -14
  61. package/src/host/components/HeaderTelemetry.tsx +11 -11
  62. package/src/host/components/PixiIsolationSceneContent.tsx +2 -2
  63. package/src/host/components/ResolutionPicker.tsx +4 -4
  64. package/src/host/components/scene-document.tsx +3 -3
  65. package/src/host/components/world-root-stage-binding.tsx +1 -1
  66. package/src/host/components/world-root-stage.ts +1 -1
  67. package/src/host/coverage/authoring-read-probe.ts +1 -1
  68. package/src/host/coverage/capability-coverage.ts +22 -22
  69. package/src/host/coverage/game-contract-seam-evidence.ts +8 -8
  70. package/src/host/coverage/project-verb-coverage.ts +1 -1
  71. package/src/host/coverage/system-adapter-coverage.ts +19 -6
  72. package/src/host/game-location-guard.ts +4 -4
  73. package/src/host/game-module-access.ts +6 -6
  74. package/src/host/game-realm-page.ts +3 -3
  75. package/src/host/game-realm-reclaim.ts +1 -1
  76. package/src/host/gameplay-recording.ts +5 -5
  77. package/src/host/gated-globals.ts +13 -13
  78. package/src/host/ingest/registry.ts +14 -14
  79. package/src/host/play-control-hook.ts +1 -1
  80. package/src/host/playwright-shim.ts +3 -3
  81. package/src/host/projection/pixi.ts +2 -2
  82. package/src/host/react-mount-runtime.ts +1 -1
  83. package/src/host/roots/canvas-root.tsx +2 -2
  84. package/src/host/roots/r3f-root.tsx +1 -1
  85. package/src/host/scene-view-drawability.ts +1 -1
  86. package/src/host/sdk/tools.ts +1 -1
  87. package/src/host/staged-projects.ts +1 -1
  88. package/src/host/stories/story-pixi-preview.ts +1 -1
  89. package/src/host/stories/story-three-preview.ts +1 -1
  90. package/src/host/three-ingest-runtime.ts +1 -1
  91. package/src/ingest/active-ingest.ts +1 -1
  92. package/src/ingest/authoring/ingest-dom-surface-authoring.ts +4 -4
  93. package/src/ingest/authoring/ingest-root-adapter.ts +11 -11
  94. package/src/ingest/capture-wait-report.ts +4 -4
  95. package/src/ingest/discovery-public-ingest.ts +4 -4
  96. package/src/ingest/dom-stub-mark.ts +1 -1
  97. package/src/ingest/entry-load.ts +1 -1
  98. package/src/ingest/game-contract-realm.ts +3 -3
  99. package/src/ingest/game-pointer-lock.ts +1 -1
  100. package/src/ingest/ingest-canvas-scene-document.tsx +2 -2
  101. package/src/ingest/ingest-evidence-hook.ts +6 -6
  102. package/src/ingest/ingest-frame-snapshot.ts +2 -2
  103. package/src/ingest/ingest-play-commands.ts +1 -1
  104. package/src/ingest/ingest-play-control.ts +11 -11
  105. package/src/ingest/ingest-render-debug.ts +5 -5
  106. package/src/ingest/ingest-siblings.ts +3 -3
  107. package/src/ingest/module-mode.ts +2 -2
  108. package/src/ingest/mount-canvas-ingest-root.ts +10 -10
  109. package/src/ingest/mount-coverage.ts +3 -3
  110. package/src/ingest/mount-dom-ingest-root.ts +7 -7
  111. package/src/ingest/mount-ingest-root.ts +11 -11
  112. package/src/ingest/mount-three-ingest-root.ts +5 -5
  113. package/src/ingest/resolve-three.ts +2 -2
  114. package/src/ingest/served-bundle.ts +6 -6
  115. package/src/ingest/served-html-boot.ts +8 -8
  116. package/src/ingest/surface-dom.ts +9 -9
  117. package/src/ingest/surface-three.ts +1 -1
  118. package/src/ingest/types.ts +1 -1
  119. package/src/ingest/unmount-ingest-root.ts +3 -3
  120. package/src/network/NetworkInspectorPanel.tsx +2 -2
  121. package/src/play/play-boot-stall.ts +1 -1
  122. package/src/play/play-mode.ts +31 -30
  123. package/src/play/play-recording.ts +12 -12
  124. package/src/play-bar/PlayBar.tsx +8 -8
  125. package/src/play-bar/PlayerCountPicker.tsx +3 -3
  126. package/src/profiler/FrameDebuggerPanel.tsx +2 -2
  127. package/src/profiler/PerformancePanel.tsx +4 -4
  128. package/src/react/design-time-react-mount.ts +5 -5
  129. package/src/react/dom-authoring-adapter.ts +3 -3
  130. package/src/react/react-inspector-section.tsx +2 -2
  131. package/src/react/react-world-authoring-adapter.ts +20 -20
  132. package/src/react/story-documents/story-documents.tsx +4 -4
  133. package/src/react/ui-component-board.ts +1 -1
  134. package/src/runtime/adapter/audio-meter.ts +1 -1
  135. package/src/runtime/adapter/ingest/contract-debug-adapter.ts +4 -4
  136. package/src/runtime/adapter/ingest/contract-system-adapters.ts +9 -9
  137. package/src/runtime/adapter/ingest/merge-debug-adapters.ts +2 -2
  138. package/src/runtime/adapter/ingest/observation-debug-adapter.ts +1 -1
  139. package/src/runtime/adapter/native-debug-module.ts +5 -5
  140. package/src/runtime/audio/pose-guard.ts +1 -1
  141. package/src/runtime/core/game-scoped-slot.ts +1 -1
  142. package/src/runtime/create-runtime.ts +15 -15
  143. package/src/runtime/debug-bridge.ts +25 -25
  144. package/src/runtime/debug-registry.ts +17 -17
  145. package/src/runtime/dev/instruments.ts +1 -1
  146. package/src/runtime/dev/performance-profiler.ts +2 -2
  147. package/src/runtime/dev/register-render-vitals.ts +2 -2
  148. package/src/runtime/dev/static-batch-advisor.ts +3 -3
  149. package/src/runtime/dev-build.ts +3 -3
  150. package/src/runtime/game.ts +5 -5
  151. package/src/runtime/input-router.ts +1 -1
  152. package/src/runtime/mount-manifest.ts +10 -10
  153. package/src/runtime/pixi/authoring.ts +1 -1
  154. package/src/runtime/pixi/ingest.ts +1 -1
  155. package/src/runtime/presentation.ts +1 -1
  156. package/src/runtime/render-control.ts +21 -21
  157. package/src/runtime/render-seed.ts +3 -3
  158. package/src/runtime/run-ticks-settled.ts +1 -1
  159. package/src/services/game-audio.ts +3 -3
  160. package/src/services/game-network.ts +4 -4
  161. package/src/three/authoring/model-asset-inspector-section.css +15 -15
  162. package/src/three/authoring/model-asset-inspector-section.tsx +7 -7
  163. package/src/three/authoring/r3f-design-session.ts +10 -10
  164. package/src/three/authoring/r3f-source-authoring-adapter.ts +5 -5
  165. package/src/three/authoring/three-authoring-adapter.ts +5 -4
  166. package/src/three/authoring/typed-three-inspector.ts +1 -1
  167. package/src/three/story-documents/three-story-documents.tsx +3 -3
  168. package/src/three/three-board/board-scene.ts +9 -9
  169. package/src/three/three-board/three-component-board.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * THE BUILD PROFILES PANEL — the configuration surface the `build-profiles`
3
3
  * document draws: the project's build-role configurations as a target list,
4
- * the name/resolution/app-id fields it writes back into `vgai.project.json`
4
+ * the name/resolution/app-id fields it writes back into `volter.project.json`
5
5
  * through the project's file history, the Build trigger, and the finished
6
6
  * build's report. The LOG is not here: it streams into the Build Output tab
7
7
  * (the native Output panel’s Build channel), which is the whole point of the split — a
@@ -49,7 +49,7 @@ interface ProjectConfig {
49
49
  appId: string;
50
50
  }
51
51
 
52
- const MANIFEST_PATH = 'vgai.project.json';
52
+ const MANIFEST_PATH = 'volter.project.json';
53
53
 
54
54
  const DEFAULT_CONFIG: ProjectConfig = {
55
55
  name: 'My Game',
@@ -216,7 +216,7 @@ export function BuildProfilesPanel() {
216
216
  <div style={fieldRowStyle}>
217
217
  <label style={labelStyle}>Name</label>
218
218
  <TextInput
219
- className="vgai-input"
219
+ className="volter-input"
220
220
  style={{ flex: 1 }}
221
221
  value={config.name}
222
222
  onChange={(e) => updateConfig({ name: e.target.value })}
@@ -228,7 +228,7 @@ export function BuildProfilesPanel() {
228
228
  <div style={{ display: 'flex', alignItems: 'center', gap: spaceVar[2], flex: 1 }}>
229
229
  <TextInput
230
230
  type="number"
231
- className="vgai-input"
231
+ className="volter-input"
232
232
  style={{ width: 0, flex: 1 }}
233
233
  value={config.resolution.width}
234
234
  onChange={(e) => {
@@ -239,7 +239,7 @@ export function BuildProfilesPanel() {
239
239
  <span style={{ fontSize: fontSizeVar.sm, color: text[3] }}>&times;</span>
240
240
  <TextInput
241
241
  type="number"
242
- className="vgai-input"
242
+ className="volter-input"
243
243
  style={{ width: 0, flex: 1 }}
244
244
  value={config.resolution.height}
245
245
  onChange={(e) => {
@@ -253,7 +253,7 @@ export function BuildProfilesPanel() {
253
253
  <div style={fieldRowStyle}>
254
254
  <label style={labelStyle}>App ID</label>
255
255
  <TextInput
256
- className="vgai-input"
256
+ className="volter-input"
257
257
  style={{ flex: 1 }}
258
258
  value={config.appId}
259
259
  onChange={(e) => updateConfig({ appId: e.target.value })}
@@ -309,7 +309,7 @@ export function BuildProfilesPanel() {
309
309
  <a
310
310
  href={getDownloadUrl(artifact)}
311
311
  download={artifact}
312
- className="vgai-btn"
312
+ className="volter-btn"
313
313
  data-variant="secondary"
314
314
  data-size="default"
315
315
  style={{
@@ -394,7 +394,7 @@ function BuildReportSummary({ report }: { report: BuildReport }) {
394
394
  position: 'absolute',
395
395
  inset: 0,
396
396
  width: `${Math.max(2, (file.bytes / largest) * 100)}%`,
397
- background: 'color-mix(in srgb, var(--vgai-accent) 16%, transparent)',
397
+ background: 'color-mix(in srgb, var(--volter-accent) 16%, transparent)',
398
398
  }}
399
399
  />
400
400
  <div
@@ -552,8 +552,8 @@ function CanvasBoardContent({ active }: WorkspaceDocumentContentProps) {
552
552
  return (
553
553
  <div
554
554
  data-testid="canvas-board"
555
- data-vgai-backdrop-color={active ? REACT_DESIGN_CANVAS_COLOR : undefined}
556
- data-vgai-backdrop-policy={active ? 'dark-frost' : undefined}
555
+ data-volter-backdrop-color={active ? REACT_DESIGN_CANVAS_COLOR : undefined}
556
+ data-volter-backdrop-policy={active ? 'dark-frost' : undefined}
557
557
  style={{
558
558
  position: 'absolute',
559
559
  inset: 0,
@@ -51,6 +51,6 @@ export const canvasComponentBoard: ComponentBoard = {
51
51
  `This project has no ${CANVAS_COMPONENTS_TITLE} board (${CANVAS_COMPONENTS_DOCUMENT_ID}): ` +
52
52
  "board presence keys on STORIES, not on roots, and none of this project's stories declares " +
53
53
  'the "canvas" medium. Declare it — a manifest root entry naming the story\'s module, or a ' +
54
- '`vgai.adapter.ts` regionInclude that covers it — and the board appears. `vgai console` ' +
54
+ '`volter.adapter.ts` regionInclude that covers it — and the board appears. `volter-game-editor console` ' +
55
55
  'names every story it could not place.',
56
56
  };
@@ -120,7 +120,7 @@ function createDesignGame(): GameInternal {
120
120
  * which part of the unbounded authored plane is visible. */
121
121
  function createDesignCanvas(): HTMLCanvasElement {
122
122
  const canvas = document.createElement('canvas');
123
- canvas.dataset['vgaiCanvasSceneSurface'] = 'true';
123
+ canvas.dataset['volterCanvasSceneSurface'] = 'true';
124
124
  canvas.style.position = 'absolute';
125
125
  canvas.style.inset = '0';
126
126
  canvas.style.width = '100%';
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * It reads the session's own singletons plus two project files the browser
6
6
  * cannot read for itself, and hands the facts to the pure derivation. The
7
- * report goes out the doors coverage already uses — `vgai status`'s
7
+ * report goes out the doors coverage already uses — `volter-game-editor status`'s
8
8
  * `projectCoverage` facet, and the editor console via
9
9
  * `coverage/session-coverage.ts`, which unions this family with the other two
10
10
  * so one headline counts them all. No new transport, no new panel: the console
@@ -59,7 +59,7 @@ let _filesFor: string | null = null;
59
59
 
60
60
  /**
61
61
  * Drop the cached file facts so the next read re-asks the dev server. Called
62
- * on `vgai restart` (a restart is precisely "my project's files changed —
62
+ * on `volter-game-editor restart` (a restart is precisely "my project's files changed —
63
63
  * re-read them"; the probe-measured failure was the dependency detector
64
64
  * grading rows against a package.json edit two restarts old) and by tests.
65
65
  */
@@ -148,7 +148,7 @@ export function projectVerbFacts(): ProjectVerbFacts | null {
148
148
 
149
149
  /**
150
150
  * The `project.*` report for the open project, re-derived on every read — the
151
- * scripts a project declares change while it is open (`vgai add` writes them),
151
+ * scripts a project declares change while it is open (`volter-game-editor add` writes them),
152
152
  * so a cached answer would start lying.
153
153
  */
154
154
  export function projectVerbCoverage(): CapabilityCoverageReport | null {
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * It reads the session's own singletons and hands the facts to the pure
6
6
  * derivation. The report goes out the two doors coverage already uses —
7
- * `vgai status`'s `systemCoverage` facet, and the editor console via
7
+ * `volter-game-editor status`'s `systemCoverage` facet, and the editor console via
8
8
  * `coverage/session-coverage.ts`, which unions this family with the others so
9
9
  * one headline counts them all — so an unbound slot becomes a STANDING
10
10
  * condition rather than a one-off line. No new transport, no new panel, and no
@@ -129,8 +129,8 @@ export function nativeSystemCoverage(): CapabilityCoverageReport | null {
129
129
  // NetworkingAdapter for a single-player game, telling its author to
130
130
  // register one because "this project declares a `server` block" when it
131
131
  // declares nothing of the sort. A matchmaker is a listener; no port, no
132
- // server. (`vgai edit`'s auto-boot had the identical bug — see
133
- // `packages/vgai-cli/src/colyseus-autoboot.ts`'s `readDeclaredProcess`.)
132
+ // server. (`volter-game-editor edit`'s auto-boot had the identical bug — see
133
+ // `packages/volter-cli/src/colyseus-autoboot.ts`'s `readDeclaredProcess`.)
134
134
  declaresServer: (project.config.configurations ?? []).some(
135
135
  (c) => c.kind === 'process' && typeof (c as { port?: unknown }).port === 'number',
136
136
  ),
@@ -23,13 +23,13 @@
23
23
  * Two doors, one derivation — the same shape `ingest/mount-coverage.ts` already
24
24
  * uses:
25
25
  *
26
- * - `vgai status`, through {@link rootCoverageFacet}, so an agent reads the
26
+ * - `volter-game-editor status`, through {@link rootCoverageFacet}, so an agent reads the
27
27
  * same answer without opening the editor;
28
28
  * - the editor console, through `coverage/session-coverage.ts`, which unions
29
29
  * this family with the game- and project-scoped ones so the warning's
30
30
  * headline counts every seam rather than this family's 21. The console
31
31
  * ledger turns that into a standing unresolved condition, loud on every
32
- * `vgai` command until it is closed.
32
+ * `volter` command until it is closed.
33
33
  */
34
34
 
35
35
  import { measureAdapter } from '../host/adapter-reach';
@@ -24,7 +24,7 @@
24
24
  *
25
25
  * It owns assembly and the console door. Every family still derives itself, in
26
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
27
+ * per-family facets on `volter-game-editor status` (`command-listener.ts`) stay separate for
28
28
  * the same reason they always were — a machine reader wants the rows keyed by
29
29
  * subject, and it is the HUMAN-facing sentence that has to be a union.
30
30
  */
@@ -90,7 +90,7 @@ export function sessionCoverageReport(
90
90
  *
91
91
  * Keyed on the rendered TEXT rather than a mount or project token, because the
92
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
93
+ * session attaches, `volter-game-editor add` lands a script) and the honest rule is "say it
94
94
  * when the answer changes". A recurrence after a real change is a new condition
95
95
  * and gets said again; the server ledger sums repeats of an unchanged one.
96
96
  */
@@ -73,10 +73,10 @@ function RailColumn({ children }: { readonly children: ReactNode }) {
73
73
  width: RAIL_WIDTH,
74
74
  height: 600,
75
75
  display: 'flex',
76
- border: '1px solid var(--vgai-border-2)',
76
+ border: '1px solid var(--volter-border-2)',
77
77
  borderRadius: 8,
78
78
  overflow: 'hidden',
79
- background: 'var(--vgai-bg-1)',
79
+ background: 'var(--volter-bg-1)',
80
80
  }}
81
81
  >
82
82
  {children}
@@ -2,7 +2,7 @@
2
2
  * W2c (F13) — Game-tab device preset dropdown. Chrome-device-mode-style:
3
3
  * picking a preset constrains the game mount to that device's CSS resolution
4
4
  * + DPR (letterboxed/scaled by `GamePanel`), phone/tablet presets add the
5
- * safe-area overlay + `--vgai-safe-area-inset-*` CSS vars and auto-enable
5
+ * safe-area overlay + `--volter-safe-area-inset-*` CSS vars and auto-enable
6
6
  * pointer-as-touch. State lives in `../device-preview.ts`; this component is
7
7
  * pure UI over it.
8
8
  */
@@ -30,18 +30,18 @@ export function DevicePresetPicker({
30
30
  const isFit = active.kind === 'fit';
31
31
 
32
32
  return (
33
- <div className="vgai-playbar-popover-anchor">
33
+ <div className="volter-playbar-popover-anchor">
34
34
  <Button
35
35
  ref={ref}
36
36
  variant="ghost"
37
37
  size="comfortable"
38
38
  aria-haspopup="menu"
39
39
  aria-expanded={open}
40
- aria-controls={open ? 'vgai-device-preset-menu' : undefined}
40
+ aria-controls={open ? 'volter-device-preset-menu' : undefined}
41
41
  data-testid="device-preset-picker"
42
42
  onClick={() => setOpen((value) => !value)}
43
43
  title={
44
- 'Device preview — constrain the game to a device resolution + DPR. Phone/tablet presets show the safe area, set --vgai-safe-area-inset-top/right/bottom/left CSS vars on the game mount, and send mouse input as touch.'
44
+ 'Device preview — constrain the game to a device resolution + DPR. Phone/tablet presets show the safe area, set --volter-safe-area-inset-top/right/bottom/left CSS vars on the game mount, and send mouse input as touch.'
45
45
  }
46
46
  >
47
47
  <EditorIcon icon={faMobileScreenButton} size="md" />
@@ -49,9 +49,9 @@ export function DevicePresetPicker({
49
49
  </Button>
50
50
  {open && (
51
51
  <AnchoredMenu
52
- id="vgai-device-preset-menu"
52
+ id="volter-device-preset-menu"
53
53
  anchorRef={ref}
54
- className="vgai-resolution-menu"
54
+ className="volter-resolution-menu"
55
55
  gap={4}
56
56
  onDismiss={() => setOpen(false)}
57
57
  >
@@ -27,7 +27,7 @@ export function GameCaptureFrameButton() {
27
27
  size="compact"
28
28
  variant="ghost"
29
29
  data-testid="game-capture-frame"
30
- className="vgai-frame-capture-game-button"
30
+ className="volter-frame-capture-game-button"
31
31
  disabled={!available}
32
32
  title={
33
33
  available
@@ -60,7 +60,7 @@ function GameDebugMenu() {
60
60
  data-testid="game-debug-menu"
61
61
  aria-haspopup="menu"
62
62
  aria-expanded={open}
63
- aria-controls={open ? 'vgai-game-debug-menu' : undefined}
63
+ aria-controls={open ? 'volter-game-debug-menu' : undefined}
64
64
  onClick={() => setOpen((value) => !value)}
65
65
  >
66
66
  <span>Debug</span>
@@ -68,7 +68,7 @@ function GameDebugMenu() {
68
68
  </Button>
69
69
  {open && (
70
70
  <AnchoredMenu
71
- id="vgai-game-debug-menu"
71
+ id="volter-game-debug-menu"
72
72
  anchorRef={ref}
73
73
  gap={3}
74
74
  onDismiss={() => setOpen(false)}
@@ -74,7 +74,7 @@ import {
74
74
  * surfaces (stacked canvases + React DOM layers). */
75
75
  export function collectGameSurfaces(container: HTMLElement): Element[] {
76
76
  return Array.from(container.children).filter(
77
- (node) => (node as HTMLElement).dataset?.['vgaiRootSurface'] === 'true',
77
+ (node) => (node as HTMLElement).dataset?.['volterRootSurface'] === 'true',
78
78
  );
79
79
  }
80
80
 
@@ -250,7 +250,7 @@ function InstanceViewport({ index }: { index: number }) {
250
250
  focused={mountedId != null && focused === mountedId}
251
251
  onFocus={mountedId ? () => setFocusedInstance(mountedId) : undefined}
252
252
  >
253
- <div ref={ref} data-vgai-instance-viewport="" style={{ position: 'absolute', inset: 0 }} />
253
+ <div ref={ref} data-volter-instance-viewport="" style={{ position: 'absolute', inset: 0 }} />
254
254
  </InstanceSlot>
255
255
  );
256
256
  }
@@ -355,7 +355,7 @@ export function GamePanel({ style }: { style?: React.CSSProperties }) {
355
355
  // the same call — and switching resolution DURING play would silently drop
356
356
  // the running game's canvases with the removed element. Only nodes the game
357
357
  // HOST mounted are
358
- // stashed (world surfaces carry `data-vgai-root-surface`): the fill/device branches are keyed below so
358
+ // stashed (world surfaces carry `data-volter-root-surface`): the fill/device branches are keyed below so
359
359
  // React really remounts, but if it ever aliases the container DOM node
360
360
  // again, a blind childNodes copy would capture React-owned children too —
361
361
  // that exact aliasing put the incoming inner div in the stash and made
@@ -412,7 +412,7 @@ export function GamePanel({ style }: { style?: React.CSSProperties }) {
412
412
  // which consults `deviceEmulatedPixelRatio()` once the session exists.)
413
413
  // What size this game is PRESENTED at. Two things can name one and the precedence lives in
414
414
  // `resolvePresentedSize`: a device preset the user picked wins, and otherwise the project's own
415
- // declared `resolution` (`vgai.project.json`) puts the game on screen at its authored logical
415
+ // declared `resolution` (`volter.project.json`) puts the game on screen at its authored logical
416
416
  // size, uniformly scaled and letterboxed by the branch below — presentation scaling, never a
417
417
  // stretch mode. A project that declares neither fills the panel exactly as before.
418
418
  const declaredResolution = project?.config.resolution;
@@ -474,16 +474,16 @@ export function GamePanel({ style }: { style?: React.CSSProperties }) {
474
474
 
475
475
  // Safe-area contract: the game MOUNT container always carries the
476
476
  // inset CSS vars (0px unless the active preset declares insets), so game
477
- // UI can style with `var(--vgai-safe-area-inset-top, 0px)` etc. Real
477
+ // UI can style with `var(--volter-safe-area-inset-top, 0px)` etc. Real
478
478
  // `env(safe-area-inset-*)` cannot be injected from a same-document host
479
479
  // (env() is UA-supplied for the top-level viewport only) — the vars + the
480
480
  // visual overlay below ARE the emulation.
481
481
  const safeArea = preset.safeArea;
482
482
  const safeAreaVars = {
483
- '--vgai-safe-area-inset-top': `${safeArea?.top ?? 0}px`,
484
- '--vgai-safe-area-inset-right': `${safeArea?.right ?? 0}px`,
485
- '--vgai-safe-area-inset-bottom': `${safeArea?.bottom ?? 0}px`,
486
- '--vgai-safe-area-inset-left': `${safeArea?.left ?? 0}px`,
483
+ '--volter-safe-area-inset-top': `${safeArea?.top ?? 0}px`,
484
+ '--volter-safe-area-inset-right': `${safeArea?.right ?? 0}px`,
485
+ '--volter-safe-area-inset-bottom': `${safeArea?.bottom ?? 0}px`,
486
+ '--volter-safe-area-inset-left': `${safeArea?.left ?? 0}px`,
487
487
  } as React.CSSProperties;
488
488
 
489
489
  return (
@@ -138,7 +138,7 @@ export function InstanceInspectorPicker() {
138
138
  const warning = (diagnostics?.loop.firedWhileHeld ?? 0) > 0;
139
139
 
140
140
  return (
141
- <div className="vgai-playbar-popover-anchor">
141
+ <div className="volter-playbar-popover-anchor">
142
142
  <Button
143
143
  ref={ref}
144
144
  variant="ghost"
@@ -12,8 +12,8 @@
12
12
  * sets CSS custom properties on the game mount container
13
13
  * (`data-testid="game-runtime-container"`), the element game canvases and
14
14
  * react-world DOM layers mount into:
15
- * --vgai-safe-area-inset-top / -right / -bottom / -left (CSS px)
16
- * Game UI reads them with `var(--vgai-safe-area-inset-top, 0px)`.
15
+ * --volter-safe-area-inset-top / -right / -bottom / -left (CSS px)
16
+ * Game UI reads them with `var(--volter-safe-area-inset-top, 0px)`.
17
17
  * Recorded choice: real `env(safe-area-inset-*)` injection is NOT
18
18
  * possible from a same-document host (env() values come from the UA for
19
19
  * the top-level viewport only), so the overlay + CSS vars ARE the
@@ -41,7 +41,7 @@
41
41
  * event before the clone.
42
42
  *
43
43
  * Persistence: preset + touch override are the PROJECT settings layer's
44
- * `devicePreview` (`settings-store.ts` → `.vgai/settings.json`, committed):
44
+ * `devicePreview` (`settings-store.ts` → `.volter/settings.json`, committed):
45
45
  * the frame a game is designed for is a fact about the project, shared by
46
46
  * everyone who opens it.
47
47
  */
@@ -331,5 +331,5 @@ function _stateForE2E() {
331
331
  }
332
332
 
333
333
  if (typeof window !== 'undefined') {
334
- (window as unknown as Record<string, unknown>)['__vgaiDevicePreview'] = _stateForE2E;
334
+ (window as unknown as Record<string, unknown>)['__volterDevicePreview'] = _stateForE2E;
335
335
  }
@@ -136,7 +136,7 @@ function _updateContactPoints(group: THREE.Group, contacts: Float32Array | null)
136
136
  }
137
137
 
138
138
  /**
139
- * e2e hook (mirrors the world root's stage's `__vgaiViewport`): mechanical state for
139
+ * e2e hook (mirrors the world root's stage's `__volterViewport`): mechanical state for
140
140
  * The question this answers — is the Rapier debug wireframe live in the
141
141
  * game scene with real geometry, and how many contact markers are drawn.
142
142
  */
@@ -167,7 +167,7 @@ function _stateForE2E(): {
167
167
  };
168
168
  }
169
169
  if (typeof window !== 'undefined') {
170
- (window as unknown as Record<string, unknown>)['__vgaiPhysicsDebug'] = _stateForE2E;
170
+ (window as unknown as Record<string, unknown>)['__volterPhysicsDebug'] = _stateForE2E;
171
171
  }
172
172
 
173
173
  function _teardown(): void {
@@ -70,13 +70,13 @@ function OutputPreview({
70
70
 
71
71
  if (src && output.kind === 'image') {
72
72
  const preview = (
73
- <img className="vgai-generation-output-media" src={src} alt={output.name} loading="lazy" />
73
+ <img className="volter-generation-output-media" src={src} alt={output.name} loading="lazy" />
74
74
  );
75
75
  return onOpen ? (
76
76
  // The preview itself opens the asset — the gesture a gallery implies.
77
77
  <Button
78
78
  variant="ghost"
79
- className="vgai-generation-output-open"
79
+ className="volter-generation-output-open"
80
80
  onClick={onOpen}
81
81
  aria-label={`Open ${output.name}`}
82
82
  >
@@ -91,7 +91,7 @@ function OutputPreview({
91
91
  // Deliberately no autoplay and no `muted` autoplay trick: a gallery that
92
92
  // starts sound is the failure this panel is replacing.
93
93
  <video
94
- className="vgai-generation-output-media"
94
+ className="volter-generation-output-media"
95
95
  src={src}
96
96
  controls
97
97
  preload="metadata"
@@ -102,7 +102,7 @@ function OutputPreview({
102
102
  }
103
103
  if (src && output.kind === 'audio') {
104
104
  return (
105
- <div className="vgai-generation-output-audio">
105
+ <div className="volter-generation-output-audio">
106
106
  <AudioAssetThumb url={src} name={output.name} />
107
107
  <audio src={src} controls preload="metadata" title={output.name} />
108
108
  </div>
@@ -112,7 +112,7 @@ function OutputPreview({
112
112
  return <ModelThumbnail url={output.url} />;
113
113
  }
114
114
  return (
115
- <div className="vgai-generation-output-file">
115
+ <div className="volter-generation-output-file">
116
116
  <EditorIcon icon={output.kind === 'model' ? faFile : faFileLines} />
117
117
  <Text variant="caption" tone="muted">
118
118
  {output.name}
@@ -160,7 +160,7 @@ function StateMedia({ job, state }: { job: GenerationJob; state: GenerationCardS
160
160
  const pending = state === 'queued' || state === 'running' || state === 'saving';
161
161
  const failing = state === 'failed' || state === 'save-failed';
162
162
  return (
163
- <div className="vgai-generation-state-media" data-state={state}>
163
+ <div className="volter-generation-state-media" data-state={state}>
164
164
  <StateSurface
165
165
  compact
166
166
  tone={STATE_TONE[state]}
@@ -172,7 +172,7 @@ function StateMedia({ job, state }: { job: GenerationJob; state: GenerationCardS
172
172
  // Determinate ONLY when the provider reported progress; otherwise the
173
173
  // native indeterminate bar, which claims nothing.
174
174
  <progress
175
- className="vgai-generation-progress"
175
+ className="volter-generation-progress"
176
176
  aria-label={`${job.label} progress`}
177
177
  {...(state === 'running' && job.progress !== undefined
178
178
  ? { value: job.progress, max: 1 }
@@ -195,7 +195,7 @@ function CardActions({
195
195
  run: (action: () => Promise<void>) => void;
196
196
  }) {
197
197
  return (
198
- <div className="vgai-generation-card-actions">
198
+ <div className="volter-generation-card-actions">
199
199
  {generationSaveRetryable(job, error) && (
200
200
  // There is NO add-to-project gate: the server accepts a finished
201
201
  // output on its own. This appears only once a save has actually
@@ -250,7 +250,7 @@ function GenerationCard({
250
250
 
251
251
  return (
252
252
  <article
253
- className="vgai-generation-card"
253
+ className="volter-generation-card"
254
254
  data-state={state}
255
255
  aria-busy={generationJobIsActive(job)}
256
256
  aria-label={generationTitle(job)}
@@ -265,31 +265,31 @@ function GenerationCard({
265
265
  }
266
266
  }}
267
267
  >
268
- <div className="vgai-generation-card-media" data-outputs={Math.min(outputs.length, 4)}>
268
+ <div className="volter-generation-card-media" data-outputs={Math.min(outputs.length, 4)}>
269
269
  {outputs.length === 0 ? (
270
270
  <StateMedia job={job} state={state} />
271
271
  ) : (
272
272
  outputs.map((output) => (
273
- <div className="vgai-generation-output" key={output.path} title={output.path}>
273
+ <div className="volter-generation-output" key={output.path} title={output.path}>
274
274
  <OutputPreview output={output} onOpen={openOutput(output)} />
275
275
  </div>
276
276
  ))
277
277
  )}
278
278
  </div>
279
279
 
280
- <div className="vgai-generation-card-body">
281
- <div className="vgai-generation-card-heading">
280
+ <div className="volter-generation-card-body">
281
+ <div className="volter-generation-card-heading">
282
282
  <Text variant="label" truncate title={generationTitle(job)}>
283
283
  {generationTitle(job)}
284
284
  </Text>
285
- <EditorBadge className="vgai-generation-chip" data-state={state}>
285
+ <EditorBadge className="volter-generation-chip" data-state={state}>
286
286
  {GENERATION_STATE_LABEL[state]}
287
287
  {state === 'running' && job.progress !== undefined
288
288
  ? ` · ${Math.round(job.progress * 100)}%`
289
289
  : ''}
290
290
  </EditorBadge>
291
291
  {unread && (
292
- <EditorBadge className="vgai-generation-chip" data-state="new">
292
+ <EditorBadge className="volter-generation-chip" data-state="new">
293
293
  New
294
294
  </EditorBadge>
295
295
  )}
@@ -305,7 +305,7 @@ function GenerationCard({
305
305
  </Text>
306
306
 
307
307
  {prompt && (
308
- <p className="vgai-generation-card-prompt" title={prompt}>
308
+ <p className="volter-generation-card-prompt" title={prompt}>
309
309
  {prompt}
310
310
  </p>
311
311
  )}
@@ -317,7 +317,7 @@ function GenerationCard({
317
317
  // text promises nothing and the retry button carries it instead.
318
318
  <EditorBanner
319
319
  tone={error || state === 'save-failed' ? 'error' : 'warning'}
320
- className="vgai-generation-card-alert"
320
+ className="volter-generation-card-alert"
321
321
  >
322
322
  {error ??
323
323
  (state === 'save-failed'
@@ -363,8 +363,8 @@ export function GenerationActivity() {
363
363
  const storeError = generationJobsError();
364
364
 
365
365
  return (
366
- <div className="vgai-generation-gallery">
367
- <EditorToolbar label="Generations" compact className="vgai-generation-gallery-bar">
366
+ <div className="volter-generation-gallery">
367
+ <EditorToolbar label="Generations" compact className="volter-generation-gallery-bar">
368
368
  <Text variant="label">Generations</Text>
369
369
  <Text variant="caption" tone="muted">
370
370
  {jobs.length} {jobs.length === 1 ? 'generation' : 'generations'}
@@ -385,14 +385,14 @@ export function GenerationActivity() {
385
385
  </EditorToolbar>
386
386
 
387
387
  {storeError && (
388
- <EditorBanner tone="error" className="vgai-generation-gallery-alert">
388
+ <EditorBanner tone="error" className="volter-generation-gallery-alert">
389
389
  {storeError}
390
390
  </EditorBanner>
391
391
  )}
392
392
 
393
393
  {jobs.length === 0 ? (
394
394
  <StateSurface
395
- className="vgai-generation-gallery-empty"
395
+ className="volter-generation-gallery-empty"
396
396
  title="No generated assets yet"
397
397
  description="Preview generated images, video, audio and models here. Create an asset to get started."
398
398
  action={
@@ -402,7 +402,7 @@ export function GenerationActivity() {
402
402
  }
403
403
  />
404
404
  ) : (
405
- <section className="vgai-generation-grid" aria-label="Generated assets">
405
+ <section className="volter-generation-grid" aria-label="Generated assets">
406
406
  {jobs.map((job) => (
407
407
  <GenerationCard
408
408
  key={job.id}