openspec-bulk-archive-change について
複数の完了した OpenSpec 変更をまとめてアーカイブするスキルです。成果物とタスクの状態を確認し、仕様パスの競合を検出して、コード上の実装状況に基づき同期方法を判断します。対象の選択と実行確認はユーザーが行います。
主な機能
- 01選択した変更の一括アーカイブ
- 02成果物とタスクの進捗確認
- 03差分仕様パスの競合検出
- 04コード上の根拠に基づく競合解決
- 05アーカイブ先の重複確認
活用シーン
- 01複数の完了済み変更をまとめてアーカイブ
- 02アーカイブ前に未完了作業を確認
- 03仕様パスが重なる変更への対応
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ fission-ai/ openspec --skill openspec-bulk-archive-changeインストール後、Claude Code で/openspec-bulk-archive-changeを入力して読み込まれたか確認します。
詳細
完了した複数の変更を、1回の操作でアーカイブします。
このスキルを使うと、複数の変更をまとめてアーカイブできます。コードベースを確認して実際に実装されている内容を判断することで、仕様の競合にも適切に対処します。
ストアの選択: ユーザーがストア(このマシンに登録されている独立した OpenSpec リポジトリ)を指定した場合、または作業対象がストア内にある場合は、openspec store list --json を実行して登録済みのストア ID を確認し、仕様や変更を読み書きするコマンド(new change、status、instructions、list、show、validate、archive、doctor、context、schemas、view)に --store <id> を渡します。いったん選択したら、ワークフローの残りの間は --store <id> を常に指定してください。以下に示す、ストア指定のないコマンド例はすべて省略形です。実行する前にフラグを追加してください。たとえば、以下に示すストア指定なしの形式ではなく、openspec status --change "<name>" --json --store "<id>" を実行します。コマンドが出力するヒントにはすでにフラグが含まれています。後続のコマンドでもフラグを維持してください。ストアを指定しない場合、コマンドは最も近いローカルの openspec/ ルートを対象にします。
プロジェクトの確認: この手順は、すでに OpenSpec を使用しているプロジェクトを対象としています。最初に書き込みを行う手順(new change、archive、sync specs、または成果物ファイルの作成)に進む前に、プロジェクトにルートがあることを確認してください。openspec list --json を実行し(ストアを選択している場合は、そのストアがルートとなるため --store <id> を指定します)、root を読み取ります。ルートオブジェクトがあれば、プロジェクトはセットアップ済みです。"root": null の場合はセットアップされていません。ここに openspec/ ディレクトリがなく、openspec new change のような書き込みコマンドを実行すると、副作用として作成されます。このコマンドはゼロ以外の終了コードも返しますが、それが答えです。CLI の不具合ではないため、再試行したり回避策を講じたりせず、JSON を確認してください。
"root": null でも、セットアップに関する問題ではない場合が1つあります。status のエラーメッセージが Declared in または Invalid store declaration in で始まり、このプロジェクトの openspec/config.yaml(または config.yml)を示している場合、このプロジェクトは宣言済みのストアを通じて OpenSpec を使用していますが、このマシンでは解決できません(ストアが登録されていないか、store: 行の形式が正しくありません)。未初期化と判断して以下の分岐をスキップしてはいけません。書き込みを行う前に停止し、そのエラーの message と fix をユーザーに表示してください。
それ以外の場合、ルートがないときの次の対応は、このワークフローを開始した経緯によって異なります。
- 自動選択: OpenSpec に言及することなく、このスキルやそのスラッシュコマンドも指定せずに、あなた自身でこのワークフローを選んだ場合は、OpenSpec の使用をやめ、OpenSpec がインストールされていない場合と同様に、通常どおりリクエストに回答してください。セットアップを求めたり、OpenSpec のセットアップについて言及したりしないでください。
- OpenSpec の明示的なリクエスト: ユーザーが OpenSpec に言及した、このスキルを指定した、またはそのスラッシュコマンドを実行した場合は、書き込みを行う前に停止し、次のどの方法で進めるかを尋ねてください。このプロジェクトをセットアップする(
openspec init)、既存のストアを対象にする(--store <id>)、または今回のリクエストでは OpenSpec を使わずに続行する。回答を待ってください。
どちらの分岐でも、副作用としてルートを作成してはいけません。ユーザーが求めるまで openspec init を実行せず、openspec/ ファイルを手動で作成せず、コマンドによる作成も許可しないでください。
<capability-path> は specs/ からの相対パスで指定する仕様ディレクトリです(例:user-auth または identity/user-auth)。メイン仕様を解決するときは、各差分仕様の完全なパスを維持してください。
入力: 不要(選択を促すプロンプトを表示します)
手順
-
アクティブな変更を取得する
openspec list --jsonを実行し、すべてのアクティブな変更を取得します。アクティブな変更がない場合は、ユーザーに伝えて終了します。
-
変更の選択を促す
ユーザーに変更を選択してもらいます(複数選択可)。
- リストの出力から各変更名とタスクのステータスを表示する
- 「すべての変更」オプションを含める
- 任意の数の選択を許可する(1つ以上で動作しますが、通常は2つ以上です)
重要: 自動選択してはいけません。必ずユーザーに選択してもらってください。
選択したルートの現在のアーカイブ入力を、バッチ検証の前に一度だけ読み込みます。 このルートから選択した変更を1つ選び、同じ選択済みルートのフラグを指定して
openspec instructions archive --change "<selected-change>" --jsonを実行します。この参照は参考用で任意です。追加のプロンプト入力を提供するだけなので、バッチを決して妨げてはなりません。失敗した場合や無効なJSONが返された場合(たとえば、このコマンドにまだ対応していない古いCLIの場合)は、コンテキストも操作ガイダンスもなしでバッチを続行します。エラーを報告したり、処理を停止したりしないでください。有効な応答では、
contextとoperationGuidanceが省略される場合があります。contextはバッチ全体で必要なプロンプトレベルの入力として扱います。読み取って検討し、関連するプロジェクトの事実、規約、制約を適用してください。operationGuidanceは任意の追加アドバイスとして扱います。すべての項目を読み取って検討し、組み込みのバッチワークフローに適用可能で、かつ矛盾しない項目に従ってください。両方のフィールドは、競合分析、ユーザーによる明示的な選択、解決済みパス、CLIチェック、コマンドの契約とは分けて扱ってください。コンテキストがそれらの制御入力と矛盾する場合は、その矛盾を報告し、制御入力の値を優先してください。ガイダンスが適用できない場合や、制御入力と矛盾する場合は、それに従わず、その理由を説明してください。どちらのフィールドからも、省略されたプロンプト、置換パス、フラグを推測しないでください。また、そのテキストを仕様、変更、要約にそのまま転載しないでください。これらはプロンプトレベルの動作契約であり、強制可能なチェックではありません。
-
バッチ検証 — 選択したすべての変更のステータスを収集する
タスクの進捗確認のため、同じ選択済みルートのフラグを指定して
openspec list --jsonを1回実行します。参照に失敗した場合、無効なJSONが返された場合、選択した変更が1つでも欠落している場合、選択した変更が重複している場合、またはカウントが無効な場合は、問題を報告し、バッチの同期やアーカイブを行う前に停止します。選択した変更ごとに、以下を収集します。
a. 成果物のステータス —
openspec status --change "<name>" --jsonを実行します。schemaName、artifacts、planningHome、changeRoot、artifactPaths、actionContextを解析します。- どの成果物が
doneで、どれがその他の状態かを記録します。
b. タスクの完了状況 — listの応答から、この変更と
nameが完全一致するchangesエントリを見つけます。totalTasksとcompletedTasksが非負の整数であり、completedTasks <= totalTasksであることを確認します。- 未完了タスク数 =
totalTasks - completedTasks - CLIは、カスタム成果物名、出力パス、globを含む、スキーマで追跡されているタスクファイルを解決します。
- 成果物のステータス、
tasksという成果物ID、またはトップレベルのtasks.mdが存在しないことから、タスクの完了を推測しないでください。 - CLIは
x/Xのチェックボックスマーカーのみを完了としてカウントします。その他のマーカーは未完了のままです。 totalTasksがゼロの場合は「タスクなし」と記録します。
c. 差分仕様 — status JSONの
artifactPaths.specs.existingOutputPathsを確認します。- 既存の機能仕様を一覧表示します。
- 各仕様から要件名(
### Requirement: <name>に一致する行)を抽出します。 - このリストだけを差分仕様の情報源として扱います。
specsエントリが存在しない場合、またはリストが空の場合、その変更の仕様同期や仕様の指示参照は行わないでください。無関係な成果物から差分を推測しないでください。 specs成果物がないスキーマを含む混在スキーマのバッチも含め、変更ごとに個別に評価します。 d. アーカイブ先 - 各変更のターゲット名を一度だけ計算し、その変更の<target-name>として記録します- すでに
YYYY-MM-DD-プレフィックスで始まっている場合は変更名をそのまま使用し、そうでない場合は現在の日付をYYYY-MM-DD-<name>として前に付けます(openspec archiveと同じルールです) <planningHome.changesDir>/archive/<target-name>がすでに存在するか確認します- 存在する場合、または選択した別の変更が同じターゲット名になる場合は、そのような変更をすべて
Blockedとし、Archive directory already existsと記録します - ブロックされた変更は同期も移動もされません。ステップ 6 の表では
Blockedと表示し、競合解決の対象から除外して(他の変更のみを使って競合を解決し)、ステップ 8d ではFailedと記録します - メインの仕様を書き込む前にここで確認することで、
openspec archiveと同じ動作になります。同期後に衝突が見つかると、アーカイブが実行されないのにメインの仕様だけが書き換えられてしまいます
-
仕様の競合を検出する
<capability-path>(specs/からの相対パスの完全一致)をキーとするマップを作成します。identity/user-auth -> [change-a, change-b] <- CONFLICT (2+ changes) billing/user-auth -> [change-c] <- OK (different full path)2 件以上の選択した変更に、まったく同じ
<capability-path>の差分仕様がある場合、競合が発生します。 -
エージェント的に競合を解決する
競合ごとに、コードベースを調査します。
a. 差分仕様を読む 各競合する変更の差分仕様を読み、それぞれが何を追加・変更するとしているかを把握します
b. コードベースを検索する 実装の根拠を探します:
- 各差分仕様の要件を実装するコードを探します
- 関連するファイル、関数、テストを確認します
c. 解決方法を決定する:
- 実装されている変更が 1 件だけの場合 → その変更の仕様を同期します
- 両方が実装されている場合 → 時系列順(古いものから新しいものへ)に適用し、新しいものが上書きします
- どちらも実装されていない場合 → 仕様の同期をスキップし、ユーザーに警告します
d. 各競合の解決内容を記録する:
- 変更と
<capability-path>をキーとして、各差分仕様を含めるか除外するかの判断 - 適用する対象として含める差分仕様と、その適用順序
- 実装が見つからないため、同期から除外する差分仕様
- 根拠(コードベースで見つかった内容)
-
統合ステータス表を表示する
すべての変更をまとめた表を表示します。
| Change | Artifacts | Tasks | Specs | Conflicts | Status | |---------------------|-----------|-------|---------|-----------|--------| | schema-management | Done | 5/5 | 2 delta | None | Ready | | project-config | Done | 3/3 | 1 delta | None | Ready | | add-oauth | Done | 4/4 | 1 delta | identity/user-auth (!) | Ready* | | add-verify-skill | 1 left | 2/5 | None | None | Warn |競合については、解決内容を表示します。
* Conflict resolution: - identity/user-auth spec: Will apply add-oauth then add-jwt (both implemented, chronological order)不完全な変更については、警告を表示します。
Warnings: - add-verify-skill: 1 incomplete artifact, 3 incomplete tasks -
一括操作を確認する
ユーザーに確認の質問を 1 つだけ行います。
- ステータスに応じた選択肢を用意し、「N 件の変更をアーカイブしますか?」と尋ねます
- 選択肢の例:
- 「N 件すべての変更をアーカイブ」
- 「準備完了の N 件の変更のみをアーカイブ(不完全な変更はスキップ)」
- 「キャンセル」
不完全な変更がある場合は、警告付きでアーカイブされることを明確に伝えます。
回答はラベルの完全一致ではなく、意図に基づいて処理します。ラベルは自分で作成したものなので、上記の文言ではなくユーザーが選んだ内容に合わせて判断します。
- 「キャンセル」— 停止し、アーカイブしません。何もアーカイブされなかったことを報告し、残りのステップをスキップします。
- すべてをアーカイブする選択肢 —
Blockedではない選択済みの変更をすべて処理します。 - 準備完了の変更のみをアーカイブする選択肢 — ステップ 6 の表で
ReadyまたはReady*とされた変更のみを処理し、残りはステップ 8d でSkippedと記録します。ただし、Blockedの変更はArchive directory already existsのままFailedとします。Ready*の変更の競合相手がスキップされる場合は、アーカイブ対象の変更のみを使って、その競合の解決内容を再度導き出します。 - 上記以外 — アーカイブせず、もう一度尋ねます
ステップ 8 が最初のメイン仕様を書き込むか、いずれかの変更を移動する前に、確認済みバッチに必要なすべての specs-rule スナップショットを取得します。具体的な
artifactPaths.specs.existingOutputPathsを同期する各変更について、同じ選択済みルートフラグを付けてopenspec instructions specs --change "<name>" --jsonをちょうど 1 回実行します。最初の書き込みまたは移動の前に、すべてのスナップショットを取得してください。いずれかのルックアップが非ゼロで終了するか、無効な artifact-instruction JSON を返した場合は、影響を受ける変更を特定し、エラーを報告し、メイン仕様の書き込みまたは変更の移動を行う前にバッチ全体を停止してください。ルックアップの失敗を、ルールの省略として扱わないでください。rulesを含まない有効な応答は、ルールなしのケースです。
-
確認済みの各変更に対してアーカイブを実行する
処理の前に、ステップ 5 で記録した決定(ステップ 7 での再導出がある場合はその後)を、デルタごとの 2 つのセットに引き継ぎます。
includedDeltas: 確認済みの変更からの競合しないすべてのデルタ仕様、および同期対象として選択された競合デルタexcludedDeltas: 実装が欠けているために除外された、確認済みの変更からの競合デルタ- 1 つの変更が、含まれるデルタ仕様と除外されるデルタ仕様の両方を持つことがあります。決定はデルタごとに保持してください。変更ごとの同期フラグにまとめないでください。
決定された順序で変更を処理します(競合解決を尊重します)。
a. 含まれるデルタ仕様を同期する:
includedDeltasにエントリがある変更に対してのみ、openspec-sync-specsワークフローをインラインで実行します(エージェント駆動のインテリジェントマージ)。含まれるデルタパスのみを渡し、その変更のexcludedDeltasを無視するよう明示的に指示します。完了するまで待ちます。- 同期が停止またはブロッキング条件を報告した場合、同期は失敗したものとして扱います。その変更の処理を直ちに停止します。次の変更へ進む前に、この変更の結果をバッチ結果に Failed として記録し、同期のブロッキング/エラー条件を含めます。
- 同期後のコンテンツ比較を実行せず、その
changeRootを移動しないでください。変更はそのまま残します。 - 競合については、解決された順序で適用します。
- その変更について取得した specs-rule スナップショットをインライン同期に渡します。インライン同期は、指示を再度取得せずにそれを再利用しなければなりません。
- artifact ルールは、その変更によって生成されたメイン仕様にのみ適用します。それらは競合解決、アーカイブの動作、CLI 契約を変更せず、そのテキストは出力ファイルにコピーされません。
- バックグラウンドタスクに委任しないでください。ステップ 8c は、まだ読み取り中の同期の下から
changeRootを移動してしまいます。 - 変更に含まれるデルタ仕様がない場合は、その変更に対して同期ワークフローを実行しないでください。
b. changeRoot を移動する前に、含まれるデルタ仕様を検証する:
<planningHome.root>/openspec/specs/<capability-path>/spec.mdのメイン仕様に対して、includedDeltas内のデルタ仕様のみを対象に比較を再実行します(ハードコードされたリポジトリパスではなく、ステップ 3 のステータス JSON から得たストア対応のplanningHome.rootを使用します)。- メイン仕様が更新されていることを検証します:
- ADDED された要件が存在する
- MODIFIED された要件が、デルタで指定されたシナリオと説明の変更を伴って存在し、その他のシナリオがそのまま維持されている
- REMOVED された要件が存在しない — また、この同期がケイパビリティを廃止した場合(最後の要件を削除し、
## Requirementsを空のままにした場合)、そのメイン仕様は空のまま残されず削除されている - RENAMED された要件が新しい名前で存在し、古い名前では存在しない
excludedDeltas内のデルタ仕様は検証しないでください。それらは意図的に未同期のままにされます。- 同期が失敗した場合、またはいずれかのケイパビリティが検証と一致しない場合は、差分を報告し、その変更の
changeRootの移動を失敗/スキップしてください — その変更をアーカイブしないでください。changeRootはそのまま残ります。
c. アーカイブを実行する:
ターゲット名: ステップ 3d でこの変更に対して記録した
<target-name>をそのまま使用します。ここで再計算しないでください。真夜中を過ぎて実行されるバッチは、ステップ 3 で一方の日付を確認し、もう一方へ移動してしまいます。 対象がすでに存在するか確認します:- 手順 3 ですでに確認済みですが、移動の直前にも再確認します。バッチ処理の途中で対象が作成される可能性があります。
- 存在する場合:この変更を
Archive directory already existsとして失敗に記録し、changeRootはそのままにします。手順 8a ですでに同期したメイン仕様があれば報告し、残りの変更を続行します。 - 存在しない場合:
changeRootをアーカイブディレクトリに移動します。
mkdir -p "<planningHome.changesDir>/archive" mv "<changeRoot>" "<planningHome.changesDir>/archive/<target-name>"移動によって入れ子になっていないことを確認します: 確認後に対象が作成された場合、
mvは終了コード 0 を返し、変更を対象の 中に 移動します。<planningHome.changesDir>/archive/<target-name>/<change-directory-name>(changeRootの最後のパス要素)が存在する場合は、そのディレクトリをchangeRootに戻し、この変更をArchive directory already existsとして失敗に記録します。アーカイブ済みとして報告してはいけません。d. 各変更の結果を記録します:
- 成功:アーカイブに成功
- 失敗:アーカイブまたは仕様の検証中にエラーが発生(エラーを記録)
- スキップ:ユーザーがアーカイブしないことを選択した場合(該当する場合)
- 同期をスキップ:
excludedDeltasの各差分について、変更、<capability-path>、および記録された理由を含めてsync skippedと報告します。これはアーカイブをスキップすることとは別です。
-
概要を表示
最終結果を表示します。
## Bulk Archive Complete Archived 3 changes: - schema-management-cli -> archive/2026-01-19-schema-management-cli/ - project-config -> archive/2026-01-19-project-config/ - add-oauth -> archive/2026-01-19-add-oauth/ Skipped 1 change: - add-verify-skill (user chose not to archive incomplete) Spec sync summary: - 4 delta specs synced to main specs - 1 delta spec sync skipped (add-jwt, identity/user-auth: implementation not found) - 1 conflict resolved (identity/user-auth: synced add-oauth, skipped add-jwt)失敗がある場合:
Failed 1 change: - some-change: Archive directory already exists
競合解決の例
例 1:一方のみ実装済み
Conflict: <planningHome.root>/openspec/specs/auth/spec.md touched by [add-oauth, add-jwt]
Checking add-oauth:
- Delta adds "OAuth Provider Integration" requirement
- Searching codebase... found src/auth/oauth.ts implementing OAuth flow
Checking add-jwt:
- Delta adds "JWT Token Handling" requirement
- Searching codebase... no JWT implementation found
Resolution: Only add-oauth is implemented. Will sync add-oauth specs only.
例 2:両方とも実装済み
Conflict: <planningHome.root>/openspec/specs/api/spec.md touched by [add-rest-api, add-graphql]
Checking add-rest-api (created 2026-01-10):
- Delta adds "REST Endpoints" requirement
- Searching codebase... found src/api/rest.ts
Checking add-graphql (created 2026-01-15):
- Delta adds "GraphQL Schema" requirement
- Searching codebase... found src/api/graphql.ts
Resolution: Both implemented. Will apply add-rest-api specs first,
then add-graphql specs (chronological order, newer takes precedence).
成功時の出力
## Bulk Archive Complete
Archived N changes:
- <change-1> -> archive/<target-name-1>/
- <change-2> -> archive/<target-name-2>/
Spec sync summary:
- N delta specs synced to main specs
- No conflicts (or: M conflicts resolved)
一部成功時の出力
## Bulk Archive Complete (partial)
Archived N changes:
- <change-1> -> archive/<target-name-1>/
Skipped M changes:
- <change-2> (user chose not to archive incomplete)
Failed K changes:
- <change-3>: Archive directory already exists
変更がない場合の出力
## No Changes to Archive
No active changes found. Create a new change to get started.
ガードレール
- 変更はいくつでも許可します(1 件でも問題ありません。一般的なユースケースでは 2 件以上です)
- 必ず選択を求め、自動選択はしません
- 仕様の競合を早期に検出し、コードベースを確認して解決します
- 両方の変更が実装されている場合は、仕様を時系列順に適用します
- 実装がない場合に限り、仕様の同期をスキップします(ユーザーに警告します)
- 確認前に、変更ごとのステータスを明確に表示します
- バッチ全体に対する確認は 1 回だけ行います
- ユーザーが確認をキャンセルした後は、決してアーカイブしません。キャンセルされたバッチでは何もアーカイブしません
- すべての結果(成功/スキップ/失敗)を追跡して報告します
- アーカイブに移動する際は .openspec.yaml を保持します
- アーカイブ先ディレクトリには、ステップ 3d で一度だけ計算して移動時に再利用する現在の日付を使用します:YYYY-MM-DD-。すでに
YYYY-MM-DD-プレフィックスで始まる名前はそのまま使用します(日付を二重に付けません) - アーカイブ先が存在する場合、その変更は失敗とし、ほかの変更は続行します
- 最初のメイン仕様を書き込む前に、ステップ 3 ですべてのアーカイブ先を確認します。対象がすでに存在する変更は、同期も移動もしません
- 同期が要求された場合、差分仕様が含まれる各変更について、
openspec-sync-specsワークフローをインラインで(エージェント主導で)実行します - 差分ごとの
includedDeltasとexcludedDeltasの判断を実行に引き継ぎ、含める差分のみを同期して検証します - 除外した差分はすべて
sync skippedとして報告し、アーカイブ自体をスキップ扱いにはしません - 仕様の同期が進行中の変更をアーカイブしてはいけません。同期をインラインで実行し、移動前に
<planningHome.root>/openspec/specs/<capability-path>/spec.mdのメイン仕様を検証します。その後でchangeRootを移動します - 仕様の確認や移動を行う前に、選択されたルートごとにアーカイブ入力を一度取得します
- バッチで最初のメイン仕様を書き込む、または移動する前に、必要な仕様ルールのスナップショットをすべて取得します
- アーカイブ入力の取得に失敗してもバッチはブロックしません。コンテキストもガイダンスもない状態で続行します
- 仕様指示の取得に失敗した場合は、バッチ全体をアトミックに停止します
- 具体的な
artifactPaths.specs.existingOutputPathsがない変更は、仕様の同期なしで続行します - 関連するランタイムコンテキストをバッチ全体に適用し、競合を報告します
- 操作ガイダンスはあくまで参考情報です。すべての項目を検討し、採用しない助言についても理由を説明します
- ランタイム入力、競合分析、CLI から取得した値、アーティファクトルールは、それぞれ分けて扱います
- アーティファクトルールは、書き込む仕様のみに適用します
- ランタイム入力やアーティファクトルールのテキストを、出力ファイルにそのままコピーしてはいけません