[PR #6036] [MERGED] fix(browser): name web-bundle budgets and recover web deadlines #7132

Closed
opened 2026-11-01 21:45:38 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6036
Author: @morluto
Created: 10/21/2026
Status: ✅ Merged
Merged: 10/21/2026
Merged by: @morluto

Base: main ← Head: cursor/web-bundle-deadlines-2486


📝 Commits (10+)

  • 7f5c93a fix(browser): name web-bundle budgets and recover web deadlines
  • 4aa4a43 Merge remote-tracking branch 'origin/main' into cursor/web-bundle-deadlines-2486
  • c583cf8 fix(browser): apply selected web deadlines to the owning phase
  • 1867730 fix(browser): retain scenario commands that finish after their deadline
  • d2bc278 fix(browser): keep child command timeouts as the public failure
  • 450f48e Merge remote-tracking branch 'origin/main' into cursor/web-bundle-deadlines-2486
  • 2d74fd1 fix(browser): keep runtime cleanup on the fixed grace
  • 618ea8d test(browser): prove a short command deadline cannot fail runtime cleanup
  • 3d5a3fd fix(browser): name the effective source-map decode deadline
  • 97135d5 fix(browser): separate handshake and target-attach deadlines

📊 Changes

82 files changed (+3201 additions, -465 deletions)

View changed files

📝 docs/browser-observation.md (+40 -19)
📝 docs/browser-scenario-contract.md (+15 -3)
📝 docs/web-network-captures.md (+3 -2)
📝 docs/web-runtime.md (+1 -1)
📝 docs/web-source-location.md (+3 -2)
📝 src/application/BrowserEvidence.ts (+8 -0)
📝 src/application/WebNetworkCaptureService.test.ts (+24 -0)
📝 src/application/WebNetworkCaptureService.ts (+3 -0)
📝 src/application/WebSourceLocationPorts.ts (+1 -0)
📝 src/application/WebSourceLocationService.test.ts (+44 -1)
📝 src/application/WebSourceLocationService.ts (+14 -6)
📝 src/application/javascript/ElectronEvidence.ts (+3 -0)
📝 src/browser/BrowserProcessStartup.ts (+1 -1)
📝 src/browser/CdpBrowserProvider.ts (+7 -2)
📝 src/browser/CdpConnection.ts (+85 -12)
📝 src/browser/CdpElectronInspection.test.ts (+2 -2)
📝 src/browser/CdpElectronProvider.ts (+6 -1)
📝 src/browser/CdpElectronScripts.ts (+12 -4)
📝 src/browser/CdpEndpoint.test.ts (+44 -0)
📝 src/browser/CdpEndpoint.ts (+39 -15)

...and 62 more files

📄 Description

Summary

Refs #5910 (parent #5808). Web-bundle heap, per-script, and total deadlines already existed and now name those phases. Capture, CDP command, source-map decode, and source-map fetch deadlines become validated settings at today's defaults. DevTools startup already accepted timeoutMs and now names it. Fixed discovery, cleanup grace, byte budgets, and Electron hook retention say there is no runtime override when the agent sees them.

Review follow-up: a short command_timeout_ms starts at the WebSocket handshake, after HTTP discovery. Browser-socket discovery keeps its own deadline. Scenario launch startup, connect-over-CDP, target lookup, environment commands, and storage CDP commands, including attached child replies, use the selected command deadline. A command that exceeds that deadline stays owned: cleanup closes a browser or context that appears afterward, and restores an environment mutation that completes afterward. Service-worker restoration stays on the fixed 5000 ms grace. Operations that do not accept command_timeout_ms do not name that setting. capture-browser-scenario recovery tells the caller to set command_timeout_ms in the scenario JSON; that command has no --command-timeout-ms option. When Chrome acknowledges delivery of a child command such as Page.enable and never replies, the stored failure is that timeout. The public error names the command, the selected deadline, and the scenario JSON recovery.

Runtime restoration calls beginCleanupGrace with the fixed 5000 ms grace before the first restoration command, so a shorter command_timeout_ms cannot return cleanup_failed for an otherwise successful observation. list_browser_targets no longer accepts command_timeout_ms. HTTP discovery and browser-socket discovery stay on the fixed 10-second deadline, and the socket closes without a later command. That listing deadline has no runtime override.

trace_web_source_location limitations name the effective decode_timeout_ms in both the result and Evidence: the selected value, or 20000 ms when omitted. An omitted deadline stays absent from parameters.

A browser-level Target.attachToTarget receives its own command_timeout_ms after the WebSocket handshake. Blocked service-worker attachment keeps the fixed discovery deadline on endpoint discovery; the following handshake and Target.attachToTarget each use command_timeout_ms.

The first blocked service-worker registration check, before discovery, has its own fixed 10000 ms deadline. command_timeout_ms does not apply to that check. Discovery, the handshake, and Target.attachToTarget stay on their separate deadlines.

Web-bundle memory exhaustion names the resource the runtime enforces. Node names the selected V8 old-space heap. Windows Bun names the process commit limit (max_heap_mb plus a 512 MiB reserve). Other Bun hosts say that raising max_heap_mb does not change the exit.

Browser-socket discovery timeout recovery names the 64 MiB protocol message budget. HTTP discovery timeout recovery still names the 8 MiB document budget.

When web-bundle result admission reaches zero, the failure names the operand that did it. Host heap pressure, while the fixed 8 MiB result budget still has room, names that host headroom and does not say the fixed allowance has no further room. Exhaustion of the 8 MiB allowance still names that fixed budget. A Windows Bun allocation before the process commit limit is reported as reached still names the configured limit and says it was not reached.

Merged origin/main (2aadcf7d0). The only conflict was src/cli/electronCommands.ts: the selected Electron page command timeout stays, and input failures keep main's issue diagnostics.

Problem and expected behavior

Timeout and budget failures read as unnamed hard caps, or named a generic server deadline. A caller could not tell a per-script web-bundle timeout from the total analysis deadline, or raise the capture, CDP command, source-map decode, or source-map fetch deadline without a code change.

analyze_web_bundle names max_heap_mb (default 1024 MiB, range 128..16384), analysis_timeout_ms (default 30000), and total_analysis_timeout_ms (default 300000). A per-script deadline above the effective total is rejected. Omitted values stay at today's defaults and stay absent from Evidence. On Bun, max_heap_mb is not a V8 old-space heap: Windows enforces a process commit limit plus a 512 MiB reserve, and other Bun hosts enforce no analyzer heap limit.

These settings are adjustable, default unchanged, integer range 1..2147483647:

  • capture_timeout_ms / --capture-timeout-ms — 30000
  • command_timeout_ms / --command-timeout-ms — 20000
  • decode_timeout_ms / --decode-timeout-ms — 20000
  • source_map_fetch_timeout_ms / --source-map-fetch-timeout-ms — 30000

DevToolsActivePort startup still accepts caller timeoutMs (default 60000) and the failure names that argument. HTTP CDP discovery is 10000 ms and 8 MiB. Browser-socket discovery is the same 10000 ms deadline and the 64 MiB protocol message budget. Cleanup grace (5000 ms), other protocol and capture byte budgets, source-map map/reply/codec-heap budgets, and the 16 MiB Electron hook retention stay fixed and say there is no runtime override. The blocked service-worker registration check before discovery is a fixed 10000 ms deadline with no runtime override.

Omitted scenario command_timeout_ms means 20000. That value bounds launch startup. Action timeout_ms, wait_for_timeout.duration_ms, and navigation stay separate. It does not bound the pre-discovery service-worker registration check.

list-browser-targets has no --command-timeout-ms option. Passing command_timeout_ms to list_browser_targets is rejected.

Change and scope

Recovery text lives with the owning deadline. CDP connections, runtime sessions, the capture decoder, and the source-map codec use the selected value. Schema descriptions are the CLI and MCP contract; this does not regenerate the MCP catalog.

Follow the contribution scope. Not applicable: no new provider, target execution, injection, mutation, or protection recovery.

Intentionally not included: MCP catalog work (#6005), provider limits (#6014), JavaScript analysis heap (#6022), Android/JADX/apktool (#6024), and E2E scripts.

Contract and boundary impact

  • Semantic owner and earliest changed stage: domain deadline schemas, then the browser, capture, and source-map owners that already enforced the timers.
  • Contribution scope fit and linked maintainer decision: ordinary fix inside existing browser and source-map boundaries. Maintainer scope decision not applicable.
  • CLI and MCP/tool-catalog contract: new optional fields and matching CLI flags. Omitted means today's default and applies on the next call. Generated MCP catalog is not committed. capture-browser-scenario takes scenario JSON only. list_browser_targets does not accept command_timeout_ms.
  • Provider, bridge, target-format, or platform compatibility: none. Numeric defaults are unchanged. Launch startup now uses command_timeout_ms (20000 when omitted) where it previously waited without that deadline.
  • Evidence, artifact, provenance, or reconstruction contract: a selected deadline is recorded in Evidence parameters; an omitted deadline stays absent. Target listing Evidence has no command_timeout_ms. Source-location limitations name the effective decode deadline in milliseconds. Web-bundle memory failures name the exhausted resource for the running runtime.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): no change to browser authority. Cleanup grace stays 5000 ms and is not raised or shortened by command_timeout_ms. A timed-out scenario command remains owned until it settles, so a late browser, context, session, or applied environment mutation is closed or restored.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact (CI generates and validates ignored catalogs and skills/; edit authored instructions in .agents/skills/reverse-engineer-anything/ and never commit build outputs): none committed. Public browser, capture, source-location, scenario-contract, and web-runtime docs name the controls.

Expected effects (check known effects; use documentation-only on its own).
Unchecked items do not establish absence; leave uncertainties visible.

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated: src/domain/webDeadlineControls.test.ts covers rejection of a per-script deadline above the total, omitted defaults, the 1..2147483647 range, recovery text that omits command_timeout_ms when the operation does not accept it, and runtime-specific web-bundle exhaustion text (Node V8 heap, Windows Bun process commit limit, other Bun allocation, and a configured Windows limit that was not reported as reached). It also checks that host result capacity 0 with the fixed 8388608-byte budget still available names host pressure, and that a zero fixed allowance still names that fixed budget. Behavior tests apply non-default capture_timeout_ms, command_timeout_ms, decode_timeout_ms, and source_map_fetch_timeout_ms, including explicit-versus-omitted Evidence parameters, cleanup, discovery staying outside a short command deadline, handshake versus Page.getFrameTree labeling, the fixed 5000 ms cleanup grace, and scenario launch plus primary connect. This follow-up adds late launch close-before-profile-removal, late connect close without blocking the timeout, late environment restore, a stalled child Page.enable reply bounded by command_timeout_ms, and scenario recovery that does not mention --command-timeout-ms. The stalled child reply test asserts the public timeout: Page.enable, the selected 40 ms deadline, and the scenario JSON recovery. The session test connection implements beginCleanupGrace. Runtime cleanup with command_timeout_ms 250 keeps a hung Profiler.disable on the 5000 ms grace and still succeeds after that command completes; a stall names the fixed grace and does not name the 250 ms command deadline. list_browser_targets rejects command_timeout_ms and leaves it out of Evidence. WebSourceLocationService.test.ts checks that a selected 250 ms decode_timeout_ms is named as 250 ms decode_timeout_ms deadline in both the result and Evidence limitations, and that an omitted deadline names 20000 ms while staying absent from parameters. cdpTargetDeadlines delays the browser-socket handshake and still expects one full command_timeout_ms timer for Target.attachToTarget. The blocked service-worker test expects the 10000 ms discovery timer to be gone once attach is in flight, with one command_timeout_ms timer active. A stalled frame.evaluate during the first blocked registration check fails on its own 10000 ms deadline before any discovery request and without arming command_timeout_ms. Browser-socket discovery timeout text names the 67108864-byte protocol budget; HTTP discovery timeout text still names the 8388608-byte document budget. WebBundleAnalysisWorker.test.ts projects a heap-marker exit through the same runtime classifier. WebBundleAnalysisWorkerCapacity.test.ts refuses a zero host heap before launch and expects the host message, not the fixed-budget sentence.
  • Base reproduction or source-derived reasoning: source-derived from the limits review for #5910 and the Codex and Greptile threads on this PR. Source tests and Portable tests on c583cf8bf failed in PlaywrightScenarioSession.test.ts because the mock connection lacked beginCleanupGrace. The child-timeout thread was source-derived: fail() stored every cause as protocol_error, so settle() hid the typed timeout. The source-location deadline text was source-derived: codecBudgetLimitation() hardcoded “20-second deadline” after the decoder already used the selected timeout. The attach threads were source-derived: one runtimeDeadline wrapped handshake and attach, and withCdpDiscoveryDeadline still enclosed the service-worker handshake and attach. Later threads were source-derived: web-bundle exit text always named the V8 old-space heap, browser-socket discovery timeout named the HTTP document budget, and the first blocked registration check no longer had a deadline. The latest threads were source-derived: a zero host-heap term still said the fixed result budget had no further room, and a Windows Bun allocation before the Job limit said no process limit was enforced.
  • User-visible CLI/MCP output (if applicable): timeout and budget failures name the control, the effective value, and whether a sibling budget can be raised. Scenario command recovery names command_timeout_ms in the capture JSON. A stalled child storage command surfaces that timeout directly. Target listing no longer advertises command_timeout_ms. Source-location limitations name the effective decode_timeout_ms in milliseconds. A stalled browser-level attach names Target.attachToTarget and the selected command deadline. Web-bundle memory failures name the exhausted resource for Node, Windows Bun, or other Bun. A Windows Bun allocation before the commit limit names that configured limit and says it was not reached. Browser-socket discovery timeouts name the 64 MiB protocol budget. A stalled pre-discovery service-worker check names its fixed 10000 ms deadline. Host result pressure names host heap headroom while the fixed result budget still has room.
  • Remaining proof gaps: no live Chrome, Electron, or codec process was launched in this change. Real-provider deadline behavior is unverified. The Windows Bun commit-limit and other-Bun allocation messages were checked as text for those host facts; this host is Node, so the worker projection run classified a heap-marker exit as the V8 heap. The host-capacity path was checked by forcing heap_size_limit to 0.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run check:fast — passed (typecheck and lint) on the tree committed as e96ace766.
  • npm run test:focused -- src/domain/webDeadlineControls.test.ts src/browser/WebBundleAnalysisWorkerCapacity.test.ts src/browser/WebBundleAnalysisWorker.test.ts — passed, 28 tests, before the capacity-test type narrowing. After that narrowing, npm run check:fast passed again and npm run test:focused -- src/domain/webDeadlineControls.test.ts src/browser/WebBundleAnalysisWorkerCapacity.test.ts passed, 7 tests. The worker suite was not repeated after the type narrowing because that edit was only in the capacity test.
  • Earlier on 48aa28e2d, npm run check:fast passed. npm run test:focused -- src/domain/webDeadlineControls.test.ts src/browser/CdpEndpoint.test.ts src/browser/WebBundleAnalysisWorker.test.ts src/browser/PlaywrightScenarioSession.test.ts tests/boundary/browser/cdpTargetDeadlines.test.ts had 93 passed and 1 failed; the Windows Bun assertion was corrected, webDeadlineControls was rerun (5 passed), and CdpEndpoint was rerun (11 passed). The worker (21), scenario session (36), and cdpTargetDeadlines (22) results were from the run before that assertion-only edit.
  • Earlier on 97135d5b1, npm run check:fast passed. npm run test:focused -- tests/boundary/browser/cdpTargetDeadlines.test.ts src/browser/PlaywrightScenarioSession.test.ts passed, 57 tests. npm run test:focused -- tests/boundary/browser/cdpWebRuntime.test.ts tests/boundary/browser/cdpWebRuntimeTermination.test.ts tests/boundary/browser/cdpBrowserProvider.browserSocket.test.ts passed, 36 tests. Those three CDP suites were not repeated after this follow-up.
  • Earlier on 3d5a3fdd2, npm run check:fast passed and npm run test:focused -- src/application/WebSourceLocationService.test.ts passed, 20 tests. That source-location run was not repeated after later commits.
  • Earlier on 618ea8df1, npm run test:focused -- tests/boundary/browser/webDeadlineBehavior.test.ts src/domain/webDeadlineControls.test.ts passed with the then-current cdpTargetDeadlines count. That behavior file was not repeated after later commits.
  • Earlier on this branch, npm run test:focused -- src/browser/PlaywrightScenarioBrowser.test.ts src/browser/PlaywrightScenarioStorage.test.ts passed, 42 tests. That run was not repeated after the main merge.

Compatibility, safety, and release

  • Breaking changes or migration steps: none for omitted fields. An explicit total_analysis_timeout_ms below the effective per-script deadline (including the 30000 ms default) is now rejected. Raise analysis_timeout_ms only up to the total, or raise the total. Launch startup is now bounded by command_timeout_ms (20000 when omitted). list_browser_targets rejects command_timeout_ms; that field was not on main. Source-location limitation text now states the effective deadline in milliseconds (20000 ms decode_timeout_ms deadline when omitted) instead of a fixed “20-second deadline”. A browser-level attach can now use a full command_timeout_ms after a handshake that already consumed part of that same number of milliseconds. Bun web-bundle exhaustion no longer tells the caller the V8 old-space heap was exhausted. Browser-socket discovery timeouts name 64 MiB instead of 8 MiB. A stalled blocked service-worker registration check now fails after 10000 ms instead of waiting without a deadline. Host result pressure no longer says the fixed result budget has no further room. A Windows Bun allocation before the commit limit names that limit.
  • Real Hopper/Ghidra, browser, or OS coverage: not run. Browser and source-map coverage here is unit and boundary tests with fake transports and one owned Node decoder process for the capture deadline. The web-bundle heap-marker projection used an owned Node worker.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: deadlines do not add authority. Fixed byte budgets and the Electron hook retention limit are unchanged. The reported browser-socket budget now matches the 64 MiB limit the connection already enforced.

Author readiness

Human owner: @morluto

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.
Open in Web Open in Cursor 

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/6036 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/21/2026 **Status:** ✅ Merged **Merged:** 10/21/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `cursor/web-bundle-deadlines-2486` --- ### 📝 Commits (10+) - [`7f5c93a`](https://github.com/morluto/rea/commit/7f5c93aacb9c052615951a16990b8a16ba11eb2d) fix(browser): name web-bundle budgets and recover web deadlines - [`4aa4a43`](https://github.com/morluto/rea/commit/4aa4a438ab2f4eb674bc3fb6ff2bc3d545cdc4f9) Merge remote-tracking branch 'origin/main' into cursor/web-bundle-deadlines-2486 - [`c583cf8`](https://github.com/morluto/rea/commit/c583cf8bffd960cdf19645508aea907f87f45ffc) fix(browser): apply selected web deadlines to the owning phase - [`1867730`](https://github.com/morluto/rea/commit/1867730a6fa8f1e9cab87adbf69b1350416e7d9d) fix(browser): retain scenario commands that finish after their deadline - [`d2bc278`](https://github.com/morluto/rea/commit/d2bc278bd00299d040da8731936f66a18e3deaa9) fix(browser): keep child command timeouts as the public failure - [`450f48e`](https://github.com/morluto/rea/commit/450f48ee48019f1ec06dd718f3b428229195dc07) Merge remote-tracking branch 'origin/main' into cursor/web-bundle-deadlines-2486 - [`2d74fd1`](https://github.com/morluto/rea/commit/2d74fd13131e687ad09b1749f8c93904b42c9e07) fix(browser): keep runtime cleanup on the fixed grace - [`618ea8d`](https://github.com/morluto/rea/commit/618ea8df1aa0310f2973b5cf54eb07f44167d708) test(browser): prove a short command deadline cannot fail runtime cleanup - [`3d5a3fd`](https://github.com/morluto/rea/commit/3d5a3fdd28a4180ecb2c3232c70ce7f8d9180b31) fix(browser): name the effective source-map decode deadline - [`97135d5`](https://github.com/morluto/rea/commit/97135d5b163b4c99a5d8756e549f55dea098aa49) fix(browser): separate handshake and target-attach deadlines ### 📊 Changes **82 files changed** (+3201 additions, -465 deletions) <details> <summary>View changed files</summary> 📝 `docs/browser-observation.md` (+40 -19) 📝 `docs/browser-scenario-contract.md` (+15 -3) 📝 `docs/web-network-captures.md` (+3 -2) 📝 `docs/web-runtime.md` (+1 -1) 📝 `docs/web-source-location.md` (+3 -2) 📝 `src/application/BrowserEvidence.ts` (+8 -0) 📝 `src/application/WebNetworkCaptureService.test.ts` (+24 -0) 📝 `src/application/WebNetworkCaptureService.ts` (+3 -0) 📝 `src/application/WebSourceLocationPorts.ts` (+1 -0) 📝 `src/application/WebSourceLocationService.test.ts` (+44 -1) 📝 `src/application/WebSourceLocationService.ts` (+14 -6) 📝 `src/application/javascript/ElectronEvidence.ts` (+3 -0) 📝 `src/browser/BrowserProcessStartup.ts` (+1 -1) 📝 `src/browser/CdpBrowserProvider.ts` (+7 -2) 📝 `src/browser/CdpConnection.ts` (+85 -12) 📝 `src/browser/CdpElectronInspection.test.ts` (+2 -2) 📝 `src/browser/CdpElectronProvider.ts` (+6 -1) 📝 `src/browser/CdpElectronScripts.ts` (+12 -4) 📝 `src/browser/CdpEndpoint.test.ts` (+44 -0) 📝 `src/browser/CdpEndpoint.ts` (+39 -15) _...and 62 more files_ </details> ### 📄 Description <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Summary Refs #5910 (parent #5808). Web-bundle heap, per-script, and total deadlines already existed and now name those phases. Capture, CDP command, source-map decode, and source-map fetch deadlines become validated settings at today's defaults. DevTools startup already accepted `timeoutMs` and now names it. Fixed discovery, cleanup grace, byte budgets, and Electron hook retention say there is no runtime override when the agent sees them. Review follow-up: a short `command_timeout_ms` starts at the WebSocket handshake, after HTTP discovery. Browser-socket discovery keeps its own deadline. Scenario launch startup, connect-over-CDP, target lookup, environment commands, and storage CDP commands, including attached child replies, use the selected command deadline. A command that exceeds that deadline stays owned: cleanup closes a browser or context that appears afterward, and restores an environment mutation that completes afterward. Service-worker restoration stays on the fixed 5000 ms grace. Operations that do not accept `command_timeout_ms` do not name that setting. `capture-browser-scenario` recovery tells the caller to set `command_timeout_ms` in the scenario JSON; that command has no `--command-timeout-ms` option. When Chrome acknowledges delivery of a child command such as `Page.enable` and never replies, the stored failure is that timeout. The public error names the command, the selected deadline, and the scenario JSON recovery. Runtime restoration calls `beginCleanupGrace` with the fixed 5000 ms grace before the first restoration command, so a shorter `command_timeout_ms` cannot return `cleanup_failed` for an otherwise successful observation. `list_browser_targets` no longer accepts `command_timeout_ms`. HTTP discovery and browser-socket discovery stay on the fixed 10-second deadline, and the socket closes without a later command. That listing deadline has no runtime override. `trace_web_source_location` limitations name the effective `decode_timeout_ms` in both the result and Evidence: the selected value, or 20000 ms when omitted. An omitted deadline stays absent from parameters. A browser-level `Target.attachToTarget` receives its own `command_timeout_ms` after the WebSocket handshake. Blocked service-worker attachment keeps the fixed discovery deadline on endpoint discovery; the following handshake and `Target.attachToTarget` each use `command_timeout_ms`. The first blocked service-worker registration check, before discovery, has its own fixed 10000 ms deadline. `command_timeout_ms` does not apply to that check. Discovery, the handshake, and `Target.attachToTarget` stay on their separate deadlines. Web-bundle memory exhaustion names the resource the runtime enforces. Node names the selected V8 old-space heap. Windows Bun names the process commit limit (`max_heap_mb` plus a 512 MiB reserve). Other Bun hosts say that raising `max_heap_mb` does not change the exit. Browser-socket discovery timeout recovery names the 64 MiB protocol message budget. HTTP discovery timeout recovery still names the 8 MiB document budget. When web-bundle result admission reaches zero, the failure names the operand that did it. Host heap pressure, while the fixed 8 MiB result budget still has room, names that host headroom and does not say the fixed allowance has no further room. Exhaustion of the 8 MiB allowance still names that fixed budget. A Windows Bun allocation before the process commit limit is reported as reached still names the configured limit and says it was not reached. Merged `origin/main` (`2aadcf7d0`). The only conflict was `src/cli/electronCommands.ts`: the selected Electron page command timeout stays, and input failures keep main's issue diagnostics. ## Problem and expected behavior Timeout and budget failures read as unnamed hard caps, or named a generic server deadline. A caller could not tell a per-script web-bundle timeout from the total analysis deadline, or raise the capture, CDP command, source-map decode, or source-map fetch deadline without a code change. `analyze_web_bundle` names `max_heap_mb` (default 1024 MiB, range 128..16384), `analysis_timeout_ms` (default 30000), and `total_analysis_timeout_ms` (default 300000). A per-script deadline above the effective total is rejected. Omitted values stay at today's defaults and stay absent from Evidence. On Bun, `max_heap_mb` is not a V8 old-space heap: Windows enforces a process commit limit plus a 512 MiB reserve, and other Bun hosts enforce no analyzer heap limit. These settings are adjustable, default unchanged, integer range 1..2147483647: - `capture_timeout_ms` / `--capture-timeout-ms` — 30000 - `command_timeout_ms` / `--command-timeout-ms` — 20000 - `decode_timeout_ms` / `--decode-timeout-ms` — 20000 - `source_map_fetch_timeout_ms` / `--source-map-fetch-timeout-ms` — 30000 DevToolsActivePort startup still accepts caller `timeoutMs` (default 60000) and the failure names that argument. HTTP CDP discovery is 10000 ms and 8 MiB. Browser-socket discovery is the same 10000 ms deadline and the 64 MiB protocol message budget. Cleanup grace (5000 ms), other protocol and capture byte budgets, source-map map/reply/codec-heap budgets, and the 16 MiB Electron hook retention stay fixed and say there is no runtime override. The blocked service-worker registration check before discovery is a fixed 10000 ms deadline with no runtime override. Omitted scenario `command_timeout_ms` means 20000. That value bounds launch startup. Action `timeout_ms`, `wait_for_timeout.duration_ms`, and navigation stay separate. It does not bound the pre-discovery service-worker registration check. `list-browser-targets` has no `--command-timeout-ms` option. Passing `command_timeout_ms` to `list_browser_targets` is rejected. ## Change and scope Recovery text lives with the owning deadline. CDP connections, runtime sessions, the capture decoder, and the source-map codec use the selected value. Schema descriptions are the CLI and MCP contract; this does not regenerate the MCP catalog. Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). Not applicable: no new provider, target execution, injection, mutation, or protection recovery. Intentionally not included: MCP catalog work (#6005), provider limits (#6014), JavaScript analysis heap (#6022), Android/JADX/apktool (#6024), and E2E scripts. ## Contract and boundary impact - Semantic owner and earliest changed stage: domain deadline schemas, then the browser, capture, and source-map owners that already enforced the timers. - Contribution scope fit and linked maintainer decision: ordinary fix inside existing browser and source-map boundaries. Maintainer scope decision not applicable. - CLI and MCP/tool-catalog contract: new optional fields and matching CLI flags. Omitted means today's default and applies on the next call. Generated MCP catalog is not committed. `capture-browser-scenario` takes scenario JSON only. `list_browser_targets` does not accept `command_timeout_ms`. - Provider, bridge, target-format, or platform compatibility: none. Numeric defaults are unchanged. Launch startup now uses `command_timeout_ms` (20000 when omitted) where it previously waited without that deadline. - Evidence, artifact, provenance, or reconstruction contract: a selected deadline is recorded in Evidence parameters; an omitted deadline stays absent. Target listing Evidence has no `command_timeout_ms`. Source-location limitations name the effective decode deadline in milliseconds. Web-bundle memory failures name the exhausted resource for the running runtime. - Target selection, authority, upstream behavior, and cleanup details (if applicable): no change to browser authority. Cleanup grace stays 5000 ms and is not raised or shortened by `command_timeout_ms`. A timed-out scenario command remains owned until it settles, so a late browser, context, session, or applied environment mutation is closed or restored. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact (CI generates and validates ignored catalogs and `skills/`; edit authored instructions in `.agents/skills/reverse-engineer-anything/` and never commit build outputs): none committed. Public browser, capture, source-location, scenario-contract, and web-runtime docs name the controls. Expected effects (check known effects; use documentation-only on its own). Unchecked items do not establish absence; leave uncertainties visible. - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: `src/domain/webDeadlineControls.test.ts` covers rejection of a per-script deadline above the total, omitted defaults, the 1..2147483647 range, recovery text that omits `command_timeout_ms` when the operation does not accept it, and runtime-specific web-bundle exhaustion text (Node V8 heap, Windows Bun process commit limit, other Bun allocation, and a configured Windows limit that was not reported as reached). It also checks that host result capacity 0 with the fixed 8388608-byte budget still available names host pressure, and that a zero fixed allowance still names that fixed budget. Behavior tests apply non-default `capture_timeout_ms`, `command_timeout_ms`, `decode_timeout_ms`, and `source_map_fetch_timeout_ms`, including explicit-versus-omitted Evidence parameters, cleanup, discovery staying outside a short command deadline, handshake versus `Page.getFrameTree` labeling, the fixed 5000 ms cleanup grace, and scenario launch plus primary connect. This follow-up adds late launch close-before-profile-removal, late connect close without blocking the timeout, late environment restore, a stalled child `Page.enable` reply bounded by `command_timeout_ms`, and scenario recovery that does not mention `--command-timeout-ms`. The stalled child reply test asserts the public timeout: `Page.enable`, the selected 40 ms deadline, and the scenario JSON recovery. The session test connection implements `beginCleanupGrace`. Runtime cleanup with `command_timeout_ms` 250 keeps a hung `Profiler.disable` on the 5000 ms grace and still succeeds after that command completes; a stall names the fixed grace and does not name the 250 ms command deadline. `list_browser_targets` rejects `command_timeout_ms` and leaves it out of Evidence. `WebSourceLocationService.test.ts` checks that a selected 250 ms `decode_timeout_ms` is named as `250 ms decode_timeout_ms deadline` in both the result and Evidence limitations, and that an omitted deadline names 20000 ms while staying absent from parameters. `cdpTargetDeadlines` delays the browser-socket handshake and still expects one full `command_timeout_ms` timer for `Target.attachToTarget`. The blocked service-worker test expects the 10000 ms discovery timer to be gone once attach is in flight, with one `command_timeout_ms` timer active. A stalled `frame.evaluate` during the first blocked registration check fails on its own 10000 ms deadline before any discovery request and without arming `command_timeout_ms`. Browser-socket discovery timeout text names the 67108864-byte protocol budget; HTTP discovery timeout text still names the 8388608-byte document budget. `WebBundleAnalysisWorker.test.ts` projects a heap-marker exit through the same runtime classifier. `WebBundleAnalysisWorkerCapacity.test.ts` refuses a zero host heap before launch and expects the host message, not the fixed-budget sentence. - Base reproduction or source-derived reasoning: source-derived from the limits review for #5910 and the Codex and Greptile threads on this PR. Source tests and Portable tests on c583cf8bf failed in `PlaywrightScenarioSession.test.ts` because the mock connection lacked `beginCleanupGrace`. The child-timeout thread was source-derived: `fail()` stored every cause as `protocol_error`, so `settle()` hid the typed timeout. The source-location deadline text was source-derived: `codecBudgetLimitation()` hardcoded “20-second deadline” after the decoder already used the selected timeout. The attach threads were source-derived: one `runtimeDeadline` wrapped handshake and attach, and `withCdpDiscoveryDeadline` still enclosed the service-worker handshake and attach. Later threads were source-derived: web-bundle exit text always named the V8 old-space heap, browser-socket discovery timeout named the HTTP document budget, and the first blocked registration check no longer had a deadline. The latest threads were source-derived: a zero host-heap term still said the fixed result budget had no further room, and a Windows Bun allocation before the Job limit said no process limit was enforced. - User-visible CLI/MCP output (if applicable): timeout and budget failures name the control, the effective value, and whether a sibling budget can be raised. Scenario command recovery names `command_timeout_ms` in the capture JSON. A stalled child storage command surfaces that timeout directly. Target listing no longer advertises `command_timeout_ms`. Source-location limitations name the effective `decode_timeout_ms` in milliseconds. A stalled browser-level attach names `Target.attachToTarget` and the selected command deadline. Web-bundle memory failures name the exhausted resource for Node, Windows Bun, or other Bun. A Windows Bun allocation before the commit limit names that configured limit and says it was not reached. Browser-socket discovery timeouts name the 64 MiB protocol budget. A stalled pre-discovery service-worker check names its fixed 10000 ms deadline. Host result pressure names host heap headroom while the fixed result budget still has room. - Remaining proof gaps: no live Chrome, Electron, or codec process was launched in this change. Real-provider deadline behavior is unverified. The Windows Bun commit-limit and other-Bun allocation messages were checked as text for those host facts; this host is Node, so the worker projection run classified a heap-marker exit as the V8 heap. The host-capacity path was checked by forcing `heap_size_limit` to 0. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run check:fast` — passed (typecheck and lint) on the tree committed as `e96ace766`. - `npm run test:focused -- src/domain/webDeadlineControls.test.ts src/browser/WebBundleAnalysisWorkerCapacity.test.ts src/browser/WebBundleAnalysisWorker.test.ts` — passed, 28 tests, before the capacity-test type narrowing. After that narrowing, `npm run check:fast` passed again and `npm run test:focused -- src/domain/webDeadlineControls.test.ts src/browser/WebBundleAnalysisWorkerCapacity.test.ts` passed, 7 tests. The worker suite was not repeated after the type narrowing because that edit was only in the capacity test. - Earlier on `48aa28e2d`, `npm run check:fast` passed. `npm run test:focused -- src/domain/webDeadlineControls.test.ts src/browser/CdpEndpoint.test.ts src/browser/WebBundleAnalysisWorker.test.ts src/browser/PlaywrightScenarioSession.test.ts tests/boundary/browser/cdpTargetDeadlines.test.ts` had 93 passed and 1 failed; the Windows Bun assertion was corrected, `webDeadlineControls` was rerun (5 passed), and `CdpEndpoint` was rerun (11 passed). The worker (21), scenario session (36), and `cdpTargetDeadlines` (22) results were from the run before that assertion-only edit. - Earlier on `97135d5b1`, `npm run check:fast` passed. `npm run test:focused -- tests/boundary/browser/cdpTargetDeadlines.test.ts src/browser/PlaywrightScenarioSession.test.ts` passed, 57 tests. `npm run test:focused -- tests/boundary/browser/cdpWebRuntime.test.ts tests/boundary/browser/cdpWebRuntimeTermination.test.ts tests/boundary/browser/cdpBrowserProvider.browserSocket.test.ts` passed, 36 tests. Those three CDP suites were not repeated after this follow-up. - Earlier on `3d5a3fdd2`, `npm run check:fast` passed and `npm run test:focused -- src/application/WebSourceLocationService.test.ts` passed, 20 tests. That source-location run was not repeated after later commits. - Earlier on `618ea8df1`, `npm run test:focused -- tests/boundary/browser/webDeadlineBehavior.test.ts src/domain/webDeadlineControls.test.ts` passed with the then-current `cdpTargetDeadlines` count. That behavior file was not repeated after later commits. - Earlier on this branch, `npm run test:focused -- src/browser/PlaywrightScenarioBrowser.test.ts src/browser/PlaywrightScenarioStorage.test.ts` passed, 42 tests. That run was not repeated after the main merge. ## Compatibility, safety, and release - Breaking changes or migration steps: none for omitted fields. An explicit `total_analysis_timeout_ms` below the effective per-script deadline (including the 30000 ms default) is now rejected. Raise `analysis_timeout_ms` only up to the total, or raise the total. Launch startup is now bounded by `command_timeout_ms` (20000 when omitted). `list_browser_targets` rejects `command_timeout_ms`; that field was not on main. Source-location limitation text now states the effective deadline in milliseconds (`20000 ms decode_timeout_ms deadline` when omitted) instead of a fixed “20-second deadline”. A browser-level attach can now use a full `command_timeout_ms` after a handshake that already consumed part of that same number of milliseconds. Bun web-bundle exhaustion no longer tells the caller the V8 old-space heap was exhausted. Browser-socket discovery timeouts name 64 MiB instead of 8 MiB. A stalled blocked service-worker registration check now fails after 10000 ms instead of waiting without a deadline. Host result pressure no longer says the fixed result budget has no further room. A Windows Bun allocation before the commit limit names that limit. - Real Hopper/Ghidra, browser, or OS coverage: not run. Browser and source-map coverage here is unit and boundary tests with fake transports and one owned Node decoder process for the capture deadline. The web-bundle heap-marker projection used an owned Node worker. - Package or release metadata impact: none. - Security, privacy, process, or containment review: deadlines do not add authority. Fixed byte budgets and the Electron hook retention limit are unchanged. The reported browser-socket budget now matches the 64 MiB limit the connection already enforced. ## Author readiness Human owner: @morluto - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-5977e40a-ed6f-5269-b93b-f5c059152486?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-5977e40a-ed6f-5269-b93b-f5c059152486&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:45:38 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7132
No description provided.