Nous confions chaque jour de vrais tickets aux agents de codage, et ils livrent presque toujours quelque chose qui fonctionne. Ce n’était jamais l’inquiétude. L’inquiétude, c’est comment ils travaillent : un nouvel utilitaire à côté de trois qui font déjà le travail, une abstraction flambant neuve pour un seul appelant, un correctif qui rafistole le seul chemin nommé dans le ticket et laisse quatre chemins frères cassés, un constat qui est « probablement un bug » sans preuve dans un sens ou dans l’autre. Chaque changement est localement raisonnable. Dans l’ensemble, c’est de l’entropie.
TL;DR : Sur cinq pull requests de Tier 3 dans notre cœur d’orchestration d’agents, trois compétences composables —
ponytail(soustraire),grain(aligner) etreview-proof(prouver) — ont supprimé 821 lignes tout en livrant cinq fonctionnalités, ont attrapé une rupture de contrat silencieuse que la seule plausibilité aurait fait fusionner, et ont maintenu chaque changement dans le sens du grain de l’architecture existante. Voici ce que fait chacune, avec les vrais diffs à l’appui.
Retirez les garde-fous et un agent de codage devient un générateur très rapide de passifs d’apparence plausible. Nous nous appuyons donc sur trois petites compétences qui poussent dans l’autre sens — un instinct chacune : soustraire, aligner, prouver.
ponytail— écrire la chose la plus paresseuse qui fonctionne vraiment. Supprimer avant d’ajouter. (Nous n’avons pas écrit celle-ci — c’est une compétence open source de Dietrich Gebert que nous avons adaptée à notre stack.)grain/grain-review— la placer là où la base de code a déjà décidé qu’elle va. Ne pas inventer une seconde façon de faire.review-proof— ne pas croire un constat tant qu’il ne se reproduit pas sous forme de test en échec.
grain et review-proof, nous les avons construites dans le même esprit que ponytail, ajustées à notre architecture. Chacune des cinq PR ci-dessous touche notre cœur d’orchestration d’agents — l’endroit le plus coûteux du dépôt où se relâcher — et chacune est classée Tier 3 : couverture de tests supplémentaire et revue humaine en plus du relecteur automatisé, sans exception.
Les trois compétences en un coup d’œil : ponytail soustrait, grain aligne, review-proof prouve.
Partie 1 · QUOI — l’entropie est le comportement par défaut
Voici ce dont personne ne vous prévient quand vous confiez un dépôt à des agents IA : chaque agent optimise localement et ne se souvient de rien. Il voit le ticket, pas les mois de conventions sur lesquelles votre équipe a convergé. Il n’a aucune raison de préférer votre service d’e-mail existant à un nouveau, aucun souvenir que l’ensemble des statuts de redirection est déjà défini trois fichiers plus loin, aucun instinct que « le correctif va dans la fonction partagée, pas dans cet appelant précis ». Laissés libres, N agents produisent N façons légèrement différentes de faire la même chose. Ce n’est pas un problème de qualité de code qu’on peut éliminer avec un linter — c’est une dérive structurelle qui s’accumule.
Les trois compétences ciblent chacune un axe de cette dérive.
ponytail — la chose la plus paresseuse qui fonctionne
Ponytail est un développeur senior qui a été réveillé à 3 h du matin pour l’abstraction ingénieuse de quelqu’un d’autre et qui refuse d’écrire la suivante. Il déroule une échelle et s’arrête au premier barreau qui tient : est-ce que cela doit exister du tout (YAGNI) → est-ce déjà dans cette base de code → la bibliothèque standard le fait-elle → une fonctionnalité native de la plateforme → une dépendance déjà installée → est-ce que ça tient en une ligne → et seulement alors, le minimum de code qui fonctionne.
Le barreau qui compte le plus pour les agents est « est-ce déjà dans cette base de code ? ». Réimplémenter ce qui se trouve quelques fichiers plus loin est la forme la plus courante de bâclage des agents. Et la règle de correction de bugs de ponytail garde les diffs honnêtes : corriger la cause racine, pas le symptôme. Passez au grep tous les appelants de la fonction que vous vous apprêtez à toucher ; une garde dans la fonction partagée est un diff plus petit qu’une garde dans chaque appelant — et elle ne laisse pas les frères cassés.
grain / grain-review — aller dans le sens du grain
Si ponytail régit combien peu vous écrivez, grain régit où cela va et quelle forme cela prend. Sa règle unique : trouvez l’exemple existant le plus proche, copiez sa forme, nommez ce que vous avez copié. Le nouveau code doit se lire comme si la personne qui a écrit le fichier d’à côté avait aussi écrit celui-ci.
Grain est aussi le lieu où l’architecture est appliquée. Notre backend est une disposition assez standard en tranches verticales + hexagonale — la présentation appelle l’application qui appelle le domaine, l’infrastructure dépend vers l’intérieur, et le domaine ne remonte jamais vers l’extérieur. Un constat comme « cette route saute son contrôleur et appelle directement le service » n’est pas de la pédanterie — c’est la différence entre une base de code qu’un agent pourra parcourir le mois prochain et une qu’il ne pourra pas. grain-review traque exactement ces cas : utilitaires dupliqués, frontières de couches franchies, accès aux entrailles d’une autre fonctionnalité, une seconde convention pour quelque chose déjà fait d’une seule manière.
review-proof — mériter le constat
Une revue de code IA standard produit des constats plausibles. Certains sont réels ; d’autres sont des inepties confiantes ; de l’extérieur, ils se ressemblent tous. review-proof refuse de se faire confiance : il examine, puis force chaque constat de correction à se reproduire sous forme de test en échec réel ou de reproduction exécutable, et écarte tout ce qui n’y parvient pas. Il se termine par une passe grain-review pour la cohérence structurelle. Ce qui est livré est une revue où chaque élément s’accompagne de preuves exécutables — pas d’une impression.
Ce que nous devrions observer si cela fonctionne
- H1 — Les suppressions apparaissent dans les PR de fonctionnalités. Si ponytail + grain fonctionnent, ajouter une fonctionnalité devrait souvent retirer de la structure nette, pas seulement en ajouter.
- H2 — Les correctifs arrivent une seule fois, au bon endroit partagé. Les corrections de cause racine devraient ramener de nombreux sites d’appel vers une seule garde, et non parsemer des gardes par appelant.
- H3 — La revue attrape les ruptures de contrat qu’un humain survole. Une revue appuyée par des preuves devrait faire remonter des bugs que la revue « ça a l’air correct » manque — en particulier ceux qui sont silencieux.
Partie 2 · ET ALORS — cinq PR, un instinct chacune
Cinq changements réels sur notre cœur d’agents. Nous gardons volontairement les détails internes vagues — le dépôt est privé — mais les chiffres sont calculés à partir des diffs réels et les leçons sont la partie transférable.
Soustraire : une garde pour une douzaine de sites de récupération
Une famille d’étapes de flux récupérait des URL fournies par l’utilisateur sans contrôle de sécurité par résolution DNS, de sorte qu’un nom d’hôte qui se résolvait vers une adresse interne pouvait atteindre les métadonnées cloud depuis le backend. Le correctif tentant ajoute une vérification à chacun des douze sites de récupération et plus. La réponse de Ponytail était l’inverse : un utilitaire de récupération partagé et protégé, utilisé partout — et nous avons supprimé une table de réseau privé faite maison qu’une astuce de DNS générique contournait allègrement, plus trois boucles de redirection dupliquées et un contrôle réseau copié-collé dans plusieurs fichiers.
Le diff a ajouté l’utilitaire partagé et supprimé ~90 lignes de duplication dans 22 fichiers. Cette suppression est toute l’histoire : c’est H2 incarné — la correction de cause racine a fait passer chaque appelant par une seule garde au lieu de rafistoler le seul chemin nommé dans le ticket.
La correction de cause racine : une douzaine de sites de récupération ad hoc s’effondrent en un seul utilitaire partagé et protégé. Le correctif paresseux et le correctif sûr sont le même correctif.
Soustraire + prouver : une garde de forme, prouvée sur le runtime réel
Notre runtime de workers persiste le résultat d’une exécution sous forme de chaîne sérialisée, parfois encapsulée dans une liste à un seul élément. Les consommateurs qui attendaient un objet simple plantaient dessus. Le mauvais correctif disperse des vérifications de type défensives chez chaque consommateur. À la place : un petit utilitaire de normalisation de forme, et chaque consommateur redirigé vers lui — un ajout quasi pur d’une garde qui remplace les N gardes ad hoc qu’un agent moins discipliné aurait écrites (+558 / −24, 7 fichiers).
Ce qui fait de ceci une histoire review-proof, c’est le test. Au lieu d’affirmer une forme de sérialisation supposée, nous avons exécuté un vrai workflow à travers le runtime et le stockage réels — aucun mock — et prouvé la forme que le runtime persiste réellement. La question ouverte du ticket était littéralement que sérialise le runtime ici ? — et la seule réponse honnête est une réponse que l’on peut exécuter.
Prouver : la revue a attrapé une rupture de contrat silencieuse
Fonctionnalité : un modèle de repli par nœud, afin qu’un flux épinglé à un fournisseur se dégrade proprement pendant une panne. La première version évidente enveloppait le modèle dans le combinateur de repli intégré au framework.
Cela fonctionnait sur le chemin nominal. Mais cela désactivait silencieusement deux fonctionnalités du fournisseur qui dépendent du type concret du modèle via isinstance — un objet enveloppé n’a plus ce type, donc la sortie structurée native et la mise en cache des prompts se sont toutes deux éteintes sans bruit. Aucune erreur. Aucun test en échec sur le chemin nominal. Exactement le genre de chose qu’une revue humaine survole et qu’un agent qui « trouve ça correct » approuve.
review-proof ne l’a pas approuvé — il a reproduit les deux ruptures sous forme de tests en échec, ce qui a forcé la refonte : appliquer le repli plus bas, au moment de l’exécution, pour que chaque modèle conserve son type concret et que les fonctionnalités dépendant du type continuent de fonctionner. H3, confirmée de manière décisive : la preuve a attrapé un bug que la plausibilité aurait livré.
Aligner : un seul sélecteur, pas deux copies
L’ajout d’un second canal de notification signifiait que l’interface de sélection de canal avait désormais deux foyers — un assistant de création et une fenêtre de paramètres. Le réflexe par défaut de l’agent ajoute la nouvelle branche aux deux, faisant croître deux copies de la même machine à états. grain a dit : il existe déjà une seule façon dont cela devrait être conçu — rendez-le partagé. Nous avons extrait un unique hook de sélection et fait passer les deux écrans par lui, inséré le nouveau canal dans l’union de configuration existante et réutilisé le service d’e-mail existant au lieu d’ajouter une nouvelle machinerie d’envoi.
+1 735 / −340 sur 24 fichiers. Une fonctionnalité de cette taille qui supprime 340 lignes, c’est H1 rendue visible : la déduplication de deux copies du sélecteur en une seule a payé une bonne partie du nouveau canal.
Aligner + prouver : réutiliser le point de terminaison, refléter le chemin
Permettre aux utilisateurs de joindre des fichiers à la création d’un ticket aurait pu signifier un nouveau point de terminaison d’upload, un nouveau mécanisme de dispatch, un nouveau chemin de prompt. grain a dirigé presque tout cela vers des rails existants : le point de terminaison d’upload existant, une liste d’acceptation côté frontend qui reflète exactement la liste blanche du backend, et une correction de dispatch différé qui réutilisait le mécanisme d’éligibilité déjà utilisé par le travail planifié. La fonctionnalité a été livrée avec des corrections appuyées par des preuves, y compris un vrai bug d’isolation de transaction qui aurait perdu des données lors d’uploads parallèles. +1 776 / −218 sur 27 fichiers — une grosse fonctionnalité qui a malgré tout trouvé 218 lignes à supprimer en rejoignant des tranches existantes au lieu d’en inventer de nouvelles.
Le tableau de bord
Cinq PR de Tier 3 : ce que chacune a ajouté, ce qu’elle a supprimé, et l’instinct derrière.
Cinq PR de fonctionnalités et de corrections sur le cœur d’agents ont supprimé 821 lignes — non pas en faisant moins, mais en refusant de dupliquer ce qui existait déjà et de conserver des rustines de symptômes qu’une correction de cause racine avait rendues redondantes.
Divulgation complète
- Ce sont des compétences, pas une étude. Il ne s’agit pas d’une expérience contrôlée avec un bras de référence ; ce sont cinq PR réelles où la discipline a été appliquée. Le contrefactuel — ce que le même agent aurait livré sans les compétences — est une estimation informée, pas une mesure. L’histoire de la rupture de contrat silencieuse est la preuve la plus nette, car nous avons vu la revue reproduire le bug avant la refonte.
- Les comptes de lignes sont des indicateurs indirects. Le −821 est un chiffre réel issu des diffs, mais « lignes supprimées » représente « duplication et flexibilité morte évitées ». Une compétence qui dissuade un agent d’écrire 200 lignes spéculatives ne laisse aucune trace dans un diff — les plus grands gains sont ici invisibles.
- Les économies de tokens sont directionnelles. Des diffs plus petits, moins de fichiers touchés et des structures réutilisées signifient moins de tokens dépensés à générer, relire et relire encore — mais nous ne citons pas de delta de tokens ferme par PR.
ponytailn’est pas la nôtre. C’est une compétence open source de Dietrich Gebert ; nous l’avons adaptée.grainetreview-proofsont les nôtres, construites dans le même esprit. Les trois s’exécutent comme compétences locales de projet sur Claude Code — des prompts et des procédures, pas un binaire à installer.
Partie 3 · ET MAINTENANT
Ce qui a été livré. Trois compétences composables. ponytail et grain s’exécutent pendant l’écriture ; ponytail-review, grain-review et review-proof s’exécutent sur un diff. review-proof enchaîne grain-review comme phase finale, de sorte qu’une seule revue prouvée bénéficie aussi d’une passe structurelle gratuite.
Ce que vous pouvez faire dès lundi — vous n’avez pas besoin de nos compétences exactes :
- Faites de « réutiliser » le deuxième barreau, pas le dixième. Avant qu’un agent n’écrive un utilitaire, faites-lui chercher par grep s’il en existe un. « Est-ce déjà dans cette base de code ? » doit venir au-dessus de « puis-je l’écrire proprement ? »
- Corrigez à la racine, prouvez-le avec la liste des appelants. Exigez que chaque correction de bug nomme tous les appelants de la fonction touchée. Une garde dans la fonction partagée vaut mieux qu’une garde par appelant — et c’est un diff plus petit.
- Donnez au nouveau code un frère le plus proche à copier. « Trouve l’exemple existant le plus proche et reflète sa forme » transforme l’architecture d’un document que personne ne lit en un comportement par défaut que l’agent suit.
- Appliquez les frontières de couches en CI, pas à l’instinct. Un cliquet qui échoue uniquement sur les nouveaux imports inter-couches vous permet de tenir la ligne sans faire bouillir l’océan de la dette existante.
- Ne livrez pas un constat que vous ne pouvez pas reproduire. Faites écrire d’abord le test en échec à l’agent. S’il n’arrive pas à faire reproduire le bug, ce n’est pas un bug — c’est une opinion. Écartez-la.
- Laissez la revue supprimer. Orientez une passe de revue spécifiquement vers la sur-ingénierie — « que pouvons-nous couper » — séparément de l’exactitude. Le meilleur résultat d’un diff, c’est qu’il devienne plus court.
Essayez, surtout si cela échoue chez vous. Si vous faites tourner des agents de codage sur une vraie base de code, l’entropie est déjà à l’œuvre — vous ne l’avez simplement pas mesurée. Transformez l’une de ces compétences en passe de revue sur vos dix prochaines PR d’agents et comptez les suppressions. Si soustraire-aligner-prouver ne réduit pas vos diffs ou n’attrape pas une rupture silencieuse, nous serions sincèrement curieux de le savoir. Corrections et contre-exemples particulièrement bienvenus.
Un agent ajoute. Le travail consiste à faire en sorte que l’agent mérite chaque ligne.

