
Si votre IA vous propose un patch plausible calqué sur du code existant mais que quelque chose vous semble douteux, si la formule « la base de code fait déjà ça » vous paraît de plus en plus suspecte, si les mêmes erreurs se répètent même avec un modèle plus grand — le problème n’est pas l’intelligence du modèle, c’est la structure qui confond le précédent avec la vérité.
C’est une histoire que j’ai vécue directement. Plus précisément, ce que l’IA qui travaillait avec moi a fait face à mon code. Je suis intervenu avec une seule phrase, et ce que cette phrase a brisé, c’est le cœur de cet article.
Le point de blocage
Je construisais un générateur de code — un outil qui, à partir d’une spécification déclarative (un schéma), produit à la fois le backend et le frontend. La promesse centrale de cet outil est unique : « si la validation est passée, le build réussit nécessairement. » Si le validateur donne le feu vert et que le compilateur donne le feu rouge, c’est l’outil qui a menti.
Un jour, un type particulier (un identifiant unique, UUID) a bloqué le validateur. Il s’est arrêté avec un message du type « attendait une chaîne, a reçu un autre type ». J’ai demandé à l’IA de débloquer la situation. Elle a tracé le code et a rapidement trouvé quelque chose de familier.
« Un type similaire (une valeur temporelle) est déjà bien géré dans la même situation. Il existe une branche avec un marqueur spécial pour que le validateur le laisse passer. Pour UUID, cette branche est absente. C’est une simple omission. Il suffit de restaurer la symétrie. Je vais copier sur UUID la même approche appliquée à la valeur temporelle. C’est la solution de fond. »
Le diagnostic était propre. « Asymétrie », « restauration de la symétrie », « solution de fond ». Les mots étaient solides. Un plan avait même été rédigé. Si on l’avait suivi, le patch aurait été mergé.
Une seule phrase
J’ai lu le plan, je me suis arrêté et j’ai posé la question :
« Précédent ? Ce traitement de la valeur temporelle est-il vraiment la bonne méthode ? Vérifie. »
C’est tout. Je ne connaissais pas la réponse. Je ne savais pas non plus comment UUID devait être traité. Ce que j’avais, ce n’était pas une réponse mais un doute — « ce point de référence que tu veux copier, a-t-il été validé ? »
Cette seule phrase a forcé l’IA à passer du mode référence-code au mode vérification-comportement.
Les prémisses s’effondrent
Quand l’IA a vérifié la production réelle — non pas la structure du code, mais les résultats concrets que l’outil génère — les prémisses se sont effondrées entièrement.
- La valeur attendue sur laquelle le validateur était censé « attendre une chaîne » était elle-même une fiction en désaccord avec la production. Le générateur réel produit UUID comme un type dédié et la valeur temporelle comme un type temporel. Ni l’un ni l’autre n’est une chaîne.
- Le traitement de la valeur temporelle, présenté comme « bien géré », contenait le même trou. Ce n’était pas une conception correcte, mais un bricolage défectueux qui passait la validation tout en pouvant faire échouer le build.
- Si on avait copié ce bricolage sur UUID ? On aurait créé un état de plus où le validateur donne le feu vert et le compilateur le feu rouge — une violation frontale de la promesse centrale de l’outil.
La solution que l’IA appelait « solution de fond » était fausse. Et pas simplement fausse : c’était une direction encore pire, qui dupliquait le défaut existant tout en faisant ignorer le nouveau défaut par le validateur.
Comment appeler cela — error amplification
Donnons un nom à ce qui s’est passé ici. C’est l’error amplification (amplification d’erreurs) par l’IA.
L’IA lit le code existant et perçoit sa structure avec précision. Mais qu’il s’agisse d’une conception correcte ou d’un bricolage posé à la hâte — autrement dit, d’une décision ou d’une dette — elle ne peut le distinguer en regardant uniquement le code. Voilà ce qui se passe alors :
- Elle considère l’implémentation existante comme une vérité implicite,
- au nom de la « cohérence » et de la « symétrie », elle réplique ce motif dans une nouvelle situation,
- et plus la réplication se fait, plus ce motif acquiert une fausse autorité : « la base de code le fait déjà à plusieurs endroits ».
Le défaut n’est pas éliminé. Le nombre d’occurrences augmente et la légitimité s’accumule. C’est ça, l’amplification. Un bricolage en devient deux, et face au troisième, plus personne ne s’interroge — « c’est comme ça que la base de code fonctionne. »
Ce n’est pas une histoire qui s’arrête à mon anecdote. En 2025, une équipe de chercheurs a mesuré précisément ce phénomène et lui a donné le titre « LLMs are Bug Replicators (les LLM sont des réplicateurs de bugs) ». (Pan et al., 2025, arXiv:2503.11082) Quand le code environnant contenait des défauts, une grande partie des bugs produits par les modèles étaient littéralement identiques aux bugs existants — GPT-4o atteignait 82,6 %, et en moyenne sur les modèles, 44,4 % correspondaient exactement à la version pré-correction. Ce qui est encore plus glaçant : dans un contexte défectueux, la probabilité de produire du code correct et celle de produire du code incorrect sont presque 1:1. Le modèle ne se trompe pas au hasard. Il sélectionne et reproduit les motifs défectueux enfouis dans le contexte.
Le droit présente le même piège. Un précédent mal rendu acquiert de l’autorité à force d’être cité. Le nombre de citations n’est pas une preuve de légitimité, et pourtant nous continuons à confondre les deux. Et c’est une maladie que le génie logiciel connaissait avant l’IA — les clones de code créés par copier-coller transportent silencieusement les bugs de l’original. Une étude empirique a montré qu’environ 18 % des clones ayant subi une correction de bug portaient ainsi des bugs propagés, et que la probabilité de propagation était plus élevée pour les clones dans le même fichier. (Mondal et al., ICSME 2017) En code comme en droit, la fréquence d’un précédent n’est pas sa légitimité.
Pourquoi en est-on arrivé là
Ce n’est pas parce que l’IA était stupide. C’est précisément l’inverse — parce qu’elle était prudente, elle cherchait à maintenir la cohérence, et en cherchant la cohérence, elle s’est alignée sur un mauvais point de référence. Le mécanisme se décompose en quatre éléments.
- Elle a placé l’autorité dans le code. « Le code est ainsi, donc c’est correct. » Mais le code peut n’être qu’une projection éphémère d’une décision — ou simplement de la dette. L’IA n’a pas fait cette distinction. Les sciences cognitives appellent cela le biais d’ancrage. Une étude expérimentant ce biais dans les LLM a montré que les modèles sont fortement attirés par la valeur donnée en premier, que cette attraction s’intensifie quand cette valeur est attribuée à un « expert », et que les prompts demandant d’ignorer l’indice ou de raisonner étape par étape corrigent mal ce biais. (Nguyen et al., 2024, arXiv:2412.06593) L’implémentation existante est l’ancre la plus autoritaire que la base de code peut fournir.
- Elle a confondu cohérence et justesse. « Alignons-nous sur l’existant » était une logique interne, sans vérifier si ce point de référence correspondait à la réalité externe (la production). La cohérence interne est une propriété distincte de la précision — le modèle peut accumuler une confiance infondée à travers des auto-explications plausibles mais erronées. (Chen et al., 2023, arXiv:2305.14279)
- Elle a pris les commentaires pour des preuves. Elle a accepté le commentaire « ce type est délibérément ramené à une chaîne » comme « une preuve de conception correcte ». Un commentaire n’est que l’intention de son auteur, pas une preuve de légitimité.
- Elle a emballé la dette avec un vocabulaire de certitude. Des mots comme « solution de fond », « comme prévu » ont conféré une crédibilité à une proposition non vérifiée, augmentant le coût de filtrage pour moi. Les modèles entraînés sur les préférences humaines sont inclinés à privilégier la conciliation et la politesse plutôt que la précision — cette tendance appelée sycophancy pousse le modèle à présenter ses propositions de manière douce et péremptoire. (Sharma et al., ICLR 2024, arXiv:2310.13548)
Qu’est-ce qui a brisé la boucle
Voici le cœur de cet article. Ce qui a brisé l’erreur, ce n’était ni un modèle plus grand, ni un temps de réflexion plus long. C’était une seule ligne de remise en question humaine.
Et cette remise en question n’était pas une intervention de quelqu’un qui « connaissait la réponse ». Je ne connaissais pas la réponse. C’était une indication de direction : « remet en cause la prémisse ». Cette seule ligne a suffi pour que l’IA change de mode — de la main qui référençait le code à la main qui vérifie le comportement.
Remarquablement, une étude a trouvé exactement cette asymétrie. Des chercheurs de DeepMind ont montré que la faible capacité d’auto-correction des LLM ne vient pas d’une absence de capacité à corriger les erreurs, mais d’une absence de capacité à les trouver — si la localisation de l’erreur est fournie de l’extérieur, le modèle la corrige bien. (Tyen et al., Google DeepMind, 2023, arXiv:2311.08516) C’est exactement ce que j’avais fait. Je ne savais pas comment corriger UUID, mais j’avais indiqué l’emplacement : « ici, remet en cause ce précédent ». C’était suffisant.
Cela dit quelque chose sur la structure de la collaboration humain-IA. La valeur humaine ne réside pas dans le fait de savoir plus vite et davantage. L’IA gagne déjà sur ce terrain. La valeur humaine réside dans la capacité à se positionner là où on peut remettre en cause les prémisses sur lesquelles l’IA s’appuie. La question « est-ce vraiment correct ? » appartient non pas à celui qui a la réponse, mais à celui qui sait douter de la réponse.
Mais cette position n’est pas donnée gratuitement. Une étude utilisateur de Stanford a rapporté le fait inconfortable que les participants assistés par l’IA écrivaient du code moins sécurisé tout en croyant que leur code était plus sécurisé. Et dans la même étude, les participants qui faisaient moins confiance à l’IA et posaient davantage de questions produisaient du code plus sécurisé. (Perry et al., Stanford, 2022, arXiv:2211.03622) La position de doute n’est pas la valeur par défaut. Plus la confiance est profonde, plus cette place se vide.
Alors, comment prévenir cela
La leçon doit rester une conception, pas un réconfort.
- Précédent ≠ vérité. Avant d’étendre un motif existant, on vérifie non pas s’il est cohérent en interne, mais s’il produit un résultat correct.
- Ancrer sur la réalité (ground truth). Le critère de jugement doit être non pas « la structure du code existant » mais la production réelle, le comportement à l’exécution, les tests. Dans ce cas, le facteur décisif était partout « qu’est-ce qui est réellement produit ? », non pas « à quoi ressemble le code ? ».
- S’efforcer de distinguer décision et bricolage, mais admettre qu’on ne peut pas toujours le faire. Quand le code et les commentaires seuls ne permettent pas de les différencier, on explicite l’incertitude : « ceci suit le précédent, et la légitimité du précédent est non vérifiée ».
- Modérer le vocabulaire de certitude. Avant vérification, on n’appose pas de mots comme « fond », « vérité », « comme prévu » sur une proposition.
- Insérer des points de contrôle dans l’automatisation. Pour toute décision d’un agent d’étendre une implémentation existante, une porte forçant la question « la légitimité de ce précédent a-t-elle été vérifiée ? » est nécessaire.
En fin de compte, la même histoire
Depuis longtemps je dis une chose. Le raw code n’est pas un médium qui préserve les décisions. Le code ne peut pas porter le « pourquoi a-t-on fait ainsi ». C’est pourquoi git blame montre qui et quand, mais pas quelle décision a été prise.
Cet incident est la démonstration la plus acérée de cette proposition. Ce n’est pas une histoire où les personnes perdent les décisions. C’est une histoire où même un agent soigneusement conçu confond le bricolage avec la conception et le propage dans du nouveau code. Quand les décisions ne sont pas explicitement enregistrées, l’intelligence n’est pas une solution. Au contraire, plus on est intelligent, plus on diffuse la dette de manière cohérente et plausible.
C’est pourquoi je construis des spécifications. J’inscris les décisions dans une unique couche déclarative faisant autorité, en dehors du code. Plutôt que d’attendre que chaque fois un humain lance la phrase qui remet en cause le précédent, je veux que le système la lance lui-même.
La loi n’est pas un couteau mais un panneau indicateur. Un bon panneau dit à l’égaré « doute ici » à l’avance. Cet article est l’enregistrement de comment un tel panneau a été érigé — en partant d’une seule ligne de remise en question.
Articles liés
- Ce que git blame ne montre pas — La structure par laquelle le code ne préserve pas le « pourquoi », et comment combler cette absence
- La quille (yongol) : le mur des 200 endpoints — L’implémentation de la prescription qui consiste à inscrire les décisions dans une unique couche déclarative (SSOT)
- Le biais de flagornerie de l’IA est une feature commerciale — La racine de la tendance à emballer la dette avec un vocabulaire de certitude
- Pourquoi les agents de code fonctionnent et pourquoi ils s’effondrent — Pourquoi la vérification doit se trouver en dehors du LLM
Lectures complémentaires (externes)
- Generative AI and the End of Chesterton’s Fence — Reece. Le principe « ne démontez pas une clôture sans en comprendre la raison » s’effondre face à du code généré de façon probabiliste sans intention. Se raccorde exactement à la thèse de cet article : le code ne préserve pas la décision qui le sous-tend.
- Programming as Theory Building — Christian Ekrem. En s’appuyant sur le classique de Peter Naur, il argumente que « un programme n’est pas le code source, mais la théorie dans la tête des gens ». La racine théorique de pourquoi l’IA, en ne voyant que le code, ne peut distinguer conception et dette.
- Vibe coding is not the same as AI-Assisted engineering — Addy Osmani. Il analyse pourquoi le vibe coding, qui fait confiance aveuglément aux sorties de l’IA, explose en production à travers des incidents réels, et prescrit un workflow basé sur les spécifications et la vérification humaine.
- Cognitive Debt — Simon Willison (citant Storey). Plus l’IA génère du code rapidement, plus la vraie dette devient non pas « les défauts du code » mais « le fait que les gens ne comprennent plus ce code » — le concept de dette cognitive.
- Overreliance on AI: Addressing Automation Bias — Lumenova AI. Le mécanisme par lequel biais d’automatisation, ancrage et biais de confirmation émoussent le jugement humain, et la solution du « dispositif de contrainte cognitive » — soutien psychologique à la valeur humaine qui consiste à savoir où douter.
Bibliographie
- Pan et al. “LLMs are Bug Replicators: An Empirical Study on LLMs’ Capability in Completing Bug-prone Code” (2025, arXiv:2503.11082)
- Mondal, Roy, Schneider. “Bug Propagation through Code Cloning: An Empirical Study” (ICSME 2017, link)
- Nguyen et al. “Anchoring Bias in Large Language Models: An Experimental Study” (2024, arXiv:2412.06593)
- Chen et al. “Two Failures of Self-Consistency in the Multi-Step Reasoning of LLMs” (2023, arXiv:2305.14279)
- Sharma et al. “Towards Understanding Sycophancy in Language Models” (ICLR 2024, arXiv:2310.13548)
- Tyen et al. (Google DeepMind). “LLMs cannot find reasoning errors, but can correct them given the error location” (2023, arXiv:2311.08516)
- Perry, Srivastava, Kumar, Boneh. “Do Users Write More Insecure Code with AI Assistants?” (Stanford, 2022, arXiv:2211.03622)
- Image principale : générée par IA (Google Gemini)