[PR #5268] [CLOSED] fix(browser): bound the start navigation with a provider-owned deadline #6848

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5268
Author: @sx4im
Created: 10/19/2026
Status: ❌ Closed

Base: main ← Head: fix/5266-browser-start-navigation-deadline


📝 Commits (1)

  • 37e0991 fix(browser): bound the start navigation with a provider-owned deadline

📊 Changes

2 files changed (+29 additions, -2 deletions)

View changed files

📝 src/browser/PlaywrightScenarioSession.test.ts (+24 -1)
📝 src/browser/PlaywrightScenarioSession.ts (+5 -1)

📄 Description

Summary

Fixes #5266. Opening a browser scenario waited for the start page's load event with no deadline of its own, so a page whose script navigates away early to a host that never answers held the scenario open indefinitely. The start navigation now runs under a fixed 60s provider-owned deadline.

Problem and expected behavior

PlaywrightScenarioSession.open called page.goto(start_url, { waitUntil: "load", timeout: 0 }) inside withPlaywrightExecutionBoundary(..., undefined, signal). With Playwright timeouts disabled by design (the context sets both default timeouts to 0), only the caller's signal could end that wait. If the start page's script starts a navigation before load and that navigation never commits, goto never settles, so nothing reaches assertBlocked, storage.settle, or the first step. docs/browser-scenario-contract.md says navigation timeouts stay fixed provider-owned liveness limits, but the start navigation had none.

Change and scope

Pass a new fixed constant, PLAYWRIGHT_SCENARIO_START_NAVIGATION_TIMEOUT_MS (60s), to the execution boundary around the start navigation, instead of undefined. The boundary's AnalysisTimeoutError flows through the existing failed-open path: the session closes, cleanup runs, and the open fails with a typed timeout error. Two files changed, nothing else touched. 60s lines up with the provider's other startup-scale bounds (browser devtools startup, electron startup) since the start navigation waits for a full load of a real target page.

Not included: per-action goto navigations keep their caller-supplied timeout_ms behavior, untouched.

Contract and boundary impact

  • Semantic owner and earliest changed stage: browser scenario provider, scenario open/start navigation.
  • Contribution scope fit and linked maintainer decision: ordinary fix within existing boundaries; not applicable.
  • CLI and MCP/tool-catalog contract: none.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: the timeout error carries the existing partial-observation record (start origin, limits, and the "Scenario navigation failed before the initial state was captured" limitation).
  • Target selection, authority, upstream behavior, and cleanup details: the failed-open path already closes the session and releases the browser; unchanged.
  • Generated metadata, package, or installation impact: none.

Expected effects: none of the listed effects are new; the change only bounds an existing provider-side wait. The failed-open cleanup that terminates the browser session already existed for other failures.

Evidence and regression coverage

  • Tests added or updated: src/browser/PlaywrightScenarioSession.test.ts gains "bounds a never-settling start navigation with the provider-owned deadline". The mocked page's goto never settles, fake timers advance past the 60s deadline, and the test asserts open rejects with _tag: "AnalysisTimeoutError", timeoutMs: 60000, and that browser cleanup ran once.
  • Base reproduction or other evidence: executed, not source-only. On the base revision the same test hangs and the runner times it out at 30s, which is the reported behavior. With the fix, open fails exactly at the deadline.
  • User-visible CLI/MCP output: none.
  • Remaining proof gaps: no real-browser run of a redirect-to-dead-host page in this PR (no Chrome on the build host). The reporter verified the underlying Playwright behavior in #5266 with a standalone script on playwright-core 1.58.2, the version this repo pins.

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

  • npx vitest run src/browser/PlaywrightScenarioSession.test.ts — 26/26 pass (new test fails on base via 30s hang timeout, passes with fix in 133ms under fake timers).
  • npm run test:local -- src/browser/PlaywrightScenarioBrowser.test.ts src/browser/PlaywrightBrowserScenarioProvider.test.ts — 48/48 pass.
  • npm run check:fast — typecheck and lint, 2/2 tasks successful.
  • npm run verify:test-discovery — all 1666 test files discovered exactly once.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. A start navigation that previously hung forever now fails after 60s; that is the fix.
  • Real Hopper/Ghidra, browser, or OS coverage: no real-browser run; see proof gaps above.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: no new process or network effects. A previously unbounded wait now terminates, which reduces resource retention.

Author readiness

Human owner:

  • 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.

🔄 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/5268 **Author:** [@sx4im](https://github.com/sx4im) **Created:** 10/19/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/5266-browser-start-navigation-deadline` --- ### 📝 Commits (1) - [`37e0991`](https://github.com/morluto/rea/commit/37e0991bde2731d7765458a454bb8777546ea0e3) fix(browser): bound the start navigation with a provider-owned deadline ### 📊 Changes **2 files changed** (+29 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `src/browser/PlaywrightScenarioSession.test.ts` (+24 -1) 📝 `src/browser/PlaywrightScenarioSession.ts` (+5 -1) </details> ### 📄 Description ## Summary Fixes #5266. Opening a browser scenario waited for the start page's `load` event with no deadline of its own, so a page whose script navigates away early to a host that never answers held the scenario open indefinitely. The start navigation now runs under a fixed 60s provider-owned deadline. ## Problem and expected behavior `PlaywrightScenarioSession.open` called `page.goto(start_url, { waitUntil: "load", timeout: 0 })` inside `withPlaywrightExecutionBoundary(..., undefined, signal)`. With Playwright timeouts disabled by design (the context sets both default timeouts to 0), only the caller's signal could end that wait. If the start page's script starts a navigation before `load` and that navigation never commits, `goto` never settles, so nothing reaches `assertBlocked`, `storage.settle`, or the first step. `docs/browser-scenario-contract.md` says navigation timeouts stay fixed provider-owned liveness limits, but the start navigation had none. ## Change and scope Pass a new fixed constant, `PLAYWRIGHT_SCENARIO_START_NAVIGATION_TIMEOUT_MS` (60s), to the execution boundary around the start navigation, instead of `undefined`. The boundary's `AnalysisTimeoutError` flows through the existing failed-open path: the session closes, cleanup runs, and the open fails with a typed timeout error. Two files changed, nothing else touched. 60s lines up with the provider's other startup-scale bounds (browser devtools startup, electron startup) since the start navigation waits for a full `load` of a real target page. Not included: per-action `goto` navigations keep their caller-supplied `timeout_ms` behavior, untouched. ## Contract and boundary impact - Semantic owner and earliest changed stage: browser scenario provider, scenario open/start navigation. - Contribution scope fit and linked maintainer decision: ordinary fix within existing boundaries; not applicable. - CLI and MCP/tool-catalog contract: none. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: the timeout error carries the existing partial-observation record (start origin, limits, and the "Scenario navigation failed before the initial state was captured" limitation). - Target selection, authority, upstream behavior, and cleanup details: the failed-open path already closes the session and releases the browser; unchanged. - Generated metadata, package, or installation impact: none. Expected effects: none of the listed effects are new; the change only bounds an existing provider-side wait. The failed-open cleanup that terminates the browser session already existed for other failures. ## Evidence and regression coverage - Tests added or updated: `src/browser/PlaywrightScenarioSession.test.ts` gains "bounds a never-settling start navigation with the provider-owned deadline". The mocked page's `goto` never settles, fake timers advance past the 60s deadline, and the test asserts `open` rejects with `_tag: "AnalysisTimeoutError"`, `timeoutMs: 60000`, and that browser cleanup ran once. - Base reproduction or other evidence: executed, not source-only. On the base revision the same test hangs and the runner times it out at 30s, which is the reported behavior. With the fix, `open` fails exactly at the deadline. - User-visible CLI/MCP output: none. - Remaining proof gaps: no real-browser run of a redirect-to-dead-host page in this PR (no Chrome on the build host). The reporter verified the underlying Playwright behavior in #5266 with a standalone script on playwright-core 1.58.2, the version this repo pins. 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 - `npx vitest run src/browser/PlaywrightScenarioSession.test.ts` — 26/26 pass (new test fails on base via 30s hang timeout, passes with fix in 133ms under fake timers). - `npm run test:local -- src/browser/PlaywrightScenarioBrowser.test.ts src/browser/PlaywrightBrowserScenarioProvider.test.ts` — 48/48 pass. - `npm run check:fast` — typecheck and lint, 2/2 tasks successful. - `npm run verify:test-discovery` — all 1666 test files discovered exactly once. ## Compatibility, safety, and release - Breaking changes or migration steps: none. A start navigation that previously hung forever now fails after 60s; that is the fix. - Real Hopper/Ghidra, browser, or OS coverage: no real-browser run; see proof gaps above. - Package or release metadata impact: none. - Security, privacy, process, or containment review: no new process or network effects. A previously unbounded wait now terminates, which reduces resource retention. ## Author readiness Human owner: <!-- @GitHub-handle --> - [ ] 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. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:43:29 +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#6848
No description provided.