L'instinct face aux fonctionnalités complexes est « essayons quelque chose » — mais les décisions d'architecture se cachent dans le 3ᵉ modèle, le 5ᵉ edge case. La vraie valeur du plan mode est de déplacer la conversation architecturale vers le texte avant le code. Cas réel : le système de jury communautaire de Pickful — 3 032 lignes, 119 specs au vert, un seul commit, zéro retouche architecturale ensuite.
Face à une fonctionnalité complexe, l'instinct de la plupart des gens est « je vais juste essayer un truc ».
Le problème : les systèmes complexes ont une particularité — les décisions d'architecture se cachent dans le 3ᵉ modèle, le 5ᵉ edge case, la 8ᵉ règle de points. Plonger dans le code et buter sur ces décisions à mi-chemin, puis revenir en arrière pour les changer, coûte 10× plus cher que d'en avoir discuté par écrit dès le départ.
J'ai utilisé le plan mode de Claude Code pour construire TopicReview, le système de jury communautaire de Pickful, et j'y ai vu la version extrême de cette inégalité : un seul commit, 3 032 lignes, 119 specs au vert, livré d'un seul coup. Aucun des dix et quelques commits qui ont suivi n'est une refonte architecturale — tous sont des ajustements de paramètres, des finitions d'UI, des correctifs d'edge cases. Le système tourne sans accrocs depuis, et il est aujourd'hui au cœur de la façon dont la communauté se modère elle-même.
Cet article traite de pourquoi les fonctionnalités complexes exigent d'abord le plan mode, de ce que fait réellement la phase de plan, et de quand la conversation est assez mûre pour commencer à écrire du code.
TopicReview est un vote communautaire qui décide si un post de faible qualité doit être supprimé. Une phrase pour résumer — mais le spec se déplie en couches :
Le cœur de la complexité ne se trouve dans aucune règle isolée — il est dans la façon dont les règles interagissent. Chaque règle ajoutée peut déclencher un rollback ailleurs.
Quand tu écris d'une traite, les problèmes les plus durs ne sont pas les faits visibles — ce sont les questions que tu n'as pas pensé à poser. En lisant le code de TopicReview à l'envers, il y a au moins quatre murs qui te frapperaient immanquablement si tu sautais le plan :
Règles d'éligibilité des jurés. Ça ressemble juste à User.jurors_and_judges.sample(12). Mais les vraies règles sont : exclure l'auteur du post, exclure quiconque l'a signalé, exclure quiconque a déjà voté au premier tour (pour qu'il ne vote pas aussi en appel). Trois exclusions empilées. En écrivant le modèle d'une traite, tu en oublies une ou deux.
Paiement différé des points. Un verdict remove déclenche normalement le paiement des jurés. Mais un appel peut renverser un remove — et quand il le fait, les jurés qui avaient voté conforme à l'ancien verdict se retrouvent du mauvais côté, donc les paiements doivent être recalculés selon le nouveau verdict. Donc le verdict remove doit attendre la fermeture de la fenêtre d'appel de 24 h avant de payer les jurés. Saute l'écriture de cette règle, paie avant, et tu te retrouves à vouloir récupérer des points — 10× plus pénible que de payer en retard.
Design de l'interface du job planifié. CloseTopicReviewJob ressemble à « fin de la review ». En pratique il gère trois situations :
# Expiration de la fenêtre de vote initial
CloseTopicReviewJob.set(wait_until: voting_ends_at).perform_later(review.id)
# Paiement différé des jurés après un verdict remove
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, award_juror_points: true)
# Expiration de la fenêtre d'appel
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, appeal_id: appeal.id)
Sans planification préalable, tu écris la première signature, et au cas n°2 tu te rends compte que l'interface doit changer.
Le mur le plus cher : peut-on faire appel pendant la suppression provisoire ? Quand les votes remove franchissent le seuil, le post est masqué immédiatement (provisoire), mais la review reste à l'état voting — pas decided. L'utilisateur peut-il déjà faire appel ?
decided et appealedCette seule décision remonte en arrière et change les vérifications de paramètres dans open_appeal! ainsi que la logique de la machine à états. Décider à mi-chemin = réécrire la moitié du système.
Le plan mode de Claude Code est un mode où écrire du code est interdit — Claude peut lire le repo, réfléchir aux approches, discuter avec toi, mais toute modification de fichier est hard-bloquée jusqu'à ce que tu approuves un plan.
Cette contrainte mécanique, c'est tout le sujet : elle force la conversation de niveau architecture à se tenir dans du texte.
Quelques choses que la phase de plan fait en pratique :
1. Dessiner la machine à états et les rôles. 5 états, 4 rôles (juré / juge / auteur / rapporteur), ce que chaque rôle peut et ne peut pas faire dans chaque état — tout tient en quelques lignes de markdown. Quelques lignes vs des dizaines de fichiers. Le coût du changement est distant de deux ordres de grandeur.
2. Parcourir le flux de chaque rôle :
Là où la marche coince, une question cachée surgit : « les jurés voient-ils les votes des autres jurés ? », « que peut faire l'auteur pendant la suppression provisoire ? »
3. Interroger les edge cases. La phase de plan ne conçoit pas le « chemin normal » — elle pose délibérément les questions qui ne remontent pas d'ordinaire :
finalize en même temps — la course double-t-elle le paiement ? (Ajouter un champ juror_points_awarded pour l'idempotence.)95 % de ces questions n'émergent pas naturellement quand on écrit du code. La phase de plan te force à les traiter une par une.
4. Le grand livre des points. Le système de points est trop complexe pour que la discussion suffise — il faut vraiment dessiner la table : chaque flux de points avec son déclencheur, son montant, sa voie de rollback. Une fois le grand livre équilibré, tous les edge cases (remboursement provisoire, remboursement d'appel, bonus) se réconcilient.
Un critère dur :
closed (keep / remove / warn × avec appel / sans × provisoire / pas) — tu la racontes de bout en boutQuand tu atteins ce seuil, écrire du code devient traduire le plan en Ruby.
La première livraison du système :
d162f1e Add community moderation system with jury/judge review and appeals
63 files changed, 3032 insertions(+)
119 specs, 0 failures
63 fichiers, 3 032 lignes, 119 specs au vert. Livré d'un seul coup.
Les dix et quelques commits suivants confirment que l'architecture a tenu :
Apply legacy penalty (1pt) for posts created before 2026-03-26
Fix topic review appeal bugs: window mismatch and verdict not updated
Add topic_removed status for posts removed by community review
Default to keep verdict when review expires with zero votes
Reduce provisional removal penalty to 1pt during trial period
Allow topic creator to withdraw active reviews
Add handled tab to jury dashboard, fix tabs styling
Chacun est ajustement / fix / finition / petite feature. Aucun n'est « retourner redessiner la machine à états » ou « le modèle de points doit changer ». Le squelette était entièrement correct.
C'est la vraie récompense du plan : l'exécution reste ininterrompue. Pas de « attends, comment ce chemin est géré » — le plan l'a déjà couvert. Pas de « je n'avais pas pensé à cet edge case » — la phase de plan l'a demandé. Pas de « cette interface doit être refaite » — le plan l'a déjà tranché.
Des heures à écrire du code, en ne faisant qu'une chose : traduire un design clair sur le clavier.
Toutes les tâches ne méritent pas un plan :
Le gain du plan mode vient de baisser le coût de réécriture. Si la tâche n'a pas de risque de réécriture, le plan n'est que du surcoût.
« Réfléchir avant d'agir » sonne comme un conseil de caractère. Le plan mode, ce n'est pas ça.
Le plan mode consiste à faire en sorte que la conversation de niveau architecture se tienne là où 10 mots peuvent la changer — pas là où 30 fichiers doivent changer.
Sous la complexité, il faut inverser ce vieux proverbe de l'industrie « words are cheap, code is expensive » — ce n'est pas « écris le code d'abord et on verra » (ça ne vaut que quand l'écart de coût est petit), c'est utiliser cet écart de coût : déplacer la conversation chère en amont, dans le médium bon marché.
3 000 lignes en un seul commit, c'est une sensation très forte. Pas parce que j'ai écrit vite — parce que le plan a transformé l'« écriture » en acte purement mécanique.