13 KiB
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:
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:
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:
CLAUDE.mdandAGENTS.md.docs/plans/2026-08-02-placement-cutover.md— canonical placement-cutover plan and the 2026-08-03 checkpoint.- This prompt.
docs/research/2026-08-02-collision-throughput-handoff/implementer-progress.md— especially## P1and the final stabilization checkpoint.docs/research/2026-08-02-collision-throughput-handoff/p1-retirement-receipt-loop.md.docs/research/2026-08-02-c3c-cutover-closeout.md.docs/ISSUES.md#269 and #276–#280.docs/architecture/retail-divergence-register.mdrows 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.txtby namedclass::methodbefore 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, orgit checkout -- <path>. 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
-
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 reportlogs/connected-r6-soak-20260802-204309.report.jsonwithPassed=true, nine checkpoints, zero failures, zero wait cues, zero pending retirements, and no recurrence of the 243x exception.
-
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.
-
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.
-
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.
-
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-restorewith 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
RuntimeLiveEntitySessionControllerTestsremote-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:
$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
RuntimeWorldTransitStateandRuntimePortalPlacementAuthority; - 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::PreFetchCellsandCLandBlockInfo::PreFetchCells;SmartBox::UseTime @ 0x00455410whileblocking_for_cells;- the
TAS_TUNNEL_CONTINUEresume/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:
- Delete every superseded placement writer and compatibility projection.
- Run focused Runtime/Core/App tests for every route.
- Run the complete Release solution suite with the installed pak.
- Run the exact lifecycle/reconnect route.
- 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. - Perform two-client observation for remote creation, chase/attack, doors, drops/pickups, portal departure/arrival, arrows, and spells.
- 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
ShadowShapeBuilderthe 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 inventedSetup.Radiuscylinders,Radius * 2heights, 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_offsetproject 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, andAGENTS.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.