Dieci sviluppatori, una cartella docs
Superpowers è un plugin per Claude Code (286.000 star su GitHub) le cui skill scrivono spec e piani di implementazione come file markdown e li committano nel repository. Di default ognuno di questi file finisce in una sola cartella, docs/superpowers/. A giugno i maintainer di Okama, una libreria Python per la finanza, hanno scoperto che otto piani di implementazione scritti lì da un agente, committati esattamente come previsto dal plugin, erano stati renderizzati come pagine web pubbliche su Read the Docs. Se ne sono accorti dopo il rilascio.
Ora scala il problema: un team front-end di dieci sviluppatori, quattro squad, un solo repository, e ogni sviluppatore che genera questi file. Tre domande arrivano sulla scrivania del lead. Cosa versioniamo esattamente? Il drift è un problema quando una spec nomina un path eliminato due sprint fa? E chi governa la cartella? La fuga di Okama non è stata causata dal committare. È stata causata dal committare senza una regola. Questo articolo ne offre cinque.
Ogni tool committa i file
Superpowers non chiede mai se committare. La riga 18 della sua skill di planning salva ogni piano sotto docs/superpowers/plans/, datato, un file per feature. La skill di brainstorming scrive il documento di design e lo committa nello stesso passaggio, prima che tu abbia visto il piano.
Non è una stranezza di Superpowers. Ogni tool spec-driven importante fa la stessa scelta:
| Tool | Editore | Dove vivono le spec |
|---|---|---|
| Superpowers (286.000 star) | obra | docs/superpowers/, una cartella per tutto |
| Spec Kit (136.000 star) | GitHub | una cartella numerata per feature, sul branch di quella feature |
| Kiro | Amazon | .kiro/specs/, una cartella per feature |
| Playbook AI-native SDLC | Anthropic | un artefatto committato per ogni stage: intent, spec, plan, diff, review findings, incident record |
Kiro vende le cartelle per feature come un modo per far collaborare i colleghi su feature diverse contemporaneamente. Il playbook di Anthropic, pubblicato in agosto, va oltre: ogni stage committa un artefatto che lo stage successivo può leggere. Quindi la domanda non è mai stata se committare, e il dove lo risponde ogni tool. Chi possiede il file, e quando è morto, no. Questo è il vuoto che le cinque regole coprono.
Tre modi in cui va storto
I piani committati falliscono in tre modi distinti.
Fallimento 1: il generatore di docs. Una build della documentazione che renderizza ogni file markdown sotto docs/, che sia elencato in un sommario o no, spedisce la cartella dei piani insieme al manuale. È esattamente quello che è successo a Okama.
Fallimento 2: il branch. La issue 1246 di Superpowers riporta che il brainstorm committa il piano direttamente su main. Un utente conta 10-15 commit per sessione, uno nuovo ogni poche modifiche. La richiesta del thread sta in una riga: niente piani e spec sul branch main.
Fallimento 3: il drift. Lo spec drift è il fallimento silenzioso: il codice evolve e la spec no. Birgitta Böckeler di Thoughtworks nomina tre livelli di spec-driven development:
| Livello | Significato |
|---|---|
| Spec-first | Scritta, usata una volta |
| Spec-anchored | Mantenuta per tutta la vita della feature |
| Spec-as-source | L'umano modifica solo la spec |
Superpowers scrive documenti spec-first e li conserva per sempre. Di default ottieni uno storage spec-anchored con manutenzione da prima bozza: nessuno aggiorna il file, e un agente lo legge il trimestre dopo come verità. TrueFoundry lo dice chiaramente: il drift è inevitabile nella pratica spec-first e gestibile in quella spec-anchored, ma solo se la divergenza è rilevabile.
Un repository con 41 spec e 9 agent file non ha un problema di ordine. Ha 41 input di comportamento non versionati. La reazione di Böckeler: preferirebbe fare review del codice piuttosto che di tutti questi file markdown. Un piano che nessuno ricarica più è clutter. Un piano che un agente ricarica è un'istruzione, e una istruzione superata è un'istruzione sbagliata.
Regola 1: una casa per squad, con owner
Regola 1: la cartella ha un owner, e l'owner è una squad, non il plugin. Dalla versione 5, Superpowers rispetta le istruzioni nel CLAUDE.md del tuo progetto sopra i suoi default. Dici dove vanno i piani, e ci vanno.
Una tabella di path però non basta. Nella issue 939, un utente aveva scritto una tabella di output path e il modello ha seguito il path concreto nella skill, ignorando la tabella. La nota di override della skill è una parentesi. Una riga in grassetto, imperativa, ha risolto il problema al primo tentativo: le spec devono essere salvate qui, non lì, con il default nominato come la cosa da evitare.
Il layout è una cartella per squad (checkout, search, accounts, design-system), ciascuna con le proprie spec e piani. In un monorepo, metti la riga nel CLAUDE.md del singolo package. Claude Code carica il file di una sottocartella su richiesta quando legge lì, e la documentazione dice che tipicamente l'owner di ogni directory mantiene il proprio file. Gli engineer che non hanno mai installato il plugin non ne sono toccati: la riga scatta solo quando una skill chiede dove salvare.
Poi lascia che sia la piattaforma a far rispettare l'ownership. Una riga CODEOWNERS per cartella di squad, e ogni review di spec arriva alle persone che dovranno viverci insieme. Un'avvertenza: l'override è un prompt, non un'impostazione. Controlla la prima spec dopo ogni rilascio del plugin.
Regola 2: personale contro condiviso
Regola 2: non ogni piano è un artefatto di team. La prima persona a chiedere a Superpowers una posizione configurabile (issue 337) l'ha detto meglio: i file di piano possono essere documenti di lavoro personali, non artefatti di progetto.
Il lato personale ha un file fatto apposta. CLAUDE.local.md sta accanto al file condiviso, si carica dopo, e la documentazione ti dice di metterlo tu stesso in git-ignore. Il tuo redirect verso una cartella privata vive lì e nessun altro lo vede. Per la cartella stessa, Git ha un file di ignore che non tocca mai l'albero condiviso: .git/info/exclude è per singolo clone, mai committato, e non richiede una pull request. Il plugin stesso lo fa già per il proprio spazio di scratch: dalla versione 6.0.3 la sua working directory rilascia un .gitignore contenente * al proprio interno, quindi si auto-ignora senza toccare alcun file tracciato.
Il lato condiviso è tutto ciò che ha superato il gate di review che il brainstorm esegue già: spec scritta, review richiesta, approvata da una seconda persona. Approvata, entra nella cartella della squad. Non approvata, resta locale. Entrambe si scrivono su un branch, mai su main. Due righe nel CLAUDE.md condiviso bastano: trattare le spec e i piani come l'inizio di una feature, e creare il worktree prima di scriverle.
Un limite: un piano git-ignorato non viaggia. I maintainer di Okama hanno provato prima a ignorare la cartella e sono tornati indietro, perché i piani smettevano di sincronizzarsi tra macchine e agenti. Personale significa personale.
Regola 3: un ciclo di vita, come le ADR
Regola 3: una spec ha uno stato, e una spec morta lo dice. L'idea ha 15 anni. Michael Nygard, nel 2011, ha proposto di mantenere le architecture decision record (ADR) nel repository, un file numerato ciascuna. Una decisione è proposta, poi accettata. Quando un record successivo la cambia, quella vecchia viene marcata deprecated o superseded con un riferimento al suo sostituto. Se una decisione viene invertita, il vecchio record resta ma viene marcato superseded.
Applicato alle spec, ogni spec condivisa si apre con un header di cinque righe che l'agente legge già:
| Campo | Scopo |
|---|---|
| status | proposed, accepted, superseded |
| superseded-by | la spec sostitutiva |
| owner | la squad |
| touches | i path su cui la spec fa affermazioni |
| review date | quando è stata controllata l'ultima volta |
Non modificare mai una spec accepted trasformandola in una decisione diversa. Scrivine la prossima, fai puntare quella indietro, e la storia resta onesta. Un'eccezione, dichiarata nel playbook di Anthropic: quando l'implementazione si allontana dal piano, aggiorna il piano nello stesso commit. Il piano viaggia con il diff che l'ha rotto, e un hook può farlo rispettare.
Spec Kit nomina tre modi in cui una spec può vivere. Flow-forward: una nuova cartella per feature, le vecchie tenute come storia. Living spec: la spec è il contratto e il resto si rigenera. Flow-back: la build rimodella la spec. La loro regola è non lasciare un cambiamento nei task o nel codice se la spec dice ancora qualcosa di diverso. Questo è scegliere spec-anchored di proposito.
Il limite: lo status è metadata che imposta un umano. L'agente non marcherà la propria spec come superseded a meno che il tuo CLAUDE.md non glielo dica, e anche allora la review deve accorgersene.
Regola 4: un drift gate in CI
Regola 4: una spec che mente sull'albero fa fallire la build. Il paper che ha nominato il problema, pubblicato a giugno, lo chiama silent spec-code drift: il codice evolve, la specifica no, e la divergenza resta invisibile finché non diventa costosa da riparare. La sua risposta è un drift gate, una condizione bloccante per il merge.
Il controllo è più piccolo di quanto sembri. Per ogni spec il cui header dice accepted, estrai i path che nomina, tra backtick o nella riga touches, e verifica che ognuno esista. Path mancante, build fallita, con il nome della spec nel log. I file superseded e proposed vengono saltati: solo le spec accepted fanno affermazioni sull'albero, quindi solo le spec accepted vengono controllate. TrueFoundry lo descrive come un diff programmato piuttosto che archeologia post-incidente: una spec è impalcatura, e un cambiamento di spec è un cambiamento di policy.
Le persone eseguono già la versione manuale. Un commentatore fa confrontare a Claude i file di spec con la codebase e apre ticket per ciò che manca. Lo script fa la stessa cosa su ogni pull request, gratis.
La seconda protezione è quella che Okama ha adottato: escludere la cartella dalla build dei docs. Una riga nella configurazione di Sphinx mantiene i file in Git ma fuori dall'HTML.
Il limite: un controllo dei path individua i file eliminati, non il comportamento cambiato. Una spec può nominare ogni file esistente e descrivere comunque un'API che non c'è più. È lì che entrano in gioco la review e la regola dello stesso commit.
Regola 5: un budget di dimensione, e il costo
Regola 5: la maggior parte del lavoro non merita una spec. Le prove sull'overhead dello spec-driven sono coerenti:
| Esperimento | Risultato |
|---|---|
| Marmelab, Spec Kit su una feature che mostra la data corrente | 8 file, 1.300 righe di testo di specifica |
| Bake-off OpenSpec, stessi requisiti con un tool di spec contro Claude Code da solo | 50% più codice, 50% più complessità ciclomatica, il doppio del tempo, tre volte il costo |
| Un team che ha eseguito spec-driven development per mesi | 2-3 volte i token, circa il doppio del tempo, grande costo di coordinamento per cambiamenti che non lo richiedevano; nessuna prova che il codice sia migliorato |
Il bake-off è un esperimento, non un benchmark, e il suo autore lo dice. Ma la direzione tiene. Quindi la regola: scrivi una spec quando il lavoro attraversa il confine di una squad o verrà letto di nuovo entro 90 giorni. Tutto il resto è un prompt.
Superpowers già smista ogni richiesta in tre percorsi: spike, bounded, architectural. Solo il percorso architectural scrive una spec. Mantieni il percorso bounded bounded, e mantieni la spec vicino alle 300 righe. I praticanti aggiungono due righe: non fare spec troppo grandi, e leggi le spec generate.
Il limite vale in entrambe le direzioni. Lo stesso bake-off ha trovato tre gap che la run semplice non ha colto. La spec compra copertura, non velocità. Paga per essa dove la copertura conta.
Verdetto: committa, poi governa
Torniamo alle tre domande del lead. Cosa versioniamo: spec e piani approvati, su un branch, nella cartella della squad. Drift: un header di status e un gate in CI. Governance: owner e una regola di dimensione.
Cinque regole, e nessuna di esse è imposta da un tool oggi. La issue sull'override è aperta. La issue sul branch main è aperta. La pull request che riordinava l'istruzione è stata chiusa senza merge. Il team che si è bruciato ha mantenuto la pratica: 8 piani e 6 spec, committati, esclusi dalla build dei docs.
L'obiezione di Böckeler resta valida. Con un header di status e un budget di dimensione, leggi solo le spec accepted, e meno di esse. Quello che ottieni in cambio è ciò che il playbook di Anthropic chiama audit trail: chi ha chiesto cosa, cosa ha prodotto l'agente, e chi ha approvato.
Questo è processo, non tooling: un file CLAUDE.md, un file CODEOWNERS, un header e uno script di quindici righe. E se il team non revisionerà una richiesta CODEOWNERS, non revisionerà nemmeno una spec. In quel caso, il .gitignore era la scelta onesta.
AIDive