docs(B.4c): ship handoff + close #58 + file #61 #62 + roadmap/CLAUDE update

Phase B.4c shipped end-to-end 2026-05-13. Holtburg inn doorway
double-click verified: door visually swings open, player walks
through, door visually swings closed.

4 implementation commits:
- B.4c Task 1: door spawn-time AnimationSequencer with state-seeded cycle
- B.4c Task 2: [door-cycle] diagnostic in OnLiveMotionUpdated
- B.4c Task 2 review: IsDoorName shared predicate + durable comment + UM locals
- B.4c stance fix: NonCombat = 0x3D (not 0x01); read spawn.MotionState

Closes #58. Files:
- #61 (AnimationSequencer link->cycle frame-0 flash; visible as brief
  flap at end of door swing; low-severity polish)
- #62 (PARTSDIAG null-guard for sequencer-driven entities; latent
  not currently reachable for doors)

Memory file project_interaction_pipeline.md updated outside the repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-14 07:50:36 +02:00
parent 454d88ed8e
commit ebdbf821dc
4 changed files with 470 additions and 40 deletions

View file

@ -46,6 +46,77 @@ Copy this block when adding a new issue:
# Active issues
## #62 — PARTSDIAG null-guard for sequencer-driven entities
**Status:** OPEN
**Severity:** LOW (latent crash; not reachable for doors today — see notes)
**Filed:** 2026-05-13 (code-quality review of B.4c Task 1)
**Component:** diagnostic / `GameWindow.TickAnimations` PARTSDIAG block
**Description:** The PARTSDIAG block at `GameWindow.cs:7657` reads
`ae.Animation.PartFrames.Count` without a null-guard. B.4c introduced
`Animation = null!` for sequencer-driven door entities (per the same
pattern at line 7857). Today this is safe: doors never enter
`_remoteDeadReckon` (ACE never sends UpdatePosition for them), and
`_remoteDeadReckon` membership is one of the outer guards on the
PARTSDIAG block. The diagnostic never fires for doors.
**Risk:** Future code that admits more non-creature entities via the
B.4c branch — or extends ACE to send UpdatePosition for doors — would
make `_remoteDeadReckon` membership reachable for null-Animation
entities. The next time someone enables `ACDREAM_REMOTE_VEL_DIAG=1`
and that scenario occurs, the diagnostic crashes the tick.
**Acceptance:** PARTSDIAG block tolerates null `ae.Animation`. One-line
fix:
```csharp
int animFrame0Parts = ae.Animation?.PartFrames.Count > 0
? ae.Animation.PartFrames[0].Frames.Count
: -1;
```
**Files:** `src/AcDream.App/Rendering/GameWindow.cs:7657` (one-line null-coalescing change).
**Estimated scope:** Trivial. One-line edit + a build verification.
---
## #61 — AnimationSequencer link→cycle boundary flash on one-shot motion (door swing)
**Status:** OPEN
**Severity:** LOW (visual polish — animation works, brief one-frame flash through prior pose at end of swing)
**Filed:** 2026-05-13 (visual test of B.4c)
**Component:** animation / `AcDream.Core.Physics.AnimationSequencer` link+cycle transition
**Description:** When a door receives `UpdateMotion(NonCombat, On)` via the
B.4c spawn-time-registered sequencer, the swing-open animation plays
correctly but exhibits a brief one-frame flash through the closed pose
at the END of the swing before settling at the open pose. Same flash on
close (settles at closed pose after one-frame flash through open).
**Root cause hypothesis:** `AnimationSequencer.SetCycle` enqueues a
transition link (the swing motion) followed by the target cycle (likely
a single-frame static rest pose). If the link's last frame and the
cycle's frame 0 don't match exactly, the renderer reads one frame of
the cycle's start pose before the cycle's natural rest. Cumulative
effect: link plays Closed→Open over N frames → cycle's frame 0 is
Closed → cycle resets to frame 0 for one render → cycle advances to
its single rest frame which IS the open pose. Visible as a flap.
**Acceptance:** Door open / close cycles play cleanly with no closed/open
pose flash at the link→cycle transition. Test: in Holtburg, double-click
inn door, watch swing animation rest at open pose with no intermediate flash.
**Files (likely):**
- `src/AcDream.Core/Physics/AnimationSequencer.cs` — link+cycle queue boundary handling
- (read the link node's last-frame extraction + the cycle's frame-0 evaluation)
**Estimated scope:** Moderate. Requires understanding the sequencer's link-vs-cycle queue semantics and possibly the underlying MotionTable's cycle data shape for doors. Could be a one-line fix (e.g. "preserve last link frame as cycle rest pose") or a deeper sequencer behavior change.
**Workaround:** None needed for M1 — the flash is brief enough that doors are usable.
---
## #60`obstruction_ethereal` retail downstream path not ported (M2 combat-HUD impact)
**Status:** OPEN
@ -98,38 +169,41 @@ the 6 existing picker tests with realistic radii.
---
## #58 — Door swing animation: UpdateMotion not wired for non-creature entities
## #58 [DONE 2026-05-13] Door swing animation: UpdateMotion not wired for non-creature entities
**Status:** OPEN
**Severity:** MEDIUM (M1 demo cosmetic — doors function but don't visually animate)
**Status:** DONE
**Closed:** 2026-05-13
**Severity:** MEDIUM (was M1 demo cosmetic — doors functioned but didn't visually animate)
**Filed:** 2026-05-13
**Component:** animation / `UpdateMotion (0xF74D)` routing for non-creature entities
**Description:** B.4b shipped end-to-end interaction (click → BuildUse →
SetState → collision exempt → walk through). When ACE opens a door it
broadcasts TWO packets: `SetState (0xF74B)` (the collision-bit flip,
handled by L.2g) AND `UpdateMotion (0xF74D)` with `(NonCombat, On)` (the
swing animation cycle, NOT handled). acdream's `UpdateMotion` pipeline is
currently scoped to player + creature animation (Phase L.3); door entities
do not receive cycle commands.
**Closure:** Closed by Phase B.4c on branch `claude/phase-b4c-door-anim`
(4 implementation commits). The complete animation round-trip for door entities
is now wired and visual-verified at the Holtburg inn doorway: double-click a
closed door → swing-open animation plays → player walks through → ~30s later
ACE broadcasts `UpdateMotion (NonCombat, Off)` → swing-close animation plays.
**Root cause / status:** The `UpdateMotion` packet handler in
`GameWindow.OnLiveMotionUpdated` filters to player + creature entity types.
Non-creature WorldEntity instances (doors, chests, etc.) silently drop
the `(NonCombat, On)` cycle command that ACE sends when the door opens.
Implementation: spawn-time `AnimationSequencer` registration for door entities
in `GameWindow.OnLiveEntitySpawnedLocked` (Task 1, commit `9053860`), with
initial state seeded from `spawn.PhysicsState` so closed doors initialize to
the `Off` cycle and open doors initialize to the `On` cycle. A `[door-cycle]`
diagnostic line in `OnLiveMotionUpdated` (Task 2, commit `b89f004`) confirms
each `UpdateMotion` is processed. A shared `IsDoorName` predicate (Task 2
review, commit `8a9b15e`) eliminates duplication. A stance-value fix (bonus,
commit `454d88e`) corrected `NonCombat = 0x3D` (not `0x01`), which was causing
doors to render halfway underground due to empty sequencer frames.
**Files (likely):**
- `src/AcDream.App/Rendering/GameWindow.cs``OnLiveMotionUpdated` handler
- `src/AcDream.Core/Physics/AnimationSequencer.cs` — may have creature-specific assumptions
- The entity-spawn adapter (unknown if non-creature entities are wired to an AnimationSequencer at all)
Two follow-up items were filed: issue #61 (link→cycle boundary flash — brief
visual flap at end of swing animation; low severity) and issue #62 (PARTSDIAG
null-guard for sequencer-driven entities; latent, not currently reachable).
**Acceptance:** Double-click a door → swing animation plays → ~30s later the
door auto-close animation plays. Log shows `UpdateMotion (NonCombat, On)` processed
for the door entity.
See [`docs/research/2026-05-13-b4c-shipped-handoff.md`](research/2026-05-13-b4c-shipped-handoff.md)
for the full evidence trail, log output, and bonus-discovery narrative. M1
demo target "open the inn door" now has full visual feedback.
**Estimated scope:** Unknown. Could be quick (route UpdateMotion to non-creature
WorldEntity with cycle dispatch, ~30 min) or moderate (AnimationSequencer audit
for creature-specific assumptions, ~2 hrs). Spike before committing to estimate.
**Files (what shipped):**
- `src/AcDream.App/Rendering/GameWindow.cs``IsDoorSpawn` / `IsDoorName` helpers, spawn-time `AnimationSequencer` registration branch in `OnLiveEntitySpawnedLocked`, `_doorSequencers` dict, `[door-cycle]` diagnostic in `OnLiveMotionUpdated`, `TickAnimations` loop extended to advance door sequencers.
- `src/AcDream.Core/Physics/AnimationSequencer.cs` — no changes required; existing link+cycle API was sufficient.
---