212 comentários do revisor de IA em 38 PRs: 47 viraram mudança de código antes do merge
O revisor automático deixou 212 comentários em 38 pull requests de uma base que eu acompanho. Quarenta e sete viraram alteração de código antes do merge. Cento e quarenta e dois ficaram parados: ninguém tocou no arquivo e ninguém respondeu nada.
A primeira linha dessa conta é a que o painel da ferramenta mostra na reunião. É a que não serve para decidir nada. Comentário em pull request mede volume de saída do modelo, do mesmo jeito que porcentagem de cobertura mede quanta linha o teste executou. Já peguei uma suíte marcando 92% nessa mesma casa e o mutation testing devolveu 41% de score real. A métrica estava lá, a garantia não.
O texto "There is an AI code review bubble" está com 351 pontos e 249 comentários no Hacker News, e a discussão inteira gira em volta disso: ninguém discute se o revisor comenta, discute se o comentário vale algo. O LeadDev publicou que o tempo que a IA economiza na escrita está sendo consumido na revisão. Combinando as duas coisas, você tem uma ferramenta vendida por produtividade que está empurrando trabalho para a fila mais caras da esteira, a fila onde gente lê.
Então eu parei de olhar quantidade e passei a contar outra coisa.
O que eu conto como achado
Um achado só existe se ele mexeu no repositório ou se alguém discordou dele por escrito. Três baldes, e todo comentário cai em exatamente um:
- alterou: depois do comentário, um commit do mesmo PR mexeu naquele arquivo, naquela região de linha, antes do merge.
- respondido: ninguém mexeu, mas alguém respondeu na thread dizendo por que não vale.
- silêncio: ninguém mexeu e ninguém respondeu. O comentário foi para o merge intacto.
O balde do silêncio é o que me interessa, porque ele é o custo escondido. Cada um daqueles 142 comentários foi lido por alguém, pelo menos de raspão, e descartado sem registro. Isso é leitura paga sem produto.
A coleta
Primeira parte puxa os comentários de review e os commits de cada PR da janela. Preciso dos dois porque a pergunta é temporal: o commit veio depois do comentário?
REPO=org/app
gh pr list --repo "$REPO" --state merged --limit 60 \
--search "merged:2026-09-22..2026-11-02" --json number \
| jq -r '.[].number' > prs.txt
: > comentarios.ndjson
: > commits.ndjson
while read -r PR; do
gh api --paginate "repos/$REPO/pulls/$PR/comments" \
| jq -c --argjson pr "$PR" '.[] | {pr:$pr, id, reply:.in_reply_to_id,
autor:.user.login, bot:(.user.type=="Bot"),
path, linha:.original_line, criado:.created_at}' \
>> comentarios.ndjson
gh api --paginate "repos/$REPO/pulls/$PR/commits" \
| jq -c --argjson pr "$PR" '.[] | {pr:$pr, sha:.sha, data:.commit.committer.date}' \
>> commits.ndjson
done < prs.txt
Segunda parte cruza. Para cada comentário, olho os commits posteriores do mesmo PR, abro o diff só daquele arquivo e vejo se algum hunk encosta na linha comentada. Três linhas de tolerância para cima e para baixo, porque a correção raramente cai na linha exata.
import json, re, subprocess
from collections import Counter
TOL = 3
HUNK = re.compile(r"^@@ -(\d+)(?:,(\d+))?")
def ler(arq):
with open(arq) as f:
return [json.loads(linha) for linha in f]
comentarios = ler("comentarios.ndjson")
commits = ler("commits.ndjson")
respostas = {c["reply"] for c in comentarios if c["reply"]}
def diff(sha, path):
cmd = ["git", "show", "--unified=0", "--format=", sha, "--", path]
return subprocess.run(cmd, capture_output=True, text=True).stdout
def tocou(c):
for k in commits:
if k["pr"] != c["pr"] or k["data"] <= c["criado"]:
continue
for linha in diff(k["sha"], c["path"]).splitlines():
m = HUNK.match(linha)
if not m:
continue
ini = int(m.group(1))
n = int(m.group(2) or 1)
if ini - TOL <= c["linha"] <= ini + n + TOL:
return True
return False
placar = Counter()
for c in comentarios:
if c["reply"] or c["linha"] is None:
continue
quem = "bot" if c["bot"] else "gente"
if tocou(c):
placar[quem + ":alterou"] += 1
elif c["id"] in respostas:
placar[quem + ":respondido"] += 1
else:
placar[quem + ":silencio"] += 1
for chave, valor in sorted(placar.items()):
print(chave.ljust(18), valor)
Roda com o repositório clonado e atualizado na pasta, senão o git show não acha os shas.
$ python3 achados.py
bot:alterou 47
bot:respondido 23
bot:silencio 142
gente:alterou 61
gente:respondido 22
gente:silencio 13
O que os números dizem
Do lado do revisor: 212 achados abertos, uns 22% viraram código, perto de 67% morreram no silêncio. Do lado das pessoas, nos mesmos 38 PRs: 96 comentários e 61 alterações, algo em torno de 63%. Mesma base, mesma semana, mesmo time. A diferença não está em quem lê, está no que cada um resolve apontar.
Aí eu fiz a parte chata, que nenhum script faz: li os 47 comentários que viraram código na mão, umas duas horas. Trinta e um eram coisa que o ESLint e o compilador já reclamavam no CI (import pendurado, any solto, nome de variável). Dezesseis mudaram comportamento de verdade: nulo que chegava sem tratamento, await esquecido num Promise dentro de try, consulta no banco dentro de laço, chave de API num arquivo de seed.
Dezesseis em 212. Para cada achado que mudou o que o sistema faz em produção, o time passou por treze comentários. É esse o preço que não entra na planilha de ganho de produtividade.
O que eu mudei depois
- Desliguei no revisor toda categoria que o linter e o compilador já cobrem. Sobrou um escopo estreito: nulo não tratado, promessa sem await, consulta dentro de laço, segredo em diff.
- Achado sem resposta passou a travar o merge. Ou alguém muda o código, ou alguém escreve a frase explicando por que não vale. Silêncio deixou de ser saída.
- A contagem roda no fim do mês e devolve um número só, alterações divididas por achados abertos. Primeiro mês depois do corte: 71 comentários do revisor, 38 alterações. O volume caiu uns dois terços, a taxa de ação passou de 22% para perto de 53%.
Onde isso pode estar errado
A heurística de três linhas conta falso positivo. Se o PR teve uma refatoração grande no mesmo arquivo, o hunk encosta na linha comentada por coincidência e eu marco como alterado sem ter sido. Quem quiser fechar essa brecha precisa casar o texto do comentário com o conteúdo do hunk, e aí já não é mais script de uma tarde.
E é uma base só, 38 PRs, cinco pessoas, monolito em Node com TypeScript. Não sei se o número se segura em repositório com 200 PRs por semana, nem em time de três onde todo mundo lê tudo de qualquer jeito. Também é bem possível que o mesmo revisor, com a configuração que o time de vocês escolheu, tenha taxa de ação melhor que a dos humanos daqui.
O que eu defendo é só o procedimento: antes de renovar a assinatura, conte quantos achados viraram commit e quantos foram para o merge sem ninguém discordar deles.
Quem aqui já rodou essa contagem no próprio repositório? Queria saber duas coisas: qual a sua taxa de achado que virou alteração, e se vocês deixam o comentário do bot morrer sem resposta ou se ele trava o merge.
Fonte, para quem quiser a versão longa de onde a revisão automática substitui gente e onde não substitui: https://revin.com.br/pt/blog/code-review-automatizado-por-ia-onde-substitui-humano-e-onde-nao-substitui