audit-style
O simplify nativo tem bom gosto, mas não conhece as suas regras. Ele não
sabe que uma exceção customizada precisa justificar a própria existência por um
gate, que uma falha esperada deveria ser um resultado tipado em vez de um throw,
ou que abstração é um custo que você só paga na terceira ocorrência. E como ele
otimiza por menos código, pode introduzir exatamente a super-abstração que as
suas regras proíbem. O audit-style é o leitor que segura as regras numa mão e
o diff na outra.
O que resolve
O Octopus já guarda a qualidade do código em dois eixos — mas nenhum deles é o das regras de design da casa:
- o bloqueio sintático (o bundle
guardrails) barra código sem formatar, sem tipo ou com segredo — mas julga sintaxe, não se uma decisão de design honra uma regra que o time escreveu; - o sinal semântico de grounding (
audit-grounding) sinaliza convenções inventadas e fatos de domínio sem suporte — mas julga o diff contra o domínio, não contra as regras de código.
Sobra o terceiro eixo: este código honra as regras de design opinativas, e
está super-engenheirado? Um formatter nunca vai dizer “esta exceção customizada
tem um ponto de throw e zero de catch — lance o tipo da stdlib”. O simplify
genérico nunca vai dizer “você extraiu isto na segunda ocorrência; a regra manda
esperar a terceira”. O audit-style é o lado que lê as regras e reporta onde o
diff diverge.
Os três achados
rule-violation— um construto que o diff introduz e que contradiz uma regra declarada: uma exceção customizada que falha no gate, um throw onde se pede um resultado tipado, um parâmetro booleano, um número mágico, um guard clause ausente, lógica de negócio vazando para um repositório, uma exceção engolida.over-engineering— abstração que as regras explicitamente chamam de custo: uma abstração prematura, uma hierarquia de subtipos especulativa “para o futuro”, DRY aplicado antes de três ocorrências, uma camada de indireção sem consumidor presente. Esta é a dimensão que osimplifygenérico estruturalmente não produz — oaudit-styleé o leitor que sabe a hora de não simplificar.rigidity— a falha oposta: um conceito espalhado por vários arquivos, de modo que toda extensão precisa editar todos eles. Diferente dos outros dois, este nunca é um juízo de valor. Ele só é emitido sobre evidência medida.
Uma régua, dois sentidos
Sinalizar excesso e falta de abstração na mesma review é um bom jeito de soar incoerente — a menos que as duas leituras venham da mesma medição. E vêm:
Abstração sem co-change é abstração prematura. Co-change sem abstração é rigidez.
A medição é o octopus git-signals: uma passada determinística sobre o
histórico do git que encontra clusters de co-change — arquivos que mudam
sempre no mesmo commit, que é a cara de um conceito morando em três lugares. É
git e awk, nada além disso: sem parser de linguagem, sem ferramenta de
cobertura, sem CI, sem baseline. Roda em qualquer repositório, em qualquer
linguagem, e não custa tokens de modelo.
Só que um cluster, por si só, não é um achado sobre o seu PR. O que gera um achado é este diff ampliar o cluster — tocar dois ou mais membros e puxar para dentro um caminho que não era membro. Passar por um cluster que outra pessoa criou é informação; acrescentar um quarto arquivo que vai pagar o mesmo pedágio para sempre é algo que você fez.
Quem mede, quem decide
O audit-style roda no tier de modelo mais barato e continua signal-only: ele
reporta a evidência e para por aí, deliberadamente sem nomear princípio nem
pattern. O role architect pega o achado no tier de fronteira e decide:
| Evidência | Veredito |
|---|---|
| o diff amplia o cluster | BLOCKING |
| o diff toca o cluster sem ampliá-lo | ADVISORY |
| evidência indisponível (clone raso, sem histórico) | QUESTION |
O architect é também onde entra o vocabulário: o princípio SOLID em jogo e o
design pattern que criaria o seam. Uma regra o amarra — um pattern nunca é
nomeado sem a linha de evidência que o justifica. “Considere um Strategy
aqui” é cargo-cult. “Cada provedor novo edita estes três arquivos, oito vezes
em noventa dias” é uma afirmação que se pode contestar.
Nada é reportado como um zero limpo quando não foi medido: um clone raso ou um repositório sem histórico suficiente retorna indisponível, nunca “nenhuma rigidez encontrada”.
A fonte de verdade
Ele carrega as regras que o repositório já entrega, em ordem, e degrada com
elegância quando uma está ausente: rules/common/exceptions.md (o gate de
exceção customizada), rules/common/patterns.md (Result pattern, separação
repository/service, guard clauses), rules/common/coding-style.md (nomes,
estrutura, o catálogo de anti-patterns) e as regras de stack ativas que casam
com as linguagens que o diff toca. Uma regra ausente vira uma nota info, para
você saber que a auditoria foi parcial — ele nunca inventa uma regra que não
está escrita.
Por que signal-only, nunca bloqueia
Um veredito de design é um julgamento. Bloquear um merge com base numa leitura
probabilística de “isto está super-engenheirado?” seria pior que o problema que
resolve. O gate sintático já bloqueia no commit; o audit-style revela a lacuna
das regras de design como warn / info e deixa a decisão com você. Achados
recorrentes alimentam o loop de conhecimento existente, então uma violação que o
time repete é promovida a regra em vez de ser sinalizada para sempre.
Como roda
Diferente de audit-grounding e audit-verification, o audit-style não tem
Stop hook — não há custo de LLM por task. Ele roda só quando um fluxo de review
o invoca: os self-reviews do codereview e do pr-review, ou o passo de
simplify do implement. Registra no bundle quality:
bundles: - quality - guardrailshooks: trueO audit-style complementa o simplify nativo em vez de substituí-lo: o passo
genérico aplica gosto e edita o código, o audit-style lê as regras da casa e
sinaliza — incluindo o over-engineering que o passo genérico pode deixar passar.
Os limiares de rigidez ficam em git_signals.cochange no .octopus.yml e não
precisam de configuração para funcionar. O que vale conhecer é o
max_findings, cujo padrão é 1: um repositório maduro tem muitos clusters
de co-change, e reportar todos é como uma review vira um paredão de dívida
ambiente que ninguém lê.