Skip to content

feat(evals): add the skill eval suite and the checks that guard it - #261

Draft
ryzizub wants to merge 5 commits into
mainfrom
feat/skill-evals
Draft

ryzizub wants to merge 5 commits into
mainfrom
feat/skill-evals

Conversation

@ryzizub

@ryzizub ryzizub commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Description

Ports the eval suite and the CI checks that guard it from vgv-ai-flutter-plugin.

  • 47 claude plugin eval cases across 10 skills, each a directory under evals/<skill>/<case>/, discovered from the tree.
  • One neutral fixture every case symlinks to. evals/README.md is the spec: case format, grader reference, the traps that each cost us a false result, and what the suite cannot reach.
  • evals.yaml runs after a merge to main, scoped by --tag to the changed skills, with-plugin arm only, advisory. It needs the ANTHROPIC_API_KEY secret.
  • ci.yaml pins the Claude Code version, verifies every case's fixture.sh symlink, runs the hook test suite, and spell-checks YAML.

Runs grant Read, Glob, Grep and Skill, plus Write for the four cases whose subject is a document the skill writes — those read the file back with a { source: file, path: … } target. create-pr and rebase have no cases: disable-model-invocation: true puts them out of reach of any prompt.

Measured state: 24 of 47 cases pass at --threshold 0.8 on a single run each; an earlier two-arm run scored mean Δ +0.28. Reds are three different things and only one of them is a case defect: routing misses the skills are responsible for (7 cases in the last run), judge noise on single runs, and run-to-run variance — cases flip between 1.00 and red across runs of the same suite. That is why the suite is advisory and why evals/README.md says to confirm a red case with --runs 3.

The skill fixes these findings justify are in the PR stacked on top of this one.

Type of Change

  • New feature (feat)
  • Bug fix (fix)
  • Code refactor (refactor)
  • Documentation (docs)
  • CI change (ci)
  • Chore (chore)

🤖 Generated with Claude Code

- 47 `claude plugin eval` cases across 10 skills, discovered from the tree
- one neutral fixture every case symlinks to, with `evals/README.md` as the spec
- `evals.yaml` runs post-merge, scoped by `--tag` to the changed skills, advisory only
- CI pins Claude Code, verifies every case's fixture symlink, runs the hook tests, and spell-checks YAML

`create-pr` and `rebase` have no cases: `disable-model-invocation: true` puts them out of reach of any prompt.
A two-arm run of all 47 cases found the suite scoring the harness, not the
skills: graders asserting template wording a skill only writes into a file,
rubrics a blind judge could not satisfy, and prompts that stopped the skill
from firing at all.

- Prompts keep the task a task and name the read-only sandbox as a fact; the
  "do not edit anything, just describe it" phrasing killed routing in 5 of 5
  cases that tried it.
- Graders assert the vocabulary the reply really carries, with unstable judges
  converted to regex on the skill's own words.
- `evals/README.md` records both traps, plus the ceiling on skills that only
  speak through a file they write.

21 of 47 cases passed before this; 25 pass now, and the rest are findings about
the skills rather than broken cases.
@ryzizub
ryzizub added this pull request to stack #263 October 26, 2026 17:58
Four cases are about a file the skill produces — the plan's Implementation
Phases block, the brainstorm write-up — and were asserting that wording against
the chat reply, where it never appears. They now grant `Write` and read the
file back with a `files` target, which matches across everything the run wrote
and so never has to guess the filename the skill picked.

CI and the documented commands pass `--allow-tools Write`; without it those
cases score 0 with no failing content grader.
…e one

`target: files` matches the paths a run wrote, not what is inside them, so the
four document cases were asserting template wording against a list of filenames
and failing for a reason that had nothing to do with the skills. They now use
`{ source: file, path: … }` against a path the prompt asks for by name.

Writing a real plan also costs turns: both plan cases were hitting the 12-turn
cap and the 900-second timeout mid-write, which scores 0 with no failing grader
and reads as a content regression. Document cases now run 20 turns and 1500
seconds.

The `llm` grader on a 19k-character plan is gone for the reason the runner
itself prints — judges are noisy on long inputs. `evals/README.md` records all
three traps.
Both drive a triage, a fix, a test and a reduced review inside 12 turns;
`hotfix-refuses-to-skip-review-under-pressure` hit the cap mid-run, which
scores 0 with no failing grader and reads as a content miss.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant