Thresholds live in the spec
Add atests: block, keyed by question:
prototype/examples/swe_agent/patch_eval.yml
hunch test checks each configured threshold, prints PASS or FAIL, and exits 1 if a required check fails. A check marked severity: warn prints WARN without failing the build. CI therefore enforces the limits you write; it does not reject every edit that makes any individual answer worse.
Here is a judgment that reads a coding agent’s patch and predicts whether it will pass the project’s tests, from the SWE-agent cookbook, run against the real test results. These are the key lines of the summary:
min_accuracy, min_act_accuracy (accuracy among answers above the act bar) and order_stability for choices; the spec reference describes each. A question with no configured threshold still reports measurements, marked measured rather than passing. Its measurements alone cannot fail CI. If a configured check lacks gold, the report marks it not assessed.
Two more kinds of check live in the same spec. Examples check named cases on each run; they do not prove what will happen on unseen rows. Metrics check a rule built from several answers, such as “stop the command if any question says yes”, against gold, with limits like max_missed.
Thresholds compare the point estimate, not the lower end of its interval. With only 30 reviewed rows the uncertainty can be wide; read the interval before choosing a limit.
What CI needs
test compares answers with gold, so CI needs both.
Gold is your answer key column and your *.reviews.csv files. Commit them.
Answers come from the store. test asks the engine for any it lacks, which in CI would mean paying on every pull request. Two things keep that small:
- Cache the store between runs. Answers are stored by their exact input, so a restored store is always safe to reuse, and only changed rows or questions are asked again.
- Always pass
--max-cost. If the missing answers would cost more,testasks nothing and exits 1.
TYPESAFE_API_KEY for Jev, or your engine’s key (Environment).
A GitHub Actions workflow
.github/workflows/judgments.yml
results_comment.py reads only the published results format, with the standard library; the step fetches it, or copy it into your repository and pin it. The job also needs permissions: pull-requests: write:
test also adds a table to the run’s summary page: per question, accuracy, its range and any failed check, and a line for each metric and for the examples. The same numbers are in the results file for any other CI.
The cache key changes every run and restore-keys picks the newest store, so answers asked in one run are there for the next. hunch uses the nearest .hunch/store.sqlite at or above the spec’s folder, or creates one at the repository root. Set HUNCH_STORE to choose another path.
To see what a pull request does to the answers, add a step with hunch diff evals/ --against git:origin/main --max-cost 0.50. It reports and does not fail the build.
Reading a failure
Exit 1 has two causes, and the last line of the log tells them apart. Here is the command guard tested with
--max-cost 0 on a fresh store, before any answers exist:
test writes its results to .hunch/target/, as JSON with a passed field; a stopped one writes nothing. See the results file.