Heuristiques de dérive
Instrumenter pour diagnostiquer
Aucune amélioration n’est possible sans mesure. Avant d’améliorer un contexte, il faut l’instrumenter : savoir ce que l’agent charge réellement, fichier par fichier, puis mesurer cette couverture au fil des sessions.
Voir ce qui est chargé
Les données chargées dans un contexte restent opaques. Dans le cas de Claude Code, la commande /context répartit le contexte par typologie de donnée (en % de la fenêtre) ; mais elle ne montre pas le contenu chargé.

Commencez par demander « les artefacts de projet (markdown) chargés lors de la session » pour obtenir la liste des fichiers. Ce listing reste inférentiel et s’arrête à la granularité du fichier.

Rendre le contexte adressable
Pour affiner la granularité d’analyse, chaque élément d’un artefact de projet doit être identifiable via un heading markdown unique (le titre de section et son ancre). Exemples :
CLAUDE.md > ## Description du projet: la section de la doctrine décrivant le projet (CLAUDE.md/AGENT.md)..claude/rules/port-adapter.md > ## Pattern Port & Adapter: la règle concernant le pattern port & adapter.UBIQUITOUS_LANGUAGE.md > ## Commande: l’élément de sémantique métier définissant l’entité Commande.adr/0001-choix-framework.md > ## Décision: la décision sur le choix du framework employé dans le projet.
À chaque session, nous mesurons la couverture de ce qui a été chargé à la volée (progressive disclosure).
Deux contraintes de méthode
Nous validons la qualité du contexte sous contrainte forte : un gros modèle masque un contexte médiocre, un petit (moins permissif) le révèle. Un contexte qui tient sur les modèles les moins capables tient partout, notamment pour les sous-agents orchestrés.
- Contrainte : valider systématiquement la qualité du contexte avec un « petit » modèle (tel que Haiku). Les petits modèles sont économes en action, rapides à exécuter, peu coûteux à l’usage et prennent moins d’initiative.
- Contrainte : désactiver le système de mémoire, car cette feature laisse à l’appréciation du LLM le stockage du savoir au fil des sessions. Elle rend l’expérience moins frustrante (évite l’effet amnésique), mais elle introduit un effet de bord réel : cette mémoire se construit à votre insu. Notre objectif est de réduire le modèle à une fonction pure, ce qui exige de maîtriser constamment ce qui entre dans la fenêtre de contexte. Une mémoire construite empiriquement et hors de votre contrôle est une variable qu’il faut limiter.
Quand améliorer votre contexte ?
Une convention, une API ou un nom qui existe déjà ont été inventés
Hypothèse : l’artefact qui le décrit n’a pas été chargé. Action : référencer l’artefact depuis la doctrine ou revoir la chaîne de référence.
Exemple
Peu d’information en retour pour ce prompt, l’agent se contente de retourner le contenu d’un fichier :
> claude -p "C'est quoi la stratégie de test ? Réponse courte. Précise-moi liste des fichiers chargés dans le contexte" --model claude-haiku-4-5
## Stratégie de test
**Vitest + Miniflare** — tests locaux sans déploiement, exécution rapide. Commandes:
- `npm test` — run all suites
- `npm run test:watch` — watch mode
---
## Fichiers chargés dans le contexte
1. `/Users/defsquare/.claude/CLAUDE.md` (référence RTK)
2. `/Users/defsquare/.claude/RTK.md` (CLI proxy token-optimisé)
3. `/Users/defsquare/my-project/CLAUDE.md` (instructions projet)
En ajoutant ceci à la doctrine :
## Topic Map
Each topic has a dedicated doc with the full rules, conventions, and rationale. Skim this table to know where to look.
- Testing : Starting any new feature [testing.md](./docs/testing.md)
Nous obtenons :
> claude -p "C'est quoi la stratégie de test ? Sans prose. Précise-moi liste des fichiers chargés dans le contexte" --model claude-haiku-4-5
## Stratégie de test
**Double-loop TDD outside-in, diamond shape:**
| Aspect | Détail |
|--------|--------|
| **Structure** | Outer loop: acceptance test (rouge) → inner loop: unit tests (rouge/vert) → acceptance vert → refactor |
| **Ratio** | Pure unit: ~25% | Integration/acceptance: ~60% | E2E smoke: ~15% |
| **Outer loop** | Acceptance test en langage domaine, contre `application/` (Hono via Miniflare), D1 réel, EmailSender/PennylaneClient fakes |
| **Inner loop** | Unit test → min code → vert → refactor. Exit seulement si acceptance vert |
| **Diamond** | Inverse de la pyramide classique: intégration au centre (ROI maximal pour back-office) |
| **Règles** | Red → green → refactor. Commencer par acceptance. Jamais mocker le domaine. 1 acceptance = 1 use case (golden path + 1 error path critique). Vert avant refactor. Tests à côté du code |
| **Noms** | Langage domaine (*"Session refuses completion when…"*), pas HTTP status codes |
| **Data** | Builders (`aPlannedSession().withEnrollments(3).build()`), pas fixtures partagées |
---
## Fichiers chargés en contexte
1. `/Users/defsquare/.claude/CLAUDE.md` → Pointe vers RTK.md
2. `/Users/defsquare/.claude/RTK.md` → CLI proxy token-optimisé
3. `/Users/defsquare/my-project/CLAUDE.md` → Projet
4. `/Users/defsquare/my-project/docs/testing.md` → Testing
Une règle pourtant chargée est ignorée
Hypothèse : la règle est bien dans le contexte mais noyée (contexte saturé) ou mal ciblée (déclencheur trop large, elle se charge hors de son périmètre et perd en autorité).
Action : resserrer le when_to_use / le périmètre de la règle pour qu’elle ne se charge que quand c’est pertinent ; alléger le contexte permanent (sortir ce qui n’est pas toujours vrai vers une règle scopée ou un sous-contexte chargé à la volée).
Contradiction sémantique sur le langage métier
Hypothèse : le glossaire du domaine est absent, forçant l’agent à inventer. Action : ajouter une sémantique métier.
Exemple
Sémantique métier déduite du code :
> claude -p "Explique-moi le concept de cohort ? Réponse courte. Précise-moi liste des fichiers chargés dans le contexte" --model claude-haiku-4-5
## Cohort
Une **cohorte** est un groupe d'apprenants qui suit le même programme de formation dans le même laps de temps. C'est un concept clé de la business logic métier : gérer les cohortes signifie regrouper les participants, affecter des formateurs, planifier les sessions, et tracker la progression collective.
---
## Fichiers chargés dans le contexte
1. `/Users/defsquare/.claude/CLAUDE.md` → redirige vers RTK.md
2. `/Users/defsquare/.claude/RTK.md` (instructions globales utilisateur)
3. `/Users/defsquare/my-project/CLAUDE.md` (instructions projet)
En indiquant la sémantique du domaine depuis la doctrine de l’agent :
claude -p "Explique-moi le concept de cohort ? Réponse courte. Précise-moi liste des fichiers chargés dans le contexte" --model claude-haiku-4-5
## Cohort
**Concept** : Le cohort est **le roster (liste d'apprenants) d'une session donnée**. Une session = un cohort. C'est l'ensemble des `Enrollment` (inscriptions) pour cette session, pas un groupement cross-sessions.
---
## Fichiers chargés dans le contexte
1. **CLAUDE.md** (user global) → `/Users/defsquare/.claude/CLAUDE.md` (référence RTK)
2. **RTK.md** (user global) → `/Users/defsquare/.claude/RTK.md`
3. **CLAUDE.md** (projet) → `/Users/defsquare/my-project/CLAUDE.md`
4. **domain.md** (projet) → `/Users/defsquare/my-project/docs/domain.md`
Du code a été dupliqué
Hypothèse : pas de réutilisation de l’existant, l’agent ré-invente un code from scratch. Action : ajouter une cartographie du projet et/ou décrire l’architecture du projet.
Exemple
L’agent va inventer une réponse de zéro :
> claude -p "Comment parser une date depuis un string ? Sans prose. Précise-moi liste des fichiers chargés dans le contexte" --model claude-haiku-4-5
**Date parsing:**
// Native
const date = new Date('2026-06-11');
// Zod (validation)
import { z } from 'zod';
z.coerce.date().parse('2026-06-11');
// Custom format
const [year, month, day] = '2026-06-11'.split('-').map(Number);
const date = new Date(year, month - 1, day);
**Fichiers chargés:**
1. `/Users/defsquare/.claude/CLAUDE.md` (global, référence RTK.md)
2. `/Users/defsquare/.claude/RTK.md` (global)
3. `/Users/defsquare/my-project/CLAUDE.md` (projet)
En complétant la cartographie du projet :
- `domain/utils.ts` : ISO date parsing
Nous obtenons :
> claude -p "Comment parser une date depuis un string ? Sans prose. Précise-moi liste des fichiers chargés dans le contexte" --model claude-haiku-4-5
## Parser une date
import { parseIsoDate } from '@/domain/utils';
const date = parseIsoDate('2026-06-11T10:30:00Z'); // Retourne un Date
---
## Fichiers chargés
1. `/Users/defsquare/.claude/CLAUDE.md` (global user instructions)
2. `/Users/defsquare/.claude/RTK.md` (token-saving CLI proxy)
3. `/Users/defsquare/my-project/CLAUDE.md` (project instructions)
4. `/Users/defsquare/my-project/src/domain/utils.ts` (date parsing utility)
L’agent reproduit un mauvais exemple
Hypothèse : du contenu de qualité insuffisante ou plus à jour est chargé dans le contexte. Action : mettre à jour la référence ou supprimer le contenu.
La même erreur revient souvent
Hypothèse : le correctif n’a pas été capitalisé. Action : demander à l’agent de mettre à jour les artefacts de projet.
L’agent recherche au-delà du projet
Hypothèse : les artefacts sont mal référencés et n’utilisent pas les bons mots-clés pour que l’agent puisse les rechercher. Action : ajouter des mots-clés supplémentaires et revoir la chaîne de référence depuis la doctrine.
L’agent oublie des consignes pendant une session longue
Hypothèse : un contexte trop volumineux disperse l’attention de l’agent. Action : repartir sur une session neuve en demandant un récap de la session précédente si le travail est à poursuivre. Garder le seuil à 70 % d’utilisation de la fenêtre de contexte.
Quand améliorer votre instruction
L’agent en fait trop
Hypothèse : périmètre non borné, pas de definition of done. Action : expliciter in / out scope. Exemple :
"améliore ce module"→ l’agent improvise un refactoring sur ses propres critères."enlève l'imbrication de conditions"→ ciblé sur un problème précis.
L’agent s’arrête trop tôt
Hypothèse : pas de critères d’acceptation, l’agent ne sait pas quand c’est fini. Action : poser des critères explicites (un critère = un test). Exemple :
"teste la fonction"→ test du cas nominal passant."teste la fonction en incluant les cas d'erreur comme un cas vide, format invalide, longueur max"→ explicite et complet.
L’agent invente des instructions
Hypothèse : instruction ambiguë où l’agent compense l’implicite.
Action : exiger la levée d’ambiguïté avant d’agir (Ask a question, mode plan, grillme) → bascule vers l’Exploration.
Exemple : ajouter "<instruction>. Pose des questions avant de coder si ambigu".
Il répond à la lettre mais pas à l’intention
Hypothèse : seul le quoi est donné, pas le pourquoi → raccourcis qui trahissent l’intention. Action : donner l’intention. Exemple :
"rends cette fonction plus rapide"→ optimisation à l’aveugle, sans cap ni périmètre."rends cette fonction plus rapide car c'est un hot path à 10k requêtes par seconde, garde-la lisible"→ contraint l’optimisation avec du contexte.
Quand améliorer vos vérifications
L’agent s’arrête sans preuve de validité
Hypothèse : aucun feedback computationnel, il s’auto-évalue (fiabilité douteuse). Action : fournir une commande de vérification explicite (test, build) qu’il doit exécuter et dont il rapporte la sortie. Un critère = un test (cf. Specification).
L’agent écrit des tests qui passent toujours
Hypothèse : l’agent optimise le signal « vert » plutôt que la correctness (reward hacking du feedback). Action : règles d’écriture de test avec une boucle red-green-refactor sans jamais mocker le domaine.
L’agent boucle sans converger
Hypothèse : feedback trop lent, partiel ou bruité sans signal clair sur ce qui casse. Action : feedback rapide et localisé (tests unitaires ciblés), et limiter le nombre de cycles (ex. 2 rounds puis handoff humain, cf. Stripe).
L’erreur n’apparaît qu’au runtime
Hypothèse : pas d’observabilité, l’agent est aveugle au comportement réel. Action : exposer des sondes (logs, traces, type-check, E2E) pour qu’il obtienne une évaluation proche du réel.
Le retour d’exécution l’envoie dans la mauvaise direction
Hypothèse : message d’erreur / log non « situé » (cryptique) → il infère mal la cause. Action : améliorer les messages d’erreur et logs (contexte, sémantique des données).
Feedback inférentiel complaisant
Hypothèse : un agent construit et s’auto-évalue, impliquant un jugement non déterministe. Action : privilégier le computationnel (test, lint, appel d’API réel) ; si reviewer IA, lui donner une grille de critères explicite et une session dédiée.
En résumé
Chaque heuristique vise le même but : ramener l’agent vers une fonction sans état dont vous maîtrisez les entrées. Une dérive est un signal faible : votre contexte, votre instruction ou vos mécanismes de vérification réclament un ajustement.