Negli ultimi due anni qualcosa si è invertito in silenzio, nell’ingegneria del software. Per quasi tutta la storia del settore il codice era l’artefatto e la specifica era l’impalcatura usa e getta che gli stava intorno: un documento scritto una volta, scorso due e abbandonato entro il terzo sprint. Oggi gli agenti AI scrivono una quota crescente del codice, e l’economia si è ribaltata. Il codice è diventato economico da produrre ed economico da rigenerare. Ciò che scarseggia è un enunciato preciso di quello che il codice deve fare. La specifica non è più un’impalcatura. È l’artefatto ingegneristico.
I team che la trattano così ottengono dagli agenti una leva che si capitalizza: affidano lavoro ben definito, verificano il risultato in modo meccanico e integrano con fiducia. I team che non lo fanno ottengono un nuovo tipo di debito tecnico: codice dall’aria plausibile che nessuno aveva chiesto, generato più in fretta di quanto chiunque riesca a revisionarlo. La differenza tra i due non sta nel modello né negli strumenti. Sta nel fatto che la specifica sia un contratto oppure no.
Un prompt non è una specifica
Il fallimento più comune è trattare la casella di chat come una specifica. Un prompt è l’apertura di una conversazione: descrive l’intento in prosa, lascia i casi limite alla buona volontà di chi legge e sparisce in un buffer di scorrimento nell’istante in cui viene inviato. Nessuno può revisionarlo, farne il diff o indicarlo tre settimane dopo, quando il comportamento è contestato. Un agente a cui si dà un prompt fa quello che fa un’impresa a cui si dà una chiacchiera in corridoio: riempie ogni vuoto con le proprie ipotesi, con sicurezza.
Una specifica è un oggetto diverso. Vive nel repository, accanto al codice che governa. È versionata, così si vede che cosa era stato concordato e quando è cambiato. È revisionabile, così un collega può obiettare sul requisito invece che sull’implementazione. Ed è verificabile - la proprietà cruciale - cioè per qualsiasi pezzo di lavoro consegnato esiste un modo meccanico di chiedere: soddisfa la specifica, sì o no? Nel momento in cui quella domanda richiede un giudizio discrezionale, si ha della prosa, non un contratto.
Che cosa rende una specifica un contratto
Quattro ingredienti separano un contratto da un desiderio. Vengono per primi i criteri di accettazione: affermazioni osservabili e binarie sul comportamento. «Veloce» è un desiderio; «p95 sotto i 200ms a 50 richieste al secondo» è un criterio. «Gestisce gli input errati» è un desiderio; «rifiuta i payload malformati con un 422 e un codice di errore leggibile da una macchina» è un criterio. Se non si riesce a decidere superato o non superato dall’esterno dell’implementazione, lo riscriva finché non ci riesce.
Vengono secondi gli esempi svolti, e fanno più lavoro di qualsiasi altra sezione. Coppie concrete di input e output - compresi quelli brutti: la lista vuota, l’invio duplicato, il caso limite del fuso orario, l’utente che incolla un’emoji nel campo dell’importo. Gli esempi sono il punto in cui affiorano le ipotesi nascoste. E sono anche, non per caso, casi di test in attesa di essere trascritti.
Vengono terzi gli invarianti: proprietà che devono valere qualunque strada prenda l’implementazione. I saldi non vanno mai in negativo. Ogni transizione di stato viene registrata. Le cancellazioni sono logiche. Nessuna chiamata al fornitore di pagamento senza una chiave di idempotenza. Gli invarianti sono i guard rail che sopravvivono al refactoring - cosa che conta doppio quando il refactoring lo fa un agente che non era alla riunione in cui la regola è stata spiegata.
Vengono per ultimi i non obiettivi, ed è la parte più trascurata. Il modo di sbagliare di un agente raramente è fare troppo poco: è fare troppo - inventare opzioni di configurazione, aggiungere una cache che nessuno aveva chiesto, «migliorare» il codice vicino. Un breve elenco di ciò che questa modifica non deve toccare e dei problemi che non deve risolvere è il controllo del perimetro più economico che scriverà mai.
Un agente riempie con le proprie ipotesi ogni vuoto della specifica - con sicurezza. Il contratto esiste perché non ci siano vuoti da riempire.
I contratti vanno fatti rispettare
Un contratto che nessuno fa rispettare è decorazione. Il livello che lo impone è ciò che rende lo sviluppo guidato dalle specifiche una pratica ingegneristica invece di un’abitudine documentale, ed è fatto di tre parti. Primo, i test come forma eseguibile del contratto.I criteri di accettazione e gli esempi svolti vengono trascritti in una suite di test prima che l’agente scriva il codice di implementazione. La suite è la specifica compilata in qualcosa che una macchina può verificare; il compito dell’agente è farla passare senza indebolirla. In revisione si presidiano i test stessi: un agente che modifica un’asserzione per farla passare ha rinegoziato il contratto unilateralmente.
Secondo, i confini tipizzati.Schemi, tipi e contratti di API inchiodano ogni interfaccia che il codice dell’agente tocca. Uno schema rigido al confine trasforma un’intera classe di output plausibili ma sbagliati in errori di compilazione e fallimenti di validazione - un riscontro che l’agente riceve in pochi secondi, dentro il ciclo, invece di un riscontro che chi revisiona consegna giorni dopo. Più rigido è il confine, meno spazio c’è perché la spazzatura sicura di sé lo attraversi.
Terzo, cancelli di revisione che confrontano il diff con il contratto.La revisione umana non sparisce: cambia bersaglio. Revisionare l’output di un agente riga per riga alla velocità dell’agente è una partita persa - c’è semplicemente più codice che attenzione. Confrontare il diff con il contratto è invece trattabile: la modifica soddisfa ogni criterio di accettazione, rispetta ogni invariante, resta dentro i non obiettivi? Qualunque cosa nel diff che il contratto non spieghi è la prima domanda della revisione, non un di più.
I tre modi in cui va storta
Specifica vaga, spazzatura sicura di sé.Il team scrive tre punti elenco, l’agente produce ottocento righe e il divario tra intento e comportamento si scopre in produzione. L’indizio sono le conversazioni di revisione che iniziano con «non è questo che intendevo»: una frase che accusa la specifica, non l’agente. Il rimedio è noioso: più esempi, criteri più affilati, scritti prima della generazione e non dopo.
Iper-specificazione, nessuna leva.Il fosso opposto. Se la specifica detta l’implementazione - file per file, funzione per funzione - il codice è stato scritto due volte, una in italiano e una nel linguaggio in cui gira, e l’agente è ridotto a un dattilografo. Si specifichi il comportamento al confine e gli invarianti al suo interno; l’implementazione la si lasci a chi la scrive. Se specificare un’attività richiede più tempo che svolgerla, quell’attività non aveva bisogno di un agente.
Deriva della specifica.Il fallimento più silenzioso. Il contratto diceva una cosa, la produzione è evoluta in un’altra, e dopo tre mesi di piccole rinegoziazioni di passaggio la specifica descrive un sistema che non esiste più. La deriva è inevitabile; la deriva non registrata è una scelta. La regola che la previene costa una frase: i cambi di comportamento atterrano prima come cambi di specifica, nella stessa pull request, oppure non atterrano.
Il flusso di lavoro, dall’inizio alla fine
Nella pratica è un ciclo breve. Scrivere il contratto - criteri, esempi, invarianti, non obiettivi - e farlo revisionare da chi con quel comportamento dovrà convivere: è qui che il disaccordo costa poco. Trascrivere in test le parti verificabili, che devono fallire. Consegnare il contratto all’agente e lasciarlo lavorare contro la suite che fallisce, iterando finché i controlli meccanici - test, tipi, schemi, linter - passano senza modifiche ai controlli stessi. Poi confrontare il diff con il contratto, non con la propria pazienza: criteri soddisfatti, invarianti rispettati, niente fuori dai non obiettivi. Il merge registra il contratto e il suo adempimento in un’unica unità atomica, e l’attività successiva parte da una linea di base onesta.
Il ciclo ha un beneficio di secondo ordine che sorprende i team: i contratti rendono parallelizzabile il lavoro degli agenti. Due agenti su un unico brief vago si scontrano; cinque agenti su cinque contratti con confini tipizzati tra loro si integrano in modo pulito, perché ogni contratto dichiara che cosa il suo pezzo deve fare e dove finisce. La stessa proprietà che rende verificabile una specifica la rende componibile - ed è così che un piccolo team senior supervisiona una quantità di implementazione in parallelo che cinque anni fa avrebbe richiesto un intero reparto.
Un’ultima regola meccanica tiene onesto il ciclo: i controlli girano in CI, non sulla parola dell’agente. Un agente che dichiara «tutti i test passano» formula un’affermazione; una pipeline verde su una suite di test non modificata è un fatto. Il contratto, i suoi test e la pipeline formano insieme un arbitro neutrale a cui non interessa se il codice l’ha scritto una persona in una brutta giornata o un modello in una giornata sicura di sé - ed è esattamente quell’indifferenza a rendere affidabile il risultato.
I team che adottano questa pratica scoprono che il collo di bottiglia si è spostato. La competenza scarsa non è più produrre codice: è decidere con precisione che cosa il codice deve fare ed esprimerlo in modo verificabile. È sempre stata la parte difficile del software; gli agenti non hanno creato il problema, hanno tolto il posto in cui si nascondeva.
Quando conviene - e quando è solo sovraccarico
Lo sviluppo guidato dalle specifiche non è gratis, e fingere il contrario ne uccide l’adozione. Il contratto si ripaga quando il lavoro ha conseguenze e il costo di sbagliare è reale: sistemi che muovono denaro, che toccano dati dei clienti, che stanno sui confini tra team, o che saranno mantenuti da persone - e da agenti - che non erano presenti quando le decisioni sono state prese. Si ripaga più in fretta proprio dove l’output di un agente è più difficile da revisionare a occhio.
È invece sovraccarico per gli spike, i prototipi e gli script usa e getta - codice il cui unico scopo è essere buttato via una volta che ha risposto a una domanda. Si scriva una frase di intento, si lasci correre l’agente, si tenga ciò che si è imparato e si cancelli il codice. La disciplina sta nel sapere in quale modalità ci si trova, e nell’essere onesti nel momento in cui un prototipo comincia in silenzio a diventare un sistema. È quel momento - non la riscrittura sei mesi dopo - il momento in cui il contratto va scritto.
Il settore ha passato due decenni a imparare che i test non sono burocrazia, ma la cosa che permette di andare veloci senza rompere ciò che conta. Le specifiche stanno facendo ora lo stesso percorso, per la stessa ragione. Quando il costo marginale di scrivere codice tende a zero, il valore si concentra nell’enunciato di ciò che il codice deve fare - e i team che scrivono quell’enunciato come un contratto sono quelli per cui gli agenti si capitalizzano davvero.