acdream/docs/research/2026-07-06-177-stairs-pickup-handoff.md
Erik 0cbe1102d9 docs(#177): mark stairs pickup-handoff SUPERSEDED (flood theory disproven)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 10:10:53 +02:00

8.2 KiB
Raw Blame History

🅿️ SUPERSEDED 2026-07-07 — #177 is PARKED and this doc's premise is WRONG. The "portal-visibility miss" framing below was DISPROVEN by a live retail cdb trace (retail's flood collapses identically to ours). Do NOT follow the flood/clip workflow here. Current truth + the fresh lead (step statics) live in ISSUES #177 (session-3 + 3b blocks) and the render digest top banner. Kept only for the apparatus map.

Pickup handoff — #177 dungeon stairs pop in/out (portal-visibility miss at the stair cells)

Paste the companion prompt (bottom) into a fresh session. Read this file, then claude-memory/project_render_pipeline_digest.md (top banners), then ISSUES #177 (full entry — including the superseded lighting attribution and why it was re-attributed to VISIBILITY at the 2026-07-06 gate).

TL;DR — what #177 is

Facility Hub (0x8A02), the staircase connecting two levels (corridor 0x0178 → ramp 0x0182 → lower room 0x0183): (a) invisible looking into the stair room from the corridor, (b) pops into existence on entering the room, (c) the last step vanishes running down. The 2026-07-06 gate PROVED this is NOT lighting (the A7 visible-cell light fix shipped and the stairs were still missing looking back from the corridor) — it is a portal-flood admission miss: the stair cells are not reached by PortalVisibilityBuilder from the viewer's cell until the viewer crosses in. The digest tags it "#119 class, dungeon edition; floor-portal level links."

Acceptance: the staircase renders whenever its room is visible through the connecting opening, and stays rendered through the full descent.

Where to start (the apparatus already exists)

  1. tests/AcDream.App.Tests/Rendering/Issue176177FacilityHubFloodReplayTests.cs — headless flood replays against the REAL dat, with two scenarios written for exactly this issue and never fully mined:
    • Scenario A (stair approach): eye in corridor 0x0178 at several x positions + pitches, printing whether ramp 0x0182 / lower 0x0183 are admitted.
    • Scenario B (descent): eye path down the ramp, printing per-step admitted-set diffs (the "last step vanishes" case). Run these FIRST — the miss should reproduce headlessly, and the printed admitted sets name which portal hop fails.
  2. Issue181VisFlapReplayTests.cs — the same-file pattern for perturbation sweeps + per-cell view-region AREA measurement (the shoelace diagnostic). Cell 0x8A020181 — right next to the stair complex 0x0182/0x0183 — rides a knife-edge zero-area admission; the #177 miss and the #181 sliver are plausibly the SAME flood defect seen two ways (a floor-portal chain that clips to nothing from above).
  3. The builder: src/AcDream.App/Rendering/PortalVisibilityBuilder.cs. The admission gates per portal hop, in order: the side test (CameraOnInteriorSide, PortalSideEpsilon 0.01 — AP-19), then ClipPortalAgainstView (homogeneous clip against the parent's accumulated region; clippedRegion.Count == 0 ⇒ the flood stops there). For a DOWNWARD stair chain the suspect class is the FLOOR-portal hop: a horizontal portal seen edge-on from the corridor clips to ~zero area (exactly the 0x0181 sliver signature) and the chain below never floods. ACDREAM_A8_DUMP_PV=1 dumps per-portal census + EXIT-PROJ/EXIT-CLIP lines for the camera cell (first 2 builds per cell).
  4. Retail oracle: retail PView floods portals with per-poly clip (polyClipFinish — the W=0 clip pseudocode doc 2026-06-11) and DOES show stair rooms through their openings. If our clip collapses a genuinely-visible aperture to zero, compare ClipPortalAgainstView against PView::ClipPortals/GetClip (decomp:433572) at the failing hop's exact geometry. #119's lesson applies: visibility must derive from the same data that gets drawn (feedback_culling_bounds_from_drawn_data).

What tonight's #180/#181 session gives you for free

  • All camera/sweep mechanisms are Ghidra-verified faithful (stateful sought, adjust_to_plane, adjust_sphere_to_poly, viewer radius-anchored stepping) — commits 48aaab81/f10fe4e9/3f34bca0. The camera's ViewerCellId is trustworthy; the render roots at it (Option A).
  • The wall-pressed camera wanders ~0.5 mm/frame in a bit-exact 12-frame limit cycle (Issue181WallPressEquilibriumTests — measured, all local algorithms verified; plausibly retail-class). Any admission knife-edge within that wobble band flaps ~10 Hz ([flap] vis 31↔32, whole-session). For #177 this matters at stair THRESHOLDS: expect flappy admission exactly at descent transitions.
  • Lighting is now retail-shaped: resident+player-anchored pool (d8984e87), idempotent re-apply (87cddce2), stationary fixtures on the verified static curve (233b469b). Do NOT re-open lighting for #177 — the gate already refuted it.
  • #181 is PARKED (see its ISSUES entry for the still-open leads). Do not resume it inside the #177 arc; if stair work surfaces new flicker evidence, append to #181's entry instead.

Watchouts

  • The old #177 root-cause text (128-cap light eviction) is SUPERSEDED — kept in the entry for history. The re-attribution is the ⚠️ UPDATE block at the top of #177.
  • The flood replay's ViewProj must match production FOV/aspect (π/3, 16:9) — the Issue181 test does; the older Issue176177 scenarios use 1.2 rad / 1280×720 (fine for admission questions, but keep in mind for NDC-sensitive comparisons).
  • Issue120ReciprocalPingPongTests.LoadAllInteriorCells + CornerFloodReplayTests. ResolveDatDir are the shared fixtures loaders (App.Tests); Core.Tests has its own ConformanceDats.
  • A client may be running — the user manages its lifecycle; ASK before rebuilding if the App DLL is locked (MSB3027 = lock, not code).

State

  • Branch claude/vigorous-joliot-f0c3ad @ 233b469b+ (this handoff's commit). Suites green: Core 2600+2skip / App 733+2skip / UI 425 / Net 385 / Content 56.
  • Test char spawns in the Facility Hub corridor (0x8A020142 area); the stair complex is 0x0178/0x0182/0x0183 (+0x0181 adjacent).
  • Launch recipe + graceful-close rules: CLAUDE.md "Running the client". The GDI-capture + keybd_event autonomous visual loop scripts live in this session's scratchpad (capture-still.ps1, imgdiff.ps1, imgdiffmap.ps1, crop.ps1) — recreate from the #180 handoff's recipe if the scratchpad is gone.

Companion prompt (paste into the fresh session)

Fix #177 — Facility Hub stairs pop in/out across levels (invisible from the
corridor, pop on entry, last step vanishes running down). The 2026-07-06 gate
re-attributed this from lighting to a PORTAL-FLOOD ADMISSION MISS at the stair
cells (0x8A020178 corridor → 0x0182 ramp → 0x0183 lower; 0x0181 adjacent) — do
NOT re-open lighting (gate-refuted; the A7 fixes are in and verified).

READ FIRST, in order:
1. docs/research/2026-07-06-177-stairs-pickup-handoff.md (apparatus map, the
   #181 park boundary, watchouts)
2. claude-memory/project_render_pipeline_digest.md (top banners)
3. docs/ISSUES.md #177 (the ⚠️ UPDATE block supersedes the old root cause)

START by running the existing headless replays (Issue176177FacilityHubFloodReplay
Tests Scenarios A/B — real dat, no client): they print per-pose admitted sets for
the stair cells and should reproduce the miss offline. Then trace the failing
portal hop through PortalVisibilityBuilder's gates (side test → ClipPortalAgainst
View; the floor-portal seen edge-on clipping to ~zero area is the suspect class —
the same signature as #181's 0x0181 sliver next door). Retail oracle for the clip:
PView::ClipPortals/GetClip (decomp:433572) + the 2026-06-11 polyClipFinish W=0
pseudocode doc. Workflow: replay → identify the gate → read retail → pseudocode →
port → the replays become pins → autonomous visual loop (stair approach/descent
drive) → user gate.

#181 (the pressed-camera flicker) is PARKED with its evidence ledger in ISSUES —
if stair work surfaces flicker evidence, append there; don't resume it in this arc.

State: branch claude/vigorous-joliot-f0c3ad, suites green (Core 2600+2skip / App
733+2skip). Test char spawns in the Facility Hub corridor. A client may be
running — the user manages its lifecycle; ASK before rebuilding if the App DLL
is locked.