Skip to content

Add promptfoo-based skill eval suite (Phase 1) - #58

Open
nonrational wants to merge 12 commits into
mainfrom
skill-eval-suite
Open

Add promptfoo-based skill eval suite (Phase 1)#58
nonrational wants to merge 12 commits into
mainfrom
skill-eval-suite

Conversation

@nonrational

Copy link
Copy Markdown
Owner

Problem

Two skills (code-comment-register, prose-register) ship evals.json suites, but each carries its own ~600-line bespoke run-evals.mjs — near-duplicates of each other — and nothing runs the evals as config changes. Skill behavior that was pinned down by hand can silently regress.

Motivation

Skill workflows should be independently testable units: change a skill, run its evals, see whether the behavior you liked still holds. A shared runner is also the foundation for CI (Phase 2: validate-always, path-filtered full runs) without maintaining a per-skill runner copy per suite.

Proposed Solution

A new top-level evals/ npm package with promptfoo as the runner and evals.json kept as the canonical authored format (spec: docs/superpowers/specs/2026-08-29-skill-eval-suite-design.md, plan alongside):

  • tests.mjs generator reads home/.agents/skills/*/evals.json and emits one promptfoo test per case; answer-key fields never enter the subject prompt.
  • providers/subject.mjs spawns claude -p with cwd at the repo root, so the Skill tool and project skills are in the loop; a promptfooconfig.compare.yaml adds the skill-hidden baseline condition (successor to the old --compare).
  • Discrimination/detection grade deterministically via assert modules ported byte-for-byte from the old runner; transformation grades via llm-rubric (judge pinned to claude-sonnet-5).
  • bin/validate.mjs (offline, zero tokens) and bin/check-gate.mjs (deterministic cases must all pass; 90% suite floor) behind make eval-validate / make eval SKILL=<name> / make eval-compare SKILL=<name>.
  • Live parity run before retirement: 11/12 deterministic cases matched the old runner; the exception (disc-09) was model-response variance against the shared keyword-overlap threshold, with prompts and graders verified byte-identical. The code-comment-register runner is deleted; prose-register's stays until Phase 2.

36 unit tests (cd evals && npm test), all offline; make preflight untouched and green.

Feedback

  • The llm-rubric judge path has not run live — no ANTHROPIC_API_KEY in the dev environment. First keyed make eval SKILL=code-comment-register verifies it; the failure mode is loud (judge errors gate the run).
  • disc-09's keyword-overlap sensitivity predates the port but can flake make eval; worth retuning its expected_rule (or the 0.2 threshold) before Phase 2 lets CI block PRs on it.
  • The 90% floor and 0.75 rubric threshold are Phase-1 guesses, intended for tuning after real runs.

nonrational and others added 12 commits August 29, 2026 11:39
Promptfoo replaces the duplicated per-skill run-evals.mjs runners;
evals.json stays the canonical case format, fed to promptfoo by a
generator. CI validates structure always and spends model tokens only
on PRs touching an evaluated skill. Scoped deliberately apart from
Bernard, which compares whole config repos rather than gating one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ten tasks: scaffold the evals package, port the loader, heuristics,
prompt builders, and deterministic graders from the bespoke runner,
add the claude-code subject provider and promptfoo configs, gate and
validate scripts with Make targets, live parity run, then retire the
code-comment-register run-evals.mjs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ported from the code-comment-register runner, generalized to any skill
and tolerant of case types Phase 1 does not grade yet. Validation checks
the cross-skill common schema (required fields, structural constraints)
and allows per-skill rubric and trap field naming conventions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes: correct Unicode escapes for smart quotes (‘’ and “”) and restore expected output to use straight quotes in normalize test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Subject prompt templates are ported verbatim from the bespoke runner so
the parity check compares like with like.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Promptfoo suite reached parity: 11/12 deterministic cases match the
old runner's outcomes; the exception (disc-09) was model-response
variance against the shared keyword-overlap threshold, with prompts
and graders verified byte-identical. Transformation cases now grade
via promptfoo llm-rubric, a deliberately different judge protocol
than the old runner's bespoke judge; live judge verification awaits
an ANTHROPIC_API_KEY environment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The layout snippet and the code use a custom JS provider; the prose
still said exec script.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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