fix(govern): observe({page}) routes through the live-capture path#56
Conversation
captureFromBridge has accepted a caller-owned page since the broker seam (PR #5), but observe()'s hasBridge check only looked for browserWSEndpoint/ browserURL — a bare {page} fell through to captureFromHtml(undefined) instead of reading the live session. Callers holding an authed page (broker checkout, an agent's active browser_use session) can now observe current page state through the live extractor: computed-style hidden detection, shadow roots, no navigation, lifecycle untouched.
sprayberry-reviewer
left a comment
There was a problem hiding this comment.
Automated review from the Sprayberry Labs fleet code reviewer.
Verdict: No blocking issues found — clean, well-scoped one-line routing fix with a matching regression test.
What I checked
gh pr difffor the full change (2 files, +27/-3):src/govern.mjsandtest/broker.test.mjs.src/capture.mjs::captureFromBridge(not touched by this PR) to confirm theopts.pagebranch it already implements matches what the PR's comments claim:src/capture.mjs:261-269— whenopts.pageis set, it only callspage.setContent/page.gotoifhtml/urlare given, otherwise reads the page as-is and pullsurlfrompage.url(). That matches the PR description's claim of "no navigation when no url/html is given."- CI rollup via
gh pr checks 56: CodeQL, analyze, test, test-node20 — allpass.
The fix
src/govern.mjs:98 (new):
const hasBridge = input.browserWSEndpoint != null || input.browserURL != null || input.page != null;Before this PR, observe({page}) alone (no browserWSEndpoint/browserURL) fell through to captureFromHtml(input.html, ...) with input.html === undefined, silently bypassing the live-capture path that captureFromBridge already supported for a caller-owned page. Adding input.page != null to the bridge-detection predicate is the correct, minimal fix — captureFromBridge (untouched) already handles the opts.page case correctly, so this is purely a routing correction at the call site.
Test coverage
test/broker.test.mjs adds a regression test (observe({page}) ...) that stubs a page with goto/evaluate/url(), asserts capturedBy: 'cdp', the live URL is read, zero navigations occur, and the live text surfaces in safe.text — directly covering the bug this PR fixes.
What's good
- The fix is a single-condition addition with no behavioral change to the existing
browserWSEndpoint/browserURLpaths. - Comments explain why (not just what), and correctly describe
captureFromBridge's existing no-navigation-on-bare-page behavior. - New test isolates the exact regression scenario described in the PR body.
- All CI checks green (CodeQL, analyze, test, test-node20).
No correctness, security, reuse, or efficiency concerns in the changed lines.
What
captureFromBridgehas accepted a caller-owned{page}since the broker seam (PR #5) — butobserve()'shasBridgecheck only looked forbrowserWSEndpoint/browserURL, so a bareobserve({page})silently fell through tocaptureFromHtml(undefined)instead of reading the live session.One-line routing fix:
input.page != nullnow counts as a bridge target.captureFromBridgealready handles the rest — page reused as-is, no navigation when no url/html is given (current page state read in place), lifecycle untouched,urlfrompage.url().Why now
Dogfooding: askalf's fleet
browser_usetool (platform#701) firewalls its live Puppeteer session through fieldpass. Today it has to serialize the DOM and use the static path; with this seam it can hand its page straight toobserve()and get live-extractor parity — computed-style hidden detection and shadow-root descent on the agent's current page state.Tests
New regression in
test/broker.test.mjs:observe({page})must producecapturedBy: 'cdp', readpage.url(), perform zero navigations, and surface the live node text in the safe view. Suite: 146/146 green locally (freshnpm install).