acdream/docs/research/2026-05-24-door-collision-session-end-handoff.md
Erik 6a2c432e5a docs(handoff): door collision session end — honest accounting
Replaces the puffed-up framing in the prior task7-shipped handoff.
Honest summary: no user-visible bug fixed this session. Off-center
and inside-out door walk-through still 100% reproducible. The 4
commits shipped real infrastructure (multi-part registration + the
GetNearbyObjects dedup fix that would have silently broken any
future multi-part feature) but no observed behavioral change.

Also explicitly retracts the "step-up is the bug" hypothesis from
the prior handoff doc — ACDREAM_DUMP_STEPUP=1 in the apparatus
produced no stepup: ENTER lines, so DoStepUp wasn't even being
called. That hypothesis was over-reach from an inference I should
not have inflated to a conclusion.

Recommends the apparatus-replay pattern (same one that closed issue
#98 after 6+ speculation rounds): live capture via
ACDREAM_CAPTURE_RESOLVE → harness replay test → first per-field
divergence names the broken assumption.

DO-NOT list for the next session: do not redo the multi-part work,
do not speculate-and-fix, do not relaunch with more probes hoping
for an obvious signal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:52:53 +02:00

188 lines
8.4 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.

# Door collision — end-of-session handoff (2026-05-24, late)
**Branch:** `claude/strange-albattani-3fc83c`
**Worktree:** `C:\Users\erikn\source\repos\acdream\.claude\worktrees\strange-albattani-3fc83c`
## TL;DR — what was actually accomplished
**No user-visible bug was fixed this session.** The door bug the user
reported at the start (center blocks, off-center walks through,
inside-out walks through) is **identically reproducible after the
4 commits** as it was before them.
What changed: infrastructure. Server-spawned doors now register
multi-part shadow shapes (cylinder + BSP slab) instead of one
cylinder approximation. The BSP slab is queried 135 times per door
near approach but produces **zero collision hits**, so observed
behavior is unchanged.
**Don't re-do the infrastructure.** It's correctly built and necessary
for any future fix. The remaining work is downstream of it.
## Commits landed (4)
```
163a1f0 diag(phys): [bsp-test] probe + grounded apparatus test + handoff
ca9341c feat(phys): A6.P4 Task 7 — RegisterLiveEntityCollision uses ShadowShapeBuilder + RegisterMultiPart
3b7dc46 fix(phys): GetNearbyObjects dedup-by-entityId silently drops multi-part shadows
e1d94d7 test(phys): door setup + GfxObj dat-inspection — Hypothesis A falsified
```
**Real-but-latent value from these:**
- The dedup-by-entityId issue (3b7dc46) was a latent footgun: any
future attempt at multi-part shadows (NPCs with hit-region capsules,
multi-part creatures, props with separated collision) would have
silently dropped all but the first shape. Now safe.
- The dat-inspection (e1d94d7) proved part 0 (`0x010044B5`) has a
real 1.9×0.26×2.5 m BSP slab in the dat. A future fix doesn't have
to question whether the data exists.
- The Task 7 wiring (ca9341c) puts the right architecture in place —
doors now register the shapes retail expects (cyl per CylSphere +
cyl per Sphere + BSP per Part-with-BSP).
- The `[bsp-test]` probe (163a1f0) fires before the cache lookup,
distinguishing "cache miss → silent skip" from "queried but no
hit" — neither of which `[resolve-bldg]` ever showed.
**Brutally clear: zero of these commits change observed door behavior.**
## What we now know vs. what we don't
### Known (from this session's probes)
- `0x010044B5` PhysicsBSP has 6 collision-bearing polygons forming a
1.925 × 0.261 × 2.490 m door slab. All `SidesType=Landblock`
(two-sided). Bounding sphere radius 1.975 m. Verified by direct
dat read.
- `0x010044B6` (the two leaf parts) have `HasPhysics=false`,
`PhysicsBSP=null`, `PhysicsPolygons.Count=0`. Visual-only by retail
design — our skip matches retail's
`CPhysicsPart::find_obj_collisions:275051`.
- Live Holtburg doors register with `shapes=cyl1+bsp1`. Cache is
populated. BSP entries are visited (135x for one door at player
approaches as close as 0.42 m).
- The BSP traversal produces ZERO attributed hits during live walking
(all 19 `[resolve-bldg]` lines show `gfxObj=0x00000000`, which is
the Cylinder shape). Whatever is happening inside
`SphereIntersectsPolyInternal` or the dispatch around it is
swallowing the hit silently.
### NOT known (don't speculate further)
- **Whether `DoStepUp` is involved.** The prior handoff doc
(`2026-05-24-door-collision-task7-shipped-but-bug-remains.md`)
asserted "step-up incorrectly succeeds" as the leading hypothesis.
That was over-reach. In the apparatus, `ACDREAM_DUMP_STEPUP=1`
produced no `stepup: ENTER` lines — `DoStepUp` was never called.
So the apparatus shows `hit=yes n=(0,0,1)` from some OTHER path
(terrain step-down? walkable poly preservation?). It does not
confirm step-up is the production bug.
- **Whether the production hit happens at the BSP polygon edge test,
the BSP node traversal, or some other layer.**
- **Whether the production code path is the same as the apparatus
path 5 in the first place.**
The earlier framing of "step-up is the bug" was a guess I inflated
into a conclusion. Treat it as a candidate, not a finding.
## Proper next move
**Same pattern that closed issue #98 after 6+ failed speculation rounds:
live capture + apparatus replay.**
The infrastructure for this already exists in the codebase:
1. `ACDREAM_CAPTURE_RESOLVE=<path>` env var (see
`src/AcDream.Core/Physics/PhysicsResolveCapture.cs`) captures every
player-side `PhysicsEngine.ResolveWithTransition` call as a JSON
Lines record with full `PhysicsBody` before-and-after snapshots.
2. `CellarUpTrajectoryReplayTests.LoadCapturedRecord` +
`AssertCallMatchesCapture` replay a captured record through a
harness engine and emit the first per-field divergence between
live and harness outputs.
The plan:
1. Launch with `ACDREAM_CAPTURE_RESOLVE=door-walkthrough.jsonl`
(no other probes — capture is independent).
2. Walk into a closed Holtburg cottage door 50 cm off-center.
3. Close gracefully. Save the JSONL.
4. Write a new test `LiveCompare_DoorOffCenterWalkthrough` that loads
the failing-tick record and replays it through a harness with the
real `0x010044B5` BSP hydrated + registered via
`RegisterMultiPart`. Compare per-field.
5. The first divergent field names the broken assumption. Fix that.
This is concrete, deterministic, and doesn't ask you to relaunch
multiple times for each fix attempt. The harness round-trip is <500
ms; a fix iteration is ~3 seconds.
## What NOT to do
1. **Do NOT re-do the multi-part registration.** It's correct. The
dedup fix is correct. Task 7 is correct. Verified by 53/53 tests
in the targeted scope.
2. **Do NOT speculate-and-fix.** This session burned cycles on a
"step-up is the bug" hypothesis that wasn't supported by the
evidence. The apparatus-first rule (`feedback_apparatus_for_physics_bugs.md`)
exists for exactly this. Build the apparatus before the fix.
3. **Do NOT re-investigate whether the door has BSP polygons.**
It does. 6 of them. Forming a full door slab. Cached. Visited.
4. **Do NOT relaunch with more probes hoping for an obvious signal.**
The probes we have already say "BSP visited 135 times, no hits."
More log lines won't tell us WHY it doesn't hit. The apparatus
replay will.
## Files to read first
- This doc (you're in it).
- `docs/research/2026-05-24-door-dat-inspection-findings.md` the
dat data, polygon layout, bounding sphere center vs frame offset.
- `docs/research/2026-05-24-door-collision-task7-shipped-but-bug-remains.md`
the prior end-of-session handoff. **Read with skepticism** its
"leading hypothesis" section overstates confidence in the step-up
theory (corrected here).
- `tests/AcDream.Core.Tests/Physics/CellarUpTrajectoryReplayTests.cs`
the capture+replay pattern to mirror for the door bug. See
`LiveCompare_*` tests.
## State of the M1.5 milestone
Doors at Holtburg cottages: center blocks, off-center walks through,
inside-out walks through. Same as it was 24 hours ago. The walking-
through case is the actual user pain point. Until the apparatus
replay names the divergence, treat M1.5 indoor-world as still
incomplete on the door front.
The infrastructure is in place for the eventual fix. The fix itself
remains future work.
## Pickup prompt for the next session
```
Door collision investigation. Previous session shipped infrastructure
(multi-part registration + GetNearbyObjects dedup fix) but did NOT fix
the user-visible bug: off-center / inside-out approaches still walk
through closed Holtburg cottage doors.
Read docs/research/2026-05-24-door-collision-session-end-handoff.md
State both altitudes:
Currently working toward: M1.5 — Indoor world feels right
Current phase: A6.P4 door bug — apparatus replay phase.
Multi-part registration shipped; need live capture
+ per-field divergence comparison to identify why
the door's BSP slab fires zero attributed hits
despite being visited 135x per approach.
First move: launch the client with ACDREAM_CAPTURE_RESOLVE=<path>,
walk into a closed Holtburg cottage door 50 cm off-center, close
gracefully. Then write a LiveCompare_* test in CellarUpTrajectoryReplayTests
that loads the captured failing tick + replays through a harness
with the door BSP hydrated via the existing 0x010044B5 dat read
pattern and registered via RegisterMultiPart.
DO NOT redo the multi-part registration. DO NOT speculate about
step-up without evidence — the apparatus tested DoStepUp and it
didn't fire. The bug is upstream of step-up. The replay will name
the actual divergence.
```