Si è giudicato da solo: PASS
Il controllo di verifica integrato in Claude Code, /verify, ha restituito PASS su una funzionalità che era rotta. È il risultato di un banco di prova di 116 sessioni di Claude Code su un repository vero, dove ogni "fatto" è stato valutato in seguito da test di accettazione che l'agente non aveva mai visto.
Boris Cherny, che ha creato Claude Code, definisce la verifica la cosa più importante che si possa dargli. Il controllo integrato si avvia solo su richiesta dalla versione v2.1.215 di Claude Code: o scrivi /verify, oppure non parte. In questo banco di prova ha detto PASS in 24 run su 24, e uno di quei run aveva rilasciato una funzionalità rotta. Cosa ha effettivamente scovato il bug è spiegato più avanti, insieme al setup che è costato due volte e mezzo di più e non ha cambiato nulla.
Il banco di prova: 116 run, test mai visti
Un "fatto" falso è una sessione che si conclude dichiarando il lavoro terminato mentre un test di accettazione nascosto, o la suite di test del repository stesso, fallisce. Il banco di prova misura quanto spesso questo accade in sei setup di verifica diversi.
Il dubbio nasce dall'issue tracker di Claude Code stesso: la issue #96416, aperta il 2026-09-23, descrive una review che ha elencato 19 problemi, ne ha verificati 5 e ha comunque concluso "accept as is".
| Parametro | Valore |
|---|---|
| Repository | msiemens/tinydb (database di documenti Python), commit 18d73a1 |
| Suite di test del repository | 226 test |
| Richieste di funzionalità | 6, ciascuna con 5 requisiti dichiarati |
| Test di accettazione nascosti | uno per ogni requisito dichiarato, scritto prima di qualsiasi run, mai mostrato all'agente |
| Modelli | Opus 5.5, Sonnet 5, Haiku 4.5 |
| Claude Code | 2.1.283, headless (claude -p), limite di 60 turni |
| Sessioni | 112 run di task + 4 run /verify cross-model = 116 |
| Spesa | $66,29 equivalente API |
I sei setup vanno da Claude Code puro (solo la richiesta) a un modello che controlla il lavoro allo stop:
| Setup | Cosa aggiunge |
|---|---|
| A plain | niente |
| B /verify | il /verify integrato digitato come secondo turno |
| C verify skill | uno skill di progetto scritto secondo il workflow di Anthropic |
| D Stop hook | uno script che blocca lo stop finché la suite è rossa e chiede una prova per ogni requisito |
| E tests first | una regola in CLAUDE.md: un test che fallisce per ogni requisito prima di scrivere codice |
| F Opus verifier | uno Stop hook che esegue /verify con Opus sulla modifica |
Le richieste chiare su una libreria ben testata sono il caso facile. Opus 5.5 puro ha fatto 12 run su 12 corrette, e in 11 di queste ha lanciato da solo la suite di test prima di dire fatto.
Il /verify integrato: PASS, sempre, 2,5x
/verify è lo skill di verifica incluso in Claude Code. Esegue la modifica, legge il diff e scrive un verdetto passo per passo. Dalla v2.1.215 si avvia solo su comando dell'utente, quindi nel banco di prova è stato digitato dopo ogni task come secondo turno.
Ha restituito un verdetto PASS in 24 run su 24 nei tre modelli, inclusa la modifica rotta di Haiku. Su Opus 5.5 non ha cambiato alcun esito e ha costato 2,5 volte tanto:
| Opus 5.5, per task | Plain | Con /verify |
|---|---|---|
| Costo | $0,39 | $0,96 |
| Tempo reale | 75 s | 125 s |
| Esiti cambiati | 0 su 12 |
Va detto che /verify ha trovato un bug reale: in un task di Opus ha segnalato un problema di reuse-after-close già presente nella libreria, non causato dalla modifica che stava controllando. Su un lavoro già corretto, è un secondo parere costoso.
Skill o hook: quella che viene saltata
Uno skill è una procedura in markdown che Claude può aprire quando la giudica rilevante. Il post sul blog di Anthropic sui loop di verifica descrive una ricetta in sei passi: scegli il controllo manuale che fai più spesso, prova prima il /verify integrato, scrivi la procedura in inglese semplice, trasformala in uno skill, poi invocalo su un nuovo task e itera. Lo skill del banco di prova, verify-change, è stato costruito esattamente così e dice a Claude di dimostrare ogni requisito sul codice reale prima di dire fatto.
Uno skill è un suggerimento, ed è Claude a decidere se aprirlo:
| Modello | Sessioni che hanno aperto lo skill |
|---|---|
| Opus 5.5 | 8 su 12 |
| Sonnet 5 | 2 su 6 |
| Haiku 4.5 | 0 su 6 |
| Totale | 10 su 24 |
L'unico "fatto" falso di Sonnet è arrivato da una sessione in cui lo skill non si è mai aperto: si è conclusa con due dei suoi stessi nuovi test falliti.
Uno Stop hook è uno script che Claude Code esegue ogni volta che l'agente tenta di terminare. Può rifiutare lo stop e rimandare indietro l'agente con una motivazione. Lo hook del banco di prova esegue la suite di test, blocca finché è rossa e, al primo stop, chiede una riga di prova per ogni requisito. Si è attivato in ogni sessione. Su Opus è costato il 20% in più, $0,47 contro $0,39 per task (94 s contro 75 s). In questo banco di prova non ha mai incontrato una suite rossa al momento dello stop, quindi non aveva nulla da scovare: uno hook si attiva sempre, ma controlla solo ciò che gli hai detto di controllare.
Il punto cieco: 11 su 11 mancati
Il task che ha fallito chiedeva campi univoci su una tabella: due utenti non possono condividere un'email, e qualsiasi update che lascerebbe due documenti con lo stesso valore univoco deve sollevare DuplicateKeyError.
Haiku 4.5 ha testato lo spostamento di un utente sull'email di un altro utente, ed è stato correttamente rifiutato. Non ha mai testato un update che corrisponde a più documenti e scrive la stessa nuova email su tutti. Quel caso è passato senza errori in 11 sessioni di Haiku su 11, in ogni setup con lo stesso modello: plain, /verify, lo skill, lo Stop hook e tests first.
Il /verify di Haiku stesso ha spuntato il caso che aveva provato e scritto PASS. Il test nascosto ha riportato DID NOT RAISE DuplicateKeyError. Anche Sonnet 5, a cui è stato chiesto di eseguire /verify sulla stessa modifica, ha restituito PASS. Opus e Sonnet hanno entrambi scritto questa funzionalità correttamente da soli, quindi si tratta di un modello su un task, ma un controllo scritto dallo stesso modello ne condivide il punto cieco.
Il controllo esterno: Opus dice FAIL
Lo stesso /verify sulla stessa modifica di Haiku, eseguito da Opus 5.5, ha restituito FAIL in 3 run su 3, nominando ogni volta il caso mancato: un update che corrisponde a più documenti scrive lo stesso valore su tutti senza errore. La cattura è arrivata da un modello diverso, non dall'autore e non dal controllo dell'autore stesso.
Collegato come Stop hook (setup F), Opus controlla il lavoro di Haiku ogni volta che Haiku tenta di terminare. I risultati:
| T6, per run | Haiku + controllore Opus | Opus 5.5 da solo |
|---|---|---|
| Bug corretto / "fatto" falso | corretto in 3 su 3 | 0 "fatto" falsi |
| Turni | limite di 60 turni raggiunto in ogni run | |
| Costo | $1,36 incluso il controllore | $0,76 |
Il controllo esterno funziona. Su questo task è costato più del modello più forte che scrive la funzionalità da solo.
Cosa portare a casa, e cosa costa
Smettete di lasciare che il modello che ha scritto una modifica sia l'unico a controllarla.
| Regola | Perché | Costo su questo banco di prova |
|---|---|---|
| Tenete uno Stop hook per tutto ciò che uno script può controllare | si attiva in ogni sessione | circa il 20% in più su Opus |
| Fate arrivare il controllo vero da fuori l'autore: un modello più forte al gate, o vostri test scritti a partire dalla richiesta | lo stesso modello ha mancato il proprio bug 11 volte su 11 | $1,36 per task per Haiku + controllore Opus |
Su una richiesta chiara con Opus, saltate /verify |
0 esiti cambiati | costo 2,5x, 125 s contro 75 s |
I limiti: una piccola libreria, sei richieste chiare, da una a tre run per cella, sessioni headless, e test nascosti che controllano solo ciò che ogni richiesta dichiara. Su lavori più disordinati, i numeri cambieranno.
AIDive