skill-evals · v1.0 · 2026-10-28 · sha256 d1e5761d6c78faa7
skill-evals v1.0A
Immutable. This exact content never changes and is served at /api/v1/blob/d1e5761d6c78faa7.
---
name: skill-evals
description: "Écrit, exécute et consigne les jeux d'evals des skills critiques de l'utilisateur (déclenchement, non-déclenchement, qualité, régression, token-hygiene) au format natif de skill-creator (evals.json + triggers.json), avec contrôles déterministes hors LLM (check_static.py : frontmatter, description ≤ 1024, chemins en dur, IP, nom de modèle versionné, renvois → skill fantômes, changelog) AVANT tout juge LLM. À utiliser quand l'utilisateur dit « écris/lance les evals de X », « teste ce skill avant de le repackager », « est-ce que X se déclenche encore », « régression sur un skill », « vérifie qu'il n'y a pas de chemin en dur », ou avant toute réécriture ou repackaging d'un skill (R59). Ne pas utiliser pour : créer ou réécrire un skill → skill-creator (création) ; inventaire, health check ou conflits de skills → tk-knowledge:skill-manager (inventaire)."
license: MIT
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent
metadata:
version: "1.0"
author: GeekFamilyCorp
domain: eval-lab
activation: auto
plan: "TricorderKit v0.3 — Phase 8 eval-lab"
created: "2026-09-07"
compatibility: "Nécessite python3 (stdlib) pour check_static.py ; le skill Anthropic skill-creator (scripts/run_eval.py, quick_validate.py, aggregate_benchmark.py, eval-viewer) pour le reste ; la CLI claude pour run_eval.py (sinon triggers jugés à la main)."
---
# skill-evals — le banc d'essai des skills critiques
Un skill sans test se dégrade en silence : un renvoi vers un skill archivé, un nom de modèle qui
dérive, une description qui ne déclenche plus. Ce skill impose la règle de la Phase 8 :
**chaque skill critique a ≥ 5 tests, les régressions se voient, et le déterministe passe avant le
juge LLM.** Règles citées : R51 (recouper, ne pas affirmer de mémoire), R53 (proposer, ne pas
exécuter), R59 (repackager après chaque MAJ — donc tester avant), R31 NO-DROP.
## Quand lancer
| Moment | Quoi |
|---|---|
| Avant toute réécriture d'un skill | jeu complet → c'est la **ligne de base** ; sans elle, pas de régression détectable |
| Après la réécriture, avant repackaging (R59) | jeu complet ; comparer à la ligne de base ; un cas qui passait et échoue = STOP |
| Après un renommage/archivage de skill voisin | `check_static.py` seul (renvois → skill) sur tous les skills qui le citent |
| Périodiquement (tâche planifiée `default`, jamais `deep`) | `check_static.py` sur tous les SKILL.md ; les cas LLM restent manuels |
## Le jeu d'evals d'un skill — `evals/<skill>/`
Deux fichiers, **format natif de skill-creator, sans champ inventé** ; gabarit complet et exemple
dans `${CLAUDE_PLUGIN_ROOT}/skills/skill-evals/references/gabarit-eval.md`.
- `evals.json` — `{skill_name, evals:[{id, prompt, expected_output, files, expectations[]}]}`
(schéma : `references/schemas.md` de skill-creator). Le **type** du cas se lit en tête de
`expected_output` : `[TRIGGER]`, `[NO-TRIGGER → skill]`, `[QUALITÉ]`, `[RÉGRESSION]`,
`[TOKEN-HYGIENE]`.
- `triggers.json` — `[{query, should_trigger}]`, le format exact de `scripts/run_eval.py` ;
`kind` et `expected_skill` sont documentaires. C'est ici que vit le **no-trigger**, mesuré par
script ; il est doublé dans `evals.json` pour le grader quand `claude -p` manque.
Minimum par skill : 2 `[TRIGGER]` (dont un quasi-faux-positif : phrase voisine d'un autre skill qui
doit rester ici), 1 `[NO-TRIGGER]` nommant le skill compétent, 2 `[QUALITÉ]`. Ajouter un
`[RÉGRESSION]` par défaut corrigé dans le changelog du skill.
### Assertions : déterministe d'abord
Chaque `expectation` est préfixée. Les `[DET …]` se vérifient par `grep`/script, **avant** de payer
un juge :
`[DET must_contain]` · `[DET must_not_contain]` · `[DET must_match]` (regex) ·
`[DET must_not_match]` · `[DET tool_used]` · `[DET tool_not_used]` · `[DET file_exists]`.
`[LLM]` ne sert qu'à ce qu'un grep ne tranche pas, et l'énoncé oblige le juge à **citer une preuve**.
Ce qu'on vérifie systématiquement en `[QUALITÉ]` : sections attendues, tableau au bon en-tête,
« sur GO » / rien d'exécuté sans accord, aucun chemin en dur, vouvoiement de l'utilisateur, **alias de
modèle (`fast`/`default`/`deep`) et jamais un nom de version**.
Une assertion qui passerait aussi sur une sortie fausse est à réécrire (cf. `agents/grader.md`,
« Critique the Evals »).
## Exécution — commandes exactes
Racines : `SE=${CLAUDE_PLUGIN_ROOT}/skills/skill-evals` ; `SC` = dossier de skill-creator
(`~/.claude/skills/synced/*/skill-creator` ou `/mnt/skills/*/skill-creator` ; `run_evals.sh` le
cherche seul, sinon `SKILL_CREATOR_ROOT=…`).
```sh
# 0. contrôles hors LLM, sur un ou plusieurs skills (aucun appel modèle)
python3 "$SE/scripts/check_static.py" <dossier-skill> [...] --scan-root <racine-plugins> \
[--known-skills a,plugin:b] [--ignore-refs nom-de-tache] [--json] [--strict]
# 1. tout-en-un pour UN skill : check_static → quick_validate → run_eval.py (triggers) → rappel qualité
sh "$SE/scripts/run_evals.sh" <dossier-skill> [--static-only] [--model <alias>] [--workspace <dir>]
# 2. déclenchement seul (format run_eval.py), depuis le dossier de skill-creator
cd "$SC" && python -m scripts.run_eval --eval-set "$SE/evals/<skill>/triggers.json" \
--skill-path <dossier-skill> --runs-per-query 3 --trigger-threshold 0.5 --verbose
# 3. cas qualité : un sous-agent par eval (skill-creator, « Running and evaluating test cases »)
# → <workspace>/iteration-N/eval-<id>/with_skill/outputs/ + eval_metadata.json + timing.json
# → grader (agents/grader.md) → grading.json → puis :
cd "$SC" && python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <skill>
python "$SC/eval-viewer/generate_review.py" <workspace>/iteration-N --skill-name <skill> \
--benchmark <workspace>/iteration-N/benchmark.json --static <workspace>/review.html
# 4. optimiser la description (Claude Code / Cowork seulement, après accord de l'utilisateur)
cd "$SC" && python -m scripts.run_loop --eval-set "$SE/evals/<skill>/triggers.json" \
--skill-path <dossier-skill> --model <alias-de-la-session> --max-iterations 5 --verbose
```
Pas de sous-agents (Claude.ai) : exécuter chaque prompt d'`evals.json` soi-même après lecture du
SKILL.md cible, un par un, puis grader ; sauter le benchmark.
## Lire `grading.json` et décider
`grading.json` (un par run) : `expectations[]` avec `text` / `passed` / `evidence` — ces trois
noms exacts, le viewer en dépend — puis `summary.pass_rate`, `execution_metrics`, `claims[]`,
`eval_feedback` (le grader critique aussi les evals : lire ses suggestions).
`run_eval.py` rend `results[].trigger_rate` et `pass` par requête.
**Seuil de passage** :
- déclenchement : 100 % des requêtes de `triggers.json` conformes (`trigger_rate ≥ 0.5` si
`should_trigger`, `< 0.5` sinon), sur 3 runs ;
- qualité : **100 % des `[DET]`** et `pass_rate ≥ 0.8` sur l'ensemble ;
- régression : aucun cas qui passait dans la ligne de base ne doit échouer — un seul suffit à
bloquer le repackaging ;
- un résultat « tout à zéro » sur les triggers signale un harnais qui n'a pas tourné (timeout,
auth) : **NON MESURÉ**, pas une régression (R51).
## Consigner
1. **Projet** : `claude/veilles/JOURNAL_skill-evals.md` — une ligne datée par run :
`date | skill | version | check_static OK/KO | triggers n/N | qualité pass_rate | verdict | lien workspace`,
et une ligne au `claude/veilles/REGISTRE.md` à la création du journal.
2. **Vault** : `<vos-notes>/skills/<skill>/EVALS.md` — dernière ligne de base et
verdict ; le skill n'est « testé » que si c'est écrit et daté (R79).
3. Les workspaces (`<skill>-workspace/evals-<date>/`) restent hors du dépôt public (R37).
## Exemples
- « Lance les evals de code-corrector avant que je le repackage » → `run_evals.sh` complet ; verdict +
ligne au JOURNAL ; repackaging seulement si aucune régression.
- « Est-ce que model-router se déclenche encore sur "quel modèle pour cette tâche" ? » → `run_eval.py` sur
`evals/model-router/triggers.json` ; si `trigger_rate < 0.5`, proposer `run_loop.py` (sur GO).
- « Vérifie qu'aucun skill ne cite encore task-classifier » → `check_static.py` sur tous les
SKILL.md avec `--scan-root` ; les `REF-SKILL` listent les renvois fantômes.
- « Écris un jeu d'evals pour polyglotte » → gabarit `references/gabarit-eval.md`, 6 cas
(2 trigger, 1 no-trigger, 2 qualité, 1 régression), `[DET]` d'abord.
## Frontières
Créer, réécrire ou packager un skill → `skill-creator`. Inventaire, health check /8, conflits,
archivage → `tk-knowledge:skill-manager` (qui peut appeler `check_static.py` comme 9e critère).
Ce skill mesure et consigne ; il ne
modifie jamais un SKILL.md cible, et ne repackage rien sans GO (R53).
## Changelog
- **2026-09-07 — 1.0** : création (Phase 8 eval-lab). `check_static.py` (stdlib, 11 contrôles),
`run_evals.sh` (POSIX, adossé aux scripts de skill-creator), gabarit d'eval, jeux pour les skills
critiques ; la version publique en fournit cinq : code-corrector, dev-protocol,
doubt-driven-development, skill-manager, model-router.