Code review na era dos agentes: a revisão começa na especificação

Este texto é uma releitura de um artigo que publiquei em 2019 (leia o original).

Em 2019 eu escrevi um texto curto sobre o que tinha aprendido em 18 meses de code review. Na época eu estava numa empresa onde nenhuma linha entrava na branch principal sem passar por pelo menos outra pessoa, e confesso que no começo achei isso invasivo. Demorou pouco para eu perceber o contrário: eu aprendia mais com os comentários dos colegas do que com qualquer curso que já tinha feito.

Sete anos depois, boa parte do código que passa por revisão não foi digitada por uma pessoa. Foi sugerida pelo Copilot, gerada por um agente a partir de uma issue ou montada a partir de um prompt. A conclusão a que cheguei é que a revisão mais importante deixou de acontecer no diff. Ela acontece antes, na especificação, e depois, em gates que nenhum humano precisa executar à mão.

O que não mudou

Code review continua sendo uma rua de mão dupla. Você revisa para aprender e para ensinar, não para julgar. O tom continua importando: “isso está errado” e “o que acontece aqui se a lista vier vazia?” apontam para o mesmo problema, mas só o segundo abre uma conversa. E o contexto continua sendo tudo. Revisar um diff sem entender o problema que ele resolve é ler a resposta sem saber a pergunta.

O que mudou: o revisor virou o gargalo

Antes, escrever código era a parte cara e revisar era a parte barata. Isso inverteu. Com agentes, uma pessoa abre em uma tarde a quantidade de pull requests que antes levaria uma semana. O código sai bem formatado, com nomes decentes e até com testes, e para na fila de revisão, porque a nossa capacidade de ler e entender não acelerou na mesma proporção. O revisor deixou de ser a segunda opinião e passou a ser, muitas vezes, a primeira pessoa que de fato leu aquele código. Se a gente tentar compensar isso só lendo mais rápido, o resultado é fadiga, e revisor cansado aprova qualquer coisa.

A revisão começa na especificação

Existe um detalhe que muita gente esquece: o modelo aprendeu com o código que leu. E nem todo código que ele leu está correto, seguro ou acessível. Sem orientação, o que sai é uma média de tudo o que existe por aí, com os mesmos vícios. A forma mais barata de mudar isso não é corrigir no diff, é dizer com clareza, antes, o que se espera.

Por isso, se o código nasce de um prompt ou de uma spec, o prompt e a spec são código-fonte, e código-fonte passa por revisão. Nos projetos em que participo, versionamos as instruções que os agentes recebem, os arquivos de contexto do repositório e as specs que originam cada tarefa, e revisamos isso com o mesmo cuidado de um diff. Uma spec ambígua gera dez PRs ambíguos. Uma spec que esquece acessibilidade gera dez telas inacessíveis. Revisar a origem é corrigir uma vez em vez de dez, e é uma forma de ensinar o time inteiro de uma vez.

Uma boa spec responde, no mínimo: qual problema de negócio estamos resolvendo, quais são os critérios de aceite, quais casos de borda importam, quais restrições de segurança, privacidade e acessibilidade valem, e o que não faz parte do escopo. Se a pessoa que pediu não consegue responder isso, o problema não é do modelo.

Clean Code, Clean Architecture, SOLID e DDD só fazem sentido se você sabe defender

Virou comum ver prompts do tipo “use Clean Architecture, SOLID e DDD”. O modelo obedece: cria camadas, interfaces, repositórios, agregados. O código fica com cara de bem feito. Mas cada uma dessas abordagens é uma troca. Clean Architecture compra isolamento ao custo de indireção. DDD compra alinhamento com o negócio ao custo de modelagem e de linguagem que precisa ser construída com quem entende a operação. SOLID levado ao pé da letra vira uma interface para cada classe. Nenhuma delas é grátis, e nenhuma serve para tudo.

A minha regra é simples: só peça ao modelo uma metodologia, um framework ou uma técnica se você entende e está pronto para responder, numa revisão, por cada um dos prós e contras dela naquele contexto. Se a resposta para “por que esse agregado existe?” é “porque o agente criou”, o padrão virou cerimônia. Escrevi sobre isso em 2019, em O problema não é e nunca foi do DDD, e a IA só deixou o problema mais rápido de se reproduzir.

Testes, mais do que nunca, são assunto de gente

Quando o mesmo modelo escreve o código e os testes, os testes tendem a confirmar o que o código faz, não o que o negócio precisa. Eles passam, a cobertura sobe, e ninguém verificou se a regra estava certa. Por isso, testes precisam ser revisados com mais rigor do que nunca e, sempre que possível, escritos por pessoas, com apoio dos times de negócio. Os critérios de aceite da spec viram cenários de teste antes de virar código. Aí sim o agente pode implementar até tudo ficar verde, e o verde passa a significar alguma coisa.

Gates determinísticos diminuem a fadiga da revisão

A melhor forma de proteger a atenção de quem revisa é não gastar essa atenção com o que uma máquina verifica de forma determinística, sempre do mesmo jeito. O humano não deveria ser o primeiro a descobrir que o build quebrou ou que uma dependência tem vulnerabilidade conhecida. Os gates que eu considero mínimos:

  • Linters e formatadores, com as regras do time versionadas no repositório.
  • Análise estática de código e de segurança (SAST), incluindo dependências e segredos expostos.
  • Análise dinâmica (DAST) e verificações de acessibilidade automatizadas nas interfaces, sabendo que elas pegam só uma parte dos problemas.
  • Execução dos testes de unidade, integração e ponta a ponta, em cada etapa do desenvolvimento, não só no fim.

E o mais importante: as mesmas regras compartilhadas em três lugares. Nos hooks do Git, para o desenvolvedor saber antes do commit. Nos hooks do harness do agente, para o próprio agente ser barrado e corrigir sozinho antes de abrir o PR. E no pipeline de CI/CD, como garantia final de que nada passou por fora. Quando a regra é a mesma nos três, o PR que chega para a pessoa já passou por tudo o que é mecânico, e a revisão humana pode se concentrar em intenção, domínio e risco.

Modelos ajudam a revisar, mas nunca dão a palavra final

Eu uso modelos na revisão, sim. Mas com duas condições. A primeira: o modelo que analisa precisa ser diferente do que gerou o código. Um modelo revisando o próprio trabalho tende a concordar consigo mesmo e a repetir os mesmos pontos cegos. A segunda: a análise do modelo é apoio, nunca a revisão final. Quando um time trata a aprovação automática como suficiente, o que acontece é que um modelo gera, outro aprova e ninguém entende o que foi para produção.

O que só uma pessoa pega

  • Intenção. O código faz o que a spec pediu. Mas a spec pediu a coisa certa?
  • Domínio. A regra que só faz sentido para quem conhece a operação, o caso de borda que só aparece no fim do mês, o campo que significa outra coisa naquele sistema legado.
  • Acessibilidade. Esse é o ponto que mais me toca, como pessoa com deficiência visual e usuário de leitor de tela. Código gerado produz interfaces que parecem corretas e que, com frequência, são inutilizáveis com NVDA: botões sem nome acessível, modais que não prendem o foco, ordem de tabulação sem sentido. O modelo aprendeu com uma web que, em sua maioria, é inacessível. Ferramenta automatizada ajuda, mas não substitui alguém testando de verdade.
  • Segurança contextual. Não é a injeção de SQL, que o scanner pega. É saber que aquele endpoint não pode expor aquele campo porque existe um contrato com uma área regulada.

O que eu levo de 2019 para 2026

Code review nunca foi sobre encontrar erros. Sempre foi sobre construir entendimento compartilhado. Em 2026, esse entendimento começa na especificação, é protegido por gates determinísticos e termina numa pessoa que sabe responder por cada decisão que foi para produção. A ferramenta que gera o código mudou; a responsabilidade de entender continua sendo nossa.

E no seu time, como está isso? Vocês já revisam specs e testes com o mesmo cuidado do código, ou a revisão ainda começa e termina no diff? Me conta nos comentários.

Comentários

Deixe um comentário