Avant de lui confier un bug, je lui ai appris où chercher
Deux semaines avec Claude Code sur un back-office qui a de l’histoire. Ce que je lui ai donné avant de lui demander quoi que ce soit, un bug d’export qu’il a démêlé grâce à ça, et l’endroit où je mets la limite.
Cela fait deux semaines que nous utilisons Claude Code sur notre back-office de prise de commande. Deux semaines, ce n’est pas un bilan : c’est un début, et je l’écris comme tel.
Mais ces deux semaines m’ont déjà appris une chose. Sur une application qui a de l’histoire, ce qu’il faut savoir pour corriger un bug n’est presque jamais dans le code. C’est dans le plan batch, dans les logs d’une tâche automatisée, dans une table, dans la page qui décrit ce qu’une autre application attend de la nôtre. Un agent qui ne voit que le dépôt devine. Je voulais un agent qui aille vérifier.
Alors avant de lui confier quoi que ce soit, j’ai passé du temps à lui apprendre où chercher.
Trois étages
Rien d’exotique : des fichiers texte et quelques gestes rangés.
- Un
CLAUDE.md, partagé par l’équipe. L’architecture, les conventions du projet, et surtout les liens vers les pages de flux de notre Confluence, dont il garde le contenu sous la main : ce que l’application reçoit, ce qu’elle envoie, à qui, et qui dépend d’elle. - Un
CLAUDE.local.md, propre à mon poste. Comment se brancher aux bases et aux machines depuis mon poste. Hors production, sans exception. - Des skills, pour les gestes qui reviennent. Retrouver un flux et ce qui l’entoure. Préparer une livraison, scripts de migration compris — ceux de la note précédente.
Il sait aussi comment tourne la maison : notre back-office suit un plan batch précis, marché par marché, et il sait où retrouver les logs de chaque tâche automatisée.
Le résultat, c’est qu’il ne part plus d’une page blanche. Face à un bug, il se fabrique son contexte lui-même : il lit le plan, ouvre les logs, regarde en base, relit le flux concerné. Exactement ce que je ferais, dans le même ordre.
Un bug, pour voir
Le métier nous remonte un problème : aucun message n’est généré pour le service d’éditique, c’est-à-dire l’imprimeur.
Le contexte tient en trois lignes. Nos bases sont multi-pays. L’export vers l’éditique est un job qui ramasse en base les messages disponibles et en fait un fichier ; il est lancé une fois par marché. Pendant longtemps il n’y a eu qu’un marché. Nous venions d’en ajouter deux.
Trois marchés, donc trois exécutions, à cinq minutes d’intervalle :
T export --market=A -> picks up every pending message, flags them all as A
T + 5 min export --market=B -> nothing left to export
T + 10 min export --market=C -> nothing left to exportLe paramètre qui indique le marché existait bien. Il ne servait qu’aux logs. Il ne filtrait rien.
// Simplified. Before: the market only reached the logs.
log.info("Export started for market {}", market);
List<Message> pending = messageRepository.findPending();
// After: the market decides what the job is allowed to take.
List<Message> pending = messageRepository.findPendingByMarket(market);Tant qu’il n’y avait qu’un marché, ce code était juste. Il l’est resté longtemps. Le jour où deux pays sont arrivés, la première exécution a tout pris, tout étiqueté à son nom, et les deux suivantes ont tourné à vide. C’est le genre de bug que le code hérité fabrique tout seul : rien n’a cassé, c’est le monde autour qui a changé.
Ce que Claude Code m’a rendu, ce n’est pas seulement la ligne à corriger. C’est l’histoire complète : l’historique du plan batch et de ses trois exécutions, ce qui était disponible comme messages à ce moment-là, la cause, le correctif proposé, et un plan de rattrapage pour les messages étiquetés au mauvais marché.
Le correctif tient en une ligne. Tout le reste est du contexte, et c’est ce reste qui prend du temps quand on le reconstitue à la main.
Où je mets la limite
Il propose. La décision reste la mienne, et certaines portes restent fermées.
Pas de production. Ses accès s’arrêtent aux autres environnements. Ce n’est pas un réglage que j’ajusterai quand j’aurai davantage confiance : c’est une porte qui ne s’ouvre pas.
Je lis en ce moment deux textes qui m’aident à mettre des mots là-dessus. Addy Osmani décrit le développeur qui devient le manager de ses agents : le plus difficile n’est plus d’écrire le code, c’est de bien confier le travail et de vérifier ce qui revient. Et un long texte sur les boucles et les graphes d’agents défend une idée que je trouve très juste : on ouvre les vannes selon ce que coûte une erreur, pas selon l’assurance affichée par le modèle.
J’en garde trois règles, pour la suite :
- Le contrôle d’abord. « Ça a l’air bon » n’est pas une vérification. Il faut quelque chose qui puisse échouer : un test, un cas rejoué sur une base de recette.
- La réversibilité décide. Une correction isolée se défait d’un revert. Une migration, une suppression, une écriture sur des données de production ne se défont pas : celles-là, il les prépare, quelqu’un les relit, quelqu’un d’autre les passe.
- Une cause confirmée devient une règle. Ce bug doit laisser une trace dans le
CLAUDE.md: un paramètre de job qui ne filtre rien est suspect. Sinon je le recroiserai.
Ce que j’en retiens
Un agent vaut ce que vaut le contexte qu’on lui laisse trouver.
Je n’ai pas gagné du temps parce qu’un modèle écrit du Java plus vite que moi. J’en ai gagné parce que j’ai écrit, une fois, ce que je sais de cette application et où se trouve le reste — ce que j’aurais dû écrire de toute façon, pour le prochain collègue qui arrive.
Deux semaines, donc. Trop tôt pour dire ce qui tiendra. Je reviendrai ici dans quelques mois, avec ce qui a raté.