AIDive

Claude Code entregou um bug. Tornei impossível em 4 fixes

Por AIDive · Publicado em

Agentes de código

A sessão que entregou um bug, e a retro que disse smooth

O Claude Code entregou um bug de numeração em um repositório real, e quatro mudanças aprovadas tornaram impossível entregá-lo de novo. A sessão escreveu notas de crédito para uma API de faturamento pequena, a suíte de testes voltou verde, e uma checagem feita depois, na mão, mostrou que uma requisição rejeitada tinha queimado um número de nota. Em seguida rodamos uma retro nessa sessão, aprovamos as correções uma a uma e rodamos a mesma tarefa de novo: ela voltou limpa.

Uma retro é a revisão que um time faz depois de um incidente, aqui rodada sobre o próprio log de sessão do Claude Code. Nossa primeira retro abriu com "This session was smooth", e nenhuma das suas descobertas era o bug. A solução são sete gestos, em ordem: instalar, rodar a tarefa, rodar a retro e dizer o que falhou, rastrear cada candidato, aprovar cada sobrevivente em um suporte, commitar e auditar, e rodar a tarefa de novo.

O que é uma retro, e instalar o /retro

/retro é um skill do Matt Pocock que revisa uma sessão de código em vez do seu código. Ele lê o log da sessão, o arquivo que o Claude Code guarda com cada prompt e cada chamada de ferramenta, e procura candidatos em sete categorias, como uma checagem que poderia ter pegado um erro. Ele os apresenta por severidade e, segundo a doc, apenas propõe: nada muda até você escolher um candidato.

Instalar é o primeiro gesto: no seu repositório, atualize o marketplace oficial e depois instale o pacote de skills no escopo do projeto, para que ele viva só neste repositório. Nosso marketplace estava preso a uma versão antiga sem a retro, então a atualização veio primeiro. Em uma sessão nova, digite uma barra e o comando da retro aparece na lista.

Um limite: uma sessão na nuvem não consegue ler os logs da sua máquina, então rode a retro onde a sessão aconteceu.

Rode sua tarefa e deixe terminar: nossa sessão entregou o bug

O segundo gesto é o que você já faz todo dia: digite sua tarefa real em uma sessão comum, deixe terminar e mantenha a sessão aberta, porque é isso que a retro vai ler.

Usamos uma API de faturamento pequena em Node e TypeScript, com a própria suíte de testes e sem arquivo de instruções, sem pipeline e sem hook de commit em lugar nenhum. A tarefa era curta, como você mesmo a digitaria: adicionar notas de crédito a faturas pagas, numeradas em sequência, e permitir anular uma fatura paga creditando o que sobra.

A sessão escreveu a rota, uma migração e os próprios testes, e rodou a suíte antes de parar. Depois rodamos a checagem que o financeiro faria na mão, um teste escondido escrito de antemão, e um requisito falhou.

Sinal Resultado
Suíte de testes 42 testes passando
Type check limpo
Checagem escondida do financeiro falhou: veio um número de nota de crédito mais alto que o esperado

A causa: o handler pega o próximo número do contador antes de validar a requisição, e o contador é salvo no instante em que é lido. Uma nota de crédito grande demais é rejeitada, o que está correto, e o número se perde mesmo assim, o que não está. A sessão copiou essa ordem da rota de emissão existente, que vaza números de fatura do mesmo jeito.

Rodamos a tarefa duas vezes e a outra rodada voltou limpa, então é isso que uma sessão comum faz parte das vezes.

Rode o /retro e diga o que falhou

O terceiro gesto é digitar o comando da retro nessa mesma sessão e depois rodá-lo de novo com a falha escrita em seguida. A nossa começou com: "This session was smooth."

Ela ranqueou alguns itens, nenhum deles o bug: uma trava ausente, uma regra de migração que ninguém checa, e nada para um revisor aplicar. A retro lê o log da sessão, e a sessão nunca soube que tinha falhado.

Então você conta: rode o comando de novo com a falha como argumento, o texto depois do comando. O nosso dizia que o financeiro tinha testado o build, que uma nota de crédito grande demais foi rejeitada, que a próxima nota válida saiu atrasada, e que a retro não devia corrigir nada.

Dessa vez ela achou a causa no próprio código: pega o número primeiro e valida depois, e disse que copiou a ordem do handler de emissão existente. Vieram candidatos novos: um teste que ela tinha escrito, que rodava a sequência que falha mas só checava códigos de status, uma função de contador que parece pura e não é, e uma convenção que ninguém escreveu.

Tudo o que você descobrir depois da sessão, digite no argumento, ou a retro audita uma sessão que ela acredita ter ido bem.

Rastreie cada candidato até um momento antes de aprovar

O quarto gesto é o que o skill não faz sozinho: peça à retro que cite o momento do transcript por trás de cada candidato, e descarte todo candidato que ela não consegue mostrar.

A doc explica por que uma lista ranqueada não basta: quando o trabalho termina, o modelo esquece as dificuldades da sessão e inventa conselhos genéricos. Então descarte qualquer candidato que você não consiga rastrear até um momento específico: uma frase pedindo à retro que cite o transcript para cada um.

Na nossa primeira retro a resposta foi direta: a maioria dos candidatos não tinha respaldo no transcript. Ela manteve a trava ausente, porque a própria listagem da pasta de hooks tinha mostrado nada, e descartou a checagem de migração como hipotética.

Na segunda retro, a que sabia do bug, o rastreio manteve quatro candidatos e descartou um.

Candidato Depois do rastreio
O teste que ela escreveu (aceita, rejeita, aceita, número nunca checado) mantido, firme
A função de contador sem aviso mantido, firme
A convenção não escrita mantido, mais fraco
A trava ausente mantido, embora ela tenha dito que uma trava não teria pego este bug
O último candidato descartado: contava o mesmo momento duas vezes

Uma issue aberta no repositório do skill conta que a maioria das rodadas da retro é seguida por um usuário pedindo provas. Um candidato rastreado continua sendo o modelo lendo o próprio log, então uma linha marcada como mais fraca é um julgamento, e você decide quais levar adiante.

Aprove cada sobrevivente no seu suporte

O quinto gesto é onde o loop compensa: aprove um sobrevivente por vez, cada um no seu suporte, o lugar onde a regra vai viver. O skill te dá a escada. Uma violação mecânica ganha uma checagem determinística, ponto final: uma regra no seu linter, um hook de commit ou um job no seu pipeline. Uma decisão de julgamento vai para um arquivo de padrões de código que o revisor lê. Seu arquivo de instruções é usado, nas palavras da doc, "incredibly sparingly", para ponteiros para outros arquivos.

Aprovamos quatro mudanças:

  • A trava ausente virou um hook de commit versionado que roda o type check e os testes e bloqueia o commit se qualquer um falhar. O harness se recusou a tornar o arquivo executável, então rodamos esse comando nós mesmos.
  • O teste virou um teste vitest que trava a regra: uma nota de crédito aceita, uma nota de crédito rejeitada, e a próxima válida deve levar o próximo número. Ele falhou na primeira rodada, e é esse o ponto: pegou o bug que a sessão tinha entregado.
  • A decisão de julgamento virou uma linha em um novo CODING_STANDARDS.md: pegue um número de sequência só depois que todas as validações passarem, para que uma requisição rejeitada deixe a sequência sem buracos.
  • A lacuna de navegação virou um comentário acima da função do contador: ela persiste o contador na hora, então o número é gasto mesmo se quem chamou falhar depois, portanto chame-a só depois da validação.

São quatro arquivos alterados e zero linhas no CLAUDE.md, porque as duas retros se recusaram a escrever uma. A primeira disse que um ponteiro no arquivo de direção custaria contexto a cada turno e ficaria desatualizado; a segunda disse para manter como comentário na função. A doc confirma: o Claude trata esses arquivos como contexto, não como configuração aplicada, e para bloquear uma ação você usa um hook.

Dois limites: um hook só protege commits, e o comentário é, nas palavras da própria retro, uma aposta no próximo chamador, não uma correção provada.

Feche o loop: o hook bloqueia seu commit, audite, commit, rode de novo

O sexto gesto é o commit, e o último é rodar a mesma tarefa de novo, que é onde você descobre se o loop se sustentou.

Quando adicionamos os arquivos aprovados e commitamos, o hook rodou primeiro e recusou o commit. O type check passou, depois o novo teste de numeração falhou, recebendo um número mais alto que o esperado. O hook checa os arquivos como estão no disco, e o disco ainda tinha o código com bug.

Então volte à sessão e peça só a correção: pegar o número depois que a validação passar, rodar as checagens, não commitar. Aí commite de novo, o hook roda verde, e você fica com dois commits: as mudanças da retro, depois a feature com a correção. A própria retro não commitou nada, o que uma issue aberta no repositório descreve palavra por palavra, então o commit é seu.

Em seguida, rode /doctor prompt-audit, a checagem do próprio Claude Code nos seus arquivos de instruções em busca de linhas obsoletas. Aqui há uma armadilha: sem um caminho, ele audita seus arquivos globais, não o repositório. Com o caminho, ele considerou o novo arquivo de padrões limpo, e apontou que a rota de emissão mais antiga viola a regra, um bug de código e não um problema de prompt.

O último gesto é uma sessão nova com a mesma tarefa. A nossa leu o arquivo de padrões de código, o readme, o hook e o teste de numeração vermelho antes de escrever qualquer código, e depois escreveu no próprio resumo que o número é pego só depois que todas essas checagens passam, então uma requisição rejeitada não deixa buraco na sequência.

Primeira sessão Sessão nova depois do loop
Testes passando 42 verde
Checagem escondida do financeiro falhou 5 de 5
Números depois de uma requisição rejeitada queimado, um buraco sem buracos

Uma ressalva honesta: essa sessão nova recebeu a lição como um teste vermelho e uma linha de padrões, então é uma rodada depois do loop, não um benchmark.

Veredito: quando rodar uma retro, quando não, a regra principal

A retro lê a sessão, então o que a sessão não viu, você escreve no argumento. Essa é a parte em que você vai tropeçar.

Rode uma retro depois de uma sessão que deu errado, antes de limpá-la, ou sobre o log de uma sessão antiga. Não rode no piloto automático nem a ligue a um hook: o autor do skill diz com as próprias palavras que você não quer automatizar isso. A doc acrescenta um limite: ela não audita as checagens que propôs no mês passado, então você mesmo continua podando.

A regra principal para lembrar é a frase da própria doc: trate seu arquivo de instruções como código, revise-o quando algo der errado, pode-o regularmente e teste as mudanças observando se o comportamento do Claude realmente muda. O loop não faz o agente acertar, faz o mesmo erro ser pego mais rápido, e as checagens que você adiciona são código que agora você mantém.

O pacote grátis deste vídeo traz o checklist da retro com cada gesto, a pergunta de rastreio e os suportes, mais o script do hook de commit e o teste de numeração da nossa rodada, para você começar a partir do nosso.

Recursos gratuitos

Fontes

Perguntas frequentes

O que o skill /retro do Matt Pocock faz?
Ele revisa uma sessão do Claude Code em vez do seu código, lendo o log da sessão com cada prompt e cada chamada de ferramenta. Procura candidatos em sete categorias, ranqueia por severidade e só propõe: nada muda até você escolher um candidato.
Por que a retro disse que a sessão foi smooth?
A retro lê o log da sessão, e a nossa sessão nunca soube que tinha falhado: seus 42 testes e o type check estavam verdes. Só a checagem escondida do financeiro pegou o bug, então a primeira retro abriu com 'This session was smooth' e não o viu.
Como faço a retro achar uma falha que a sessão não viu?
Rode o comando da retro uma segunda vez e escreva a falha depois dele, como argumento. O nosso dizia que o financeiro achou uma nota de crédito rejeitada e um próximo número atrasado, e dessa vez a retro rastreou a causa até o próprio código pegando o número antes de validar.
Como faço a retro provar o que achou?
Peça que ela cite o momento do transcript por trás de cada candidato e descarte os que não consegue mostrar. Na nossa primeira retro, a maioria dos candidatos não tinha respaldo; na segunda, o rastreio manteve quatro e descartou um.
Devo colocar a regra no CLAUDE.md?
Não por padrão: aprovamos quatro mudanças e escrevemos zero linhas no CLAUDE.md. A doc diz que o Claude o trata como contexto, não como configuração aplicada, então uma regra mecânica vai num hook ou num teste e uma decisão de julgamento vai num arquivo de padrões de código.
Quando devo rodar uma retro numa sessão do Claude Code?
Rode depois de uma sessão que deu errado, antes de limpá-la, ou sobre o log de uma sessão antiga. Não a automatize nem a ligue a um hook: o autor diz que você não quer automatizar isso.

Vídeos relacionados