From 9a150e242169600ef7753e34072c83d268800b14 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 21 Jul 2026 10:03:20 +0200 Subject: [PATCH] docs(architecture): close live animation slice Record the shipped presentation owner, exact frame-handoff lifetime, retail short-frame behavior, current GameWindow metrics, and Slice 3 as the next structural boundary. --- AGENTS.md | 13 ++++--- CLAUDE.md | 13 ++++--- docs/architecture/code-structure.md | 19 +++++++--- docs/plans/2026-04-11-roadmap.md | 16 ++++++--- docs/plans/2026-05-12-milestones.md | 7 ++-- ...dow-slice-2-live-animation-presentation.md | 13 ++++++- memory/project_animation_runtime.md | 36 +++++++++++++++++++ 7 files changed, 94 insertions(+), 23 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ce61024d..6a5b179b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -115,16 +115,19 @@ and the final two-client portal-out/materialization observer flow are user-gated. Deterministic world-lifecycle automation protects fresh login, outdoor/world-edge/dungeon travel, same-location revisit, exact graceful disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts. -Release builds; 6,558 tests pass / 5 skip (17 tracked warnings, #228). +Release builds; 6,575 tests pass / 5 skip (17 tracked warnings, #228). **Active prerequisite before new M4 subsystem work:** continue the behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21. Selection/interaction Slice 1 is complete: `WorldSelectionQuery` and `SelectionInteractionController` own the domain, exact-incarnation queued work, -and retail's shared inventory-request transaction. Slice 2 finishes live -animation presentation; later slices finish live-session and live-entity App -integration, landblock presentation, update/render orchestration, and -composition cleanup. +and retail's shared inventory-request transaction. Live-animation-presentation +Slice 2 is also complete: `LiveEntityAnimationPresenter` owns final visual and +rigid PartArray composition, effect poses, and MotionDone; scheduler handoffs +are incarnation-, clock-, projection-, and appearance-bound. `GameWindow` is +14,546 lines, 277 fields, and 190 methods. Slice 3 completes live-session +ownership next; later slices finish live-entity App integration, landblock +presentation, update/render orchestration, and composition cleanup. See `docs/architecture/code-structure.md`. **Carried:** #153, #116, remaining R6 ownership cleanup, TS-50/TS-51, Modern Pipeline MP1b+, and #225's lifestone/particle alpha visual gate. diff --git a/CLAUDE.md b/CLAUDE.md index 0ba9129b..2ed93be2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,16 +113,19 @@ and the final two-client portal-out/materialization observer flow are user-gated. Deterministic world-lifecycle automation protects fresh login, outdoor/world-edge/dungeon travel, same-location revisit, exact graceful disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts. -Release builds; 6,558 tests pass / 5 skip (17 tracked warnings, #228). +Release builds; 6,575 tests pass / 5 skip (17 tracked warnings, #228). **Active prerequisite before new M4 subsystem work:** continue the behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21. Selection/interaction Slice 1 is complete: `WorldSelectionQuery` and `SelectionInteractionController` own the domain, exact-incarnation queued work, -and retail's shared inventory-request transaction. Slice 2 finishes live -animation presentation; later slices finish live-session and live-entity App -integration, landblock presentation, update/render orchestration, and -composition cleanup. +and retail's shared inventory-request transaction. Live-animation-presentation +Slice 2 is also complete: `LiveEntityAnimationPresenter` owns final visual and +rigid PartArray composition, effect poses, and MotionDone; scheduler handoffs +are incarnation-, clock-, projection-, and appearance-bound. `GameWindow` is +14,546 lines, 277 fields, and 190 methods. Slice 3 completes live-session +ownership next; later slices finish live-entity App integration, landblock +presentation, update/render orchestration, and composition cleanup. See `docs/architecture/code-structure.md`. **Carried:** #153, #116, remaining R6 ownership cleanup, TS-50/TS-51, Modern Pipeline MP1b+, and #225's lifestone/particle alpha visual gate. diff --git a/docs/architecture/code-structure.md b/docs/architecture/code-structure.md index 633ea2b4..cb96795c 100644 --- a/docs/architecture/code-structure.md +++ b/docs/architecture/code-structure.md @@ -1,7 +1,7 @@ # acdream — code structure & extraction sequence **Status:** Living document. Created 2026-05-16; implementation reconciliation -completed 2026-07-21; Slice 1 landed the same day. This is the active +completed 2026-07-21; Slices 1 and 2 landed the same day. This is the active structural program before new M4 subsystems enter the App layer. **Purpose:** Describe the desired structural state of the App layer, explain the rules we've adopted, and lay out the safe extraction @@ -24,6 +24,7 @@ The structural debt is concentrated in **one file**: ``` baseline cf50ee3d 15,723 lines / 278 fields / 205 methods after Slice 1 14,912 lines / 278 fields / 191 methods +after Slice 2 14,546 lines / 277 fields / 190 methods ``` `GameWindow` is the single object that: @@ -388,7 +389,7 @@ useful ordering seam, but its ownership status is **partial**. | Startup options | **Complete** | `RuntimeOptions` owns startup configuration (`eda936dc`). Remaining direct environment reads are legacy runtime diagnostics, not startup configuration. | | Network session | **Partial** | `LiveSessionController` owns endpoint resolution, `WorldSession` construction, ticking, and disposal (`0b25df53`). `TryStartLiveSession`, character choice/entry, session clearing, about 440 lines of subscriptions, and most App packet handlers remain in `GameWindow`. | | Live identity/lifetime | **Complete core owner** | `LiveEntityRuntime` owns incarnation identity, accepted snapshots/timestamps, runtime components, logical/spatial lifetime, and teardown. `GameWindow` still owns large hydration and wire-to-presentation adapter bodies. | -| Inbound/object-frame order | **Partial** | `RetailInboundEventDispatcher`, `RetailLiveFrameCoordinator`, `LiveEntityAnimationScheduler`, static scheduler, remote/projectile updaters, and teleport owners are shipped. `AdvanceLiveObjectRuntimeCore`, final part/mesh/effect composition, and several integration tails remain in `GameWindow`. | +| Inbound/object-frame order | **Partial** | `RetailInboundEventDispatcher`, `RetailLiveFrameCoordinator`, `LiveEntityAnimationScheduler`, `LiveEntityAnimationPresenter`, static scheduler, remote/projectile updaters, and teleport owners are shipped. `AdvanceLiveObjectRuntimeCore` retains the visible cross-owner order until Slice 6. | | World reveal | **Complete** | `WorldRevealCoordinator` owns login/portal readiness and reveal lifetime (`a4ef5788`). The accepted deterministic lifecycle trace did not change after extraction. | | Retained gameplay UI | **Mostly complete feature ownership** | `RetailUiRuntime` and focused panel/controllers own layout and behavior. `GameWindow.OnLoad` still performs substantial service composition, which is allowed until the final composition cleanup. | | Selection/interaction | **Complete** | `WorldSelectionQuery` owns read-only picking/classification/range queries; `SelectionInteractionController` owns selection intent, Use/PickUp transport, exact-incarnation queues, and auto-walk deferral; `ItemInteractionController` owns ItemHolder policy plus the shared retail inventory-request transaction. `GameWindow` retains construction and narrow lifecycle forwarding only. | @@ -443,7 +444,7 @@ legacy state for composed owners. Three independent retail, architecture, and adversarial review loops finished clean. Release build passed; 6,558 tests passed and five fixture/conformance tests skipped intentionally. -#### Slice 2 — finish live animation presentation — NEXT +#### Slice 2 — finish live animation presentation — COMPLETE 2026-07-21 Move `TickAnimations`, final rigid/visual part composition, effect-pose publication, and motion-done binding into `LiveEntityAnimationPresenter`. @@ -457,7 +458,17 @@ rigid effect poses, part availability, same-frame hook pose publication, and incarnation replacement. Run the R6 object-frame and projectile/effect suites plus the connected locomotion/projectile gate. -#### Slice 3 — complete live-session ownership +Result: `LiveEntityAnimationPresenter` owns final visual/rigid part +composition, effect-pose publication, MotionDone binding, and typed diagnostics. +Schedules carry exact record/entity/component/epoch/projection/presentation +identity and own their authored frame prefix until the next scheduler tick. +Appearance and static-owner rebinding invalidate stale work. Named-retail +`CPartArray::UpdateParts` short-frame retention now preserves both visual and +rigid trailing poses. `GameWindow` lost 366 lines, two methods, and one net +field. Three independent retail, architecture, and adversarial review loops +finished clean; focused App/Core tests and the complete App suite pass. + +#### Slice 3 — complete live-session ownership — NEXT Expand `LiveSessionController` to own connect, character-list validation, character selection, EnterWorld, graceful character logout, reconnect, and diff --git a/docs/plans/2026-04-11-roadmap.md b/docs/plans/2026-04-11-roadmap.md index 8c5ca825..f9353755 100644 --- a/docs/plans/2026-04-11-roadmap.md +++ b/docs/plans/2026-04-11-roadmap.md @@ -21,10 +21,16 @@ stateful intent owner are extracted, exact-incarnation lifetime is enforced, and retail's global inventory-request transaction is shared across every UI mutation surface. `GameWindow` is 811 lines and 14 methods smaller. -**Next:** Slice 2 finishes live animation presentation by moving final -part/mesh/effect-pose composition and motion-done binding behind -`LiveEntityAnimationPresenter`, while preserving the shipped scheduler and -retail object-frame order. +Slice 2 live animation presentation landed 2026-07-21: final visual/rigid +PartArray composition, effect-pose publication, MotionDone binding, and +diagnostics now live in `LiveEntityAnimationPresenter`. Exact incarnation, +projection, object-clock, and appearance-revision tokens reject stale work; +ordinary/static frame handoffs own their buffers; retail short AnimFrames +retain trailing visible and rigid poses. `GameWindow` is now 14,546 lines. + +**Next:** Slice 3 completes live-session ownership by moving connection, +character entry, typed event subscriptions, graceful logout, reconnect, and +session-scoped cleanup behind `LiveSessionController`/`LiveSessionEventRouter`. This is a behavior-preserving structural program. Severe regressions still get root-cause fixes in separate commits; ordinary feature work resumes with M4 @@ -1479,7 +1485,7 @@ OpenGL ceiling; revisit macOS only if a supported graphics backend is chosen. ## Cross-cutting work tracked in parallel -- **Test coverage.** Each phase lands with layer-matched unit and integration tests in `tests/`. Current Release baseline: 6,558 passed / 5 intentional skips (2026-07-21). +- **Test coverage.** Each phase lands with layer-matched unit and integration tests in `tests/`. Current Release baseline: 6,575 passed / 5 intentional skips (2026-07-21). - **Memory files.** Live subsystem state and digests are indexed by `claude-memory/MEMORY.md`; stable engineering references remain under `memory/`. Canonical program status stays in milestones/roadmap/issues. - **`CLAUDE.md` discipline.** Check all four references (ACE, ACViewer, WorldBuilder, Chorizite) before committing to an approach. WorldBuilder is the closest stack match and should be checked first. diff --git a/docs/plans/2026-05-12-milestones.md b/docs/plans/2026-05-12-milestones.md index ac36e633..009d6bc8 100644 --- a/docs/plans/2026-05-12-milestones.md +++ b/docs/plans/2026-05-12-milestones.md @@ -17,14 +17,15 @@ layer, the active structural prerequisite is the behavior-preserving `GameWindow` decomposition in [`docs/architecture/code-structure.md`](../architecture/code-structure.md). The 2026-07-21 audit baseline was 15,723 lines, 278 fields, and 205 methods. -Selection/interaction Slice 1 is complete at 14,912 lines, 278 fields, and 191 -methods. Slice 2 — final live animation presentation ownership — is next. +Selection/interaction Slice 1 and live-animation-presentation Slice 2 are +complete. `GameWindow` is now 14,546 lines, 277 fields, and 190 methods. Slice 3 +— complete live-session ownership — is next. Carried: #153 far-teleport residual, #116 slide-response, the remaining R6 ownership cleanup plus registered TS-50/TS-51 timing residuals (the complete-root-Frame/object-workset cutover is automated- and visual-gate complete; Release builds with 17 known -test-project warnings tracked by #228, and 6,558 tests pass / 5 skip), and +test-project warnings tracked by #228, and 6,575 tests pass / 5 skip), and the deferred Modern Pipeline track (MP1b+). The separate #225 shared-alpha implementation has passed connected lifetime/performance gates and awaits only its lifestone/particle visual comparison. diff --git a/docs/plans/2026-07-21-gamewindow-slice-2-live-animation-presentation.md b/docs/plans/2026-07-21-gamewindow-slice-2-live-animation-presentation.md index f7cbac56..67ce907f 100644 --- a/docs/plans/2026-07-21-gamewindow-slice-2-live-animation-presentation.md +++ b/docs/plans/2026-07-21-gamewindow-slice-2-live-animation-presentation.md @@ -1,9 +1,14 @@ # GameWindow Slice 2 — live animation presentation ownership -**Status:** Approved for execution 2026-07-21. +**Status:** Complete 2026-07-21. Automated and three-agent review gates pass; +connected visual regression gate is carried to the final campaign gate. **Parent program:** [`docs/architecture/code-structure.md`](../architecture/code-structure.md), Slice 2. **Baseline:** `9ad8113c`; `GameWindow.cs` is 14,912 lines, 278 fields, and 191 methods before this slice. +**Result:** `GameWindow.cs` is 14,546 lines, 277 fields, and 190 methods. +The slice also closed stale-schedule ABA across replacement, appearance +rebinding, static rebind, and borrowed sequencer buffers. Forty-one focused +Release tests and the full 6,575-pass / 5-skip Release suite are green. **Behavior rule:** This is an ownership extraction over the accepted R6 object frame plus one named-retail conformance correction: short AnimFrames retain the prior/rest pose of trailing CPartArray parts. It must not otherwise change @@ -335,6 +340,12 @@ Additional invariants: ### Cross-owner order and reconciliation +The presenter-level portions below are covered by Slice 2. The full +instrumented owner-order trace and non-advancing spatial-reconcile assertion +remain assigned to Slice 6, where the update sequence becomes one testable +orchestrator instead of a `GameWindow` method. Slice 2 preserves that order but +does not claim an end-to-end orchestrator test prematurely. + - One instrumented object-frame test pins presenter, children, static hooks, fades, ordinary hook drain, effect roots, emitters, lights, particles, and scripts. A PES-created particle first simulates on the following frame. diff --git a/memory/project_animation_runtime.md b/memory/project_animation_runtime.md index c20dee3b..1cb8fcd3 100644 --- a/memory/project_animation_runtime.md +++ b/memory/project_animation_runtime.md @@ -1,5 +1,41 @@ # Animation Runtime Crib +## Current live presentation ownership (2026-07-21) + +`LiveEntityAnimationScheduler` owns ordinary-object time, PartArray advance, +root motion, and the retail manager tail. `RetailStaticAnimatingObjectScheduler` +owns the separate retail static-object workset. `LiveEntityAnimationPresenter` +is the sole consumer that composes final drawable part transforms, publishes +rigid part/effect poses, and binds `MotionDone`. `GameWindow` wires these owners +but no longer contains the presentation body. + +The frame handoff is identity- and lifetime-bound. A schedule carries the exact +`LiveEntityRecord`, `WorldEntity`, animation state, sequencer, object-clock +epoch, projection mutation version, and presentation revision. Both ordinary +and static schedulers copy the sequencer's borrowed PartArray view into their +own buffers before invoking callbacks. Presentation is non-reentrant because +it consumes legacy elapsed time and static prepared frames exactly once. + +Appearance rebinding increments `PresentationRevision`. That rejects a pose +prepared against the old part template without replacing the live animation +component. For a static owner, rejecting only that stale visual pose must retain +the same sequencer's pending `process_hooks` tail so `MotionDone` is not lost; +owner, sequencer, residency, projection, or clock mismatches still invalidate +the entire handoff. + +Retail `CPartArray::UpdateParts` updates only the authored AnimFrame prefix. +When a frame contains fewer parts than the Setup, trailing parts keep their +previous pose (or their rest pose on first presentation) in both channels: + +- visual: `DefaultScale * rotation * translation(origin) * ObjScale`; +- rigid/effect: `rotation * translation(origin * ObjScale)`. + +Canonical per-frame order remains scheduler tick, static tick, live presenter, +equipped-child update, static `process_hooks`, deferred hook drain, attached +effects/lights, particles, and draw. The end-to-end order assertion belongs to +Slice 6's extracted update orchestrator; do not reintroduce local ordering into +the presenter. + ## Live entity lifecycle invariant `CreateObject` creates a live entity and a real `DeleteObject` destroys it.