Le contexte que vous écrivez
Lequel de vos mots est lequel
Le nom qu’il a mal compris
L’agent s’est trompé sur un mot. Tout ce qui découlait de ce mot était juste.
La tâche touchait une chose appelée workspace. Il ne m’a jamais demandé ce que ça voulait dire, parce qu’il ne savait pas qu’il y avait quelque chose à demander. Il avait déjà un sens parfaitement utilisable : un workspace, c’est l’endroit où je travaille. L’endroit où je travaille, c’est ce dépôt. Donc cette fonctionnalité parle de ce dépôt.
Puis il a planifié. Soigneusement, longuement, exactement comme on veut qu’un agent planifie. Ce qui est revenu, c’était une restructuration complète du dépôt. Des répertoires déplacés, des frontières de modules redessinées, une migration ordonnée avec les étapes risquées signalées et séquencées. Du vrai bon travail, posé sur le mauvais nom.
Il y avait un vrai Workspace dans cette base de code. Un objet du domaine, avec ses champs, ses tests et ses appelants. L’agent en avait inventé un second sans jamais remarquer la collision, parce que de l’intérieur il n’y avait rien à remarquer.
Je l’ai attrapé à la revue du plan d’implémentation, le dernier point de contrôle avant qu’un agent ne commence à toucher aux fichiers, et j’ai refusé le plan. Ce point de contrôle est un filet, pas une solution, et savoir où les placer est une discipline en soi.
Ce qui me reste, c’est à quel point c’était tard. Le mauvais nom a survécu à la lecture, au raisonnement, à la rédaction, et à la revue que l’agent a faite de son propre plan. Rien n’a bronché, parce que rien n’était incohérent. Son raisonnement était juste de bout en bout.
Un mot faux ne tombe pas en panne bruyamment. Il se compose en silence jusqu’à ce qu’on ait construit quelque chose de cher par-dessus.
Lequel de vos mots est lequel
Voilà ce que j’en retire. Votre agent n’a pas besoin de plus de votre base de code. Il a besoin de savoir lequel de vos mots est lequel.
Ça paraît mineur à côté du choix du modèle, de l’outillage, ou de l’autonomie que vous lui laissez. Ça ne l’est pas. Le billet précédent se terminait sur une question qu’il refusait délibérément de trancher : de tout ce que vous pourriez charger en permanence dans la fenêtre, quels tokens méritent vraiment leur place ? Voici la réponse, et elle est plus petite que ce que la plupart des gens attendent.
Le réflexe, c’est de combler l’écart en donnant plus à l’agent. Pointez-le sur le code. Laissez-le explorer d’abord. Donnez-lui la doc, le wiki, les ADR. Ce réflexe échoue pour deux raisons, et ce ne sont pas les mêmes.
La première : le code ne peut pas le lui dire. Un vrai dépôt contient plusieurs sens vivants de votre mot, si bien qu’en lire davantage aggrave l’ambiguïté au lieu de la lever.
La seconde : la moitié du temps, vous ne pouvez pas le lui dire non plus, parce que votre équipe n’a jamais tranché le mot.
Je les prends dans l’ordre.
ℹ️ L’indirection ? Le billet 1 vous a donné la divulgation progressive : ne charger un document ou une skill que lorsqu’une étape en a réellement besoin. L’indirection est la primitive en dessous. En informatique, une indirection est une façon de désigner quelque chose par un nom, une référence ou un conteneur plutôt que par la valeur elle-même, et chaque saut par un tel nom est un niveau d’indirection. Le DNS en est l’image.
en.wikipedia.orgtient lieu d’une adresse réseau comme208.80.154.224, si bien que la référence reste courte, mémorisable, et survit au déplacement de la chose. Retenez cette dernière propriété. Elle revient.
Le code n’est pas un glossaire
« Laisse-le juste lire le code d’abord » suppose que le code est un glossaire. Il ne l’est pas. C’est un endroit où les mots vivent, et ils y vivent dans plus d’un sens à la fois.
Ce dépôt workspace avait intégré git. Git a un workspace. L’arbre contenait donc un sens du mot réel, actif, abondamment référencé, qui n’avait rien à voir avec l’objet du domaine du même nom. Un agent qui greppe workspace trouve les deux, et les deux sont légitimes. En lire plus ne tranche pas. En lire plus ajoute des candidats.
Les voisins arrivent de trois directions, et une seule est la vôtre :
- Vos dépendances. Le workspace de git, la session de votre framework, l’entity de votre ORM.
- Le vocabulaire de votre propre outillage. Les mots que votre système de build et vos scripts revendiquent déjà.
- Le vocabulaire du harnais de l’agent lui-même. C’est là qu’est l’embuscade.
Chez Packmind, les entités métier du produit s’appelaient standard, command et skill. Ce sont aussi des mots qu’un agent emploie pour parler de son propre échafaudage. Alors « mets à jour nos standards » était constamment lu comme mets à jour le contexte curé au lieu de mets à jour le code qui gère les standards. Il partait éditer la mauvaise couche du système, purement et simplement.
Celui-là, je l’ai attrapé en quelques secondes, parce qu’un agent qui édite un fichier visiblement faux, ça se voit. Le cas workspace a survécu jusqu’à un plan terminé. Même classe d’erreur, coût radicalement différent, et la seule variable était la vitesse à laquelle l’erreur devenait visible.
Lui donner un lexique a réglé le cas Packmind net. La réaction que j’ai notée à l’époque, c’était « il sait de quoi on parle ».
Mais pas pour la raison que j’ai d’abord supposée. Ce qui corrige, ce n’est pas que l’entrée définit votre mot. C’est qu’elle nomme ceux d’à côté. Dans le dépôt à git intégré, l’entrée qui a fini par régler workspace posait l’objet du domaine à côté des objets git que ce même arbre utilisait, en quelques lignes. L’agent n’a pas reçu une meilleure définition. Il a reçu une frontière.
Définissez votre mot et vous avez dit à l’agent ce qu’il est. Nommez les voisins et vous lui avez dit ce qu’il n’est pas. C’est la seconde chose qui lui manquait.
Panier, caddie, corbeille
Maintenant la moitié la moins confortable. La plupart du temps, la confusion de l’agent est héritée. Elle a commencé chez les humains.
Le signe, ce sont les synonymes. Panier, caddie, corbeille. Ils veulent probablement tous dire la même chose. Vous en êtes sûr ? En lisant cette base de code là, maintenant, pourriez-vous dire si ces trois mots nomment un concept ou deux, et lequel une nouvelle classe devrait employer ?
Si vous ne pouvez pas, l’agent non plus, et il est plus mal loti que vous. La recherche est son outil principal. Il greppe, lit ce qui remonte, greppe encore. La dérive synonymique casse ça en silence. On ne peut pas chercher un mot dont on ignore qu’il est le canonique, et un raté ne produit aucune erreur. Il produit un ensemble de résultats plus petit, et une réponse assurée bâtie dessus.
C’est un dommage mécanique, pas une question de propreté. Ce n’est pas une préférence de style sur le fait de bien nommer les choses. C’est l’instrument principal de l’agent qui renvoie discrètement des résultats partiels.
Ça porte un nom, et c’est plus vieux que tout ça. Eric Evans a nommé la pratique langage omniprésent dans Domain-Driven Design, paru en 2003. Ça fait plus de vingt ans que des gens tiennent le même discours à la même salle : tranchez les mots, puis écrivez le code.
Je le faisais avant que les agents existent, et je le faisais pour les humains. Je le fais davantage aujourd’hui, parce que la facture arrive plus vite. Un ingénieur senior compense en silence un mot flou toute la journée. Un agent, lui, avance. Commencer par ancrer la sémantique n’est pas seulement bon pour les agents.
Ce qui mérite une entrée
Donc vous écrivez un lexique. Et aussitôt le mauvais réflexe se pointe : décrire le code.
Non. Le lexique n’est pas la documentation du code. C’est la surface de conception sur laquelle vous argumentez.
Voici ce qui m’en a convaincu. Un autre projet, un autre workspace mal défini, sauf que celui-là était mal défini pour les humains aussi. Personne dans l’équipe ne donnait deux fois la même réponse. project était déjà écrit noir sur blanc, comme une entrée avec ses relations, et avoir ces quelques lignes sous les yeux a rendu la rédaction des vraies relations entre tout le reste rapide et précise. On a fini par changer la définition de workspace pour qu’elle colle au modèle mental qu’on trimballait sans l’avoir examiné.
On ne fait pas ça à un document qui décrit du code. On le fait à un artefact de conception. Cette seule propriété décide de tout le reste de ce qui a sa place dans le fichier.
C’est purement métier. Le lexique ne sait rien du code ni des techniques. Il ne contient aucune règle. Tout ce qui contient un devrait n’est pas une entrée de lexique, ça appartient à l’artefact qui porte vos décisions d’architecture.
Les interfaces méritent parfois une entrée. Leurs implémentations, jamais. Un Git Provider mérite une ligne, parce que le domaine a exactement une idée de ce qu’est un fournisseur git. Les fournisseurs concrets derrière, non, parce que le domaine ignore leur existence. Toutes les interfaces ne méritent pas de rester dans le lexique, mais quand elles le méritent, leur implémentation ne doit jamais suivre.
Il contient moins d’entrées que le code n’a d’entités. Il n’y a pas de correspondance 1:1 et il ne doit pas y en avoir. Les entités codées en plus existent pour la maintenabilité ou pour la performance. Ce sont de vraies raisons, et ce ne sont pas des faits du domaine.
Les exclusions découlent de là. Pas d’objets-valeurs, pas de types d’identifiants, pas de commandes ni d’événements, pas de types d’infrastructure, pas de sous-types polymorphes. Deux d’entre eux, les objets-valeurs et les événements, sont des catégories d’Evans lui-même. Les objets-valeurs viennent du livre de 2003, les événements de la référence de 2015 qui a suivi. Le reste sort du même test : est-ce que le métier discute un jour de cette chose ? Personne ne discute d’un type d’identifiant.
Et chaque entrée porte un propriétaire. Pas une définition isolée, mais une place dans une hiérarchie. Un LineItem appartient à un Cart, un Cart appartient à un Customer, et Customer est une entité racine. C’est cette colonne qui fait de l’artefact quelque chose sur quoi on peut argumenter. Les relations construisent d’abord le modèle mental humain. Ensuite, quand un agent rédige un plan, elles rendent visible la portée d’une tâche : touchez au Cart et la chaîne d’appartenance vous dit ce qu’il y a d’autre dans le rayon d’impact.
Qui l’écrit ? Nous deux. L’agent rédige la plupart des entrées à partir d’une session de conception. J’en réécris des morceaux à la main quand c’est plus rapide que de le demander, ce qui est souvent le cas. Le travail continu n’est pas la correction, c’est la suppression : les détails d’implémentation qui se sont glissés dedans et qui ne portent aucune valeur métier. C’est LE document que vous voulez garder tranchant.
Ancrer deux fois
Il existe une solution populaire au problème du mauvais nom, que je veux nommer puis écarter. Faire marquer à l’agent ses hypothèses dans le fil. Lui faire baliser ce qu’il a décidé, ce dont il n’est pas sûr, ce qu’il attend de vous, puis lire les balises et y répondre.
J’ai fait tourner ça un moment. Ça traite un problème de séquencement comme un problème d’étiquetage. La question surgit au mauvais moment, et améliorer la notation ne déplace pas le moment.
Ordonnez les phases pour qu’elle ne puisse pas surgir. Ancrer, puis challenger et concevoir, puis mettre à jour le lexique, puis ancrer à nouveau, puis spécifier, puis implémenter.
Six étapes, et celle sur laquelle on m’interroge, c’est la quatrième. Pourquoi ancrer deux fois ?
Parce que la conception et la spécification veulent des contextes différents. Quand je challenge une conception, je veux les concepts du domaine et leurs relations, et presque rien d’autre. Aucun détail d’implémentation. Et cette session explore : elle argumente, elle produit des maquettes, elle descend deux chemins et en abandonne un. Tout ça a de la valeur pendant que ça se produit, et devient radioactif après.
Chaque phase reçoit donc une note de passation neuve. Pas une note qui grossit. La session de spécification hérite des décisions verrouillées et d’aucune trace de la dispute qui les a produites. Amnésie délibérée, exprès, à chaque frontière.
C’est aussi pour ça que le lexique n’est jamais préchargé. La première session le lit, ou en lit la partie qui compte. Ce qui repart vers l’avant, c’est l’extrait, à l’intérieur de la note de passation, jamais le fichier. C’est l’indirection de tout à l’heure qui fait son travail : le lexique est posé à côté du pipeline et on l’atteint par son nom, donc il peut grossir autant qu’il veut sans qu’une seule session paie pour ça.
Depuis que j’ordonne les choses ainsi, ces questions ont cessé de remonter au mauvais moment. La seule chose qui escalade encore, c’est un vrai angle mort dans le plan d’implémentation, où l’agent tombe sur quelque chose qu’il ne peut pas résoudre et s’arrête pour demander. Ça, c’est l’escalade que je veux. C’est la seule qui reste.
Assez petit pour être relu
Le diagnostic du billet 1 était un instrument. Une ligne de statut qui change de couleur à mesure que la fenêtre se remplit, pour qu’on ne puisse pas rater le chiffre même quand on a arrêté de le lire. Ici, il n’y a pas d’instrument. Rien à surveiller.
Ce qu’il y a à la place, c’est une taille. La phase d’ancrage produit une vingtaine de lignes. Parfois plutôt trente. Ça ressemble à ça :
## Grounding (Phase 1)
**Lexical terms used**: Cart, LineItem, Checkout, Order, Customer, SavedBasket
(in code only — not yet in lexicon).
**Vocabulary discrepancies found**:
- **SavedBasket** exists in code (`services/checkout`, `SavedBasketRepository`) but is
missing from `docs/LEXICON.md`. Follow-up: run `/update-lexicon` to add it under the
`checkout` section.
- Support calls this a "trolley"; the code calls it `Cart`; the design docs call it
`Bag`. Resolved → **"Cart"** is canonical going forward. "Basket" is reserved for the
saved-for-later list.
**Locked decisions reused**:
- A Cart belongs to exactly one Customer; guest carts are keyed by session.
`docs/design/checkout.md:41` (locked 2026-03-12).
- Cart totals are recomputed at checkout, never trusted from the client. `checkout.md:58`.
**Subagent findings**:
- Q: Does a Cart persist across sessions for guests? A: **No.** Session-scoped only,
dropped at 30 days. Source: `services/checkout/src/cart_repository.rs:112-130`.
- Q: Is there an existing SavedBasket → Cart transfer path? A: **None.** Net-new work.
Source: `services/checkout/` survey.
Combien de temps ça vous a pris de le vérifier ?
Voilà le mécanisme. Pas une alarme, une granularité. La sortie de chaque phase est assez petite pour que la relecture ait réellement lieu, au lieu d’être une chose que j’ai l’intention de faire puis que je survole parce qu’elle fait quatre cents lignes et que j’ai une réunion.
Beaucoup de petites sorties relisibles battent une seule grosse et tardive. Ce qui referme la boucle de ce billet. Le plan workspace a été attrapé à la revue du plan d’implémentation, le dernier point de contrôle, par un humain qui lisait des pages. Une vingtaine de lignes d’ancrage auraient tué le mauvais nom dans les premières minutes de la première session, et le plan soigneux bâti par-dessus n’aurait jamais été écrit.
La carte, pas le savoir
Donc : de tout ce que vous pourriez charger en permanence, quels tokens méritent leur place ?
Pas le savoir. La carte.
Il y a un fichier que votre agent lit au début de chaque session, quel que soit le nom que lui donne votre fournisseur. La convention inter-outils s’est fixée sur AGENTS.md, porté par l’Agentic AI Foundation sous la Linux Foundation. Ce fichier doit contenir ce que n’importe quel agent, dans n’importe quelle session, brûlerait sinon des tokens à redécouvrir. Ce qu’est ce projet, en une phrase. Avec quoi il est construit. Les commandes pour le compiler et le tester. Et un plan très court disant où vit le lexique, où vivent les documents de conception, où vit le code.
C’est tout le fichier. Les miens ne dépassent jamais cent lignes, et cent, c’est déjà beaucoup. C’est ma règle empirique plutôt qu’une loi, et si vous organisez votre travail autrement, le nombre bouge.
Remarquez ce qui n’y est pas. Le lexique n’y est pas. Le lexique est pointé par lui, et lu quand une phase d’ancrage en a besoin. Tout ce que ce billet a défendu repart vers l’avant sous la forme d’une ligne d’un fichier, et le fichier pointé peut être dix fois plus gros sans que personne paie la différence. Un pointeur coûte une ligne.
Le garde-fou est une vieille phrase, en général attribuée à David Wheeler : tous les problèmes en informatique peuvent être résolus par un niveau d’indirection supplémentaire. L’addendum que tout le monde ajoute est la moitié la plus utile. Sauf le problème du trop grand nombre de niveaux d’indirection. Cent lignes de pointeurs purs sans substance, c’est une carte de carte, et ça ne sert à personne. Gardez la phrase qui dit ce que cette chose est vraiment.
Ce qui laisse la question que je contourne depuis le début. Un lexique est un document, et le code bouge sous les documents. C’est à ça que sert la liste des écarts dans la note d’ancrage. Elle compare les mots du code aux mots du fichier à chaque session, si bien que la dérive apparaît comme une ligne de plus au lieu d’une surprise.
Sources
- Indirection, Wikipedia. Consulté le 28/07/2026. https://en.wikipedia.org/wiki/Indirection
- Evans, E., Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley, 2003.
- AGENTS.md, Agentic AI Foundation (Linux Foundation). Consulté le 28/07/2026. https://agents.md/