fix(browser): survive a closed tab, pass Google's automation check and tear the browser down after one-shot runs - #1600
Merged
Conversation
…d tear the browser down after one-shot runs Field test of the visible hand-off against a real GitHub login surfaced three defects. Google refused the sign-in with "this browser or app may not be secure": Chrome under remote debugging reports navigator.webdriver as true unless the AutomationControlled blink feature is disabled. The launcher now passes that flag; a headed session reports webdriver false, which is what the check looks at. When the user closed the window afterwards, wait died with a raw CDP "session with given id not found". The session now hears the detach and destroy events for its page and recognises the error code: page-scoped commands surface ErrPageClosed, wait reports the closed page as a result the model can act on, status tags it, and the next command attaches a fresh blank tab before talking to the page, so the session keeps working without a relaunch. The browser outlived every chatcli -p run: the one-shot path returned without the interactive teardown and Fatal exited without unwinding. The tool helper shutdown, browser, language servers and background processes, is now one shared helper called from the interactive cleanup, deferred in the one-shot handler and invoked on each of its failure paths before Fatal. Also open no longer prefixes https:// onto about:, data:, file: and other scheme-carrying URLs, which made about:blank an invalid navigation.
Contributor
Quality GateResult: ✅ all floors passed
Config: .github/quality-gate.yml. Workflow: |
This was referenced Sep 15, 2026
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.
Why
Field test of the
show→waithand-off (PR #1598) against a real GitHub login, with the user signing in through Google, surfaced three defects.What
navigator.webdriver === trueunless--disable-blink-features=AutomationControlledis passed. The launcher now passes it (measured:true→false), which is what that check looks at. Documented, with the fallback of attaching to the user's everyday Chrome viaCHATCLI_BROWSER_CDP_URL.waitfailed with a rawcdp error -32001: Session with given id not found. The session now enables target discovery, marks the page gone onTarget.detachedFromTarget/Target.targetDestroyedfor its own target, and recognises-32001on page-scoped commands: they surfacebrowser.ErrPageClosed;waitreturns it as a result the model can act on;statustags it; the next command attaches a fresh blank tab before talking to the page (no relaunch, session and cookies kept).statusnever reattaches.chatcli -prun — the one-shot path returned without the interactive teardown, andlogger.Fatalexits without unwinding.shutdownToolProcesses(browser + LSP pool + @proc supervisor) is now one helper shared by the interactivecleanup, deferred inHandleOneShotOrFatal, and called on each failure path beforeFatal. Verified with the real binary: 0 Chrome processes left after a one-shot coder run that opened the browser.Also:
open about:blankwas turned intohttps://about:blank(invalid navigation) — scheme-carrying URLs (about:,data:,file:, …) are now left alone.Tests
pkg/browser:chromeArgscarries the flag and orders--headless=newfirst; fake browser that answers-32001once the page is "closed" →ErrPageClosed,PageClosed(), exactly one new target created on the next call and the session drives it;detachedFromTargetmarks the page closed, events for other targets are ignored, and the first call after a detach reattaches without ever seeing-32001.cli/plugins:waitreturns the closed-page message as a result and still propagates other errors; URL normalization table incl.about:blankreaching the backend untouched.go test -racegreen onpkg/browser,cli/plugins;clione-shot/config tests green; golangci-lint v2.13.2 0 issues.