Skip to content

fix(screenshot-diff): reject string values for captureBaseline/captureCurrent - #1385

Merged
latekvo merged 4 commits into
mainfrom
fix/screenshot-diff-strict-booleans
Oct 23, 2026
Merged

latekvo merged 4 commits into
mainfrom
fix/screenshot-diff-strict-booleans

Conversation

@latekvo

@latekvo latekvo commented Oct 12, 2026

Copy link
Copy Markdown
Member

Closes #811

captureBaseline / captureCurrent used z.coerce.boolean(), which is JS truthiness: the string "false" parsed to true, so a caller that declined a live capture got one. They now use plain z.boolean(), like the other plain boolean params, so a string value fails validation with a clear expected boolean, received string error.

No docs update needed.

Verification

Probe drives screenshot-diff through the real Registry.invokeTool path (safeParse -> services() -> resolve -> execute) on built dist/, with two real PNGs and no device (udid emulator-5554, no SimulatorServer blueprint registered).

Before (fix reverted, rebuilt):

{baselinePath, currentPath, captureCurrent:"false"}  -> ERR Service dependency failed: Service "SimulatorServer:emulator-5554" not found
{baselinePath, currentPath, captureBaseline:"false"} -> ERR Service dependency failed: Service "SimulatorServer:emulator-5554" not found
{baselinePath, currentPath, captureCurrent:"no"}     -> ERR Service dependency failed: Service "SimulatorServer:emulator-5554" not found
{baselinePath, currentPath, captureCurrent:false}    -> OK Screenshot diff summary
{baselinePath, currentPath}                          -> OK Screenshot diff summary

After:

{baselinePath, currentPath, captureCurrent:"false"}  -> ERR Invalid params for tool "screenshot-diff": `captureCurrent`: Invalid input: expected boolean, received string
{baselinePath, currentPath, captureBaseline:"false"} -> ERR Invalid params ... `captureBaseline`: Invalid input: expected boolean, received string
{baselinePath, currentPath, captureCurrent:"no"}     -> ERR Invalid params ... `captureCurrent`: Invalid input: expected boolean, received string
{baselinePath, currentPath, captureCurrent:false}    -> OK Screenshot diff summary
{baselinePath, currentPath}                          -> OK Screenshot diff summary

Schema-level (zodSchema.safeParse + services()): before, "false" / "0" -> true and services=["simulatorServer"]; after, invalid_type. Real booleans unchanged both ways.

Checks: npx tsc --build exit 0; vitest tool-server (screenshot-diff-tool, tool-input-schema-contract, flows/flow-composition) 237/237, argent-cli flag-parser 67/67, argent-tools-client file-inputs 24/24; prettier --check and eslint clean on the touched file. The CLI path is unaffected (flag-parser already maps false/0 to a boolean).

Not included: the lower-impact twin includeBody in network/network-request.ts still coerces.

…eCurrent

z.coerce.boolean() is JS truthiness, so the string "false" parsed to true
and a caller that declined a live capture got one. Use z.boolean() like
every other boolean param in the catalogue.

Closes #811
@coderabbitai

coderabbitai Bot commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

latekvo pushed a commit that referenced this pull request Oct 22, 2026
> [!NOTE]
> **AI-generated, not reviewed by a human.** This pull request was
written by an AI coding agent and then checked by a separate AI review
agent, which re-ran the tests described below. No human has reviewed the
code. It is submitted by @monsterlag, who runs these agents. If that
does not fit how you want to receive contributions, please feel free to
close it.


## Summary

Fixes #1538.

`view-network-request-details` declared `includeBody` with
`z.coerce.boolean()`, which uses JS truthiness, so an MCP or HTTP caller
sending `"includeBody": "false"` (or `"0"`) got the response body
anyway, with no sign the value was ignored.

Declare it as a plain `z.boolean()`, the same change #1385 makes for
`captureBaseline`/`captureCurrent` in `screenshot-diff`. A string value
is now rejected as `invalid_type` on `includeBody` instead of being
silently turned into `true`. Booleans and the `true` default are
unchanged. The CLI already maps `--includeBody false` to a real boolean,
so it is not affected.

Add regressions in `chromium-network.test.ts`: string values (`"false"`,
`"0"`, `"true"`) are rejected, booleans are accepted as given.

No docs update is needed: the tools reference does not describe this
parameter.

## Testing

- New tests: **3 failed / 2 passed before** the fix, **all passed
after**.
- `npx vitest run test/chromium-network.test.ts test/network` (in
`packages/tool-server`): 4 files, **295 passed**
- `npm run build`
- `npm run typecheck:tests --workspaces --if-present`
- `npx eslint` (with `NODE_OPTIONS=--max-old-space-size=2600`, the
default heap ran out in the container) and `npx prettier --check` on the
two changed files: clean

Container note: dependencies were installed with `npm ci
--ignore-scripts`, because the `tree-sitter` native build fails under
Node 24 in the test container. No live-device testing was performed.
@latekvo

latekvo commented Oct 23, 2026

Copy link
Copy Markdown
Member Author

Makes sense, the test added is minimal and really shows the issue

@latekvo
latekvo marked this pull request as ready for review October 23, 2026 17:15
@latekvo
latekvo merged commit 6e7985c into main Oct 23, 2026
10 checks passed
@latekvo
latekvo deleted the fix/screenshot-diff-strict-booleans branch October 23, 2026 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

screenshot-diff: captureBaseline/captureCurrent coerce the string "false" to true, so a declined live capture happens anyway

1 participant