# Next-agent prompt — finish the retail placement/collision campaign Continue acdream from the 2026-08-03 stabilization checkpoint. The code is modern; behavior must remain retail-faithful. The campaign is playable again, but it is **not closed**. ## Start here Use the merged local `main` worktree: ```text C:\Users\erikn\source\repos\acdream ``` The completed fixes originated on `codex/port-claude-agents` and are merged into local `main`. Confirm the exact starting commit with `git rev-parse HEAD` and read the operator's handoff message for the merge SHA. Do not reset, clean, or overwrite the main worktree's untracked research/reference files. The original feature worktree remains at: ```text C:\Users\erikn\.codex\worktrees\af5e\acdream ``` That feature worktree contains protected user-local modifications and is not the preferred continuation workspace. Read these files in order before editing: 1. `CLAUDE.md` and `AGENTS.md`. 2. `docs/plans/2026-08-02-placement-cutover.md` — canonical placement-cutover plan and the 2026-08-03 checkpoint. 3. This prompt. 4. `docs/research/2026-08-02-collision-throughput-handoff/implementer-progress.md` — especially `## P1` and the final stabilization checkpoint. 5. `docs/research/2026-08-02-collision-throughput-handoff/p1-retirement-receipt-loop.md`. 6. `docs/research/2026-08-02-c3c-cutover-closeout.md`. 7. `docs/ISSUES.md` #269 and #276–#280. 8. `docs/architecture/retail-divergence-register.md` rows AP-1, AP-22, AP-131, AD-1, AD-10, AD-60, and TS-28. `docs-drafts.md` is now explicitly historical. Do **not** apply it wholesale: it predates the final fixes and incorrectly tries to reuse issue number #280. ## Binding rules - Grep `docs/research/named-retail/acclient_2013_pseudo_c.txt` by named `class::method` before fresh decompilation. Retail behavior is the oracle. - Preserve the modern Runtime-owned, presentation-independent architecture. Graphical and headless hosts must use the same canonical gameplay owners. - Root causes only. Do not add timeouts, grace periods, suppression flags, catch-and-swallow paths, duplicated placement writers, or compatibility bypasses to make a test green. - The user's connected observations are acceptance facts. A green automated test cannot overrule a live regression. - Never use `git add -A`, `git add .`, `git reset --hard`, or `git checkout -- `. Stage exact paths only. - Do not delete or normalize unrelated/untracked worktree content. - Each independent fix must be a bisectable commit whose message records the root cause and evidence. - Update the divergence register and issues in the same commit that changes their truth. Retire a row only when its exact legacy mechanism is gone. - Do not push unless the user explicitly asks. - Connected tests require the user's ACE server at `127.0.0.1:9000`. Close the client gracefully before reconnecting so ACE releases the session. ## What has been completed ### C3c and collision-publication checkpoint - `529e0e9d` — C3c production first-entry cutover for graphical and headless hosts. - `71604331` — O(changed) per-landblock collision publication checkpoint. Its original commit was deliberately marked WIP after the first feel test; do not treat that old label as the current product status. The following fixes addressed the observed failures. ### Stabilization fixes, all user-verified where visual behavior applies 1. `01f4791e` — **retirement-receipt replay loop fixed.** - Root cause: a pending-only live-projection bucket was promoted to a second full landblock cleanup receipt after the first detach had already committed. The duplicate guard threw; a broad resumable path replayed the detach 243 times. - Fix: retain pending identities without manufacturing another receipt; post-commit receipt invariants are terminal, not resumable. - Evidence: focused recenter tests; complete Release suite 10,815 passed / 4 skipped; lifecycle report `logs/connected-world-gate-20260802-203751/report.json`; nine-stop report `logs/connected-r6-soak-20260802-204309.report.json` with `Passed=true`, nine checkpoints, zero failures, zero wait cues, zero pending retirements, and no recurrence of the 243x exception. 2. `670f307c` — **remote placement and targeting share one world frame.** - Root cause: CreateObject positions are landblock-local, but Runtime submitted remote first-entry placement with zero world offset; the local physics host also published a landblock-local origin to targeting. - Fix: Runtime owns the accepted local-player world center, converts remote Create placement before SetPosition, and publishes the local body's world position. - User gate: monsters and statics place correctly; monsters chase and hit the visible player instead of attacking another coordinate. 3. `1fc529cd` — **distant Use/approach restored.** - Root cause: Runtime object lookup is intentionally non-constructing, so a static door/corpse could enter MoveTo without a physics host and its target snapshot expired at the origin. Startup placement could also leave an impossible pre-PartArray motion suffix ahead of later actions. - Fix: ensure the canonical minimal static host before routing MoveTo and reconcile the startup suffix exactly at presentation attach. - User gate: near and distant object use works, including approach, turn, and use after arrival. 4. `f24532ad` — **spell, recall, projectile, and static VFX binding fixed.** - Root cause: C3c could create effect/projectile/static-animation sidecars before first SetPosition had bound the entity's mesh, pose, cell, and visibility. One-shot F754/F755 packets were lost and projectiles could inherit a cell-less body. - Fix: exact-incarnation presentation barrier and FIFO replay; retry projectile/static binding on the committed visibility edge; synchronize effect cells on rebucket. - User gate: buffs/protections, recall effects, arrows, combat spell projectiles, portals, and static animation all work. 5. `175ad6b0` — **login materialization acknowledgement fixed.** - Root cause: ACE creates the local player Hidden and releases that state on LoginComplete. Sending LoginComplete from raw F746 receipt raced first canonical placement and left the purple haze over the character. - Fix: one completion callback from Runtime's local first-entry terminal edge; content-less headless retains its only truthful accepted-Create edge. - User gate: ordinary login no longer leaves the purple haze; recall still has the intended materialization presentation. ### Latest focused verification After the final fix, these passed: - 90 focused App effect/projectile/static-animation scheduler tests. - Two focused Runtime login-completion tests. - The exact live-entity cell-tracking regression. - All 79 Headless tests. - `dotnet build AcDream.slnx -c Release --no-restore` with zero errors (existing warnings remain). The long complete suite and connected nine-stop soak were **not rerun after the final four stabilization commits**. The P1 soak proves P1's binary, not the final campaign binary. ## What remains — execute in this order ### 1. Reconcile the six selected-fixture failures A broad selected run after cleanup exposed: - five failures in `LiveEntityRuntimeTests`, associated with the still-open placement/cell cutover; - one old `RuntimeLiveEntitySessionControllerTests` remote-first-entry fixture that provides an empty collision source while the production contract now requires truthful collision admission. Re-run these two classes first and record the exact test names and assertions. Classify each as either a real product failure or a stale fixture. If stale, update the fixture to provide the same valid prepared collision neighborhood as production; never weaken the product contract or merely change expected values. If real, fix the owning production mechanism and add a smaller regression test. Suggested first commands: ```powershell $env:ACDREAM_PAK_PATH='C:\Users\erikn\Documents\Asheron''s Call\acdream.pak' dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Release --no-restore --filter FullyQualifiedName~LiveEntityRuntimeTests -m:1 dotnet test tests/AcDream.Runtime.Tests/AcDream.Runtime.Tests.csproj -c Release --no-restore --filter FullyQualifiedName~RuntimeLiveEntitySessionControllerTests -m:1 ``` ### 2. Finish C4: remaining authoritative placement routes The plan still marks routes 2–7 open: - route 2: ForcePosition; - route 3: portal placement through `RuntimeWorldTransitState` and `RuntimePortalPlacementAuthority`; - route 4: remote Create/Position, deleting the remaining `RemoteTeleportController`/inline MoveOrTeleport duplicate; - route 5: authoritative projectile correction; - route 6: drops and split-recovery marking; - route 7: pickup, parent-detach, and delete/recreate residue. Inventory every current writer before editing. For each route, prove: - one Runtime SetPosition transaction owns accepted frame, exact cell, collision result, shadow/workset membership, and deferred-cell lifetime; - App only projects the committed result; - graphical and headless hosts use the same command and state path; - stale sequences, delete/GUID reuse, missing cells, portal generations, and replacement collision generations cannot commit old state; - no route reconstructs from a stale spawn or uses the legacy outdoor demote/ terrain-Z lift. Resolve #276 when the spawn settler's resolved `CellId` becomes authoritative. Resolve #277 with a real service-window/celless lifecycle instead of relying on ACE's current broadcast radius. ### 3. Fix #280: destination prefetch before portal reveal Current behavior waits only a hard-coded radius-one (3x3) outdoor neighborhood, while the visible configured world extends farther. The user can see distant terrain continue building after portal exit. Port the retail mechanism, not a larger magic number: - `CellManager::PreFetchCells @ 0x00455820`; - `LScape::PreFetchCells @ 0x00505660`; - `CLandBlock::PreFetchCells` and `CLandBlockInfo::PreFetchCells`; - `SmartBox::UseTime @ 0x00455410` while `blocking_for_cells`; - the `TAS_TUNNEL_CONTINUE` resume/reveal order. Use the quality/view-distance configured destination window. Hold one generation-scoped reservation across terrain, buildings/statics, EnvCells, render publication, composite textures, and collision. Keep portal UI and wait cue responsive. Never reveal early because of a timeout, and do not wait for an impossible terminal marker for all dynamic ACE objects. Acceptance: repeated login, `/ls`, spell recall, and portals at every quality setting reveal no constructing terrain, missing nearby statics/buildings, unready interiors, missing composites, or absent nearby collision. Dynamic monsters/items may still arrive later from ACE. ### 4. C5 closeout and live gates After steps 1–3: 1. Delete every superseded placement writer and compatibility projection. 2. Run focused Runtime/Core/App tests for every route. 3. Run the complete Release solution suite with the installed pak. 4. Run the exact lifecycle/reconnect route. 5. Run the canonical nine-stop soak on the **final binary**. Read `report.json`, not marker output. Required: `Passed=true`, zero failures, every canonical checkpoint, `waitCueShown=false`, zero pending publication/retirement/reveal debt, graceful exit, and no render-shadow mismatch. Diagnose any real failure; do not rerun past it. 6. Perform two-client observation for remote creation, chase/attack, doors, drops/pickups, portal departure/arrival, arrows, and spells. 7. Ask the user for the remaining #269/#278 slope-glide comparison at the known impassable slope. Only then retire AP-1, AD-1, AP-131, and the legacy half of AD-60 and close the corresponding placement issues. ### 5. Finish the original physics-divergence campaign After placement C5 is green: - **AP-22:** make `ShadowShapeBuilder` the sole authority for authored Setup collision shapes. Preserve cylinder order; use authored spheres when there are no cylinders; cylinder-first for mixed data; truly shapeless means no shadow. Remove invented `Setup.Radius` cylinders, `Radius * 2` heights, and sphere-to-cylinder coercion across graphical, headless, static, and live paths. - **AD-10:** prove remote motion uses the full transition sweep, remove terrain-normal preprojection, and let `CTransition::adjust_offset` project against the actual retained contact plane. Preserve interpolation, correction replacement, Hidden state, and network cadence. - Run the final movement/collision matrix and update the divergence ledger, architecture, roadmap, milestones, memory, `CLAUDE.md`, and `AGENTS.md`. Resume vendor Slice 5 only after this campaign is genuinely closed. ## Required deliverable For every remaining item report: - observed failure and deterministic reproduction; - retail/reference evidence with named functions and addresses; - root cause in plain language plus file/line evidence; - exact fix and why it preserves Runtime ownership; - tests added or corrected; - commit SHA; - complete build/test/connected-gate numbers; - user visual result where required; - divergence/issue rows retired, narrowed, or left open. Finish with an explicit list of anything still open. Do not describe the campaign as complete while any C4 route, #280, final-binary soak, AP-22, AD-10, or required user visual gate remains.