La code review che dimostra ogni bug segnalato

La code review che dimostra ogni bug segnalato

Chiedi a un'IA di rivedere la tua PR e ti restituisce un checklist ordinato: injection controllata, secret controllati, auth controllata, tutto a posto. Sembra diligenza. Se abbia davvero trovato qualcosa è una proprietà diversa — ed è proprio il checklist a nascondere la lacuna. Gestiamo una directory che testa le skill di Claude sul campo, e quando abbiamo puntato il nostro benchmark su una skill di review che avevamo già valutato promossa, è passata accanto a un secret hardcoded che invece il baseline senza guida aveva beccato. La lista non aveva una voce per quel punto, quindi il reviewer non ci ha mai guardato.

Questa lacuna è il motivo per cui esiste review-discipline — ed è il motivo per cui esiste nella sua seconda versione. È gratis e con licenza MIT: github.com/Skillproofdev/review-discipline. Ogni finding che riporta deve indicare un input concreto che raggiunge il codice e produce un esito sbagliato — altrimenti viene declassato a [suspicion], mai presentato come fatto. Sul nostro bench a bug seminati cattura 18,5 su 21 bug piantati con zero falsi positivi e un failure path dimostrato sul ~100% dei finding.

Il vuoto: ogni skill di review è un checklist, e i checklist creano tunnel vision

Prima di scrivere una riga abbiamo passato in rassegna 321 skill di review indicizzate più il campo standalone — incluso il plugin ufficiale di code review di Anthropic. Tre meccanismi non comparivano in nessuna di loro come regole vincolanti a singolo agente. Tutte e tre riconducono allo stesso fallimento che abbiamo visto succedere nel nostro bench.

Un checklist dice al reviewer cosa cercare. Ma è anche una lista di cosa non guardare. Quando le categorie non includono il bug, il bug sopravvive — e per di più la review torna verde lo stesso, perché ogni casella esistente è stata spuntata. I due modi in cui una review fallisce sono riportare come fatto delle ipotesi non dimostrate (rumore) e saltare in silenzio un bug reale perché è piccolo o perché uno più spaventoso ha assorbito tutta l'attenzione (copertura mancante). Un checklist è strutturalmente bravo a produrre entrambi.

Il plugin di Anthropic combatte la metà "rumore" con agenti scorer paralleli che votano un numero di confidenza. È un meccanismo reale, ma richiede più agenti e non affronta affatto la metà "copertura". Nessuno mette in campo la cosa che ribalta la forma del checklist: cacciare tutto prima di consultare qualsiasi lista di categorie, dimostrare o etichettare ogni finding solo dopo, e scartare solo ciò che puoi davvero confutare — in un solo agente, in un solo file installabile.

Otto regole, tre delle quali nessun altro le applica

La skill è un insieme di regole vincolanti (SKILL.md completo). Le parti familiari ci sono tutte: severità P0–P3 con definizioni reali invece che sensazioni, disciplina di scope sul diff (rivedi il cambiamento, non l'intera codebase), segnalazioni di test mancanti legate al comportamento modificato, e zero elogi di riempimento. Le parti che nessun altro applica:

  1. Niente failure path dimostrato, niente finding. Ogni finding deve indicare un input o uno stato concreto che raggiunge il codice segnalato e produce un esito sbagliato. Non riesci a costruirne uno? Esce come [suspicion], classificato sotto ogni finding dimostrato — mai come fatto. Un'affermazione non dimostrata presentata come bug è l'unico output vietato dalla skill.
  2. Due passate, caccia libera per prima. Leggi il cambiamento come un attaccante senza nessuna lista di categorie in mano e annota ogni anomalia — nessuna soglia minima di severità, anche qualcosa che sembra solo leggermente strano va scritto. Solo dopo passa il checklist standard (secret, injection, boundary, aritmetica, concorrenza…) per cercare quello che la caccia libera si è persa. Ogni concorrente è il checklist; qui gira per secondo, di proposito.
  3. Uccidi il tuo finding prima di segnalarlo. Un tentativo onesto di confutazione per ogni finding — guardie a monte, comportamento intenzionale, copertura test esistente, raggiungibilità — e il report dice cosa è stato verificato. La confutazione è l'unico filtro autorizzato a scartare un finding; "non mi sono preso la briga di dimostrarlo" diventa un [suspicion], non uno scarto silenzioso. I finding che muoiono davvero, muoiono in silenzio.

La regola portante è l'ordine: ampiezza prima della profondità. Raccogli ogni anomalia senza soglia minima di severità prima di verificarne anche solo una, così l'approfondimento su un bug non può mai troncare la caccia sugli altri. Sembra ovvio. Ed è esattamente la regola che la nostra prima versione non aveva — il motivo per cui ha perso.

Il benchmark onesto (risultati negativi inclusi)

Protocollo a bug seminati: campioni di codice reali (~200–400 righe ciascuno, TypeScript / Python / JS) con bug documentati di severità nota — logici, di sicurezza, edge-case, di concorrenza — con ground truth fissata prima di ogni run. Nei campioni resta anche codice reale e sano per misurare i falsi positivi. Stessi prompt, stesso modello; l'unica variabile è se l'agente legge prima il SKILL.md. Metodologia completa: skillproof.dev/methodology.

4 campioni, 21 bug seminati, 12 trappole intenzionalmente sane per i falsi positivi. La colonna interessante non è base contro skill — è v1 contro v2, perché è proprio il nostro bench ad aver forzato la ricostruzione.

Metrica Base (senza skill) Skill v1 Skill v2
Bug seminati trovati (su 21) 17,0 (81%) 16,5 (79%) 18,5 (88%)
Catch P0 (sfruttabile / perdita dati) 3/3 3/3 3/3
Catch P1 (comportamento sbagliato, path realistico) 7/7 7/7 7/7
Catch P2 (edge / path aritmetici) 6/7 4/7 7/7
Sonda secret hardcoded trovato trovato trovato
Tasso falsi positivi 5,6% (1 FP) 0% 0%
Finding con failure path dimostrato ~63% ~100% ~100%
Declassamenti [suspicion] (dubbi onesti) 0 3 5
Righe di elogio / riempimento presenti assenti assenti

Leggi la colonna centrale e vedi il fallimento che ha dato il nome a questa skill. v1 ha ottenuto 16,5 — sotto i 17 del baseline senza guida. Aveva già la disciplina del failure path (aveva azzerato i falsi positivi e dimostrato ~100% dei suoi finding), ma era peggiore a trovare bug, perché si era fissata sui P0 spaventosi in un campione e non aveva mai passato le righe silenziose di arrotondamento monetario. Aveva la tunnel vision. Il nostro bench pubblico su una skill che avevamo valutato promossa è quello che l'ha beccato: v1 si è persa due veri P2 — un errore logico in prorate /30 e un troncamento int(amount × 100) — che il baseline aveva colto solo leggendo in modo lineare.

La correzione è stata la regola ampiezza-prima-di-profondità. v2 raccoglie ogni anomalia senza soglia minima di severità prima di verificarne una sola. Risultato: il P2 è passato da 4/7 a un pulito 7/7 (ha persino recuperato uno StopIteration su CSV vuoto che sia base che v1 si erano persi), il recall totale è salito a 18,5 — oltre i 17 del base — e la disciplina ha tenuto: ancora zero falsi positivi, ancora ~100% di path dimostrati, e più dubbi onesti [suspicion] (5 contro 3) invece che meno. L'adjudicazione completa a tre vie è in bench/results/verdict.md.

Un mito che il bench ha smontato, chiaramente: l'ipotesi "il checklist crea tunnel vision sui secret" che aveva motivato l'intero progetto non si è riprodotta nel run seminato — tutti e tre i bracci hanno trovato la sonda del secret hardcoded (S4-B1). La lacuna originale era reale ed è quella che ci ha insegnato la forma del problema; il bench seminato ha solo mostrato che non è il secret in sé dove l'ampiezza paga. Sono gli edge case di arrotondamento monetario. Riportiamo il meccanismo che ha davvero mosso i numeri, non quello che dava una storia d'origine più bella.

Dove v2 ha perso — pubblicato comunque

La nostra metodologia richiede di mettere le perdite accanto alle vittorie. v2 è il braccio migliore su tutto ciò che blocca un merge, ma non è un superset stretto di v1, e non faremo finta del contrario.

Nella caccia all'ampiezza esaustiva, v2 ha smesso di scavare in una funzione (_parse_tags) ed è passata accanto a un sottile sospetto di deep-nesting con literal_eval (S2-B5) che invece la passata in profondità di v1 aveva colto in modo unico. Quindi sull'asse P3 / fuori-checklist, v2 è effettivamente regredita — dal 2,5/4 di v1 a 1,5/4. Nel complesso è uno scambio buono (+2 medi per −1 P3 sottile), ma è una regressione reale su quell'asse, non un dominio pulito. Il reviewer ideale è l'ampiezza di v2 più la voglia di v1 di scavare un livello in più sul codice che sembra tranquillo — e preferiamo dirtelo piuttosto che arrotondarlo.

C'è anche un bug che nessun braccio ha trovato: un pareggio strict-< sulla scadenza di un coupon (S1-B6), mancato da base, v1 e v2 allo stesso modo. La skill riduce le lacune; non rende Claude infallibile.

SKILL SKILLPROOF

review-discipline è gratis, MIT, e tutto sta in un file. Leggi le otto regole, l'harness a bug seminati e il verdetto completo a tre vie — poi provala sui tuoi diff.

Scarica review-discipline su GitHub

Installazione

git clone https://github.com/Skillproofdev/review-discipline ~/.claude/skills/review-discipline

Riavvia Claude Code. Un solo comando — il repo è la skill. Si attiva su "review this PR/diff", "check this before merge", "find bugs in" e sui controlli pre-merge — e resta fuori dai piedi quando scrivi feature, fai linting di solo stile o revisioni di prosa. Fa parte della nostra serie discipline: token-discipline taglia quanto costa un agente, research-discipline taglia quanto sbaglia sui fatti, e questa taglia quanto una review si perde.

STARTER PACK GRATUITO

Vuoi le nostre skill con il punteggio più alto più la checklist di installazione che usiamo prima di ogni test? Ti mandiamo lo starter pack gratuito via email.

Ottieni lo starter pack gratuito

FAQ

In cosa è diverso dal plugin di code review di Anthropic? Il plugin filtra i falsi positivi facendo votare a agenti scorer paralleli un numero di confidenza — efficace, ma richiede più agenti e affronta solo il problema del rumore. review-discipline filtra con un failure path dimostrato in un singolo agente, in un solo file installabile, e affronta anche il problema della copertura che il plugin non tocca: la regola caccia-libera-prima-del-checklist che ha portato il nostro recall P2 da 4/7 a 7/7.

"Dimostrare ogni finding" non rischia di far perdere cose che non si possono dimostrare? No — è per questo che esiste il meccanismo [suspicion]. Un bug reale per cui non riesci a costruire un failure path (serve uno stato a runtime che non vedi, o un sistema esterno) viene comunque segnalato, marcato [suspicion] e classificato sotto i finding confermati, con una riga su cosa manca. Declassare la confidenza è lo strumento; scartare non lo è. Nel bench, v2 ha emesso 5 dubbi onesti di questo tipo invece di ingoiarli.

Rivede l'intera codebase o solo il mio diff? Solo il cambiamento. I finding devono essere causati o attivati da questo diff; i problemi preesistenti finiscono in una breve nota fuori scope, non nella lista classificata. L'unica eccezione è un P0 preesistente — un secret attivo o una vulnerabilità in corso — che viene sempre segnalato in modo prominente. Questa eccezione esiste proprio per via della lacuna della storia d'origine.

18,5/21 basta per saltare la review umana? No. Cattura ogni merge-blocker P0 e P1 nel nostro bench e batte un baseline senza guida sul recall totale con zero falsi positivi — il che ne fa un primo reviewer forte che non timbra mai a occhi chiusi e nomina sempre cosa ha attaccato. Ma si è persa un bug seminato del tutto e ha scambiato un P3 sottile per l'ampiezza, entrambi documentati sopra. Usala per assicurarti che i bug ovvi e quelli aritmetici silenziosi non arrivino a un umano; tieni l'umano per l'ultimo livello di profondità.

★ 9.6/10 × 3

Lo starter pack gratuito

I 3 skill con i nostri punteggi di test più alti, più la checklist di installazione: il setup che metteremmo su una macchina appena formattata. Gratis, via email.

Una email con il pack + un breve digest settimanale con i nuovi risultati dei test. Puoi disiscriverti quando vuoi.