Salta al contenuto principale

Debugging skill: scientific method e checkpoint pattern in Claude Code

Cluster 3 della serie Claude Code Workflow. La skill debugging forza un loop ipotesi-test-misura con checkpoint fra cicli, per bug che non si risolvono al primo tentativo. Pattern, esempi reali del portfolio, anti-pattern.

Cosa ne pensi di questo articolo?

Debugging skill: scientific method e checkpoint pattern in Claude Code
Claude Code WorkflowFoto:PixabayPexels

In Breve

Cluster 3 della serie Claude Code Workflow. La skill debugging forza un loop ipotesi-test-misura con checkpoint fra cicli, per bug che non si risolvono al primo tentativo. Pattern, esempi reali del portfolio, anti-pattern.

Risposta diretta

La skill di Superpowers struttura l'investigazione dei bug difficili attraverso un processo scientifico, formulando ipotesi, testandole e misurandone gli effetti, raffinando la causa fino a raggiungere il fix deterministico. Ciò evita tentativi disordinati e sprecare tempo, consentendo di risolvere bug complessi in tempi più rapidi.

I bug facili si risolvono al primo tentativo, senza pensarci troppo. Sono il novanta percento dei bug. Il restante dieci percento - quelli che ti tengono sveglio di notte, quelli che pensavi di aver risolto e tornano, quelli che sembrano random ma non lo sono - richiedono un processo. La skill debugging di Superpowers esiste per dare struttura a quella minoranza che divora ore se affrontata a istinto.

Disclaimer di indipendenza: non sono affiliato a obra né ad Anthropic. Tutto quanto segue è esperienza diretta sulla skill debugging applicata a una sessantina di bug medium-to-hard sul mio portfolio brownfield in circa un anno.

Perché serve un loop scientifico per i bug difficili

Un bug facile è una catena causale corta: clicca il bottone X, vedi l'errore Y, il fix è in un punto evidente. Un bug difficile ha tre caratteristiche almeno:

  1. La causa è lontana dal sintomo (errore nel modulo A, ma origine in B).
  2. La riproducibilità è imperfetta (succede il 30% delle volte, su specifiche condizioni).
  3. Più ipotesi sono plausibili (almeno tre cause potrebbero spiegare ciò che vedi).

Senza un processo, l'investigazione di un bug difficile diventa una serie di tentativi disordinati: cambi una cosa, ricarichi, vedi se va meglio, cambi un'altra cosa, ti confondi su quale modifica abbia avuto effetto, perdi un'ora e torni al punto di partenza con il sospetto che forse l'errore sia altrove. È il modo più diffuso di sprecare un pomeriggio di lavoro.

Il metodo scientifico applicato al debug è ovvio (formula ipotesi, testa, misura, raffina), ma sotto pressione viene saltato. La skill debugging impone il processo anche quando l'istinto vorrebbe saltare i passaggi.

Cosa fa la skill, ciclo per ciclo

Una sessione di debug con la skill attiva segue una struttura ricorrente, ripetuta finché il bug non è risolto:

  1. Stato corrente: cosa sappiamo, cosa non sappiamo, cosa abbiamo escluso.
  2. Ipotesi: una sola, esplicita. "Il bug X dipende da Y." Niente "potrebbe essere A o B o C" - quelli sono ipotesi multiple e vanno testate separatamente.
  3. Test che la verifica: l'esperimento minimo che permette di confermare o rigettare l'ipotesi. Idealmente un test deterministico che riproduca il bug, ma a volte è un log strategico o una richiesta cURL specifica.
  4. Misurazione: cosa ti aspetti di vedere se l'ipotesi è corretta, cosa ti aspetti di vedere se è sbagliata. Importante: questa frase va scritta prima di eseguire il test.
  5. Esecuzione e risultato: esegui, registra cosa hai osservato, confronta con la misurazione attesa.
  6. Checkpoint: aggiorna stato corrente con quanto hai imparato. Decidi prossima ipotesi.

Il ciclo si chiude quando hai un test che fallisce in modo deterministico sul bug e passa dopo il fix. Quel test diventa la regression test permanente nel CI.

Esempio illustrativo: bug i18n hreflang del portfolio

Riassunto di una sessione debug reale (sintetizzata). Bug osservato: Google Search Console segnala "Alternate page with proper canonical tag" per 999+ URL del sito multilingua. Sintomo concreto: `/sv/blog/...` viene indicizzato sotto canonical `/en/blog/...` invece che mantenere il proprio canonical.

Stato corrente
  - 18 lingue config in CLAUDE.md
  - 7 lingue compilate AOT, 11 lingue runtime
  - Hreflang dichiarato ma GSC rifiuta canonical /sv/

Ciclo 1
  Ipotesi: hreflang malformato nel head HTML
  Test: curl https://federicocalo.dev/sv/blog/X | grep hreflang
  Atteso: 18 entries hreflang con codici corretti
  Risultato: 18 entries corrette
  Checkpoint: hreflang OK -> bug altrove

Ciclo 2
  Ipotesi: content lingua effettiva non corrisponde al locale dichiarato
  Test: curl /sv/blog/X | grep "lang=" | head
  Atteso: lang="sv"
  Risultato: lang="en" (!!)
  Checkpoint: confermato content drift. SSR serve bundle EN sotto path /sv/.

Ciclo 3
  Ipotesi: SSR route mapping /sv/ -> bundle EN se sv non compilato AOT
  Test: ng serve --localize=sv (verifica bundle separato)
  Atteso: bundle sv esiste OR fallback documentato
  Risultato: sv NON compilato AOT, fallback automatico a EN bundle
  Checkpoint: causa confermata. Fix: chrome runtime Transloco per sv +
    altre 10 lingue runtime, gia documentato nel piano i18n 35.

Senza la skill avrei probabilmente provato due-tre cose a caso prima di arrivare alla causa. Con la skill, tre cicli strutturati = causa identificata in 20 minuti.

Il checkpoint pattern come memoria operativa

Il checkpoint pattern è la parte della skill che mi ha cambiato di più il modo di debuggare. Funziona così: dopo ogni ciclo, la skill produce un blocco di testo strutturato (lo "stato corrente" del ciclo successivo) che riassume:

  • Ipotesi testate e loro esito (confermate / rifiutate / inconcludenti).
  • Fatti accertati (cosa è stato osservato come vero).
  • Ipotesi escluse (cosa è stato eliminato dal set delle cause possibili).
  • Prossima ipotesi da testare.

Il checkpoint è di solito 200-400 parole. Se interrompi la sessione (chiamata urgente, fine giornata, kernel panic), riprendi il giorno dopo leggendo il checkpoint. Niente "come funzionava il debug ieri?". È tutto scritto.

Sul mio portfolio uso checkpoint anche dopo aver risolto il bug: incollato nel git commit message come "investigation summary", o salvato in docs/memory/ per bug ricorrenti su componenti che tornano a darmi problemi. Negli ultimi sei mesi questa pratica mi ha permesso di risolvere in 5 minuti bug che la prima volta avevo impiegato due ore a diagnosticare.

Strategie di test efficaci nel ciclo

La parte "test che verifica l'ipotesi" è dove la skill fa la differenza tra debug efficiente e tentativi a caso. Quattro strategie pratiche:

  1. Test deterministico minimo. Riproduci il bug nel modo più piccolo possibile. Se il bug è in produzione su un endpoint API con dieci parametri, isolalo a uno script che chiama l'endpoint con un payload ridotto. Più piccolo è il test, più stretta l'ipotesi.
  2. Test binario. Formula il test in modo che il risultato sia binario: l'ipotesi è confermata o rifiutata. Evita test che producono output ambiguo.
  3. Misurazione pre-esecuzione. Scrivi prima di eseguire cosa ti aspetti di vedere. Senza questa scrittura, post-hoc-rationalize ogni risultato come "potrebbe confermare l'ipotesi". È il modo più diffuso di auto-ingannarsi.
  4. Test che lascia traccia. Aggiungi log strategici che sopravvivono al test. Se il bug si ripresenta in produzione tra una settimana, il log permette di ripartire da dove avevi lasciato.

Anti-pattern: ipotesi multiple in parallelo

La tentazione naturale è dire: "Forse è A, forse è B, forse è C, proviamo tutti e tre e vediamo cosa cambia." Errore. Se cambi tre cose e il bug scompare, non sai quale delle tre era la causa. Se il bug torna domani, non sai quale fix sia regredito.

La skill debugging impone una ipotesi alla volta. Cicli più, ma ogni ciclo lascia un fatto accertato. Tre cicli singoli sono più veloci di un "test multiplo" che richiede poi diecimila ulteriori cicli per disambiguare.

Integrazione con TDD

La skill debugging è complementare a tdd-guide:

  • tdd-guide forza RED-GREEN-REFACTOR su business logic nuova.
  • debugging entra in gioco su business logic esistente che fallisce in modo non ovvio.

Pattern integrato:

  1. Bug osservato in produzione.
  2. Invoca debugging, primo ciclo: ipotesi su causa.
  3. Test che riproduce il bug deterministicamente (è il "RED" della parte TDD).
  4. Ipotesi confermata = causa identificata.
  5. Scrivi il fix che fa passare il test (è il "GREEN" della parte TDD).
  6. Refactor se necessario (RED-GREEN-REFACTOR completo).
  7. Commit + push, regression test resta nel CI.

Il test scritto durante l'investigazione (passo 3) non va buttato dopo il fix: diventa la regression test che ti protegge se qualcuno reintroduce il bug.

Quando la skill non basta: bug di sistema

Ci sono bug che la skill da sola non risolve. Casi tipici:

  1. Bug che vivono fuori dal codice: configurazione di infrastruttura, version drift su dipendenze, problemi di rete. L'ipotesi deve uscire dal repository e indagare l'ambiente. La skill guida il processo, ma il test richiede strumenti esterni (ssh + log inspection, monitoring dashboards, ecc.).
  2. Bug intermittente che non si riproduce in locale. L'ipotesi tipica è "race condition" o "timing dependent". La skill spinge verso strumenti di stress test (concurrent requests, fault injection) che richiedono setup non banale.
  3. Bug di percezione: l'utente segnala un comportamento che, investigato, è un fraintendimento del comportamento corretto. Qui il "fix" è documentazione o UX, non codice. La skill, applicata rigidamente, non lo coglie e ti fa cercare cause inesistenti.

In tutti e tre i casi la skill resta utile per strutturare l'investigazione, anche se la soluzione esce dal codice.

Sessione tipica: tempi e costi

Sul mio portfolio, una sessione debug tipica (bug medium-complexity) ha questi parametri:

  • Cicli: 3-7 per bug medium, 8-12 per bug hard.
  • Durata: 15-40 minuti per medium, 60-120 minuti per hard.
  • Token consumati: 15-40k in/out per medium.
  • Output finale: bug risolto + test regression + checkpoint summary committato.

Confronto: prima dell'adozione della skill, debug a istinto medio era 45-90 minuti per bug medium. Riduzione del 50-60% del tempo, con un bonus: il test regression resta nel CI come protezione futura.

Checklist invocazione skill debugging

  1. Il fix banale ha già fallito? Se no, prima prova quello (più veloce).
  2. Hai un sintomo osservabile (errore in log, test che fallisce, comportamento UI sbagliato)? Se no, la skill non ha materiale.
  3. Il bug è riproducibile (anche imperfetto)? Se totalmente non riproducibile, prima fase ipotesi è "come renderlo riproducibile".
  4. Hai 15+ minuti per la sessione? La skill ha overhead di setup; per debug rapidi (<5min) è overkill.

Variante custom: debugging con focus performance

Sul portfolio ho una variante custom della skill, specializzata su bug performance (LCP regressioni, INP issues, slow SSR endpoints). Frontmatter illustrativo:

---
name: debugging-performance
description: Use when investigating a performance regression (LCP > target,
  INP > 200ms, SSR endpoint slow). Drives a scientific loop focused on
  measurement first (real metrics from Lighthouse / CrUX), then hypothesis
  on cause, then test. Stops when measured metric returns under target.
metadata:
  type: rigid
---

La variante aggiunge al body principale due steps:

  1. "Measure first" - primo ciclo è sempre misurazione di baseline (no ipotesi).
  2. "Compare with target" - ogni ciclo successivo confronta misurazione attuale con target SLO esplicito.

Senza queste due aggiunte, la skill base tendeva a saltare alla "ipotesi su causa" senza prima misurare bene. La variante fissa il problema.

Cosa ho imparato scrivendo questo articolo

La cosa più sorprendente è quanto fosse "ovvio" il metodo scientifico letto e quanto fosse difficile applicarlo sotto pressione. Avevo letto libri sul debugging strutturato anni prima (Andy Hunt + Dave Thomas, il vecchio "Pragmatic Programmer"), ma in pratica continuavo a saltare i passaggi quando il bug era urgente.

La skill ha fatto la differenza non per il contenuto (che già sapevo) ma per la forma: avere una procedura esplicita scritta da qualcun altro a cui dover rispondere ("hai formulato l'ipotesi singola? hai scritto cosa ti aspetti di vedere?") attiva la disciplina meglio del buon proposito personale. È strano da ammettere ma è così.

Anti-pattern evitati

  • Skip checkpoint per fretta. La tentazione, dopo aver risolto il bug, è di non scrivere il checkpoint finale ("ho capito, andiamo avanti"). Errore: tre mesi dopo lo stesso bug si ripresenta in forma leggermente diversa e non ricordi più i fatti accertati. Cinque minuti di checkpoint ti salvano due ore di re-debug.
  • Ipotesi non falsificabile. "Forse il problema è nel framework" non è un'ipotesi testabile. La skill insegna a riformulare: "Se il problema è nel framework, il bug deve scomparire downgradando alla versione precedente. Test: downgrade alla 3.4.10 e verifica." Ora è testabile.

Una storia ricevuta che vale la pena condividere

Sezione segnaposto. Se hai un bug che hai risolto con metodo scientifico (o uno che ti tormenta ancora), scrivimi a federico@federicocalo.dev. La storia (pseudonimizzata, con consenso) entra nel cluster successivo.


← Cluster precedente: Brainstorming skill Prossimo cluster: TDD enforcement skill →

Domande frequenti

Qual è la differenza tra un bug facile e uno difficile?

Un bug facile è una catena causale corta, mentre un bug difficile ha almeno tre caratteristiche: non è immediatamente evidente, richiede un processo strutturato per essere risolto e può sembrare casuale.

Perché la skill di Superpowers è necessaria per i bug difficili?

La skill di Superpowers è necessaria perché fornisce una struttura al processo di debug, aiutando a evitare tentativi disordinati e a concentrarsi su ipotesi specifiche.

Cosa fa la skill durante un ciclo di debug?

La skill produce un checkpoint dopo ogni ciclo, che è un blocco di testo strutturato che riassume lo stato corrente del ciclo successivo. Ciò aiuta a mantenere traccia dei progressi fatti e a riprendere facilmente la sessione di debug.

Quali sono le strategie di test efficaci utilizzate dalla skill?

La skill utilizza quattro strategie di test efficaci: formulare ipotesi singole, testare l'ipotesi, misurare e raffinare. Inoltre, la skill evita l'anti-pattern di formulare ipotesi multiple in parallelo.

Fonti e approfondimenti

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti