AIDive

Claude Code livre un bug. Je le rends impossible en 4 fixes

Par AIDive · Publié le

Agents de code

La session qui a livré un bug, et la rétro qui a dit « smooth »

Claude Code a livré un bug de numérotation sur un vrai dépôt, et quatre changements validés à la main ont rendu ce bug impossible à livrer de nouveau. La session a écrit des avoirs pour une petite API de facturation, la suite de tests est revenue au vert, et un contrôle lancé ensuite à la main a montré qu'une requête rejetée avait brûlé un numéro de facture. On a alors lancé une rétro sur cette session, validé les correctifs un par un, puis relancé la même tâche : elle est ressortie propre.

Une rétro est la revue qu'une équipe tient après un incident, menée ici sur le journal de session de Claude Code lui-même. Notre première rétro a commencé par « This session was smooth », et aucune de ses conclusions n'était le bug. La solution tient en sept gestes, dans l'ordre : installer, lancer la tâche, lancer la rétro et lui dire ce qui a échoué, relier chaque candidat à un moment, valider chaque survivant dans un support, committer et auditer, puis relancer la tâche.

Ce qu'est une rétro, et installer /retro

/retro est un skill de Matt Pocock qui passe en revue une session de code plutôt que votre code. Il lit le journal de session, le fichier où Claude Code garde chaque prompt et chaque appel d'outil, et cherche des candidats dans sept catégories, par exemple un contrôle qui aurait pu attraper une erreur. Il les présente par ordre de gravité et, d'après sa doc, il ne fait que proposer : rien ne change tant que vous n'avez pas choisi un candidat.

L'installer est le premier geste : dans votre dépôt, mettez à jour la marketplace officielle, puis installez le pack de skills au niveau projet pour qu'il ne vive que dans ce dépôt. Notre marketplace était figée sur une version plus ancienne, sans la rétro, donc la mise à jour est passée en premier. Dans une nouvelle session, tapez une barre oblique et la commande de rétro apparaît dans la liste.

Une limite : une session dans le cloud ne peut pas lire les journaux de votre machine, donc lancez la rétro là où la session a eu lieu.

Lancez votre tâche et laissez finir : notre session a livré le bug

Le deuxième geste est celui que vous faites déjà tous les jours : tapez votre vraie tâche dans une session ordinaire, laissez-la finir, et gardez la session ouverte, car c'est ce que la rétro va lire.

On a utilisé une petite API de facturation en Node et TypeScript, avec sa propre suite de tests et sans fichier d'instructions, sans pipeline ni hook de commit nulle part. La tâche était courte, comme vous la taperiez vous-même : ajouter des avoirs aux factures payées, numérotés en séquence, et permettre d'annuler une facture payée en créditant ce qu'il en reste.

La session a écrit la route, une migration et ses propres tests, puis a lancé la suite avant de s'arrêter. Ensuite on a lancé le contrôle que la finance ferait à la main, un test caché écrit à l'avance, et une exigence a échoué.

Signal Résultat
Suite de tests 42 tests qui passent
Type check propre
Contrôle caché de la finance échec : un numéro d'avoir plus tardif que prévu

La cause : le handler prend le numéro suivant dans le compteur avant de valider la requête, et le compteur est sauvegardé dès qu'il est lu. Un avoir trop grand est rejeté, ce qui est correct, et le numéro est perdu quand même, ce qui ne l'est pas. La session a copié cet ordre sur la route d'émission existante, qui fait fuiter les numéros de facture de la même façon.

On a lancé la tâche deux fois et l'autre exécution est ressortie propre, donc voilà ce qu'une session ordinaire fait une partie du temps.

Lancez /retro, puis dites-lui ce qui a échoué

Le troisième geste est de taper la commande de rétro dans cette même session, puis de la relancer avec l'échec écrit derrière. La nôtre a commencé par : « This session was smooth. »

Elle a classé quelques éléments, dont aucun n'était le bug : un garde-fou manquant, une règle de migration que personne ne vérifie, et rien à faire appliquer par un relecteur. La rétro lit le journal de session, et la session n'a jamais su qu'elle avait échoué.

Alors on le lui dit : relancez la commande avec l'échec comme argument, le texte après la commande. Le nôtre disait que la finance avait testé le build, qu'un avoir trop grand était rejeté, que le prochain avoir valide sortait en retard, et que la rétro ne devait rien corriger.

Cette fois elle a trouvé la cause dans son propre code : il prend le numéro d'abord et valide ensuite, et elle a dit avoir copié cet ordre sur le handler d'émission existant. De nouveaux candidats ont suivi : un test qu'elle avait écrit, qui jouait la séquence en échec mais ne vérifiait que les codes de statut, une fonction de compteur qui a l'air pure et ne l'est pas, et une convention que personne n'a écrite.

Tout ce que vous avez découvert après la session, tapez-le dans l'argument, sinon la rétro audite une session qu'elle croit s'être bien passée.

Reliez chaque candidat à un moment avant de valider

Le quatrième geste est celui que le skill ne fait pas tout seul : demandez à la rétro de citer le moment du transcript derrière chaque candidat, et écartez tout candidat qu'elle ne peut pas montrer.

La doc explique pourquoi une liste classée ne suffit pas : une fois le travail terminé, le modèle oublie les difficultés de la session et invente des conseils génériques. Écartez donc tout candidat que vous ne pouvez pas relier à un moment précis : une phrase qui demande à la rétro de citer le transcript pour chacun.

Sur notre première rétro, la réponse a été franche : la plupart des candidats n'avaient aucun appui dans le transcript. Elle a gardé le garde-fou manquant, parce que son propre listing du dossier des hooks n'avait rien affiché, et abandonné le contrôle de migration comme hypothétique.

Sur la deuxième rétro, celle qui connaissait le bug, le traçage a gardé quatre candidats et en a écarté un.

Candidat Après le traçage
Le test qu'elle a écrit (accepté, rejeté, accepté, numéro jamais vérifié) gardé, solide
La fonction de compteur sans avertissement gardé, solide
La convention non écrite gardé, plus faible
Le garde-fou manquant gardé, même si elle a dit qu'un garde-fou n'aurait pas attrapé ce bug
Le dernier candidat écarté : il comptait deux fois le même moment

Une issue ouverte sur le dépôt du skill compte la plupart des exécutions de rétro suivies d'un utilisateur qui demande des preuves. Un candidat tracé reste le modèle qui relit son propre journal, donc une ligne marquée plus faible est un jugement, et c'est vous qui décidez lesquelles vous retenez.

Validez chaque survivant dans son support

Le cinquième geste est celui où la boucle paie : validez un survivant à la fois, chacun dans son support, l'endroit où la règle va vivre. Le skill vous donne l'échelle. Une violation mécanique reçoit un contrôle déterministe, point final : une règle dans votre linter, un hook de commit, ou un job dans votre pipeline. Un jugement va dans un fichier de standards de code que le relecteur lit. Votre fichier d'instructions s'utilise, selon les mots de la doc, « incredibly sparingly » (avec une extrême parcimonie), pour des pointeurs vers d'autres fichiers.

On a validé quatre changements :

  • Le garde-fou manquant est devenu un hook de commit versionné qui lance le type check et les tests et bloque le commit si l'un des deux échoue. Le harness a refusé de rendre le fichier exécutable, donc on a lancé cette commande nous-mêmes.
  • Le test est devenu un test vitest qui verrouille la règle : un avoir accepté, un avoir rejeté, et le suivant valide doit porter le numéro suivant. Il a échoué dès sa première exécution, et c'est le but : il a attrapé le bug que la session avait livré.
  • Le jugement est devenu une ligne dans un nouveau CODING_STANDARDS.md : ne prenez un numéro de séquence qu'une fois toutes les validations passées, pour qu'une requête rejetée laisse la séquence sans trou.
  • Le manque de navigation est devenu un commentaire au-dessus de la fonction de compteur : elle sauvegarde le compteur immédiatement, donc le numéro est dépensé même si l'appelant échoue ensuite, alors appelez-la seulement après la validation.

Ça fait quatre fichiers modifiés et zéro ligne dans CLAUDE.md, parce que les deux rétros ont refusé d'en écrire une. La première a dit qu'un pointeur dans un fichier de pilotage coûterait du contexte à chaque tour et deviendrait périmé ; la seconde a dit de le garder comme commentaire sur la fonction. La doc les appuie : Claude traite ces fichiers comme du contexte, pas comme une configuration imposée, et pour bloquer une action on utilise un hook.

Deux limites : un hook ne protège que les commits, et le commentaire est, selon les mots de la rétro, un pari sur le prochain appelant, pas un correctif prouvé.

Bouclez la boucle : le hook bloque votre commit, audit, commit, relance

Le sixième geste est le commit, et le dernier consiste à relancer la même tâche, ce qui montre si la boucle a tenu.

Quand on a indexé les fichiers validés et committé, le hook s'est lancé en premier et a refusé le commit. Le type check est passé, puis le nouveau test de numérotation a échoué, recevant un numéro plus tardif que prévu. Le hook vérifie les fichiers tels qu'ils sont sur le disque, et le disque contenait encore le code buggé.

Retournez donc dans la session et demandez le correctif seul : prendre le numéro après la validation, lancer les contrôles, ne pas committer. Ensuite committez de nouveau, le hook passe au vert, et vous obtenez deux commits : les changements de la rétro, puis la fonctionnalité avec son correctif. La rétro elle-même n'a rien committé, ce qu'une issue ouverte sur le dépôt décrit mot pour mot, donc c'est vous qui committez.

Lancez ensuite /doctor prompt-audit, le contrôle propre à Claude Code qui cherche des lignes périmées dans vos fichiers d'instructions. Voici un piège : sans chemin, il audite vos fichiers globaux, pas le dépôt. Avec le chemin, il a jugé le nouveau fichier de standards propre, et signalé que l'ancienne route d'émission viole la règle, un bug de code et pas un problème de prompt.

Le dernier geste est une session neuve avec la même tâche. La nôtre a lu le fichier de standards de code, le readme, le hook et le test de numérotation rouge avant d'écrire du code, puis a écrit dans son propre résumé que le numéro n'est pris qu'après la réussite de toutes ces vérifications, si bien qu'une requête rejetée ne laisse aucun trou dans la séquence.

Première session Session neuve après la boucle
Tests qui passent 42 vert
Contrôle caché de la finance échec 5 sur 5
Numéros après une requête rejetée brûlé, un trou sans trou

Une réserve honnête : cette session neuve a reçu la leçon sous forme d'un test rouge et d'une ligne de standards, c'est donc une exécution après la boucle, pas un benchmark.

Verdict : quand lancer une rétro, quand ne pas le faire, la règle à retenir

La rétro lit la session, donc ce que la session n'a pas vu, vous l'écrivez dans l'argument. C'est là que vous allez trébucher.

Lancez une rétro après une session qui a mal tourné, avant de la vider, ou sur le journal d'une ancienne session. Ne la lancez pas en pilote automatique et ne la branchez pas sur un hook : l'auteur du skill le dit avec ses mots, vous ne voulez pas automatiser ça. La doc ajoute une limite : elle n'audite pas les contrôles qu'elle a proposés le mois dernier, donc c'est à vous de les élaguer.

La règle à retenir est la phrase de la doc : traitez votre fichier d'instructions comme du code, relisez-le quand ça tourne mal, élaguez-le régulièrement, et testez les changements en observant si le comportement de Claude change vraiment. La boucle ne rend pas l'agent juste, elle rend la même erreur plus rapide à attraper, et les contrôles que vous ajoutez sont du code que vous maintenez désormais.

Le pack gratuit de cette vidéo contient la checklist de rétro avec chaque geste, la question de traçage et les supports, plus le script du hook de commit et le test de numérotation de notre run, pour que vous puissiez partir du nôtre.

Ressources gratuites

Sources

Questions fréquentes

Que fait le skill /retro de Matt Pocock ?
Il passe en revue une session Claude Code plutôt que votre code, en lisant le journal de session de chaque prompt et appel d'outil. Il cherche des candidats dans sept catégories, les classe par gravité et ne fait que proposer : rien ne change tant que vous n'avez pas choisi un candidat.
Pourquoi la rétro a-t-elle dit que la session était smooth ?
La rétro lit le journal de session, et notre session n'a jamais su qu'elle avait échoué : ses 42 tests et le type check étaient au vert. Seul le contrôle caché de la finance a attrapé le bug, donc la première rétro a commencé par 'This session was smooth' et l'a manqué.
Comment faire trouver à la rétro un échec que la session n'a pas vu ?
Relancez la commande de rétro et écrivez l'échec derrière, comme argument. Le nôtre disait que la finance avait trouvé un avoir rejeté et un numéro suivant en retard, et cette fois la rétro a remonté la cause jusqu'à son propre code, qui prenait le numéro avant de valider.
Comment faire prouver ses conclusions à la rétro ?
Demandez-lui de citer le moment du transcript derrière chaque candidat et d'écarter ceux qu'elle ne peut pas montrer. Sur notre première rétro, la plupart des candidats n'avaient aucun appui ; sur la deuxième, le traçage en a gardé quatre et écarté un.
Dois-je mettre la règle dans CLAUDE.md ?
Pas par défaut : on a validé quatre changements et écrit zéro ligne dans CLAUDE.md. La doc dit que Claude le traite comme du contexte, pas comme une configuration imposée, donc une règle mécanique va dans un hook ou un test et un jugement dans un fichier de standards de code.
Quand lancer une rétro sur une session Claude Code ?
Lancez-la après une session qui a mal tourné, avant de la vider, ou sur le journal d'une ancienne session. Ne l'automatisez pas et ne la branchez pas sur un hook : son auteur dit qu'on ne veut pas automatiser ça.

Vidéos liées