[GH-ISSUE #3929] [Bug] Oversized passive observation windows report completion after milliseconds #1538

Closed
opened 2026-10-16 21:06:51 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 15, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3929

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Process capture or runtime observation

Observed behavior

The public observe-web-session CLI accepts --observation-ms 3000000000 and --observation-ms 2147483648, then returns successful observation Evidence with end_reason: "window_elapsed" after only 2 ms. The result retains the original requested duration, so it falsely reports completion of a window it did not observe. A 1,000 ms control lasted 1,001 ms without a warning.

Reproduction

Use the baseline and runtime stated under Runtime or environment, with the repository's locked dependencies installed and runtime already built. From the repository root, run the following harness. It starts the repository's fake CDP browser on loopback, invokes the public CLI rather than an internal observation helper, and bounds each CLI invocation with a 10-second watchdog.

case_dir="$(mktemp -d)"
mkdir -p "$case_dir/home"
cat > src/browser/observationWindowRepro.test.ts <<'TEST'
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { expect, it } from "vitest";
import { startFakeCdpBrowser } from "../../tests/fixtures/fakeCdpBrowser.js";

const run = promisify(execFile);

it("measures the public CLI observation window", async () => {
  const browser = await startFakeCdpBrowser();
  try {
    for (const duration of [3000000000, 2147483648, 1000]) {
      const { stdout, stderr } = await run(process.execPath, [
        "scripts/rea.mjs", "observe-web-session", browser.endpoint,
        "allowed-page", "--allowed-origins", browser.allowedOrigin,
        "--observation-ms", String(duration), "--json",
      ], { env: process.env, timeout: 10000, maxBuffer: 1048576 });
      const evidence = JSON.parse(stdout);
      const window = evidence.normalized_result.window;
      const elapsed = Date.parse(window.ended_at) - Date.parse(window.armed_at);
      console.log(JSON.stringify({
        requested_ms: duration, operation: evidence.operation,
        reported_ms: window.requested_ms, elapsed_ms: elapsed,
        end_reason: window.end_reason, stderr,
      }));
      expect(evidence.operation).toBe("observe_web_session");
      expect(window.requested_ms).toBe(duration);
      expect(window.end_reason).toBe("window_elapsed");
    }
  } finally {
    await browser.close();
  }
}, 35000);
TEST
HOME="$case_dir/home" npx --no-install vitest run src/browser/observationWindowRepro.test.ts
result=$?
rm src/browser/observationWindowRepro.test.ts
rm -rf "$case_dir"
exit "$result"

Compare the printed elapsed intervals and warnings. The first two requests should not report that their entire windows elapsed within milliseconds. The watchdog bounds the test if long-duration handling changes; watchdog termination does not establish that a full long window completed. Remove the harness after running it, as the commands above do.

Expected behavior

The operation promises to arm a CDP observation window of the requested duration while the user operates the selected page. Both concrete oversized inputs pass the public CLI validation. An admitted window must not report window_elapsed before its requested interval has elapsed. If the implementation cannot support a requested interval, the caller needs an explicit actionable validation failure instead of a successful result that misstates the observed duration. Cancellation, target termination, and leaving the allowed origin remain legitimate distinct early outcomes.

docs/browser-observation.md:20 and src/contracts/browserToolContracts.ts:197 promise the requested-duration observation window.

Impact and scope

P2. Both admitted oversized durations falsely report successful completion and omit the intended observation coverage. The ordinary 1,000 ms control worked. Real-browser frequency and full multi-day completion were not measured. Shorter windows avoid the demonstrated overflow, but a workaround preserving one uninterrupted long observation window was not verified.

REA version

rea 6.5.0 at source commit 4692bb3330

Runtime and platform

Node 24.18.0; macOS arm64

Target and artifact context

Loopback HTTP/WebSocket fake CDP browser, target allowed-page, explicit allowed origin, and isolated HOME. No real browser or external API was used.

Interface

CLI

Earliest failure stage

Capture or observation

Relevant output or evidence

Observed through the public CLI against the fake CDP browser: both oversized requests exited with code 0 and returned operation: "observe_web_session", preserved their requested durations, and reported end_reason: "window_elapsed" after 2 ms. The 1,000 ms control exited with code 0 and reported the same end reason after 1,001 ms. Each oversized request reproduced once in this independent run. The control ran once.

The oversized child processes printed warnings of this form, with the requested value substituted for the interval:

TimeoutOverflowWarning: 3000000000 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.

The control produced no stderr. These observations establish premature completion at the real CLI boundary with a simulated browser; they do not establish behavior against a real browser or completion of a multi-day window.

Typed outcome or recovery expected

Run the same public CLI requests against the controlled browser. The oversized requests must either receive an explicit duration-range error before observation or remain active beyond the immediate overflow interval without claiming window_elapsed. If they remain active, verify cancellation produces its proper outcome and releases the connection. A bounded pending/cancellation check does not prove complete multi-day waiting; verify long-interval scheduling separately with an appropriate clock-controlled check if that behavior is supported. The 1,000 ms control must still observe its requested interval and return window_elapsed without an overflow warning. Preserve the existing distinct outcomes for target termination and leaving the allowed origin.

Analysis or suspected cause

Source-derived: src/domain/browserSession.ts:15 and src/cli/browserCommands.ts:191 admit these durations. src/browser/CdpObservationSession.ts:95,376 forwards the duration directly to Node setTimeout; line 120 retains the original requested duration in the result. This agrees with the observed overflow warnings.

Additional context

The cited failing code is unchanged on current origin/main at 22ec8bdb2f7d4626587f23b1eed4a207df600386.

Related #3392 concerns Playwright scenario waits and action deadlines. Open PR #3515 changes only src/domain/browserScenarioValues.ts and src/domain/browserScenario.test.ts; it does not change observe_web_session or src/browser/CdpObservationSession.ts. Its scenario fix leaves this separate passive observation timer unchanged.

Originally created by @coygeek on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3929 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Process capture or runtime observation ### Observed behavior The public `observe-web-session` CLI accepts `--observation-ms 3000000000` and `--observation-ms 2147483648`, then returns successful observation Evidence with `end_reason: "window_elapsed"` after only 2 ms. The result retains the original requested duration, so it falsely reports completion of a window it did not observe. A 1,000 ms control lasted 1,001 ms without a warning. ### Reproduction Use the baseline and runtime stated under Runtime or environment, with the repository's locked dependencies installed and runtime already built. From the repository root, run the following harness. It starts the repository's fake CDP browser on loopback, invokes the public CLI rather than an internal observation helper, and bounds each CLI invocation with a 10-second watchdog. ```bash case_dir="$(mktemp -d)" mkdir -p "$case_dir/home" cat > src/browser/observationWindowRepro.test.ts <<'TEST' import { execFile } from "node:child_process"; import { promisify } from "node:util"; import { expect, it } from "vitest"; import { startFakeCdpBrowser } from "../../tests/fixtures/fakeCdpBrowser.js"; const run = promisify(execFile); it("measures the public CLI observation window", async () => { const browser = await startFakeCdpBrowser(); try { for (const duration of [3000000000, 2147483648, 1000]) { const { stdout, stderr } = await run(process.execPath, [ "scripts/rea.mjs", "observe-web-session", browser.endpoint, "allowed-page", "--allowed-origins", browser.allowedOrigin, "--observation-ms", String(duration), "--json", ], { env: process.env, timeout: 10000, maxBuffer: 1048576 }); const evidence = JSON.parse(stdout); const window = evidence.normalized_result.window; const elapsed = Date.parse(window.ended_at) - Date.parse(window.armed_at); console.log(JSON.stringify({ requested_ms: duration, operation: evidence.operation, reported_ms: window.requested_ms, elapsed_ms: elapsed, end_reason: window.end_reason, stderr, })); expect(evidence.operation).toBe("observe_web_session"); expect(window.requested_ms).toBe(duration); expect(window.end_reason).toBe("window_elapsed"); } } finally { await browser.close(); } }, 35000); TEST HOME="$case_dir/home" npx --no-install vitest run src/browser/observationWindowRepro.test.ts result=$? rm src/browser/observationWindowRepro.test.ts rm -rf "$case_dir" exit "$result" ``` Compare the printed elapsed intervals and warnings. The first two requests should not report that their entire windows elapsed within milliseconds. The watchdog bounds the test if long-duration handling changes; watchdog termination does not establish that a full long window completed. Remove the harness after running it, as the commands above do. ### Expected behavior The operation promises to arm a CDP observation window of the requested duration while the user operates the selected page. Both concrete oversized inputs pass the public CLI validation. An admitted window must not report `window_elapsed` before its requested interval has elapsed. If the implementation cannot support a requested interval, the caller needs an explicit actionable validation failure instead of a successful result that misstates the observed duration. Cancellation, target termination, and leaving the allowed origin remain legitimate distinct early outcomes. `docs/browser-observation.md:20` and `src/contracts/browserToolContracts.ts:197` promise the requested-duration observation window. ### Impact and scope P2. Both admitted oversized durations falsely report successful completion and omit the intended observation coverage. The ordinary 1,000 ms control worked. Real-browser frequency and full multi-day completion were not measured. Shorter windows avoid the demonstrated overflow, but a workaround preserving one uninterrupted long observation window was not verified. ### REA version rea 6.5.0 at source commit 4692bb33300c7cb77b095b6cc0c33da861c1b860 ### Runtime and platform Node 24.18.0; macOS arm64 ### Target and artifact context Loopback HTTP/WebSocket fake CDP browser, target `allowed-page`, explicit allowed origin, and isolated HOME. No real browser or external API was used. ### Interface CLI ### Earliest failure stage Capture or observation ### Relevant output or evidence Observed through the public CLI against the fake CDP browser: both oversized requests exited with code 0 and returned `operation: "observe_web_session"`, preserved their requested durations, and reported `end_reason: "window_elapsed"` after 2 ms. The 1,000 ms control exited with code 0 and reported the same end reason after 1,001 ms. Each oversized request reproduced once in this independent run. The control ran once. The oversized child processes printed warnings of this form, with the requested value substituted for the interval: ```text TimeoutOverflowWarning: 3000000000 does not fit into a 32-bit signed integer. Timeout duration was set to 1. ``` The control produced no stderr. These observations establish premature completion at the real CLI boundary with a simulated browser; they do not establish behavior against a real browser or completion of a multi-day window. ### Typed outcome or recovery expected Run the same public CLI requests against the controlled browser. The oversized requests must either receive an explicit duration-range error before observation or remain active beyond the immediate overflow interval without claiming `window_elapsed`. If they remain active, verify cancellation produces its proper outcome and releases the connection. A bounded pending/cancellation check does not prove complete multi-day waiting; verify long-interval scheduling separately with an appropriate clock-controlled check if that behavior is supported. The 1,000 ms control must still observe its requested interval and return `window_elapsed` without an overflow warning. Preserve the existing distinct outcomes for target termination and leaving the allowed origin. ### Analysis or suspected cause Source-derived: `src/domain/browserSession.ts:15` and `src/cli/browserCommands.ts:191` admit these durations. `src/browser/CdpObservationSession.ts:95,376` forwards the duration directly to Node `setTimeout`; line 120 retains the original requested duration in the result. This agrees with the observed overflow warnings. ### Additional context The cited failing code is unchanged on current `origin/main` at `22ec8bdb2f7d4626587f23b1eed4a207df600386`. Related #3392 concerns Playwright scenario waits and action deadlines. Open PR #3515 changes only `src/domain/browserScenarioValues.ts` and `src/domain/browserScenario.test.ts`; it does not change `observe_web_session` or `src/browser/CdpObservationSession.ts`. Its scenario fix leaves this separate passive observation timer unchanged.
Author
Owner

@XinwangTao commented on GitHub (Oct 15, 2026):

Confirmed: returning window_elapsed after ~2 ms for a multi-billion ms window reports a completion the tool never observed — the 2147483648 case strongly suggests a 32-bit signed truncation of the duration. The window budget should be validated (or carried in a wide type) before observation starts, and an unobservable/oversized duration should fail or warn up front instead of fabricating a completed window.

<!-- gh-comment-id:6186317059 --> @XinwangTao commented on GitHub (Oct 15, 2026): Confirmed: returning window_elapsed after ~2 ms for a multi-billion ms window reports a completion the tool never observed — the 2147483648 case strongly suggests a 32-bit signed truncation of the duration. The window budget should be validated (or carried in a wide type) before observation starts, and an unobservable/oversized duration should fail or warn up front instead of fabricating a completed window.
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#1538
No description provided.