ship(phys): A6.P3 slice 1 — Indoor ContactPlane retention COMPLETE

Slice 1 ships the strip-synthesis + Mechanism B (LKCP restore) fix
addressing A6.P2 Finding 2. Includes:

  - scen3_inn_2nd_floor_postfix paired capture (retail.log + decoded
    + acdream.log) as verification artifact. acdream cp-write count
    dropped from 86,748 to 25,082; per-unit-of-activity rate dropped
    63x (164.61 -> 2.60 cp-writes per cell-cache event).

  - Findings doc (docs/research/2026-05-21-a6-cdb-capture-findings.md)
    appended with slice 1 SHIPPED section: commit map, scen2/scen3
    pre/post comparison tables, user happy-test results, status of
    each A6.P2 finding (Finding 1 CLOSED as side-effect, Finding 2
    PARTIALLY CLOSED with remaining 99.3% from L622 seed flagged
    as #96, Finding 3 + #95 still open), slice 2 recommendation.

  - Issue #96 filed: "Per-tick PhysicsEngine.ResolveWithTransition CP
    seed contributes 99.3% of post-slice-1 CP writes." Slice 2 target.
    Sketch options: remove entirely / gate by change-detection / no-op
    guard inside SetContactPlane.

  - Issue #97 filed: "Phantom collisions + occasional fall-through on
    indoor 2nd floor." User-reported during happy-testing. HYPOTHESIS:
    side-effect of #96; falsifiable by re-testing post-slice-2.

  - CLAUDE.md updated: Currently-working-toward block now points at
    A6.P3 slice 2 (#96) as the active phase. M1.5 building/cellar
    demo half is ACHIEVABLE NOW (slice 1 unblocked the physics).

  - Roadmap updated: A6.P3 broken into 3 slices, slice 1 marked
    SHIPPED with commit history.

KEY USER-VISIBLE OUTCOME: stairs + cellar descent now WORK in acdream
(user happy-test confirmed walking up/down inn stairs multiple times,
walking down to cellar). A6.P2 Finding 1 (dispatcher entry frequency
mismatch) confirmed as secondary effect of Finding 2 — closed without
explicit Finding 1 work, as A6.P2 hypothesized.

REMAINING CONCERNS for slice 2 + future:
  - L622 per-tick seed (#96) still firing 24,906 times in scen3 postfix
  - Phantom collisions + fall-through on 2nd floor (#97)
  - See-through-walls indoors (#95, separate scope)
  - Indoor lighting broken (A7 scope)

Test suite: 1148 pass + 8 pre-existing fail (baseline maintained;
T3 IndoorContactPlaneRetentionTests adds the +1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-22 10:11:44 +02:00
parent 066568a711
commit f04ea90050
7 changed files with 127435 additions and 24 deletions

View file

@ -602,6 +602,68 @@ Retail oracle for cell-id hysteresis: `acclient_2013_pseudo_c.txt:308742-308783`
---
## #96 — Per-tick PhysicsEngine.ResolveWithTransition CP seed contributes 99.3% of post-slice-1 CP writes
**Status:** OPEN — **A6.P3 slice 2 target**
**Severity:** MEDIUM (functional code works; symptom is CP-write-rate mismatch vs retail; suspected cause of #97 phantom collisions)
**Filed:** 2026-05-21
**Component:** physics, ContactPlane retention
**Description:** After A6.P3 slice 1 (commits `5aba071` + `5f7722a` + `39fc037`) stripped the `TryFindIndoorWalkablePlane` synthesis path from `Transition.FindEnvCollisions` indoor branch, scen3 post-fix re-capture showed acdream still writes ContactPlane fields 25,082 times during a flat-floor walk — 24,906 of those (99.3%) come from `PhysicsEngine.ResolveWithTransition` line 622, which seeds `ci.ContactPlane` from `body.ContactPlane` at every transition start when the body is grounded. Retail's equivalent code path fires `set_contact_plane` zero times during the same flat-floor walk (scen3 retail BP7 = 0).
**Root cause / status:** The L622 seed is per-tick infrastructure (every transition tick that's grounded), writing the same plane value repeatedly. Retail does NOT seed `ci.ContactPlane` at transition start — it relies on Mechanism A (Path-6 land write inside `BSPQuery.FindCollisions`) and Mechanism B (LKCP restore inside `validate_transition`, ported in slice 1 commit `5aba071`) to populate `ci.ContactPlane` only when needed.
The L622 seed comment claims it preserves slope-walking continuity. Need to verify whether removing it (relying on Mechanism B for cross-tick CP propagation) breaks slope walking, or whether the seed is redundant infrastructure left over from before Mechanism B existed.
**Fix sketch (slice 2 candidates):**
- Option A: Remove the L622 seed entirely. Rely on Mechanism A + Mechanism B for CP propagation. Verify slope walking still works (uphill/downhill, walking up stairs).
- Option B: Gate the L622 seed to fire only when `body.ContactPlane` has changed since last seed (track last-seeded plane). Most ticks would skip writes.
- Option C: Hybrid — keep the seed but route it through a no-op-if-unchanged guard inside `CollisionInfo.SetContactPlane` itself (also applies to all other call sites).
**Evidence (committed):**
- `docs/research/2026-05-21-a6-captures/scen3_inn_2nd_floor_postfix/acdream.log` — shows 24,906 cp-write entries with `caller=PhysicsEngine.ResolveWithTransition:622`.
- A6.P2 findings doc: per-unit-of-activity CP-write rate dropped 63× from slice 1 strip, but absolute count remains high.
**Files:**
- `src/AcDream.Core/Physics/PhysicsEngine.cs:622` (the seed call site)
- `src/AcDream.Core/Physics/TransitionTypes.cs:251-270` (`CollisionInfo.SetContactPlane` — candidate for no-op-if-unchanged guard, Option C)
**Acceptance:** scen3 re-capture shows acdream cp-write count ≤ 100 (matching retail's BP7 ~0 with small tolerance for legitimate Mechanism A/B fires). Slope walking + stair-climb + cellar descent still work in visual verification.
---
## #97 — Phantom collisions + occasional fall-through on indoor 2nd floor (post-slice-1 happy-testing)
**Status:** OPEN — **investigate after issue #96 lands** (hypothesized to be a side-effect)
**Severity:** MEDIUM (intermittent; doesn't block stair-walking which works post-slice-1)
**Filed:** 2026-05-21
**Component:** physics, ContactPlane stability
**Description:** During user happy-testing post-A6.P3 slice 1 (2026-05-21), walking on the inn 2nd floor in acdream produced:
- Intermittent "phantom collisions" — hitting invisible barriers in open floor space.
- One observed "fall-through the floor" — character dropped through the 2nd floor at a specific spot.
These are NOT the indoor stair-climb or cellar-descent symptoms (those WORK post-slice-1). They appear during normal flat-floor walking.
**Root cause / status:** Hypothesis: caused by issue #96 (L622 per-tick CP seed). The seed writes `ci.ContactPlane` every tick from `body.ContactPlane`, which may carry stale values across cell transitions or after the BSP didn't land a fresh plane. If a transient `ci.ContactPlane` value points to a plane that doesn't match the actual current floor geometry, `ValidateWalkable` (called from the outdoor terrain fallback) or downstream physics may briefly believe the player is below the floor → fall-through; OR may believe a wall is present where there isn't one → phantom collision.
Falsifiable: if #96 fix closes #97 as a side-effect, the hypothesis is confirmed. If #97 persists post-#96, deeper investigation needed (possibly cell-resolver stickiness — Finding 3 family).
**Reproduction (informal — needs sharpening):**
- Launch acdream, teleport to inn 2nd floor.
- Walk back and forth across the floor for ~30 seconds in various patterns.
- Phantom collisions appear intermittently — exact reproduction location unknown.
- Fall-through happened at one specific spot; location not recorded.
**Files:**
- `src/AcDream.Core/Physics/PhysicsEngine.cs` (CP seed + body persist)
- `src/AcDream.Core/Physics/TransitionTypes.cs` (`Transition.FindEnvCollisions` indoor branch + `Transition.ValidateTransition`)
- `src/AcDream.Core/Physics/BSPQuery.cs` (Path-6 land write site)
**Acceptance:** Walking on inn 2nd floor for ≥60 seconds in varied patterns produces zero phantom collisions and zero fall-through events.
---
**Status:** DONE