/wt-split — 親 issue を分解して並列 worktree に投げる
複数タスクを含む親 issue を子 issue に分解し、並列に進められる子から worktree + Claude Code セッションを起動する。dev(本体 checkout)側で実行する。worktree 側のセッションでこれを打たれたら、dev 側で実行するよう案内して止まる。タスク = issue = ブランチ = PR の 1:1:1 は子 issue の単位で保つ。親にはブランチを持たせない。
手順
- 引数が空なら、どの issue を分解するか質問する。GitHub 連携(
gh repo view --json nameWithOwnerが成功)が前提。ローカル repo では子 issue を作れないため、手順 3 の分解案の確認だけ行い、番号なし命名・ローカル版の定型尾部(/wt 参照)で手順 5 を実行する。 - 親 issue を取得する:
gh issue view <N> --json number,title,body,state。OPEN でなければ報告して止まる。本体 checkout の現在ブランチ(= 全 worktree の base)が default branch と異なるときは、PR の base とずれて無関係なコミットが混ざるため、続行してよいか確認する。 - 分解案を作ってユーザーの確認を得る(省略禁止 — 起票と複数セッションの起動は取り消しにくい)。親本文にチェックリストがあればそれをベースに、なければ本文から起こす。子ごとに「タイトル(体言止め)/ 受け入れ条件の骨子 / 並列可能か・どの子のあとか」を提示する。分解の原則:
- 機能は縦に切る(1 つの子でフロント〜バックまで薄く通す)。層で切らない。
- 同じファイル群を触らざるを得ない子同士は並列にせず、依存(直列)にする。並列の子はマージ時のコンフリクトを自分では解けない。
- 子は「scripts/check が通る最小の完結単位」(目安: 半日〜2 日、差分 400 行程度まで)。分解してもこの粒度に届かない・タスクが実質 1 つなら、分解せず /wt か /wt-detail を案内して止まる。
- 子 issue を起票し、親を書き換える:
- 子ごとに本文を scratchpad に書き、
gh issue create --title <体言止め> --body-file <path>で番号を得る。本文は## 背景(親の文脈 + この子の担当範囲。「親 issue: #N」の行を含める)と## 受け入れ条件(チェックボックス箇条書き)— /wt と同じく、この本文がそのまま初期プロンプトになる粒度で書く。 - 親 issue の本文を
gh issue edit <N> --body-file <path>で更新し、## 子タスク節に- [ ] #子番号 <タイトル>のタスクリストを置く。依存は行末に「(#M のあと)」と書く(再実行時はこの表記だけを見て依存を判定する)。元のチェックリストはこのタスクリストに置き換え、それ以外の本文は残す。
- 子ごとに本文を scratchpad に書き、
- 依存のない子から 1 本ずつ順に起動する(bootstrap の依存インストールが並走するとパッケージキャッシュを取り合うため、
wt newの完了を待って次へ):worktree 名は /wt と同じ規約:
<子番号>-+ 小文字 kebab-case 2〜3 語。git branch --list 'worktree-*'で衝突を確認する。初期プロンプトは「issue #子N <タイトル>」の行 + 子 issue 本文 + 子タスク版の定型尾部(/wt の issue フロー版ではなく下のもの)。冒頭に次の並列注意を足す(平叙文で始まるので
wt newの先頭文字制約も満たす):この作業は親 issue #親N を分解した子タスクの 1 つで、他の worktree セッションが別の子タスクを並行で進めている。自分の issue の受け入れ条件の範囲外のファイルはできるだけ触らず、範囲が重なりそうなときは /wt-ask で dev 側に確認すること。
子タスク版の定型尾部(N は子 issue の実番号に置換。レビューは人間でなく AI が行い、マージまで自動で進む):
実装が終わったら変更をコミットし、/wt-auto-review で AI レビューを受けること。PASS したら承認済みとして /wt-merge で PR を作成し、CI の完了を待ってマージし、/wt-clean で worktree を片付けること(PR の Fixes #N でこの issue が閉じる)。AI レビューが 2 巡で通らないときや仕様の判断が要るときは、勝手に決めず /wt-ask で dev 側セッションに聞いて /wt-review の人間レビューに切り替えること(宛先は
wt peersの role=dev 行の name)。scratchpad にファイルを書き、
wt new <name> --prompt-file <path>を子ごとに実行する。wt newは毎回 workspace にフォーカスするため、最後に起動した 1 本が前面になる(機能上の問題はない)。
- 報告する: 起票した子 issue の URL 一覧 / 起動した worktree と宛先名
wt-<task>/ 起動しなかった子とその理由(依存待ち)。依存待ちの子は、先行の子の PR がマージされたら dev 側で/wt-split #親Nを再実行すれば起動される旨を添える。
再実行(依存が解けた子の追加起動)
/wt-split #親N が再実行されたら、親本文の ## 子タスク のタスクリストを読み、子ごとに判定する:
- 子 issue が CLOSED → 済み。スキップする。
- ブランチ
worktree-<子番号>-*が既にある → 進行中。スキップする(wt listで対応 worktree を報告する)。 - 「(#M のあと)」の #M がすべて CLOSED → 手順 5 の方法で起動する。OPEN の依存が残る子は待ちとして報告する。
- すべての子が CLOSED → 親の受け入れ条件に未消化の項目がないか確認し、
gh issue close <親N>して完了を報告する。
エラー時
- 「herdr サーバなしでは Claude にプロンプトを渡せない」→ herdr の起動を促す。起票済みの子 issue と親の書き換えはそのまま生きているので、herdr 起動後に
/wt-split #親Nを再実行すれば未起動の子だけが起動される。起動途中で失敗したときも同じ — 再実行で続きから起動する(起票をやり直さない)。
注意
- 全 worktree が本体の
.envへの symlink を共有する。アプリを同時に起動する子が複数あると PORT や DB パスが衝突し得る — 回避は repo 側scripts/worktree-setupの責務(worktree-parallel 参照)。 - 並列の子の PR は base(default branch)の更新のたびにコンフリクトし得る。取り込みは 1 本ずつ、コンフリクトの扱いは /wt-merge の手順に従う。