docs(memory): distill CLAUDE.md render+physics banners into claude-memory digests
Collapse ~285 lines of dated render-flap + A6/#98/door/#100/#101 physics saga banners into two pointers to new claude-memory digests (project_render_pipeline_digest + project_physics_collision_digest), each carrying current-truth + a DO-NOT-RETRY table. Add an always-loaded memory pointer to the How-to-operate section: read the digests before domain work; update the digest, don't add new dated banners here. ~380 fewer lines in the always-loaded instruction file; no code change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a1b12dff40
commit
d0bd28543b
1 changed files with 25 additions and 379 deletions
404
CLAUDE.md
404
CLAUDE.md
|
|
@ -249,6 +249,19 @@ pursuing live in [`docs/architecture/code-structure.md`](docs/architecture/code-
|
|||
|
||||
## How to operate
|
||||
|
||||
**Memory — read the digests before domain work.** Durable project knowledge
|
||||
lives in `claude-memory/` (the auto-loaded index is `MEMORY.md`). Before starting
|
||||
work in a domain that has a **digest**, read it first: `project_render_pipeline_digest.md`
|
||||
(indoor render / doorway FLAP) and `project_physics_collision_digest.md`
|
||||
(physics / collision / #98 / membership). Each digest is current-truth-on-top
|
||||
plus a DO-NOT-RETRY table — it supersedes the dated banners that used to sprawl
|
||||
across this file. The memory-handling protocol (distill-don't-journal, the digest
|
||||
pattern, tags, recall + capture) is in `reference_obsidian_vault.md`. **Do NOT add
|
||||
new dated banners to this file — update the relevant digest instead.** Obsidian
|
||||
(auto-started in the main repo via a SessionStart hook) is the live search / graph /
|
||||
tag lens over `claude-memory/` through the `mcp__obsidian__*` tools when it's
|
||||
running; the files read and write the same with it closed.
|
||||
|
||||
**You are the lead engineer AND architect on this project at all times.**
|
||||
You own the architecture (`docs/architecture/acdream-architecture.md`),
|
||||
the execution plan (milestones doc + strategic roadmap), the development
|
||||
|
|
@ -725,389 +738,22 @@ Visual side-by-side passed: Holtburg town, inn interior, dungeon all
|
|||
render identically to pre-O. Spec:
|
||||
[`docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md`](docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md).
|
||||
|
||||
**2026-05-30 — RENDER PIPELINE PIVOT (read this first).** The two-pipe
|
||||
(inside / outside) render approach is **ABANDONED**. acdream inherited a
|
||||
WorldBuilder-style split — a normal outdoor draw plus a separate flat
|
||||
`RenderInsideOut` stencil pass toggled on `cameraInsideBuilding` — and that
|
||||
split is the root cause of every indoor seam bug (the flap, missing/transparent
|
||||
walls, terrain bleeding into interiors). Retail has no such split; it renders
|
||||
through one portal-visibility traversal (`PView`) and is seamless by
|
||||
construction. We are building **Phase U — a single unified retail-faithful
|
||||
render pipeline**. This supersedes the A8/A8.F two-pipe arc (issue #103). The
|
||||
camera-collision work (retail `SmartBox::update_viewer` spring arm) + a
|
||||
physics viewer-cap fix **SHIPPED this session and are kept** (they're real and
|
||||
retail-faithful, just not the seam fix). Full decision + scope + next-session
|
||||
pickup prompt:
|
||||
[`docs/research/2026-05-30-unified-render-pipeline-decision-and-handoff.md`](docs/research/2026-05-30-unified-render-pipeline-decision-and-handoff.md).
|
||||
The M1.5 narrative below is history retained for context.
|
||||
|
||||
**2026-05-31 — U.4c doorway FLAP FIXED** (`0ee328a`, visual-verified "flap gone").
|
||||
Root cause (converged on a live `ACDREAM_PROBE_FLAP` capture, after disproving an
|
||||
H2 `PortalSide` side-test fix and an H1 PVS-grounding hypothesis): indoor visibility
|
||||
was rooted at the 3rd-person camera **eye**, which drifts out of the player's cell →
|
||||
`FindCameraCell` returns a STALE cell for its grace frames → the doorway portal is
|
||||
culled as behind-the-eye → exit cell + terrain + shells drop. Fix: root indoor
|
||||
visibility (cell resolution + portal-side test) at the **player's cell**
|
||||
(retail `CellManager::ChangePosition`; matches the existing lighting decision). Eye
|
||||
still drives projection. **The flap is done; the indoor pipeline is NOT yet seamless** —
|
||||
the visual gate revealed three SEPARATE residuals: (1) **#78** outdoor terrain not gated
|
||||
inside (now more visible since terrain draws again); (2) **camera collision** needed (the
|
||||
chase eye is outside the player's cell ~79% of frames → the eye-projected clip
|
||||
over-includes → transparent outer walls); (3) **U.5** outside-looking-in (deferred).
|
||||
Camera collision (retail `SmartBox::update_viewer` keeping the eye in the cell) is the
|
||||
highest-leverage next step. CANONICAL handoff (read first next session):
|
||||
[`docs/research/2026-05-31-u4c-flap-fixed-and-residuals-handoff.md`](docs/research/2026-05-31-u4c-flap-fixed-and-residuals-handoff.md).
|
||||
Apparatus `ACDREAM_PROBE_FLAP` + `tools/A8CellAudit` are committed + ready. Do NOT retry
|
||||
H1 (PVS grounding) or H2 (`PortalSide` side-test) — both evidence-disproven.
|
||||
|
||||
**Currently working toward: M1.5 — Indoor world feels right** (resumed
|
||||
from 2026-05-20 baseline after Phase O ship).
|
||||
|
||||
**2026-06-08 (evening) — FLAP ROOT CAUSE SETTLED BY LIVE-RETAIL MEASUREMENT; full retail render
|
||||
port DECIDED (Option A). READ THIS FIRST — it supersedes EVERY flap banner below, including the
|
||||
bounded-propagation/churn direction (REFUTED by measurement: `maxPop=1`, 0 churn).** We attached cdb
|
||||
to the **live 2013 retail client** at the Holtburg doorway + read the decomp. Findings (measured, not
|
||||
inferred): **retail has ONE render path — `DrawInside(viewer_cell)` every frame, NO inside/outside
|
||||
branch** (`RenderNormalMode`'s outside branch is dead code; `is_player_outside` only gates
|
||||
sky/lighting). "Entering a building" is NOT a render event — only the camera sweep resolving a
|
||||
different `viewer_cell` (outdoor `CLandCell` → indoor `CEnvCell`); same path before/after the
|
||||
threshold → no seam → no flap. **Retail's eye JITTERS ~36 µm at rest** (so a byte-stable eye is the
|
||||
WRONG target — my render-position rest-snap fix `cd974b2` failed + regressed, reverted `9b1857a`);
|
||||
retail's membership is stable anyway because it does **many small per-building floods** (~7/frame,
|
||||
~2 cells each, via the terrain BSP → `DrawPortal` → `ConstructView(CBldPortal)`), not one giant
|
||||
unified flood. **Our 3 divergences:** (D1) we invented an inside/outside branch
|
||||
(`GameWindow.cs:7498`, `clipRoot = viewerRoot ?? _outdoorNode` :7396); (D2) a synthetic `_outdoorNode`;
|
||||
(D3) one unified flood. **Decision (user-approved): Option A — rip out the branch + outdoor node, root
|
||||
always at the real `viewer_cell`, one `DrawInside`, per-building rendering.** DO NOT retry: byte-stable
|
||||
eye, bounded-propagation/churn, physics rest-jitter, viewer-cell dead-zone, two-pipe split (all
|
||||
evidence-disproven). **CANONICAL PICKUP (exhaustive — read top-to-bottom before any code):**
|
||||
[`docs/research/2026-06-08-full-retail-render-port-OPTION-A-handoff.md`](docs/research/2026-06-08-full-retail-render-port-OPTION-A-handoff.md).
|
||||
Close its §8 open traces (viewer_sought_position write site; ClipPortals/AddViewToPortals; how
|
||||
`DrawInside` handles an outdoor `CLandCell` root) BEFORE writing the implementation plan.
|
||||
**Indoor render & the doorway "FLAP" — read the digest, not banners.**
|
||||
The full current state, the root cause, the DO-NOT-RETRY list, the ⚠️
|
||||
`ACDREAM_PROBE_FLAP`→white-textures landmine, and the detail-doc pointers are
|
||||
distilled in **`claude-memory/project_render_pipeline_digest.md`** (auto-loaded
|
||||
via MEMORY.md). As of 2026-06-09 (HEAD `a1b12df`): governing direction is
|
||||
**Option A — one `DrawInside(viewer_cell)`, NO inside/outside branch**;
|
||||
R-A1/R-A2/R-A2b shipped (outside-looking-in flap GONE, seams GONE, portal-flood
|
||||
churn KILLED); remaining = the visible indoor flap narrowed to §4 (edge-on
|
||||
doorway grey + corner camera-seal). Render roots at the **VIEWER** cell, not the
|
||||
player cell. Read the digest before any render/flap work — it supersedes the
|
||||
dated render banners that used to live here.
|
||||
|
||||
**2026-06-05 (PM) — Indoor FLICKER + bluish VOID ROOT CAUSE CONFIRMED (decomp + live cdb); 3-part retail-faithful fix PLANNED (READ THIS FIRST).**
|
||||
The "core inside render / cellar floor drops" framing below is **SUPERSEDED** by this session's diagnosis.
|
||||
R1's per-cell `DrawInside` is already built and the cottage/cellar **seals** (user visual-verified). The
|
||||
residual indoor **flicker (grey↔texture while standing still)** + **stable bluish void** are ONE root cause —
|
||||
**visibility metastability at cell boundaries:** the 3rd-person camera **boom drifts at rest**
|
||||
(`desiredBack 3.11→3.07`), walking the eye across a portal plane, and acdream re-resolves the **viewer cell**
|
||||
fresh each frame with **no hysteresis** → it flips `0170↔0171` → the render (rooted at the viewer cell)
|
||||
redraws two solves → flicker; and the 2D project-then-clip **degenerates** at close portals (`proj=0`) → grey
|
||||
void. **Live cdb on retail CONFIRMS** retail's `viewer_cell` is rock-stable here (clean monotonic transitions,
|
||||
ZERO oscillation across 4,916 samples) — retail holds the boom + uses a **0.2 mm cell dead-zone** + clips
|
||||
portals **in clip-space**. **FIX (3 parts, retail-faithful, planned):** (1) camera boom stability
|
||||
[`RetailChaseCamera`; `UpdateCamera` 0x456660] → kills the flicker trigger; (2) viewer-cell ±0.2 mm dead-zone
|
||||
[`PhysicsCameraCollisionProbe.SweepEye`; `point_inside_cell_bsp` 0x53c1f0]; (3) w-space (w=0) portal clip
|
||||
[`PortalProjection`/`PortalVisibilityBuilder`; `GetClip` 0x5a4320 / `polyClipFinish` 0x6b6d00]. Two partial
|
||||
fixes committed: `5f596f2` (NDC side-plane clip — KEEP), `9f95252` (eye-in-portal flood — reassess/revert).
|
||||
Baseline App 183p / Core 1326p-4f-1s. **CANONICAL PICKUP:**
|
||||
[`docs/research/2026-06-05-viewer-cell-flicker-rootcause-and-fix-plan-handoff.md`](docs/research/2026-06-05-viewer-cell-flicker-rootcause-and-fix-plan-handoff.md).
|
||||
|
||||
**2026-06-05 — Render Residual A (camera collision) SHIPPED + user-kept; next = the CORE INSIDE RENDER (R1 completion) (SUPERSEDED 2026-06-05 PM — see the banner above; the cellar IS sealed, the real bug is the boundary flicker/void).**
|
||||
Residual A = a verbatim port of retail `SmartBox::update_viewer` (pc:92761): the indoor sweep's start
|
||||
cell is seated at the head-PIVOT via `AdjustPosition` (pc:280009) → `find_visible_child_cell` (pc:311397),
|
||||
plus the two fallbacks + cellId==0 snap-to-player. Commits `0ffc3f5` (spec) / `5177b54` (Core primitives)
|
||||
/ `9e70031` (`ResolveResult.Ok` + `SweepEye` orchestration); TDD, 11 new tests, no regression (Core
|
||||
1326p/4f/1s, App 179p). **Key finding (live capture):** A's V1 sweep ALREADY contained the eye
|
||||
(`eyeInRoot=Y` 99.75%, `viewerCell` never 0) — so A is a faithfulness completion, not the fix for the
|
||||
dominant bluish void. **What A EXPOSED (the bridge to the next phase):** the render roots at the VIEWER
|
||||
cell (`clipRoot = visibility.CameraCell`, GameWindow.cs:7322, Phase W V1 "one viewpoint"); A made that
|
||||
cell ACCURATE (the eye's real cell), so when the player is in the cellar but the eye is up in the room,
|
||||
`clipRoot = room` and the PVS flood from the room does NOT reach the cellar → the cellar floor drops.
|
||||
The user chose **"Keep it"** (the faithful viewpoint) over revert. **NEXT = the CORE inside render (R1
|
||||
completion)** — make `DrawInside` flood + seal correctly from the viewer cell so the cottage/cellar
|
||||
interior is SEALED: no bluish void, no see-through-to-other-buildings BLEED, cellar floor draws. This
|
||||
(NOT the handoff-era "C / outside-looking-in", which is R2, a later phase) is what fixes the visible
|
||||
problems; the locked design already exists. **CANONICAL PICKUP:**
|
||||
[`docs/research/2026-06-05-render-residual-a-shipped-core-inside-render-handoff.md`](docs/research/2026-06-05-render-residual-a-shipped-core-inside-render-handoff.md)
|
||||
(+ the LOCKED render design [`docs/superpowers/specs/2026-06-02-render-pipeline-redesign-design.md`](docs/superpowers/specs/2026-06-02-render-pipeline-redesign-design.md)).
|
||||
|
||||
**2026-06-03 — P1 membership DONE + P2 active (history; cellar-lip now FIXED per the 2026-06-05 banner above).** The verbatim spatial-pipeline
|
||||
port (master plan
|
||||
[`docs/superpowers/specs/2026-06-03-verbatim-spatial-pipeline-port-master-plan.md`](docs/superpowers/specs/2026-06-03-verbatim-spatial-pipeline-port-master-plan.md))
|
||||
is the active effort. **P1 (membership) = DONE** — proven to ALREADY match retail; the believed
|
||||
doorway "0/11 lag" was a cdb CAPTURE ARTIFACT (`change_cell` logs `m_position` before `set_frame`
|
||||
writes it). Aligned re-capture → production gate 9/9 with NO code change; live `[cell-transit]` clean.
|
||||
Merged + pushed to both remotes (HEAD `f0d37d8`). **P2 (door/building-shell collision) = IN PROGRESS,
|
||||
root cause LOCALIZED** to **BSP Path 5 grounded step-up** — the Path 5 wrappers (`DoStepUp`=retail
|
||||
`step_up`, `DoStepDown`=retail `step_down`) are verified faithful; the divergence is in the step-up
|
||||
CLIMB (`find_walkable`/`step_sphere_down` up-adjust). The 5 failing Core tests are P2's target. The
|
||||
visible doorway seam has moved from physics into the RENDER path (P3 camera-collision + P4 PView seal).
|
||||
The (a)–(d) membership cleanups (remove `ResolveCellId`, unify `find_env_collisions`, intrinsic
|
||||
building stabs, per-cell collision graph) are **approval-gated refactors of WORKING code**. **CANONICAL
|
||||
PICKUP:**
|
||||
[`docs/research/2026-06-03-p2-door-stepup-handoff.md`](docs/research/2026-06-03-p2-door-stepup-handoff.md)
|
||||
(+ the P1 RESOLVED banner in
|
||||
[`docs/research/2026-06-03-p1-membership-swept-advance-handoff.md`](docs/research/2026-06-03-p1-membership-swept-advance-handoff.md)
|
||||
and the visual-gate/render-residuals note
|
||||
[`docs/research/2026-06-03-p1-visual-gate-render-residuals.md`](docs/research/2026-06-03-p1-visual-gate-render-residuals.md)).
|
||||
|
||||
**A6.P1 + A6.P2 + A6.P3
|
||||
slice 1 SHIPPED 2026-05-21.** **A6.P3 slice 2 v2 SHIPPED 2026-05-22**
|
||||
(commit `f8d669b`): tried removing the L622 per-tick CP seed
|
||||
(`892019b` v1) but it broke BSP step_up at the last step of stairs;
|
||||
reverted + added a benign no-op-if-unchanged guard inside
|
||||
`CollisionInfo.SetContactPlane`. Slice 2 outcome: **#96 partially
|
||||
addressed — accepted as documented retail divergence** (the per-tick
|
||||
seed is load-bearing for `AdjustOffset` slope-projection on sub-step 1
|
||||
which BSP step_up depends on; matching retail would require deeper
|
||||
refactor of AdjustOffset). Slice 2 verification surfaced a NEW
|
||||
M1.5-blocking bug: **user cannot walk UP out of cottage cellar — stuck
|
||||
at last step due to cell-resolver ping-pong (filed as issue #98,
|
||||
Finding 3 family).** **A6.P3 slice 3 SHIPPED 2026-05-22** (commits `8898166` v1 +
|
||||
`3e140cf` v2): cell-resolver stickiness added in `ResolveCellId`'s
|
||||
indoor branch (point-in check against `fallbackCellId`'s CellBSP
|
||||
before falling through to FindCellList). Data confirms ping-pong is
|
||||
FULLY CLOSED — scen4 cellar capture shows 1 cell-transit (login
|
||||
teleport) vs 20+ pre-fix. **#90 workaround now redundant — deferred
|
||||
to A6.P4 removal. #98 APPARATUS COMPLETE 2026-05-23 evening**
|
||||
(commits `35b37df` triage → `f62a873` cell-dump probe → `3f56915`
|
||||
fixtures → `856aa78` replay harness → `6f666c1` cdb script →
|
||||
`28c282a` divergence comparison doc). Four sessions of speculative
|
||||
fixes (10+ variants) shipped the wrong diagnosis each time; this
|
||||
session shipped the APPARATUS that turns evidence-driven analysis
|
||||
into a 200ms test loop. Real divergence: retail's sphere is at
|
||||
world Z ≈ 94.48 (resting on cottage floor) when find_walkable
|
||||
accepts; acdream's failing-frame sphere is at world Z ≈ 92.01
|
||||
(2.47m lower). Retail's ContactPlane writes during cellar-up are
|
||||
ONLY flat floors (cellar floor or cottage floor), never the ramp.
|
||||
Retail's find_crossed_edge fires once in 35K BPs; ours uses it
|
||||
heavily. **Fix targets (priority): (1) Transition.AdjustOffset
|
||||
slope projection / DoStepUp WalkInterp handling — ramp climb
|
||||
doesn't gain Z; (2) cottage-cell candidacy using wrong sphere
|
||||
reference; (3) find_crossed_edge over-use; (4) ramp polygon normal
|
||||
divergence (low confidence).** Full divergence reading +
|
||||
fix-plan pickup prompt at
|
||||
[`docs/research/2026-05-23-a6-p3-issue98-replay-comparison.md`](docs/research/2026-05-23-a6-p3-issue98-replay-comparison.md).
|
||||
Current A6 phase:
|
||||
**A6.P3 — PAUSED 2026-05-23 (full day). Trajectory replay harness shipped
|
||||
but BLOCKED on a new bug surfaced during commissioning.** Read
|
||||
[`docs/research/2026-05-23-a6-p3-issue98-harness-handoff.md`](docs/research/2026-05-23-a6-p3-issue98-harness-handoff.md)
|
||||
as the canonical pickup document — it has the chronological commit list,
|
||||
the apparatus inventory, the exclusion list (do-not-retry), and three
|
||||
concrete next-session options ranked by recommendation.
|
||||
|
||||
The session shipped further apparatus + first failed fix attempt + revert:
|
||||
`8a232a3` (`[step-walk-adjust]` probe inside `Transition.AdjustOffset`
|
||||
revealing branch tokens and per-call zGain), `8daf7e7` (findings note
|
||||
at [`docs/research/2026-05-23-a6-stepwalkadjust-findings.md`](docs/research/2026-05-23-a6-stepwalkadjust-findings.md)
|
||||
+ capture snapshot), `0cb4c59` (Shape 1 fix: gate `BSPQuery.AdjustSphereToPlane`'s
|
||||
two `SetContactPlane` call sites by `Normal.Z >= 0.99`), `402ec10`
|
||||
(revert — Shape 1 broke OnWalkable tracking, sphere went into falling
|
||||
state on every sloped surface). **Refined diagnosis:** AdjustOffset is
|
||||
CORRECT (145/146 calls take `into-plane` branch, +0.045 m mean zGain
|
||||
per call when offset points into ramp); the climb CAPS at world Z ≈
|
||||
92.80 because step-up's downward step-down probe finds no walkable
|
||||
within 0.6 m below the proposed position (cottage floor is ABOVE).
|
||||
Earlier "Fix targets 1–4" priority list is OBSOLETE — AdjustOffset
|
||||
projection is not the problem. The actual bug is in the step-up
|
||||
validation at the ramp top. **Honest next-session moves**: (1) build
|
||||
deterministic trajectory replay harness so fix attempts iterate in
|
||||
<500ms instead of 5-minute live-test cycles; (2) pivot to a less-
|
||||
coupled M1.5 issue while #98 awaits the harness; (3) targeted decomp
|
||||
research on `CEnvCell::find_env_collisions` → `BSPTREE::find_collisions`
|
||||
indoor CP-setting chain (prior research worked on the outdoor
|
||||
`CLandCell` path; indoor was never fully traced). Session-end ISSUES.md
|
||||
entry has the full reading and pickup prompt. **NO further #98 fix
|
||||
attempts until apparatus or research has converged — six+ failed
|
||||
attempts in the saga is the signal.**
|
||||
|
||||
**Late-day extension (2026-05-23 PM):** trajectory replay harness shipped
|
||||
(commits `4c9290c` → `5c6bdbe`). Mechanics work — runs 200 ticks in <100 ms.
|
||||
Five tests pass. NEW finding: the cellar ramp polygon is in a GfxObj
|
||||
(static building piece), not the cell's PhysicsPolygons. Harness now
|
||||
includes `RegisterStairRampGfxObj` for synthetic stair construction
|
||||
and `AttachSyntheticBsp` to wrap hydrated cells (which have BSP=null)
|
||||
with a one-leaf BSP that exposes the indoor BSP collision path.
|
||||
**NEW BLOCKER:** even with full apparatus, sphere goes airborne at
|
||||
tick 1 with `hit=(0,1,0)` (a +Y wall normal matching no registered
|
||||
geometry). 6 hypotheses tested via the harness, none isolated root cause.
|
||||
Per systematic-debugging skill's "question architecture" rule, stop and
|
||||
reflect. Next session: build a side-by-side comparison harness that
|
||||
captures live PlayerMovementController state and diffs against the
|
||||
test harness — evidence-first instead of speculation-first.
|
||||
Findings doc:
|
||||
[`docs/research/2026-05-21-a6-cdb-capture-findings.md`](docs/research/2026-05-21-a6-cdb-capture-findings.md).
|
||||
|
||||
**Evening extension v2 (2026-05-23 PM late) — apparatus shipped + root
|
||||
cause identified.** Four commits (`fb5fba6` → `44614ab` → `0f2db62` →
|
||||
`f29c9d5`). The side-by-side comparison harness was built and exercised:
|
||||
- `PhysicsResolveCapture` ships a JSON Lines writer for every player-side
|
||||
`ResolveWithTransition` call. Off by default; turn on via
|
||||
`ACDREAM_CAPTURE_RESOLVE=<path>`. Filtered to `IsPlayer` so NPC / remote
|
||||
DR doesn't pollute.
|
||||
- Two live captures from a cottage-cellar session (41K + 70K records).
|
||||
- Three `LiveCompare_*` tests load 3 representative records (spawn,
|
||||
on-ramp, first-cap). Spawn + on-ramp PASS bit-perfect; the first-cap
|
||||
test originally FAILED with a clear divergence — and that divergence
|
||||
pinpoints the root cause.
|
||||
- **The cap is caused by `obj=0xA9B47900` — a landblock-baked cottage
|
||||
GfxObj.** Cottage floor polygons live in this GfxObj's polygon table
|
||||
(registered as a ShadowEntry), NOT in any cottage cell. The harness's
|
||||
cell fixtures (0xA9B40143/146/147) don't include the cottage GfxObj,
|
||||
so the harness fails to reproduce the live cn=(0,0,-1) cap.
|
||||
- User's confirming observation: jumping in the cellar caps at the same
|
||||
Z — purely vertical motion. This rules out every step-up / AdjustOffset
|
||||
hypothesis from the prior 6-shape saga. The bug is the head sphere
|
||||
hitting the cottage floor at Z=94.0 from below (math: foot Z=92.74
|
||||
+ sphereHeight 1.20 = head center 93.94, head top 94.42, intersects
|
||||
cottage floor Z=94.0).
|
||||
- The first-cap test is now in documents-the-bug form (PASSES while
|
||||
bug exists; FAILS when fix lands). Test baseline maintained at
|
||||
1178 + 8 (serial run).
|
||||
- 13 new cell fixtures cover the full 0xA9B4014X neighborhood (272 KB).
|
||||
Findings doc (canonical pickup):
|
||||
[`docs/research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md`](docs/research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md).
|
||||
|
||||
**Evening v2 follow-on — apparatus convergence SHIPPED 2026-05-23 PM.**
|
||||
Two commits (`cc3afbc` → `97fec19`):
|
||||
- `cc3afbc` adds the GfxObj dump infrastructure (`ACDREAM_DUMP_GFXOBJS`)
|
||||
mirroring the existing `ACDREAM_DUMP_CELLS` pattern, with new
|
||||
`GfxObjDump`/`GfxObjDumpSerializer` parallel to `CellDump`. The new
|
||||
env var triggers `PhysicsDataCache.CacheGfxObj` to write the full
|
||||
resolved polygon table as JSON when a listed id caches. Closes the
|
||||
gap that the existing `[resolve-bldg]` probe couldn't fill (the BSP
|
||||
wire site that populates `LastBspHitPoly` was never wired, so the
|
||||
probe only emitted GfxObj-level metadata, not per-poly geometry).
|
||||
- `97fec19` lands the cottage GfxObj fixture (`0x01000A2B`, 74 polygons,
|
||||
BSP radius 13.989m matching live), the new `RegisterCottageGfxObj`
|
||||
harness helper, and a minimum-stub landblock so
|
||||
`TryGetLandblockContext` succeeds at the cellar XY. Harness now
|
||||
reproduces the live `cn=(0,0,-1)` cap bit-perfect. The full per-field
|
||||
round-trip uncovers ONE residual: live preserves +0.0266m of +X
|
||||
motion through the cap (edge-slide along the cottage floor); harness
|
||||
blocks all motion. Captured in
|
||||
`LiveCompare_FirstCap_ResidualXMotionDivergence_DocumentsNextInvestigation`
|
||||
in documents-the-bug form.
|
||||
- All 21 issue-#98-relevant tests (12 harness + 4 GfxObjDumpRoundTrip +
|
||||
1 new PhysicsDiagnosticsTests + 4 CellDumpRoundTripTests) pass
|
||||
deterministically in isolation.
|
||||
- Pre-existing test suite flakiness observed (8–19 failures across runs
|
||||
of the same code, from PhysicsResolveCapture / PhysicsDiagnostics
|
||||
statics leaking between test classes). INDEPENDENT of A6.P3 — verified
|
||||
by stashing the cottage helper and reproducing the same flaky range.
|
||||
Out of scope for this session; tracked as follow-up.
|
||||
|
||||
**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).
|
||||
|
||||
**A6.P4 door bug — `pos_hits_sphere` near-miss recording shipped
|
||||
2026-05-25 PM** (commit `3253d84`). Single-line ordering fix in
|
||||
`BSPQuery.PosHitsSphere`: `if (hit) hitPoly = poly;` now precedes the
|
||||
front-face cull, matching retail's `CPolygon::pos_hits_sphere` at
|
||||
`acclient_2013_pseudo_c.txt:322974-322993` where `*arg5 = this` fires
|
||||
on static-overlap BEFORE `dot(N, movement) >= 0 → return 0`. With this
|
||||
ordering, Path 5's existing `if (hitPoly0 is not null)` near-miss
|
||||
branch (`BSPQuery.cs:1869`) finally fires — `NegPolyHitDispatch`
|
||||
sets `path.NegPolyHit`, the outer `transitional_insert` loop dispatches
|
||||
via `slide_sphere`, and the sphere slides along walls it's touching
|
||||
instead of squeezing through. The handoff hypothesized swept-sphere +
|
||||
closest-considered-polygon tracking; reading retail showed both
|
||||
`pos_hits_sphere` and `polygon_hits_sphere_slow_but_sure` are STATIC
|
||||
tests using motion only for the cull — the fix is just the ordering.
|
||||
3 new RED→GREEN unit tests in `BSPQueryTests.FindCollisions_Path5_*`
|
||||
cover: overlap + parallel motion (RED→GREEN), overlap + away motion
|
||||
(RED→GREEN), overlap + into motion (regression guard, already passed).
|
||||
Zero regressions in full Core suite — with-fix failure set is a strict
|
||||
subset of baseline (14 vs 17, the 14 are pre-existing static-leak
|
||||
flakiness + 2 stale-capture document-the-bug tests). Issue #98
|
||||
`LiveCompare_FirstCap_FixClosesCottageFloorCap` regression test
|
||||
passes. **Needs visual verification at Holtburg cottage door inside-
|
||||
out off-center ~50 cm scenario** before A6.P4 is marked complete —
|
||||
sphere should block at the door surface with no squeeze-through. The
|
||||
"runs a bit into the door" over-penetration symptom is hypothesized
|
||||
to close together with the squeeze-through (continuous near-miss
|
||||
recording while approaching a wall means the sphere slides along it
|
||||
substep-by-substep rather than catastrophically penetrating then
|
||||
recovering), but separate investigation if the symptom persists.
|
||||
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
|
||||
building/cellar half (PARTIALLY ACHIEVABLE post-slice-1; cellar-ascent
|
||||
blocked on #98) + dungeon half (blocked on #95). Issues in scope: #80,
|
||||
#81, #83, #88, #90 (workaround removal after slice 3), **#95**
|
||||
(visibility; not A6 scope), **#96** (L622 seed; retail divergence
|
||||
accepted), **#97** (phantom collisions; may close as #98 side-effect),
|
||||
**#98** (cellar-ascent stuck; A6.P3 slice 3 target), L-indoor,
|
||||
L-spotlight, indoor sling-out (Finding 3 family with #98), and the
|
||||
`TryFindIndoorWalkablePlane` definition deletion (A6.P4). **M2
|
||||
("Kill a drudge") is deferred until M1.5 lands.** Full M1.5 writeup at
|
||||
the corresponding block in `docs/plans/2026-05-12-milestones.md`.
|
||||
|
||||
**A6.P8 — Mesh-AABB-fallback phantom suppression for GfxObj-only stabs — SHIPPED 2026-05-25.**
|
||||
Three commits: `f6305b1` (PhysicsDataCache.IsPhantomGfxObjSource + 3 unit tests),
|
||||
`5240d65` (GameWindow.cs wire-in at line 6127), `6ca872f` (test-class doc
|
||||
line-ref sync from code review). Issue #101 CLOSED — the 10 phantom stair
|
||||
cyls on the Holtburg upper-floor cottage staircase are gone; collision
|
||||
falls through to entity `0x40B50089` (GfxObj `0x01000C16`, `hasPhys=True`
|
||||
BSP with walkable inclined polygon at `Normal.Z=0.717`, world ramp from
|
||||
(111.10, 25.50, 94.00)→(107.50, 27.10, 97.50)). Visual-verified end-to-end
|
||||
2026-05-25: holding W continuously climbs Z=94→97.5 over the full 45°
|
||||
ramp; no phantom diagonal slides (`[cyl-test]` count on `obj=0x40B500*`
|
||||
post-fix = 0 vs 7101 pre-fix). Spec:
|
||||
[`docs/superpowers/plans/2026-05-25-issue-101-stairs-cyl-phantom.md`](docs/superpowers/plans/2026-05-25-issue-101-stairs-cyl-phantom.md).
|
||||
|
||||
**Issue #100 — Transparent ground around buildings — SHIPPED 2026-05-25 (primary acceptance);
|
||||
visibility-culling follow-up handed off.** Three commits: `f48c74a` (terrain shader Z nudge,
|
||||
retail `zFightTerrainAdjust = 0.00999999978` applied per-vertex in `terrain_modern.vert`),
|
||||
`a64e6f2` (removed ~50 LOC of `hiddenTerrainCells` / `BuildingTerrainCells` plumbing across
|
||||
LandblockMesh / LoadedLandblock / LandblockLoader / GameWindow / GpuWorldState /
|
||||
LandblockStreamer + 2 dead tests), `84e3b72` (docs SHA stabilization follow-up).
|
||||
Visual-verified 2026-05-25 PM at Holtburg: 24m × 24m transparent rectangles around
|
||||
every cottage are GONE; ground reads as continuous cobblestone / grass. Plan:
|
||||
[`docs/superpowers/plans/2026-05-25-issue-100-terrain-cutout.md`](docs/superpowers/plans/2026-05-25-issue-100-terrain-cutout.md);
|
||||
predecessor research [`docs/research/2026-05-25-issue-100-terrain-cutout-handoff.md`](docs/research/2026-05-25-issue-100-terrain-cutout-handoff.md).
|
||||
**Secondary finding from visual verification:** outdoor terrain mesh visible inside
|
||||
cottage cellars at certain camera angles (clears when camera moves closer; gameplay
|
||||
unaffected). High-confidence root cause: **indoor-cell visibility culling not gating
|
||||
outdoor terrain** — same family as filed issue #78 (outdoor stabs visible through inn
|
||||
floor) and #95 (dungeon portal-graph blowup). Per user direction, NOT filed as a new
|
||||
issue; treated as additional evidence for #78. Next session investigates + ports
|
||||
retail's `CEnvCell::find_visible_child_cell` (decomp anchor
|
||||
`acclient_2013_pseudo_c.txt:311397`) and/or WB's `RenderInsideOut` stencil pipeline.
|
||||
Full handoff with pickup prompt:
|
||||
[`docs/research/2026-05-25-issue-100-shipped-and-culling-handoff.md`](docs/research/2026-05-25-issue-100-shipped-and-culling-handoff.md).
|
||||
**Physics / collision / cell-membership — read the digest, not banners.** The #98 cellar-ascent saga, the A6.P* phase ledger, the door/step-up (P2) work, the phantom-collision fixes (#100/#101), P1 membership, the apparatus inventory, and the full 18-entry DO-NOT-RETRY list are distilled in **`claude-memory/project_physics_collision_digest.md`** (auto-loaded via MEMORY.md). Current state (2026-06-09): #98 CLOSED via the `b3ce505` stopgap (a WORKAROUND — it introduced #99 door run-through, OPEN HIGH); P2 cellar-lip FIXED (`cc4590f`, visual-gated); P1 membership matches retail (no port needed); #100/#101 CLOSED. The open debt is the per-cell shadow architecture (A6.P4) that closes #99. Read the digest before any collision/physics/membership work — it supersedes the dated A6 banners that used to live here.
|
||||
|
||||
**Today's pre-M1.5 baseline (2026-05-20).** Five surgical fixes
|
||||
shipped to close the user-reported "logged in inside the inn, ran
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue