O que GateGuard — Portão de Pré-Ação com Exigência de Fatos faz?
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
- Ao trabalhar em qualquer base de código onde edições de arquivos afetam múltiplos módulos
- Projetos com arquivos de dados que têm esquemas ou formatos de data específicos
- Times onde o código gerado por IA deve corresponder a padrões existentes
- Qualquer fluxo de trabalho onde o Claude tende a adivinhar em vez de investigar
Conceito Central
Autoavaliação de LLMs não funciona. Pergunte "você violou alguma política?" e a resposta é sempre "não." Isso foi verificado experimentalmente.
Mas perguntar "liste todos os arquivos que importam este módulo" força o LLM a executar Grep e Read. A própria investigação cria contexto que altera a saída.
Portão de três estágios:
1. NEGAR — bloquear a primeira tentativa de Editar/Escrever/Bash
2. FORÇAR — dizer ao modelo exatamente quais fatos reunir
3. PERMITIR — autorizar a repetição após os fatos serem apresentados
Nenhum concorrente faz todos os três. A maioria para na negação.
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 roda e passa nos testes. A diferença está na profundidade do design.
Tipos de Portão
Portão de Editar / MultiEditar (primeira edição por arquivo)
MultiEditar é tratado de forma idêntica — cada arquivo no lote é bloqueado 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 redigidos ou sintéticos, não dados brutos de produção)
4. Cite a instrução atual do usuário literalmente
Portão de Escrever (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 redigidos ou sintéticos, não dados brutos 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 único lote paralelo, a primeira chamada é negada e a negação marca o arquivo como verificado, portanto as edições irmãs nesse lote são aplicadas. Nada é revertido: o arquivo pode acabar contendo as edições irmãs sem a que foi 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 ponto 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 sobre qualquer outra coisa do lote.
Um bloqueio em todo o lote 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 exigência 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). Tentar novamente o mesmo arquivo ou
comando após apresentar 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 a carga continuam sendo executadas:
| Variável | Padrão | Efeito |
|---|---|---|
GATEGUARD_BASH_ROUTINE_DISABLED | não definido (portão ligado) | Desativa apenas o portão de Bash rotineiro. O portão de 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 Editar/Escrever/MultiEditar correspondente pula a exigência 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 sejam condensadas em uma única linha. 0 condensa desde a primeira negação. |
GATEGUARD_BASH_EXTRA_DESTRUCTIVE | não definido | Padrões extras de comandos destrutivos, como fonte de regex, adicionados ao conjunto embutido. Um regex malformado é tratado como não definido (os 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 fazer 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 em branco); qualquer outro valor
mantém 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 apenas 1 — 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 alvo relativo ao projeto. A raiz do projeto é
CLAUDE_PROJECT_DIR, recuando para o cwd do payload do hook, depois 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 alvo absoluto e podem
deliberadamente isentar caminhos fora do projeto.
Tanto padrões quanto caminhos usam separadores / e correspondência em minúsculas. * corresponde
dentro de um segmento, ** entre segmentos, e ? a um caractere que não seja 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 não ancoradas existentes 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, ativações de portão).
Anti-Padrões
- Não use autoavaliação no lugar. "Tem certeza?" sempre obtém "sim." Isso foi verificado experimentalmente.
- Não pule a verificação de esquema de dados. Ambos os agentes de teste A/B assumiram datas ISO-8601 quando os dados reais usavam
%Y/%m/%d %H:%M. Verificar a estrutura de dados (com valores redigidos) previne toda essa classe de bugs. - Não bloqueie todo comando Bash. Portões de bash rotineiro atuam uma vez por sessão. Portões de bash destrutivo atuam todas as vezes. Esse equilíbrio evita lentidão enquanto captura riscos reais.
Melhores Práticas
- Deixe o portão disparar naturalmente. Não tente pré-responder às 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 tiver 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)