Skip to content

v1.57.8.0 feat: browse js/eval --out render-to-file (canonical Chromium for offline rendering)#1929

Merged
garrytan merged 5 commits into
mainfrom
garrytan/fix-issue-1906
Jun 10, 2026
Merged

v1.57.8.0 feat: browse js/eval --out render-to-file (canonical Chromium for offline rendering)#1929
garrytan merged 5 commits into
mainfrom
garrytan/fix-issue-1906

Conversation

@garrytan

@garrytan garrytan commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #1906. Makes browse the single canonical Chromium per box, including offline local-render workloads, so skills stop bundling their own puppeteer + a second drifting Chromium.

Render-to-file (b6f03e53)

  • js "<expr>" --out <file> and eval script.js --out <file> write the evaluate result to disk instead of returning it. A data:*;base64,... result is decoded to raw bytes (case-insensitive header parse, split on first comma, base64-charset validated before decode — malformed errors loudly, no corrupt file); --raw forces a literal write. Parent dirs are created. Only a short ... result written: <path> (<N> bytes) status crosses the command channel.
  • --out is modeled as a per-invocation WRITE capability: requires write scope, never dispatchable over the pair-agent tunnel (canDispatchOverTunnel now consults args), and counts as a mutation for watch-mode and tab-ownership. js/eval stay read commands for dispatch; only the security gates treat --out as a write. Shared parseOutArgs/hasOutArg/resultToString helpers keep the handler and the gate in sync.

Docs (6a8c8190, 830f6b6e)

  • Blessed offline render path in the browse skill (headless, no proxy/Xvfb): visual output via screenshot --selector (no bytes over CDP), bytes a function returns via js --out. Puppeteer→browse cheatsheet row, "don't bundle your own Chromium" note (browse skill + CONTRIBUTING), and the --out/--raw reference rows across SKILL.md / llms.txt / BROWSER.md.

Test Coverage

All new code paths covered. Added: parseOutArgs/hasOutArg unit tests (--out/--out=, --raw, repeats, missing value, ordering, --output lookalike), --out render-to-file integration (large string not truncated, data-URL→PNG decode, --raw literal, malformed-base64 error, outside-safe-dir reject, mkdir parents, eval parity, byte-for-byte null/undefined), and tunnel-gate guards proving --out is never tunnel-dispatchable. Targeted suites: commands.test.ts + tunnel-gate-unit.test.ts = 277 pass / 0 fail. Full free suite: green (exit 0).

Pre-Landing Review

No issues found. Pass 1 (critical): no SQL; no new LLM trust-boundary egress (--out returns a short status; file bytes written server-side); validateOutputPath runs before mkdir so an out-of-safe-dir path is rejected before any write. Security gate verified: --out blocked over tunnel, requires write scope, gated in watch/tab. Adversarial angles (uppercase --OUT, ---prefixed value, data-URL path escape, symlink) all closed.

Design Review

No frontend files changed — design review skipped.

Adversarial Review

Clean. The render-to-file path and the write-capability gate were challenged during planning (codex) and at pre-landing; no surviving findings.

TODOS

No TODOS.md items completed by this change. Advisory follow-up (not in this PR): migrate downstream local-render skills off bundled puppeteer onto browse.

Documentation

/document-release audited all docs against the v1.57.8.0 browse render-to-file change.

Doc diff preview

  • BROWSER.md: updated the js and eval reference rows to show the new [--out <file>] [--raw] flags and the WRITE-capability / no-tunnel note, matching SKILL.md, gstack/llms.txt, and browse/SKILL.md.

The feature's own commits already updated browse/SKILL.md(.tmpl), gstack/llms.txt, SKILL.md, and CONTRIBUTING.md. The CHANGELOG entry for v1.57.8.0 was left intact. VERSION is at 1.57.8.0.

Documentation Debt

  • js/eval --out and offline render mode have reference + how-to coverage in browse/SKILL.md but no standalone tutorial (low priority — browse/SKILL.md §14 has a worked example).

🤖 Generated with Claude Code

garrytan and others added 4 commits June 9, 2026 08:35
Add --out <file> / --raw to js and eval so an evaluate result is written
straight to disk (base64 data URLs auto-decoded to bytes, charset-validated
before decode, parent dirs created) instead of serialized back through the
CLI. --out is modeled as a per-invocation WRITE: it requires write scope, is
never dispatchable over the pair-agent tunnel (canDispatchOverTunnel now
consults args), and counts as a mutation for watch-mode and tab-ownership.
Shared parseOutArgs/hasOutArg/resultToString helpers keep the handler and the
gate in sync. Tests cover the parser, render-to-file paths, and tunnel guards.
Document the blessed offline-render path (headless, no proxy/Xvfb): visual
output via screenshot --selector, bytes a function returns via js --out.
Add the puppeteer->browse cheatsheet row, a "don't bundle your own Chromium"
note (browse skill + CONTRIBUTING), and the --out/--raw command descriptions.
Regenerate browse/SKILL.md, SKILL.md, and gstack/llms.txt from the templates.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…v1.59.1.0)

The js and eval reference rows in BROWSER.md drifted: every other reference
surface (SKILL.md, gstack/llms.txt, browse/SKILL.md) already shows the new
[--out <file>] [--raw] flags from v1.59.1.0, but the complete browser
reference still showed the pre-feature signatures. Add the flags plus the
WRITE-capability / no-tunnel note so the reference matches what shipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Jun 9, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

E2E Evals: ✅ PASS

17/17 tests passed | $1.72 total cost | 12 parallel runners

Suite Result Status Cost
e2e-browse 6/6 $0.34
e2e-deploy 2/2 $0.34
e2e-qa-workflow 1/1 $0.58
llm-judge 6/6 $0.12
e2e-deploy 2/2 $0.34

12x ubicloud-standard-8 (Docker: pre-baked toolchain + deps) | wall clock ≈ slowest suite

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@garrytan garrytan changed the title v1.59.1.0 feat: browse js/eval --out render-to-file (canonical Chromium for offline rendering) v1.57.8.0 feat: browse js/eval --out render-to-file (canonical Chromium for offline rendering) Jun 9, 2026
@garrytan garrytan merged commit 421460f into main Jun 10, 2026
24 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant