acdream/docs/research/2026-08-04-session-handoff-c4-remaining.md
Erik 3e002993dd docs: C4 handoff for routes 4b-3, 5, 6, 7, 3
Closes #312 as user-confirmed, with the caveat recorded rather than buried: the
accepting session's probe capture showed 22 parks and zero park-restores, so the
restoration path was not observed executing. If an invisible-remote report
recurs, that is where to start.

Re-scopes #309 as largely superseded by #312 — the presentation restore is the
behaviour its connected check was written to probe. What survives is the
narrower faithfulness question: retail's GotoLostCell keeps a lost-cell object
hidden until reenter_visibility, where acdream re-shows it on cancel.

Adds the handoff itself: branch state and the measured 11,027 baseline, the two
known flakes and the standing instruction not to conflate them, per-route
scope with the retail addresses and the traps already paid for (teleport_hook
runs BEFORE the placement; route 5 has no possible live gate because ACE never
sends UpdatePosition for a missile; route 6 needs zero production lines and the
campaign plan carries a false premise about create-time effects; route 7 must
write the child cell at BOTH the set_parent analog and the per-commit position
analog), and the six process rules this session paid for — chiefly that the
contract causes the defect, that a slice must split on discovery, and that a
green suite and a clean-looking live session are both non-evidence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 12:00:15 +02:00

133 lines
7.6 KiB
Markdown

# C4 handoff — routes 4b-3, 5, 6, 7, 3 (2026-08-04)
Written at the end of a long session. **Read this before touching anything.**
## Where the branch is
- Worktree `C:\Users\erikn\source\repos\acdream\.claude\worktrees\peaceful-visvesvaraya-e0a196`
- Branch `claude/acdream-physics-divergence-5aa784`, HEAD **`2eb39a02`**
- **`main` is at `c7d5fc14` and must stay there.** The commits on this branch are
deliberately unmerged. Do not merge, rebase, or push unless the user asks.
- Complete Release suite: **11,027 passed / 4 skipped / 0 failed**. This is the
baseline. Any deviation is a regression you introduced.
```
$env:ACDREAM_PAK_PATH = "$env:USERPROFILE\Documents\Asheron's Call\acdream.pak"
dotnet test AcDream.slnx -c Release -m:1
```
- Two known flakes — do **not** chase, and do **not** conflate (they have been
conflated twice): **#302** `PortalProjectionTests.ClipToRegion_FrameOwnedStore_…`,
a GC-allocation assertion in App.Tests; **#308** `NakEmissionTests.LossSoak_…`,
a wall-clock deadline in Core.Net.Tests that fails only under full-suite load.
## What landed this session (all user-accepted)
| commit | what |
|---|---|
| `634bc551` | park restore — shipped defect, separate from the feature it was found in |
| `2e8e09ac` | route 4b-1, dormant infrastructure |
| `7f1c1f5a` | **route 4b-2** — remote far snap; far-snap walk passed |
| `204d0ae0` | remote slide on steep faces (#32 remote half) |
| `b1f914d5` | presentation restored on cancelled park (#312) |
| `2eb39a02` | AP-140 — route remote Positions on contact, not walkability |
Plus scoping/research commits `07e97939`, `11a87428`, `1b631f12` and doc
corrections `f058dfc9`, `97b22b86`, `f4f25795`.
## What is left, in order
**4b-3 — remote teleport + cell-less.** ~400-700 production lines. Deletes
`RemoteTeleportController` (605 lines), `RemoteTeleportPlacement` (85),
`RemoteShadowPlacementSynchronizer` (49) and ~1,709 lines of their tests.
Retail: `MoveOrTeleport` @0x00516330's cell-less/teleport branch @0x00516386 →
`teleport_hook` @0x005163EF → `SetFlags(0x1012)` @0x00516414 → `SetPosition`
@0x00516420 → `return 1` @0x00516438. **`teleport_hook` @0x00514ED0 runs BEFORE
the placement** and is `CancelMoveTo` + `UnStick` + `StopInterpolating` +
`UnConstrain` + TargetManager teardown + `report_collision_end(this, 1)`
@0x00514F31. The classifier already carries
`RuntimeTeleportHookPhase.BeforePositionOperation` for that branch
(`RuntimeAuthoritativePositionRouteClassifier.cs:410`) and currently
records-and-drops it for the remote arm. **4b-3 retires AP-137's cell-less
enqueue-vs-place delta** — today acdream enqueues where retail places
unconditionally, at any distance.
**5 — projectile.** ~180 non-comment lines; **half already shipped** (the
Create half and the residence-window Position half are canonical). What remains
is the post-residence accepted Position, short-circuited before the classifier
at `LiveEntityNetworkUpdateController.cs:1428-1448`. Must land **after 4b-2**
(done) because it widens `RuntimeRemotePlacementDriveController.OwnsPlacement`,
which excludes `ProjectileAuthoritative` today. **No live gate is possible**:
ACE never sends `UpdatePosition` for a missile (the one site is commented out at
`WorldObject_Tick.cs:333-334`). Test-gated; say so rather than inventing a gate.
Scoping: `docs/research/2026-08-04-c4-route-5-scoping.md`.
**6 — drops. ZERO production lines.** C3c already satisfied it; a dropped item
classifies as route 1's shape and both drop flavours converge on
`LiveEntityHydrationController.OnCreate`. The campaign plan's "replay
create-time effects" requirement is a **false premise** — correct
`docs/plans/2026-08-02-placement-cutover.md:98-100`. Retail's "split-recovery
marking" is a *selection* transfer (`UIAttemptSplitTo3D` @0x0058D850,
`DeclareValid` @0x0058E340), missing but not placement — file outside C4.
Scoping: `docs/research/2026-08-04-c4-routes-6-7-scoping.md`.
**7 — pickup / parent / delete.** ~300-490 lines, one slice, **must not be
split**. Retail performs NO placement here (`DoPickupEvent` @0x00452240 =
`unset_parent` + `leave_world`; `DoParentEvent` @0x00452290 = `set_parent` +
`SetPlacementFrame`), so it **inverts 4b-2's rule: never arm `ConstrainTo`**.
The real defect: a parented child's canonical cell has two writers, and acdream
re-cells it from a **render tick** (`EquippedChildRenderController.TickChild:408`),
so headless parented children stay cell-less forever.
**Blocker resolved** — `docs/research/2026-08-04-retail-child-cell-ownership.md`:
retail propagates via `enter_cell` @0x00510ed0 recursion **and** an explicit
depth-1 child loop in `SetPositionInternal` @0x0051539c-@0x005153d8. `set_parent`
@0x00515a90 contains **no** cell write. **The Runtime replacement must write the
child's cell at BOTH the `set_parent` analog AND the per-commit position
analog** — a `set_parent`-only write is correct at attach and stale on the
parent's first cell crossing.
**3 — portal (local player).** Last. Needs the
`RuntimeWorldTransitState` → `RuntimePortalPlacementAuthority` adapter, which
does not exist. #280 rides with it.
## Process rules learned the hard way this session
1. **The contract causes the defect.** Route 4b-2's round-1 freeze traced
directly to my contract saying "arm `ConstrainTo` on refusal" without saying
"and still advance the pose." Write what must remain true, not only what must
change.
2. **Split on discovery.** When a slice uncovers a defect outside its scope,
commit it separately *immediately*. 4b-2 carried a shared-core park defect
through three extra review rounds because it wasn't split.
3. **A green suite is not evidence.** This slice was green at 10,990 / 10,997 /
11,004 while containing real defects, twice including a permanently
invisible-and-intangible entity.
4. **Tests must assert the layer that broke.** #312 shipped because the park
restore's tests asserted `InWorld` / clock / residency — exactly the three
fields eight reviews had named — while presentation stayed torn down.
5. **A clean-looking live session is not a passed gate.** Confirm the code path
actually executed (probe line, counter), not just that nothing looked wrong.
6. **Stale comments are endemic** — six consecutive slices shipped comments
asserting behaviour the code no longer had, including inside the round meant
to end it. Verify every comment you touch against the code beside it, and
prefer symbol references to line numbers.
## Open, not blocking
- **#309** — largely superseded by #312; re-scope before running. What survives
is narrow: retail's `GotoLostCell` keeps a lost-cell object hidden until
`reenter_visibility`; acdream re-shows it on cancel.
- **#32 residuals** — `LeaveGround` chatter bound, the `!Ok` airborne latch, and
the `contact_allows_move` watch item (a remote lacking Contact|OnWalkable
silently loses action animations — the literal root cause of closed #270). If
a "missing attack/cast animation on flat ground" report appears, start there.
- **Diagnostic probes are still in the tree** and are marked TEMPORARY:
`ACDREAM_PROBE_REMOTE_LANDING`, `ACDREAM_PROBE_REMOTE_SLIDE`,
`ACDREAM_PROBE_PARK`. Strip as a family when the physics work settles.
## Connected-test recipes that worked
- **Far snap:** stand still; second character runs past ~100 m, stops, turns,
runs back. Three or four times.
- **Steep slide:** second character jumps onto a sloped roof.
- **Park:** move to a landblock not visited this session, have the remote arrive
while it is still streaming, have them take a step, then stand still.
- Graceful close matters — a hard kill leaves ACE holding the session ~3 minutes.