acdream/docs/research/2026-05-21-open-items-pickup-prompt.md
Erik 6d18d879a2 docs(milestones): promote indoor work to M1.5 — primary focus
Continued indoor testing through 2026-05-20 surfaced a deep family
of physics + lighting bugs that span buildings AND dungeons. Today's
session shipped 5 surgical fixes (A4 + #89 + #90 + #91 + #92) that
close the user-visible "walls walk through at Holtburg inn" symptom,
but #90 specifically is a CLAUDE.md-rules workaround (sphere-overlap
stickiness on top of point-only cell containment) added without prior
approval. The underlying issue (BSP push-back distance probably
diverges from retail) hasn't been measured. Plus the umbrella #83
(indoor multi-Z walking) has been open since 2026-05-19 with multiple
aborted fix attempts; plus indoor lighting (#80 + #81 + new #93 +
#94) has been deferred as "M7 polish" but is actually part of the
same indoor-experience problem.

Promoting to a milestone of its own forces the work to be central,
retail-anchored, and complete — not another whack-a-mole patch.

Milestone M1.5 — "Indoor world feels right":
  Demo: enter Holtburg Sewer through the in-town portal, navigate
  through 5-7 rooms with stairs + a multi-Z chamber, exit back to
  town. Walls block. Stairs work. Items block. Lighting reads
  correctly. Cell transitions smooth.

  Phases:
    A6 — Indoor physics fidelity (cdb-driven)
    A7 — Indoor lighting fidelity (RenderDoc + retail-decomp driven)

  Issues in scope: #80, #81, #83, #88, #90 (workaround removal),
  #93 (new lighting umbrella), #94 (held-item spotlight),
  + TryFindIndoorWalkablePlane synthesis removal.

M2 ("Kill a drudge") deferred until M1.5 lands.

This commit updates:
  - docs/plans/2026-05-12-milestones.md (M1.5 block inserted, M2 moved
    to deferred status)
  - docs/plans/2026-04-11-roadmap.md (A6 + A7 sub-pieces detailed)
  - CLAUDE.md (Currently working toward updated to M1.5, M2 paragraph
    marked deferred, M1.5 baseline shipped paragraph added)
  - docs/ISSUES.md (#80, #81, #83, #88, #90 tagged M1.5 scope;
    new #93 indoor lighting umbrella + #94 held-item spotlight filed)
  - docs/research/2026-05-21-open-items-pickup-prompt.md (landscape
    table reorganized around M1.5 phases)

A6 + A7 specs to be drafted in the next session(s).

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

14 KiB

Open items pickup prompt — 2026-05-21 session aftermath

After the 2026-05-21 collision-fix session, six discrete items remain. This doc gives a fresh session the full landscape: how the items relate, what depends on what, what order makes sense.

The pasteable session-start prompt is at the bottom of this doc.

The landscape at a glance (updated 2026-05-20 — MILESTONE PROMOTION)

Status as of end of 2026-05-20 session: the original 6-item landscape has been promoted to a milestone of its own — M1.5 "Indoor world feels right" — opened today. M2 ("Kill a drudge") is deferred until M1.5 lands. Today's session shipped a 5-fix M1.5 baseline (A4 + #89 + #90 workaround + #91 + #92) closing the user-visible "walls walk through at Holtburg inn" symptom; the proper root-cause fix (BSP push-back distance investigation + synthesis removal) is the actual M1.5 work.

# Item Domain M1.5 phase Status
A4 Multi-cell BSP iteration — walls in adjacent cells too Collision (baseline, shipped) CLOSED 2026-05-20
#89 Sphere-overlap in CheckBuildingTransit Collision (baseline, shipped) CLOSED 2026-05-20
#90 CellId ping-pong at doorway threshold (workaround in place) Collision — cell tracking A6.P4 (workaround removal) ⚠ WORKAROUND
#91 Indoor cell shadows in FindObjCollisions Collision (baseline, shipped) CLOSED 2026-05-20
#92 Server cell id at player-mode entry Cell tracking (baseline, shipped) CLOSED 2026-05-20
#83 Indoor multi-Z walking (cellars, 2nd floors) — UMBRELLA Physics A6.P1-P3 OPEN (M1.5 primary)
stairs Stairs walk-through + stuck-in-falling Physics A6.P1-P3 (subsumed by #83) OPEN
2nd-floor / cellar Multi-Z navigation Physics A6.P1-P3 (subsumed by #83) OPEN
TryFindIndoorWalkablePlane Per-frame CP synthesis (99.87% MISS) Physics — synthesis removal A6.P4 OPEN (workaround)
#88 Indoor static objects vibrate Physics — sub-step state A6 (suspected family) OPEN
#93 Indoor lighting broken (UMBRELLA — new) Lighting A7.L1-L3 OPEN (M1.5 primary)
#94 Held items project spotlight on walls (new) Lighting A7.L1-L3 OPEN
#80 Camera on 2nd floor goes dark Lighting A7.L1-L3 OPEN
#81 Static building stabs don't react to atmospheric lighting Lighting A7.L1-L3 OPEN
A2 PHSP inversion Collision math post-M1.5 (Low) OPEN

Two domains, one critical-path chain

The 6 items split cleanly:

Domain 1 — Collision (M2 critical path). A4, stairs, A2, A3. These block "kill a drudge" because dungeons have drudges and dungeons have walls/stairs/floors that need to behave correctly. The dependency chain is:

                  A4 (multi-cell iteration)
                       │
            ┌──────────┴──────────┐
            ▼                     ▼
        stairs (verify          A3 (remove
        post-A4)                synthesis,
                                relies on
                                A4 retention)
                                     ▲
                                     │
                                 A2 (PHSP fix
                                 — also useful
                                 standalone)

A4 is the biggest user-visible win and it unblocks A3. A2 is a small self-contained correctness fix that pairs naturally with A3. Stairs are likely an A4 side-effect.

Domain 2 — Rendering (M7 polish). L-indoor + L-spotlight. These don't affect gameplay correctness — the world just looks wrong. Different code paths (lighting, not physics), different files, different domain knowledge. Best tackled in their own session, ideally after collision is solid so the visual artifacts are easier to isolate.

Why this order

  1. A4 first. Biggest user-visible improvement. Closes the "vestibule cells don't block walls" gap by querying every cell the sphere overlaps, not just the one cell the player's center is in. Retail oracle: CTransition::check_other_cells at acclient_2013_pseudo_c.txt:272717-272798. Existing CellTransit.FindCellList already enumerates the right cells; A4 wires that into FindEnvCollisions. Probably 1-2 days.

  2. Verify stairs after A4. If A4 closes vestibule walls, it probably also closes stairs (same architectural gap — stairs span cells). If stairs still walk-through after A4, investigate per-cell physics-poly coverage for stair geometry as a separate sub-issue.

  3. A2. One-line flip in PolygonHitsSpherePrecise (BSPQuery.cs:117) plus a unit test for the tangent boundary. Improves correctness across every BSP query (walls, step-up, step-down). Pairs cleanly with A3.

  4. A3. Once A4 + A2 land, the architectural cleanup becomes safe. Delete TryFindIndoorWalkablePlane (TransitionTypes.cs:1294) and the synthesis call site. Retail's grounded path doesn't synthesize CP — it retains via Mechanisms A/B/C (already in our code at BSPQuery.cs:1615, TransitionTypes.cs:2618, TransitionTypes.cs:896). The 2026-05-20 session tried A3 prematurely (Bug A) and reverted because the doorway-exit case relied on multi-cell iteration that wasn't there. A4 closes that gap.

  5. Lighting (M7). Separate session. Different domain. Defer until M2 ships.

Per-item starter notes

A4 — multi-cell BSP iteration

Read first:

Approach:

  • Extract a "cell_array" set from the player's current cell via the existing CellTransit BFS.
  • Iterate each cell, run BSPQuery.FindCollisions against each one.
  • Combine results: any cell returning Collided/Adjusted halts; any cell returning Slid is remembered; all OK = return OK.

Acceptance: Walk into the Holtburg inn vestibule (cell 0xA9B40164). Walls in cell 0xA9B40157 should now block when the player's sphere extends into them, even though the player's center is still in the vestibule.

Stairs walk-through

Strategy: verification-only, after A4. Launch with the same probe set, walk up the inn stairs, watch the [indoor-bsp] results. If stair hits fire correctly, done. If not, investigate the cell's physics-poly data — stairs may be packed as static objects rather than cell-structure polys.

A2 — PHSP inversion fix

Bug: BSPQuery.cs:117 has if (MathF.Abs(dist) > rad) return false; — bails when sphere is FAR from plane. Retail's polygon_hits_sphere_slow_but_sure at acclient_2013_pseudo_c.txt:322509-322517 does the opposite — bails when sphere is OVERLAPPING plane.

Fix: flip the comparison. New unit test for the tangent boundary (sphere center at radius distance from plane → continue, not reject).

Caveat: doesn't fix walkable synthesis on its own — AdjustSphereToPlane also rejects at the tangent boundary (strict < check on interp). The two together gate the synthesis. Fixing A2 alone changes which side of the boundary the rejection happens on but doesn't close the gap. Pair with A3 for the full benefit.

Read first:

  • §"Phase A2" of docs/research/2026-05-21-collision-fixes-shipped-handoff.md
  • docs/research/2026-05-21-walk-miss-capture-findings.md (the smoking-gun analysis of the 2 cm boundary)

A3 — synthesis removal

Bug: retail's grounded path doesn't re-synthesize ContactPlane. It retains via three mechanisms (Path 4 land, LKCP proximity restore, post-OK step-down probe — all already in our code). Our TryFindIndoorWalkablePlane runs every frame and is unfaithful.

Fix: delete TryFindIndoorWalkablePlane (TransitionTypes.cs:1294) and its call site. ~500 lines deleted.

Critical prerequisite: A4 must ship first. The 2026-05-20 session tried A3 prematurely (Bug A) and reverted because doorway transitions caused free-fall — Mechanism C couldn't find a floor poly at the threshold because the indoor cell's BSP had no coverage past the doorway, and multi-cell iteration wasn't there to query the adjacent cell.

Read first:

  • docs/research/2026-05-20-indoor-walking-bug-a-handoff.md (Bug A's premise + reversion)
  • §"Phase A3" of the 2026-05-21 handoff

L-indoor — lighting broken inside

Symptom: lights inside buildings don't illuminate correctly.

Likely areas:

  • Cell-light association (which lights belong to which cell)
  • Light visibility culling (visible-cells set + light bounds)
  • Per-light projection matrix indoors

Domain: rendering, not physics. Separate session.

L-spotlight — items projecting spotlight on walls

Symptom: held items (torches, etc.) project spotlight effects onto walls in unexpected directions.

Likely areas:

  • Per-entity light direction transform
  • LightingHookSink owner-tracking

Domain: rendering, not physics. Separate session.

CLAUDE.md rules to remember

  1. Work-order autonomy. You pick what to work on. Recommended order above but adjust if you find something blocking.
  2. No workarounds, retail-faithful. Same rule that drove A1 through A1.7. If a fix starts to look like a band-aid, stop.
  3. Probe-first, design-second. Already have rich probes ([indoor-bsp], [cell-transit], [cell-cache], [walk-miss], [floor-polys], [resolve-bldg]). Capture before theorizing.
  4. Visual verification is the acceptance test. Walk the building after each fix.
  5. Stop signals. Three failed visual verifications in a session = write a handoff, don't push for a fourth.
  6. Don't enable ACDREAM_PROBE_RESOLVE for live play. It lagged the client last session (400k+ lines at 30 Hz).
  7. Subagent policy: Sonnet for implementers, Opus only for load-bearing review.
  8. Worktrees. Use the superpowers:using-git-worktrees skill to create a fresh worktree branched from main before touching code.

Launch command (light probes only)

$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_CELL           = "1"
$env:ACDREAM_PROBE_CELL_CACHE     = "1"
dotnet build -c Debug
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 |
    Tee-Object -FilePath "launch.log"

UTF-16LE → UTF-8 conversion for grep:

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

The pasteable session-start prompt

Open a new Claude Code session in the main acdream worktree (C:\Users\erikn\source\repos\acdream, branch main at SHA f80b537 or later). Then paste:


Pick up the acdream open-items cleanup. After the 2026-05-21 session,
6 items remain across collision + rendering.

1. Read docs/research/2026-05-21-open-items-pickup-prompt.md FIRST.
   It maps the 6 items, their dependencies, and the recommended
   order (A4 → verify-stairs → A2 → A3 → lighting in a separate
   session). Each item has its own "Read first" anchor list inside.

2. Branch state: main is at f80b537 with all 2026-05-21 fixes
   landed (A1, A1.5, A1.6, A1.7 + probe spike + handoff docs).
   Build green, 1129-test baseline holds, four user-visible
   improvements visually verified. Local main is ahead of
   origin/main (origin at 7034be9); push only if explicitly asked.

3. **Set up isolation FIRST.** Use the superpowers:using-git-worktrees
   skill to create a fresh worktree from main. Don't work directly
   in the parent worktree. The 2026-05-21 session's worktree
   (claude/lucid-goldberg-1ba520) is identical to main and can be
   removed.

4. Recommended first phase: **A4 (multi-cell BSP iteration)**. It
   has the biggest user-visible payoff (closes vestibule-cell wall
   walk-through, likely closes stairs too) and unblocks A3
   architectural cleanup. Retail oracle is at
   acclient_2013_pseudo_c.txt:272717-272798 (CTransition::check_other_cells).
   Existing CellTransit helpers (FindCellList, FindTransitCellsSphere,
   AddAllOutsideCells) already enumerate the right cells; A4's
   work is wiring them into Transition.FindEnvCollisions.

5. Use the superpowers:brainstorming skill before writing A4 code.
   A4 is a real architectural change (multi-day, 2 files modified +
   tests) and deserves its own spec + plan. Don't shortcut it.

6. CLAUDE.md rules:
   - No workarounds. Retail-faithful.
   - Probe-first, design-second.
   - Visual verification at Holtburg inn cell 0xA9B40164 vestibule
     is the A4 acceptance test (walls in adjacent cell 0xA9B40157
     should block when the player straddles the boundary).
   - Don't enable ACDREAM_PROBE_RESOLVE for live play (lags the
     client). Use [indoor-bsp] + [cell-transit] + [cell-cache] only.
   - Three failed visual verifications = handoff, not a fourth attempt.

7. M2 ("kill a drudge") is the active milestone. A4 + stair
   verification + A2 + A3 are all on the M2 critical path because
   dungeons need walkable indoor space. Lighting is M7 polish;
   defer.

8. Launch command (light probes only):
   $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_CELL           = "1"
   $env:ACDREAM_PROBE_CELL_CACHE     = "1"
   dotnet build -c Debug
   dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 |
       Tee-Object -FilePath "launch.log"

State the milestone + chosen phase in your first action.