Lo sviluppatore che digita "add user authentication" in Claude Code ottiene un risultato diverso ogni volta. Forse JWT. Forse cookie di sessione. Forse un flusso OAuth2 completo con refresh token e PKCE. L'agente non sa cosa vuoi perche non gliel'hai detto. Gli hai dato una direzione, non una destinazione.
Gli sviluppatori che vedo ottenere output consistente e pronto per il rilascio da Claude Code condividono un'abitudine: scrivono una specifica prima di affidare il lavoro all'agente. Non un romanzo. Non un ticket Jira con tre frasi di contesto. Un documento concreto che definisce come appare "completato" prima che qualcuno scriva una riga di codice.
Non e una saggezza nuova. Lo sviluppo spec-first precede l'IA di decenni. Ma con gli agenti, il costo di saltare la specifica e piu alto e il beneficio di scriverne una e piu grande. Uno sviluppatore umano puo fermarsi a meta dell'implementazione e chiedere "aspetta, intendevi autenticazione con password o SSO?" Un agente ne scegliera uno in silenzio e proseguira. Quando te ne accorgi, ha costruito la cosa sbagliata, e hai speso 20 minuti a revisionare codice da buttare.
Questo articolo attraversa il ciclo di vita spec-driven che uso con Claude Code ogni giorno: come scrivere specifiche contro cui gli agenti possono eseguire, il checkpoint plan-before-code che cattura i malintesi in anticipo, e un protocollo di verifica piu rigoroso di "compila."
Perche "costruiscilo e basta" fallisce con gli agenti
Siamo specifici sulla modalita di fallimento. Quando dai a Claude Code un'istruzione vaga, tre cose vanno storte:
Assunzioni silenziose. L'agente colma ogni lacuna nella tua specifica con le proprie assunzioni. A volte sono ragionevoli. A volte no. Non saprai in quale categoria sei fino a quando non leggi l'output. Con istruzioni vaghe, finisci per leggere l'output con piu attenzione di quanto avresti impiegato a scrivere una specifica.
Risultati non riproducibili. Esegui lo stesso prompt vago due volte e ottieni due implementazioni diverse. Non solo nomi di variabili o formattazione diversi. Decisioni architetturali diverse. Librerie diverse. Strategie di gestione degli errori diverse. Se non puoi riprodurre l'output, non puoi costruire un processo affidabile attorno ad esso.
La revisione diventa il collo di bottiglia. Quando l'agente prende tutte le decisioni, devi verificare tutte le decisioni. Un diff di 400 righe dove comprendi ogni scelta richiede 5 minuti di revisione. Un diff di 400 righe dove l'agente ha scelto lo schema del database, la forma dell'API, i codici di errore e la logica di validazione richiede 30 minuti perche stai ricostruendo la specifica dall'implementazione.
La soluzione non sono prompt migliori. E anticipare le decisioni importanti in un documento contro cui l'agente puo eseguire.
Il ciclo di vita spec-driven
Il workflow ha cinque fasi. Ognuna ha una chiara condizione d'ingresso e una chiara condizione d'uscita.
Fase 1: Brainstorming. Esplori lo spazio del problema. Quali sono i vincoli? Quali approcci esistono? Cosa hai provato prima? Qui pensi ad alta voce, da solo o con Claude Code in modalita conversazionale. Condizione d'uscita: hai un approccio preferito e comprendi i compromessi.
Fase 2: Revisione. Metti l'approccio sotto pressione. Cosa potrebbe andare storto? Quali casi limite esistono? Questo entra in conflitto con qualcosa gia presente nel codebase? Se lavori con piu agenti, qui un agente di architettura o un secondo parere e prezioso. Condizione d'uscita: sei sicuro che l'approccio sia solido.
Fase 3: Specifica. Scrivi cio che hai deciso. Descrizione del problema, approccio proposto, file da modificare, criteri di accettazione verificabili meccanicamente e un piano di test. Questo e il contratto. Condizione d'uscita: qualcuno (umano o agente) potrebbe leggere questa specifica e sapere esattamente cosa costruire e come verificarlo.
Fase 4: Implementazione. L'agente esegue contro la specifica. Non contro un'idea vaga. Contro un documento concreto con criteri testabili. Condizione d'uscita: l'agente dichiara di aver completato e ha pubblicato prove di verifica.
Fase 5: Verifica. Tu (o un agente QA) confermi che l'implementazione corrisponde alla specifica. Non "sembra corretto" ma "soddisfa ogni criterio di accettazione." Condizione d'uscita: ogni criterio e verificato, e quelli che falliscono tornano alla Fase 4.
L'intuizione chiave: le fasi 1-3 costano poco. Richiedono 10-20 minuti per una funzionalita di medie dimensioni. La fase 4 richiede il tempo necessario per l'implementazione. La fase 5 richiede 5-10 minuti. Saltare le fasi 1-3 non fa risparmiare 10-20 minuti. Costa il tempo per revisionare, debuggare e rifare lavoro che andava nella direzione sbagliata.
Come appare una buona specifica per agenti
Ecco un vero template di specifica. Non una user story. Non un documento di requisiti di prodotto. Un documento di lavoro che dice a un agente esattamente cosa costruire.
## Problem
The filter bar resets when switching workspaces. Users lose their
filter state and have to re-apply filters every time they switch.
## Approach
Persist filter state per-workspace in localStorage. Key the stored
state by workspace database path so filters don't bleed across
workspaces.
## Files to Modify
- lib/local-storage.ts: Add getWorkspaceFilters / setWorkspaceFilters
- components/filter-bar.tsx: Read initial state from localStorage,
write on every change
- hooks/use-workspace.ts: Trigger filter restore on workspace switch
## Acceptance Criteria
1. Select workspace A, set filters to status=open + type=bug
2. Switch to workspace B. Filters reset to defaults.
3. Switch back to workspace A. Filters restore to status=open + type=bug.
4. Close the browser tab, reopen. Filters for the active workspace
are still applied.
5. bd list --status=open --type=bug output matches the filtered table.
## Out of Scope
- Server-side filter persistence
- Filter presets / saved filter combinations
- URL-based filter state (query params)
## Test Plan
- Unit test: getWorkspaceFilters returns stored value for matching
workspace path
- Unit test: setWorkspaceFilters writes correct key format
- Manual test: steps 1-5 from acceptance criteria above
Nota cosa contiene e cosa non contiene questa specifica. Non spiega come funziona localStorage. Claude Code lo sa. Non giustifica perche abbiamo scelto localStorage al posto degli URL params. Questo e successo nella fase di brainstorming. Lista ogni file che l'agente dovrebbe toccare, il che significa che se l'agente inizia a modificare file fuori da questa lista, e un segnale d'allarme. Include una sezione fuori ambito, che impedisce all'agente di fare gold plating.
I criteri di accettazione sono la parte piu importante. Ognuno e un'azione concreta con un risultato osservabile. Non "i filtri dovrebbero persistere." Questo e ambiguo. "Passa al workspace A, verifica che i filtri siano status=open + type=bug" e testabile. Un agente puo eseguirlo. Un revisore QA puo verificarlo.
Il pattern plan-before-code
Ecco un protocollo che cattura la maggior parte degli errori di implementazione prima che diventino codice: richiedere all'agente di pubblicare il suo piano di implementazione prima di scrivere qualsiasi cosa.
In pratica, si presenta come un commento strutturato sul task. Prima che l'agente apra qualsiasi file, scrive esattamente cosa intende fare.
PLAN: Persist filter state per-workspace using localStorage.
1. Add workspace-scoped storage helpers to lib/local-storage.ts:
- getWorkspaceFilters(dbPath: string): FilterState | null
- setWorkspaceFilters(dbPath: string, filters: FilterState): void
- Key format: "beadbox:filters:{dbPath}"
2. Update components/filter-bar.tsx:
- On mount, read stored filters for current workspace
- On every filter change, write to localStorage
- Accept databasePath as prop (currently not passed)
3. Update hooks/use-workspace.ts:
- On workspace switch, emit event that filter-bar listens for
- Filter-bar reads new workspace's stored filters on event
4. Threading databasePath:
- filter-bar needs databasePath from the workspace context
- Will add it to the WorkspaceProvider context value
Files: lib/local-storage.ts, components/filter-bar.tsx,
hooks/use-workspace.ts, components/workspace-provider.tsx
Test: Unit tests for storage helpers, manual test of all 5
acceptance criteria.
All'agente servono circa 30 secondi per produrlo. A te servono circa 2 minuti per leggerlo. E in quei 2 minuti, puoi individuare problemi che richiederebbero 20 minuti per essere corretti dopo l'implementazione:
- L'agente sta toccando file fuori dalla specifica? (Aggiungere workspace-provider.tsx non era nella specifica. Va bene o e scope creep?)
- L'approccio ha senso? (Usare un event emitter per i cambi di workspace potrebbe essere sovradimensionato. Un semplice cambio di prop potrebbe bastare.)
- Mancano dei passaggi? (Che dire della pulizia delle vecchie voci localStorage quando un workspace viene rimosso?)
Il piano e un checkpoint. Se sembra corretto, dici all'agente di procedere. Se sembra sbagliato, correggi il piano. In ogni caso, hai investito 2 minuti invece di 20.
