distill-test-set
Skill3 starsChanged 17 days agoMITView on GitHub
Turn a large dataset (an existing oversized Coval test set, an export of past conversations, or a CSV/JSON of cases) into a small, high-signal Coval test set by removing duplicates, identifying unique scenarios, and selecting a representative, failure-weighted subset — then bulk-loading it with no row cap. Use when the user says "I have thousands of cases", "dedupe my test set", "my test set is too big", "turn this dataset into a test set", "pick representative scenarios", or "my CSV import only kept 10 / uploaded everything".
- Reads credentials
In this repository33 other files it gives its agents.
- setup-agentSkill
- build-dashboardSkill
- coval-calibrate-metricSkill
- coval-compare-runsSkill
- coval-discover-failuresSkill
- coval-eval-auditSkill
- coval-evals-as-codeSkill
- coval-eval-startSkill
- review-llm-annotations-and-improve-promptSkill
- configure-metricsSkill
- migrate-bluejaySkill
- onboardSkill
- coval-resourcesSkill
- design-personaSkill
- personas-from-artifactsSkill
- analyze-accent-reportSkill
- analyze-adversarial-reportSkill
- analyze-audio-quality-reportSkill
- launch-runSkill
- quick-evalSkill
- run-accent-testingSkill
- run-adversarial-testingSkill
- run-audio-quality-testingSkill
- watch-runSkill
- download-audioSkill
- get-resultsSkill
- consult-sofiaSkill
- build-test-suiteSkill
- huggingface-importSkill
- configure-trace-metricsSkill
- debug-tracesSkill
- optimize-trace-observabilitySkill
- setup-tracingSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 3 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 25
If $ARGUMENTS is a Coval test set id (8 chars) or a file path, use it as the source in Phase 1.
- Very specific: line 41
If not authenticated: coval login (get a key at https://app.coval.dev/settings → Organization → Manage → API Keys).
- Very specific: line 70
If the source is a Coval test set whose metadata is packed into a pipe-delimited description (e.g.
- Distinctive: line 79
Run the distiller. It (1) drops rows with no checkable answer, (2) removes exact + paraphrase duplicates, (3) caps boilerplate-convergence …
- Distinctive: line 101
No third-party packages are needed.
- Distinctive: line 115
Ask: "Does this coverage look right?
- Very specific: line 131
Create a SCENARIO test set and load the distilled cases with --stdin — the uncapped path that loads exactly the rows you chose (no 10-case …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Distill Test Set
Turn a large, noisy dataset into a small, high-signal Coval test set. Big datasets are the wrong input for simulation: running thousands of sims is slow, expensive, and likely to overwhelm the agent under test, and most rows are duplicates, paraphrases, or boilerplate. The goal is a representative 10–50 case suite that covers the agent's real scenarios once each, weighted toward known failures.
Drive everything through the coval CLI and the bundled scripts/distill.py. Follow the
phases in order. Present a summary and get confirmation before creating anything.
If $ARGUMENTS is a Coval test set id (8 chars) or a file path, use it as the source in
Phase 1.
Why this skill instead of a plain import? Coval has two loaders, and neither dedupes: the CSV/XLSX importer and
coval test-cases create --stdinload every row 1:1 (great once you've chosen your rows), while "Create test set → attach a file" runs an LLM that synthesizes only ~10–15 scenarios (a generation cap, not a representative sample). This skill does the dedup + representative selection itself, then loads the result with the uncapped path.
Phase 0: Preflight + Inventory
Step 1: Check authentication
coval whoamiIf not authenticated: coval login (get a key at https://app.coval.dev/settings → Organization → Manage → API Keys). No account? https://coval.dev.
Before you start: this skill needs only the
covalCLI andpython3(used by the bundled script and a couple of small JSON reads) — nojqor other tools. Ifcovalis a shell alias on your machine, run the commands withcoval-cliinstead (which covalto check).
Step 2: Inventory existing test sets (so we don't clobber one)
coval test-sets list --format jsonNote the ids/sizes. If the user wants to distill an existing Coval test set, confirm its id here.
Phase 1: Locate + Profile the Source Dataset
Determine where the large dataset lives. Two common cases:
- An existing, oversized Coval test set — use
--source coval:<TEST_SET_ID>(the script pulls every case via the API, paginated). Confirm the id and its size:coval test-sets get <TEST_SET_ID> --format json | python3 -c "import json,sys;d=json.load(sys.stdin);print(d.get('display_name'), d.get('test_case_count') or '(size shown in app)')" - A local file — CSV, JSON, or NDJSON of past conversations / SME-reviewed rows / logs.
Then identify the field mapping by inspecting a few rows:
- the user utterance / scenario field (
--input-field, defaultinput_str) - the expected answer / behavior field (
--expected-field, defaultexpected_behaviors) - a label to stratify by — the intent or route or category (
--label-field) - a pass/fail field if the data is review-graded (
--pass-fail-field; values starting withPass/Fail)
If the source is a Coval test set whose metadata is packed into a pipe-delimited
description (e.g. journey=… | sub_topic=… | next_agent_status=… | sme_result=…), add
--parse-coval-description so those become usable labels.
Load references/distillation-method.md if you need help choosing the field mapping or
understanding what the script does.
Phase 2: Distill
Run the distiller. It (1) drops rows with no checkable answer, (2) removes exact + paraphrase duplicates, (3) caps boilerplate-convergence clusters (many different asks that all hit one generic fallback/greeting) to a small quota, and (4) selects a stratified, failure-weighted subset across your labels and languages.
python3 scripts/distill.py \
--source <coval:TEST_SET_ID | path> \
--parse-coval-description \ # only if labels are in a pipe-delimited description
--label-field <intent/route field> \
--pass-fail-field <pass/fail field> \
--target-size 30 \ # start small: 10–50
--min-minority-ratio 0.3 \ # keep ~1/3 of a minority language (e.g. non-English); 0 to disable
--out distilled.ndjsonThe script prints a report to stderr — show it to the user:
dropped_low_info / boilerplate_groups / scenario_rows_after_dedup /
selected / selected_fail / selected_cjk / selected_by_label- No third-party packages are needed; paraphrase clustering uses a character n-gram heuristic by default.
- For higher-quality clustering on multilingual data, set
OPENAI_API_KEYand add--embeddings on(it falls back to the heuristic automatically if anything fails). - Tuning knobs:
--target-size,--fail-weight(default 0.45),--boilerplate-quota(default 4),--jaccard-threshold/--embed-threshold. Seereferences/distillation-method.md.
Phase 3: Review + Adjust
Show the user a sample of the distilled set and the label/pass-fail/language breakdown:
python3 -c "import json;[print('IN :',json.loads(l)['input_str'][:70],'| EXP:',json.loads(l)['expected_output_str'][:60]) for l in open('distilled.ndjson')]"
wc -l distilled.ndjsonAsk: "Does this coverage look right? (yes / re-run with different size or weighting / edit the file)"
- Too many fallback/greeting rows → lower
--boilerplate-quota. - Want more failure coverage → raise
--fail-weightor--target-size. - Want to hand-curate → edit
distilled.ndjsondirectly (one JSON object per line:{"input_str", "expected_output_str", "description"}). Keep every line valid JSON — the bulk loader stops at the first malformed line, so a stray typo can silently drop the rest. - Sanity-check coherence → confirm each
expected_output_stractually answers itsinput_str. The distiller preserves whatever input/answer pairing your source had, so any misalignment already in the source data carries through (garbage in, garbage out).
Start small. A 20–30 case suite you can run and trust beats a 2,000 case suite you can't. Get the agent passing these, then add a new test set for the next workflow.
Phase 4: Create the Test Set + Bulk-Load (uncapped)
Create a SCENARIO test set and load the distilled cases with --stdin — the uncapped
path that loads exactly the rows you chose (no 10-case generation limit):
TS=$(coval test-sets create --name "<Agent> — Representative Suite" --type SCENARIO \
--description "Distilled from <source>: deduped, failure-weighted representative scenarios" \
--format json | python3 -c "import json,sys;print(json.load(sys.stdin)['id'])")
cat distilled.ndjson | coval test-cases create --test-set-id "$TS" --stdin
--stdinreads one JSON object per line (input_strrequired;expected_output_str,descriptionoptional) and POSTs one test case per line with no row cap. This is the fix for "the importer only kept ~10 cases".
Note:
SCENARIOis the right type for persona-driven eval and is also the CLI default. If an older CLI build rejects--type, just omit it (you still get SCENARIO).
Phase 5: Verify + Next Steps
coval test-cases list --test-set-id "$TS" --page-size 100 --format json | python3 -c "import json,sys;print(len(json.load(sys.stdin)))"Confirm the count matches the distilled file, then show the app link:
https://app.coval.dev/test-sets/<TS>
What's next?
Create personas to drive these scenarios: /design-persona or /personas-from-artifacts
Add expected behaviors / refine cases: /build-test-suite
Configure evaluation metrics: /configure-metrics
Launch an evaluation on the small set first: /quick-eval
Iterate: once the agent passes this suite, distill a NEW test set for the next workflow
rather than growing this one — narrow, branch-covering suites beat one giant set.Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

