You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore(claude): add stacked PR pattern for inter-ticket dependencies
Les tickets peuvent désormais déclarer leurs dépendances dans une
section `Depends on:` de leur body. `/epic` parse cette section et
calcule la branche de base à passer à code-dev :
- Aucune dépendance → origin/alpha
- Toutes dépendances mergées → origin/alpha (refresh)
- 1 dépendance en In review → ticket/<parent-slug> (stacked PR)
- 2+ dépendances en In review → partial blocking v1
code-dev crée sa branche depuis la base reçue et ouvre la PR avec
--base correspondant. GitHub retargette automatiquement vers alpha
quand la PR parent est mergée. L'exécution n'attend jamais une
validation humaine.
Parent issue GitHub reste utilisé uniquement pour la relation
epic → ticket. Les dépendances inter-tickets passent par la section
Depends on pour être parseable et éviter l'ambiguïté.
5.**Validation utilisateur** — « valide-tu ce découpage ? »
38
+
6.**Sur approbation** — créer chaque ticket :
39
+
- Parent issue = **epic** (uniquement pour relier au parent, PAS pour les dépendances)
40
+
-**Section `Depends on`** dans le body listant les tickets dont il dépend (format `- #<N>`)
37
41
- Labels appliqués
38
-
6.**Commentaire final sur l'epic** — `[Validation utilisateur] Architecture validée — N tickets créés, prêt pour /epic`
42
+
7.**Commentaire final sur l'epic** — `[Validation utilisateur] Architecture validée — N tickets créés, prêt pour /epic`
39
43
40
44
## Contraintes
41
45
42
46
-**Respecter `rules/ticket-spec-format.md`** — toutes les sections requises, chemins de fichiers explicites, pas de « voir le code »
43
-
-**Max 8 critères d'acceptation par ticket** — découper sinon
44
-
-**Dépendances via Parent issue / Sub-issues GitHub** — `/epic` respecte cet ordre
47
+
-**Max 8 critères d'acceptation par ticket** — découper sinon, et lier via `Depends on`
48
+
-**Dépendances inter-tickets via section `Depends on`** dans le body (jamais via `Parent issue` qui sert uniquement à lier l'epic) — `/epic` parse cette section pour orchestrer le stacked-PR pattern
49
+
-**Pas de cycles** dans le DAG de dépendances — sinon `/epic` refuse de dispatcher
45
50
-**Aucune décision résiduelle** pour `code-dev` — Sonnet exécute, ne conçoit pas
- Si `<base-branch>` ≠ `origin/alpha`, on est en mode **stacked PR** — la PR sera ouverte avec `--base <base-branch>`, GitHub retargettera vers `alpha` quand la PR parent sera mergée
25
31
26
32
5.**Implémenter** :
27
33
- Modifier les fichiers listés dans le ticket
@@ -42,10 +48,11 @@ You execute one pre-specified ticket end-to-end : edit code, write/update tests,
42
48
- Démarrer dev server sur le port assigné
43
49
- Playwright → screenshots desktop (1280×800) + mobile (375×667)
44
50
45
-
8.**PR draft** via `gh pr create --draft` :
46
-
- Base = branche epic (ou master)
51
+
8.**PR draft** via `gh pr create --draft --base <base-branch>` :
52
+
- Base = la `<base-branch>` reçue en input (`origin/alpha`ou `ticket/<parent-slug>`)
47
53
- Body : lien ticket (`Closes #NNN`), résumé, test plan, screenshots
48
54
-**Ticket reste en In progress** pendant les validators
55
+
- Si stacked : noter dans le body « Stacked on #<parent-PR> — GitHub retargettera automatiquement sur `alpha` une fois le parent mergé »
49
56
50
57
9.**Validations en parallèle** — 3 axes simultanés, tous doivent être verts avant de passer à l'étape 10.
Copy file name to clipboardExpand all lines: .claude/rules/ticket-spec-format.md
+12-2Lines changed: 12 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -66,12 +66,22 @@ Si pas d'UI, écrire "N/A".>
66
66
-[ ] Lint vert (`pnpm lint:check`)
67
67
-[ ] Scénario(s) rejoué(s) sans erreur par `functional-validator`
68
68
-[ ] (si UI) Comparaison visuelle PASS par `design-validator`
69
+
70
+
## Depends on
71
+
72
+
<Liste des tickets dont celui-ci dépend (le code/schéma de ces tickets doit exister avant que celui-ci puisse être implémenté). Un ticket par ligne avec le numéro GitHub :
73
+
74
+
- #<N1>
75
+
- #<N2>
76
+
77
+
Si aucune dépendance, écrire "N/A" ou omettre la section entièrement.>
69
78
```
70
79
71
80
## Règles de rédaction
72
81
73
-
-**Un ticket = une unité cohérente** : si les critères d'acceptation dépassent 8 éléments, découper en deux tickets avec dépendance parent-enfant GitHub.
82
+
-**Un ticket = une unité cohérente** : si les critères d'acceptation dépassent 8 éléments, découper en deux tickets et exprimer la dépendance via la section `Depends on`.
74
83
-**Pas de décision architecturale** dans le ticket : l'architect a déjà tranché. Le dev exécute.
75
84
-**Pas de "voir le code pour comprendre"** : les fichiers à lire doivent être listés explicitement.
76
85
-**Le label `complexe`** est ajouté uniquement si la tâche demande un raisonnement multi-étapes non trivial (refacto multi-fichiers, perf critique, algo complexe). Par défaut, Sonnet suffit.
77
-
-**Dépendances** : utiliser le champ `Parent issue` / sub-issues GitHub. `/epic` respecte l'ordre : les tickets sans dépendance partent en premier, les suivants dès que leurs parents sont **Done**.
86
+
-**Dépendances inter-tickets** : listées dans la section `Depends on` du body. `/epic` parse cette section et applique la stratégie **stacked PRs** : si un ticket `T2` dépend de `T1` encore `In review` (PR non mergée), `T2` est créé avec `--base` sur la branche de `T1`. Ainsi l'exécution n'attend jamais une validation humaine.
87
+
-**Parent issue GitHub** : utilisé uniquement pour pointer vers l'epic (relation epic → ticket). **Pas** pour exprimer des dépendances inter-tickets — utiliser `Depends on` à la place.
Copy file name to clipboardExpand all lines: .claude/skills/epic/SKILL.md
+38-17Lines changed: 38 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,23 +19,35 @@ Dispatche les sous-issues d'un epic sur plusieurs worktrees en parallèle, invoq
19
19
20
20
- Vérifier que l'issue existe et a le label `Epic`
21
21
- Fetcher ses sous-issues avec leur statut board — utiliser le snippet op. 5 de `rules/github-board.md`
22
-
- Filtrer : ne conserver que les tickets dont le champ `Status` = **To Do** (ignorer Backlog / In progress / In review / Done)
23
-
- Valider le graphe de dépendances (parents avant enfants, pas de cycles)
22
+
-**Parser la section `Depends on`** du body de chaque sub-issue pour construire le DAG de dépendances inter-tickets (regex : extraire les `#<N>` listés dans la section).
23
+
- Valider le DAG : pas de cycles. Si cycle détecté → exit avec diagnostic.
24
+
- Filtrer les tickets dispatchables = en **To Do** (ignorer Backlog / In progress / In review / Done).
24
25
25
-
Si rien en To Do → exit avec `Nothing to dispatch on epic #<N>`.
26
+
Si aucun ticket dispatchable → exit avec `Nothing to dispatch on epic #<N>`.
Si un worktree avec ce path existe déjà (re-run d'`/epic`), le réutiliser plutôt que d'en créer un nouveau.
@@ -44,39 +56,46 @@ Si un worktree avec ce path existe déjà (re-run d'`/epic`), le réutiliser plu
44
56
45
57
# Step 2 — Dispatch loop
46
58
47
-
Tant qu'il reste des tickets en **To Do**dont toutes les dépendances (Parent issue / Sub-issues GitHub) sont en **In review** ou **Done** :
59
+
Tant qu'il reste des tickets en **To Do**dispatchables (toutes dépendances résolues selon le tableau de Step 1) :
48
60
49
61
1.**Sélectionner les N prochains tickets dispatchables** — parallélisme par défaut **N = 3**. Ajuster selon la RAM de la machine (~1–2 GB par dev server).
50
62
51
63
2.**Invoquer `code-dev` en parallèle** (un Agent tool call par ticket, dans un seul message) :
52
64
- Model : **opus** si label `complexe`, sinon **sonnet**
53
-
- Arguments : ticket number, worktree path, dev server port
65
+
- Arguments : ticket number, worktree path, dev server port, **base branch** (cf. tableau Step 1)
54
66
-`run_in_background: true` pour que `/epic` continue à orchestrer pendant l'exécution
55
67
56
68
3.**Attendre la complétion** de tous les `code-dev` lancés. Chaque retour est PASS ou REFACTO.
57
69
58
70
4.**Traiter les verdicts** :
59
-
-**PASS** → ticket en **In review**, PR prête (`gh pr ready`). Worktree conservé pour revue utilisateur.
60
-
-**REFACTO** → ticket retourné en **To Do** avec diagnostic. Signaler à l'utilisateur qu'une intervention `architect` est probablement nécessaire.
71
+
-**PASS** → ticket en **In review**, PR prête (`gh pr ready`). Worktree conservé pour revue utilisateur. Les tickets qui dépendaient de celui-ci deviennent **dispatchables** en stacked (leur base branch = la branche de ce ticket).
72
+
-**REFACTO** → ticket retourné en **To Do** avec diagnostic. Signaler à l'utilisateur qu'une intervention `architect` est probablement nécessaire.**Tous les tickets qui en dépendent restent bloqués** jusqu'à résolution.
61
73
62
74
5.**Reboucler** sur Step 2 tant qu'il reste des tickets dispatchables.
63
75
76
+
**Fin de boucle** — il peut rester des tickets en To Do dont les dépendances ne sont ni `In review` ni `Done` (ex : dépendances multiples toutes encore en flight). Dans ce cas, sortir proprement du loop et signaler à l'utilisateur que certains tickets attendent le merge humain d'une de leurs dépendances.
77
+
64
78
---
65
79
66
80
# Step 3 — Report
67
81
68
82
```
69
83
## Epic #<N>: dispatch complete
70
84
71
-
PASS (In review): #N1, #N3, #N4
85
+
PASS (In review):
86
+
- #N1 (PR #101, base: origin/alpha)
87
+
- #N3 (PR #103, base: ticket/N1-slug ← stacked)
88
+
- #N4 (PR #104, base: ticket/N3-slug ← stacked)
72
89
REFACTO (retour To Do): #N2 — <diagnostic>
90
+
Bloqués (en attente merge humain) : #N5 (dépend de #N3 merged)
73
91
Worktrees actifs: ../egapro-epic<N>-t*
74
92
75
93
Next:
76
-
1. Revoir les PR ouvertes
77
-
2. Passer manuellement les tickets In review → Done
78
-
3. Si REFACTO : re-lancer /ticket sur l'epic (phase architect) puis /epic
79
-
4. `git worktree remove ../egapro-epic<N>-t*` après merge de toutes les PR
94
+
1. Revoir et merger les PR dans l'ordre du stack (#101 → #103 → #104)
95
+
2. Les PR dépendantes seront auto-retargettées par GitHub vers `alpha` après chaque merge
96
+
3. Passer manuellement les tickets In review → Done
97
+
4. Si REFACTO : re-lancer /ticket sur l'epic (phase architect) puis /epic
98
+
5. `git worktree remove ../egapro-epic<N>-t*` après merge de toutes les PR
80
99
```
81
100
82
101
---
@@ -86,4 +105,6 @@ Next:
86
105
-**Nettoyage worktrees** : conservés après `/epic` pour la revue humaine. L'utilisateur les supprime après merge.
87
106
-**Never auto-Done** : `/epic` termine sur **In review** pour tous les tickets PASS. La transition **Done** est manuelle.
88
107
-**Parallélisme** : max 3 par défaut. Chaque dev server consomme de la RAM et des ports. Ajuster `N` si machine modeste.
89
-
-**Ordre de dispatch** : les tickets sans dépendance partent en premier. Les tickets dépendants attendent que leur parent soit **In review** (pas Done — sinon `/epic` bloquerait sur la validation humaine).
108
+
-**Stacked PR pattern** : un ticket dépendant part immédiatement dès que son parent est **In review** (PR prête, pas encore mergée). Sa PR est ouverte avec `--base ticket/<parent-slug>`. GitHub retargette automatiquement vers `alpha` quand le parent est mergé. Évite le blocage sur la validation humaine.
109
+
-**Ordre de merge humain** : critique. Merger les PR **dans l'ordre du stack** (parent avant enfant). Merger un enfant avant son parent casse l'historique. `/epic` le rappelle dans le report final.
110
+
-**Multi-dépendances non mergées** (v1) : partial blocking — attendre qu'au moins une dépendance soit mergée avant de dispatcher le ticket. v2 future : merge commits croisés si besoin.
0 commit comments