Vai al contenuto
cd /blog

Mining del loop: come le modifiche diventano memoria istituzionale

[Architettura][Workflows]

> I commit git diventano voci di changelog strutturate e record di decisioni architetturali, poi rientrano negli agenti AI come memoria istituzionale interrogabile.

I numeri in questo articolo riflettono il sistema al momento della pubblicazione (febbraio 2026). Consulta la nostra pagina del team per le cifre attuali.

Ogni team di ingegneria affronta la stessa sfida: le modifiche avvengono di continuo, ma il perché dietro quelle modifiche scompare. Sei mesi dopo, qualcuno chiede “perché abbiamo adottato DuckDB per gli stage della pipeline?” e la risposta vive solo nella testa di chi ha preso quella decisione — se è ancora in giro.

Abbiamo costruito un workflow di mining che chiude questo ciclo. Le modifiche fluiscono attraverso i commit git, vengono elaborate dalla nostra pipeline di mining, diventano voci di changelog strutturate e record di decisioni architetturali, e poi rientrano nei nostri agenti AI tramite query da CLI. Il risultato: una memoria istituzionale a cui possono accedere sia gli esseri umani che l’AI.

Il problema: le decisioni evaporano

Considera uno scenario tipico. Uno sviluppatore fa il commit di:

feat(canonical): add DuckDB runtime for pipeline stages

Questo commit rappresenta una scelta architetturale significativa. Il team ha valutato le opzioni, considerato i trade-off, e optato per DuckDB per motivi specifici. Ma tutto quel contesto vive in:

  • Un thread Slack (probabilmente cancellato)
  • La memoria di qualcuno (che sicuramente sbiadisce)
  • Un commento nel codice (forse, se sei fortunato)

Tre mesi dopo, un nuovo membro del team chiede: “Dovrei usare DuckDB o SQLite per questo nuovo stage?” Senza memoria istituzionale, o reinventa la ruota o fa scelte incoerenti.

Il loop: dai commit al contesto

Il nostro workflow di mining trasforma la cronologia git in conoscenza interrogabile:

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’intuizione chiave: sia i changelog che le decisioni architetturali fluiscono dalla stessa cronologia git, elaborata attraverso una pipeline unificata. Questo garantisce che nulla sfugga.

Come funziona il mining

Passo 1: sincronizza l’indice

uv run orkestra mine sync

Questo comando scansiona la cronologia git e costruisce un indice di tutti i commit. Estrae segnali strutturati da ogni commit:

  • Tipo di commit convenzionale (feat, fix, chore, docs)
  • Scope (quale package o area)
  • Marcatori di breaking change
  • File toccati e metriche di complessità

Passo 2: controlla lo stato di copertura

uv run orkestra mine status

Ecco come appare il nostro stato attuale:

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 commit elaborati. 476 sono diventati decisioni architetturali. 6.799 sono diventate voci di changelog. Ogni commit classificato.

Passo 3: ottieni i candidati per la revisione

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

Questo fa emergere i commit non ancora elaborati, con il contesto completo per la classificazione:

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

I segnali aiutano a guidare la classificazione: is_releasable_type: true suggerisce che questo dovrebbe apparire nel changelog. Il grande numero di inserimenti e i file infrastrutturali suggeriscono che potrebbe anche essere una decisione architetturale.

Passo 4: classifica i commit

Qui i percorsi si dividono in due: voci di changelog e decisioni architetturali.

Per le voci di changelog:

uv run orkestra mine classify abc123 --changelog added

Questo registra che il commit abc123 dovrebbe apparire nel changelog sotto la categoria “Added”.

Per le decisioni architetturali:

Prima, ottieni un ID di decisione reale:

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

Poi classifica con l’ID di decisione:

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

Questo collega il commit a un record di decisione che verrà creato o aggiornato.

Per l’elaborazione batch (quello che facciamo davvero):

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

Il formato JSONL supporta entrambi i domini in un solo passaggio:

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

Passo 5: renderizza gli output

uv run orkestra changelog render --package <pkg>

Questo genera file CHANGELOG.md per package a partire dal ledger. I changelog sono artefatti derivati — cancellali e si rigenerano perfettamente dal ledger sorgente.

La struttura del record di decisione

Le decisioni estratte diventano file YAML con metadati ricchi:

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

Ogni decisione rimanda ai suoi commit sorgente. Ogni decisione specifica quali file interessa. Le relazioni tra decisioni sono esplicite.

Integrazione CLI: interrogare la memoria istituzionale

È qui che il loop si chiude. Gli agenti possono interrogare le decisioni tramite la CLI:

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

Restituisce decisioni sulla logica di retry, gestione degli errori, pattern di recupero.

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

Restituisce il record di decisione completo con contesto, motivazione e impatto.

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

Mostra quali scelte architetturali sono state fatte di recente.

Come gli agenti usano questo

Le istruzioni di base del nostro orchestratore includono:

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

Quando a un agente viene chiesto di implementare qualcosa legato a DuckDB, può prima controllare:

uv run orkestra decisions search --query "DuckDB"

E scoprire DEC-PL-142, imparando:

  • Perché abbiamo scelto DuckDB (context)
  • Come usarlo correttamente (agent_guidance)
  • Quali file guardare (files)
  • Quali decisioni correlate esistono (related)

L’agente non reinventa la ruota. Costruisce su pattern già stabiliti.

Il test delle tre domande

Non ogni commit merita un record di decisione. Usiamo il test delle tre domande per filtrare:

  1. È stato difficile da prendere? Ha richiesto un’analisi significativa, una valutazione dei trade-off, o un dibattito?
  2. È costoso da cambiare? Invertire questa decisione richiederebbe un rilavoro significativo?
  3. Ha un impatto a livello di sistema? Interessa più package o stabilisce pattern che altri seguiranno?

Se un commit risponde “sì” ad almeno una di queste domande, è un candidato per l’estrazione di una decisione. Il nostro tasso tipico: 1-4 decisioni ogni 100 commit (circa l’1-4%).

Per le voci di changelog, la soglia è più bassa: ogni modifica visibile all’utente (feature, correzioni, miglioramenti) viene registrata. Le faccende interne, gli aggiornamenti di documentazione, e i refactor tipicamente vengono saltati. Il nostro tasso tipico: 30-50 voci di changelog ogni 100 commit.

Archiviazione dei dati: ledger append-only

Il sistema di mining usa ledger JSONL append-only per un funzionamento multi-agente senza conflitti:

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

Il formato JSONL con merge=union in .gitattributes significa che più agenti possono classificare i commit simultaneamente senza conflitti di merge. Ogni riga è indipendente.

Gate di validazione

Prima di ogni sessione di mining, eseguiamo la validazione:

uv run orkestra mine validate --quick

Questo controlla:

  • Validità del formato SHA
  • Conformità del formato dell’ID di decisione
  • Nessuna voce duplicata per lo stesso SHA
  • Le decisioni referenziate esistono davvero

Dopo la classificazione, validiamo di nuovo prima di fare il commit delle modifiche.

Perché questo conta

Il loop di feedback che abbiamo costruito risolve diversi problemi:

Per i nuovi membri del team: invece di chiedere “perché abbiamo fatto X?”, possono cercare nel registro delle decisioni. Il contesto è preservato.

Per gli agenti AI: non operano nel vuoto. Possono interrogare la conoscenza istituzionale prima di fare raccomandazioni. Quando viene chiesto di aggiungere un nuovo stage alla pipeline, possono scoprire il pattern DuckDB e seguirlo.

Per la coerenza architetturale: le decisioni sono esplicite e ricercabili. Quando qualcuno propone un approccio che contraddice una decisione esistente, il sistema può far emergere il conflitto.

Per la generazione del changelog: le note di rilascio non sono una corsa dell’ultimo minuto. Sono un sottoprodotto della classificazione continua durante lo sviluppo.

Per l’onboarding: i nuovi agenti ereditano il contesto completo del codebase. Non vedono solo il codice — vedono le decisioni che lo hanno plasmato.

Stato attuale

Ad oggi:

  • 15.637 commit elaborati attraverso la pipeline
  • 476 decisioni architetturali estratte e documentate
  • 6.799 voci di changelog registrate
  • 100% di copertura su entrambi i domini

Ogni commit da quando abbiamo iniziato è stato classificato. La memoria istituzionale è completa e interrogabile.

Come iniziare

Se vuoi implementare qualcosa di simile:

  1. Inizia con i commit convenzionali. La pipeline di mining funziona meglio quando i commit hanno prefissi strutturati (feat:, fix:, chore:).

  2. Definisci i tuoi domini. Noi usiamo domini come pipeline, agent-design, observability, data-modeling. Questi organizzano le decisioni per area.

  3. Costruisci l’abitudine alla classificazione. Il mining funziona quando i team classificano regolarmente i commit. L’elaborazione batch con assistenza LLM aiuta a scalare.

  4. Rendi le decisioni interrogabili. Il valore si moltiplica quando gli agenti possono cercare le decisioni via CLI. Struttura il tuo output per il consumo automatico.

  5. Chiudi il loop. Le decisioni dovrebbero influenzare il lavoro futuro. Includi riferimenti alle decisioni nelle istruzioni per gli agenti e nelle checklist di code review.

L’obiettivo non è una documentazione perfetta. È rendere il perché dietro le modifiche accessibile sia agli esseri umani che all’AI, oggi e tra sei mesi. Quando le modifiche diventano memoria istituzionale, i team costruiscono su pattern stabiliti invece di reinventarli.


Il workflow di mining fa parte del nostro motore di orchestrazione, in particolare del modulo del motore di contesto nel nostro package di orchestrazione.

Letture correlate

Altro dal diario di costruzione di Maguyva