diff --git a/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md b/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md index 4b7ca68e..6018d6da 100644 --- a/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md +++ b/docs/superpowers/specs/2026-06-08-portal-flood-enqueue-once-port-design.md @@ -1,8 +1,48 @@ -# Portal-Flood Enqueue-Once Port — the indoor "flap" fix (verified design) +# Portal-Flood Bounded-Propagation Port — the indoor "flap" fix (verified design) + +**Date:** 2026-06-08 (revised — enqueue-once superseded) +**Branch:** `claude/thirsty-goldberg-51bb9b` +**Status:** Design revised after the writing-plans decomp pass; pending re-review. + +> ## ⚠️ REVISION (2026-06-08 PM): "enqueue-once" REFUTED — corrected to "bounded propagation" +> The original approach below (§4 enqueue-once, §5 correct-the-test) is **WRONG** and is retained only +> for the audit trail. The writing-plans decomp pass read `FixCellList` (decomp 433407) → +> `AdjustCellView` (433741) → `ClipPortals(update_count)` + `AddViewToPortals`, which proves **retail +> DOES re-process a grown-after-drawn cell**. So: +> - **Re-processing on growth is retail-faithful and STAYS.** Pure enqueue-once is wrong; it would break +> `Build_ViewGrowthAfterDoneCell_PropagatesNewSlicesToExit` for the *right* reason (the test is correct +> — do NOT "correct" it; §5 below is VOID). +> - **The real divergence is BOUNDING.** Retail's re-processing terminates *structurally* — each view +> slice is processed once (the `update_count` watermark is monotonic) and a redundant **reciprocal** +> back-contribution clips to **empty** (`OtherPortalClip` → no `copy_view` → no new slice; decomp +> 433654/433711-712). acdream's reciprocal (`ApplyReciprocalClip`+`ClipToRegion`) instead yields a +> **drifted non-empty sliver** → `grew` → re-enqueue → churn, bounded only by the +> `MaxReprocessPerCell=16` **hack**. The churn's fixpoint is eye-sensitive → the flap. +> - **Corrected fix:** port retail's **bounded propagation** — make redundant reciprocal/re-clip +> contributions NOT generate new propagatable slices (match retail's empty-reciprocal + monotonic +> `update_count` watermark), and remove the `MaxReprocessPerCell` cap. Keep re-processing. +> - **Scope:** still `PortalVisibilityBuilder` only; no rooting/camera/clip-math-rewrite/seal change. The +> user approved this corrected "faithful moderate port" direction (over a non-faithful epsilon-dedup +> band-aid) on 2026-06-08. +> - **One open precision (→ plan Task 1):** exactly *where* acdream's reciprocal sliver becomes non-empty +> is float-drift-dependent on real doorway geometry — a runtime fact. The implementation plan's first +> task **instruments `PortalVisibilityBuilder` (per-pop re-pop count + reciprocal-clip in/out + `grew`), +> captures at the doorway, and pins the exact line** before the fix, rather than guessing from decomp. +> - **Corrected retail grounding (the full traversal):** `ConstructView` 433750 (pop-once → draw-list → +> `ClipPortals(cell,0)` → `AddViewToPortals`); `ClipPortals` 433572 (slices `[update_count,view_count)`, +> `GetClip` per portal, exit→`copy_view`/OutsideView, neighbour→`OtherPortalClip`); `AddViewToPortals` +> 433446 (first-discovery→`InitCell`+`InsCellTodoList`; growth→`AddToCell`+`FixCellList`); +> `FixCellList` 433407 = `AdjustCellPlace` + `AdjustCellView` 433741 (=`ClipPortals(update_count)` + +> `AddViewToPortals` — **the re-process**); `OtherPortalClip` 433524 (reciprocal, empty-for-redundant). +> +> Everything below this banner is the ORIGINAL (superseded) enqueue-once design — kept for the record. +> --- + +# (SUPERSEDED) Portal-Flood Enqueue-Once Port — original design **Date:** 2026-06-08 **Branch:** `claude/thirsty-goldberg-51bb9b` -**Status:** Design approved (brainstorm). Pending implementation plan. +**Status:** SUPERSEDED by the revision banner above. > **Supersedes** the enqueue logic in `docs/superpowers/specs/2026-06-08-portal-flood-membership-stability-design.md` > (whose §4 enqueue-once was an *incomplete* attempt — it dropped the `AddToCell` growth half) and the