From 9d569c344a7b0d26545fb1d4549f567ac2a4423e Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Sat, 24 Oct 2026 07:20:57 +0800 Subject: [PATCH] fix(cli): coerce web execution observation duration --- scripts/lib/browser-runtime-e2e.mjs | 6 +++++- src/cli/webRuntimeCommands.ts | 15 ++++++++++----- src/domain/webExecution.ts | 3 ++- tests/acceptance/webRuntimeCli.test.ts | 20 ++++++++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/scripts/lib/browser-runtime-e2e.mjs b/scripts/lib/browser-runtime-e2e.mjs index f0c69843a9..aad63c97f6 100644 --- a/scripts/lib/browser-runtime-e2e.mjs +++ b/scripts/lib/browser-runtime-e2e.mjs @@ -274,7 +274,11 @@ async function executionCli(entrypoint, input, env, action, isolatedContext) { }); try { const [code] = await once(child, "close"); - assert.equal(code, 0, stderr); + assert.equal( + code, + 0, + `observe-web-execution exited ${String(code)} (signal ${String(child.signalCode)})\nstdout:\n${stdout}\nstderr:\n${stderr}`, + ); assert.ok(actionPromise, "CLI did not report an actual armed point"); await actionPromise; return stdout; diff --git a/src/cli/webRuntimeCommands.ts b/src/cli/webRuntimeCommands.ts index 6cc2137735..083ca57ad9 100644 --- a/src/cli/webRuntimeCommands.ts +++ b/src/cli/webRuntimeCommands.ts @@ -7,7 +7,7 @@ import { } from "../cliObservationOptions.js"; import { logCliCommand } from "../cliLogging.js"; import { CLI_COMMANDS } from "../cliCommandNames.js"; -import { observeWebExecutionInputSchema } from "../domain/webExecution.js"; +import { MAX_BROWSER_DEADLINE_MS } from "../domain/browserDeadline.js"; import type { Logger } from "pino"; import type { ProgressReporter } from "../application/ProgressReporter.js"; import { withCommandCancellation } from "./commandCancellation.js"; @@ -36,10 +36,15 @@ export const registerWebRuntimeCommands = ( }), options: z.object({ ...browserScopeOptions, - observationMs: - observeWebExecutionInputSchema.shape.observation_ms.describe( - "Observation duration in milliseconds", - ), + // incur only coerces ZodNumber argv fields; domain z.int() constructs + // ZodNumberFormat. Preserve the canonical bounds in this CLI adapter. + observationMs: z + .number() + .int() + .min(1) + .max(MAX_BROWSER_DEADLINE_MS) + .default(10_000) + .describe("Observation duration in milliseconds"), }), run: ({ args, options }) => withCommandCancellation((signal) => diff --git a/src/domain/webExecution.ts b/src/domain/webExecution.ts index f249e01ded..632206c8bd 100644 --- a/src/domain/webExecution.ts +++ b/src/domain/webExecution.ts @@ -1,4 +1,5 @@ import { z } from "zod"; +import { MAX_BROWSER_DEADLINE_MS } from "./browserDeadline.js"; import { jsonObjectSchema } from "./jsonValue.js"; import { webRuntimeLocationSchema, @@ -10,7 +11,7 @@ import { browserVersionSchema } from "./browserObservationSchemas.js"; /** Explicit instrumentation request for one finite, externally driven execution window. */ export const observeWebExecutionInputSchema = webRuntimeScopeSchema.extend({ - observation_ms: z.int().min(1).max(2_147_483_647).default(10_000), + observation_ms: z.int().min(1).max(MAX_BROWSER_DEADLINE_MS).default(10_000), }); export type ObserveWebExecutionInput = z.infer< typeof observeWebExecutionInputSchema diff --git a/tests/acceptance/webRuntimeCli.test.ts b/tests/acceptance/webRuntimeCli.test.ts index 2b37fecddd..25bd201449 100644 --- a/tests/acceptance/webRuntimeCli.test.ts +++ b/tests/acceptance/webRuntimeCli.test.ts @@ -18,6 +18,26 @@ const environment = () => ({ HOPPER_LAUNCHER_PATH: "/rea-unconfigured-provider/hopper", }); +it("advertises the canonical observation duration bounds through the compiled CLI", async () => { + const { stdout } = await promisify(execFile)( + process.execPath, + [entrypoint, "observe-web-execution", "--schema", "--json"], + { env: environment(), timeout: 20_000 }, + ); + expect(JSON.parse(stdout)).toMatchObject({ + options: { + properties: { + observationMs: { + type: "integer", + minimum: 1, + maximum: 2_147_483_647, + default: 10_000, + }, + }, + }, + }); +}); + it("runs the compiled public listener command through its default native CDP composition", async () => { const browser = await startRuntimeBrowser(); onTestFinished(() => browser.close());