Retail SEAMLESS at the same spot (user-confirmed) => real acdream bug: the eye seats in a sparse 5-poly connector cell 0xF6820118 looking back at the player's room 0116, and acdream drops 0116 (back-portal side-culled) so the doorway aperture shows the fog clear color = grey; retail keeps 0116 drawn. RULED OUT: null-root/AD-20/AD-21 (root valid, eyeInRoot=Y); the color-clear gating (retail's gated DrawCells Clear is depth/stencil, post-LScape::draw). Next step = retail cdb trace (viewer_cell + cell_draw_list at the grey pose) to pin viewer-cell PICK vs portal FLOOD, then a careful frozen-render fix. Full handoff + apparatus + DO-NOT-RETRY + code/decomp sites in the doc. Keeps the offline cell-geometry inspection test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 KiB
Handoff: #186 — indoor GREY flap at a top-floor connecting room (new house type)
Date: 2026-07-08 · Status: ROOT CAUSE NARROWED (report-only) — fix NOT started. It lives in the FROZEN portal-flood / viewer-cell render code (the doorway-FLAP family that cost weeks), so it needs a retail cdb trace to pin the last fork BEFORE any code, then a careful change. Milestone: M1.5.
Read these first, in order:
- This handoff.
claude-memory/project_render_pipeline_digest.md— the render/doorway-FLAP SSOT + DO-NOT-RETRY table ("root at VIEWER cell"; the deleted EyeInsidePortalOpening rescue; PortalSideEpsilon root-lag).docs/architecture/retail-divergence-register.mdrows AD-17 (≤8 clip-plane / union-AABB scissor), AD-20 (camera-sweep fallback seeds eye cell from PLAYER cell), AD-21 (null-clipRoot outdoor fallback).docs/ISSUES.md#186.
0. Symptom (user, live)
Top floor of a house type not tried before; a connecting opening/room between two parts of the house. Passing through → a brief GREY flap (the framebuffer clear color). Stopping at the precise spot → the WHOLE screen is grey and stays; turning the camera clears it, turning back → grey again (camera-DIRECTION dependent, player stationary). A jump is NOT involved (that's #185). Retail is SEAMLESS at the same spot (user-confirmed) → this is a real acdream bug, not inherent.
1. The cells + the grey pose (ACDREAM_PROBE_FLAP capture)
Landblock 0xF682. Three cells, all envId 0x0365, cell-struct origin (132,84,62):
| cell | render polys | physics polys | portals | role |
|---|---|---|---|---|
0xF6820116 |
15 | 12 | →0117,0118,0113 |
player's room (closed) |
0xF6820117 |
10 | 6 | →0118,0116,0115,0119 |
next room (closed) |
0xF6820118 |
5 | 3 | →0117,0116 |
thin connector (root when grey) |
Grey-pose facts (from [flap]/[flap-cam]/[flap-sweep], 88,249 frames; the grey frames are vis=1
root=0xF6820118, ~6,725 frames):
[flap-cam]:root=viewerCell=0xF6820118 playerCell=0xF6820116 eyeInRoot=Y playerInRoot=n terrain=Skip outVisible=False eye=(134.81,83.59,69.07) player=(137.30,83.32,66.82).[flap]grey line:root=0118 | p0->0x0117 D=0.14 TRV proj=4 clip=0 | p1->0x0116 D=0.18 CULL proj=5 clip=4 || outPolys=0 vis=1. (Dominant D to 0117 ≈ 0.14; ALWAYS positive 0.00–0.50 → eye is genuinely INSIDE 0118, never across the plane.)[flap-sweep]:ok=True resolved=Y pulledIn=-0.00(the chase boom reaches FULL distance, NO collision pull-in, seating the eye in the connector).
Read of the geometry: the eye sits in the sparse connector 0118, in the doorway threshold, looking
BACK toward the player's room 0116. p1->0116 is ON-screen (proj=5 clip=4) but side-CULLED (eye ~0.18–0.31
on 0116's side of the p1 plane — a back-portal). p0->0117 is genuinely OFF-screen (clip=0 with proj≥3
= off-screen per the builder's own probe doc, PortalVisibilityBuilder.cs:818-821). So no neighbour floods,
only the 5-poly connector draws, and its shell doesn't cover the forward view → the framebuffer clear color
(fog, GameWindow.cs:8968) shows through = GREY. Turning re-aims off the back-portal → a room floods → picture.
2. What is CONFIRMED / RULED OUT (workflow wf_362bbeda-933, 4 tracers + synthesis, + my own re-checks)
- ❌ NOT null viewer-root / AD-21 — the render root is a valid indoor cell on 88,248/88,249 frames
(one lone
[outdoor-node] root=OUT). (This refutes THE FIRST hypothesis in this investigation.) - ❌ NOT viewer-cell root-lag / AD-20 —
eyeInRoot=Yat every grey frame: the eye is geometrically INSIDE0118's BSP. The root is the fresh eye-derived sweptcurr_cell(PhysicsCameraCollisionProbe.cs:92), NOT a stale player-seeded fallback. (Refutes the workflow synthesis's own leading "31 cm gap" theory — the eye is NOT across the boundary; I checked theeyeInRootflag directly.) - ❌ NOT the flood-admission being unfaithful — the empty-clip cull (
PortalVisibilityBuilder.cs:320-324) and the back-portal side-CULL (:292-298,CameraOnInteriorSide :857-863) are faithful ports: retailPView::ClipPortalsgates neighbour processing onif (ecx_8 != 0)(pc 005a5660) andAddViewToPortalsonview_count != 0(pc 005a5357). #177 already proved acdream's flood is retail-identical. - ❌ NOT the color clear (the tempting "3-line fix" — DEAD END, do not revisit). Retail's DrawCells
(
0x005a4840, decomp line 432709) has its onlyClearINSIDEif (outside_view.view_count > 0)(line 432715), right AFTERLScape::draw(the landscape draw, 432719). The Clear isClear(4, &RGBAColor_Black, 1.0f)(0x820fc0 = RGBAColor_Black) — but clearing COLOR after drawing the landscape would erase it, so that4flag is depth/stencil, not color. So retail's color clear is NOT gated here, and matching "don't color-clear a sealed interior" would be WRONG. (This is why I did the cdb prep — it killed a wrong fix before shipping.) - ✅ It IS a real acdream bug (retail seamless) in the doorway-FLAP flood/pick family: acdream drops
the room the camera looks back at (
0116) from the connector root; retail keeps it drawn.
3. THE ONE OPEN FORK → the retail cdb trace (do this FIRST in the new session)
Retail is seamless, so retail either (A) roots at the player's room 0116, not the connector (a
viewer-cell PICK divergence — acdream over-switches to 0118), or (B) roots at 0118 but its flood still
admits 0116 (a FLOOD divergence — retail keeps the back-portal / uses an on-screen sliver acdream drops).
Static decomp cannot decide; observe retail.
Toolchain (CLAUDE.md "Retail debugger toolchain"; binary CONFIRMED pairs with refs/acclient.pdb via
py tools/pdb-extract/check_exe_pdb.py "C:/Turbine/Asheron's Call/acclient.exe" → MATCH).
- User: launch retail, connect to local ACE, walk to the SAME connecting room, and HOLD the grey pose (so most captured frames are it).
bp acclient!SmartBox::update_viewer(0x00453ce0) → dumpviewer_cell(aCObjCell*,acclient.h:35194) and its cell id. AND/ORbp acclient!PView::DrawCells(0x005a4840) → dumpcell_draw_num+cell_draw_list.data[]ids (acclient.h:45939-45940) — the drawn cell set.- Decide: retail
viewer_cell == 0116→ PICK fix (acdream's viewer-cell pick/hysteresis over-retains the connector —CellTransit.cs:862-916 BuildCellSetAndPickContaining, or the camera boom coasting the eye into the connector atpulledIn=-0.00where retail's PathClippedviewer_spheresweep hard-stops in0116). retailviewer_cell == 0118butcell_draw_list⊇0116→ FLOOD fix (retail admits the back-portal from the connector; acdream's side-CULL / the deleted EyeInsidePortalOpening rescue is the site). - cdb watchouts (CLAUDE.md):
qdONLY at a top-level threshold, never inside a conditional bp action (strands cdb → kills retail);dt acclient!Class @ecx fieldfor reads (@@c++is broken here);.sympath <local>(nosrv*, the;splits); spaced.if ()letsqddetach.
4. Apparatus (re-create in the new session — temp files won't persist)
- Flap capture: launch acdream with
ACDREAM_PROBE_FLAP=1(canonical live cmd, CLAUDE.md). Emits per frame:[flap](root + per-portal proj/clip/side,PortalVisibilityBuilder.cs:790),[flap-cam](root/viewerCell/playerCell/eyeInRoot/playerInRoot/terrain/outVisible,GameWindow.cs:11142-11152),[flap-sweep](ok/resolved/pulledIn/viewerCell,PhysicsCameraCollisionProbe.cs:74-87),[outdoor-node](root=IN/OUT). ⚠️ heavy (per-frame); output goes to the raw background-task.output, not the Tee'd log. Have the user HOLD the grey pose + turn to clear + turn back a couple times. - Offline cell geometry dump:
tests/AcDream.Core.Tests/Physics/Issue186ConnectorCellGeometryInspectionTests.cs(Dump_ConnectorCells_ShellAndCollision) loads0116/0117/0118from the dat and prints render/physics poly counts + normal-axis buckets. No live launch needed. (That's how the §1 table was produced.) - Decomp workflow:
wf_362bbeda-933(this session) — the 4-tracer + synthesis analysis; results in its journal under the session'ssubagents/workflows/dir.
5. DO-NOT-RETRY (each already refuted or a known trap)
- Do NOT re-open the null-root / AD-20 / AD-21 angle — root is valid,
eyeInRoot=Y. - Do NOT implement the color-clear gating — retail's gated
Clearis depth/stencil (post-LScape::draw); matching it would add non-retail stale-content. - Do NOT re-add the deleted
EyeInsidePortalOpeningrescue (PortalVisibilityBuilder.cs:314-319) blindly — it caused the0171↔0173flood-cycle churn (the ORIGINAL doorway flap). - Do NOT widen
PortalSideEpsilon(:38-56) — a documented root-lag band, NOT retail (F_EPSILON=0.0002); BR-4 refuted tightening/widening without eye-exact tracking. - Do NOT "fix" the flood by propagating an empty/edge-on portal — the empty-clip cull is retail-faithful.
- The sparse connector geometry (
0118= 5 render / 3 physics polys) is FAITHFUL to the dat (retail draws the same). It is context, not the bug — the bug is that0116isn't drawn, not that0118is thin.
6. Key code sites
- Frame-top clear (unconditional color+depth+stencil to fog):
GameWindow.cs:8968-8983. NOT the fix. - Viewer-cell resolution:
GameWindow.cs:9137-9148(viewerCellId = _retailChaseCamera.ViewerCellId). - Camera boom sweep:
PhysicsCameraCollisionProbe.cs(SweepEye, PathClipped,pulledIn,r.CellId=curr_cell). - Viewer-cell PICK:
CellTransit.cs:862-916(BuildCellSetAndPickContaining, center-basedpoint_in_cell, current-cell-first hysteresis, port offind_cell_listpseudo_c:308788-308825). - Portal FLOOD:
PortalVisibilityBuilder.cs(Build; side-testCameraOnInteriorSide :857-863; empty-clip cull:320-324;PortalSideEpsilon :38-56; the off-screen-vs-sliver note:818-821).
7. Retail decomp anchors
PView::DrawCells0x005a4840(decomp line 432709): Clear gated onoutside_view.view_count>0(432715), Clear at 432732 (depth/stencil, post-LScape::draw); cells drawn unconditionally after (432815+).SmartBox::update_viewer0x00453ce0:viewer_cell = sphere_path.curr_cell(the render root = swept cell).PView::ClipPortalsempty-clip gateif(ecx_8!=0)pc 005a5660;AddViewToPortalsview_count!=0pc 005a5357.PView::InitCellside test decomp:432962.RGBAColor_Black@0x820fc0.
8. Acceptance
- No grey flap passing through OR stopping in the connecting room at any camera angle; matches retail's seamless.
- Regression: the outside→inside doorway + other multi-room houses + the #177/#181 render-flap suites unchanged.
9. Context: this session also FIXED #185 (unrelated, DONE + gated)
The outdoor-stairs "invisible wall" (07c5b832) — a shadow part-id uint32 overflow dropping stair collision.
Unrelated to #186 (that was collision/registration; #186 is render/visibility). See
docs/superpowers/specs/2026-07-08-185-outdoor-stairs-fix-design.md.