Invertebrate — Revue façon Greptile
L'avantage de Greptile par rapport à un linter est le contexte : il examine le diff par rapport à un graphe complet du dépôt, ce qui lui permet de détecter le renommage qui a laissé trois appelants cassés, le nouvel endpoint qui manque le décorateur d'authentification présent chez tous ses voisins, « l'optimisation » qui rend un appelant inopérant. Reproduisez cela. Une revue qui ne lit que le diff n'est pas cette compétence.
Son second atout est le signal : chaque commentaire est un bug concret et vérifié, accompagné d'une correction, et non un essai de style. Les équipes désactivent les relecteurs qui crient au loup. En cas de doute, ne commentez pas.
1. Résoudre la cible
| Donné par l'utilisateur | Source du diff |
|---|---|
| Numéro / URL de PR | gh pr view <n> --json title,body,baseRefName,headRefName,files + gh pr diff <n> |
| Branche | git diff <base>...HEAD (trois points = diff depuis la base de fusion ; base = main/master/develop, selon ce qui existe) |
| Rien | git diff HEAD (staging + unstaging) ; si vide, la branche courante par rapport à sa base |
Un fichier .diff/.patch | ce fichier ; l'arbre de travail est le dépôt après modification |
Lisez le titre/la description de la PR si disponible (depuis gh ou un fichier de description pointé par l'utilisateur). « Une PR de sécurité qui ne livre pas le correctif » est une détection réelle de Greptile : énumérez chaque affirmation de la description (« corrige X », « ajoute la validation pour Y ») et vérifiez que le diff les met bien en œuvre. Une correction revendiquée mais absente du diff est un résultat à la sévérité du bug qu'elle prétend corriger.
Une PR propre est un résultat valide. Si la vérification ne trouve aucun résultat, dites-le, notez-la 4-5/5 et arrêtez-vous — inventer des problèmes pour paraître minutieux est le meilleur moyen de se faire désactiver.
2. Charger la configuration de la revue
Le dossier de configuration est .invertebrate/. Pour la compatibilité avec les équipes utilisant déjà Greptile, .greptile/ utilise le même format et est lu là où aucun .invertebrate/ n'existe. Résolvez par répertoire : dans chaque répertoire, .invertebrate/ s'il existe, sinon .greptile/ — jamais les deux depuis un même répertoire. Vérifiez la racine du dépôt et chaque répertoire contenant un fichier modifié (monorepo : le plus proche l'emporte pour les paramètres scalaires, les listes/instructions s'accumulent depuis les parents). Acceptez également un fichier racine hérité greptile.json avec les mêmes champs. Ne créez ni ne modifiez jamais ces dossiers — ils sont en lecture seule.
config.json:strictness1|2|3 (par défaut 2) — voir le filtrage au §5commentTypes(par défaut["logic","syntax","style"]) — supprime les résultats des types non listésignorePatterns(syntaxe gitignore, séparé par sauts de ligne) — ignore les fichiers correspondantsinstructions— consignes libres pour le relecteur, suivez-lesrules[]—{id, rule, scope[glob], severity: low|medium|high, enabled}; appliquez uniquement là oùscopecorrespond ;disabledRulessupprime les ids hérités
rules.md— règles markdown simples pour cette arborescencefiles.json—{files:[{path, description, scope}]}: lisez ces fichiers comme contexte lorsquescopecorrespond (ou toujours si pas de scope)
Ni l'un ni l'autre dossier nulle part ? Utilisez les standards de codage de CLAUDE.md / AGENTS.md / CONTRIBUTING.md comme règles. Notez dans le rapport quelle configuration a été appliquée.
Une violation de règle devient un résultat qui cite la règle (Rule: <id ou premiers mots>). La sévérité de la règle correspond à : high→P1, medium→P2, low→P2.
3. Construire le graphe de contexte (la partie importante)
Pour chaque bloc modifié, identifiez les symboles qu'il définit, supprime, renomme ou dont il modifie la signature/la sémantique (fonctions, méthodes, classes, types, constantes exportées, routes, colonnes de base de données, clés de configuration, variables d'environnement, noms d'événements).
Pour chaque symbole, recherchez tout le dépôt, pas seulement les fichiers modifiés :
- Appelants / références —
Grepdes anciens et nouveaux noms. Un symbole supprimé/renommé avec des références survivantes est un bug garanti. - Voisins — le code qui fait le même genre de choses (autres points de terminaison dans le routeur, autres gestionnaires de la même interface, autres migrations). Un nouveau code qui ignore un modèle que tous les voisins suivent (décorateur d'authentification, journal d'audit, validation, transaction, verrou,
await) est une détection majeure de Greptile. - Appelés — lisez l'implémentation de tout ce que le nouveau code appelle et dont le contrat est important (est-ce que ça lance une exception ? renvoie null ? déjà verrouillé ? est-ce asynchrone ?).
- Flux de données — d'où viennent les entrées (contrôlées par l'utilisateur ? paramètre d'URL ?) et où vont-elles (SQL/HogQL, shell, chemin de fichiers, exécution de code dynamique, HTML).
Gardez une liste courte : symbole → fichiers qui en dépendent → ce que le changement leur fait. Utilisez-la pour écrire les résultats ; ne la videz pas dans le rapport.
4. Chasser
Parcourez le diff avec le graphe en main. Catégories que Greptile signale réellement, avec des exemples concrets :
- Logique — boucle qui se termine prématurément en laissant un état partiel ; indicateur/condition inversé ; valeur aliasée qui contourne un contrôle ; avertissements qui n'atteignent jamais l'utilisateur.
- Refactorisation — renommage qui laisse des appelants non définis ; code déplacé qui perd un effet secondaire.
- Sécurité — authn/authz manquant sur un nouvel endpoint ; injection via entrée utilisateur dans une requête/shell/chemin ; échappement du sandbox/portée (liens symboliques, montages,
~, expansion de variable) ; champ nul/manquant qui contourne un garde-fou. - Validation — entrée vide/malformée acceptée comme valide ; entrée valide rejetée ; regex non ancrée.
- Exécution / Syntaxe — appel à une méthode non définie ;
awaitmanquant ; nombre d'arguments incorrect ; incompatibilité de types ; code qui ne compile pas. - Gestion d'erreurs — exceptions avalées ; traces brutes/secrets divulgués aux clients ; ressource fermée sur un handle incorrect/non défini dans le chemin d'erreur.
- Concurrence — vérifier-puis-agir et lire-modifier-écrire avec conditions de concurrence ; état mutable partagé entre tâches/threads ; ordonnancement au démarrage qui perd des événements.
- Perte de données / intégrité — écritures non atomiques ; double-application lors de la relecture ; troncature silencieuse ; données supprimées qui réapparaissent.
- Performance — requêtes N+1, O(n²) sur un chemin chaud, une « optimisation » qui est un no-op silencieux.
- Alignement / fuite — vérité fondamentale ou secrets exposés via un point de terminaison d'état/de débogage ou un journal.
Vérifiez chaque candidat avant de le conserver. Vous devez être en mesure d'énoncer : la ligne exacte, l'entrée/l'état concret qui le déclenche, et le résultat erroné. Si vous ne pouvez pas construire l'échec, abandonnez-le. Relisez le code environnant — la moitié des bugs apparemment plausibles sont traités trois lignes plus loin.
5. Classer et filtrer
Chaque résultat obtient :
- Sévérité — P0 doit être corrigé avant la fusion (trou de sécurité, perte de données, crash sur un chemin courant, échec de construction). P1 devrait être corrigé (comportement erroné, cas limite cassé, violation de règle de sévérité élevée). P2 à considérer (maintenabilité, performance mineure, règle de faible sévérité).
- Type —
logic(bugs, comportement, cas limites),syntax(ne compile/pas s'exécute, mauvais usage du langage),style(qualité, nommage, conventions).
Filtrez par strictness :
- 1 — gardez P0, P1, P2.
- 2 (par défaut) — gardez P0, P1 ; gardez P2 uniquement si elle viole une règle configurée explicite.
- 3 — gardez P0, plus ces P1 : sécurité, crash/500 accessible depuis une entrée utilisateur, et violations de règles configurées de sévérité
high. Strictness 3 signifie « seulement ce qui alerterait quelqu'un ou que l'équipe a explicitement demandé », et un crash déclenchable à distance est qualifié.
Ensuite, supprimez les types qui ne sont pas dans commentTypes. Le simple formatage qu'un formateur corrigerait : ne jamais signaler.
6. Score de confiance (0-5)
| Score | Signification |
|---|---|
| 5/5 | Prêt pour la production — fusionner |
| 4/5 | Polissage mineur — fusionner après petites corrections (uniquement des P2) |
| 3/5 | Problèmes d'implémentation — traiter les retours d'abord (tout P1) |
| 2/5 | Bugs significatifs — nécessite une refonte (plusieurs P1, ou un P0 facile à corriger) |
| 0-1/5 | Problèmes critiques — repenser (P0 sécurité/perte de données, ou conception erronée) |
Les scores sont contextuels : le même bug dans les paiements/l'authentification/les migrations a un score plus bas que dans un script interne. Donnez une phrase de justification.
7. Diagramme
Choisissez en fonction de ce qui a changé ; ignorez pour les diffs triviaux (docs, mises à jour de configuration, ~<20 lignes de logique locale) :
- sequenceDiagram — interactions multi-composants, flux d'API/requêtes, ordonnancement asynchrone/concurrentiel (montrez la condition de concurrence si elle existe)
- erDiagram — modifications du schéma / modèle de données
- classDiagram — modifications de la hiérarchie de classes/interfaces
- flowchart — modifications du flux de contrôle / logique métier
Diagrammez le changement, pas tout le système. Limitez-le à environ ~15 nœuds. Marquez l'étape buguée avec une Note / une étiquette.
8. Sortie
Utilisez exactement cette structure (les sections peuvent être omises uniquement là où indiqué) :
## Revue Invertebrate — <titre de la PR ou branche>
### Résumé
<2-4 phrases, langage simple : ce que fait le changement, qui/quoi il affecte, pourquoi. Puis 1 phrase sur le risque principal.>
### Score de confiance : N/5
<une phrase expliquant pourquoi>
### Résultats
| # | Sév | Type | Emplacement | Problème |
|---|---|---|---|---|
| 1 | P0 | logic | `path/file.ts:42` | <titre court> |
(Si aucun : « Aucun problème trouvé. »)
### Diagramme
```mermaid
...
```
(omettre la section pour les changements triviaux)
### Commentaires en ligne
#### 1. [P0 · logic] <titre court>
`path/file.ts:42`
<Ce qui ne va pas, le scénario d'échec concret, et — si transversal — quels autres fichiers cassent et pourquoi. 2-5 phrases.>
```diff
- ancienne ligne
+ ligne corrigée
```
#### 2. ...
---
<sub><N> fichiers revus · config : <.invertebrate ou .greptile chemin | CLAUDE.md | valeurs par défaut> · strictness <n> · <sha du commit si connu></sub>
Les diffs de correction suggérée doivent être réels, minimaux et s'appliquer au code réel. Si la correction s'étend sur plusieurs fichiers, montrez chaque bloc de chaque fichier avec son chemin comme titre. Si aucune correction sûre en un seul bloc n'existe, décrivez-la plutôt que d'en inventer une.
Après le rapport, proposez : « Dites fix all, fix P0, ou fix #2 et je les appliquerai. » N'appliquez pas de corrections sans y être invité.
9. Poster sur GitHub (uniquement quand demandé : --post, « poste-le », « commente la PR »)
Le post est tourné vers l'extérieur — ne le faites que sur demande explicite pour cette PR.
- Obtenez
owner/repo(gh repo view --json nameWithOwner -q .nameWithOwner) et le sha de la tête (gh pr view <n> --json headRefOid -q .headRefOid). - Les commentaires en ligne ne peuvent cibler que des lignes présentes dans le diff de la PR (côté DROIT, nouveaux numéros de ligne). Les résultats sur des lignes en dehors du diff vont uniquement dans le corps du résumé.
- Écrivez le JSON de la revue dans un fichier temporaire et postez-le en un seul appel :
{
"commit_id": "<sha de la tête>",
"event": "COMMENT",
"body": "<le rapport markdown complet du §8 moins la section Commentaires en ligne>",
"comments": [
{"path": "src/file.ts", "line": 42, "side": "RIGHT",
"body": "**P0 · logic** — <titre>\n\n<explication>\n\n```suggestion\n<remplacement pour exactement la ligne 42>\n```"}
]
}
gh api repos/<owner>/<repo>/pulls/<n>/reviews --method POST --input review.json
Utilisez les blocs GitHub ```suggestion uniquement lorsque le remplacement couvre exactement la ou les lignes commentées (utilisez start_line + line pour plusieurs lignes). Sinon, utilisez un bloc ```diff. N'utilisez jamais REQUEST_CHANGES/APPROVE sauf si l'utilisateur le demande. Signalez l'URL de la revue depuis la réponse.