Le developpeur qui tape "add user authentication" dans Claude Code obtient un resultat different a chaque fois. Peut-etre du JWT. Peut-etre des cookies de session. Peut-etre un flux OAuth2 complet avec refresh tokens et PKCE. L'agent ne sait pas ce que vous voulez parce que vous ne le lui avez pas dit. Vous lui avez donne une direction, pas une destination.
Les developpeurs que je vois obtenir des resultats coherents et livrables de Claude Code partagent une habitude : ils ecrivent une spec avant de confier du travail a l'agent. Pas un roman. Pas un ticket Jira avec trois phrases de contexte. Un document concret qui definit a quoi ressemble "termine" avant que quiconque ecrive une ligne de code.
Ce n'est pas une sagesse nouvelle. Le developpement spec-first precede l'IA de plusieurs decennies. Mais avec les agents, le cout de sauter la spec est plus eleve et le benefice d'en ecrire une est plus grand. Un developpeur humain peut s'arreter en pleine implementation et demander "attends, tu voulais dire l'auth par mot de passe ou le SSO ?" Un agent en choisira un silencieusement et continuera. Le temps que vous remarquiez, il a construit la mauvaise chose, et vous avez passe 20 minutes a relire du code qui doit etre jete.
Cet article parcourt le cycle de vie pilote par les specs que j'utilise avec Claude Code chaque jour : comment ecrire des specs contre lesquelles les agents peuvent executer, le checkpoint plan-avant-le-code qui attrape les malentendus tot, et un protocole de verification plus rigoureux que "ca compile."
Pourquoi "construis-le" echoue avec les agents
Soyons precis sur le mode d'echec. Quand vous donnez a Claude Code une instruction vague, trois choses tournent mal :
Des hypotheses silencieuses. L'agent comble chaque lacune de votre spec avec ses propres hypotheses. Parfois elles sont raisonnables. Parfois non. Vous ne saurez pas dans quelle categorie vous etes jusqu'a la lecture du resultat. Avec des instructions vagues, vous finissez par lire le resultat plus attentivement que le temps qu'il vous aurait fallu pour ecrire une spec.
Des resultats non reproductibles. Executez le meme prompt vague deux fois et vous obtenez deux implementations differentes. Pas juste des noms de variables ou du formatage differents. Des decisions architecturales differentes. Des bibliotheques differentes. Des strategies de gestion d'erreurs differentes. Si vous ne pouvez pas reproduire le resultat, vous ne pouvez pas construire un processus fiable autour.
La revue devient le goulot d'etranglement. Quand l'agent prend toutes les decisions, vous devez verifier toutes les decisions. Un diff de 400 lignes ou vous comprenez chaque choix prend 5 minutes de revue. Un diff de 400 lignes ou l'agent a choisi le schema de base de donnees, la forme de l'API, les codes d'erreur et la logique de validation prend 30 minutes parce que vous reconstruisez la spec a partir de l'implementation.
La solution n'est pas de meilleurs prompts. C'est de concentrer en amont les decisions qui comptent dans un document contre lequel l'agent peut executer.
Le cycle de vie pilote par les specs
Le workflow comporte cinq phases. Chacune a une condition d'entree claire et une condition de sortie claire.
Phase 1 : Brainstorming. Vous explorez l'espace du probleme. Quelles sont les contraintes ? Quelles approches existent ? Qu'avez-vous deja essaye ? C'est la ou vous pensez a voix haute, seul ou avec Claude Code en mode conversationnel. La condition de sortie : vous avez une approche preferee et vous comprenez les compromis.
Phase 2 : Revue. Vous mettez l'approche a l'epreuve. Qu'est-ce qui pourrait mal tourner ? Quels cas limites existent ? Est-ce que ca entre en conflit avec quelque chose deja dans le codebase ? Si vous travaillez avec plusieurs agents, c'est la qu'un agent d'architecture ou un second avis est precieux. La condition de sortie : vous etes confiant que l'approche est solide.
Phase 3 : Spec. Vous ecrivez ce que vous avez decide. Enonce du probleme, approche proposee, fichiers a modifier, criteres d'acceptation verifiables mecaniquement et un plan de test. C'est le contrat. La condition de sortie : quelqu'un (humain ou agent) pourrait lire cette spec et savoir exactement quoi construire et comment le verifier.
Phase 4 : Implementation. L'agent execute contre la spec. Pas contre une idee vague. Contre un document concret avec des criteres testables. La condition de sortie : l'agent affirme avoir termine et a publie des preuves de verification.
Phase 5 : Verification. Vous (ou un agent QA) confirmez que l'implementation correspond a la spec. Pas "est-ce que ca a l'air correct" mais "est-ce que ca satisfait chaque critere d'acceptation." La condition de sortie : chaque critere est verifie, et ceux qui echouent retournent a la Phase 4.
L'idee cle : les phases 1-3 sont peu couteuses. Elles prennent 10-20 minutes pour une fonctionnalite de taille moyenne. La phase 4 prend le temps que necessite l'implementation. La phase 5 prend 5-10 minutes. Sauter les phases 1-3 ne fait pas gagner 10-20 minutes. Ca vous coute le temps de relire, deboguer et refaire du travail qui partait dans la mauvaise direction.
A quoi ressemble une bonne spec pour agent
Voici un vrai template de spec. Pas une user story. Pas un document de requirements produit. Un document de travail qui dit a un agent exactement quoi construire.
## Problem
The filter bar resets when switching workspaces. Users lose their
filter state and have to re-apply filters every time they switch.
## Approach
Persist filter state per-workspace in localStorage. Key the stored
state by workspace database path so filters don't bleed across
workspaces.
## Files to Modify
- lib/local-storage.ts: Add getWorkspaceFilters / setWorkspaceFilters
- components/filter-bar.tsx: Read initial state from localStorage,
write on every change
- hooks/use-workspace.ts: Trigger filter restore on workspace switch
## Acceptance Criteria
1. Select workspace A, set filters to status=open + type=bug
2. Switch to workspace B. Filters reset to defaults.
3. Switch back to workspace A. Filters restore to status=open + type=bug.
4. Close the browser tab, reopen. Filters for the active workspace
are still applied.
5. bd list --status=open --type=bug output matches the filtered table.
## Out of Scope
- Server-side filter persistence
- Filter presets / saved filter combinations
- URL-based filter state (query params)
## Test Plan
- Unit test: getWorkspaceFilters returns stored value for matching
workspace path
- Unit test: setWorkspaceFilters writes correct key format
- Manual test: steps 1-5 from acceptance criteria above
Remarquez ce que cette spec contient et ne contient pas. Elle n'explique pas comment fonctionne localStorage. Claude Code le sait. Elle ne justifie pas pourquoi nous avons choisi localStorage plutot que les URL params. Ca s'est passe pendant le brainstorming. Elle liste chaque fichier que l'agent doit toucher, ce qui signifie que si l'agent commence a modifier des fichiers hors de cette liste, c'est un signal d'alerte. Elle inclut une section hors-perimetre, qui empeche l'agent de faire du gold plating.
Les criteres d'acceptation sont la partie la plus importante. Chacun est une action concrete avec un resultat observable. Pas "les filtres doivent persister." C'est ambigu. "Basculer vers le workspace A, verifier que les filtres sont status=open + type=bug" est testable. Un agent peut executer ca. Un reviseur QA peut le verifier.
Le pattern plan-avant-le-code
Voici un protocole qui attrape la majorite des erreurs d'implementation avant qu'elles ne deviennent du code : exiger que l'agent publie son plan d'implementation avant d'ecrire quoi que ce soit.
En pratique, ca ressemble a un commentaire structure sur la tache. Avant que l'agent n'ouvre un fichier, il ecrit exactement ce qu'il compte faire.
PLAN: Persist filter state per-workspace using localStorage.
1. Add workspace-scoped storage helpers to lib/local-storage.ts:
- getWorkspaceFilters(dbPath: string): FilterState | null
- setWorkspaceFilters(dbPath: string, filters: FilterState): void
- Key format: "beadbox:filters:{dbPath}"
2. Update components/filter-bar.tsx:
- On mount, read stored filters for current workspace
- On every filter change, write to localStorage
- Accept databasePath as prop (currently not passed)
3. Update hooks/use-workspace.ts:
- On workspace switch, emit event that filter-bar listens for
- Filter-bar reads new workspace's stored filters on event
4. Threading databasePath:
- filter-bar needs databasePath from the workspace context
- Will add it to the WorkspaceProvider context value
Files: lib/local-storage.ts, components/filter-bar.tsx,
hooks/use-workspace.ts, components/workspace-provider.tsx
Test: Unit tests for storage helpers, manual test of all 5
acceptance criteria.
Ca prend environ 30 secondes a l'agent. Ca vous prend environ 2 minutes a lire. Et dans ces 2 minutes, vous pouvez detecter des problemes qui prendraient 20 minutes a corriger apres l'implementation :
- L'agent touche-t-il des fichiers hors de la spec ? (Ajouter workspace-provider.tsx n'etait pas dans la spec. C'est acceptable ou c'est du scope creep ?)
- L'approche a-t-elle du sens ? (Utiliser un event emitter pour les changements de workspace est peut-etre surdimensionne. Un simple changement de prop pourrait suffire.)
- Manque-t-il des etapes ? (Qu'en est-il du nettoyage des anciennes entrees localStorage quand un workspace est supprime ?)
Le plan est un checkpoint. S'il parait correct, dites a l'agent de continuer. S'il parait incorrect, corrigez le plan. Dans les deux cas, vous avez investi 2 minutes au lieu de 20.
