Move the live-session reset and routing graph, combat and diagnostic command targets, and the sole gameplay input subscriber into Phase 7 before frame publication. Add exact retryable ownership for late bindings so partial startup cannot strand session or component teardown edges. Co-authored-by: Codex <codex@openai.com>
9.7 KiB
GameWindow Slice 8 — Checkpoint I.8 Frame Roots and Session Start
Status: Active — I.8a complete; I.8b frame-root composition next
Parent: 2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md
Scope: Complete Phase 7's session-facing owners, then implement ordered composition Phases 8 and 9.
1. Outcome
Finish the production startup graph without changing accepted input, update, render, network, portal, or UI behavior:
- complete Phase 7 before any frame root is visible;
- construct update and render roots locally and publish the pair atomically;
- start the optional live session as the absolute final startup operation.
The current ordering defect is structural: GameWindow.OnLoad publishes the
frame pair before the combat/diagnostic command targets and sole gameplay input
subscriber are attached. I.8 moves those pre-frame owners into the Phase-7
result, so native callbacks can never observe an incomplete input/command
graph.
This is an ownership move. Retail algorithms and wire behavior remain unchanged, so no divergence-register row is added.
2. I.8a — complete session/player composition
Completed 2026-07-22. LiveSessionRuntimeFactory now owns the exact
reset/router/command graph without a window reference. Phase 7 publishes the
session host, exact-owner combat and diagnostic command bindings, and the sole
gameplay input subscriber before Phase 8 can expose a frame root. Desired
components have a focused canonical snapshot owner. The component-lifecycle
handoff into the earlier live-presentation phase is an exact, retryable
adoption lease, so any later Phase-7 fault rolls it back without stranding or
replaying teardown.
2.1 Focused session runtime factory
Add LiveSessionRuntimeFactory under AcDream.App/Net. It owns the existing
domain-specific construction of:
LiveSessionHostBindings;- reset manifest bindings;
- selection and entered-world callbacks;
- event and command routers;
- inventory, character, and social session bindings.
The factory receives focused owners and state slots, never GameWindow and
never a callback to a substantial window method. Move the existing reset and
router bodies verbatim. Preserve the exact reset order and the existing
retail citations around player-module identity/shortcut/component cleanup.
Add DesiredComponentSnapshotState beside ShortcutSnapshotState so session
routers mutate one focused state owner. GameWindow.DesiredComponents remains
an ABI-compatible read-only projection over that owner. Existing
LocalPlayerIdentityState, LocalPlayerControllerSlot, and
ShortcutSnapshotState remain canonical; no mirrored values are introduced.
2.2 Commands and sole gameplay subscriber
At the tail of SessionPlayerCompositionPhase, after player mode and teleport
exist but before result publication:
- create
LiveSessionHostthrough the focused factory; - create and bind
LiveCombatModeCommandController; - create and bind
RuntimeDiagnosticCommandController; - create
GameplayInputCommandControllerand priority targets; - create and attach the sole
GameplayInputActionRouter.
Add exact-owner BindOwned tokens to the combat and diagnostic command slots.
The existing gameplay router already owns both subscriptions transactionally;
Phase 7 scope-owns it immediately after construction and before Attach.
Extend SessionPlayerResult and its publication seam with the exact
LiveSessionHost, command owners, and optional gameplay router. Publication
rejects replacement before changing any field. Failure before publication
disposes the router, detaches command targets, and rolls back the existing
Phase-7 suffix in reverse order.
3. I.8b — atomic frame-root composition
Add FrameRootCompositionPhase implementing the existing
IFrameRootCompositionPhase contract. Its dependencies are focused App owners;
prior phase results supply all resources created during startup.
Preserve the exact current construction order:
- teleport/login/GL-state and render-live preparation;
- render resource begin/clear/live phases;
- weather, sky-PES, world environment, camera, visibility, settings preview, root, animated-object, and building sources;
- terrain, PView, scene-pass, and world-scene diagnostics;
- optional lifecycle automation;
- retained/devtools/private presentation;
- render orchestrator;
- live-frame coordinator, camera frame, and update orchestrator;
- atomic update/render pair publication as the final Phase-8 action.
Add GameFrameGraphSlot.PublishOwned. Its lease withdraws only the exact pair
it published, is idempotent, and cannot withdraw a later replacement. Scope-own
the lease immediately. A failure before publication leaves the slot empty; a
failure after publication withdraws the exact pair unless result publication
has transferred lifetime to the window shutdown owner.
3.1 Automation and resource snapshots
Add WorldLifecycleResourceSnapshotSource now rather than retaining
CaptureWorldLifecycleResourceSnapshot on the window. It samples the same
canonical world, live-runtime, effect, particle, light, script, mesh, texture,
GPU-memory, managed-memory, render-diagnostic, and frame-profiler owners.
This advances the owner-extraction portion of Checkpoint K; K still changes checkpoint timing, acknowledgement barriers, JSONL validation, and soak comparison. No checkpoint semantics change in I.8.
FrameRootRuntimeBindings owns the optional automation late binding and any
other Phase-8 external edge. It uses reverse, retryable, no-replay cleanup.
Shutdown withdraws the frame graph first, then detaches these frame-owned
bindings before borrowed session/presentation owners retire.
3.2 Publication
FrameRootResult contains:
- exact update and render roots;
- optional lifecycle automation owner;
- Phase-8 runtime bindings;
- the
LiveSessionHostborrowed from Phase 7 for terminal start.
IGameWindowFrameRootPublication stores only owners needed by steady-state or
shutdown. Replacement is rejected atomically.
4. I.8c — terminal start and window cutover
Add SessionStartCompositionPhase implementing
ISessionStartCompositionPhase<FrameRootResult>. It invokes only
LiveSessionHost.Start(RuntimeOptions) and preserves the existing diagnostics
for missing credentials and failed startup.
GameWindow.OnLoad ends with:
Phase 7 Compose
Phase 8 Compose and atomic pair publication
Phase 9 Start
return
There is no callback attachment, binding, publication, diagnostics setup, or other work after Phase 9. Delete the old inline frame construction, session factory/reset/router methods, snapshot method, and terminal status switch.
The existing typed nine-phase GameWindowCompositionPipeline remains the
executable order/failure oracle. Production OnLoad uses the same phase
interfaces and result chain explicitly because later-phase dependency records
are assembled from earlier concrete results; it must not introduce a retained
mega-context, service locator, or delegate façade around GameWindow.
5. Ownership and rollback order
Before frame publication, Phase-7 rollback is:
- gameplay router detach;
- diagnostic and combat command unbind;
- remaining session/player bindings;
- teleport, live session, and streamer teardown.
After frame publication, Phase-8 rollback is:
- exact frame-pair withdrawal;
- automation/other frame binding detach;
- no disposal of resources borrowed from earlier successful phases.
Normal shutdown retains the frozen barrier order:
- logical input/command quiescence;
- live-session convergence;
- physical input callback detach;
- frame-pair withdrawal;
- frame then session/player late-binding detach;
- remaining session, live-entity, effect, render, content, GL, and native owners.
6. Automated gates
Session/runtime
- exact live-session host construction and reset trace;
- no
GameWindowfield or delegate capture in the focused factory; - exact-owner combat/diagnostic bind, competing-owner rejection, idempotent release, and rebind;
- gameplay router attaches before frame publication and rolls back from either partial subscription;
- failed Phase-7 publication leaves no command/input/session target behind.
Frame roots
- exact render/update leaf construction order;
- frame slot is empty at every pre-publication fault;
- exact pair publishes once and both native callbacks see the same generation;
- rollback withdraws only the published pair and never a later replacement;
- automation disabled path acquires nothing;
- automation enabled path binds once, detaches exactly, and samples the same resource values as the former window method;
- frame result publication rejects replacement atomically.
Terminal start and structure
- terminal start runs only after frame publication and every input/command attachment;
- missing credentials and failed starts preserve current diagnostics;
- no operation follows
Start; GameWindowcontains no live-session binding factory, frame-root construction body, resource-snapshot algorithm, or direct frame-pair publication;- no backend dependency enters Core and panels remain on UI abstractions;
- App Release tests, clean solution Release build, and complete Release suite pass;
- behavior/order, architecture/ownership, and adversarial failure reviews are clean.
7. Commit sequence
docs(architecture): plan frame roots and terminal session startrefactor(app): complete session startup compositionrefactor(app): compose atomic frame rootsrefactor(app): make session start terminal
Each implementation commit is independently buildable and preserves the
protected pre-existing TransitionTypes.cs, .test-out/, and logs/ changes.
I.9 performs the complete Checkpoint-I corrected-diff review and documentation
closeout after these cuts land.