AIDive

Le /verify de Claude Code a dit PASS. Le code était cassé

Par AIDive · Publié le

Agents de codeModèles d'IA

Il s'est noté lui-même : PASS

Le check de vérification intégré à Claude Code, /verify, a renvoyé un PASS sur une fonctionnalité qui était cassée. C'est le résultat d'un banc de 116 sessions Claude Code sur un dépôt réel, où chaque "terminé" a été noté après coup par des tests d'acceptation que l'agent n'a jamais vus.

Boris Cherny, qui a créé Claude Code, dit que la vérification est la chose la plus importante qu'on puisse lui donner. Le check intégré ne se lance que sur demande depuis Claude Code v2.1.215 : soit vous tapez /verify, soit il ne se lance pas. Sur ce banc, il a dit PASS dans 24 runs sur 24, et l'un de ces runs avait livré une fonctionnalité cassée. Ce qui a vraiment attrapé le bug est couvert plus bas, avec le dispositif qui a coûté deux fois et demi plus cher et n'a rien changé.

Le banc d'essai : 116 runs, des tests jamais vus

Un faux "terminé" est une session qui se termine en prétendant que le travail est fini alors qu'un test d'acceptation caché, ou la suite du dépôt lui-même, échoue. Le banc mesure la fréquence de ce phénomène sous six configurations de vérification.

Le doute derrière tout ça vient du propre tracker d'issues de Claude Code : l'issue #96416, déposée le 2026-09-23, décrit une review qui a listé 19 préoccupations, en a vérifié 5 et a quand même conclu "accept as is".

Paramètre Valeur
Dépôt msiemens/tinydb (base de données de documents Python), commit 18d73a1
Suite de tests du dépôt 226 tests
Demandes de fonctionnalité 6, chacune énonçant 5 exigences
Tests d'acceptation cachés un par exigence énoncée, écrit avant tout run, jamais montré à l'agent
Modèles Opus 5.5, Sonnet 5, Haiku 4.5
Claude Code 2.1.283, headless (claude -p), plafond de 60 tours
Sessions 112 runs de tâche + 4 runs /verify inter-modèles = 116
Dépense $66.29 en équivalent API

Les six configurations vont de Claude Code seul (juste la demande) à un second modèle qui vérifie le travail à l'arrêt :

Configuration Ce qu'elle ajoute
A plain rien
B /verify le /verify intégré tapé comme second tour
C verify skill un skill de projet écrit selon le workflow d'Anthropic
D Stop hook un script qui bloque l'arrêt tant que la suite est rouge et demande des preuves par exigence
E tests first une règle CLAUDE.md : un test qui échoue par exigence avant tout code
F Opus verifier un Stop hook qui lance /verify avec Opus sur le changement

Des demandes claires sur une bibliothèque bien testée, c'est le cas facile. Opus 5.5 seul a réussi ses 12 runs sur 12, et il a lancé la suite de tests par lui-même dans 11 d'entre eux.

Le /verify intégré : PASS, à chaque fois, 2,5x

/verify est le skill de vérification livré avec Claude Code. Il lance le changement, lit le diff et écrit un verdict étape par étape. Depuis la v2.1.215, il n'est déclenché que par l'utilisateur, donc sur le banc il a été tapé après chaque tâche comme un second tour.

Il a renvoyé un verdict PASS dans 24 runs sur 24 à travers les trois modèles, y compris le changement cassé de Haiku. Sur Opus 5.5, il n'a changé aucun résultat et a coûté 2,5 fois plus cher :

Opus 5.5, par tâche Plain Avec /verify
Coût $0.39 $0.96
Temps réel 75 s 125 s
Résultats changés 0 sur 12

Pour être honnête, /verify a trouvé un vrai bug : sur une tâche d'Opus, il a signalé un problème de réutilisation après fermeture déjà présent dans la bibliothèque, pas causé par le changement qu'il vérifiait. Sur un travail déjà correct, c'est un second avis coûteux.

Skill ou hook : celui qui se fait sauter

Un skill est une procédure markdown que Claude peut ouvrir quand il juge que c'est pertinent. Le billet de blog d'Anthropic sur les boucles de vérification décrit une recette en six étapes : repérer le suivi manuel qu'on fait le plus souvent, essayer d'abord le /verify intégré, écrire la procédure en anglais courant, en faire un skill, puis l'invoquer sur une nouvelle tâche et itérer. Le skill du banc, verify-change, a été construit exactement de cette façon et dit à Claude de prouver chaque exigence sur le vrai code avant de dire que c'est terminé.

Un skill est une suggestion, et c'est Claude qui décide de l'ouvrir ou non :

Modèle Sessions ayant ouvert le skill
Opus 5.5 8 sur 12
Sonnet 5 2 sur 6
Haiku 4.5 0 sur 6
Total 10 sur 24

Le seul faux "terminé" de Sonnet vient d'une session où le skill ne s'est jamais ouvert : elle s'est terminée avec deux de ses propres nouveaux tests en échec.

Un Stop hook est un script que Claude Code exécute chaque fois que l'agent essaie de terminer. Il peut refuser l'arrêt et renvoyer l'agent au travail avec une raison. Le hook du banc lance la suite de tests, bloque tant qu'elle est rouge, et au premier arrêt demande une ligne de preuve par exigence. Il s'est déclenché à chaque session. Sur Opus, il a coûté 20% de plus, $0.47 contre $0.39 par tâche (94 s contre 75 s). Dans ce banc, il n'a jamais rencontré de suite en échec au moment de l'arrêt, donc il n'avait rien à attraper : un hook se déclenche toujours, mais il ne vérifie que ce qu'on lui a dit de vérifier.

L'angle mort : 11 sur 11 ratés

La tâche qui a échoué demandait des champs uniques sur une table : deux utilisateurs ne peuvent pas partager un email, et toute mise à jour qui laisserait deux documents avec la même valeur unique doit lever DuplicateKeyError.

Haiku 4.5 a testé le déplacement d'un utilisateur vers l'email d'un autre utilisateur, et cela a été correctement refusé. Il n'a jamais testé une mise à jour qui correspond à plusieurs documents et écrit le même nouvel email sur tous. Ce cas est passé sans erreur dans 11 sessions Haiku sur 11, dans chaque configuration avec le même modèle : plain, /verify, le skill, le Stop hook et tests first.

Le propre /verify de Haiku a coché le cas qu'il avait essayé et écrit PASS. Le test caché a rapporté DID NOT RAISE DuplicateKeyError. Sonnet 5, invité à lancer /verify sur le même changement, a lui aussi renvoyé PASS. Opus et Sonnet ont tous deux écrit cette fonctionnalité correctement de leur côté, donc c'est un modèle sur une tâche, mais un check écrit par le même modèle partage son angle mort.

Le contrôle externe : Opus dit FAIL

Le même /verify, sur le même changement de Haiku, mais lancé par Opus 5.5, a renvoyé FAIL dans 3 runs sur 3, en nommant à chaque fois le cas manqué : une mise à jour qui correspond à plusieurs documents écrit la même valeur sur tous, sans erreur. L'attrape est venue d'un modèle différent, pas de l'auteur ni de son propre check.

Câblé comme Stop hook (configuration F), Opus vérifie le travail de Haiku à chaque fois que Haiku essaie de terminer. Les résultats :

T6, par run Haiku + vérificateur Opus Opus 5.5 seul
Bug corrigé / faux "terminé" corrigé dans 3 sur 3 0 faux "terminé"
Tours plafond de 60 tours atteint à chaque run
Coût $1.36 avec le vérificateur inclus $0.76

Le contrôle externe fonctionne. Sur cette tâche, il a coûté plus cher que le modèle le plus fort écrivant la fonctionnalité seul.

Ce qu'il faut retenir, et ce que ça coûte

Arrêtez de laisser le modèle qui a écrit un changement être le seul à le vérifier.

Règle Pourquoi Coût sur ce banc
Garder un Stop hook pour tout ce qu'un script peut vérifier il se déclenche à chaque session environ 20% de plus sur Opus
Faire venir le vrai contrôle de l'extérieur de l'auteur : un modèle plus fort à la porte, ou vos propres tests écrits depuis la demande le même modèle a raté son propre bug 11 fois sur 11 $1.36 par tâche pour Haiku + vérificateur Opus
Sur une demande claire avec Opus, sauter le /verify 0 résultat changé 2,5x le coût, 125 s contre 75 s

Les limites : une petite bibliothèque, six demandes claires, un à trois runs par cellule, des sessions headless, et des tests cachés qui ne vérifient que ce que chaque demande énonce. Sur un travail plus désordonné, les chiffres bougeront.

Sources

Questions fréquentes

Est-ce que le /verify de Claude Code attrape les bugs ?
Pas de façon fiable quand le même modèle vérifie son propre travail. Sur un banc de 116 sessions, /verify a renvoyé PASS dans 24 runs sur 24, y compris un changement de Haiku 4.5 qui échouait une exigence énoncée ; lancé par Opus 5.5 sur ce même changement, il a renvoyé FAIL 3 fois sur 3.
Le /verify vaut-il le coup sur Claude Code avec Opus ?
Pas sur des demandes claires. Sur Opus 5.5, il a fait passer le coût par tâche de $0.39 à $0.96 (2,5x) et le temps de 75 s à 125 s, sans changer aucun des 12 résultats, parce qu'Opus seul lançait déjà la suite de tests lui-même dans 11 runs sur 12.
Faut-il utiliser un skill Claude Code ou un Stop hook pour la vérification ?
Un Stop hook, pour tout ce qu'un script peut vérifier. Claude n'a ouvert un skill de vérification que dans 10 sessions sur 24 (Opus 8 sur 12, Sonnet 2 sur 6, Haiku 0 sur 6), alors qu'un Stop hook s'exécute chaque fois que l'agent essaie de terminer ; il a coûté environ 20% de plus sur Opus.
Qu'est-ce qu'un Stop hook Claude Code ?
Un script que Claude Code exécute chaque fois que l'agent essaie de terminer. Il peut refuser l'arrêt avec une décision JSON de blocage et une raison, ce qui renvoie l'agent au travail ; il ne vérifie que ce que le script teste.
Un modèle plus fort peut-il vérifier le code d'un modèle plus faible dans Claude Code ?
Oui. Un /verify Opus 5.5 câblé comme Stop hook a fait corriger son cas manqué par Haiku 4.5 dans 3 runs sur 3. C'était coûteux : chaque run a atteint le plafond de 60 tours et coûté en moyenne $1.36, contre $0.76 pour Opus écrivant la fonctionnalité seul.
Pourquoi un modèle d'IA rate-t-il des bugs dans son propre code ?
Son check ne teste que les cas auxquels il a déjà pensé. Haiku a vérifié le déplacement d'un utilisateur vers l'email d'un autre, mais jamais une mise à jour touchant plusieurs documents, donc son propre /verify a coché le cas essayé et écrit PASS alors que le test caché échouait.

Vidéos liées