> ## Documentation Index
> Fetch the complete documentation index at: https://checkfu.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Evaluate an agent against a task set

> Compile an open task directory into graded-Session inputs and understand the planned verifier-to-Outcome mapping.

"Did my change make the agent worse?" is the question an eval answers. Checkfu
does not add a second evaluation subsystem for it: a task is an **ingestion
shape**, not a stored entity, and every task compiles into the ordinary graded
Session inputs you already use. The planned live integration will reconcile the
verifier a task carries into an Outcome verdict through the same grading
chokepoint as any other evaluation, never beside it.

This guide covers the open task directory format Checkfu reads, the compile-only
resources available today, and how the ROADMAP-owned live slice is intended to
map the verifier's reward onto `outcome.*` events.

## The task directory

A task directory is the open Harbor / Terminal-Bench lineage format: an
instruction, a config, an environment reference, and a verifier that writes a
reward file.

```
my-task/
  task.toml         # name, environment, verifier contract
  instruction.md    # the prompt the agent receives
  tests/
    run.py          # the verifier: writes /logs/verifier/reward.txt
```

`task.toml` declares the environment and the verifier:

```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
name = "sort-array"
max_iterations = 2

[environment]
image = "python:3.12-slim"

[verifier]
command = ["python", "/tests/run.py"]
reward_format = "reward_text"
pass_threshold = 1.0
```

`instruction.md` is the authoritative drive and accepts 1–4,096 characters,
the same bound as the Outcome description it becomes. For Terminal-Bench
compatibility, `prompt.md` is used only when `instruction.md` does not exist;
an unreadable `instruction.md` is an error rather than permission to select the
fallback. Every selected task file must be a regular, fatal-UTF-8 file no larger
than 1,048,576 bytes; symlinks and other non-regular entries are rejected. Both
`eval task` and `eval experiment` use this same loader. Experiment discovery
ignores a candidate only when its `task.toml` is genuinely absent: a symlink,
FIFO, directory, oversized file, or invalid byte stream is a visible error and
stops the experiment before any Session is created. The verifier contract is a
bounded, non-empty argv whose members are all non-empty strings — never a shell
string. The live execution slice will run it in the session sandbox after the
agent settles and read its reward from
`/logs/verifier/reward.txt` (a float in `0`–`1`) or
`/logs/verifier/reward.json` (`{ "reward": 0.0 }`).

## Compile a task into graded-Session inputs

`checkfu eval task <dir>` reads the directory, validates it, and compiles it
into the ordinary Checkfu resources one isolated graded Session needs:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
checkfu eval task ./my-task
```

The instruction becomes the Outcome **description**. Today the Outcome
**rubric** truthfully asks Checkfu's ordinary grader to judge the settled result
against that instruction. The verifier contract is preserved as a separate
future input; it is not posted as though Checkfu executed it or read its reward.
The ROADMAP-owned grading integration will replace this current posture when it
can run the verifier and reconcile its reward. The environment maps to a named
base SandboxProfile.
The default output is a complete, terminal-safe JSON-escaped human rendering:
it preserves the full description and rubric, the environment's discriminant
and content, the verifier argv boundaries, reward format, and pass threshold.
Task-controlled terminal, Unicode line, and bidirectional controls are emitted
only through valid JSON escapes. Native JSON serialization uses its standard
short forms for several C0 controls (for example, `\n` and `\t`); any remaining
raw DEL/C1, Unicode line/paragraph, or D97 bidirectional control is normalized
to a four-hex-digit `\uXXXX` escape. Escaping changes presentation without
changing the compiled value. The compiled Outcome definition contains the
description, rubric, and iteration-budget fields of a future
`user.define_outcome` drive; a live caller additionally supplies event framing
and attribution. This command does not create a Session; the live
verifier-backed slice owns one-task/one-Session execution and minted-identity
isolation.

Pass `--json` to read the same complete compiled resources as one terminal-safe
machine document. A JSON parser reconstructs the exact original values:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
checkfu eval task ./my-task --json
```

This command is distinct from `checkfu eval` (Blueprint plan evaluation, which
judges an authoring project's plan and cannot authorize promotion). The two
instruments are never conflated.

## Compare harnesses under controlled conditions

`checkfu eval experiment <dir>` can run the same task set against multiple
published AgentDefinitions. Give every lane a stable label, repeat the sample
enough times to expose variance, and request the machine report:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
checkfu eval experiment ./tasks \
  --agent checkfu=agent_... \
  --agent claude=agent_... \
  --agent codex=agent_... \
  --agent pi=agent_... \
  --repeat 5 \
  --principal prin_... \
  --json
```

Before creating a Session, matrix mode reads each lane's latest published
AgentVersion, resolves its public HarnessProfile, and refuses the run unless
every non-harness definition control matches: model routing profile and tier, sandbox
profile, tools, instructions, Skills,
exposure and compaction policy, output schema, PermissionAssignment scopes, mounts, lifecycle hooks,
and the remaining frozen fields. Active AgentDefinition-scoped Budget policies
must also match; Workspace- and Principal-scoped Budgets are already common
because every sample uses the same Workspace and Principal. Each lane must use
a distinct active AgentDefinition and harness profile. A matrix is bounded to
1,000 Sessions (`tasks × lanes × repetitions`) so a broad directory or typo
cannot silently create an unbounded bill.

The report does not trust that preflight snapshot after work begins. It reads
every `run.created.execution_pins` and `model.routed` event and fails control
equivalence if a Session used a different AgentVersion, harness profile, model
model routing profile revision, realized model/tier, harness driver, SandboxProfile/image, or
plane policy. Unpinned and `@latest` harness references are resolved to the
current profile version before the first sample, and that resolved profile and
immutable release digest must remain constant across every sample in the lane;
both coordinates are included in the report.
Per lane it reports pass rate and population variance for iteration count,
tokens, active latency, tool calls, retries, tool failures, compactions, and
recoveries. Optional cost dimensions also report observed and missing sample
counts; missing measurements remain unknown and are never scored as zero. A
JSON report is emitted even when a sample fails; the command exits zero only
when every Outcome is `satisfied` and runtime controls remained equivalent.

The task directories can mix coding and operational tasks. This experiment
currently uses the ordinary Outcome grader described above: it does not claim
to run the task's retained verifier or realize its environment until the live
verifier-backed ROADMAP slice lands.

## Observe one production harness release

Controlled experiments answer whether two harness lanes differ under frozen
inputs. After a release has real traffic, `checkfu eval observe` answers a
narrower question: what behavior did one exact harness release exhibit across
an explicit set of existing Sessions?

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
checkfu eval observe \
  --profile hprof_...@7 \
  --session sess_... \
  --session sess_... \
  --minimum-samples 30 \
  --max-transient-retries-per-turn 0.05 \
  --max-overflow-recoveries-per-turn 0.01 \
  --json
```

The command reads only the named Sessions through the public event-list API.
It accepts at most 500 unique Sessions and 10,000 events per Session, and it
never lists an ambient customer population or changes any Session. Every
sample must prove the requested exact HarnessProfile and the cohort must
resolve to one immutable release digest. Every named Session must contribute a
completed turn, and the machine report records its last observed event sequence
so the measured append-only prefix is explicit. Recovery counters must be
present on every completed turn; an older or third-party harness that omits
them is reported as missing evidence, never as zero retries.

Without reviewed limits, complete evidence is marked ready for human review.
With limits, the report says whether measured retries and overflow recoveries
are within them or need review. This is decision support, not an auto-tuner:
the command does not mutate a HarnessProfile, AgentDefinition, model route, or
harness configuration.

## How the verifier reward is intended to become a verdict

Verifier-not-judge is the intended posture, matching how Checkfu proves its own
claims: the verifier program — not a model judge — will decide whether the work
satisfied the task. The platform-free reconciliation mapping below is built and
tested, but the live grading chokepoint does not yet run the task verifier or
read its reward. Once that ROADMAP slice lands, a settled Run with an active
Outcome will reconcile the reward as follows:

* A reward at or above `pass_threshold` (default `1.0`) settles the Outcome
  **satisfied**.
* A lower reward produces **needs\_revision**, driving the grade-and-revise loop
  until the iteration budget exhausts, at which point the chokepoint converts the
  terminal **max\_iterations\_reached**.

A reward that cannot be read or is out of range is a retryable grading failure,
never a verdict — the same posture as an undecodable model reply. No reward
writes an Outcome except through the grading chokepoint (law 7): evaluation
enforcement is domain truth on the event surface, not observability.

## Honest gaps in this version

Two design questions the plan records as open are answered at the honest floor
rather than silently:

* **SandboxProfile realization.** A task names a base SandboxProfile by `image`. A
  task Dockerfile is read, preserved in full in both output modes, and recorded
  as an unrealized `image_build` gap — v1 does not content-hash it into a derived
  image, so the surface says exactly what it can run.
* **Live execution.** This surface compiles and validates a task directory into
  the resources a graded Session needs. The existing `eval experiment` command
  can drive those Outcome fields through public Session APIs, but it does not
  realize the task SandboxProfile or execute the task verifier. The customer-eval
  ROADMAP item retains ownership of that complete verifier-backed loop: realizing
  the SandboxProfile, driving one isolated Session against a target, running the
  verifier in the sandbox, reconciling its reward through the Outcome chokepoint,
  writing a run manifest under `.local/`, exporting the format in reverse, and
  documenting the result. No server-side eval entity exists: an "eval run" is a
  client-side composition whose results are projections of session events, and
  retained manifests are local artifacts.
