Hooks déterministes¶
Quatre scripts PowerShell dans scripts/ s'interposent aux moments critiques de chaque session. Ils constituent la couche déterministe qui garantit que l'état de la spirale (spiral-state.md), la traçabilité des outils, et les règles de vocabulaire sont toujours respectés — indépendamment de la volonté ou de la vigilance de l'agent IA.
Principe
Les hooks sont non-négociables : ils s'exécutent à des événements fixes, lisent stdin en JSON, et peuvent soit enrichir le contexte (SessionStart), soit refuser une action (PreToolUse), soit écrire un artefact (PreCompact, Stop). Ils ne contiennent aucune intelligence — uniquement des règles.
Vue d'ensemble¶
| Hook | Événement | Rôle principal | Peut bloquer ? |
|---|---|---|---|
hook-session-start.ps1 |
SessionStart |
Injecter spiral-state.md comme contexte système |
Non |
hook-pretooluse.ps1 |
PreToolUse |
Logger chaque usage outil + lint vocabulaire CODIR | Oui |
hook-precompact.ps1 |
PreCompact |
Sauvegarder spiral-state.md avant compaction |
Non |
hook-stop.ps1 |
Stop |
Créer le fichier session + gate traçabilité spirale | Non |
hook-session-start.ps1¶
Événement : démarrage d'une session Claude Code.
Entrée : JSON depuis stdin (objet session).
Action :
- Lit
.product/spiral-state.mds'il existe. - Émet un JSON
hookSpecificOutputcontenant unadditionalContextavec le contenu despiral-state.mdencadré par=== ETAT SPIRAL ===/=== FIN ETAT SPIRAL ===.
Effet : l'agent IA reçoit, dès son premier tour, l'état explicite de la spirale (où nous en sommes, quelle porte est active, quels objets sont LIVING). Pas de devinette possible.
hook-pretooluse.ps1¶
Événement : avant chaque appel d'outil par l'agent (Edit, Write, Bash…).
Entrée : JSON incluant tool_name, tool_input, sessionId.
Actions :
- Log JSONL : append dans
.product/.events/.tools/YYYY-MM-DD.jsonld'une ligne{ts, tool, sessionId, input}. Trace exhaustive de tout usage outil de la journée. - Lint vocabulaire CODIR : si l'outil édite un fichier
.html, scan du contenu nouvellement écrit (newStringoucontent). Liste de termes interdits : \bEHS\b,\bLBC\b→ vocabulaire interne du kernel, à remplacer par vocabulaire CODIR\binvariant\b→ technique, remplacer par « critère »\bKR[0-9]?\b→ jargon OKR, remplacer par « résultat clé »\bEpic Hypothesis\b→ jargon SAFe, à traduire
Si un terme interdit est détecté, le hook émet une décision deny avec la raison → l'outil est refusé, l'agent reçoit le message d'erreur et doit réécrire avec le vocabulaire approprié.
Effet : impossible d'infiltrer du jargon interne dans un livrable destiné au COMEX. La règle est mécanique, pas contractuelle.
hook-precompact.ps1¶
Événement : juste avant une compaction du contexte (automatique ou manuelle).
Entrée : JSON incluant sessionId, trigger.
Action :
- Cherche le fichier session du jour dans
.product/.events/. - S'il n'existe pas, en crée un (
YYYY-MM-DD-HH-mm-session-autocompact.md). - Y append un bloc
## Snapshot PreCompact — <timestamp>contenant un dump markdown complet despiral-state.md.
Effet : aucune compaction ne peut effacer la mémoire de la spirale. L'état est toujours sauvegardé dans un fichier humain-lisible, versionné, consultable.
hook-stop.ps1¶
Événement : fin de session (arrêt du processus Claude Code).
Entrée : JSON incluant sessionId, stop_hook_active.
Actions :
- Anti-boucle : si
stop_hook_active === true, sortie immédiate (évite la réentrance). - Création du fichier session : si aucun
YYYY-MM-DD-*.mdn'existe encore dans.product/.events/, crée un fichier avec en-tête + zones vides pour prompt et décisions. - Gate traçabilité spirale : vérifie la date de dernière modification de
.product/spiral-state.md. - Si pas modifié aujourd'hui → émet un
systemMessage: « TRACABILITE : spiral-state.md n'a pas été mis à jour aujourd'hui. » - Si absent → émet un
systemMessagealertant de sa création nécessaire.
Effet : impossible de clore une journée de travail sans que la spirale soit mise à jour, sans laisser de trace. Le rappel est visible à la fermeture, pas après.
Configuration¶
Les hooks sont déclarés dans .claude/settings.json du projet consommateur (ou dans .claude/settings.local.json pour un paramétrage utilisateur). Exemple :
{
"hooks": {
"SessionStart": ["pwsh -File .sdeg/scripts/hook-session-start.ps1"],
"PreToolUse": ["pwsh -File .sdeg/scripts/hook-pretooluse.ps1"],
"PreCompact": ["pwsh -File .sdeg/scripts/hook-precompact.ps1"],
"Stop": ["pwsh -File .sdeg/scripts/hook-stop.ps1"]
}
}
Décisions liées¶
- ADR 0003 — PowerShell pour les hooks : pourquoi PowerShell plutôt que Bash ou Node.
- ADR 0005 — LIVING/COLD comme invariant : pourquoi la spirale est centrale.
Voir aussi : Invariant sécurité · Stack technique.