Evaluation Harness
This module instantiates a public task bundle into an isolated run directory,
runs one source-native Claude Code QueryEngine session, executes hidden judge
attempts, and writes compact JSONL trajectories for later skill extraction.
Source-Native Architecture
The harness entrypoint calls runSourceTaskLoop, which creates exactly one SourceClaudeSessionAgent for the run. That session
constructs QueryEngine directly from the local Claude source and reuses it
across judge feedback rounds.
Per run:
createTaskRuncopies only public task files intoruns/<run_id>/public.resolveTaskRuntimeverifies the task Python before agent startup.SourceClaudeSessionAgentbuilds a minimal tool pool from Claude source tools plus the in-processfinalize_submissiontool.createHarnessCanUseToolenforces run-local read/write policy for tool use.DefaultJudgeRunnercopies private judge assets into.judge_privateonly when a judge attempt is triggered.
Batch mode is source-only: repeated --task values are dispatched as one worker
process per run. The removed legacy runtime is rejected explicitly.
Loop Semantics
max_rounds means maximum judge attempts, not maximum agent tool calls. A judge
attempt is triggered only when the agent calls finalize_submission and output
validation passes against the public output contract. Validation failures are
returned as recoverable tool feedback and do not consume a judge round.
Natural-language messages such as "done" are ignored. If an agent turn ends
without a passing finalize_submission, the harness gives exactly one
same-round no-finalize recovery prompt. Recovery does not auto-validate,
auto-submit, or auto-judge; if it still ends without a passing
finalize_submission, the run fails or times out without a judge attempt.
Missing workspace/plan.md or workspace/plans/round_NN.md files are recorded
as warnings, not hard blockers, when outputs are otherwise valid.
Task Visibility
Agent-visible paths are limited to the current run:
public/: read-only public task bundle.workspace/: writable solver code, notes, and scratch files.outputs/: writable final submission files.logs/agent/: writable agent logs.
Private evaluation/, std_code/, reference output, and judge data paths are
not copied into the agent-visible workspace. They are available only to the
external judge under runs/.judge_private/<run_id>/.
The initial prompt now includes a compact public file manifest, output contract,
visible case summary, and the full public README. No public/HARNESS_HINTS.md
file is generated.
Runtime Resolution
The harness resolves Python once before creating the Claude session. It reads
public/envs/env_manifest.json, chooses the platform-specific Python path, and
falls back to conventional runtime locations:
- Windows:
public/envs/runtime/.venv/Scripts/python.exe - POSIX/WSL:
public/envs/runtime/.venv/bin/python - POSIX/WSL alternate:
public/envs/runtime/.venv-posix/bin/python
If no runtime exists, the run exits as infra_error; the agent is not asked to
repair virtual environments or install packages.
Virtual-environment directories are linked into the run instead of copied, so a
run does not spend minutes duplicating site-packages.
Trajectories
SourceTrajectoryWriter writes two append-only files:
logs/trajectory.clean.jsonl: compact training-friendly records.logs/trajectory.raw.jsonl: raw source events for debugging.
Static context is written once as run_context. Judge feedback is compacted
before being sent as a continuation prompt in the same session, while the raw
judge JSON stays in trajectory.raw.jsonl for debugging.
Clean trajectories also record validation pass/fail events, run warnings, and
no-finalize recovery markers. Raw trajectories preserve source events exactly;
clean trajectories filter standalone punctuation-only assistant text such as
. or ....
CLI
bun src/harness/evaluation/cli.ts --task <task_id> --runs-dir output/runs --max-rounds 3 --timeout-seconds 1800 --temperature 1 --thinking disabled
--system-prompt <path> is a debug-only explicit override. Normal source-native
runs use the built-in lean system contract plus the generated initial prompt;
there is no default config/AGENT.md.
The default LLM options are --thinking disabled --temperature 1. With
thinking disabled, temperature is sent to the model. With --thinking adaptive,
temperature is intentionally omitted and logged as ignored in run metadata.
--max-turns-per-round <n> caps agentic turns within one judge round. It is
optional; full implementation regressions usually leave it unset and rely on
--timeout-seconds as the whole-loop hard timeout. Set a cap when diagnosing
no-finalize loops or running short smoke tests.