Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7c0f217
docs: spec and plan for region-of-interest states
Aug 29, 2026
aa62629
feat: Overlay carries region types and root; detect appeared subroots…
Aug 29, 2026
d5ad082
feat: region coverage probe and classifier in overlay module
Aug 29, 2026
5bb3664
feat: region-aware state hash, baseHash, memoized diff and areaOfInte…
Aug 29, 2026
db0b584
feat: detect region of interest from page diff during capture
Aug 29, 2026
d1c8b15
feat: record region-of-interest transitions in state manager
Aug 29, 2026
dab7b8f
feat: root selector envelope key scopes experience to open regions
Aug 29, 2026
2758f4c
feat: key research by base page hash and research any named region
Aug 29, 2026
1143c9b
feat: tester context carries region root and inline area of interest
Aug 29, 2026
0eddbfc
feat: pilot state context distinguishes overlaying modals from inline…
Aug 29, 2026
114f1d9
refactor: driller reads nested overlays from page diff instead of DOM…
Aug 29, 2026
6370cfb
refactor: remove selector-based overlay detection; overlay.ts is the …
Aug 29, 2026
07c4cd8
docs: changelog for region-of-interest states
Aug 29, 2026
1422f4f
docs: complete region-of-interest plan checklist
Aug 29, 2026
a6bcce9
fix: invalidate memoized diff when html is reassigned
Aug 29, 2026
724c6b0
refactor: Overlay value object plus OverlayPage detector as the overl…
Aug 29, 2026
f98f18d
refactor: verify region openness with a single center hit-test
Aug 29, 2026
109fd8e
docs: fixes spec from first field-run trace analysis
Aug 29, 2026
785bf3e
docs: bound region detection with a max-change ratio; oversized chang…
Aug 29, 2026
5fdbd3a
docs: semantic-only region roots with wrapper-chain descent, no posit…
Aug 29, 2026
dabb286
feat: persist regions until verified close, bound detection, semantic…
Aug 29, 2026
c9514ab
docs: changelog for region persistence and detection fixes
Aug 29, 2026
81bd63d
fix: announce a nested region replacing an open overlay in tool results
Aug 29, 2026
74ffa44
refactor: declare root on WebPageState instead of an inline intersection
Aug 30, 2026
bc225fd
fix: detect mid-size panels and drop identity-less regions
Aug 30, 2026
5aa2fe7
fix: probe the largest appeared element, not the first
Aug 30, 2026
e5ff599
fix: walk region candidates instead of aborting on the largest
Aug 30, 2026
174cbb5
Merge branch 'main' into region-states
DavertMik Aug 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,91 @@
# Changelog

## 2026-08-30

### Changes

- State Manager: An open panel now stays part of the state until it actually closes. Detection used
to fire only on the single action that opened a drawer — one step later the agent forgot the
drawer existed, so its scope hints, the Pilot's state line and the panel's own experience file
never materialised. The panel is now re-checked on every action and carried forward while its
content is still on top; when it closes, the state moves back and the transition is recorded.
- State Manager: A panel that opens inside another open panel no longer erases the outer one. When
the inner panel closes, the outer drawer is checked and restored as the active area.
- Action: Drawers that open together with a URL change are now detected. A side panel that updates
the address bar used to be indistinguishable from real navigation; it now counts as a panel as
long as most of the previous page is still there underneath.
- Action: A change that replaces most of the page is treated as a new page, not a panel. Content
finishing to load, or a page redrawing after a dialog closes, no longer gets reported as an
opened drawer — and scattered small changes across the page never count as one either.
- Action: Panel scope selectors are always meaningful now — an id or a real CSS class, found by
walking past anonymous wrapper elements and utility classes into the panel itself. A positional
path like `//body/div[10]` or a container that spans the whole page is never suggested as a
scope; when nothing meaningful exists, the scope is simply omitted.
- Action: A newly opened panel is named by the heading that just appeared, not by the title of the
page or panel behind it.
- Action: Dialogs recognised by their accessibility role now also get a scope selector, so the
"scope your locators here" hint works for them too.
- Action: When a batch of commands fails midway, the page state is still captured — a drawer opened
by the second command no longer goes unnoticed because the third command failed — and the report
now correctly shows which commands succeeded before the failure instead of marking all of them
failed.
- [Pilot] Reviews progress immediately when a panel opens or closes, instead of staying silent for
the whole life of a drawer between scheduled check-ins.
- Action: Smaller side panels are recognised now — a split-pane form of a few thousand characters
used to fall under the size floor and go undetected while the agent worked inside it blind. The
floor is 5K of cleaned panel content, still well above dropdowns and toasts.
- Action: A large redraw with no identity is no longer reported as a panel. A list that re-renders
its rows has no new heading and no meaningful container, so announcing it as an unnamed region
only added noise; a panel must bring either a name or a scope selector to count.
- Action: A dialog is found even when the app redraws half the page around it. Opening a modal used
to be missed entirely when it came with a burst of stray rendering — the burst won the "biggest
change" contest and cancelled detection. Every appeared area is considered now: oversized redraws
are set aside, the area bringing a new heading is preferred, and anything covered by another
element on screen is passed over — so the dialog itself gets the scope, like "Select suite for
test" in #modal-overlays.
- Action: The element probed for visibility is the panel itself, not an invisible helper that
appeared with it — a transparent resize guard rendered next to a side panel used to make the
visibility check fail and silently drop the panel.

## 2026-08-29

### Changes

- State Manager: Drawers, side panels and swapped-in subviews are now recognised as pages in their
own right. Until now only a modal that announced itself as a dialog counted as a state; a panel
built as a plain positioned element, or a wizard step that replaced half the screen without
changing the URL, was invisible — the agent kept aiming at the elements behind it, and a test that
opened and closed the same panel over and over looked like it was standing still. A large area
appearing on the page is now detected by comparing the page before and after the action and
measuring whether it covers what is behind it, so opening one is recorded as a move to a new state
and closing it as a move back.
- Action: The result of a click that opens a panel now leads with the panel. A large change used to
be written off as a whole-page redraw and replaced with a placeholder saying how many characters
were dropped, which threw away the one thing worth reading. The result now names what opened and
where it lives, and carries that area's markup instead of the placeholder.
- [Tester] Knows to keep working inside the area that just opened. For a panel that covers the page,
it is told the exact container to scope its locators to. For one that appears inline, it is told
the scenario most likely continues there while the rest of the page stays available — the stricter
"nothing outside is clickable" wording is reserved for areas actually measured as covering.
- [Pilot] Tells a covering modal apart from an inline area. The state summary now shows the
container for a modal and a separate `region:` line for an area that appeared in place, so Pilot
can steer a stuck Tester into a subview instead of assuming a dialog is blocking it.
- [Researcher] Describes drawers and subviews, not just dialogs. The extra pass that documents what
a modal contains now runs for any named area that opens, and its notes are still filed under the
page they belong to, so a panel that is open when a page is first analyzed no longer splits that
page's UI map in two.
- Experience Tracker: Steps learned while a panel was open are now scoped to it. Experience files
written for such a state record the panel's container as `root:` in their frontmatter, and are
loaded only while a matching area is open — so panel-specific recipes stop being offered as advice
on the plain page. Existing files without the key behave exactly as before.
- [Driller] Reads a nested popup or menu from what the click already reported instead of asking the
browser a second time.
- Overlay detection is now one mechanism instead of three. The old path recognised overlays by
looking for class names containing words like "modal" or "drawer", which only ever worked on sites
that happened to name their CSS that way; it has been removed in favour of accessibility roles
plus the page-comparison and geometry check above. One consequence: an overlay already on screen
at the very first capture that carries no accessibility role is no longer detected until the next
action.
- [Provider] Groq prompt cache hits are counted again. Groq reports how much of a prompt it served
from cache, but the pinned `@ai-sdk/groq` build read that number out of the response and then
dropped it, so every Groq request was recorded as a full-price miss and the cache hit rate showed
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ All persisted formats share one rule: **envelope keys (YAML frontmatter, HTML co
| Format | Location & owner | Envelope | Body grammar |
|---|---|---|---|
| Knowledge | `knowledge/*.md`, KnowledgeTracker | `url`/`path`, `wait`, `waitForElement`, `noExperienceReading/Writing` | Free prose facts |
| Experience | `experience/<stateHash>.md`, ExperienceTracker | sparse frontmatter | `## FLOW:` / `## ACTION:` h2 blocks; bullets + ```js``` + `Solution:` line; h3 forbidden under blocks |
| Experience | `experience/<stateHash>.md`, ExperienceTracker | sparse frontmatter: `url`, `title`, optional `root` (region scoping selector — record loads only while a matching region is open) | `## FLOW:` / `## ACTION:` h2 blocks; bullets + ```js``` + `Solution:` line; h3 forbidden under blocks |
| Test plan | `output/plans/*.md`, test-plan-markdown.ts | `<!-- test ... -->` comment: `priority`, `style`; scenario heading, `url:` line, bullets as steps | Notes/results appended by runner |

These are **data formats**: written and read back inside the runtime loop (knowledge/experience steer every run; plans are consumed by the runner and rerun).
Expand Down
Loading
Loading