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>
188 lines
8.4 KiB
Markdown
188 lines
8.4 KiB
Markdown
# 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.
|
||
```
|