pr-splitter — découper une grosse PR en morceaux reviewables
La branche originale est du matériel source, jamais une victime : prenez-en un snapshot, construisez des PRs plus petites à partir d'elle délibérément, et gardez un registre local de ce qui est allé où.
Annoncez au démarrage : « Utilisation de la compétence pr-splitter — découpage de {branch} en PRs plus petites. »
Ne jamais utiliser de commandes git interactives (git restore -p, git add -i, git rebase -i) — elles bloquent dans cet environnement. Chaque extraction ci-dessous est non-interactive.
Étape 1 : Snapshot avant de toucher à quoi que ce soit
git status --porcelain # doit être vide ; sinon, ARRÊT — committez ou stashez d'abord
BASE=$(git merge-base origin/main HEAD)
git branch backup/original-$(git branch --show-current)
Ne supprimez pas ou ne réécrivez pas la branche originale jusqu'à ce que la découpe soit entièrement déployée.
Étape 2 : Inventorier la PR originale
git diff --stat $BASE...HEAD
git diff --name-only $BASE...HEAD
git log --oneline $BASE..HEAD
Classifiez chaque fichier modifié dans exactement une unité de review :
| Unité | Exemples |
|---|---|
| prep / refactor | renommages, extractions, pas de changement de comportement |
| API / changements de type | signatures, modèles, types générés |
| behavior | la vraie logique de fonctionnalité/correction |
| tests | tests nouveaux ou modifiés |
| docs / métadonnées | AGENTS.md, docs, changelogs |
| generated / lockfiles | pnpm-lock.yaml, types générés |
Étape 3 : Créer le scratchpad
Écrivez .ai/scratch/pr-split.md (gitignored — ne le committez jamais) :
# PR split — {original branch}
Backup: backup/original-{branch} · Base: {BASE sha}
## PRs planifiées
1. {branch-name} — scope: … — files/hunks: … — verify: … — status: …
## Intention originale restante
- …
## Drift notes (date / branch / ce qui a changé et pourquoi)
- …
Étape 4 : Choisir la forme de découpe
| Situation | Forme |
|---|---|
| Le travail ultérieur dépend du travail antérieur | PRs empilées (chacune branchée sur la précédente) |
| Les changements sont vraiment indépendants | PRs parallèles en dehors de main |
| Un changement prep partagé débloque du travail indépendant | PR fondatrice + suites parallèles |
| Incertain | Empilées — les erreurs de dépendance remontent comme conflits, pas comme builds cassées |
Règles : ne jamais séparer les tests du code qu'ils vérifient ; ne jamais découper un comportement sur deux PRs par limite de fichier ; chaque PR doit compiler et passer ses tests seule.
Étape 5 : Extraire non-interactivement
Démarrez chaque PR sur la bonne base (main, ou la PR précédente de la pile) :
git checkout -b {pr-branch} {base}
Fichiers entiers (le fichier appartient entièrement à cette PR) :
git checkout backup/original-{branch} -- path/to/file.ts
Partie d'un fichier (le fichier mélange des changements pour différentes PRs) :
git diff {base} backup/original-{branch} -- path/to/file.ts > .ai/scratch/extract.patch
# Éditez .ai/scratch/extract.patch : gardez les lignes d'en-tête du fichier (---/+++),
# SUPPRIMEZ tous les @@-hunks qui appartiennent à une PR différente, gardez ceux que vous voulez.
git apply .ai/scratch/extract.patch
Si git apply échoue (incompatibilité de contexte), ne le combattez pas : ouvrez le fichier et faites les changements voulus à la main, en utilisant le patch comme référence. Puis supprimez le fichier patch.
Committez chaque extraction avec un message conventionnel et cochez-la dans le scratchpad, en notant exactement quels fichiers/hunks ont bougé.
Étape 6 : Vérifier chaque PR indépendamment
Pour chaque branche PR, avant de l'ouvrir :
pnpm exec biome check --write --no-errors-on-unmatched <changed paths>
pnpm exec turbo run typecheck --filter=<pkg> # par package touché, jamais tout le repo
pnpm --filter <pkg> test
Une PR qui ne compile que sur un frère unmerged est empilée — dites-le dans sa description et définissez sa branche de base GitHub en conséquence.
Étape 7 : Descriptions de PR
## Summary
PR {N} de {M} issue de {original branch}.
## Scope
- …
## Intentionnellement exclus (PRs de suivi)
- …
## Verification
- {commandes lancées + résultats}
Gardez le registre d'extraction détaillé dans .ai/scratch/pr-split.md, pas dans les corps de PR.
Étape 8 : Gérer la dérive à mesure que les reviews arrivent
- Les changements approuvés par le reviewer sont la nouvelle source de vérité — quand une PR antérieure change, rebasez ses dépendants dessus et résolvez les conflits en faveur de la direction reviewée, jamais aveuglément vers la branche originale.
- Après chaque rebase/force-push :
git range-diff {old-tip}...{new-tip}et résumez les différences significatives pour les reviewers. - Diffez périodiquement la pile contre le backup pour trouver l'intention restante (travail pas encore déployé dans aucune PR) — pas pour forcer l'égalité octet par octet.
- Enregistrez chaque divergence intentionnelle dans les drift notes du scratchpad.
Fait quand
- [ ] Chaque hunk de
git diff $BASE...backup/original-{branch}est soit déployé dans une PR, soit explicitement listé dans le scratchpad comme abandonné (avec une raison) - [ ] Chaque PR compile et passe ses gates scopées indépendamment
- [ ] Les tests déployés dans la même PR que le code qu'ils vérifient
- [ ] Branche de backup toujours intacte
Modes d'échec à éviter
Découper par fichier quand le comportement s'étend sur les fichiers · extraire les tests sans leur code · une PR de suivi qui ne compile pas · force-push sans résumé range-diff · supprimer le backup trop tôt · résoudre les conflits de pile en revertant le feedback du reviewer.