Navigator: capture rejection signal + give the AI a stop() tool#39
Open
DavertMik wants to merge 4 commits into
Open
Navigator: capture rejection signal + give the AI a stop() tool#39DavertMik wants to merge 4 commits into
DavertMik wants to merge 4 commits into
Conversation
Exposes the AI Navigator as a one-shot CLI command. Exits 0 when the target URL is reached and 1 otherwise, so it can be used as a reachability probe in CI. Inherits --session and all common options, making it the canonical way to capture an authenticated session for downstream agents in a single command. Also restructures docs/commands.md to treat CLI as a first-class surface alongside TUI: a comprehensive reference table, per-command sections showing both invocations side by side, and coverage of the previously-undocumented CLI-only commands. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When a click succeeds but the URL stays put, Navigator now diffs the page and extracts any new alert/status/alertdialog messages, then includes them (plus the ARIA changes) in the next retry prompt. This breaks the loop where Navigator would re-fire 9 syntactic locator variants against a form that was actually being rejected by the server. The retry prompt now tells the model to re-examine credentials or input data before changing locators when the page reacted. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Navigator's resolveState loop was passing tools=undefined to the AI, so the model had no way to signal "this is hopeless, the page is rejecting the submit." Combined with a retry prompt that, on app-rejection, told the model both "do not change the locator" AND "propose new solutions" in the same turn — the model spent its full retry budget mutating locators that were already correct. This adds a stop(reason) tool the AI can call when no locator change will help (wrong credentials, missing knowledge, captcha, blocking error). When called, the reason is logged at error level and surfaced in the existing interactive failure prompt so the user knows what to fix. The retry prompt is restructured so the two paths are mutually exclusive: - if the page reacted (alerts / ARIA changes): two clear choices — call stop(reason), or correct the submitted data using known knowledge. Do not change the locator. - if the page did not react: propose new locator strategies (the old behaviour). No control-flow rewrite — the model can still emit code blocks in text; the tool is an optional escape valve, mirroring how Tester uses its stop() tool at tester.ts:938. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two Navigator improvements that together fix the failure mode where Navigator burns 9 retry attempts on a form that is actually being rejected by the server, not by a bad locator.
Commit 1 — Feed back why the URL didn't change
When a click runs cleanly but the URL doesn't change to the expected target, Navigator now:
alert/alertdialog/statusARIA messages.Reuses the existing
ActionResult.diffinfrastructure. Adds one helperextractAlerts(snapshot)tosrc/utils/aria.ts.Commit 2 — Give Navigator a
stop(reason)tool + fix the prompt contradictionEven with the rejection signal fed back, Navigator was still stuck: the retry prompt told the model both "this is NOT a locator issue" AND "propose new solutions" in the same turn, and the model had no tool to opt out.
This commit:
tools = undefinedinresolveStatewith a singlestop(reason)tool the AI can call when no locator change can help (wrong credentials, missing knowledge, captcha, blocking error). Mirrors Tester's existingstoptool pattern attester.ts:938.stop()or correct the submitted data (two clear choices, no locator changes); click didn't register → propose new locator strategies (old behaviour).stop()is called, the reason is logged at error level and surfaced in the existing interactive failure prompt so the user knows what to fix.No control-flow rewrite — the model can still emit code blocks in text; the tool is an optional escape.
Test plan
bun run format/bun run lint:fixcleanextractAlertssmoke-tested across 7 snapshot shapes (named, YAML-colon, container-with-text, status, alertdialog, nested, empty)./bin/explorbot-cli.ts navigate /against the demo app: happy path still succeeds on first attempt in ~10s with ARIA locators.env, runexplorbot navigate /, expect Navigator to callstop()after seeing the rejection alert (instead of looping 9 times). I couldn't run this end-to-end in CI because explorbot'sloadEnvoverwrites command-line env vars, and the demo's experience file caches the correct credentials. Easy to verify locally.🤖 Generated with Claude Code