@vgai/engine 0.5.23 → 0.5.25

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.
@@ -59,6 +59,11 @@ export declare const GAME_LIFECYCLE_SHAPE: {
59
59
  readonly kind: "function";
60
60
  readonly required: "effect";
61
61
  };
62
+ readonly dispose: {
63
+ readonly optional: true;
64
+ readonly kind: "function";
65
+ readonly required: "effect";
66
+ };
62
67
  };
63
68
  export declare const GAME_SCENES_SHAPE: {
64
69
  readonly list: {
@@ -1 +1 @@
1
- {"version":3,"file":"game-contract-seams.d.ts","sourceRoot":"","sources":["../../../src/adapter/ingest/game-contract-seams.ts"],"names":[],"mappings":"AAAA;;sEAEsE;AAgBtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAS9B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;CAI/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;CAI5B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;CAG3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;CAK7B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;CAIpC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;CAIrC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;CAK7B,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOrC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;CAGlC,CAAC"}
1
+ {"version":3,"file":"game-contract-seams.d.ts","sourceRoot":"","sources":["../../../src/adapter/ingest/game-contract-seams.ts"],"names":[],"mappings":"AAAA;;sEAEsE;AAgBtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAS9B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;CAK/B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;CAI5B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;CAG3B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;CAK7B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;CAIpC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;CAIrC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;CAK7B,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOrC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;CAGlC,CAAC"}
@@ -16,6 +16,7 @@ export const GAME_LIFECYCLE_SHAPE = defineSeamShape()({
16
16
  start: { optional: true, kind: 'function', required: 'effect' },
17
17
  pause: { optional: true, kind: 'function', required: 'effect' },
18
18
  resume: { optional: true, kind: 'function', required: 'effect' },
19
+ dispose: { optional: true, kind: 'function', required: 'effect' },
19
20
  });
20
21
  export const GAME_SCENES_SHAPE = defineSeamShape()({
21
22
  list: { optional: false, kind: 'function', required: 'operation' },
@@ -32,6 +32,28 @@ export interface VgaiGameLifecycle {
32
32
  start?(): void;
33
33
  pause?(): void;
34
34
  resume?(): void;
35
+ /**
36
+ * END this session: unmount the game's root, stop its frame loop, release
37
+ * what its boot created. The host calls it FIRST at ingest teardown, before
38
+ * its own reclamation — the game's own way out always outranks the host's.
39
+ *
40
+ * Why this slot exists (measured on racing-game): a self-booting R3F game's
41
+ * fiber loop is not the host's to stop — the game never calls
42
+ * `renderer.setAnimationLoop` (the loop-gate's own warning says it cannot
43
+ * hold it) and fiber is a shared bare dependency the realm scheduler does
44
+ * not wrap — so after teardown the DEAD mount's `useFrame` kept ticking
45
+ * against React-nulled refs, one `TypeError` per frame (~490 per walk)
46
+ * until the page reloaded. Only the code that created the root can end it,
47
+ * and for a vendored game that code is the host-added entry shim, which
48
+ * publishes the unmount for the contract shim to declare here.
49
+ *
50
+ * A game that declares nothing keeps today's behavior — host-side
51
+ * reclamation only, with its loop's ungovernability remaining the
52
+ * loop-gate's named standing warning. A CANVAS ingest whose module-scope
53
+ * `Application` survives teardown BY DESIGN (the warm-remount contract —
54
+ * see `resolve-three.ts`'s `remountEpochs` doc) simply does not declare it.
55
+ */
56
+ dispose?(): void;
35
57
  }
36
58
  /** One of the game's own scenes, as {@link VgaiGameScenes} lists it. `id` is the
37
59
  * game's OWN identifier for it — the string `current()` reports and `goTo()`
@@ -1 +1 @@
1
- {"version":3,"file":"game-contract.d.ts","sourceRoot":"","sources":["../../../src/adapter/ingest/game-contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game-contract.d.ts","sourceRoot":"","sources":["../../../src/adapter/ingest/game-contract.ts"],"names":[],"mappings":"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"}
@@ -56,6 +56,15 @@ export interface NativeDebugModule {
56
56
  readonly events?: {
57
57
  readonly subscribe: (listener: (event: string, detail?: unknown) => void) => () => void;
58
58
  };
59
+ /**
60
+ * `false` while the app is intentionally BETWEEN worlds — a scene remount in flight (a
61
+ * `reload_current_scene`-style restart unmounts the running scene and the fresh one arrives
62
+ * on an ASYNC React commit). Session tick drivers (`runTicksWhenSettled`, behind both
63
+ * run-ticks doors) wait for `true` before each tick, so which tick first runs the fresh
64
+ * world is a function of the sim, never of wall timing between driver calls. Omitted =
65
+ * always settled.
66
+ */
67
+ readonly settled?: () => boolean;
59
68
  }
60
69
  export interface NativeDebugBinding {
61
70
  readonly rootId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"native-debug-module.d.ts","sourceRoot":"","sources":["../../src/adapter/native-debug-module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-debug-module.d.ts","sourceRoot":"","sources":["../../src/adapter/native-debug-module.ts"],"names":[],"mappings":"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"}
@@ -107,7 +107,7 @@ export function nativeDebugBindingFromEntryModule(rootId, entryModule) {
107
107
  throw new Error(`Root "${rootId}" exports \`debug\`, but it is not an object.`);
108
108
  }
109
109
  const raw = entryModule['debug'];
110
- rejectUnknownKeys(raw, ['commands', 'state', 'input', 'events'], `Root "${rootId}" debug export`);
110
+ rejectUnknownKeys(raw, ['commands', 'state', 'input', 'events', 'settled'], `Root "${rootId}" debug export`);
111
111
  // A thunk table defers to install time (see {@link NativeTable}); a plain
112
112
  // record validates here, where the error can still name the export.
113
113
  const parseTable = (value, at) => {
@@ -132,7 +132,11 @@ export function nativeDebugBindingFromEntryModule(rootId, entryModule) {
132
132
  const state = parseTable(raw['state'], 'debug.state');
133
133
  const input = raw['input'] === undefined ? undefined : parseInput(raw['input']);
134
134
  const events = raw['events'] === undefined ? undefined : parseEvents(raw['events']);
135
- if (!commands && !state && !input && !events) {
135
+ const settled = raw['settled'];
136
+ if (settled !== undefined && typeof settled !== 'function') {
137
+ throw new Error('debug.settled must be a function returning a boolean.');
138
+ }
139
+ if (!commands && !state && !input && !events && !settled) {
136
140
  throw new Error(`Root "${rootId}" exports an empty \`debug\` object.`);
137
141
  }
138
142
  return {
@@ -142,6 +146,7 @@ export function nativeDebugBindingFromEntryModule(rootId, entryModule) {
142
146
  ...(state ? { state } : {}),
143
147
  ...(input ? { input } : {}),
144
148
  ...(events ? { events } : {}),
149
+ ...(settled ? { settled: settled } : {}),
145
150
  },
146
151
  };
147
152
  }
@@ -303,6 +308,10 @@ export function installNativeDebugBindings(game, bindings) {
303
308
  // subscription's disposer is deliberately dropped: it lives exactly as
304
309
  // long as this Game's registry does.
305
310
  binding.debug.events?.subscribe((event, detail) => root.emit(event, detail));
311
+ // The app's own between-worlds truth → the session's tick gate
312
+ // (`runTicksWhenSettled`). Same lifetime rule as the event subscription.
313
+ if (binding.debug.settled)
314
+ registry.registerWorldSettledProbe(binding.debug.settled);
306
315
  }
307
316
  }
308
317
  /**
@@ -152,6 +152,18 @@ export interface VgaiDebugHandle {
152
152
  * silent no-op.
153
153
  */
154
154
  runTicks(n: number, opts?: RunTicksOptions): void;
155
+ /**
156
+ * The SETTLED-AWARE variant of {@link runTicks} (`runtime/run-ticks-settled.ts` — one
157
+ * implementation with the editor relay's `run-ticks` case, D17): drives the budget one tick
158
+ * at a time and, before each tick, waits for every registered world-settled probe
159
+ * (`DebugRegistry.registerWorldSettledProbe`, declared by the game's `debug.settled` entry
160
+ * export) — so a tick never races a scene remount's async commit, and WHICH tick first runs
161
+ * a freshly reloaded world is a function of the sim rather than wall timing. Session tick
162
+ * drivers (`@vgai/live`'s fastForward) prefer this door; with no probe registered it behaves
163
+ * exactly like {@link runTicks}. Bounded: throws `WORLD_UNSETTLED_TIMEOUT` if a probe never
164
+ * settles.
165
+ */
166
+ runTicksSettled(n: number, opts?: RunTicksOptions): Promise<void>;
155
167
  /**
156
168
  * Collapses `input.setVirtualAction(action, true)` → wait `simSeconds` of
157
169
  * REAL sim time (real ticks — deliberately NOT `runTicks`/fast-forward;
@@ -1 +1 @@
1
- {"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@
15
15
  * field whose runtime reader THIS module is).
16
16
  */
17
17
  import { DebugError } from './debug-registry';
18
+ import { runTicksWhenSettled } from './run-ticks-settled';
18
19
  /** Query-param name that opts a standalone page into the debug bridge (D18) —
19
20
  * mirrors `render-seed.ts`'s `RENDER_MODE_QUERY_PARAM` naming/shape, own
20
21
  * const because this is a different call site with a different flag. */
@@ -216,6 +217,9 @@ function buildDebugHandle(opts) {
216
217
  }
217
218
  target.runTicks(n, runTicksOpts);
218
219
  },
220
+ runTicksSettled(n, runTicksOpts) {
221
+ return runTicksWhenSettled(registry, n, runTicksOpts);
222
+ },
219
223
  async holdFor(action, simSeconds, worldId) {
220
224
  const target = requireInputTarget('holdFor', worldId);
221
225
  const setResult = target.setVirtualAction(action, true);
@@ -294,6 +294,24 @@ export interface DebugRegistry {
294
294
  * error in that case rather than silently no-op-ing — see
295
295
  * `debug-bridge.ts`'s `runTicks` method. */
296
296
  getRunTicksTarget(): RunTicksTarget | null;
297
+ /**
298
+ * Register a WORLD-SETTLED probe: `false` while this game is intentionally
299
+ * between worlds — a scene remount in flight (`reload_current_scene`'s
300
+ * React remount commits asynchronously). The game declares it through the
301
+ * `settled` key of its `debug` entry export (`native-debug-module.ts`);
302
+ * session tick drivers ({@link runTicksWhenSettled} behind BOTH run-ticks
303
+ * doors) wait for every probe to answer `true` before each tick, so WHICH
304
+ * tick first runs a freshly remounted scene is a function of the sim, not
305
+ * of wall timing between driver calls — measured before this seam: the
306
+ * same drive script produced 7 or 8 post-respawn walked ticks depending on
307
+ * how long the driver idled between ticks. Returns the deregistration.
308
+ */
309
+ registerWorldSettledProbe(probe: () => boolean): () => void;
310
+ /** `true` when every registered probe answers `true` (and vacuously with
311
+ * none registered). A probe that THROWS counts as settled=false — a
312
+ * broken probe must stall the driver loudly (its bounded wait names the
313
+ * timeout), never silently un-gate it. */
314
+ worldSettled(): boolean;
297
315
  /** D15/T-D15.3/.5 — the CURRENT shared game tick (the same counter the
298
316
  * built-in `time` provider's `tick` field reads), for a per-world
299
317
  * `InputManager.poll(tick)` call to key its `scheduleActionAtTick`
@@ -1 +1 @@
1
- {"version":3,"file":"debug-registry.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"debug-registry.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-registry.ts"],"names":[],"mappings":"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"}
@@ -116,6 +116,7 @@ export function createDebugRegistry(opts) {
116
116
  const inputTraceSources = new Map();
117
117
  const virtualInputTargets = new Map();
118
118
  let runTicksTarget = null;
119
+ const worldSettledProbes = new Set();
119
120
  let attachedRoom = null;
120
121
  const pendingServerCommands = new Map();
121
122
  let requestCounter = 0;
@@ -487,6 +488,26 @@ export function createDebugRegistry(opts) {
487
488
  getRunTicksTarget() {
488
489
  return runTicksTarget;
489
490
  },
491
+ registerWorldSettledProbe(probe) {
492
+ worldSettledProbes.add(probe);
493
+ return () => {
494
+ worldSettledProbes.delete(probe);
495
+ };
496
+ },
497
+ worldSettled() {
498
+ for (const probe of worldSettledProbes) {
499
+ try {
500
+ if (!probe())
501
+ return false;
502
+ }
503
+ catch {
504
+ // A throwing probe stalls the driver LOUDLY (the bounded wait's
505
+ // timeout names it) rather than silently un-gating the tick.
506
+ return false;
507
+ }
508
+ }
509
+ return true;
510
+ },
490
511
  getGameTick() {
491
512
  return opts.getTick();
492
513
  },
@@ -536,6 +536,18 @@ export interface GameInternal extends Game {
536
536
  * absorbs it exactly as it would absorb any other slow-frame gap (up to
537
537
  * 8 substeps, additional time dropped) — `runTicks` does not need to
538
538
  * (and does not) touch the accumulator itself to make this safe.
539
+ * One consequence worth its own sentence: because the burst is one
540
+ * synchronous JS turn, no React commit can interleave it — a scene
541
+ * RELOAD triggered inside the burst (a translated
542
+ * `reload_current_scene`, a `SceneManager.LoadScene`) leaves the
543
+ * incoming world unmounted for the burst's remaining ticks, which the
544
+ * outgoing world's replacement therefore never simulates. Measured on
545
+ * the starter-kit port: a 20-tick burst spanning a reload left the
546
+ * fresh scene with zero ticks (its census had no player), while the
547
+ * same 20 ticks driven as 1-tick calls interleaved the commit and
548
+ * matched the source engine, whose reloads happen between frames. A
549
+ * caller that can trigger remounts mid-window drives 1-tick bursts
550
+ * (the fidelity driver's `advanceTicks` is the worked example).
539
551
  * - **`opts.render`** (default `'last'`): `'last'` skips the `preRender`/
540
552
  * `render` phases for ticks `0..n-2` and runs the full phase list
541
553
  * (including `preRender`/`render`) on the final tick only — the GGPO
@@ -1 +1 @@
1
- {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `runTicksWhenSettled` — the settled-aware tick driver behind BOTH session run-ticks doors
3
+ * (the bridge's `window.__vgai.runTicksSettled`, the editor relay's `run-ticks` case), one
4
+ * implementation with byte-identical semantics across doors, exactly as `runTicks` itself is
5
+ * shared (D17).
6
+ *
7
+ * Why it exists: `Game.runTicks` is deliberately SYNCHRONOUS, but a game may be intentionally
8
+ * BETWEEN worlds when a tick arrives — `reload_current_scene` unmounts the running scene and
9
+ * the fresh one arrives on an ASYNC React commit. A tick driven into that gap runs against
10
+ * nothing, and WHICH tick first runs the fresh world then depends on wall timing between
11
+ * driver calls — measured on the starter-kit fidelity drive: the same script produced 7 or 8
12
+ * post-respawn walked ticks depending on how long the driver idled between ticks. The fidelity
13
+ * contract (docs/MIGRATE-FIDELITY.md) treats a nondeterministic channel as a MECHANISM defect,
14
+ * and this is the mechanism: ticks must not race remounts.
15
+ *
16
+ * So this driver runs the budget ONE tick at a time and, before each tick, waits for every
17
+ * registered world-settled probe ({@link DebugRegistry.registerWorldSettledProbe} — declared by
18
+ * the game through its `debug.settled` entry export) to answer `true`. The wall-clock poll is
19
+ * sound because the OUTCOME no longer depends on timing: however long the commit takes, the
20
+ * next tick is always the fresh world's first. A game that registers no probe gets the old
21
+ * behavior exactly (every wait resolves immediately).
22
+ *
23
+ * The wait is BOUNDED and loud: a remount that never settles is a real defect, and
24
+ * `WORLD_UNSETTLED_TIMEOUT` names it rather than letting the driver hang.
25
+ */
26
+ import { type DebugRegistry, type RunTicksOptions } from './debug-registry';
27
+ export declare function runTicksWhenSettled(registry: Pick<DebugRegistry, 'worldSettled' | 'getRunTicksTarget'>, n: number, opts?: RunTicksOptions,
28
+ /** Test-only overrides — real callers leave this unset (the same seam
29
+ * convention as fast-forward's `batchTicks`). */
30
+ waits?: {
31
+ timeoutMs?: number;
32
+ pollMs?: number;
33
+ }): Promise<void>;
34
+ //# sourceMappingURL=run-ticks-settled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-ticks-settled.d.ts","sourceRoot":"","sources":["../../src/runtime/run-ticks-settled.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQxF,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,cAAc,GAAG,mBAAmB,CAAC,EACnE,CAAC,EAAE,MAAM,EACT,IAAI,CAAC,EAAE,eAAe;AACtB;kDACkD;AAClD,KAAK,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `runTicksWhenSettled` — the settled-aware tick driver behind BOTH session run-ticks doors
3
+ * (the bridge's `window.__vgai.runTicksSettled`, the editor relay's `run-ticks` case), one
4
+ * implementation with byte-identical semantics across doors, exactly as `runTicks` itself is
5
+ * shared (D17).
6
+ *
7
+ * Why it exists: `Game.runTicks` is deliberately SYNCHRONOUS, but a game may be intentionally
8
+ * BETWEEN worlds when a tick arrives — `reload_current_scene` unmounts the running scene and
9
+ * the fresh one arrives on an ASYNC React commit. A tick driven into that gap runs against
10
+ * nothing, and WHICH tick first runs the fresh world then depends on wall timing between
11
+ * driver calls — measured on the starter-kit fidelity drive: the same script produced 7 or 8
12
+ * post-respawn walked ticks depending on how long the driver idled between ticks. The fidelity
13
+ * contract (docs/MIGRATE-FIDELITY.md) treats a nondeterministic channel as a MECHANISM defect,
14
+ * and this is the mechanism: ticks must not race remounts.
15
+ *
16
+ * So this driver runs the budget ONE tick at a time and, before each tick, waits for every
17
+ * registered world-settled probe ({@link DebugRegistry.registerWorldSettledProbe} — declared by
18
+ * the game through its `debug.settled` entry export) to answer `true`. The wall-clock poll is
19
+ * sound because the OUTCOME no longer depends on timing: however long the commit takes, the
20
+ * next tick is always the fresh world's first. A game that registers no probe gets the old
21
+ * behavior exactly (every wait resolves immediately).
22
+ *
23
+ * The wait is BOUNDED and loud: a remount that never settles is a real defect, and
24
+ * `WORLD_UNSETTLED_TIMEOUT` names it rather than letting the driver hang.
25
+ */
26
+ import { DebugError } from './debug-registry';
27
+ /** A remount is a couple of React commits on an idle main thread; polling faster buys nothing
28
+ * and slower delays every settled check by the poll period. */
29
+ const SETTLED_POLL_MS = 4;
30
+ /** A commit that hasn't landed after this long is not "in flight", it is stuck. */
31
+ const SETTLED_TIMEOUT_MS = 10_000;
32
+ export async function runTicksWhenSettled(registry, n, opts,
33
+ /** Test-only overrides — real callers leave this unset (the same seam
34
+ * convention as fast-forward's `batchTicks`). */
35
+ waits) {
36
+ const target = registry.getRunTicksTarget();
37
+ if (target === null) {
38
+ throw new DebugError('RUN_TICKS_UNAVAILABLE', 'runTicksWhenSettled: no run-ticks target is wired — no Game has mounted yet');
39
+ }
40
+ const timeoutMs = waits?.timeoutMs ?? SETTLED_TIMEOUT_MS;
41
+ const pollMs = waits?.pollMs ?? SETTLED_POLL_MS;
42
+ const render = opts?.render ?? 'last';
43
+ for (let i = 0; i < n; i++) {
44
+ if (!registry.worldSettled()) {
45
+ const deadline = Date.now() + timeoutMs;
46
+ while (!registry.worldSettled()) {
47
+ if (Date.now() > deadline) {
48
+ throw new DebugError('WORLD_UNSETTLED_TIMEOUT', `runTicksWhenSettled: a world-settled probe still answers false after ${timeoutMs}ms — ` +
49
+ 'a scene remount (or a broken probe) is stuck, and driving ticks into it would race it');
50
+ }
51
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
52
+ }
53
+ }
54
+ const isFinalTick = i === n - 1;
55
+ // Same per-tick render policy `Game.runTicks` applies across its own loop.
56
+ const tickRender = render === 'all' ? 'all' : render === 'none' ? 'none' : isFinalTick ? 'last' : 'none';
57
+ target.runTicks(1, { render: tickRender });
58
+ }
59
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@vgai/engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "Apache-2.0",
5
- "version": "0.5.23",
5
+ "version": "0.5.25",
6
6
  "description": "Readable TypeScript game engine and universal host for Three.js, PixiJS, and React games.",
7
7
  "keywords": [
8
8
  "game-engine",
@@ -31,6 +31,7 @@ export const GAME_LIFECYCLE_SHAPE = defineSeamShape<VgaiGameLifecycle>()({
31
31
  start: { optional: true, kind: 'function', required: 'effect' },
32
32
  pause: { optional: true, kind: 'function', required: 'effect' },
33
33
  resume: { optional: true, kind: 'function', required: 'effect' },
34
+ dispose: { optional: true, kind: 'function', required: 'effect' },
34
35
  });
35
36
 
36
37
  export const GAME_SCENES_SHAPE = defineSeamShape<VgaiGameScenes>()({
@@ -42,6 +42,28 @@ export interface VgaiGameLifecycle {
42
42
  start?(): void;
43
43
  pause?(): void;
44
44
  resume?(): void;
45
+ /**
46
+ * END this session: unmount the game's root, stop its frame loop, release
47
+ * what its boot created. The host calls it FIRST at ingest teardown, before
48
+ * its own reclamation — the game's own way out always outranks the host's.
49
+ *
50
+ * Why this slot exists (measured on racing-game): a self-booting R3F game's
51
+ * fiber loop is not the host's to stop — the game never calls
52
+ * `renderer.setAnimationLoop` (the loop-gate's own warning says it cannot
53
+ * hold it) and fiber is a shared bare dependency the realm scheduler does
54
+ * not wrap — so after teardown the DEAD mount's `useFrame` kept ticking
55
+ * against React-nulled refs, one `TypeError` per frame (~490 per walk)
56
+ * until the page reloaded. Only the code that created the root can end it,
57
+ * and for a vendored game that code is the host-added entry shim, which
58
+ * publishes the unmount for the contract shim to declare here.
59
+ *
60
+ * A game that declares nothing keeps today's behavior — host-side
61
+ * reclamation only, with its loop's ungovernability remaining the
62
+ * loop-gate's named standing warning. A CANVAS ingest whose module-scope
63
+ * `Application` survives teardown BY DESIGN (the warm-remount contract —
64
+ * see `resolve-three.ts`'s `remountEpochs` doc) simply does not declare it.
65
+ */
66
+ dispose?(): void;
45
67
  }
46
68
 
47
69
  /** One of the game's own scenes, as {@link VgaiGameScenes} lists it. `id` is the
@@ -77,6 +77,15 @@ export interface NativeDebugModule {
77
77
  readonly events?: {
78
78
  readonly subscribe: (listener: (event: string, detail?: unknown) => void) => () => void;
79
79
  };
80
+ /**
81
+ * `false` while the app is intentionally BETWEEN worlds — a scene remount in flight (a
82
+ * `reload_current_scene`-style restart unmounts the running scene and the fresh one arrives
83
+ * on an ASYNC React commit). Session tick drivers (`runTicksWhenSettled`, behind both
84
+ * run-ticks doors) wait for `true` before each tick, so which tick first runs the fresh
85
+ * world is a function of the sim, never of wall timing between driver calls. Omitted =
86
+ * always settled.
87
+ */
88
+ readonly settled?: () => boolean;
80
89
  }
81
90
 
82
91
  type NativeInputBinding = NonNullable<NativeDebugModule['input']>;
@@ -177,7 +186,11 @@ export function nativeDebugBindingFromEntryModule(
177
186
  throw new Error(`Root "${rootId}" exports \`debug\`, but it is not an object.`);
178
187
  }
179
188
  const raw = entryModule['debug'];
180
- rejectUnknownKeys(raw, ['commands', 'state', 'input', 'events'], `Root "${rootId}" debug export`);
189
+ rejectUnknownKeys(
190
+ raw,
191
+ ['commands', 'state', 'input', 'events', 'settled'],
192
+ `Root "${rootId}" debug export`,
193
+ );
181
194
 
182
195
  // A thunk table defers to install time (see {@link NativeTable}); a plain
183
196
  // record validates here, where the error can still name the export.
@@ -198,7 +211,11 @@ export function nativeDebugBindingFromEntryModule(
198
211
  const state = parseTable(raw['state'], 'debug.state');
199
212
  const input = raw['input'] === undefined ? undefined : parseInput(raw['input']);
200
213
  const events = raw['events'] === undefined ? undefined : parseEvents(raw['events']);
201
- if (!commands && !state && !input && !events) {
214
+ const settled = raw['settled'];
215
+ if (settled !== undefined && typeof settled !== 'function') {
216
+ throw new Error('debug.settled must be a function returning a boolean.');
217
+ }
218
+ if (!commands && !state && !input && !events && !settled) {
202
219
  throw new Error(`Root "${rootId}" exports an empty \`debug\` object.`);
203
220
  }
204
221
  return {
@@ -208,6 +225,7 @@ export function nativeDebugBindingFromEntryModule(
208
225
  ...(state ? { state } : {}),
209
226
  ...(input ? { input } : {}),
210
227
  ...(events ? { events } : {}),
228
+ ...(settled ? { settled: settled as () => boolean } : {}),
211
229
  },
212
230
  };
213
231
  }
@@ -418,6 +436,9 @@ export function installNativeDebugBindings(
418
436
  // subscription's disposer is deliberately dropped: it lives exactly as
419
437
  // long as this Game's registry does.
420
438
  binding.debug.events?.subscribe((event, detail) => root.emit(event, detail));
439
+ // The app's own between-worlds truth → the session's tick gate
440
+ // (`runTicksWhenSettled`). Same lifetime rule as the event subscription.
441
+ if (binding.debug.settled) registry.registerWorldSettledProbe(binding.debug.settled);
421
442
  }
422
443
  }
423
444
 
@@ -18,6 +18,7 @@
18
18
  import type { DebugAdapter, TickStampedEvent } from '../adapter/system-adapter';
19
19
  import type { GameLoopLiveness } from '../core/types';
20
20
  import { DebugError, type DebugRegistry, type RunTicksOptions } from './debug-registry';
21
+ import { runTicksWhenSettled } from './run-ticks-settled';
21
22
 
22
23
  /** Query-param name that opts a standalone page into the debug bridge (D18) —
23
24
  * mirrors `render-seed.ts`'s `RENDER_MODE_QUERY_PARAM` naming/shape, own
@@ -143,6 +144,18 @@ export interface VgaiDebugHandle {
143
144
  * silent no-op.
144
145
  */
145
146
  runTicks(n: number, opts?: RunTicksOptions): void;
147
+ /**
148
+ * The SETTLED-AWARE variant of {@link runTicks} (`runtime/run-ticks-settled.ts` — one
149
+ * implementation with the editor relay's `run-ticks` case, D17): drives the budget one tick
150
+ * at a time and, before each tick, waits for every registered world-settled probe
151
+ * (`DebugRegistry.registerWorldSettledProbe`, declared by the game's `debug.settled` entry
152
+ * export) — so a tick never races a scene remount's async commit, and WHICH tick first runs
153
+ * a freshly reloaded world is a function of the sim rather than wall timing. Session tick
154
+ * drivers (`@vgai/live`'s fastForward) prefer this door; with no probe registered it behaves
155
+ * exactly like {@link runTicks}. Bounded: throws `WORLD_UNSETTLED_TIMEOUT` if a probe never
156
+ * settles.
157
+ */
158
+ runTicksSettled(n: number, opts?: RunTicksOptions): Promise<void>;
146
159
  /**
147
160
  * Collapses `input.setVirtualAction(action, true)` → wait `simSeconds` of
148
161
  * REAL sim time (real ticks — deliberately NOT `runTicks`/fast-forward;
@@ -468,6 +481,9 @@ function buildDebugHandle(opts: {
468
481
  }
469
482
  target.runTicks(n, runTicksOpts);
470
483
  },
484
+ runTicksSettled(n, runTicksOpts) {
485
+ return runTicksWhenSettled(registry, n, runTicksOpts);
486
+ },
471
487
  async holdFor(action, simSeconds, worldId) {
472
488
  const target = requireInputTarget('holdFor', worldId);
473
489
  const setResult = target.setVirtualAction(action, true);
@@ -370,6 +370,24 @@ export interface DebugRegistry {
370
370
  * error in that case rather than silently no-op-ing — see
371
371
  * `debug-bridge.ts`'s `runTicks` method. */
372
372
  getRunTicksTarget(): RunTicksTarget | null;
373
+ /**
374
+ * Register a WORLD-SETTLED probe: `false` while this game is intentionally
375
+ * between worlds — a scene remount in flight (`reload_current_scene`'s
376
+ * React remount commits asynchronously). The game declares it through the
377
+ * `settled` key of its `debug` entry export (`native-debug-module.ts`);
378
+ * session tick drivers ({@link runTicksWhenSettled} behind BOTH run-ticks
379
+ * doors) wait for every probe to answer `true` before each tick, so WHICH
380
+ * tick first runs a freshly remounted scene is a function of the sim, not
381
+ * of wall timing between driver calls — measured before this seam: the
382
+ * same drive script produced 7 or 8 post-respawn walked ticks depending on
383
+ * how long the driver idled between ticks. Returns the deregistration.
384
+ */
385
+ registerWorldSettledProbe(probe: () => boolean): () => void;
386
+ /** `true` when every registered probe answers `true` (and vacuously with
387
+ * none registered). A probe that THROWS counts as settled=false — a
388
+ * broken probe must stall the driver loudly (its bounded wait names the
389
+ * timeout), never silently un-gate it. */
390
+ worldSettled(): boolean;
373
391
  /** D15/T-D15.3/.5 — the CURRENT shared game tick (the same counter the
374
392
  * built-in `time` provider's `tick` field reads), for a per-world
375
393
  * `InputManager.poll(tick)` call to key its `scheduleActionAtTick`
@@ -458,6 +476,7 @@ export function createDebugRegistry(opts: {
458
476
  const inputTraceSources = new Map<string, () => InputTraceSnapshot>();
459
477
  const virtualInputTargets = new Map<string, DebugVirtualInputTarget>();
460
478
  let runTicksTarget: RunTicksTarget | null = null;
479
+ const worldSettledProbes = new Set<() => boolean>();
461
480
  let attachedRoom: DebugRoomHandle | null = null;
462
481
  const pendingServerCommands = new Map<string, PendingServerCommand>();
463
482
  let requestCounter = 0;
@@ -907,6 +926,24 @@ export function createDebugRegistry(opts: {
907
926
  getRunTicksTarget() {
908
927
  return runTicksTarget;
909
928
  },
929
+ registerWorldSettledProbe(probe: () => boolean) {
930
+ worldSettledProbes.add(probe);
931
+ return () => {
932
+ worldSettledProbes.delete(probe);
933
+ };
934
+ },
935
+ worldSettled() {
936
+ for (const probe of worldSettledProbes) {
937
+ try {
938
+ if (!probe()) return false;
939
+ } catch {
940
+ // A throwing probe stalls the driver LOUDLY (the bounded wait's
941
+ // timeout names it) rather than silently un-gating the tick.
942
+ return false;
943
+ }
944
+ }
945
+ return true;
946
+ },
910
947
  getGameTick() {
911
948
  return opts.getTick();
912
949
  },
@@ -777,6 +777,18 @@ export interface GameInternal extends Game {
777
777
  * absorbs it exactly as it would absorb any other slow-frame gap (up to
778
778
  * 8 substeps, additional time dropped) — `runTicks` does not need to
779
779
  * (and does not) touch the accumulator itself to make this safe.
780
+ * One consequence worth its own sentence: because the burst is one
781
+ * synchronous JS turn, no React commit can interleave it — a scene
782
+ * RELOAD triggered inside the burst (a translated
783
+ * `reload_current_scene`, a `SceneManager.LoadScene`) leaves the
784
+ * incoming world unmounted for the burst's remaining ticks, which the
785
+ * outgoing world's replacement therefore never simulates. Measured on
786
+ * the starter-kit port: a 20-tick burst spanning a reload left the
787
+ * fresh scene with zero ticks (its census had no player), while the
788
+ * same 20 ticks driven as 1-tick calls interleaved the commit and
789
+ * matched the source engine, whose reloads happen between frames. A
790
+ * caller that can trigger remounts mid-window drives 1-tick bursts
791
+ * (the fidelity driver's `advanceTicks` is the worked example).
780
792
  * - **`opts.render`** (default `'last'`): `'last'` skips the `preRender`/
781
793
  * `render` phases for ticks `0..n-2` and runs the full phase list
782
794
  * (including `preRender`/`render`) on the final tick only — the GGPO
@@ -0,0 +1,72 @@
1
+ /**
2
+ * `runTicksWhenSettled` — the settled-aware tick driver behind BOTH session run-ticks doors
3
+ * (the bridge's `window.__vgai.runTicksSettled`, the editor relay's `run-ticks` case), one
4
+ * implementation with byte-identical semantics across doors, exactly as `runTicks` itself is
5
+ * shared (D17).
6
+ *
7
+ * Why it exists: `Game.runTicks` is deliberately SYNCHRONOUS, but a game may be intentionally
8
+ * BETWEEN worlds when a tick arrives — `reload_current_scene` unmounts the running scene and
9
+ * the fresh one arrives on an ASYNC React commit. A tick driven into that gap runs against
10
+ * nothing, and WHICH tick first runs the fresh world then depends on wall timing between
11
+ * driver calls — measured on the starter-kit fidelity drive: the same script produced 7 or 8
12
+ * post-respawn walked ticks depending on how long the driver idled between ticks. The fidelity
13
+ * contract (docs/MIGRATE-FIDELITY.md) treats a nondeterministic channel as a MECHANISM defect,
14
+ * and this is the mechanism: ticks must not race remounts.
15
+ *
16
+ * So this driver runs the budget ONE tick at a time and, before each tick, waits for every
17
+ * registered world-settled probe ({@link DebugRegistry.registerWorldSettledProbe} — declared by
18
+ * the game through its `debug.settled` entry export) to answer `true`. The wall-clock poll is
19
+ * sound because the OUTCOME no longer depends on timing: however long the commit takes, the
20
+ * next tick is always the fresh world's first. A game that registers no probe gets the old
21
+ * behavior exactly (every wait resolves immediately).
22
+ *
23
+ * The wait is BOUNDED and loud: a remount that never settles is a real defect, and
24
+ * `WORLD_UNSETTLED_TIMEOUT` names it rather than letting the driver hang.
25
+ */
26
+ import { DebugError, type DebugRegistry, type RunTicksOptions } from './debug-registry';
27
+
28
+ /** A remount is a couple of React commits on an idle main thread; polling faster buys nothing
29
+ * and slower delays every settled check by the poll period. */
30
+ const SETTLED_POLL_MS = 4;
31
+ /** A commit that hasn't landed after this long is not "in flight", it is stuck. */
32
+ const SETTLED_TIMEOUT_MS = 10_000;
33
+
34
+ export async function runTicksWhenSettled(
35
+ registry: Pick<DebugRegistry, 'worldSettled' | 'getRunTicksTarget'>,
36
+ n: number,
37
+ opts?: RunTicksOptions,
38
+ /** Test-only overrides — real callers leave this unset (the same seam
39
+ * convention as fast-forward's `batchTicks`). */
40
+ waits?: { timeoutMs?: number; pollMs?: number },
41
+ ): Promise<void> {
42
+ const target = registry.getRunTicksTarget();
43
+ if (target === null) {
44
+ throw new DebugError(
45
+ 'RUN_TICKS_UNAVAILABLE',
46
+ 'runTicksWhenSettled: no run-ticks target is wired — no Game has mounted yet',
47
+ );
48
+ }
49
+ const timeoutMs = waits?.timeoutMs ?? SETTLED_TIMEOUT_MS;
50
+ const pollMs = waits?.pollMs ?? SETTLED_POLL_MS;
51
+ const render = opts?.render ?? 'last';
52
+ for (let i = 0; i < n; i++) {
53
+ if (!registry.worldSettled()) {
54
+ const deadline = Date.now() + timeoutMs;
55
+ while (!registry.worldSettled()) {
56
+ if (Date.now() > deadline) {
57
+ throw new DebugError(
58
+ 'WORLD_UNSETTLED_TIMEOUT',
59
+ `runTicksWhenSettled: a world-settled probe still answers false after ${timeoutMs}ms — ` +
60
+ 'a scene remount (or a broken probe) is stuck, and driving ticks into it would race it',
61
+ );
62
+ }
63
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
64
+ }
65
+ }
66
+ const isFinalTick = i === n - 1;
67
+ // Same per-tick render policy `Game.runTicks` applies across its own loop.
68
+ const tickRender =
69
+ render === 'all' ? 'all' : render === 'none' ? 'none' : isFinalTick ? 'last' : 'none';
70
+ target.runTicks(1, { render: tickRender });
71
+ }
72
+ }