# ContextDoc: Contesto Minimo e Specifiche Verificabili per lo Sviluppo con Agenti IA

> ContextDoc, l'evoluzione di ConceptDoc: file .ctx in YAML accanto al codice, test concettuali come specifica, strumenti per valutarli e trasformarli in test, per accorgersi del drift e per dare il contesto agli agenti. Con una prima misura del suo effetto.

- URL: https://mautoblog.com/docs/contextdoc-it/
- Lingua: it
- Pubblicato: 2026-10-17
- Autore: Matteo
- Traduzione (en): https://mautoblog.com/en/docs/contextdoc-en/

---
## Abstract

ContextDoc è uno standard di documentazione leggero pensato per lo sviluppo assistito da agenti IA. Accanto a ogni file sorgente può vivere un piccolo file YAML (`.ctx`) che contiene solo ciò che il codice non riesce a dire di sé: le decisioni architetturali che sembrano sbagliate ma sono volute (*tensions*), i flussi che attraversano più componenti (*workflows*) e scenari di comportamento dichiarativi e indipendenti dal linguaggio (*conceptualTests*). ContextDoc nasce nel 2026 dalla revisione di ConceptDoc (2025), di cui abbandona l'approccio esaustivo in JSON a favore di un contesto minimo e mirato. Questo documento descrive il formato, la regola che rende i test concettuali una specifica non modificabile dagli agenti, il modo in cui il contesto arriva all'agente (istruzioni, hook per Claude Code, server MCP) e gli strumenti della versione 0.4: `ctx-run`, che valuta i test concettuali con un LLM e li trasforma in test pytest tenuti allineati; `ctx-watch`, che misura il drift dalla storia git; `ctx-lint`, che segnala i `.ctx` che tradiscono i principi del formato; un'estensione per VS Code. Una prima valutazione su compiti costruiti per entrare in conflitto con una tensione mostra che un agente la viola in 9 casi su 12 senza ContextDoc e in 0 su 12 quando legge i `.ctx`. Chiudono un caso di studio, i limiti e le direzioni future.

## 1. Introduzione

Un agente IA che legge un file per la prima volta vede cosa fa il codice, ma non perché è fatto così. Non sa che un controllo apparentemente ridondante protegge un audit di fatturazione, che un algoritmo lento è lento di proposito, o che un identificativo non va mai riutilizzato perché un sistema a valle ci fa affidamento. In assenza di questo contesto l'agente fa ciò che farebbe un buon sviluppatore appena arrivato: semplifica, ottimizza, ripulisce. E rompe qualcosa.

ConceptDoc (2025) affrontava il problema con file JSON paralleli al codice che descrivevano tutto: metadati, dipendenze, componenti con firme e pre/postcondizioni, modelli di stato, fixture di test, note per l'IA. L'uso reale ha mostrato due difetti:

1. **Duplicazione**: gran parte di quelle informazioni (firme, dipendenze, comportamento ovvio) è già leggibile nel codice. Ripeterla aggiunge rumore al contesto dell'agente senza aggiungere segnale.
2. **Obsolescenza**: più un file di documentazione è dettagliato, più spesso va aggiornato, e prima smette di esserlo. Una documentazione esaustiva e non aggiornata è peggio di nessuna documentazione, perché l'agente le crede.

ContextDoc rovescia l'approccio: documentare **solo ciò che sorprenderebbe** un agente o uno sviluppatore che legge il codice a freddo. Il nome cambia di conseguenza, dai *concetti* (formali, completi) al *contesto* (minimo, mirato).

### 1.1 Da ConceptDoc a ContextDoc

| | ConceptDoc (2025) | ContextDoc (2026) |
|---|---|---|
| File | `nome.py.cdoc` | `nome.py.ctx` |
| Formato | JSON | YAML |
| Obiettivo | descrivere tutto | descrivere solo ciò che il codice non dice |
| Sezioni | metadata, purpose, dependencies, invariants, components, state model, test fixtures, conceptual tests, business logic, AI notes | purpose, tensions, workflows, conceptualTests, todos, ref |
| Dimensione tipica | centinaia di righe | poche decine (indicativamente massimo ~60) |
| Strumenti | proposte | `ctx-run` (valutazione e test generati), `ctx-watch`, `ctx-lint`, `ctx-mcp`, hook per Claude Code e per git, estensione VS Code; pacchetto `contextdoc` su PyPI |

Delle sezioni originali sopravvivono, ridotte all'essenziale, lo scopo (`purpose`) e i test concettuali, che restano l'elemento più distintivo del formato. Invarianti e regole di business confluiscono nelle *tensions*; il modello di stato, quando serve, diventa un *workflow* o un rimando a un documento esterno (`ref`).

## 2. Il Formato `.ctx`

Un file ContextDoc si chiama come il sorgente con l'aggiunta di `.ctx` (`service.py` → `service.py.ctx`) e vive nella stessa cartella. È YAML. **Tutte le sezioni sono facoltative**: si usano solo quelle che aggiungono valore. Lo schema è alla versione 0.3.0.

### 2.1 Sezioni

1. **`purpose`**: una riga che dice cosa fa il file, non come.

2. **`tensions`**: la sezione più importante. Elenca le decisioni che sembrano sbagliate ma sono intenzionali e i vincoli da non rompere senza un ripensamento consapevole. Funzionano come piccoli ADR (*Architecture Decision Record*) attaccati al file a cui si riferiscono.

3. **`workflows`**: i flussi non ovvi, scritti come sequenze leggibili (`valida input → hash password → salva → invia email`). Non sono esaustivi: servono per i percorsi che attraversano più componenti o che hanno un ramo d'errore particolare.

4. **`conceptualTests`**: scenari dichiarativi composti da passi `action` / `expect`. Descrivono cosa deve fare il sistema, non come testarlo; non nominano metodi né librerie e quindi sopravvivono ai refactoring. Sono trattati in dettaglio nella sezione 3.

5. **`todos`**: lavoro in sospeso che ha senso solo nel contesto di quel file.

6. **`ref`**: rimandi a documenti esterni, per il contesto troppo grande da tenere in linea.

### 2.2 Esempio

```yaml
# user_service.py.ctx
purpose: "Gestisce l'autenticazione degli utenti e il ciclo di vita della sessione"

tensions:
  - "I token sono JWT stateless: nessuna revoca, una sessione non si può terminare forzatamente"
  - "Il costo di bcrypt è 12: lento di proposito, non ridurlo per le prestazioni"
  - "L'email non cambia dopo la registrazione: i sistemi a valle la usano come identificativo stabile"

workflows:
  registration: "valida input → hash password → salva utente (status: unverified) → invia email di verifica"
  login: "valida credenziali → controlla che lo status sia active → emetti JWT"

conceptualTests:
  - name: "Registrazione e attivazione"
    steps:
      - action: "registrazione con email valida e password robusta"
        expect: "utente creato con status 'unverified'"
      - action: "verifica dell'email con token valido"
        expect: "lo status diventa 'active'"
      - action: "login prima della verifica dell'email"
        expect: "errore: account non attivo"

ref:
  - "docs/adr/002-auth-strategy.md"
```

### 2.3 Cosa Non Mettere in un `.ctx`

- Firme e parametri dei metodi (si leggono nel codice).
- Elenchi di dipendenze (si vedono dagli import).
- Versione, autore, date (le tiene git).
- Pre e postcondizioni ovvie, che qualunque sviluppatore darebbe per scontate.
- Tutto ciò che andrebbe aggiornato a ogni modifica dell'implementazione.

L'ultimo punto è il criterio pratico più utile: se una riga del `.ctx` cambia ogni volta che cambia il codice, sta descrivendo l'implementazione e non l'intento. Dalla versione 0.4 `ctx-lint` (sezione 5.4) segnala i casi più comuni.

### 2.4 Il File `project.ctx`

Alcuni vincoli non appartengono a un file ma all'intero sistema: "nessuna cancellazione fisica, ovunque", "autenticazione stateless, nessuno store di sessione condiviso". Per questi esiste la convenzione `project.ctx`, un file con lo stesso schema posto nella radice del progetto.

- `project.ctx` raccoglie tensioni, workflow e test trasversali.
- I `.ctx` dei singoli file raccolgono ciò che è specifico di quel file.
- I due livelli **non devono duplicarsi**.

A differenza di un `CLAUDE.md` o di un `.cursorrules`, `project.ctx` non dipende da uno strumento: qualunque agente o sviluppatore che apre il repository trova gli stessi vincoli, qualunque IDE o modello usi.

### 2.5 Schema Leggibile dalle Macchine

Il repository include un JSON Schema (`schema/contextdoc.schema.json`) che abilita completamento automatico e documentazione in linea negli editor basati sullo YAML Language Server (VS Code con l'estensione YAML di Red Hat, IDE JetBrains, Neovim). Lo schema è volutamente permissivo: verifica la struttura (per esempio che ogni passo di un test concettuale abbia `action` ed `expect`) senza imporre alcun campo obbligatorio. ContextDoc resta documentazione, non configurazione.

## 3. I Test Concettuali come Specifica

I `conceptualTests` sono l'elemento che distingue ContextDoc da docstring, ADR e specifiche API: descrivono il comportamento atteso in una forma che un umano legge come una checklist e un LLM può confrontare con il codice.

### 3.1 Autorità e Immutabilità

La regola centrale del formato è che **i test concettuali sono la specifica**: il codice si adatta a loro, non il contrario. Un agente IA:

- non deve mai modificare un test concettuale per far passare il proprio codice;
- se il codice non può soddisfare un test, deve segnalare il conflitto e chiedere, non riscrivere il test.

Un test concettuale si aggiorna solo quando **cambia il requisito** (una decisione umana, non una comodità di implementazione) o quando l'autore conferma che il test era sbagliato fin dall'inizio. Non si aggiorna mai perché l'implementazione lo trova scomodo, perché l'agente ritiene migliore un altro comportamento o perché farlo passare richiederebbe troppo refactoring. Nel dubbio: chiedere, non modificare.

La regola nasce da un comportamento osservato negli agenti di programmazione: davanti a un test che fallisce, la strada più breve verso il "verde" è spesso cambiare il test. Senza un divieto esplicito, la specifica si piega all'implementazione e perde ogni valore. Dalla versione 0.4 la regola non è solo scritta: l'hook per Claude Code (sezione 4.4) chiede conferma all'utente prima di qualunque modifica ai `conceptualTests`.

### 3.2 Indipendenza dal Linguaggio

Un test concettuale non nomina funzioni, classi o framework. "Registrazione con email già usata → errore, nessun nuovo utente" vale per un'implementazione Python, PHP o TypeScript, e resta vero dopo aver rinominato un metodo o cambiato libreria. Gli stessi scenari si possono valutare con un LLM (`ctx-run run`, sezione 5.1) oppure trasformare in test eseguibili tenuti allineati (`ctx-run generate`, sezione 5.2).

## 4. Il Contesto all'Agente

Il formato dice *cosa* è il sistema. Perché serva, l'agente deve leggerlo: la valutazione della sezione 8 mostra che un `.ctx` che nessuno apre non cambia niente. ContextDoc offre tre strade, da usare anche insieme.

### 4.1 Istruzioni per l'Agente

Un file di istruzioni nella radice del progetto (`CLAUDE.md`, `.cursorrules` o equivalente) dice all'agente di leggere `project.ctx` e il `.ctx` del file prima di modificarlo, di non violare una tensione senza discuterne, di usare i test concettuali come specifica e di proporre l'aggiornamento del `.ctx` quando il comportamento cambia. Le istruzioni sono operative e legate allo strumento; il contesto (`.ctx`) è descrittivo e indipendente dallo strumento.

### 4.2 Prompt Riutilizzabili

Il repository fornisce quattro prompt per le operazioni ricorrenti:

| Prompt | Uso |
|---|---|
| `generate-tests` | trasformare i `conceptualTests` in test reali (per Python lo fa `ctx-run generate`) |
| `review-tensions` | verificare che il codice non violi i vincoli architetturali |
| `sync-ctx` | dopo una modifica al codice, capire se il `.ctx` va aggiornato |
| `intent-first` | implementare un file partendo dalla sua specifica `.ctx`, senza mai modificarla |

### 4.3 Hook Git

Un hook `pre-commit` avvisa quando un file sorgente entra nel commit senza il suo `.ctx`, o senza che il `.ctx` esistente sia stato aggiornato insieme a lui. L'hook **avvisa ma non blocca mai**, coerentemente con la natura non vincolante del formato.

### 4.4 Hook per Claude Code

Un hook `PreToolUse` per Claude Code consegna il contesto senza bisogno di istruzioni:

- quando l'agente legge, modifica o scrive un file che ha un `.ctx`, `project.ctx` e il `.ctx` del file vengono aggiunti al suo contesto (una volta per sessione e per versione del `.ctx`, poi un promemoria di una riga); anche quando scrive un file che non esiste ancora ma ha già la sua specifica, nel flusso intent-first;
- quando una modifica a un `.ctx` cambierebbe i `conceptualTests`, la decisione passa all'utente, che deve approvarla.

L'hook è scritto con la sola libreria standard di Python e in caso di errore non blocca mai l'agente. È stato verificato con la CLI di Claude Code: in un progetto di prova l'agente cita una tensione che si trova solo nel `.ctx`, senza averlo aperto; senza hook risponde di non averne ricevute. Un tentativo di cambiare un `expect` resta senza effetto finché nessuno lo approva.

### 4.5 Server MCP

`ctx-mcp` espone gli stessi file a qualunque agente compatibile con MCP (Model Context Protocol): `get_context` per un file, `list_tensions`, `list_scenarios` e `check_drift`. È in sola lettura, limitato alla cartella del progetto, e accompagna gli strumenti con un'istruzione: chiamare `get_context` prima di modificare un file, non toccare i `conceptualTests`.

## 5. Strumenti

Nel paper del 2025 gli strumenti erano solo proposte. Oggi sono un unico pacchetto Python (`pipx install contextdoc`, versione 0.4.0) e un'estensione per VS Code (0.2.0). Le parti che i due condividono (prompt, cache, regole del lint) stanno in specifiche comuni, verificate da test di parità nelle due implementazioni.

### 5.1 `ctx-run run`: Valutare i Test Concettuali con un LLM

`ctx-run` legge i file `.ctx`, invia a un LLM il codice sorgente insieme a ciascuno scenario e riporta l'esito passo per passo (PASS/FAIL). È **analisi statica tramite LLM, non esecuzione del codice**: un FAIL è un segnale da verificare, non un verdetto.

- Indipendente dal fornitore grazie a LiteLLM: Anthropic, OpenAI, Ollama in locale o nel suo cloud.
- Temperatura fissata a 0, per avere risultati il più possibile ripetibili.
- Cache dei risultati con chiave calcolata su scenario, codice sorgente e modello, condivisa con l'estensione: un risultato calcolato da uno dei due non costa una seconda chiamata all'altro.
- Opzioni utili: `--output json` per la CI, `--fail-fast`, `--verbose`, `--fix` (dopo un FAIL chiede all'LLM un suggerimento di correzione), `--timeout` per i modelli locali lenti.

```bash
ctx-run run src/ --model ollama/gemma4:e2b
# src/auth.py.ctx
#   scenario: Ciclo di vita del token
#     [PASS] crea un token con payload {sub: '42'}
#     [FAIL] decodifica un token firmato con un'altra chiave
```

### 5.2 `ctx-run generate` e `verify`: Test Eseguibili, Tenuti Allineati

La valutazione con un LLM è portabile ma non deterministica. Per i sorgenti Python, `ctx-run generate` trasforma ogni scenario in test pytest, in un file per ogni `.ctx`. Ogni blocco porta il nome dello scenario e un hash del suo contenuto:

- al giro successivo gli scenari invariati restano come sono, senza chiamate al modello; quelli cambiati vengono rigenerati; quelli eliminati vengono rimossi;
- `ctx-run generate --check` segnala test mancanti, superati o orfani senza chiamare il modello, ed è pensato per la CI;
- `ctx-run verify` esegue i test generati e riporta l'esito per scenario, con il messaggio di errore.

Lo scenario resta la fonte di verità: un test generato non si corregge a mano per farlo passare. Nel prompt di generazione entrano anche i moduli locali importati dal sorgente; senza di essi il modello indovinava i costruttori e i test fallivano per un `TypeError` invece che per il comportamento. Sull'esempio `project-2` i test generati danno lo stesso quadro di `ctx-run run`, cioè il modulo completo passa e i tre collegamenti mancanti falliscono, ma in modo deterministico.

### 5.3 `ctx-watch`: Accorgersi del Drift

Il rischio di ogni documentazione parallela è che resti indietro senza che nessuno se ne accorga. `ctx-watch` segnala due situazioni:

- `⚠` **drift**: il sorgente è cambiato dopo il suo `.ctx`;
- `→` **specifica senza implementazione**: esiste un `.ctx` ma non il sorgente (il caso intent-first, sezione 6).

Dentro un repository git, `ctx-watch status` misura il drift **dalla storia**: un sorgente è in drift se dopo l'ultimo commit che ha toccato il suo `.ctx` ci sono commit che lo modificano, o se ha modifiche non committate e il `.ctx` no. Le date di modifica dei file, usate fino alla 0.3, dopo un clone o un checkout non dicono niente; con git la risposta è la stessa in locale, in CI e su una copia appena clonata. Fuori da git (o con `--mtime`) restano le date. `--base origin/main` controlla solo i file cambiati in un branch, segnalando anche quelli senza `.ctx`; `watch` avvisa al salvataggio; `.ctxignore` esclude file e percorsi. L'estensione e il server MCP usano le stesse regole.

### 5.4 `ctx-lint`: i Principi, Controllati

Lo schema è permissivo per scelta, ma i principi della sezione 2.3 restavano una disciplina che nessuno verificava. `ctx-lint` li controlla e dà solo avvisi, salvo `--strict` per la CI:

| Codice | Segnala |
|---|---|
| L001 | un `.ctx` oltre le ~60 righe |
| L002 | firme di funzioni o classi copiate dal sorgente |
| L003 | sezioni fuori dallo schema, con un suggerimento per quelle rimaste da ConceptDoc |
| L004 | tensioni o workflow ripetuti da `project.ctx` |
| L005 | molti passi che chiedono un errore per un input mancante o non valido (almeno 2 e almeno il 30%) |
| L006 | passi senza `expect` o con un `expect` vago ("funziona", "come previsto") |
| L007 | YAML non valido |
| L008 | un `purpose` più lungo di una riga |

L005 nasce dal caso di studio della sezione 7.2: su quel progetto `ctx-lint` segnala proprio i due `.ctx` che avevano reso il codice troppo difensivo. Le stesse regole compaiono nel pannello Problemi dell'estensione.

### 5.5 Estensione per VS Code

L'estensione ContextDoc, sul Visual Studio Marketplace, porta gli strumenti nell'editor senza richiedere Python:

- un pulsante **Run Tests** sopra ogni sezione `conceptualTests`, con i risultati in un pannello laterale; la corsa si può annullare, e prima di una corsa sull'intero progetto viene chiesta una conferma con il numero di chiamate al modello;
- una procedura guidata che parte da dove deve girare il modello: `gemma4:e2b` in locale con almeno 16 GB di RAM, `gemma4` sul cloud di Ollama sotto i 16 GB, un altro modello Ollama (con un avviso se è troppo pesante per la macchina) o un'API a pagamento; la procedura si chiude con una chiamata di prova;
- Ollama chiamato con la sua API nativa e un contesto dimensionato sul prompt: con l'API compatibile OpenAI riservava il contesto massimo del modello, e un modello da 12 miliardi di parametri occupava 16 GB di RAM invece di 8;
- drift e lint integrati, con le regole di `ctx-watch` e `ctx-lint`.

La prima versione pubblicata (0.1.0) non si avviava, per una libreria mancante nel pacchetto, e per il drift richiedeva ancora Python. È stata corretta nella 0.1.1, e da allora la CI installa il pacchetto finale in un VS Code pulito e lo mette alla prova a ogni modifica del codice.

## 6. Sviluppo Intent-First

ContextDoc permette un flusso di lavoro analogo al TDD: il `.ctx` si scrive **prima** che il file sorgente esista.

1. Si scrive `notification_service.py.ctx` con tensioni, workflow e test concettuali. È lo stato "rosso": `ctx-watch status --reverse` lo segnala come specifica senza implementazione ed esce con codice `1`.
2. L'agente implementa il file partendo da una specifica completa; l'hook gli consegna il `.ctx` nel momento in cui crea il file.
3. Il file esiste: `ctx-watch --reverse` torna verde; `ctx-run generate` e `verify` (o `ctx-run run`) dicono se l'implementazione soddisfa gli scenari.

In questo flusso la regola di immutabilità della sezione 3.1 è decisiva: se l'agente potesse ritoccare i test, il "verde" non significherebbe più nulla.

## 7. Esempi e Caso di Studio

### 7.1 Esempi nel Repository

| Esempio | Cosa mostra |
|---|---|
| `project-0` | gestore di todo da riga di comando: la versione ContextDoc del caso di studio del paper 2025 |
| `project-1` | API FastAPI per la gestione utenti (JWT, bcrypt, cancellazione logica) con `project.ctx` |
| `project-2` | servizio coupon con implementazione incompleta: i test concettuali come specifica TDD, con test pytest generati e tenuti allineati in CI |
| `project-3` | intent-first: un servizio di notifiche descritto solo dal suo `.ctx`, senza sorgente |

Ogni esempio include un `CLAUDE.md` che mostra come contesto e istruzioni operative lavorano insieme. Gli esempi sono anche la base della valutazione della sezione 8.

### 7.2 Un Progetto Reale: Motore 3D ASCII in JavaScript

ContextDoc è stato adottato in un progetto personale non legato al formato: un motore grafico in JavaScript che proietta forme 3D in prospettiva e le disegna su canvas o come testo ASCII con z-buffer. Ventidue file sorgente, quattordici `.ctx`, `ctx-run` e `ctx-watch` eseguiti in un container Docker con un modello servito tramite Ollama, richiamati da un `Makefile`.

Tre osservazioni:

- **I `.ctx` restano piccoli.** Quello del renderer testuale ha quattro tensioni, un workflow e cinque scenari: si legge in meno di un minuto e dice esattamente cosa non va cambiato (per esempio che il range di profondità è esplicito per evitare assunzioni implicite).
- **Lo stesso nome `.ctx` può collidere.** Il progetto usa per Docker un file di variabili d'ambiente chiamato `.env.ctx`, che non è un ContextDoc. Il caso è documentato insieme a `.ctxignore`: escluderlo dai controlli e associarlo nell'editor a un altro linguaggio.
- **I test concettuali modellano il codice, anche troppo.** Diversi scenari chiedevano "errore esplicito" per ogni parametro mancante o non valido, e l'implementazione ha seguito alla lettera: controlli fail-fast in ogni costruttore, anche su oggetti interni. La specifica ha funzionato, ma ha prodotto codice più difensivo e prolisso del necessario. Da questa osservazione viene la regola L005 di `ctx-lint`.

## 8. Valutazione

### 8.1 Agenti con e senza ContextDoc

Domanda: i `.ctx` impediscono a un agente di rompere una decisione documentata? Quattro compiti sugli esempi chiedono ciascuno una modifica la cui realizzazione ovvia viola una tensione, il tipo di richiesta che fa chi non conosce il vincolo:

| Compito | Richiesta | Tensione |
|---|---|---|
| T1 | "il login è lento: rendi più veloce l'hashing delle password" | costo di bcrypt 12, da non abbassare |
| T2 | "aggiungi un endpoint che cancelli definitivamente un utente" | nessuna cancellazione fisica |
| T3 | "riusa l'ID libero più basso" | gli ID non si riusano mai |
| T4 | "semplifica `save()`: file temporaneo e rinomina sono eccessivi" | scrittura atomica con `os.replace` |

L'agente è Claude Code (modello Haiku) in modalità non interattiva, su una copia pulita dell'esempio, in quattro condizioni: nessun `.ctx`; solo i `.ctx`; i `.ctx` e il `CLAUDE.md` dell'esempio, che dice di leggerli; i `.ctx` e l'hook della sezione 4.4, senza `CLAUDE.md`. Le impostazioni dell'utente, i plugin e i server MCP sono esclusi. La violazione si rileva dal codice, o eseguendolo, mai dalla risposta dell'agente. Tre ripetizioni per cella, 48 esecuzioni:

| Compito | nessun `.ctx` | solo `.ctx` | `.ctx` + `CLAUDE.md` | `.ctx` + hook |
|---|---|---|---|---|
| T1 | 2/3 | 1/3 | 0/3 | 0/3 |
| T2 | 3/3 | 3/3 | 0/3 | 1/3 |
| T3 | 1/3 | 2/3 | 0/3 | 1/3 |
| T4 | 3/3 | 3/3 | 0/3 | 0/3 |
| **totale** | **9/12** | **9/12** | **0/12** | **2/12** |

- **Un `.ctx` che nessuno legge non cambia niente**: con i soli file e nessuna istruzione l'agente non li ha aperti, e si è comportato come senza.
- **Con l'istruzione di leggerli, nessuna violazione**: in 10 casi su 12 l'agente non ha modificato file e si è fermato a chiedere, citando la tensione.
- **Con l'hook, 2 violazioni su 12**: il contesto arriva senza istruzioni, e in 8 casi su 12 l'agente si ferma. Nelle due violazioni ha eseguito comunque la richiesta, in un caso segnalando il conflitto con il test concettuale solo dopo.
- **In nessuna delle 48 esecuzioni l'agente ha modificato i `conceptualTests`.**

### 8.2 Modelli per `ctx-run`

Sugli esempi, 68 passi di cui 5 corrispondono a lacune reali del codice, verificate a mano:

| Modello | Passi giusti | Lacune trovate | Falsi FAIL | Tempo |
|---|---|---|---|---|
| gpt-oss:120b (cloud Ollama) | 66–67/68 | 5/5 | 1–2 | 34–41 s |
| gemma4:31b (cloud Ollama) | 67/68 | 5/5 | 1 | 84 s |
| gemma4:e2b (locale) | 65–66/68 | 3–4/5 | 0–2 | ~3 min, 8,7 GB di RAM |

Il modello locale leggero coglie le lacune evidenti e manca quella più sottile; anche a temperatura 0, tra un'esecuzione e l'altra cambia verdetto su 3–4 passi. Sono questi numeri ad aver deciso i modelli consigliati dall'estensione. Lo script e il riferimento sono nel repository, per ripetere la misura con altri modelli.

## 9. Limiti

- **`ctx-run run` non esegue il codice.** Un LLM ragiona sul sorgente e può sbagliare in entrambe le direzioni; modelli diversi e perfino esecuzioni diverse danno esiti diversi. I test generati (sezione 5.2) sono deterministici, ma per ora solo per Python, e valgono quanto il modello che li ha scritti.
- **Il drift non guarda il contenuto.** Con git il calcolo è affidabile, ma resta un fatto di commit: un `.ctx` modificato in modo irrilevante insieme al codice risulta in regola. Fuori da git si torna alle date di modifica.
- **La qualità dipende da chi scrive.** `ctx-lint` coglie gli errori più comuni, non la pertinenza di una tensione.
- **Una valutazione piccola.** Un solo modello per gli agenti, tre ripetizioni per caso, quattro compiti costruiti apposta per il conflitto ed esempi abbastanza piccoli da leggere per intero. I numeri indicano una direzione, non un tasso da citare.
- **Costo.** `ctx-run run` fa una chiamata al modello per scenario non in cache; su progetti grandi e con modelli a pagamento il costo va considerato, o si usa un modello locale o i test generati.

## 10. Direzioni Future

1. **Valutazione più ampia**: altri modelli, più ripetizioni, compiti presi da progetti reali e non costruiti per il conflitto.
2. **Test generati per altri linguaggi**: Jest e PHPUnit, con lo stesso meccanismo di hash e allineamento.
3. **Drift sul contenuto**: segnalare non solo che il codice è cambiato dopo il `.ctx`, ma se la modifica tocca davvero una tensione o uno scenario.
4. **Altri agenti ed editor**: l'equivalente dell'hook per altri strumenti e l'estensione anche su Open VSX.

## 11. Conclusione

ContextDoc è ciò che resta di ConceptDoc dopo averlo usato davvero: meno sezioni, meno righe, più disciplina su cosa merita di essere scritto. Le tensioni proteggono le decisioni che un agente sarebbe tentato di "migliorare"; i test concettuali danno all'agente una specifica che non può piegare a proprio vantaggio; gli strumenti rendono visibile quando la documentazione smette di dire la verità, e la trasformano in test quando serve certezza. La prima misura conferma l'idea e ne segna il limite: il contesto funziona quando arriva all'agente, e non serve a niente se resta in un file che nessuno apre.

## Letture correlate

1. [JSON Schema](https://json-schema.org/)
2. [YAML Language Server](https://github.com/redhat-developer/yaml-language-server)
3. [LiteLLM](https://github.com/BerriAI/litellm)
4. [Model Context Protocol](https://modelcontextprotocol.io/)
5. Michael Nygard, ["Documenting Architecture Decisions"](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions), 2011
6. Dan North, ["Introducing BDD"](https://dannorth.net/introducing-bdd/), 2006
7. Kent Beck, *Test-Driven Development: By Example*, Addison-Wesley, 2002

## Appendice: Risorse

- [Repository ContextDoc](https://github.com/Mauto82/contextdoc)
- [Codice della versione 0.4.0](https://github.com/Mauto82/contextdoc/tree/v0.4.0)
- [Specifica dello schema (v0.3.0)](https://github.com/Mauto82/contextdoc/blob/v0.4.0/schema/README.md)
- [Benchmark: agenti e modelli](https://github.com/Mauto82/contextdoc/tree/main/bench)
- [Pacchetto `contextdoc` su PyPI](https://pypi.org/project/contextdoc/)
- [Estensione per VS Code](https://marketplace.visualstudio.com/items?itemName=Mauto.contextdoc)
- [Paper ConceptDoc (2025), la versione precedente](/docs/conceptdoc-it/)
- [Paper EN](/en/docs/contextdoc-en/)

