Skip to content

feat: target the connected browser, not Chrome by default (#29) - #30

Merged
jack-arturo merged 4 commits into
mainfrom
agent/kernel-worker/64ffceab
Nov 7, 2026
Merged

jack-arturo merged 4 commits into
mainfrom
agent/kernel-worker/64ffceab

Conversation

@jack-arturo

Copy link
Copy Markdown
Member

Browser Hand assumed Google Chrome across the stack. When the extension
runs in a non-Chrome Chromium browser (e.g. "Search"), tab bootstrap failed
with HTTP 500 ("debugger.attach isn't available in Search"), doctor
recommended the wrong fix (path_b), file: URLs failed in tabs.create, and
the skill text pushed agents to fall back to open -a "Google Chrome".

Implements the four asks from #29:

  1. Detect the host browser. extension/utils/browser-info.ts reads the
    product brand/version from navigator.userAgentData (preferring the real
    product over the shared "Chromium" engine brand and the GREASE
    placeholder), falling back to a UA-string parse. The extension registers
    it with the relay on connect; the relay only ever holds one extension
    connection, so the connected browser is the current target. --browser
    lets the caller assert which browser they expect and warns on mismatch.

  2. Report it. The relay exposes browser: {name, version} on the health
    endpoint; doctor surfaces it. doctor now distinguishes
    debugger_unavailable (this browser restricts chrome.debugger) from
    path_b_required (needs a separate debug profile).

  3. Fall back to scripting. When chrome.debugger.attach is unavailable,
    TabManager marks the browser debugger-unavailable and switches the tab to
    the scripting transport instead of throwing, so open still creates the
    tab via chrome.tabs.create and continues rather than returning HTTP 500.

  4. Local files. file: URLs fail in chrome.tabs.create, so the CLI rewrites
    them to the relay's new /local-file route, which reads the file and
    serves it over http with a content type.

Docs: SKILL.md now says "your browser with the Browser Hand extension" (not
Chrome), documents the file: and debugger_unavailable paths, and adds a rule
to never open tabs with OS commands as a fallback.

Tests: browser-info detection, debugger_unavailable classification + doctor
distinction, file: URL rewrite, local-file serving, and the TabManager
scripting fallback.

Closes #29

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Closes #29

Opened by AutoJack after the AutoHub babysit finalizer exited without creating the PR (agent-fp-480b25e580478ac264ffceab, retry attempt fede23f2).

Browser Hand assumed Google Chrome across the stack. When the extension
runs in a non-Chrome Chromium browser (e.g. "Search"), tab bootstrap failed
with HTTP 500 ("debugger.attach isn't available in Search"), doctor
recommended the wrong fix (path_b), file: URLs failed in tabs.create, and
the skill text pushed agents to fall back to `open -a "Google Chrome"`.

Implements the four asks from #29:

1. Detect the host browser. `extension/utils/browser-info.ts` reads the
   product brand/version from navigator.userAgentData (preferring the real
   product over the shared "Chromium" engine brand and the GREASE
   placeholder), falling back to a UA-string parse. The extension registers
   it with the relay on connect; the relay only ever holds one extension
   connection, so the connected browser is the current target. `--browser`
   lets the caller assert which browser they expect and warns on mismatch.

2. Report it. The relay exposes `browser: {name, version}` on the health
   endpoint; `doctor` surfaces it. `doctor` now distinguishes
   `debugger_unavailable` (this browser restricts chrome.debugger) from
   `path_b_required` (needs a separate debug profile).

3. Fall back to scripting. When chrome.debugger.attach is unavailable,
   TabManager marks the browser debugger-unavailable and switches the tab to
   the scripting transport instead of throwing, so `open` still creates the
   tab via chrome.tabs.create and continues rather than returning HTTP 500.

4. Local files. `file:` URLs fail in chrome.tabs.create, so the CLI rewrites
   them to the relay's new `/local-file` route, which reads the file and
   serves it over http with a content type.

Docs: SKILL.md now says "your browser with the Browser Hand extension" (not
Chrome), documents the file: and debugger_unavailable paths, and adds a rule
to never open tabs with OS commands as a fallback.

Tests: browser-info detection, debugger_unavailable classification + doctor
distinction, file: URL rewrite, local-file serving, and the TabManager
scripting fallback.

Closes #29

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T02:48:25.007752Z 6c12c4a Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c14709b8b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread relay/src/relay.ts Resolved
Comment thread cli-js/src/tool.js Resolved
@jack-arturo

Copy link
Copy Markdown
Member Author

@claude please take the Codex P1 on this PR: local HTML documents opened by the relay (relay/src/relay.ts:584) appear able to reach the unrestricted file-reading endpoint. Investigate the exposure (what origin local pages are served from, whether they can fetch arbitrary paths through the local-file endpoint, and whether any token or origin check gates it), then propose or implement a fix, e.g. serve local documents from an isolated origin and scope file reads to the opened document's directory behind a per-document capability.

While you're there, also look at the Codex P2 at cli-js/src/tool.js:519 about relative resource resolution for local documents, and make sure the fix for the P1 keeps relative assets working.

Please don't merge this PR. Note: the failing Daemon (TypeScript + Tests) (ubuntu-latest) job is a runner issue ("Playwright does not support chromium on ubuntu26.04-x64"), so pinning ubuntu-24.04 is fine to include.

@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Agent autojack-orchestrator failed after 13s

Server restarted while task was running (reconciled: no live worker)

Task github-autojack-6f9e22b0333a193b68dd5cb0

@autojack-bot

autojack-bot Bot commented Nov 4, 2026

Copy link
Copy Markdown

Dispatched as task agent-fp-b85f988b75b0b1bb86908302. It's next up on the runner, with 0 of 2 lanes busy.

P1 (relay/src/relay.ts:584). From the review comment, local pages are served from the relay's own origin. /local-file?path= takes an arbitrary path, and the review reports no token or origin check. So a local document's JS could fetch any file the relay can read. The task will confirm this in the code and add a regression test for it.

Planned fix.

  • Replace the raw-path route with a per-document random capability token and /local/<token>/<relative path> URLs.
  • Reads are confined to the registered document's directory: realpath resolution, no .., no symlink escape, and sibling-prefix directories are blocked.
  • Local documents are served from an origin separate from the relay API.
  • Documents get a CSP, nosniff, no-referrer and no CORS.
  • Tokens expire and are bounded in number.

P2 (cli-js/src/tool.js:519). Relative assets such as ./style.css and img/a.png will resolve under the document's tokenized directory path. Tests will cover this, and the original query and hash are preserved.

CI. The Playwright-based jobs will be pinned to ubuntu-24.04, including the failing Daemon job.

The work goes onto this PR's branch, agent/kernel-worker/64ffceab. I won't merge this PR, and the hub will post the result here when the task finishes.

jack-arturo and others added 2 commits November 4, 2026 03:08
Codex review on #30.

P1: /local-file?path=... let any page served by the relay (same origin as the
relay API) read any file the relay process could read and call every relay
route. Replace it with a registration flow: POST /local-docs (CLI-only: no
Origin header, JSON body) returns a 192-bit token, and documents are served
from a second listener (its own origin) at /local/<token>/<relative path>,
resolved with realpath strictly inside the document's directory. Traversal,
encoded traversal, absolute paths, escaping symlinks, dotfiles and sibling
directories sharing the prefix are all 404.

Doc responses carry CSP connect-src 'self', nosniff, no-referrer, CORP
same-origin and no CORS headers. Control routes (including the /cdp and
/extension upgrades) reject requests whose Host or Origin is the document
origin. Tokens expire after 2h idle, the registry is bounded (64, LRU) and
cleared on stop().

P2: rewriteLocalFileUrl is now async: it registers with the relay and returns
the capability URL, so ./style.css, img/a.png etc. resolve inside the
document's directory, and the file: URL's query string and hash are kept.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Codex review on #30: P1 (/local-file) and P2 (rewriteLocalFileUrl)

Both findings reproduced on this PR's head (c100e1e) and are fixed in 6c12c4a. Note: that commit was made by a worker that was told not to push, so it lands on this branch via the finalizer. Until then it is not visible here.

Investigation (pre-fix, unmodified relay, real Chromium)

Question Answer (confirmed by reading relay/src/relay.ts + running it)
What origin do local pages run on? The relay's own origin, http://127.0.0.1:<port>. Same origin as /, /pages, /local-file.
Can a page fetch arbitrary paths? Yes. readLocalFile did resolve(requested) + readFile with no root. A page in /tmp/bh-repro/report/ read /tmp/bh-repro/secret/creds.txt (a sibling directory) via fetch('/local-file?path=…') → 200 "TOP-SECRET-TOKEN=abc123".
Any token / Origin / Host gate? None, on any route. There was no auth middleware, no Origin/Host check, no CORS config. The only protection was the loopback bind, and same-origin script needs no CORS. The page also read /pages (200).
P2 Same page: ./style.css → relay /style.css → 404.

Pre-fix DOM captured in headless Chromium: origin=http://127.0.0.1:19333, /local-file?path=<secret> -> 200, /pages -> 200, ./style.css -> 404.

Design

  • Capability, not a path. POST /local-docs {path} registers one document and returns a 192-bit token (crypto.randomBytes(24)). Documents are served at /local/<token>/<relative path>. /local-file is removed, and no served route accepts a filesystem path.
  • Containment. Reads are resolved with realpath and must be a strict descendant of the registered document's directory. 404 for .., %2e%2e, %2f/%5c, NUL, malformed escapes, absolute paths, symlinks leaving the directory, a sibling sharing the prefix (/report vs /report-secret), and dotfiles (.env, .git, …). A registered document that itself symlinks out of its directory is refused (400). Every failure is the same bare 404.
  • Origin isolation: separate listener. The relay starts a second HTTP listener (OS-assigned port, localDocPort to pin it). Origins include the port, so documents are never same-origin with the API. I picked this over a localhost vs 127.0.0.1 split because that depends on a Host check being right on every route (including WS upgrades) and breaks if the relay is bound to a non-loopback host. The doc listener has no route except /local/<token>/….
  • Headers on every doc response: Content-Security-Policy: … connect-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self', X-Content-Type-Options: nosniff, Referrer-Policy: no-referrer (keeps the token out of Referer), Cross-Origin-Resource-Policy: same-origin, Cache-Control: no-store, and no CORS headers.
  • Control routes reject the doc origin. A middleware in front of every relay route (health, /pages, /cdp and /extension upgrades, /local-docs) returns 403 when Origin or Host is the doc authority.
  • Registration is CLI-only: it must carry no Origin header (browsers always send one on POST), Content-Type: application/json, and a valid absolute path to a regular file.
  • Lifetime: idle TTL 2 h (sliding), registry bounded to 64 with LRU eviction, cleared on stop().
  • P2 / CLI: rewriteLocalFileUrl is now async: it registers with the relay and returns <doc origin>/local/<token>/<basename> plus the original ?query#hash. It runs after ensureRelayConnected, since registering needs a running relay. A relay that predates this change gets a clear "restart browser-hand relay" error. ./style.css, img/a.png and ../x (within the directory) resolve against the capability URL.
  • CI: c100e1e already pins Daemon (TypeScript + Tests) to ubuntu-24.04. No other workflow installs Playwright browsers (release.yml and the other ci.yml jobs don't), so nothing else needed pinning.
  • Docs: SKILL.md local-file bullet, browser-hand --help, and an AGENTS.md relay note (never add a route that takes a path from a request).

Verification

Post-fix, same hostile page, real Chromium, relay + CLI path (rewriteLocalFileUrl) as shipped:

origin=http://127.0.0.1:53451                      <- not the relay origin (19334)
search=?relay=http://127.0.0.1:19334 hash=#frag     <- query/hash preserved
css applied via relative ./style.css: body color=rgb(255, 0, 0)
relative ./style.css -> 200
old route /local-file?path=<secret> -> 404
relative ../secret/creds.txt -> 404
encoded %2e%2e/secret/creds.txt -> 404
same-origin /pages (doc listener) -> 404
relay API http://127.0.0.1:19334/pages -> BLOCKED (TypeError)       <- CSP connect-src 'self'
relay POST http://127.0.0.1:19334/local-docs -> BLOCKED (TypeError)
relay:   node --import tsx --test "src/*.test.ts"   tests 21 / pass 21 / fail 0
cli-js:  node --test "test/*.test.js"               tests 164 / pass 164 / fail 0
relay:   tsc -p tsconfig.json --noEmit              clean
prettier --check on every touched file I own        clean

New coverage: relative CSS/JS/image/nested loads; traversal (raw, encoded, absolute) → 404; symlink and /report vs /report-secret prefix sibling → 404; unknown and expired tokens → 404; doc origin can't reach /, /pages, /cdp, /extension or /local-docs (Origin, Host and WS-upgrade variants, with positive controls); registration refuses Origin/text-plain/relative/missing; TTL slide, LRU bound, clear; CLI contract against a stub relay plus an end-to-end test that drives the real rewriteLocalFileUrl against a real relay. I mutation-checked the guards: disabling containment, the doc-origin guard, the CSP connect-src or the dotfile rule each makes tests fail.

Caveats worth a reviewer's eye

  • A document can still read its own directory tree (minus dotfiles and symlinks out). That is the requested capability scope. Opening a report from a broad directory like ~/Downloads exposes that directory to the page.
  • connect-src 'self' means a report that fetches remote JSON no longer works through open file:…. Scripts, styles and images from https: still load.
  • The other control routes remain unauthenticated and reachable by any local process (pre-existing, out of scope here). DNS rebinding of those routes would need a Host allowlist, which I did not add.
  • Size: the delta on top of c100e1e is 894 changed lines (roughly half are tests).
  • The old query-path /local-file URL is gone, with no compatibility shim.
  • node_modules was symlinked from the main checkout for the run; nothing under it is committed.

@autohub-claude autohub-claude Bot added the babysit:active Babysit agent is actively working this PR label Nov 4, 2026
@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Babysit stopped — size. This remediation push grew the PR from 560 to 1280 changed lines (additions + deletions). Remediation has added 720 lines since babysit started at 560, past the 600-line remediation budget. A PR still growing this much inside review is a design being renegotiated, not a fix being applied. Split it along the proposed split below (the split-to-prs skill carries it out), or re-run with --allow-large.

Proposed split: 9 PRs, in landing order. Each part keeps source files with their tests and lands after the parts it needs. Parts stay under the 400-line per-PR target unless one file and its tests are larger. Babysit has not created any branch or PR. To go ahead, ask an agent to run this split with the split-to-prs skill. This comment is the plan it needs approved.

Part Changed lines Base Open threads
1. relay/src/local-file.ts 392 (240 source, 152 tests) main 0
2. cli-js/src/tool.js 210 (80 source, 130 tests) main 0
3. relay/src/relay.ts, AGENTS.md 387 (151 source, 234 tests, 2 docs) part 2 0
4. extension/utils/browser-info.ts, extension/entrypoints/background.ts 190 (109 source, 81 tests) main 0
5. extension/services/TabManager.ts 71 (35 source, 36 tests) main 0
6. cli-js/src/cli.js 13 main 0
7. skills/browser-hand/SKILL.md 7 main 0
8. .github/workflows/ci.yml 5 main 0
9. relay/package.json, relay/src/standalone.ts 5 main 0
graph LR
  base["main"]
  P1["1. 392 lines"]
  base --> P1
  P2["2. 210 lines"]
  base --> P2
  P3["3. 387 lines"]
  P1 --> P3
  P2 --> P3
  P4["4. 190 lines"]
  base --> P4
  P5["5. 71 lines"]
  base --> P5
  P6["6. 13 lines"]
  base --> P6
  P7["7. 7 lines"]
  base --> P7
  P8["8. 5 lines"]
  base --> P8
  P9["9. 5 lines"]
  base --> P9
Loading
Files, dependencies and threads per part

Part 1. Branches off main.

  • relay/src/local-file.ts (+240 -0)
  • relay/src/local-file.test.ts (+152 -0)

Part 2. Branches off main.

  • cli-js/src/tool.js (+80 -0)
  • cli-js/test/doctor-browser.test.js (+130 -0)

Part 3. Stacks on part 1, because relay/src/relay.ts imports relay/src/local-file.ts; part 2, because relay/src/local-file-server.test.ts imports cli-js/src/tool.js.

  • relay/src/relay.ts (+149 -2)
  • relay/src/local-file-server.test.ts (+234 -0)
  • AGENTS.md (+1 -1)

Part 4. Branches off main.

  • extension/entrypoints/background.ts (+16 -1)
  • extension/utils/browser-info.ts (+92 -0)
  • extension/__tests__/browser-info.test.ts (+81 -0)

Part 5. Branches off main.

  • extension/services/TabManager.ts (+35 -0)
  • extension/__tests__/TabManager.test.ts (+36 -0)

Part 6. Branches off main.

  • cli-js/src/cli.js (+10 -3)

Part 7. Branches off main.

  • skills/browser-hand/SKILL.md (+5 -2)

Part 8. Branches off main.

  • .github/workflows/ci.yml (+4 -1)

Part 9. Branches off main.

  • relay/package.json (+3 -1)
  • relay/src/standalone.ts (+1 -0)

What this run did

  • Pushed 6c12c4a to this branch as a fast-forward from c100e1e (no force). PR head verified as 6c12c4a552dd7c26b74ab53d899ca4bc070710a9. The push stays: it carries the P1 and P2 fixes, and both Codex threads are replied to and resolved.
  • Size: preflight 560 changed lines, after this push 1280 (+720). The 900-line gate is a preflight rule; after a push the stop comes from the remediation budget (600 total / 400 per push). --allow-large was not passed, so I stopped here rather than start another review round.
  • To continue, either: approve a split (ask an agent to run the split-to-prs skill with the plan above), or re-run Babysit with --allow-large to accept a 1,280-line review. Roughly half of the added lines are tests.
  • Seam note on the plan (I did not edit it): the planner splits the PR's whole net diff against main, so it also separates the original connected-browser work (extension parts 4 and 5, 261 lines) that this PR carried before the fix. Parts 6 to 9 are 5 to 13 lines each. A human may prefer folding 6 to 9 into their nearest parts and keeping 4 and 5 together, which is about 4 PRs instead of 9.

Verification on the pushed head

Check Result
relay: node --import tsx --test "src/*.test.ts" 21 / 21 pass
cli-js: node --test "test/*.test.js" 164 / 164 pass
relay: tsc -p tsconfig.json --noEmit clean
Real headless Chromium, hostile page on the doc origin (isolated relay on :19555, doc origin :59713, loaded through the shipped rewriteLocalFileUrl) origin is not the relay origin; ?query#hash preserved; relative ./style.css, app.js, img/a.png load (rgb(255, 0, 0) applied); ../secret/creds.txt, %2e%2e/…, ../report-secret/… and old /local-file?path= are all 404; / and /pages on the doc origin 404; relay API and POST /local-docs blocked by CSP
Doc response headers (read in the browser) connect-src 'self' CSP, nosniff, no-referrer, CORP: same-origin, no-store, zero access-control-*
Mutation check: remove the containment check in LocalDocRegistry.read 2 tests go red, including a document cannot read outside its directory (P1 regression). Restored; tree identical to 6c12c4a

Not run: a curl matrix of forged Host and Origin requests against the live relay (the call was declined in this environment). Those variants, including WebSocket upgrades and positive controls, are covered by relay/src/local-file-server.test.ts, which passes.

CI at the time of this comment (not waited on, per the size stop): Daemon (TypeScript + Tests) (ubuntu-24.04) pending, so the runner pin took effect; Daemon ... (windows-latest) and CLI (Rust) (windows-latest) pending; CLI (Rust) (ubuntu-latest), Build Daemon Bundles and Format Checks pass. Codex has not yet reacted to this head. mergeable is MERGEABLE.

Open advisory finding, left unfixed on purpose

The bounded local review pass (Codex, gpt-6.1-sol, medium, one pass) reported one P2 against relay/src/local-file.ts:203-205, and I reproduced it on this head: the dotfile rule only inspects the requested path, so a non-dot symlink that stays inside the document directory and points at a dotfile bypasses it.

/index.html -> 200
/.env       -> 404
/config.txt -> 200 "API_KEY=hunter2"     (config.txt is a symlink to .env in the same directory)

Why I did not fix it here: the requested containment still holds (nothing leaves the registered directory), the dotfile rule is an extra layer the worker added beyond the acceptance criteria, and this PR has no Review Contract or Threat Model to make it a direct breach. Under the Babysit rules that makes it a hardening decision, not an auto-fix. Untested sketch of the change: after realpath, apply the existing dot-segment check to relative(entry.root, real).split(sep) as well, keeping the exception for the registered document itself, plus a regression test with config.txt -> .env.

It is not filed as a separate issue: it concerns unmerged code, and AGENTS.md routes vulnerability-class reports to private advisories. It is tracked only in this comment.

Babysit finalizer: Claude Code (claude-sonnet-5-5) via the AutoHub GitHub App. 0 Codex review requests were posted by this run. No merge was performed.

@autohub-claude autohub-claude Bot added babysit:blocked Babysit stopped; unresolved blocker needs human and removed babysit:active Babysit agent is actively working this PR labels Nov 4, 2026
@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Agent kernel-worker failed after 2089s

Too large for one PR: 1280 changed lines on agent/kernel-worker/64ffceab. Split proposed, no PR opened.

Task agent-fp-b85f988b75b0b1bb86908302

@jack-arturo

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6c12c4a552

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cli-js/src/tool.js Resolved
@autohub-claude autohub-claude Bot added babysit:active Babysit agent is actively working this PR and removed babysit:blocked Babysit stopped; unresolved blocker needs human labels Nov 4, 2026
…hides

When the host browser rejects debugger.attach, TabManager falls back to the
scripting transport, so the doctor's smoke tab opens fine and classification
returned tab_bootstrap_works before ever seeing the error it keyed on. The
documented debugger_unavailable status was unreachable with the updated
extension, and limits such as Page.navigate being rejected on scripting tabs
went unreported.

- extension: TabManager reports the limitation to the relay (register message)
  the first time it sees it; registerHostBrowser re-sends it on every connect,
  since ConnectionManager.send drops messages while the socket is down.
- relay: keep the report per extension connection (cleared on replace/close),
  validated and bounded, and expose it as `debugger` on GET /.
- doctor: re-read the relay after the smoke tab (the attach, and so the
  discovery, happens during it), classify debugger_unavailable explicitly even
  when the smoke succeeded, expose `debugger` in the result, and drop the
  misleading "Tab bootstrap failed" path_b note for this status.

Tests: fake extension -> real relay -> real doctor end-to-end, classifier unit
tests, and TabManager report-once / wedge-is-not-a-limitation tests.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@autohub-claude autohub-claude Bot added babysit:waiting-ci Babysit waiting for CI checks on current head babysit:ready 👍 Codex all clear + gates pass; human may merge and removed babysit:active Babysit agent is actively working this PR babysit:waiting-ci Babysit waiting for CI checks on current head labels Nov 4, 2026
@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Babysit hand-off — verified green at 4cde108cf242183cb2bea424105ea7afe522f014 (Claude Code via AutoHub GitHub App)

  • Fixed: the open P2 (cli-js/src/tool.js:860, debugger capability not reaching doctor) in 4cde108. Thread replied to and resolved; 0 unresolved threads remain.
  • CI: 6/6 checks pass on this head.
  • Codex: auto-review did not fire for 4cde108 inside the 10m grace window (no 👀, no 👍, no quota notice). Earlier heads c14709b8b8 and 6c12c4a552 were reviewed. So this head carries an auto-review skip, not an explicit Codex pass.
  • Size: 1,611 changed lines (start 1,280, +331 this push), over the 900-line gate. Proceeded on the operator's instruction to ignore the earlier size-gate stop; a split plan is available on request.
  • Tests: relay 25/25, cli-js 165/165, extension 67/67, relay typecheck clean. Extension tsc still reports 3 errors, all in __tests__/CDPRouter.test.ts, a file this PR does not touch.
  • Not done: the local pre-push review was skipped (runner invocation declined), and the new tests were not run red against the pre-fix code, only green with the fix.
  • Behavior note: debugger_unavailable keeps success: false (doctor exits non-zero), like every status other than tab_bootstrap_works; SKILL.md says so.

Label: babysit:ready. No merge was performed.

@autohub-claude

autohub-claude Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Agent kernel-worker failed after 789s

Babysit follow-on finished but label verification failed: Command failed: gh pr view 30 --json labels --jq [.labels[].name] | map(select(startswith("babysit:")))
GraphQL: Could not resolve to a PullRequest with the number of 30. (repository.pullRequest)

Task agent-fp-b85f988b75b0b1bb86908302

@jack-arturo
jack-arturo merged commit 7b02d50 into main Nov 7, 2026
6 checks passed
@jack-arturo
jack-arturo deleted the agent/kernel-worker/64ffceab branch November 7, 2026 22:28
@jack-arturo jack-arturo removed the babysit:ready 👍 Codex all clear + gates pass; human may merge label Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant