Que fait démêler ?
Une base de code enchevêtrée est un tas de décisions que personne n'a prises. L'IA a écrit ce que la prochaine invite demandait, n'a jamais refusé et n'a jamais proposé de repenser, donc le dépôt contient désormais trois façons de faire chaque chose et aucune trace du pourquoi. Démêler signifie prendre chacune de ces décisions une fois, la consigner par écrit, et faire en sorte que le code et ses vérifications soient en accord.
Vous faites le mapping, les preuves et les modifications. L'humain prend les décisions.
État cible
Le travail est terminé lorsque les cinq conditions suivantes sont remplies :
- Une seule façon de faire chaque chose : authentification, accès aux données, erreurs, configuration, journalisation.
- Les tests échouent lorsque le comportement est incorrect.
- Chaque élément survivant a une raison que quelqu'un peut énoncer.
- Les décisions sont consignées là où la prochaine personne ou agent les lira.
- Des vérifications automatisées empêchent l'enchevêtrement de revenir.
Si la base de code répond déjà à ces critères, dites-le et arrêtez-vous. Inventer du travail est un échec d'audit.
Règles pour chaque phase
- Le registre est l'état.
UNTANGLE.mdà la racine du dépôt enregistre la couverture, les constatations, les décisions et la progression. Lisez-le d'abord et mettez-le à jour avant la fin de votre tour. Un long nettoyage survit à votre fenêtre de contexte ; le registre est ce qui assure la continuité. S'il existe, reprenez à partir de lui au lieu de refaire un audit. - Preuve ou ce n'est pas une constatation. Chaque constatation porte
fichier:ligneet la commande ou l'observation qui la démontre. "Ça sent le fouillis" n'est pas une constatation. - Vous proposez, l'humain décide. Rien n'est supprimé, fusionné ou déclaré gagnant sans une ligne de registre approuvée. Recommandez une valeur par défaut pour chaque décision afin que l'approbation soit rapide.
- La structure et le comportement changent dans des commits séparés. Une refactorisation qui corrige aussi un bug ne peut être vérifiée ni comme l'un ni comme l'autre.
- Ne rapportez que ce que vous avez exécuté. Enregistrez les commandes avec leurs résultats réels. Enregistrez ce que vous avez lu attentivement, ce que vous avez seulement cartographié, et ce que vous n'avez jamais ouvert.
- Soustrayez. Pas de réécriture, pas de nouvelle dépendance, pas de nouvelle couche d'abstraction, pas de compatibilité. Le nombre de lignes doit diminuer.
- Secrets. Si vous trouvez un identifiant actif, arrêtez-vous et dites à l'humain de le révoquer. N'imprimez jamais sa valeur. Ne réécrivez jamais l'historique vous-même.
Phases
Audit → Triage → Refactor → Pérenniser, dans cet ordre. Sans registre, commencez par Audit. Avec un registre, continuez à partir de la phase qu'il enregistre. Un argument nommant une phase ou un chemin réduit le travail. Il ne saute jamais Audit, car Refactor n'agit que sur les constatations approuvées.
1. Audit : lecture seule
Ne modifie rien sauf UNTANGLE.md. Commencez-le à partir du modèle dans templates.md.
- Référence. Trouvez les vraies commandes d'installation, de construction, de test, de lint et de vérification de types et exécutez-les. Enregistrez les résultats textuellement. Un dépôt qui ne se construit pas à partir de son README est une constatation numéro un.
- Cartographie avant lecture. Liste des fichiers, tailles, points d'entrée, direction des imports, activité de l'historique git. Choisissez ensuite où lire attentivement, d'abord les plus risqués : authentification, argent, écritures de données, infrastructure. Enregistrez la couverture par chemin.
- Chassez en utilisant
catalog.md. Exécutez les outils d'analyse de manière éphémère (npx,uvx,go run) pour que les dépendances du projet restent intactes. - Testez les tests. Choisissez trois règles métier. Pour chacune, modifiez la règle pour qu'elle renvoie une réponse incorrecte sans lever d'exception, exécutez la suite, restaurez le fichier avec
git restore, et confirmez quegit statusest propre. Enregistrez si un test a remarqué le changement. - Évaluez le tableau de bord dans
templates.md. Chaque vérification est réussite, échec, ou "non vérifiable à partir du dépôt" avec la question que l'humain doit répondre. - Rapportez et arrêtez-vous. Principales constatations par risque, ce qui va bien, ce qui n'a pas été couvert.
2. Triage : décider
- Avant de lister les correctifs un par un, cherchez la décision unique qui dissout plusieurs constatations. Demandez-vous à quoi ressemblerait ce code si ses exigences avaient été connues dès le départ.
- Pour chaque préoccupation avec des implémentations concurrentes, recommandez un gagnant et donnez la raison : le plus de points d'appel, le mieux testé, correspond à la convention du framework.
- Marquez chaque constatation comme garder, corriger ou supprimer. Classez par risque : probabilité de dommage × degré de dépendance.
- Ordonnez les tranches. Filet de sécurité d'abord, puis suppressions (peu coûteuses, et elles réduisent tout ce qui suit), puis consolidation, puis restructuration.
- Présentez un tableau, obtenez une approbation en une seule passe, et arrêtez-vous jusqu'à l'obtenir. Enregistrez les rejets comme
wontfixavec la raison.
3. Refactor : une tranche à la fois
Travaillez sur une branche nommée untangle/<sujet>. Ne poussez jamais. Pour chaque tranche approuvée :
- Filet. Les tests couvrent le comportement que cette tranche touche, et vous les avez vus échouer sous une rupture délibérée. Si ce n'est pas le cas, écrivez d'abord des tests de caractérisation : figez ce que le code fait aujourd'hui, bugs inclus. Consignez chaque bug comme une nouvelle constatation au lieu de le corriger silencieusement.
- Modifiez une préoccupation.
- Vérifiez avec les commandes de référence complètes. En cas d'échec, corrigez la modification ou annulez la tranche.
- Commitez avec les identifiants des constatations, mettez à jour le registre, et continuez à la tranche suivante sans demander.
Arrêtez-vous et demandez quand une tranche nécessite une décision que le registre ne contient pas.
"Mort" signifie prouvé inaccessible : verdict d'un outil statique plus une recherche d'accès dynamique via des chaînes de caractères, réflexion, routes, noms DI, configuration, cron, templates, API publique et appelants en dehors du dépôt. Tout ce qui n'est pas prouvé est suspect et va à l'humain.
4. Pérenniser : rendre cela pérenne
- Pour chaque décision, demandez-vous si une machine peut l'appliquer. Si oui, ajoutez la règle de lint, la limite d'import, l'étape CI ou le test. Les règles en prose sont pour ce que les machines ne peuvent pas vérifier.
- Écrivez
AGENTS.mdà partir des décisions : commandes, la seule façon par préoccupation avec un pointeur vers un fichier exemple, et où va le nouveau code. Gardez-le assez court pour être lu à chaque session. SiCLAUDE.md,.cursorrulesou des fichiers similaires existent, faites-en un la source et faites pointer les autres vers lui. - Écrivez un ADR pour chaque décision qui a choisi un gagnant.
- Rendez le setup du README depuis un checkout propre vrai, et commitez un modèle d'environnement.
- La CI exécute les commandes de référence et échoue en cas d'échec. La protection de branche et le routage des alertes vivent en dehors du dépôt, donc listez-les pour l'humain.
- Ré-évaluez, enregistrez avant et après, et laissez les éléments non terminés listés dans le registre.
Quand vous êtes tenté
| Pensée | Faites plutôt |
|---|---|
| "Je vais corriger ça pendant que je suis là" | Ajoutez une constatation. Les modifications non approuvées sont la façon dont l'enchevêtrement a été créé. |
| "Le test est obsolète, je vais ajuster l'assertion" | Un test rouge après un changement structurel signifie que le changement a modifié le comportement. Corrigez le changement ou annulez-le. |
| "Rien ne référence ceci, c'est mort" | Prouvez-le contre l'accès dynamique, ou marquez-le comme suspect. |
| "Un wrapper maintient les anciens appelants en fonctionnement" | Mettez à jour les appelants. Un shim est un surplus avec un nouveau nom. |
| "Ceci devrait juste être réécrit" | Tranches. Une réécriture jette tout comportement que les tests ne couvrent pas. |
| "J'ai couvert la base de code" | La couverture est ce que le registre dit que vous avez lu. |
| "Le contexte devient long, je vais finir vite" | Écrivez le registre, dites ce qui reste, arrêtez-vous. |
| "La suite passe, donc ça marche" | Une réussite ne prouve que ce que l'étape 4 de l'audit a montré que les tests peuvent détecter. |