fix: own a labelled browser tab so Chrome's Gemini panel (or an operator tab) can't take it (0.3.2) - #3
Merged
Conversation
Seen live 2026-09-13 on merchantAgent: one Kill Team item priced, then every navigation failed with `net::ERR_BLOCKED_BY_CLIENT`. Chrome 149's built-in Gemini side panel (gemini.google.com/glic) opened on its own in the headed window as a `webview` target, and the pinned agent-browser (0.27.1) makes a newly discovered target the ACTIVE tab — so `open` navigated the panel, which Chrome refuses. (Upstream 0.34.0 fixed "event-discovered targets steal the active tab"; the core pin is still 0.27.1.) - `Browser.ensure_page_tab()`: one `tab list`; when the active tab is not an ordinary page (a `page` target on http(s)/about:blank that is not the Gemini panel), close the non-page targets, reselect the first web page, or open a new tab. Runs before every navigation. - A navigation that still fails with ERR_BLOCKED_BY_CLIENT is repaired and retried once; with nothing to repair it raises as before. - A read whose `location.href` is the panel (or chrome:// / devtools://) is treated as decided — the settle loop no longer spins ~10 s on it — and `_fetch` repairs the tab, re-navigates and re-reads once instead of reporting "couldn't find the results list". - Skill: ERR_BLOCKED_BY_CLIENT explained as a browser-tab problem, not an eBay one. - 142 host-free tests (was 135); 0.3.2. Not done: disabling the panel at launch (`--disable-features=Glic`) — the feature name for Chrome 149 could not be verified, and `--args` splits on commas, which would clobber the base `--disable-features=Translate`. The repair covers it whatever opens the panel. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UQ33xXfygwEkzbbJx3YwZ
… any foreign read Review round 1 on this PR (FIX FIRST): the first cut closed every tab that was not http(s) — the operator's file://, data:, view-source: tabs too — and reselected whichever web tab agent-browser listed first, which could be the operator's Gmail; its re-read after a repair skipped the settle loop (the false "markup changed" error the redirect fix exists to prevent); session status could report signed_in:false when another tab answered. - The plugin owns ONE labelled tab (`ebaytab`). The launch step is now `tab ebaytab` / `tab new --label ebaytab` WITH the launch flags — verified live on a throwaway session: it launches Chrome on the requested profile with the stealth argument, is reused on repeat, and `open` lands in the labelled tab. The old `open about:blank` launch blanked whatever tab was active (could be the operator's). - Every navigation switches to that tab first (one CLI call, flags attached, so a dead daemon relaunches with OUR options instead of a default headless browser). - Only Chrome's panels are ever closed: `type == "webview"` or the Gemini URL. An ordinary page is never closed, whatever its URL. - ERR_BLOCKED_BY_CLIENT on a navigation → close panels, reclaim our tab, retry once. - tools: ONE read path (`_read_page`: navigate → wait → read → settle). A read whose host is not the requested site (panel, about:blank, an operator tab) reclaims the tab, re-navigates and reads again through the SAME settle loop — once. Used by sold and active searches, Amazon, session status (never a false "signed out": it says it could not check) and the page probe (reports landed_url). - 156 host-free tests (was 142): ordering asserted (switch immediately before each navigation; panel closed and tab reclaimed BETWEEN the two navigations), pages never closed, labelled-tab creation without navigating another tab, flags on tab commands, settle after reclaim, session status / probe / Amazon reclaim, host rules. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UQ33xXfygwEkzbbJx3YwZ
Member
Author
|
Gate for e011018: CI test pass; Vera's panel returned PASS (check-run: "PASS verdict — post refused" — GitHub refused the review post, so the red protoReview check is a posting failure, not a finding); in-session adversarial review round 2: MERGE, no blockers. Non-blocking follow-ups are on branch |
mabry1985
added a commit
that referenced
this pull request
Sep 13, 2026
…h (0.3.3) Review round 2 on #3 (MERGE, no blockers) confirmed two gaps with stubs; closed here. - Wedged own tab: if the labelled tab exists but will not take focus (hung/crashed), `tab new --label` is refused "already used" and every navigation failed until the operator closed it by hand. Now: close OUR labelled tab (the only one carrying the label) and create a fresh one ("recreated"). - Wrong-search reads: the host check let an operator's own eBay search (a cmd-click in the shared window) answer ours — `ok: true` with prices for the operator's query. For a search request, the landed page must be the same host and, when it states search terms (`_nkw` on eBay /sch/, `k` on Amazon /s), the SAME terms (normalized: case, +/%20, spacing, parameter order). An item/product page answering a search is a hijack. Sign-in and challenge hops on subdomains, and search pages that state no terms (eBay rewrites), are not judged here. - The module docstring now states the residual sub-second race honestly (0.27.1's `open` cannot name a tab; the read-side check catches the result). - Tests: wedged-tab recovery closes only the labelled tab; reclaim through a blocked navigation with an operator Gmail and an operator eBay search in the list closes only the panel (locks in round 1's fix via the real path); 10 same-search cases. 168 host-free tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UQ33xXfygwEkzbbJx3YwZ
mabry1985
added a commit
that referenced
this pull request
Sep 13, 2026
…h (0.3.3) (#4) * fix: recover a wedged plugin tab; a search read must be our own search (0.3.3) Review round 2 on #3 (MERGE, no blockers) confirmed two gaps with stubs; closed here. - Wedged own tab: if the labelled tab exists but will not take focus (hung/crashed), `tab new --label` is refused "already used" and every navigation failed until the operator closed it by hand. Now: close OUR labelled tab (the only one carrying the label) and create a fresh one ("recreated"). - Wrong-search reads: the host check let an operator's own eBay search (a cmd-click in the shared window) answer ours — `ok: true` with prices for the operator's query. For a search request, the landed page must be the same host and, when it states search terms (`_nkw` on eBay /sch/, `k` on Amazon /s), the SAME terms (normalized: case, +/%20, spacing, parameter order). An item/product page answering a search is a hijack. Sign-in and challenge hops on subdomains, and search pages that state no terms (eBay rewrites), are not judged here. - The module docstring now states the residual sub-second race honestly (0.27.1's `open` cannot name a tab; the read-side check catches the result). - Tests: wedged-tab recovery closes only the labelled tab; reclaim through a blocked navigation with an operator Gmail and an operator eBay search in the list closes only the panel (locks in round 1's fix via the real path); 10 same-search cases. 168 host-free tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UQ33xXfygwEkzbbJx3YwZ * fix: only a different site counts as settled; same-search check survives `domain: ebay.com` Review of #4 (MERGE, no blockers) — two confirmed follow-ups folded in: - FP2: `_is_undecided` treated any hijack as settled, so a same-site page flagged by the same-search rule that was ALSO still loading skipped the settle loop and failed as "could not find the results list". Now only `_foreign_host` (a different site) is settled. - FN1: the same-search check compared the raw hostname, so with `domain: ebay.com` (no www) eBay's redirect to www silently disabled it on every read. Compare `_site(host)`. - Tests: www-less domain in both directions, a search landing on a sign-in subdomain, and the settle behaviour (the reviewer's surviving mutant M1 now fails). 172 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011UQ33xXfygwEkzbbJx3YwZ --------- Co-authored-by: Claude Opus 5 (1M context) <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.
Chrome's Gemini panel steals the browser tab → ERR_BLOCKED_BY_CLIENT
Live 2026-09-13 on merchantAgent: one Kill Team item priced, then every navigation failed with
net::ERR_BLOCKED_BY_CLIENT. Chrome 149's built-in Gemini side panel opened by itself as awebviewtarget; agent-browser 0.27.1 makes any newly discovered target the ACTIVE tab and runs every command on the active tab, so the plugin navigated the panel. (Upstream fixed tab stealing in 0.34.0; the core pin is 0.27.1.)Design (after review round 1)
ebaytab). The launch step istab ebaytab/tab new --label ebaytabwith the launch flags — no navigation of any other tab. (The oldopen about:blanklaunch blanked whatever tab was active, which could be the operator's.)type == "webview"or the Gemini URL); ordinary pages never, whatever their URL._read_page: navigate → wait → read → settle). A read whose host is not the requested site reclaims the tab and re-reads through the same settle loop, once. Sold/active search, Amazon, session status (never a false "signed out") and the page probe all use it.Verification
tab new --label ebaytab --profile P --args …launched Chrome on P with the stealth arg; repeat reused the same Chrome; unknown label → exit 1 "No tab with label"; duplicate label refused;openlanded in the labelled tab.tab listshowedt2 webview ACTIVE gemini.google.com/glic; closing it restored navigation.🤖 Generated with Claude Code
https://claude.ai/code/session_011UQ33xXfygwEkzbbJx3YwZ