Fransys
Tous les cours
M8
1 h 30
Pédagogie complète

Specs-as-code et PRD optimisés pour l'IA

Plan Mode, PRD agentiques, AGENTS.md, TDD inversé.

Product managers, lead devs, dirigeants tech

Pourquoi ce module

Un PRD écrit pour des humains (prose libre, ambiguïté acceptée) n'est pas optimal pour un agent IA. En pratique, nous avons observé que beaucoup d'équipes rencontrent le problème suivant : "Pourquoi Claude ne finit pas la feature ?" Réponse : le PRD manquait de critères d'acceptance mesurables, de garde-fous explicites, et de test plan.

Inversement, les équipes qui adoptent specs-as-code (PRD structuré, non-ambigus, testables) obtenient des taux de réussite first-shot >90 %. Ce module enseigne le craft : écrire un PRD que un agent IA peut exécuter en autonomie, sans ambiguïté, avec critères de succès vérifiables.

Prérequis : maîtriser Claude Code et ses modes (voir J1), avoir suivi M1–M3 sur les agents, connaître le basics de TDD (Test-Driven Development).

Objectifs pédagogiques

À l'issue de ce module, vous serez capable de :

  1. Maîtriser les modes de permission Claude Code (6 modes : default, plan, acceptEdits, auto, dontAsk, bypassPermissions) et le workflow plan → implémentation → /clear
  2. Écrire un PRD AI-ready : structure sections (Goal / Non-Goals / Constraints / Acceptance Criteria / Test Plan), exemples et contre-exemples
  3. Appliquer TDD inversé : écrire les tests d'acceptance AVANT le PRD, laisser Claude implémenter jusqu'à passing
  4. Gérer AGENTS.md vs CLAUDE.md : contrat agent (conventions projet) vs instructions outil (runtime)
  5. Automatiser plan → review → exec : workflow sans étapes manuelles perdues
  6. Évaluer la qualité d'un PRD : checklist "AI-ready ready" avant de lancer exec
  7. Mesurer le taux de réussite first-shot et itérer PRD structure

Plan détaillé

  1. Modes de permission + workflow plan → implémentation → /clear
  2. Filosofie specs-as-code
  3. Structure PRD AI-ready
  4. Goal, Non-Goals, Constraints
  5. Acceptance Criteria testables
  6. Test Plan écrit avant implémentation
  7. Anti-patterns PRD courants
  8. AGENTS.md vs CLAUDE.md
  9. Workflow : Linear ticket → PRD → exec
  10. Atelier : PRD TDD complet
  11. Pièges et best practices

Modes de permission & workflow plan → implémentation → /clear

Précision importante. Claude Code a 6 modes de permissiondefault, plan, acceptEdits, auto, dontAsk, et bypassPermissions — que l'on bascule au clavier (Shift+Tab) ou via --permission-mode. /clear et /compact sont des commandes, pas des modes. Ce qui suit décrit le workflow recommandé : analyser en mode plan, implémenter en acceptEdits (ou bypassPermissions), puis /clear entre deux tâches.

Remarque : le cycle Shift+Tab montre les 5 modes principaux (defaultplanacceptEditsbypassPermissionsauto), avec dontAsk accessible via CLI. Le mode auto (disponible depuis v2.1.83) élimine les prompts de permission routiniers par un classifieur, tandis que dontAsk refuse automatiquement tout appel d'outil qui demanderait une confirmation.

On entre en mode plan de deux façons : Shift+Tab (cycle des modes) ou la commande /plan [description]/plan bascule en mode plan, et une description optionnelle démarre directement sur la tâche (ex. /plan corrige le bug d'auth). On sort du plan en l'approuvant (le mode passe en acceptEdits) ou via Shift+Tab. En revanche, il n'existe pas de commande /exec : l'implémentation se déclenche par la validation du plan.

Étape PLAN (mode plan) : analyser sans modifier

Claude lit le PRD, le projet, pose des questions, puis livre une analyse structurée : risques, dépendances, chronologie, ressources. Pas d'implémentation — en mode plan, les écritures sont bloquées. Vous reviewerez avant d'implémenter.

Claude Code explique le rôle du mode plan dans le terminal
L'esprit du mode plan, résumé par Claude : analyser et présenter un plan d'action avant d'exécuter, sans modifier de fichiers tant que rien n'est validé.
# Basculer en mode plan : Shift+Tab (jusqu'à "plan mode"), puis :
> Ajouter authentification SSO avec Okta

Claude répond :

## Analyse de faisabilité

### Chronologie estimée
1. Setup Okta tenant (1h)
2. Intégrer SDK Next.js (2h)
3. Protéger routes (1h)
4. Tests E2E (2h)
Total: ~6h

### Dépendances
- Okta org + API creds (blocking)
- Environnement test (ready)

### Risques
- Token expiration corner case
- Multi-tenant scope creep (non-goal? confirmer)

### Recommandations
1. Commencer par OIDC flow seul, laisser les rôles pour V2
2. Ajouter rate limiting côté Okta (anti-replay attacks)
Claude Code en mode plan : analyse du code et questions structurées avant de proposer un plan
Le mode plan en action (, via Shift+Tab ou /plan) : Claude analyse sans rien modifier et peut poser des questions structurées avant de finaliser — ici la portée d'un toggle de thème. Le plan part dans un fichier (~/.claude/plans/…), zéro écriture dans le code tant qu'il n'est pas validé.

Vous reviewez : "Correct, mais ajoute aussi audit logs de connexion". Claude note, puis vous validez le plan pour passer à l'implémentation.

Prompt d'approbation du plan dans Claude Code : proceed avec auto mode, validation manuelle, ou affiner
La porte plan → exec : le plan rédigé, Claude demande l'autorisation. Yes, auto mode (→ acceptEdits) lance l'implémentation, manually approve edits valide chaque diff, ou on affine le plan. Rien ne s'exécute avant cette validation.

Étape IMPLÉMENTATION (mode acceptEdits ou bypassPermissions) : implémenter en autonomie

Claude Code propose une modification de fichier sous forme de diff avant validation
L'implémentation, concrètement : Claude propose chaque changement sous forme de diff (rouge/vert) que vous validez — en acceptEdits, ces diffs sont appliqués automatiquement.
# Approuver le plan (le mode passe en acceptEdits), ou Shift+Tab → "accept edits", puis :
> Implémente le plan validé

Claude implémente : crée branches, commits, tests, pushe. En fin, reporte status. (acceptEdits auto-accepte les éditions de fichiers ; bypassPermissions saute aussi les confirmations de commandes — à réserver aux environnements de confiance.)

Commande /clear : réinitialiser le contexte

Après 10h de travail, le contexte est saturé (500 K tokens). /clear oublie tout l'historique et redémarre frais. Économise énormément de tokens. (Pour condenser sans tout perdre, préférez /compact.)

Pattern optimal :

Chargement du schéma…

Workflow optimal: plan → review → exec → clear

Filosofie specs-as-code

Plan architectural détaillé avec équerre et crayon technique
Specs-as-code : des plans rigoureux avant construction, comme en architecture

Hypothèse classique : écrire le code est plus long que l'écrire le spec. Donc optimiser le spec saving time.

Hypothèse specs-as-code : écrire un PRD vraiment bon pour un agent prend autant de temps que commencer à coder, mais la qualité du résultat est 10x meilleure. Optimiser pour réussite first-shot vs vitesse spec writing.

Corollaire : un agent ne demande pas "clarification" pendant l'exécution. Il fini ou il rate. Donc la spec doit être complète.

Métriques :

  • PRD "classique" : 30 min à écrire, 4h à coder, 6h à fixer bugs = 10h30 total
  • PRD "specs-as-code" : 1h30 à écrire, 2h to code, 0.5h to fix = 4h total. Gain 60 %.

Chargement du schéma…

ROI specs-as-code: PRD rigoureux = moins de bugs et de temps total

Structure PRD AI-ready

Voici la structure recommandée :

# PRD: [Titre court, impératif]

**Auteur** : [Nom]  **Date** : [YYYY-MM-DD]  **Status** : [Draft/Ready/In Progress]

## 1. Goal (2–3 phrases max)

Quoi faire, pourquoi, pour qui. Une seule phrase marketing.

Exemple OK:
"Ajouter authentification SSO Okta pour les clients Enterprise, 
réduire support password-reset de 30 requêtes/jour à 2."

Exemple MAUVAIS (ambigü):
"Implémenter SSO. Okta c'est cool."

## 2. Non-Goals (3–5 bullets)

Quoi **ne pas** faire. Critique pour éviter scope creep.

OK:
- Ne pas implémenter self-service user provisioning (future V2)
- Ne pas supporter SAML 1.0 (legacy, descoped en 2024)
- Ne pas changer la structure de la table users

MAUVAIS (trop vague):
- SSO simple seulement

## 3. Constraints (2–4 bullets)

Limites hard que Claude doit respecter.

OK:
- La migration doit être backward-compatible (users sans SSO continuent avec password)
- Temps de déploiement max 10 min (prod tranquillité)
- Aucun data loss sur les 50K users actuels

MAUVAIS:
- "Faire vite"

## 4. Acceptance Criteria (4–8, testables)

Conditions précises pour déclarer "fait".

Format **Gherkin-ish** (Given/When/Then) ou assert-style.

OK:
  • WHEN un utilisateur Enterprise clique SSO → redirect Okta, alors back après auth
  • THEN la session JWT stocke user.id, email, okta_group_ids
  • AND les routes /dashboard protégées retournent 401 sans JWT valide
  • AND user peut toggle "Prefer SSO" dans settings
  • AND si SSO fail, fallback password login with 5min rate limiting
  • AND audit logs tracent chaque SSO success/fail (pour compliance)
  • AND nouvelle colonne users.sso_okta_id exists, nullable

MAUVAIS:
  • SSO fonctionne
  • Users peuvent login
  • C'est secure (vague)

## 5. Test Plan (détails avant implémentation)

Écrire les tests **avant** de coder (TDD). Claude lira ceci et implémentera jusqu'à passing.

```typescript
describe("SSO Okta", () => {
  describe("Authorization flow", () => {
    test("redirects to Okta authorize endpoint with correct params", () => {
      // GIVEN user clicks "Sign in with Okta"
      // WHEN GET /api/auth/okta/login
      // THEN response.status == 302 && response.location includes Okta auth URL
    });

    test("callback with valid code exchanges for token", () => {
      // GIVEN user approved on Okta
      // WHEN GET /api/auth/okta/callback?code=AUTH_CODE
      // THEN fetch /oauth/token with code+code_verifier (PKCE)
      // AND store JWT in httpOnly cookie
    });
  });

  describe("User lookup / provisioning", () => {
    test("existing user with okta_id logs in directly", () => {
      // GIVEN user.okta_id = "okta_123" exists
      // WHEN SSO completes with Okta ID "okta_123"
      // THEN login succeeds, no new user created
    });

    test("new Okta user creates account auto (if Enterprise tier)", () => {
      // GIVEN org.tier == "Enterprise"
      // WHEN SSO with new Okta email
      // THEN create user, link okta_id, return JWT
    });

    test("non-Enterprise Okta user rejected", () => {
      // GIVEN org.tier == "Starter"
      // WHEN SSO with new Okta user
      // THEN return 403 "SSO not available for your plan"
    });
  });

  describe("Fallback & security", () => {
    test("failed SSO falls back to password login", () => {
      // GIVEN Okta API is down
      // WHEN SSO fails
      // THEN show password login form
    });

    test("rate limiting: 5 failed logins = 15min lockout", () => {
      // GIVEN 5 failed auth attempts on one email
      // WHEN 6th attempt
      // THEN return 429 + "Try again in 14m 30s"
    });
  });

  describe("Audit & compliance", () => {
    test("each SSO action logged to audit_logs table", () => {
      // WHEN SSO success / fail / fallback password
      // THEN audit_logs.create({
      //   event: "okta_sso_success" | "okta_sso_fail",
      //   user_id, email, okta_id,
      //   ip, user_agent,
      //   timestamp
      // })
    });
  });
});

Anti-patterns PRD courants

Anti-patternSymptômeFix
Goal ambiguClaude implémente une feature différenteSpécifier 1 customer persona + 1 metric de succès
Pas de Non-GoalsScope creep : Claude ajoute "et aussi les rôles, et aussi audit..."Lister 5 choses explicitement NON incluses
Constraints manquantsClaude casse backward-compat / crée schema instableLister 3–4 contraintes hard (perf, compat, data)
AC trop vague"Secure", "fast", "user-friendly"Gherkin format ou assertions testables
Test plan absentClaude implémente sans référence, tests flousÉcrire test cases AVANT PRD (TDD)
Dependencies non-mentionnéesClaude bloque sur "comment maker requête Okta ?"Lister libraries, APIs, credentials required
Erreur paths ignoréesFeature marche en happy path, crash en edge casesDétailler 3–5 failure modes dans AC

AGENTS.md vs CLAUDE.md

⚠️ À désamorcer d'emblée : AGENTS.md n'écrase pas CLAUDE.md, et Claude Code ne le lit même pas de lui-même. C'est l'idée reçue la plus répandue sur le sujet. La règle officielle tient en une phrase : Claude Code lit CLAUDE.md, pas AGENTS.md. Aucune notion d'override n'existe entre les deux.

AGENTS.md est une convention inter-agents : un contrat projet que plusieurs outils de code (Cursor, Codex, etc.) savent lire. Beaucoup de dépôts en ont déjà un. Pour que Claude Code le prenne en compte, on l'importe depuis le CLAUDE.md, avec éventuellement les consignes propres à Claude en dessous :

# ./CLAUDE.md — point d'entrée pour Claude Code
@AGENTS.md

## Claude Code
Utiliser le mode plan pour toute modification sous `src/billing/`.

Un symlink (ln -s AGENTS.md CLAUDE.md) convient si vous n'avez rien à ajouter — mais il exige des droits administrateur ou le mode développeur sous Windows, donc l'import reste le choix par défaut.

Chargement du schéma…

Le montage réel : CLAUDE.md est le point d'entrée, il importe AGENTS.md. Tout est concaténé, rien n'est écrasé.

Ce qui va dans quel fichier :

# ~/.claude/CLAUDE.md — vos préférences, tous projets confondus
Ne jamais utiliser pkill de façon large (risque de tuer l'IDE).
Toujours entourer les chemins de guillemets dans les commandes git.
# AGENTS.md — contrat du projet, lisible par tous les agents
Ce projet utilise Next.js 15 (breaking changes depuis votre cutoff).
Lire node_modules/next/dist/docs/ avant de coder.
Structure : /app (router), /lib (utils), /styles (CSS modules).
Anti-pattern : prop drilling sur 3 niveaux ou plus → refactor obligatoire.
Tests : ./tests/*.test.ts, exécutés avant chaque commit.

Le modèle mental correct : il n'y a pas de hiérarchie d'override mais une concaténation. Claude Code remonte l'arbre des dossiers et empile tout ce qu'il trouve, de la racine vers le dossier de lancement — les consignes les plus proches de votre point de lancement sont donc lues en dernier. En cas de contradiction entre deux fichiers, Claude arbitre au jugé, la consigne la plus spécifique l'emportant généralement : deux règles qui se contredisent, c'est un bug de configuration à corriger, pas un mécanisme de priorité sur lequel s'appuyer.

📎 Détail complet des emplacements, de l'ordre de chargement, des imports @chemin et des règles à portée de chemin (.claude/rules/) : voir J1 — Mémoire projet.

🆕 /doctor sait maintenant tailler vos CLAUDE.md (v2.1.205 et v2.1.206). Deux évolutions qui touchent directement ce module :

  • v2.1.205 : /doctor n'est plus un simple diagnostic — c'est un checkup complet qui diagnostique et corrige. /checkup en est l'alias.
  • v2.1.206 : il propose désormais de tailler les CLAUDE.md versionnés en coupant ce que Claude pourrait déduire du code lui-même.

Cette seconde vérification mérite d'être lancée en atelier, parce qu'elle matérialise le principe central de ce module : un CLAUDE.md n'est pas de la documentation. « Le projet utilise TypeScript », « les tests sont dans /tests », « on utilise Tailwind » — Claude le voit en ouvrant le dépôt. Chaque ligne de ce type est payée en tokens à chaque requête, dilue les consignes qui comptent, et devient fausse dès que le code bouge sans que personne ne pense à la corriger.

Ce qui mérite d'y rester, c'est ce qui n'est pas déductible : une contrainte non écrite dans le code (« la prod tourne sur Node 20, pas 22 »), une décision et son motif (« on n'utilise pas l'ORM sur la table events, trop lent en batch »), un piège appris à ses dépens. Le test à faire passer à chaque ligne : « Claude trouverait-il ça tout seul en trente secondes de lecture ? » — si oui, elle dégage.

C'est aussi ce que recommande publiquement l'équipe Claude Code, sous une forme plus radicale : supprimer périodiquement son CLAUDE.md et ne réintroduire que ce dont l'absence fait mesurablement échouer le modèle — même discipline d'ablation que celle décrite en J1 pour le system prompt. Un fichier de consignes n'est jamais fini : il grossit tout seul et ne maigrit que si on le décide.

Workflow : Linear ticket → PRD → exec

Scenario complet :

1. Linear ticket arrive (e.g., #2841 "Add Okta SSO")
   Assigné à Claude via workflow automation

2. Claude en mode plan
   Lit ticket + codebase + AGENTS.md + MEMORY.md
   Produit PRD draft avec questions

3. Product manager reviewe PRD draft
   "Non-Goals OK, mais ajoute audit logs à AC"
   Commente dans Linear

4. Claude reformate PRD

5. Manager approuve le plan (→ acceptEdits)
   ↓
   Claude exécute (3–4h)
   → Push branch, créer PR
   → Run tests, fix failures
   → Ready for human review

6. Code review : engineer regarde diff
   "Looks good, merge?"
   
7. Merge to main

Atelier : PRD TDD complet (90 min)

Vous prenez un vrai Linear ticket (ou user story), écrivez le PRD AI-ready, exécutez en mode plan, recevez feedback, puis exec.

Livrable :

  1. Test plan (écrire en premier, TDD style)

    • 10–15 test cases en Gherkin ou TypeScript
    • Couvrir happy path + edge cases
    • Sauvegardé dans ./tests/feature.spec.ts (vide, juste déclarations)
  2. PRD AI-ready

    • Goal (1 phrase claire)
    • Non-Goals (5 items)
    • Constraints (3–4)
    • AC (Gherkin format, testables)
    • Test Plan (copie des tests above)
    • Dependencies (libraries, APIs, config needed)
  3. Execution

    • Mode plan (Shift+Tab) → Analyze
    • Review feedback (ajuster PRD si needed)
    • Approuver le plan (→ acceptEdits) → Implementation
    • Mesurer : combien de tests passent ? first-shot rate ?
  4. Audit

    • Vérifier zéro ambiguïté dans PRD
    • Zéro scope creep (Claude n'a fait que AC listed)
    • Tests tous passants (ou justifier pourquoi pas)

Critères de succès :

  • ✅ PRD écrit avant exécution (TDD spirit)
  • ✅ Test plan structure + détaillé
  • ✅ Goal 1 sentence, Non-Goals 5 items, Constraints 3–4
  • ✅ AC en format Gherkin (Given/When/Then)
  • ✅ Plan mode passe sans ambiguïté
  • ✅ Exec mode complète feature
  • ✅ >= 80 % tests passing first-shot

Pièges courants

PiègeSymptômeCure
Ambiguïté dans AC"Fais ça secure" → Claude implémente basiqueSpécifier explicitement (TLS 1.3+, HMAC-SHA256, audit logs)
Non-Goals floueScope creep : Claude ajoute stuff non-demandéLister 5 choses ne pas faire, signer off product
Pas de error pathsFeature crash en edge caseDans Test Plan : "when API fails, return 503"
Dépendances manquantesClaude bloque sur "je peux pas appeler Okta API"Lister libs, API keys, credentials needed
Tests pas assez spécifiques"Test authentication" ne dit rienGherkin : "WHEN wrong password THEN 401"
Long delay plan → execContexte change entre les deux, réduit cohérenceExec max 2h après plan (ou replan)
Pas de rollback planFeature cassée en prod, comment revenir?Dans Non-Goals : "No rollback strategy this sprint" OK si confirmé

Pour aller plus loin

Récapitulatif

À retenir absolument :

  1. Specs-as-code wins on ROI : 1h30 PRD + 2h code + 30min fixes beats 30min PRD + 4h code + 6h debug
  2. TDD first : écrire tests avant PRD, Claude implémente jusqu'à passing
  3. Non-Goals explicites : liste 5 choses à NE PAS faire, scope control
  4. AC testables : Gherkin format (Given/When/Then), zéro ambiguïté
  5. Plan avant exec : review risques, dépendances, avant lancer full exec
  6. AGENTS.md = contrat inter-agents, importé par le CLAUDE.md (jamais un override : la concaténation est additive)
  7. Mode clear après chaque grosse feature = contexte frais