acdream/docs/research/2026-05-21-indoor-walking-doorway-investigation-prompt.md
Erik d258334573 docs(handoff): pickup prompt for indoor walking doorway investigation
Companion to the Bug A wrong-scope handoff (35c266a). Provides the
boxed copy-paste prompt for a fresh session + quick reference for the
user and the helper:
- Branch state + KEEP/REMOVE recommendation
- Anti-patterns to avoid (don't repeat Bug A, validate risks with
  probe data, stop at three failed verifications)
- Code anchors for Mechanisms A/B/C in our code
- Retail decomp anchors for the doorway investigation
- Probe + diagnostic env var menu
- 5-scenario visual verification list
- Launch command with UTF-8 conversion step

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

11 KiB

Indoor walking — doorway-edge investigation pickup prompt

Status: Bug B shipped today (de8ffde) — indoor BSP world-origin fix. Bug A attempted + reverted (9f874f40a7ce8f). Real bug is deeper than scoped: indoor cell floor polys don't cover the player's full XY range when crossing thresholds. ISSUES #83 stays OPEN.

This doc is the start-of-session brief for whoever picks up next.


What's on the branch (claude/sad-aryabhata-2d2479)

10 commits ahead of main. See docs/research/2026-05-20-indoor-walking-bug-a-handoff.md for the full table with KEEP/REMOVE recommendations.

Shippable to main alone: Bug B fix at de8ffde (closes corruption, has tests). The probe at 66de00d is invaluable and should stay.

Reverted-but-documented: Bug A spec/plan/fix/revert. Useful as a "tried this, didn't work, here's why" record. Can clean up later.


How to start a fresh session

Copy the block below into a fresh Claude Code session in this repo (or paste any subset — the boxed prompt is the meat):


Pick up the acdream indoor walking issue (ISSUES #83). The prior session
on 2026-05-20 shipped Bug B (BSP world-origin fix, de8ffde) but its
attempted Bug A (delete TryFindIndoorWalkablePlane) caused a worse
regression (fell through ground at doorways) and was reverted.

1. Read docs/research/2026-05-20-indoor-walking-bug-a-handoff.md FIRST.
   It's comprehensive: what shipped, what failed, the probe evidence,
   the deeper diagnosis (cell-geometry, not CP retention), and 5
   prioritized investigation targets. The "Investigation targets for
   next session" section is the entry point.

2. The current state of the branch is self-consistent post-Bug-B:
   world-origin fix shipped, Phase 2 synthesis (TryFindIndoorWalkablePlane)
   reinstated as it was before today's session. Indoor walking still
   glitches (stuck-falling when brushing upper-floor edges) but doesn't
   drop people into the void — that was Bug A's specific regression.

3. Bug A's premise was WRONG. Don't repeat it. "Just delete the
   synthesis and trust BSP retention" doesn't work because:
     - We already have all three retail CP retention mechanisms
       (A: Path 6 land, B: LKCP proximity restore, C: post-OK step-down
       probe). They're at BSPQuery.cs:1615, TransitionTypes.cs:2618,
       TransitionTypes.cs:896 respectively.
     - The actual failure mode is: at doorway thresholds, the indoor
       cell's BSP has NO floor poly under the player's new XY. The
       step-down probe (Mechanism C) fires correctly but finds nothing.
       Step-down returns OK without writing CP. Mechanism B's
       proximity check fails because the player moved laterally.
       oi.Contact clears. Player free-falls.

4. The investigation priority (per the handoff):
   a) PROBE/CDB FIRST. Attach Windows cdb to a live retail acclient
      (CLAUDE.md "Retail debugger toolchain" section). Set a breakpoint
      at BSPLEAF::find_walkable + BSPTREE::find_collisions. Walk the
      SAME Holtburg cottage threshold the failed Bug A run captured.
      Watch what retail's BSP iterates over. The answer is one of:
      - retail's cell has more floor polys (our dat-decoder bug);
      - retail's cell-id changes before the sphere reaches the edge
        (our cell-transition timing lag);
      - retail uses a portal-traversal mechanism we haven't ported.

   b) Cross-reference WorldBuilder's EnvCellRenderManager and
      PortalRenderManager to see how WB handles indoor cell boundaries
      at thresholds.

   c) Add a one-shot [cell-floor-coverage] probe that, when an indoor
      cell is loaded, dumps the cell's floor poly count + their XY
      bounding boxes. Then compare to the player's XY when step-down
      misses. This isolates "no floor poly here" from "wrong floor
      poly picked".

5. CLAUDE.md rules apply, especially:
   - No workarounds or band-aids. Find the root cause.
   - Probe-first, design-second. Don't ship a fix until probe data
     validates the hypothesis. (Bug A failed because I skipped this
     step for the R1 risk.)
   - Visual verification is the acceptance test.
   - Three failed visual verifications in a session = stop signal.
     Write a handoff, don't push for a fourth.
   - For investigation/audit requests, use the /investigate skill
     (REPORT-ONLY mode) before touching code.

6. Launch command (same as before — both probes on, log to UTF-8 after):
   $env:ACDREAM_PROBE_INDOOR_BSP    = "1"
   $env:ACDREAM_PROBE_CONTACT_PLANE = "1"
   $env:ACDREAM_DEVTOOLS            = "1"
   dotnet build -c Debug
   dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 |
     Tee-Object -FilePath "launch-doorway.log"
   # Convert to UTF-8 after:
   Get-Content launch-doorway.log -Encoding Unicode |
     Out-File launch-doorway.utf8.log -Encoding utf8

7. M2 ("kill a drudge") is the active milestone. Indoor walking is on
   the M2 critical path because dungeons have drudges, but it's
   unscoped how many phases this investigation will burn. If this looks
   like 3+ phases, consider asking the user whether to pivot to other
   M2 work (F.2 / F.3 / F.5a / L.1c / L.1b) and defer indoor walking
   to M7 polish.

State the milestone + chosen phase in your first action.

Quick reference for the user

To start the new session: open a fresh Claude Code in the acdream worktree and paste the boxed prompt above. Or just say:

"Read docs/research/2026-05-21-indoor-walking-doorway-investigation-prompt.md and start on the next phase."

Key files for the helper

Handoff (read first):

Specs/plans on the branch (for context, don't re-execute Bug A):

Code anchors (Mechanisms A/B/C in our code):

  • src/AcDream.Core/Physics/BSPQuery.cs:1615 — Mechanism A: Path 4 land + set_contact_plane.
  • src/AcDream.Core/Physics/TransitionTypes.cs:2618-2662 — Mechanism B: LKCP proximity restore.
  • src/AcDream.Core/Physics/TransitionTypes.cs:896-933 — Mechanism C: post-OK step-down probe.
  • src/AcDream.Core/Physics/TransitionTypes.cs:1442 — Bug B fix site (Matrix4x4.Decompose + worldOrigin pass).
  • src/AcDream.Core/Physics/TransitionTypes.cs:1294TryFindIndoorWalkablePlane (the duct-tape Bug A wanted to delete).
  • src/AcDream.Core/Physics/PhysicsDiagnostics.cs[cp-write], [indoor-bsp], [indoor-walkable] probe gates.

Retail decomp anchors:

  • acclient_2013_pseudo_c.txt:323725-323939BSPTREE::find_collisions full body.
  • :323924set_contact_plane write in Path 6 collide-path land.
  • :323565-323579BSPTREE::step_sphere_up.
  • :323665-323721BSPTREE::step_sphere_down (directly writes contact_plane_valid = 1 at :323711).
  • :326211 / :326793BSPNODE::find_walkable + BSPLEAF::find_walkable.
  • :323006-323028CPolygon::walkable_hits_sphere (the slope filter + overlap test).
  • :272565-272578validate_transition LKCP proximity restore (Mechanism B in retail).
  • :273242-273307transitional_insert post-OK step-down probe (Mechanism C in retail).
  • :276183init_contact_plane (the seed equivalent of our PhysicsEngine.cs:583).

Probe + diagnostic env vars:

  • ACDREAM_PROBE_INDOOR_BSP=1 — one [indoor-bsp] line per indoor cell BSP query.
  • ACDREAM_PROBE_CONTACT_PLANE=1 — one [cp-write] line per CP/LKCP field mutation.
  • ACDREAM_PROBE_CELL=1 — one [cell-transit] line per PlayerMovementController.CellId change.
  • ACDREAM_PROBE_BUILDING=1[resolve-bldg] lines for building BSP collision attribution.

Visual verification scenarios (re-use for the next phase)

The same 5 scenarios from today, in order of severity:

  1. Cottage entry (outdoor → indoor) — should be smooth.
  2. Cottage exit (indoor → outdoor through the same doorway) — should NOT cause fall-through-ground. This is the regression Bug A introduced.
  3. 2nd-floor walking — should NOT get stuck in falling animation when brushing upper-floor edges. The original symptom we set out to fix.
  4. Cellar descent — walk down stairs into a cellar. Should descend smoothly.
  5. Single-floor cottage walk (regression check) — confirm M1 baseline holds.

Acceptance: at minimum, scenarios 1 + 2 + 5 work (no fall-through-ground). Scenarios 3 + 4 are the M2-blocking targets.


Anti-patterns to avoid (carry forward from today)

  1. Don't re-attempt Bug A. "Just delete the synthesis" doesn't work — the BSP genuinely has no floor poly past doorway thresholds. Some replacement is needed; what replacement is the open question.

  2. Don't trust the previous handoff's recommendation blindly. The 2026-05-19 handoff said "delete TryFindIndoorWalkablePlane"; that recommendation was based on incomplete decomp analysis. Validate hypotheses against probe data BEFORE designing.

  3. Don't fix two related bugs in one phase. Bug B + Bug A were both indoor-CP issues but had different root causes. Slicing them was the right call; the failure was Bug A's design.

  4. Don't skip a probe spike when a risk is flagged in the spec. Bug A's R1 risk ("flat floor, no step-down momentary airborne") was the actual failure mode. A small probe spike to validate "will Mechanism C catch it?" before deleting the synthesis would have surfaced this.

  5. Stop at three failed visual verifications. Today: stuck-falling (Bug B verification, pre-Bug-A) → can't exit building (Bug A first run) → fell through ground (Bug A second run). The third should have been the trigger to revert + handoff, not "let's gather more data".


Launch command (with probes)

$env:ACDREAM_DAT_DIR   = "$env:USERPROFILE\Documents\Asheron's Call"
$env:ACDREAM_LIVE      = "1"
$env:ACDREAM_TEST_HOST = "127.0.0.1"
$env:ACDREAM_TEST_PORT = "9000"
$env:ACDREAM_TEST_USER = "testaccount"
$env:ACDREAM_TEST_PASS = "testpassword"
$env:ACDREAM_DEVTOOLS  = "1"
$env:ACDREAM_PROBE_INDOOR_BSP    = "1"
$env:ACDREAM_PROBE_CONTACT_PLANE = "1"
dotnet build -c Debug
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 |
    Tee-Object -FilePath "launch-doorway.log"

After the client closes, convert the UTF-16LE log to UTF-8 before grepping:

Get-Content launch-doorway.log -Encoding Unicode |
    Out-File launch-doorway.utf8.log -Encoding utf8

Then grep against launch-doorway.utf8.log from Bash.