@volter/editor-game 0.5.67 → 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 (173) hide show
  1. package/NOTICE +7 -7
  2. package/contributions/autoplay.service.ts +1 -1
  3. package/contributions/build-player.document.tsx +95 -0
  4. package/contributions/build-profiles.document.tsx +1 -1
  5. package/contributions/build-progress.status.tsx +2 -2
  6. package/contributions/build.header.tsx +1 -1
  7. package/contributions/connection.status.tsx +1 -1
  8. package/contributions/coverage.service.ts +2 -2
  9. package/contributions/game-eval.command.ts +6 -6
  10. package/contributions/gameplay.command.ts +2 -2
  11. package/contributions/generations.status.tsx +1 -1
  12. package/contributions/ingest.service.ts +2 -2
  13. package/contributions/play.command.ts +6 -6
  14. package/contributions/react/react-inspector.service.ts +1 -1
  15. package/package.json +9 -8
  16. package/serving/index.ts +1 -1
  17. package/src/asset-budget/AssetBudgetPanel.tsx +1 -1
  18. package/src/asset-budget/asset-budget-model.ts +14 -14
  19. package/src/asset-budget/optimize-apply.ts +8 -8
  20. package/src/bridge/call.ts +3 -3
  21. package/src/bridge/dispatch.ts +12 -12
  22. package/src/bridge/screenshot.ts +6 -6
  23. package/src/build/BuildProfilesPanel.tsx +19 -8
  24. package/src/build/build-session.ts +35 -0
  25. package/src/canvas/canvas-board/CanvasBoardDocument.tsx +78 -5
  26. package/src/canvas/canvas-board/canvas-component-board.ts +1 -1
  27. package/src/canvas/canvas-design-mount.ts +1 -1
  28. package/src/coverage/live-project-verbs.ts +3 -3
  29. package/src/coverage/native-system-coverage.ts +3 -3
  30. package/src/coverage/root-coverage.ts +2 -2
  31. package/src/coverage/session-coverage.ts +2 -2
  32. package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +2 -2
  33. package/src/game-document/DevicePresetPicker.tsx +6 -6
  34. package/src/game-document/GameCaptureFrameButton.tsx +1 -1
  35. package/src/game-document/GameDocument.tsx +2 -2
  36. package/src/game-document/GamePanel.tsx +9 -9
  37. package/src/game-document/InstanceInspectorPicker.tsx +1 -1
  38. package/src/game-document/device-preview.ts +4 -4
  39. package/src/game-document/physics-debug.ts +2 -2
  40. package/src/generation/GenerationActivity.tsx +22 -22
  41. package/src/generation/GenerationGallery.css +79 -79
  42. package/src/generation/generation-documents.tsx +25 -25
  43. package/src/generation/generation-presentation.ts +1 -1
  44. package/src/host/adapter-reach.ts +1 -1
  45. package/src/host/adapter-runtime-bindings.ts +5 -5
  46. package/src/host/after-paint.ts +3 -3
  47. package/src/host/api/configurations.ts +1 -1
  48. package/src/host/authoring/canvas-runtime-recognition.ts +2 -2
  49. package/src/host/authoring/contract-hierarchy-authoring.ts +6 -6
  50. package/src/host/authoring/contract-scenes-stories.ts +5 -5
  51. package/src/host/authoring/ingest-data-writer.ts +1 -1
  52. package/src/host/authoring/ingest-source-persistence.ts +2 -2
  53. package/src/host/authoring/mount-isolated-pixi-screen.ts +1 -1
  54. package/src/host/authoring/pixi-authoring-adapter.ts +206 -28
  55. package/src/host/authoring/pixi-creatable-kinds.ts +80 -0
  56. package/src/host/authoring/pixi-live-write-target.ts +6 -5
  57. package/src/host/authoring/pixi-source-write-target.ts +118 -20
  58. package/src/host/authoring/pixi-structure-history.ts +3 -3
  59. package/src/host/binding-resolver.ts +6 -6
  60. package/src/host/browser-transpile.ts +10 -10
  61. package/src/host/canvas-preview-frames.ts +1 -1
  62. package/src/host/components/CameraAuthoringOverlay.tsx +14 -14
  63. package/src/host/components/HeaderTelemetry.tsx +11 -11
  64. package/src/host/components/PixiIsolationSceneContent.tsx +3 -3
  65. package/src/host/components/ResolutionPicker.tsx +4 -4
  66. package/src/host/components/scene-document.tsx +3 -3
  67. package/src/host/components/world-root-stage-binding.tsx +1 -1
  68. package/src/host/components/world-root-stage.ts +1 -1
  69. package/src/host/coverage/authoring-read-probe.ts +1 -1
  70. package/src/host/coverage/capability-coverage.ts +22 -22
  71. package/src/host/coverage/game-contract-seam-evidence.ts +8 -8
  72. package/src/host/coverage/project-verb-coverage.ts +1 -1
  73. package/src/host/coverage/system-adapter-coverage.ts +19 -6
  74. package/src/host/game-location-guard.ts +3 -3
  75. package/src/host/game-module-access.ts +6 -6
  76. package/src/host/game-realm-page.ts +3 -3
  77. package/src/host/game-realm-reclaim.ts +1 -1
  78. package/src/host/gameplay-recording.ts +5 -5
  79. package/src/host/gated-globals.ts +13 -13
  80. package/src/host/ingest/registry.ts +14 -14
  81. package/src/host/play-control-hook.ts +1 -1
  82. package/src/host/playwright-shim.ts +2 -2
  83. package/src/host/projection/pixi.ts +2 -2
  84. package/src/host/react-mount-runtime.ts +1 -1
  85. package/src/host/roots/canvas-root.tsx +13 -1
  86. package/src/host/roots/r3f-root.tsx +1 -1
  87. package/src/host/scene-view-drawability.ts +1 -1
  88. package/src/host/sdk/tools.ts +1 -1
  89. package/src/host/served-bundle-runtime-modules.ts +2 -0
  90. package/src/host/staged-projects.ts +1 -1
  91. package/src/host/stories/story-pixi-preview.ts +1 -1
  92. package/src/host/stories/story-three-preview.ts +1 -1
  93. package/src/host/three-ingest-runtime.ts +1 -1
  94. package/src/ingest/active-ingest.ts +1 -1
  95. package/src/ingest/authoring/ingest-dom-surface-authoring.ts +4 -4
  96. package/src/ingest/authoring/ingest-root-adapter.ts +11 -11
  97. package/src/ingest/capture-wait-report.ts +4 -4
  98. package/src/ingest/discovery-public-ingest.ts +4 -4
  99. package/src/ingest/dom-stub-mark.ts +1 -1
  100. package/src/ingest/entry-load.ts +1 -1
  101. package/src/ingest/game-contract-realm.ts +3 -3
  102. package/src/ingest/game-pointer-lock.ts +1 -1
  103. package/src/ingest/ingest-canvas-scene-document.tsx +3 -3
  104. package/src/ingest/ingest-evidence-hook.ts +6 -6
  105. package/src/ingest/ingest-frame-snapshot.ts +2 -2
  106. package/src/ingest/ingest-play-commands.ts +1 -1
  107. package/src/ingest/ingest-play-control.ts +11 -11
  108. package/src/ingest/ingest-render-debug.ts +5 -5
  109. package/src/ingest/ingest-siblings.ts +3 -3
  110. package/src/ingest/module-mode.ts +2 -2
  111. package/src/ingest/mount-canvas-ingest-root.ts +10 -10
  112. package/src/ingest/mount-coverage.ts +3 -3
  113. package/src/ingest/mount-dom-ingest-root.ts +7 -7
  114. package/src/ingest/mount-ingest-root.ts +10 -10
  115. package/src/ingest/mount-three-ingest-root.ts +5 -5
  116. package/src/ingest/resolve-three.ts +2 -2
  117. package/src/ingest/served-bundle.ts +6 -6
  118. package/src/ingest/served-html-boot.ts +8 -8
  119. package/src/ingest/surface-dom.ts +9 -9
  120. package/src/ingest/surface-three.ts +1 -1
  121. package/src/ingest/types.ts +1 -1
  122. package/src/ingest/unmount-ingest-root.ts +3 -3
  123. package/src/network/NetworkInspectorPanel.tsx +521 -54
  124. package/src/network/network-inspector-model.ts +6 -0
  125. package/src/play/play-boot-stall.ts +1 -1
  126. package/src/play/play-mode.ts +31 -30
  127. package/src/play/play-recording.ts +12 -12
  128. package/src/play-bar/PlayBar.tsx +8 -8
  129. package/src/play-bar/PlayerCountPicker.tsx +3 -3
  130. package/src/profiler/FrameDebuggerPanel.tsx +2 -2
  131. package/src/profiler/PerformancePanel.tsx +4 -4
  132. package/src/react/design-time-react-mount.ts +5 -5
  133. package/src/react/dom-authoring-adapter.ts +3 -3
  134. package/src/react/react-inspector-section.tsx +2 -2
  135. package/src/react/react-world-authoring-adapter.ts +20 -20
  136. package/src/react/story-documents/story-documents.tsx +4 -4
  137. package/src/react/ui-component-board.ts +1 -1
  138. package/src/runtime/adapter/audio-meter.ts +1 -1
  139. package/src/runtime/adapter/ingest/contract-debug-adapter.ts +4 -4
  140. package/src/runtime/adapter/ingest/contract-system-adapters.ts +9 -9
  141. package/src/runtime/adapter/ingest/merge-debug-adapters.ts +2 -2
  142. package/src/runtime/adapter/ingest/observation-debug-adapter.ts +1 -1
  143. package/src/runtime/adapter/native-debug-module.ts +5 -5
  144. package/src/runtime/audio/pose-guard.ts +1 -1
  145. package/src/runtime/core/game-scoped-slot.ts +1 -1
  146. package/src/runtime/create-runtime.ts +15 -15
  147. package/src/runtime/debug-bridge.ts +25 -25
  148. package/src/runtime/debug-registry.ts +17 -17
  149. package/src/runtime/dev/instruments.ts +1 -1
  150. package/src/runtime/dev/performance-profiler.ts +2 -2
  151. package/src/runtime/dev/register-render-vitals.ts +2 -2
  152. package/src/runtime/dev/static-batch-advisor.ts +3 -3
  153. package/src/runtime/dev-build.ts +3 -3
  154. package/src/runtime/game.ts +5 -5
  155. package/src/runtime/input-router.ts +24 -11
  156. package/src/runtime/mount-manifest.ts +9 -9
  157. package/src/runtime/pixi/authoring.ts +1 -1
  158. package/src/runtime/pixi/ingest.ts +1 -1
  159. package/src/runtime/presentation.ts +1 -1
  160. package/src/runtime/render-control.ts +21 -21
  161. package/src/runtime/render-seed.ts +3 -3
  162. package/src/runtime/run-ticks-settled.ts +1 -1
  163. package/src/services/game-audio.ts +3 -3
  164. package/src/services/game-network.ts +125 -15
  165. package/src/three/authoring/model-asset-inspector-section.css +15 -15
  166. package/src/three/authoring/model-asset-inspector-section.tsx +7 -7
  167. package/src/three/authoring/r3f-design-session.ts +10 -10
  168. package/src/three/authoring/r3f-source-authoring-adapter.ts +5 -5
  169. package/src/three/authoring/three-authoring-adapter.ts +5 -4
  170. package/src/three/authoring/typed-three-inspector.ts +1 -1
  171. package/src/three/story-documents/three-story-documents.tsx +3 -3
  172. package/src/three/three-board/board-scene.ts +9 -9
  173. package/src/three/three-board/three-component-board.ts +1 -1
@@ -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
  }
@@ -4,7 +4,7 @@
4
4
  * `PlayBar` renders two different transports — the native one (title "Play
5
5
  * (run game)") and the ingest one (label "Run ingested game") — and anything
6
6
  * outside the component that needs to find "the play control" was matching a
7
- * LABEL. `vgai doctor` polled for the native string as its editor-readiness
7
+ * LABEL. A probe polled for the native string as its editor-readiness
8
8
  * boundary and therefore waited out its whole timeout budget on every ingest
9
9
  * project, which renders the other one (SimCity ingest dogfood, S-6).
10
10
  *
@@ -8,7 +8,7 @@
8
8
  * `page-script` relay op constructs one per call and hands it to a
9
9
  * reconstructed step function; a real `@playwright/test` `Page` drives the SAME
10
10
  * step file when the spec runs under `PageTransport`
11
- * (`packages/vgai-live/src/game-client/client.ts`) in CI. That duality is why
11
+ * (`packages/volter-live/src/game-client/client.ts`) in CI. That duality is why
12
12
  * `createPageShim`'s return value is typed `as Page` — every implemented member
13
13
  * matches Playwright's own shape closely enough that a step written against it
14
14
  * compiles against the real type too.
@@ -41,7 +41,7 @@
41
41
  * under both `PageTransport` (real Playwright, real closures) and
42
42
  * `RelayTransport` (this shim, serialized) must be written as though ALWAYS
43
43
  * serialized — inline every value the step needs; see
44
- * `packages/vgai-live/src/game-client/client.ts`'s `GameClient.page()` doc comment for
44
+ * `packages/volter-live/src/game-client/client.ts`'s `GameClient.page()` doc comment for
45
45
  * the client-facing half of this contract.
46
46
  */
47
47
 
@@ -179,8 +179,8 @@ export class PixiProjector {
179
179
  if (rect.width <= 0 || rect.height <= 0) return null;
180
180
  const mapped = this.mapping?.pointFromClient?.(clientX, clientY, rect) ?? null;
181
181
  if (this.mapping?.pointFromClient) return mapped;
182
- const logicalWidth = Number(surface.dataset?.['vgaiStageWidth'] ?? rect.width);
183
- const logicalHeight = Number(surface.dataset?.['vgaiStageHeight'] ?? rect.height);
182
+ const logicalWidth = Number(surface.dataset?.['volterStageWidth'] ?? rect.width);
183
+ const logicalHeight = Number(surface.dataset?.['volterStageHeight'] ?? rect.height);
184
184
  if (!(logicalWidth > 0) || !(logicalHeight > 0)) return null;
185
185
  return {
186
186
  x: (clientX - rect.left) * (logicalWidth / rect.width),
@@ -54,7 +54,7 @@ function staticReactRootMountRuntime(): ReactRootMountRuntime {
54
54
 
55
55
  /**
56
56
  * Import + shape-check the packaged runtime's synthetic
57
- * `/__vgai-react-world-runtime` module (`vite-plugin-module-doorways.ts`,
57
+ * `/__volter-react-world-runtime` module (`vite-plugin-module-doorways.ts`,
58
58
  * registered only by `packaged.ts`'s project-rooted Vite instance and by
59
59
  * `vitest.config.ts` for test coverage — never by `dev.ts`/the root
60
60
  * `vite.config.ts`). A loud, named failure if the module resolves but is
@@ -134,7 +134,7 @@ function canvasWorldAdapter(
134
134
  throw new Error(
135
135
  `canvas world "${id}": this lane has already mounted this canvas. @pixi/react keys ` +
136
136
  'its reconciler roots off the canvas element, so re-using one would resurrect a ' +
137
- 'root whose Application is destroyed. Hand each mount a fresh canvas (every vgai ' +
137
+ 'root whose Application is destroyed. Hand each mount a fresh canvas (every volter ' +
138
138
  'host already does).',
139
139
  );
140
140
  }
@@ -307,6 +307,18 @@ function canvasWorldAdapter(
307
307
  // the host only gates/advances it.
308
308
  mountedApp.ticker.update(elapsedMs);
309
309
  },
310
+ // Pixi's own hit test finds only interactive objects (`eventMode` static or dynamic), so a
311
+ // 2D layer claims its tappable objects and lets every other point fall through to the world beneath.
312
+ hitTest(x: number, y: number): boolean {
313
+ if (disposed) return false;
314
+ // Pixi points its boundary at the last rendered scene inside each of its own pointer
315
+ // handlers; a hit test asked from outside them does the same, or finds no root.
316
+ const boundary = mountedApp.renderer.events.rootBoundary;
317
+ const rendered = mountedApp.renderer.lastObjectRendered;
318
+ if (!rendered) return false;
319
+ boundary.rootTarget = rendered;
320
+ return boundary.hitTest(x, y) !== null;
321
+ },
310
322
  resize(width: number, height: number): void {
311
323
  if (disposed) return;
312
324
  // `autoDensity: true` makes Pixi re-stamp `canvas.style.width`/
@@ -208,7 +208,7 @@ function threeWorldAdapter(id: string, component: ComponentType, runtime: R3FRun
208
208
  Fragment,
209
209
  null,
210
210
  content,
211
- createElement(MountEffectsReady, { key: 'vgai-mount-effects-ready' }),
211
+ createElement(MountEffectsReady, { key: 'volter-mount-effects-ready' }),
212
212
  );
213
213
  // A reconcile-time crash (e.g. a missing `extend` catalogue entry)
214
214
  // surfaces as an uncaught window error and `onCreated` never fires —
@@ -21,7 +21,7 @@
21
21
  * throw, attributes it to that scene, and stops re-throwing it forever.
22
22
  *
23
23
  * The game is NOT lost when this fires: its own renderer keeps drawing into its
24
- * own canvas, which the host adopted, so the Game tab and `vgai screenshot`
24
+ * own canvas, which the host adopted, so the Game tab and `volter-game-editor screenshot`
25
25
  * show the real thing. What is lost is the editor-camera Scene view of it,
26
26
  * which is exactly what the message says.
27
27
  */
@@ -5,7 +5,7 @@
5
5
  * input/result schemas, structured error codes, and the metadata a caller reads
6
6
  * before invoking (`permission`, `host`, `mutates`, `supportsDryRun`). The
7
7
  * contract exists because a tool is called across a process boundary — CLI to
8
- * editor to node host, and `vgai mcp` to an external agent over stdio — where
8
+ * editor to node host, and `volter mcp` to an external agent over stdio — where
9
9
  * you cannot throw. `ToolRegistry.dispatch` turns every expected failure
10
10
  * (unknown name, bad input, an `impl` throw, a bad return) into a typed outcome
11
11
  * instead.
@@ -172,6 +172,8 @@ export const BUNDLE_RUNTIME_MODULE_LOADERS: Record<string, () => Promise<unknown
172
172
  // against the same sweep.
173
173
  '@colyseus/sdk': () => import('@colyseus/sdk'), // template main.ts
174
174
  'react-dom': () => import('react-dom'), // template main.ts
175
+ 'pixi.js': () => import('pixi.js'), // template main.ts (a `canvas` root)
176
+ '@pixi/react': () => import('@pixi/react'), // template main.ts (a `canvas` root)
175
177
  // ---- Editor-citizen modules PROJECT TOOL CONTRIBUTIONS import. A
176
178
  // contribution is project source rendered inside the editor's own panels,
177
179
  // so these must resolve to the editor's LIVE modules — a second copy of the
@@ -20,5 +20,5 @@ export function isSafeIngestId(id: string): boolean {
20
20
  }
21
21
 
22
22
  export function publicIngestManifestUrl(id: string): string {
23
- return `${PUBLIC_INGEST_BASE}${id}/vgai.project.json`;
23
+ return `${PUBLIC_INGEST_BASE}${id}/volter.project.json`;
24
24
  }
@@ -350,7 +350,7 @@ const FIRST_FRAME_TIMEOUT_MS = PIXI_MOUNT_TIMEOUT_MS;
350
350
  * Wait until every collected `Application` has PRESENTED a frame with content
351
351
  * in it — the readiness test a capture of a canvas story owes itself.
352
352
  *
353
- * MEASURED DEFECT (this is why the function exists): `vgai screenshot
353
+ * MEASURED DEFECT (this is why the function exists): `volter-game-editor screenshot
354
354
  * <file>.stories.tsx` photographed a `@pixi/react` story blank. The capture
355
355
  * lane's own readiness test is "the container has committed child nodes", and
356
356
  * `<Application>` commits its `<canvas>` on the FIRST commit — before
@@ -150,7 +150,7 @@ export interface MountedStoryObject3D {
150
150
 
151
151
  /** The name of the wrapper `<group>` every story is rendered into, so its root
152
152
  * `Object3D` can be extracted unambiguously from fiber's scene. */
153
- export const PREVIEW_ROOT_NAME = 'vgai:story-preview-root';
153
+ export const PREVIEW_ROOT_NAME = 'volter:story-preview-root';
154
154
 
155
155
  /** How long to wait for fiber's first commit before giving up. The LAST-RESORT
156
156
  * ceiling only: a reconcile-time crash is now caught by
@@ -4,7 +4,7 @@
4
4
  * `canvas-entry-runtime.ts`'s `resolveCanvasPixiForEditor`.
5
5
  *
6
6
  * See `../vite-plugin-module-doorways.ts` for the measured failure this
7
- * closes and for why the ingest lane does not borrow `/__vgai-r3f-runtime`.
7
+ * closes and for why the ingest lane does not borrow `/__volter-r3f-runtime`.
8
8
  *
9
9
  * A mount site resolves this ONCE and hands what it gets to everything it
10
10
  * builds for that game. Nothing further down reaches for a static import: a
@@ -108,7 +108,7 @@ export type ActiveIngest = (
108
108
  ) & {
109
109
  siblings: SiblingMount[];
110
110
  /** The mounted world's id — the SAME id every log line and the
111
- * `__vgaiIngest` hook's `gameId` names. Carried on the slot (rather than
111
+ * `__volterIngest` hook's `gameId` names. Carried on the slot (rather than
112
112
  * re-derived) so the status facet can report WHICH world is live
113
113
  * without a second source of truth (S-1). */
114
114
  worldId: string;
@@ -20,7 +20,7 @@ import {
20
20
  walkOidTree,
21
21
  } from '../../react/react-world-authoring-adapter';
22
22
  import type { AuthoringAdapter } from '@volter/editor-project/adapter';
23
- import type { VgaiGameContract } from '@volter/editor-project/adapter/ingest/game-contract';
23
+ import type { VolterGameContract } from '@volter/editor-project/adapter/ingest/game-contract';
24
24
 
25
25
  type ReadableDomRoot = OverlayElement & DomElementLike & { readonly ownerDocument?: Document };
26
26
 
@@ -50,7 +50,7 @@ function iframeDocumentRoot(hostEl: HTMLElement): ReadableDomRoot | null {
50
50
 
51
51
  function resolveGameDomRoot(
52
52
  hostEl: HTMLElement,
53
- declaredRoot: VgaiGameContract['root'] | undefined,
53
+ declaredRoot: VolterGameContract['root'] | undefined,
54
54
  ): ReadableDomRoot | null {
55
55
  if (isReadableDomRoot(declaredRoot)) return declaredRoot;
56
56
  return iframeDocumentRoot(hostEl) ?? (isReadableDomRoot(hostEl) ? hostEl : null);
@@ -143,7 +143,7 @@ export function withDetectedDomSurface(args: {
143
143
  primary: AuthoringAdapter;
144
144
  worldId: string;
145
145
  hostEl: HTMLElement;
146
- declaredRoot?: VgaiGameContract['root'];
146
+ declaredRoot?: VolterGameContract['root'];
147
147
  store: EditorShellStore;
148
148
  }): AuthoringAdapter {
149
149
  const gameRoot = resolveGameDomRoot(args.hostEl, args.declaredRoot);
@@ -158,7 +158,7 @@ export function withDetectedDomSurface(args: {
158
158
  // refuse every detected DOM sibling before the ingest could mount.
159
159
  const domUiJournalId = `${args.worldId}/dom-ui`;
160
160
  const liveUiRoot: DomElementLike & OidElementLike = {
161
- tagName: 'vgai-dom-surface',
161
+ tagName: 'volter-dom-surface',
162
162
  id: '',
163
163
  className: '',
164
164
  get children() {
@@ -385,7 +385,7 @@ function bootWindowPageErrors(startedAt: number): string[] {
385
385
  /**
386
386
  * Wait for the game's world to be BUILT, declaration first.
387
387
  *
388
- * A game that declares `window.vgaiGame.ready` is awaited exactly once and the
388
+ * A game that declares `window.volterGame.ready` is awaited exactly once and the
389
389
  * measured poll never runs — the game states when it is done, so the host has
390
390
  * nothing to estimate. Everything else keeps {@link waitForSceneToSettle},
391
391
  * which is the MEASURED fallback and is labelled as such wherever readiness is
@@ -408,7 +408,7 @@ async function awaitWorldReady(
408
408
  return 'declared';
409
409
  } catch (err) {
410
410
  editorConsole.error(
411
- `Ingest game "${gameId}" declared \`window.vgaiGame.ready\` and it REJECTED (${String(err)}) ` +
411
+ `Ingest game "${gameId}" declared \`window.volterGame.ready\` and it REJECTED (${String(err)}) ` +
412
412
  '— the world was already captured, so the host fell back to the measured settle wait. ' +
413
413
  'This root now reports readiness as measured.',
414
414
  'ingest',
@@ -442,8 +442,8 @@ async function waitForSceneToSettle(scene: THREE.Scene, maxMs = 5000): Promise<v
442
442
  * Some games append their canvas to `document.body` — reparent it into the
443
443
  * host. A DOM-hybrid game (React/R3F with HTML UI: HUDs, overlay panels, drei
444
444
  * `<Html>` portals) can declare the element that OWNS its canvas via
445
- * `window.vgaiGame.root` (the declared game→host contract, game-contract.ts;
446
- * `__vgaiGameRoot` is the pre-contract alias). Adopting only the bare canvas
445
+ * `window.volterGame.root` (the declared game→host contract, game-contract.ts;
446
+ * `__volterGameRoot` is the pre-contract alias). Adopting only the bare canvas
447
447
  * would strand that UI at page level over the editor chrome, and following the
448
448
  * canvas would require the game to know host layout internals — an arcane
449
449
  * demand. Adopt the declared root wholesale so the game's own DOM structure
@@ -472,7 +472,7 @@ function adoptGameDomRoot(hostEl: HTMLElement, surface: HTMLElement): HTMLElemen
472
472
  const realmWindow = ingestGameRealmWindow();
473
473
  const declaredRoot =
474
474
  readIngestGameContract()?.root ??
475
- (realmWindow as unknown as { __vgaiGameRoot?: unknown }).__vgaiGameRoot;
475
+ (realmWindow as unknown as { __volterGameRoot?: unknown }).__volterGameRoot;
476
476
  const declared =
477
477
  declaredRoot instanceof HTMLElement && declaredRoot.contains(surface) ? declaredRoot : surface;
478
478
  if (declared.contains(hostEl)) return hostEl;
@@ -516,7 +516,7 @@ export async function mountIngestGame(
516
516
  // Host policy, not per-game CSS — see `game-realm-page.ts` for the four
517
517
  // page-shaped assumptions this covers and why each one breaks an in-realm
518
518
  // mount. Registered on the DEFAULT realm because an ingest descriptor's
519
- // module urls carry no `?vgai-mount=` (binding-resolver.ts's
519
+ // module urls carry no `?volter-mount=` (binding-resolver.ts's
520
520
  // `resolveIngestDescriptor` builds bare `fsImportPath` urls).
521
521
  const realmPage = setGameSurface(hostEl);
522
522
 
@@ -614,10 +614,10 @@ export async function mountIngestGame(
614
614
  // Signal COLD MOUNT before the entry executes: editor mounts are for
615
615
  // inspection first, so a session-driven game MAY defer its side-effects
616
616
  // (backend connection, narrative, audio) until the editor's play control
617
- // dispatches 'vgai:ingest-play' (getIngestPlayControl, ingest/mount-ingest-root.ts).
617
+ // dispatches 'volter:ingest-play' (getIngestPlayControl, ingest/mount-ingest-root.ts).
618
618
  // Rendering must continue regardless — capture needs a frame — and games
619
619
  // that ignore the flag behave exactly as before (opt-in, never demanded).
620
- (window as unknown as { __vgaiMountCold?: boolean }).__vgaiMountCold = true;
620
+ (window as unknown as { __volterMountCold?: boolean }).__volterMountCold = true;
621
621
  // THE BOOT WINDOW OPENS HERE (M29). Everything the page throws from this
622
622
  // instant until the mount resolves belongs to this game's boot, and it is the
623
623
  // fact that separates "crashed before ready" from "never became ready" — the
@@ -650,7 +650,7 @@ export async function mountIngestGame(
650
650
  // boots in the background parks here instead of dying, with the trap still
651
651
  // installed, so the first frame after the human foregrounds the tab is the
652
652
  // captured one. `setCaptureWait` is what keeps that park from reading as a
653
- // hung mount — `vgai status` names it.
653
+ // hung mount — `volter-game-editor status` names it.
654
654
  rt = await capture.waitForCapture({
655
655
  timeoutMs,
656
656
  onWait: (wait) => setCaptureWait(game.id, wait),
@@ -797,10 +797,10 @@ export async function mountIngestGame(
797
797
  // well after `setPaused` returned. Nothing else would notify the store, and
798
798
  // `collectState` is push-based — the control API would keep serving a
799
799
  // snapshot taken before the measurement existed, reporting `loop: null`
800
- // forever. Broadcast so `vgai status` sees the verdict it just produced.
800
+ // forever. Broadcast so `volter-game-editor status` sees the verdict it just produced.
801
801
  onVerdict: () => store.shell.notifyIngestEdit(),
802
802
  });
803
- // The game's DECLARED system surface (`window.vgaiGame.systems`), projected
803
+ // The game's DECLARED system surface (`window.volterGame.systems`), projected
804
804
  // onto the host's ordinary `SystemAdapters.debug`. `activateCapturedThreeIngest`
805
805
  // hands `mounted.systems` straight to `setActiveSystems`, so a shim that
806
806
  // declares verbs makes `game.commands()`/`game.state()` work through the same
@@ -7,13 +7,13 @@
7
7
  * background — the normal human path — no longer burns its window unable to
8
8
  * draw. What it does instead is WAIT, potentially for as long as the human
9
9
  * takes to come back to the tab, and a wait is exactly the state every door
10
- * used to report as silence: nothing mounted, nothing failed, `vgai status`
10
+ * used to report as silence: nothing mounted, nothing failed, `volter-game-editor status`
11
11
  * counting down a clock that was not running. So the wait is published:
12
- * `collectState`'s `ingestCaptureWait` carries it, and `vgai status` prints
12
+ * `collectState`'s `ingestCaptureWait` carries it, and `volter-game-editor status` prints
13
13
  * "waiting for first visible frame — tab is hidden" instead of a countdown.
14
14
  *
15
15
  * A LIVE VIEW, never a snapshot — same rule as `IngestMount.realmLoopVerdict`
16
- * and the `__vgaiIngest` hook's `reflected`/`sceneChildren`: the elapsed
16
+ * and the `__volterIngest` hook's `reflected`/`sceneChildren`: the elapsed
17
17
  * numbers move on their own, so a frozen copy starts lying the instant it is
18
18
  * taken. The slot holds the window itself and derives the report at read time.
19
19
  *
@@ -27,7 +27,7 @@
27
27
  import { notifyLiveSessionsChanged } from '@volter/editor-sdk/kit/live-session-registry';
28
28
  import type { VisibleCaptureWindow } from '@volter/threejs-runtime/adapter/ingest/visible-capture-window';
29
29
 
30
- /** The wait as `vgai status` reports it. */
30
+ /** The wait as `volter-game-editor status` reports it. */
31
31
  export interface CaptureWaitStatus {
32
32
  /** The world whose first frame is being waited for. */
33
33
  readonly worldId: string;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * The three sibling of `surface-canvas.ts` (the pixi lane, which is the idiom
5
5
  * benchmark this file is modelled on): a game vendored under
6
- * `public/ingest/<id>/` carries its own declarative `vgai.project.json`, and
6
+ * `public/ingest/<id>/` carries its own declarative `volter.project.json`, and
7
7
  * its id resolves it into the SAME `IngestGame` descriptor every other three
8
8
  * ingest route produces. Adding a fourth vendored game is a folder plus a
9
9
  * manifest — no edit to this file, no per-game page, no branch anywhere.
@@ -81,7 +81,7 @@ function readVendoredIngestRoot(
81
81
  const roots = declaredRoots(manifest);
82
82
  if (roots.length !== 1) {
83
83
  throw new Error(
84
- `vendored ingest discovery: "${folderId}/vgai.project.json" must declare exactly one root ` +
84
+ `vendored ingest discovery: "${folderId}/volter.project.json" must declare exactly one root ` +
85
85
  `(found ${roots.length}).`,
86
86
  );
87
87
  }
@@ -92,7 +92,7 @@ function readVendoredIngestRoot(
92
92
  root.adapter.identity !== expect.identity
93
93
  ) {
94
94
  throw new Error(
95
- `vendored ingest discovery: "${folderId}/vgai.project.json" must declare one ` +
95
+ `vendored ingest discovery: "${folderId}/volter.project.json" must declare one ` +
96
96
  `${expect.surface} { ingest } root (found surface "${root.surface}", adapter identity ` +
97
97
  `"${root.adapter.identity}").`,
98
98
  );
@@ -161,7 +161,7 @@ export function buildPublicCanvasIngestGame(
161
161
  }
162
162
 
163
163
  /**
164
- * Resolve a vendored game id against `public/ingest/<id>/vgai.project.json`.
164
+ * Resolve a vendored game id against `public/ingest/<id>/volter.project.json`.
165
165
  *
166
166
  * `null` means "no such vendored three ingest" (no manifest served at that
167
167
  * path) — the caller falls through to its own unknown-id report. A manifest
@@ -4,4 +4,4 @@
4
4
  * page can retire the stub whose id it supplies itself (`served-html-boot.ts`).
5
5
  * Shared here because the two sides must agree on one mark.
6
6
  */
7
- export const DOM_STUB_MARK = 'vgaiDomStub';
7
+ export const DOM_STUB_MARK = 'volterDomStub';
@@ -3,7 +3,7 @@
3
3
  * editor's realm, preceded by the host-added contract module the manifest names
4
4
  * in `ingest.contractShim` when it declares one.
5
5
  *
6
- * ORDER IS THE WHOLE CONTRACT. The shim assigns `window.vgaiGame` synchronously
6
+ * ORDER IS THE WHOLE CONTRACT. The shim assigns `window.volterGame` synchronously
7
7
  * at top level (see the field's schema description), so it must be evaluated
8
8
  * BEFORE the game's entry — a game that reads the declaration during its own
9
9
  * module evaluation would otherwise see nothing, and a shim that lazily
@@ -1,13 +1,13 @@
1
1
  import { gameRealmForMountId } from '../host/gated-globals';
2
2
  import {
3
3
  readGameContract,
4
- type VgaiGameContract,
4
+ type VolterGameContract,
5
5
  } from '@volter/editor-project/adapter/ingest/game-contract';
6
6
 
7
7
  /**
8
8
  * The browser realm used by the singleton ingest routes.
9
9
  *
10
- * Vendored ingest entry graphs deliberately carry no `?vgai-mount=` query:
10
+ * Vendored ingest entry graphs deliberately carry no `?volter-mount=` query:
11
11
  * they share the editor's Pixi/Three packages and run in the default gated
12
12
  * realm. Realm hardening keeps game-owned expandos on that realm's window
13
13
  * proxy, so host code must read the contract from the same proxy rather than
@@ -28,7 +28,7 @@ export function ingestGameRealmWindow(): Window {
28
28
  * reached by every `bridge-call`) degrading instead of throwing
29
29
  * `window is not defined` at them.
30
30
  */
31
- export function readIngestGameContract(): VgaiGameContract | null {
31
+ export function readIngestGameContract(): VolterGameContract | null {
32
32
  if (typeof window === 'undefined') return null;
33
33
  return readGameContract(ingestGameRealmWindow());
34
34
  }
@@ -59,7 +59,7 @@ export function installGamePointerLockGate(): void {
59
59
  if (entry && !entry.gate()) {
60
60
  // A NEW native console.error site, suppressed to keep this task's diff at
61
61
  // zero new lint warnings — and native on purpose: this fires from a game's
62
- // own click handler in the page, and the page console is what `vgai
62
+ // own click handler in the page, and the page console is what `volter-game-editor
63
63
  // status` reads.
64
64
  // biome-ignore lint/suspicious/noConsole: see comment above
65
65
  console.error(
@@ -136,8 +136,8 @@ export function IngestCanvasSceneContent({
136
136
  <div
137
137
  ref={containerRef}
138
138
  data-testid="world-document:ingest-canvas-scene"
139
- data-vgai-backdrop-color={active ? CANVAS_SCENE_BACKGROUND : undefined}
140
- data-vgai-backdrop-policy={active ? 'dark-frost' : undefined}
139
+ data-volter-backdrop-color={active ? CANVAS_SCENE_BACKGROUND : undefined}
140
+ data-volter-backdrop-policy={active ? 'dark-frost' : undefined}
141
141
  style={{
142
142
  position: 'absolute',
143
143
  inset: 0,
@@ -148,7 +148,7 @@ export function IngestCanvasSceneContent({
148
148
  }}
149
149
  >
150
150
  <CanvasSceneBackdrop view={view} documentId={documentId} />
151
- <RootSelectionOverlay adapter={adapter} view={view} transformModeAware />
151
+ <RootSelectionOverlay adapter={adapter} view={view} transformModeAware presentationId={documentId} />
152
152
  <SurfaceStateOverlay
153
153
  explanation={surfaceExplanation}
154
154
  testId="ingest-canvas-surface-status"