ContextDoc: il Tuo Coding Agent Finalmente Smette di Fare Danni

File .ctx neon illuminati su sfondo cyberpunk con coding agent AI
Dai gli occhi al tuo scultore cieco. Ha già lo scalpello.
Matteo 10 min

Ricordi il post sul Coding Agent e l’Arte del Prompt Perfetto? Quello dove parlavo dello scultore cieco che massacra il marmo perché non vede dove sta andando?

Bene. Dopo averlo pubblicato ho continuato a smanettare sul problema. E quello che era ConceptDoc — il mio progetto per dare contesto all’AI — ha subito una trasformazione radicale.

Nuovo nome: ContextDoc. Nuova filosofia. Nuovi strumenti. E soprattutto: molto meno rumore.

Siediti comodo. C’è roba da raccontare.


Il Problema con ConceptDoc (Sì, Lo Ammetto)

Il vecchio ConceptDoc era ambizioso. Forse troppo. File .cdoc in JSON con metadata, components, pre/postcondizioni, testFixtures, businessLogic, aiNotes. Una struttura bellissima sulla carta. Un incubo da mantenere nella pratica.

Il problema ha un nome preciso: overhead di manutenzione. Ogni volta che cambiavi anche solo una riga di implementazione, dovevi aggiornare il file di documentazione. E la verità — quella che nessuno vuole dire — è che se devi aggiornare la doc ogni volta che cambia il codice, la doc non viene mai aggiornata davvero.

Perché sei umano. Hai cose più urgenti da fare. Dopo la terza volta che ti dici “aggiorno dopo”, non aggiorni mai più.

Risultato: documentazione stale che inganna l’AI peggio di nessuna documentazione.

Quindi ho fatto una cosa coraggiosa: ho buttato via tutto quello che non valeva la pena di mantenere.


Da 200 Righe di JSON a 30 Righe di YAML

La regola che ha guidato tutto il processo di pulizia è brutalmente semplice:

Se puoi ricavarlo dal codice o dal git log, non metterlo nel .ctx. Se non puoi ricavarlo da nessuna parte, va nel .ctx.

Fuori: firme dei metodi, liste di parametri, descrizioni di cosa fa una funzione. L’AI li legge direttamente dal codice — documentarli di nuovo è ridondante e diventa stale in tre giorni.

Dentro: le tensioni architetturali, i test concettuali, i workflow che attraversano più file. Roba che il codice non dice mai.

Il risultato è stato drammatico: da 200 righe di JSON verboso a 30 righe di YAML leggibile. Meno rumore, più segnale. Più facile da scrivere, più facile da mantenere, più utile per l’AI.


Il File .ctx: Tre Sezioni, Zero Orpelli

Un file .ctx ben scritto ha tre e solo tre componenti.

1. Le Tensioni Architetturali

Una tensione non è un commento normale. È la documentazione di una scelta che sembra sbagliata ma non lo è — o di un vincolo che non si tocca senza riconsiderare il castello di carte che ci sta sopra.

Esempio reale dal progetto:

tensions:
  - id: atomic-write
    what: "Le scritture su storage usano write-then-rename, non write diretta"
    why: "Garantisce atomicità su filesystem POSIX. Una write diretta lascia il file
          corrotto in caso di crash."
    constraint: "Non sostituire con write diretta senza implementare recovery esplicito."

  - id: no-id-reuse
    what: "Gli ID dei todo eliminati non vengono mai riassegnati"
    why: "Evita race condition in sistemi distribuiti e cache stale nei client."
    constraint: "Non ottimizzare con un counter che riparte da 0."

  - id: cli-parser-simple
    what: "Il parser CLI è intenzionalmente minimale, senza librerie esterne"
    why: "La semplicità è il requisito. Aggiungere argparse introdurrebbe dipendenze
          non necessarie per i 4 flag supportati."
    constraint: "Non aggiungere argparse o click senza rivalutare la filosofia del tool."

Quando l’AI legge questo, non rimuoverà l’atomic write pensando sia ridondante. Non semplificherà il generatore di ID. Non aggiungerà argparse “per migliorare il codice”. Sa perché le cose sono fatte così — e sa cosa non deve toccare.

La differenza tra un commento inline e una tensione? Il commento dice cosa. La tensione dice perché e soprattutto cosa non cambiare e cosa riconsiderare se ci provi.

2. I Test Concettuali

Questa è la parte più originale di ContextDoc, quella che mi diverte di più.

I test unitari testano l’implementazione — si rompono quando rinomini una classe, cambi framework o riscrivi una funzione. I test concettuali testano l’intento — sopravvivono ai refactor perché descrivono comportamento, non codice.

conceptualTests:
  - id: lifecycle-todo
    scenario: "Un todo attraversa il suo ciclo di vita completo"
    given: "Un todo attivo con titolo valido"
    when: "Viene completato, poi riattivato"
    then: "Lo stato torna ad active, la data di completamento viene azzerata"
    invariant: "L'ID non cambia mai durante il ciclo di vita"

  - id: validation-on-entry
    scenario: "La validazione avviene all'ingresso, non durante l'elaborazione"
    given: "Un titolo vuoto o con più di 100 caratteri"
    when: "Si tenta di creare un todo"
    then: "Errore esplicito prima che il dato entri nel sistema"
    note: "Non inserire validazione nelle classi interne — viola l'architettura."

  - id: persistence-after-restart
    scenario: "I todo persistono tra un riavvio e l'altro"
    given: "Tre todo creati in una sessione"
    when: "Il processo viene riavviato"
    then: "Tutti e tre i todo sono ancora presenti con gli stessi ID"

Sono language-agnostic: funzionano in Python, PHP, Go, JavaScript. Quando cambi framework, i test concettuali non si rompono. Sono la spec, non l’implementazione della spec.

3. I Workflow

Per i flussi che attraversano più file e che un AI non può ricostruire guardando un singolo componente:

workflows:
  - id: create-todo
    description: "Flusso completo di creazione"
    steps:
      - "TodoService riceve e valida l'input"
      - "Genera ID univoco (mai riusabile)"
      - "Crea TodoItem in stato active"
      - "Persiste via StorageService (atomic write)"
      - "Restituisce l'item creato"
    note: "La persistenza è sempre l'ultimo step. La validazione è sempre il primo."

Il project.ctx: Le Tensioni che Appartengono al Sistema

Hai vincoli che si ripetono in ogni file? Decisioni che non appartengono a nessun modulo specifico ma all’intero progetto?

Entra in scena il project.ctx — un file nella radice del progetto che cattura le tensioni cross-cutting:

# project.ctx
tensions:
  - id: soft-delete-global
    what: "Nessuna entità viene mai eliminata fisicamente dal database"
    why: "Requisito di audit. I dati devono essere recuperabili per 7 anni."
    constraint: "Qualsiasi DELETE fisico è un bug. Usare sempre il flag deleted_at."

  - id: jwt-stateless
    what: "I JWT non vengono mai salvati lato server"
    why: "Architettura stateless — scalabilità orizzontale senza shared session store."
    constraint: "Non aggiungere una blacklist di token senza riprogettare l'auth layer."

La regola di scope è fondamentale: non duplicare le tensioni di progetto nei file individuali (diventa rumore) e non mettere tensioni di singolo file in project.ctx (perde il focus).

La cosa migliore del project.ctx? È portabile. Funziona con Claude Code, Cursor, Windsurf, o qualsiasi agente personalizzato — senza riscrivere nulla. Il contesto è universale. Le direttive operative sono specifiche dell’IDE.


CLAUDE.md + .ctx: La Combo Che Fa la Differenza

Il .ctx da solo non basta. Serve anche dire all’agente come comportarsi con questa documentazione. Entra in scena CLAUDE.md:

# Regole Operative per questo Progetto

## Prima di modificare qualsiasi file
1. Leggi il `.ctx` corrispondente se esiste
2. Leggi `project.ctx` per i vincoli globali
3. Non violare nessuna tensione senza una discussione esplicita

## Quando aggiungi codice nuovo
- Rispetta i pattern architetturali documentati
- Se introduci una nuova tensione, aggiungila al `.ctx` appropriato

## Prompt riutilizzabili disponibili
- `generate-tests` → genera test unitari dai test concettuali del `.ctx`
- `review-tensions` → verifica che il codice non violi le tensioni documentate
- `sync-ctx` → aggiorna il `.ctx` dopo modifiche significative

La separazione è netta e intenzionale: il .ctx dice cosa è il sistema. Il CLAUDE.md dice come deve lavorarci l’agente. Il primo è portabile ovunque. Il secondo è accoppiato all’IDE.


I Nuovi Tool: ctx-watch e ctx-run

ctx-watch: Il Guardiano del Drift

Il rischio principale di qualsiasi documentazione parallela è che diventi obsoleta senza che nessuno se ne accorga. ctx-watch risolve il problema su due fronti.

In sviluppoctx-watch watch gira in background e monitora i file. Quando salvi un .py (o .php, o quello che usi), controlla se il corrispondente .ctx è ancora sincronizzato. Se c’è drift, te lo dice subito — non al commit, non in CI, mentre stai ancora lavorando.

ctx-watch watch
# ⚠  storage_service.py modificato — storage_service.py.ctx potrebbe essere stale
# →  notification_service.py.ctx esiste senza source corrispondente

Due segnali distinti: significa drift — il source è cambiato ma il .ctx non è stato aggiornato. significa spec senza implementazione — il .ctx esiste ma il file sorgente non ancora (intent-first mode).

In CIctx-watch status --changed-files "$(git diff --name-only HEAD~1)" è un check bloccante. Pipeline fermata se i file modificati hanno un .ctx non aggiornato. Exit code 1. Niente merge finché la doc è in sync.

Il segnale d’allarme più sottile: se il tuo .ctx non cambia da mesi mentre il codice evolve, probabilmente è stale. ctx-watch te lo dice anche questo.

ctx-run: La Spec Che Diventa Test

I test concettuali che hai scritto nel .ctx non sono solo documentazione passiva. Con ctx-run, un agente AI li legge e li traduce in test reali nel linguaggio del tuo progetto:

ctx-run generate-tests src/todo_service.py.ctx --output tests/
# → Generati 3 test pytest da 3 conceptualTests
# → tests/test_todo_lifecycle.py
# → tests/test_todo_validation.py
# → tests/test_todo_persistence.py

Non stai solo documentando l’intento — stai creando una spec eseguibile che l’AI trasforma automaticamente in pytest, PHPUnit, Jest, o qualsiasi framework usi.


Intent-First Development: la Spec Prima del Codice

TDD classico: scrivi un test che fallisce → implementa → il test passa.

Intent-First Development: scrivi il .ctx con tutti i test concettuali e le tensioni → implementa per soddisfarli → ctx-watch e ctx-run verificano che l’implementazione rispetti l’intento.

Il .ctx diventa il tuo “red state”. Il codice è il “green state”. L’AI ha una spec precisa prima di toccare qualsiasi cosa — non deve inferire l’intento dal nulla, non deve indovinare quali vincoli esistono.

ctx-watch status --reverse
# → notification_service.py.ctx: source non trovato
# Exit code 1 — usabile in CI per bloccare spec non implementate

Nel repository trovi examples/project-3: un notification service completamente specificato nel .ctx, con il file sorgente intenzionalmente assente. È un “red state” puro — spec scritta, implementazione da fare. Esattamente come un test rosso in TDD, prima che tu scriva la prima riga di codice.

Il vantaggio per l’AI è enorme: invece di partire da un prompt vago e dover inferire tutto, parte da una spec strutturata che descrive cosa deve costruire e quali vincoli deve rispettare. Meno iterazioni sbagliate, meno tempo a spiegare cosa non doveva toccare.


ContextDoc vs. Gli Strumenti che Già Conosci

Non è un rimpiazzo — è un complemento che copre il buco che nessun altro strumento copre.

JSDoc e docstrings documentano la firma del metodo — non i vincoli architetturali. L’AI li legge già dal codice.

OpenAPI è ottimo per i contratti HTTP — tace completamente sull’implementazione interna.

ADR (Architecture Decision Records) ha il giusto livello di astrazione — ma vive in una cartella separata e non è collegato al codice che descrive.

ContextDoc è file-level, vive accanto al codice, è minimo, e documenta esattamente quello che nessun altro strumento documenta: il perché delle scelte, i vincoli che non si toccano, i flussi che attraversano i confini dei moduli.


Come Iniziare Oggi (Senza Riscrivere Tutto)

Non devi documentare tutto il progetto in un weekend.

  1. Identifica i 2-3 file più fragili — quelli dove l’AI o un nuovo collega fa più danni.
  2. Per ognuno, chiediti: “Cosa sorprenderebbe qualcuno che legge questo file senza contesto?” Quella risposta è la tua prima tensione.
  3. Crea nome_file.ctx accanto al sorgente con quella tensione.
  4. Aggiungi un CLAUDE.md con l’istruzione di leggerlo prima di modificare.
  5. Installa ctx-watch watch come watcher in background.

La documentazione cresce con il progetto — non la scrivi tutta il primo giorno e poi la lasci marcire.

Red flag da tenere d’occhio:

  • .ctx troppo lungo → stai replicando il codice, non documentando le tensioni
  • Sezioni vuote → cancellale, non tenerle per dovere
  • Contenuto che cambia ogni volta che cambia l’implementazione → stai documentando la firma, non la tensione
  • Il .ctx non è cambiato da mesi mentre il codice è evoluto → ctx-watch te lo dirà, ma già saperlo è metà del lavoro

Il repository con esempi, tool e documentazione completa è su GitHub: ContextDoc.

E se dopo tutto questo il tuo coding agent continua a fare danni… beh, almeno ora sai con certezza che il problema non è la documentazione. Prova a cambiare modello. 🙃


content_copy Copiato