Checagens de compreensão vs testes: quando cada uma vence
Testes e linters deixam passar o maior risco do código gerado por IA: você não entender o que foi escrito. Veja quando cada opção realmente vence.

Aqui vai um cenário que está ficando comum: seu agente de código escreve 600 linhas em quatro arquivos, os testes passam, o linter está satisfeito, e você faz o merge. Duas semanas depois quebra em produção e você encara o diff como se um estranho tivesse escrito, porque, funcionalmente, foi. A falha não estava no código. Estava na lacuna entre o código e o seu modelo mental dele. Essa lacuna é o que as checagens de compreensão de código com IA, portões que te fazem perguntas sobre um diff antes de ele ir para produção, tentam fechar. Um novo Git hook open-source chamado Sphinx fez barulho esta semana justamente nisso: antes do seu push passar, ele lê o diff e te faz uma pergunta sobre o que o código faz quando as coisas dão errado.
Meu instinto, como ex-engenheiro de ML, foi ser cético. Mais um portão? Mais um ritual? Mas quanto mais penso nos modos de falha que vejo de fato em código gerado por agentes, mais acho que essa ideia ataca algo que testes estruturalmente não conseguem. Então vamos à comparação honesta: checagens de compreensão versus a rede de segurança automatizada que você já tem (testes, linters, type checkers, CI) e quando cada uma realmente vence.
O que testes e linters verificam de fato
Verificações automatizadas respondem uma pergunta: o código se comporta como as checagens esperam? É um ciclo fechado inteiramente dentro da máquina. Um teste codifica a crença de alguém sobre o comportamento correto, o código satisfaz ou não, e nenhuma compreensão humana é necessária no momento do merge. Isso é um recurso. É o que permite que cem engenheiros enviem para o mesmo repositório sem ler o trabalho uns dos outros.
O problema está na premissa embutida nesse modelo: que quem faz o merge tem um modelo mental preciso do que o código deveria fazer, e que a suíte de testes reflete isso. Com código escrito à mão, essa premissa em geral se sustenta. Você escreveu, brigou com ele, sabe onde estão os esqueletos. Com código gerado por agente, ela quebra discretamente. Você descreveu um objetivo, o agente produziu uma implementação, e os testes passam porque o agente escreveu esses também. O check verde agora certifica que o código do agente bate com os testes do agente. Sua compreensão nunca entrou no circuito.
Esta é a mesma armadilha sobre a qual escrevi em por que benchmarks de IA deixam passar a maior parte do trabalho real: uma métrica só consegue certificar aquilo que mede. Uma suíte de testes mede conformidade comportamental nos casos que alguém pensou em codificar. Ela não diz nada sobre a lógica de retry cobrar duas vezes um cliente num timeout do Stripe, sobre o agente ter escolhido o endpoint errado, ou sobre o 'conserto' esconder uma race condition engolindo uma exceção. Essas são falhas de compreensão, e passam batidas pelo CI.
O que as checagens de compreensão pegam e os testes deixam passar
Uma checagem de compreensão inverte a direção da verificação. Em vez de perguntar 'o código funciona?', pergunta 'a pessoa que está enviando isso sabe o que acontece quando as coisas dão errado?'. O exemplo ilustrativo do Sphinx é bom: seu handler de webhook agora salva o ID do evento do Stripe antes de chamar charge(). O que acontece num retry depois de um timeout? Se você disser 'o cliente é cobrado duas vezes', está errado, porque o ID salvo curto-circuita o retry. Mas aí vem o seguimento: se o próprio charge() falhar, o que o próximo retry faz? Ele pula a cobrança. O cliente nunca é faturado, e nenhum teste falha, porque isso é um padrão de idempotência com aparência correta aplicado na ordem errada.
Repare que tipo de bug é esse. Não é um erro de sintaxe, de tipo ou uma asserção falhando. É uma falha de design que só aparece sob uma sequência específica de falhas, e a única forma barata de pegar isso antes da produção é um humano raciocinar sobre o caminho de falha. Testes poderiam pegar, se alguém tivesse escrito um teste para 'cobrança falha depois que o ID do evento é persistido'. Mas quem escreveria esse teste é quem entendeu o risco de ordenação, e se essa pessoa existisse, nós nem estaríamos aqui. Checagens de compreensão sondam exatamente a compreensão que teria escrito o teste que faltou.
Há um segundo benefício, menos sobre pegar bugs e mais sobre reverter um vazamento lento de habilidade. Muitos desenvolvedores descrevem a mesma experiência: brigar com um agente até chegar a um resultado que funciona consome energia de verdade, mas não deixa nada aprendido. Você entrega mais e entende menos, e a lacuna se acumula. Um quiz na hora do push força pelo menos uma reconstrução superficial da lógica do diff, muitas vezes o suficiente para transformar 'código que aprovei' de volta em 'código que eu domino'. Já argumentei que ferramentas de IA estão mudando discretamente como os desenvolvedores pensam; portões assim são uma das primeiras ferramentas que empurram na direção oposta.
Quando testes automatizados vencem
Não vamos romantizar o portão humano. Os testes vencem com folga em várias áreas, e fingir o contrário é como acabar com um quiz como única rede de segurança.
- Detecção de regressão em escala. Nenhum modelo mental sobrevive a um refactor de 30.000 linhas. Testes reverificam milhares de comportamentos por commit por centavos. Uma checagem de compreensão consegue cobrir talvez três perguntas de um diff.
- Correção mecânica. Erros de off-by-one, strings de formato erradas, fusos horários mal tratados: máquinas são melhores em checar isso exaustivamente do que um humano respondendo perguntas sob pressão de tempo.
- Repetibilidade. Um teste roda de forma idêntica para sempre. A qualidade de uma pergunta de quiz depende do modelo que a gerou e de quão desperto você está às 17h de uma sexta-feira.
- Confiança em refatorações. Quando o comportamento não deveria mudar de jeito nenhum, os testes são a única checagem que faz sentido. Entender o código não ajuda você a verificar que não o alterou.
Existe também um gênero de código onde checagens de compreensão só adicionam atrito sem valor: boilerplate gerado, migrações mecânicas, atualizações de dependências, mudanças de configuração. Fazer um quiz sobre o que um reformat do Prettier faz é um imposto, não um portão. Qualquer ferramenta nesse espaço precisa de uma boa resposta para diffs de baixo risco, senão as pessoas vão contorná-la. O Sphinx antecipa isso com uma saída de emergência, sphinx yolo, que registra cada pulo. Esse registro importa mais do que parece: um portão que todo mundo contorna em silêncio é pior do que nenhum portão.

Quando checagens de compreensão vencem
Checagens de compreensão vencem exatamente onde o humano é o elo mais fraco, o que, no desenvolvimento assistido por agentes, acontece com mais frequência do que gostaríamos de admitir.
- Raciocínio sobre caminhos de falha. Retries, timeouts, escritas parciais, transações distribuídas: são os caminhos de código que só executam quando algo já está quebrado. Agentes são razoáveis no caminho feliz e descuidados no caminho triste.
- Diffs de alto raio de explosão. Pagamentos, autenticação, migrações de dados, qualquer coisa que toque sistemas que deveriam resistir à catástrofe. O custo de uma resposta errada aqui é muito maior que dois minutos de atrito do quiz.
- Código que você não escreveu e mal revisou. O PR de 1.500 linhas de um colega que não é dev, a branch autônoma noturna do agente. Um praticante relatou usar um prompt 'me faça um quiz sobre este PR' justamente para manter o foco numa revisão estruturada desses casos.
- Onboarding e manutenção de habilidades. Se seu time envia código de agente mais rápido do que alguém aprende o domínio, um portão de compreensão é o mecanismo de forçamento mais barato disponível.
O fio condutor: checagens de compreensão se pagam quando o diff é consequente e o modelo mental do humano é suspeito. Isso é um nicho específico, não algo universal.
Os modos de falha do próprio portão
Seria um desserviço não listar honestamente as formas como isso pode dar errado, porque os céticos têm argumentos reais.
Primeiro, fadiga de confirmação. Já passamos por isso: banners de cookies, diálogos de 'tem certeza?', perguntas de segurança que todo mundo clica sem ler. Um portão que dispara em todo push treina as pessoas a responder rápido em vez de pensar, e em um mês o quiz vira teatro ritual. A mitigação é o escopo: rodar nas branches protegidas e nos caminhos de alto risco, não em todo commit de uma branch de feature.
Segundo, qualidade das perguntas. O quiz é gerado por um LLM lendo o diff, o que significa que herda os modos de falha de LLMs: perguntas superficiais, respostas 'corretas' erradas, fixação na mudança óbvia enquanto a sutil passa despercebida. Um revisor observou que a versão dele ajudou a estruturar a revisão, mas não pegou decisões ruins como chamar o endpoint errado. Uma pergunta ruim é pior que pergunta nenhuma, porque certifica uma compreensão que ela nunca testou. Essa é uma limitação real e não acho que seja totalmente solucionável; é o mesmo motivo pelo qual o design do harness do agente importa mais que a escolha do modelo em tantas dessas ferramentas.
Terceiro, e esse me fez rir porque é verdade: alguém vai eventualmente apontar um agente para o portão para responder as perguntas no lugar dele. O design da ferramenta mostra consciência disso: suas respostas nunca chegam ao agente de código, e os segredos ficam fechados. Mas nada impede um desenvolvedor determinado de colar a pergunta numa janela de chat. Nesse ponto, a ferramenta está medindo a disposição para trapacear, que é um problema de cultura que nenhum hook consegue resolver.
Um portão de compreensão não verifica o código. Ele verifica se um humano com contexto e responsabilidade realmente se engajou com ele, que é exatamente o que os fluxos de trabalho com agentes removeram discretamente.
Colocando o portão num fluxo de trabalho real
Se você quiser experimentar, há duas opções práticas. O caminho de baixo atrito é uma skill baseada em prompt no seu agente atual: 'me faça um quiz sobre a branch atual antes de eu abrir o PR'. Várias pessoas construíram exatamente isso e relatam que funciona bem para estruturar a revisão, mas repare que depende de você escolher rodá-la, o que falha justamente quando você está mais apressado.
O caminho obrigatório é um Git hook. O Sphinx se instala em um minuto: npm install -g sphinx-understand, depois sphinx install, que conecta o Git e seus agentes de código e pergunta qual modelo deve fazer a revisão. Funciona com Claude Code, Codex, Cursor e outros, ou apenas com Git puro, e pode rodar em qualquer endpoint compatível com a OpenAI. Se preferir fazer o seu próprio, o esqueleto é um hook pre-push:
#!/usr/bin/env bash
# .git/hooks/pre-push — quiz gate for protected branches
protected_branch="main"
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$current_branch" != "$protected_branch" ]; then
exit 0 # only gate the branches that matter
fi
diff=$(git diff origin/main...HEAD)
if [ -z "$diff" ]; then
exit 0
fi
# Send the diff to your model of choice, get a scenario question,
# check the answer. Pseudocode for the core loop:
question=$(quiz_generate "$diff")
echo "$question"
read -r answer
if ! quiz_verify "$diff" "$question" "$answer"; then
echo "Not quite — here's why. Push blocked; try again."
exit 1
fi
Duas decisões de design importam mais que o código. Coloque portões em branches, não em pushes: dispare em pushes para main e branches de release e, idealmente, também em 'solicitar revisão', porque barrar o lixo antes que ele consuma a atenção de um colega é, possivelmente, o posicionamento de maior valor. E registre todo bypass. A saída de emergência é necessária; a trilha de auditoria é o que a mantém honesta.
Considere também onde isso fica em relação à revisão humana. Já escrevi sobre como cada camada de revisão deixa um time mais lento, e mantenho isso, então não adicione isso por cima de tudo. Use para substituir a primeira passada, mais rasa, da revisão: a passada do 'o autor sabe mesmo o que isso faz?'. É exatamente essa passada que as checagens de compreensão automatizam de verdade.
A recomendação
Testes e checagens de compreensão não são concorrentes, pois verificam assuntos diferentes. Testes verificam o código; checagens de compreensão verificam a pessoa responsável por ele. O desenvolvimento assistido por agentes quebrou a suposição implícita de que as duas coisas eram a mesma, e esses portões são um remendo pragmático, não uma gracinha.
Minha recomendação: mantenha sua suíte de testes como rede de segurança principal, pois nada aqui a substitui, e adicione um portão de compreensão de forma restrita, em branches protegidas e caminhos de alto risco, com uma saída de emergência registrada. Se você escreve a maior parte do código à mão, não precisa disso; o valor do portão cresce conforme cresce a parte do diff que você não escreveu. E se o quiz começar a parecer uma chatice que você contorna, isso também é um sinal: significa que você está enviando código que não entende rápido o bastante para que uma pausa de dois minutos pareça cara. Pense nisso. A versão desconfortável da tese dessa ferramenta é a correta: você pode terceirizar o raciocínio, mas a compreensão precisa continuar sua, porque às 3h da manhã, quando o loop de retry cobrar alguém sem ninguém perceber, o agente não está de plantão. Você está.


