The user's primary symptom (interior walls + cellar floor render as grey clear-color
with dynamic objects / outdoor slices showing through; flicker at room/cellar
transitions) is the KNOWN R1-completion problem: the PView flood roots at the CAMERA
cell (viewer cell), and when the camera is in a different interior cell than the player
(room 0171 vs cellar 0174), the flood does not seal the player's cell. Decisive
evidence: flap-cam root=0xA9B40171 playerCell=0xA9B40174. This handoff separates the
two problems I conflated, lists the disproven causes, gives the next diagnostic step
(shell/flap/vis probes in the cellar), and a kickoff prompt. HEAD 2b7f5a1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
16 KiB
Handoff — Indoor SHELL-SEALING / wrong-flood-root (cellar floor + interior walls drop to grey) — 2026-06-05 (PM/eve)
For the next session/model. Read this FIRST. The previous model (me) spent this session on the "viewer-cell flicker" 3-part plan, shipped two real-but-partial fixes, and conflated two distinct problems. The user's PRIMARY pain — interior walls + cellar floor render as grey background with dynamic objects / outdoor slices showing through, plus flicker when changing rooms / entering the cellar — is the KNOWN, already-documented "R1-completion" problem, NOT the boom and NOT the branch I touched. Get a SCREENSHOT +
[shell]evidence EARLY; do not re-litigate the disproven causes below.Tree: branch
claude/thirsty-goldberg-51bb9b, worktreeC:/Users/erikn/source/repos/acdream/.claude/worktrees/thirsty-goldberg-51bb9b. HEAD2b7f5a1. Do NOT branch/worktree. Do NOT push without asking. NEVERgit stash/gc. PowerShell on Windows; launch logs are UTF-16 (useSelect-String/Get-Content, they handle it).
0. The honest TL;DR
- The user reports (with a screenshot): standing inside the cottage, the floor draws but the walls are grey (the time-of-day clear color), with NPCs/doors/chests and a slice of the outdoor world floating in the grey. In the cellar, the floor is missing (just grey). It flickers when changing rooms / entering the cellar. This persisted through both of this session's fixes.
- Decisive evidence (live, this session):
The render roots the visibility flood at the CAMERA's cell[flap-cam] root=0xA9B40171 viewerCell=0xA9B40171 playerCell=0xA9B40174 eyeInRoot=Y eye=(153.46,6.66,94.92) player=(153.58,8.88,92.76) terrain=Planes outVisible=True [flap] root=0xA9B40171 ... | p0->0170 proj=4 | p1->0173 proj=0 | p2->0175 proj=5 || outPolys=1 vis=40171(the room, z≈95), but the PLAYER is in0174(the cellar, z≈93). The flood reachesvis=4cells from the room; the player's actual cell0174is not sealed by it (the stair-chain portalp1→0173isproj=0). So the cellar shell around the player isn't drawn → grey. - This is exactly what the 2026-06-05 Residual-A handoff already flagged as NEXT: "when the player is in the cellar but the eye is up in the room, clipRoot = room → the PVS flood from the room does NOT reach the cellar → the cellar floor drops." And the 2026-06-02 design doc §3 calls the grey a SHELL-SEALING bug ("the closed cell mesh is not covering those pixels"). The answer was in the docs the whole time.
- Two fixes shipped this session (both real, both PARTIAL, neither is the cellar/walls fix):
d2212cf— Part 1 camera boom convergence snap (retailUpdateCamera0x00456fcd). Freezes the at-rest boom drift. Test-covered. The user confirmed the at-rest room was never flickering, so this fixed a real-but-invisible thing. KEEP (faithful) or reassess.2b7f5a1— branch inside/outside onis_player_outside(retailRenderNormalMode0x453aa0) instead of the camera cell. Reduced the player-OUTSIDE doorway grey ("reduced a lot" — user). Test-covered. Does NOT touch the player-inside case. KEEP (no regression — see §4) or reassess.
1. The two problems (do NOT conflate them — I did, and it cost the session)
| Problem A — doorway transition grey | Problem B — interior shell not sealed (THE user's pain) | |
|---|---|---|
| When | Player fully outside (landcell <0x100), camera lags inside the doorway |
Player inside cell X, camera inside a DIFFERENT cell Y (camera in room, player in cellar) |
| Why | Branch keyed on camera → wrongly ran DrawInside rooted at the threshold |
Flood roots at the camera's cell Y; the player's cell X isn't in/sealed by the flood from Y |
| Symptom | Whole screen grey at the in↔out threshold | Walls/cellar-floor grey while standing inside; flicker at room/cellar transitions |
| Status | Reduced by 2b7f5a1 (retail-verified) |
UNSOLVED — this is the real target |
| Evidence | outPolys=0 while the exit portal projects full-screen (proj=6 clip=8) |
root=0171 vs playerCell=0174; vis=4 from the room excludes the cellar |
Problem B is the one to fix. Problem A's fix is a genuine retail-faithful improvement that happens to share a "grey" symptom, which is what made me conflate them.
2. Problem B — what we know, and the core open question
The render roots the PView flood at clipRoot = visibility.CameraCell (the VIEWER/camera cell) —
GameWindow.cs:7322 (now wrapped by the ShouldRenderIndoor branch, but still the viewer cell when
indoor). Retail RenderNormalMode (0x453aa0:92675) literally calls DrawInside(this->viewer_cell). So
rooting at the viewer cell is retail-faithful on its face.
But when the 3rd-person camera is in a different interior cell than the player (room vs cellar), the
flood from the camera's cell does not seal the player's cell → the geometry around the player
(cellar floor, near walls) isn't drawn → grey. The decisive [flap-cam] line (root=0171,
playerCell=0174) is the whole story.
The core open question the next model MUST resolve against the decomp (don't guess — this is the crux): how does retail avoid this? Candidate mechanisms, each needs decomp verification:
- (a) Retail's collided camera stays in (or floods to) the player's cell. Residual A
(
SmartBox::update_viewer0x00453ce0, sweptviewer_sphere) is shipped, but verify: does retail'sviewer_cellactually equal the player's cell when the player is in the cellar and the boom would put the eye up in the room? The spring arm sweeps from the head-pivot — if the pivot is the player's head in the cellar, the swept eye may be stopped by the cellar ceiling and stay in0174. Check whether acdream'sviewer_cellSHOULD be0174here and isn't (i.e. the camera-collision/cell- resolution is putting the eye in0171when retail would keep it in0174). - (b) Retail's flood from the viewer cell DOES reach the player's cell, because retail's portal clip
is robust and the stair-chain portals don't go
proj=0. Herep1→0173 proj=0stops the flood. Is0174reachable only through0173(which is culled)? If so, the flood-reach is the bug, not the root. - (c) The design doc §5 intent: visibility roots at the PLAYER's physics cell (
CellGraph.CurrCell), eye drives projection only. The 2026-06-05 viewer-cell handoff said don't switch the root to the player cell ("retail rootsDrawInsideat viewer_cell"). This is a real contradiction in our own docs — design doc §5 says player-cell-roots-visibility; the later handoff says viewer-cell-roots. The next model should settle it from the decomp: inRenderNormalMode,viewer_cellis the argument toDrawInside— but WHAT setsviewer_cell, and is it ever != the player's cell in normal play? If retail'sviewer_cellis always the player's cell (because the camera collision keeps it there), then (a) and (c) converge and acdream's bug is that itsviewer_celldrifts to the camera's room cell.
Strong hypothesis to test first (cheap): acdream's viewer_cell (visibility.CameraCell) is wrong
here — it's the room because the eye is geometrically up in the room, but retail's collided
viewer_cell would be the cellar (the swept sphere from the head-pivot is stopped by the cellar
ceiling / the pivot is in the cellar). I.e. this is a camera-cell-resolution bug, not a flood/root
bug. Verify by reading how visibility.CameraCell / viewerCellId is computed (CellVisibility. FindCameraCell + PhysicsCameraCollisionProbe.SweepEye) and whether the pivot/sweep should keep the
cell in 0174.
3. The next diagnostic step (do this BEFORE any fix — evidence first)
The apparatus is committed and ready. Stand the player in the cellar with the camera up in the room (the exact repro), and capture:
$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_PROBE_FLAP="1"; $env:ACDREAM_PROBE_SHELL="1"; $env:ACDREAM_PROBE_VIS="1"
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 | Tee-Object launch.log
Pin these three things from the log while standing in the cellar:
- Is the player's cell (
0174) in the visible set?[flap-cam]showsroot=vsplayerCell=;[vis]/[flap]showsvis=count + (turn onACDREAM_PROBE_VISfor the cell-id list). If0174is NOT in the set → flood-reach / wrong-root problem (§2 a/b/c). - If
0174IS in the set, does its shell DRAW?[shell]probe (ACDREAM_PROBE_SHELL) reports per-cell shell draw (geometry/texture/depth). If0174is visible but its shell is skipped / a polygon is back-facing / depth-culled → mesh-seal problem (design doc §3: dat-dump the0174EnvCell mesh, look for a missing/back-facing floor polygon). - What
viewer_cellSHOULD it be? Compare the liveviewerCell=to where the player is. If the camera collision (Residual A) is failing to keep the eye's cell == the player's cell, that's §2(a).
This single capture discriminates root-vs-flood-vs-mesh. Don't pick a fix until it does.
4. Exactly what's committed this session (and why each is safe to keep)
| SHA | What | Keep? |
|---|---|---|
d2212cf |
Part 1 boom convergence snap — RetailChaseCamera.ApplyConvergenceSnap + wiring; retail UpdateCamera 0x00456fcd (SnapEpsilon=2×0.000199999995, RotCloseEpsilon=0.000199999995). 4 new App tests. |
Keep — retail-faithful, fixes at-rest boom drift, no regression. Not the visible fix. |
2b7f5a1 |
Branch inside/outside on is_player_outside (RenderingDiagnostics.ShouldRenderIndoor + GameWindow.cs:7322). 5 new Core tests. |
Keep — retail-faithful, reduced Problem A. Provably no Problem-B regression: for the player-inside case it yields clipRoot = CameraCell, identical to the pre-fix visibility?.CameraCell. |
Plan doc (Part 1's TDD steps; Parts 2/3 there are SUPERSEDED by this handoff —
see §5): docs/superpowers/plans/2026-06-05-indoor-viewer-cell-flicker-fix.md.
Working tree is clean (the TEMP w-stat probe added to PortalVisibilityBuilder.cs was stripped;
git status shows nothing under src/tests). Test baseline: App 187p/0f, Core 1331p / 4f / 1s,
build green. The 4 Core fails are the documented set (2× DoorBugTrajectoryReplay.LiveCompare_*,
BSPStepUpTests.D4, DoorCollisionApparatusTests).
5. DO NOT RE-LITIGATE (evidence-disproven this session)
- The flicker is NOT viewer-cell oscillation / cell-membership instability. Captured the render gate
(
terrain=Skip/Planes,outVisible) flapping with the viewer cell STABLE at0171. The planned Part 2 (point_inside_cell_bsp ±0.2 mm dead-zone) was NOT implemented and is NOT the fix. - The doorway grey is NOT the portal PROJECTION degenerating. At the grey frame the exit portal
p0→0170projects full-screen (proj=6 clip=8, ndc spans ±1) whileoutPolys=0. SoProjectToNdcis fine; theOutsideView/flood assembly (and, per §2, the root/flood-reach) is the issue. Do not "harden the w-clip" (5f596f2already did the clip-space side-plane clip; the9f95252eye-in-portal flood band-aid is still in — reassess only after Problem B is understood). - The boom drift (Part 1) was real but is NOT the visible flicker. Freezing the boom did not change the user-visible symptom.
- The 3-part plan's framing (flicker = boom + cell dead-zone; void = clip) was the previous-session hypothesis; this session's live evidence reassigns the dominant symptom to Problem B (shell sealing / flood root). Treat the plan's Parts 2-3 as superseded.
6. Canonical prior art (already documents Problem B — read these)
docs/research/2026-06-05-render-residual-a-shipped-core-inside-render-handoff.md— "player in cellar, eye in room → clipRoot=room → flood doesn't reach the cellar → cellar floor drops. NEXT = the CORE inside render (R1 completion)." THE pointer.docs/superpowers/specs/2026-06-02-render-pipeline-redesign-design.md§2 (the binaryRenderNormalModemodel), §3 (grey = SHELL-SEALING bug;[shell]probe + dat dump), §5 (the two-camera invariant — and the doc/handoff contradiction to settle, §2 above).memory/reference_render_pipeline_state.md— Residual A made the viewer cell accurate, which exposed that the flood doesn't reach the player's cell. (This session is more evidence for that.)memory/feedback_render_one_gate.md+memory/feedback_verify_render_seal_before_layering.md— get a SCREENSHOT +[shell]evidence EARLY; one gate for all geometry.memory/feedback_render_downstream_of_membership.md— a transition flicker can be a membership/ flood-root bug, not a render bug.
7. Kickoff prompt (copy-paste)
Continue acdream M1.5 indoor render in worktree thirsty-goldberg-51bb9b (branch
claude/thirsty-goldberg-51bb9b, HEAD 2b7f5a1). Do NOT branch/worktree; do NOT push without asking;
NEVER git stash/gc. PowerShell on Windows; launch logs are UTF-16. Running the client: see CLAUDE.md;
+Acdream spawns at the Holtburg cottage.
TARGET BUG (the user's real pain, with a screenshot): standing INSIDE the cottage, the floor draws but
the WALLS are grey (the time-of-day clear color) with NPCs/doors/outdoor-slices showing through; in the
CELLAR the FLOOR is missing (grey); flicker when changing rooms / entering the cellar. This is the KNOWN
"R1-completion" SHELL-SEALING / wrong-flood-root problem, NOT the camera boom and NOT the inside/outside
branch (both partially fixed this session).
READ FIRST (in order):
1. docs/research/2026-06-05-shell-sealing-cellar-floor-handoff.md (THIS handoff — the two problems §1,
the decisive root=0171/playerCell=0174 evidence §2, the next diagnostic step §3, the DO-NOT-RETRY §5).
2. docs/research/2026-06-05-render-residual-a-shipped-core-inside-render-handoff.md (the R1-completion
pointer) + docs/superpowers/specs/2026-06-02-render-pipeline-redesign-design.md (§2/§3/§5).
3. memory: reference_render_pipeline_state, feedback_render_one_gate,
feedback_verify_render_seal_before_layering, feedback_render_downstream_of_membership.
DO (evidence first — this bug has burned many speculative fixes; do NOT add a workaround):
- Reproduce + capture with ACDREAM_PROBE_FLAP=1 ACDREAM_PROBE_SHELL=1 ACDREAM_PROBE_VIS=1, player in the
CELLAR with the camera up in the room. Pin: (1) is the player's cell (0174) in the visible set? (2) if
so, does its shell DRAW ([shell] probe) or is a floor polygon missing/back-facing (dat-dump the 0174
EnvCell mesh, design doc §3)? (3) is acdream's viewer_cell wrong — should retail's collided viewer_cell
be the cellar (0174), not the room (0171)? (See §2 a/b/c — settle the design-doc-vs-handoff
viewer-cell-vs-player-cell contradiction against the decomp: RenderNormalMode 0x453aa0 / update_viewer
0x00453ce0 / what sets viewer_cell.)
- THEN fix the actual cause (camera-cell-resolution keeping the eye in the player's cell, OR the flood
reaching the player's cell, OR the mesh seal) — retail-faithful, TDD where the logic is pure,
visual-verify with the user.
DON'T (§5, evidence-disproven): the flicker is NOT viewer-cell oscillation (Part 2 dead-zone is NOT the
fix); the doorway grey is NOT the portal projection (it projects full-screen while OutsideView is empty);
the boom (Part 1) is not the visible bug. Get a SCREENSHOT/[shell] evidence EARLY; don't declare a fix
before the user's eyes confirm it.
TEST BASELINE: App 187p/0f. Core 1331p / 4f (documented) / 1s. Build green.
8. A note from the outgoing model (honest)
I repeatedly presented fixes with too much confidence and conflated Problem A (doorway grey, which I did
reduce) with Problem B (the cellar/walls shell-sealing, which I did not touch). The user called this out
correctly. The two committed changes are real and test-backed, but the next model should treat the
user's screenshot symptom (walls + cellar floor grey, interior-transition flicker) as Problem B from the
start, gather [shell]/[flap] evidence in the cellar BEFORE proposing anything, and get the user's
eyes on a sealed result before claiming success.