acdream/docs/research/2026-08-02-collision-throughput-handoff/NEXT-AGENT-PROMPT.md

285 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 -- <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
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 27 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 13:
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.