Vamos ser honestos sobre algo que a maioria de nós não fala em voz alta: mal revisamos código gerado por IA.
O diff tem 600 linhas. O agente mexeu em 14 arquivos. Você abre o pull request, rola pelas mudanças, aperta os olhos em algumas funções e faz merge. Talvez rode os testes primeiro. Talvez não. O código parece razoável. O agente disse que terminou. Manda pra produção.
Isso não é preguiça. É um problema estrutural. Code review tradicional foi projetado para um mundo onde um humano escreveu o código e podia explicar seu raciocínio quando perguntado. Onde diffs tinham 50-200 linhas porque é o que uma pessoa escreve numa sessão focada. Onde a descrição do PR dizia "Escolhi a abordagem X por causa de Y" e você podia confiar nesse contexto.
Agentes de IA não funcionam assim. Claude Code pode produzir 500 linhas de código funcional em dois minutos. A descrição do PR costuma ser apenas "implementar feature X." O diff te diz o que mudou mas nada sobre o por quê. Sem registro de quais alternativas o agente considerou. Sem explicação de quais tradeoffs ele fez. Sem evidência de que realmente testou algo. Você está revisando o output de uma caixa preta, e a ferramenta de review só te mostra o output.
Este artigo detalha por que review baseado em diff falha para output de agente, qual é a camada realmente faltante, e um padrão concreto que torna código gerado por IA revisável sem triplicar seu tempo de review.
A lacuna da review
Desenvolvedores são honestos sobre isso em particular. Em threads da comunidade, o padrão se repete: "Basicamente só passo o olho nos diffs do agente." "Verifico se os testes passam e faço merge." "Se parece mais ou menos certo, aprovo."
Esse é um comportamento racional dadas as restrições. Quando um colega humano envia um PR, você tem contexto: sabe no que ele estava trabalhando, viu o ticket, talvez tenham discutido a abordagem no standup. O diff é suplementar. A review real aconteceu através do contexto compartilhado.
Com um agente, você não tem nada disso. O agente pegou uma tarefa, ficou em silêncio por três minutos e produziu um diff. O único contexto é a descrição de uma linha que o agente deixou no PR. Revisar esse diff do zero, sem contexto sobre intenção ou raciocínio, leva 5-10x mais tempo que revisar um PR humano do mesmo tamanho. Então as pessoas não fazem. Checam por alto algumas áreas críticas e aprovam.
O resultado é previsível. Bugs passam que teriam sido pegos com contexto. Drift arquitetural se acumula conforme agentes tomam decisões pequenas que se compõem. Qualidade do código degrada de formas sutis: não quebrado, mas não totalmente correto. Tratamento de erros inconsistente em um arquivo. Uma query de banco que funciona mas escala mal. Uma nova função utilitária que duplica uma existente porque o agente não sabia que ela existia.
Nenhuma dessas falhas é visível numa review de diff. Só são visíveis quando você entende o que o agente estava tentando fazer e pode comparar sua intenção com sua execução.
Por que diffs não são suficientes
Um diff é um registro de mudanças textuais. Só isso. Para code review humana, diffs funcionam porque o revisor pode inferir intenção a partir de reconhecimento de padrões e contexto compartilhado. Você vê um colega adicionar um bloco try/catch e sabe que ele está tratando o caso de erro do bug report da semana passada. Vê ele renomear uma função e sabe que está seguindo a convenção de nomes que o time combinou.
Com código gerado por agente, você não pode inferir intenção porque não fazia parte do processo de raciocínio. Eis o que um diff de 500 linhas de um agente realmente te diz:
- Quais arquivos foram modificados
- Quais linhas foram adicionadas, alteradas ou removidas
- A estrutura sintática do novo código
Eis o que ele não te diz:
Por que essa abordagem foi escolhida. O agente pode ter considerado três implementações diferentes. Escolheu uma. Você não sabe por quê. Talvez a escolhida seja ótima. Talvez tenha sido a primeira coisa que tentou e funcionou bem o suficiente. Pelo diff você não consegue saber.
Quais alternativas foram descartadas. Se o agente escolheu uma estratégia de polling ao invés de subscriptions WebSocket, foi uma decisão arquitetural deliberada ou acidente? Um diff não diz.
Se a implementação corresponde à spec. Você precisaria abrir a spec em uma janela e o diff em outra e cruzar manualmente cada critério de aceitação. A maioria não faz.
O que foi testado e como. O diff pode incluir novos arquivos de teste. Mas o agente os executou? Passaram? Cobrem os edge cases da spec? Você precisaria fazer checkout da branch e rodar eles mesmo pra saber.
Se o agente ficou no escopo. Talvez a tarefa fosse "corrigir o bug de login" e o agente também refatorou o middleware de auth, renomeou duas funções utilitárias e atualizou o schema de configuração. Todas essas mudanças parecem ok isoladamente. Mas não foram solicitadas, não foram especificadas e não foram testadas contra os critérios de aceitação originais.
Isso não é um problema de uma ferramenta de diff específica. A interface de review do GitHub, os merge requests do GitLab, Gerrit, git diff no terminal. Todos te mostram a mesma coisa: o que mudou. Para output de agente, "o que mudou" é a pergunta menos importante. A pergunta importante é: essa mudança faz o que deveria fazer, e nada mais?
A camada faltante: narrativa de implementação
O que revisores realmente precisam é o rastro de raciocínio do agente. Não o diff. A história da implementação: o que o agente planejou fazer, o que realmente fez e como verificou o resultado. Chame de narrativa de implementação.
Uma boa narrativa de implementação responde cinco perguntas:
- Qual era o plano? Antes de escrever código, o que o agente pretendia fazer? Quais arquivos, qual abordagem, qual ordem de operações?
- O que aconteceu durante a implementação? O plano sobreviveu ao contato com a codebase? Houve surpresas, mudanças de direção ou mudanças de escopo?
- Qual foi o resultado final? Não o diff. Um resumo em linguagem clara do que mudou e por quê.
- Como foi verificado? Passos específicos que o agente tomou para confirmar que a implementação funciona. Não "testes passam" mas "executei o critério de aceitação #3 fazendo X e observei Y."
- O que o revisor deveria checar? A própria recomendação do agente sobre o que merece atenção humana. Talvez haja uma decisão de design que poderia ir para qualquer lado, ou um tradeoff de performance que vale uma segunda opinião.
Nada disso existe num workflow de PR padrão. O campo de descrição do PR é texto livre que ninguém impõe. PRs de agente têm descrições mínimas por padrão porque o agente foi instruído a implementar, não a documentar seu raciocínio.
A lacuna não é tooling. É processo. A infraestrutura de review existe. O que falta é um registro estruturado da intenção do agente que o revisor possa checar contra o diff.
Aqui está um padrão que fecha a lacuna sem adicionar overhead significativo. Tem três partes: o agente comenta um plano antes de escrever código, implementa, e comenta um relatório done estruturado quando termina.
Passo 1: O comentário de plano
Antes de o agente abrir qualquer arquivo, ele escreve o que pretende fazer. Passos numerados, arquivos que vai tocar e a abordagem que vai seguir.
PLAN: Fix WebSocket reconnection dropping messages during
server restart.
1. Add a message buffer to hooks/use-websocket.ts that queues
outbound messages while the connection is in CONNECTING state
2. On successful reconnection, flush the buffer in order
3. Add a 30-second timeout: if reconnection hasn't succeeded,
surface an error to the user via the toast system
4. Update the existing reconnection test to verify buffer
behavior
Files: hooks/use-websocket.ts, components/connection-status.tsx
Test: Unit test for buffer queueing/flushing, manual test by
killing the WS server mid-operation and verifying no messages
are lost on reconnect.
Isso leva ao agente cerca de 30 segundos. O revisor lê em menos de 2 minutos. Nesses 2 minutos, você pega problemas que levariam 20 minutos para encontrar numa review de diff:
- O escopo está certo? (O plano diz 2 arquivos. Se o diff toca 6, algo desviou.)
- A abordagem é sólida? (Um buffer de mensagens com flush-on-reconnect é razoável. Se o agente tivesse proposto recarregar todo o estado do servidor, você ia querer discutir primeiro.)
- Faltam passos? (O que acontece com mensagens enviadas durante a janela de timeout? Devem ser descartadas ou retentadas?)
O plano é um checkpoint leve. Revise, aprove, e o agente prossegue com entendimento compartilhado da intenção.
Passo 2: Implementação
O agente escreve o código. Nada muda aqui. Mas como o plano existe, o agente tem um roteiro que pode seguir ao invés de tomar decisões ad hoc pelo caminho.
Passo 3: O comentário done
Quando o agente termina, publica um relatório de conclusão estruturado. Não "pronto." Não "implementei a feature." Um relato detalhado do que realmente fez.
DONE: WebSocket reconnection now buffers outbound messages
during CONNECTING state and flushes on successful reconnect.
Changes:
- hooks/use-websocket.ts: Added messageBuffer ref, queue
messages when readyState !== OPEN, flush in FIFO order on
'open' event. Added 30s reconnection timeout.
- components/connection-status.tsx: Shows "Reconnecting..."
badge during buffer state, switches to error toast after
timeout.
QA Verification:
1. Start dev server and WebSocket server
2. Open app, verify connection dot is green
3. Kill WebSocket server process
4. Trigger an action that sends a WS message (e.g., update
a bead status)
5. Restart WebSocket server within 30 seconds
6. Verify: the buffered message is delivered, bead status
updates in the UI
7. Repeat step 3, but wait >30 seconds before restart
8. Verify: error toast appears after timeout
Acceptance criteria:
- [x] Messages sent during reconnection are not lost (step 6)
- [x] Timeout surfaces user-visible error (step 8)
- [x] No behavior change when connection is stable (step 2)
Commit: f4e2a1b
Agora o revisor tem tudo que precisa. Lê o plano (o que era pretendido), lê o comentário done (o que foi realmente construído e como foi verificado), e então olha o diff com contexto completo. A review do diff vai de "o que é tudo isso?" para "deixa eu confirmar que isso bate com o que o agente disse que fez."
Checklists de review para output de agente
Mesmo com a narrativa de implementação, você precisa de uma abordagem sistemática. Aqui está um checklist que uso quando reviso output do Claude Code. Leva 5-10 minutos por review e pega as categorias de bugs que diffs sozinhos deixam passar.
Alinhamento com a spec:
- A implementação endereça cada critério de aceitação da spec?
- Há mudanças que vão além do que a spec pediu?
- O comentário done mapeia cada critério para um passo de verificação?
Contenção de escopo:
- O agente só modificou arquivos listados no plano?
- Se tocou arquivos adicionais, há uma razão declarada?
- Há mudanças de "limpeza" (renomeações, reformatações, refatorações) que não faziam parte da tarefa?
Cobertura de testes:
- Existem novos testes para novos comportamentos?
- Os testes realmente testam a coisa certa? (Agentes às vezes escrevem testes que passam trivialmente porque testam o mock, não a implementação.)
- O agente afirmou ter rodado os testes? Há evidência?
Consistência arquitetural:
- As mudanças seguem padrões existentes na codebase?
- Há novas abstrações que duplicam existentes?
- A estratégia de tratamento de erros combina com o resto do projeto?
Consciência de dependências:
- Se o agente adicionou dependências, são justificadas?
- As mudanças quebram funcionalidade existente? (Verifique arquivos que importam os módulos modificados.)
- Se a tarefa tem dependências com outras tarefas, essas dependências estão resolvidas?
Esse checklist funciona com qualquer ferramenta de code review. Imprima num post-it, coloque no seu template de PR, ou integre na sua CLAUDE.md para que o agente saiba a qual padrão será medido. O ponto não são os itens específicos. É ter um protocolo estruturado ao invés de "parece bom."
Beads como superfície de review
O padrão plan-comment-done precisa de um lugar pra morar. Se planos e comentários done estão espalhados entre mensagens do Slack, descrições de PR e output do terminal, você perde a conexão entre spec, plano, implementação e verificação.
Esse é o problema que beads resolve. Beads é um issue tracker Git-nativo e open-source onde cada "bead" carrega o ciclo de vida completo de uma tarefa: a spec como descrição, planos do agente como comentários, relatórios done como comentários e resultados de QA como comentários. Tudo anexado a uma única entidade, pesquisável e permanente.
Eis como o workflow de review fica com o CLI bd:
Criar a tarefa com a spec:
bd create --title "Fix WebSocket reconnection message loss" \
--description "## Problem
Messages sent during WebSocket reconnection are silently
dropped...
## Acceptance Criteria
1. Messages queued during CONNECTING state are delivered
on reconnect
2. 30-second timeout surfaces error to user
3. No behavior change when connection is stable" \
--type bug --priority p1
Agente reivindica o trabalho e publica um plano:
bd update bb-f4e2 --claim --actor eng1
bd comments add bb-f4e2 --author eng1 "PLAN: Add message
buffer to WebSocket hook...
1. Queue outbound messages when readyState !== OPEN
2. Flush buffer in FIFO order on 'open' event
3. Add 30s timeout with error toast
4. Update reconnection test
Files: hooks/use-websocket.ts, components/connection-status.tsx"
Você revisa o plano em 2 minutos:
bd show bb-f4e2 # Ler spec + comentário do plano
Se o plano parece certo, o agente prossegue. Se não, você comenta com correções antes de qualquer código ser escrito.
Agente completa e publica um relatório done:
bd comments add bb-f4e2 --author eng1 "DONE: WebSocket
reconnection now buffers outbound messages...
QA Verification:
1. Kill WS server, trigger action, restart within 30s...
Acceptance criteria:
- [x] Buffered messages delivered on reconnect
- [x] Timeout error visible
- [x] No regression on stable connection
Commit: f4e2a1b"
bd update bb-f4e2 --status ready_for_qa
QA verifica independentemente:
bd show bb-f4e2 # Ler os passos de verificação do comentário done
# Executar cada passo
bd comments add bb-f4e2 --author qa1 "QA PASS: All 3 criteria
verified. Buffer flushes correctly, timeout fires at 30s,
stable connections unaffected."
Todo o rastro de review está num só lugar. Seis meses depois, quando alguém perguntar "por que o WebSocket faz buffer de mensagens durante a reconexão?", a resposta está no bead: a spec explica o problema, o plano explica a abordagem, o comentário done explica o que foi construído, e o comentário QA confirma que funciona.
Quando review no terminal atinge seu limite
Rodar bd show em uma tarefa te dá tudo. Mas quando você está revisando output de múltiplos agentes através de vários workstreams paralelos, o workflow do CLI escala linearmente: um bd show por tarefa, um bd list pra ver o que está pronto pra review, um bd show por plano que precisa aprovar.
É aqui que Beadbox se encaixa. Beadbox é um dashboard em tempo real que te mostra cada tarefa no seu workspace com seu status atual, último comentário e posição no pipeline de review. Você vê quais agentes publicaram planos que precisam da sua aprovação. Quais publicaram relatórios done prontos pra sua review. Quais ainda estão em andamento. Tudo atualizando ao vivo conforme agentes escrevem comentários e mudam status pelo CLI bd.
Você não precisa do Beadbox pra usar o padrão plan-comment-done. O CLI cuida de todo o workflow. Mas quando você tem cinco agentes produzindo output revisável simultaneamente, poder ver a fila de review num relance ao invés de consultar cada tarefa individualmente muda a velocidade com que você avança pelo pipeline.
Beadbox é grátis durante o beta, e o CLI beads sobre o qual roda é open-source.
O problema da review não vai se resolver sozinho
Código gerado por IA está aumentando mais rápido que nossa capacidade de revisá-lo. As ferramentas que temos foram construídas para uma escala e um workflow diferentes. GitHub PRs, diffs de IDE, até análise estática sofisticada: nenhuma delas endereça o problema fundamental, que é que revisar código sem conhecer a intenção do autor é dramaticamente mais difícil do que revisá-lo conhecendo.
A solução não são ferramentas de diff melhores. É intenção estruturada: um registro do que o agente planejou fazer, o que realmente fez e como verificou o resultado. O padrão plan-comment-done te dá esse registro sem adicionar overhead significativo. O agente gasta 30 segundos escrevendo um plano. Você gasta 2 minutos revisando. O agente gasta 60 segundos escrevendo um relatório done. Você revisa o diff com contexto completo ao invés de do zero.
Cinco princípios pra levar:
-
Exija planos antes do código. Um comentário de plano de 30 segundos economiza sessões de review de 20 minutos. Se o plano estiver errado, corrija antes que o código exista.
-
Exija relatórios done estruturados. "Pronto" não é um relatório done. Passos de verificação, mapeamento de critérios de aceitação e hashes de commit são um relatório done.
-
Revise contra a spec, não contra o diff. O diff mostra o que mudou. A spec diz o que deveria ter mudado. Cruze as referências.
-
Imponha limites de escopo. Se o agente tocou arquivos fora do plano, isso é um alerta. Mudanças não planejadas são mudanças não revisadas.
-
Trate review como um protocolo, não como julgamento. Um checklist pega mais bugs que intuição. "Parece bom" não é uma review.
Os agentes vão continuar ficando mais rápidos. Os diffs vão continuar ficando maiores. A questão é se seu processo de review escala com eles, ou se você continua apertando os olhos em diffs de 600 linhas torcendo pelo melhor.
Se você está construindo workflows como esses, dê uma estrela no Beadbox no GitHub.