From ad17a9798a0df86245f13b010e71ee1de1b9c00d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Jul 2026 03:39:02 +0000 Subject: [PATCH 1/2] docs: design exploration for a model-performance eval suite Captures the interactively-decided design for an in-repo evals/ suite: model-only diff-out tasks mined from git history across four domains (bugfix, feature, UI snapshot, balance/simulator), deterministic graders with an LLM judge on top, fast (~15 min) and slow (simulator) tiers. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01BxnJXgu63wex2CCtfuPy7G --- .../2026-07-15-model-eval-suite.md | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 docs/explorations/2026-07-15-model-eval-suite.md diff --git a/docs/explorations/2026-07-15-model-eval-suite.md b/docs/explorations/2026-07-15-model-eval-suite.md new file mode 100644 index 00000000..37a6ba37 --- /dev/null +++ b/docs/explorations/2026-07-15-model-eval-suite.md @@ -0,0 +1,254 @@ +# Exploring: an eval suite for measuring model performance on Quest + +**Status**: pre-commitment design, crystallized through an interactive Q&A +session (decisions logged below). Nothing here is implemented — graduate it +into an `/opsx:propose` change (or just build `evals/` directly, since this +is dev tooling, not game behavior) when someone is ready to build. + +**Prompted by**: "I would like to create an eval suite for measuring +performance of a model working on various aspects of quest." + +## Decisions locked in with the owner + +| Axis | Decision | +|---|---| +| Subject | **Model-only, scoped tasks** — not the full agent loop. Fixed context in, single answer out, deterministic grading. | +| Coverage | **Bug fixing**, **feature implementation**, **UI/TUI rendering**, **balance & simulation reasoning** (all four). | +| Task source | **Mined from git history** (real merged PRs, reverted to create tasks with known-good reference solutions). | +| Grading | **Deterministic gates + LLM judge** — tests/snapshots/simulators decide pass/fail; a rubric judge scores quality on top. | +| Task format | **Files in, diff out** — prompt + selected source files + failing output; model returns a unified diff. | +| Runtime budget | **Fast suite ≈ 15 min** for the main tier; simulator-graded tasks in a separate slow tier. | +| Location | **In-repo, `evals/`** directory. | +| Contamination | **Not a concern** — relative comparison between models/prompts is the use case. | + +## Why Quest is a good eval substrate + +The repo already contains the hard part of any coding eval — trustworthy, +deterministic graders: + +- **`cargo test`** with a large unit/integration surface, including the + save-compat corpus (`tests/fixtures/saves/`) that catches serde breakage. +- **UI snapshot tests** (insta + ratatui `TestBackend`) — committed `.snap` + files are pixel-exact ground truth for rendering tasks, and + `snapshot_rendering_is_deterministic` catches wall-clock/RNG leaks. +- **Seeded simulators** (`simulator --check-progression`, `deep_simulator`, + `voyage_simulator`) — objective graders for balance reasoning, a domain + most coding evals can't touch at all. +- **~754 merged PRs** of real history to mine (the working clone is shallow + at 50 commits; mining requires `git fetch --unshallow`). + +## Architecture + +``` +evals/ +├── README.md # how to run, how to add tasks +├── harness/ # Python runner (uv script, anthropic SDK) +│ ├── run.py # materialize → prompt → apply diff → grade → report +│ ├── judge.py # LLM judge pass over passing/failing diffs +│ └── mine.py # task-mining pipeline (see below) +├── tasks/ +│ ├── bugfix/qb-001-crit-double-dip/ +│ │ ├── task.yaml # metadata + grader spec (schema below) +│ │ ├── prompt.md # what the model is told +│ │ ├── bug.patch # applied to the eval base commit to create the task state +│ │ └── reference.patch# the known-good solution (never shown to the model) +│ ├── feature/ … +│ ├── ui/ … +│ └── balance/ … # slow tier +└── results/ # gitignored; JSON + markdown reports per run +``` + +### `task.yaml` schema + +```yaml +id: qb-001-crit-double-dip +domain: bugfix # bugfix | feature | ui | balance +tier: fast # fast | slow +source_pr: 412 # provenance, for auditing +context_files: # exactly what the model sees, in order + - src/combat/damage.rs + - src/core/constants.rs +show_failing_output: true # include grader output in the prompt +graders: # hard gates, all must pass + - cargo test --test combat_tests crit_ + - cargo test --lib combat:: +edit_allowlist: # diff may only touch these paths + - src/combat/** +judge_rubric: bugfix # which rubric judge.py applies +``` + +### One base commit, one warm build + +All fast-tier tasks are pinned to a **single eval snapshot commit** (a tag, +e.g. `eval-base-2026-07`), with each task's `bug.patch` rebased onto it +during mining. This is the key to the 15-minute budget: the harness builds +the snapshot once (warm `target/`), then each task is +apply-patch → incremental rebuild (~10–30 s) → targeted test filter. Tasks +that can't be rebased onto the snapshot are dropped or hand-adapted rather +than letting the suite fragment across base commits. + +The snapshot is re-cut deliberately (e.g. quarterly, or after a big system +lands like Act 2) and tasks re-validated against it — the mining pipeline +makes regeneration cheap. + +### Run flow per task + +1. `git worktree add` at the snapshot tag, apply `bug.patch`. +2. Render the prompt: `prompt.md` + full contents of `context_files` + + (optionally) the failing grader output, captured once at mining time so + the run doesn't pay for a red build. +3. One model call. The model must return a single fenced unified diff. +4. Apply with `git apply --3way`. If it fails to apply, **one** repair round + (the model sees only the apply error, not grader feedback), then fail as + `apply_error`. A `--strict` flag disables the repair round for pure + single-shot measurement. +5. Enforce the `edit_allowlist` — a diff touching tests, `.snap` files, + `evals/`, or anything outside the allowlist is an automatic + `illegal_edit` failure. This is what keeps graders trustworthy: + *the model can never re-bless a snapshot, edit a test, or touch the + harness.* +6. Run the graders. All green → **pass**; record which gate failed otherwise. +7. Judge pass (async, batched): rubric-scored 0–4 regardless of pass/fail. + +## The four domains + +### 1. Bug fixing (`bugfix/`, fast tier, ~25 tasks) + +Mined by reverse-applying real fix commits onto the snapshot. Grader = the +tests that shipped with (or already covered) the fix. Quest-specific +sub-flavors worth deliberately over-sampling because the repo's conventions +make them distinctive: + +- combat/damage-pipeline math (ordering of Giant's Might → Haven → + prestige → ascension → defense → crit) +- serde/save-compat regressions (grader: `save_compat_tests` on the corpus) +- RNG determinism leaks (grader: `snapshot_rendering_is_deterministic`) +- tick-loop timing (grader: `game_tick_tests`) + +### 2. Feature implementation (`feature/`, fast tier, ~15 tasks) + +Small, scoped features mined from history (a new title, a new fishing rank +tier, a new input keybinding routed through `handle_game_input`, a new +`TickEvent`). Grader = the tests that shipped with the feature. The prompt +states the required behavior precisely (derived from the PR description + +test names); the test *source* is withheld but expected test names are +listed, so the task is implementation, not spec-guessing. Full +add-a-minigame (15 integration points) is out of scope for model-only +single-shot — that belongs in a future agentic tier. + +### 3. UI / TUI rendering (`ui/`, fast tier, ~10 tasks) + +Perturb render code (layout math, style/color selection, responsive-tier +branching, overlay composition) and grade against the committed `.snap` +ground truth via `cargo test snapshot` filters. The edit allowlist +categorically excludes `src/ui/snapshots/` — an intentional-looking +re-bless is an `illegal_edit`. Determinism rules (freezable `ui/clock.rs`) +give a second grader for free on several tasks. + +### 4. Balance & simulation reasoning (`balance/`, **slow tier**, ~10 tasks) + +The distinctive domain. Two shapes: + +- **Restore**: revert a real balance retune (e.g. part of the era retune in + PR #731) and ask the model to restore progression, given the simulator's + failing assertion output. Grader: `simulator --check-progression` + (~2–5 min). +- **Hit a target**: "Ascension VII is reached too early at P200 speedrun; + adjust costs so it lands in tick range X–Y without breaking the other + scenarios." Grader: progression check + a task-specific assertion run. + +Slow tier runs on demand / nightly, not per-iteration. Where possible each +balance task also gets a *fast proxy grader* (a unit test asserting the +derived curve, e.g. cumulative ascension cost) so the fast suite still +carries a thin balance signal. + +## Mining pipeline (`mine.py`) + +1. `git fetch --unshallow`; list merged PRs via the GitHub API. +2. **Filter**: 5–300 changed lines in `src/`; must touch test files or be + covered by existing tests; exclude the heavy audit-log noise (the + majority of recent commits are 1-line `meta-audit` history appends — + subject-line and path filters remove them). +3. **Classify** domain by path (`src/combat|core` → bugfix/balance, + `src/ui` → ui, etc.) + subject keywords; human curates the final label. +4. **Validate** the task property that makes grading meaningful: + - graders **red** after `bug.patch` (task state), + - graders **green** after `reference.patch` (reference solves it), + - reference diff stays inside the `edit_allowlist`. + Tasks failing any leg are auto-rejected. +5. Emit the task directory; a human pass writes/edits `prompt.md` (mined + prompts start from the PR title/description, rewritten to describe the + *symptom*, not the solution). + +## LLM judge + +Runs after deterministic grading, never overrides it. Per-domain rubrics +scoring 0–4 on: + +- **Convention compliance** — the CLAUDE.md rules a test can't always catch: + seeded-RNG cleanliness in the tick loop, Haven-bonus-as-parameter (no + globals), `serde(default)` on new `GameState` fields, no wall-clock reads + in render code, comment discipline. +- **Minimality** — did the diff change only what the task required? +- **Solution match** — semantic proximity to `reference.patch` (informative, + not gating; legitimate alternative fixes score full marks if conventions + hold). + +Judge model pinned per suite version so scores are comparable across runs. + +## Metrics & reporting + +- **Primary**: pass@1 overall and per domain (all hard gates green). +- **Diagnostic funnel** per task: `apply_error` → `illegal_edit` → + `build_error` → `test_fail` → `pass`. Separating these matters: a model + that can't emit applicable diffs needs different work than one that + writes plausible-but-wrong fixes. +- **Secondary**: mean judge score (reported separately, never blended into + pass rate); pass@k optional via `--samples k`. +- Output: `results//report.{json,md}` — per-task rows plus domain + aggregates; markdown report designed for pasting into a PR/issue when + comparing two models or prompts. + +## Suite size and runtime (targets) + +| Tier | Tasks | Grading cost | Wall clock | +|---|---|---|---| +| Fast | ~50 (25 bugfix, 15 feature, 10 ui) | warm build + ~10–30 s incremental each | ≤ 15 min sequential after one-time snapshot build | +| Slow | ~10 balance | 2–5 min sim each | ~30–50 min, nightly/on-demand | + +Model-call latency overlaps with grading (call task N+1 while N grades), so +the model side shouldn't extend wall clock. + +## Deliberately out of scope (for now) + +- **Agentic tier** — full Claude Code sessions graded on final repo state + (where add-a-minigame, spec-workflow adherence, and `drive-game` visual + verification would live). The task schema above is designed so an agentic + runner could reuse the same task directories later (same patches, same + graders; just drop the `context_files` spoon-feeding). +- **Doc/wiki tasks** — gradeable only by judge, weakest signal; the audit + skills already cover this ground operationally. +- **Contamination mitigation** — explicitly waived; if the use case ever + shifts to absolute cross-lab claims, add post-cutoff-only mining and + symbol-renaming mutation. + +## Open questions + +1. **Snapshot cadence** — re-cut `eval-base` per quarter, or freeze it for + longitudinal comparability and accept growing drift from HEAD? (Leaning: + freeze per suite version `v1`, `v2`, …; never mutate a shipped version.) +2. **Feature-task test visibility** — names-only (proposed) vs. full test + source in the prompt. Names-only measures more, but a badly named test + makes the task unfair; curation has to catch that. +3. **Harness language** — Python + anthropic SDK is the fast path; a Rust + harness in-repo would dodge a toolchain but slow iteration. (Leaning + Python under `evals/harness/`, `uv` single-file scripts, repo stays + pure-Rust outside `evals/`.) + +## History + +- **2026-07-15** — initial design session. Eight design decisions taken + interactively (table at top); repo groundwork checked: shallow clone + (50 commits, `--unshallow` needed for mining), ~754 merged PRs upstream, + recent history dominated by 1-line audit-log commits (mining filter + required). From af69a84bdc3d4a7b1d464359e08888dd6c7d7b7d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Jul 2026 04:21:23 +0000 Subject: [PATCH 2/2] =?UTF-8?q?evals:=20v1=20model-eval=20suite=20?= =?UTF-8?q?=E2=80=94=20harness,=205=20validated=20seed=20tasks,=20miner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the eval-suite design (docs/explorations/2026-07-15-model-eval-suite.md): - evals/harness/: stdlib-only Python runner. run.py materializes each task in a scratch worktree (bug.patch on the pinned base commit), prompts the model (files in, one unified diff out), enforces per-task edit allowlists + a global denylist (no tests, no .snap re-bless, no harness edits), grades with the repo's own tests/snapshots/simulators, and reports an apply_error -> illegal_edit -> build_error -> test_fail -> pass funnel. validate mode proves every task honest: graders red on the bug state, green after reference.patch. judge.py adds rubric quality scores on top; mine.py lists/extracts task skeletons from git history. - evals/tasks/: 5 hand-authored seed tasks, all red/green-validated — 2 bugfix (damage-percent stacking, serde save-wipe), 1 ui (prestige gauge vs snapshots), 1 feature (shift-hotkey via input replay), and 1 slow-tier balance task graded by the progression simulator. - make eval-validate target; evals/results/ + __pycache__/ gitignored; CLAUDE.md pointer and design-doc history entry. Reference-mode end-to-end run passes 4/4 on the fast tier; the balance task validates red/green against the release simulator. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01BxnJXgu63wex2CCtfuPy7G --- .gitignore | 4 + CLAUDE.md | 10 + Makefile | 7 +- .../2026-07-15-model-eval-suite.md | 39 +- evals/README.md | 127 +++++++ evals/config.toml | 38 ++ evals/harness/judge.py | 95 +++++ evals/harness/lib.py | 347 ++++++++++++++++++ evals/harness/mine.py | 189 ++++++++++ evals/harness/rubrics/balance.md | 18 + evals/harness/rubrics/bugfix.md | 18 + evals/harness/rubrics/feature.md | 17 + evals/harness/rubrics/ui.md | 17 + evals/harness/run.py | 268 ++++++++++++++ .../balance/qbal-001-meadow-wall/bug.patch | 17 + .../qbal-001-meadow-wall/failing_output.txt | 69 ++++ .../balance/qbal-001-meadow-wall/prompt.md | 20 + .../qbal-001-meadow-wall/reference.patch | 17 + .../balance/qbal-001-meadow-wall/task.toml | 9 + .../bugfix/qb-001-armory-stacking/bug.patch | 21 ++ .../qb-001-armory-stacking/failing_output.txt | 36 ++ .../bugfix/qb-001-armory-stacking/prompt.md | 18 + .../qb-001-armory-stacking/reference.patch | 21 ++ .../bugfix/qb-001-armory-stacking/task.toml | 9 + evals/tasks/bugfix/qb-002-save-wipe/bug.patch | 12 + .../qb-002-save-wipe/failing_output.txt | 67 ++++ evals/tasks/bugfix/qb-002-save-wipe/prompt.md | 20 + .../bugfix/qb-002-save-wipe/reference.patch | 12 + evals/tasks/bugfix/qb-002-save-wipe/task.toml | 9 + .../feature/qf-001-shift-hotkeys/bug.patch | 13 + .../qf-001-shift-hotkeys/failing_output.txt | 36 ++ .../feature/qf-001-shift-hotkeys/prompt.md | 17 + .../qf-001-shift-hotkeys/reference.patch | 13 + .../feature/qf-001-shift-hotkeys/task.toml | 9 + .../tasks/ui/qu-001-prestige-gauge/bug.patch | 16 + .../qu-001-prestige-gauge/failing_output.txt | 99 +++++ .../tasks/ui/qu-001-prestige-gauge/prompt.md | 17 + .../ui/qu-001-prestige-gauge/reference.patch | 16 + .../tasks/ui/qu-001-prestige-gauge/task.toml | 9 + 39 files changed, 1778 insertions(+), 18 deletions(-) create mode 100644 evals/README.md create mode 100644 evals/config.toml create mode 100644 evals/harness/judge.py create mode 100644 evals/harness/lib.py create mode 100644 evals/harness/mine.py create mode 100644 evals/harness/rubrics/balance.md create mode 100644 evals/harness/rubrics/bugfix.md create mode 100644 evals/harness/rubrics/feature.md create mode 100644 evals/harness/rubrics/ui.md create mode 100644 evals/harness/run.py create mode 100644 evals/tasks/balance/qbal-001-meadow-wall/bug.patch create mode 100644 evals/tasks/balance/qbal-001-meadow-wall/failing_output.txt create mode 100644 evals/tasks/balance/qbal-001-meadow-wall/prompt.md create mode 100644 evals/tasks/balance/qbal-001-meadow-wall/reference.patch create mode 100644 evals/tasks/balance/qbal-001-meadow-wall/task.toml create mode 100644 evals/tasks/bugfix/qb-001-armory-stacking/bug.patch create mode 100644 evals/tasks/bugfix/qb-001-armory-stacking/failing_output.txt create mode 100644 evals/tasks/bugfix/qb-001-armory-stacking/prompt.md create mode 100644 evals/tasks/bugfix/qb-001-armory-stacking/reference.patch create mode 100644 evals/tasks/bugfix/qb-001-armory-stacking/task.toml create mode 100644 evals/tasks/bugfix/qb-002-save-wipe/bug.patch create mode 100644 evals/tasks/bugfix/qb-002-save-wipe/failing_output.txt create mode 100644 evals/tasks/bugfix/qb-002-save-wipe/prompt.md create mode 100644 evals/tasks/bugfix/qb-002-save-wipe/reference.patch create mode 100644 evals/tasks/bugfix/qb-002-save-wipe/task.toml create mode 100644 evals/tasks/feature/qf-001-shift-hotkeys/bug.patch create mode 100644 evals/tasks/feature/qf-001-shift-hotkeys/failing_output.txt create mode 100644 evals/tasks/feature/qf-001-shift-hotkeys/prompt.md create mode 100644 evals/tasks/feature/qf-001-shift-hotkeys/reference.patch create mode 100644 evals/tasks/feature/qf-001-shift-hotkeys/task.toml create mode 100644 evals/tasks/ui/qu-001-prestige-gauge/bug.patch create mode 100644 evals/tasks/ui/qu-001-prestige-gauge/failing_output.txt create mode 100644 evals/tasks/ui/qu-001-prestige-gauge/prompt.md create mode 100644 evals/tasks/ui/qu-001-prestige-gauge/reference.patch create mode 100644 evals/tasks/ui/qu-001-prestige-gauge/task.toml diff --git a/.gitignore b/.gitignore index 1c48a5fb..0d413eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,7 @@ Thumbs.db # insta pending snapshots (accepted snapshots in src/**/snapshots/ ARE committed) *.snap.new *.pending-snap + +# model-eval run artifacts (evals/tasks/ and the harness ARE committed) +evals/results/ +__pycache__/ diff --git a/CLAUDE.md b/CLAUDE.md index 8b838931..60aecb06 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -141,6 +141,16 @@ Larger modules have their own `CLAUDE.md` with implementation patterns, integrat | Vessel | `src/vessel/` | [CLAUDE.md](src/vessel/CLAUDE.md) | Act 2: Vessel launch gate + Voyage engine, dark behind the `ACT2_ENABLED` kill-switch (`QUEST_ACT2=1` to preview) | | Main Helpers | `src/main_helpers/` | [CLAUDE.md](src/main_helpers/CLAUDE.md) | Orchestration between main.rs and domain modules | +### Model Evals (`evals/`) + +A model-performance eval suite over this codebase: scoped "files in, diff +out" tasks graded by the repo's own tests/snapshots/simulators. Tasks are +pinned to `evals/config.toml`'s `base_commit`; `make eval-validate` proves +every fast-tier task is still honest (graders red on the bug state, green on +the reference fix) — run it when touching `evals/` or re-cutting the base +commit. Design rationale: `docs/explorations/2026-07-15-model-eval-suite.md`; +operational docs: [evals/README.md](evals/README.md). + ### Simulators **Game Simulator** (`src/bin/simulator/`): Headless game balance simulator calling `game_tick_with_context()` with no UI/delay. Supports `--ticks`, `--seed`, `--prestige`, `--runs`, `--strategy ` (casual/optimal/speedrun), `--stormbreaker`, `--assertions`, `--check-progression`. Strategy profiles inject challenge wins, enhancement, sigils, ascension, and auto-prestige. diff --git a/Makefile b/Makefile index e760bb17..6b7f935b 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ # `/opsx:*` skills' bare `openspec ...` commands behave predictably. OPENSPEC_VERSION := 1.5.0 -.PHONY: check fmt lint test build audit all clean install setup openspec-setup coverage coverage-html coverage-check +.PHONY: check fmt lint test build audit all clean install setup openspec-setup coverage coverage-html coverage-check eval-validate # Run all PR checks locally (uses same script as CI) check: @@ -62,6 +62,11 @@ coverage-check: --ignore-filename-regex "(ui/|utils/updater|utils/build_info|tick_events)" \ --fail-under-lines 90 +# Integrity-check the model-eval task suite (red on bug, green on reference). +# Fast tier only; add "--tier all" manually to validate simulator-graded tasks. +eval-validate: + @python3 evals/harness/run.py validate + # Clean build artifacts clean: @cargo clean diff --git a/docs/explorations/2026-07-15-model-eval-suite.md b/docs/explorations/2026-07-15-model-eval-suite.md index 37a6ba37..99d48997 100644 --- a/docs/explorations/2026-07-15-model-eval-suite.md +++ b/docs/explorations/2026-07-15-model-eval-suite.md @@ -58,23 +58,21 @@ evals/ └── results/ # gitignored; JSON + markdown reports per run ``` -### `task.yaml` schema - -```yaml -id: qb-001-crit-double-dip -domain: bugfix # bugfix | feature | ui | balance -tier: fast # fast | slow -source_pr: 412 # provenance, for auditing -context_files: # exactly what the model sees, in order - - src/combat/damage.rs - - src/core/constants.rs -show_failing_output: true # include grader output in the prompt -graders: # hard gates, all must pass - - cargo test --test combat_tests crit_ - - cargo test --lib combat:: -edit_allowlist: # diff may only touch these paths - - src/combat/** -judge_rubric: bugfix # which rubric judge.py applies +### `task.toml` schema + +(TOML rather than YAML: Python 3.11's stdlib `tomllib` keeps the harness +zero-dependency.) + +```toml +id = "qb-001-armory-stacking" +domain = "bugfix" # bugfix | feature | ui | balance +tier = "fast" # fast | slow +source = "hand-authored" # or "mined:" for provenance +context_files = ["src/combat/player_attack.rs", "src/combat/events.rs"] +show_failing_output = true # include cached grader output in the prompt +graders = ["cargo test --test combat_tests"] # hard gates, all must pass +edit_allowlist = ["src/combat/"] # diff may only touch these +judge_rubric = "bugfix" # which rubric judge.py applies ``` ### One base commit, one warm build @@ -252,3 +250,10 @@ the model side shouldn't extend wall clock. (50 commits, `--unshallow` needed for mining), ~754 merged PRs upstream, recent history dominated by 1-line audit-log commits (mining filter required). +- **2026-07-15 (same day)** — v1 implemented in `evals/` on this design: + stdlib-only Python harness (`run.py` / `mine.py` / `judge.py`), TOML task + metadata (deviation from the yaml sketch above, noted inline), and five + hand-authored seed tasks (2 bugfix, 1 ui, 1 feature, 1 slow-tier + balance), each red/green-validated against the real graders. See + `evals/README.md` for the operational docs; this exploration stays as + the rationale record. diff --git a/evals/README.md b/evals/README.md new file mode 100644 index 00000000..8d6886a0 --- /dev/null +++ b/evals/README.md @@ -0,0 +1,127 @@ +# Quest model-eval suite + +Measures how well a model works on Quest's codebase using scoped, +deterministic tasks: the model gets a symptom description + selected source +files + failing check output, and must return one unified diff. The harness +applies the diff in an isolated worktree and grades it with the repo's own +graders (tests, snapshot tests, seeded simulators). + +Design rationale: [docs/explorations/2026-07-15-model-eval-suite.md](../docs/explorations/2026-07-15-model-eval-suite.md). + +## Quick start + +```bash +# Integrity-check every fast task (no API key needed): +python3 evals/harness/run.py validate + +# Dry-run the full pipeline using the reference solutions as "the model": +python3 evals/harness/run.py run --reference + +# Evaluate a real model (needs ANTHROPIC_API_KEY + `pip install anthropic`): +python3 evals/harness/run.py run --model claude-sonnet-5 + +# Include the slow tier (simulator-graded balance tasks): +python3 evals/harness/run.py run --tier all --model claude-sonnet-5 + +# Judge pass over a finished run (quality scores on top of pass/fail): +python3 evals/harness/judge.py evals/results/ +``` + +Reports land in `evals/results/-