Une spécification suffisamment détaillée, c’est du code
(haskellforall.com)- À propos de l’affirmation selon laquelle, avec le codage agentique, « la documentation de spécification peut remplacer le code », une limite fondamentale est soulignée : si une spécification devient suffisamment précise, elle finit inévitablement par converger vers la même forme que le code
- Le projet Symphony d’OpenAI montre que le fichier SPEC.md concerné n’est pas une spécification, mais en pratique un pseudocode au format Markdown
- En tentant réellement une implémentation en Haskell à partir de la spécification de Symphony, de nombreux bugs et des problèmes de fiabilité sont apparus, notamment une attente infinie de l’agent
- Le travail de spécification exige à l’origine une réflexion plus profonde que le codage, mais dans le climat actuel d’optimisation de la vitesse dans l’industrie, cela conduit à la production en masse de spécifications médiocres générées par l’IA
- Le principe « garbage in, garbage out » s’applique tel quel aussi aux agents de codage, et avec des documents dépourvus de clarté et de détail, il est impossible de générer du code fiable
Deux malentendus sur le codage agentique
- Les défenseurs du codage agentique s’appuient sur deux malentendus centraux
- Malentendu 1 : un document de spécification est plus simple que le code correspondant — une vision de type externalisation, selon laquelle on pourrait transformer les ingénieurs en gestionnaires rédigeant des spécifications et déléguer le travail à une équipe d’agents
- Malentendu 2 : le travail de spécification est nécessairement plus réfléchi que le travail de codage — l’idée qu’en passant par un document de spécification, on améliorerait la qualité et on encouragerait de meilleures pratiques d’ingénierie
Du code déguisé en spécification : analyse du cas Symphony
- Le projet Symphony d’OpenAI est présenté comme un orchestrateur d’agents généré à partir d’un document de spécification (SPEC.md), mais en réalité le contenu de ce SPEC.md se rapproche davantage d’un pseudocode au format Markdown que d’une spécification
- Types de contenu inclus dans SPEC.md :
- Dump rédigé en prose du schéma de base de données — énumération de champs comme
session_id,thread_id,codex_input_tokens, etc. - Transformation en prose de code — formules comme
available_slots = max(max_concurrent_agents - running_count, 0)pour le contrôle de concurrence, ou la formule de backoff de nouvelle tentative (delay = min(10000 * 2^(attempt-1), agent.max_retry_backoff_ms)) - Sections redondantes comme « Config Fields Summary (Cheat Sheet) », explicitement ajoutées pour aider le modèle à générer du code
- Sections « Reference Algorithms » qui sont en pratique du code à l’état pur, comme la fonction
start_service()
- Dump rédigé en prose du schéma de base de données — énumération de champs comme
- Affirmer qu’un document de spécification remplace le code alors que ce document se lit lui-même comme du code est trompeur
- Pour rendre un document de spécification suffisamment précis, il faut inévitablement le transformer sous une forme proche du code, ou l’écrire dans un anglais formel hautement structuré
L’argument de « l’interface étroite » chez Dijkstra
- En citant Dijkstra, le texte rappelle que le choix d’une interface n’est pas une simple répartition du travail, et qu’il ajoute un coût de collaboration et de communication à travers cette interface
- Exemples historiques à l’appui : les mathématiques grecques ont stagné en restant dans des activités langagières et visuelles, l’algèbre islamique a décliné en revenant à un style rhétorique, et l’Europe occidentale a progressé en s’éloignant des « vaines tentatives de précision verbale » du scolasticisme médiéval grâce aux systèmes symboliques formels de Vieta, Descartes, Leibniz, Boole et d’autres
- Les codeurs agentiques ne peuvent pas éviter le « narrow interface » (= le code) qu’exige le travail d’ingénierie ; ils ne peuvent que transformer ce travail en une forme qui paraît différente en surface mais exige la même précision
Instabilité : les problèmes de fiabilité de la génération de code à partir d’une spécification
- En demandant à Claude Code une implémentation en Haskell comme le recommande le README de Symphony, le résultat ne fonctionne pas
- De nombreux bugs apparaissent, nécessitant des corrections via les prompts (vérifiables dans l’historique des commits)
- Même dans les cas où cela « fonctionne » sans message d’erreur, l’agent
codexreste bloqué en attente infinie sans aucun progrès sur un ticket Linear simple (« créer un dépôt git vide »)
- Pour reprendre l’expression de Dijkstra, cela confirme que les « vaines tentatives de précision verbale » de Symphony échouent toujours à produire une implémentation fiable
- Le problème ne se limite pas à Symphony — même des spécifications comme YAML, extrêmement détaillées, largement utilisées et dotées de suites de tests de conformité, voient la majorité des implémentations YAML ne pas respecter complètement la spec
- La spécification de Symphony représente déjà un sixième de la taille de l’implémentation Elixir incluse ; en l’étendant davantage, on finirait dans une situation comparable à « De la rigueur de la science » de Borges — la fable d’une carte de l’empire à l’échelle de l’empire lui-même, devenue finalement inutile
- À l’objection selon laquelle « le résultat serait meilleur dans un langage plus mainstream », l’auteur répond que si les agents peinent à générer du code Haskell, cela suggère un manque de capacité de généralisation au-delà des données d’entraînement
Slop : le problème de qualité des spécifications générées par l’IA
- Le travail de spécification devrait à l’origine être plus difficile que le codage ; son but est d’amener à considérer un projet avec un regard réfléchi et critique avant de commencer à coder
- Mais dans la tendance actuelle du secteur tech à réduire et dévaloriser le travail, partir de l’hypothèse que « le travail de spécification est plus facile que le codage » mène à un échec programmé
- Il est impossible d’accomplir le travail difficile et inconfortable qu’exige la rédaction de spécifications tout en poursuivant l’optimisation de la vitesse de livraison
- La section 10.5 du SPEC.md de Symphony (contrat d’extension
linear_graphql) est un exemple représentatif de slop — une production d’agent faite de phrases qui ressemblent à une spécification mais manquent de cohérence, de finalité et de compréhension d’ensemble- Des règles individuelles sont listées, comme le fait que
querydoit être une chaîne non vide et contenir exactement une opération GraphQL, mais le contexte global manque
- Des règles individuelles sont listées, comme le fait que
- Même lorsqu’ils sont écrits par des humains, de tels documents de spécification sont inévitablement du slop — parce qu’ils sont optimisés pour le délai de livraison plutôt que pour la cohérence ou la clarté
- Le fait que des snippets de code soient annotés comme
textsans coloration syntaxique est aussi un signe de document généré par l’IA — vraisemblablement parce que le modèle a suivi la lettre de la demande plutôt que son intention
Conclusion
- Les spécifications n’ont pas été conçues à l’origine comme un mécanisme de gain de temps
- Si l’objectif est l’optimisation du délai de livraison, il est plus avantageux d’écrire directement le code que de passer par un document de spécification intermédiaire
- Le principe « garbage in, garbage out » s’applique ici sans changement — si l’entrée est un document manquant de clarté et de détail, il n’existe pas de monde dans lequel un agent de codage pourra combler ce manque de manière fiable
- Les agents de codage ne lisent pas dans les pensées ; et même s’ils le pouvaient, si la pensée elle-même est confuse, ils ne peuvent rien y faire
6 commentaires
On dirait exactement la même chose qu’à l’époque du développement piloté par les modèles.
Le développement piloté par les spécifications, SDD, ça existait déjà à l’origine, non ?
On dirait qu’avec des solutions basées sur Python ou JavaScript, il est possible d’obtenir une implémentation satisfaisante avec un simple document de spécifications détaillées. Je travaille dans le jeu vidéo et le médical sur une base C/C++, et ces derniers temps je me dis de plus en plus que même automatiser à partir d’un document de spécifications détaillées est déjà bien trop risqué, sans parler de déléguer à un agent IA complet.
Commentaires Hacker News
Je ne suis pas d’accord avec l’idée qu’un agent de codage ne peut pas combler les détails manquants si on lui donne une documentation floue
Les LLM sont fondamentalement des machines d’interpolation/extrapolation du langage, et ils sont très doués pour compléter les détails manquants
Il existe de nombreux cas où ils produisent du code fonctionnel à partir d’une description courte et concise
En revanche, ces compléments ne sont pas toujours exacts, et pour garantir la fiabilité il faut contraindre explicitement les parties importantes
Nous avons aujourd’hui une culture de l’écriture de code, mais presque aucune culture de rédaction de spécifications ultra-précises, en dehors d’endroits comme la NASA
Plus le code est court et courant, mieux cela fonctionne, mais dès qu’une description devient complexe, cela s’effondre vite
Au fond, reconnaître que « les détails ajoutés peuvent être faux », c’est admettre qu’une génération fiable est difficile
Il existe par exemple des langages de synthèse de programmes comme Synquid
Ils montrent les limites des spécifications mathématiquement exactes pour la génération de programmes
Le problème appelé specification gap — autrement dit prouver qu’un programme implémente fidèlement sa spécification — est l’enjeu central
Le langage naturel est trop ambigu pour définir correctement un programme
Le fait qu’un LLM remplisse les vides avec des détails plausibles ne résout pas cet écart
Les langages de spécification mathématique sont précis, mais leur courbe d’apprentissage est élevée, et c’est bien plus difficile et laborieux que d’écrire simplement un prompt en Markdown
Le modèle se souvient de mes centres d’intérêt, ou comble les lacunes avec ses propres connaissances, pour produire une application, un jeu ou un livre blanc abouti
Parfois, c’est « exactement ce que je voulais », et parfois c’est « précisément l’ambiance que j’essayais de décrire »
Sa capacité à traiter le sens, le contexte et les nuances dépasse même parfois celle des humains
L’IA devient de plus en plus intelligente et compétente
Autrement dit, ils ne créent pas vraiment des détails totalement nouveaux ; ils se rapprochent plutôt d’un rappel de ce qu’ils ont vu dans les données d’entraînement
Je me reconnais dans l’idée que « une spécification suffisamment détaillée, c’est déjà du code »
C’est le même raisonnement que dans No Silver Bullet de Brooks
Mais la plupart des gens ne veulent pas ce niveau de détail
Quand on dit à une IA « crée-moi une application de to-do », cela veut en réalité dire : « crée-moi une application meilleure que celle que j’imagine »
Mais cette approche se généralise mal à d’autres types de logiciels
Au final, cette différenciation doit être exprimée sous forme de spécification
Mais dans des domaines comme les bases de données, systèmes de fichiers, calcul parallèle, où l’exactitude et les performances comptent, l’implémentation est bien plus difficile que la spécification
Dans ces contextes, faire produire par l’IA du code qui passe une vérification formelle est un énorme défi
Pour gagner de l’argent ou concurrencer d’autres produits, il faut des exigences concrètes
Si l’on regarde le vibe coding du point de vue de la théorie de l’information, cela suppose l’existence d’un décodeur capable de reconstruire un espace de programmes utiles à partir d’un petit espace de prompts
Le taux de compression est alors précisément le gain apporté par le vibe coding
Un prompt du type « application de communication d’équipe basée sur des canaux IRC » est impossible à décoder si l’on ne connaît pas Slack
Il est donc important d’identifier ce qui manque
Pour coder efficacement avec l’IA, il faut découper les prompts en petites unités et fournir en plus la documentation existante, le code déjà tenté, etc.
Selon l’Algorithmic Information Theory, la quantité d’information d’une chaîne est égale à la longueur de sa représentation autoporteuse la plus compressée
Cela dit, la condition « autoporteuse » ne tient que lorsque les poids du modèle jouent le rôle de livre de codes
Les humains supposent un contexte partagé bien plus large que les LLM, et surestiment donc souvent les limites du décodeur
Mais avec un système fortement contraint et des points d’accentuation clairs, on pourrait probablement faire exploser le taux de compression du vibe coding
Le langage naturel offre aussi une nouvelle interface à des personnes pour qui les langages de programmation sont moins accessibles
Le LLM ne réfléchit pas à leur place, mais il ouvre une nouvelle voie pour transformer une idée en système fonctionnel
Bientôt, les gens vont probablement créer une sorte de dialecte d’anglais technique comme LLMSpeak pour améliorer les performances des modèles et l’efficacité en tokens
L’idée serait de réduire l’ambiguïté, d’économiser des tokens et de compresser des concepts complexes en un seul mot
On verra peut-être même apparaître des règles grammaticales comme la virgule d’Oxford pour gagner en clarté
Si l’on va jusqu’à spécifier les choses avec ce niveau de détail, il n’y a plus vraiment de raison d’utiliser des prompts
Au final, il faut donc le redéfinir en langage humain ordinaire, ce qui limite fortement le gain en tokens
Voir le wiki Lojban et une vidéo d’un locuteur de Lojban
Les tentatives de dialectes artificiels risquent fort d’échouer, comme l’espéranto
Ce genre de langue pourrait plutôt être utile entre LLM
Les langages de programmation jouent déjà en partie ce rôle
Une spécification (spec) est comme une enveloppe qui contient tous les programmes satisfaisant les conditions données
Construire cette enveloppe est plus difficile qu’écrire un seul programme
De la même façon qu’un LLM génère un code différent à chaque fois, une spécification autorise à la fois de bonnes et de mauvaises implémentations
En pratique, une fois qu’une implémentation est adoptée, elle devient la spécification de fait de la version suivante
Dans un environnement brownfield, où il existe déjà du code, les spécifications ne sont pas propres, ce qui rend la tâche difficile pour les LLM
Il y a une explosion combinatoire : il faut réfléchir à la façon dont chaque ligne d’une spécification interagit avec les autres
Mais du point de vue d’un compilateur, le code n’est lui aussi qu’une spécification
Au final, dire que « le code est plus facile que la spécification » reste une affirmation relative
Une spécification du type « stocker les identifiants utilisateur » couvre aussi bien bcrypt que des cookies en clair
Les humains ont une intuition du type « ça, il ne faut pas le faire », mais un agent ne le sait pas si on ne le précise pas
Donc, pour garantir la sécurité, il faut aussi spécifier ce qu’il ne faut pas faire
Si les performances ou la sécurité sont importantes, il faut spécifier aussi ces propriétés
Par exemple, une phrase comme « ce programme doit être en O(n) » est bien plus simple que l’implémentation elle-même
On dirait que chacun utilise spec avec un sens différent
Pour moi, une spec définit le « quoi » (what), un plan définit le « comment » (how), et un build packet désigne les étapes détaillées
Dans la plupart des cas, ce qui compte, c’est le « quoi »
Écrire comme spécification que des données vont de A à B, passent par C, sont conservées dans D et représentées sous la forme F dans E est bien plus simple que de l’implémenter en Rust
Quand on pratique l’ingénierie agentique, on se retrouve souvent avec des documents de spécification plus longs que le code
Le langage naturel est imparfait, mais le code est exact
Le but d’une spécification est de préserver les fonctionnalités au fil de plusieurs itérations de développement
J’ai trouvé que des documents de conception de type waterfall étaient plus efficaces que des tests ou des commentaires
Avec cette approche, j’ai aussi pu refactorer sans friction des projets complets de vibe coding ou changer de langage
En ce moment, on a presque l’impression de revenir aux méthodes de développement des années 70–80
Une phrase comme « implémente une interface TCP » est bien plus courte que le code réel
Au fond, si l’on peut faire la correspondance avec un schéma clair, le langage naturel peut lui aussi être assez compressif
La direction Spec → LLM est inefficace et gaspilleuse
La direction LLM → Spec est au contraire plus réaliste
Si la spécification existe sous une forme compilable, le LLM peut utiliser ce retour pour générer un meilleur code
Les tentatives de créer un « anglais validé » ne font qu’ajouter de la complexité
Ce qui compte au final, c’est du code qui fonctionne réellement
Le code contient bien plus d’informations qu’une spécification
Dans la plupart des projets, 90 % relèvent du framework ou du code d’infrastructure, et seulement 10 % de la logique métier
Une spécification ne traite pas des détails du langage ou du framework, donc elle est bien plus concise
On obtient alors un code presque au même niveau qu’une spécification
Des experts métier peuvent le lire, et il devient aussi plus facile à tester
En revanche, le code réel change assez fortement
Le conflit entre la vision de la spécification comme outil de gestion et sa vision comme outil d’ingénierie crée une dissonance cognitive
Les managers voient la spécification comme un ticket à déléguer, tandis que les développeurs l’utilisent comme un outil de pensée pour affiner leur raisonnement
Certains développeurs commencent commodément avec l’état d’esprit du manager, puis finissent vite par comprendre
Le battage médiatique ou les réunions avec les investisseurs peuvent faire tenir un temps, mais au bout du compte, les utilisateurs veulent un vrai produit
Ensuite, ils vont aussi réinventer le cycle en V et l’agile, j’imagine.
En tant que développeur embarqué en C, j’établis des spécifications qui permettent de vérifier presque tous les flux d’une Feature/Subfeature sous forme de diagrammes.
Après avoir longuement revu les spécifications et les avoir définitivement validées,
je génère et utilise du code qui leur correspond complètement, en 1:1.
Quand on les examine via les spécifications, la lisibilité est de loin supérieure à une revue de code.