Canonical pickup for the next session. Membership root cause (static :1947 re-derive)
FIXED the retail way (find_cell_list interior-wins pick + swept determination, 59f3a13)
and offline-verified (doorway strobe -> one clean transition). T0 made the suite
deterministic (12 known failures, none Phase-W regressions). Stage 3 (render-root
unification) DONE (6a1fbbd->573c555). Remaining: Stage 4 (the seal: sky/landscape inside
the portal-clip bracket + conditional doorway Z-clear = no blue-hole), Stage 5 (entity/
particle clip), green-tests triage, then the single final visual verification. Render is
wire-and-fill-gaps (PView infra exists). Flags a stash discrepancy (1 of 2 stashes missing
from the shared refs/stash) for the user to check against other worktrees.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
13 KiB
Phase W (session 2) — Membership FIXED + render-rewrite handoff (2026-06-02)
Canonical pickup for the next session. This session found the root cause of the indoor cell-strobe and fixed it the retail way (offline-verified), then planned + began the render rewrite. Read this first, then the design doc + the render plan. The membership half is done; the render half is planned + partly executing.
0. Git / safety state — READ FIRST
- Branch
claude/thirsty-goldberg-51bb9b— UNPUSHED. Do not push without the user. - ⚠ STASH DISCREPANCY — investigate. Session START had 2 stashes; now there is 1
(
stash@{0}: …issue98-pre-triage-backup-20260523-145942). The#98/#101/A8-culling WIPstash (originallystash@{0}) is no longer listed.refs/stashis shared repo-wide across the user's many worktrees, and that stash's note said "pop to restore" — so it may have been legitimately popped by another worktree, OR dropped by a base-comparisongit stashtest in a subagent this session. Agit fsck --unreachablesearch did NOT surface it in this repo's dangling objects. Action for the user: check your other worktrees /git reflogfor it; recovery window is ~2 weeks (gc). Lesson: never let subagents rungit stashwhile pre-existing stashes exist — instruct them to use a fresh worktree or commit-to-temp-branch for base comparisons. - HEAD at handoff time =
573c555(Stage 3 complete). Stage 3 (render-root unification) DONE —6a1fbbd→573c555: deleted theFindCameraCellAABB grace-frame fallback, added theseen_outsidesky/terrain gate (retailCellManager::ChangePosition), addedCellGraph.FindVisibleChildCell, 6CellGraphRootTestsgreen. Build 0/0, App 160/160, Core 12-failure baseline unchanged (no new failures). Next: Stage 4. (git log --oneline -20.) - Throwaway untracked (delete freely):
baseline-w2a-*.png,shot-*.png,launch*.log.doorway-capture.jsonl(719 MB) was deleted this session — the committed fixturetests/AcDream.Core.Tests/Fixtures/issue98/doorway-threshold-capture.jsonlreplaces it.
1. Commit ledger (session 2, oldest→newest)
| SHA | What |
|---|---|
840c1b6 |
4-model research (3 in-tree + Codex) + Phase W design (transition-membership + PView render) |
50b168b |
chunk-1 plan (membership flicker fix) |
851cecc |
Stage 0 — [cell-swept] diagnostic (zero behavior change) |
3e1d502 |
Stage 1 — return swept sp.CurCellId from ResolveWithTransition (kept) |
2acd8f9→d23d1f4 |
W2b stab-list hysteresis (SHIPPED then reverted — wrong mechanism, wrong place) |
ed00719 |
design §1a — Stage-1 gate finding: deeper root is FindEnvCollisions:1947 |
59f3a13 |
MEMBERSHIP FIX — faithful find_cell_list (interior-wins pick + swept determination, drop static :1947) |
a06226f |
render-rewrite plan (Stages 3-5), grounded |
21ee5e1,fcea816 |
T0 — static-leak test isolation + portable doorway fixture |
6a1fbbd,3520860,38a52a7,573c555 |
Stage 3 DONE — render-root unification (delete FindCameraCell fallback; seen_outside gate; FindVisibleChildCell; 6 tests; no regressions) |
2. What's SOLVED — cell membership (the root cause)
The indoor 0170↔0031 doorway strobe (and 0170↔0171, cellar) is fixed, offline-verified.
- Root cause (airtight, code analysis): acdream re-derived the cell from the static sphere
position twice — once in
ResolveWithTransition's return (Stage 1 fixed that) and, the deeper one, inTransition.FindEnvCollisionsatTransitionTypes.cs:1947, which calledengine.ResolveCellId(staticOrigin,…)and clobberedsp.CheckCellIdevery sweep pass. Retail never re-derives statically — it carriessphere_path.curr_cellthrough the swept transition (validate_transitionadvances on an accepted move, reverts on a block) and commits it inSetPositionInternal. - The fix (
59f3a13), the retail way:CellTransit.BuildCellSetAndPickContaining— ported retailfind_cell_list's containing-cell pick (pseudo_c:308788-308819): interior-wins (first EnvCell whose BSP contains the center, stop), else the outdoor landcell via the XY-column test (which acdream had been skipping — the missing half that forced the:1947bolt-on).FindEnvCollisions:1947— replaced the staticResolveCellIdwith the sweptCellTransit.FindCellSet(...)(production /DataCache != null; the oldResolveCellIdstays only as a test-engine fallback). Gated downstream by the existing accept-on-move inValidateTransition(TransitionTypes.cs:3404).
- Offline verification: replaying the real captured doorway trajectory (committed fixture)
through the fixed engine gives one clean
0170→0031transition, no ping-pong (was a per-tick strobe).LiveCompare_FirstCap(#98 cottage-floor-cap) still passes. Not yet live-verified — folds into the single final visual gate. - A-vs-B is settled: "B" (transition-owned membership) was correct AND turned out small (the sweep already tracks the cell; the bug was the static re-derive). The "A" (post-sweep portal-crossing detector) was a non-retail invention — off the table.
3. Canonical artifacts
- Design:
docs/superpowers/specs/2026-06-02-phase-w-transition-membership-and-pview-render-design.md(§1 root cause, §1a the:1947finding, §2 render target, §5 risks, §6 acceptance). - Render plan (per-step, grounded):
docs/superpowers/plans/2026-06-02-phase-w-render-rewrite.md— T0 (done), Stage 3-5 + the green-tests triage. This is what the new session executes. - Membership plan:
docs/superpowers/plans/2026-06-02-phase-w-membership-flicker-fix.md(done). - Research:
docs/research/2026-06-02-retail-cell-render-study-{opus48-a,opus48-b,sonnet46,codex}.md- the shared prompt
…-research-prompt.md+ the evidence…-render-cell-membership-evidence.md.
- the shared prompt
4. Render rewrite — state + what's next
Key reframe (good news): the render half is wire-and-fill-gaps, NOT a from-scratch port.
The PView infrastructure already exists — PortalVisibilityBuilder (visible-set BFS +
OutsideView, enqueue-once gate, so #102's MaxReprocessPerCell is already gone), ClipFrame/
ClipFrameAssembler (the doorway clip), EnvCellRenderer GL_BLEND fix (already shipped U.4),
WbDrawDispatcher cell gate — and the old RenderInsideOut/ACDREAM_A8_INDOOR_BRANCH stencil
split is already gone (comments only). The gaps:
- Stage 3 (DONE
573c555) — root render atCellGraph.CurrCell+seen_outside; deleted the AABBFindCameraCellgrace-frame fallback;seen_outsidesky/terrain gate (retailCellManager::ChangePosition);CellGraph.FindVisibleChildCelladded. Interim state (expected, no user sees it before the final gate): sky may draw full-screen indoors until Stage 4 clips it. - Stage 4 (the seal) — draw sky/landscape inside the portal-clip bracket + the conditional
doorway Z-clear (depth only, not color → no blue-hole); verify ceilings + opaque walls.
Key gap found: sky currently draws BEFORE the clip bracket (
GameWindow.cs:~7268); move it in. - Stage 5 — clip entities/particles to the PView visible set (kills NPC/door/smoke bleed).
- Green-tests triage — see §5.
The plan has exact file:line change-points (verify — lines shift): physicsRoot/visibility
~GameWindow.cs:7162-7166; sky gate ~:7267; terrain gate ~:7406; FindCameraCell
CellVisibility.cs:389; grace :214; ComputeVisibilityFromRoot :356; EnvCellRenderer
GL_BLEND :1004-1023; PortalVisibilityBuilder.Build BFS+OutsideView :1-239.
5. The directives (CRITICAL — from the user, this session)
- NO intermediate user visual gates. Drive Stages 3→4→5 + triage to done. The per-stage "visual gates" in the plan are internal build+test-green checkpoints only.
- Single final visual verification — cottage AND a dungeon (sealed, sky/rain through the door, no blue-hole, no transparent walls, no bleed). That is the ONLY time to bring the user in.
- GREEN tests at verification — no broken/red tests when handed over. T0 made the suite
deterministic: exactly 12 failures. None are Phase-W regressions (the membership fix only
changed the returned cell id, not
ResolveResult.Position). Of the 12:- 3 document-the-bug (
DoorBugTrajectoryReplayTests×2,DoorCollisionApparatusTests) — reconcile per their stage. - 9 pre-existing tech debt (red before Phase W, unrelated):
MotionInterpreterTests.GetMaxSpeed×3 (method doesn't branch on command),BSPStepUpTestsB1/C3/D4 (step-up gaps),PlayerMovementControllerTests.Update_ForwardInput…,PositionManagerTests.ComputeOffset_BothActive…,DispatcherToMovementIntegrationTests.Dispatcher_W_held…. - Triage-to-green pass before the final gate: fix the stale ones (e.g. GetMaxSpeed test if
the no-branch behavior is intended), and for any genuine pre-existing gap that's out of Phase-W
scope (step-up), transparently flag it to the user — do NOT silently
[Skip]real-bug tests.
- 3 document-the-bug (
- Process:
superpowers:writing-plans(done) +superpowers:subagent-driven-development(each stage = a bounded subagent task + review). Sonnet implementers; Opus for load-bearing review.
6. Apparatus / how to reproduce
- Launch (per CLAUDE.md "Running the client") with
ACDREAM_PROBE_CELL=1(decisive[cell-transit], low volume) and/orACDREAM_PROBE_SWEPT=1([cell-swept]— swept cell per resolve, this session's diagnostic). Pipe viaTee-Object; the log is UTF-16 — read with PowerShellGet-Contentor the ripgrep Grep tool, NOT GNU grep. Screenshots: PowerShellCopyFromScreenonAcDream.App. - Cottage cells:
0171room (Z94),0175stairs (Z93),0174cellar (Z90),0170vestibule,0031/0032outdoor. ACE respawns at last logout (sometimes outside0031, sometimes in0171). - Offline membership verification (no walk): replay
…/Fixtures/issue98/doorway-threshold-capture.jsonl(57 records, the0170↔0031seam) throughResolveWithTransition, chaining the cell — seeDoorwayMembershipReplayTests.ACDREAM_CAPTURE_RESOLVE=<path>captures a fresh trajectory if needed.
7. Do-NOT-repeat / settled facts
- Membership is fixed — the
find_cell_listport (59f3a13). Don't re-investigate the strobe root; it's:1947(the static re-derive), now replaced by the swept pick. Don't reintroduce a staticResolveCellIdin the sweep. - A-vs-B settled: B, and it was small. No portal-crossing-detector invention ("A").
- Render infra already exists (PView builder, clip frame, GL_BLEND fix, cell gate); the A8 stencil split is gone. Render = wire + 3 gaps (root, sky-inside-clip + Z-clear, entity clip). Don't rebuild the PView builder or rip out a stencil pipeline that isn't there.
- The 12 test failures are NOT Phase-W regressions (position unchanged). Don't chase them as regressions; triage per §5.
- Earlier-disproven (do not revisit): camera/eye as root, stencil-mask, flag-based per-entity gate routing, W2b's stab-list-prune-in-ResolveCellId.
8. Pickup prompt (copy-paste)
PHASE W (Unified Cell Graph) — continue on branch claude/thirsty-goldberg-51bb9b (do NOT
branch/worktree; do NOT push without asking). FIRST: git log --oneline -20 + git status to see
where Stage 3 landed; AND check the stash discrepancy in the handoff §0 (one of 2 stashes is
missing — check other worktrees before doing anything that gc's objects).
READ FIRST: docs/research/2026-06-02-phase-w-membership-fixed-render-handoff.md, then the design
docs/superpowers/specs/2026-06-02-phase-w-transition-membership-and-pview-render-design.md and the
render plan docs/superpowers/plans/2026-06-02-phase-w-render-rewrite.md.
STATE: M1.5 "indoor world feels right." Cell-membership root cause FIXED the retail way
(find_cell_list interior-wins pick + swept determination, static :1947 removed; commit 59f3a13;
offline-verified — doorway strobe → one clean transition). T0 made the suite deterministic (12
known failures, none Phase-W regressions). Stage 3 (render-root unification) was dispatched.
DO NEXT, subagent-driven (superpowers:subagent-driven-development), NO intermediate user gates:
1. Stage 3 (render-root unification) is DONE (`6a1fbbd`→`573c555`, build green, 6 tests). START at Stage 4.
2. Stage 4 — the seal: sky/landscape inside the portal-clip bracket + conditional doorway Z-clear
(no blue-hole); verify ceilings/opaque walls. The big one.
3. Stage 5 — entity/particle cell-clip.
4. Green-tests triage (handoff §5): fix stale tests, reconcile document-the-bug, flag genuine
pre-existing gaps; full suite GREEN.
5. THEN — and only then — the SINGLE final visual verification (user): cottage + a dungeon, sealed
and seamless. Update roadmap + flip Phase W shipped.
EVIDENCE-FIRST for render/visual: launch with ACDREAM_PROBE_CELL/SWEPT, read the UTF-16 log with
PowerShell/ripgrep (not GNU grep). Membership is verifiable offline via the committed
doorway-threshold fixture (no walk). Render is wire+fill-gaps (infra exists); do not rebuild it.