swarm-migrate について
YAML 仕様に基づき、並列ワーカー、依存関係ごとの段階、CI ゲート、永続的な台帳を使って複数リポジトリの反復変更を調整するスキルです。3 リポジトリ以上の移行向けで、プルリクエストのマージは人が行います。
主な機能
- 01YAML 移行仕様の検証
- 02依存関係に沿ったリポジトリの段階分け
- 03隔離ワークツリーでの並列実行数制御
- 04CI 結果に基づく後続段階の制御
- 05台帳による進捗追跡と再開
- 06マージせずにプルリクエストを作成
活用シーン
- 01複数リポジトリで依存関係を更新
- 02共通ワークフローの変更を展開
- 03複数リポジトリで codemod を実行
- 04中断後に移行を再開
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yonatangross/ orchestkit --skill swarm-migrateインストール後、Claude Code で/swarm-migrateを入力して読み込まれたか確認します。
詳細
swarm-migrate — リポジトリ横断移行スウォーム
1つのコマンド、N 個のリポジトリ、1人のコーディネーター、1つの台帳。
使用する場面
同じ形式の変換を3つ以上のリポジトリに適用する必要がある場合に使用します(ワークフローの更新、依存関係のアップグレード、codemod、Lint ルールの導入、シークレットのローテーション、Runbook ヘッダーなど)。1つのリポジトリだけで作業する場合は使用しないでください。その場合は implement を使います。新しいことを探索する場合は使用しないでください。その場合は brainstorm を使います。
このスキルが作られたのは、275 セッションの分析から、25 セッションが PR の連鎖を手作業で調整するのに費やされていたことが分かったためです(M164 deploy-migration、M17 yg-mcp-core の抽出、14 リポジトリにわたる @v1 再利用可能ワークフローの展開)。パターンはいつも同じでした。リポジトリを選び、ブランチを作成し、変更を適用し、プッシュし、CI を確認して、繰り返します。このスキルは、その繰り返しを自動化します。
CC
/workflows(2.1.154)との違い: CC の動的ワークフローは、バックグラウンドで数十から数百のエージェントをオーケストレーションし、/workflowsを通じて結果を報告します。swarm-migrateは意図的に異なります。CI ゲート、競合の自動リベース、未知の失敗時の停止を備えた、コーディネーター主導のフォアグラウンド DAGです。実行を見守ることができ、予期しない失敗が最初に発生した時点で停止します。大規模なバックグラウンドの一括実行を任せたい場合は CC/workflowsを、各ステップで CI ゲートと人が確認できる台帳が必要な場合はswarm-migrateを使ってください。CC 2.1.202 では/configに動的ワークフローのサイズ設定が追加されました(エージェント数を small/medium/large から選択)。これは/workflowsで起動するエージェント数の目安になります。強制上限ではないため、実行数を手動で制限する前に確認してください。
入力
swarm-specs/<name>.yaml にある YAML 仕様:
name: bump-actions-checkout-v4
description: "Pin @actions/checkout to v4 across all repos"
# Topology — repos in dependency order. Coordinator only proceeds
# to a downstream repo after every upstream parent has merged green.
repos:
- path: ~/coding/yonatan-hq/platform
upstream: []
- path: ~/coding/yonatan-hq/ventures/jobscraper
upstream: [platform] # waits for platform to merge first
# Transformation — applied identically per repo. The agent runs this
# inside the isolated worktree, then verifies with the next field.
transform:
type: codemod # codemod | regex | command
command: |
grep -rl 'actions/checkout@v3' .github/workflows | \
xargs sed -i '' 's|actions/checkout@v3|actions/checkout@v4|g'
# Verification — must pass before PR opens. Coordinator skips the repo
# if it fails locally (records skip-reason in ledger).
verify:
- command: "git diff --quiet"
expect: nonzero # must have changes
- command: "grep -r 'actions/checkout@v3' .github/workflows"
expect: nonzero # zero matches = clean
# PR shape — title, body, base branch
pr:
branch_prefix: chore/bump-checkout-v4
title: "chore(ci): pin @actions/checkout to v4"
body_file: swarm-specs/bump-actions-checkout-v4.pr.md
base: main
labels: [chore, ci]
# CI gate — coordinator waits for required checks to pass before
# moving downstream. Set to false for dry-run, or in repos without CI.
ci_gate:
required_checks: ["build", "test"]
timeout_minutes: 20
on_failure: pause # pause | skip | abort
# Limits
max_parallel: 4
abort_on_novel_failure: true
動作の仕組み
┌────────────────────────────────┐
│ COORDINATOR (you) │
│ reads spec → builds DAG → │
│ writes .swarm-state.json │
└─────────────────┬──────────────┘
┌────────────┼────────────┐
┌──────────┐ ┌──────────┐ ┌──────────┐
│ WORKER A │ │ WORKER B │ │ WORKER C │
│ (repo 1) │ │ (repo 2) │ │ (repo 3) │
└────┬─────┘ └────┬─────┘ └────┬─────┘
└─────────── isolated worktrees ─────┘
│ each: clone branch, transform,
│ verify, push, open PR, wait for CI, report
▼
┌────────────────────────────────┐
│ .swarm-state.json │
│ rolling ledger of {repo, │
│ status, pr_url, ci_state, │
│ last_action_at} │
└────────────────────────────────┘
各ワーカーは、Agent ツールの呼び出しです(配線にはサブエージェント型 git-operations-engineer、スキーマ関連の移行には backend-system-architect を使用します)。コーディネーター(あなた、このスキル)はウェーブの間に台帳を読み、後続のウェーブを開始するか、一時停止するかを判断します。
ポーリングせず、プッシュで通知する(CC 2.1.224 以降)
ワーカーは状態の変化(CI 成功、CI 失敗、未知の失敗、スキップ)を、コーディネーターがウェーブ間に台帳を再読み込みするのではなく、SendMessage でコーディネーターにメッセージを送って報告します。
セッション間の返信は親に届きます(CC 2.1.248): サブエージェントが別のセッションに
SendMessageを送信すると、返信はサブエージェントではなく親セッションの会話に届きます。サブエージェントはメッセージを送信して作業を続け、親が返信を読みます。セッション間のSendMessage/ListAgentsは、Bedrock、Vertex、Foundry でも、テレメトリーが無効な場合でも機能します(CC 2.1.248)。
- Agent ツールのサブエージェントとして起動されたワーカーは、セッション内の
SendMessageを使用します(CC 2.1.77 以降で利用可能)。 - 独立したセッションまたは
claude -pプロセスとして実行されるワーカーは、セッション間メッセージングを使用します(CC 2.1.224、chain-patterns の Pattern 10 を参照)。-pワーカーが返信を受信するには、--settingsでcrossSessionInbound: "accept"を指定して実行する必要があります。
重要:セッション間の配信は保証されません。受信制御によってメッセージが保留または拒否される場合があります。.swarm-state.json は引き続き信頼できる永続的な記録であり、すべての状態変更はそこにも書き込まれます。メッセージは低遅延の通知であり、真の記録は台帳です。
フェーズ 1 — 仕様の検証
<spec-file.yaml> を読み込みます。次を確認してください。
- すべての
repos[].pathが存在し、Git リポジトリであること(git -C <path> rev-parseで確認します)。 transform.commandがドライランモードで 0 を返すこと(またはtransform.type: codemodがswarm-specs/codemods/に登録されている既知の codemod を解決すること)。- すべての
upstream参照先が宣言済みのリポジトリであること(依存関係の参照漏れがないこと)。 pr.body_fileが存在し、空でないこと。
いずれかの確認に失敗した場合は、中止して失敗の一覧表を出力してください。続行してはいけません。
フェーズ 2 — トポロジカルソート
upstream のエッジから DAG を構築します。循環を検出した場合は中止します。ノードをトポロジカルなウェーブごとにグループ化します(ウェーブ 0 = 依存関係なし、ウェーブ 1 = ウェーブ 0 のみを依存先とする、…)。コーディネーターは一度に 1 つのウェーブを開始します。
このスキルを実行しているリポジトリのルートに .swarm-state.json を書き込みます。
{
"spec": "swarm-specs/bump-actions-checkout-v4.yaml",
"started_at": "2026-05-16T17:00:00Z",
"waves": [
{ "id": 0, "repos": ["platform"] },
{ "id": 1, "repos": ["jobscraper"] }
],
"repos": {
"platform": { "status": "pending", "pr_url": null, "ci_state": null, "last_action_at": null },
"jobscraper": { "status": "blocked", "blocked_on": ["platform"], "pr_url": null }
}
}
フェーズ 3 — ディスパッチウェーブ
現在のウェーブ内の各リポジトリに対して、並列で(max_parallel の範囲内で)次を実行します。
- ワークツリー —
origin/<base>を基点に、<repo>/../<repo>-swarm-<spec-name>に分離されたワークツリーを作成します。稼働中の作業ツリーは決して変更しないでください。 - ブランチ —
git checkout -b <branch_prefix>-<short-sha>を実行します。 - 変換 —
transform.commandを実行するか、コードモッドを適用します。標準出力を.swarm-logs/<repo>-transform.logに保存します。 - 検証 — 各
verify[].commandを実行し、終了コードがexpectと一致することを確認します。一致しない場合は、理由とともにリポジトリを台帳でskippedとして記録し、プッシュしないでください。 - プッシュと PR — ブランチをプッシュし、
gh pr createで PR を作成します。PR URL を台帳に記録します。 - CI の監視 —
ci_gate.timeout_minutesに達するまで、45 秒ごとにgh pr checks <n>をポーリングします。状態が遷移するたびに、台帳のci_stateを更新します。
ステップ 1~5 では、メインコンテキストを軽く保つため、subagent_type: ork:git-operations-engineer を指定して Agent ツールを使用してください。コーディネーターは台帳のみを読み取ります。
フェーズ 4 — ウェーブゲート
各ウェーブの後に、台帳を確認します。
- すべて
green→ 次のウェーブを開始します。 pending CIがある → ポーリングを続けます。red CIがある →ci_gate.on_failureを確認します。pause→ スウォームを停止し、.swarm-state.jsonに概要を書き込み、失敗したログを提示してユーザーに確認します。skip→ リポジトリをfailed-ciとして記録し、依存するリポジトリが明示的に存在しない場合を除き、下流をブロックしたうえで、同じウェーブ内の他のリポジトリの処理を続けます。abort→ スウォームを終了し、オープン中の PR はそのまま残します。決してマージしないでください。
フェーズ 5 — コンフリクト発生時の自動リベース
上流のリポジトリがマージされたことにより、下流リポジトリのワーカーがリベース時にマージコンフリクトに遭遇した場合、ワーカーは次の手順を実行します。
- 上流のマージコミット SHA を再取得します。
git rebase origin/<base>を試みます。コンフリクトがなければ、プッシュして台帳を更新します。- コンフリクトがある場合は、コンフリクトしたファイルを台帳に記録し、自動解決はせず、コーディネーターに報告します。コンフリクトは、自動修正ツールが壊れたコードを投入する最もよくある原因です。
フェーズ 6 — 最終レポート
すべてのウェーブが完了したとき(またはスウォームが一時停止/中止したとき)、.swarm-logs/<spec-name>-report.md に Markdown 形式のレポートを 1 つ出力します。
# Swarm report: bump-actions-checkout-v4
Completed: 12/14 repos · paused: 2 · duration: 47 min
| repo | status | PR | CI | duration |
|-----------------|---------|-------|--------|----------|
| platform | merged | #3456 | green | 8 min |
| jobscraper | merged | #281 | green | 6 min |
| ... |
| dormant-repo-1 | skipped | — | — | (no CI runner configured) |
| trading-ai | paused | #99 | red | (novel failure — see logs) |
## Novel failures (escalated)
- trading-ai #99: pyproject lockfile mismatch — see .swarm-logs/trading-ai-ci.log
完了条件。 完了とは、仕様に含まれるすべてのリポジトリで、PR がオープンされており CI が成功している(スウォームによってマージされていない)か、理由とともにスキップされているか、または新たな失敗が記録された状態で一時停止しており、最終レポートが作成されていることです。Read("../../shared/rules/long-run-protocol.md") に従ってください。ユーザーからの入力が不要なステップは続け、ユーザーなしでは続行できない場合や破壊的な操作の前に限って停止して確認します。各サブエージェントの証拠を確認してから結果を受け入れ、確認できなかった事項には、どこを調べたかを添えて記録します。
絶対遵守のルール
- PR を決してマージしないでください。スウォームは PR を作成し、マージするのは人間です。希望する場合、スウォーム完了後にユーザーが
gh pr merge --autoで自動マージを有効にできます。 - 決して強制プッシュしないでください。ワーカーがファストフォワードできない場合は、一時停止します。
- 仕様で宣言された
repos[]の範囲外を決して調べないでください。変換が他の場所でも役立ちそうな場合も同様です。 - 認証情報は必ず隔離してください。ワーカーはユーザーの gh 認証を使用し、コーディネーターはトークンを記録せず、URL のみを記録します。
- 既存のブランチ保護は必ず尊重してください。必須レビュアーなどのルールが原因で
gh pr createが失敗する場合、それは回避すべき問題ではなく、意図された動作です。
実際に遭遇する障害モード
| モード | 発生時の状況 | 対処 |
|---|---|---|
| 古いロックファイル | 依存関係の更新後、npm ci で CI が失敗する | 仕様に post_transform.command: npm install のステップを含めます |
| ブランチ保護により PR 作成がブロックされる | gh pr create がゼロ以外で終了する | コーディネーターがリポジトリを blocked-by-protection として記録し、ユーザーに報告します |
| トポロジーの循環 | フェーズ 2 が中止される | 上流エッジを再定義します |
| 処理途中でコーディネーターがクラッシュする | .swarm-state.json が不完全な状態で書き込まれる | スキルは再開可能です。同じ仕様で再実行すると、台帳を読み込み、merged/green のリポジトリをスキップします |
| ワーカーのサブエージェントが応答しなくなる | 5 分を超えて台帳が更新されない | コーディネーターがエージェントをタイムアウトさせ、リポジトリを worker-timeout として記録し、ログを報告します |
関連スキル
- 上流 — 仕様を設計するには
brainstorm、ディスパッチ前に DAG を ASCII でプレビューするにはvisualize-planを使います。 - 下流 — マージ後にリポジトリごとに
verifyを実行し、組織全体を一斉に確認するには/statusを使います。ワーカーで CI が失敗した場合は/ci-debugを使います。 - 連携 —
create-pr(各ワーカーが呼び出します)、github-operations(スウォーム後にラベルやマイルストーンを一括更新します)。
このスキルが行わないこと
- 仕様を考案することはありません。仕様を書くのはあなたで、このスキルはそれを実行します。
- 複数の DB にまたがるスキーマ移行は行いません(単一リポジトリ向けのスキルと
database-patternsを使ってください)。 - 本番環境へのデプロイはオーケストレーションしません。PR を開くところまでで、デプロイは別のゲート(プラットフォームの deploy-operator)が担います。
create-prの playground-gate ルールを回避することはありません。リポジトリで適用されている場合、各 PR の本文に playground への参照を含める必要があります。
呼び出し例
# Dry-run: build the DAG, verify spec, do NOT push or open PRs
swarm-migrate swarm-specs/bump-actions-checkout-v4.yaml --dry-run
# Live: dispatch up to 4 workers in parallel
swarm-migrate swarm-specs/bump-actions-checkout-v4.yaml --max-parallel=4
# Resume after pause: same command, the ledger remembers
swarm-migrate swarm-specs/bump-actions-checkout-v4.yaml
これが存在する理由(1 段落)
1 か月の間に、リポジトリをまたぐ PR の調整を手作業で行うセッションを 25 回実施しました。14 リポジトリにわたる @v1 ワークフローのロールアウト、M17 の yg-mcp-core の切り出し、M164 のデプロイ移行。どのセッションも同じ形でした。コーディネーター(あなた)が頭の中で DAG を管理し、異なるターミナルタブでワーカー(あなた自身)に順番にタスクを割り振り、メモに手作業でステータス表を作っていました。このスキルでは、コーディネーターを YAML ファイルに、ワーカーを並列サブエージェントに置き換えます。DAG、台帳、自動リベース、ウェーブのゲートなど、手作業で行っていたすべての管理作業が、一度コード化されます。仕様を書いたら、その場を離れ、戻ってきたときにはレポートを確認できます。