Skip to content

feat(evals): case-level live board, per-case logs and a run summary - #3090

Merged
miguelg719 merged 15 commits into
evals/tui-3-doctorfrom
evals/tui-4-run-experience
Oct 12, 2026
Merged

miguelg719 merged 15 commits into
evals/tui-3-doctorfrom
evals/tui-4-run-experience

Conversation

@miguelg719

@miguelg719 miguelg719 commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Stack

4 of 4 in the evals TUI overhaul. Base: #3089.
#3087 concurrency · #3088 config v2 + env · #3089 doctor · → #3090

Summary

A 6-wide HardBench run used to render as one row that kept flipping between running, passed and failed. Every suite names all its cases agent/<suite>, and the board keyed rows by task × model, so every in-flight case and every trial overwrote the same row. Concurrency looked like 1 whatever -c said.

Before (6 in flight):

    Task                                                     Model               Result
  ⣾ agent/hardbenchmark                                      openai/gpt-5.4-mini running

After:

Live board

Live board

  • Row identity: progress events carry a row key (cell + case + trial) and a case label: short id, domain and question, read from id|task_id, web|website and ques|confirmed_task (framework/caseIdentity.ts).
  • One row per case in flight: id domain · question · phase · elapsed.
    • Phases (session → agent → verify) are reported from inside the harness and target code through an AsyncLocalStorage row context (framework/rowContext.ts).
    • Elapsed time turns yellow once a row outlasts the p75 of finished rows.
  • Status bar: progress, ✓ / ✗ / ⏱ counts, elapsed time and ETA, plus the queue line from feat(evals): per-provider concurrency under the global cap #3087 (running · queued · openai 6/6 · throttled). Queued rows are counted there and never take a row.
  • Recent: the last few finishes with their outcome kind (max_turns, sdk_error, gated, ungraded) and session URL.
  • Keys: esc stop, v logs off → all → one, ? help. They work in argv mode and the REPL, and the REPL no longer echoes keystrokes onto the board.
  • Non-TTY (CI, pipes): one line per event, with no cursor escapes.

Logs

  • Every case writes its own file: .trajectories/<run>/logs/<id>-<site>__<provider>-<model>.log. Default runs used to drop all output.
  • Console output from inside a row goes to that row's file instead of over the board.
  • -v streams the lines above the board, attributed by case id; --follow <id> streams one case.
  • --json writes only the summary object to stdout; the header, board and logs go to stderr.

-v

Summary

  • Headline: suite · runs · duration · tokens, plus cost when the harness reports it.
  • Per-cell table (harness × tool × model): pass rate, max_turns, sdk_error, gated (the judge passed it, a deterministic gate such as no_browser_use failed it), ungraded, retried.
  • Failures: infra failures first, with reason and session URL; rubric fails listed by case id.
  • Links: the experiment URL, the trajectory group and the log directory.

Summary

  • Dead judge: when the judge graded nothing (a retired model, a bad key), every row fails closed, so the pass rate says nothing about the agent. The run now says so and exits 1:

Dead judge

Also

  • evals run --help lists each harness's tool surfaces (default starred) and the suites, from a registry (framework/benchSuites.ts) that parse and the planner now share.
  • The --preview header lists every constant column, so a single-cell run still names its tool surface.
  • The README run section is rewritten around the new screenshots, replacing run.gif.

Notes

  • Screenshots are rendered from the real ProgressRenderer and summary code with fixture events and a fixed clock (ANSI → HTML → Playwright), not mocked up.
  • Apply the shared eval contract across existing harnesses #2903 (isolated CODEX_HOME) touches benchHarness.ts, runner.ts and run.test.ts. A trial merge conflicted in 6 hunks, all mechanical.

Test plan

  • vitest packages/evals/tests: 954 passing. New: caseIdentity, rowLog, runSummary, progress (board layout, p75 colouring, non-TTY output, --json routing to stderr), resultsSummary, benchSuites, help. Also extended runnerProgressEvents (distinct row keys across cases × trials, phases landing on the right concurrent row, per-row log files) and run.test (v cycling, --follow, dead judge exit 1).
  • tsc, fmt:check
  • Live evals run b:hardbenchmark --harness codex --tool stagehand_facade -e browserbase: the board showed one row per case with phases and the queue line. (That run's facade calls were cancelled by a local ~/.codex/config.toml approvals_reviewer setting; Apply the shared eval contract across existing harnesses #2903's isolated CODEX_HOME fixes that and it's unrelated to this PR.)

Summary by cubic

The evals run experience gets a case-level live board, per-case log files, and an end-of-run summary. A suite run used to collapse every in-flight case into one row (all cases share the task name agent/<suite>), so concurrency looked like 1 regardless of -c; now each case in flight gets its own row.

  • Board rows are keyed by case id, domain, question, and trial, show the current phase (session → agent → verify) and elapsed time, and list the latest finishes with their outcome kind and session URL; queued rows only appear in the status line.
  • Every case writes its own log file under .trajectories/<run>/logs/; -v streams all case logs above the board, --follow <id> streams one, and the v/esc/? keys work in both the REPL and argv modes. Filenames keep the model provider and get ~2/~3 suffixes on collision; a filesystem error disables that row's file instead of failing the row.
  • Runs end with a per-cell table (pass rate, max_turns, sdk_error, gated, ungraded, retried), infra failures with session URLs, and a dead-judge banner (exit 1) when the judge graded nothing.
  • --json emits only the summary to stdout; non-TTY output is one line per event with no cursor escapes. The board draws on stderr and sizes to that stream, Ctrl/Meta chords stay off it so Ctrl+C still interrupts, and the preview header names an overridden model once.
  • evals run --help lists each harness's tool surfaces and the suites from a shared registry that discovery also reads, so a listed suite always gets discovered. The README run section is rewritten around screenshots rendered from the real renderer, replacing run.gif.

Written for commit be4fc36. Summary will update on new commits.

View guided diff Turn on auto-fix

Suite rows all share the task name (agent/hardbenchmark), so the board
keyed by task × model collapsed every in-flight case into one flipping
row. Progress events now carry a row key, the case (short id, domain,
question) and the trial, and the board draws one row per case in flight
with its phase (session → agent → verify, reported through an
AsyncLocalStorage row context), elapsed time, a queue line and the last
few finishes with their outcome kind and session URL.

Every case writes its own log file under .trajectories/<run>/logs/; -v
streams all of them above the board, --follow <id> one case, and the v
key cycles off → all → one during a run (esc stops, ? shows keys, in the
REPL and argv modes). Non-TTY output is one line per event. --json
writes only the summary to stdout.

The summary reports suite · runs · duration · tokens · cost, a per-cell
table (pass rate, max_turns, sdk_error, gated, ungraded, retried), infra
failures with session URLs, and exits 1 with a banner when the judge
graded nothing. README screenshots are rendered from the real renderer.
@changeset-bot

changeset-bot Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: be4fc36

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

@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.

2 issues found across 40 files

Confidence score: 3/5

  • caseIdentity.ts can give cases from different suites the same log file and summary name when dataset IDs overlap. Include the suite or task name in both identities.
  • parse.test.ts duplicates the suite list from benchSuites.ts, so adding a benchmark can break this test or require a manual, order-sensitive update. Build the expected message from the shared suite list.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/evals/framework/caseIdentity.ts">

<violation number="1" location="packages/evals/framework/caseIdentity.ts:66">
P2: This case label is not unique across suites, so overlapping dataset IDs cause separate rows to share a log file and summary name. Include the suite/task name in the derived log and display identity.</violation>
</file>

<file name="packages/evals/tests/tui/parse.test.ts">

<violation number="1" location="packages/evals/tests/tui/parse.test.ts:165">
P3: This test duplicates the suite list that benchSuites.ts is meant to own, so adding a benchmark to BENCH_SUITE_NAMES breaks this test and forces a manual, order-sensitive update here. Build the expected message from the registry instead: `new RegExp(`Supported: ${listBenchSuites().join(", ")}\.`)`, importing `listBenchSuites` from `../../framework/benchSuites.js`.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant CLI as CLI / REPL
    participant Runner as Bench Runner
    participant RC as RowContext (AsyncLocalStorage)
    participant RowLog as RowLogWriter
    participant Harness as Harness / Agent
    participant BB as Browserbase
    participant Verifier as Verifier / Judge
    participant TUI as TUI Renderer / Board

    Note over CLI,Runner: Run lifecycle with per-case identity and logs
    
    CLI->>Runner: runEvals(options)
    Runner->>Runner: generate run token + logDir
    
    loop Each testcase
        Runner->>Runner: rowKey (cell + case + trial)
        Runner->>RC: runInRowContext(rowContext)
        RC->>RowLog: RowLogWriter (per-case file)
        
        alt Provider slot available
            Runner->>Harness: executeBenchTask(input)
            Harness->>RC: reportRowPhase("session")
            Harness->>BB: launch browser session
            BB-->>Harness: session URL
            Harness->>RC: reportRowPhase("agent", {sessionUrl})
            Harness->>Harness: run agent with tool surface
            Harness->>RC: reportRowPhase("verify")
            Harness->>Verifier: grade external trajectory
            Verifier->>RC: verify phase
        else Provider throttled/queued
            Runner->>TUI: onQueue (queued count)
            Note over Runner,TUI: Row stays queued, never takes board row
        end
        
        Note over Harness,RC: Log lines from EvalLogger or console
        Harness->>RC: logToRow(entry)
        RC->>RowLog: write entry to per-case log file
        RC->>TUI: onProgress log event (if verbose)
        
        alt Retry on 429 / backpressure
            Runner->>RowLog: attempt(n) marker
            Runner->>Harness: retry execution
        end
        
        RowLog->>Runner: close() + logPath
        Runner->>TUI: started/passed/failed with rowKey, case, outcome
    end
    
    Note over Runner,TUI: Live board rendering
    TUI->>TUI: onStart (one row per case in flight)
    TUI->>TUI: onPhase (session → agent → verify)
    TUI->>TUI: p75 elapsed threshold (yellow highlight)
    
    alt TTY animated
        TUI->>CLI: keys (esc/v/?)
        CLI->>TUI: onKey / setStopping
    else JSON mode
        Runner-->>CLI: --json summary
        CLI->>TUI: stderr only
    end
    
    Note over Runner,TUI: End-of-run summary
    Runner->>Runner: buildRunSummaryJson()
    Runner->>TUI: renderRunSummary
    
    alt Dead judge (graded 0)
        TUI->>CLI: red banner + exit 1
    else Normal completion
        TUI->>CLI: cell table + failures + links
    end
Loading

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

Re-trigger cubic

Comment thread packages/evals/framework/rowLog.ts Outdated
Comment thread packages/evals/framework/caseIdentity.ts
Comment thread packages/evals/framework/benchRunner.ts
Comment thread packages/evals/framework/benchSuites.ts
Comment thread packages/evals/tui/results.ts Outdated
Comment thread packages/evals/README.md Outdated
Comment thread packages/evals/tests/framework/benchSuites.test.ts Outdated
Comment thread packages/evals/tests/tui/parse.test.ts Outdated
Comment thread packages/evals/tests/framework/runSummary.test.ts
Comment thread packages/evals/tests/framework/runnerProgressEvents.test.ts Outdated
Log file names keep the model's provider (openai/foo and anthropic/foo
are different rows), and RowLogNames gives colliding rows in one run
(the same case id in two suites, two tool surfaces of one cell) ~2, ~3
suffixes. A filesystem error disables the row's file instead of throwing.
EvalLogger.error() defaults row entries to level 0 and keeps the
serialized stack. The console-routing test now uses an echoing logger so
it can fail.
Under --json the board draws on stderr, so it now takes its width from
that stream (falling back to stdout's when it isn't a terminal). A failed
row with no outcome (aborted while queued) shows its error in the recent
list. Summary failure rows collapse multi-line reasons to one line and
move the session URL to its own line when it would push the row past the
terminal width.
…e hand-off

Ctrl/Meta chords no longer reach the live board's key handler, so Ctrl+C
stays on readline's SIGINT path. Clearing input typed during a run jumps
to the end of the line before Ctrl-U so nothing right of the cursor
survives. The welcome hand-off runs through the same muted dispatch as a
typed command, so v / ? aren't echoed onto its board.
…dth test

With --model, the constants line no longer repeats the model the
'Model override:' line already shows. Restores the run-header test for
providers.<p>.concurrency (dropped in this branch), now also checking
that EVAL_PROVIDER_CONCURRENCY wins over the config width and that the
config widths are forwarded to the runner.
discovery.ts kept its own copy of the agent suite names, so a suite
added to benchSuites.ts would parse and plan but never be discovered.
It now reads listBenchSuiteTaskNames(), the registry test pins the
concrete list and checks discovery against it, and the parse test builds
its expected message from the registry.
Phase contract tests: the stagehand bench runner reports session then
agent, and external harnesses report agent after the adapter is prepared
(both fail if the report is removed). The summary test now checks a
row's logPath reaches collectFailures and the --json payload. README and
run help no longer claim a log file per case regardless of output,
'retried' is described as a retry count rather than a failure kind, and
the live board is described as linking failures' session URLs.
# Conflicts:
#	packages/evals/README.md
#	packages/evals/tests/tui/parse.test.ts
#	packages/evals/tests/tui/run.test.ts
#	packages/evals/tui/commands/parse.ts
#	packages/evals/tui/commands/run.ts
@miguelg719
miguelg719 added this pull request to stack #3091 October 1, 2026 19:27
@miguelg719
miguelg719 merged commit bc9fc3b into main Oct 12, 2026
25 checks passed
@miguelg719
miguelg719 deleted the evals/tui-4-run-experience branch October 12, 2026 22:53
miguelg719 added a commit that referenced this pull request Oct 12, 2026
## Stack

2 of 4 in the evals TUI overhaul. Base: #3087.
#3087 concurrency · **→ #3088** · #3089 doctor · #3090 run experience

## Summary

**Personal settings no longer go in the tracked config file, and there
is now one `.env` loader.**

**Config v2**
- `evals.config.json` gains `version: 2` and the sections
`defaults.harness` / `defaults.successMode`, `benchmarks.<suite>.limit`,
`harnesses.<h>.{models,tool}`, `providers.<p>.concurrency`,
`verifier.{model,maxUnverifiableCriteria}` and `campaign.tag`.
- **Env twins:** every key in the new sections has one, and config
values resolve to env overrides only when the twin is unset (`flag → env
→ local → tracked → default`).
- **`defaults.*` keeps its existing order:** flag, then local, then
tracked, then the ambient `EVAL_*` vars. The help, `evals config` and
README now state both rules.
- v1 files load unchanged.
- **`evals.config.local.json`** (gitignored) holds personal overrides.
`evals config set …` and the first-run marker write there. `--shared`
edits the tracked file and can't leak local overrides into it.
- New subcommands: `config harnesses | providers | verifier | campaign`.
- **Dist migration:** `build-cli` moves a pre-v2 dist config's personal
edits into `dist/cli/evals.config.local.json`. Values equal to the old
tracked defaults are not treated as edits, so dist installs pick up the
new `concurrency: 3` instead of pinning the old 10.

```
$ evals config providers set openai concurrency 6
  ✓ Set providers.openai.concurrency to 6 (evals.config.local.json)
$ evals config set harness codex
  ✓ Set harness to codex (evals.config.local.json)
$ evals config

  Configuration:

    env          local
    trials       3
    concurrency  3
    api          false
    verbose      false
    model        (default per category)
    harness      codex (local)
    successMode  (outcome)

    providers (local overrides)
      openai  {"concurrency":6}

    Precedence: flag → env → evals.config.local.json → evals.config.json → default
    Files: …/packages/evals/evals.config.json + evals.config.local.json
```

**Env**
- `loadEvalsEnv()` (`evalsEnv.ts`) replaces the two inline
`dotenv.config` calls in `cli.ts`, with the same order: the cwd `.env`
first, then `packages/evals/.env`, and shell exports always win.
- It records which file supplied each key and which keys were shadowed;
the doctor reports that in #3089.
- The welcome wizard's `promotePackageEnv` is removed: with one loader
it could never fire.

**Run header and preflight**
- Missing Browserbase credentials fail once before planning, naming the
missing keys, instead of failing per task inside session creation.
- Bench runs print the judge model (and whether config set it), the
success mode and whether trajectories persist:

```
  Env: BROWSERBASE  Harness: codex  Tool: stagehand_facade  Concurrency: 6 global · openai 6
  Judge: google/gemini-3.5-flash  Success: outcome  Trajectories: on (.trajectories)
```

## Test plan

- [x] `vitest packages/evals/tests`: 866 passing. New or updated:
`config.test.ts` (merge, diff, `--shared` isolation, v1 read),
`evalsEnv.test.ts`, `parse.test.ts` (config sections → env overrides,
env twins win), `run.test.ts` (Browserbase preflight, config widths in
the header), and `cli.test.ts` (writes land in the local file; the
tracked file is untouched).
- [x] tsc, `fmt:check`
- [x] Ran `evals config …` against a scratch worktree (output above).

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Personal settings now live in a gitignored local config file, and the
CLI loads `.env` through one loader, so the doctor reports exactly what
the runner loaded.

**Config v2**

- `evals.config.json` becomes v2; `evals config set` writes personal
overrides to the gitignored `evals.config.local.json`, and `--shared`
edits the tracked file without leaking local overrides; `--shared` is
rejected for `core`/`tracing`, which stay personal-only.
- New sections (`defaults.harness`/`successMode`, `benchmarks`,
`harnesses`, `providers`, `verifier`, `campaign`) only apply when their
env twin is unset; `EVAL_SUCCESS_MODE` and `STAGEHAND_BROWSER_TARGET`
beat the config by exception.
- New subcommands: `config harnesses | providers | verifier | campaign`;
`config path local` prints the gitignored file.
- Validation tightened: integers must be safe (`maxUnverifiableCriteria`
accepts 0), judge ids need provider and model segments,
`harnesses.<h>.models` is rejected for harnesses that pick models per
task category (e.g. `stagehand`), and a malformed local `defaults` fails
loudly.
- v1 configs load unchanged; `build-cli` migrates pre-v2 personal edits
from `dist` into the local file without pinning old defaults.

**Env and run header**

- `loadEvalsEnv()` replaces the two inline `dotenv.config` calls,
loading cwd `.env` first, then `packages/evals/.env`, with shell exports
always winning; it records provenance for the doctor.
- Missing Browserbase credentials fail once before planning instead of
per task; bench run headers print the judge model, success mode,
trajectory persistence, and the per-provider concurrency widths that
actually gate the run.

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

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/3088?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="View guided diff"
src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a>
<a
href="https://www.cubic.dev/action/auto-fix/pr/browserbase/stagehand/3088?returnTo=https%3A%2F%2Fgithub.com%2Fbrowserbase%2Fstagehand%2Fpull%2F3088&source=description"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img
alt="Turn on auto-fix"
src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
miguelg719 added a commit that referenced this pull request Oct 12, 2026
## Stack

3 of 4 in the evals TUI overhaul. Base: #3088.
#3087 concurrency · #3088 config v2 + env · **→ #3089** · #3090 run
experience

## Summary

**`evals doctor --harness a,b [--probe]`** prints a probe matrix with
one row per harness, plus the judge, Browserbase and the env files. Each
failing row prints the exact command that fixes it.

- **Per harness:** binary or runtime resolvable, provider key present,
key validity (with `--probe`: one request to the provider's models
endpoint, so a dead key shows up here instead of as a silent `sdk_error`
mid-run), and one extra per harness: `CODEX_HOME` writable for codex,
Node heap for the in-process harnesses (mastra, pi) at concurrency ≥ 5.
fx and cursor are listed as not probed yet.
- **Judge:** the resolved verifier model and its key. With `--probe` it
also checks that the model is still served; a retired judge would
otherwise fail every criterion and make the run exit as dead-judge.
- **Browserbase:** both credentials. With `--probe` it also looks up the
project with the key (401/403 means the key was rejected, 404 means the
project wasn't found).
- **Env files:** which `.env` files were loaded and which keys they
shadowed (from the #3088 loader). A shadowed key always warns.
- **Verdict:** only requested harnesses (`--harness`, or
`defaults.harness`) can fail it, and when one is requested, the judge
and Browserbase rows can too. The rest of the matrix is informational.
- **`--probe`** is now a public, documented flag. It was hidden before.

![evals
doctor](https://github.com/browserbase/stagehand/raw/evals/tui-3-doctor/packages/evals/assets/readme/doctor.png)

## Test plan

- [x] `vitest packages/evals/tests`: 882 passing. New:
`doctorHarnesses.test.ts`, with probes stubbed and covering each row
kind, verdict narrowing and fix hints.
- [x] tsc, `fmt:check`

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds a probe matrix to `evals doctor` that checks each harness's binary,
provider keys, key validity (with `--probe`), and harness-specific
extras, plus the judge model and Browserbase project. Each failing row
prints the exact command that fixes it, and `--probe` is now a public,
documented flag.

**Details**

- `evals doctor --harness a,b [--probe]` probes every executable harness
(stagehand through gemini_cua): binary or runtime resolvability, key
presence for every provider in the harness's model matrix (in the
planner's order), key validity via one request to each provider's model
endpoint, and extras such as heap size for in-process harnesses or
`CODEX_HOME` writability for codex. `fx` and `cursor` are not probed
yet.
- Also checks the resolved verifier model (env or config, and with
`--probe` that it's still served on each provider), both Browserbase
credentials plus project lookup with `--probe` (a rejected key reads as
401/403, an unknown project as 404, and 429/5xx as a rate limit or
outage to retry rather than a bad key), and reports which `.env` files
were loaded and which keys they shadowed.
- Only requested harnesses (`--harness`, `defaults.harness`, or
`--harness all` to make every row count) can fail the verdict; when one
is requested, the verifier and Browserbase rows can too. Everything else
is informational. Shadowed env keys always warn.

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

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/3089?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="View guided diff"
src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a>
<a
href="https://www.cubic.dev/action/auto-fix/pr/browserbase/stagehand/3089?returnTo=https%3A%2F%2Fgithub.com%2Fbrowserbase%2Fstagehand%2Fpull%2F3089&source=description"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img
alt="Turn on auto-fix"
src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.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.

2 participants