Mantenere allineati specifiche, test e codice nello sviluppo di AI

Impedisci agli agenti AI di allontanarsi dalle specifiche, dai test e dal codice.

Indice

Gli agenti di coding AI rilasciano funzionalità rapidamente, ma specifiche, test e codice tendono a divergere silenziosamente. Questa guida illustra un modello di tracciabilità, il mapping da specifiche a test e da specifiche a codice, e i controlli CI che individuano queste divergenze prima del merge.

Una specifica che nessuno verifica nuovamente rispetto al sistema in esecuzione è peggiore di nessuna specifica, perché crea una falsa sicurezza. I revisori si fidano del documento invece della diff, e un agente AI a cui viene chiesto di “seguire lo schema esistente” seguirà con piacere ciò che il codice fa effettivamente, anche quando ciò contraddice il requisito che dovrebbe soddisfare.

La soluzione non è più documentazione. È un piccolo, eseguibile collegamento tra quattro elementi che esistono già nella maggior parte dei repository: il requisito, la decisione di progettazione dietro di esso, i test che lo dimostrano e i commit o le pull request che lo hanno modificato.

collegamenti di tracciabilità che connettono specifiche, test e codice

Una volta che questo collegamento esiste come dati piuttosto che come comprensione condivisa, puoi interrogarlo. Puoi chiedere quali requisiti non hanno copertura di test, quali test non mappano più a nessun requisito e quali file sono cambiati in una pull request senza un ID requisito corrispondente. Questa interrogazione è il deliverable effettivo di questo articolo, e il resto del post illustra come costruirla con strumenti che probabilmente già utilizzi.

Il problema della divergenza: perché specifiche, test e codice escono di sincronia

La divergenza appare in quattro forme riconoscibili, e i team assistiti dall’AI tendono a incontrare tutte e quattro più rapidamente dei team che scrivono ogni riga manualmente.

  • La specifica cambia, il codice no. Un requisito viene chiarito in una conversazione di follow-up o in una discussione nei commenti, ma nessuno rigenera o modifica l’implementazione per adattarlo.
  • Il codice cambia, la specifica no. Un agente o uno sviluppatore corregge un bug o rifattorizza un modulo, e la specifica continua a descrivere il vecchio comportamento come se fosse ancora attuale.
  • I test coprono l’implementazione, non l’intento. I test unitari affermano ciò che il codice fa attualmente, il che è circolare: passano per costruzione anche quando il codice soddisfa il requisito sbagliato.
  • Le pull request non fanno riferimento ai requisiti. I revisori approvano una diff sulla base del fatto che “sembra ragionevole” perché non c’è un’affermazione esplicita contro cui verificarla.

Le recenti ricerche sui processi nei framework di sviluppo AI identificano la deriva delle specifiche come un rischio ricorrente proprio perché gli agenti rigenerano il codice rapidamente e ripetutamente, e ogni rigenerazione è una nuova opportunità per far divergere ulteriormente specifica e implementazione. Il dibattito sullo Sviluppo Guidato dalle Specifiche vs Vibe Coding è in realtà un argomento su questa stessa modalità di fallimento: una specifica che nessuno fa rispettare degenera nella stessa divergenza che si ottiene senza di essa, solo con cerimonie aggiuntive.

I flussi di lavoro moderni in stile spec-kit inquadrano sempre più questo problema come degradazione delle specifiche: la specifica continua a sembrare autorevole mentre perde silenziosamente la sua connessione con ciò che il sistema fa realmente. La definizione fondamentale dello sviluppo guidato dalle specifiche tratta la specifica come la fonte di verità, ma una fonte di verità rimane tale solo se qualcosa continua a verificarla rispetto alla realtà.

Un modello di tracciabilità per lo sviluppo assistito dall’AI

Un modello di tracciabilità funzionante ha bisogno di sei identificatori che collegano un requisito aziendale fino alle righe di codice e alla pull request che l’ha implementato. La maggior parte dei team ne ha già tre o quattro; quelli mancanti sono solitamente l’ID della decisione di progettazione e il collegamento esplicito inverso dai test e dai commit.

Identificatore Si trova in Esempio
ID Requisito requirements.md o strumento di specifica REQ-014
ID Decisione di progettazione ADR / registro delle decisioni ADR-0032
ID Attività scomposizione delle attività o tracker delle issue TASK-014-3
ID Test file di test o nome del test test_req_014_password_reset
Link Commit / PR cronologia Git PR #482
File modificati diff Git auth/reset.go, auth/reset_test.go

Le relazioni tra questi identificatori formano un grafico piuttosto che una linea retta, perché un requisito può generare diverse attività, e una singola pull request può toccare diversi requisiti contemporaneamente.

graph TD REQ["Requisito
REQ-014"] --> ADR["Decisione di Progettazione
ADR-0032"] ADR --> TASK["Attività
TASK-014-3"] TASK --> CODE["Modifica Codice
auth/reset.go"] TASK --> TEST["Test
test_req_014_password_reset"] CODE --> PR["Pull Request
#482"] TEST --> PR PR --> COMMIT["Cronologia Commit"]

Memorizzare questo grafico come dati strutturati, non come prosa, è ciò che ti permette di interrogarlo successivamente. L’ecosistema Spec Kit di GitHub si è mosso esattamente in questa direzione: estensioni come spec-kit-trace scansionano i token REQ-XXX incorporati nei file di specifica e nei file di test e generano una matrice deterministica da quella corrispondenza di testo letterale, evitando deliberatamente il guessing basato su nomi fuzzy che produce falsi positivi silenziosi.

Mapping da Specifica a Test: Trasformare i Criteri di Accettazione in Casi di Test

Ogni criterio di accettazione in una specifica è, per costruzione, un’affermazione comportamentale: dato questo stato, quando l’attore fa questo, allora il sistema dovrebbe rispondere in quel modo. Questa è già la forma di un caso di test, ed è per questo che i flussi di lavoro SDD più robusti generano test dagli stessi criteri di accettazione che generano il codice, invece di chiedere all’agente che genera il codice di inventare anche i propri test a posteriori.

Un formato ampiamente utilizzato per scrivere questi criteri è EARS (Easy Approach to Requirements Syntax), che forza ogni requisito in un pattern inequivocabile e testabile come “Quando <trigger>, il sistema deve <response>.” Questa struttura si mappa pulitamente su quattro categorie di test che ogni requisito dovrebbe avere:

  • Test positivi — il percorso felice descritto esplicitamente dal requisito.
  • Test negativi — input o stati che il requisito dice devono essere rifiutati.
  • Test di confine — i bordi di intervalli, limiti e soglie menzionati nei criteri di accettazione.
  • Test di migrazione — comportamento per dati o stati che precedono il requisito, in modo che un vecchio record non bypassi silenziosamente una nuova regola.
Tipo di requisito Categoria di test da aggiungere Errore comune
“Il sistema deve rifiutare X” Negativo Viene testato solo il percorso di accettazione
“Il limite è N elementi” Confine N-1, N e N+1 non sono tutti coperti
“Il nuovo campo sostituisce il vecchio campo” Migrazione I vecchi record senza il nuovo campo crashano silenziosamente
“Entro 60 secondi” Confine + timing Il test afferma la logica, non il budget di tempo effettivo

I test unitari scritti in questo modo rimangono importanti come livello veloce ed economico della piramide; i pattern pratici per strutturarli sono trattati nella guida ai test unitari in Go e nella guida ai test unitari in Python. Ciò che la tracciabilità aggiunge è un token di requisito letterale e stabile incorporato nel nome del test o in un commento del test, in modo che un’interrogazione successiva possa dimostrare — non assumere — che REQ-014 ha copertura.

Mapping da Specifica a Codice: Dai Piani di Progettazione a una Tabella di Tracciabilità

Il mapping da specifica a test prova il comportamento; il mapping da specifica a codice prova l’ambito. Risponde a una domanda diversa: quali file dovevano effettivamente cambiare per questo requisito, e la diff è rimasta entro quel confine o ha traboccato in moduli non correlati?

Un piano di progettazione che elenca i file interessati in anticipo — anche una lista approssimativa — ti dà qualcosa contro cui diffare la pull request reale in seguito. I commenti nel codice dovrebbero fare riferimento a un ID requisito solo quando questo aggiunge informazioni che un revisore non può ottenere dalla specifica stessa; un commento che ripete testualmente il testo del requisito è rumore, ma // enforce REQ-014 boundary: max 5 reset attempts per hour si guadagna il suo posto perché il numero è altrimenti invisibile nella diff.

Una tabella di tracciabilità generata trasforma questo in qualcosa di revisionabile in secondi piuttosto che in qualcosa che un revisore deve ricostruire leggendo entrambi i documenti affiancati:

Requisito Decisione di progettazione File modificati Test Stato
REQ-014 ADR-0032 auth/reset.go, auth/reset_test.go test_req_014_* (4) Coperto
REQ-015 ADR-0032 auth/reset.go nessuno Lacuna
REQ-016 auth/notify.go test_notify_basic Link specifica orfano

Questa singola tabella mette in evidenza due dei pattern di fallimento più comuni a colpo d’occhio: REQ-015 ha modificato il codice con zero test corrispondenti, e il test associato a REQ-016 non fa riferimento a un ID requisito, il che significa che o la specifica manca o il test è stato classificato erroneamente.

Il flusso di lavoro delle Pull Request: Revisionare Specifiche, Codice e Diff dei Test Insieme

Una pull request costruita attorno alla tracciabilità revisiona tre diff affiancati invece di uno: cosa è cambiato nella specifica, cosa è cambiato nel codice e cosa è cambiato nei test. La domanda di revisione smette di essere “sembra corretto?” e diventa molto più specifica: “quale requisito soddisfa questa modifica, e le prove lo dimostrano?”

sequenceDiagram participant Dev as Sviluppatore o Agente participant PR as Pull Request participant CI as Pipeline CI participant Rev as Revisore Dev->>PR: Apri PR con diff specifica + diff codice + diff test PR->>CI: Attiva controlli di tracciabilità CI->>CI: Verifica presenza ID REQ nella descrizione PR CI->>CI: Esegui controllo copertura specifica-test CI->>CI: Esegui controllo ambito file specifica-codice CI-->>PR: Pubblica report di tracciabilità come commento PR Rev->>PR: Revisiona rispetto a "quale requisito soddisfa?" Rev->>PR: Approva o richiede modifiche

Una breve lista di controllo concreta per i revisori funziona meglio qui che una lunga, perché i revisori saltano le liste lunghe sotto pressione delle scadenze:

  1. La descrizione della PR nomina l’ID/i requisito/i che soddisfa?
  2. Ogni file modificato appare nell’elenco dei file interessati del piano di progettazione, o l’ambito extra è spiegato?
  3. Almeno un test nuovo o esistente fa riferimento a ogni ID requisito toccato da questa PR?
  4. Se la specifica è cambiata, il codice e i test sono cambiati nella stessa PR, o c’è un follow-up tracciato?

Automatizzare la tracciabilità in CI

La revisione manuale individua la divergenza solo quando i revisori ricordano di cercarla, ed è per questo che i controlli sopra descritti appartengono al CI piuttosto che in una pagina wiki che nessuno rilegge. Gli stessi pattern del cheat sheet di GitHub Actions che già utilizzi per i job di build e test si applicano direttamente qui — i controlli di tracciabilità sono solo un altro job nella stessa pipeline.

Idee pratiche di automazione, approssimativamente in ordine di sforzo:

  • Controlli CI per i file di specifica — fallisci la build se un file di specifica è stato modificato senza una corrispondente modifica di codice o test nella stessa PR, o viceversa.
  • Richiedi ID requisito nei titoli o nelle descrizioni delle PR — un controllo regex leggero (REQ-\d+) blocca i merge che non nominano cosa implementano.
  • Riepiloghi di tracciabilità generati dall’agente — fai produrre all’agente un breve riepilogo di quali requisiti una PR tocca, per una conferma umana piuttosto che scriverlo da zero.
  • Copertura dei test per criterio di accettazione, non solo per riga — la copertura delle righe ti dice che il codice è stato eseguito; la copertura dei requisiti ti dice che un’affermazione è stata verificata.
  • Avvisi di specifiche obsolete — segna le specifiche che non sono state toccate in N commit che toccano i loro file collegati, poiché le specifiche a lungo silenziose sono quelle più probabili a essere degradate silenziosamente.

Le estensioni costruite sopra lo Spec Kit di GitHub implementano già meccanicamente diverse di queste: una scansiona i token letterali REQ-XXX attraverso i file di specifica e test per costruire una matrice e segnare i test orfani, e un pacchetto più rigoroso orientato al Modello V va oltre, generando una specifica di test abbinata per ogni specifica di sviluppo e producendo matrici di tracciabilità multiple per team che lavorano sotto framework regolatori come IEC 62304 o ISO 26262. Non hai bisogno di quel livello di cerimonia per la maggior parte dei progetti, ma l’idea sottostante — una matrice generata da script e deterministica piuttosto che un foglio di calcolo mantenuto a mano — scala verso il basso altrettanto bene quanto scala verso l’alto.

Usare gli agenti AI per la tracciabilità, non come oracolo

Gli agenti AI sono ben adatti alle parti meccaniche della tracciabilità e poco adatti a essere il giudice finale se un requisito è stato effettivamente soddisfatto. Tre task si adattano direttamente ai punti di forza di un agente:

  • Confronta specifica e diff — chiedi all’agente di elencare ogni requisito menzionato nei file di specifica toccati da una PR, e ogni uno per cui non ha trovato codice corrispondente.
  • Trova requisiti non coperti — chiedi all’agente di scansionare la suite di test per i token di requisito e riportare quali requisiti nella specifica non ne hanno.
  • Rileva codice non descritto dalla specifica — chiedi all’agente di segnalare file o funzioni modificati che toccano moduli portatori di requisiti ma non corrispondono a nessun ID requisito nella diff.

La modalità di fallimento da guardia è fidarsi del riepilogo dell’agente come verità fondamentale invece che come punto di partenza per un revisore. Un agente può fraintendere un commento, perdere un token di requisito diviso tra due file, o dichiarare con sicurezza la copertura per un test che esercita il percorso del codice solo superficialmente. Tratta ogni report di tracciabilità generato dall’agente come tratteresti il passaggio di un revisore junior: utile, veloce e ancora soggetto a un secondo controllo prima che blocchi un merge. Questa è la stessa cautela che si applica ai registri delle decisioni per lo sviluppo guidato dall’AI — il registro rimane affidabile solo se qualcosa di diverso dall’agente che l’ha scritto alla fine lo verifica.

Un modello minimo di tracciabilità che puoi copiare

Non hai bisogno di un framework pesante per iniziare. Un modello di cinque file, verificato nel repository accanto al codice che descrive, copre l’essenziale:

docs/
  requirements.md     # ID REQ con criteri di accettazione stile EARS
  design.md           # ID ADR, file interessati, decisioni architetturali
  tasks.md            # ID TASK mappati a uno o più ID REQ
  tests.md            # quali file/funzioni di test fanno riferimento a quali ID REQ
  traceability.md     # tabella generata: REQ -> ADR -> TASK -> file -> test -> PR

requirements.md, design.md e tasks.md sono scritti o modificati da umani e agenti insieme, nello stesso modo in cui il flusso di lavoro di sviluppo guidato dalle specifiche descrive già. tests.md e traceability.md dovrebbero essere generati, non mantenuti a mano, anche se il generatore è uno script breve che cerca solo REQ-\d+ attraverso la directory dei test e i file di specifica — le tabelle di tracciabilità mantenute a mano sono esse stesse una forma di rischio di divergenza, perché nessuno aggiorna un foglio di calcolo sotto pressione delle scadenze.

Conclusione

Lo sviluppo guidato dalle specifiche non è finito nel momento in cui il codice esce da un agente; è utile solo quando codice, test e specifiche si mantengono onesti nel tempo, attraverso PR, rifattorizzazioni e modifiche ai requisiti che arrivano mesi dopo. Un modello di tracciabilità costruito da sei identificatori semplici, applicato da un pugno di controlli CI e revisionato con una breve lista di controllo PR ti dà la maggior parte del beneficio senza il sovraccarico di un framework di conformità completo. Inizia con il modello minimo, collega prima il controllo CI più economico — ID requisito nelle descrizioni delle PR — e aggiungi la tabella di tracciabilità e gli avvisi di specifiche obsolete una volta che questa abitudine si radica.

La tracciabilità è un pezzo di una disciplina più ampia di testing e documentazione trattata nel cluster Architettura App in Produzione, e si colloca accanto alle domande di strumentazione esplorate nel cluster Strumenti per sviluppatori AI per i team che scelgono quali flussi di lavoro degli agenti standardizzare.

Iscriviti

Ricevi nuovi articoli su sistemi, infrastruttura e ingegneria AI.