Méthode de travail avec Claude Code
Le dépôt est aussi un kit Claude Code : règles, hooks, agents et skills encadrent la façon dont le labo est conçu, codé, testé et validé. Fichiers : CLAUDE.md, .claude/settings.json, .claude/hooks/, .claude/agents/, .claude/skills/.
Règles non négociables (CLAUDE.md)
- Plan d'abord : aucun code avant un
PLAN.mdapprouvé par Stéphane. L'approbation est la ligne de statut passée àAPPROUVÉavec son nom et la date, écrite par lui seul. - Aucun tiret cadratin (U+2014), nulle part : code, docs, commentaires, commits.
- Langues : prose de documentation en français ; code, identifiants, commentaires de code et messages de commit en anglais.
- Commits au format Conventional Commits (
feat:,fix:,docs:,test:,refactor:,chore:). - Gate pytest : aucun sprint soumis à validation sans
/gateau vert. - LiteLLM, seule sortie vers les LLM ; versions
1.82.7et1.82.8interdites (vol d'identifiants). - Répartition des modèles : agents
architectetsecurity-reviewersur Opus ;implementerettest-gatesur Sonnet. - Souveraineté : tout auto-hébergé, en local via Docker Compose.
- Données synthétiques ou publiques uniquement ; aucune donnée du client, ni dans le dépôt, ni envoyée à un modèle.
- Périmètre strict : ni fonctionnalité, ni priorisation, ni phasage non demandés.
S'y ajoutent les règles globales du NUC (~/.claude/CLAUDE.md) : consommer les briques partagées, ne jamais supprimer un service retiré d'un docker-compose (le commenter avec un en-tête), journaliser toute action d'infrastructure dans ~/Documents/central/README.md.
Cycle d'un sprint
flowchart LR
A["/plan-sprint composant"] --> B["agent architect<br/>PLAN.md au statut BROUILLON"]
B --> C["Relecture par Stéphane<br/>décisions tranchées"]
C --> D["Stéphane passe le statut<br/>à APPROUVÉ (nom, date)"]
D --> E["agent implementer<br/>code du plan"]
D --> F["agent test-gate<br/>tests pytest"]
E --> G["/gate"]
F --> G
G -->|vert| H["message de commit proposé<br/>commit validé par Stéphane"]
G -->|rouge| E
/plan-sprint <composant ou objectif>délègue à l'agentarchitect, qui litCLAUDE.mdpuis la skill de référence, remplitPLAN.mddepuis.claude/skills/plan-sprint/template.mdet s'arrête. Le statut resteBROUILLON.- Stéphane relit, tranche les décisions ouvertes, puis remplace lui-même la ligne de statut.
- L'agent
implementercode le plan approuvé, et seulement lui ; l'agenttest-gateécrit et lance les tests. Si le plan est incomplet ou contradictoire, l'implémentation s'arrête et propose une modification dePLAN.md, qui repasse enBROUILLON. /gate: tests, scans de conventions, revue de sécurité, conformité au plan, message de commit proposé (voir tests-et-gate.md).- Stéphane valide le commit ; Claude Code demande confirmation avant
git commitetgit push.
Le PLAN.md actuel couvre les quatre composants en un seul plan, sans ordre ni phasage, avec un avenant Traefik du 2026-10-23. Ses décisions ouvertes ont été déléguées par Stéphane le 2026-10-22 (« coche toutes les cases pour moi ») ; elles sont reprises dans decisions.md.
Hooks
Déclarés dans .claude/settings.json en PreToolUse sur Write|Edit|MultiEdit|Bash, écrits en Python avec la seule bibliothèque standard (helpers communs dans .claude/hooks/_common.py). Un code de sortie 2 bloque l'appel et renvoie le message à Claude.
| Hook | Effet | Mode scan |
|---|---|---|
no_em_dash.py |
Refuse tout contenu écrit ou toute commande contenant U+2014 | --scan <chemin> : liste les lignes fautives, sortie 1 s'il y en a |
guard_litellm.py |
Refuse LiteLLM 1.82.7 et 1.82.8 dans les manifestes, fichiers de verrouillage, fichiers Compose, Dockerfiles, fichiers .yml, .yaml, .toml, .txt, .cfg, .ini, et dans les commandes d'installation ou d'image (pip, uv, poetry, docker...). Accepte l'exclusion !=1.82.7,!=1.82.8. La prose peut citer ces versions |
--scan <chemin> sur les manifestes |
plan_gate.py |
Refuse l'écriture de tout fichier hors PLAN.md, CLAUDE.md, README.md, .gitignore, docs/ et .claude/ tant que PLAN.md n'est pas approuvé ; refuse toute écriture de la ligne d'approbation par Claude, par outil de fichier ou par Bash |
aucun |
Limite connue : plan_gate.py contrôle les outils d'écriture, pas les redirections shell (cat > fichier, sed -i). Personnalisation : BANNED_RE dans guard_litellm.py, FREE_PATHS dans plan_gate.py.
Permissions (.claude/settings.json)
| Type | Règles |
|---|---|
| Autorisé sans confirmation | docker compose ps, logs, up, config ; pytest, python -m pytest ; dbt ; git status, git diff, git log, git add ; scans des deux hooks |
| Confirmation demandée | git commit, git push, docker compose down |
| Interdit | Lecture de .env et de secrets/ ; modification de .claude/hooks/ et de .claude/settings.json |
Les réglages personnels vont dans .claude/settings.local.json (ignoré par git).
Agents
| Agent | Modèle | Outils | Rôle |
|---|---|---|---|
architect |
Opus | Read, Grep, Glob, WebFetch, WebSearch, Write, Edit | Conçoit : PLAN.md et fichiers sous docs/ seulement ; appuie chaque choix de fidélité sur une page Snowflake citée ; marque « à vérifier » le non vérifié ; laisse ouvertes les décisions non tranchées ; statut toujours BROUILLON |
implementer |
Sonnet | Read, Grep, Glob, Write, Edit, MultiEdit, Bash | Implémente un plan approuvé ; lit la skill du composant ; tout appel LLM par LITELLM_BASE_URL ; aucun secret ; propose le message de commit sans commiter |
test-gate |
Sonnet | Read, Grep, Glob, Write, Edit, Bash | Tests unitaires et de contrat sans réseau (faux client LiteLLM), tests integration sautés sans services ; vérifie la forme des retours, pas la qualité ; teste preuves et confidence_class sur chaque table standardized |
security-reviewer |
Opus | Read, Grep, Glob, Bash | Revue du diff sans rien modifier : secrets, sortie LLM, versions LiteLLM, données, réseau, dépendances épinglées, droits Polaris ; rapport en tableau (point, statut, fichier et ligne, détail) |
Skills
| Skill | Déclenchement | Rôle |
|---|---|---|
plan-sprint |
Commande /plan-sprint <composant> |
Rédaction de PLAN.md par architect, gabarit template.md |
gate |
Commande /gate |
Gate de fin de sprint |
new-cortex-function |
Commande /new-cortex-function <NOM> |
Ajout d'une fonction AI_* depuis sa page Snowflake (contrat, tests, UDF, macros, façades) |
lakehouse-conventions |
Chargée par Claude quand la tâche touche le socle ou les couches de données | Référence du socle, des couches, de l'intake et de la portabilité |
cortex-compat |
Chargée quand la tâche touche cortex_lab ou une fonction AI_* |
Référence de cortex_lab, contrats dans references/contracts.md |
forecast-t0 |
Chargée quand la tâche touche la prévision | Référence du modèle t0, des entrées, de la table forecast |
Les trois premières ont disable-model-invocation: true : elles ne se déclenchent que sur commande.
Fidélité Snowflake
Chaque choix de fidélité s'appuie sur une page de documentation Snowflake citée par URL dans PLAN.md (section « Référence Snowflake ») ou dans contracts.md, avec une date de lecture. Ce qui n'a pas été lu est marqué « à vérifier ». Une fonction Cortex absente de contracts.md ne s'implémente pas sans passer par /new-cortex-function, qui écrit d'abord son contrat.
Écrire dans docs/
docs/ fait partie des chemins libres de plan_gate.py : la documentation peut s'écrire sans plan approuvé. Elle reste soumise aux hooks no_em_dash.py et aux tests de conventions (aucun tiret cadratin, aucun motif de secret réel).