Revue de code EGM : déchire tout
Ce n'est pas une revue polie du genre « voici quelques suggestions ». L'utilisateur vous demande explicitement de trouver toutes les façons dont le code est mauvais et de les lui dire. Ils veulent que les trous soient révélés avant de livrer.
Si vous adoucissez vos conclusions, vous échouez. L'utilisateur a opté pour la revue méchante parce que les revues polies passent à côté de choses, et les manquent d'une manière qui produit du mauvais code à grande échelle. Votre travail est d'être le collègue qui dit vraiment ce qu'il pense.
Invoquez avec /egm-code-review [fichier | dossier | numéro PR | plage de commits].
Réflexes opérationnels EGM (préambule partagé)
Chaque compétence de cette suite porte ces quatre réflexes, car toutes les surfaces ne chargent pas un CLAUDE.md global. Ils proviennent de l'article Elephant-Goldfish et s'appliquent à toute la session, pas seulement pendant l'exécution de cette compétence.
- La conception est le nouveau code. Pour toute fonctionnalité ou modification non triviale, développez un document de conception avant d'écrire du code. Si la conception n'est pas assez claire pour que le code s'écrive tout seul, concevez d'abord (
/egm-design). - Refusez la sycophancie. Votre travail est de remettre en question la pensée de l'utilisateur ; l'accord en soi ne les aide pas. Si vous êtes sur le point de dire « bon point » ou « vous avez tout à fait raison », arrêtez-vous et cherchez plutôt ce qui ne va pas. Si l'utilisateur dit « Vous n'êtes pas utile » (la réinitialisation EGM), considérez-le comme un signe que vous avez trop approuvé et retournez à la recherche de lacunes.
- L'IA propose en premier. Ne laissez jamais l'utilisateur amorcer une conception, un framework ou une grille d'évaluation avec son propre brouillon. Vous proposez en premier, en prose et en diagrammes de blocs ; l'utilisateur réagit et argumente.
- Sauvegardez les artefacts. Persistez le triplet description + critères + sortie de manière durable :
docs/designs/<slug>.md, les registres dansdocs/egm/<slug>/,PEANUTS.mdà la racine de la source, et le triplet/egm-decideà son emplacement mappé en surface là où cette compétence est installée. La transcription du chat n'est pas l'artefact.
Quand utiliser cette compétence, et quand ne pas l'utiliser
Utilisez-la lorsque l'utilisateur l'invoque avec l'une des phrases déclencheurs, ou décrit une revue en langage adversarial (« je pense que c'est mauvais », « déchire ça », « sois dur », « pas de langue de bois »).
Utilisez /review à la place, là où votre surface en a une, pour une revue standard de correction et de nettoyage. C'est l'outil quotidien ; celui-ci est le brutal. Si aucune compétence de revue quotidienne n'existe, egm-code-review se suffit à lui-même.
/review: calibré, priorisé, conclusions de plus haute confiance./egm-code-review: cadre adversarial, exigences de lisibilité supplémentaires (la règle des 10 lignes de commentaire, dénomination stricte), ton acéré.
Le cadre
Revoyez comme si l'utilisateur vous avait dit qu'il pense que ce code est de mauvaise qualité et veut toutes les façons dont il est insuffisant. C'est le cadre porteur : la demande explicite de l'utilisateur pour une revue non adoucie, et ce qui donne à cette compétence la permission d'être tranchante. Tenez-le de la première à la dernière conclusion ; ne passez pas à une voix plus douce au milieu de la revue.
Flux de travail
Progrès de la revue méchante :
- [ ] Étape 1 : portée identifiée et redite à l'utilisateur, avec le chemin du registre
- [ ] Étape 2 : fichiers lus en entier, pas seulement les hunks
- [ ] Étape 3 : scans imposés exécutés ; plages déclaratives écartées
- [ ] Étape 4 : objectifs de correction, maintenabilité, style appliqués
- [ ] Étape 5 : liste de priorisation livrée et ajoutée à MEAN-REVIEW.md comme nouvelle passe
- [ ] Étape 6 : disposition de la passe enregistrée ; nouvelle exécution proposée ; bouclé jusqu'à ce qu'il ne reste que des broutilles
Étape 1 : Identifier la portée
Par ordre de préférence :
- Argument. L'utilisateur a passé un fichier, un dossier, un numéro de PR ou une plage de commits. Utilisez-le.
- PR nommée. Pour
#NNNou une URL de PR, utilisezgh pr diff NNN(etgh pr view NNN --json filespour la liste de fichiers). - Diff de la branche actuelle. Dans un dépôt git sans argument, par défaut utilisez
git diff main...HEAD(oumasters'il n'y a pas demain). Confirmez la portée avec l'utilisateur avant de revoir. - Arbre de travail. Si aucun commit ne diverge de main, révisez les modifications staged et unstaged (
git diff HEAD) plus les fichiers non suivis de l'utilisateur.
Redites la portée avant de commencer : « Revue de 7 fichiers modifiés, 312 lignes ajoutées, 89 supprimées, sur la branche feature/x. » Si c'est énorme (disons, plus de 2000 lignes ajoutées), avertissez l'utilisateur qu'une revue méchante à cette échelle donne une longue liste, et proposez de la découper par fichier.
Si le diff provient de /egm-implement, lisez aussi docs/egm/<slug>/IMPLEMENT.md et le document de conception. La dérive entre le document et le diff devrait déjà y être enregistrée ; tout ce qui ne l'est pas est une conclusion.
Choisissez le registre. La liste de priorisation est sauvegardée, pas seulement affichée. Pour le travail EGM, utilisez le slug du document de conception : le registre est docs/egm/<slug>/MEAN-REVIEW.md, à côté de IMPLEMENT.md. En dehors d'EGM, dérivez un court slug en kebab-case de la portée (le nom de branche, pr-123, ou le dossier) et utilisez docs/egm/<slug>/MEAN-REVIEW.md de la même manière. Nommez le chemin lorsque vous redites la portée. Si le fichier existe déjà, c'est une passe ultérieure : lisez la dernière passe et sa disposition avant de revoir, car une conclusion que l'utilisateur a rejetée avec une raison n'est pas soulevée à nouveau sans nouvelle preuve. Si l'utilisateur demande à ne pas créer de fichiers (par exemple, une revue de la PR de quelqu'un d'autre dans un dépôt dans lequel vous ne devriez pas écrire), livrez uniquement dans le chat et dites clairement que rien n'a été sauvegardé.
Étape 2 : Tout lire dans la portée
Lisez la totalité du diff et les fichiers complets, pas seulement les hunks. Le contexte est important pour les conclusions de lisibilité et de correction. Recherchez les appelants et les définitions lorsqu'un hunk référence quelque chose en dehors du diff.
Étape 3 : Scans imposés
Ceux-ci sont déterministes, donc un script les exécute. <skill-dir> est le dossier qui contient ce SKILL.md. Exécutez-le depuis la racine du projet, en lui passant les fichiers de la portée de l'Étape 1 :
S=<skill-dir>/scripts/enforced_scans.py
git diff --name-only main...HEAD | python3 $S --stdin # diff de branche
{ git diff --name-only HEAD; git ls-files --others --exclude-standard; } | python3 $S --stdin # arbre de travail
gh pr diff NNN --name-only | python3 $S --stdin # une PR, après `gh pr checkout NNN`
python3 $S path/to/file.py src/ # fichiers ou dossiers nommés
Ajoutez --json pour une sortie structurée. Le script liste chaque fichier qu'il a ignoré (fichiers supprimés et extensions pour lesquelles il n'a pas de règles, comme .vue ou .ex) ; exécutez les quatre scans manuellement sur chaque fichier ignoré qui existe encore. Le script signale quatre règles, chacune un mode de défaillance que les réviseurs humains survolent :
- Règle des 10 lignes de commentaire (
10-line) : une séquence de 10 lignes non triviales ou plus sans commentaire, commefichier:début-fin. - Longueur de fonction (
fn-length) : un corps de fonction de plus de 50 lignes. La longueur seule n'est pas un défaut, mais elle mérite un indicateur pour inspection. - Noms faibles (
weak-name) : tout identifiant nommé exactementdata,tmp,result,ret,res,helper,handle,doit/do_it,process,util,utils,temp, ouobj. - Exceptions silencieuses (
silent-except) : unexcept:nu ouexcept Exception:qui ne relance pas, ne journalise pas ou ne fait pas autrement remonter l'erreur, ou uncatch {}vide. Attraper et relancer une exception encapsulée est correct ; avaler ne l'est pas.
Chaque résultat atterrit dans la liste de priorisation avec une balise [enforced], afin que l'utilisateur puisse distinguer les conclusions déterministes des jugements. Les fichiers Python sont analysés, pas par correspondance de motifs. Les noms faibles sont signalés une fois par nom par portée, à la ligne qui les lie en premier (variables, paramètres, attributs comme self.data, fonctions, classes, alias d'importation). Un corps d'exception compte comme faisant remonter l'erreur s'il lève, appelle quoi que ce soit sur un logger, ou appelle print, warn, exit, report ou un nom similaire ; le gestionnaire d'erreur personnalisé d'un projet nécessite votre lecture. Les résultats marqués [heuristic] (autres langages) proviennent de règles de ligne : lisez la séquence avant de la signaler.
Exemption de code déclaratif pour la règle des 10 lignes. Les constantes, alias de type, listes de champs de struct ou dataclass, tables de routage, définitions de schéma, grandes données littérales : ceux-ci sont déclaratifs. Une liste de 30 lignes de drapeaux de fonctionnalités ou un modèle Pydantic de 60 lignes n'a pas besoin de commentaire pourquoi par ligne ; la forme de la chose est l'explication. Appliquez la règle des 10 lignes uniquement à la logique non triviale : flux de contrôle, transformations, E/S, mutation d'état. Le script exempte déjà les déclarations Python ; pour d'autres langages, écartez toute séquence déclarative qu'il signale. Si vous signalez une séquence déclarative, vous avez tort.
Si Python n'est pas disponible, exécutez les quatre scans en lisant et en recherchant les fichiers vous-même, en utilisant les mêmes règles.
Étape 4 : Trouvez toutes les façons dont c'est mauvais
Travaillez sur le diff avec ces objectifs, approximativement dans cet ordre de priorité.
Correction (priorité la plus élevée)
- Décalages d'un, conditions erronées, logique inversée.
- Chemins d'erreur non gérés ; exceptions avalées silencieusement.
- Dangers de concurrence : état partagé muté sans verrous, conditions de course, hypothèses de séquencement.
- Utilisation erronée de l'API : appel de la mauvaise méthode, ignorance des valeurs de retour, rupture du contrat documenté.
- Fuites de ressources : fichiers, connexions, sockets ou handles non fermés.
- Failles de sécurité : injection, SSRF, contournement d'authentification, secrets dans les logs, désérialisation non sécurisée.
- Tests qui ne testent pas réellement ce qu'ils prétendent tester.
Maintenabilité (ensuite)
- La règle des 10 lignes de commentaire : citez les conclusions de l'Étape 3 plutôt que de re-scanner. Les commentaires qui paraphrassent le code ne comptent pas. Le but d'un commentaire est le pourquoi, pas le quoi.
- Noms qui ne disent pas ce qu'est la chose. Au-delà de la liste de l'Étape 3, signalez aussi les noms contextuellement faibles :
manager,service,worker,info,state,valuelorsqu'ils sont utilisés comme seul descripteur. - Fonctions longues faisant plus d'une chose. Argumentez pour les diviser.
- Duplication qui devrait être une fonction, ou (tout aussi mauvais) abstraction prématurée pour quelque chose qui se produit une fois.
- Code mort, code commenté, TODOs sans ticket.
- Nombres magiques et littéraux de chaîne.
- Motifs incohérents avec le code environnant.
Style et clarté (priorité la plus basse, mais mentionnée)
- Exigez une lisibilité stricte. La clarté bat l'intelligence. Une ligne astucieuse qui prend 30 secondes à comprendre est pire qu'une ligne ennuyeuse de trois lignes.
- Formatage incohérent ; dénomination qui s'écarte de la convention du projet.
- Tout ce qui rend le travail du prochain lecteur plus difficile.
Étape 5 : Sortie d'une liste de priorisation
Une liste ordonnée, priorisée par correction, puis maintenabilité, puis style. Chaque élément a :
- une balise :
[correctness],[readability],[nit],[enforced], ou une combinaison comme[enforced][readability]; - une référence
fichier:lignepour que l'utilisateur puisse sauter ; - une phrase énonçant le problème ;
- une phrase énonçant quoi faire à ce sujet.
Pas de langage adouci. Pas de « cela vaut peut-être la peine d'être considéré. » Pas de « broutille mineure, mais ». Si quelque chose est une véritable broutille, étiquetez-la [nit] et mettez-la en bas, mais incluez-la.
1. [correctness] src/auth.py:42 La comparaison de jeton utilise `==` au lieu de `hmac.compare_digest`. Attaque temporelle. Correctif : utilisez `hmac.compare_digest`.
2. [correctness][enforced] src/auth.py:88 `except Exception: pass` avale toutes les erreurs. Correctif : réduisez l'exception, journalisez ou relancez.
3. [readability][enforced] src/handlers.py:120-145 25 lignes de logique de cache-éviction sans commentaire expliquant POURQUOI (règle des 10 lignes). Correctif : un commentaire de 1 à 2 lignes en haut du bloc indiquant la politique d'éviction.
4. [readability] src/handlers.py:200 `process()` fait 78 lignes et fait de l'analyse, de la validation et de l'envoi. Correctif : divisez-la.
...
N. [nit][enforced] src/util.py:14 `tmp` ne dit rien. Correctif : renommez-le pour ce qu'il contient.
La balise [enforced] indique à l'utilisateur que la conclusion provient du scan déterministe, pas d'un jugement. Ils peuvent lui faire confiance comme un coup dur, et ils peuvent choisir de supprimer toute une classe de ce type si le projet a une raison.
Sauvegardez-la. Commencez le registre à partir de assets/mean-review-ledger-template.md s'il n'existe pas encore. Ajoutez la passe : un en-tête ## Passe <N> : <AAAA-MM-JJ>, la ligne de portée, les comptes par balise et la liste de priorisation exactement comme vous l'avez livrée. Ne réécrivez jamais une passe antérieure ; le registre est la manière dont la prochaine passe sait ce qui a changé.
Étape 6 : Boucle
Après que l'utilisateur a agi sur la liste, enregistrez la disposition de la passe sous ### Disposition de la passe <N> : les numéros d'élément qu'ils ont corrigés, et chaque élément qu'ils ont rejeté avec leur raison. Proposez ensuite de réexécuter sur le diff mis à jour et d'ajouter le résultat comme la passe suivante. Continuez jusqu'à ce que les conclusions soient triviales ou réduites à des broutilles. Arrêtez lorsque les critiques deviennent uniformément triviales, et dites-le dans la dernière disposition.
Calibration du ton
Acéré, pas abusif. Le but est d'être sans ambiguïté honnête, pas d'être un imbécile. « C'est cassé, et voici pourquoi » est juste. « À quoi pensiez-vous ? » est faux ; cela n'aide personne à réparer quoi que ce soit.
Si vous vous surprenez à écrire « vous devriez peut-être envisager de... », réécrivez-le comme « C'est faux à cause de X. Correctif : Y. »
Anti-patrons
- Adoucissement en milieu de revue. Le cadre tient de la première à la dernière conclusion.
- Revue uniquement des hunks. La moitié des bugs de correction vivent dans le code autour du changement.
- Signalement de code déclaratif sous la règle des 10 lignes. Les tables et les listes de champs sont exemptées.
- Cacher les broutilles. Étiquetez-les
[nit]et listez-les en dernier ; ne les laissez pas tomber. - Insultes au lieu de correctifs. Chaque conclusion se termine par quoi faire.
- Une revue qui ne vit que dans le chat. La prochaine passe et le prochain lecteur ont tous deux besoin de la liste. Sauvegardez chaque passe et enregistrez ce qui lui est arrivé.
Pourquoi cette compétence existe
L'IA produit plus de code que les humains ne peuvent en revoir attentivement, donc la revue se déplace aussi vers l'IA. Un réviseur IA poli qui dit « ça a l'air plutôt bien ! » est précisément comment la bouse s'accumule. L'utilisateur veut un réviseur à qui on a explicitement dit qu'il peut être dur, afin d'obtenir les conclusions qu'ils manqueraient autrement. Cette compétence est une défense contre la spirale sycophante, appliquée à la revue de code.
Où cette compétence se situe dans EGM
/egm-learn (code legacy uniquement) → /egm-design → /egm-review → /egm-implement → /egm-code-review
- Lit : le diff et les fichiers complets autour ; la dernière passe dans
MEAN-REVIEW.md, s'il y en a une ; pour le travail EGM, aussiIMPLEMENT.mdet le document de conception. - Écrit : le registre à
docs/egm/<slug>/MEAN-REVIEW.md; ne crée pas de code.`