Miner la boucle : comment les changements deviennent mémoire institutionnelle
> Les commits Git deviennent des entrées de changelog structurées et des fiches de décision architecturale, puis reviennent nourrir les agents IA sous forme de mémoire institutionnelle interrogeable.
Les chiffres de cet article reflètent le système au moment de la publication (février 2026). Consultez notre page équipe pour les chiffres actuels.
Chaque équipe d’ingénierie fait face au même défi : les changements se produisent en continu, mais le pourquoi derrière ces changements disparaît. Six mois plus tard, quelqu’un demande « pourquoi avons-nous adopté DuckDB pour les étapes du pipeline ? », et la réponse ne vit que dans la tête de la personne qui a pris cette décision — si elle est encore là.
Nous avons construit un flux de travail de minage qui referme cette boucle. Les changements transitent par les commits Git, sont traités par notre pipeline de minage, deviennent des entrées de changelog structurées et des fiches de décision architecturale, puis reviennent nourrir nos agents IA via des requêtes en ligne de commande. Le résultat : une mémoire institutionnelle accessible aussi bien aux humains qu’à l’IA.
Le problème : les décisions s’évaporent
Considérez un scénario typique. Un développeur commite :
feat(canonical): add DuckDB runtime for pipeline stages
Ce commit représente un choix architectural significatif. L’équipe a évalué des options, pesé des compromis, et opté pour DuckDB pour des raisons précises. Mais tout ce contexte vit dans :
- Un fil Slack (probablement supprimé)
- La mémoire de quelqu’un (qui s’estompe assurément)
- Un commentaire dans le code (peut-être, si vous avez de la chance)
Trois mois plus tard, un nouveau membre de l’équipe demande : « Dois-je utiliser DuckDB ou SQLite pour cette nouvelle étape ? » Sans mémoire institutionnelle, il réinvente la roue ou fait des choix incohérents.
La boucle : des commits au contexte
Notre flux de travail de minage transforme l’historique Git en savoir interrogeable :
Git Commits
│
▼
┌─────────────────────┐
│ mine sync │ ← Build index from git history
└─────────────────────┘
│
▼
┌─────────────────────┐
│ mine candidates │ ← Surface commits for review
└─────────────────────┘
│
▼
┌─────────────────────┐
│ Classification │ ← Human or LLM assessment
│ (changelog or ADR) │
└─────────────────────┘
│
├──────────────────────┐
▼ ▼
┌─────────────┐ ┌───────────────┐
│ Changelog │ │ Decisions │
│ Ledger │ │ Registry │
│ (JSONL) │ │ (YAML files) │
└─────────────┘ └───────────────┘
│ │
▼ ▼
┌─────────────┐ ┌───────────────┐
│ CHANGELOG.md│ │ orkestra CLI │
│ per package │ │ queries │
└─────────────┘ └───────────────┘
│ │
└──────────────────────┘
│
▼
┌───────────────┐
│ AI Agents │
│ (via CLI) │
└───────────────┘
L’idée clé : les entrées de changelog et les décisions architecturales découlent toutes deux du même historique Git, traité par un pipeline unifié. Cela garantit que rien ne passe entre les mailles du filet.
Comment fonctionne le minage
Étape 1 : synchroniser l’index
uv run orkestra mine sync
Cette commande scanne l’historique Git et construit un index de tous les commits. Elle extrait de chaque commit des signaux structurés :
- Type de commit conventionnel (
feat,fix,chore,docs) - Portée (quel package ou quelle zone)
- Marqueurs de changement cassant
- Fichiers touchés et métriques de complexité
Étape 2 : vérifier le statut de couverture
uv run orkestra mine status
Voici à quoi ressemble notre statut actuel :
Mining Status
=============
Decisions
---------
Coverage: 100.0%
Processed: 15637 (of 15637)
Extracted: 476
Skipped: 15161
Changelog
---------
Coverage: 100.0%
Processed: 15637 (of 15637)
Released: 6799
Skipped: 8838
15 637 commits traités. 476 sont devenus des décisions architecturales. 6 799 sont devenus des entrées de changelog. Chaque commit est classé.
Étape 3 : obtenir des candidats à relire
uv run orkestra mine candidates --limit 50 --full
Cela fait remonter les commits pas encore traités, avec le contexte complet pour la classification :
on
{
"sha": "90571786d99166c0039ca2e80e4d9cd96184bd85",
"date": "2026-01-26",
"subject": "feat(canonical): add DuckDB runtime for pipeline stages",
"signals": {
"commit_type": "feat",
"scope": "canonical",
"breaking": false,
"is_releasable_type": true,
"domains_affected": ["pipeline", "data-architecture"]
},
"body": "Establishes DuckDB as canonical in-process analytical database...",
"files_changed": ["packages/canonical/pipelines/stages/duckdb_runtime.py", "..."],
"stats": {"files": 8, "insertions": 450, "deletions": 120}
}
Les signaux aident à guider la classification : is_releasable_type: true suggère que ceci devrait apparaître dans le changelog. Le grand nombre d’insertions et les fichiers d’infrastructure suggèrent que cela pourrait aussi être une décision architecturale.
Étape 4 : classer les commits
Deux chemins divergent ici : les entrées de changelog et les décisions architecturales.
Pour les entrées de changelog :
uv run orkestra mine classify abc123 --changelog added
Cela enregistre que le commit abc123 doit apparaître dans le changelog sous la catégorie « Ajouté ».
Pour les décisions architecturales :
D’abord, obtenez un véritable identifiant de décision :
uv run orkestra decisions new --domain pipeline --dry-run
# Returns: DEC-PL-143
Puis classez avec cet identifiant de décision :
uv run orkestra mine classify abc123 --decision DEC-PL-143
Cela relie le commit à une fiche de décision qui sera créée ou mise à jour.
Pour le traitement par lots (ce que nous faisons réellement) :
# Generate classifications file with LLM assistance
uv run orkestra mine commit --input classifications.jsonl
Le format JSONL prend en charge les deux domaines en un seul passage :
on
l
{"sha":"abc123","domain":"changelog","action":"release","category":"added","summary":"Add DuckDB runtime for pipeline stages"}
{"sha":"abc123","domain":"decisions","action":"extract","decision_id":"DEC-PL-142"}
{"sha":"def456","domain":"changelog","action":"skip","reason":"Chore: dependency update"}
Étape 5 : générer les sorties
uv run orkestra changelog render --package <pkg>
Cela génère, à partir du registre, des fichiers CHANGELOG.md par package. Les changelogs sont des artefacts dérivés — supprimez-les, et ils se régénèrent parfaitement à partir du registre source.
La structure d’une fiche de décision
Les décisions extraites deviennent des fichiers YAML dotés de métadonnées riches :
id: DEC-PL-142
title: Adopt DuckDB as Canonical Processing Runtime for Pipeline Stages
domain: pipeline
status: active
created: '2026-01-26'
summary: |
Establishes DuckDB as the canonical in-process analytical database for pipeline
stage transformations. Provides a shared runtime module that resolves settings
from pipeline defaults with stage-level overrides.
context: |
Pipeline stages performing data transformations each independently configured
DuckDB connections. This led to inconsistent settings, duplicated configuration
code, and no way to tune DuckDB globally for a pipeline run.
rationale:
- DuckDB provides efficient in-process OLAP with zero configuration deployment
- Centralized runtime module eliminates duplicated DuckDB setup across stages
- Hierarchical settings enable global tuning with stage-level overrides
- Memory limits and thread counts can be adjusted per-pipeline
impact:
positive:
- Consistent DuckDB configuration across all pipeline stages
- Single point of control for memory/thread tuning
- Reduced code duplication in conversion and export stages
negative:
- Adds dependency on shared runtime module
- Stages must adopt new configuration pattern
source_commits:
- sha: 90571786d99166c0039ca2e80e4d9cd96184bd85
message: 'feat(canonical): add DuckDB runtime for pipeline stages'
date: '2026-01-26'
role: primary
files:
- packages/canonical/pipelines/stages/duckdb_runtime.py
- packages/canonical/pipelines/runner.py
- packages/canonical/pipelines/stages/convert_hdx_admin_boundaries_to_geoparquet.py
related:
- DEC-DA-014 # Data architecture decisions that influenced this
Chaque décision renvoie à ses commits sources. Chaque décision précise quels fichiers elle affecte. Les relations entre décisions sont explicites.
Intégration CLI : interroger la mémoire institutionnelle
C’est ici que la boucle se referme. Les agents peuvent interroger les décisions via la CLI :
# Search by topic
uv run orkestra decisions search --query "retry"
Renvoie les décisions liées à la logique de nouvelle tentative, à la gestion des erreurs, aux schémas de récupération.
# Get full details on a specific decision
uv run orkestra decisions info DEC-PL-142
Renvoie la fiche de décision complète, avec contexte, justification et impact.
# List recent decisions for context
uv run orkestra decisions list --limit 15
Montre quels choix architecturaux ont été faits récemment.
Comment les agents utilisent cela
Les instructions de base de notre orchestrateur incluent :
**Essential CLI commands:**
- `orkestra decisions search "X"` — Find architectural decisions
Quand un agent reçoit la demande d’implémenter quelque chose lié à DuckDB, il peut d’abord vérifier :
uv run orkestra decisions search --query "DuckDB"
Et découvrir DEC-PL-142, apprenant ainsi :
- Pourquoi nous avons choisi DuckDB (context)
- Comment l’utiliser correctement (agent_guidance)
- Quels fichiers consulter (files)
- Quelles décisions connexes existent (related)
L’agent ne réinvente pas la roue. Il s’appuie sur des schémas déjà établis.
Le test des trois questions
Tout commit ne mérite pas une fiche de décision. Nous utilisons le test des trois questions pour filtrer :
- Était-ce difficile à décider ? Cela a-t-il exigé une analyse significative, une évaluation de compromis, ou un débat ?
- Est-ce coûteux à changer ? Revenir sur cette décision exigerait-il un travail de refonte important ?
- A-t-elle un impact à l’échelle du système ? Affecte-t-elle plusieurs packages, ou établit-elle des schémas que d’autres suivront ?
Si un commit répond « oui » à au moins une de ces questions, il est candidat à l’extraction en décision. Notre taux habituel : 1 à 4 décisions pour 100 commits (environ 1 à 4 %).
Pour les entrées de changelog, la barre est plus basse : tout changement visible par l’utilisateur (fonctionnalités, corrections, améliorations) est enregistré. Les tâches internes, les mises à jour de documentation et les refactorisations sont généralement écartées. Notre taux habituel : 30 à 50 entrées de changelog pour 100 commits.
Stockage des données : registres en ajout seul
Le système de minage utilise des registres JSONL en ajout seul, pour un fonctionnement multi-agents sans conflit :
packages/orchestration/ai_assets/reference/changelog/
├── commits_processed.jsonl # Classification ledger (both domains)
├── release_notes.jsonl # Changelog entries
└── commits_index.yaml # Derived index (gitignored)
packages/orchestration/ai_assets/reference/decisions/
├── registry.yaml # Decision index
└── records/
├── DEC-AD-001.yaml
├── DEC-AD-002.yaml
└── ...
Le format JSONL, avec merge=union dans .gitattributes, signifie que plusieurs agents peuvent classer des commits simultanément sans conflit de fusion. Chaque ligne est indépendante.
Portes de validation
Avant toute session de minage, nous exécutons une validation :
uv run orkestra mine validate --quick
Cela vérifie :
- La validité du format SHA
- La conformité du format d’identifiant de décision
- L’absence d’entrées en double pour un même SHA
- L’existence réelle des décisions référencées
Après la classification, nous validons à nouveau avant de commiter les changements.
Pourquoi cela compte
La boucle de rétroaction que nous avons construite résout plusieurs problèmes :
Pour les nouveaux membres de l’équipe : au lieu de demander « pourquoi avons-nous fait X ? », ils peuvent chercher dans le registre des décisions. Le contexte est préservé.
Pour les agents IA : ils n’opèrent pas dans le vide. Ils peuvent interroger le savoir institutionnel avant de formuler des recommandations. Quand on leur demande d’ajouter une nouvelle étape de pipeline, ils peuvent découvrir le schéma DuckDB et le suivre.
Pour la cohérence architecturale : les décisions sont explicites et interrogeables. Quand quelqu’un propose une approche qui contredit une décision existante, le système peut faire remonter le conflit.
Pour la génération du changelog : les notes de version ne sont pas une course de dernière minute. Elles sont un sous-produit de la classification continue pendant le développement.
Pour l’intégration : les nouveaux agents héritent du contexte complet de la base de code. Ils ne voient pas seulement le code — ils voient les décisions qui l’ont façonné.
État actuel
À ce jour :
- 15 637 commits traités par le pipeline
- 476 décisions architecturales extraites et documentées
- 6 799 entrées de changelog enregistrées
- 100 % de couverture sur les deux domaines
Chaque commit depuis nos débuts a été classé. La mémoire institutionnelle est complète et interrogeable.
Pour commencer
Si vous voulez implémenter quelque chose de similaire :
-
Commencez par des commits conventionnels. Le pipeline de minage fonctionne mieux quand les commits ont des préfixes structurés (
feat:,fix:,chore:). -
Définissez vos domaines. Nous utilisons des domaines comme
pipeline,agent-design,observability,data-modeling. Ils organisent les décisions par zone. -
Construisez l’habitude de classification. Le minage fonctionne quand les équipes classent régulièrement les commits. Le traitement par lots assisté par LLM aide à passer à l’échelle.
-
Rendez les décisions interrogeables. La valeur se compose quand les agents peuvent chercher les décisions via la CLI. Structurez votre sortie pour une consommation par machine.
-
Refermez la boucle. Les décisions doivent influencer le travail futur. Incluez des références aux décisions dans les instructions des agents et les listes de vérification de revue de code.
L’objectif n’est pas une documentation parfaite. C’est de rendre le pourquoi derrière les changements accessible, à la fois aux humains et à l’IA, aujourd’hui comme dans six mois. Quand les changements deviennent mémoire institutionnelle, les équipes construisent sur des schémas établis plutôt que de les réinventer.
Le flux de travail de minage fait partie de notre moteur d’orchestration, plus précisément du module de moteur de contexte de notre package d’orchestration.
Lectures associées
Encore plus du journal de bord Maguyva
Pourquoi nous avons fait évoluer la recherche de code vers voyage-4-large_
Nous avons migré nos embeddings de code vers voyage-4-large — actuellement en tête du classement public RTEB pour la récupération de code. La version honnête : le compromis que nous faisons, ce que nous indexons réellement, et pourquoi nous payons pour des embeddings premium.
Auto-amélioration récursive des langages : affiner l'intelligence du code sur environ 280 langages_
Nous prenons en charge l'intelligence du code pour environ 280 langages. Aucun humain ne peut auditer cela à la main. Nous avons donc construit une boucle d'auto-amélioration récursive des langages — contrôle ponctuel, LLM en tant que juge, correction d'un seul élément, revalidation — et nous la faisons tourner avec une flotte d'agents isolés jusqu'à ce que l'extraction soit vraiment correcte, pas seulement au vert.
Recherche par fusion multimodale : choisir le bon moteur de récupération pour chaque requête_
Une requête comme « où est défini parseConfig » appelle une recherche différente de « comment fonctionne l'authentification ». Maguyva classe l'intention, pondère en conséquence quatre modalités de récupération, puis fusionne les résultats avec une Reciprocal Rank Fusion pondérée.