Skill evaluation infrastructure

skillproof

Auto-generates benchmarks from a SKILL.md folder, then measures the pass-rate delta an agent gets from having the skill mounted — its skill uplift.
View on GitHub
1Chunk & cluster
2Author & validate
3Evaluate uplift
Overall skill uplift
+4pp
Mean uplift — pass-rate gain from mounting the skill
50%
Pass rate with the skill
46%
Pass rate without the skill

Micro-averaged across all 35 benchmarks × 3 models (175 graded skill / benchmark / model results, 3 trials each). The mean hides wide variance: per-skill uplift ranges from −38pp (frontend-design) to +33pp (brand-guidelines).

Models under test

The three coding agents benchmarked below, by parameter count — all open-weight mixture-of-experts models. The large "total" figure is the full parameter pool; "active" is what actually fires per token.

Kimi‑K2.7‑Code
1T
32B active · MoE
+4pp mean skill uplift
DeepSeek‑V4‑Flash
284B
13B active · MoE
+1pp mean skill uplift
Qwen3.6‑35B‑A3B
35B
3B active · MoE
+8pp mean skill uplift
Explainer

How it works

skillproof turns a skill folder (a SKILL.md plus supporting scripts/references) into a set of graded, reproducible coding tasks, then measures whether mounting that skill actually changes an agent's pass rate. Nothing here is hand-written per skill — the whole pipeline below runs the same way for every skill, from chunking the docs to grading the final trial.

a. Chunk & cluster

Each skill's markdown is split into heading-bounded chunks (one chunk per section/subsection). Every chunk is embedded with the configured embedding model, then clustered with k-means, sweeping k over a small range and keeping whichever k gives the best silhouette score. From those clusters, skillproof greedily selects the k_benchmarks most mutually dissimilar clusters (max-min selection on cluster-centroid distance) — the goal is one benchmark per genuinely distinct capability the skill covers, not five benchmarks that all probe the same paragraph.

View: chunk/cluster counts and embedding model, per skill

b. Benchmark authoring

For each selected cluster, a headless coding agent (Codex CLI or Claude Sonnet in headless mode) is given that cluster's chunk text and a strict output contract, and asked to author a complete, self-contained benchmark: a task prompt, input fixtures, a reference solution, and a deterministic grader — without seeing the skill's own guidance beyond that cluster, so the benchmark tests the capability rather than parroting the skill's phrasing.

View: authoring contract (verbatim)

      

c. Validation gate

An authored benchmark is only kept if it clears three checks: the bundled reference solution must pass the grader; an untouched/empty workspace must fail the grader (otherwise the task is gradeable by doing nothing); and the grader must return the same verdict on two independent runs of the reference solution (determinism — no flaky timing- or ordering-dependent checks). If a benchmark fails validation, the authoring agent gets the failure output back and retries up to max_attempts times; if it still can't produce something that passes the gate, the benchmark is dropped and a FAILED.md explaining why is written instead, excluding it from evaluation entirely.

d. Evaluation harness

Evaluation is a single model-agnostic loop that drives any model over OpenRouter through a small bash/read_file/write_file tool surface (see schemas below) inside the sandbox. Every benchmark is run in two arms: with_skill, where the skill's SKILL.md is injected into the system prompt and its supporting files are mounted read-only at /skill; and without_skill, where the agent gets neither the injected instructions nor the mount — same task, same tools, same model, skill withheld. Uplift for a given benchmark × model is simply pass_rate(with_skill) − pass_rate(without_skill).

System preamble sent to the agent

      
Skill injection template (with_skill arm only)

      
Tool schemas (bash / write_file / read_file)

      

e. Sandbox

Every trial — authoring, validation, and each evaluation arm — runs in a fresh, network-less Docker container built from the same image, so nothing can cheat by calling out to the internet and nothing leaks state between trials. Grading follows a snapshot-then-grade pattern: the agent's final /workspace is captured, then copied into a brand-new container to run the grader, so a grader can't be influenced by leftover agent processes or a corrupted shell.

Dockerfile

      
sandbox_packages (source of truth for what's installed, quoted to the authoring agent)

      

f. LLM judge panel

Some capabilities (tone, completeness, "did it avoid overclaiming") don't reduce to a substring match. For those, the grader exits with code 3 and prints one or more yes/no questions about the produced artifact; skillproof routes each question to a three-model judge panel and takes a majority vote. The panel is instructed to be strict: for a multi-condition question, every condition has to be satisfied for a YES, and any doubt resolves to NO — there's no partial credit for grading purposes.

Judge system prompt

      

g. Config

One YAML file controls the seed, embedding provider/model, clustering k range, authoring backend/model/attempt budget, and evaluation defaults (trial count, model list, timeouts) for every skill run through the pipeline.

config.yaml

      
Full project README

    
Overview

At a glance

Per-skill

Skills, benchmarks & results

Analysis

Notable findings

The cross-skill pattern: uplift concentrates exactly where model capability runs out. Proprietary knowledge (Anthropic's brand colors) lifts every model; public best practices (Vercel's React rules) lift only the weakest model in the fleet; self-documenting tools (agent-browser's mock CLI) lift no one because the task itself teaches the protocol; and injected guidance can go negative when its general advice distracts from the specific constraints a task grades on (frontend-design). A skill's measured value is not a property of the skill alone — it's the gap between what the skill knows and what the model already does.
frontend-design is net-negative: −38pp mean, with per-benchmark means from −11pp to −56pp. All five benchmarks derive from the skill's "restraint" content: judge-graded checks that a design commit to ONE bold signature element and keep everything else calm. But the full injected skill preaches boldness and distinctiveness throughout — with-skill models over-design and fail the restraint checks (DeepSeek falls from 100% without to 0% with on "Restraint and self-critique"), while without-skill models pass by being plain by default. The reading is genuinely dual: the skill's guidance is double-edged in practice, and restraint-themed benchmarks structurally reward default blandness.
vercel-react-best-practices: training-saturated for strong models, real uplift only for the weak one. Its 215 chunks (largest corpus in the fleet) yielded 5 validated benchmarks, all on attempt 1. DeepSeek and Kimi score 100% in both arms on every benchmark — these public best practices are already in their training data — so all uplift comes from Qwen: +67pp on event-listener deduplication and +33pp on the async cheap-condition check. Telling detail: only 4 of 45 with-skill trials ever read a /skill/rules/*.md file.
agent-browser: clever offline benchmarks, but a 36/36 ceiling. The authoring agent built mock-CLI benchmarks that simulate the browser tool offline — and every one of the 36 trials passed, both arms, all models, 0pp uplift everywhere. The mock's own error messages teach the CLI protocol in-band: a model that guesses wrong gets corrected by the harness it's being tested on. Browser-automation skills fundamentally need a live-browser evaluation harness to show differentiated results.
find-skills splits cleanly: one ceiling benchmark, one real uplift. bench_01 ("verify skill quality before recommending") passes 100% in both arms for all models. bench_02 ("common skill categories") shows genuine knowledge uplift: DeepSeek +67pp and Kimi +33pp with the skill, both at 0% without it (Qwen fails both arms).
slack-gif bench_02 went from −100pp to +11pp after grader regeneration. The original "Drawing from scratch" grader penalized the skill's own recommended workflow, scoring every model worse with the skill than without (−100pp across the board). Regenerated and re-run at 3 trials/arm, the same capability now measures +11pp mean (DeepSeek +33pp, Kimi and Qwen 33%/33% either way) — the negative signal was an artifact of a skill-hostile grader, not the skill.
brand-guidelines is a pure knowledge gap, and the 3-trial run proves it. On the single "Anthropic SVG Brand Poster" benchmark, the 1-trial run showed Kimi and Qwen swinging from 0% to 100% with the skill mounted (DeepSeek stayed at 0% either way) — consistent with models not knowing Anthropic's exact accent-color and typography thresholds from memory. Re-run at 3 trials/arm, the same three models settle at a much more modest 33% with / 0% without — the underlying gap is real, but a single trial had been reporting an inflated ±100pp estimate of it.
docx uplift tracks the bundled scripts, not the prose. In the 3-trial run (mean uplift +13pp across the 15 benchmark×model cells), nearly every positive-uplift cell — Kimi's +100pp on "Embed a PNG into a DOCX", Kimi's +33pp on tracked changes and fake lists, DeepSeek's +33pp on heading styles — shows /skill/scripts/office/{pack,unpack,validate}.py in that trial's skill_files_read. Cells with 0pp uplift mostly show no skill files read at all, or only the validator. The skill's value here is largely "here is working OOXML tooling," not the surrounding guidance text.
docx bench_01 (tracked changes) flipped sign once trials increased. At 1 trial/arm the tracked-OOXML-replacement benchmark averaged −33pp across the three models (a single Kimi without-arm pass made the skill look harmful). At 3 trials/arm the same benchmark averages +22pp — DeepSeek and Kimi both at 67% with / 33% without — a clean example of a single-trial cell reporting the wrong sign of a real effect.
internal-comms went from a measurement floor to real, fractional signal. The first run scored 0pp on the large majority of benchmark×model cells under a substring-match grader — a floor effect, not evidence the skill does nothing. Re-authored with judge-based grading and re-run at 3 trials/arm, the skill now shows a modest +7pp mean uplift built from genuine fractional pass rates (e.g. Qwen 67% with / 0% without on the "how to use this skill" benchmark; DeepSeek 33% with / 67% without elsewhere) — a mix of real positive and negative effects instead of a wall of zeros.
pdf is a near-total ceiling skill: PDF library knowledge is training-saturated. With all five benchmarks now evaluated at 3 trials/arm, bench_03 (pypdf basics), bench_04 (advanced pdf libraries), and bench_05 (poppler-utils) pass 100% in both arms for every model; bench_02 (qpdf/pdfplumber) is near-ceiling (only DeepSeek slips to 67% with-skill); and bench_01 (fillable forms) is a noisy wash — Qwen +33pp, Kimi −33pp, DeepSeek 0pp. Net verdict: roughly 0pp uplift for the whole skill. pypdf, pdfplumber, qpdf, and poppler are so heavily represented in training data that documenting them adds nothing these models don't already know — an earlier 1-trial +100pp Qwen result had already evaporated by the first full re-run.
3-trial runs shrink single-trial ±100pp cells toward honest fractional rates. A 1-trial arm can only ever report 0% or 100%, so any partially-reliable behavior gets rounded to a coin flip. brand-guidelines, internal-comms, and slack-gif-creator all re-ran the same benchmarks at 3 trials/arm and saw their most extreme single-trial cells (0%/100% swings) replaced by 33%/67%-style rates — the more trials, the less any one cell looks like a clean win or loss.
Three skills haven't entered the pipeline yet. mcp-builder, web-artifacts-builder, and webapp-testing have no chunk/cluster data, no authored benchmarks, and no evaluation runs recorded — clustering hasn't been kicked off for them. They're listed, not benchmarked, at the end of the skills section above.