[STG-2513] fix: browse skill BROWSE_SESSION precedence + container guidance#2336
Conversation
…ce in browse skill Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Behavioral A/B evidence (post-review, informational): ran the exact same 4-task bare-loop sandbox smoke twice — stock skill vs this PR's text (only delta between tarballs = these two paragraphs; n=1/task, qualitative).
Reading: the BROWSE_SESSION-precedence paragraph works — once agents keep the env session name, cleanup paths line up and session leaks disappear. The container/ Full trajectories: |
… 22 (#2344) ## Why Every stagehand release since 2026-07-09 18:52 UTC is broken. The Release workflow's "Update npm for Trusted Publishing" step runs `npm install -g npm@latest`; npm@12.0.0 was published 2026-07-08 21:06 UTC and became `latest`, and it requires node `^22.22.2 || ^24.15.0 || >=26` — the release job runs node 20, so the step dies with `EBADENGINE` before versioning even starts. - Last green Release: 2026-07-08 17:50 UTC - First failure: 2026-07-09 18:52 UTC ([run](https://github.com/browserbase/stagehand/actions/runs/29043380120) — `npm error notsup Required: {"node":"^22.22.2 || ^24.15.0 || >=26.0.0"} / Actual: {"npm":"10.8.2","node":"v20.20.2"}`) - This currently blocks the browse release carrying `browse skills show` (#2335) and the browse-skill guidance fixes (#2336), whose changeset is pending on main. ## What Pin the step to `npm@11` (currently 11.18.0): supports node >= 20.17 **and** Trusted Publishing/OIDC (needs npm >= 11.5.1) — the reason this step exists, since node 20 bundles npm 10.8.2 which predates it. One line + a comment stating the constraint. The alternative (bump the job to node 22/24 and keep `@latest`) changes the entire release build environment (SEA binaries, prebuilds) and isn't hotfix material; it can be considered separately. ## Validation | Command / flow | Observed output | Confidence / sufficiency | | --- | --- | --- | | Failure-log inspection of both failed Release runs | `EBADENGINE ... npm@12.0.0 ... Required node ^22.22.2 \|\| ^24.15.0 \|\| >=26 / Actual node v20.20.2`, exit 1 at the pinned step | Proves the failure mechanism exactly at this line | | `curl registry.npmjs.org/npm` → dist-tags + publish times | `latest = 12.0.0`, published 2026-07-08T21:06Z — inside the 07-08 17:50 → 07-09 18:52 breakage window | Proves `@latest` drift is the trigger; nothing repo-side changed | | npm 11.x engine range vs job node | npm 11.18.0 supports node >= 20.17; job runs 20.20.2 | Proves the pin resolves the engine conflict while keeping Trusted Publishing (>= 11.5.1) | | Real release exercise | Not possible pre-merge — the Release workflow only runs from main. Merging this PR pushes to main, which itself triggers Release with the pending browse changeset — that run is the live verification | The one path that cannot be tested from a branch | Linear: STG-2520 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Pin `npm` in the Release workflow to `11.18.0` to avoid `npm@12` requiring Node >=22. Restores releases on Node 20 and keeps Trusted Publishing (Linear: STG-2520). <sup>Written for commit 90a6d71. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2344?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
A 3-provider bare-loop smoke test (E2B/Modal/Vercel, real sandboxes, local CLI build) surfaced two systematic gaps in the bundled
browseskill (packages/cli/skills/browse/SKILL.md):BROWSE_SESSIONenv var and self-named sessions via--session <name>(one run orphaned a Browserbase session as a result). The skill taught named--sessionusage but never said "ifBROWSE_SESSIONis already set, every command already targets that session — don't pass--sessionor invent a new name." This defeats the sandbox-template env-steering pattern (BROWSERBASE_API_KEY+BROWSE_SESSION=<name>→ flagless remote commands).--localfirst inside Chrome-less containers, hit "No Chrome or Chromium found", then recovered on retry. The skill lacked explicit guidance that--localrequires local Chrome/Chromium and that containers/CI/sandboxes without Chrome should go straight to--remote.What changed
Two minimal additions to
packages/cli/skills/browse/SKILL.md, both in the existing "Browser Target Selection" section (the section that already teaches local/remote choice and named-session usage) — no restructuring, no new sections:Verified the precedence claim against the actual implementation before writing the wording (not just trusting the smoke-test writeup):
packages/cli/src/lib/driver/flags.ts:73—export function sessionName(value?: string): string { return value ?? process.env.BROWSE_SESSION ?? "default"; }. An explicit--sessionflag always wins overBROWSE_SESSION; when omitted,BROWSE_SESSIONbecomes the effective session; with neither, it's"default".packages/cli/src/lib/driver/command-cli.ts:75—runDriverCommandFromFlagscallssessionName(flags.session)for every driver command, so this precedence applies uniformly acrossopen,snapshot,click,stop, etc.packages/cli/src/lib/driver/remote.ts:130— exact no-Chrome error string is"No Chrome or Chromium found on this machine. Install one (Linux: apt install chromium · macOS: brew install --cask google-chrome, or Chromium with CHROME_PATH set), attach to a running browser with --cdp <port>, or set BROWSERBASE_API_KEY to use a remote browser."No changeset
This is a skill-text-only change (
SKILL.md), same category as PR #2329 (skill-text-only fix, no changeset). The updated text ships with the nextbrowserelease — a release is already queued by #2335's changeset — and is consumed at runtime by the evals harness added in #2334.E2E Test Matrix
pnpm install && pnpm turbo run build --filter=browse(worktree, local build)Tasks: 4 successful, 4 totalbundledCliSkillPath()from the compileddist/lib/skills/install.jsviarequire.resolve+ manual path join (noskills showcommand exists onmainyet — it ships in PR #2335, unmerged at time of this PR)resolved bundledCliSkillPath: <worktree>/packages/cli/skills/browsebrowse skills installresolves to at runtime is the file this PR edits, not a stale copy.grep -n "already set in the environment|do not retry" packages/cli/skills/browse/SKILL.md76:If \BROWSE_SESSION` is already set in the environment, every command already targets that session...68:...If `--local` fails with "No Chrome or Chromium found"...do not retry `--local`.`node bin/run.js skills install --helpbrowse skills install(no side effects triggered — did not run the real install, which mutates the global~/.agents/skillspool vianpx skills add --global)pnpm test:cli(vitest, worktree build)Test Files 23 passed (23)/Tests 344 passed (344)pnpm eslint .pnpm format:check(prettier)All matched files use Prettier code style!tsc --noEmit -p tsconfig.jsonRelated
🤖 Generated with Claude Code
Summary by cubic
Clarifies the
browseskill docs to prevent session misrouting and container failures by documentingBROWSE_SESSIONprecedence and when to use--remoteinstead of--local. Addresses Linear STG-2513.BROWSE_SESSIONis set, commands target that session; only pass--sessionto override (precedence:--session>BROWSE_SESSION>default).--localrequires Chrome/Chromium; in containers/CI/sandboxes use--remote. If you see "No Chrome or Chromium found," switch to--remoteinstead of retrying--local.Written for commit 829ff7b. Summary will update on new commits.