@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
@@ -31,8 +31,8 @@ import type { Game } from './game';
31
31
 
32
32
  /**
33
33
  * The minimal structural shape `ctx.debug.attachRoom` needs from a joined
34
- * Colyseus room: just enough to send the reserved `__vgai:debugCommand`
35
- * message and listen for its `__vgai:debugCommandResult` reply. Structural,
34
+ * Colyseus room: just enough to send the reserved `__volter:debugCommand`
35
+ * message and listen for its `__volter:debugCommandResult` reply. Structural,
36
36
  * not a Colyseus type import — the same seam-boundary style every other
37
37
  * `DebugCtxSurface` member uses (no wrapper around Colyseus itself, D2).
38
38
  * `onMessage`'s return type is `unknown` because Colyseus's own return shape
@@ -99,15 +99,15 @@ export interface DebugCtxSurface {
99
99
  /**
100
100
  * Task 2.2 — server-locus command routing (client leg). Call once your
101
101
  * game code has joined its Colyseus room, so `locus: 'server'` commands
102
- * have somewhere to send `__vgai:debugCommand`. Returns a detach function
102
+ * have somewhere to send `__volter:debugCommand`. Returns a detach function
103
103
  * (call on room leave/dispose) — game-scoped, last-attached room wins.
104
104
  */
105
105
  attachRoom(room: DebugRoomHandle): () => void;
106
106
  }
107
107
 
108
108
  /** Engine-local error for the debug seam — mirrors the `code` + `data` shape
109
- * `packages/vgai-sdk/src/errors.ts` uses (no import: the engine does not
110
- * depend on `@vgai/sdk`). `code` is always machine-readable; nothing reading
109
+ * `packages/volter-sdk/src/errors.ts` uses (no import: the engine does not
110
+ * depend on the SDK). `code` is always machine-readable; nothing reading
111
111
  * this error may key off `message` prose. */
112
112
  export class DebugError extends Error {
113
113
  readonly code: string;
@@ -129,7 +129,7 @@ const REGISTRATION_HINT =
129
129
  * (`POST /__editor/command`) and `page.evaluate` both serialize the error's
130
130
  * `data` bag — and an `Error` stringifies to `{}` there, so a command's own
131
131
  * refusal text ("no such waypoint") vanished and the developer at
132
- * `vgai eval` saw only `debug: command "x" threw`. The text has to travel as
132
+ * `volter-game-editor eval` saw only `debug: command "x" threw`. The text has to travel as
133
133
  * plain strings, and in the `message` above all: that is the one field every
134
134
  * client (`SessionError`, the CLI's own error print) actually surfaces. */
135
135
  function describeCause(cause: unknown): {
@@ -145,12 +145,12 @@ function describeCause(cause: unknown): {
145
145
  }
146
146
 
147
147
  /** Task 2.2 — how long `invoke()` waits for a `locus: 'server'` command's
148
- * `__vgai:debugCommandResult` reply before failing loudly. */
148
+ * `__volter:debugCommandResult` reply before failing loudly. */
149
149
  const SERVER_COMMAND_TIMEOUT_MS = 10_000;
150
150
 
151
151
  /** The virtual-input surface the debug bridge (`runtime/debug-bridge.ts`)
152
152
  * actuates through: a root's input door — its entry's `debug.input`
153
- * (`adapter/native-debug-module.ts`) or a `vgai.adapter.ts` input binding
153
+ * (`adapter/native-debug-module.ts`) or a `volter.adapter.ts` input binding
154
154
  * (`host/adapter-runtime-bindings.ts`), wired once per root when its bindings
155
155
  * install, at the same spot as `setInputActionsSource` — absent until then. */
156
156
  export interface DebugVirtualInputTarget {
@@ -200,7 +200,7 @@ export interface InputTraceSnapshot {
200
200
  * (`runtime/game.ts`, D15/T-D15.3-.4) for full semantics. Named here (not
201
201
  * re-declared per-caller) so the bridge (`runtime/debug-bridge.ts`), the
202
202
  * editor relay (`command-listener.ts`'s `run-ticks` case), and
203
- * `play.runTicks` (`@vgai/sdk`) all reference the SAME type. */
203
+ * `play.runTicks` (the SDK) all reference the SAME type. */
204
204
  export interface RunTicksOptions {
205
205
  /** `'last'` (default) — skip `preRender`/`render` for every tick except
206
206
  * the final one. `'all'` — render every tick. `'none'` — never render,
@@ -295,7 +295,7 @@ export interface DebugRegistry {
295
295
  * Every world's target is kept, keyed by `worldId`, and
296
296
  * {@link getVirtualInputTarget} resolves ONE of them via
297
297
  * {@link resolveInputRootId} — the SAME resolution the debug bridge
298
- * (`window.__vgai.input.*`) and the editor relay both call through, so they
298
+ * (`window.__volter.input.*`) and the editor relay both call through, so they
299
299
  * can never disagree about which root an unaddressed actuation reaches. An
300
300
  * explicit `worldId` reaches that world specifically. */
301
301
  setVirtualInputTarget(worldId: string, target: DebugVirtualInputTarget): void;
@@ -318,7 +318,7 @@ export interface DebugRegistry {
318
318
  * actuation target — called ONCE by `createGame`, immediately (unlike
319
319
  * {@link setVirtualInputTarget}, which waits for a per-world mount, a
320
320
  * `Game`'s own `runTicks` exists the instant the Game shell does). The
321
- * SAME target backs `runtime/debug-bridge.ts`'s `window.__vgai.runTicks`
321
+ * SAME target backs `runtime/debug-bridge.ts`'s `window.__volter.runTicks`
322
322
  * (door a) and the editor relay's `run-ticks` case → `play.runTicks`
323
323
  * (door b) — one implementation, byte-identical semantics across doors
324
324
  * (D17).
@@ -605,8 +605,8 @@ export function createDebugRegistry(opts: {
605
605
  /**
606
606
  * Task 2.2 — server-locus command routing (client leg). A `locus: 'server'`
607
607
  * command never calls its own registered `fn` locally: `invoke()` instead
608
- * sends the reserved room message `__vgai:debugCommand` and resolves on the
609
- * matching `__vgai:debugCommandResult` reply, so a fixture mutates the
608
+ * sends the reserved room message `__volter:debugCommand` and resolves on the
609
+ * matching `__volter:debugCommandResult` reply, so a fixture mutates the
610
610
  * AUTHORITATIVE (server) copy of state, not client prediction. Request ids
611
611
  * are a monotonic per-registry counter (`dbg-<n>`), not `Math.random`/
612
612
  * `Date.now`, so two in-flight commands never collide and correlation is
@@ -635,14 +635,14 @@ export function createDebugRegistry(opts: {
635
635
  );
636
636
  }, SERVER_COMMAND_TIMEOUT_MS);
637
637
  pendingServerCommands.set(requestId, { resolve, reject, timer });
638
- room.send('__vgai:debugCommand', { name, args, requestId });
638
+ room.send('__volter:debugCommand', { name, args, requestId });
639
639
  });
640
640
  }
641
641
 
642
642
  // Defect 8 fix — the live detach() for whatever room is CURRENTLY attached
643
643
  // (or null if none). `attachRoom` calls this itself before attaching a new
644
644
  // room: without it, a second `attachRoom` call (no explicit `detach()` in
645
- // between) left the first room's `__vgai:debugCommandResult` subscription
645
+ // between) left the first room's `__volter:debugCommandResult` subscription
646
646
  // live forever (a leak — the old room keeps getting messages dispatched to
647
647
  // a handler nothing reads anymore) and stranded any of ITS in-flight
648
648
  // commands riding the full 10s timeout with no way to ever be answered.
@@ -652,7 +652,7 @@ export function createDebugRegistry(opts: {
652
652
  * surface (game-scoped, last-attached room wins — and, since Defect 8,
653
653
  * actually CLEANS UP the previous attachment rather than merely
654
654
  * overwriting the pointer). Subscribes to the reserved
655
- * `__vgai:debugCommandResult` reply and resolves/rejects the matching
655
+ * `__volter:debugCommandResult` reply and resolves/rejects the matching
656
656
  * in-flight {@link invokeServerCommand} promise by `requestId`. */
657
657
  function attachRoom(room: DebugRoomHandle): () => void {
658
658
  // Last-wins, but with cleanup: detach whatever room was attached before
@@ -661,7 +661,7 @@ export function createDebugRegistry(opts: {
661
661
  detachCurrentRoom?.();
662
662
 
663
663
  attachedRoom = room;
664
- const unsubscribe = room.onMessage('__vgai:debugCommandResult', (message) => {
664
+ const unsubscribe = room.onMessage('__volter:debugCommandResult', (message) => {
665
665
  const reply = message as
666
666
  | { requestId?: string; ok?: boolean; result?: unknown; error?: unknown }
667
667
  | undefined;
@@ -21,7 +21,7 @@
21
21
  * game's own camera writes never fight it because the game keeps rendering
22
22
  * through its own canvas untouched. Per the non-redundancy rule that governs
23
23
  * this list, a control the editor's own chrome furnishes gets no instrument;
24
- * agents reach that camera through the editor half of `vgai eval`, not the
24
+ * agents reach that camera through the editor half of `volter-game-editor eval`, not the
25
25
  * game registry.
26
26
  *
27
27
  * ── THE DOOR ────────────────────────────────────────────────────────────────
@@ -266,7 +266,7 @@ export function createPerformanceProfiler(initiallyEnabled = false) {
266
266
  startMs: existing?.startMs ?? phaseStart - frameStart,
267
267
  });
268
268
  if (recording)
269
- performance.measure(`vgai.phase.${name}`, { start: phaseStart, duration: elapsed });
269
+ performance.measure(`volter.phase.${name}`, { start: phaseStart, duration: elapsed });
270
270
  },
271
271
  systemObserver: {
272
272
  beginSystem() {
@@ -344,7 +344,7 @@ export function createPerformanceProfiler(initiallyEnabled = false) {
344
344
  frames.push(frame);
345
345
  if (frames.length > 600) frames.splice(0, frames.length - 600);
346
346
  if (recording)
347
- performance.measure('vgai.frame', { start: frameStart, duration: frame.cpuMs });
347
+ performance.measure('volter.frame', { start: frameStart, duration: frame.cpuMs });
348
348
  publish();
349
349
  },
350
350
  subscribe(listener: () => void) {
@@ -3,7 +3,7 @@
3
3
  * game's own debug registry (`runtime/debug-registry.ts`), so a running game
4
4
  * explains its own frame cost through the SAME seam every other reading and
5
5
  * verb uses — `game.state('render.vitals')` / `game.command('render.census')`
6
- * through `vgai eval`, and `game.providers()`/`game.commands()` to discover
6
+ * through `volter-game-editor eval`, and `game.providers()`/`game.commands()` to discover
7
7
  * them without being told they exist.
8
8
  *
9
9
  * Engine-owned and first-party, seeded by BOTH three-root mount paths — a game
@@ -175,7 +175,7 @@ export function registerRenderVitals(
175
175
  'Meshes grouped by shared (geometry, material) identity, largest group first — the ' +
176
176
  'instancing shortlist for a draw-call diet. `structural` is the same scan keyed by ' +
177
177
  'VALUE instead of object identity: what would collapse under a <Frozen> wrapper ' +
178
- '(vgai add static-batch) even when every mesh carries its own inline material.',
178
+ '(volter-game-editor add static-batch) even when every mesh carries its own inline material.',
179
179
  args: z.tuple([]),
180
180
  locus: 'client',
181
181
  },
@@ -138,7 +138,7 @@ export function decideStaticBatchAdvisory(
138
138
  `are repeats of ${grouped(structural.familyCount)} structural families, ` +
139
139
  `${where}. If that scenery is mount-static — nothing under it moves, re-colours or ` +
140
140
  `unmounts after mount — one wrapper collapses it to a few draws: wrap it in ` +
141
- `${fix}…</Frozen> (vgai add static-batch). Reactive scenery goes outside the wrapper, ` +
141
+ `${fix}…</Frozen> (volter-game-editor add static-batch). Reactive scenery goes outside the wrapper, ` +
142
142
  `and a subtree that must stay unbatched declares it: userData={{ staticBatch: false }}.`;
143
143
 
144
144
  return { drawCalls, collapsible, subtree, fix, message };
@@ -150,14 +150,14 @@ export function decideStaticBatchAdvisory(
150
150
  * along with everything else on the console. Same mechanism, and the same
151
151
  * reason, as dev-tools' unconfigured-section warning.
152
152
  */
153
- const WARNED_KEY = '__vgaiStaticBatchAdvised';
153
+ const WARNED_KEY = '__volterStaticBatchAdvised';
154
154
 
155
155
  function alreadyWarned(): boolean {
156
156
  return (globalThis as unknown as Record<string, boolean | undefined>)[WARNED_KEY] === true;
157
157
  }
158
158
 
159
159
  /**
160
- * The console IS this advisory's channel: `vgai status` reports console
160
+ * The console IS this advisory's channel: `volter-game-editor status` reports console
161
161
  * warnings, which is where a building agent already looks. An in-editor
162
162
  * banner would be one nobody opens, and a provider would be one nobody reads
163
163
  * without already knowing to ask.
@@ -24,7 +24,7 @@
24
24
  * case: it is a dev session by definition even when the editor SPA it
25
25
  * runs inside is a production build.
26
26
  * 2. A dev build — `import.meta.env.DEV`. The ordinary local/editor case.
27
- * 3. A production build's EXPLICIT opt-in — `VITE_VGAI_DEV_BUILD=true`.
27
+ * 3. A production build's EXPLICIT opt-in — `VITE_VOLTER_DEV_BUILD=true`.
28
28
  * Instrumenting a production bundle is a real, legitimate choice (an
29
29
  * internal playtest build, a QA build), and it must be an opt-in someone
30
30
  * had to type, never something a default drifts into.
@@ -40,8 +40,8 @@ export function devBuildEnabled(override?: boolean | undefined): boolean {
40
40
  // of the dev answer importable from ANY program rather than forcing every
41
41
  // downstream tsconfig to adopt Vite's ambient types.
42
42
  const env = (import.meta as unknown as { env?: unknown }).env as
43
- | { DEV?: boolean | undefined; VITE_VGAI_DEV_BUILD?: string | undefined }
43
+ | { DEV?: boolean | undefined; VITE_VOLTER_DEV_BUILD?: string | undefined }
44
44
  | undefined;
45
45
  if (env?.DEV === true) return true;
46
- return env?.VITE_VGAI_DEV_BUILD === 'true';
46
+ return env?.VITE_VOLTER_DEV_BUILD === 'true';
47
47
  }
@@ -744,9 +744,9 @@ export interface GameInternal extends Game {
744
744
  * call the SAME per-tick pipeline `runFrame` uses, `n` times in a tight
745
745
  * loop, with `dt` fixed to the host loop's own fixed timestep
746
746
  * (`this.loop.fixedDt` — `core/game-loop.ts`). This generalizes
747
- * `render-control.ts`'s proven `VgaiRenderHarness. simulateSubsteps` from
748
- * the capture-only door (`?vgai-render=1`) to a Game-level primitive every
749
- * door can reach (the bridge's `window.__vgai.runTicks`, the editor relay's
747
+ * `render-control.ts`'s proven `VolterRenderHarness. simulateSubsteps` from
748
+ * the capture-only door (`?volter-render=1`) to a Game-level primitive every
749
+ * door can reach (the bridge's `window.__volter.runTicks`, the editor relay's
750
750
  * `run-ticks` case → `play.runTicks`) — `simulateSubsteps` itself is
751
751
  * UNTOUCHED by this addition (it may later delegate to this method; not
752
752
  * this unit's job).
@@ -816,7 +816,7 @@ export function createGame(opts: {
816
816
  * on its own terms, whether or not the project's manifest DECLARES that
817
817
  * reproducibility as a contract). The manifest-aware boot path
818
818
  * (`mount-manifest.ts`'s `mountManifestRoots`) is what actually resolves
819
- * `manifest.determinism.defaultSeed`/`?vgai-seed=`/explicit config and
819
+ * `manifest.determinism.defaultSeed`/`?volter-seed=`/explicit config and
820
820
  * passes the result here, BEFORE any world's `mount()`/`setup()` runs —
821
821
  * `createGameRuntime` always constructs the Game (this call) first (see
822
822
  * this function's own doc comment below). */
@@ -1618,7 +1618,7 @@ export function createGame(opts: {
1618
1618
  // D15/T-D15.4: wire the run-ticks target the instant the Game shell exists
1619
1619
  // (unlike `setVirtualInputTarget`, which waits for a per-world mount, a
1620
1620
  // Game's own `runTicks` needs nothing else) — this is what makes
1621
- // `window.__vgai.runTicks` (`debug-bridge.ts`) and the editor relay's
1621
+ // `window.__volter.runTicks` (`debug-bridge.ts`) and the editor relay's
1622
1622
  // `run-ticks` case reach the SAME implementation `game.runTicks` above is.
1623
1623
  debugRegistry.setRunTicksTarget({ runTicks: gameInternal.runTicks });
1624
1624
  // D15 (T-D15.1/.3) — same "file after the shell exists" ordering as the
@@ -160,7 +160,7 @@ export function createInputRouter(
160
160
  if (claimant && claimant !== bottomId) {
161
161
  const entry = byId.get(claimant);
162
162
  if (entry) {
163
- // The claim is exclusive: the world beneath never hears a press its HUD took.
163
+ // The claim is exclusive: the world beneath never hears a press the layer above took.
164
164
  evt.stopPropagation();
165
165
  forwardEvent(entry.canvas, evt);
166
166
  }
@@ -130,7 +130,7 @@ export interface MountManifestOptions {
130
130
  * never a real host. See `RootsRuntimeConfig.headless`. */
131
131
  readonly headless?: boolean | undefined;
132
132
  /**
133
- * Task 2.1: overrides for the `?vgai-debug=1` bridge `mountManifestRoots`
133
+ * Task 2.1: overrides for the `?volter-debug=1` bridge `mountManifestRoots`
134
134
  * installs at the tail of every mount — the engine-owned install point so
135
135
  * every standalone project gets it with zero template edits. Omit both in
136
136
  * a real host (defaults to `window.location`/ `window`); a headless test
@@ -145,7 +145,7 @@ export interface MountManifestOptions {
145
145
  | undefined;
146
146
  /**
147
147
  * D15 (T-D15.1) — the "explicit config" leg of the boot-time seed
148
- * precedence (`manifest.determinism.defaultSeed` → `?vgai-seed=` → this),
148
+ * precedence (`manifest.determinism.defaultSeed` → `?volter-seed=` → this),
149
149
  * highest-precedence, for a caller that already knows the exact seed it
150
150
  * wants (a future CLI `--seed`/probe fixture `seed` option, T-D15.6).
151
151
  * Ignored entirely unless the manifest declares
@@ -154,7 +154,7 @@ export interface MountManifestOptions {
154
154
  readonly seed?: number | undefined;
155
155
  /** Host identity for a private play run or coordinated Team Test. */
156
156
  readonly playtest?: PlaytestContext | null | undefined;
157
- /** Where to read `?vgai-seed=` from for the boot-time seed reader. Same
157
+ /** Where to read `?volter-seed=` from for the boot-time seed reader. Same
158
158
  * override precedent as `debugBridge.url` (defaults to `window.location`
159
159
  * when a real `window` exists; a headless caller with no override gets no
160
160
  * query-param seed, same as `maybeInstallDebugBridge`'s own url default). */
@@ -166,13 +166,13 @@ export interface MountManifestOptions {
166
166
  * `mountManifestRoots` threads into `createGameRuntime` (and therefore
167
167
  * `createGame`, BEFORE any world's `mount()`/`setup()` runs). Returns
168
168
  * `undefined` when the manifest doesn't declare `determinism.seededRandom`
169
- * at all — `?vgai-seed=` and `defaultSeed` are both ignored in that case
169
+ * at all — `?volter-seed=` and `defaultSeed` are both ignored in that case
170
170
  * (§2.a: "the mount path seeds ctx.random ... iff declared"; an undeclared
171
171
  * project's `ctx.random` still exists, just boots from `createGame`'s own
172
172
  * fixed default, unaffected by the manifest or the URL).
173
173
  *
174
174
  * Precedence when declared (highest wins): `explicitSeed` (a caller-supplied
175
- * config value) → `?vgai-seed=<int>` on `url` → `manifest.determinism
175
+ * config value) → `?volter-seed=<int>` on `url` → `manifest.determinism
176
176
  * .defaultSeed`.
177
177
  */
178
178
  export function resolveDeterminismSeed(opts: {
@@ -250,7 +250,7 @@ export function resolveManifest(raw: unknown): ResolvedGameManifest {
250
250
 
251
251
  // ---------------------------------------------------------------------------
252
252
  // Per-kind entry -> adapter resolution (mirrors `resolveRootBinding`'s
253
- // per-identity dispatch, `packages/editor/src/binding-resolver.ts`)
253
+ // per-identity dispatch, `packages/editor-game/src/host/binding-resolver.ts`)
254
254
  // ---------------------------------------------------------------------------
255
255
 
256
256
  function resolveThreeAdapter(
@@ -341,7 +341,7 @@ function buildRootMountSpec(
341
341
  zOrder: world.zOrder,
342
342
  pausable: world.pausable,
343
343
  // `root` is this file's own resolved manifest record; the rest — the
344
- // parsed `vgai.adapter.ts`, the entry namespace, the entry's declared
344
+ // parsed `volter.adapter.ts`, the entry namespace, the entry's declared
345
345
  // debug/systems bindings — only the caller who loaded the entry can know.
346
346
  ...(entry?.declaration === undefined
347
347
  ? {}
@@ -376,7 +376,7 @@ function buildRootMountSpec(
376
376
  // ---------------------------------------------------------------------------
377
377
 
378
378
  /**
379
- * Mount every world declared by a `vgai.project.json` manifest onto `container`,
379
+ * Mount every world declared by a `volter.project.json` manifest onto `container`,
380
380
  * standalone — no editor, no dev server. The generalization of
381
381
  * `examples/tri-world/src/main.ts`'s hand-built `RootMountSpec[]` (D-Z2). Reuses
382
382
  * the pure `loadGameManifest` + `createGameRuntime({ roots })` and mirrors
@@ -441,7 +441,7 @@ export async function mountManifestRoots(opts: MountManifestOptions): Promise<Ga
441
441
  getGameplayRngTrapControl(session.game)?.setEnabled(true);
442
442
  }
443
443
 
444
- // Task 2.1 — install the `?vgai-debug=1` bridge at the TAIL of every
444
+ // Task 2.1 — install the `?volter-debug=1` bridge at the TAIL of every
445
445
  // manifest mount (engine-owned, so a standalone project gets it with zero
446
446
  // template edits). `getDebugRegistry` returns `null` only for a bare
447
447
  // `Game`-shaped test stand-in predating T7.1 — real mounts always have one.
@@ -458,7 +458,7 @@ export async function mountManifestRoots(opts: MountManifestOptions): Promise<Ga
458
458
  debugRegistry.setRoomDeclared(true);
459
459
  }
460
460
  // Defect 5 fix: `maybeInstallDebugBridge` adds `window` listeners and
461
- // publishes `window.__vgai` with no way to undo either — wire its
461
+ // publishes `window.__volter` with no way to undo either — wire its
462
462
  // `uninstall()` into THIS session's own `stop()` so a caller that tears
463
463
  // this mount down doesn't leave the bridge (and its listeners) live.
464
464
  const bridgeHandle = maybeInstallDebugBridge({
@@ -188,7 +188,7 @@ function viewOwnerLabel(view: Container): string | undefined {
188
188
  * on a 20 000-node `@pixi/react` world blocked the main thread for 199.5
189
189
  * SECONDS in one synchronous run, 69% of all profiler samples inside this
190
190
  * search, because `parentRenderGroup` reaches an array of every node in the
191
- * tree and the search walked it once per unlabeled node. `vgai play`,
191
+ * tree and the search walked it once per unlabeled node. `volter-game-editor play`,
192
192
  * `screenshot` and `stop` all timed out against a tab that was heartbeating
193
193
  * normally the whole time.
194
194
  */
@@ -62,7 +62,7 @@ export interface IngestMount2D {
62
62
  * `onWait` is the three lane's own seam (`ingest-root-adapter.ts` passes
63
63
  * `setCaptureWait`): the capture window PARKS while the tab is hidden, and a
64
64
  * parked wait is otherwise indistinguishable from a hung mount at every door.
65
- * Threading it here is what lets `vgai status` say "waiting for the first
65
+ * Threading it here is what lets `volter-game-editor status` say "waiting for the first
66
66
  * visible frame — the tab is hidden" over a canvas ingest too.
67
67
  */
68
68
  export async function mountIngestGame2D(
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * runtime/presentation.ts — how a game with a DECLARED resolution is presented in a host panel.
3
3
  *
4
- * `vgai.project.json`'s `resolution` is the game's own LOGICAL size: the coordinate space its
4
+ * `volter.project.json`'s `resolution` is the game's own LOGICAL size: the coordinate space its
5
5
  * cameras frame, its DOM overlay lays out in, and its 2D worlds author positions against. A host
6
6
  * panel is whatever size the user dragged it to, and the two are not the same number.
7
7
  *
@@ -17,14 +17,14 @@
17
17
  *
18
18
  * Also does NOT install anything by default — a caller must explicitly call
19
19
  * {@link installRenderControlHarness}, and even then it only actually
20
- * publishes `window.__vgaiRender` when the page's URL opts in via
21
- * `?vgai-render=1` (AC 4: unavailable/protected in normal production
20
+ * publishes `window.__volterRender` when the page's URL opts in via
21
+ * `?volter-render=1` (AC 4: unavailable/protected in normal production
22
22
  * gameplay unless explicitly enabled). See `render-seed.ts` for the
23
23
  * matching `Math.random` determinism hardening, which must run BEFORE this
24
24
  * module (or any other game module) is even imported.
25
25
  *
26
26
  * I5 (`--simulate` render, §15 I5) is implemented HERE, alongside `renderOnce`:
27
- * {@link VgaiRenderHarness.simulateSubsteps} drives `game.runFrame(fixedDt)` a
27
+ * {@link VolterRenderHarness.simulateSubsteps} drives `game.runFrame(fixedDt)` a
28
28
  * fixed integer number of times — the FULL fixed-step gameplay frame (every
29
29
  * phase in `PHASE_ORDER`, including `physics`/`gameLogic`/`animation`), unlike
30
30
  * `renderOnce`'s deliberately gameplay-free `preRender`+`render`-only pass.
@@ -109,11 +109,11 @@ export interface SeekableClock {
109
109
  */
110
110
  export type FrameAdvancer = (dt: number) => void;
111
111
 
112
- /** The `window.__vgaiRender` surface (I2 AC, extended by I8's `advanceFrame`).
112
+ /** The `window.__volterRender` surface (I2 AC, extended by I8's `advanceFrame`).
113
113
  * Every method here is synchronous except the two that genuinely need to
114
114
  * wait on the browser (composited render completion, async readiness
115
115
  * probes). */
116
- export interface VgaiRenderHarness {
116
+ export interface VolterRenderHarness {
117
117
  /** Evaluate every registered sequence/cinematic-participating evaluator at
118
118
  * exact time `t` (seconds) via `clock.seek(t)` — never advances gameplay
119
119
  * substeps. Synchronous: the clock's subscribed evaluators run inline,
@@ -129,7 +129,7 @@ export interface VgaiRenderHarness {
129
129
  * by exactly `dt` seconds, in registration order. A render-mode capture
130
130
  * loop calls this ONCE per OUTPUT frame, with `dt = 1 / fps`, BEFORE
131
131
  * `seekFrame`/`renderOnce` for that frame — see
132
- * `packages/vgai-sdk/src/render/render-cinematic.ts`'s `captureFrames`, which
132
+ * `packages/volter-sdk/src/render/render-cinematic.ts`'s `captureFrames`, which
133
133
  * drives exactly this sequence. `advanceFrame` is a genuinely
134
134
  * FORWARD-ONLY, INCREMENTAL tick (it has no notion of "time" to seek
135
135
  * to — it only knows "advance by `dt` more") — unlike {@link seek}/
@@ -213,7 +213,7 @@ export interface VgaiRenderHarness {
213
213
  */
214
214
  simulateFixedDt(): number;
215
215
  /**
216
- * W3d (F11 perf regression gates) — the `vgai perf` sampling seam. Runs
216
+ * W3d (F11 perf regression gates) — the `volter perf` sampling seam. Runs
217
217
  * exactly `steps` FULL fixed-step gameplay frames (the same
218
218
  * `game.runFrame(fixedDt)` path {@link simulateSubsteps} drives — every
219
219
  * phase in `PHASE_ORDER`, including `render`, so `renderer.info`-backed
@@ -226,7 +226,7 @@ export interface VgaiRenderHarness {
226
226
  * from the existing profiler (timings, render counters) or the live world
227
227
  * roots themselves (counts).
228
228
  *
229
- * Honesty notes, recorded here because this seam is what `vgai perf`
229
+ * Honesty notes, recorded here because this seam is what `volter perf`
230
230
  * reports: `gpuMs` is whatever the profiler's render reporter measured —
231
231
  * `null` under headless SwiftShader (no usable GPU timer), never a
232
232
  * fabricated 0; CPU timings include the profiler's own (small) phase
@@ -237,7 +237,7 @@ export interface VgaiRenderHarness {
237
237
  perfSample(steps: number): PerfSampleReport;
238
238
  }
239
239
 
240
- /** One measured fixed-step frame from {@link VgaiRenderHarness.perfSample}. */
240
+ /** One measured fixed-step frame from {@link VolterRenderHarness.perfSample}. */
241
241
  export interface PerfFrameSample {
242
242
  /** CPU time (ms) for the whole `runFrame` pass (profiler `cpuMs`). */
243
243
  readonly cpuMs: number;
@@ -255,7 +255,7 @@ export interface PerfFrameSample {
255
255
  };
256
256
  }
257
257
 
258
- /** Per-world structural counts from {@link VgaiRenderHarness.perfSample}. */
258
+ /** Per-world structural counts from {@link VolterRenderHarness.perfSample}. */
259
259
  export interface PerfRootCount {
260
260
  readonly id: string;
261
261
  readonly kind: string;
@@ -279,7 +279,7 @@ export interface RenderControlHarnessOptions {
279
279
  /**
280
280
  * `GameInternal` (not just the game-facing `Game`) — this harness is
281
281
  * itself a host (the render/capture driver), and I5's
282
- * {@link VgaiRenderHarness.simulateSubsteps} needs the host-only
282
+ * {@link VolterRenderHarness.simulateSubsteps} needs the host-only
283
283
  * `runFrame` surface (`runtime/game.ts`'s `GameInternal.runFrame` doc
284
284
  * comment: "the host loop ... and `GameSession.step()` are the only
285
285
  * callers"). Every real call site already holds a `GameInternal` (the
@@ -292,9 +292,9 @@ export interface RenderControlHarnessOptions {
292
292
  /** Where to publish the harness. Defaults to the real `window` — override
293
293
  * in a unit test to avoid touching the global object. */
294
294
  readonly target?: Record<string, unknown>;
295
- /** Where to read `?vgai-render=1` from. Defaults to `window.location`. */
295
+ /** Where to read `?volter-render=1` from. Defaults to `window.location`. */
296
296
  readonly location?: { readonly search: string };
297
- /** I8 render-integration seam — see {@link VgaiRenderHarness.advanceFrame}.
297
+ /** I8 render-integration seam — see {@link VolterRenderHarness.advanceFrame}.
298
298
  * Zero or more `FrameAdvancer`s invoked, in array order, on every
299
299
  * `harness.advanceFrame(dt)` call. Default `[]` (no-op), which is exactly
300
300
  * what a fixture with nothing gameplay-phase-driven (e.g. I0's fixture)
@@ -303,7 +303,7 @@ export interface RenderControlHarnessOptions {
303
303
  readonly frameAdvancers?: readonly FrameAdvancer[];
304
304
  /**
305
305
  * I5 `--simulate` seam: the fixed substep `dt` (seconds)
306
- * {@link VgaiRenderHarness.simulateSubsteps} passes to every
306
+ * {@link VolterRenderHarness.simulateSubsteps} passes to every
307
307
  * `game.runFrame(fixedDt)` call. Default `1/60` — the same fixed timestep
308
308
  * every real host's `createGameLoop` config uses (`create-runtime.ts`), so
309
309
  * a `--simulate` fixture's Rapier world (whose own `integrationParameters.dt`
@@ -313,7 +313,7 @@ export interface RenderControlHarnessOptions {
313
313
  */
314
314
  readonly simulateFixedDt?: number;
315
315
  /**
316
- * I5 AC 5 — see {@link VgaiRenderHarness.excludedFromDeterminism}. A
316
+ * I5 AC 5 — see {@link VolterRenderHarness.excludedFromDeterminism}. A
317
317
  * static, page-declared list of subsystems this fixture/game has that do
318
318
  * NOT participate in deterministic capture (e.g. live networking,
319
319
  * non-seeded ambient audio) — named here as an explicit, reviewable
@@ -412,7 +412,7 @@ function warnUnrenderable(worldLabel: string, reason: string): void {
412
412
 
413
413
  /**
414
414
  * I5 AC 5 policy text for the two conditions {@link renderableRoots} skips —
415
- * shared so {@link VgaiRenderHarness.excludedFromDeterminism} names the SAME
415
+ * shared so {@link VolterRenderHarness.excludedFromDeterminism} names the SAME
416
416
  * roots `renderOnce()` warns about, in the SAME words, rather than
417
417
  * maintaining a second, driftable description of the same two checks.
418
418
  */
@@ -539,17 +539,17 @@ async function buildReadinessReport(hooks: RenderReadinessHooks): Promise<Readin
539
539
 
540
540
  /**
541
541
  * Build (and, when render mode is actually requested, publish) the
542
- * `window.__vgaiRender` harness. AC 4 — production protection — lives HERE,
542
+ * `window.__volterRender` harness. AC 4 — production protection — lives HERE,
543
543
  * not just at the call site: even if a host application calls this
544
544
  * unconditionally on every boot, the harness is only ever constructed *and*
545
545
  * attached to `target` when `isRenderModeRequested(location)` is true;
546
546
  * otherwise this is a no-op that returns `undefined`. A normal production
547
- * gameplay page therefore never gets `window.__vgaiRender` no matter how
547
+ * gameplay page therefore never gets `window.__volterRender` no matter how
548
548
  * this function is wired into its entry point.
549
549
  */
550
550
  export function installRenderControlHarness(
551
551
  opts: RenderControlHarnessOptions,
552
- ): VgaiRenderHarness | undefined {
552
+ ): VolterRenderHarness | undefined {
553
553
  const location = opts.location ?? window.location;
554
554
  if (!isRenderModeRequested(location)) return undefined;
555
555
 
@@ -559,7 +559,7 @@ export function installRenderControlHarness(
559
559
  const simulateFixedDt = opts.simulateFixedDt ?? 1 / 60;
560
560
  const declaredExclusions = opts.excludedFromDeterminism ?? [];
561
561
 
562
- const harness: VgaiRenderHarness = {
562
+ const harness: VolterRenderHarness = {
563
563
  seek(t: number): void {
564
564
  clock.seek(t);
565
565
  },
@@ -610,7 +610,7 @@ export function installRenderControlHarness(
610
610
  },
611
611
  };
612
612
 
613
- target['__vgaiRender'] = harness;
613
+ target['__volterRender'] = harness;
614
614
  return harness;
615
615
  }
616
616
 
@@ -54,14 +54,14 @@ export function installDeterministicRandom(seed: number): void {
54
54
  * mode must be unavailable/protected in normal production gameplay unless
55
55
  * explicitly enabled). Shared with `render-control.ts`'s own production
56
56
  * guard so both checks agree on the same flag. */
57
- export const RENDER_MODE_QUERY_PARAM = 'vgai-render';
57
+ export const RENDER_MODE_QUERY_PARAM = 'volter-render';
58
58
  /** Optional query param to pin a specific seed (default below when absent). */
59
- export const RENDER_SEED_QUERY_PARAM = 'vgai-seed';
59
+ export const RENDER_SEED_QUERY_PARAM = 'volter-seed';
60
60
  const DEFAULT_RENDER_SEED = 0x9e3779b9; // golden-ratio constant — an arbitrary but fixed default
61
61
 
62
62
  /**
63
63
  * Seed `Math.random` iff the page's URL opts into render mode
64
- * (`?vgai-render=1`), reading an optional `?vgai-seed=<int>` override.
64
+ * (`?volter-render=1`), reading an optional `?volter-seed=<int>` override.
65
65
  * Returns whether it seeded, purely for the caller's own diagnostics/log —
66
66
  * the bootstrap entry doesn't need to branch on it.
67
67
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `runTicksWhenSettled` — the settled-aware tick driver behind BOTH session run-ticks doors
3
- * (the bridge's `window.__vgai.runTicksSettled`, the editor relay's `run-ticks` case), one
3
+ * (the bridge's `window.__volter.runTicksSettled`, the editor relay's `run-ticks` case), one
4
4
  * implementation with byte-identical semantics across doors, exactly as `runTicks` itself is
5
5
  * shared (D17).
6
6
  *
@@ -36,9 +36,9 @@ function resumeSuspended(): void {
36
36
 
37
37
  /** Install once at editor boot (`audio.service.ts`). Idempotent. */
38
38
  export function installGameAudio(): void {
39
- const host = window as unknown as { __vgaiAudioUnlock?: boolean } & typeof window;
40
- if (host.__vgaiAudioUnlock) return;
41
- host.__vgaiAudioUnlock = true;
39
+ const host = window as unknown as { __volterAudioUnlock?: boolean } & typeof window;
40
+ if (host.__volterAudioUnlock) return;
41
+ host.__volterAudioUnlock = true;
42
42
  const Orig = window.AudioContext;
43
43
  if (typeof Orig !== 'function') return;
44
44
  window.AudioContext = class extends Orig {
@@ -445,9 +445,9 @@ function observeMatchmaking(input: RequestInfo | URL, response: Response): void
445
445
 
446
446
  /** Install once at editor boot (`network-observer.service.ts`). Idempotent. */
447
447
  export function installGameNetwork(): void {
448
- const host = window as unknown as { __vgaiNetworkObserver?: boolean } & typeof window;
449
- if (host.__vgaiNetworkObserver) return;
450
- host.__vgaiNetworkObserver = true;
448
+ const host = window as unknown as { __volterNetworkObserver?: boolean } & typeof window;
449
+ if (host.__volterNetworkObserver) return;
450
+ host.__volterNetworkObserver = true;
451
451
  const Orig = window.WebSocket;
452
452
  if (typeof Orig === 'function') {
453
453
  const Observed = class extends Orig {
@@ -574,7 +574,7 @@ async function roomCall(method: string, args: unknown[], what: string, roomId?:
574
574
  const query = new URLSearchParams({ roomId: roomId ?? mirror.roomId, method, args: JSON.stringify(args) });
575
575
  const response = await fetch(`${monitorApi(mirror)}/room/call?${query}`);
576
576
  if (response.status === 404) {
577
- throw new Error(`The room server serves no Monitor view, so ${what} has nowhere to go (its \`server\` configuration sets VGAI_ROOM_MONITOR=1).`);
577
+ throw new Error(`The room server serves no Monitor view, so ${what} has nowhere to go (its \`server\` configuration sets VOLTER_ROOM_MONITOR=1).`);
578
578
  }
579
579
  if (!response.ok) throw new Error(`The room server refused ${what} (${response.status}).`);
580
580
  }