Naar inhoud springen
cd /blog

De lus minen: hoe wijzigingen institutioneel geheugen worden

[Architectuur][Workflows]

> Git-commits worden gestructureerde changelog-items en architecturale beslissingsdossiers, die vervolgens terugvloeien naar AI-agents als doorzoekbaar institutioneel geheugen.

Cijfers in deze post weerspiegelen het systeem op het moment van publicatie (februari 2026). Zie onze teampagina voor actuele cijfers.

Elk engineeringteam staat voor dezelfde uitdaging: wijzigingen gebeuren voortdurend, maar de waarom achter die wijzigingen verdwijnt. Zes maanden later vraagt iemand “waarom hebben we DuckDB gekozen voor pipelinestages?” en het antwoord leeft alleen in het hoofd van wie die beslissing nam — als die persoon er nog is.

We hebben een miningworkflow gebouwd die deze lus sluit. Wijzigingen stromen via git-commits, worden verwerkt door onze miningpipeline, worden gestructureerde changelog-items en architecturale beslissingsdossiers, en vloeien vervolgens terug naar onze AI-agents via CLI-queries. Het resultaat: institutioneel geheugen dat zowel mensen als AI kunnen raadplegen.

Het probleem: beslissingen verdampen

Bekijk een typisch scenario. Een developer commit:

feat(canonical): add DuckDB runtime for pipeline stages

Deze commit vertegenwoordigt een significante architecturale keuze. Het team evalueerde opties, woog trade-offs af en koos voor specifieke redenen voor DuckDB. Maar al die context leeft in:

  • Een Slack-thread (waarschijnlijk verwijderd)
  • Iemands geheugen (zeker vervagend)
  • Een comment in de code (misschien, als je geluk hebt)

Drie maanden later vraagt een nieuw teamlid: “Moet ik DuckDB of SQLite gebruiken voor deze nieuwe stage?” Zonder institutioneel geheugen vinden ze het wiel opnieuw uit of maken ze inconsistente keuzes.

De lus: van commits naar context

Onze miningworkflow transformeert git-geschiedenis naar doorzoekbare kennis:

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)     │
      └───────────────┘

Het belangrijkste inzicht: zowel changelogs als architecturale beslissingen stromen uit dezelfde git-geschiedenis, verwerkt via één uniforme pipeline. Dat zorgt ervoor dat niets tussen wal en schip valt.

Hoe mining werkt

Stap 1: de index synchroniseren

uv run orkestra mine sync

Dit commando scant de git-geschiedenis en bouwt een index van alle commits. Het extraheert gestructureerde signalen uit elke commit:

  • Conventional-commit-type (feat, fix, chore, docs)
  • Scope (welk package of gebied)
  • Breaking-change-markers
  • Aangeraakte bestanden en complexiteitsmetrieken

Stap 2: dekkingsstatus controleren

uv run orkestra mine status

Dit is hoe onze huidige status eruitziet:

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 verwerkt. 476 werden architecturale beslissingen. 6.799 werden changelog-items. Elke commit geclassificeerd.

Stap 3: kandidaten voor review ophalen

uv run orkestra mine candidates --limit 50 --full

Dit brengt commits naar boven die nog niet zijn verwerkt, met volledige context voor classificatie:

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}
}

De signalen helpen bij de classificatie: is_releasable_type: true suggereert dat dit in de changelog moet verschijnen. Het grote aantal insertions en de infrastructuurbestanden suggereren dat het ook een architecturale beslissing kan zijn.

Stap 4: commits classificeren

Hier splitsen twee paden zich: changelog-items en architecturale beslissingen.

Voor changelog-items:

uv run orkestra mine classify abc123 --changelog added

Dit legt vast dat commit abc123 in de changelog moet verschijnen onder de categorie “Added”.

Voor architecturale beslissingen:

Vraag eerst een echte decision-ID op:

uv run orkestra decisions new --domain pipeline --dry-run
# Returns: DEC-PL-143

Classificeer vervolgens met de decision-ID:

uv run orkestra mine classify abc123 --decision DEC-PL-143

Dit koppelt de commit aan een beslissingsdossier dat wordt aangemaakt of bijgewerkt.

Voor batchverwerking (wat we in de praktijk doen):

# Generate classifications file with LLM assistance
uv run orkestra mine commit --input classifications.jsonl

Het JSONL-formaat ondersteunt beide domeinen in één doorgang:

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"}

Stap 5: outputs renderen

uv run orkestra changelog render --package <pkg>

Dit genereert per-package CHANGELOG.md-bestanden vanuit het ledger. De changelogs zijn afgeleide artefacten — verwijder ze en ze worden perfect opnieuw gegenereerd vanuit het bron-ledger.

De structuur van het beslissingsdossier

Geëxtraheerde beslissingen worden YAML-bestanden met rijke metadata:

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

Elke beslissing verwijst terug naar zijn bron-commits. Elke beslissing specificeert welke bestanden hij raakt. Relaties tussen beslissingen zijn expliciet.

CLI-integratie: institutioneel geheugen bevragen

Hier sluit de lus zich. Agents kunnen beslissingen bevragen via de CLI:

# Search by topic
uv run orkestra decisions search --query "retry"

Geeft beslissingen over retrylogica, foutafhandeling, herstelpatronen.

# Get full details on a specific decision
uv run orkestra decisions info DEC-PL-142

Geeft het complete beslissingsdossier met context, onderbouwing en impact.

# List recent decisions for context
uv run orkestra decisions list --limit 15

Toont welke architecturale keuzes recent zijn gemaakt.

Hoe agents dit gebruiken

De baseline-instructies van onze orchestrator omvatten:

**Essential CLI commands:**
- `orkestra decisions search "X"` — Find architectural decisions

Wanneer een agent wordt gevraagd iets te implementeren dat met DuckDB te maken heeft, kan hij eerst controleren:

uv run orkestra decisions search --query "DuckDB"

En DEC-PL-142 ontdekken, waarbij hij leert:

  • Waarom we voor DuckDB kozen (context)
  • Hoe je het correct gebruikt (agent_guidance)
  • Welke bestanden je moet bekijken (files)
  • Welke gerelateerde beslissingen bestaan (related)

De agent vindt het wiel niet opnieuw uit. Hij bouwt voort op gevestigde patronen.

De Drie-Vragen-Test

Niet elke commit verdient een beslissingsdossier. We gebruiken de Drie-Vragen-Test om te filteren:

  1. Was dit moeilijk om te nemen? Vereiste het significante analyse, afweging van trade-offs, of discussie?
  2. Is het kostbaar om te wijzigen? Zou het terugdraaien van deze beslissing significant herwerk vereisen?
  3. Heeft het systeembrede impact? Raakt het meerdere packages of vestigt het patronen die anderen zullen volgen?

Als een commit “ja” antwoordt op minstens één van deze vragen, is hij een kandidaat voor beslissingsextractie. Ons typische percentage: 1-4 beslissingen per 100 commits (ongeveer 1-4%).

Voor changelog-items ligt de lat lager: elke gebruikersgerichte wijziging (features, fixes, verbeteringen) wordt vastgelegd. Interne chores, documentatie-updates en refactors worden doorgaans overgeslagen. Ons typische percentage: 30-50 changelog-items per 100 commits.

Dataopslag: append-only ledgers

Het miningsysteem gebruikt append-only JSONL-ledgers voor conflictvrije multi-agent-werking:

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
    └── ...

Het JSONL-formaat met merge=union in .gitattributes betekent dat meerdere agents tegelijk commits kunnen classificeren zonder merge-conflicten. Elke regel is onafhankelijk.

Validatiegates

Voor elke miningsessie draaien we validatie:

uv run orkestra mine validate --quick

Dit controleert:

  • Geldigheid van het SHA-formaat
  • Naleving van het decision-ID-formaat
  • Geen dubbele items voor dezelfde SHA
  • Dat gerefereerde beslissingen daadwerkelijk bestaan

Na classificatie valideren we opnieuw voordat we wijzigingen committen.

Waarom dit ertoe doet

De feedbacklus die we hebben gebouwd, lost verschillende problemen op:

Voor nieuwe teamleden: In plaats van te vragen “waarom hebben we X gedaan?” kunnen ze het beslissingsregister doorzoeken. De context blijft bewaard.

Voor AI-agents: Ze opereren niet in een vacuüm. Ze kunnen institutionele kennis bevragen voordat ze aanbevelingen doen. Wanneer ze wordt gevraagd een nieuwe pipelinestage toe te voegen, kunnen ze het DuckDB-patroon ontdekken en volgen.

Voor architecturale consistentie: Beslissingen zijn expliciet en doorzoekbaar. Wanneer iemand een aanpak voorstelt die in strijd is met een bestaande beslissing, kan het systeem het conflict naar boven halen.

Voor changeloggeneratie: Release notes zijn geen last-minute gehaast geregel. Ze zijn een bijproduct van continue classificatie tijdens de ontwikkeling.

Voor onboarding: Nieuwe agents erven de volledige context van de codebase. Ze zien niet alleen de code — ze zien ook de beslissingen die haar vormgaven.

Huidige status

Op dit moment:

  • 15.637 commits verwerkt door de pipeline
  • 476 architecturale beslissingen geëxtraheerd en gedocumenteerd
  • 6.799 changelog-items vastgelegd
  • 100% dekking over beide domeinen

Elke commit sinds we begonnen is geclassificeerd. Het institutionele geheugen is compleet en doorzoekbaar.

Aan de slag

Als je iets vergelijkbaars wilt implementeren:

  1. Begin met conventional commits. De miningpipeline werkt het best wanneer commits gestructureerde prefixes hebben (feat:, fix:, chore:).

  2. Definieer je domeinen. Wij gebruiken domeinen zoals pipeline, agent-design, observability, data-modeling. Die organiseren beslissingen per gebied.

  3. Bouw de classificatiegewoonte op. Mining werkt wanneer teams regelmatig commits classificeren. Batchverwerking met LLM-ondersteuning helpt bij het opschalen.

  4. Maak beslissingen bevraagbaar. De waarde stapelt zich op wanneer agents beslissingen kunnen doorzoeken via de CLI. Structureer je output voor machineconsumptie.

  5. Sluit de lus. Beslissingen moeten toekomstig werk beïnvloeden. Neem decision-referenties op in agentinstructies en code-reviewchecklists.

Het doel is geen perfecte documentatie. Het doel is de waarom achter wijzigingen toegankelijk maken voor zowel mensen als AI, vandaag en over zes maanden. Wanneer wijzigingen institutioneel geheugen worden, bouwen teams voort op gevestigde patronen in plaats van ze opnieuw uit te vinden.


De miningworkflow maakt deel uit van onze orchestration engine, specifiek de context engine-module in ons orchestration-package.

Gerelateerde artikelen

Meer uit het bouwlogboek van Maguyva