GateGuard — Portão de Verificação de Fatos Pré-Ação
Um hook PreToolUse que força o Claude a investigar antes de editar. Em vez de autoavaliação ("você tem certeza?"), ele exige fatos concretos. O ato de investigar cria consciência que a autoavaliação nunca criou.
Quando Ativar
- Trabalhando em qualquer base de código onde edições de arquivos afetam múltiplos módulos
- Projetos com arquivos de dados que possuem esquemas ou formatos de data específicos
- Equipes onde o código gerado por IA deve corresponder a padrões existentes
- Qualquer fluxo de trabalho onde Claude tende a adivinhar em vez de investigar
Conceito Central
A autoavaliação de LLMs não funciona. Pergunte "você violou alguma política?" e a resposta é sempre "não." Isso é verificado experimentalmente.
Mas perguntar "liste cada arquivo que importa este módulo" força o LLM a executar Grep e Read. A própria investigação cria contexto que muda a saída.
Portão de três estágios:
1. NEGAR — bloquear a primeira tentativa de Edit/Write/Bash
2. FORÇAR — dizer ao modelo exatamente quais fatos coletar
3. PERMITIR — permitir a repetição após os fatos serem apresentados
Nenhum concorrente faz os três. A maioria para em negar.
Evidências
Dois testes A/B independentes, agentes idênticos, mesma tarefa:
| Tarefa | Com Portão | Sem Portão | Diferença |
|---|---|---|---|
| Módulo de análise | 8,0/10 | 6,5/10 | +1,5 |
| Validador de webhook | 10,0/10 | 7,0/10 | +3,0 |
| Média | 9,0 | 6,75 | +2,25 |
Ambos os agentes produzem código que executa e passa nos testes. A diferença está na profundidade do design.
Tipos de Portão
Portão de Edit / MultiEdit (primeira edição por arquivo)
MultiEdit é tratado de forma idêntica — cada arquivo no lote é verificado individualmente.
Antes de editar {caminho_do_arquivo}, apresente estes fatos:
1. Liste TODOS os arquivos que importam/requerem este arquivo (pesquise a árvore — Glob/Grep, ou find/grep via Bash)
2. Liste as funções/classes públicas afetadas por esta alteração
3. Se este arquivo lê/escreve arquivos de dados, mostre nomes de campos, estrutura
e formato de data (use valores editados ou sintéticos, não dados reais de produção)
4. Cite a instrução atual do usuário literalmente
Portão de Write (primeira criação de arquivo)
Antes de criar {caminho_do_arquivo}, apresente estes fatos:
1. Nomeie o(s) arquivo(s) e linha(s) que chamarão este novo arquivo
2. Confirme que nenhum arquivo existente atende ao mesmo propósito (pesquise a árvore — Glob/Grep, ou find/grep via Bash)
3. Se este arquivo lê/escreve arquivos de dados, mostre nomes de campos, estrutura
e formato de data (use valores editados ou sintéticos, não dados reais de produção)
4. Cite a instrução atual do usuário literalmente
Portão de Bash Destrutivo (todo comando destrutivo)
Dispara em: rm -rf, git reset --hard, git push --force, drop table, etc.
1. Liste todos os arquivos/dados que este comando modificará ou excluirá
2. Escreva um procedimento de reversão de uma linha
3. Cite a instrução atual do usuário literalmente
Portão de Bash Rotineiro (uma vez por sessão)
1. A solicitação atual do usuário em uma frase
2. O que este comando específico verifica ou produz
Lotes Paralelos e Aplicação Parcial
O portão de primeiro toque avalia cada chamada de ferramenta independentemente. Quando várias edições em um arquivo que ainda não foi tocado são enviadas em um lote paralelo, a primeira chamada é negada e a negação marca o arquivo como verificado, então as edições irmãs nesse lote são aplicadas. Nada é desfeito: o arquivo pode acabar contendo as edições irmãs sem a negada.
A mensagem de negação nomeia o arquivo e avisa que os irmãos do lote podem já ter sido aplicados. Trate-a literalmente:
- Envie edições dependentes para um arquivo ainda não tocado sequencialmente, não em um lote paralelo. Uma definição e seu primeiro uso, ou uma importação e seu local de chamada, não devem estar no mesmo lote.
- Após uma negação de primeiro toque, apresente os fatos, repita a edição negada, e releia o arquivo antes de construir qualquer outra coisa do lote.
Um bloqueio de lote inteiro não é possível: hooks veem chamadas de ferramenta uma de cada vez, então o portão não pode saber quais chamadas chegaram juntas.
Início Rápido
Opção A: Usar o hook ECC (instalação zero)
O hook em scripts/hooks/gateguard-fact-force.js está incluído neste plugin. Ative-o via hooks.json.
Se o GateGuard bloquear trabalhos de configuração ou reparo, inicie a sessão com
ECC_GATEGUARD=off. Para controle em nível de hook, continue usando
ECC_DISABLED_HOOKS com o ID do hook GateGuard.
Em sessões longas, apenas as primeiras GATEGUARD_FACT_FORCE_FULL_DENIALS
negações de verificação de fatos (padrão 3) emitem o bloco completo de quatro fatos;
negações posteriores são condensadas em uma única linha carregando o ordinal da negação,
para que blocos quase idênticos não possam se acumular na janela de contexto e
amplificar loops de repetição do modelo (#2142). Repetir o mesmo arquivo ou
comando após apresentar os fatos nunca reativa o portão.
Controles graduados
ECC_GATEGUARD=off (ou GATEGUARD_DISABLED=1) desliga o portão completamente.
As variáveis nesta tabela não — cada uma estreita um comportamento enquanto
as verificações de Bash destrutivo que suportam carga continuam em execução:
| Variável | Padrão | Efeito |
|---|---|---|
GATEGUARD_BASH_ROUTINE_DISABLED | não definido (portão ligado) | Desabilita apenas o portão Bash rotineiro. O portão Bash destrutivo (rm -rf, git reset --hard, drop table, dd if=, …) não é afetado. |
GATEGUARD_EXEMPT_GLOBS | não definido (sem isenções) | Globs separados por vírgula; um alvo de Edit/Write/MultiEdit correspondente pula a verificação de fatos de primeiro toque. Destinado a árvores de baixo valor de importação (testes, artefatos gerados, diretórios temporários) onde "quem importa isso / qual esquema" não carrega sinal. |
GATEGUARD_FACT_FORCE_FULL_DENIALS | 3 | Quantas negações emitem o bloco completo de quatro fatos antes que as posteriores condensem para uma única linha. 0 condensa desde a primeira negação. |
GATEGUARD_BASH_EXTRA_DESTRUCTIVE | não definido | Padrões adicionais de comandos destrutivos, como fonte de regex, adicionados ao conjunto embutido. Um regex malformado é tratado como não definido (embutidos ainda se aplicam) e registrado uma vez em stderr. |
GATEGUARD_STATE_DIR | ~/.gateguard | Onde o estado do portão por sessão é mantido. Se o estado não puder ser persistido, o portão permite a operação em vez de entrar em loop, e nomeia esta variável no aviso. |
GATEGUARD_BASH_ROUTINE_DISABLED aceita 1, true, on, enabled,
enable, ou yes (insensível a maiúsculas/minúsculas e espaços); qualquer outro valor
deixa o portão ligado.
Desligando o portão completamente
| Variável | Efeito |
|---|---|
ECC_GATEGUARD=off | Desabilita o GateGuard para a sessão. Aceita 0, false, off, disabled, ou disable. |
GATEGUARD_DISABLED=1 | Mesmo efeito. Reconhece 1 apenas — as grafias acima não se aplicam aqui. |
Para controle em nível de hook, continue usando ECC_DISABLED_HOOKS com o ID do hook GateGuard.
Semântica de glob para GATEGUARD_EXEMPT_GLOBS
Padrões correspondem a todo o caminho do alvo relativo ao projeto. A raiz do projeto é
CLAUDE_PROJECT_DIR, recuando para o cwd do payload do hook, depois para o diretório de trabalho do processo do hook. Globs relativos nunca isentam alvos fora dessa
raiz. Globs absolutos explícitos correspondem a todo o caminho absoluto do alvo e podem
isentar deliberadamente caminhos fora do projeto.
Tanto padrões quanto caminhos usam separadores / e correspondência em minúsculas. * corresponde
dentro de um segmento, ** através de segmentos, e ? um caractere não separador.
**/ inclui zero diretórios, então **/tests/** também corresponde a tests/foo.js.
Padrões malformados são descartados sem conceder isenção.
Desde 2.2.1, services/** cobre apenas a árvore de serviços raiz do projeto, e
*.md cobre apenas seus arquivos Markdown raiz. Use **/*.md para todos os arquivos Markdown
dentro do projeto. Isenções existentes não ancoradas podem precisar de ajuste:
{
"env": {
"GATEGUARD_BASH_ROUTINE_DISABLED": "1",
"GATEGUARD_EXEMPT_GLOBS": "**/tests/**,tests/**,**/*.test.*,**/docs/**,**/dist/**"
}
}
Opção B: Pacote completo com configuração
pip install gateguard-ai
gateguard init
Isso adiciona .gateguard.yml para configuração por projeto (mensagens personalizadas, caminhos de ignorar, alternâncias de portão).
Anti-Padrões
- Não use autoavaliação em vez disso. "Você tem certeza?" sempre obtém "sim." Isso é verificado experimentalmente.
- Não pule a verificação do esquema de dados. Ambos os agentes do teste A/B assumiram datas ISO-8601 quando os dados reais usavam
%Y/%m/%d %H:%M. Verificar a estrutura de dados (com valores editados) previne toda essa classe de bugs. - Não coloque portão em todo comando Bash. Portão Bash rotineiro uma vez por sessão. Portão Bash destrutivo toda vez. Este equilíbrio evita lentidão enquanto captura riscos reais.
Melhores Práticas
- Deixe o portão disparar naturalmente. Não tente pré-responder as perguntas do portão — a própria investigação é o que melhora a qualidade.
- Personalize as mensagens do portão para seu domínio. Se seu projeto tem convenções específicas, adicione-as aos prompts do portão.
- Use
.gateguard.ymlpara ignorar caminhos como.venv/,node_modules/,.git/.
Habilidades Relacionadas
safety-guard— Verificações de segurança em tempo de execução (complementar, não sobreposto)code-reviewer— Revisão pós-edição (GateGuard é investigação pré-edição)