GateGuard — Porte Pré-Action par Investigation Factuelle
Un crochet PreToolUse qui force Claude à enquêter avant de modifier. Contrairement à l'auto-évaluation (« Êtes-vous sûr ? »), il exige des faits concrets. L'acte d'enquête crée une conscience que l'auto-évaluation n'a jamais atteinte.
Quand l'activer
- Travailler sur toute base de code où les modifications de fichiers affectent plusieurs modules
- Projets avec des fichiers de données ayant des schémas ou formats de dates spécifiques
- Équipes où le code généré par IA doit correspondre aux motifs existants
- Tout flux de travail où Claude a tendance à deviner au lieu d'enquêter
Concept central
L'auto-évaluation des LLM ne fonctionne pas. Demandez « avez-vous violé des politiques ? » et la réponse est toujours « non. » Cela est vérifié expérimentalement.
Mais demander « listez chaque fichier qui importe ce module » force le LLM à exécuter Grep et Read. L'enquête elle-même crée un contexte qui modifie la sortie.
Porte en trois étapes :
1. REFUSER — bloquer la première tentative Edit/Write/Bash
2. FORCER — dire au modèle exactement quels faits rassembler
3. AUTORISER — permettre une nouvelle tentative après présentation des faits
Aucun concurrent ne fait les trois. La plupart s'arrêtent au refus.
Preuves
Deux tests A/B indépendants, agents identiques, même tâche :
| Tâche | Contrôlé | Non contrôlé | Écart |
|---|---|---|---|
| Module d'analyse | 8,0/10 | 6,5/10 | +1,5 |
| Validateur webhook | 10,0/10 | 7,0/10 | +3,0 |
| Moyenne | 9,0 | 6,75 | +2,25 |
Les deux agents produisent du code qui s'exécute et réussit les tests. La différence réside dans la profondeur de conception.
Types de portes
Porte Edit / MultiEdit (première modification par fichier)
MultiEdit est traité de manière identique — chaque fichier du lot est contrôlé individuellement.
Avant de modifier {chemin_fichier}, présentez ces faits :
1. Listez TOUS les fichiers qui importent/nécessitent ce fichier (recherchez dans l'arborescence — Glob/Grep, ou find/grep via Bash)
2. Listez les fonctions/classes publiques affectées par cette modification
3. Si ce fichier lit/écrit des fichiers de données, montrez les noms de champs, la structure
et le format de date (utilisez des valeurs masquées ou synthétiques, pas de données de production brutes)
4. Citez l'instruction actuelle de l'utilisateur textuellement
Porte Write (première création de fichier)
Avant de créer {chemin_fichier}, présentez ces faits :
1. Nommez le(s) fichier(s) et la(les) ligne(s) qui appelleront ce nouveau fichier
2. Confirmez qu'aucun fichier existant ne sert le même but (recherchez dans l'arborescence — Glob/Grep, ou find/grep via Bash)
3. Si ce fichier lit/écrit des fichiers de données, montrez les noms de champs, la structure
et le format de date (utilisez des valeurs masquées ou synthétiques, pas de données de production brutes)
4. Citez l'instruction actuelle de l'utilisateur textuellement
Porte Bash destructeur (chaque commande destructive)
Déclencheurs : rm -rf, git reset --hard, git push --force, drop table, etc.
1. Listez tous les fichiers/données que cette commande va modifier ou supprimer
2. Écrivez une procédure de restauration en une ligne
3. Citez l'instruction actuelle de l'utilisateur textuellement
Porte Bash de routine (une fois par session)
1. La demande actuelle de l'utilisateur en une phrase
2. Ce que cette commande spécifique vérifie ou produit
Lots parallèles et application partielle
La porte de premier contact évalue chaque appel d'outil indépendamment. Lorsque plusieurs modifications vers un fichier non encore touché sont envoyées dans un même lot parallèle, le premier appel est refusé et le refus marque le fichier comme vérifié, de sorte que les modifications sœurs de ce lot sont appliquées. Rien n'est annulé : le fichier peut se retrouver avec les modifications sœurs sans celle refusée.
Le message de refus nomme le fichier et avertit que les modifications sœurs du lot peuvent déjà avoir été appliquées. Traitez-le à la lettre :
- Envoyez les modifications dépendantes vers un fichier non encore touché séquentiellement, pas dans un lot parallèle. Une définition et sa première utilisation, ou une importation et son site d'appel, ne doivent pas voyager dans le même lot.
- Après un refus de premier contact, présentez les faits, réessayez la modification refusée, et relisez le fichier avant de construire sur quoi que ce soit d'autre du lot.
Un verrou au niveau du lot n'est pas possible : les crochets voient les appels d'outils un par un, donc la porte ne peut pas savoir quels appels sont arrivés ensemble.
Démarrage rapide
Option A : Utiliser le crochet ECC (zéro installation)
Le crochet dans scripts/hooks/gateguard-fact-force.js est inclus dans ce plugin. Activez-le via hooks.json.
Si GateGuard bloque des travaux de configuration ou de réparation, démarrez la session avec
ECC_GATEGUARD=off. Pour un contrôle au niveau du crochet, continuez à utiliser
ECC_DISABLED_HOOKS avec l'ID du crochet GateGuard.
Dans les longues sessions, seules les GATEGUARD_FACT_FORCE_FULL_DENIALS
premières invitations factuelles (par défaut 3) émettent le bloc complet de quatre faits ;
les invitations suivantes sont condensées en une seule ligne portant l'ordinal du refus, afin
que des blocs quasi identiques ne puissent pas s'accumuler dans la fenêtre de contexte et
amplifier les boucles de répétition du modèle (#2142). Réessayer le même fichier ou la même
commande après avoir présenté les faits ne déclenche jamais à nouveau la porte.
Contrôles gradués
ECC_GATEGUARD=off (ou GATEGUARD_DISABLED=1) désactive complètement la porte.
Les variables de ce tableau ne le font pas — chacune restreint un comportement tandis que
les vérifications destructives de Bash, qui supportent la charge, continuent de fonctionner :
| Variable | Défaut | Effet |
|---|---|---|
GATEGUARD_BASH_ROUTINE_DISABLED | non défini (porte active) | Désactive uniquement la porte Bash de routine. La porte Bash destructeur (rm -rf, git reset --hard, drop table, dd if=, …) n'est pas affectée. |
GATEGUARD_EXEMPT_GLOBS | non défini (aucune exemption) | Glob séparés par des virgules ; une cible Edit/Write/MultiEdit correspondante ignore l'investigation factuelle de premier contact. Destiné aux arbres à faible valeur d'importation (tests, artéfacts générés, répertoires temporaires) où « qui importe ceci / quel schéma » n'apporte aucun signal. |
GATEGUARD_FACT_FORCE_FULL_DENIALS | 3 | Combien de refus émettent le bloc complet de quatre faits avant que les suivants ne soient condensés en une seule ligne. 0 condense dès le premier refus. |
GATEGUARD_BASH_EXTRA_DESTRUCTIVE | non défini | Motifs supplémentaires de commandes destructives, sous forme de source regex, ajoutés à l'ensemble intégré. Une regex malformée est traitée comme non définie (les motifs intégrés s'appliquent toujours) et est enregistrée une fois sur stderr. |
GATEGUARD_STATE_DIR | ~/.gateguard | Où l'état de la porte par session est conservé. Si l'état ne peut pas être persisté, la porte autorise l'opération plutôt que de boucler, et nomme cette variable dans l'avertissement. |
GATEGUARD_BASH_ROUTINE_DISABLED accepte 1, true, on, enabled,
enable ou yes (insensible à la casse et aux espaces) ; toute autre valeur
laisse la porte active.
Désactiver complètement la porte
| Variable | Effet |
|---|---|
ECC_GATEGUARD=off | Désactive GateGuard pour la session. Accepte 0, false, off, disabled ou disable. |
GATEGUARD_DISABLED=1 | Même effet. Reconnaît uniquement 1 — les orthographes ci-dessus ne s'appliquent pas ici. |
Pour un contrôle au niveau du crochet, continuez à utiliser ECC_DISABLED_HOOKS avec l'ID du crochet GateGuard.
Sémantique des globs pour GATEGUARD_EXEMPT_GLOBS
Les motifs correspondent au chemin cible complet relatif au projet. La racine du projet est
CLAUDE_PROJECT_DIR, avec repli sur le cwd de la charge utile du crochet, puis le répertoire
de travail du processus du crochet. Les globs relatifs n'exemptent jamais les cibles en dehors de
cette racine. Les globs absolus explicites correspondent au chemin cible absolu complet et peuvent
exempter délibérément des chemins en dehors du projet.
Les motifs et les chemins utilisent des séparateurs / et une correspondance en minuscules. * correspond
à l'intérieur d'un segment, ** à travers les segments, et ? à un caractère non séparateur.
**/ inclut zéro répertoire, donc **/tests/** correspond aussi à tests/foo.js.
Les motifs malformés sont ignorés sans accorder d'exemption.
Depuis 2.2.1, services/** ne couvre que l'arborescence racine des services du projet, et
*.md ne couvre que ses fichiers Markdown racine. Utilisez **/*.md pour tous les fichiers
Markdown du projet. Les exemptions non ancrées existantes peuvent nécessiter un ajustement :
{
"env": {
"GATEGUARD_BASH_ROUTINE_DISABLED": "1",
"GATEGUARD_EXEMPT_GLOBS": "**/tests/**,tests/**,**/*.test.*,**/docs/**,**/dist/**"
}
}
Option B : Paquet complet avec configuration
pip install gateguard-ai
gateguard init
Cela ajoute .gateguard.yml pour la configuration par projet (messages personnalisés, chemins ignorés, interrupteurs de porte).
Anti-patrons
- N'utilisez pas l'auto-évaluation à la place. « Êtes-vous sûr ? » obtient toujours « oui. » Cela est vérifié expérimentalement.
- Ne sautez pas la vérification du schéma de données. Les deux agents des tests A/B ont supposé des dates ISO-8601 alors que les données réelles utilisaient
%Y/%m/%d %H:%M. Vérifier la structure des données (avec des valeurs masquées) évite toute cette classe de bugs. - Ne contrôlez pas chaque commande Bash. La porte Bash de routine contrôle une fois par session. La porte Bash destructeur contrôle à chaque fois. Cet équilibre évite les ralentissements tout en capturant les vrais risques.
Meilleures pratiques
- Laissez la porte se déclencher naturellement. N'essayez pas de répondre aux questions de la porte à l'avance — c'est l'enquête elle-même qui améliore la qualité.
- Personnalisez les messages de la porte pour votre domaine. Si votre projet a des conventions spécifiques, ajoutez-les aux invites de la porte.
- Utilisez
.gateguard.ymlpour ignorer des chemins comme.venv/,node_modules/,.git/.
Compétences associées
safety-guard— Vérifications de sécurité à l'exécution (complémentaires, non redondantes)code-reviewer— Révision post-édition (GateGuard est une investigation pré-édition)