# HANDOFF — Indoor crossing flap: MEASURED vs HYPOTHESIS vs OPEN (read before ANY code) **Date:** 2026-06-08 (late). **Branch:** `claude/thirsty-goldberg-51bb9b`. **HEAD:** the `docs(render): plan status` commit (after `c7069cf`). Working tree clean. --- ## ⚠️ 0. CALIBRATION NOTE — read this first This session's diagnosis of the indoor flap **shifted four times** as measurements came in: `per-building` → `camera-jitter (R-A4)` → `camera swept/published eye` → `flood edge-on`. **Each "confident" claim was refuted by the NEXT measurement, in the same session.** The author (me) also stated a final scoreboard ("conclusively pinned / camera ruled out") with **more confidence than the data earns.** So this handoff is structured to **prevent the next session from inheriting an overclaim:** - §2 = **MEASURED** (high confidence, with the data + file refs). - §3 = **LEADING HYPOTHESIS** (medium — explicitly NOT isolated). - §4 = **ALTERNATIVE NOT RULED OUT** (a real competing explanation I waved away). - §5 = **WHAT TO VERIFY FIRST** — do this BEFORE building anything. Do not trust §3 until §5 confirms it. - §6 = **DO-NOT** (genuinely refuted, high confidence — safe to not re-try). **The honest one-liner:** the flap is a **motion-time** grey-flash at openings; eye-jitter-at-rest is ruled out (measured); but whether the cause is the **clip math at edge-on** (§3) or the **camera not pulling the eye in like retail** (§4) is **NOT yet disambiguated** — the one "clean" pass wasn't clean enough (it had back-and-forth). Disambiguate (§5) before choosing the fix. --- ## 1. What SHIPPED this session (all green, visual-confirmed by the user) | Commit | What | Verified | |---|---|---| | `7fe9809` | R-A1 — canonicalize outdoor root on `LoadedCell.IsOutdoorNode` (behavior-preserving) | tests | | `c62663d` | R-A2 — per-building floods (`ConstructViewBuilding`; `OutdoorCellNode` portal-less; per-building merge in `RetailPViewRenderer.DrawInside`) | **user: outside-looking-in flap GONE** | | `2ec189c` | R-A2 seam fix — flood null-`BuildingId` cells (don't drop) | **user: missing textures GONE** | | `3c178b2` | `tools/cdb/flap-cam-measure.cdb` — retail eye + CameraManager capture | apparatus | | `c7069cf` | `[flap-sweep]` probe: F6 `in=`(desiredEye) / `out=`(eye) | apparatus | | `docs…` | plan-doc STATUS note (R-A4 ruled out) | docs | Test baseline: App `~Rendering` **207**, Core `PlayerMovementControllerTests` **14**. Build green. Plan: `docs/superpowers/plans/2026-06-08-full-retail-render-port-option-a.md`. **The user's remaining symptom (verbatim):** *"grey background color flapping entrances between rooms and cellar entrance and when going outside."* I.e., the clear/background color flashes through openings during MOTION; at rest it does not flap. --- ## 2. MEASURED FACTS (high confidence — data + file refs) ### 2.1 acdream eye at REST ≈ 1 µm stable (NOT a jitter problem) `flap-cam-measure.log` (acdream run, user held completely still, 768 samples). Last 150 frames: `in` (desiredEye) Y range **0.000 mm** (1 distinct value); `out` (eye) Y range **0.001 mm** (2 distinct); `pulledIn=0`. → The convergence snap (`RetailChaseCamera.ApplyConvergenceSnap`, `SnapEpsilon 0.0004`) holds; there is **no at-rest jitter**. (acdream at rest is actually steadier than retail's settled eye.) ### 2.2 The earlier "~1.3 mm jitter at rest" was MOTION misread as rest `launch-flap-pin2.log` `[pv-input]` showed ~1.3 mm; that was during the crossing. The F2-precision print rounded sub-cm walking to "d=0", which I mis-analyzed as a static eye. **The flap is motion-time only.** ### 2.3 On a (mostly) one-way pass: eye SMOOTH, but visible-cell count OSCILLATES `launch-camprobe.log`, the clean-pass tail (~25.7k sweep frames): - **Eye:** 3D path = 34.1 m, net = 8.2 m (**ratio 4.2×**), direction reversals **X=3, Y=18** (i.e. few large direction changes — the motion is smooth, not jittery). - **Visible cells (`[flap] vis=`):** oscillated **414×** between **1 and 6**; **648 `clip=0`** events. Distribution `1:4084 2:6300 3:3860 4:10634 5:439 6:427`. Roots: `0171` (room) 21396, `0031` (outdoor) 4084, others tiny. - **⚠️ CAVEAT (why this is NOT isolated):** ratio 4.2× means the pass was **not** purely one-way — it had back-and-forth + indoor↔outdoor. The 414 oscillations therefore **mix** (a) indoor-flood oscillation (root `0171`, vis 2↔6) AND (b) indoor↔outdoor **root swaps** (`0171`↔`0031`, the "going outside" grey; the 4084 vis=1 frames are root `0031` = legitimately just the outdoor node). These were **not separated.** So "smooth eye + oscillating vis ⇒ flood bug" is **indicated but not proven** — some of the oscillation is the back-and-forth and the root-swap. ### 2.4 Retail eye at the cottage doorway: COLLIDED 93%, settled jitter ~tens of µm `flap-cam-measure.log` (retail, `acclient.exe`, PDB **MATCH** `refs/acclient.pdb`), 768 samples: - **`pub != sought` 716/768 = 93% COLLIDED** — retail's boom hits the cottage; the eye is pulled toward the player (a more **head-on** view of the doorway, not floating 3 m back). - Settled jitter (quarters Q2–Q4) ≈ **93 µm**; Q1's 1.4 mm was the user walking up (settling motion), verified by the quarter split. - Offsets: `CameraManager.t_stiffness@+0x08`, `r_stiffness@+0x0c`, `viewer_offset@+0x48`; `SmartBox.camera_manager@+0xa0`. acdream's damping already matches retail's formula (`alpha = clamp(stiffness·dt·10,0,1)`, stiffness 0.45) — `RetailChaseCamera.ComputeDampingAlpha`. --- ## 3. LEADING HYPOTHESIS (medium confidence — NOT isolated; see §2.3 caveat) The flood/clip's **"is the room behind this opening visible?"** decision is **non-monotonic near a doorway's EDGE-ON angle.** The portal projects to an on-screen area that hovers at ~zero (coin-on-edge); small smooth eye steps flip the clip 0↔nonzero → the cell behind drops → grey flash. This matches the "grey at room↔room / cellar entrances." Mechanism candidates inside this hypothesis: `ProjectToClip` / `ClipToRegion` collapsing at edge-on (`PortalProjection.cs`), and/or the band-aids `MaxReprocessPerCell` (D4) + `EyeInsidePortalOpening` (D5) re-processing differently frame-to-frame during motion. --- ## 4. ALTERNATIVE NOT RULED OUT (a real competing explanation) **The edge-on viewing might be a CONSEQUENCE of the camera not pulling the eye in like retail.** §2.4: retail's eye is **collided 93% (head-on)**; acdream's `[flap-sweep]` showed it **uncollided much more often (floats free, 3 m back → edge-on view of the doorway)**. A doorway viewed edge-on is exactly when the clip collapses. So the root cause could be **camera collision / eye position** (acdream's spring-arm not pulling in where retail's does), NOT the clip math. - **What IS ruled out:** eye-jitter / wobble / at-rest instability (§2.1, §2.3 — smooth + 1 µm). - **What is NOT ruled out:** eye **position** (collision pull-in). These are different. I conflated them in the scoreboard. Disambiguate in §5.2. - Separately, the **"going outside" grey** is the root `0171↔0031` wholesale swap (§2.3) — likely a distinct sub-issue (indoor↔outdoor root transition), not the same as the room↔room edge-on flap. --- ## 5. VERIFY FIRST — before building ANY fix (this is the anti-overclaim gate) 1. **Isolate pure indoor-flood oscillation.** Do a **genuinely one-way, slow** walk through **ONE interior doorway** (room→room), **no going outside, no back-and-forth, camera fixed**. Capture `ACDREAM_PROBE_FLAP=1`. Confirm whether `vis` (root `0171` only) oscillates 2↔6 for a **monotonic** eye (check `[flap-sweep] out=` is monotonic — ratio ≈ 1, ~0 reversals). **If it does NOT oscillate when the eye is truly monotonic → the flap was the back-and-forth / root-swap, not a flood bug** (then §3 is wrong). The clean pass in §2.3 had ratio 4.2× — not clean enough to conclude. 2. **Disambiguate clip-math (§3) vs camera-position (§4).** At the SAME interior doorway, measure acdream's eye-to-doorway angle vs retail's (collided) — is acdream viewing it edge-on where retail views it head-on (because retail's eye is pulled in)? Add the doorway-plane signed distance + the collide state to `[flap-sweep]`. If acdream floats edge-on where retail pulls in → the fix is the **camera collision**, not the flood. 3. **Read retail's edge-on clip handling (the fix ORACLE — do NOT guess the fix without this):** `PView::GetClip` (`0x5a4320`, decomp ~`:432344`), `PView::ClipPortals` (`0x5a5520`, `:433572`), `ACRender::polyClipFinish` (the w=0 clip, `:702749`). Questions: does retail's clip collapse to zero at edge-on like ours, or stay robust? Does retail keep a flooded cell once added? Cross-check `PortalProjection.cs` (our port — handoff says it's faithful; verify at edge-on specifically). --- ## 6. DO-NOT RETRY (genuinely refuted this session — high confidence) - **Camera eye-JITTER / R-A4 stiffness change.** Eye is smooth (3/18 reversals) + 1 µm at rest (§2.1, §2.3). acdream's damping already matches retail's stiffness 0.45. Do not "reduce jitter." - **RenderPosition rest-snap** (`cd974b2`, reverted). The eye isn't the jitter source; at rest it's 1 µm. - **"1.3 mm jitter at rest"** — it was MOTION (§2.2). - **A robust-MEMBERSHIP scheme retail lacks.** Retail's flood is clip-driven too — `PView::add_views` (`0x5a5210`) only pre-pushes view slices onto the stab_list cells via `curr_view_push`; it does NOT ground `cell_draw_list` membership. So the robustness must live in the **clip's edge-on behavior** (§3) or the **camera position** (§4), NOT a stab_list membership-grounding. - **Two-pipe inside/outside split; bounded-propagation/churn; byte-stable eye** — all refuted earlier (see the 2026-06-08 OPTION-A handoff §7). --- ## 7. The fix (R-A2b) — GATED on §5 Do NOT design until §5 disambiguates. Two branches: - **If §5.1 + §5.3 show the clip collapses at edge-on (clip-math):** port retail's edge-on clip robustness into `PortalProjection` / `PortalVisibilityBuilder`; conformance-test "smooth monotonic eye through a doorway ⇒ monotonic vis (no oscillation)"; visual-gate. - **If §5.2 shows acdream's eye floats edge-on where retail pulls in (camera-position):** the fix is the camera collision (`PhysicsCameraCollisionProbe.SweepEye` / `RetailChaseCamera`) — make the eye pull in like retail (93% collided at the doorway). This is the camera **position**, distinct from the ruled-out eye-jitter. - The "going outside" grey (§4, root `0171↔0031` swap) is likely a separate, smaller task. --- ## 8. Apparatus (reuse — don't rebuild) - **acdream probes** (gated in `AcDream.Core.Rendering.RenderingDiagnostics`): - `ACDREAM_PROBE_FLAP=1` → `[flap]` (per-portal `D`/side-test `TRV/CULL`/`clip=` vertex count, `vis=`), `[flap-sweep]` (camera sweep: `pulledIn`, and **`in=`(desiredEye) / `out=`(eye) at F6** — added `c7069cf`), `[flap-cam]`. HEAVY (per-frame per-portal) — short captures only. - `ACDREAM_PROBE_PVINPUT=1` → `[pv-input]` (eye/player/rawPlayer F6 + flood count). Lighter. - **cdb on retail:** `tools/cdb/flap-cam-measure.cdb` (eye origin per frame `pub`+`sought` raw float hex + `CameraManager`/`SmartBox` type dumps). Attach: `Get-Process acclient` → pid; `cdb.exe -p -cf tools\cdb\flap-cam-measure.cdb`. Exit code **5 is expected** (clean detach). PDB `refs/acclient.pdb` — verify with `py tools/pdb-extract/check_exe_pdb.py "C:/Turbine/Asheron's Call/acclient.exe"` (MATCH). - **Logs (UNTRACKED, large — gitignore/delete):** `launch-camprobe.log`, `launch-flap-pin2.log`, `flap-cam-measure.log`, `launch-ra2.log`. - **Launch:** CLAUDE.md "Running the client" env block + `$env:ACDREAM_PROBE_FLAP="1"`. - **Build-while-client-running gotcha:** the running client locks the DLLs → build fails MSB3027. Close the client (graceful `CloseMainWindow`) before building. --- ## 9. Exact pickup (next session) 1. Read this doc top-to-bottom, then memory `project_indoor_flap_rootcause` (2026-06-08 late CORRECTION). 2. `git log --oneline -8` (HEAD = the plan-status docs commit). `dotnet build` green; App `~Rendering` 207 / Core `PlayerMovementControllerTests` 14 green. 3. **Do §5 FIRST** (isolate indoor-flood vs camera-position vs root-swap). **Do NOT write a fix until §5 tells you which of §3 / §4 is real.** This is the whole point of the calibration note. 4. Then §5.3 (retail clip oracle) → design the gated fix (§7) → conformance-test PRE-gate → visual-gate. 5. Strip the throwaway probes after the visual gate; update memory + the plan + milestones. --- ## 10. One-paragraph version (for when you're tired) Outside-flap and seams are FIXED and confirmed. The indoor flap is a motion-time grey-flash at openings. We MEASURED that it's not eye-jitter (eye is smooth + 1 µm at rest). We did NOT prove it's the clip math: the one "clean" pass had back-and-forth (ratio 4.2×) so the 414 oscillations mix flood-edge-on, back-and-forth, and indoor↔outdoor root-swaps. And we did NOT rule out the camera *position* (retail's eye is pulled-in/head-on 93% at the doorway; ours floats edge-on). So: isolate a truly one-way single interior-doorway pass, compare acdream's vs retail's eye angle at that doorway, and read retail's edge-on clip code — THEN choose between the clip-math fix and the camera-position fix. Don't pick one until those three are done.