docs: A6.P3 #98 — new root-cause hypothesis (stale ramp contact plane)
Today's evening session ran from "harness still doesn't reproduce the cap" → "harness reproduces it" → "wait, the cap is only a symptom, the real cause is upstream Z drift from the contact plane never refreshing." The breakthrough question, from the user: "we know how retail OPENs it from above, how hard can it be to know how to open it from below?" — which reframed the investigation away from cap-event mechanics (where six prior attempts looked) and toward "what about our STATE is wrong when the player is in the cellar but not on the ramp?" The math: player at cap is 10 m away from the cellar ramp in cell-local X, but body.ContactPlane is still the ramp's slope plane. AdjustOffset projects forward motion along that stale slope every tick, lifting Z by +0.201 m per tick. After enough ticks of horizontal walking, the head sphere reaches Z=94 and bumps the cottage floor. If the contact plane refreshed to the flat cellar floor when the player walked off the ramp, the drift would be zero, the cap would never be reachable. Next session's task (per the pickup prompt at the bottom of the findings doc): (1) verify the hypothesis chronologically against the live capture, (2) find the walkable-refresh gap in Transition.FindEnvCollisions / SpherePath.SetWalkable, (3) cross-ref retail's CObjCell::find_env_collisions for the per-tick contact-plane refresh logic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7729bdcf98
commit
bf6d97625c
2 changed files with 240 additions and 46 deletions
50
CLAUDE.md
50
CLAUDE.md
|
|
@ -872,13 +872,49 @@ Two commits (`cc3afbc` → `97fec19`):
|
|||
by stashing the cottage helper and reproducing the same flaky range.
|
||||
Out of scope for this session; tracked as follow-up.
|
||||
|
||||
**Next-session move:** investigate the residual +X edge-slide divergence
|
||||
in `Transition.transitional_insert` / `AdjustOffset`'s handling of a
|
||||
`cn=(0,0,-1)` head-bump. Live treats it as a Z-only constraint and
|
||||
slides the remaining XY motion along the cottage floor; harness blocks
|
||||
the entire move vector instead. The harness's
|
||||
`LiveCompare_FirstCap_ResidualXMotionDivergence_DocumentsNextInvestigation`
|
||||
test gives <1s feedback per fix attempt. ~2 hours estimate.
|
||||
**Evening v3 finding (2026-05-23 PM, even later) — NEW root-cause
|
||||
hypothesis identified:** the cottage-floor cap is a SYMPTOM. The actual
|
||||
bug is **stale ramp contact plane causing per-tick Z drift** that makes
|
||||
the cap reachable in the first place.
|
||||
|
||||
Evidence:
|
||||
- Body's contact plane at cap = ramp's plane (n=(0, 0.7190, 0.6950),
|
||||
d=-69.5035) from the live capture's `bodyBefore`
|
||||
- Cellar ramp's actual world XY: X∈[129.7, 131.3], Y∈[10.19, 13.09]
|
||||
(computed from the cellar cell fixture's vertex data + WorldTransform)
|
||||
- Player position at cap: world (141.5, 7.22, 92.74) — **10 m away**
|
||||
from the ramp in cell-local X
|
||||
- `AdjustOffset` projects requested motion along the contact-plane
|
||||
perpendicular. Math: dot((0.0266, -0.4022, 0), (0, 0.719, 0.695))
|
||||
= -0.2892 → projected = (0.0266, -0.1943, +0.2010). **+0.201 m of
|
||||
Z gain per tick**, applied because the engine believes the player
|
||||
is on the slope.
|
||||
- Head sphere top at cap = foot Z + 1.68 = 94.42. Cottage floor at
|
||||
Z=94.00. **Head sphere exceeds cottage floor by 0.42 m** → cap fires
|
||||
- If the contact plane refreshed to the flat cellar floor when the
|
||||
player walked off the ramp, AdjustOffset would produce zero Z gain
|
||||
(no Z component in requested motion + horizontal-plane perpendicular).
|
||||
No drift, no cap.
|
||||
|
||||
How this question surfaced: user asked "we know how retail OPENs it
|
||||
from above, how hard can it be to know how to open it from below?" —
|
||||
that reframing made the question "what's different about our state
|
||||
when walking up vs down?" The answer: **nothing, actually — the
|
||||
cottage geometry is the same. But our contact plane is wrong.** The
|
||||
six prior fix attempts were all investigating the cap-event mechanics
|
||||
(step-up, slope projection at the cap, edge-slide, SidesType, +X
|
||||
residual). None questioned why the contact plane was the ramp at all
|
||||
when the player was 10 m from the ramp.
|
||||
|
||||
**Next-session move:** verify the stale-contact-plane hypothesis
|
||||
chronologically against the live capture (walk the JSONL records, find
|
||||
the last tick the player was on the actual ramp, quantify Z drift),
|
||||
then locate the walkable-refresh code path in
|
||||
`Transition.FindEnvCollisions` / `SpherePath.SetWalkable` that's
|
||||
supposed to detect a new walkable polygon under the sphere and
|
||||
overwrite the contact plane. Retail decomp anchor:
|
||||
`CObjCell::find_env_collisions`. Full pickup prompt at the bottom of
|
||||
[`docs/research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md`](docs/research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md).
|
||||
Original demo scenario (Holtburg Sewer end-to-end) is unreachable: sewer
|
||||
doesn't exist on this server, and **issue #95** (portal-graph visibility
|
||||
blowup) blocks any substitute dungeon. Revised M1.5 demo split into
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue