15 KiB
15 KiB
Task: Diagnose agent_browser call failures
Identity
- Task ID: 20260906-agent-browser-failure-a7c91e4d
- Mode: Feature
- Branch: main
- Worktree: D:\Datas\OthersProjects\makelore
- Base commit:
5c61110f46 - Owner: developer
- Status: Ready for Integration
Scope
- Preserve the completed diagnosis of the parent Pi
agent_browserfailure and use its deterministic reproduction as the implementation baseline. - Restore a lightweight Coding-owned shared browser surface and route Pi opens through a bounded Main/Renderer presentation handshake before inspection actions continue.
- Preserve zero browser resources and zero browser polling while the surface is closed; scope diagnostics to explicit Agent or user demand and keep event buffers bounded.
- Close the browser on panel dismissal, failed presentation, module/project exit,
window hide, or Renderer loss, and preserve structured
AgentBrowserFaultdetails across the Pi bridge. - Add focused regression coverage plus typecheck, lint, unit, Electron UI, build, and deterministic performance-boundary verification in proportion to the change.
Intent And Constraints
- Preserve ADR-006: Pi
0.84.2remains the sole Coding runtime;agent_browsercrosses the generated Makelore extension into the Main-owned browser service. - Keep
agent_browser, selected-modelmakelore_web_search, and the unrelated release-preflightelectron/agent-browsermodule distinct. - Reproduce the exact failure before ranking or testing hypotheses. Redact credentials, headers, prompts, tool arguments/results, account/session identities, and user paths from reported evidence.
- Do not restart, abort, recover, or replay a live Conversation, and do not invoke a paid Provider while implementing or verifying the repair.
- Establish a red-capable performance baseline before attributing cost. Prefer profiler/timing/resource measurements over broad logging, and distinguish the persistent interactive browser from the short-lived release-preflight browser.
- Implement only the smallest replacement surface needed by the current Pi/Main architecture; do not restore OpenCode state, speculative compatibility layers, or the pre-optimization polling behavior.
- The active legacy Web Search coordinator owns a separate old-base native-search scope and does not semantically overlap this diagnosis.
Outcome
- Restored a lightweight Coding right-side development-browser panel with an
explicit header toggle. An Agent
openevent expands the same panel automatically; manual opening alone creates noWebContentsView. - Added an event-driven Main/Pi presentation handshake. Pi opens the browser hidden, requests the Renderer surface, and waits at most five seconds for visible bounds for the same browser generation. Timeout, close, crash, debugger loss, or generation replacement rejects the wait; failed presentation destroys the browser instead of retaining an unusable renderer.
- Kept project paths Main-owned for the restored Renderer call sites. The panel sends the active project id under the existing Renderer capability, and the Host route resolves and revalidates the active real path before each operation.
- Replaced the single diagnostics toggle with owner leases. Agent diagnostics stay enabled only for the current run, Renderer diagnostics only while the Console/Network drawer is expanded, and the domains plus buffers are released after the last owner exits. Event rendering remains capped at 500 records and reads use a five-second long poll with bounded drain backoff.
- Closed the browser during idle
background_sleepin addition to the existing panel, project, window, Renderer, and application teardown paths. The panel performs no interval polling and installs its document observer and resize observer only while open; it does a single state refresh when the app regains focus after a background close. - Preserved
AgentBrowserFaultcode, retryability, generation, and outcome across the Pi extension bridge, so callers receiveVIEWPORT_NOT_READYand other actionable faults instead of the genericBridge request failedsymptom. - Confirmed primary cause: the Pi product-tool path creates the Main-owned browser
without a Renderer presentation handshake.
PiAgentBrowserTool.open()callsAgentBrowserModule.open()directly withvisible: falseand no bounds. The resulting live snapshot is thereforestate: attached,visible: false, andbounds: null. navigate,send_cdp,read_events, andread_payloadenterrequirePresented()(directly or throughrequireAttached()), which rejects that state withVIEWPORT_NOT_READY. This is intentional browser-module behavior: the shared development browser pauses agent debugging while its viewport is hidden.- The required presentation owner no longer exists in the current Coding Renderer.
Commit
5a275b9removedsrc/pages/Chat/AgentBrowserPanel.tsxand its 619-line unit test file as part of the legacy OpenCode removal. That panel was the only code which measured the viewport and calledpresentAgentBrowser()with visible bounds. Current source has no caller ofpresentAgentBrowser()and no consumer ofagent-browser:show; the installed Renderer bundle likewise contains that event name only as the key/value pair in the generic event map. - The Pi path also bypasses the Host API route that emits
agent-browser:showafter an open. Therefore merely retaining the route event is insufficient: the Pi product-tool open requires the same presentation notification/coordinator, and the current Coding Renderer requires a replacement shared-browser surface. - Confirmed secondary cause of the unhelpful symptom: the extension bridge receives
an HTTP 400 from
PiExtensionHost, whose broad catch preserves onlyDevicePackageError; it replacesAgentBrowserFault(includingVIEWPORT_NOT_READY) with the literalBridge request failed. The generated Pi extension correctly reports the text it receives, so the loss occurs in Main. - The direct Pi browser path was introduced by commit
13ab383already usingvisible: false. While the old panel still existed, a user-presented viewport could satisfy the gate; after5a275b9removed that panel, current supported UI has no way to do so, making the failure deterministic for inspection actions. - Historical performance concern is confirmed, but the deletion itself was not a
performance fix. Commit
927e133first optimized the then-live browser surface: it removed the 2.5-second state interval, replaced the 750 ms event interval with a diagnostics-only 5-second long poll, limited the rendered event tail to 500, activated the document-wide MutationObserver only while the panel was open, disabled Runtime/Log/Network/Page CDP domains by default, cleared their buffers when diagnostics closed, and destroyed the WebContentsView when the panel closed. Five days later5a275b9deleted the already-optimized panel as part of the legacy OpenCode hard cutover; its commit message and diff do not identify browser performance as the deletion reason. - A deterministic historical work-budget comparison reproduced the old amplification:
a collapsed-but-active browser retained one Chromium renderer, dispatched 24
state requests per minute, kept the whole-document observer active, and captured
four CDP event domains continuously. An open panel dispatched another 80 event
reads per minute even when its diagnostics drawer was collapsed. The
927e133version passed the corresponding zero-background-work source assertions. - Current source retains the Main-side diagnostics gating and teardown, but has a
lifecycle regression around the Pi path. Pi
opencan create a hidden renderer indefinitely; it emits no presentation event, andcodingProducts.sleep()stops Pi workers/the Agent Server without closing the browser. An executable red test expected browser close duringbackground_sleepand observed zero calls. Window hide, renderer exit/navigation, and project deactivation do close it, but merely leaving the Programming module does not. - No preserved profiler capture or hardware-normalized CPU/memory measurement was found for the historical browser. Therefore the verified conclusions are about retained resources and deterministic background work, not a fabricated MB, CPU, startup-time, or frame-time improvement number.
- Falsified alternatives:
- Tool registration/authentication is not the cause: live
openandstatuscalls cross the extension/Main seam successfully. - General request-schema drift is not the cause: a minimal
read_eventsrequest has the exact supported shape. One historical malformedread_payloadcall is isolated and cannot explain the other failures. - Installed/source component drift is not the cause of this symptom: the running installed package contains the same hidden-open, viewport gate, and bridge mask.
- A GPU-process warning is present in the application log, but no evidence links
it to these failures; the browser reaches
attachedand the deterministic viewport rejection occurs before actionable CDP work.
- Tool registration/authentication is not the cause: live
- The three adopted pre-existing task records remain unchanged. Product changes are limited to the current Agent Browser presentation, diagnostics, and lifecycle path; the isolated release-preflight browsers remain unchanged.
Verification
- Red baseline: the four focused implementation suites initially produced six expected failures and 106 passes for the missing presentation wait, diagnostic ownership, structured bridge fault, and background close behaviors.
- Focused post-change verification passed across browser core/routes/panel, Pi product tools/extension host, Coding background sleep, and Coding feature UI; the final panel suite has 3 passing tests, including zero Host API calls while closed and one-shot foreground resynchronization.
pnpm run typecheck: passed.pnpm run lint:check: passed with zero errors and five pre-existing warnings insrc/pages/Home/index.tsxandsrc/pages/Makelore/index.tsx; no changed file produced a warning.pnpm test: 1,913 tests passed and 2 existing tests were skipped across the two repository test phases.node ./node_modules/@playwright/test/cli.js test tests/e2e/pi-coding-first-chat.spec.ts: all 4 Electron E2E tests passed, including the restored browser toggle and diagnostics-off initial state.pnpm run build:vite: passed for Renderer, Electron Main, Preload, and utility worker. Only existing Browserslist, mixed dynamic-import, and chunk-size advisories were emitted.pnpm run perf:budget: passed. Initial JS gzip was 205,846 / 358,400 bytes, initial CSS gzip 24,377 / 30,720 bytes, fonts 1,729,900 / 2,097,152 bytes, and module media 241,362 / 1,048,576 bytes.git diff --check: passed.- Deterministic captured-trace assertion was run twice against the latest local Pi
session, without exposing prompts, arguments, results, identities, or paths. Both
runs reproduced the same red condition: 3 successful opens and 14 subsequent
Bridge request failedresults. - Minimized captured sequence reproduced the failure as one successful
openfollowed by one failedread_events. Across the inspected session, 20agent_browserresults comprised 6 successes (open/status) and 14 failures (read_events,send_cdp,navigate, and one malformedread_payload). pnpm exec vitest run tests/unit/pi-extension-bundle.test.ts tests/unit/pi-product-tools.test.ts tests/unit/agent-browser-routes.test.ts --maxWorkers=1with the repository-pinned pnpm 10.33.4: 3 files, 35 tests passed. These tests confirm registration/bridge schema/route forwarding but mock the browser module and do not exercise the broken cross-layer sequence.pnpm exec vitest run tests/unit/agent-browser-core.test.ts -t "keeps a view hidden until open/present receives current bounds" --maxWorkers=1: 1 passed, 77 skipped. It confirms that open without bounds yieldsvisible: false,bounds: null, and thatsendCdp/readEventsthen reject withVIEWPORT_NOT_READYuntil a visible presentation with bounds occurs.- Read-only inspection of the running installed package confirmed all load-bearing
code literals and paths: Pi open is hidden,
requirePresented()emits the viewport fault, Main masks it, and the Renderer bundle has no show-event consumer. - Git history/blame confirmed the Pi path originated in
13ab383and the presentation surface plus its tests were removed in5a275b9without a Coding replacement. - Historical zero-idle budget check: pre-
927e133intentionally failed with one retained renderer, 24 collapsed-state requests/minute, 80 open-panel event requests/minute, an always-on DOM observer, and always-on diagnostic CDP domains; the927e133source passed all seven inverse assertions. - Current lifecycle red test (
debug-agent-browser-background-release.test.ts, removed immediately after diagnosis) failed as expected:background_sleepinvoked the browserclosespy 0 times instead of 1. - Focused current-source verification passed: 2 files and 4 tests covering
diagnostics-off first-load events, hidden-until-present behavior, full close
teardown, and agent-only hidden open. The temporary diagnostic test was removed;
git statusshows no product-source residue from the investigation.
Follow-ups
- No required implementation follow-up remains.
- If hardware-normalized CPU, memory, or frame-time numbers are needed, capture a
controlled before/after profile through the existing
app:performancesnapshot. The current evidence deliberately claims deterministic resource/work bounds and bundle-budget compliance, not an invented runtime percentage.
Promotion Candidates
- Target:
.project-docs/30-worklog/current-state.md- Summary: Pi
agent_browsernow has a Coding-owned visible-surface handshake; presentation failure tears down the browser and structured browser faults cross the Pi bridge unchanged. - Evidence: focused browser/Pi/bridge tests, Electron E2E, and production build.
- Future impact: keep the visibility gate and presentation coordinator together; do not reintroduce hidden actionable CDP access.
- Summary: Pi
- Target:
.project-docs/30-worklog/current-state.md- Summary: the restored Agent Browser preserves the post-
927e133zero-idle lifecycle: no closed-state polling/observers/browser process, owner-scoped diagnostics, bounded event retention, and idle background teardown. - Evidence: panel/core/background regression tests, full unit suite, E2E, and the passing bundle performance budget.
- Future impact: future browser UI changes must preserve these deterministic work bounds and keep release-preflight browsers isolated from the interactive one.
- Summary: the restored Agent Browser preserves the post-