MÓDULO 5.2

🐛 Debug em Projeto Que Nunca Vi

6 passos para investigar um bug em código desconhecido sem saturar contexto. Subagentes para explorar, hipóteses ordenadas, fix + teste + docs. Cada passo com prompt pronto.

6
Passos
~35
Minutos
Prática
Tipo
6
Prompts

🎬O cenário

Um colega te passa um repositório e diz: "o botão X não funciona, dá uma olhada?". Você nunca viu o código. O instinto ruim é abrir tudo, ler aleatoriamente e adivinhar. Em 10 minutos o contexto está lotado de arquivos irrelevantes e você ainda não tem hipótese nenhuma. A saída é investigar como cientista: delegar a exploração, reproduzir o bug, hipóteses ordenadas, testar uma de cada vez. 6 passos.

1

🔍 Explore com subagente

Objetivo: achar o código do "botão X" sem poluir o contexto principal. O subagente Explore lê arquivos numa sessão isolada e te devolve só o destilado. Seu contexto recebe ~500 tokens em vez de 50k de código bruto.

Prompt pronto para copiar

passo 1
Delegue para um subagente Explore: encontre onde o 'botão X'
é renderizado e todos os handlers envolvidos. Me traga
só os caminhos dos arquivos e um resumo de 5 linhas.

📥O que esperar da resposta

Arquivos:
- src/components/CheckoutButton.tsx (render)
- src/hooks/useCheckout.ts (handler principal)
- src/api/checkout.ts (chamada de backend)
- src/store/cart.slice.ts (estado relacionado)

Resumo:
Botão renderizado em CheckoutButton. onClick chama
useCheckout().submit, que valida carrinho via cart.slice,
monta payload e chama api/checkout. Loading e erro
controlados no hook. Não há retry configurado.

Pronto: você tem o mapa do problema sem os 2000 linhas de implementação no contexto.

💡Por que subagente em vez de ler direto

Ler na sessão principal significa que todo arquivo inspecionado fica no contexto até o fim. Com subagente, a exploração acontece em memória separada — você recebe só o resumo. Para um repo grande, isso pode significar a diferença entre 10% e 60% de janela usada.

Próximo passo: reproduzir o bug localmente antes de qualquer fix.
2

🔄 Reproduzir localmente

Objetivo: ver o bug com os próprios olhos. Sem reprodução, qualquer fix é suposição. Aqui você quer comandos, não explicação — a intenção é rodar em 30 segundos.

Prompt pronto para copiar

passo 2
Quais comandos rodar para reproduzir o bug localmente?
Só me dê a sequência, sem explicação.

📥O que esperar da resposta

1. npm install
2. cp .env.example .env
3. docker compose up -d db
4. npm run migrate
5. npm run seed
6. npm run dev
7. Abrir http://localhost:3000/checkout
8. Clicar em "Finalizar compra"
9. Observar: console mostra "Uncaught TypeError"

Comandos enumerados, último item descrevendo o sintoma esperado. Se vier prosa, peça: "Só comandos numerados, sem explicações."

⚠️Não pule este passo

Debugar sem reproduzir = trabalhar baseado em relato. Você e o Claude podem passar 1h discutindo um bug que é outro. Reprodução te dá um sinal binário: depois do fix, o mesmo passo-a-passo ou quebra ou funciona. Sem ambiguidade.

Próximo passo: gerar hipóteses ordenadas por probabilidade.
3

🎯 Hipóteses em ordem de probabilidade

Objetivo: forçar o Claude a raciocinar antes de mexer no código. Uma lista ordenada com razão e teste dá plano de investigação — e em ~80% dos casos a hipótese 1 acerta.

Prompt pronto para copiar

passo 3
Com base no código que viu, liste 3–5 hipóteses para o bug,
da mais provável à menos. Para cada: razão + como testar.

📥O que esperar da resposta

H1 (mais provável): payload montado com cart vazio
  Razão: useCheckout não checa cart.items.length
  Testar: console.log(payload) antes do fetch

H2: API retorna 400 que não é tratado
  Razão: handler só captura network error, não HTTP 4xx
  Testar: inspecionar Network tab ao clicar

H3: Token expirado silenciosamente
  Razão: não há refresh antes do submit
  Testar: limpar localStorage e tentar de novo

H4 (menos provável): race condition no cart.slice
  Razão: submit pode disparar antes de hydrate
  Testar: adicionar timeout 500ms e tentar

💡"Razão + como testar" é a chave

Hipóteses sem teste são opinião. Ao exigir como testar, você força o modelo a pensar em sinal observável — e te dá o próximo comando executável. "Vai lá no código e vê" não é teste; console.log(payload) é.

Próximo passo: testar a hipótese 1 com alteração mínima.
4

🧪 Testar a hipótese mais provável

Objetivo: confirmar ou descartar H1 com a menor alteração possível. Menor alteração = mais fácil de reverter, menor risco de introduzir outro bug, sinal mais claro.

Prompt pronto para copiar

passo 4
Vamos testar a hipótese 1. Que alteração mínima
confirma ou descarta?

📥O que esperar da resposta

  • Proposta de 1–3 linhas a adicionar (console.log, breakpoint, guard clause)
  • Explicação do sinal esperado: "Se logar payload.items = [], H1 confirmada."
  • Comando para rodar novamente (normalmente igual ao passo 2)

⚠️Uma hipótese por vez

Testar H1 + H2 juntas é suicídio epistêmico. Se o bug sumir, você não sabe qual foi a causa. Se persistir, idem. Cada iteração = um sinal limpo. Se H1 falhar, volte ao prompt com "H1 descartada (razão: X), vamos para H2".

Próximo passo: identificada a causa, fix + teste + commit.
5

🩹 Fix + teste + commit

Objetivo: aplicar o fix real (não mais o debug log), cobrir com teste automatizado e commitar. Teste primeiro garante proteção anti-regressão — ninguém reintroduz o bug "sem querer" daqui a 2 meses.

Prompt pronto para copiar

passo 5
Confirmada a hipótese 1. Aplique o fix.
Rode o teste do botão X. Se passar, commit
com mensagem descritiva.

📥O que esperar da resposta

  • Diff do fix (guarda ou validação nova)
  • Teste novo cobrindo o caso do bug (ex: test("submit bloqueado com carrinho vazio"))
  • Output da suite: "X testes ok, 0 falhas"
  • Commit: fix(checkout): bloquear submit com carrinho vazio

Convenção de commit para fix

fix(escopo): o que foi corrigido
  • fix(checkout): bloquear submit com carrinho vazio
  • fix(auth): refresh token antes de submit crítico
  • fix(cart): hydrate antes de renderizar total
Próximo passo: deixar uma nota curta para quem vier depois.
6

📝 Docs/memória para o próximo

Objetivo: transformar debug pontual em memória organizacional. 10 linhas em docs/debugging.md podem economizar horas a um colega ou ao futuro você.

Prompt pronto para copiar

passo 6
Adicione uma nota em docs/debugging.md sobre: onde está
o código do botão X, o que era o bug, como reconhecer
se aparecer de novo. Máximo 10 linhas.

📥O que esperar da resposta

## Botão "Finalizar compra"

Código: src/components/CheckoutButton.tsx
Handler: src/hooks/useCheckout.ts

Bug conhecido (abril 2026): submit disparava com
carrinho vazio, API retornava 400 silencioso.
Fix: guard em useCheckout.submit().

Como reconhecer se voltar: "Uncaught TypeError" no
console ao clicar com cart.items.length === 0.
Ver commit fix(checkout): bloquear submit ...

💡"Máximo 10 linhas" é importante

Docs longas não são lidas. 10 linhas com o essencial (onde, o que era, como reconhecer) cabem num scroll e sobrevivem a busca. Também cabem no CLAUDE.md sem inflar o contexto em sessões futuras.

📋Resumo do Módulo

Subagente Explore para mapear código — contexto principal fica limpo
Reproduzir antes de consertar — sinal binário, sem ambiguidade
Hipóteses ordenadas com razão + teste — raciocínio antes de ação
Uma hipótese por vez — sinais limpos, menor alteração
Fix + teste + commit juntos — proteção anti-regressão
Docs curtas no fim — memória durável de ~10 linhas

Próximo módulo:

5.3 — 📚 Documentando Código Legado em 3 Sessões

Projeto grande sem docs. 3 sessões encadeadas, subagentes paralelos e economia real de ~5×.