Repository navigation
feat(vitest-evals): Pass case expectations to suite judges and add createTaskHarness - #116
Draft
sentry-junior[bot] wants to merge 1 commit into
Draft
sentry-junior[bot] wants to merge 1 commit into
sentry-junior[bot] wants to merge 1 commit into
Conversation
…eateTaskHarness
`run(input, options)` now forwards per-case judge params such as `expected`
and `expectedTools` to every automatic suite judge, and `toSatisfyJudge(...)`
reuses them for the returned run unless matcher options override them. The
suite `judgeThreshold` keeps its existing semantics: it is compared against
the average score of all automatic judges, like the legacy `threshold`.
`createTaskHarness(name, task)` wraps a plain task function that returns
`string | { result, toolCalls }` and builds the transcript events itself, so
legacy task functions can move to the harness API without hand-written
adapters. `createHarness(...)` still rejects top-level `toolCalls`.
Co-Authored-By: David Cramer <23610+dcramer@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
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.
getsentry/toolkit#1974 moved 27 eval files off
vitest-evals/legacy, and the migration needed ~117 lines of adapters:utils/harness.ts+95 andutils/toolCallJudge.ts+22. This PR closes the two gaps behind those adapters. Both changes are additive: existing 0.18 call sites andlegacy/are untouched.1. Per-case expectations for automatic suite judges
applyAutomaticJudgesonly passedinput/output/toolCalls/run/sessionto suite judges. That meant the built-inToolCallJudgeandStructuredOutputJudgenever saw a case'sexpectedTools/expectedunless you calledtoSatisfyJudge(...), and that path checks each judge against its own threshold. Toolkit worked around this by packing the expectations into the harness input and re-wrapping every judge to unpack them.The fix is an optional second argument to
run:input,output,run,toolCalls, …) always win.toSatisfyJudge(...)reuses them for the returned run. Explicit matcher options still override them.RegExpexpectations toolkit uses out of the serialized run.Threshold semantics (checked, unchanged): the suite
judgeThresholdis already compared against the average score of all automatic judges, and anullscore counts as 0. That is the same rule as legacythreshold, so toolkit needs no opt-in. This PR documents it onDescribeEvalOptions.judgeThresholdand in the docs, and adds a test where one judge scores 0, another scores 1, and the case passes at 0.5.2.
createTaskHarness(name, task)createHarnessdeliberately rejects a top-leveltoolCallsresult (there is a test for it), so a plain task returning{ result, toolCalls }had to build transcript events by hand. I chose a small built-in wrapper over looseningcreateHarness:createHarness's strict "ordered events or messages" contract and its existing rejection.(input) => string | { result, toolCalls }task shape 1:1. The wrapper builds user →tool_call(+tool_resultwhen a call has aresult) → assistant events itself. Errors, fallback traces and artifacts come fromcreateHarness.createJudge(name, assess). An object formcreateTaskHarness({ name, task })wraps to 4 lines under oxfmt in every toolkit eval file, which would make the files longer, not shorter. The positional form also matches toolkit's existing local helper, so call sites don't change.Proof in toolkit
I used a scratch copy of toolkit at
198335d(not pushed) and swapped in the packed branch build. I rewrote the utils and all 27 eval files to the new API.tsc --noEmitandoxfmt --checkpass onmcp-server-evals.I also ran a mock-model smoke eval:
MockLanguageModelV3drivingMcpToolCallTaskRunnerthrough the real MCP stdio server and MSW mocks. Results:ToolCallJudgescored 1 whenexpectedToolscame fromrun(...).it.failscase with the wrongexpectedToolsfailed as expected.utils/harness.tsEvalCase+ a 10-linedefineEvalCases)utils/toolCallJudge.tsToolCallJudge)utils/index.tsutils/structuredOutputJudge.ts/toolPredictionJudge.tsctx.expected/ctx.expectedToolsinstead ofctx.input.*)get-issue.eval.tslist-teams.eval.tssearch-events-agent.eval.tsMost of the savings are in the adapters. Per-file changes are only import moves. The rest of the ~10-line-per-file growth in #1974 comes from code layout (a separate
const cases, thedescribeEvaloptions block), not from the API.get-issue.eval.ts:The adapter it no longer needs (
utils/harness.ts):Possible follow-up (not in this PR)
A
casesoption ondescribeEvalwould remove toolkit's last helper (defineEvalCases).it.for(cases)(…)already covers most of it, so I left it out.Open questions
runoptions. This PR uses a flatrun(input, { expected, expectedTools, ...custom }). That's terse, but any future non-judgerunoption, such as a per-run timeout or metadata, would share a namespace with custom judge params. The alternative is a nestedrun(input, { judge: { … } }).EvalRunOptionstypesexpectedandexpectedToolsbut has an index signature for custom params, so a typo in a custom param name won't be caught. Inferring the allowed keys from the suite'sjudgestuple is possible but adds generics todescribeEval.createTaskHarnessscope. It has nousage/tracespassthrough, and non-object toolargumentsare dropped, the same as the toolkit adapter did. Anything richer should usecreateHarness. Is that the boundary you want?pnpm testhas one failure in this sandbox,report-ui"returns 500 when asset reads fail", and it fails the same way onmainhere. The sandbox user can still read achmod 000file, so this is not caused by this change.via @dcramer.
--
View Session [Sentry]