*.eval.ts file and declared with defineEval.
It reads like a unit test, but the output of the system under test is nondeterministic. The same eval case runs several times according to the Experiment’s attempts. Each run is one Attempt, and together they give a pass rate or a score.
What an eval case contains
An eval case does not declare which Agent to use, so the same eval case can run against different Agents under different Experiments. The Agent is an Experiment field, and the CLI does not override it ad hoc.
Do not write
id or name by hand. NiceEval derives the ID from the file path.Path is identity
evals/weather/brooklyn.eval.ts has the ID weather/brooklyn. Positional arguments after the Experiment name filter by ID prefix:
terminal-swe-bench also matches terminal-swe-bench-astropy-1, and the next character does not have to be /.
Lifecycle
1
Discover
The Runner loads
*.eval.ts files and Fixture directories under evals/.2
Schedule
It combines concurrency, result reuse,
attempts, and earlyExit to produce the Attempts for this run.3
Call the system under test
t.send() calls the Adapter selected by the Experiment and receives a standard Turn.4
Check
NiceEval records every check: value assertions, assertions on the Turn and Session, Judge scores, and each item’s score contribution.
5
Judge the outcome
A pass/fail eval combines the check results into a final verdict; a scored eval accumulates a score.
6
Save and report
The terminal and Reporters output results; the Run and published Attempts are written to
.niceeval/record.sqlite.Four verdicts
Each Attempt of a pass/fail eval gets exactly one of four verdicts:passed
Every required Boolean check is satisfied, every measurement with
.gate(minimum) reaches its minimum, and no execution error occurred.failed
At least one required Boolean check is not satisfied, or a measurement with
.gate(minimum) falls below its minimum.errored
An execution exception, a timeout, or a mistake in the eval code means this run cannot reach a trustworthy conclusion.
skipped
The eval case skipped itself, usually with
t.skip(reason).0. Reports show the score by default and do not count it toward the pass rate, but the verdict is still kept. A result with a failed verdict does not enter the success ranking even if its score was fully computed.
The points in .score(points) is the weight of that item, not the total score. Reports do not convert scores to percentages automatically. When one Experiment contains both kinds of evals, the report shows the pass rate and the score separately.
Verdicts and measurements
In pass/fail evals, Boolean checks affect the verdict by default. In scored evals, Boolean checks are only recorded by default. Continuous measurements and Judge scores are numbers between 0 and 1. Both kinds of evals use.gate(minimum) to set a minimum, and falling below it gives failed. In a scored eval, the score already earned is kept when a gate is not met. See Assertion and Match for the complete rules.
The *.eval.ts convention
Only files ending in .eval.ts are discovered. Directories only form ID prefixes:
Array exports and data-driven tests (dataset fan-out)
A file can also default-export an array ofdefineEval(...) calls, generating multiple eval cases from the same logic:
sql/0000 and sql/0001. See Data-driven tests.
Related reading
- Experiment — The other half: what to evaluate and how to run it, and why it is separate from eval cases.
- Assert — Assertion and verdict rules.