acdream/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i8-frame-roots-session-start.md
Erik 3628aeb520 refactor(app): compose atomic frame roots
Move the complete update/render construction graph into a typed Phase-8 owner, explicitly carry the content dependencies it consumes, and publish both roots through one exact lease. Extract lifecycle resource sampling and frame-owned late bindings so partial startup and shutdown withdraw the same generation without window callbacks.

Co-authored-by: Codex <codex@openai.com>
2026-07-22 19:02:08 +02:00

10 KiB
Raw Blame History

GameWindow Slice 8 — Checkpoint I.8 Frame Roots and Session Start

Status: Active — I.8aI.8b complete; I.8c terminal start 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:

  1. complete Phase 7 before any frame root is visible;
  2. construct update and render roots locally and publish the pair atomically;
  3. 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:

  1. create LiveSessionHost through the focused factory;
  2. create and bind LiveCombatModeCommandController;
  3. create and bind RuntimeDiagnosticCommandController;
  4. create GameplayInputCommandController and priority targets;
  5. 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

Completed 2026-07-22. FrameRootCompositionPhase now constructs the unchanged render and update graphs from explicit prior-phase results and focused runtime owners. GameFrameGraphSlot.PublishOwned publishes and withdraws one exact pair. Optional lifecycle automation has a Phase-8 binding owner, and WorldLifecycleResourceSnapshotSource samples the same canonical owners without window callbacks or mirrored counters. The Phase-8 contract now receives the Phase-2 content result explicitly because scripts and particles are real frame dependencies; this removes a hidden reach-back through the window shell.

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:

  1. teleport/login/GL-state and render-live preparation;
  2. render resource begin/clear/live phases;
  3. weather, sky-PES, world environment, camera, visibility, settings preview, root, animated-object, and building sources;
  4. terrain, PView, scene-pass, and world-scene diagnostics;
  5. optional lifecycle automation;
  6. retained/devtools/private presentation;
  7. render orchestrator;
  8. live-frame coordinator, camera frame, and update orchestrator;
  9. 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 LiveSessionHost borrowed 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:

  1. gameplay router detach;
  2. diagnostic and combat command unbind;
  3. remaining session/player bindings;
  4. teleport, live session, and streamer teardown.

After frame publication, Phase-8 rollback is:

  1. exact frame-pair withdrawal;
  2. automation/other frame binding detach;
  3. no disposal of resources borrowed from earlier successful phases.

Normal shutdown retains the frozen barrier order:

  1. logical input/command quiescence;
  2. live-session convergence;
  3. physical input callback detach;
  4. frame-pair withdrawal;
  5. frame then session/player late-binding detach;
  6. 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 GameWindow field 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;
  • GameWindow contains 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

  1. docs(architecture): plan frame roots and terminal session start
  2. refactor(app): complete session startup composition
  3. refactor(app): compose atomic frame roots
  4. refactor(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.