acdream/docs/research/2026-08-30-cathedral-handover.md
Erik c287db8651 docs: full session handover - cathedral state, open through-wall defect
Owner-requested handover for a successor session: worktree/branch/HEAD,
tonight''s ledger (falls + rain + torch fixes user-verified; slices 4+5
reverted; the seven-report corpus), the OPEN through-wall remote-player
defect with both attempted fixes and the post-fix [dyn-route] evidence
(the DynamicLast root-flood gate works; the remaining draw path is the
legacy look-in machinery), the leading punch-depth hypothesis marked
unverified, the retail-shaped fix direction, the remaining queue, all
probe families, and the binding lessons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 22:17:30 +02:00

9.6 KiB
Raw Blame History

HANDOVER — Campaign FW / cathedral defects (2026-08-30, end of session)

For the next session taking over. Read this top to bottom, then the campaign memory (claude-memory/project_frame_walk_campaign.md), then the synthesis (docs/research/2026-08-30-cathedral-synthesis.md).

Where you are

  • Worktree: C:\Users\erikn\source\repos\acdream\.claude\worktrees\peaceful-blackburn-5333f0
  • Branch: claude/campaign-w-retail-frame-walk (pushed; NOT merged to main)
  • HEAD at handover: the commit after 4686a1acgit log --oneline -15 shows tonight's chain. Suites at HEAD: hermetic App 6,762/0, InstalledDat walk conformance 40/1, walk lane green.
  • Launch (owner-gated visual checks): PowerShell, env ACDREAM_DAT_DIR="$env:USERPROFILE\Documents\Asheron's Call", ACDREAM_LIVE=1, ACDREAM_TEST_HOST=127.0.0.1, ACDREAM_TEST_PORT=9000, ACDREAM_TEST_USER=testaccount, ACDREAM_TEST_PASS=testpassword, probe ACDREAM_PROBE_WALK_ROOT=1, then dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Release. ALWAYS build first; the owner closes the client for you (never Stop-Process — graceful-close rules in CLAUDE.md).
  • The defect scene: cathedral, landblock 0xF418. Owner telelocs: terrace 0xF4180104 [31.9 57.3 169.8]; the seam pair 0x0104↔0x0101 at y≈72; remote player parked at 0xF4180112 [36.3 18.6 169.8] (south hall). The remote player is a second account/client the owner runs.

Campaign status (FW stages)

  • FW0FW3 landed (see the plan docs/plans/2026-08-30-campaign-fw-frame-walk.md status blocks). FW1 residue: foundry F6779 (probe script tools/walk-oracle/fw1-f67-viewpoint-probe.cdb, needs an owner retail session). FW4 is ACTIVE and partially executed via tonight's slices. FW5/FW6 not started.
  • The production renderer is still a HYBRID: the walk owns statics, terrain, sky, seals-set, punch fans, and (as of tonight) static-owner particle turns; the LEGACY PortalVisibilityBuilder still builds pvFrame every frame and feeds per-cell clip slices, the look-in frames + look-in dynamics, the DynamicLast per-cell viewcone, and the outside-dynamics slice loop. FW4's goal is deleting that duality — the through-wall defect below is a direct consequence of it.

Tonight's ledger (chronological, all pushed)

USER-VERIFIED WINS:

  1. Cathedral falls bleed FIXED (280c0549) — the #132 positional invariant ported walk-natively: WalkFrameEventKind.StaticParticles submits each landscape cell's / building shell's emitter owners AT ITS WALK TURN; the batched pre-clear submission is deleted. Mechanism credit: the OWNER's pointer to the old pipeline's e102fb36 fix.
  2. Indoor/seam rain FIXED (75eab42f) — retail gates the weather pass on SmartBox::is_player_outside @0x00451e80 (Ghidra: (player objcell & 0xFFFF) < 0x100); one boolean at the executor's weather site. GameSky draws at DEPTHTEST_ALWAYS (pc 0x00507063) — the depth-disabled weather port was correct.
  3. In-cathedral torch regression FIXED by reverting slices 4+5 (7f500b97).
  4. Earlier same-day: FW4 slices 1/2/3/6 (37febd1f,c40aecfc,5f7ccdea, bb9212c7) — kept per the tri-review verdicts, with reworks listed in the synthesis.

THE REVIEW CORPUS (read before ANY new cathedral theory): docs/research/2026-08-30-cathedral-review-{prompt,fable,opus,audit, datformat,datgeometry,decomp}.md + 2026-08-30-cathedral-synthesis.md. The decomp report is the retail frame SSOT (one-frame seal latch; TWO PViews; FIFO no-sort alpha lists; full 0f DrawBuilding flush; ShouldDrawParticles update-time; CEnvCell::IsInView = constant PARTIALLY_INSIDE). The DAT-geometry report is the F418 ground truth (falls = landblock stabs 0xCF418000-13; exits are FULL-SIZE, no "thin bands"; the seam = COINCIDENT double exit-to-outside planes at y=48 and the 0x104/0x101 boundary at y=72).

THE OPEN DEFECT — through-wall remote player (NOT FIXED)

Symptom: a remote player parented at 0xF4180112 renders through opaque walls when the observer stands in 0xF4180101 AND from outdoors. From 0xF4180104 he is correctly hidden. Retail never shows him (no sightline chain exists through the complex). Owner-reported ~21:46; two fix attempts tonight; still visible after both.

Attempt 1 (context): slice 3 (5f7ccdea) had already moved the outside-stage predicate's flood to walk VisitedCells — related plumbing, not aimed at this.

Attempt 2 (the [dyn-route] trace + the root-flood gate — latest commit): the trace ([dyn-route] lines, probe ACDREAM_PROBE_WALK_ROOT) proved: the LEGACY builder manufactures REAL 35-plane cell views for 0x112 from sightline-less roots (vis=1 cone=3+4 / 3+5 — NOT the zero-plane pass-all trapdoor), and routing flip-flops between lookin-excluded and DynamicLast as the observer moves. Fix shipped: RenderScenePViewBuildInput.RootFloodCells (the walk's InteriorFloodCells as a set) — an interior-parented dynamic rides DynamicLast ONLY if its parent is in the walk's own root flood; non-walk frames fall back to the legacy drawableCells meaning (BuildAndCompare default likewise). Verified working in the post-fix log: every 0x112 dynamic now logs rootflood-excluded.

AND THE PLAYER STILL RENDERS. Post-fix log (%LOCALAPPDATA%\Temp\fw4-rootflood-gate.log): 0x112 dynamics show BOTH rootflood-excluded AND lookin-excluded states — meaning the remaining draw path is the LookInObject route: DrawBuildingLookInDynamics (RetailPViewRenderer, runs inside DrawLandscapeDynamicsPhase, which for interior roots runs in the pre-clear closure) draws look-in-cell dynamics from the OLD apparatus's look-in frames (_lookInFrames, built by BuildInteriorRootLookIns / MergeNearbyBuildingFloods) — the very frames whose invented visibility the trace exposed. Two doors let him through; only DynamicLast was closed.

Leading hypothesis for the next session (UNVERIFIED — trace first): the old look-in machinery not only draws him with invented clip regions, it also PUNCHES far-Z apertures for its invented frames (DrawLookInPortalPunch, forceFarZ) — erasing true wall depth exactly where the invented aperture sits, so the pre-clear-drawn player passes depth there. Check also whether look-in DYNAMICS draw before/after wall shells and with which clip slots.

The retail-shaped fix direction (synthesis steps 4+7 completed properly): look-in dynamics must be keyed to THE WALK's look-in cells (the walk's VisitedCells InteriorFloodCells per frame, or better: a per-look-in walk turn like StaticParticles), and the old apparatus's look-in frames/punches must lose their production role (FW4's deletion list). An interim honest gate: DrawBuildingLookInDynamics skips cells the WALK did not visit as look-ins this frame — that alone should kill the invented-frame draws while keeping legitimate look-ins. Do NOT band-aid at the symptom (no-workarounds rule); the trace must first confirm the punch/route hypothesis: extend [dyn-route]-style logging into DrawBuildingLookInDynamics (which cells, which frames, whether 0x112 appears, and whether look-in punches fire for it).

Also open (diagnosed, unfixed, in priority order after the above)

  1. The stalks — dark shapes at the east cliff = DRAWN never-drawn marker anchors (GfxObj 0x010001EC, DIDDegrade 0x1100002E). The retail degrade-admission port exists as fce250ec on the QUARANTINED branch claude/cathedral-rendering-debug-47a417 — NOT an ancestor of this branch. Re-land it (synthesis step 10).
  2. FW1 foundry F6779 residue (needs an owner retail cdb session).
  3. Remaining synthesis Phase II items: seals from walk views (step 6), full-flush DrawBuilding barrier + FIFO no-sort alpha queue (step 8), terrain in_view culling for interior roots (step 9 — slice 6 currently uses the full camera frustum), then FW4's deletions, FW5 camera, FW6.
  4. Walk-path alloc tail ~1.5 MB/frame (FW6 hygiene).

Instrumentation available (all under ACDREAM_PROBE_WALK_ROOT=1)

[walk-root] (continuous rooting: root flood vs visited split, walk ov), [walk-cam] (replayable cameras), [walk-portal] (per-portal side/clip), [walk-part]/[walk-alpha] (submission routes + drains with pre/post phase tags), [walk-dyn] (outside-stage verdicts), [dyn-route] (DynamicLast admission, on-change), [falls]/[falls-adm] (falls owner watch 0xCF418000-13 + admission). Documented in docs/launch-options.md. RenderDoc 1.45 is at %LOCALAPPDATA%\Programs\RenderDoc_1.45_64\ (key-triggered capture does NOT work over this RDP session — use the target-control python API to trigger, or the in-app overlay locally; an old acdream capture exists at %LOCALAPPDATA%\Temp\RenderDoc\).

Binding rules for the successor (hard-learned tonight)

  1. Never identify render content from aggregate owner sets — trace ids to the DAT (0x4…=interior allocator, 0xC…=landblock statics, 0x8…=scenery, raw=server entities).
  2. Phase-level probes cannot see position-within-phase — order inside a stage is its own dimension.
  3. The owner's old-pipeline fix history is an oracle — check e102fb36-era work (C:\Users\erikn\.codex\worktrees\16ee\acdream, docs/research/2026-08-29-cathedral-seam-progress.md) before re-deriving.
  4. Ghidra arbitration is mandatory for BN branch senses (multiple misreads; MCP on port 8081, patchmem.gpr must be open).
  5. The oracle traces (docs/research/2026-08-30-fw-walk-oracle/, posed/ = the fixture set) are frame truth; posed/terrace-center = DI f4180104, flood n=1, ov=1.
  6. One fix at a time, trace-pinned first, owner-gated after — six blind rounds preceded tonight's three verified fixes.