feat(verifier): add rubric verifier engine - #2133
Merged
Merged
Conversation
🦋 Changeset detectedLatest commit: 19ca056 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
There was a problem hiding this comment.
1 issue found across 19 files
Confidence score: 3/5
- There is a concrete stability risk in
packages/core/lib/v3/verifier/prompts/firstPointOfFailure.ts: unbounded range expansion can trigger OOM or hangs when parsing malformed LLM output. - Because this is severity 7/10 with high confidence (8/10) and can directly impact runtime behavior, the merge risk is moderate until a guardrail is added.
- Pay close attention to
packages/core/lib/v3/verifier/prompts/firstPointOfFailure.ts- cap per-range expansion (for example, max steps) to prevent runaway memory/CPU use.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/core/lib/v3/verifier/prompts/firstPointOfFailure.ts">
<violation number="1" location="packages/core/lib/v3/verifier/prompts/firstPointOfFailure.ts:131">
P1: Unbounded range expansion can cause OOM or hang on malformed LLM output. Add a cap on the number of elements generated from a single range segment (e.g., limit to 1000 steps).</violation>
</file>
Architecture diagram
sequenceDiagram
participant Client as V3Evaluator (public API)
participant Verifier as RubricVerifier (internal)
participant LLM as LLMClient (provider-managed)
participant Evidence as evidence.ts (collector)
participant Prompts as prompt modules
participant Taxonomy as errorTaxonomy.ts
participant Disk as Trajectory on disk
Note over Client,Disk: Primary entry: V3Evaluator.verify(trajectory, taskSpec)
Client->>Verifier: verify(trajectory, taskSpec)
alt STAGEHAND_EVALUATOR_BACKEND=verifier
Client->>Client: NEW: instantiate RubricVerifier(getClient)
else legacy
Client->>Client: delegate to LegacyV3Evaluator (unchanged)
end
Verifier->>Disk: collectCanonicalEvidence(trajectory)
Note over Verifier,Disk: NEW: rehydrate tier-1 agent images from imagePath<br/>NEW: rehydrate tier-2 probe screenshots from screenshotPath
Disk-->>Verifier: canonicalImages[], canonicalText[]
Verifier->>Taxonomy: getTaxonomyText(1,6,3)
Taxonomy-->>Verifier: rendered taxonomy block
Verifier->>Prompts: render RUBRIC_GENERATION_PROMPT(task, urlContext)
alt taskSpec has precomputedRubric
Verifier->>Verifier: use precomputed rubric (skip generation)
else no precomputed rubric
Verifier->>LLM: NEW: call getClient().generate() with rubric prompt
LLM-->>Verifier: parsed rubric JSON (items: criterion[])
end
Verifier->>Verifier: NEW: select approach via VERIFIER_APPROACH env var
alt Approach B (default) — fused judgment
Verifier->>Evidence: groupTopKByCriterion(numCriteria, relevanceScores, topK)
Evidence-->>Verifier: Map<criterionIdx, evidenceIdx[]>
Verifier->>Prompts: build evidence manifest for all criteria
Verifier->>LLM: NEW: FUSED_JUDGMENT_PROMPT (single multi-modal call)
Note over Verifier,LLM: Grades ALL criteria + outcome + optional failure analysis + task validity
LLM-->>Verifier: fused JSON (outcome, per_criterion[], optional failure_point, optional task_validity)
Verifier->>Verifier: mapFusedPerCriterionToScores(rubric, perCriterion)
Verifier->>Verifier: build Verdict from fused response
else Approach A — per-criterion + fused outcome
Verifier->>LLM: loop N times (NEW: MM_BATCHED_RELEVANCE_PROMPT in batches)
Note over Verifier,LLM: Batched relevance: one call per batch of B evidence points
LLM-->>Verifier: relevance scores per evidence per criterion
Verifier->>Evidence: groupTopKByCriterion(...)
Verifier->>LLM: loop N times (NEW: MM_PER_CRITERION_SCORE_PROMPT — one call per criterion)
Note over Verifier,LLM: Per-criterion analysis + score (parallelizable)
LLM-->>Verifier: per-criterion earned_points, justification
Verifier->>Prompts: build rubric_summary from per-criterion scores
Verifier->>LLM: NEW: FUSED_OUTCOME_PROMPT (consumes pre-scored rubric)
LLM-->>Verifier: outcome verdict + optional failure analysis + task validity
end
opt Optional steps not folded (VERIFIER_OPTIONAL_STEPS=separate)
Verifier->>LLM: NEW: FIRST_POINT_OF_FAILURE_PROMPT (Step 9a separate call)
LLM-->>Verifier: failure analysis JSON
Verifier->>Verifier: parseFailureStepNumbers() for each failure point
Verifier->>LLM: NEW: TASK_VALIDITY_PROMPT (Step 10 separate call)
LLM-->>Verifier: task validity JSON
end
Verifier-->>Client: Verdict { success, processScore, outcome, failurePoint, taskValidity, criterionScores }
Note over Client: generateRubric(taskSpec) also uses RubricVerifier
Client->>Verifier: generateRubric(taskSpec)
alt STAGEHAND_EVALUATOR_BACKEND=verifier
Verifier->>LLM: RUBRIC_GENERATION_PROMPT (same as Step 0a)
LLM-->>Verifier: rubric items
Verifier-->>Client: Rubric { items: criterion[] }
else legacy
Client->>Client: return single legacyTaskCompletionCriterion (unchanged)
end
Note over Client: ask() / batchAsk() blocked on verifier backend
Client->>Client: throw: "verifier backend only supports verify() and generateRubric()"
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
Re-trigger cubic
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 15, 2026 21:23
3fee3cb to
7d010ed
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 15, 2026 21:23
163db47 to
ebe60bf
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 15, 2026 21:45
7d010ed to
cfa9a9a
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 15, 2026 21:45
ebe60bf to
191904b
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 15, 2026 22:33
cfa9a9a to
a152252
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 15, 2026 22:33
191904b to
62cb8db
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 15, 2026 23:27
a152252 to
fc5a9f7
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
2 times, most recently
from
May 16, 2026 04:40
a6ee702 to
2e7ff0f
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 16, 2026 04:40
fc5a9f7 to
be24a26
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 16, 2026 05:50
2e7ff0f to
b725247
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 16, 2026 05:50
be24a26 to
4e9c26e
Compare
Contributor
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Fix all with cubic | Re-trigger cubic
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 18, 2026 23:54
4e9c26e to
d9b4fb0
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 18, 2026 23:54
cabb4c5 to
5f74a4b
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 19, 2026 00:01
d9b4fb0 to
a3e0ae0
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
3 times, most recently
from
May 19, 2026 00:34
623bea5 to
e5244c2
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 19, 2026 00:36
c11e852 to
cbe0087
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 19, 2026 00:36
e5244c2 to
c3623e8
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 19, 2026 00:49
cbe0087 to
9f2c33d
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
2 times, most recently
from
May 21, 2026 17:33
0d70b72 to
f1d11dd
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
from
May 21, 2026 17:33
9f2c33d to
4d72649
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
May 21, 2026 17:46
f1d11dd to
beeba4f
Compare
miguelg719
force-pushed
the
miguelgonzalez/verifier-04-evidence-normalization
branch
2 times, most recently
from
May 21, 2026 22:29
984bf40 to
24affdf
Compare
Attach the terminal URL, ariaTree, and final screenshots to the fused judgment/outcome prompts so the judge always sees the closing frame, even when per-criterion top-K relevance selection misses it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
miguelg719
force-pushed
the
miguelgonzalez/verifier-05-core-engine
branch
from
June 2, 2026 06:23
e5ff81b to
2443ff9
Compare
…er-04-evidence-normalization # Conflicts: # packages/core/lib/v3/handlers/v3CuaAgentHandler.ts # packages/core/lib/v3/verifier/types.ts
… miguelgonzalez/verifier-05-core-engine
originalStepIndex and trajectoryStepPosition were always assigned the same value and nothing downstream read the latter. Also type addTextEvidence's payload as string | undefined, stringifying the unknown-shaped json/tool sources explicitly at the call sites. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… miguelgonzalez/verifier-05-core-engine
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… miguelgonzalez/verifier-05-core-engine
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… miguelgonzalez/verifier-05-core-engine
miguelg719
changed the base branch from
miguelgonzalez/verifier-04-evidence-normalization
to
main
June 10, 2026 22:30
…er-05-core-engine # Conflicts: # packages/core/lib/v3/index.ts # packages/core/lib/v3/verifier/evidence.ts # packages/core/lib/v3/verifier/index.ts # packages/core/lib/v3/verifier/types.ts
pirate
approved these changes
Jun 11, 2026
Merged
This was referenced Jun 12, 2026
seanmcguire12
pushed a commit
that referenced
this pull request
Jun 19, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @browserbasehq/stagehand@3.6.0 ### Minor Changes - [#2178](#2178) [`c49a3fc`](c49a3fc) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add support for WebMCP ### Patch Changes - [#2217](#2217) [`147e310`](147e310) Thanks [@monadoid](https://github.com/monadoid)! - Add Azure OpenAI Microsoft Entra ID model auth support. - [#2231](#2231) [`cf3603d`](cf3603d) Thanks [@miguelg719](https://github.com/miguelg719)! - Add claude-fable-5 support: native structured outputs via the @ai-sdk/anthropic bump, adaptive thinking (including the new "xhigh" effort) on the agent path, the API's built-in server-side refusal fallback to claude-opus-4-8, and auto tool choice for the final done call on models that reject forced tool use. - [#2233](#2233) [`8d7d414`](8d7d414) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Normalize URLs in `ActCache` key derivation by sorting query parameters before hashing. Semantically equivalent URLs that differ only in parameter order (e.g. `?utm_source=email&id=42` vs `?id=42&utm_source=email`) now hit the cache instead of silently missing. Fragments and duplicate keys are preserved. - [#2229](#2229) [`fd42e65`](fd42e65) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - launch local browser with --enable-features=WebMCPTesting,DevToolsWebMCPSupport by default - [#2220](#2220) [`a64c6b7`](a64c6b7) Thanks [@monadoid](https://github.com/monadoid)! - Fix Stagehand-generated shadow-root XPath resolution so deterministic actions can target elements inside web components. - [#2132](#2132) [`ed3e566`](ed3e566) Thanks [@miguelg719](https://github.com/miguelg719)! - Add canonical verifier evidence normalization for screenshots and text signals without requiring image dependencies in core installs. - [#2133](#2133) [`840aac8`](840aac8) Thanks [@miguelg719](https://github.com/miguelg719)! - Add the rubric-based verifier engine with normalized public rubric output and bounded failure-step parsing. ## @browserbasehq/stagehand-evals@2.0.3 ### Patch Changes - Updated dependencies \[[`147e310`](147e310), [`cf3603d`](cf3603d), [`8d7d414`](8d7d414), [`fd42e65`](fd42e65), [`a64c6b7`](a64c6b7), [`c49a3fc`](c49a3fc), [`ed3e566`](ed3e566), [`840aac8`](840aac8)]: - @browserbasehq/stagehand@3.6.0 ## @browserbasehq/stagehand-server-v3@3.7.1 ### Patch Changes - [#2217](#2217) [`147e310`](147e310) Thanks [@monadoid](https://github.com/monadoid)! - Add Azure OpenAI Microsoft Entra ID model auth support. - Updated dependencies \[[`147e310`](147e310), [`cf3603d`](cf3603d), [`8d7d414`](8d7d414), [`fd42e65`](fd42e65), [`a64c6b7`](a64c6b7), [`c49a3fc`](c49a3fc), [`ed3e566`](ed3e566), [`840aac8`](840aac8)]: - @browserbasehq/stagehand@3.6.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
felipeofdev-ai
pushed a commit
to felipeofdev-ai/stagehand
that referenced
this pull request
Aug 4, 2026
# Why With trajectory capture and canonical evidence in place, the verifier needs the actual rubric-based judgment engine. This PR adds the new verifier backend while keeping legacy `ask()` and `batchAsk()` isolated behind the backend flag. # What Changed - Added `RubricVerifier` with Approach A and Approach B verifier paths. - Added prompt modules for rubric generation, relevance, per-criterion scoring, fused judgment, fused outcome, failure analysis, and task validity. - Added task validity and error taxonomy support. - Consolidated engine option, taxonomy, and failure-step parser types into `verifier/types.ts`; implementation modules import those types directly. - Aligned raw verifier result types with the engine output for empty trajectories and task-validity reasoning. - Extended trajectory asset path containment to externalized tier-1 image paths. - Bounded first-point-of-failure step-range parsing so malformed model output cannot expand unbounded ranges. - Wired `STAGEHAND_EVALUATOR_BACKEND=verifier` through `V3Evaluator.verify()` and `generateRubric()`. - Kept `ask()` and `batchAsk()` on the legacy backend only. - Removed upstream verifier references from comments. # Tests - `pnpm --filter @browserbasehq/stagehand run typecheck` - `pnpm --filter @browserbasehq/stagehand run build:esm` - `pnpm --filter @browserbasehq/stagehand run test:core -- packages/core/dist/esm/tests/unit/verifier-failure-step-parser.test.js packages/core/dist/esm/tests/unit/verifier-trajectory.test.js` - `pnpm -w exec prettier --check packages/core/lib/v3/verifier packages/core/tests/unit/verifier-failure-step-parser.test.ts packages/core/tests/unit/verifier-trajectory.test.ts packages/evals/cli.ts packages/evals/framework packages/evals/tests/framework/rubricCache.test.ts packages/evals/tests/framework/verifierAdapter.test.ts packages/evals/tests/tui/commandTree.test.ts packages/evals/tui packages/evals/tasks/bench/agent` - `git diff --check` ---------
felipeofdev-ai
pushed a commit
to felipeofdev-ai/stagehand
that referenced
this pull request
Aug 4, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @browserbasehq/stagehand@3.6.0 ### Minor Changes - [browserbase#2178](browserbase#2178) [`c49a3fc`](browserbase@c49a3fc) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add support for WebMCP ### Patch Changes - [browserbase#2217](browserbase#2217) [`147e310`](browserbase@147e310) Thanks [@monadoid](https://github.com/monadoid)! - Add Azure OpenAI Microsoft Entra ID model auth support. - [browserbase#2231](browserbase#2231) [`cf3603d`](browserbase@cf3603d) Thanks [@miguelg719](https://github.com/miguelg719)! - Add claude-fable-5 support: native structured outputs via the @ai-sdk/anthropic bump, adaptive thinking (including the new "xhigh" effort) on the agent path, the API's built-in server-side refusal fallback to claude-opus-4-8, and auto tool choice for the final done call on models that reject forced tool use. - [browserbase#2233](browserbase#2233) [`8d7d414`](browserbase@8d7d414) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Normalize URLs in `ActCache` key derivation by sorting query parameters before hashing. Semantically equivalent URLs that differ only in parameter order (e.g. `?utm_source=email&id=42` vs `?id=42&utm_source=email`) now hit the cache instead of silently missing. Fragments and duplicate keys are preserved. - [browserbase#2229](browserbase#2229) [`fd42e65`](browserbase@fd42e65) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - launch local browser with --enable-features=WebMCPTesting,DevToolsWebMCPSupport by default - [browserbase#2220](browserbase#2220) [`a64c6b7`](browserbase@a64c6b7) Thanks [@monadoid](https://github.com/monadoid)! - Fix Stagehand-generated shadow-root XPath resolution so deterministic actions can target elements inside web components. - [browserbase#2132](browserbase#2132) [`ed3e566`](browserbase@ed3e566) Thanks [@miguelg719](https://github.com/miguelg719)! - Add canonical verifier evidence normalization for screenshots and text signals without requiring image dependencies in core installs. - [browserbase#2133](browserbase#2133) [`840aac8`](browserbase@840aac8) Thanks [@miguelg719](https://github.com/miguelg719)! - Add the rubric-based verifier engine with normalized public rubric output and bounded failure-step parsing. ## @browserbasehq/stagehand-evals@2.0.3 ### Patch Changes - Updated dependencies \[[`147e310`](browserbase@147e310), [`cf3603d`](browserbase@cf3603d), [`8d7d414`](browserbase@8d7d414), [`fd42e65`](browserbase@fd42e65), [`a64c6b7`](browserbase@a64c6b7), [`c49a3fc`](browserbase@c49a3fc), [`ed3e566`](browserbase@ed3e566), [`840aac8`](browserbase@840aac8)]: - @browserbasehq/stagehand@3.6.0 ## @browserbasehq/stagehand-server-v3@3.7.1 ### Patch Changes - [browserbase#2217](browserbase#2217) [`147e310`](browserbase@147e310) Thanks [@monadoid](https://github.com/monadoid)! - Add Azure OpenAI Microsoft Entra ID model auth support. - Updated dependencies \[[`147e310`](browserbase@147e310), [`cf3603d`](browserbase@cf3603d), [`8d7d414`](browserbase@8d7d414), [`fd42e65`](browserbase@fd42e65), [`a64c6b7`](browserbase@a64c6b7), [`c49a3fc`](browserbase@c49a3fc), [`ed3e566`](browserbase@ed3e566), [`840aac8`](browserbase@840aac8)]: - @browserbasehq/stagehand@3.6.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
With trajectory capture and canonical evidence in place, the verifier needs the actual rubric-based judgment engine. This PR adds the new verifier backend while keeping legacy
ask()andbatchAsk()isolated behind the backend flag.What Changed
RubricVerifierwith Approach A and Approach B verifier paths.verifier/types.ts; implementation modules import those types directly.STAGEHAND_EVALUATOR_BACKEND=verifierthroughV3Evaluator.verify()andgenerateRubric().ask()andbatchAsk()on the legacy backend only.Tests
pnpm --filter @browserbasehq/stagehand run typecheckpnpm --filter @browserbasehq/stagehand run build:esmpnpm --filter @browserbasehq/stagehand run test:core -- packages/core/dist/esm/tests/unit/verifier-failure-step-parser.test.js packages/core/dist/esm/tests/unit/verifier-trajectory.test.jspnpm -w exec prettier --check packages/core/lib/v3/verifier packages/core/tests/unit/verifier-failure-step-parser.test.ts packages/core/tests/unit/verifier-trajectory.test.ts packages/evals/cli.ts packages/evals/framework packages/evals/tests/framework/rubricCache.test.ts packages/evals/tests/framework/verifierAdapter.test.ts packages/evals/tests/tui/commandTree.test.ts packages/evals/tui packages/evals/tasks/bench/agentgit diff --check