Mining del loop: come le modifiche diventano memoria istituzionale
> 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:
- È stato difficile da prendere? Ha richiesto un’analisi significativa, una valutazione dei trade-off, o un dibattito?
- È costoso da cambiare? Invertire questa decisione richiederebbe un rilavoro significativo?
- 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:
-
Inizia con i commit convenzionali. La pipeline di mining funziona meglio quando i commit hanno prefissi strutturati (
feat:,fix:,chore:). -
Definisci i tuoi domini. Noi usiamo domini come
pipeline,agent-design,observability,data-modeling. Questi organizzano le decisioni per area. -
Costruisci l’abitudine alla classificazione. Il mining funziona quando i team classificano regolarmente i commit. L’elaborazione batch con assistenza LLM aiuta a scalare.
-
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.
-
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
Perché abbiamo aggiornato la ricerca sul codice a voyage-4-large_
Abbiamo spostato i nostri embedding del codice su voyage-4-large — attualmente in cima alla classifica pubblica RTEB per il retrieval di codice. La versione onesta: il compromesso che facciamo, cosa indicizziamo davvero, e perché paghiamo per embedding premium.
Auto-miglioramento ricorsivo dei linguaggi: il grind della Code Intelligence su ~280 linguaggi_
Supportiamo la Code Intelligence per ~280 linguaggi. Nessun essere umano può controllarli a mano uno per uno. Così abbiamo costruito un loop di auto-miglioramento ricorsivo dei linguaggi — campionamento, LLM come giudice, correggi una cosa, rivalida — e lo facciamo girare con una flotta di agenti isolati finché l'estrazione non è davvero corretta, non solo verde.
Ricerca a fusione multi-modale: scegliere il retriever giusto per ogni query_
Una query come 'dove è definito parseConfig' vuole una ricerca diversa da 'come funziona l'auth'. Maguyva classifica l'intento, pesa di conseguenza quattro modalità di retrieval, e fonde i risultati con una Reciprocal Rank Fusion pesata.