acdream/docs/research/2026-07-03-r4-verify-session-handoff.md
Erik 304327b0a4 docs: R2-R4 visual pass PASSED (user-verified) - file #165 wall-swallow + #166 slope-landing sled; next entry R5
All four visual-pass items confirmed by the user's eyes (jump/ledge
momentum, run-in-circles blend, stop settle, retail-observer view of
+Acdream). Two observations filed from the pass:

- #165: retail movers observed from acdream penetrate walls a bit
  ("swallowed") instead of stopping flush - remote-DR collision class,
  PROBE_RESOLVE capture is the first investigative step.
- #166: downhill-jump landing glide+bounce (retail sled) absent - the
  register predicted this exact gap (AD-25 risk column) - composite of
  AD-25 + AP-7 + TS-4, retire together post-R6 per the user's
  "polish later" call.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 17:59:45 +02:00

103 lines
8.2 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.

# R4 live-verify session handoff — fresh-session entry point (2026-07-03, evening)
Successor to `2026-07-03-phase-r-session-handoff.md` (whose postscripts
summarize the same arc — this doc is the current entry point). Worktree
`vigorous-joliot-f0c3ad`, branch `claude/vigorous-joliot-f0c3ad`, tree CLEAN
at `3c866f95`. Full suite green: **3,963** (+15 since the R4 handoff).
## State
**R4 is SHIPPED and user-verified live** (V0V6 + five root-cause fixes the
live pass exposed). Confirmed working by the user's eyes: local use-walk
(turn-first, walk/run by distance, arrival, door opens once), door open +
door SWING animation, remote (retail-client) close-range moveto walking,
and remote run-distance movetos at correct animation pace AND speed (#160).
## The five live fixes (trail, newest first — each is a real mechanism, no adaptations added)
| Commit | Root cause fixed |
|---|---|
| `41006e79` | **#160 slow-motion remote runs**: remote interps had NO weenie → retail's `apply_run_to_command` rate chain (`weenie ? (InqRunRate() ?: my_run_rate) : 1.0`, raw 305062-305076) took the degenerate 1.0 branch; the wire's `MoveToRunRate` (stored in `MyRunRate` by the mt-6/7 unpack, M13) was never consumed. Fix: `RemoteWeenie` (Core) — retail's per-object ACCWeenieObject stand-in; `InqRunRate` FAILS → `my_run_rate` fallback; `IsThePlayer`=false ends the "null weenie counts as the player" A3 reading. |
| `350fb5e3` | **Door-swing snap** (register TS-40): CMotionInterp's detached-object link-strip guard (`physics_obj->cell == 0`, raw @305627) was proxied by `CellPosition.ObjCellId==0`, seeded only by the local player's `SnapToCell` → every REMOTE body read "detached" and every dispatched transition link was stripped same-tick. Fix: explicit `PhysicsBody.InWorld` set by SnapToCell + RemoteMotion construction. |
| `006cf659` | **Remote-player glide (partial)** + **door UMs dropped**: (a) remote PLAYERS' MoveToManagers were never ticked (the V4 UseTime slot was NPC-only) — extracted `TickRemoteMoveTo`, now also in the grounded player-remote (L.3 M2) pipeline; (b) UP-less entities (doors) never got a RemoteMotion → since the S2b funnel cutover their UM motions were parsed and dropped — rm now created on first UM, with a `LastServerPosTime>0` gate keeping UP-less bodies OUT of the dead-reckoning tick. |
| `24569fd2` | **Moveto stall #2**: login `SetPosition` ran before the DefaultSink bind in `EnterPlayerModeNow` → its StopCompletely A9 node had no completion partner → ONE immortal pending_motions node → wait-for-anims gate never opened. Fix: bind block moved above SetPosition; `LoginQueue_DrainsToEmpty_UnderProductionFeed` pins the invariant. |
| `c2dc1a88` | **Moveto stall #1 (the big one)**: the R3 port MISREAD `StopCompletely_Internal` (0x0050ead0) as a velocity zero — it is `CPartArray::StopCompletelyInternal` (0x00518890) = `MotionTableManager::PerformMovement(type 5)`, the ANIMATION-side stop whose UNCONDITIONALLY-queued entry is the matched pop for the A9 pending_motions node. Fix: `IInterpretedMotionSink.StopCompletely()` → the R2 manager's already-ported type-5 op. Also: retail's per-tick `CheckForCompletedMotions` slot (CPartArray::HandleMovement 0x00517d60) added to the controller tick, and the P1 autonomous-STORE family completed (unpack store 00509730, input-edge stores DoMotion@00510030/StopMotion@005100e0, section-2 stops per-frame stamping, speculative install stores false). |
## The queue model (the load-bearing mental model — do not relearn)
`pending_motions` (interp) pops HEAD-ANY on each `MotionDone`; completions
come from the manager's `pending_animations` entries. **Every enqueue must
have a completion partner** (dispatch → manager entry). One orphan =
permanent ≥1 backlog (later completions just relabel it) = `MotionsPending`
true forever = `BeginTurnToHeading`'s verbatim wait-for-anims gate wedges
every moveto. Orphan producers found: StopCompletely-before-sink-bind and
the misread StopCompletely_Internal. The `[autowalk-gate]` probe prints the
whole gate state — it is how both wedges were pinned.
## OPEN — next session picks up here (full trails in docs/ISSUES.md)
1. ~~**#161 — remote jump landing stuck in the falling pose**~~ **CLOSED
2026-07-03 `b1cf0102`, user live-verified.** The prime suspect was
right; the mechanism was a BN decomp artifact: retail REWRITES the
apply pass's params word (raw 305778 smeared store, mask 0x37ff →
`ModifyInterpretedState=false`; ACE MotionInterp.cs:444-449 confirms),
so retail PRESERVES interpreted fwd through the fall and HitGround
re-dispatches it (the landing-link exit). Also: both landing blocks
cleared Gravity BEFORE `Motion.HitGround()` (whose verbatim state&0x400
gate then no-opped — fixed order, AP-81); K-fix17's SetCycle DID
execute but re-set the clobbered Falling command — both copies deleted.
NOTE: "HitGround raw @305949" below was a mislabel (that line is inside
`move_to_interpreted_state`; real HitGround = 0x00528ac0 →
`apply_current_movement(0,0)`). Full trail: ISSUES Recently-closed #161.
2. ~~**#162 — glide-class adjudication**~~ **CLOSED 2026-07-03, no
adaptation.** User A/B: retail does NOT glide (new-fact branch) — and
post-#161 acdream doesn't either (user-verified walk/run-by-distance +
clean mid-chain key takeover). Mechanism re-audit: head-interrupt +
CancelMoveTo ports are retail-verbatim (retail's observer ALSO loses
the armed moveto on the first reflection); ACE's mt-0 reflections carry
the mover's real locomotion, so the legs stay correct after any cancel.
The old glide was killed by the R4-V5 stack + #161's apply-pass params
fix. Full evidence: ISSUES Recently-closed #162.
3. ~~**#163 — strip the TEMPORARY diagnostics**~~ **DONE 2026-07-03**
(`[autowalk-gate]` + clock, `[autowalk-feed]`, and the short-lived
`[MOVETO-CANCEL]` probe; the durable ProbeAutoWalk family stays).
4. ~~Combined R2+R3+R4 visual-pass remainder~~ **PASSED 2026-07-03,
user-verified** (jump/ledge momentum, run-in-circles blend, stop
settle, retail-observer view of +Acdream — all four "looks good").
Two observations filed from the pass: **#165** (remote movers get
"swallowed" into walls a bit instead of stopping flush — remote-DR
collision, capture with PROBE_RESOLVE first) and **#166**
(slope-landing glide+bounce polish — the AD-25 + AP-7 + TS-4
composite, post-R6 by user's call). NEXT SESSION ENTERS AT **R5**
(MovementManager facade + StickyManager + ConstraintManager + full
TargetManager — retires TS-39 + AP-79's adapter).
## Session gotchas worth keeping
- **Evidence-first**: two plausible-but-wrong theories (a per-tick
apply_current_movement "pump" — retail's apply callers are EVENT-driven
only; and "ACE chain broadcasts mt-0 locomotion" — it doesn't) were
killed by the raw + wire captures. The `[autowalk-gate]` probe and the
UM raw hex dumps (autonomy byte at offset +14) were the decisive tools.
- **Retail object-model completeness matters**: two of the five fixes were
"retail gives every placed object X and we only gave it to the player"
(a weenie; a cell/InWorld). When a dispatch path behaves differently for
remotes, check what retail's CPhysicsObj carries that our RemoteMotion
lacks BEFORE suspecting the ported logic.
- The launch recipe + graceful-close rules are unchanged (CLAUDE.md); the
client locks builds — ask the user to close it, never kill.
- Register: TS-40 added; TS-33 extended (orientation-diff gap); AP-79
covers both tracker instances; TS-36/AD-26 retired earlier today.
## Key files this session touched
`MotionInterpreter.cs` (StopCompletely sink dispatch, InWorld guards),
`MoveToManager.cs` (MoveToComplete widened to BeginNextNode completion),
`MotionTableDispatchSink.cs` + `InterpretedMotionFunnel.cs`
(StopCompletely sink op), `PhysicsBody.cs` (InWorld), `RemoteWeenie.cs`
(new), `PlayerMovementController.cs` (UseTime slot + per-tick Check +
edge autonomy stores + temp probe), `GameWindow.cs` (P1 gate + store,
RouteServerMoveTo, TickRemoteMoveTo, rm-on-UM, EnterPlayerModeNow bind
order, player tracker feed), tests: `PlayerMoveToCutoverTests`,
`MoveToManagerCompletionSeamTests`, `InWorldLinkGuardTests`,
`RemoteWeenieRunRateTests`, `W6EdgeDrivenMovementTests` (apply-pass form).