diff --git a/AGENTS.md b/AGENTS.md index 0c6f40d3..30fb71a3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -115,7 +115,7 @@ 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; 7,052 tests pass / 5 skip. +Release builds; 7,054 tests pass / 5 skip. **Active prerequisite before new M4 subsystem work:** continue the behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21. @@ -123,12 +123,13 @@ Selection/interaction Slice 1, live-animation-presentation Slice 2, complete live-session ownership Slice 3, and live-entity App integration Slice 4 are landed. Focused hydration, teardown, inbound-authority, network-update, and motion-runtime owners now sit over canonical `LiveEntityRuntime` without a -second GUID dictionary. Slice 5 checkpoints A–G have moved the complete DAT +second GUID dictionary. Slice 5 is complete: the complete DAT build, render/physics/static publication, retryable retirement, and shared- -origin lifetime barrier out of `GameWindow`; it is now 8,793 raw lines, down -44% from the 15,723-line campaign baseline. Slice 5H lifecycle/connected -closeout is active; later slices finish update/render orchestration and -composition cleanup. +origin lifetime barrier are out of `GameWindow`; it is now 8,811 raw lines / +247 fields / 153 methods, down 44% from the 15,723-line campaign baseline. +The lifecycle/reconnect and synchronized nine-stop soak gates pass. Slice 6 +update-frame orchestration is active; later slices finish 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 eb7fed10..ce3e9c7f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -113,7 +113,7 @@ 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; 7,052 tests pass / 5 skip. +Release builds; 7,054 tests pass / 5 skip. **Active prerequisite before new M4 subsystem work:** continue the behavior-preserving `GameWindow` decomposition reconciled on 2026-07-21. @@ -121,12 +121,13 @@ Selection/interaction Slice 1, live-animation-presentation Slice 2, complete live-session ownership Slice 3, and live-entity App integration Slice 4 are landed. Focused hydration, teardown, inbound-authority, network-update, and motion-runtime owners now sit over canonical `LiveEntityRuntime` without a -second GUID dictionary. Slice 5 checkpoints A–G have moved the complete DAT +second GUID dictionary. Slice 5 is complete: the complete DAT build, render/physics/static publication, retryable retirement, and shared- -origin lifetime barrier out of `GameWindow`; it is now 8,793 raw lines, down -44% from the 15,723-line campaign baseline. Slice 5H lifecycle/connected -closeout is active; later slices finish update/render orchestration and -composition cleanup. +origin lifetime barrier are out of `GameWindow`; it is now 8,811 raw lines / +247 fields / 153 methods, down 44% from the 15,723-line campaign baseline. +The lifecycle/reconnect and synchronized nine-stop soak gates pass. Slice 6 +update-frame orchestration is active; later slices finish 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 9878bb36..efb4d015 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; Slices 1–4 landed the same day. This is the active +completed 2026-07-21; Slices 1–5 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 @@ -27,7 +27,7 @@ after Slice 1 14,912 lines / 278 fields / 191 method after Slice 2 14,546 lines / 277 fields / 190 methods after Slice 3 14,310 lines / 274 fields / 190 methods after Slice 4 10,301 lines / 267 fields / 163 methods -after Slice 5G 8,793 lines (field/method closeout in H) +after Slice 5 closeout 8,811 lines / 247 fields / 153 methods ``` `GameWindow` is the single object that: @@ -400,7 +400,7 @@ useful ordering seam, but its ownership status is **partial**. | 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. | -| Landblock presentation | **Complete; closeout active** | `LandblockBuildFactory` owns the captured-origin DAT transaction; concrete render/physics/DAT-static publishers and `LandblockPresentationPipeline` own publication and exact retryable retirement. `StreamingOriginRecenterCoordinator` serializes old-window retirement with teleport/session origin lifetimes. `GameWindow` retains construction and one pipeline field only (`c79d0a49`). | +| Landblock presentation | **Complete** | `LandblockBuildFactory` owns the captured-origin DAT transaction; concrete render/physics/DAT-static publishers and `LandblockPresentationPipeline` own publication and exact retryable retirement. `StreamingOriginRecenterCoordinator` serializes old-window retirement with teleport/session origin lifetimes. `GameWindow` retains construction and one pipeline field only (`c79d0a49`, closeout `4a205a3e`). | | 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. | @@ -547,15 +547,19 @@ Slice 5 checkpoints A–G are complete. The pipeline owns the serialized worker build, concrete render/physics/static publication, and retryable Near/full retirement. The direct cutover deleted the legacy apply/facade/scratch body and added one retained shared-origin lifetime transaction for teleport, logout, -and fast relogin. `GameWindow.cs` is 8,793 raw lines and no longer owns -landblock build/apply/retirement behavior. Deterministic and connected closeout -is active in H. +and fast relogin. `GameWindow.cs` was 8,793 raw lines at checkpoint G and no +longer owns landblock build/apply/retirement behavior. H then corrected native +shutdown ordering so live-session reset converges before the streamer and +other reset dependencies are disposed. The final measurement is 8,811 raw +lines / 247 fields / 153 methods. The complete Release suite (7,054 pass / 5 +skip), the 311-second capped/reconnect lifecycle gate, and the synchronized +394-second nine-stop resource soak all pass (`4a205a3e`). -#### Slice 5 — extract landblock presentation — CHECKPOINTS A–G COMPLETE +#### Slice 5 — extract landblock presentation — COMPLETE Detailed execution ledger: [`docs/plans/2026-07-21-gamewindow-slice-5-landblock-presentation.md`](../plans/2026-07-21-gamewindow-slice-5-landblock-presentation.md) -(active). +(complete). Create `LandblockPresentationPipeline` around the existing immutable `LandblockBuild` transaction. It owns DAT build context, scenery/EnvCell @@ -565,8 +569,8 @@ what is resident; `GpuWorldState` continues owning spatial buckets. Tests pin loaded/pending/demoted/unloaded symmetry, stale build generations, resource pin/release balance, collision footprints across landblock seams, and -first-login bootstrap replacement. Run the deterministic world-lifecycle gate -and the seven-destination resource soak. +first-login bootstrap replacement. The deterministic world-lifecycle gate and +nine-destination resource soak pass. #### Slice 6 — extract update-frame orchestration diff --git a/docs/architecture/retail-divergence-register.md b/docs/architecture/retail-divergence-register.md index 38ffd9a9..39fcd22c 100644 --- a/docs/architecture/retail-divergence-register.md +++ b/docs/architecture/retail-divergence-register.md @@ -67,7 +67,7 @@ accepted-divergence entries (#96, #49, #50). |---|---|---|---|---|---| | AD-38 | Outgoing teleport viewports retire when retail's quantized animation level exceeds the last captured visible level 1022 (index 96), suppressing levels 1023/1024 up to 20.2 ms before retail's literal `elapsed >= 1.0` state edge. Incoming fades retain the exact timer. | `src/AcDream.Core/World/TeleportAnimSequencer.cs` (`OutgoingViewportReachedTerminalProjection`) | An uncapped 2000 FPS pass can publish the finite tunnel at levels 1023/1024 even though the paired 2013 retail capture switches viewports after 1022. The table-level cutover preserves the captured visible viewport ordering without throttling the application. | Exit sound, viewport replacement, and logout tunnel entry can occur at most two easing-table quanta (about 20.2 ms) earlier than retail's logical timer. | `UIGlobals::GetAnimLevel @ 0x004EE540`; `gmSmartBoxUI::UseTime @ 0x004D6E30`; paired retail/acdream captures documented in `docs/research/2026-07-15-retail-portal-space-pseudocode.md` | | AD-1 | Lost-cell machinery replaced by recoverable outdoor demote (**#107** safety net) + outdoor-restore `max(terrainZ, z)` under-terrain lift; retail goes `GotoLostCell` | `src/AcDream.Core/Physics/PhysicsEngine.cs:553` (+ :808) | acdream has no lost-cell state machine; outdoor landcell is the recoverable equivalent; the #107 auto-entry hold should make the demote branch unreachable | Gap in the hold → player committed to outdoor terrain inside/under a building (fake-grounded spawn, fall-through); a legit below-heightmap server restore is silently lifted — upward warp vs server | `GotoLostCell` pc:283418; `SetPositionInternal` 0x00515bd0, pc:283892-283945 | -| AD-2 | Async readiness gates replace retail's synchronous destination cell load. **#229 refinement (2026-07-20):** login and F751 portal-space exit now share `WorldRevealReadinessBarrier`, so neither path can expose the normal viewport until the same render-publication, composite-texture, and collision domains converge. A hydratable indoor claim requires its owning Near-tier static/EnvCell mesh set, destination composites, and exact EnvCell physics (`IsSpawnCellReady`); an outdoor claim requires those render domains plus terrain/collision residency for the priority near ring. Hard-recenter generations and tier-aware completion application prevent stale overlapping loads/unloads or Far/Near jobs from opening or erasing the gate; mesh upload remains separate from balanced landblock ownership. Claims beyond NumCells still take the loud forced-placement path. `WorldRevealCoordinator` owns this shared lifetime; diagnostic telemetry observes its generation without defining another readiness path. The portal hold→materialize→regain-control lifecycle remains owned by `TeleportAnimSequencer`. | `src/AcDream.App/Streaming/WorldRevealCoordinator.cs`; `src/AcDream.App/Streaming/WorldRevealReadinessBarrier.cs`; `src/AcDream.App/Rendering/GameWindow.cs` (owner wiring + draw eligibility); `src/AcDream.App/Streaming/StreamingController.cs` (`IsRenderNeighborhoodResident`); `src/AcDream.App/Streaming/GpuWorldState.cs` (`IsRenderReady`); `src/AcDream.App/Rendering/Wb/LandblockSpawnAdapter.cs`; `src/AcDream.Core/Physics/PhysicsEngine.cs` (`IsSpawnCellReady`, `IsNeighborhoodTerrainResident`) | This is the asynchronous equivalent of retail leaving `SmartBox::position_update_complete` false while `CellManager::blocking_for_cells` is set: neither initial login nor portal arrival may reveal an empty collision world, a terrain-only Far shell, or a published-but-not-drawable GPU landblock. Indoor does not require a terrain heightmap, only the owning render landblock and exact EnvCell. | Gate opens early → grey/untextured first login or portal reveal, free-fall, wrong-cell rooting, or missing scenery; predicate never satisfies (streamer/DAT/upload failure) → login remains behind the world render gate, while portal transit reaches its existing loud timeout/forced-placement diagnostic. | `SmartBox::UseTime` 0x00455410; `gmSmartBoxUI::EndTeleportAnimation` 0x004D65A0 | +| AD-2 | Async readiness gates replace retail's synchronous destination cell load. **#229 refinement (2026-07-20):** login and F751 portal-space exit now share `WorldRevealReadinessBarrier`, so neither path can expose the normal viewport until the same render-publication, composite-texture, and collision domains converge. A hydratable indoor claim requires its owning Near-tier static/EnvCell mesh set, destination composites, and exact EnvCell physics (`IsSpawnCellReady`); an outdoor claim requires those render domains plus terrain/collision residency for the priority near ring. Hard-recenter generations and tier-aware completion application prevent stale overlapping loads/unloads or Far/Near jobs from opening or erasing the gate; mesh upload remains separate from balanced landblock ownership. Claims beyond NumCells still take the loud forced-placement path. `WorldRevealCoordinator` owns this shared lifetime; diagnostic telemetry observes its generation without defining another readiness path. The portal hold→materialize→regain-control lifecycle remains owned by `TeleportAnimSequencer`. | `src/AcDream.App/Streaming/WorldRevealCoordinator.cs`; `src/AcDream.App/Streaming/WorldRevealReadinessBarrier.cs`; `src/AcDream.App/Streaming/StreamingOriginRecenterCoordinator.cs`; `src/AcDream.App/Streaming/LandblockPresentationPipeline.cs`; `src/AcDream.App/Rendering/GameWindow.cs` (owner wiring + draw eligibility); `src/AcDream.App/Streaming/StreamingController.cs` (`IsRenderNeighborhoodResident`); `src/AcDream.App/Streaming/GpuWorldState.cs` (`IsRenderReady`); `src/AcDream.App/Rendering/Wb/LandblockSpawnAdapter.cs`; `src/AcDream.Core/Physics/PhysicsEngine.cs` (`IsSpawnCellReady`, `IsNeighborhoodTerrainResident`) | This is the asynchronous equivalent of retail leaving `SmartBox::position_update_complete` false while `CellManager::blocking_for_cells` is set: neither initial login nor portal arrival may reveal an empty collision world, a terrain-only Far shell, or a published-but-not-drawable GPU landblock. Indoor does not require a terrain heightmap, only the owning render landblock and exact EnvCell. | Gate opens early → grey/untextured first login or portal reveal, free-fall, wrong-cell rooting, or missing scenery; predicate never satisfies (streamer/DAT/upload failure) → login remains behind the world render gate, while portal transit reaches its existing loud timeout/forced-placement diagnostic. | `SmartBox::UseTime` 0x00455410; `gmSmartBoxUI::EndTeleportAnimation` 0x004D65A0 | | AD-3 | Outdoor seeds always walk the transit array (retail skips the walk when the seed CLandCell is null/unloaded); per-cell lookups no-op on unhydrated data | `src/AcDream.Core/Physics/CellTransit.cs:503` | Equivalence argument: with nothing hydrated every lookup inside the walk no-ops, so the result matches retail's skipped walk | Near partially-streamed landblocks, building-transit promotion silently can't fire until structs hydrate — membership stays outdoor while the player is inside a building | `CObjCell::find_cell_list` 0052b535-0052b56c (null-CLandCell case) | | AD-4 | `point_in_cell` against an unhydrated CellBSP returns false (skip) rather than the null-node "inside" default; retail never queries unloaded cells | `src/AcDream.Core/Physics/CellTransit.cs:588` | The null-node default would make an unhydrated cell spuriously claim every point; skipping is the conservative streaming-safe choice | During hydration, a point genuinely inside a not-yet-loaded cell resolves outdoor/stale — transient membership misclassification driving wrong collision set and render root | `CEnvCell::find_visible_child_cell` :311397; cell-BSP vtable[0x84] | | AD-5 | Outdoor `point_in_cell` is an identity compare against the global XY-column cell from `LandDefs.AdjustToOutside` (no per-cell containment test) | `src/AcDream.Core/Physics/CellTransit.cs:865` | Landcells are disjoint 24 m columns — identity-compare against the column under the sphere centre is exactly equivalent to retail's per-candidate test | If block-origin/lcoord math is wrong at a landblock seam, the compare silently never matches — outdoor membership freezes at boundaries (the pre-#106 symptom) | `find_cell_list` pick pc:308788-308825; `CLandCell::point_in_cell` (get_block_offset pc:308804) | diff --git a/docs/plans/2026-04-11-roadmap.md b/docs/plans/2026-04-11-roadmap.md index 417106a9..87c4edf4 100644 --- a/docs/plans/2026-04-11-roadmap.md +++ b/docs/plans/2026-04-11-roadmap.md @@ -47,15 +47,16 @@ passes 6,940 tests with five intentional skips. The 310-second connected R6 gate passed seven destinations/revisits, movement/jump/combat exercises, and graceful close. -**Current:** Slice 5 checkpoints A–G have extracted the DAT-backed worker +Slice 5 is complete: checkpoints A–G extracted the DAT-backed worker build plus render, physics, DAT-static, and retryable Near/full presentation ownership into `LandblockPresentationPipeline`. Production has no callback facade back into the deleted GameWindow apply bodies. A retained shared-origin transaction retires the complete old window before teleport recenter or -session replacement, including failure/retry and fast relogin. `GameWindow` is -8,793 raw lines (44% below the campaign baseline) and the Release suite passes -7,052 tests with five intentional skips. Slice 5H deterministic and connected -closeout is active. +session replacement, including failure/retry and fast relogin. Shutdown keeps +the reset graph alive until disposal converges. `GameWindow` is 8,811 raw +lines / 247 fields / 153 methods (44% below the campaign baseline); 7,054 +Release tests, the capped/reconnect lifecycle gate, and the synchronized +nine-stop resource soak pass. Slice 6 update-frame orchestration is active. This is a behavior-preserving structural program. Severe regressions still get root-cause fixes in separate commits; ordinary feature work resumes with M4 diff --git a/docs/plans/2026-05-12-milestones.md b/docs/plans/2026-05-12-milestones.md index 3ac80c58..0b248c75 100644 --- a/docs/plans/2026-05-12-milestones.md +++ b/docs/plans/2026-05-12-milestones.md @@ -19,14 +19,15 @@ layer, the active structural prerequisite is the behavior-preserving The 2026-07-21 audit baseline was 15,723 lines, 278 fields, and 205 methods. Selection/interaction Slice 1, live-animation-presentation Slice 2, complete live-session ownership Slice 3, and live-entity App integration Slice 4 are -complete. Slice 5 landblock-presentation checkpoints A–G are also complete: +complete. Slice 5 landblock presentation is also complete: the worker DAT transaction, render/physics/static publishers, and retryable Near/full retirement now have focused owners. The direct production cutover also serializes complete old-window retirement with teleport and session -origin lifetimes. `GameWindow` is 8,793 raw lines, down 1,508 from the Slice-5 -baseline and 6,930 (44%) from the campaign baseline. The full Release suite -passes 7,052 tests / 5 skips; Slice 4's seven-destination connected R6 route -passed in 310 seconds. Slice 5H deterministic/connected closeout is active. +origin lifetimes. `GameWindow` is 8,811 raw lines / 247 fields / 153 methods, +down 1,490 lines from the Slice-5 baseline and 6,912 (44%) from the campaign +baseline. The full Release suite passes 7,054 tests / 5 skips; the 311-second +capped/reconnect lifecycle gate and synchronized 394-second nine-destination +resource soak both pass. Slice 6 update-frame orchestration is next. Carried: #153 far-teleport residual, #116 slide-response, the remaining R6 ownership cleanup plus diff --git a/docs/plans/2026-07-21-gamewindow-slice-5-landblock-presentation.md b/docs/plans/2026-07-21-gamewindow-slice-5-landblock-presentation.md index 750ae702..9ef6385b 100644 --- a/docs/plans/2026-07-21-gamewindow-slice-5-landblock-presentation.md +++ b/docs/plans/2026-07-21-gamewindow-slice-5-landblock-presentation.md @@ -1,6 +1,6 @@ # GameWindow Slice 5 — landblock presentation -**Status:** Active 2026-07-21. +**Status:** Complete 2026-07-21 (`4a205a3e`). **Parent program:** [`docs/architecture/code-structure.md`](../architecture/code-structure.md), Slice 5. **Baseline:** `2b10e91e`; `GameWindow.cs` is 10,301 lines, 267 fields, and 163 methods. Release baseline: 6,940 passed / 5 skipped. The connected R6 @@ -98,9 +98,23 @@ test, and bisectable commit rather than being hidden in a mechanical move. `GameWindow.cs` is 9,011 lines. - [x] G — cut `StreamingController` and `GameWindow` directly to the pipeline; delete old bodies, scratch state, and callback facades. -- [ ] H — three-agent corrected-diff review, full Release suite, deterministic - lifecycle gate, seven-destination resource soak, documentation, and durable +- [x] H — three-agent corrected-diff review, full Release suite, deterministic + lifecycle gate, nine-destination resource soak, documentation, and durable memory closeout. + - Landed in `4a205a3e`: native shutdown now keeps the live-session reset + dependencies alive until deferred/reentrant disposal actually converges; + source and behavioral tests pin that completion barrier. Both connected + harnesses scan the final post-close logs for shutdown/disposed-resource + failures. The resource gate uses an already-warm Caul → Sawato → Caul + plateau instead of comparing a cold first load to a warmed cache, and + every route command blocks on its exact portal-materialization count. + - All three final reviews are clean. Release gate: 7,054 passed / 5 skipped. + The capped/reconnect lifecycle gate passed in 311.4 seconds. The + synchronized nine-stop soak passed in 394.1 seconds; Caul return → plateau + changed working/private memory by only +56.4/+48.4 MiB and update p95 by + 0.8 → 0.7 ms. `GameWindow.cs` closes Slice 5 at 8,811 raw lines, 247 + fields, and 153 methods—1,490 lines below the Slice-5 baseline and 6,912 + lines (44%) below the campaign baseline. Every checked checkpoint is committed as a bisectable architectural unit. Documentation records the exact commit and accepted test count as work lands. @@ -385,15 +399,15 @@ the shared origin may be reused. Reviews closed full-window overlap, radius reconfiguration, sealed-dungeon bootstrap, committed-callback retry, reentrancy, fast-relogin, and ordinary-logout gaps. Three final reviews are clean; the zero-warning Release build and 7,052 tests pass with five skips. -`GameWindow.cs` is 8,793 raw lines, 1,508 below the Slice-5 baseline and 6,930 -(44%) below the campaign baseline. +`GameWindow.cs` was 8,793 raw lines at checkpoint G, 1,508 below the Slice-5 +baseline and 6,930 (44%) below the campaign baseline. ### H — closeout -**Active.** No new landblock ownership moves are planned in H; it proves the -landed graph under deterministic and connected lifecycle churn, reconciles -divergence pointers/documentation, and records the final Slice-5 structural -measurement before Slice 6 begins. +**Complete in `4a205a3e`.** H proved the landed graph under deterministic and +connected lifecycle churn, corrected shutdown-stage ordering so session reset +converges before its streaming dependencies are disposed, and strengthened the +resource oracle to compare already-warm steady-state revisits. - Run focused App/Core/Net tests after each checkpoint. - After each code checkpoint, run three independent read-only reviews: retail/ @@ -401,7 +415,7 @@ measurement before Slice 6 begins. analysis. Fix confirmed findings and repeat review until clean. - Run `dotnet build AcDream.slnx -c Release` and the full Release test suite. - Run deterministic first-login/portal lifecycle automation and the connected - seven-destination resource soak. Verify retirement/preparation queues drain, + nine-destination resource soak. Verify retirement/preparation queues drain, residence matches the region, resource counts remain bounded, and graceful close succeeds. - Update the divergence register pointers in IA-14, AD-2, AD-22, and any other @@ -410,6 +424,11 @@ measurement before Slice 6 begins. - Update architecture, milestones, roadmap, issues if needed, synchronized `AGENTS.md`/`CLAUDE.md`, and durable decomposition/render memory. +The final IA-14/AD-2/AD-22 audit found no new retail divergence. IA-14 and +AD-22 still point at the correct WB/mesh owners; AD-2 now names the extracted +origin-recenter/presentation owners. AD-6, AD-24, AP-31, and TS-52 remain open +as required. + ## 6. Acceptance matrix Automated acceptance includes: