# os-adr Eval A — prompted skill-execution across model tiers _Last updated: 2026-07-03 — harness built and self-tested (perfect-run PASS, untouched-sandbox FAIL, for all six scenarios)._ Measures whether a **given model tier** (haiku, sonnet, …) can correctly execute the os-adr skills when explicitly invoked. This is **not** the held-out unprompted-behavior eval (requirements 4–5, "Eval B") — those scenarios stay deferred and must not be run informally (see `docs/adr-system/06-eval-scenarios.md`). Eval A prompts are not held-out; they may be read, discussed, and iterated against freely. **Metric:** pass rate over the scenario × model grid, scored by the deterministic checker. The model-sensitive surface under test is skill-*following* (reading SKILL.md and doing what it says: right CLI, right args, right judgment calls). Skill *dispatch*, the CLIs, hook, and index are deterministic and covered by the plugin's own 62 tests. ## Layout | Path | What | | --- | --- | | `fixture/project/` | 4-ADR project (incl. a superseded pair) — scenarios S1–S4 | | `fixture/legacy-project/` | monolithic `DECISIONS.md`, no `docs/adr/` — scenarios S5–S6 | | `scenarios/S1..S6.md` | task prompt (verbatim block) + what the checker asserts | | `bin/sandbox ` | fresh git-initialized sandbox copy of the right fixture | | `bin/check [--tsv ]` | deterministic scorer; exit 0/1; TSV mode for autoresearch | | `runner-prompt.md` | the prompt template for the model under test | | `bin/run-headless ` | `claude -p` fallback runner (costlier) | Scenarios: S1 create · S2 create+supersede · S3 find/conflict · S4 find/distractor · S5 init · S6 migrate+fills. S3/S4 need the model's final answer saved to `/ANSWER.md` (the runner prompt instructs the model to write it; if a subagent only returns text, the driver saves that text to `ANSWER.md` before checking). ## Running the grid in-session (preferred — cheaper than `claude -p`) A driver session (any model) runs, for each cell of {S1..S6} × {haiku, sonnet}: 1. `eval/bin/sandbox S3 /tmp/adr-eval/S3-haiku-r1` 2. Render `runner-prompt.md` (`{{SANDBOX}}`, `{{PLUGIN_ROOT}}` = the plugin dir, `{{SKILL}}`, `{{TASK}}` = the scenario file's Task block) and spawn it as an **Agent tool subagent with `model:` pinned to the tier under test**. Spawn independent cells in parallel. 3. Ensure `ANSWER.md` exists (write the subagent's returned text there if it didn't). 4. `eval/bin/check S3 /tmp/adr-eval/S3-haiku-r1 --tsv haiku >> results.tsv` 12 cells ≈ 12 subagent runs per round. Pass rate = `grep -c PASS results.tsv` / total. **Fidelity caveats vs a real interactive session** (accepted for Eval A): no SessionStart hook context (irrelevant — these are explicit invocations), no slash-command dispatch (deterministic plumbing), subagent system prompt differs slightly from an interactive session. The headless runner exists when full fidelity matters. ## Optimizing with `/autoresearch` (Classic mode) Invoke in a driver session at the cc-os root: ``` /autoresearch Goal: raise the os-adr skill-execution pass rate on weak models by tightening SKILL.md wording Scope: plugins/os-adr/skills/*/SKILL.md ONLY — never edit bin/, lib/, tests/, or anything under eval/ Metric: pass rate over the {S1..S6} x {haiku, sonnet} grid via plugins/os-adr/eval/bin/check --tsv Verify: run the in-session grid per plugins/os-adr/eval/README.md, append all 12 TSV lines to the round's results.tsv, report pass rate and per-cell failures Iterations: 5 ``` Ground rules the loop must respect: - **Scope is the guard against metric-gaming**: the checker, fixtures, scenarios, and runner prompt are frozen during a loop. If a scenario or checker turns out to be wrong, stop the loop and fix it as a separate, human-reviewed change. - Keep/discard on the **haiku** column first — a wording change that helps haiku and is neutral for sonnet is a keep; one that regresses sonnet is a discard. - Failures in `results.tsv` column 4 name the exact broken invariant (e.g. "0001 status ... != Superseded") — feed that string into the next modify step. - SKILL.md edits must not contradict the plugin's `invariants.md` (e.g. never suggest hand-editing the index). Run `ruby tests/all.rb` after each accepted edit as a regression gate. ## Adding a scenario Add `scenarios/S7.md` (Task block + criteria), a `S7` class in `bin/check`, the fixture route in `bin/sandbox`, then self-test both directions: simulate a perfect run with the CLIs (must PASS) and check an untouched sandbox (must FAIL).