- Middleware : CORSMiddleware ajouté en dernier = plus externe = tous les codes de retour (dont 429) portent Access-Control-Allow-Origin → résout "no response / Failed to fetch" sur POST /auth/challenge - Dev mode : rate_limit_auth = RATE_LIMIT_DEFAULT (60/min) au lieu de 10/min → plus de blocage login après quelques reconnexions - app.vue : watcher activeSlug → refetch documents/décisions/protocoles/mandats → le sélecteur de workspace filtre désormais le contenu en temps réel - TDD : 4 tests middleware (RED→GREEN) + doc méthode docs/dev/tdd-methode.md - Régression : 190/190 tests verts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
145 lines
5.0 KiB
Markdown
145 lines
5.0 KiB
Markdown
# Méthode de travail TDD — libreDecision
|
|
|
|
## Principe fondamental
|
|
|
|
**Tu décris la règle métier. Claude traduit en test. Tu valides. Claude implémente.**
|
|
|
|
Jamais l'inverse. Le test est la source de vérité ; l'implémentation n'est que le moyen de le faire passer.
|
|
|
|
---
|
|
|
|
## Workflow par itération
|
|
|
|
```
|
|
1. Tu décris une règle en français naturel
|
|
→ "Si scope=personal, la décision est toujours individuelle"
|
|
|
|
2. Claude écrit le(s) test(s) — RED (le test échoue avant l'implémentation)
|
|
→ Tu valides que le test capture bien l'intention
|
|
|
|
3. Claude implémente le minimum pour que le test passe — GREEN
|
|
→ Rien de plus que ce que le test exige
|
|
|
|
4. Claude refactorise si nécessaire — REFACTOR
|
|
→ Sans casser les tests existants
|
|
|
|
5. Répétition avec la règle suivante
|
|
```
|
|
|
|
---
|
|
|
|
## Commandes de prompt
|
|
|
|
| Commande | Action |
|
|
|---|---|
|
|
| `+test` | Écrire le(s) test(s) sans implémenter |
|
|
| `+impl` | Implémenter pour faire passer les tests en attente |
|
|
| `+test+impl` | Test + implémentation d'un coup (règle simple) |
|
|
| `+règle` | Ajouter une règle au moteur existant |
|
|
| `+règle remplace` | Une nouvelle règle remplace une précédente (précise laquelle) |
|
|
| `+régression` | Vérifier qu'aucun test existant n'est cassé après un changement |
|
|
| `+résumé` | Afficher l'état des règles implémentées et en attente |
|
|
|
|
---
|
|
|
|
## Format d'une règle métier
|
|
|
|
Pour être efficace, une règle doit préciser :
|
|
|
|
```
|
|
ENTRÉES : les variables concernées et leurs valeurs
|
|
RÉSULTAT : ce que le système doit retourner ou faire
|
|
EXCEPTIONS : cas qui brisent la règle générale (si aucune, dire "aucune")
|
|
```
|
|
|
|
**Exemple :**
|
|
```
|
|
ENTRÉES : scope = "personal"
|
|
RÉSULTAT : decision_type = "individual", recommend_onchain = False
|
|
EXCEPTIONS : aucune — même si stakes = "critical", une décision personnelle reste individuelle
|
|
```
|
|
|
|
---
|
|
|
|
## Structure des tests dans ce projet
|
|
|
|
```
|
|
backend/app/tests/
|
|
test_qualifier.py ← moteur de qualification (tunnel Décider)
|
|
test_middleware.py ← rate limiter, CORS, headers
|
|
test_threshold.py ← formules WoT existantes
|
|
test_votes.py ← logique de vote
|
|
test_decisions.py ← service décisions
|
|
...
|
|
```
|
|
|
|
Chaque fichier de test correspond à un module ou un bloc fonctionnel.
|
|
Les tests d'intégration (qui touchent la DB) sont marqués `@pytest.mark.integration`.
|
|
|
|
---
|
|
|
|
## Les 4 blocs algorithmiques
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ TUNNEL "DÉCIDER" │
|
|
│ │
|
|
│ 1. QUALIFIER → nature / enjeu / réversibilité │
|
|
│ ↓ │
|
|
│ 2. ROUTEUR → individual / collective / delegated │
|
|
│ ↓ ↓ │
|
|
│ 3. PROTOCOLE → sélection formule WoT + paramètres │
|
|
│ ↓ │
|
|
│ 4. GRAVURE → recommandation on-chain (IPFS+remark) │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
Les blocs sont testés indépendamment puis en intégration.
|
|
Un changement dans le bloc 1 ne doit jamais casser silencieusement le bloc 4.
|
|
|
|
---
|
|
|
|
## Invariants fondamentaux (ne jamais casser)
|
|
|
|
Ces règles doivent avoir un test dédié et rester vertes en permanence :
|
|
|
|
1. Une décision `individual` ne génère jamais de session de vote
|
|
2. Une décision `on_chain` implique toujours `recommend_onchain = True`
|
|
3. `recommend_onchain = True` requiert `reversibility = "impossible"` **ou** `stakes = "critical"`
|
|
4. Le qualificateur ne retourne jamais un type inconnu (enum strict)
|
|
5. Un protocole WoT sélectionné doit exister en base (slug valide)
|
|
|
|
---
|
|
|
|
## Règles de régression
|
|
|
|
- Après chaque implémentation : `pytest backend/app/tests/ -v --tb=short`
|
|
- Avant tout commit : zéro test rouge
|
|
- Si un test existant casse après un nouveau changement → **stop, analyser, ne pas contourner**
|
|
- `RATE_LIMIT_AUTH` en dev = 60/min minimum (pas de blocage en développement)
|
|
|
|
---
|
|
|
|
## Où sont les règles métier documentées
|
|
|
|
| Source | Contenu |
|
|
|---|---|
|
|
| `docs/dev/tdd-methode.md` | Cette méthode |
|
|
| `docs/dev/qualifier-rules.md` | Règles du moteur de qualification (créé au fil des itérations) |
|
|
| `backend/app/engine/qualifier.py` | Implémentation du qualificateur |
|
|
| `backend/app/tests/test_qualifier.py` | Tests — source de vérité exécutable |
|
|
|
|
---
|
|
|
|
## À propos de la mémoire de contexte
|
|
|
|
Entre les sessions, Claude peut perdre le contexte des règles en cours.
|
|
Pour reprendre efficacement :
|
|
|
|
```
|
|
"Résume les règles du qualificateur implémentées jusqu'ici"
|
|
→ Claude lit test_qualifier.py et qualifier.py et synthétise
|
|
```
|
|
|
|
Les tests sont leur propre documentation. Ne pas dupliquer les règles en commentaires.
|