@volter/editor-game 0.5.68 → 0.5.69

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 +1 -1
  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 +10 -10
  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 +3 -3
  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 +2 -2
  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 +10 -10
  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 +14 -14
  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 +9 -9
  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
@@ -52,7 +52,7 @@ import type {
52
52
  } from '@volter/editor-project/adapter';
53
53
  import { WRITE_ANCHOR_KINDS } from '@volter/editor-project/adapter';
54
54
  import type { AdapterSurface } from '@volter/editor-project/adapter/adapter-surface';
55
- import type { VgaiGameContract } from '@volter/editor-project/adapter/ingest/game-contract';
55
+ import type { VolterGameContract } from '@volter/editor-project/adapter/ingest/game-contract';
56
56
  import type { SystemAdapters } from '@volter/editor-project/adapter/system-adapter';
57
57
  import { SYSTEM_ADAPTERS_SHAPE } from '@volter/editor-project/adapter/system-seam-contract';
58
58
  import {
@@ -92,7 +92,7 @@ export {
92
92
  * gets a row.
93
93
  *
94
94
  * The rest are contract facts about an ingested game — declarations only a
95
- * `window.vgaiGame` can make — and they grow with the contract; nothing
95
+ * `window.volterGame` can make — and they grow with the contract; nothing
96
96
  * switches exhaustively on this type, so no consumer breaks when it does.
97
97
  */
98
98
  export type CapabilityCoverageSeam =
@@ -212,7 +212,7 @@ export interface SystemsPresence {
212
212
  * and this file never calls any of them.
213
213
  */
214
214
  export interface ContractPresence {
215
- /** `readGameContract()` answered at all (a v1 `window.vgaiGame`). */
215
+ /** `readGameContract()` answered at all (a v1 `window.volterGame`). */
216
216
  readonly declared: boolean;
217
217
  readonly root: boolean;
218
218
  readonly start: boolean;
@@ -224,7 +224,7 @@ export interface ContractPresence {
224
224
  }
225
225
 
226
226
  /** Fold a read contract (or its absence) into presence flags. */
227
- export function measureGameContract(contract: VgaiGameContract | null): ContractPresence {
227
+ export function measureGameContract(contract: VolterGameContract | null): ContractPresence {
228
228
  const systems = contract?.systems;
229
229
  return {
230
230
  declared: contract !== null,
@@ -276,7 +276,7 @@ export interface WriteReachFacts {
276
276
  * reads healthy while every one of the 12 belongs to one lane and a whole
277
277
  * other lane — a world's physics-placed cargo, or its level-data records —
278
278
  * goes unwritten and unexercised. A per-kind tally is what makes an
279
- * exhaustive walk possible; `vgai doctor`'s edit-write phase is its reader.
279
+ * exhaustive walk possible.
280
280
  *
281
281
  * Optional, because callers older than the vocabulary supply none and a
282
282
  * fabricated zero for every kind would read as a measurement.
@@ -307,7 +307,7 @@ export interface DataWriterFacts {
307
307
  * actually holds an adapter for this slot. That is the strongest available
308
308
  * statement: it is the same object the editor's panels will call.
309
309
  * - `empty` — the game POSITIVELY answered "I have no X" through
310
- * `window.vgaiGame.systems.systemAdapters` (`evidence` is its own words).
310
+ * `window.volterGame.systems.systemAdapters` (`evidence` is its own words).
311
311
  * - `malformed` — a declaration that could not be honoured; `evidence` is the
312
312
  * projection's reason. Reported so a broken shim is loud, never silently
313
313
  * read as either of the two terminal states.
@@ -327,7 +327,7 @@ export interface SystemAdapterMeasurement {
327
327
  * shared default would state wrongly.
328
328
  *
329
329
  * This is what keeps the derivation provenance-NEUTRAL. The default fix text
330
- * below names `window.vgaiGame.systems…`, which is true of a game that
330
+ * below names `window.volterGame.systems…`, which is true of a game that
331
331
  * declares a contract and false of a first-party one; rather than have the
332
332
  * row builder ask WHO produced the measurement, the measurement carries the
333
333
  * answer as a fact (`coverage/system-adapter-coverage.ts` supplies it for a
@@ -474,7 +474,7 @@ type ResolvedCoverageFacts = Required<CapabilityCoverageFacts>;
474
474
 
475
475
  /**
476
476
  * The route for a game whose bytes may not be touched — which is EVERY
477
- * repo-vendored ingest, by doctrine. "Declare `window.vgaiGame.root`" is the
477
+ * repo-vendored ingest, by doctrine. "Declare `window.volterGame.root`" is the
478
478
  * mechanism, but a game nobody may edit cannot declare anything, so a fix that
479
479
  * stopped there would be telling the reader to do something they are not
480
480
  * allowed to do. Both host-side carriers now exist, so this names them and
@@ -483,8 +483,8 @@ type ResolvedCoverageFacts = Required<CapabilityCoverageFacts>;
483
483
  const UNMODIFIABLE_ROUTE =
484
484
  'a game whose bytes must stay unmodified declares it from a host-side carrier ' +
485
485
  'instead — a contract shim beside the game (`ingest.contractShim` in its ' +
486
- 'vgai.project.json, injected ahead of the game`s entry module; see ' +
487
- 'public/ingest/simcity/vgai.shim.js) or a recorded patch';
486
+ 'volter.project.json, injected ahead of the game`s entry module; see ' +
487
+ 'public/ingest/simcity/volter.shim.js) or a recorded patch';
488
488
 
489
489
  const CONTRACT_FIX = (endpoint: string): string =>
490
490
  `declare ${endpoint} in the game's own entry; ${UNMODIFIABLE_ROUTE}`;
@@ -656,7 +656,7 @@ function loopRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
656
656
  missing:
657
657
  "nothing in this editor controls the game's frames: ▶/⏸ and Step do not stop it, and " +
658
658
  'Edit mode cannot be quiet — it keeps simulating while you author',
659
- fix: CONTRACT_FIX('window.vgaiGame.lifecycle.pause + resume'),
659
+ fix: CONTRACT_FIX('window.volterGame.lifecycle.pause + resume'),
660
660
  };
661
661
  }
662
662
  // No verdict, and that is its own answer — never a gap. The caller supplies
@@ -681,7 +681,7 @@ function contractRootRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
681
681
  detail: `the game declares a root, but the seam failed — ${facts.contract.proof.root.detail}`,
682
682
  missing:
683
683
  'the host cannot trust that the declared element owns the game DOM rather than an unrelated or detached subtree',
684
- fix: CONTRACT_FIX('window.vgaiGame.root'),
684
+ fix: CONTRACT_FIX('window.volterGame.root'),
685
685
  };
686
686
  }
687
687
  return {
@@ -703,7 +703,7 @@ function contractRootRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
703
703
  'the host adopts the bare canvas, so any DOM this game owns beside it (HUD, overlays, ' +
704
704
  'portals) is stranded at page level over the editor chrome instead of living in the ' +
705
705
  'game pane',
706
- fix: CONTRACT_FIX('window.vgaiGame.root'),
706
+ fix: CONTRACT_FIX('window.volterGame.root'),
707
707
  };
708
708
  }
709
709
 
@@ -716,7 +716,7 @@ function contractStartRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
716
716
  detail: `lifecycle.start is declared but failed — ${facts.contract.proof.start.detail}`,
717
717
  missing:
718
718
  'the mount cannot prove it starts cold and enters a session only when Play requests one',
719
- fix: CONTRACT_FIX('window.vgaiGame.lifecycle.start'),
719
+ fix: CONTRACT_FIX('window.volterGame.lifecycle.start'),
720
720
  };
721
721
  }
722
722
  return {
@@ -738,7 +738,7 @@ function contractStartRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
738
738
  'the mount cannot be COLD: this game runs its session side-effects (backend ' +
739
739
  'connections, audio, narrative) as it loads, so opening it in the editor starts ' +
740
740
  'playing it, and ▶ is a wire event the game may ignore',
741
- fix: CONTRACT_FIX('window.vgaiGame.lifecycle.start'),
741
+ fix: CONTRACT_FIX('window.volterGame.lifecycle.start'),
742
742
  };
743
743
  }
744
744
 
@@ -792,7 +792,7 @@ function contractPauseRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
792
792
  status: 'gap',
793
793
  detail: `pause/resume is declared but failed — ${failed.detail}`,
794
794
  missing: pauseFallbackCost(facts),
795
- fix: CONTRACT_FIX('window.vgaiGame.lifecycle.pause + resume'),
795
+ fix: CONTRACT_FIX('window.volterGame.lifecycle.pause + resume'),
796
796
  };
797
797
  }
798
798
  return {
@@ -814,7 +814,7 @@ function contractPauseRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
814
814
  ? 'a contract is declared, but it names no lifecycle.pause/resume'
815
815
  : 'no game→host contract is declared at all',
816
816
  missing: pauseFallbackCost(facts),
817
- fix: CONTRACT_FIX('window.vgaiGame.lifecycle.pause + resume'),
817
+ fix: CONTRACT_FIX('window.volterGame.lifecycle.pause + resume'),
818
818
  };
819
819
  }
820
820
 
@@ -989,7 +989,7 @@ function systemsRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
989
989
  detail: `the systems carrier is declared but failed — ${facts.contract.proof.systems.detail}`,
990
990
  missing:
991
991
  '`game.commands()` / `game.providers()` cannot safely enumerate or invoke this carrier',
992
- fix: CONTRACT_FIX('window.vgaiGame.systems (commands + state)'),
992
+ fix: CONTRACT_FIX('window.volterGame.systems (commands + state)'),
993
993
  };
994
994
  }
995
995
  return {
@@ -1013,7 +1013,7 @@ function systemsRow(facts: ResolvedCoverageFacts): CapabilityCoverageRow {
1013
1013
  'this game exposes no verbs and no state to drive or read it with: `game.commands()` and ' +
1014
1014
  '`game.providers()` enumerate nothing, so there is no `game.command(...)` to play it from ' +
1015
1015
  `${commandLine('eval')} and no \`game.state(...)\` for ${commandLine('status')} to see anything of what it is doing`,
1016
- fix: CONTRACT_FIX('window.vgaiGame.systems (commands + state)'),
1016
+ fix: CONTRACT_FIX('window.volterGame.systems (commands + state)'),
1017
1017
  };
1018
1018
  }
1019
1019
 
@@ -1063,9 +1063,9 @@ function systemSlotFix(slot: SystemAdapterSlot): string {
1063
1063
  );
1064
1064
  }
1065
1065
  if (slot === 'debug') {
1066
- return CONTRACT_FIX('window.vgaiGame.systems (commands + state)');
1066
+ return CONTRACT_FIX('window.volterGame.systems (commands + state)');
1067
1067
  }
1068
- return CONTRACT_FIX(`window.vgaiGame.systems.systemAdapters.${slot}`);
1068
+ return CONTRACT_FIX(`window.volterGame.systems.systemAdapters.${slot}`);
1069
1069
  }
1070
1070
 
1071
1071
  /**
@@ -1571,7 +1571,7 @@ export function formatCapabilityCoverageBlocks(
1571
1571
  * The console door, ONCE PER MOUNT.
1572
1572
  *
1573
1573
  * The report is derived on demand (the status facet re-derives it on every
1574
- * read, so `vgai status` never serves a verdict older than the question), which
1574
+ * read, so `volter-game-editor status` never serves a verdict older than the question), which
1575
1575
  * makes "print it" a thing that could happen many times — per status poll, per
1576
1576
  * re-render, in the limit per frame. The guard is a mount token: the same
1577
1577
  * mount's report is emitted once and then never again, and a NEW mount emits
@@ -7,9 +7,9 @@ import {
7
7
  type SeamEvidenceVerdict,
8
8
  } from '@volter/editor-project/adapter';
9
9
  import type {
10
- VgaiGameContract,
11
- VgaiGameLifecycle,
12
- VgaiGameSystems,
10
+ VolterGameContract,
11
+ VolterGameLifecycle,
12
+ VolterGameSystems,
13
13
  } from '@volter/editor-project/adapter/ingest/game-contract';
14
14
  import {
15
15
  GAME_CONTRACT_SHAPE,
@@ -21,7 +21,7 @@ import { liveSeamEvidence } from '@volter/editor-sdk/kit/live-seam-evidence';
21
21
  const EPOCHS = new WeakMap<object, string>();
22
22
  let nextEpoch = 1;
23
23
 
24
- export function gameContractEpoch(contract: VgaiGameContract): string {
24
+ export function gameContractEpoch(contract: VolterGameContract): string {
25
25
  const found = EPOCHS.get(contract);
26
26
  if (found) return found;
27
27
  const epoch = `contract-${nextEpoch++}`;
@@ -38,7 +38,7 @@ export interface GameContractEvidence {
38
38
  }
39
39
 
40
40
  export function inspectGameContractSeams(options: {
41
- readonly contract: VgaiGameContract;
41
+ readonly contract: VolterGameContract;
42
42
  readonly subject?: string | undefined;
43
43
  readonly epoch?: string | undefined;
44
44
  readonly receipts?: readonly SeamEvidenceReceipt[] | undefined;
@@ -46,21 +46,21 @@ export function inspectGameContractSeams(options: {
46
46
  const subject = options.subject ?? 'game';
47
47
  const epoch = options.epoch ?? gameContractEpoch(options.contract);
48
48
  const receipts: SeamEvidenceReceipt[] = [
49
- ...inspectSeamShape<VgaiGameContract>({
49
+ ...inspectSeamShape<VolterGameContract>({
50
50
  prefix: 'contract',
51
51
  value: options.contract,
52
52
  shape: GAME_CONTRACT_SHAPE,
53
53
  subject,
54
54
  epoch,
55
55
  }),
56
- ...inspectSeamShape<VgaiGameLifecycle>({
56
+ ...inspectSeamShape<VolterGameLifecycle>({
57
57
  prefix: 'contract.lifecycle',
58
58
  value: options.contract.lifecycle,
59
59
  shape: GAME_LIFECYCLE_SHAPE,
60
60
  subject,
61
61
  epoch,
62
62
  }),
63
- ...inspectSeamShape<VgaiGameSystems>({
63
+ ...inspectSeamShape<VolterGameSystems>({
64
64
  prefix: 'contract.systems',
65
65
  value: options.contract.systems,
66
66
  shape: GAME_SYSTEMS_SHAPE,
@@ -22,7 +22,7 @@
22
22
  * something the product itself already acts on:
23
23
  *
24
24
  * - `export` reads what the export path ACTUALLY requires of a project, taken
25
- * from the door's own source: `create-vgai-project/src/deploy.ts` runs
25
+ * from the door's own source: `create-volter-project/src/deploy.ts` runs
26
26
  * `npm run build` in the project (`runProjectBuild`) and stages the `dist/`
27
27
  * that emits (`stageBuildOutput`). Ingest roots pass that door because the
28
28
  * ingest project's own build is already its standalone game; arbitrary
@@ -8,7 +8,7 @@
8
8
  * `editor.*` family — every mounted root, native or ingested, gets a row per
9
9
  * `AuthoringAdapter` provider. It deliberately keeps ONLY that family, on the
10
10
  * grounds that the remaining facts are "the ingested lane's own questions".
11
- * That is true of `contract.*` (a native game declares no `window.vgaiGame`
11
+ * That is true of `contract.*` (a native game declares no `window.volterGame`
12
12
  * and never will) and false of `system.*`: a `SystemAdapters` slot is read off
13
13
  * the editor's OWN live registry (`authoring/active-systems.ts`), which a
14
14
  * native game fills exactly as an ingested one does. So the slots went
@@ -31,7 +31,7 @@
31
31
  * `networking` is the exception, and it is the whole point. Nothing engine-side
32
32
  * builds it: a game registers a `NetworkingAdapter` itself. So its absence is
33
33
  * ruled out only by the PROJECT'S OWN FILE — no `server` block in
34
- * `vgai.project.json` means there is no room to describe. A game that DOES
34
+ * `volter.project.json` means there is no room to describe. A game that DOES
35
35
  * declare a room and binds nothing is `unanswered`, i.e. a standing warning.
36
36
  *
37
37
  * ## Provenance neutrality
@@ -59,7 +59,7 @@ import { inspectSystemAdapterSeam } from '@volter/editor-sdk/kit/system-seam-evi
59
59
  * it. Both facts are read off things that already exist; neither is a guess. */
60
60
  export interface NativeProjectFacts {
61
61
  /**
62
- * `vgai.project.json` declares a `server` block (a Colyseus room) — read from
62
+ * `volter.project.json` declares a `server` block (a Colyseus room) — read from
63
63
  * the active project view (`project-manager.ts`'s `ActiveProject.server`).
64
64
  * The decisive project-level declaration for whether this game is networked.
65
65
  */
@@ -118,7 +118,7 @@ export interface NativeProjectFacts {
118
118
  */
119
119
  const SLOT_LIBRARIES: Partial<Record<SystemAdapterSlot, readonly string[]>> = {
120
120
  physics: ['@react-three/rapier', '@dimforge/rapier3d-compat', '@dimforge/rapier2d-compat'],
121
- networking: ['colyseus.js'],
121
+ networking: ['@colyseus/sdk', 'colyseus.js'],
122
122
  navigation: ['recast-navigation', '@recast-navigation/core'],
123
123
  audio: ['tone', 'howler'],
124
124
  };
@@ -213,7 +213,7 @@ function reasonAcknowledges(reason: string, library: string): boolean {
213
213
 
214
214
  /** The file fact that rules `networking` out, in the file's own terms. */
215
215
  const NO_SERVER_EVIDENCE =
216
- "this project's vgai.project.json declares no `server` block, so there is no room for a " +
216
+ "this project's volter.project.json declares no `server` block, so there is no room for a " +
217
217
  'NetworkingAdapter to describe';
218
218
 
219
219
  /**
@@ -251,7 +251,7 @@ const ENGINE_OWNED_EVIDENCE: Partial<Record<SystemAdapterSlot, string>> = {
251
251
  };
252
252
 
253
253
  /** The fix a native game's author can actually act on, per slot. Never the
254
- * ingested lane's `window.vgaiGame` text, which would be false here. */
254
+ * ingested lane's `window.volterGame` text, which would be false here. */
255
255
  function nativeSlotFix(slot: SystemAdapterSlot, facts: NativeProjectFacts): string {
256
256
  if (!facts.mounted) {
257
257
  return 'nothing is mounted, so the live system registry has not been asked yet — enter Play, or open a project whose roots mount, and the slot reports its real state';
@@ -349,6 +349,19 @@ export function measureNativeSystemAdapters(
349
349
  : `declared absent by root "${absence.rootId}": ${absence.reason}${lastMountNote}`,
350
350
  };
351
351
  }
352
+ // A Colyseus client is the editor's to observe: Play binds its observer of the game's room
353
+ // sockets (`adapter-runtime-bindings.ts`'s `withObservedNetworking`), so an unbound slot while
354
+ // nothing plays is that observer not yet attached, not an adapter the game owes.
355
+ if (slot === 'networking' && libraries.length > 0) {
356
+ return {
357
+ slot,
358
+ state: 'empty',
359
+ attestedBy: 'host',
360
+ evidence:
361
+ `this project ships ${libraries.join(' + ')}; the editor observes its room sockets from ` +
362
+ 'Play, and nothing is connected while editing',
363
+ };
364
+ }
352
365
  // Nothing declared, and the library IS here: the host's inference below
353
366
  // would print a confident absence over real evidence to the contrary. That
354
367
  // is an UNANSWERED question — the only state that is a work order — not a
@@ -9,14 +9,14 @@
9
9
  * ordinary game code and there is no cooperative way for a game to know better.
10
10
  *
11
11
  * So the game realm's `location` is a facade: reads of the game's own
12
- * query keep working, host control-plane keys (`play`, `project`, `vgai-*`,
12
+ * query keep working, host control-plane keys (`play`, `project`, `volter-*`,
13
13
  * …) are stripped from `search`/`href` (bubbo's `getUrlParam('play')` is a
14
14
  * debug skip-to-Game; the editor's `?play=1` autoplay is not that flag),
15
15
  * and every write that would NAVIGATE is refused with a `console.error`
16
16
  * naming the game, the exact assignment, and this mechanism. Refused, never
17
17
  * swallowed — a silent no-op would make "the quit button does nothing" an
18
18
  * unexplainable bug, and the console line is a real product door
19
- * (`vgai status` reports page console errors).
19
+ * (`volter-game-editor status` reports page console errors).
20
20
  *
21
21
  * `hash` is deliberately NOT refused: it changes the URL without leaving the
22
22
  * document, and games use it for their own state.
@@ -49,7 +49,7 @@ const HOST_SEARCH_KEYS = new Set([
49
49
  ]);
50
50
 
51
51
  function isHostSearchKey(key: string): boolean {
52
- return HOST_SEARCH_KEYS.has(key) || key.startsWith('vgai');
52
+ return HOST_SEARCH_KEYS.has(key) || key.startsWith('volter');
53
53
  }
54
54
 
55
55
  /** The search string a game is allowed to read — host keys removed. */
@@ -1,10 +1,10 @@
1
1
  import { commandLine } from '@volter/editor-sdk/kit/product-command';
2
2
  /**
3
- * THE MODULE LANE of `vgai eval` — reach the RUNNING mount's own module
3
+ * THE MODULE LANE of `volter-game-editor eval` — reach the RUNNING mount's own module
4
4
  * instances, by served path, using URLs retained by their owning realm.
5
5
  *
6
6
  * WHY THE MOUNT STAMP IS LOAD-BEARING. Project modules are served per mount
7
- * as `/<path>?vgai-mount=<id>` (`project-module-instance.ts` propagates the
7
+ * as `/<path>?volter-mount=<id>` (`project-module-instance.ts` propagates the
8
8
  * id through the whole project subtree), so browser module identity is
9
9
  * per-instance BY URL. A bare `import('/src/sim/host.ts')` therefore loads a
10
10
  * SECOND, never-ticked copy — the phantom-module trap the old string-command
@@ -25,15 +25,15 @@ import { commandLine } from '@volter/editor-sdk/kit/product-command';
25
25
  // with a guard test on the one true owner.
26
26
  /** Mirrors `project-module-url.ts`'s PROJECT_MOUNT_QUERY (guarded by test —
27
27
  * the two must never drift). */
28
- const PROJECT_MOUNT_QUERY = 'vgai-mount';
28
+ const PROJECT_MOUNT_QUERY = 'volter-mount';
29
29
 
30
30
  let focusedInstanceProvider: (() => string) | null = null;
31
31
  /** The packaged shell and source-served contributions share the host realm owner. */
32
32
  function moduleUrls(instanceId: string): readonly string[] {
33
33
  const host = globalThis as typeof globalThis & {
34
- __vgaiGameModuleUrls?: (id: string) => readonly string[];
34
+ __volterGameModuleUrls?: (id: string) => readonly string[];
35
35
  };
36
- return host.__vgaiGameModuleUrls?.(instanceId) ?? [];
36
+ return host.__volterGameModuleUrls?.(instanceId) ?? [];
37
37
  }
38
38
 
39
39
  /** Wired once by the editor shell (`command-listener.ts`) at boot. */
@@ -76,7 +76,7 @@ export function loadedGameModulePaths(instanceId: string): string[] {
76
76
  }
77
77
 
78
78
  /**
79
- * The `modules` binding of `vgai eval`'s `game.run` scope and of the
79
+ * The `modules` binding of `volter-game-editor eval`'s `game.run` scope and of the
80
80
  * `game-eval` op — a RESOLVER, `modules('src/sim/host.ts')`, that also
81
81
  * ENUMERATES what it can resolve.
82
82
  *
@@ -70,7 +70,7 @@ function captureOf(options?: boolean | AddEventListenerOptions | EventListenerOp
70
70
 
71
71
  /** Mark carrying the text this observer last wrote, so its own write is not
72
72
  * re-scoped and a game's next rewrite is. */
73
- export const SCOPED_STYLE_MARK = 'vgaiScopedCss';
73
+ export const SCOPED_STYLE_MARK = 'volterScopedCss';
74
74
 
75
75
  /**
76
76
  * The `@scope` rewriter, loaded on FIRST USE — the one page-side door to the
@@ -128,7 +128,7 @@ export function loadGameCssScoper(): Promise<(css: string) => string> {
128
128
  * `url.fileURLToPath/pathToFileURL`,
129
129
  * `source-map-js.SourceMapConsumer/SourceMapGenerator` — straight into the
130
130
  * game realm's console, which made the console-silence contract unreachable in
131
- * a fresh scaffold and every `vgai` verb exit non-zero (measured three times:
131
+ * a fresh scaffold and every `volter` verb exit non-zero (measured three times:
132
132
  * the donut, cold-barrel and lit-lanes probes). The chain was
133
133
  * `play-mode.enterPlayModeInner` -> `gated-globals.setGameSurface` ->
134
134
  * `GameRealmPage.surface` -> `observeInjectedStyles` -> `import('../server/
@@ -356,7 +356,7 @@ export class GameRealmPage {
356
356
  if (!surface) return null;
357
357
  if (!this.headElement || this.headElement.parentElement !== surface) {
358
358
  const head = document.createElement('div');
359
- head.dataset['vgaiGameHead'] = '';
359
+ head.dataset['volterGameHead'] = '';
360
360
  head.hidden = true;
361
361
  surface.prepend(head);
362
362
  this.headElement = head;
@@ -26,7 +26,7 @@ import { disposeGameRealm } from './gated-globals';
26
26
  *
27
27
  * The report is the point: a game that released everything it registered is
28
28
  * silent, and a game that did not is named, with the count, on the editor
29
- * console (and therefore in `vgai console`). The editor reclaims either way.
29
+ * console (and therefore in `volter-game-editor console`). The editor reclaims either way.
30
30
  */
31
31
  export function reclaimGameRealm(id: string, name: string): void {
32
32
  const released = disposeGameRealm(id);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Live gameplay recording over the SAME clean game compositor used by
3
- * `vgai screenshot`: world canvases + DOM HUD, no editor chrome.
3
+ * `volter-game-editor screenshot`: world canvases + DOM HUD, no editor chrome.
4
4
  *
5
5
  * This is intentionally a browser primitive, not a CLI workflow. The page
6
6
  * owns `MediaRecorder` and the live pixels/audio, streams bounded chunks to
@@ -21,7 +21,7 @@
21
21
  * A counter for it was written, shipped and REMOVED in the same afternoon: it
22
22
  * keyed on `domOverlays === 0` and therefore reported a clean zero over clips
23
23
  * visibly missing their HUD. A measurement that can only ever say "fine" is
24
- * worse than none, so the limit is stated — here, and in the ack `vgai stop`
24
+ * worse than none, so the limit is stated — here, and in the ack `volter-game-editor stop`
25
25
  * prints — rather than counted. Read the world layer as complete evidence and
26
26
  * the HUD as present-when-present.
27
27
  */
@@ -62,7 +62,7 @@ export interface GameplayRecordingStartOptions {
62
62
  readonly canvasFrame?: CaptureOptions['canvasFrame'];
63
63
  readonly audio?: AudioRecordingHandle | null | undefined;
64
64
  /**
65
- * The file this recording lands in, under the project's `.vgai/recordings/`.
65
+ * The file this recording lands in, under the project's `.volter/recordings/`.
66
66
  * During Play, absent is named after the Gameplay Session; outside one it
67
67
  * falls back to `play-latest.webm`. A name is the caller's own keepsake. The server owns the literals — see
68
68
  * `editor-server.ts`'s `/__editor/recording/start`.
@@ -211,7 +211,7 @@ interface FrameClock {
211
211
  * `setInterval` on the page is the obvious pacer and it is the wrong one for
212
212
  * the case this recorder exists to serve. Chrome clamps a background tab's
213
213
  * timers to 1 Hz, and to roughly 1/min once the tab has been hidden for five
214
- * minutes — and an agent's `vgai edit` tab is hidden BY DESIGN (worktree
214
+ * minutes — and an agent's `volter-game-editor edit` tab is hidden BY DESIGN (worktree
215
215
  * sessions open behind the human's window; see `after-paint.ts` for the same
216
216
  * fact stated for rAF). A 30 fps request would encode as a handful of frames.
217
217
  *
@@ -370,7 +370,7 @@ function samplePreviewFrame(recording: ActiveRecording, mediaTimeMs: number): vo
370
370
  *
371
371
  * The refusal this replaced ("show the editor tab, then start recording")
372
372
  * exempted exactly the sessions the recorder exists for: an agent's
373
- * `vgai edit` tab opens behind the human's window and stays hidden for the
373
+ * `volter-game-editor edit` tab opens behind the human's window and stays hidden for the
374
374
  * whole run, so every unattended playthrough — the ones with no human to
375
375
  * describe what happened — would have produced no evidence at all. What a
376
376
  * hidden tab actually costs is two things, and both are handled rather than
@@ -248,7 +248,7 @@ function realmFunction(value: unknown, receiver: object): unknown {
248
248
  * one pauses its siblings. Neither is fixable in the presentation layer.
249
249
  *
250
250
  * The lookup key comes from the MODULE'S OWN URL: every project module served
251
- * under a mount carries `?vgai-mount=<id>` (the isolation transform), and the
251
+ * under a mount carries `?volter-mount=<id>` (the isolation transform), and the
252
252
  * prelude passes `import.meta.url` to {@link gameRealmForModuleUrl}. So a
253
253
  * module resolves its own realm with no plugin involvement and no threading.
254
254
  */
@@ -402,7 +402,7 @@ export function gameSurfaces(): { surface: HTMLElement; gate: () => boolean }[]
402
402
  */
403
403
  function gateFor(id: string): () => boolean {
404
404
  // AND THE SURFACE TERM (U2). `surfaceHoldsKeyboard()` is true standalone and
405
- // under the frame is the workbench's own "is the vgai pane the active
405
+ // under the frame is the workbench's own "is the volter pane the active
406
406
  // editor?", so a keystroke aimed at Monaco in the group beside a running
407
407
  // game never reaches the game's listeners. It is read HERE, once, rather
408
408
  // than folded into each lane's own predicate, because this is the one place
@@ -434,7 +434,7 @@ function realmGenerationGate(id: string, live: RealmLiveness): () => boolean {
434
434
  function mountIdOfUrl(moduleUrl: string): string {
435
435
  const query = moduleUrl.split('?')[1];
436
436
  if (query === undefined) return DEFAULT_REALM_ID;
437
- return new URLSearchParams(query).get('vgai-mount') ?? DEFAULT_REALM_ID;
437
+ return new URLSearchParams(query).get('volter-mount') ?? DEFAULT_REALM_ID;
438
438
  }
439
439
 
440
440
  /** The realm whose code is synchronously executing right now. Console capture
@@ -865,12 +865,12 @@ export function makeGatedProxy<T extends EventTarget>(
865
865
  };
866
866
 
867
867
  /** Report a refused navigation on the page's own console — which is a real
868
- * product door: `vgai status` reports page console errors. */
868
+ * product door: `volter-game-editor status` reports page console errors. */
869
869
  const refuseNavigation = (attempt: string): void => {
870
870
  // A NEW native console.error site, suppressed to keep this task's diff at
871
871
  // zero new lint warnings — and it is deliberately native rather than
872
872
  // `editorConsole`: game code runs in the page, and the page console is the
873
- // surface `vgai status` already reads (same reasoning as
873
+ // surface `volter-game-editor status` already reads (same reasoning as
874
874
  // `ingest-root-adapter.ts`'s loop-gate warning).
875
875
  // biome-ignore lint/suspicious/noConsole: see comment above
876
876
  console.error(refusedNavigationMessage(attempt));
@@ -1115,9 +1115,9 @@ function createOwnedRealmProxy<T extends EventTarget>(
1115
1115
  if (refusalReported) return;
1116
1116
  refusalReported = true;
1117
1117
  const realm = options.realmId ? `"${options.realmId}"` : 'the default realm';
1118
- // biome-ignore lint/suspicious/noConsole: game code runs in the page, and the page console is the surface `vgai status` reads (same reasoning as `refuseNavigation` above)
1118
+ // biome-ignore lint/suspicious/noConsole: game code runs in the page, and the page console is the surface `volter-game-editor status` reads (same reasoning as `refuseNavigation` above)
1119
1119
  console.warn(
1120
- `vgai: a stopped game tried to register ${what} on its ${options.role} after its realm ` +
1120
+ `volter: a stopped game tried to register ${what} on its ${options.role} after its realm ` +
1121
1121
  `(${realm}) was reclaimed; refused. Later refusals in this generation are silent.`,
1122
1122
  );
1123
1123
  };
@@ -1460,10 +1460,10 @@ function publishDefaultRealmGlobals(): void {
1460
1460
  const g = globalThis as unknown as Record<string, unknown>;
1461
1461
  const base = gameRealmForMountId();
1462
1462
  loopGate = defaultLoopGate;
1463
- g['__vgaiGameTimers'] = base.timers;
1464
- g['__vgaiGameWindow'] = base.window;
1465
- g['__vgaiGameDocument'] = base.document;
1466
- g['__vgaiGameConsole'] = base.console;
1463
+ g['__volterGameTimers'] = base.timers;
1464
+ g['__volterGameWindow'] = base.window;
1465
+ g['__volterGameDocument'] = base.document;
1466
+ g['__volterGameConsole'] = base.console;
1467
1467
  }
1468
1468
 
1469
1469
  /**
@@ -1494,8 +1494,8 @@ export function installGatedGameGlobals(): void {
1494
1494
  // The microtask pop bounds the window: it runs when the current synchronous
1495
1495
  // evaluation chunk yields, before the mount's own import().then
1496
1496
  // continuation (queued later) can run editor code.
1497
- g['__vgaiGameModuleUrls'] = loadedGameRealmModuleUrls;
1498
- g['__vgaiGameRealm'] = (mountId: string): GameRealm => {
1497
+ g['__volterGameModuleUrls'] = loadedGameRealmModuleUrls;
1498
+ g['__volterGameRealm'] = (mountId: string): GameRealm => {
1499
1499
  executingRealms.push(mountId);
1500
1500
  queueMicrotask(() => {
1501
1501
  const at = executingRealms.lastIndexOf(mountId);
@@ -47,7 +47,7 @@ import type { ResolvedAdapter, ResolvedAdapterRoot } from '@volter/editor-projec
47
47
  import { loadGameManifest, type ResolvedGameManifest } from '@volter/editor-project/manifest/load';
48
48
 
49
49
  /** The one manifest glob. Every in-tree ingest fixture, whatever its surface. */
50
- const manifestModules = import.meta.glob('./games/*/vgai.project.json', {
50
+ const manifestModules = import.meta.glob('./games/*/volter.project.json', {
51
51
  eager: true,
52
52
  import: 'default',
53
53
  }) as Record<string, unknown>;
@@ -58,7 +58,7 @@ const manifestModules = import.meta.glob('./games/*/vgai.project.json', {
58
58
  * the editor's realm. `.d.ts` is excluded: an ambient declaration file
59
59
  * is not a module and must never become a dynamic-import chunk.
60
60
  *
61
- * `vgai.adapter.ts` is excluded too, and for a different reason: it is not a
61
+ * `volter.adapter.ts` is excluded too, and for a different reason: it is not a
62
62
  * GAME module at all. It is host-realm DECLARATION (see {@link adapterModules}),
63
63
  * read without booting anything, and a manifest that named it as an `entry` or
64
64
  * a `contractShim` would be nonsense — so it is not in the set those fields
@@ -68,15 +68,15 @@ export const entryModules = import.meta.glob([
68
68
  './games/*/*.js',
69
69
  './games/*/*.ts',
70
70
  '!./games/*/*.d.ts',
71
- '!./games/*/vgai.adapter.ts',
71
+ '!./games/*/volter.adapter.ts',
72
72
  ]) as Record<string, () => Promise<unknown>>;
73
73
 
74
74
  /**
75
- * THE ADAPTER GLOB — one `vgai.adapter.ts` per ingest game, keyed by game id.
75
+ * THE ADAPTER GLOB — one `volter.adapter.ts` per ingest game, keyed by game id.
76
76
  *
77
77
  * ARCHITECTURE-CORE §The editor protocol: "Placement follows REALM: game-realm
78
78
  * code (a shim that runs inside the game) lives with the game's bundle;
79
- * host-realm declaration (`vgai.adapter.ts`) lives where the host can import it
79
+ * host-realm declaration (`volter.adapter.ts`) lives where the host can import it
80
80
  * as a real module — a repo-vendored bundle's adapter file lives in the host's
81
81
  * in-tree registry, never inside the verbatim-served bundle." This directory IS
82
82
  * that registry, so it holds BOTH populations:
@@ -86,7 +86,7 @@ export const entryModules = import.meta.glob([
86
86
  * its bytes are served verbatim from `public/ingest/<id>/` and hashed by
87
87
  * `vendor/games/verify-unaltered.mjs`, so nothing host-owned may go there.
88
88
  *
89
- * A folder with no `vgai.project.json` is invisible to {@link manifestModules}
89
+ * A folder with no `volter.project.json` is invisible to {@link manifestModules}
90
90
  * and therefore to {@link discoverIngestEntries} — the second population adds no
91
91
  * fixtures, only declarations.
92
92
  *
@@ -98,18 +98,18 @@ export const entryModules = import.meta.glob([
98
98
  * be used to fix that file"). Vite resolves the glob statically in dev and in
99
99
  * a production build alike, so no generated dispatch table is needed.
100
100
  */
101
- const adapterModules = import.meta.glob('./games/*/vgai.adapter.ts') as Record<
101
+ const adapterModules = import.meta.glob('./games/*/volter.adapter.ts') as Record<
102
102
  string,
103
103
  () => Promise<unknown>
104
104
  >;
105
105
 
106
106
  /** The adapter module's filename — the contract's ONE spelling, host side. */
107
- const ADAPTER_FILENAME = 'vgai.adapter.ts';
107
+ const ADAPTER_FILENAME = 'volter.adapter.ts';
108
108
 
109
109
  /** This directory's repo path, so a published `modulePath` names a real file. */
110
110
  const REGISTRY_REPO_DIR = 'packages/editor/src/ingest/games';
111
111
 
112
- const ADAPTER_KEY_RE = /^\.\/games\/([^/]+)\/vgai\.adapter\.ts$/;
112
+ const ADAPTER_KEY_RE = /^\.\/games\/([^/]+)\/volter\.adapter\.ts$/;
113
113
 
114
114
  /**
115
115
  * THE LOOKUP KEY IS THE GAME ID; THE STORAGE KEY IS THE FOLDER NAME. What makes
@@ -124,8 +124,8 @@ const ADAPTER_KEY_RE = /^\.\/games\/([^/]+)\/vgai\.adapter\.ts$/;
124
124
  *
125
125
  * The invariant is therefore `folder id === the id that game's manifest
126
126
  * declares`, for BOTH populations this registry serves — in-tree fixtures
127
- * (`./games/<id>/vgai.project.json`) and public bundles
128
- * (`public/ingest/<id>/vgai.project.json`, whose registry folder holds only the
127
+ * (`./games/<id>/volter.project.json`) and public bundles
128
+ * (`public/ingest/<id>/volter.project.json`, whose registry folder holds only the
129
129
  * adapter file). It is guarded ONCE, statically, in
130
130
  * `packages/editor/test/ingest-adapter-modules.test.ts`, which reads both id
131
131
  * spaces off disk — the only realm that can, since `public/` is outside the
@@ -167,7 +167,7 @@ export const assetUrls = import.meta.glob('./games/*/assets/**', {
167
167
  import: 'default',
168
168
  }) as Record<string, string>;
169
169
 
170
- const MANIFEST_KEY_RE = /^\.\/games\/([^/]+)\/vgai\.project\.json$/;
170
+ const MANIFEST_KEY_RE = /^\.\/games\/([^/]+)\/volter\.project\.json$/;
171
171
 
172
172
  /** Folder-relative glob key for a file inside a discovered game's folder. */
173
173
  export function gameFileKey(folderId: string, relPath: string): string {
@@ -206,14 +206,14 @@ function buildEntry(folderId: string, raw: unknown): IngestEntry {
206
206
  const roots = declaredRoots(manifest);
207
207
  if (roots.length !== 1) {
208
208
  throw new Error(
209
- `ingest registry: "${folderId}/vgai.project.json" must declare exactly one root ` +
209
+ `ingest registry: "${folderId}/volter.project.json" must declare exactly one root ` +
210
210
  `(found ${roots.length}).`,
211
211
  );
212
212
  }
213
213
  const root = roots[0]!;
214
214
  if (root.adapter.type !== 'ingest') {
215
215
  throw new Error(
216
- `ingest registry: "${folderId}/vgai.project.json"'s root must be an { ingest } root ` +
216
+ `ingest registry: "${folderId}/volter.project.json"'s root must be an { ingest } root ` +
217
217
  `(found adapter identity "${root.adapter.identity}").`,
218
218
  );
219
219
  }