Skip to content

Detect modals, drawers and soft navigation as region-of-interest states - #158

Open
DavertMik wants to merge 28 commits into
mainfrom
region-states
Open

Detect modals, drawers and soft navigation as region-of-interest states#158
DavertMik wants to merge 28 commits into
mainfrom
region-states

Conversation

@DavertMik

Copy link
Copy Markdown
Contributor

What

After every action, the page diff is checked for a newly appeared subtree ≥ 10K chars of minified HTML. A Playwright geometry probe (elementFromPoint sampling, viewport coverage, inert siblings, scroll lock) then classifies it: overlaying (modal/drawer — page behind not actionable) or inline region (soft navigation — area of interest, page still usable). Detection is fully structural — no AI in the path, no class-name selector heuristics.

Key changes

  • overlay.ts is now the single overlay-detection module: findAppearedSubRoot, probeRegionCoverage + classifyRegionCoverage, Overlay.fromSubRoot. Overlay gains root, present, and drawer/region types; detected keeps meaning "verified overlaying".
  • State identity: named regions enter the state hash (region_<name>), so modal open and close record transitions — visible to dead-loop detection. New baseHash keeps the research cache keyed to the page.
  • Tool results: instead of ...collapsed (12000 chars)..., an opened region reports drawer "Edit User" opened, scope: aside.detail-panel plus the region's snapshot (pageDiff.areaOfInterest).
  • Tester: <focus_scope> carries the concrete root selector for verified overlays; inline regions get a softer <area_of_interest> block that leaves page navigation actionable.
  • Pilot: <state> distinguishes modal: (overlaying, with root) from region: (inline).
  • Experience envelope: region-state files carry root: <selector> frontmatter; records with root load only while a matching region is open.
  • Removed: the selector-heuristic path — extractVisibleOverlayHtml, OVERLAY_SELECTORS, Action.captureOverlayHtml, the overlayHtml chain, and Driller's private extractor (Driller now reads nested overlays from pageDiff.htmlParts).

Trade-off (accepted): an overlay already open at the very first capture with no ARIA role isn't detected until the next action — in exchange for deleting class-name pattern matching that only worked on sites that name their CSS a certain way.

Spec: docs/superpowers/specs/2026-08-29-region-states-design.md · Plan: docs/superpowers/plans/2026-08-29-region-states.md

Tests

  • 1137 unit + 83 integration tests pass locally.
  • New coverage: appeared-subroot detection, coverage classifier, region hash/baseHash, diff memoization + areaOfInterest, StateManager region transitions, experience root write/gating, Pilot state context.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TkmQDF4DkphEYoy71twQNx

DavertMik and others added 28 commits August 29, 2026 13:33
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TkmQDF4DkphEYoy71twQNx
…e is a new state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TkmQDF4DkphEYoy71twQNx
…ional XPath

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TkmQDF4DkphEYoy71twQNx
…-only roots

Implements the region-states fixes spec: overlay carry-forward with close-check
and one-deep parent restore; cross-URL detection gated by similarity; size band
(10K floor, 60% page cap) with dominance guard; wrapper-descent semantic roots
with no positional XPath exposure; newest-heading naming; ARIA identity merged
with probe geometry; state capture on failed batches with truthful per-step
reporting; region transitions wake the Pilot.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TkmQDF4DkphEYoy71twQNx
Field replay of the 2026-08-30 run showed the New Plan split-pane at
6.6K minified sitting under the 10K floor, and a filtered-list
re-render passing every size gate as a nameless, rootless region.
Floor drops to 5K minified; a region with neither a name nor a
semantic root is discarded as noise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UNFgBpgs4waGN68TKH1m8
A panel can appear together with an empty fixed-position guard
element in the same container; probing the guard makes the center
hit-test veto the whole region as covered. The largest appeared
element is the subroot — its xpath is probed and its selector
becomes the root.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UNFgBpgs4waGN68TKH1m8
The suite-selector dialog arrived with a 622K flood of detached list
nodes under body and a positionally re-keyed app shell; largest-wins
picked the flood, tripped the cap and lost the 13K modal. Gates are
per-candidate now: oversized parts are skipped, dominance spans the
surviving candidates, fresh-heading candidates outrank larger stale
reflows, and the probe skips candidates covered by another element.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UNFgBpgs4waGN68TKH1m8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant