Skip to content

Seed the Playwright browser into the tend sandbox so a session can run the suite - #106

Merged
max-sixty merged 1 commit into
mainfrom
daily/review-runs-33241681155
Aug 29, 2026
Merged

Seed the Playwright browser into the tend sandbox so a session can run the suite#106
max-sixty merged 1 commit into
mainfrom
daily/review-runs-33241681155

Conversation

@leaf-agent

Copy link
Copy Markdown
Collaborator

Tend sessions start with an empty Playwright cache, so the suite that is most of tests/ cannot run from one — setup: installs browsers under the runner's home, which the sandbox does not inherit. This adds a sandbox_setup: block that seeds the same headless shell ci.yaml uses into the sandbox's own home, and asserts it by launching it. Verified in a real tend sandbox: cache empty at start, install 4.4s, launch 0.8s, and uv run pytest --run-nightly -n0 tests/test_render_reactions.py -k stacks_at_a_narrow_edge then passes 2 tests in 4.26s where before it could not start.

What was observed, and why this shape

The evidence

Last night's tend-nightly session (33238853704) reached this partway through the suite:

ERROR tests/test_render_conversations.py::test_the_line_offers_the_list_its_own_keys_rather_than_the_way_deeper_in
  playwright._impl._errors.Error: BrowserType.launch: Executable doesn't exist at
  /home/tend-sandbox/.cache/ms-playwright/chromium_headless_shell-1234/chrome-headless-shell-linux64/chrome-headless-shell

It did not install the browser; it stopped verifying locally and said so in its summary — "The browser suites also did not run locally — this sandbox has no Playwright browsers installed — so CI was their first pass on both PRs". Both PRs it opened (#104, #105) are green, so nothing wrong went out. What went out unverified is the point: on a repo where nearly every test drives a real browser, the session shipped with the repo's own gate unrun.

Three tend-ci-fix sessions the same night did install it themselves, and two of them lost a turn to the same wrong flag first:

Run Command Result
33229417627 playwright install --with-deps chromium --only-shell sudo: a password is required
33229417627 playwright install chromium --only-shell ok, 3s
33230715465 playwright install --with-deps chromium --only-shell sudo: a password is required
33230715465 playwright install chromium --only-shell ok, 4s
33231657192 playwright install chromium --only-shell ok, 5s

--with-deps switches to root, and the sandbox user has no sudo — the trap running-in-ci's Privileges bullet names, and its prescribed remedy is exactly this: propose the setup entry rather than work around its absence.

Why sandbox_setup: rather than setup:

setup: runs as the runner. Playwright downloads to $HOME/.cache/ms-playwright, and per tend's config reference the sandbox inherits shared system and toolcache paths but never the runner's home. sandbox_setup: runs as the sandbox user with the workspace as cwd, which puts the browser where sync_playwright() will look for it. This is the neighbour of the uv-on-PATH gap that max-sixty/tend#1071 fixed upstream for 0.1.20 — same boundary, but a home-scoped download rather than a PATH entry, so the repo owns it rather than tend.

Why no --with-deps

The runner image already carries the system libraries: the three sessions above ran the browser suite successfully after a plain --only-shell install, and so did the verification here. Adding a second setup: step to run --with-deps as the runner would be machinery for a need that has not appeared.

Cost

~5.3s per session that boots an agent (4.4s install, 0.8s launch, measured in this sandbox). sandbox_setup runs inside the max-sixty/tend/claude step, so the tend-notifications and tend-review runs that short-circuit before booting pay nothing — and tend-ci-fix's gate-skips never reach it either.

The regenerated workflows

.config/tend.yaml is the source; sandbox_setup is an action input, so it has to reach each generated workflow. Regenerated with uvx tend@0.1.20 init — the version already pinned in every workflow header — so the diff is three added lines per file and no other drift, which also confirms the committed files match what 0.1.20 generates.

Gate assessment

  • Confidence: High. Structural — the sandbox home starts without the cache on every run, so it recurs every time. Four sessions hit it in one 20-hour window: one abandoned the gate, three installed it themselves, two of those after a failed escalation.
  • Magnitude: targeted fix. One existing knob in one place, plus the mechanical regeneration it requires.
  • Cost: mostly wasted compute — a turn per session and a download per session. The nightly case is the one that isn't purely waste: a repo whose safety net is a browser suite had that net unavailable to the session doing the surveying. No wrong outward action occurred, so the remedy is held to the waste-class bar, which one config knob meets.

@leaf-agent leaf-agent added the review-runs Opened by the tend-review-runs sweep label Aug 29, 2026
@max-sixty
max-sixty merged commit 519762a into main Aug 29, 2026
4 checks passed
@max-sixty
max-sixty deleted the daily/review-runs-33241681155 branch August 29, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-runs Opened by the tend-review-runs sweep

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants