prune について
prune は、期限切れの未終了ワークフローを一括整理する Exarchos のスキルです。候補と保護条件を事前に表示して確認を待ち、通常のキャンセルとは別に整理イベントを記録します。
主な機能
- 01ドライランで候補を表示
- 02オープン PR とブランチ活動を確認
- 03続行・中止・強制の明示的な選択
- 04一括キャンセルと監査イベントの記録
活用シーン
- 01整理前に非アクティブなワークフローを確認
- 02パイプライン内の古いワークフローを一括削除
- 03保護条件による除外を確認後に強制整理
MCP 対応
Exarchos MCP サーバーの `prune_stale_workflows` オーケストレーションアクションで、ワークフローを選別して整理します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ lvlup-sw/ exarchos --skill pruneインストール後、Claude Code で/pruneを入力して読み込まれたか確認します。
同梱ファイルreferences/safeguards.md
詳細
ワークフロー整理スキル
VCS プロバイダー
このスキルの安全策では、内部で VCS 操作(オープン PR の検出)を使用します。
オーケストレーションハンドラーは、VCS プロバイダーへの振り分けを自動的に管理します。
gh/glab/az コマンドは不要です。MCP サーバーがプロバイダーへの振り分けを処理します。
概要
パイプラインに蓄積された、古くなった未完了のワークフローを一括キャンセルします。prune_stale_workflows オーケストレーションアクションを、対話形式のドライラン後に確認する UX でラップし、状態が変更される前に必ず候補一覧をユーザーに表示します。
プルーニングはメンテナンス操作であり、ワークフローのフェーズではありません。プルーニングによって、基盤となるキャンセル処理が出力する標準の workflow.cancelled イベントと併せて workflow.pruned イベントが生成されるため、後続のビューでは、ユーザーの意図によるキャンセルと一括クリーンアップを区別できます。
トリガー
次の場合にこのスキルを有効にします。
- ユーザーが
pruneコマンドを実行する - ユーザーが「ワークフローを整理」「古いワークフローをクリーンアップ」「パイプラインをクリーンアップ」と言う
exarchos:exarchos_view({ action: "pipeline", scope: "all" })に、ユーザーが一括で整理したい非アクティブなワークフローが多数表示される。プルーニングではscope: "all"で候補を確認します。デフォルトのビューはリポジトリのスコープに限定され、プルーニングの対象となる legacy 行(リポジトリ ID が記録される前に開始されたワークフロー)が非表示になるためです。リポジトリのスコープで確認すると、整理対象そのものを見逃してしまいます。
前提条件
- 1 つ以上の未完了ワークフローがある exarchos 状態ディレクトリ
- ライブ PR に対する安全策のチェックには、PATH で
ghが利用可能であること(オーケストレーションハンドラーがシェルから実行します) - ブランチのアクティビティに対する安全策のチェックには、PATH で
gitが利用可能であること
手順
Step 1: ドライランでプレビュー
必ず dryRun: true から開始します。この呼び出しでは候補の選定と安全策の評価を行いますが、ワークフローの状態は変更しません。
exarchos:exarchos_orchestrate({
action: "prune_stale_workflows",
args: {
dryRun: true
}
})
レスポンスの形式は次のとおりです。
{
candidates: [
{ featureId: string, phase: string, workflowType: string, stalenessMinutes: number }
],
skipped: [
{ featureId: string, reason: "open-pr" | "active-branch" }
]
}
任意の引数:
thresholdMinutes-- 古さの判定基準。デフォルトは 10080(7 日間)です。includeOneShot-- 候補にoneshotワークフローを含めるかどうか。デフォルトはtrueです。force-- ドライランでは関係ありません。適用モード(Step 4)でのみ有効です。
Step 2: 候補の表を表示
プルーニング対象をユーザーが確認できるよう、表を表示します。次の形式を使用してください。
## Prune Candidates (3)
| Feature ID | Type | Phase | Stale (min) |
|---|---|---|---|
| feat-old-experiment | feature | implementing | 14430 |
| oneshot-typo-fix | oneshot | plan | 9120 |
| debug-flaky-test | debug | investigate | 8650 |
## Skipped by Safeguards (2)
| Feature ID | Reason |
|---|---|
| feat-active-pr | open-pr |
| feat-recent-work | active-branch |
candidates.length === 0 かつ skipped.length === 0 の場合は、次を出力します。
プルーニング対象の古いワークフローはありません。パイプラインはクリーンです。
その後、終了します。以降の操作は不要です。
Step 3: 確認を求める
次の 3 つからユーザーに選択してもらいます。
proceed -- 一覧にある候補をプルーニングします(スキップされたワークフローはそのまま残ります) abort -- 変更せずに終了します force -- 安全策を迂回し、スキップされたワークフローもプルーニングします
ユーザーから明示的な入力があるまで待ちます。自動的に続行してはいけません。
Step 4a: 適用(proceed)
proceed の場合は、dryRun: false を指定して同じアクションを呼び出します。Step 1 でユーザーが thresholdMinutes と includeOneShot を設定している場合は、それらも引き継ぎます。
exarchos:exarchos_orchestrate({
action: "prune_stale_workflows",
args: {
dryRun: false
}
})
レスポンスに pruned 配列が追加されます。
{
candidates: [...],
skipped: [...],
pruned: [
{ featureId: string, previousPhase: string }
]
}
pruned の各エントリは、cancelled に遷移し、workflow.pruned イベントを出力したワークフローに対応します。
Step 4b: 適用(force)
force の場合は、force: true を設定します。安全策は迂回されますが、監査証跡を保てるよう、迂回したことが workflow.pruned イベントのペイロードに skippedSafeguards: [...] として記録されます。
exarchos:exarchos_orchestrate({
action: "prune_stale_workflows",
args: {
dryRun: false,
force: true
}
})
force モードでは、ドライラン中に skipped リストに含まれていたワークフローも、新たにプルーニング対象となります。
Step 4c: 適用(abort)
abort の場合は、アクションを 2 回目に呼び出さずに終了します。ドライランでは状態は変更されていません。
Step 5: 結果を報告
適用の呼び出しから応答が返ったら、結果を要約します。
## Prune Complete
**Pruned:** 3 workflows transitioned to cancelled
**Skipped:** 2 workflows preserved by safeguards
**Force bypass:** no
### Pruned Workflows
- feat-old-experiment (was: implementing)
- oneshot-typo-fix (was: plan)
- debug-flaky-test (was: investigate)
force を使用した場合は、迂回した安全策も一覧表示します。
### Safeguards Bypassed
- feat-active-pr: open-pr
- feat-recent-work: active-branch
セーフガードの説明
キャンセルの前に、オーケストレーションハンドラーで2つのセーフガードが自動的に実行されます。
| セーフガード | 動作 | 理由キー |
|---|---|---|
| オープン中のPR | gh pr list --head <branch> --state open が結果を返した場合はスキップします | open-pr |
| 最近のコミット | git log --since "24 hours ago" origin/<branch> でコミットが確認された場合はスキップします | active-branch |
状態に branchName がないワークフロー(委任前に ideate/plan の段階で放棄されたものなど)には、PRもブランチのアクティビティも存在し得ないため、セーフガードは即座に終了し、そのワークフローは削除対象になります。
force: true を指定すると両方のチェックを回避できますが、監査は回避されません。回避されたセーフガード名は workflow.pruned イベントのペイロードに記録されます。
エラー処理
- 状態ディレクトリがない場合: まず exarchos ワークフローを初期化してください。削除対象はありません。
gh/gitが利用できない場合: セーフガードのチェックはエラーで即座に終了します。PRが開いていないことを手動で確認してから、force: trueを指定して再実行してください。- すべてのワークフローがクリーンな場合: 「削除対象の古いワークフローはありません」と報告して終了します(例3を参照)。
アンチパターン
| しないこと | 代わりにすること |
|---|---|
| ドライランの手順を省略する | 常に dryRun: true から始め、まず候補をユーザーに表示します |
| 表を表示せずに自動で確定する | 候補の表を表示し、ユーザーから明示的な入力があるまで待ちます |
デフォルトで force: true を使う | ユーザーが明示的に選択した場合に限り force を使います |
古いワークフローごとに手動で cancel を呼び出す | このスキルを使います。キャンセルのループをまとめて実行し、workflow.pruned 監査イベントを発行します |
| すべてのセッションで実行する | 削除はメンテナンス操作です。パイプラインの蓄積が確認できる場合に実行します |
例
例1:クリーンなドライランの後、ユーザーが続行する
> prune
## Prune Candidates (2)
| Feature ID | Type | Phase | Stale (min) |
|---|---|---|---|
| feat-old-spike | feature | plan | 12880 |
| oneshot-readme-tweak | oneshot | implementing | 9700 |
## Skipped by Safeguards (0)
(none)
Proceed? (proceed/abort/force)
> proceed
## Prune Complete
**Pruned:** 2 workflows transitioned to cancelled
**Skipped:** 0
**Force bypass:** no
### Pruned Workflows
- feat-old-spike (was: plan)
- oneshot-readme-tweak (was: implementing)
例2:セーフガードでスキップされた後、ユーザーが強制実行する
> prune
## Prune Candidates (1)
| Feature ID | Type | Phase | Stale (min) |
|---|---|---|---|
| feat-stale-no-pr | feature | implementing | 11200 |
## Skipped by Safeguards (1)
| Feature ID | Reason |
|---|---|
| feat-stale-with-pr | open-pr |
Proceed? (proceed/abort/force)
> force
## Prune Complete
**Pruned:** 2 workflows transitioned to cancelled
**Skipped:** 0
**Force bypass:** yes
### Pruned Workflows
- feat-stale-no-pr (was: implementing)
- feat-stale-with-pr (was: implementing)
### Safeguards Bypassed
- feat-stale-with-pr: open-pr
例3:パイプラインが空の場合
> prune
No stale workflows to prune. Pipeline is clean.
スキーマの確認
正式な引数スキーマと今後追加されるフィールドについては、以下を使用してください。
exarchos:exarchos_orchestrate({
action: "describe",
actions: ["prune_stale_workflows"]
})
Exarchos との連携
prune_stale_workflows アクションは、削除したワークフローごとに2つのイベントを発行します。
workflow.cancelled(基盤となるhandleCancelパスによって自動発行されます)workflow.pruned(このハンドラーによって発行され、triggeredBy: 'manual'と任意のskippedSafeguardsが含まれます)
どちらも標準のプロジェクションによって、ワークフロー状態の _events 配列に反映されます。下流のビューでは workflow.pruned でフィルタリングすることで、まとめて行われたクリーンアップとユーザーが開始したキャンセルを区別できます。