acdream/docs/research/2026-06-06-retail-pview-renderer-replacement-attempts-handoff.md
Erik 1405dd8e90 feat(render): indoor render WORKS — terminating portal flood + every-cell seal + look-in FPS
Checkpoint of the unified retail-faithful indoor render. The two-week HANG/grey is fixed and the
interior seals (live-verified by the user). Commits the session render-rewrite foundation together
with the fixes that made it functional.

- HANG fix: PortalVisibilityBuilder.Build portal flood did not terminate (the faithful ProjectToClip
  near-side clip drifts per round, defeating the CellView dedup; the BFS had no bound after U.2a removed
  MaxReprocessPerCell). Fix = drift-tolerant snapped/canonical CellView.Add dedup (PortalView.cs) plus
  restored MaxReprocessPerCell=16 bounded re-enqueue (PortalVisibilityBuilder.cs). Re-enqueue is kept
  (load-bearing for late-slice propagation, Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit);
  only its count is capped. CellViewDedupTests added.
- Seal (DrawCells Task 2): RetailPViewRenderer.DrawEnvCellShells draws EVERY visible cell via
  IndoorDrawPlan.ShellPass (was gated on the ClipFrameAssembler slot filter, leaving slot-less cells grey).
- Look-in FPS: GameWindow exterior look-in candidates limited to the player landblock +-1 (was all ~81
  loaded LBs iterated every outdoor frame). No behaviour change (far cells were >48m, already culled).

Remaining dominant issue = the FLAP at transitions: viewer-cell metastability (render roots at the
camera-eye cell, which oscillates outdoor-indoor as the 3rd-person boom drifts across the doorway,
confirmed in render-sig). SEPARATE fix, NOT the DrawCells port. Full handoff + flap fix plan + tracked
follow-ups (#78 terrain, look-in-from-inside, look-in FPS, L-spotlight):
docs/research/2026-06-07-indoor-render-session-handoff.md.

Baselines: build 0 err; App.Tests 210/210; Core.Tests 1331 pass / 4 fail (pre-existing) / 1 skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 10:14:43 +02:00

589 lines
22 KiB
Markdown

# Handoff - M1.5 Indoor Render / Retail PView Replacement Attempts - 2026-06-06
This is a **stop-and-handoff** note for the next agent. It records what was tried, what changed on disk, what the user still sees, and what evidence should drive the next step.
The user explicitly stopped this thread after repeated visual regressions. Do **not** continue the same patching loop. Treat all current uncommitted render work as suspect until re-audited against named retail.
## Worktree And Rules
- Worktree: `C:\Users\erikn\source\repos\acdream\.claude\worktrees\thirsty-goldberg-51bb9b`
- Branch: `claude/thirsty-goldberg-51bb9b`
- Starting HEAD called out by the user: `8116d10`
- Do **not** branch or create a new worktree.
- Do **not** push without asking.
- Never run `git stash` or `git gc`.
- PowerShell on Windows.
- Launch logs are UTF-16.
- Build before launching.
- Use `apply_patch` for manual edits.
- Do not revert dirty changes unless the user explicitly asks.
Current child handoff thread created before this file:
- Child thread id: `019e9d5c-bb34-7fe3-85cc-6b9065b4e882`
- It was forked same-directory, not a new worktree.
- A follow-up prompt was sent there with the immediate evidence and constraints.
## User-Visible State At Stop
The latest user report, after the most recent relaunch:
- Transition flaps still happen between outdoor/indoor, room/room, and cellar.
- Ground floor became transparent instead of sealed.
- Cellar remains broken.
- Prior screenshots showed grey or black background filling cell openings.
- Prior screenshots showed indoor walls losing texture or drawing as clear/background color.
- Prior screenshots showed character cut in half on the cellar stairs.
- User explicitly says we are back to old bugs and nothing feels solid.
Important: **do not claim any current code is fixed**. Build/tests passed for some pieces, but visual acceptance failed.
## Current Dirty State
`git status --short --branch` showed these tracked files modified:
- `src/AcDream.App/Rendering/ClipFrameAssembler.cs`
- `src/AcDream.App/Rendering/ClipPlaneSet.cs`
- `src/AcDream.App/Rendering/GameWindow.cs`
- `src/AcDream.App/Rendering/InteriorEntityPartition.cs`
- `src/AcDream.App/Rendering/InteriorRenderer.cs`
- `src/AcDream.App/Rendering/ParticleRenderer.cs`
- `src/AcDream.App/Rendering/PortalView.cs`
- `src/AcDream.App/Rendering/PortalVisibilityBuilder.cs`
- `src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs`
- `src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs`
- `src/AcDream.Core/Rendering/RenderingDiagnostics.cs`
- `src/AcDream.Core/World/WorldEntity.cs`
- `tests/AcDream.App.Tests/Rendering/ClipFrameAssemblerTests.cs`
- `tests/AcDream.App.Tests/Rendering/ClipPlaneSetTests.cs`
- `tests/AcDream.App.Tests/Rendering/InteriorEntityPartitionTests.cs`
- `tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs`
- `tests/AcDream.App.Tests/Rendering/Wb/WbDrawDispatcherClipSlotTests.cs`
- `tests/AcDream.Core.Tests/Rendering/RenderingDiagnosticsTests.cs`
- `tools/TextureDump/Program.cs`
Important untracked files include:
- `src/AcDream.App/Rendering/RetailPViewRenderer.cs`
- `docs/research/2026-06-05-retail-pview-indoor-render-pseudocode.md`
- many probe logs and local scripts/images, including `launch-flap-shell-capture-relaunch.log`, `launch-pview-watermark-probe.log`, `a8-current-room-cellar-audit.txt`, `texture-current-room-surfaces.txt`, `analyze_*.py`, `retail-*-trace.log`, and several screenshots.
Diff size before this handoff file:
- 19 tracked files changed.
- About 1593 insertions and 773 deletions.
## Validation That Passed But Did Not Prove Visual Correctness
After the last attempted PortalVisibilityBuilder patch:
```powershell
dotnet test tests\AcDream.App.Tests\AcDream.App.Tests.csproj -c Debug --filter "FullyQualifiedName~PortalVisibilityBuilderTests|FullyQualifiedName~PortalProjectionTests"
```
Passed: 29/29.
```powershell
dotnet build -c Debug --no-restore
```
Succeeded, with 9 known warnings.
```powershell
dotnet test tests\AcDream.App.Tests\AcDream.App.Tests.csproj -c Debug --no-build
```
Passed: 196/196.
These results only prove the pure/tested slices compile and pass. They did **not** solve the live render.
## Retail PView Reference Already Written
New pseudocode note exists:
- `docs/research/2026-06-05-retail-pview-indoor-render-pseudocode.md`
It summarizes:
- `SmartBox::RenderNormalMode @ 0x00453aa0`
- `RenderDeviceD3D::DrawInside @ 0x0059f0d0`
- `PView::DrawInside @ 0x005a5860`
- `PView::ConstructView @ 0x005a57b0`
- `PView::DrawCells @ 0x005a4840`
- `RenderDeviceD3D::DrawObjCellForDummies @ 0x005a0760`
Core retail model from that note:
- Outdoor: `LScape::draw`, then portal/interior peering through PView portal paths.
- Indoor: `DrawInside(viewer_cell)`.
- `PView::ConstructView` builds `cell_draw_list`, per-cell `portal_view`, and `outside_view`.
- `PView::DrawCells` draws outside landscape through `outside_view`, then reverse `cell_draw_list` exit masks, reverse shells, reverse object lists.
- No global indoor terrain/entity/particle pass should bypass PView membership.
## Retail Functions That Still Matter
Re-read named retail before more code:
- `PView::AddViewToPortals @ 0x005a52d0`
- `PView::ConstructView @ 0x005a57b0`
- `PView::ClipPortals @ 0x005a5520`
- `PView::FixCellList @ 0x005a5250`
- `PView::AdjustCellView @ 0x005a5770`
- `PView::OtherPortalClip @ 0x005a5400`
- `PView::GetClip` around `0x005a4320`
- `SmartBox::RenderNormalMode @ 0x00453aa0`
- `SmartBox::update_viewer @ 0x00453ce0`
- `RenderDeviceD3D::DrawObjCellForDummies @ 0x005a0760`
The critical retail detail not faithfully settled yet:
- Retail tracks `view_count` and `update_count`.
- When a cell view grows after the cell was already processed, retail calls `FixCellList` / `AdjustCellView`.
- Current acdream code only approximates this. It may not match draw-list ordering or downstream propagation.
## What We Tried
### 1. Treated symptoms as separate render leaks
The session started with symptoms that looked separate:
- dynamic objects and particles visible through ground when looking out from inside;
- outside ground texture covering cellar entrance when looking in;
- grey flaps when crossing cell boundaries;
- missing cellar floor / grey cellar;
- transparent or textureless interior walls.
The user correctly pushed back that these are probably one render-pipeline failure: indoor/outdoor, cells, shells, terrain, objects, particles, and doors must all agree on one visible-cell graph.
### 2. Gated dynamic objects and particles by ownership
Attempt:
- `WorldEntity.ParentCellId` was populated for player/spawns/teleports/motion updates.
- `InteriorEntityPartition` was changed so live dynamic entities with an indoor `ParentCellId` go into their cell bucket instead of a global live-dynamic overlay.
- `WbDrawDispatcher.ResolveEntitySlot` was changed so `ServerGuid != 0` no longer always means "draw unclipped indoors".
- Particles were moved toward PView-scoped / owner-scoped behavior instead of a global indoor scene pass.
Effect:
- User reported this stopped much of the obvious dynamic-object/particle bleeding when looking out.
- It did **not** fix grey/background transition flaps.
- It did **not** fix cellar/floor/walls.
Current risk:
- This direction is probably correct, but the exact routing must be audited. A later attempt also cleared clip routing to avoid character/shell cutting, so "PView membership" and "GPU clip slot routing" are currently mixed/confused.
### 3. Added/used a `RetailPViewRenderer`
Attempt:
- Added `src/AcDream.App/Rendering/RetailPViewRenderer.cs`.
- Moved part of indoor draw orchestration into `RetailPViewRenderer.DrawInside`.
- Added `DrawPortal` for outdoor-looking-in through `PortalVisibilityBuilder.BuildFromExterior`.
- The renderer currently does:
- `PortalVisibilityBuilder.Build`
- `ClipFrameAssembler.Assemble`
- `_envCells.PrepareRenderBatches(filter: drawableCells)`
- `InteriorEntityPartition.Partition`
- landscape through outside slices
- exit masks
- EnvCell shells
- object buckets
Effect:
- This is not a full retail replacement yet.
- User repeatedly saw unchanged or worse symptoms.
- FPS was reported drastically down after one iteration.
- Subsequent attempts produced missing textures / white or grey wall panels.
Current risk:
- `RetailPViewRenderer` is not truly verbatim retail. It keeps modern infrastructure and approximates PView with GPU clip slots and callbacks.
- The user asked "have you ported retail verbatim?" and the honest answer remains no.
- `GameWindow` still has a lot of orchestration, diagnostics, and render routing around this. It is not a small caller yet.
### 4. Reworked `ClipFrameAssembler` from one clip per cell to per-slice clip slots
Attempt:
- `ClipFrameAssembler` was rewritten toward per-polygon/slice output:
- `CellIdToViewSlices`
- `OutsideViewSlices`
- per-slice `ClipViewSlice`
- `TerrainClipMode` for outside-view landscape
- The goal was to represent retail `portal_view` slices more closely.
Effect:
- The code is plausible as a draw assist, but it is not retail membership.
- User saw regressions including black covers during transitions.
Current risk:
- The next agent must ensure `ClipFrameAssembler` never decides PView membership.
- It should be draw-assist only.
- Several failures looked like GPU clip slots cutting shells or characters at door/stair boundaries.
### 5. Disabled clip routing for shells/entities to stop character/stair cutting
Attempt:
- `RetailPViewRenderer.UseIndoorMembershipOnlyRouting` clears `_envCells.SetClipRouting(null)` and `_entities.ClearClipRouting()`.
- Comment says retail portal views decide eligibility, but feeding those 2D views into GL clip distances slices characters and shells at stair/door boundaries.
Effect:
- This was a reaction to user screenshots where the character was cut in half on stairs.
- It may reduce character slicing.
- It may also mean shells/objects are currently only membership-gated, not portal-view clipped.
Current risk:
- This is not a settled retail copy. It is an emergency compromise.
- Retail does use per-view setup (`CEnvCell::setup_view`) around shell/object drawing. We need to know whether our GL clip-plane model is simply the wrong mechanism for that setup.
### 6. Tried EnvCell / DAT polygon side handling changes
Attempt:
- `ObjectMeshManager` changed CellStruct polygon side handling:
- DAT `CullMode` interpreted as retail `CPolygon::sides_type`.
- `0 = pos`
- `1 = pos twice with reversed winding`
- `2 = pos + neg surface`
- `NoPos` / `NoNeg` still suppress faces.
- Added explicit normal inversion / winding reversal logic.
Effect:
- User saw missing textures/white/grey interior panels after some launches.
- The attempt did not fix the cellar or transition flaps.
Current risk:
- This may be correct retail interpretation or may be partially wrong.
- Audit with DAT dumps and retail/ACME references before keeping.
- `a8-current-room-cellar-audit.txt` and `texture-current-room-surfaces.txt` may contain useful surface/cell evidence.
### 7. Tried outside-looking-in via `BuildFromExterior`
Attempt:
- `PortalVisibilityBuilder.BuildFromExterior` seeds interior cell views through outside-facing exit portals.
- `RetailPViewRenderer.DrawPortal` calls it from outdoor branch.
- Tests were added:
- seeds interior cell through outside portal;
- does not seed when camera is on interior side;
- traverses deeper interior portals;
- max seed distance skips distant exit portal.
Effect:
- User initially reported walls became visible looking in from outside, but ground/cellar entrance composition stayed wrong.
- Later launches regressed to transparent/grey panels and missing textures.
Current risk:
- This is probably needed, but the exterior portal path is not proven retail-faithful.
- `BuildFromExterior` may now have duplicated-looking test diff context; inspect file carefully.
### 8. Tried broad "no hybrid" render routing in `GameWindow`
Attempt:
- `GameWindow` was changed so indoor path should call `RetailPViewRenderer.DrawInside`.
- Outdoor path should draw world and call `DrawPortal`.
- Global indoor terrain/entity/particle passes were reduced or bypassed.
- New render signature diagnostics log:
- `branch`
- `root`
- `viewerRoot`
- `playerRoot`
- `viewerCell`
- `playerCell`
- `gate`
- `terrain`
- `skyGate`
- `zclear`
- `sceneParticles`
- `outSlices`
- `outPolys`
- `ids`
- `draw`
- object partition counts
Effect:
- User explicitly asked whether the hybrid was totally gone.
- It is not safe to answer "yes" without auditing `GameWindow`.
- Symptoms persisted, so either the routing is still hybrid or the PView graph/draw setup is wrong enough that "no hybrid" alone does not solve it.
Current risk:
- `GameWindow.cs` has a very large diff, around 1000 lines touched.
- Next agent should not blindly keep it.
- Audit all remaining global passes while `clipRoot != null`.
### 9. Tried PView `update_count`-style reprocessing
Attempt in the last aborted step:
- `PortalView.CellView.Add` now returns `bool` and deduplicates near-identical polygons.
- `PortalVisibilityBuilder.Build` replaced `seen` with:
- `queued`
- `drawListed`
- `processedViewCounts`
- A cell can be requeued when its view grows.
- Each processing pass clips portals against only newly added view polygons.
- Similar logic was added to `BuildFromExterior`.
- Added tests:
- `Build_CollapsedInteriorPortalNearEyeBeyondHalfMeter_FloodsNeighbour`
- `Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit`
Effect:
- Focused tests passed.
- Live probe after patch still showed `outPolys` toggling near root `0xA9B40172`.
- User then reported transition flaps still there and now ground floor transparent.
Current risk:
- This patch is **unaccepted** and may be wrong.
- It approximates retail `update_count`, but does not necessarily implement `FixCellList`, `AdjustCellPlace`, or retail draw-list ordering correctly.
### 10. Widened eye-standing-in-portal fallback
Attempt:
- `EyeStandingPerpDist` widened from `0.5f` to `1.75f`.
- Motivation: live cellar capture had `0174 -> 0175` traversable with `D=-1.41` but `ProjectToNdc` returned zero vertices.
- The fallback still requires the perpendicular projection to land inside the portal opening.
Effect:
- It made one unit test pass for the cellar-style collapsed portal.
- It did not solve live transitions.
Current risk:
- This may be a bandaid, not retail.
- It should be validated against `OtherPortalClip` / `GetClip` in named retail before keeping.
### 11. Tried reciprocal clip fallback for eye-in-opening
Attempt:
- Before `ApplyReciprocalClip`, code clones `clippedRegion` when `eyeInsideOpening`.
- If reciprocal clipping empties the region, it restores the pre-reciprocal region.
Effect:
- Tests passed.
- Live visual did not.
Current risk:
- This may over-include.
- It is not proven retail-faithful.
## Critical Evidence From Logs
### Cellar startup: root 0174 only sees itself
From `launch-flap-shell-capture-relaunch.log`:
```text
[flap] root=0xA9B40174 eye=(154.50,4.99,92.25) localEye=(7.43,2.51,-1.77) |
p0->0x0175 D=-1.41 TRV proj=0 clip=-1 || outPolys=0 vis=1
[flap-cam] root=0xA9B40174 viewerCell=0xA9B40174 playerCell=0xA9B40174
... terrain=Skip outVisible=False
[render-sig] frame=49 branch=RetailPViewInside root=0xA9B40174
... terrain=Skip/skip sky=n zclear=n sceneParticles=none
outSlices=0 outPolys=0 ids=[0xA9B40174] draw=[0xA9B40174]
```
Meaning:
- The player/viewer/root are in cellar cell `0174`.
- The only visible portal to stair connector `0175` is traversable.
- Projection produces zero vertices.
- The PView flood stops at the cellar.
- Only the cellar draws; stair/main-floor cells are not in the visible set.
This is a direct candidate cause for missing floor/grey composition.
### Root 0172: outside view toggles on/off
From `launch-pview-watermark-probe.log`:
```text
frame=3625 root=0xA9B40172
p0->0x0173 D=... TRV proj=4 clip=4
p1->0x016F D=5.28 TRV proj=0 clip=-1
outPolys=1 vis=6
ids include 0xA9B40170
terrain=Skip/draw sky=Y zclear=Y
frame=3626 root=0xA9B40172
p0->0x0173 D=... TRV proj=5 clip=5
p1->0x016F D=5.39 TRV proj=0 clip=-1
outPolys=0 vis=5
ids missing 0xA9B40170
terrain=Skip/skip sky=n zclear=n
frame=3647 root=0xA9B40172
outPolys=1 ids include 0xA9B40170 terrain draw
frame=3648/3649 root=0xA9B40172
outPolys=0 ids missing 0xA9B40170 terrain skip
```
Meaning:
- The same root cell can alternate between seeing outside and not seeing outside.
- `0x016F` is involved in the root flap line but projects to zero.
- Sometimes `0x0170` becomes reachable and outside terrain/sky/depth clear run; sometimes it disappears.
- The visible-cell list and outside-view list are not stable.
Open question:
- Is `0x016F` an outdoor/land cell, an env cell lookup miss, or a portal that retail handles differently?
- Is the toggling caused by projection/clip degeneracy, wrong portal reciprocal handling, update-count propagation, or camera/viewer-cell root?
### Earlier known evidence: root 0171 vs player 0174 contradiction
From the older `2026-06-05-shell-sealing-cellar-floor-handoff.md`:
```text
[flap-cam] root=0xA9B40171 viewerCell=0xA9B40171 playerCell=0xA9B40174
...
[flap] root=0xA9B40171 ... p1->0173 proj=0 ...
```
Meaning:
- Earlier, camera/root was the room while player was cellar.
- The flood did not seal the player's cell.
- Later, after branch/viewer changes, there are also frames where root/player/viewer are all `0174` but the flood still fails on `0174 -> 0175`.
This means the problem is probably not only "wrong root"; it also includes projection/portal traversal/flood propagation or mesh-shell handling.
## What Not To Retry Blindly
Do not simply:
- switch the root to player cell as a workaround;
- widen `EyeStandingPerpDist` further;
- globally draw all indoor shells;
- globally draw terrain/entities/particles while inside;
- turn off all clipping and hope depth sorts it;
- keep adding `if cellar` or Holtburg-cottage-specific handling;
- claim "no hybrid" without auditing all `GameWindow` indoor/outdoor passes;
- equate unit-test pass with visual correctness.
The user has explicitly asked for retail smoothness, not a new patch stack.
## Likely Root Problem Space
The next fix probably lives in one of these, but evidence must decide:
1. **PView graph construction is not retail-faithful.**
- Missing or wrong `update_count` / `FixCellList` / `AdjustCellView`.
- Wrong draw-list ordering when a processed cell receives new views.
- Downstream portal propagation incomplete.
2. **Portal projection/clip behavior differs from retail.**
- `0174 -> 0175` traversable but `proj=0`.
- `0172 -> 016F` traversable but `proj=0`.
- `OtherPortalClip` / `GetClip` may not match retail.
3. **Outdoor/exit portal classification is wrong.**
- `OtherCellId=0xFFFF` is treated as exit/outside, but `0x016F` may be another kind of outside/land portal or missing env cell.
- OutsideView may be created through a downstream path that acdream sometimes drops.
4. **Renderer draw setup is still hybrid or ordered wrong.**
- `GameWindow` may still draw or skip global passes inconsistently.
- Sky/terrain/depth clear decisions are visibly flapping with `outside_view`.
5. **EnvCell shell mesh/surface handling is wrong.**
- Missing/transparent/white walls and floors may be mesh/surface/cull-side regressions.
- Audit `ObjectMeshManager` side handling against retail and DAT dumps.
6. **GPU clip slots are being used as membership or hard clipping when retail uses view setup differently.**
- Character cut in half on stairs strongly suggests hard clip-plane use on avatars/shells is wrong or applied at wrong pass.
## Suggested Next Procedure
1. Stop patching. Inspect the dirty diff first.
2. Read `docs/research/2026-06-05-retail-pview-indoor-render-pseudocode.md`.
3. Re-read named retail functions listed above.
4. Parse `launch-flap-shell-capture-relaunch.log` and `launch-pview-watermark-probe.log` around the cited frames.
5. Add better probes if needed:
- cell id;
- portal index;
- other cell id;
- portal flags;
- other portal id;
- traversable decision;
- standing distance;
- projection vertex count;
- clip vertex count;
- reciprocal clip result;
- outside-view add/skip reason;
- cell view count / processed count / update count;
- queue/requeue reason;
- draw-list insertion/reorder.
6. Decide from evidence whether `0174 -> 0175` and `0172 -> 016F` fail because of projection, reciprocal clip, cell lookup/classification, or update propagation.
7. Patch only the retail mismatch.
8. Build/test before launch.
9. Launch with probes once.
10. Then launch clean for FPS/visual feel.
11. Do not call it done until the user visually confirms retail smoothness.
## Launch Command
Use PowerShell:
```powershell
Get-Process -Name AcDream.App -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep -Seconds 3
$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 -FilePath "launch-next-pview.log"
```
For clean visual/FPS run, remove the probe env vars.
## Minimal Prompt For Next Agent
```text
Continue acdream M1.5 indoor render in SAME worktree:
C:\Users\erikn\source\repos\acdream\.claude\worktrees\thirsty-goldberg-51bb9b
branch claude/thirsty-goldberg-51bb9b. Do NOT branch/worktree. Do NOT push. NEVER stash/gc.
The current dirty render code is not visually accepted. The user stopped the prior agent after repeated regressions.
Read docs/research/2026-06-06-retail-pview-renderer-replacement-attempts-handoff.md first.
Current symptoms: transition flaps still happen indoor/outdoor, room/room, cellar; ground floor is now transparent; cellar broken; prior runs showed grey/black clear color, missing wall textures, and character cut on stairs.
Do not patch first. Audit dirty diff, read named retail PView, parse launch-flap-shell-capture-relaunch.log and launch-pview-watermark-probe.log. Determine exactly why:
1) cellar root 0174 fails to traverse 0174 -> 0175 when proj=0;
2) root 0172 toggles outside_view/0170 reachability while 0172 -> 016F has proj=0;
3) shell/object/terrain/depth-clear decisions disagree.
Patch only the retail mismatch. Build/test before relaunch. Do not claim success before user visual confirmation.
```