acdream/docs/research/2026-08-03-c4-handoff/NEXT-AGENT-PROMPT.md
Erik 22a5c95400 docs: next-agent handoff prompt for C4 routes 2-7
Self-contained continuation prompt for the placement cutover. Records the
worktree/branch/HEAD (and that main is still at c7d5fc14 with these commits
unmerged, per the user's direction to work in the worktree), the read-first
list, binding rules, the 10,844/4/0 baseline to measure against, the 10
commits landed on this branch, and the work order: route 2 from its pinned
contract, route 3 with #280 beside it, routes 4-7 folding in #276/#277, C5
closeout, then AP-22 and AD-10.

Carries the two things a fresh session would otherwise have to rediscover:
route 2 is a seam-building slice rather than a wiring job (the accepted-Position
classifier's only production consumer is route 1's Create continuation), and
the complete-suite-before-every-commit gate that the #281-#284 regressions
bypassed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 14:43:56 +02:00

9.9 KiB
Raw Blame History

Next-agent prompt — C4 placement routes 27

Continue the acdream placement cutover from the 2026-08-03 regression-cleanup checkpoint. The code is modern; behaviour must remain retail-faithful.

Where to work

C:\Users\erikn\source\repos\acdream\.claude\worktrees\peaceful-visvesvaraya-e0a196

Branch claude/acdream-physics-divergence-5aa784, expected HEAD f2b06f378738474b0861e4d990d17f9645e07615.

The user directed that work happen in this worktree, not in main. main is still at c7d5fc14 — the 10 commits below are NOT merged. Do not merge, rebase, or push unless the user explicitly asks. Preserve the main worktree's untracked research/tooling files.

Read before editing

  1. CLAUDE.md and AGENTS.md.
  2. docs/research/2026-08-03-c4-route-2-contract.mdthe pinned contract for your first task. It is the whole ramp-up for route 2.
  3. docs/plans/2026-08-02-placement-cutover.md — the C4/C5 campaign plan.
  4. docs/research/2026-08-02-cutover-route-inventory.md — the 8-route, both-host call-chain inventory with exact file:line for every duplicate authority. THE map for routes 37.
  5. docs/plans/2026-08-03-recent-regression-cleanup.md — closed; explains the three defects fixed this session and why.
  6. docs/ISSUES.md — #276, #277, #280 (open); #281#284 (closed this session).
  7. docs/architecture/retail-divergence-register.md rows AP-1, AP-22, AP-131, AP-133, AD-1, AD-10, AD-60, TS-28.

Binding rules

  • Retail is the oracle. Grep docs/research/named-retail/acclient_2013_pseudo_c.txt by named class::method BEFORE any fresh decompilation.
  • Preserve the Runtime-owned, presentation-independent architecture. Graphical and headless hosts use the same canonical owners.
  • Root causes only. No timeouts, grace periods, suppression flags, catch-and-swallow, duplicated placement writers, or test-only bypasses.
  • The user's live observations outrank green automated tests.
  • Never git add -A, git add ., git reset --hard, or git checkout -- <path>. Stage exact paths only.
  • Each independent fix is its own bisectable commit recording root cause and evidence; issue and divergence ledgers update in that same commit.
  • Run the COMPLETE Release solution suite green before every commit. Not a focused subset. Every regression cleaned up this session shipped because a commit was gated on focused tests while the full suite was red. It costs ~30 seconds:
    $env:ACDREAM_PAK_PATH='C:\Users\erikn\Documents\Asheron''s Call\acdream.pak'
    dotnet test AcDream.slnx -c Release -m:1
    
  • Close the client gracefully before reconnecting to ACE at 127.0.0.1:9000. The user manages client lifecycle; if a rebuild is lock-blocked, ASK.
  • Launch visual gates in Release, with ACDREAM_RETAIL_UI=1 (the user prefers the retail GUI).

Baseline

Complete Release solution at HEAD: 10,844 passed / 4 skipped / 0 failed (App 4,058/3, Bake 15, Cli 4, Content 124, Core.Net 762, Core 4,247/1, Headless 79, Runtime 1,012, UI 543). Treat any deviation as a regression you introduced.

Completed on this branch (10 commits)

Commit What
6dcb94ac Restored the world-frame precondition across 5 first-entry fixtures; added RuntimeWorldFrameTests
98e9f9e8 Modelled the post-f24532ad effect cell / canonical body frame in 2 rendering fixtures
95ebc03a Filed #282#284 + cleanup plan
97d11e6c #284 — parked placements name their cause; terminal on the contradictory state
3c36b4cc #282 — one cell owner (WorldEntity.VisibilityCellId); register row AP-133
0c14c402 Connected visual acceptance for #282/#284
898ff18b #283 reachability probe (ACDREAM_PROBE_WORLD_FRAME=1)
89cf1e66 #283 — measured UNREACHABLE; permanent invariant instead of a restructure
2ef02f8c Closed the cleanup plan
f2b06f37 Pinned the route 2 contract (your starting point)

Context worth carrying: the handoff that started this session claimed "six selected fixture failures". The measured baseline was 43 — the App suite was fully green at 01f4791e and 670f307c broke 28 tests in one commit, while the Runtime suite lost 13. All were stale fixtures, fixed without weakening a single assertion. Three real product defects (#282#284) were found in the same sweep and are now closed.

Work order

1. Route 2 — ForcePosition (start here)

Execute docs/research/2026-08-03-c4-route-2-contract.md.

Scoping is already done and it is not a small wiring job: RuntimeAuthoritativePositionRouteClassifier.ClassifyAcceptedPosition produces the retail-exact ForcePosition route but has exactly ONE production consumer — RuntimeInitialCreateContinuationExecutor.cs:1948, route 1's Create continuation. A live local player receiving a Position has no Runtime consumer at all. You must build the accepted-Position execution seam, then cut App over.

Two duplicate authorities to delete:

  • LocalForcePositionTransaction (blip + pre-commit outbound ack);
  • the generic tail at LiveEntityNetworkUpdateController.cs:1264-1281, which independently writes position/cell/rotation to the render entity and rebuckets the SAME accepted Position.

Named behaviour change to call out in the commit: the outbound AutonomousPosition ack currently fires BEFORE any canonical commit, and the trailing isCurrent() only suppresses the continuation — the packet has already gone. Retail makes it SendPositionImmediately, an output of the executed route.

Retail: SmartBox::HandleReceivedPosition @0x00453FD0 — the FORCE_POSITION early return (~92932) precedes unset_parent (~92990) and the !HasAnims-gated SetPlacementFrame (~92992).

2. Route 3 — portal placement

RuntimeWorldTransitStateRuntimePortalPlacementAuthority adapter. Delete LocalPlayerTeleportPlacement.Place (LocalPlayerTeleportController.cs:214-278), which does its own resolve, body/ cell write, world-entity write, rebucket and host-notify, and then calls AcknowledgePortalMaterialized AFTERWARDS — a rubber stamp, not a gate. Re-sequence so the acknowledgement is the actual gate.

#283 is already settled, so the origin question is closed going in; the permanent guard is LiveWorldOriginState.EnsureAgreesWithRuntimeFrame.

3. #280 — portal destination prefetch (land beside route 3)

The reveal gate is a hardcoded 3×3 landblock neighbourhood (WorldRevealReadinessBarrier.OutdoorNeighborhoodRadius = 1, 576 m) while the configured view is 11×11 to 31×31 (2,1125,952 m) depending on quality preset — so the viewport opens on ~1.4% of the visible world on High and the user watches the rest stream in. Compounded by BeginOriginRecenter detaching every resident landblock (no reuse) and MaxCompletionsPerFrame 26.

Port retail's mechanism, not a bigger magic number: CellManager::PreFetchCells @0x00455820, LScape::PreFetchCells @0x00505660, CLandBlock::PreFetchCells, CLandBlockInfo::PreFetchCells, SmartBox::UseTime @0x00455410 while blocking_for_cells, and the TAS_TUNNEL_CONTINUE resume/reveal ordering. Use the configured quality/view-distance window; hold ONE generation-scoped reservation across terrain, statics/buildings, EnvCells, render publication, composites, and collision. Keep the wait cue responsive. Never reveal early on a timeout; never wait for an impossible "all dynamic objects delivered" marker.

4. Routes 47

  • 4 — remote Create/Position; delete RemoteTeleportController/Placement and the inline MoveOrTeleport duplicate. Retires AP-131.
  • 5 — authoritative projectile correction.
  • 6 — drops + split-recovery marking.
  • 7 — pickup, parent detach, delete/GUID-reuse residue.

Fold in #276 (SpawnPlacementSettler must commit the settle's resolved CellId) and #277 (far Create needs a real service-window/cell-less lifecycle instead of relying on ACE's broadcast radius) where their route becomes authoritative. #284's parked-placement counts were deliberately NOT folded into IsConverged because #277 documents a legitimate session-long park — wire them into the connected gates when #277 makes "legitimately parked" definable.

5. C5 closeout

Delete every superseded writer; focused + complete suites; lifecycle/reconnect; canonical nine-stop soak on the final binary (read report.json, require Passed=true, zero failures, all checkpoints, waitCueShown=false, no pending publication/retirement/reveal debt, no render-shadow mismatch, graceful exit); two-client observation; user visual matrix. Then retire AP-1, AD-1, AP-131 and AD-60's legacy half.

6. Then AP-22, then AD-10

  • AP-22ShadowShapeBuilder as the sole authority for authored Setup collision shapes. Preserve authored cylinder order; authored spheres when no cylinders; cylinder-first for mixed; truly shapeless means no shadow. Remove invented Setup.Radius cylinders, Radius * 2 heights, sphere-to-cylinder coercion, across graphical/headless/static/live together.
  • AD-10 — remote slope projection through the real retained transition contact plane. Prove remote motion uses the complete sweep, remove terrain-normal preprojection, let CTransition::adjust_offset project against the actual collision plane. Preserve interpolation queues, authoritative correction replacement, Hidden state, network cadence.

Then the final movement/collision matrix and ledger/architecture/roadmap/ milestones/memory/CLAUDE.md/AGENTS.md updates. Vendor Slice 5 resumes only after the campaign is genuinely closed.

Reporting

For every fix report: reproduction, retail evidence (named symbol + address), plain-language root cause, files/lines, the fix, tests, commit SHA, complete build/test numbers, user visual result where required, and which issues or divergence rows were closed, narrowed, or left open.

Do not describe the campaign as complete while any C4 route, #280, the final-binary soak, AP-22, AD-10, or a required user visual gate remains.