Skip to content

Stagehand v4 - #2671

Merged
seanmcguire12 merged 135 commits into
mainfrom
v4-spike
Aug 10, 2026
Merged

Stagehand v4#2671
seanmcguire12 merged 135 commits into
mainfrom
v4-spike

Conversation

@miguelg719

@miguelg719 miguelg719 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Stagehand v4

Lots of improvements and changes, to learn more check out the migration guide

What main becomes

A protocol-first monorepo with three SDKs over a shared core:

Package npm/PyPI Published
packages/sdk-ts @browserbasehq/stagehand 4.0.0 npm, latest
packages/sdk-python stagehand 4.0.0 PyPI
packages/sdk-go Go module (proxy tags TBD)
packages/protocol, extension, integrations, evals, docs private

What main stops being

The v3-era tree (core, cli/browse, server-v3) and its 14 workflows. All of it lives on the protected v3 branch (frozen at main's tip, release automation retargeted in #2660 — 3.x publishes under the v3 dist-tag, browse keeps latest). Anything still needed on main (e.g. browse) gets ported in follow-up PRs.

samfinton and others added 30 commits July 23, 2026 23:40
So the `v4-spike` branch that this PR would merge into is the code from
the `v4-spike` repo. On that branch, I have done only two things
*exactly*:
1. Removed all of the existing v3 code, leaving an empty repository.
2. Copied in the v4 spike exactly as it existed in the original spike
repository.

This makes the transition easy to follow. The end goal will be that this
`v4-spike` repo gets merged into `main` on launch. To do that, we now
need to add back in all of the parts of v3 we want, as well as continue
to improve v4, in atomic PRs.

This PR simply restores the top-level files from v3 that we want to keep
directly in v4 (with no changes):

- the license
- CODEOWNERS
- the pull request template
- the bug report and feature request templates
- the Cubic configuration and rules

In this stack of PRs, we'll start adding back in the v3 code we want,
piece by piece.
This copies `packages/docs` directly from v3 at
`2557a797fd685702236d59c1adca02e34fa87f3c` with no changes:

```sh
git restore --source 2557a79 -- packages/docs
```

The source and imported docs trees both have Git tree hash
`604d407510684249325932238c0055adbbf1950d`.
This fixes five links that were already broken in the v3 docs:

- `/configuration/environment` → `/v2/configuration/browser`
- `/integrations/vercel/quickstart` →
`/v2/integrations/vercel/configuration`
- `/best-practices/working-with-iframes` → `/v3/references/deeplocator`
- `/configuration/environment` → `/v3/configuration/browser`
- `/v3/best-practices/working-with-iframes` →
`/v3/references/deeplocator`

The replacements point to existing, version-specific pages. No other
documentation or styling is changed.
This formats the JavaScript and JSON files that came over with the v3
docs.

The MDX files are intentionally left unchanged. The current Oxfmt MDX
formatter changes content inside valid Mintlify code examples, including
identifiers and comment delimiters, so formatting those files would not
be a safe mechanical change.

The docs MDX path is excluded from Oxfmt until it can format these files
without changing their content.
This connects the restored docs to the v4 workspace:

- makes the docs package private and gives it the v4 package version
- uses the repository-pinned Mint CLI
- adds `just docs` for starting the local docs site
- opens the local docs site automatically
- includes docs validation and broken-link checks in `just check` and CI
- checks documentation images and videos for alt text
- documents the local development and validation commands
- updates the workspace lockfile

The original Stagehand green is unchanged. It does not meet Mint’s
light-background contrast threshold, so the docs check uses `mint a11y
--skip-contrast`. All other accessibility checks remain enabled.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Restores Stagehand docs (v2 and v3) and integrates them with the v4
workspace. Re-enables local docs dev and wires strict docs validation
into the root check used by CI.

- **New Features**
- `just docs` runs a repo-pinned `mint` dev server; no global
`mint`/`mintlify` needed.
- Root `pnpm check` runs the docs `check` (mint validate, broken links
with anchors/redirects/snippets, and `mint a11y` with contrast skipped).
  - Docs README covers local dev, validation, and publishing.

- **Dependencies**
- Migrates from `mintlify` to `mint` via the workspace catalog; bumps to
`mint@4.2.742`.
- Sets `@browserbasehq/stagehand-docs` to `4.0.0` and private; adds Mint
packages to `minimumReleaseAgeExclude`; updates the lockfile.

<sup>Written for commit 1ef3793.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2425?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. -->
The v4 spike used temporary package names and versions. This PR
establishes the package identities and version numbers we want to carry
into production.

The public TypeScript and Python SDKs both start at `4.0.0`. The new
protocol package starts at `1.0.0`, and its major version is used for
the compatibility handshake between the SDK and extension. The docs,
protocol, server, and Python version-tracking package remain private.

This PR also adds the small `.env.example` required by v4 and makes
package metadata the source of truth for runtime version reporting.

There is no publishing automation in this PR. It only establishes the
package names, versions, and metadata that the release flow in the next
PR will use.
Now that the v4 package names and versions are established, this PR adds
the stable release flow for the TypeScript and Python SDKs.

- `just changeset` records the release intent for a pull request.
- `just _version` is used by CI to apply those changes, keep the Python
version in sync, and update the root changelog.
- Changesets maintains the release pull request on `main`.
- Merging that release pull request publishes the TypeScript SDK to npm
and the Python SDK to PyPI.

The private protocol package is also versioned through Changesets
because its major version is the compatibility contract between the SDK
and extension, but it is not published to npm.

We keep one root `CHANGELOG.md` for the repository, beginning with the
existing v3 history. The release workflows only run from `main`, so this
stack cannot publish anything.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds stable v4 release automation for the TypeScript and Python SDKs. On
pushes to `main`, we open a release PR or publish TS to npm, and publish
Python to PyPI only when a new version is needed (skips if pending
Changesets exist).

- **New Features**
- Adopted `changesets` for `@browserbasehq/stagehand`,
`@browserbasehq/stagehand-python`, and versioned private
`@browserbasehq/stagehand-protocol` (not published).
- Release workflow on `main`: runs `just check`/`just build`, opens a
release PR via `changesets/action`, publishes TS via `just
_publish-typescript`, then uses a status check to publish Python only if
PyPI is missing the version and no Changesets are pending.
- Reusable Python workflow: builds wheels/sdists, smoke-tests with `uv`,
uses trusted publishing, and tags `stagehand-python@<version>`.
- Consolidated SDK changelogs into the root `CHANGELOG.md` with
SDK-labeled headings; package changelogs are temporary and removed in
CI.
- Added release scripts and `just` tasks to validate Changesets (allowed
packages only), consolidate changelogs, sync Python version from the
proxy `package.json`, verify `uv.lock`, gate Python publishing on PyPI
status, and clean stale `dist/` artifacts (including legacy names).
  - Documented the release flow and contributor steps in `README.md`.

- **Migration**
- When a PR changes a public SDK or the protocol contract, run `just
changeset`. Internal-only changes don’t need one.
- Merge the release PR on `main` to publish TypeScript; Python
auto-publishes if the synchronized version is not on PyPI. Release jobs
run only on `main`.

<sup>Written for commit 7fe4b8e.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2409?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. -->
The v2 and v3 docs are now restored and integrated into the v4
workspace. This PR brings back the v4 docs saved on the
[`preserve-docs`](https://github.com/browserbase/v4-spike/tree/preserve-docs/packages/docs)
branch of the original v4-spike repository.

It:

- copies the preserved v4 pages into `/v4`
- keeps the native TypeScript and Python `View` components
- adds v4 to the version selector and makes it the default
- leaves the existing v2 and v3 navigation unchanged
- updates internal links and redirects for the versioned routes
- restores the v4 SDK-reference conformance tests

The copied page content has only two mechanical changes: internal links
are prefixed with `/v4`, and numeric `CardGroup` attributes use quoted
values for compatibility with the current Mint markdown conversion.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Restores the Stagehand v4 docs and makes v4 the default docs version.
Adds `@mdx-js/mdx` for MDX parsing in tests, re-enables docs tests, and
fixes the Quickstart example.

- **New Features**
- Added v4 docs: First Steps, Basics, Configuration, SDK reference, and
the v4 index.
- Updated navigation (`docs.json`) to include v4 and make it default;
README now lists v2, v3, and v4 with v4 as default.
- Added SDK reference conformance tests and re-enabled docs tests in
`vitest.config.ts`.

- **Bug Fixes**
- Corrected the v4 Quickstart script (model config and env variable
examples).
- Resolved merge conflicts and aligned `README.md`, `docs.json`, and
`pnpm-lock.yaml`.

<sup>Written for commit 6f98ff6.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2428?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. -->
Removes `packages/protocol/pending-schemas.ts` by moving the definitions
that are still used into the canonical schema file and removing
definitions that are redundant with the v4 protocol or have no v4
runtime consumer. This does not change any current v4 functionality.

- **Move the eight schemas still used by v4 into `schemas.ts`.**
`ApiKeyAuthSchema`, `ThinkingEffortSchema`,
`LocalBrowserLaunchOptionsSchema`, `ModelAuthSchema`,
`ModelProviderOptionsSchema`, `LLMToolSchema`,
`ClientOptionsBaseSchema`, and `ClientOptionsSchema` retain the same
shapes while moving to the canonical schema source.

- **Remove redundant provider-specific client schemas.** Schemas such as
`OpenAIClientOptionsSchema` and `VertexClientOptionsSchema` were unused
specializations of the active client, authentication, and
provider-option schemas.

- **Remove v3-only extract and history schemas.**
`defaultExtractSchema`, `pageTextSchema`, and `HistoryEntrySchema`
supported v3 conveniences that v4 does not expose; v4 extraction already
requires an explicit schema.

- **Remove obsolete clipboard option schemas.** `ClipboardOptionsSchema`
and `ClipboardPasteOptionsSchema` duplicate targeting already
represented by the v4 context clipboard protocol and SDK-owned page
options.

- **Remove v3 REST session schemas.** Schemas such as
`SessionStartRequestSchema`, `SessionEndResponseSchema`, and
`ErrorResponseSchema` are superseded by the registered v4 JSON-RPC
lifecycle and error schemas.

- **Remove duplicate operation request and response schemas.** Schemas
such as `ActRequestSchema`, `ExtractRequestSchema`,
`ObserveResponseSchema`, and `NavigateRequestSchema` are redundant with
the registered Stagehand and page method schemas.

- **Remove legacy replay schemas.** `ReplayActionSchema`,
`ReplayResponseSchema`, and `TokenUsageSchema` described the
unimplemented v3 replay endpoint and have no v4 consumer. Token usage
will be added back in a future PR.

- **Remove legacy SSE schemas.** Schemas such as `StreamEventSchema` and
`StreamEventLogDataSchema` describe the v3 SSE response format; v4
transports logs and events through JSON-RPC.

- **Update protocol types and consumers.** SDK and server imports now
reference `schemas.ts` directly, leaving a single canonical schema
source.
## Summary

- update the V4 Python landing-page install command from `stagehand-v4`
to `stagehand`
- update the Python AI-rules prompt to use the published `stagehand`
distribution name
- remove the obsolete `v4` suffix from the Browserbase smoke-test
session label

## Why

PR #2400 renamed the V4 Python distribution to `stagehand`, but two
restored docs references still used the temporary `stagehand-v4` name
after PR #2428 merged. A repository-wide audit found no other hyphenated
`stagehand-v4` references after this change. The remaining
`stagehand_v4` strings in the Python build helper and its test are
intentionally retained so old pre-rename artifacts are cleaned from
`dist/`.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Replace remaining `stagehand-v4` references with `stagehand` in V4 docs
and Browserbase smoke test metadata. This fixes the Python install
command, aligns the AI-rules prompt with the published package name, and
removes the obsolete `-v4` suffix from the test label.

<sup>Written for commit d0afe9e.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2456?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. -->
The v4 packages stay at their stable versions until launch. This PR adds
an opt-in preview flow so we can test work without publishing a release
or changing committed package versions.

Add the `preview` label to a pull request to build:

- the TypeScript SDK tarball
- the Python SDK wheel
- the extension ZIP
- a manifest containing their versions, filenames, and checksums

These files are stored together as one GitHub Actions artifact. The
workflow leaves one comment with the download link and local install
commands. New commits replace the artifact while the label remains;
removing the label or closing the pull request removes both the artifact
and the comment.

Preview versions are created only inside a temporary checkout. They do
not add Changesets, update changelogs, create GitHub releases or tags,
publish stable packages, or deploy a Browserbase environment.
This PR copies `packages/evals` from v3 and gets it running in the v4
workspace without changing it to evaluate v4 yet.

The history deliberately shows the migration in small steps:

- Copy `packages/evals` exactly from v3 at commit `2557a797`.
- Run the v4 formatter over the restored files.
- Connect evals to the new workspace and install the published v3 SDK
under the `stagehand-v3` alias.
- Apply the small workspace-only lint and dependency-policy
configuration needed by the restored package.

This means the restored evals still run against Stagehand v3. Moving
them to Stagehand v4 will happen separately, so that change remains easy
to review.

The old eval-specific changelog is removed so the repository continues
to have one root `CHANGELOG.md`.
# why
- when new tabs were opened via a popup, `chromeTabs.activeTargetId()`
was pointing to the correct target ID, but stagehand didn't have time to
register that target in its registry
- this caused lookup to fail, and `activePage()` to return undefined
# what changed
- added polling with a max of 3 seconds inside `activePage()`
# test plan
- added tests for delayed page registration

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes a race where popups activated by user gesture were not returned by
activePage(). The method now polls for up to 3s for Chrome’s active
target to be registered and throws a clear timeout if it never is.

- **Bug Fixes**
- V3Context.activePage() polls until the active target’s Page is
registered; returns undefined when Chrome has no active target; throws a
TimeoutError after 3s if never registered.
- Added tests for delayed registration, no-active-target, and timeout;
updated the SDK smoke test to use context.activePage() and removed the
custom waitForNewPage helper.

<sup>Written for commit 7361091.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2458?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. -->
## Summary

- require every object schema in `packages/protocol/schemas.ts` to use
`z.strictObject`
- reserve dynamic data for explicit `z.json()` and `z.record()` fields
- move act, extract, and observe option optionality to their containing
RPC parameter schemas
- remove client-schema `.unwrap()` calls
- regenerate the JSON Schema and Python models so unknown fields are
forbidden
- update runtime, locator, and LLM tests for strict object parsing

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Make all protocol and SDK schemas strict. Unknown fields now error
across the wire and in both SDKs, reducing typos and hidden bugs.

- **Refactors**
- Switched all protocol object schemas to `z.strictObject()`; removed
`.strict()`, `.loose()`, `.passthrough()`, and `.catchall()`.
- JSON Schema: strict objects use `additionalProperties: false` (e.g.,
LLM results, Browserbase configs, proxy configs).
- LLM results are strict; extra fields (e.g., `providerMetadata`) are
rejected. Tests updated.
- `RuntimeDescriptorSchema` and `PageLocatorSchema` are strict; unknown
fields and stale locator handles now error.
- Params: `options` are optional at call sites (act/observe/extract,
page methods); typos in options fail tests.
- TS SDK: aligned with strict protocol types; `CdpBrowserSourceSchema`
uses `z.strictObject`; client options extend protocol options.
- Python SDK: generated models use `extra="forbid"` (including LLM
results) to disallow unknown fields.
- Added `rules/ast-grep/protocol-schema-strictness.test.ts` to enforce
`z.strictObject` in protocol schemas.
- Restored v3 eval tooling under `packages/evals` (CLI, datasets, core
tools); targets `stagehand-v3` and is wired into workspace checks
without changing v4 runtime.
- Added opt‑in PR previews: `preview` label builds the TS package
tarball, Python wheel, and extension ZIP as one artifact (no version
bumps or releases). README and `just _preview` added; `oxlint` override
allows console in `packages/evals`; repo `check` compiles
`packages/evals`.
- Docs: replaced `stagehand-v4` with `stagehand` in v4 install and
AI‑rules examples.

- **Migration**
- Remove any extra/typo keys in request bodies and options; only
documented fields are allowed.
- Do not include stale locator handles (`page`, `frame`, `element`) in
`PageLocator`.
- LLM generate results must only include defined fields; extra metadata
is rejected.
- Runtime descriptors must only include documented fields
(`protocolVersion`, `serverInfo`, `status`).

<sup>Written for commit dbea4f1.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2434?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. -->
Adds generated Go structs, enums, and union types for the Stagehand
protocol.
Adds the hand-written Go SDK client on top of the generated protocol
models.

- Reuses generated structs at JSON-RPC boundaries.
- Adds the public `Stagehand`, context, page, locator, and clipboard
APIs.
- Adds JSON-RPC and CDP transports.
- Adds matching examples and extends the SDK parity checks to Go.

Browser startup remains stubbed until the next PRs in this stack.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
Local Chrome needs the Stagehand extension unpacked on disk, while
Browserbase needs the same extension as a ZIP. This bundles one
canonical extension archive into the Go module and safely extracts it
when needed.

- Adds deterministic extension packaging and drift checks.
- Adds a hand-written Chrome launcher for macOS, Linux, and Windows.
- Matches the shared Chrome flag and browser-option behavior.
- Cleans up owned Chrome processes, profiles, and extracted extension
files.

The next PR wires this into the public client alongside Browserbase.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
Finishes the Go client by wiring all three browser sources through
`Stagehand.Init`:

- Local Chrome launches through the Go launcher and loads the bundled
extension.
- Existing CDP connections preserve caller ownership and support custom
headers.
- Browserbase uses a typed `net/http` client for extension upload,
session creation, release, and cleanup.

The Browserbase client validates typed request and response structs
through one shared request path, following the same pattern as Zod plus
`fetch` in TypeScript. The public local, CDP, and Browserbase lifecycles
are covered by real browser tests.

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>
## Summary

This PR removes some unnecessary objects and simplifies them to just
their values - where it makes sense to and we won't need to extend them
later.

Previously, the TypeScript SDK received an object from the protocol and
unwrapped its single field:

```ts
async count(): Promise<number> {
  const result = await this.rpcClient.send(
    StagehandMethods.locatorCount,
    this.descriptor,
  );
  return result.count; // unwrapped here
}
```
Now the protocol returns the value directly, so the SDK can return it
without unwrapping:
```ts
async count(): Promise<number> {
  return await this.rpcClient.send(
    StagehandMethods.locatorCount,
    this.descriptor,
  );
}
```
The user facing SDKs remain the identical before and after:

```ts
const count = await locator.count(); // number
const url = await page.url(); // string
const cookies = await context.cookies(); // Cookie[]
```



| Method and protocol result change | Why the object is unnecessary |
|---|---|
| `page.url`: `{ url: string }` → `string`<br>`page.title`: `{ title:
string }` → `string` | Each method explicitly names the scalar being
retrieved. Navigation details and other page metadata belong in separate
APIs. |
| `locator.count`: `{ count: number }` → `number` | Count is the
complete result. Match details or grouping would be a separate query. |
| `locator.is_checked`: `{ checked: boolean }` →
`boolean`<br>`locator.is_visible`: `{ visible: boolean }` → `boolean` |
Predicate methods naturally return booleans. Additional element states
or diagnostics should be separate queries. |
| `locator.input_value`: `{ value: string }` →
`string`<br>`locator.inner_text`: `{ text: string }` →
`string`<br>`locator.inner_html`: `{ html: string }` →
`string`<br>`locator.text_content`: `{ textContent: string }` → `string`
| Each method names the exact DOM scalar being retrieved. Element
metadata and diagnostics are separate concerns. |
| `locator.select_option`: `{ values: string[] }` → `string[]` | The
successfully selected values are the meaningful operation result. Target
evidence or event diagnostics would be separate instrumentation. |
| `context.clipboard_read_text`: `{ text: string }` → `string` |
`readText` is deliberately text-specific. Rich clipboard data would
require a broader clipboard method. |
| `context.cookies`: `{ cookies: Cookie[] }` → `Cookie[]` | A complete
cookie collection is the conventional result. New cookie attributes
belong on `Cookie`; pagination is not currently needed. |
| `context.get_domain_policy`: `{ policy: DomainPolicy \| null }` →
`DomainPolicy \| null` | Policy fields naturally belong inside
`DomainPolicy`. Configured and effective policies could be separate APIs
if that distinction is needed. |

`page.wait_for_selector` is intentionally unchanged because its result
semantics need a separate decision. Coordinate operation results also
remain structured objects.
There were duplicate act schemas so we were missing the ability to pass
in action inputs to `act()`.
In [Shriya’s v4 eval
PR](#2387), 27 out of 359
Act eval rows were failing for exactly this missing functionality:
```
throw new Error(
  "V4 GAP: v4 has no act(observeResult) self-healing replay...
 ```
Before this fix, Stagehand v3 scored 93.89% on Act (338/360), while v4 scored 78.83% (283/359). Naively assuming all 27 affected rows pass once the fix is merged and the evals are re-enabled, v4 would reach 86.35% (310/359)—an improvement of 7.52 percentage points.


This restores `string | Action` directly on the canonical `StagehandActParamsSchema` across the protocol, TypeScript SDK, Python SDK, and server. 

The unused legacy `ActRequestSchema` and its paired response/types are removed, leaving one live Act request contract and one reusable `ActionSchema`.


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Restores passing an `Action` from `observe` to `act` in v4 for deterministic replay and self-healing. Unifies Act input on `StagehandActParamsSchema` and makes protocol result schemas strict.

- **New Features**
  - `StagehandActParamsSchema.input` now accepts `string | Action` across the protocol (`stagehand.v4.json`), server, `sdk-ts`, `sdk-python`, and `sdk-go`.
  - Server: passing an `Action` skips the first LLM call and runs the deterministic executor with variable substitution and self-healing.
  - SDKs: `sdk-ts` adds an `act` overload for `Action` and exports `Action`/`ActResultData`; `sdk-python` `act` accepts `str | Action`; `sdk-go` adds an `ActInput` union with `ActInstruction`/`ObservedAction`.

- **Refactors**
  - Removed legacy `ActRequestSchema`/`ActResponseSchema`; one Act request contract plus a reusable `ActionSchema`.
  - Protocol result schemas now use strict objects (no extra fields).

<sup>Written for commit e3e7e18. Summary will update on new commits.</sup>

<a href="https://cubic.dev/pr/browserbase/stagehand/pull/2427?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. -->
## Summary

- tag Browserbase sessions created by the Go SDK with authoritative
`stagehand` and `stagehand_sdk_language` user metadata, mirroring the
TypeScript SDK
- preserve caller-provided session metadata while preventing the
attribution fields from being spoofed
- add a unit test that captures the outgoing session-create request and
asserts spoofed attribution keys are overridden, plus update the
existing typed-request round-trip test

## Why

Stagehand v3 identifies its SDK language with the `x-language` request
header. V4 no longer routes SDK work through the hosted Stagehand API,
so Browserbase session metadata is the durable, queryable equivalent for
cloud sessions. #2467 added this for the TypeScript and Python SDKs. The
Go SDK has since landed on `v4-spike`, so this PR completes the
follow-up for Go.

## E2E Test Matrix

| Command / flow | Observed output | Confidence / sufficiency |
| --- | --- | --- |
| Build the current server extension, then run the Go generator check
and embedded-extension check | Both freshness checks passed after
rebasing onto the current `v4-spike`. | Confirms the PR no longer
inherits the generated-model or embedded-extension drift that previously
failed CI. |
| Go CI path: gofmt, vet, example compilation, package tests with local
Chrome, generator tests, and build | All commands passed; the Stagehand
package and extension packages passed their test suites. | Covers the
complete Go CI path against the rebased branch. |
| `go test -race -run
'TestStagehandSessionMetadata|TestBrowserbaseSessionClientCreateUsesTypedEndpoint'
.` | Passed under the race detector. | Directly exercises authoritative
attribution, caller-map immutability, and the typed Browserbase request
path. |
| `BROWSERBASE_SMOKE=1 go test -run TestStagehandBrowserbaseIntegration`
→ create a real Browserbase session through the Go SDK → retrieve it
through the Browserbase API | Retrieved
`{"stagehand":"true","stagehand_sdk_language":"go","suite":"stagehand-v4-go-public-smoke"}`;
the session was released. | Proves the exact Go attribution behavior is
durable and queryable on a live Browserbase session. |

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
## Summary

- require `protocolVersion` and `clientInfo` in `runtime.configure`
- regenerate the Python and Go protocol models from the stricter schema
- ensure TypeScript, Python, and Go always send protocol compatibility
and client identity
- add wire-level and cross-SDK parity coverage

## Validation

- `just check`
- `just test`
Renames the internal `V3Context` implementation to `BrowserContext`
across the service worker, tests, and documentation. This is a
naming-only change with no behavior changes.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Renamed the browser context class from `V3Context` to `BrowserContext`
across server code and tests. Restored legacy V3 docs and merged latest
`v4-spike`; fulfills Linear STG-2647 with no behavior changes.

- **Refactors**
- Renamed class and factory in `packages/server/understudy/context.ts`
to `BrowserContext`.
  - Updated service worker to call `BrowserContext.create`.
  - Adjusted clipboard types to accept `BrowserContext`.
- Updated tests, mocks, and titles, including the smoke graph in
`rpc-client-smoke.test.ts`.

<sup>Written for commit bbce9b7.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2500?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. -->
Removes `ping`, `runtimeLoopbackStatus`, and `browserGetVersion` from
the protocol and all SDK surfaces. It also removes the extension and
runtime handlers and refreshes generated clients and documentation.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Removed internal diagnostic methods (`ping`, `runtime.loopback_status`,
and `browser.get_version`) from the v4 protocol and all SDKs to align
the public surface with Linear STG-2708. Docs, generated clients, and
tests were updated; metrics remain available.

- **Refactors**
- Protocol/Server: Removed methods and schemas from `stagehand.v4.json`
and the registry; deleted related controllers/handlers (including
`browserController`) and router routes; tightened the request schema;
dropped runtime helpers that exposed these diagnostics.
- SDKs (TS, Python, Go): Removed corresponding APIs and types;
regenerated models/clients; updated tests to use non-diagnostic calls
(e.g., `context.pages` or stubbed `test.request`) and adjusted
notification/log checks.
- Docs: Removed diagnostics from the `stagehand` reference and
first-steps intro; clarified that only metrics are built in.

- **Migration**
- Remove any usage of `stagehand.ping()`,
`stagehand.runtimeLoopbackStatus()`, and `stagehand.browserGetVersion()`
(and equivalents in Python/Go).
- For connectivity, await `stagehand.init()` and handle errors. For
browser version, query CDP `Browser.getVersion` via your own connection.
`stagehand.metrics()` is unchanged.

<sup>Written for commit fb4fdea.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2501?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. -->
akeimach and others added 6 commits August 9, 2026 18:46
# why

Standardizing the example snippets with `.data` wrapping

# what changed

# test plan


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Standardized all v4 examples to read and print from `.data` instead of
the full response, ensuring consistent payload handling across Go,
Python, and TypeScript. Addresses Linear STG-2796.

- **Refactors**
- Go (`packages/sdk-go/examples`): use `result.Data` in prints/checks
for `act`, `observe`, and aggregated outputs; adopt
`extractResult/observeResult/actResult` names.
- Python (`packages/sdk-python/examples`): use `result.data` for
`model_dump` and validations; rename to
`extract_result/observe_result/act_result`; update `custom_llm`,
`custom_logging`, `extract`, `model_gateway`, `observe`.
- TypeScript (`packages/sdk-ts/examples`): log `result.data` and
validate on `.data`; rename to `extractResult/observeResult/actResult`;
update `act`, `observe`, `extract`, `modelGateway`, `customLlm`,
`customLogging`.

<sup>Written for commit 55e390b.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2646?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: Miguel <36487034+miguelg719@users.noreply.github.com>
# why
- observe & extract previously accepted selector strings instead of
`locator`'s. for consistency across our APIs, this PR changes them to
accept `locator`'s

# what changed
- replaced `selector` / `ignoreSelectors` observe and extract protocol
options with locator descriptor fields
- migrated extension snapshot, observe, and extract internals to use
locator descriptors, including `nth`
- bypasses the current server-side cache for locator-scoped
observe/extract calls to avoid sending locator descriptors through the
selector-shaped cache contract
- updated TypeScript, Python, and Go SDK public APIs to accept
page-bound locator wrapper objects instead of protocol shaped locator
schemas
- added validation for checking that supplied locators belong to the
resolved target page before sending RPC requests
- serializes observe/extract locator options in TS batch callbacks after
resolving the operation page
- updates v4 docs and examples to show `page.locator(...)` /
`page.Locator(...)` scoping
- also updates evals to use locator-based extract scoping

returned selectors remain plain output data. `Action.selector` and
snapshot selector maps are not wrapped as live locators by this PR

## SDK shapes
TypeScript:
```ts
await stagehand.extract("Extract text", Schema, {
  page,
  locator: page.locator("main"),
  ignoreLocators: [page.locator("nav"), page.locator(".ad").nth(2)],
});
```

Python:
```py
await stagehand.extract(
    "Extract text",
    Schema,
    page=page,
    locator=page.locator("main"),
    ignore_locators=[page.locator("nav")],
)
```

Go:
```go
result, err := stagehand.Extract[resultType](
	ctx,
	client,
	"Extract text",
	&stagehand.StagehandClientExtractOptions{
		Page:    page,
		Locator: page.Locator("main"),
		IgnoreLocators: []*stagehand.PageLocator{
			page.Locator("nav"),
		},
	},
)
```

### behaviour notes:
- `page` remains optional. If omitted, Stagehand resolves the active
page and validates locators against that page
- Locator descriptors include `selector` and optional `nth` internally
- Locator-scoped observe/extract calls bypass the current server-side
cache; unscoped calls keep existing cache behavior
- Ignored locators exclude matched nodes and descendants from the
snapshot context
- `observe` results and `act(Action)` inputs still use selector strings
as action data

# test plan
- added protocol tests to cover the new observe/extract wire shape for
`locator` & `ignoreLocators`
- extension tests cover locator-scoped observe/extract snapshots,
ignored locator subtrees, cache bypass behavior, & `nth` handling
- TS SDK tests cover public `Locator` wrapper inputs, descriptor
serialization, & cross-page validation
- Python SDK tests cover public `Locator` wrapper inputs, descriptor
serialization, and cross-page validation
- Go SDK tests cover handwritten observe/extract client options,
`*PageLocator` conversion, cross-page validation, and generated model
compatibility for the SDK/internal packages
- also updated docs tests



<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Switch observe, extract, and act to accept page-bound locator inputs
instead of selector strings, standardizing scoping, enabling precise nth
targeting, and letting you exclude subtrees. Locator-scoped calls bypass
server caching; SDKs validate that locators belong to the target page.

- New Features
- Added `locator` and `ignoreLocators` to act/observe/extract; all
support `.nth` for disambiguation. `text=` locators are not yet
supported for snapshot scoping.
- TypeScript, Python, and Go SDKs accept page-bound Locator objects for
all three methods and enforce same-page validation; TS batch callbacks
serialize locators after resolving the operation page.
- Extension snapshotting and a11y scoping use locator descriptors
(`focusLocator`/`ignoreLocators`) and honor `.nth`; added targeted
tests.
- Caching: locator-scoped act/observe/extract bypass server cache
reads/writes; cache inputs omit locator descriptors; responses show
`metadata.cache.status` as `DISABLED`.
- Protocol schemas: `ActOptions` adds `ignore_locators`; observe/extract
now use `locator`/`ignore_locators`.
- Docs and evals updated to use `page.locator("...")` and `xpath=...`;
evals Vitest config updated. Go SDK: flattened per-call fields for Act
options and fixed nil `IgnoreLocators` handling.

- Migration
- Replace `selector` with `locator: page.locator("...")` and
`ignoreSelectors` with `ignoreLocators: [page.locator("..."), ...]` in
observe/extract.
- Use `.nth(index)` to target a specific match; include `xpath=` when
using XPath locators.
- Go SDK: move per-call fields to top-level of
`StagehandClientActOptions` (and already for Observe/Extract), e.g., use
`Cache`, `Timeout`, `Model`, `Locator`, `IgnoreLocators`, `Variables`
directly.
- Returned selectors in results remain strings; no change to action
inputs/outputs.

<sup>Written for commit 85138cd.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2654?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. -->
# why
- for consistency with TS/Python screenshot masks, Go should accept
page-bound locator wrappers instead of generated locator descriptor
schemas

# what changed
- adds a handwritten Go `ScreenshotOptions` type for `Page.Screenshot`
- changes `ScreenshotOptions.Mask` to accept `[]*PageLocator`
- converts mask locators to generated `LocatorDescriptor` values before
sending the `page.screenshot` RPC
- validates that mask locators belong to the screenshot target page
before sending the request
- preserves existing screenshot options like animations, caret, clip,
full page, mask color, omit background, quality, scale, style, timeout,
and type

## SDK Shape

Go:

```go
png, err := page.Screenshot(ctx, &stagehand.ScreenshotOptions{
	FullPage: &fullPage,
	Mask: []*stagehand.PageLocator{
		page.Locator(".secret"),
	},
	MaskColor: &maskColor,
})
```

## behavioural notes:
- `Page.Screenshot` still returns decoded screenshot bytes
- `nil` screenshot options still send no protocol options
- mask locators serialize to generated `LocatorDescriptor` values
internally, including `pageId`, `selector`, and optional `nth`
- mask locators from another page are rejected before RPC
- non-mask screenshot options continue to pass through unchanged
- TS/Python screenshot behavior and protocol schemas are unchanged

# test plan
- Go SDK tests cover handwritten `ScreenshotOptions` conversion to
generated protocol options
- Go SDK tests cover `*PageLocator` mask serialization, including `nth`
- Go SDK tests cover cross-page mask locator rejection before RPC
- Go SDK tests cover preservation of existing non-mask screenshot
options


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Go SDK: Page.Screenshot now accepts page-bound locator masks with strict
validation while keeping screenshot behavior unchanged. This also moves
act/observe/extract to locator-based scoping across SDKs, updates
snapshotting, and standardizes examples to read result data via `.data`.

- **New Features**
- `Page.Screenshot` `Mask` accepts `[]*PageLocator`; nil and cross-page
locators are rejected; converts to protocol descriptors before RPC.
- `act`/`observe`/`extract` accept `locator` and `ignoreLocators` (with
`.nth`), validate same-page locators, and serialize in TS batch
callbacks.
- Snapshot capture uses `focusLocator`/`ignoreLocators`; locator-scoped
calls bypass server cache (responses show cache status `DISABLED`).

- **Migration**
- Go: replace `*PageScreenshotOptions` with `*ScreenshotOptions`; pass
`page.Locator("...")` in `Mask`.
- Replace `selector`/`ignoreSelectors` with `locator`/`ignoreLocators`
for `act`/`observe`/`extract` in TS/Python/Go; use `.nth(index)` when
needed.
  - Examples now access `result.data` instead of the full response.

<sup>Written for commit 0baf98c.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2656?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. -->
# why

* Reduces docs nesting (e.g. don't have code snippet inside warning)
* Removes `.` from sub-headers for consistency
* Removes the language tabs when the snippet is language-agnostic bash

# what changed

# test plan


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Flattens Stagehand v4 docs to reduce nested notes and unify code
examples for clearer, more consistent rendering. Fixes chopped code
blocks in nested notes and removes language tabs for `bash` snippets
(STG-2804).

- Refactors
- Un-nested code blocks from notes/warnings to fix nested-note rendering
(STG-2804).
  - Removed language tabs where snippets are language-agnostic `bash`.
- Standardized subheaders by removing trailing periods; aligned titles
(e.g., “User data”, “Observe use cases”).
- Collapsed duplicate CLI/env examples across languages into a single
`bash` block.
- Reworked logging docs: clarified destinations, split external
platforms into Sentry and DataDog with setup steps, and added examples
for passing a production logger via `logging.onLog`.

<sup>Written for commit 10dc1b5.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2668?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. -->
…4-spike

chore: reconcile main into v4-spike ahead of the squash-merge
@miguelg719
miguelg719 requested a review from a team as a code owner August 10, 2026 03:34
@changeset-bot

changeset-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: d7556e9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@socket-security

socket-security Bot commented Aug 10, 2026

Copy link
Copy Markdown

@socket-security

socket-security Bot commented Aug 10, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @browserbasehq/stagehand is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/browse@0.9.5npm/@browserbasehq/stagehand@3.6.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@browserbasehq/stagehand@3.6.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm @browserbasehq/stagehand is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: packages/evals/package.jsonnpm/@browserbasehq/stagehand@3.7.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@browserbasehq/stagehand@3.7.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm @emnapi/runtime is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/vitest@4.1.9npm/tsdown@0.22.3npm/vite@8.1.3npm/mint@4.2.788npm/sharp@0.34.5npm/@emnapi/runtime@1.11.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@emnapi/runtime@1.11.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/cli under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/cli@4.0.1391

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/cli@4.0.1391. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/common under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/common@1.0.1080

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/common@1.0.1080. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/link-rot under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/link-rot@3.0.1278

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/link-rot@3.0.1278. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/models under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/models@0.0.347

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/models@0.0.347. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/prebuild under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/prebuild@1.0.1231

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/prebuild@1.0.1231. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/previewing under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/previewing@4.0.1302

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/previewing@4.0.1302. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/scraping under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/scraping@4.0.947

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/scraping@4.0.947. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm @mintlify/validation under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

From: pnpm-lock.yamlnpm/mint@4.2.788npm/@mintlify/validation@0.1.823

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@mintlify/validation@0.1.823. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm @protobufjs/float is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/browse@0.9.5npm/@browserbasehq/stagehand@3.7.1npm/@protobufjs/float@1.0.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@protobufjs/float@1.0.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm mint under Elastic-2.0

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (npm metadata)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/package.json)

License: Elastic-2.0 - The applicable license policy does not permit this license (5) (package/LICENSE)

From: packages/docs/package.jsonnpm/mint@4.2.788

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/mint@4.2.788. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm oxfmt is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package.jsonnpm/oxfmt@0.57.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/oxfmt@0.57.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm oxfmt is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package.jsonnpm/oxfmt@0.57.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/oxfmt@0.57.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm yargs is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/mint@4.2.788npm/yargs@17.7.3

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/yargs@17.7.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Adds a readonly `sessionId` to `StagehandBrowser` for Browserbase-backed
handles (`browserbase.launch` / `browserbase.connect`); undefined for
local browsers. The id was already threaded internally through the
worker init metadata — this only surfaces it.

**Why:** integration examples that persist sessions for
reconnect-after-restart (Eve native tools in #2666, managed deep agents
in #2653) currently have to recover the id out-of-band — stamping a
`userMetadata` marker at launch and querying `sessions.list` — because
the handle doesn't expose it. With this, that workaround collapses to
`browser.sessionId`.

**Scope:** two files (`browser/index.ts`, `browser/factories.ts`) +
changeset. No behavior change; purely additive surface. Gate: build,
typecheck, 186/186 unit tests.

**Port parity:** TS is the contract — Python/Go should mirror
(`session_id` on the Python browser handle) in follow-ups; the Python
managed-deepagents example has the same workaround to delete.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Added a readonly `sessionId` to `StagehandBrowser` handles for
Browserbase-backed browsers (`browserbase.launch` /
`browserbase.connect`). It’s undefined for local browsers and makes
reconnect-after-restart flows simpler.

- **New Features**
- Access the Browserbase session id via `browser.sessionId`; avoids
metadata markers + `sessions.list`.
  - Purely additive API; no behavior changes.

<sup>Written for commit 33bb054.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2672?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. -->
…2673)

Python port of #2672 (TS is the contract; this mirrors it exactly):
readonly `session_id` property on `StagehandBrowser`, populated from the
worker init metadata for Browserbase launch/connect, `None` for local
browsers.

Kills the out-of-band session-id recovery in the managed deep-agents
example (#2653), same as #2672 does for the Eve example (#2666).

Gate: ruff format/check, ty check, 457 passed / 1 skipped.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Add a read-only session_id property to StagehandBrowser in `sdk-python`,
populated from worker init metadata for Browserbase and None for local.
This lets clients persist the Browserbase session ID for reconnects
without out-of-band recovery.

<sup>Written for commit dad895e.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2673?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. -->
Go port of #2672 (TS contract) alongside the Python port #2673: nil-safe
`SessionID()` accessor on `Browser`, sourced from the worker session
metadata the handle already carries; empty string for local browsers.

Gate: gofmt clean, go vet clean, package tests pass (examples build
failure in `go test ./...` is pre-existing on v4-spike;
`scripts/check-examples.sh` passes).

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Added a nil-safe `SessionID()` method to the Go SDK `Browser` to get the
Browserbase session ID. It returns an empty string for local browsers or
when the handle is nil.

<sup>Written for commit 72f3cb2.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2674?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. -->

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/sdk-ts/src/browser/index.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed against the latest diff

Not reviewed (too large): packages/protocol/stagehand.v4.json (~7,460 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Note: This PR contains a large number of files. cubic only reviews up to 200 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.

Re-trigger cubic

Comment thread packages/docs/v4/best-practices/user-data.mdx
Comment thread packages/evals/tasks/bench/extract/extract_public_notices.ts
Comment thread packages/evals/framework/defineTask.ts
Comment thread packages/evals/framework/observationRecorder.ts
Comment thread packages/evals/tasks/bench/act/nonsense_action.ts
Comment thread packages/extension/logger.ts
Comment thread packages/evals/framework/agentToolRuntime.ts
Comment thread packages/extension/handlers/handlerUtils/timeoutGuard.ts
Comment thread packages/evals/tasks/bench/act/no_js_click.ts
Comment thread packages/evals/tasks/bench/act/os_dropdown.ts
# why
- for security
# what changed
- bumped mintlify to newer version with less transitive dep vulns



<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Upgrade Mintlify tooling to reduce transitive vulnerabilities and align
with the latest peer dependencies. Updates `mint` to 4.2.788 and
refreshes related `@mintlify/*` packages; no app code changes.

- **Dependencies**
  - Bumped `mint` to `4.2.788`.
- Updated `@mintlify/cli`, `@mintlify/common`, `@mintlify/mdx`,
`@mintlify/models`, `@mintlify/prebuild`, `@mintlify/previewing`,
`@mintlify/scraping`, `@mintlify/validation` to their latest versions.
- Mintlify now depends on `@base-ui/react` instead of
`@radix-ui/react-*` via `@mintlify/mdx`.
- Pulled in security fixes via transitive upgrades (e.g.,
`axios@1.18.0`, `tar@7.5.21`, `adm-zip@0.6.0`, `js-yaml@4.3.1`,
`postcss@8.5.23`).
- Updated `pnpm-workspace.yaml` catalog and minimumReleaseAgeExclude,
and refreshed `pnpm-lock.yaml`.

<sup>Written for commit 0c478e5.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2669?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. -->
## Summary
- give the persisted `core.tool` dry-run test a 15-second timeout
- keep the adjustment local to the two-subprocess test

The full-suite CI run took 5.025s for this test, just over Vitest’s
5-second default. Adjacent multi-process CLI tests already use explicit
15–30 second timeouts.

## Test plan
- `pnpm exec vitest run packages/evals/tests/cli.test.ts` (61 passed)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Increase timeout to 15s for the persisted `core.tool` dry-run CLI test
to avoid CI flakiness from the 5s Vitest default. The change is local to
that multi-process test only.

<sup>Written for commit 82c5f36.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2675?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. -->
@seanmcguire12
seanmcguire12 merged commit ef783e1 into main Aug 10, 2026
52 checks passed
miguelg719 added a commit that referenced this pull request Aug 10, 2026
Three fixes, all wanted **before** the 4.0.0 release run (merging this
PR to main is itself the release trigger):

1. **4.0.0 changelog entries** now carry the cutover one-liner from
#2671 and link the [v3→v4 migration
guide](https://docs.stagehand.dev/v4/migrations/v3), matching the 3.0.0
entry's pattern.
2. **3.0.1–3.7.1 history restored** — the consolidated root changelog
seeded on v4-spike jumped from 4.0.0 straight to 3.0.0, silently
dropping 16 releases. Spliced back verbatim from
`packages/core/CHANGELOG.md` on the `v3` branch (that history's
maintenance home going forward).
3. **Release workflow unblocked** — the 4.0.0 publish run
[failed](https://github.com/browserbase/stagehand/actions/runs/31361618186/job/93371433942)
with `EBADDEVENGINES`: `devEngines.packageManager` with `onFail:
"download"` makes every npm command in the repo hard-fail (npm can't
download itself into being pnpm), and `changeset publish` preflights
with `npm info` (the publish itself uses `pnpm publish`, so `catalog:`
deps resolve fine — verified in @changesets/cli 2.31's
`getPublishTool`). `onFail: "warn"` keeps the pnpm nudge without
blocking npm tooling; verified `npm info` now succeeds in-repo.

`consolidate-changelogs.ts --check` passes.
miguelg719 added a commit that referenced this pull request Aug 20, 2026
…2786)

## Why

On `v3`, every push published a snapshot of `@browserbasehq/stagehand`
as `<next>-alpha-<sha>` under the `alpha` dist-tag (`release-canary`
script + `snapshot` changesets config + a "Publish Canary" step in
`release.yml`). The v4 release rewrite (#2671) dropped all three, so
nothing newer than `4.0.0-alpha-49bc5b6…` has shipped to npm since.

## What

Port the v3 behavior onto the v4 release tooling:

- `.changeset/config.json` — restore `snapshot: { useCalculatedVersion,
prereleaseTemplate: "alpha-{commit}" }` (the v3 `snapshot.tag` key was
never part of the schema; the dist-tag comes from `--tag alpha` on
publish).
- `justfile` — new `_publish-typescript-alpha` recipe: `changeset
version --snapshot` → build `sdk-ts` → `changeset publish --tag alpha
--no-git-tag`.
- `.github/workflows/release.yml` — new `publish-typescript-alpha` job
after `release-typescript`. It's a separate job (rather than a trailing
step as on v3) so an alpha failure can't block the Python/Go release
jobs, and it only needs the node toolchain (`turbo run build
--filter=@browserbasehq/stagehand` covers protocol → extension →
sdk-ts).

Behavior matches v3: only packages with pending changesets are
versioned, so the push that cuts a stable release is a no-op for the
alpha job. Verified locally that `changeset version --snapshot` yields
`4.0.3-alpha-8b75044ee9163dc3c0d18fb11eed4a12246b4a03`.

No changeset — CI/release infra only.

## Follow-up

Python alphas (`<next>a0.dev<N>` on PyPI — PEP 440 can't carry the sha)
are coming in a separate PR. Go needs nothing: `go get
…/sdk-go/v4@<sha>` already works via pseudo-versions.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Restores commit-addressed alpha releases for the TypeScript SDK. v3
published `<next>-alpha-<sha>` to the `alpha` dist-tag on pushes; v4
dropped it. This brings back automated alphas without affecting stable
releases.

- Restores Changesets snapshot config: `useCalculatedVersion` with
`prereleaseTemplate: "alpha-{commit}"`.
- Adds `just _publish-typescript-alpha`: `changeset version --snapshot`
→ build `sdk-ts` → `changeset publish --tag alpha --no-git-tag`.
- Adds a separate `publish-typescript-alpha` job in `release.yml` after
`release-typescript`; builds `@browserbasehq/stagehand` via `turbo` and
does not block Python/Go if it fails.
- Behavior matches v3: publishes `<next>-alpha-<sha>` only when there
are pending changesets; no-op on the stable-release commit; no git tags;
CI-only. Aligns with Linear AP-2885.

<sup>Written for commit d98d0e4.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2786?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. -->
antonvishal pushed a commit to antonvishal/stagehand that referenced this pull request Aug 21, 2026
…rowserbase#2786)

## Why

On `v3`, every push published a snapshot of `@browserbasehq/stagehand`
as `<next>-alpha-<sha>` under the `alpha` dist-tag (`release-canary`
script + `snapshot` changesets config + a "Publish Canary" step in
`release.yml`). The v4 release rewrite (browserbase#2671) dropped all three, so
nothing newer than `4.0.0-alpha-49bc5b6…` has shipped to npm since.

## What

Port the v3 behavior onto the v4 release tooling:

- `.changeset/config.json` — restore `snapshot: { useCalculatedVersion,
prereleaseTemplate: "alpha-{commit}" }` (the v3 `snapshot.tag` key was
never part of the schema; the dist-tag comes from `--tag alpha` on
publish).
- `justfile` — new `_publish-typescript-alpha` recipe: `changeset
version --snapshot` → build `sdk-ts` → `changeset publish --tag alpha
--no-git-tag`.
- `.github/workflows/release.yml` — new `publish-typescript-alpha` job
after `release-typescript`. It's a separate job (rather than a trailing
step as on v3) so an alpha failure can't block the Python/Go release
jobs, and it only needs the node toolchain (`turbo run build
--filter=@browserbasehq/stagehand` covers protocol → extension →
sdk-ts).

Behavior matches v3: only packages with pending changesets are
versioned, so the push that cuts a stable release is a no-op for the
alpha job. Verified locally that `changeset version --snapshot` yields
`4.0.3-alpha-8b75044ee9163dc3c0d18fb11eed4a12246b4a03`.

No changeset — CI/release infra only.

## Follow-up

Python alphas (`<next>a0.dev<N>` on PyPI — PEP 440 can't carry the sha)
are coming in a separate PR. Go needs nothing: `go get
…/sdk-go/v4@<sha>` already works via pseudo-versions.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Restores commit-addressed alpha releases for the TypeScript SDK. v3
published `<next>-alpha-<sha>` to the `alpha` dist-tag on pushes; v4
dropped it. This brings back automated alphas without affecting stable
releases.

- Restores Changesets snapshot config: `useCalculatedVersion` with
`prereleaseTemplate: "alpha-{commit}"`.
- Adds `just _publish-typescript-alpha`: `changeset version --snapshot`
→ build `sdk-ts` → `changeset publish --tag alpha --no-git-tag`.
- Adds a separate `publish-typescript-alpha` job in `release.yml` after
`release-typescript`; builds `@browserbasehq/stagehand` via `turbo` and
does not block Python/Go if it fails.
- Behavior matches v3: publishes `<next>-alpha-<sha>` only when there
are pending changesets; no-op on the stable-release commit; no git tags;
CI-only. Aligns with Linear AP-2885.

<sup>Written for commit d98d0e4.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2786?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. -->
miguelg719 added a commit that referenced this pull request Aug 24, 2026
## Summary

- stop running the full CI workflow again after every merge to main
- keep pull request CI unchanged
- preserve workflow_dispatch for trusted external-contributor handoff
runs

This removes the main push trigger introduced in #2671. Shared protocol
changes can activate every SDK filter, so merges such as #2790 repeated
the complete test matrix after it had already passed on the PR.

## Test plan

- `actionlint -ignore SC2046 .github/workflows/ci.yml`
- `git diff --check`

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Stop running the CI workflow on pushes to `main` to avoid duplicate runs
after merges; keep CI behavior for pull requests and manual dispatches
unchanged.

- Removes the `push` trigger on `main`; retains `pull_request` and
`workflow_dispatch` (with `pull_request_number` input) for trusted
handoffs.
- Pushes to `main` no longer run CI. If any branch protection requires
push-based checks, update it to rely on PR-based statuses.

<sup>Written for commit 3d4a378.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2800?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. -->
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.

8 participants