docs(architecture): reconcile GameWindow extraction program

Close the completed M3 and portal observer gates, make the behavior-preserving GameWindow ownership campaign the explicit M4 prerequisite, and replace the stale extraction sketch with an implementation-audited sequence.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-21 06:44:29 +02:00
parent f4cf802330
commit cf50ee3d50
8 changed files with 354 additions and 220 deletions

View file

@ -108,23 +108,26 @@ movement queries.
## Current state ## Current state
**M3 — Cast a spell ACTIVE; automated implementation and connected **M3 — Cast a spell LANDED 2026-07-21. M4 — Live in the world NEXT.** Retail
single-client gates complete.** Retail cast intent, component/target gates, casting, spellbook/component-book UI, active effects, recall/portal-space
live enchantment wire, Magic-scoped input, spell bar, spellbook, component presentation, the R6 locomotion/collision/projectile/teleport/radar rebaseline,
book, effect indicators, shared main-panel switching, and positive/negative and the final two-client portal-out/materialization observer flow are
effects UI are implemented over the Step-9 projectile/DAT-effect foundation. user-gated. Deterministic world-lifecycle automation protects fresh login,
The R6 complete-root-Frame/object-workset cutover and its unattended
seven-destination input/portal/performance rebaseline pass. The 2026-07-20
deterministic world-lifecycle gate additionally protects fresh login,
outdoor/world-edge/dungeon travel, same-location revisit, exact graceful outdoor/world-edge/dungeon travel, same-location revisit, exact graceful
disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts. disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts.
Release builds; 6,480 tests pass / 5 skip (17 tracked warnings, #228). Release builds; 6,481 tests pass / 5 skip (17 tracked warnings, #228).
**Next:** the R6 locomotion/collision/projectile/teleport local visual
rebaseline when a local view is available, then the final two-client **Active prerequisite before new M4 subsystem work:** complete the
portal-out/materialization observer gate. **Carried:** #153, #116, remaining behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21. The
next slice finishes selection/interaction ownership; later slices finish
animation presentation, live-session and 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 R6 ownership cleanup, TS-50/TS-51, Modern Pipeline MP1b+, and #225's
lifestone/particle alpha visual gate. lifestone/particle alpha visual gate.
Start magic work at `claude-memory/project_magic_ui_and_casting.md`; start
Start structural work at `docs/architecture/code-structure.md`; start
magic follow-up at `claude-memory/project_magic_ui_and_casting.md`; start
render/streaming work at `claude-memory/project_render_pipeline_digest.md`. render/streaming work at `claude-memory/project_render_pipeline_digest.md`.
Documentation entry point: [`docs/README.md`](docs/README.md). Documentation entry point: [`docs/README.md`](docs/README.md).

View file

@ -106,23 +106,26 @@ movement queries.
## Current state ## Current state
**M3 — Cast a spell ACTIVE; automated implementation and connected **M3 — Cast a spell LANDED 2026-07-21. M4 — Live in the world NEXT.** Retail
single-client gates complete.** Retail cast intent, component/target gates, casting, spellbook/component-book UI, active effects, recall/portal-space
live enchantment wire, Magic-scoped input, spell bar, spellbook, component presentation, the R6 locomotion/collision/projectile/teleport/radar rebaseline,
book, effect indicators, shared main-panel switching, and positive/negative and the final two-client portal-out/materialization observer flow are
effects UI are implemented over the Step-9 projectile/DAT-effect foundation. user-gated. Deterministic world-lifecycle automation protects fresh login,
The R6 complete-root-Frame/object-workset cutover and its unattended
seven-destination input/portal/performance rebaseline pass. The 2026-07-20
deterministic world-lifecycle gate additionally protects fresh login,
outdoor/world-edge/dungeon travel, same-location revisit, exact graceful outdoor/world-edge/dungeon travel, same-location revisit, exact graceful
disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts. disconnect, and uncapped fresh-process reconnect with JSON/PNG artifacts.
Release builds; 6,480 tests pass / 5 skip (17 tracked warnings, #228). Release builds; 6,481 tests pass / 5 skip (17 tracked warnings, #228).
**Next:** the R6 locomotion/collision/projectile/teleport local visual
rebaseline when a local view is available, then the final two-client **Active prerequisite before new M4 subsystem work:** complete the
portal-out/materialization observer gate. **Carried:** #153, #116, remaining behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21. The
next slice finishes selection/interaction ownership; later slices finish
animation presentation, live-session and 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 R6 ownership cleanup, TS-50/TS-51, Modern Pipeline MP1b+, and #225's
lifestone/particle alpha visual gate. lifestone/particle alpha visual gate.
Start magic work at `claude-memory/project_magic_ui_and_casting.md`; start
Start structural work at `docs/architecture/code-structure.md`; start
magic follow-up at `claude-memory/project_magic_ui_and_casting.md`; start
render/streaming work at `claude-memory/project_render_pipeline_digest.md`. render/streaming work at `claude-memory/project_render_pipeline_digest.md`.
Documentation entry point: [`docs/README.md`](docs/README.md). Documentation entry point: [`docs/README.md`](docs/README.md).

View file

@ -24,12 +24,12 @@ What does NOT go here:
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending. - Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed. - Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
## Current queue — 2026-07-20 ## Current queue — 2026-07-21
- **Next visual gate:** R6 locomotion/collision/projectile/teleport comparison - **Active structural work:** `GameWindow` decomposition, beginning with the
after the complete-root-Frame/object-workset cutover. selection/interaction ownership slice in
- **M3 closing gate:** `#218`, final two-client portal-out/materialization and [`docs/architecture/code-structure.md`](architecture/code-structure.md).
indoor observer comparison. This is the behavior-preserving prerequisite before new M4 feature bodies.
- **Separate rendering gate:** `#225`, lifestone/particle alpha ordering. Its - **Separate rendering gate:** `#225`, lifestone/particle alpha ordering. Its
connected performance, lifetime, and unattended portal routes pass. connected performance, lifetime, and unattended portal routes pass.
- **Carried behavior debt:** `#153` far-teleport unstreamed-edge arrival and - **Carried behavior debt:** `#153` far-teleport unstreamed-edge arrival and
@ -98,7 +98,7 @@ production runtime failure.
**Acceptance:** A non-incremental Release solution build reports zero warnings **Acceptance:** A non-incremental Release solution build reports zero warnings
and zero errors without suppressing analyzers or weakening nullable checking; and zero errors without suppressing analyzers or weakening nullable checking;
the full 6,480-pass / 5-skip suite remains green. the full 6,481-pass / 5-skip suite remains green.
--- ---
@ -565,7 +565,7 @@ Passed 2026-07-17: “Yes works.”
## #218 — Portal silhouette pose, destination reveal, and indoor observer snap ## #218 — Portal silhouette pose, destination reveal, and indoor observer snap
**Status:** IN-PROGRESS — root fixes implemented 2026-07-16; pending connected visual gate **Status:** DONE — 2026-07-21, final two-client observer gate user-confirmed
**Severity:** HIGH **Severity:** HIGH
**Filed:** 2026-07-16 **Filed:** 2026-07-16
**Component:** portal VFX / streaming / physics / outbound movement **Component:** portal VFX / streaming / physics / outbound movement
@ -635,6 +635,9 @@ pose; outdoor exits reveal only fully rendered terrain/scenery; and a retail
observer sees acdream run and stop repeatedly inside a dungeon without any observer sees acdream run and stop repeatedly inside a dungeon without any
snap back to the entrance. snap back to the entrance.
**Gate:** Passed 2026-07-21. The user confirmed the final two-client
portal-out/materialization and indoor observer comparison on the R6 baseline.
--- ---
## #217 — Character windows did not receive live 64-bit experience updates ## #217 — Character windows did not receive live 64-bit experience updates

View file

@ -4,23 +4,26 @@ This page is the entry point for project documentation. It distinguishes
current sources of truth from implementation history so an old plan or issue current sources of truth from implementation history so an old plan or issue
banner cannot silently override the current program state. banner cannot silently override the current program state.
## Current snapshot — 2026-07-20 ## Current snapshot — 2026-07-21
- **Active milestone:** M3, “Cast a spell.” The automated implementation and - **Milestone state:** M3, “Cast a spell,” landed 2026-07-21. M4, “Live in the
connected single-client magic/portal presentation gates are complete. world,” is next.
- **Next visual gates:** the R6 locomotion/collision/projectile/teleport retail - **Active program:** behavior-preserving `GameWindow` decomposition before
comparison, then the final two-client portal-out/materialization observer new M4 subsystem work. The reconciled ownership ledger and slice order are
comparison (`#218`). in [`architecture/code-structure.md`](architecture/code-structure.md); the
next slice finishes selection/interaction ownership.
- **Completed gates:** R6 locomotion/collision/projectile/teleport/radar and
the final two-client portal-out/materialization observer comparison (`#218`).
- **Separate visual verification:** the shared-alpha lifestone/particle result - **Separate visual verification:** the shared-alpha lifestone/particle result
in `#225`; its connected resource-lifetime and performance routes pass. in `#225`; its connected resource-lifetime and performance routes pass.
- **Carried behavior debt:** `#153` (far teleport onto an unstreamed edge), - **Carried behavior debt:** `#153` (far teleport onto an unstreamed edge),
`#116` (two narrowed slide-response cases), and divergence rows TS-50/TS-51. `#116` (two narrowed slide-response cases), and divergence rows TS-50/TS-51.
- **Deferred engineering tracks:** Modern Pipeline MP1b+ and Linux/headless - **Deferred engineering tracks:** Modern Pipeline MP1b+ and Linux/headless
automation (Track LH). Neither is part of the active M3 gate. automation (Track LH). Neither is part of the active structural campaign.
- **Divergence audit:** 178 active rows — IA 17, AD 37, AP 85, TS 34, - **Divergence audit:** 178 active rows — IA 17, AD 37, AP 85, TS 34,
and UN 5 — plus the retained retired TS-37 history note. and UN 5 — plus the retained retired TS-37 history note.
- **Latest automated baseline:** Release build succeeds with 17 known - **Latest automated baseline:** Release build succeeds with 17 known
test-project warnings (`#228`); 6,457 tests passed and 5 intentionally test-project warnings (`#228`); 6,481 tests passed and 5 intentionally
skipped. The unattended connected R6 route skipped. The unattended connected R6 route
completed seven portal materializations, production input exercises, and a completed seven portal materializations, production input exercises, and a
graceful close. See graceful close. See

View file

@ -829,12 +829,18 @@ Current movement/collision ownership:
- **G.3 is shipped**: dungeon streaming, portal-space presentation, collision, - **G.3 is shipped**: dungeon streaming, portal-space presentation, collision,
lighting, doors, and the full round-trip gate landed. The separate far- lighting, doors, and the full round-trip gate landed. The separate far-
teleport unstreamed-edge residual is issue #153, not unfinished G.3. teleport unstreamed-edge residual is issue #153, not unfinished G.3.
- **M3** owns current connected magic/portal acceptance; Track LH is the future - **M3 landed 2026-07-21** with connected magic/portal acceptance and the final
presentation-independent Linux/headless extraction. two-client observer gate; Track LH is the future presentation-independent
Linux/headless extraction.
- **The behavior-preserving thin-`GameWindow` ownership campaign is the active
prerequisite before new M4 subsystem bodies.** Its reconciled ledger and
sequence live in `docs/architecture/code-structure.md`. This decision does
not reclassify the remaining L.2 conformance work or Track LH.
The GameEntity / thin GameWindow refactor remains a valid target architecture, Full `GameEntity` type aggregation remains a separate, higher-risk target after
but it is not a prerequisite for L.2. Do not resurrect old R1-R8 phase numbers the thin-`GameWindow` campaign. The current campaign reuses canonical
for new work; add or update roadmap phases instead. `LiveEntityRuntime` rather than introducing another entity owner. Do not
resurrect old R1-R8 phase numbers for new work; update the roadmap instead.
--- ---

View file

@ -1,11 +1,12 @@
# acdream — code structure & extraction sequence # acdream — code structure & extraction sequence
**Status:** Living document. Created 2026-05-16 as the companion to the **Status:** Living document. Created 2026-05-16; implementation reconciliation
"Code Structure Rules" section in `CLAUDE.md`. completed 2026-07-21. This is the active structural program before new M4
subsystems enter the App layer.
**Purpose:** Describe the desired structural state of 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 explain the rules we've adopted, and lay out the safe extraction
sequence from today's reality (one 14,557-line `GameWindow.cs` at the sequence from today's reality (one 15,723-line `GameWindow.cs` at the
2026-07-20 audit) to the 2026-07-21 audit) to the
target (thin `GameWindow`, small focused collaborators). target (thin `GameWindow`, small focused collaborators).
**Companion to:** [`acdream-architecture.md`](acdream-architecture.md) **Companion to:** [`acdream-architecture.md`](acdream-architecture.md)
(the layered architecture) and (the layered architecture) and
@ -21,30 +22,37 @@ layer is wire-compatible, the UI has a stable contract, plugins load.
The structural debt is concentrated in **one file**: The structural debt is concentrated in **one file**:
``` ```
src/AcDream.App/Rendering/GameWindow.cs 14,557 lines (2026-07-20) src/AcDream.App/Rendering/GameWindow.cs 15,723 lines (2026-07-21)
258 fields / ~259 methods
``` ```
`GameWindow` is the single object that: `GameWindow` is the single object that:
- Owns the GL context, the window, input, and shaders. - Owns the GL context, the window, input, and shaders.
- Reads ~40 different environment variables across its lifetime. - Reads ~40 different environment variables across its lifetime.
- Hosts the live network session (`WorldSession`) and the offline - Still owns live-session bootstrap, character entry, roughly 440 lines of
pre-login state. event subscription, and most App-side packet handlers even though
- Owns parallel dictionaries for entity lookup (`_entitiesByServerGuid`, `LiveSessionController` owns the socket/session shell.
the per-landblock entity lists in `GpuWorldState`, plus the player - Owns the adapters that hydrate canonical `LiveEntityRuntime` records into
controller's own state). animation, collision, rendering, and DAT-backed appearance resources.
- Drives selection / interaction (`WorldPicker`, `SendUse`, - Still drives selection / interaction (`WorldPicker`, target classification,
`SendPickUp`). `SendUse`, `SendPickUp`, auto-walk deferral) despite the shipped item and
combat controllers.
- Drives per-frame render orchestration (sky → terrain → opaque mesh → - Drives per-frame render orchestration (sky → terrain → opaque mesh →
transparent mesh → particles → debug lines → UI). transparent mesh → particles → debug lines → UI).
- Builds and applies streamed landblock presentation (DAT decode, scenery,
EnvCells, mesh publication, collision, and retirement) around the shipped
`StreamingController` and `GpuWorldState` owners.
- Wires up every plugin hook sink, every diagnostic, every panel. - Wires up every plugin hook sink, every diagnostic, every panel.
Almost every M1 / M2 bug touches this file. Every new feature adds a The extracted controllers are valuable and tested, but line count alone proves
field plus a method plus a wiring call. It is not getting better on its that creating collaborators has not yet made the window thin. A collaborator
own. is a completed extraction only when it owns the state and behavior body;
wrapping a `GameWindow` method in a delegate preserves ordering but remains a
partial extraction.
The fix is **not** "rewrite `GameWindow` in one pass" — that's a The fix is **not** "rewrite `GameWindow` in one pass" — that is a
high-risk change that would block M2. The fix is to **extract one high-risk change. The fix is to **extract one
collaborator at a time**, verify behavior is unchanged, ship, and collaborator at a time**, verify behavior is unchanged, ship, and
move on. This document defines that sequence. move on. This document defines that sequence.
@ -167,6 +175,7 @@ src/AcDream.App/
│ ├── GameWindow.cs # thin: GL/window lifecycle + delegates per-frame to RenderFrameOrchestrator │ ├── GameWindow.cs # thin: GL/window lifecycle + delegates per-frame to RenderFrameOrchestrator
│ ├── RenderFrameOrchestrator.cs # per-frame draw order (sky → terrain → opaque → trans → particles → debug → UI) │ ├── RenderFrameOrchestrator.cs # per-frame draw order (sky → terrain → opaque → trans → particles → debug → UI)
│ ├── LiveEntityAnimationScheduler.cs # shipped: ordinary live-object update workset │ ├── LiveEntityAnimationScheduler.cs # shipped: ordinary live-object update workset
│ ├── LiveEntityAnimationPresenter.cs # final part-pose/mesh/effect composition after scheduler output
│ ├── RetailStaticAnimatingObjectScheduler.cs # shipped: separate static-animation workset │ ├── RetailStaticAnimatingObjectScheduler.cs # shipped: separate static-animation workset
│ ├── StaticLiveRootCommitter.cs # live static root → pose + collision boundary │ ├── StaticLiveRootCommitter.cs # live static root → pose + collision boundary
│ ├── TerrainModernRenderer.cs # (already exists) │ ├── TerrainModernRenderer.cs # (already exists)
@ -176,11 +185,13 @@ src/AcDream.App/
│ ├── Wb/ # WB seam + EnvCellLandblockBuild transaction │ ├── Wb/ # WB seam + EnvCellLandblockBuild transaction
│ └── Vfx/ # (already exists) │ └── Vfx/ # (already exists)
├── Net/ ├── Net/
│ └── LiveSessionController.cs # owns WorldSession lifecycle, login/handshake, reconnect │ ├── LiveSessionController.cs # owns complete WorldSession connect/enter/logout/reconnect lifecycle
│ └── LiveSessionEventRouter.cs # typed subscriptions → focused domain handlers
├── Physics/ ├── Physics/
│ ├── ProjectileController.cs # canonical live-record projectile orchestration │ ├── ProjectileController.cs # canonical live-record projectile orchestration
│ ├── RemotePhysicsUpdater.cs # ordinary/Hidden remote narrow-tick integration │ ├── RemotePhysicsUpdater.cs # ordinary/Hidden remote narrow-tick integration
│ ├── LiveEntityOrdinaryPhysicsUpdater.cs # manager-less canonical body Transition path │ ├── LiveEntityOrdinaryPhysicsUpdater.cs # manager-less canonical body Transition path
│ ├── LiveEntityNetworkUpdateController.cs # Position/Vector/State/Motion App integration
│ ├── LiveEntityShadowPublisher.cs # authoritative exact-owner/residency collision gate │ ├── LiveEntityShadowPublisher.cs # authoritative exact-owner/residency collision gate
│ ├── RemoteInboundMotionDispatcher.cs # shared animated/headless UpdateMotion funnel │ ├── RemoteInboundMotionDispatcher.cs # shared animated/headless UpdateMotion funnel
│ ├── RemoteTeleportController.cs # loaded/pending teleport placement ownership │ ├── RemoteTeleportController.cs # loaded/pending teleport placement ownership
@ -189,13 +200,18 @@ src/AcDream.App/
├── World/ ├── World/
│ ├── InboundPhysicsStateController.cs # timestamps + accepted spawn snapshots │ ├── InboundPhysicsStateController.cs # timestamps + accepted spawn snapshots
│ ├── LiveEntityRuntime.cs # shipped: logical lifetime + ServerGuid↔entity.Id translation │ ├── LiveEntityRuntime.cs # shipped: logical lifetime + ServerGuid↔entity.Id translation
│ ├── LiveEntityHydrationController.cs # spawn/appearance/parent/delete resource integration
│ ├── RetailInboundEventDispatcher.cs # update-thread packet/frame FIFO barrier │ ├── RetailInboundEventDispatcher.cs # update-thread packet/frame FIFO barrier
│ ├── RetailLiveFrameCoordinator.cs # shipped: object/network/command/reconcile phase order
│ ├── LiveEntityPresentationController.cs # ordered Hidden/NoDraw/effect/collision side effects │ ├── LiveEntityPresentationController.cs # ordered Hidden/NoDraw/effect/collision side effects
│ ├── LiveEntityTeardown.cs # failure-isolated multi-owner lifecycle drain │ ├── LiveEntityTeardown.cs # failure-isolated multi-owner lifecycle drain
│ └── ParentAttachmentState.cs # parent generations + pending ParentEvent relations │ └── ParentAttachmentState.cs # parent generations + pending ParentEvent relations
├── Interaction/ ├── Interaction/
│ └── SelectionInteractionController.cs # owns WorldPicker, selection state, Use/PickUp dispatch │ ├── WorldSelectionQuery.cs # read-only picking/classification/description queries
├── Streaming/ # LandblockStreamer + immutable LandblockBuild completion │ └── SelectionInteractionController.cs # owns selection intents, Use/PickUp, auto-walk deferral
├── Streaming/
│ ├── LandblockPresentationPipeline.cs # DAT build/apply/retire transaction and resource publication
│ └── ... # shipped streamer/world-state/reveal owners
├── Input/ # (already exists) ├── Input/ # (already exists)
├── Audio/ # (already exists) ├── Audio/ # (already exists)
└── Plugins/ # (already exists) └── Plugins/ # (already exists)
@ -206,22 +222,27 @@ What `GameWindow` keeps:
- `IWindow` / `GL` / `IInputContext` lifecycle (constructor + `OnLoad` + - `IWindow` / `GL` / `IInputContext` lifecycle (constructor + `OnLoad` +
`Run` + `OnClosing`). `Run` + `OnClosing`).
- `RuntimeOptions` reference (the typed startup config). - `RuntimeOptions` reference (the typed startup config).
- One field per collaborator (`_liveSessionController`, - GL resource construction and top-level collaborator composition. Construction
`_liveEntityRuntime`, `_selectionInteraction`, is allowed here; feature algorithms and mutable subsystem state are not.
`_renderFrameOrchestrator`). - One field per top-level collaborator (`_liveSessionController`,
`_liveEntityRuntime`, `_selectionInteraction`, `_streamingPresentation`,
`_liveObjectFrame`, `_renderFrameOrchestrator`).
- The Silk.NET event-handler stubs that delegate to collaborators. - The Silk.NET event-handler stubs that delegate to collaborators.
What `GameWindow` loses: What `GameWindow` loses:
- The 7 startup-time env var fields → moved into `RuntimeOptions`. - Live connect/enter/logout and event-subscription bodies → completed inside
- `TryStartLiveSession` + the post-login network drain → moved into `LiveSessionController` / `LiveSessionEventRouter`.
`LiveSessionController`. - Live-object hydration adapters and final animated-part presentation → focused
- `_entitiesByServerGuid` + per-entity dictionaries + ServerGuid↔Id world/render owners over canonical `LiveEntityRuntime` records.
translation → moved into `LiveEntityRuntime`. - `WorldPicker`, target queries, and selection-driven Use/PickUp/auto-walk →
- `WorldPicker` + selection-driven `SendUse` / `SendPickUp` orchestration → moved `WorldSelectionQuery` + `SelectionInteractionController`. Core
into `SelectionInteractionController`; Core `SelectionState` remains the `SelectionState` remains the injected session owner.
already-shipped session owner and is injected into that controller. - Landblock DAT build/apply/retirement presentation →
- Per-frame draw orchestration → moved into `RenderFrameOrchestrator`. `LandblockPresentationPipeline`; `StreamingController` remains the residency
scheduler and `GpuWorldState` remains the spatial registry.
- Per-frame draw orchestration and its frame-local scratch state →
`RenderFrameOrchestrator`.
The eventual `GameEntity` aggregation (target state described in The eventual `GameEntity` aggregation (target state described in
`acdream-architecture.md` §"GameEntity: The Unified Entity") happens `acdream-architecture.md` §"GameEntity: The Unified Entity") happens
@ -247,10 +268,14 @@ allocators fail fast instead of wrapping into another landblock's namespace.
All other non-Parent packet All other non-Parent packet
families still need the future general queue tracked by divergence AD-32. families still need the future general queue tracked by divergence AD-32.
The per-frame object body is no longer an animation-dictionary loop inside The per-frame object scheduler is extracted, but final animated-part
`GameWindow`. `LiveEntityAnimationScheduler` snapshots canonical spatial root presentation is not. `LiveEntityAnimationScheduler` snapshots canonical spatial
records and advances the incarnation-stable object clock, PartArray, hooks, root records and advances the incarnation-stable object clock, PartArray,
one selected movement owner, and manager tail in retail order. Manager-less hooks, one selected movement owner, and manager tail in retail order. The
remaining `GameWindow.TickAnimations` loop still composes part transforms,
drawable `MeshRef`s, and effect poses from the scheduler output; moving that
body into `LiveEntityAnimationPresenter` is an explicit pending slice.
Manager-less
bodies delegate their candidate/Transition/cell/shadow commit to bodies delegate their candidate/Transition/cell/shadow commit to
`LiveEntityOrdinaryPhysicsUpdater`; retained projectile bodies and remote `LiveEntityOrdinaryPhysicsUpdater`; retained projectile bodies and remote
MovementManagers remain mutually exclusive movement owners. Static animation MovementManagers remain mutually exclusive movement owners. Static animation
@ -336,145 +361,194 @@ strand teleport, movement, shadow, light, or GUID-scoped state.
--- ---
## 4. Extraction sequence — safest first ## 4. Reconciled ownership ledger — 2026-07-21
Each step is **one PR-sized refactor**. Each must build clean, all This section replaces the original six-step sketch. That sketch correctly
tests pass, and visual verification at Holtburg looks identical to identified the target but overstated some extractions and omitted large bodies
the previous step. Don't bundle two steps. added during M2/M3. The current audit is based on implementation ownership, not
whether a class with the planned name exists.
### Step 1 — `RuntimeOptions` — SHIPPED (`eda936dc`) ### 4.1 What counts as extracted
**Scope:** Replace startup-time env var reads with a typed options An extraction is **complete** only when:
object built once in `Program.cs`.
**Behavior change:** None. Same env vars, same defaults, same effects. 1. the collaborator owns the mutable state and behavior body;
2. `GameWindow` constructs it and delegates through a narrow method;
3. the collaborator does not call back into arbitrary `GameWindow` methods;
4. focused tests exercise the collaborator without constructing a Silk window;
5. the accepted connected/visual behavior is unchanged.
**Risk:** Low. Mechanical substitution at ~10-15 call sites in A class that stores delegates back to substantial `GameWindow` methods is a
`GameWindow.cs` + one constructor signature change. useful ordering seam, but its ownership status is **partial**.
**Test:** Unit tests for `RuntimeOptions.FromEnvironment` parsing (the ### 4.2 Current implementation truth
new `tests/AcDream.App.Tests/` project).
**Verification:** `dotnet build` + `dotnet test` green. Visual launch | Area | Status | Current truth |
verifies live mode + dat dir resolution still work. |---|---|---|
| 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`. |
| 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 | **Partial** | `ItemInteractionController`, `CombatTargetController`, and `CombatAttackController` own focused rules. `GameWindow` still owns picking, target queries, selection intent, Use/PickUp sends, range/auto-walk deferral, and related input cases. |
| Landblock presentation | **Not extracted** | Residency scheduling is extracted, but DAT build, scenery/EnvCell construction, apply, collision/resource publication, and retirement glue remain a large `GameWindow` body. |
| Render-frame orchestration | **Not extracted** | `OnRender` plus its portal/PView/alpha/particle helpers still own the draw graph and frame-local scratch state. There is no `RenderFrameOrchestrator` yet. |
| Unified `GameEntity` | **Deferred target** | `LiveEntityRuntime` already supplies the critical canonical owner. Full type aggregation is a separate high-risk migration and is not required to make `GameWindow` thin. |
### Step 2 — `LiveSessionController` — SHIPPED (`0b25df53`) ### 4.3 Revised extraction sequence
**Scope:** Extract `TryStartLiveSession` + the WorldSession ownership + Every numbered slice is behavior-preserving and independently committed. A
the post-EnterWorld drain (`OnLiveStateUpdated`, `OnLiveEntityDeleted`, slice does not include feature work or opportunistic gameplay fixes.
etc.) into a controller class.
**Behavior change:** None. Same wire behavior, same handshake. #### Gate 0 — deterministic baseline — COMPLETE
**Risk:** Medium. WorldSession lifecycle is load-bearing — every The Release suite, connected R6 soak, world-lifecycle screenshots/checkpoints,
session-state crash would surface here. The change is a class graceful reconnect, local locomotion/collision/projectile/teleport gate, and
extraction with the same event subscriptions, not a rewrite. two-client portal observer gate form the pre-refactor baseline. Each later
slice runs the subset capable of detecting its risk; render/session slices run
the complete connected lifecycle gate.
**Test:** Existing `AcDream.Core.Net.Tests` already cover the wire #### Slice 1 — finish selection/interaction ownership — NEXT
layer. The controller itself gets a smoke test that verifies it can be
constructed without a live socket (offline mode).
**Verification:** Visual login + Holtburg traversal + door interaction Split the old Step 4 into three reviewable commits:
identical to pre-extraction.
### Step 3 — `LiveEntityRuntime` — SHIPPED 2026-07-14 1. `WorldSelectionQuery` receives camera/scene/live-object read seams and owns
picking, target classification, selection bounds, closest-target lookup,
names, and descriptions. It cannot mutate selection or send packets.
2. `SelectionInteractionController` owns selection intents, double-click Use,
Use/PickUp packet requests, range decisions, speculative facing, and the
pending auto-walk action. It composes the existing item/combat controllers
rather than duplicating their rules.
3. Selection/Use/PickUp/combat-target `InputAction` cases delegate to the new
controller; the old methods and fields are deleted from `GameWindow`.
**Shipped scope:** One `LiveEntityRecord` per server-object incarnation now owns Tests cover read-only query classification separately from stateful intents,
ServerGuid↔local-ID translation, accepted state, runtime components, parent including direct use, distant auto-walk completion, corpse/container opening,
relations, logical resource activation, exact teardown, and spatial projection pickup placement, hostile-only targeting, Hidden objects, and same-GUID reuse.
state. `RegisterLiveEntity`, `RebucketLiveEntity`, and `UnregisterLiveEntity` The connected gate is select → use door/NPC → distant corpse → loot/pickup →
make the lifetime boundary explicit. Landblock unload/reload moves the same combat target. This is the safest next slice because its outbound boundaries
`WorldEntity`; it cannot reconstruct from a stale CreateObject or replay setup are typed and existing controllers already hold most retail rules.
scripts. Equipped children use an attached projection and never enter the
top-level target/radar/status view. Canonical materialized lookup remains
available while a projection is pending; the separate visible view is the only
surface radar, picking, status, and targeting consume. Pickup/parent leave-world
clears cell membership and pauses root movement/animation without destroying the
retained owners. Top-level spawn publication is one-shot per incarnation, so
leave/re-entry restores presentation without duplicating plugin event replay.
**Remaining target:** the player-specific controller is still a separate #### Slice 2 — finish live animation presentation
aggregation. The focused effect queue is shipped; AD-32 now tracks only the
future non-effect, non-Parent packet queue.
**Behavior change:** Spatial withdrawal and re-entry now preserve logical Move `TickAnimations`, final rigid/visual part composition, effect-pose
identity and active resources instead of replaying create-time effects. publication, and motion-done binding into `LiveEntityAnimationPresenter`.
`LiveEntityAnimationScheduler` remains the time/movement owner; the presenter
only consumes one scheduler result and publishes the final draw/effect pose.
Move the surviving motion diagnostics with this owner instead of adding more
environment reads to `GameWindow`.
**Risk:** Medium-high. Entity lookup is in every hot path. The change Tests pin legacy and sequencer paths, Hidden/static eligibility, ObjScale versus
is structural (one owner instead of three) but the lookup semantics rigid effect poses, part availability, same-frame hook pose publication, and
must be byte-identical. incarnation replacement. Run the R6 object-frame and projectile/effect suites
plus the connected locomotion/projectile gate.
**Test:** `LiveEntityRuntimeTests` cover duplicate CreateObject, generation #### Slice 3 — complete live-session ownership
replacement, appearance mutation, loaded/pending rebucketing, attached
projection, pickup leave/re-entry, canonical-versus-visible lookup, resource
rollback, GUID reuse, and idempotent session teardown.
**Verification:** Walk Holtburg, click NPC, open door, pick up item. Expand `LiveSessionController` to own connect, character-list validation,
All four M1 demo targets must still work. character selection, EnterWorld, graceful character logout, reconnect, and
session-scoped disposal. Add `LiveSessionEventRouter` for typed subscriptions;
it routes events to focused domain handlers and owns unsubscription, but owns
no entity or UI state.
### Step 4 — `SelectionInteractionController` Move `TryStartLiveSession`, `ClearInboundEntityState`, and
`WireLiveSessionEvents` out of `GameWindow`. Do not create a giant context bag
or a second world-state owner. The connected gate must prove login, fresh world
reveal, command/chat, portal, exact `0xF653` logout, ACE endpoint disconnect,
and fresh-process reconnect.
**Scope:** Extract `WorldPicker`, the Core `SelectionState` consumers, `SendUse`, #### Slice 4 — extract live-entity App integration
`SendPickUp`, and the `InputAction.Select*` / `UseSelected` /
`SelectionPickUp` switch cases into one controller. Depends on Step 3
(uses `LiveEntityRuntime`).
**Behavior change:** None. This is two owners, not one replacement god object:
**Risk:** Low-medium. Selection state is local to interactions; the - `LiveEntityHydrationController` owns CreateObject/ObjDesc/Parent/Pickup/Delete
network outbound side is well-defined (`InteractRequests.BuildUse` / integration, DAT-backed appearance hydration, resource registration, and
`BuildPickUp`). exact teardown callbacks over `LiveEntityRuntime`.
- `LiveEntityNetworkUpdateController` owns App routing for accepted
Position/Vector/State/Movement updates into the existing remote physics,
motion, projectile, presentation, and teleport controllers.
**Test:** Selection state machine tests in `tests/AcDream.App.Tests/`. Neither may own a GUID dictionary. Both resolve the current incarnation only
through `LiveEntityRuntime` and must preserve the inbound FIFO/authority-token
rules. Run the complete live-entity stress suite, R6 connected route, inventory
equip/parenting, death/corpse, and portal gates.
**Verification:** Click-to-select, double-click-to-Use, F-key pickup #### Slice 5 — extract landblock presentation
all still work.
### Step 5 — `RenderFrameOrchestrator` Create `LandblockPresentationPipeline` around the existing immutable
`LandblockBuild` transaction. It owns DAT build context, scenery/EnvCell
construction, mesh/collision/light publication, demotion/full-retirement, and
the single-reader DAT lock contract. `StreamingController` continues deciding
what is resident; `GpuWorldState` continues owning spatial buckets.
**Scope:** Extract the per-frame draw sequence (sky → terrain → Tests pin loaded/pending/demoted/unloaded symmetry, stale build generations,
opaque mesh → translucent mesh → particles → debug → UI) into a resource pin/release balance, collision footprints across landblock seams, and
dedicated orchestrator that `GameWindow.OnRender` delegates to. first-login bootstrap replacement. Run the deterministic world-lifecycle gate
and the seven-destination resource soak.
**Behavior change:** None. Same draw order, same GL state. #### Slice 6 — extract update-frame orchestration
**Risk:** Medium. GL state management is touchy; the orchestrator After the stateful bodies above have owners, make the update path a real
must hand the GL context to the same renderers in the same order with orchestrator instead of delegates back into the window. It owns the fixed
the same per-pass state setup. retail phase order: input/local object → ordinary/static objects → hooks/
particles/scripts → inbound network → command interpreter → non-advancing
spatial reconcile → streaming/UI updates. `GameWindow.OnUpdate` becomes a
short time/input handoff.
**Test:** Visual verification only. Render orchestration is hard to Frame-order tests and the existing R6 gate must produce the same lifecycle and
unit-test without a GL context. movement traces before and after extraction.
**Verification:** Holtburg at radius 4, radius 8, radius 12 looks #### Slice 7 — extract `RenderFrameOrchestrator`
identical across all four quality presets.
### Step 6 — `GameEntity` aggregation (the big one) Move the complete draw graph and its reusable frame-local scratch state into a
GL-owning App collaborator. Preserve the exact modern pipeline order, clip
routing, PView flood, landscape/opaque/shared-alpha flush boundaries,
particles, debug draw, paperdoll, retained UI, and frame fences. Do not pass a
hundred individual delegates or let the orchestrator reach back into
`GameWindow`; inject a small immutable service set plus explicit per-frame
input.
**Scope:** Consolidate `WorldEntity` + `AnimatedEntity` + the per-entity Automated acceptance uses framebuffer artifacts and render/resource
state in `LiveEntityRuntime` into one `GameEntity` class (the target checkpoints. Visual acceptance compares outdoor, building, dungeon, portal
described in `acdream-architecture.md`). Every entity in the world — exit, translucent lifestone/particles, and UI at the same camera positions.
player, NPC, monster, door, item — becomes a single `GameEntity`.
**Behavior change:** None at the wire / visual level; substantial at #### Slice 8 — composition and shutdown cleanup
the call-site level (everyone moves to the new entity API).
**Risk:** High. Touches every system that reads entity state. Keep GL/window construction in `GameWindow.OnLoad`, but group creation into
small composition functions and delete feature state left behind by prior
slices. `OnClosing` delegates to the existing retryable shutdown transaction.
Silk callbacks become narrow calls into the input, update, render, resize,
focus, and shutdown owners.
**Test:** All existing tests + the new `AcDream.App.Tests` suite. Visual ### 4.4 Exit criteria
verification at every M1 / M2 scenario.
**Verification:** Full M2 demo loop (equip sword, kill drudge, pick up The campaign is complete when:
loot, open inventory) works identically.
- `GameWindow` contains no AC gameplay algorithm, entity scan, packet builder,
DAT landblock builder, animation-part composer, or draw-graph body;
- `OnUpdate`, `OnRender`, `OnInputAction`, and live-session callbacks are short
delegation methods;
- every extracted owner has App-layer tests and symmetric teardown;
- the Release suite and connected lifecycle/resource gates stay green after
every slice;
- the final local visual matrix passes unchanged.
Line count is a progress signal, not the acceptance test. The expected result
is below roughly 5,000 lines, but ownership and dependency direction decide
completion. Full `GameEntity` type aggregation is evaluated only afterwards as
a separate migration; it is not folded into this campaign.
--- ---
## 5. Rules of the road during the extraction ## 5. Rules of the road during the extraction
1. **One step at a time.** A PR that ships Step 1 ships only Step 1. 1. **One slice at a time.** Each commit ships one ownership boundary or
Bundling steps makes failures hard to isolate. mechanical call-site cutover. Bundling slices makes failures hard to
2. **Behavior preservation is the acceptance criterion.** Every step isolate.
2. **Behavior preservation is the acceptance criterion.** Every slice
must build clean, all tests pass, and visual verification at the must build clean, all tests pass, and visual verification at the
appropriate M1 / M2 scenarios must succeed. We're moving code, not appropriate accepted milestone scenarios must succeed. We're moving code, not
changing it. changing it.
3. **No new features during an extraction step.** If you spot a real 3. **No new features during an extraction step.** If you spot a real
bug while extracting, file it in `docs/ISSUES.md` and address it in bug while extracting, file it in `docs/ISSUES.md` and address it in
@ -484,9 +558,15 @@ loot, open inventory) works identically.
moves to a new owner, the diagnostic flag inside it can move to a moves to a new owner, the diagnostic flag inside it can move to a
diagnostic class as part of the same commit. We do not do a bulk diagnostic class as part of the same commit. We do not do a bulk
diagnostic-cleanup pass. diagnostic-cleanup pass.
5. **Update this document when the plan changes.** If Step 3 turns out 5. **Update this document when the plan changes.** If a slice turns out
to need a different shape than described above, update §4 in the to need a different ownership shape than described above, update §4 in the
same session you discover the divergence. same session you discover the divergence.
6. **No façade-only completion claims.** A delegate from a new class back to a
substantial `GameWindow` method is a useful intermediate seam, not a
completed extraction.
7. **No duplicate ownership.** New collaborators query `LiveEntityRuntime`,
`GpuWorldState`, `SelectionState`, or the relevant existing owner. They do
not create replacement GUID, visibility, session, or resource maps.
--- ---
@ -494,8 +574,9 @@ loot, open inventory) works identically.
- **Not a full rewrite plan.** The point is the *opposite* — small - **Not a full rewrite plan.** The point is the *opposite* — small
steps, verified at each boundary. steps, verified at each boundary.
- **Not blocking M2.** Step 1 is small enough to ship without - **Not a feature phase.** Following the 2026-07-21 user decision, this
disrupting M2 work. Later steps interleave with M2 / M3 phases as behavior-preserving campaign is the structural prerequisite before new M4
the corresponding code paths come into focus. subsystem bodies are added. Severe regressions remain fixable in separate
commits; ordinary feature work waits.
- **Not a substitute for the milestones / roadmap.** Those drive the - **Not a substitute for the milestones / roadmap.** Those drive the
feature work. This drives the structural work that runs underneath. feature work. This drives the structural work that runs underneath.

View file

@ -1,11 +1,32 @@
# acdream — strategic roadmap # acdream — strategic roadmap
**Status:** Living document. Updated 2026-07-20. **M3 active; automated implementation and connected single-client magic/portal gates complete.** M2's connected demo loop is complete. M3 now has the retail cast-intent/component/target lifecycle, exact live enchantment wire state, scoped Magic input, retained spell bar, spellbook, component book, positive/negative effects panels with authored rows and selected-spell details, the complete seven-control gameplay indicator strip and its Character Information/Link/Vitae detail pages, and shared `gmPanelUI` geometry/switching over the Step 9 projectile/PhysicsScript/particle/portal foundation. Fresh-login and portal world reveal are additionally protected by a deterministic capped/uncapped connected lifecycle gate with screenshots, resource snapshots, exact graceful disconnect, and fresh-process reconnect. The next gate is a local visual rebaseline of the new R6 object-frame path; the final M3 requirement is the two-client portal-out/materialization observer gate. Issue #225's lifestone/particle alpha comparison is a separate rendering visual gate. **Status:** Living document. Updated 2026-07-21. **M3 landed; M4 is next after the active `GameWindow` structural prerequisite.** M3's retail casting/UI, R6 locomotion/collision/projectile/teleport/radar rebaseline, deterministic fresh-login/portal world lifecycle, and final two-client portal observer flow are user-gated. The current program is the behavior-preserving ownership campaign in [`docs/architecture/code-structure.md`](../architecture/code-structure.md); new M4 quest/emote/character-creation feature bodies wait until that campaign is complete. Issue #225's lifestone/particle alpha comparison remains a separate rendering visual gate.
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file. **Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
--- ---
## Current program: M3 — Cast a spell ## Current program: `GameWindow` structural stabilization (M4 prerequisite)
**Outcome:** `GameWindow` becomes a thin Silk.NET composition/lifecycle shell
without changing accepted gameplay or rendering behavior. Focused App owners
take responsibility for selection, animation presentation, live-session and
live-entity integration, landblock presentation, and update/render frame
orchestration.
**Current sequence:** The implementation audit, exact ownership ledger, slice
boundaries, tests, connected gates, and exit criteria live in
[`docs/architecture/code-structure.md`](../architecture/code-structure.md) §4.
The next slice is selection/interaction: extract the read-only world query,
move stateful Use/PickUp/auto-walk intent into one controller, then cut the
related input cases over and delete the old `GameWindow` bodies.
This is a behavior-preserving structural program. Severe regressions still get
root-cause fixes in separate commits; ordinary feature work resumes with M4
after the campaign exit criteria pass.
---
## Completed program: M3 — Cast a spell (landed 2026-07-21)
**Outcome:** Cast a projectile spell at a hostile target, see the complete **Outcome:** Cast a projectile spell at a hostile target, see the complete
turn/windup/release/projectile/impact lifecycle, self-cast a buff and see its turn/windup/release/projectile/impact lifecycle, self-cast a buff and see its
@ -39,14 +60,14 @@ active enchantment, then recall through the DAT-driven portal presentation.
same-location revisit, graceful logout, and uncapped fresh-process same-location revisit, graceful logout, and uncapped fresh-process
reconnect. The gate records structured readiness/resource checkpoints and reconnect. The gate records structured readiness/resource checkpoints and
full-frame PNGs, and rejects early world visibility or stranded owners. full-frame PNGs, and rejects early world visibility or stranded owners.
5. **Pending local visual gate:** locomotion, collision, projectile, and 5. **Done (connected user gate):** locomotion, collision, projectile, teleport,
teleport comparison after the R6 complete-root-Frame/object-workset cutover. and radar comparison after the R6 complete-root-Frame/object-workset cutover.
6. **Pending two-client visual gate:** portal-out/materialization observer 6. **Done (two-client user gate):** portal-out/materialization observer
presentation before M3 closes, including #218's finished Hidden silhouette, presentation, including #218's finished Hidden silhouette, fully rendered
fully rendered destination reveal, and no indoor stop-time position snap. destination reveal, and no indoor stop-time position snap.
Opportunistic UI/physics fixes are no longer the work-order driver. They enter M3 is closed. Its detailed ledger remains here as the landing record; the
the active slice only when they block this demo or represent a severe regression. structural program above is the only current work-order driver before M4.
--- ---
@ -937,8 +958,7 @@ diagnostic scaffolding, not yet the final collision system.
and 0.2 -> 0.3 ms at Sawato. ACE generator population changes are reported and 0.2 -> 0.3 ms at Sawato. ACE generator population changes are reported
rather than treated as client leaks. Absolute FPS/GPU timing remains rather than treated as client leaks. Absolute FPS/GPU timing remains
session/display-path evidence, not an RDP-stable gate. The connected visual session/display-path evidence, not an RDP-stable gate. The connected visual
locomotion/collision/projectile/teleport comparison remains for the next locomotion/collision/projectile/teleport/radar comparison passed 2026-07-21.
local viewing session.
- **L.2g — Inbound motion interpretation (remote-entity CMotionInterp funnel).** - **L.2g — Inbound motion interpretation (remote-entity CMotionInterp funnel).**
ACTIVE 2026-07-02. Port retail's inbound motion pipeline verbatim for ALL ACTIVE 2026-07-02. Port retail's inbound motion pipeline verbatim for ALL
remote entities (players, NPCs, monsters — one funnel, user-approved): remote entities (players, NPCs, monsters — one funnel, user-approved):
@ -1453,7 +1473,7 @@ OpenGL ceiling; revisit macOS only if a supported graphics backend is chosen.
## Cross-cutting work tracked in parallel ## Cross-cutting work tracked in parallel
- **Test coverage.** Each phase lands with layer-matched unit and integration tests in `tests/`. Current Release baseline: 6,480 passed / 5 intentional skips (2026-07-20). - **Test coverage.** Each phase lands with layer-matched unit and integration tests in `tests/`. Current Release baseline: 6,481 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. - **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. - **`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.

View file

@ -2,28 +2,28 @@
**Status:** Living document. Created 2026-05-12. **Status:** Living document. Created 2026-05-12.
**Sits above:** [`docs/plans/2026-04-11-roadmap.md`](2026-04-11-roadmap.md) (the strategic phase index). **Sits above:** [`docs/plans/2026-04-11-roadmap.md`](2026-04-11-roadmap.md) (the strategic phase index).
**Currently working toward:** **M3 — "Cast a spell." M2 — "Kill a drudge" **Currently working toward:** **M4 — "Live in the world." M3 — "Cast a
LANDED 2026-07-15.** The complete connected melee/missile, death/loot, spell" LANDED 2026-07-21.** Projectile/self-buff casting, protection effects,
inventory, and item-giving demo is user-gated. The shared projectile/effect spellbook/component-book filtering and deletion, favorite spell bars, active
foundation is hardened through Step 9. Spellbook/component-book filtering, effects, recall, portal-space presentation, and the complete two-client
favorite spell bar, connected casting/enchantment effects, and portal-space portal-out/materialization observer flow are user-gated. The R6 locomotion,
presentation have passed their single-client visual gates. The corrective bounded collision, projectile, teleport, and radar rebaseline also passes. Deterministic
render/resource-lifetime integration passed its seven-destination connected world-lifecycle automation protects fresh login, outdoor/world-edge/dungeon
stress gate without a crash or cumulative collapse. A second deterministic travel, same-location revisit, exact graceful disconnect, and uncapped
world-lifecycle gate now protects fresh login, outdoor/world-edge/dungeon fresh-process reconnect with canonical JSON/PNG evidence.
travel, same-location revisit, exact graceful disconnect, and an uncapped
fresh-process reconnect with canonical readiness snapshots and saved PNG/JSON Before new M4 quest/emote/character-creation subsystem bodies enter the App
artifacts. The remaining M3 visual requirement is the final two-client layer, the active structural prerequisite is the behavior-preserving
portal-out/materialize observer gate. The new R6 object-update cutover has `GameWindow` decomposition in
passed its unattended connected input/portal/performance rebaseline; its [`docs/architecture/code-structure.md`](../architecture/code-structure.md).
locomotion/collision/projectile/teleport visual gate remains for the next local The 2026-07-21 audit found 15,723 lines, 258 fields, and about 259 methods;
viewing session before that observer gate. the next slice finishes selection/interaction ownership.
Carried: Carried:
#153 far-teleport residual, #116 slide-response, the remaining R6 ownership cleanup plus #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 registered TS-50/TS-51 timing residuals (the complete-root-Frame/object-workset
cutover is automated-test complete 2026-07-20; three independent re-reviews are cutover is automated- and visual-gate complete; Release builds with 17 known
clean, Release builds with 17 known test-project warnings tracked by #228, and test-project warnings tracked by #228, and 6,481 tests pass / 5 skip), and
6,480 tests pass / 5 skip after the world-reveal gate), and
the deferred Modern Pipeline track (MP1b+). The separate #225 shared-alpha the deferred Modern Pipeline track (MP1b+). The separate #225 shared-alpha
implementation has passed connected lifetime/performance gates and awaits only implementation has passed connected lifetime/performance gates and awaits only
its lifestone/particle visual comparison. its lifestone/particle visual comparison.
@ -662,8 +662,8 @@ include dungeons.
publishes outdoor landcells independently of surviving object meshes. publishes outdoor landcells independently of surviving object meshes.
Terrain/entity streaming distance is Terrain/entity streaming distance is
unchanged; the user-requested default Extended setting doubles only particle unchanged; the user-requested default Extended setting doubles only particle
range, while Retail remains available as the exact cutoff. The range, while Retail remains available as the exact cutoff. The final
final two-client visual gate is still pending. two-client visual gate passed 2026-07-21.
- **L.1c local attack receive path (implemented and live-gated 2026-07-15)** - **L.1c local attack receive path (implemented and live-gated 2026-07-15)**
local non-autonomous mt-0 UpdateMotion now uses retail's wholesale interpreted local non-autonomous mt-0 UpdateMotion now uses retail's wholesale interpreted
funnel and action-stamp gate, so ACE's server-selected melee/missile action funnel and action-stamp gate, so ACE's server-selected melee/missile action
@ -713,7 +713,17 @@ a game.
--- ---
### M3 — "Cast a spell" — 🔵 ACTIVE (started 2026-07-15) ### M3 — "Cast a spell" — ✅ LANDED 2026-07-21
**Landing writeup:** Mages now work end to end. A connected player can manage
the retail spellbook/component book and favorite bars, cast projectile and
self-targeted spells with the correct components/target gates, see traveling
missiles and DAT-driven protection/impact effects, inspect live enchantments,
and recall or portal through the retail tunnel/reveal lifecycle. The final
two-client observer gate confirms departure disappearance, destination
materialization, finished pose, rendered destination, and indoor movement
without snap-back. The R6 local locomotion/collision/projectile/teleport and
radar checks pass on the same Release baseline.
**Demo scenario:** Cast Flame Bolt at a drudge. Watch the cast animation, **Demo scenario:** Cast Flame Bolt at a drudge. Watch the cast animation,
the projectile, the impact. Self-cast a buff (Strength Self). See the the projectile, the impact. Self-cast a buff (Strength Self). See the
@ -740,9 +750,9 @@ The strip now uses retail DAT states for link quality, Helpful/Harmful effects,
Vitae, burden, mini-game availability, and end-character-session; live link Vitae, burden, mini-game availability, and end-character-session; live link
age, player load, and enchantment registries drive their retail thresholds and age, player load, and enchantment registries drive their retail thresholds and
the burden/effect/logout actions use the shared panel/dialog owners. Main-panel the burden/effect/logout actions use the shared panel/dialog owners. Main-panel
visibility now flows through retail's one-active `gmPanelUI` owner. M3 remains visibility now flows through retail's one-active `gmPanelUI` owner. The
active only for the connected single-client magic connected single-client magic UI/casting gates and final two-client portal
UI/casting visual gate and the final two-client portal observer gate. observer gate passed before landing.
The 2026-07-17 indicator follow-up also mounts authored Character Information, The 2026-07-17 indicator follow-up also mounts authored Character Information,
Link Status, Vitae, and Mini Game detail roots as children of that same Link Status, Vitae, and Mini Game detail roots as children of that same
main-panel owner. Helpful, Harmful, Character Information, Link, and Vitae main-panel owner. Helpful, Harmful, Character Information, Link, and Vitae
@ -795,7 +805,12 @@ from M3 = retail-equivalent gameplay loop for melee and casters.
--- ---
### M4 — "Live in the world" — 🔵 (~610 weeks) ### M4 — "Live in the world" — 🟡 NEXT (~610 weeks)
**Entry condition:** complete the behavior-preserving `GameWindow`
decomposition campaign before adding H.3/H.4/L.1e feature bodies. This protects
M4 from deepening the App-layer composition debt; it does not change M4's demo
scope.
**Demo scenario:** Create a fresh character from scratch (no ACE admin). **Demo scenario:** Create a fresh character from scratch (no ACE admin).
Spawn. Talk to an NPC. Accept a quest. Walk to a dungeon entrance. Portal Spawn. Talk to an NPC. Accept a quest. Walk to a dungeon entrance. Portal