Le modèle de faits¶
Toute la valeur d'AIM tient dans un choix : l'extraction produit des objets typés, pas du texte libre.
Un résumé de documentation est agréable à lire et ne change rien à ce que l'agent écrit. Un fait typé, scopé et sourcé change son comportement.
Le test appliqué à chaque fait¶
Le prompt d'extraction impose une question unique :
Si un développeur compétent mais nouveau chez ce client ignorait ce fait, produirait-il un travail différent, ou se ferait-il reprendre en revue ?
Si la réponse est non, le fait n'est pas extrait. Mieux vaut trois faits tranchants que vingt faits tièdes.
Sont explicitement écartés : la connaissance générale (« il faut écrire des tests »), les reformulations du document, tout ce qu'un bon développeur sait déjà.
Les huit types¶
| Type | Question à laquelle il répond |
|---|---|
stack |
Quelles technos, quelles versions, pour quel rôle ? |
convention |
Comment écrit-on du code qui passe la revue ici ? |
architecture |
Pourquoi c'est structuré comme ça ? |
runbook |
Comment on livre, release, rollback, débogue ? |
constraint |
Qu'est-ce qui est interdit (sécurité, conformité, SLA) ? |
pitfall |
Quel piège a déjà coûté cher à quelqu'un ? |
glossary |
Que veut dire ce terme interne ? |
contact |
Qui possède quoi ? |
Ces huit types ne sont pas une taxonomie exhaustive du savoir : ce sont les huit questions qu'un agent se pose avant d'écrire une ligne.
Anatomie d'un fait¶
{
"id": "nordwind:constraint:7f3a91c2",
"type": "constraint",
"statement": "Ne jamais modifier un script de migration Flyway déjà mergé sur main : Flyway valide les checksums et le déploiement échouera en production.",
"detail": "Crée toujours une nouvelle migration `V<n>__<description>.sql` dans `db/migration/`.",
"scope": ["db/migration/**"],
"tags": ["database", "flyway", "migration"],
"confidence": 0.95,
"status": "candidate",
"provenance": [
{
"document_id": "nordwind:file:d68deeeb4b",
"origin": "guide-dev-backend.md",
"quote": "Ne modifie jamais un script de migration déjà mergé sur main"
}
]
}
statement¶
Une phrase, impérative, autonome. Elle sera lue hors de tout contexte : elle doit se suffire à elle-même.
| Bon | « Les migrations passent par Flyway ; ne jamais modifier un script déjà mergé. » |
| Mauvais | « Le document parle de la gestion des migrations. » |
scope¶
Les globs auxquels le fait s'applique — internal/api/**, **/*_test.go. Vide
signifie « partout ».
C'est ce champ qui permet à l'outil MCP conventions
de ne renvoyer que les règles concernant le fichier en cours d'écriture, au lieu de
charger tout le contexte du client.
Une portée universelle est une absence de portée
Un ** explicite est retiré à la compilation. Conservé, il ferait passer la
règle pour spécifique à chaque fichier interrogé et noierait celles qui le sont
réellement.
confidence¶
- 0,9 et plus : le document l'affirme explicitement et sans ambiguïté.
- 0,6 à 0,8 : déduit d'un exemple ou d'un usage observé.
- 0,3 à 0,5 : inférence fragile.
La confiance sert à filtrer et à hiérarchiser, pas à décorer.
provenance¶
Le document et la citation verbatim qui justifie le fait. C'est la propriété la plus importante du modèle : quand l'agent applique une règle que tu juges fausse, tu remontes en un geste à la phrase qui l'a produite — et tu corriges la source, pas le pack.
Un fait sans provenance est invalide par construction.
Priorité : ce qui entre dans le pack¶
La place dans le pack statique est limitée. Le score de sélection donne plus de poids au type qu'à la confiance :
| Type | Poids |
|---|---|
constraint |
1,00 |
convention |
0,95 |
pitfall |
0,90 |
stack |
0,85 |
runbook |
0,70 |
architecture |
0,60 |
glossary |
0,35 |
contact |
0,30 |
Une contrainte de sécurité moyennement certaine mérite mieux sa place qu'une entrée de glossaire parfaitement sûre. S'y ajoute un bonus de corroboration : un fait confirmé par plusieurs sources indépendantes monte.
Cycle de vie¶
stateDiagram-v2
[*] --> candidate: extraction
candidate --> approved: aim review
candidate --> rejected: aim review
candidate --> conflicting: consolidation
conflicting --> approved: arbitrage humain
conflicting --> rejected: arbitrage humain
Tant que aim review n'est pas entré dans les habitudes, les faits candidate
entrent quand même dans le pack — un pack limité aux faits approuvés serait vide au
premier jour. Ce comportement se règle par client
(include_candidates).
Consolidation¶
Une extraction document par document produit inévitablement des redites : le guide d'onboarding et le dépôt affirment la même règle avec des mots différents.
Deux passes s'en occupent :
- Lexicale, automatique après chaque extraction. Rapproche les énoncés dont les vocabulaires se recouvrent largement (indice de Jaccard ≥ 0,62). Attrape les reformulations proches.
- LLM, à la demande via
aim consolidate. Attrape les paraphrases, réécrit l'énoncé fusionné, et signale les contradictions au lieu de trancher.
Une fusion n'efface jamais une provenance : deux sources qui disent la même chose deviennent un fait à deux provenances. La corroboration devient un signal de fiabilité au lieu d'être du doublon.