Skip to content

Stop telling the Tester it has HTML it never receives - #136

Open
DavertMik wants to merge 1 commit into
mainfrom
tester-no-auto-html
Open

Stop telling the Tester it has HTML it never receives#136
DavertMik wants to merge 1 commit into
mainfrom
tester-no-auto-html

Conversation

@DavertMik

Copy link
Copy Markdown
Contributor

What

The Tester's prompt referenced a <page_html> section in four places, but nothing ever injected one. Its per-iteration context (reinjectContextIfNeeded) is the accessibility tree plus the Researcher's UI map — HTML reaches it only through tool results (the page diffs returned with each action) or when it calls context() / xpathCheck() itself.

The one path that did inject full page HTML unasked was Pilot's ATTACH_HTML, which pushed simplifiedHtml() straight into the Tester's conversation. Removed. ATTACH_ARIA, ATTACH_SUMMARY and ATTACH_UI_MAP are unchanged.

Boundary this settles

  • Tester — works from the accessibility tree, keeps a light loop, sees only the HTML it asked for or that came back in a diff.
  • Navigator — reads the whole page, performs one step.

With the invariant real, the Tester needs somewhere to send work the accessibility tree cannot express. That is interact(), which delegates to the Navigator. It already existed but was effectively invisible: its description read as a generic click() alternative, and the instruction injected every turn listed only the four direct action tools. It now states its purpose and the three cases it covers — direct actions failed, the step needs a sequence of actions, or the element is not in the Tester's context — and the Tester is pointed at it each iteration.

Changes

  • src/ai/tester.ts<page_html> removed from the context block and two system rules; new rule pairing verify() and interact() as the tools that read full HTML; per-iteration fallback line for interact(); two dead cleanupTag('page_html') calls dropped.
  • src/ai/tools.tsinteract() description rewritten around its role; context() and the not-found suggestion no longer reference a <page_html> section.
  • src/ai/pilot.tsATTACH_HTML branch and its prompt mention removed; interact added to the Tester tool list Pilot validates against, which was missing it.
  • src/ai/rules.tslocatorStrategyRule referenced <aria> / <html> sections that exist under neither name; reworded, still true for Navigator.
  • CLAUDE.md — Pilot section corrected.

Behavior change worth a look

DELEGATED_ACTION_TOOLS = ['interact'] now feeds shouldStopForStalledExecution. Previously a successful interact() that left the state hash unchanged counted as no browser progress, and three of those ended the test. Now that the prompt actively pushes the Tester toward interact(), that was a trap worth closing — but it is the one change here that alters runtime behavior rather than prompt text.

Not fixed here

A failed interact() never lands in task notes: the note loop keys on execution.input?.explanation and interact's input field is instruction. Pre-existing, and Pilot still sees the failure through formatActions.

Testing

bun test tests/integration/ 80 pass / 0 fail, bun test tests/unit/ 1043 pass / 0 fail, format and lint clean. Prompt-level change — worth regression coverage before merge, your call on the label.

🤖 Generated with Claude Code

The Tester's prompt referenced a <page_html> section in four places, but
nothing ever injected one. Its per-iteration context is the accessibility
tree and the UI map; HTML reaches it only through tool results — the page
diffs that come back with each action — or when it calls context() or
xpathCheck() itself.

The one path that did inject full page HTML unasked was Pilot's
ATTACH_HTML, which dumped simplifiedHtml() straight into the Tester's
conversation. Removed; ATTACH_ARIA, ATTACH_SUMMARY and ATTACH_UI_MAP stay.

With the invariant real, the Tester needs somewhere to send work that the
accessibility tree cannot express. That is interact(), which delegates one
step to the Navigator, the agent that does read the whole page. It existed
but was invisible: its description read as a generic click() alternative,
and the instruction injected every turn listed only the four direct action
tools. It now states its purpose and the three cases it covers, and the
Tester is pointed at it each iteration.

A successful interact() also now counts as browser progress, so a delegated
step that leaves the page looking unchanged no longer counts toward the
three-strike stall that ends a test.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@DavertMik
DavertMik requested a review from DenysKuchma August 22, 2026 22:37
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