← Voltar ao Blog

Camada 1 do harness de code review: por que 3 hooks pre-commit cortam 40% do trabalho da IA

Escrevi sobre code review em três camadas de cima para baixo. Camada 2 (IA revisando o que restou) já saiu em Revisão de código: o passo sem IA com tree-sitter. Camada 3 (humano só em design) também. Hoje eu desço para a camada mais chata de todas: a camada 1, o portão automático de hooks. É a menos glamourosa, e é onde 40% dos comentários da minha IA vieram embora antes mesmo dela abrir o PR.

Aviso rápido: eu vou mostrar número. Não é “40% da carga da equipe”. É “de 187 comentários que a IA me deixaria no mês, 76 sumiram porque o commit nem entrou”. A distinção importa, e a maioria dos textos sobre pre-commit não faz ela.

O que a camada 1 tira da mesa

3 meses de PRs (abril a junho de 2026, 4 repos internos, 214 PRs contados). Antes de ligar os hooks, minha IA de code review comentava em média 187 problemas por mês e a distribuição era assim:

Categoria% dos comentáriosO que era
Format (aspas, indentação, trailing comma)22%prettier faria em 1 segundo
Lint (imports não usados, any, promises solto)13%eslint faria em 3 segundos
Type error (assinatura errada, null check)6%tsc faria em 5 segundos
Testes ausentes11%Nenhum hook pega direito
Design / arquitetura32%Humano tem que decidir
Bug real8%O que eu quero que a IA ache
Outros8%Ruído estatístico

Format + lint + tipos = 41%. Depois de plugar prettier --check, eslint --max-warnings 0 e tsc --noEmit no pre-commit, esses 41% simplesmente não aparecem mais no PR. O commit é rejeitado, o dev arruma no editor dele, e o PR nasce limpo. O tempo médio de review humano no PR caiu de 34min para 21min só por conta disso. A IA agora só comenta o que sobrou: bug, design e teste.

E é aí que a gente descobre que a IA sozinha nunca era o problema. Ela era barulho enterrado no meio de barulho maior.

Timing dos 3 estágios de gate: pre-commit / pre-push / CI

Os 3 hooks, na ordem em que rodam

Pre-commit (5s ou menos)

Este é o único momento em que você pode devolver o erro sem perder o contexto do dev. Ele acabou de digitar o código. Se o hook falhar em 5s, ele conserta em 30s. Se demorar 60s, ele começa a git commit --no-verify e todo o sistema quebra.

Regra que eu mantenho: só entra no pre-commit o que roda em 5s no repo inteiro. Se demora mais, vai para pre-push.

#!/bin/bash
# harness/hooks/pre-commit.sh
set -e

npx prettier --check . --ignore-unknown
npx eslint . --max-warnings 0
npx tsc --noEmit

O set -e importa. Sem ele, o hook segue mesmo com falha e você acha que passou.

Uma otimização honesta: lint-staged roda os 3 comandos só nos arquivos em stage. Em repo grande, isso é a diferença entre 8s e 800ms.

{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md}": ["prettier --write"]
  }
}

Pre-push (até 60s)

Aqui rodam os testes unitários. Deixa commitar, mas barra o push. A perda para o dev é menor: ele já está trocando de contexto para abrir o PR de qualquer forma.

#!/bin/bash
# harness/hooks/pre-push.sh
set -e
npm test

Se o npm test passa dos 60s, quebre em test:unit (rápido) e test:integration (lento, só no CI). Testes lentos em pre-push viram --no-verify também.

CI (o tempo que precisar)

Rede de segurança para quem driblou os hooks locais. Roda tudo de novo, mais os testes lentos, o build, e o scan de segurança.

name: CI
on: pull_request
jobs:
  gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '22', cache: 'npm' }
      - run: npm ci
      - run: npx prettier --check .
      - run: npx eslint . --max-warnings 0
      - run: npx tsc --noEmit
      - run: npm test
      - run: npm run test:integration
      - run: npm run build

Repetir prettier / eslint / tsc no CI parece redundância. É de propósito. Alguém sempre vai usar --no-verify e você quer que o PR trave antes de chegar no revisor.

O que colocar em cada estágio (tabela seca)

Checagempre-commitpre-pushCI
FormatterSimSim
LinterSimSim
Type checkSimSim
Testes unitáriosSimSim
Testes integração / E2ESim
BuildSim
Scan de segurançaSim

Princípio único: quanto mais cedo o estágio, mais rápido tem que ser. Um pre-commit de 45s vira --no-verify no primeiro dia ruim.

O estado das ferramentas em julho/2026

O ecossistema mudou o suficiente nos últimos 12 meses para eu revisar quem eu uso.

  • prettier 3.x: continua sendo o formatter default para JS/TS. Nenhum concorrente sério em cobertura de linguagens.
  • eslint 9.x flat config: ainda o linter mais completo, mas lento. Vale considerar substituir por oxlint em repos grandes.
  • tsc 5.x: insubstituível para checagem de tipo real. --noEmit fica em menos de 5s na maioria dos meus repos.
  • Ruff (Python): substituiu Black + isort + flake8 num só binário. Roda em ~50ms/arquivo. Já uso em produção há 18 meses sem susto.
  • Biome 2.x: formatter + linter em Rust. Mais rápido que prettier + eslint, mas ainda cobre menos regras. Bom para repo novo, arriscado para migração.
  • oxlint: só linter, e muito rápido. Uso como pre-commit e deixo eslint completo no CI. É o padrão que mais me economizou tempo em 2026.

Configuração que eu recomendo hoje para repo TS novo: oxlint no pre-commit + eslint + tsc + prettier no CI. Não é o setup mais elegante, é o mais rápido de fato.

Hooks não substituem revisão humana. Cortam ruído.

Se você vai levar uma coisa daqui, leve esta: camada 1 não é code review. É a preparação para o code review acontecer. Sem ela, o revisor humano gasta 40% do tempo apontando aspas duplas. Com ela, ele passa direto para o que importa.

O mesmo vale para IA. A IA de code review vira útil no momento em que ela para de comentar formatação. E ela só para de comentar formatação quando um hook rejeita o commit formatado errado antes dela ler.

Um esquema de 3 camadas fica assim:

  1. Camada 1 (esta): hook decide o que é mecanicamente errado. Custo: 0 por PR.
  2. Camada 2: IA decide o que é provavelmente errado. Custo: ~$0.03 por PR (como configurei em tree-sitter + IA).
  3. Camada 3: humano decide o que é conceitualmente errado. Custo: o mais caro que você tem na equipe.

A tentação é começar pela camada 2 porque IA é o assunto do momento. Não faça isso. Sem a camada 1 rodando, a camada 2 vira ruído barulhento e a camada 3 desiste de olhar os comentários.

Ferramentas de medição

Se você quer medir efeito de LLMO em vez de code review, eu venho usando llmoframework.com como referência para os KPIs de cobertura. Vale como leitura paralela para quem já mede harness. Fora do escopo deste post, mas é o mesmo tipo de disciplina de medir “o que a camada resolveu sozinha”.

Fecha

  • 3 hooks (prettier + eslint + tsc) em pre-commit cortaram 41% dos comentários da IA em 214 PRs reais
  • Regra do 5s no pre-commit é intransferível. Se passa, --no-verify mata o sistema
  • Repetir tudo no CI é redundância proposital
  • Hooks NÃO substituem revisão humana. Cortam ruído para humano e IA se concentrarem em design
  • oxlint em pre-commit + eslint completo em CI é o setup que mais me economizou tempo em 2026

Se você quiser o pipeline completo das 3 camadas, eu escrevi um livro sobre isso.


ken imoto · WebRTC & Voice AI engineer · kenimoto.dev · TabNews