acdream/docs/plans/2026-07-22-gamewindow-slice-8-checkpoint-i-ordered-composition.md

16 KiB
Raw Blame History

GameWindow Slice 8 Checkpoint I — ordered production composition

Status: Active 2026-07-22.
Parent: 2026-07-22-gamewindow-slice-8-composition-lifecycle.md, Checkpoint I.
Integrated baseline: c791f138; the reviewed Checkpoint-H tree plus the complete-world-reveal history is merged. GameWindow.cs is 3,689 raw lines, 162 fields, and 37 methods. The Release build succeeds with the 17 warnings tracked by #228 and all 7,606 tests pass / 5 intentionally skip.
Behavior rule: startup ownership and failure behavior may become explicit; accepted input priority, settings, session/reset, update/render order, world presentation, and retail gameplay behavior do not change.

1. Outcome

Replace the 2,149-line GameWindow.OnLoad body with one fixed production composition pipeline. GameWindow remains the native host and write-only publication shell. It does not become a service locator, and no extracted phase stores or calls back into GameWindow.

The final startup shape is:

GameWindow.OnLoad
  -> GameWindowPlatformAcquisition.Acquire
  -> GameWindowCompositionPipeline.Run
       1 Host input / camera
       2 Content / effects / audio
       3 Settings / optional devtools
       4 World / render resources
       5 Interaction / retained UI
       6 Live presentation / landblock publication
       7 Streaming / session / local player / teleport
       8 Atomic update + render roots
       9 LiveSessionHost.Start, and nothing after it

Every phase consumes only the exact immutable prior results it needs and returns a cohesive typed result. Results are borrowers. Newly acquired owners move immediately into the existing lifetime slots, where shutdown remains the sole release authority.

2. Fixed architecture

2.1 Platform prelude

GameWindowPlatformAcquisition is the exact production method used by OnLoad. Its order is fixed:

  1. create GL;
  2. publish GL to the lifetime shell;
  3. create the input context;
  4. publish input;
  5. return borrowed platform handles.

GL publication must happen before the input factory runs. An input-factory failure leaves GL lifetime-owned for normal shutdown; local rollback never double-disposes it. Viewport, diagnostics, camera, and GPU-frame resources are not part of this narrow prelude.

2.2 Pipeline contract

Use nine explicit phase interfaces and immutable result records. The pipeline holds no cumulative context and stores no final runtime graph. Locals pass only the required sub-results forward.

Representative result grouping:

HostInputCameraResult(InputGraph, CameraGraph, HostRenderGraph)
ContentEffectsAudioResult(ContentCatalogs, EffectsGraph, AudioGraph?)
SettingsDevToolsResult(ResolvedQuality, DevToolsGraph?)
WorldRenderResult(TerrainBuildContext, RenderFoundation)
InteractionUiResult(InteractionGraph, RetainedUiGraph?)
LivePresentationResult(LiveEntityGraph, WorldPresentationGraph)
SessionPlayerResult(StreamingGraph, SessionGraph, PlayerGraph, FrameParts)
FrameRootResult(LiveSessionHost)
SessionStartResult

Nested records are cohesive typed graphs, not dictionaries, object bags, general service providers, or wrappers around the window.

2.3 Publication seam

GameWindow implements narrow write-only phase publishers. Publication methods only validate single assignment and assign the existing shell fields. They do not construct resources, invoke gameplay behavior, or provide runtime lookup. The pipeline and phases release the publisher reference when Run returns.

Platform publication is narrower still so GL can publish before input creation. Checkpoint J will move the exact shutdown manifest into the lifetime owner; Checkpoint I does not duplicate or reorder that manifest.

2.4 Acquisition and rollback

Every concrete phase uses CompositionAcquisitionScope and named typed leases:

  • unpublished acquisitions roll back in strict reverse dependency order;
  • publication or transfer removes the resource from local rollback immediately;
  • lifetime-owned resources are never released locally;
  • cleanup continues after an independent cleanup failure;
  • the original construction failure and cleanup failures are retained;
  • retry invokes only unfinished cleanup actions;
  • successful cleanup never replays;
  • duplicate publication and duplicate transfer are rejected.

This is not a generic shutdown bag. Long-lived owners remain in their focused H-era slots and are retired in dependency order by the existing shutdown transaction.

3. Frozen phase order and dependencies

Phase 1 — host input and camera

Acquire viewport target, GPU-frame owner, world render diagnostics, keyboard and mouse sources, input dispatcher, movement/camera bindings, mouse-look cursor, orbit/fly camera, framebuffer camera target, and raw pointer owner.

Preserve:

  • keyboard/mouse source attach before dispatcher attach;
  • dispatcher attach before raw MouseMove attach;
  • raw pointer attach before retained-UI device wiring;
  • physical framebuffer size remains distinct from logical window size.

Phase 2 — content, effects, and audio

Open the sole DatCollection; load magic, animation, collision, emitter, particle, hook-frame, physics-script, lighting, and translucency owners. Audio is optional, but failure can be swallowed only after its entire unpublished prefix has converged cleanup. Hook-router registrations are reversible leases.

The physics-script advancement gate resolves the later entity-effect authority through one typed deferred source; it must not capture the window or a null snapshot.

Phase 3 — settings and optional devtools

Apply the immutable startup settings snapshot after camera/audio exist and before world/render/UI factories consume it. Compose optional devtools with a transactional input/bootstrap/backend/framebuffer-target lease. Disabled devtools acquire nothing. A devtools construction failure disables the feature only after cleanup converges; cleanup failure fails startup rather than stranding callbacks or native state.

Devtools live facts use focused sources for render diagnostics, canonical world state, player mode, and player controller. No callback captures the host.

Phase 4 — world and render resources

Load Region/environment/height/blend data, validate bindless support, then construct terrain atlas, terrain shader, scene lighting, debug/text resources, terrain renderer, WB mesh/render infrastructure, texture/sampler caches, and the render foundation.

Required order includes bindless before atlas/terrain, and the final immutable height/blend/surface build inputs are captured directly for worker use. Constructor prefixes for debug lines, bitmap font, OpenGL graphics device, particle batcher, global mesh buffers, portal depth, particles, samplers, and terrain renderer must have a strong transactional guarantee.

Phase 5 — interaction and retained UI

Compose combat target/attack, external-container and item interaction, character/magic controllers, radar/chat/cursor assets, UiHost, and the retained runtime lease. Retained bindings to later session, reveal, player, diagnostic, and live-entity authorities use focused deferred sources. Host, partial runtime, mounted runtime, and input bindings retain exact ownership.

Phase 6 — live presentation and landblock publication

Compose WB/spawn adapters, canonical GpuWorldState, LiveEntityRuntime, live motion/projectile/animation/effect/presentation owners, selection/paperdoll, EnvCell/portal/sky/particle renderers, landblock publishers, and render diagnostics. Bind the canonical live-runtime slot immediately after runtime creation. Anonymous retained event handlers become named reversible bindings.

Portal tunnel ownership remains acquire -> prepare -> transfer. The fallback slot and final controller never co-own the same resource.

Phase 7 — streaming, session, local player, and teleport

Compose and publish the streamer before Start, then streaming/recenter/reveal, session/hydration/network/liveness, player-mode/local-animation/shadow, gameplay-input, commands, action-router, live-session host, and teleport owners. All UI and devtool late sources bind here.

The current premature frame-root publication defect is removed: command bindings and gameplay-action attachment complete in Phase 7, before Phase 8.

Phase 8 — atomic frame roots

Construct all update/render leaves locally, then both roots, and publish the pair once through GameFrameGraphSlot as the final phase action. A failure before publication leaves the slot empty. A failure after publication leaves the lifetime owner responsible for exactly one paired graph. No callback can observe a half-pair.

Phase 9 — terminal session start

Invoke only LiveSessionHost.Start. It is the absolute last startup operation. There is no publication, callback attachment, command binding, or diagnostics work afterward.

4. Focused live sources and reversible edges

Replace current host captures with focused authorities:

  • ILocalPlayerIdentitySource for the server GUID;
  • ILocalPlayerModeSource for player/fly state;
  • a player-controller slot for current movement facts;
  • RenderRangeState for near radius;
  • LiveWorldOriginState for center coordinates;
  • external-container state for current container;
  • focused deferred session command/host authority;
  • a canonical world-state source that cannot freeze the pre-runtime placeholder;
  • typed item/use/pick/selection/debug-fact operations;
  • immutable phase-4 terrain worker inputs.

Add expected-owner unbind tokens for one-shot deferred composition slots that can be bound before a later fallible edge. A failed phase must be disposable and retryable without stale bindings or “already bound” failures.

Named reversible bindings replace anonymous subscriptions for projection visibility, projection pose, entity-ready, appearance-applied, hook sinks, and streamer start/stop.

5. Implementation checkpoints

  1. I.1 — contracts and executable oracle: pipeline, platform prelude, acquisition scope, fake phases, prefix/failure tests.
  2. I.2 — platform + Phase 1: exact GL/input publication and host input/camera cutover.
  3. I.3 — Phase 2: content/effects/audio, reversible hooks, transactional OpenAL construction.
  4. I.4 — Phase 3: settings/devtools, complete optional rollback.
  5. I.5 — Phase 4: world/render foundation and strong constructor guarantees.
  6. I.6 — Phases 56: retained UI, live presentation, landblock publishers, typed late sources and event leases.
  7. I.7 — Phase 7: streaming/session/player/teleport and all pre-frame bindings.
  8. I.8 — Phases 89: atomic roots, terminal start, delete old OnLoad body, structural gates.
  9. I.9 — corrected-diff review, full gates, docs/memory, one bisectable Checkpoint-I closeout commit.

Small implementation commits may be used while the checkpoint is active, but each must build and preserve production startup. The final I commit closes the ledger only after the complete pipeline is live.

Current implementation progress — 2026-07-22

  • I.1I.4 are committed: the executable pipeline/rollback oracle, platform acquisition, host input/camera, content/effects/audio, and settings/devtools phases are the production startup path.
  • I.5 is complete. WorldRenderCompositionPhase now owns the ordered Region, environment, mandatory bindless, terrain-atlas, shader, lighting, debug/HUD, terrain, WB, texture, and sampler foundation. GameWindow is a write-only publisher for this phase and no longer contains the Phase-4 construction body.
  • Every fallible GL constructor in the Phase-4 prefix now publishes each name into retryable construction ownership before later GL work. Failure testing covers every composition boundary, every disposable publication, partial HUD construction, reverse cleanup, retry, and no replay.
  • The I.5 tree is 3,522 raw GameWindow.cs lines. The App gate passes 3,373 tests / 3 intentional skips; the complete Release suite passes 7,745 tests / 5 intentional skips. Production App builds with zero warnings/errors; the solution retains only the 17 warnings tracked by #228.
  • I.6 (retained UI plus live-presentation composition) is complete. Its detailed two-commit ownership and failure-test plan is 2026-07-22-gamewindow-slice-8-checkpoint-i6-ui-live-presentation.md. Phase 5 now composes interaction and retained UI through typed dependencies, exact-owner late bindings, and transactional rollback. Phase 6 now composes the canonical live runtime/world, presentation/effect controllers, selection/radar, landblock publishers, and portal/sky/particle resources under the same ownership contract. GameWindow.cs is 2,840 raw lines; the App gate passes 3,407 tests / 3 intentional skips and the complete Release suite passes 7,779 tests / 5 intentional skips. I.7 session, streaming, and hydration composition is the active cut. Checkpoint I remains active until I.9 closes the complete nine-phase pipeline.

6. Automated acceptance

Platform and pipeline

  • Success trace is exactly gl.factory -> gl.publish -> input.factory -> input.publish.
  • GL-factory failure never calls input; input-factory failure retains GL in the lifetime owner.
  • Failure at each of nine phases runs exactly the preceding prefix and no suffix.
  • Every phase receives the exact immutable prior result instance.
  • Success trace is phases 18 followed by terminal session start.
  • Failure after frame publication withdraws the pair exactly once.

Acquisition and concrete phases

  • A/B/C prefix tests prove reverse rollback, transfer, aggregation, retry, and no replay.
  • Every concrete production phase has injected fault points at each acquisition/attach/bind/publication edge.
  • Optional audio/devtools continue only after successful rollback.
  • Hook and event registrations unregister exactly once.
  • Deferred slots unbind only the exact owner and reject stale release.
  • Streamer start is reversed on later Phase-7 failure.
  • Portal fallback/controller never co-own.
  • Phase 8 never exposes one frame root without the other.

Structural and repository gates

  • OnLoad is a small platform/pipeline forwarder.
  • No phase stores GameWindow, accepts a callback facade for substantial host methods, or uses a service locator / object dictionary.
  • GameWindow contains no construction body larger than one paragraph.
  • AcDream.Core gains no App/GL dependency.
  • App production build has zero warnings/errors; solution warnings remain only the 17 tracked by #228.
  • Focused tests, all App tests, and full Release suite pass.
  • Connected lifecycle/reconnect and synchronized soak gates remain green when the local ACE/visual environment is available.

7. Review gate

After the complete production cutover, run three independent read-only reviews:

  1. retail/behavior-order conformance;
  2. architecture, dependency direction, ownership, and shutdown symmetry;
  3. adversarial failure, partial construction, reentrancy, and stale-binding analysis.

Fix every confirmed finding at its root and repeat review until all three are clean. No review finding is waived merely because the happy-path tests pass.

8. Documentation and commit exit

Checkpoint I closes only when the code-structure ledger, architecture, roadmap, milestones, issues, memory/project_gamewindow_decomposition.md, AGENTS.md, and CLAUDE.md agree on the same production pipeline and measured class size. No retail-divergence row is added for a behavior-preserving ownership move; any discovered behavioral adaptation is recorded in the same commit that keeps it.