pr-splitter

Par crbnos · carbon

Divisez un pull request volumineux, difficile à relire ou mal structuré en plusieurs PRs plus petits et facilement révisables (empilés ou parallèles), sans perdre aucun travail existant — créez un snapshot de la branche, extrayez les changements de façon non interactive, vérifiez chaque PR indépendamment et suivez la dérive au fur et à mesure que les retours de review arrivent. À utiliser lorsqu'un PR est trop grand à réviser, mélange des refactorisations avec des changements de comportement, ou nécessite une livraison incrémentale. Requiert un travail commité sur une branche — effectuez un commit ou un stash au préalable.

npx skills add https://github.com/crbnos/carbon --skill pr-splitter

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.

Skills similaires