25 KiB
Phase U.4c — Stabilize Portal Visibility (fix the threshold "flap") Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Make the indoor portal-visibility set stable across camera pose so the cottage doorway no longer flaps terrain + building-shells off, by grounding the set in the per-cell precomputed PVS (stab_list) + the seen_outside flag — the retail mechanism.
Architecture: Three layers. (1) LoadedCell carries two already-in-process stable inputs (VisibleCells = stab_list, SeenOutside flag). (2) PortalVisibilityBuilder grounds set membership in the camera cell's PVS so a brittle per-frame portal-side test can no longer drop the exit-portal cell. (3) The SeenOutside flag is the stability anchor + test oracle. The per-frame portal-clip walk and every rendering consumer (ClipFrameAssembler, ClipFrame, shaders, EnvCellRenderer, terrain) are unchanged — U.4c changes only what feeds them.
Tech Stack: C# / .NET 10, System.Numerics, xUnit. GL-free CPU code only (no shader/GPU work — that shipped in U.3/U.4). Retail oracle: docs/research/named-retail/acclient_2013_pseudo_c.txt.
Spec: docs/superpowers/specs/2026-05-31-phase-u4c-stabilize-portal-visibility-design.md — read it first.
Branch: claude/thirsty-goldberg-51bb9b (continue; do NOT create a new branch/worktree, do NOT drop the two git stash entries).
Workflow rules (apply to every task)
- This is AC-specific behavior. Follow the mandated workflow: grep named → decompile → pseudocode → port → conformance-test. For Task 3 the algorithm body is ported from the cited decomp lines, not invented. If the decomp and a guess disagree, the decomp wins.
- Build + test green before every commit:
- Build:
dotnet build src/AcDream.App/AcDream.App.csproj -c Debug - App tests:
dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug
- Build:
- App-test baseline at session start: 151/151 passing (the Core suite has documented pre-existing static-leak flakiness — ignore Core unless a task touches Core; no Core production files are touched here).
- Commit messages:
<type>(render): Phase U.4c — <what>+ the trailer:Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
File Structure
| File | Change | Responsibility |
|---|---|---|
tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs |
Modify | Add the flap-reproduction regression test (Task 1) + SeenOutside/PVS-grounding tests (Tasks 3-4). |
src/AcDream.App/Rendering/CellVisibility.cs |
Modify | Add LoadedCell.VisibleCells + LoadedCell.SeenOutside fields (Task 2). |
src/AcDream.App/Rendering/GameWindow.cs |
Modify | Populate the two new fields at the existing EnvCell-build site (~5696) from envCell.VisibleCells + envCell.Flags (Task 2). |
src/AcDream.App/Rendering/PortalVisibilityBuilder.cs |
Modify | Ground set membership in the camera cell's PVS; faithful port of retail's add_views/InitCell/ClipPortals grounding (Task 3). |
src/AcDream.App/Rendering/ClipFrameAssembler.cs |
(optional, Task 6) | Cosmetic only: branch the 3 Count==0 states before AppendSlot. |
No new files. No new project references. No GL/shader changes.
Task 1: Apparatus — reproduce the flap in a GL-free unit test (RED)
The flap = the exit-portal cell drops from the visible set when an intermediate portal's per-frame side test flips as the camera moves a few cm, emptying OutsideView. Reproduce that deterministically so the fix has a falsifiable gate. This task adds no production code — it produces a RED test that documents the bug (the same discipline that #103 lacked at the unit level).
Files:
-
Test:
tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs -
Step 1: Add the flap-reproduction test
Append this to PortalVisibilityBuilderTests (it reuses the existing Cell / Quad helpers in that file). Build a ViewProj from each camera pose so the side test and the projection agree:
// -----------------------------------------------------------------------
// Phase U.4c: the threshold "flap". A chain camera(C0) -> mid(C1) -> exit(C2)
// where the C0->C1 portal's clip plane sits just in front of the camera.
// BOTH poses are legitimately inside C0 and SHOULD see the exit window; they
// straddle the C0->C1 side-test boundary by a few cm. Pre-fix, the pose just
// behind the plane hard-culls C0->C1 (CameraOnInteriorSide), C2 is never
// reached, and OutsideView empties — the flap. The fix must keep the exit
// cell visible (OutsideView non-empty) at BOTH poses.
// -----------------------------------------------------------------------
private static Matrix4x4 ViewProjAt(Vector3 eye)
{
var view = Matrix4x4.CreateLookAt(eye, eye + new Vector3(0, 0, -1), Vector3.UnitY);
var proj = Matrix4x4.CreatePerspectiveFieldOfView(1.2f, 1.0f, 0.1f, 1000f);
return view * proj;
}
private static (LoadedCell cam, Dictionary<uint, LoadedCell> all) FlapChain()
{
const uint C0 = 0x0001, C1 = 0x0002, C2 = 0x0003;
// C0 -> C1 portal at z=-1, with a clip plane (normal +Z, InsideSide=0) at z=-1.
// dot = camZ + D; with D = 1 the plane is at camZ = -1: inside iff camZ >= -1 - eps.
var c0 = Cell(C0, new CellPortalInfo((ushort)C1, 0, 0, 0));
c0.PortalPolygons.Add(Quad(0f, 0f, 0.6f, 0.6f, -1f));
c0.ClipPlanes.Add(new PortalClipPlane { Normal = new Vector3(0, 0, 1), D = 1f, InsideSide = 0 });
// C1 -> C2 (no clip plane → never culled), C2 has the exit window.
var c1 = Cell(C1, new CellPortalInfo((ushort)C2, 0, 0, 0));
c1.PortalPolygons.Add(Quad(0f, 0f, 0.6f, 0.6f, -4f));
var c2 = Cell(C2, new CellPortalInfo(0xFFFF, 0, 0, 0));
c2.PortalPolygons.Add(Quad(0f, 0f, 1.0f, 1.0f, -7f));
var all = new Dictionary<uint, LoadedCell> { [C0] = c0, [C1] = c1, [C2] = c2 };
return (c0, all);
}
[Fact]
public void Build_NearBoundaryIntermediatePortal_ExitCellStaysVisibleAcrossPose()
{
var (cam, all) = FlapChain();
Func<uint, LoadedCell?> lookup = id => all.TryGetValue(id, out var c) ? c : null;
// Pose A: a few cm IN FRONT of the C0->C1 plane (camZ = -0.9 >= -1 → inside).
var poseA = new Vector3(0, 0, -0.9f);
var frameA = PortalVisibilityBuilder.Build(cam, poseA, lookup, ViewProjAt(poseA));
// Pose B: a few cm BEHIND it (camZ = -1.1 < -1 → pre-fix the side test culls C0->C1).
var poseB = new Vector3(0, 0, -1.1f);
var frameB = PortalVisibilityBuilder.Build(cam, poseB, lookup, ViewProjAt(poseB));
// The exit cell — and therefore OutsideView — must be present at BOTH poses.
Assert.False(frameA.OutsideView.IsEmpty, "pose A should see the exit window");
Assert.False(frameB.OutsideView.IsEmpty,
"pose B (a few cm away) must ALSO see the exit window — this is the flap: " +
"an intermediate side-test flip must not drop the exit cell from the set");
Assert.Contains(0x0003u, frameB.OrderedVisibleCells);
}
- Step 2: Run the test and confirm it FAILS (reproduces the flap)
Run: dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug --filter "FullyQualifiedName~Build_NearBoundaryIntermediatePortal"
Expected: FAIL at the pose-B assertion (OutsideView empty / 0x0003 absent). If it PASSES, the fixture didn't reproduce the cull — tune the geometry (move poseB a touch further behind the plane, or nudge ClipPlanes[0].D) until pose B is RED while pose A is GREEN, then re-confirm. The RED-at-B / GREEN-at-A split is the whole point — do not proceed until you have it.
- Step 3: Commit the RED apparatus
git add tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs
git commit -m "test(render): Phase U.4c — reproduce the doorway flap (RED apparatus)
Synthetic C0->C1->C2(exit) chain; two camera poses straddle the C0->C1
side-test boundary by a few cm. Pre-fix, pose B hard-culls C0->C1 and the
exit cell drops -> OutsideView empties (the flap). Gates the U.4c fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"
Task 2: Layer 1 — LoadedCell carries the stable PVS + SeenOutside
Plumb the two already-in-process inputs onto the render-side cell. No new dat parsing.
Files:
-
Modify:
src/AcDream.App/Rendering/CellVisibility.cs(add two fields toLoadedCell) -
Modify:
src/AcDream.App/Rendering/GameWindow.cs:5696(populate them at hydration) -
Step 1: Add the two fields to
LoadedCell
In CellVisibility.cs, inside public sealed class LoadedCell, after the BuildingId property, add:
/// <summary>
/// Phase U.4c: the stab_list PVS as full (landblock-prefixed) cell ids — retail
/// CEnvCell.stab_list (acclient.h ~30925), the stable set of cells potentially
/// visible from this cell, precomputed by the AC content tools. Refreshed only at
/// hydration (= retail's per-cell-entry grab_visible_cells, decomp:311878).
/// PortalVisibilityBuilder grounds set membership in it so a brittle per-frame
/// portal-side test can't drop a potentially-visible cell from the visible set.
/// Empty when the dat carried no stab list (degenerate / old cell).
/// </summary>
public IReadOnlyList<uint> VisibleCells = System.Array.Empty<uint>();
/// <summary>
/// Phase U.4c: retail CEnvCell.seen_outside (acclient.h ~30925) — this cell sees
/// the exterior (an exit portal is reachable from it). Retail gates the landscape
/// data + draw decision on the camera cell's value (RenderNormalMode decomp:92649,
/// grab_visible_cells decomp:311878). The stable anchor for the terrain-draw test.
/// </summary>
public bool SeenOutside;
- Step 2: Populate them at the hydration site
In GameWindow.cs, in the EnvCell-build method, locate the var loaded = new LoadedCell { ... } initializer at ~5696. Immediately BEFORE it, derive the two values from envCell (the local already in scope that supplied envCell.CellPortals):
// Phase U.4c: surface the stable PVS + seen-outside flag onto the render cell.
// Both come straight off the dat EnvCell — no new parsing (PhysicsDataCache
// already reads VisibleCells the same way; A8CellAudit reads the flag).
uint lbPrefix = envCellId & 0xFFFF0000u;
var visibleCells = new List<uint>();
if (envCell.VisibleCells is not null)
foreach (var lowId in envCell.VisibleCells)
visibleCells.Add(lbPrefix | lowId);
bool seenOutside = envCell.Flags.HasFlag(AcDream.Core.Dats.EnvCellFlags.SeenOutside);
NOTE: confirm the exact
EnvCellFlagsnamespace/type by grepping the symbol used attools/A8CellAudit/Program.cs:200(envCell.Flags.HasFlag(EnvCellFlags.SeenOutside)) and match itsusing/qualified name. Do not guess the namespace.
Then add the two fields to the initializer:
var loaded = new LoadedCell
{
CellId = envCellId,
WorldPosition = cellOrigin,
WorldTransform = cellTransform,
InverseWorldTransform = inverse,
LocalBoundsMin = boundsMin,
LocalBoundsMax = boundsMax,
Portals = portals,
ClipPlanes = clipPlanes,
PortalPolygons = portalPolygons, // Phase A8
VisibleCells = visibleCells, // Phase U.4c
SeenOutside = seenOutside, // Phase U.4c
};
- Step 3: Build green
Run: dotnet build src/AcDream.App/AcDream.App.csproj -c Debug
Expected: build succeeds (the existing flap test from Task 1 is still RED — that's correct; the fix is Task 3).
- Step 4: Commit
git add src/AcDream.App/Rendering/CellVisibility.cs src/AcDream.App/Rendering/GameWindow.cs
git commit -m "feat(render): Phase U.4c — LoadedCell carries stab_list PVS + seen_outside
VisibleCells (full ids) + SeenOutside, populated at the EnvCell-build site from
envCell.VisibleCells + envCell.Flags. Mirrors retail CEnvCell.stab_list /
seen_outside (acclient.h ~30925). Data already in-process; render path no longer
drops it. Consumed by the builder in U.4c-3.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"
Task 3: Layer 2 — port retail InitCell portal_side sidedness (the fix; oracle-ported)
EVIDENCE UPDATE (2026-05-31, Task U.4c-1 ran): the flap was characterized on real dat data — see
docs/research/2026-05-31-u4c-flap-characterization.md. The flap is a direct0xA9B40171→0xA9B40170portal side-test flip (the window cell is a direct neighbour, NOT multi-hop), and the evidence selected H2 over H1: ourCameraOnInteriorSidederives the sidedness sense from the cell centroid, anti-correlated with the dat's authored per-portalPortalSideflag that retail'sInitCelluses. The fix is to port the side test to use the datPortalSide(inportal.Flags), not centroid-InsideSide. The stab_list PVS grounding (Layer 1 data, already plumbed in Task 2) stays as a correct improvement but is NOT the flap mechanism. The Task-1 synthetic test models the mechanism via a multi-hopInsideSidecull and must be re-authored to model the direct-portalPortalSide-vs-centroid divergence so it is a clean gate for the actual fix.
This is the AC-algorithm port. Read the oracle first, write pseudocode, then port — do not invent the algorithm.
Files:
-
Modify:
src/AcDream.App/Rendering/PortalVisibilityBuilder.cs -
Test gate:
tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs(Task 1's test goes GREEN) -
Step 1: Read the oracle + write a pseudocode note
Read, in docs/research/named-retail/acclient_2013_pseudo_c.txt:
PView::DrawInside433793 — callsadd_views(num_stabs, stab_list)beforeConstructView.PView::add_views433382 —for each stab: GetVisible(id); curr_view_push(cell)(seeds a live view accumulator on every PVS cell).PView::InitCell432896 — per-portal sidedness classification (the retail analog of ourCameraOnInteriorSide; note its plane-dot +portal_sidecompare + ~0.0002 epsilon, lines 432928-432968).PView::ClipPortals433572 — onlyseen && !inflagportals propagate;0xFFFF→outside_view(433662-433676).PView::AddViewToPortals433446 — enqueue on first discovery (ecx_5==0); re-incorporate on view-growth (AddToCell/FixCellList, 433494-433502).
Compare against our PortalVisibilityBuilder.Build (the walk 116-228) and CameraOnInteriorSide (237-244). Identify the divergence that lets our exit cell drop where retail's stays present. Two candidates the apparatus disambiguates:
- H1 (set grounding): retail keeps the cell present via
add_views/visible_cell_table; our pure-walk set has no such anchor. Fix = the camera cell'sVisibleCellsPVS grounds set membership. - H2 (side test): our
CameraOnInteriorSide(centroid-derivedInsideSide, ±0.01) is a less-stable reimplementation than retail'sInitCellsidedness; fix = portInitCell's sidedness faithfully.
Write a short note to docs/research/2026-05-31-u4c-pview-grounding-pseudocode.md: the retail traversal in pseudocode + the identified divergence + which fix the apparatus selects.
- Step 2: Confirm the Task-1 test is RED against current code
Run: dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug --filter "FullyQualifiedName~Build_NearBoundaryIntermediatePortal"
Expected: FAIL at pose B (carried over from Task 1).
- Step 3: Port the grounding into the builder
Implement the fix selected in Step 1, ported from the cited decomp. The design intent (spec §5.2): the camera cell's PVS (VisibleCells) is the authority on set membership; the per-frame portal-side test refines clip regions but must not drop a PVS-member cell from the visible set. Concretely, ground the traversal so that:
- every cell in
cameraCell.VisibleCellsis a participant (resolvable + reachable), so the exit cell cannot be culled out of existence by a near-boundary side-test flip; and - the
0xFFFFexit contribution toOutsideViewis gathered from PVS-member cells.
Keep the change minimal and faithful — prefer porting InitCell sidedness (H2) if that alone makes the apparatus GREEN; add the PVS membership grounding (H1) as the structural net. Do not add a hysteresis / last-frame band-aid (forbidden). Do not introduce a full-screen "draw everything when unsure" fallback as the common-case path — over-include is a §6 degenerate-data backstop only.
Cite the decomp anchors in code comments (function + address). The builder stays GL-free; its public signature + PortalVisibilityFrame shape are unchanged.
- Step 4: Run the full builder test suite — flap GREEN, no regression
Run: dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug --filter "FullyQualifiedName~PortalVisibilityBuilderTests"
Expected: ALL PASS — the new flap test GREEN and every prior builder test still GREEN. In particular Builder_BackFacingPortal_NotTraversed, Builder_SealedCellar_NoExitPortal_OutsideViewEmpty, and Builder_Cellar_WindowClippedToStairwell_NotFullWindow must still pass (a fix that over-includes — drawing terrain when genuinely sealed, or failing to narrow the window — breaks these; that is the guardrail against a band-aid).
- Step 5: Full App suite green
Run: dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug
Expected: 152/152 (151 baseline + the new flap test).
- Step 6: Commit
git add src/AcDream.App/Rendering/PortalVisibilityBuilder.cs tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs docs/research/2026-05-31-u4c-pview-grounding-pseudocode.md
git commit -m "fix(render): Phase U.4c — ground portal visibility set in the PVS (closes the flap)
Port of retail PView grounding (add_views 433382 / InitCell 432896 / ClipPortals
433572): the camera cell's stab_list PVS is the authority on visible-set
membership, so a near-boundary CameraOnInteriorSide flip no longer drops the
exit-portal cell -> OutsideView no longer spuriously empties -> no TerrainMode.Skip
flap. Flap regression test GREEN; sealed-cellar + window-narrowing tests still
GREEN (no over-include band-aid). Pseudocode note + decomp anchors inline.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"
Task 4: Layer 3 — SeenOutside invariants + assembler-unchanged confirmation
Lock the stable terrain-decision invariants (spec §5.3) so a future change can't silently re-introduce the flap or over-draw.
Files:
-
Test:
tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs -
Step 1: Add the invariant tests
[Fact] // windowless interior: no exit portal in the PVS chain → no terrain (correctly empty)
public void Build_WindowlessInterior_OutsideViewEmpty()
{
// C0 -> C1, neither has a 0xFFFF portal. Even with PVS grounding, OutsideView
// must be empty — terrain is correctly absent in a sealed room (matches retail
// DrawCells gating on outside_view.view_count, decomp:432715).
const uint C0 = 0x0001, C1 = 0x0002;
var c0 = Cell(C0, new CellPortalInfo((ushort)C1, 0, 0, 0));
c0.PortalPolygons.Add(Quad(0f, 0f, 0.6f, 0.6f, -2f));
c0.VisibleCells = new uint[] { C0, C1 };
var c1 = Cell(C1); // no portals, no exit
c1.VisibleCells = new uint[] { C0, C1 };
var all = new Dictionary<uint, LoadedCell> { [C0] = c0, [C1] = c1 };
var frame = PortalVisibilityBuilder.Build(
c0, new Vector3(0, 0, -0.5f), id => all.TryGetValue(id, out var c) ? c : null, ViewProjAt(new Vector3(0, 0, -0.5f)));
Assert.True(frame.OutsideView.IsEmpty,
"a windowless interior must draw no terrain — over-include here would be a band-aid");
}
[Fact] // threshold stability: the exit cell stays present across a swept pose (no polys=0/1 flap)
public void Build_ThresholdSweep_OutsideViewStableNonEmpty()
{
var (cam, all) = FlapChain();
cam.VisibleCells = new uint[] { 0x0001, 0x0002, 0x0003 }; // PVS reaches the exit cell
Func<uint, LoadedCell?> lookup = id => all.TryGetValue(id, out var c) ? c : null;
// Sweep the camera across the C0->C1 boundary; OutsideView must never empty.
for (float z = -0.8f; z >= -1.2f; z -= 0.05f)
{
var eye = new Vector3(0, 0, z);
var frame = PortalVisibilityBuilder.Build(cam, eye, lookup, ViewProjAt(eye));
Assert.False(frame.OutsideView.IsEmpty, $"flap at camera z={z}: OutsideView empty mid-sweep");
}
}
If the Task-3 fix grounds set membership on
cameraCell.VisibleCells, theFlapChainfixture must setcam.VisibleCells(as above) for the grounding to engage. If Task 3 instead landed on the H2 side-test port (no PVS dependency for this fixture), these tests still pass; keep both — they pin the §5.3 invariants either way.
- Step 2: Run them
Run: dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug --filter "FullyQualifiedName~PortalVisibilityBuilderTests"
Expected: ALL PASS.
- Step 3: Confirm the assembler is untouched & still correct
Run: dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Debug --filter "FullyQualifiedName~ClipFrameAssemblerTests"
Expected: ALL PASS — ClipFrameAssembler consumes the now-stable PortalVisibilityFrame unchanged (U.4c added no assembler changes).
- Step 4: Commit
git add tests/AcDream.App.Tests/Rendering/PortalVisibilityBuilderTests.cs
git commit -m "test(render): Phase U.4c — seen_outside invariants (windowless empty, threshold stable)
Pins spec 5.3: a sealed interior draws no terrain (no over-include band-aid);
a threshold cell keeps a stable non-empty OutsideView across a swept pose (no
polys=0/1 flap). Assembler tests confirm the consumer is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"
Task 5: Visual gate (acceptance — STOP for visual verification)
The real gate. Unit tests on synthetic data did not catch #103; the live scene is authoritative.
Files: none (run + observe).
- Step 1: Build green
Run: dotnet build src/AcDream.App/AcDream.App.csproj -c Debug
- Step 2: Launch with the visibility probe to a fresh UTF-16 log
PowerShell (per CLAUDE.md "Running the client"):
$env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call"
$env:ACDREAM_LIVE = "1"
$env:ACDREAM_TEST_HOST = "127.0.0.1"; $env:ACDREAM_TEST_PORT = "9000"
$env:ACDREAM_TEST_USER = "testaccount"; $env:ACDREAM_TEST_PASS = "testpassword"
$env:ACDREAM_PROBE_VIS = "1"
dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 | Tee-Object -FilePath "u4c-vis.log"
Run in the background; give it ~8 s to reach in-world.
- Step 3: User crosses the threshold (visual verification)
Ask the user to walk +Acdream through a Holtburg cottage doorway — cellar → ground floor → outside — from several angles and zoom levels, watching for terrain / building-shell flicker at the threshold. This is the acceptance test; only the user can confirm it.
- Step 4: Read the probe log (the apparatus gate)
Read u4c-vis.log (UTF-16): PowerShell Select-String "\[vis\]" u4c-vis.log (or bash tr -d '\0' < u4c-vis.log | grep '\[vis\]').
Expected: for the threshold cell, OutsideView stays non-empty and narrowing — NO outside(polys=0) frames interleaved with outside(polys=1) for the same cell. That, plus the user's "seamless" confirmation, is the gate.
- Step 5: On pass — update roadmap/issues + commit; decide push with the user
Update the M1.5 block + docs/ISSUES.md (the flap closed), commit the docs, and ask the user whether to push the branch. On fail — capture the [vis] divergence and return to Task 3 Step 1 with the new evidence (do NOT band-aid).
Task 6 (optional): cosmetic sweeps — only if trivial
Take only if zero-risk and quick; otherwise defer. Each is behaviour-neutral with its own commit.
ClipFrameAssembler/ClipFrame.AppendSlot: branch the 3Count==0states (IsNothingVisible/UseScissorFallback/ trivial) before callingAppendSlot, per the U.4 review note.- Remove orphaned
LandblockEntriesWithoutAnimatedIndex; remove deadBuildingShellAnchorPass/Rejectcounters.
Gate: build + full App suite green; no behaviour change.
Self-review notes (author)
- Spec coverage: §5.1 → Task 2; §5.2 → Task 3; §5.3 → Task 4; §7 unit gate → Tasks 1/3/4; §7 visual gate → Task 5; §8 staging maps 1:1 (U.4c-1≈Task1+Task3.Step1, U.4c-2≈Task2, U.4c-3≈Task3, U.4c-4≈Task4, U.4c-5≈Task5); §8 optional sweeps → Task 6.
- Type consistency:
VisibleCells(IReadOnlyList<uint>) +SeenOutside(bool) used identically in Tasks 2/3/4;CellView.IsEmpty/MinX/MaxX/Polygons,PortalVisibilityFrame.OutsideView/OrderedVisibleCells/CellViews,CellPortalInfo(OtherCellId, PolygonId, Flags, OtherPortalId),PortalClipPlane{Normal,D,InsideSide}all match the live source read during planning. - No-guess guard: Task 3's algorithm body is explicitly a port from cited decomp lines, pseudocode-first — not fabricated here (CLAUDE.md no-guessing mandate).
EnvCellFlagsnamespace is flagged for grep-confirmation, not guessed.