Les fichiers d’instructions destinés aux agents de programmation fondés sur l’intelligence artificielle doivent être révisés régulièrement, et non s’allonger sans fin. Chaque fois que le modèle commet une erreur, une nouvelle règle est ajoutée ; chaque fois qu’un outil change, une nouvelle méthode de contournement est ajoutée, tandis que les anciennes consignes restent en place après l’apparition de modèles plus récents. Le résultat peut être un fichier qui combine un guide de configuration pour les développeurs, un guide de style, un journal de dépannage et un ensemble d’anciennes techniques de formulation des invites.
Selon l’article, cette accumulation peut rendre l’agent de programmation moins efficace. Les modèles modernes sont davantage capables d’explorer les dépôts, de reconnaître les frameworks courants, de suivre les modèles existants et de gérer les erreurs habituelles. En revanche, ils ne connaissent pas les décisions propres à l’équipe, les contraintes cachées ou l’expérience opérationnelle accumulée en son sein. L’objectif n’est donc pas de rendre le fichier d’instructions aussi court que possible, mais de conserver le plus petit ensemble d’informations à forte valeur informative qui modifient réellement le résultat.
Considérer le contexte comme une ressource limitée
Le fichier d’instructions est ajouté au contexte disponible pour le modèle à chaque requête à laquelle il s’applique, et ses lignes se disputent l’attention du modèle avec la tâche du développeur, le code pertinent, les sorties des outils, l’historique de la conversation et les autres instructions. L’augmentation de la fenêtre de contexte ne signifie pas que chaque symbole supplémentaire est dépourvu de coût.
La question pratique n’est pas : que peut-on dire au modèle à propos du dépôt ? Mais plutôt : que doit savoir le modèle et qu’il ne peut pas découvrir, déduire ou récupérer de manière fiable ? L’article recommande de se concentrer sur les informations spécifiques, déterminantes et difficiles à déduire.
Que faut-il conserver dans le fichier ?
Les informations les plus précieuses comprennent les faits non évidents concernant le système, comme les limites de propriété entre les composants du dépôt, le fait qu’un ancien répertoire soit encore utilisé en production ou que certains fichiers soient générés et ne doivent pas être modifiés manuellement. Il est utile de préciser qu’une interface donnée possède le contrat HTTP public, ou que les règles métier appartiennent à une couche précise, plutôt que de laisser le modèle déduire ces limites à partir des noms de répertoires.
Il convient également de documenter le chemin fiable le plus court pour la compilation et la validation, en se limitant aux commandes qui ont été testées. Parmi les exemples cités dans l’article figurent l’exécution de dotnet restore App.slnx avant la première compilation, puis l’utilisation de dotnet build App.slnx --no-restore, l’exécution de tests ciblés lors de la modification d’interfaces de programmation ou de l’outil de validation des fichiers générés après la modification des contrats. Les exigences particulières doivent être précisées, par exemple le fait que les tests d’intégration nécessitent Docker et ne doivent pas être exécutés en parallèle, car une commande incorrecte répétée avec assurance est pire que l’absence de commande.
Il est également utile d’enregistrer les choix locaux que le code ne peut pas déterminer de manière constante : le framework de test adopté, la préférence pour les Minimal APIs plutôt que les contrôleurs, le modèle Result<T> pour gérer les erreurs métier attendues ou l’utilisation de TimeProvider plutôt que l’appel direct à l’horloge système. Il ne s’agit pas de règles générales de programmation, mais de décisions propres à la base de code ; elles sont donc adaptées au fichier d’instructions.
Quant aux contraintes strictes, il faut réserver des mots comme « toujours », « jamais » et « doit » aux règles réellement absolues, telles que la préservation du contrat JSON public, l’interdiction de placer des données client dans les journaux, la compatibilité des migrations de base de données avec la version précédente ou l’interdiction de modifier les fichiers de l’environnement de production sans tâche de déploiement explicite. Il est également possible de renvoyer vers les sources de vérité plutôt que d’en copier le contenu, comme les fichiers de directives de conception des interfaces, les fichiers de définition des versions de l’environnement d’exécution, la documentation du déploiement et les décisions d’architecture.
Que peut-on supprimer ou déplacer ?
L’article conseille de supprimer les conseils généraux tels que l’écriture d’un code propre, le respect des bonnes pratiques, l’utilisation de noms explicites et la gestion appropriée des erreurs. Ces formulations ne tranchent pas une décision pratique, tandis qu’une règle locale précise est plus utile, par exemple associer les erreurs de validation à une réponse 400, les ressources inexistantes à une réponse 404 et les conflits de concurrence à une réponse 409 au moyen des outils ProblemDetails existants.
Les fichiers n’ont généralement pas besoin d’un inventaire exhaustif des répertoires, car le modèle peut lire rapidement la structure du dépôt. Il n’est pas non plus nécessaire de répéter les règles de formatage imposées par les outils ; il suffit d’indiquer la commande de vérification appropriée, comme dotnet format --verify-no-changes. Il faut éviter de copier intégralement le README, les guides d’architecture et les guides de contribution, afin de ne pas augmenter le coût de maintenance ou de faire apparaître des contradictions entre les documents.
L’article met également en garde contre les « mythes des invites » anciens, comme demander au modèle de prendre une grande inspiration, de se comporter comme un ingénieur senior ou de lire chaque fichier avant d’effectuer le moindre changement. Ces formulations n’ajoutent aucune connaissance du projet et peuvent entraîner une exploration inutile. Il vaut mieux décrire le résultat, les contraintes et la validation requise : effectuer le plus petit changement qui traite la cause racine, préserver le comportement public et exécuter les tests ciblés.
Les solutions temporaires doivent être supprimées après la résolution du problème qui les avait motivées. Sinon, l’agent continuera d’éviter un chemin qui n’est plus défaillant. Les instructions doivent également être rédigées pour une catégorie de modèles plutôt que pour une version précise ; les instructions qui se ramifient en fonction de chaque modèle deviennent fragiles à mesure que les modèles et leur comportement évoluent.
Choisir la portée des instructions et les réviser
Toute directive n’est pas adaptée au fichier général du dépôt. GitHub Copilot prend en charge des instructions générales dans .github/copilot-instructions.md, des fichiers propres aux chemins sous .github/instructions/ et des instructions pour les agents telles que AGENTS.md. Le fichier d’instructions général est utilisé avec le fichier propre au chemin correspondant lorsque les deux existent.
La structure du système, les commandes communes et les contraintes générales doivent être placées dans la portée générale, tandis que les règles des frameworks, les modèles de test et les fichiers générés propres à une partie donnée doivent être déplacés dans un fichier associé au chemin. Les explications détaillées, l’historique des décisions et les procédures rares doivent plutôt rester dans des documents liés. Ainsi, une règle concernant les tests de composants React ne consomme pas l’attention du modèle pendant une tâche de migration de base de données.
L’article propose d’examiner chaque directive selon quatre résultats : conserver si elle est correcte, déterminante et difficile à déduire ; supprimer si le modèle la connaît, si un outil l’impose, si elle est devenue ambiguë ou obsolète ; déplacer si elle est utile mais concerne un autre chemin ou document ; et vérifier si elle porte sur une commande, une solution temporaire ou une version susceptible d’avoir changé.
Les moments propices à une révision comprennent l’adoption d’un modèle plus performant, la modification du système de compilation, la réorganisation du dépôt ou l’observation que les agents ignorent les instructions ou les appliquent incorrectement. Il faut ensuite tester le fichier le plus court sur une tâche précise, relever les échecs réels, puis ajouter le minimum d’instructions permettant d’empêcher leur répétition et refaire le test sur une autre tâche.
Une partie de la maintenance du projet
L’article préconise de réviser les modifications des fichiers d’instructions dans les demandes de fusion habituelles, de demander aux évaluateurs si la règle est réutilisable ou si elle ne traite qu’une seule tâche, et de désigner un responsable pour les commandes opérationnelles et les exigences de l’environnement. Les solutions temporaires doivent également être supprimées dans la même demande de fusion que celle qui traite la cause du problème, et les commandes doivent être réexaminées après les mises à jour des paquets du SDK, des frameworks, des outils de test ou du processus de compilation.
La qualité du fichier ne doit pas être évaluée en fonction du nombre de ses lignes. Un fichier de 30 lignes contenant des instructions erronées peut être pire qu’un fichier de 100 lignes décrivant les limites d’un dépôt multiprojet et des informations que le modèle ne peut pas déduire. Le meilleur critère est que le fichier permette à un modèle capable de commencer rapidement le travail, en lui fournissant ce que seule l’équipe sait : la nature du système, les limites importantes, les choix locaux, la manière de construire et de vérifier, ce qui ne doit pas être cassé, et l’endroit où trouver les détails plus approfondis.