openspec-sync-specs について
openspec-sync-specsは、変更内容の差分仕様を対応するメイン仕様へ統合するエージェントスキルです。追加・変更・削除・名称変更を反映しつつ、対象外の要件やシナリオを保持します。
主な機能
- 01差分仕様をメイン仕様へ統合
- 02対象外の要件とシナリオを保持
- 03要件の追加・変更・削除・名称変更
- 04更新した仕様を検証
活用シーン
- 01変更の要件をメイン仕様に反映
- 02変更のアーカイブ時にメイン仕様を整合
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wot-ui/ open-wot --skill openspec-sync-specsインストール後、Claude Code で/openspec-sync-specsを入力して読み込まれたか確認します。
詳細
変更内容からメイン仕様へ差分仕様を同期します。
これはエージェント主導の操作です。差分仕様を読み、変更を反映するためにメイン仕様を直接編集します。これにより、要件全体をコピーせずにシナリオを追加するなど、インテリジェントにマージできます。
ストアの選択: ユーザーがストアを指定した場合(ストアとは、このマシンに登録されている独立した 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/ ルートを対象にします。
<capability-path> は、specs/ からの相対パスで表される仕様ディレクトリです(例:user-auth または identity/user-auth)。メイン仕様を特定する際は、各差分仕様の完全なパスを保持してください。
入力:変更名は任意で指定できます。省略された場合は、会話の文脈から特定できるか確認してください。曖昧な場合や候補が複数ある場合は、利用可能な変更をユーザーに確認する必要があります。
手順
-
変更を選択する
名前が指定されている場合は、それを使用します。指定されていない場合:
- ユーザーが会話内で変更に言及していれば、そこから推測します
- アクティブな変更が 1 つだけの場合は、自動選択します
- 候補が複数ある場合は、
openspec list --jsonを実行して利用可能な変更を取得し、ユーザーに選択を依頼します
ユーザーに確認する際は、差分仕様(
specs/ディレクトリ内)がある変更を表示します。必ず「Using change: 」と、その変更名を上書きする方法(例:
/openspec-sync-specs <other>)を伝えます。 -
変更のコンテキストを解決する
次を実行します。
openspec status --change "<name>" --jsonJSON には
planningHome.rootが含まれています。メイン仕様は<planningHome.root>/openspec/specs/にあります。以下でメイン仕様のパスを指定する際は、ハードコードされたリポジトリのパスではなく、このストアを考慮したルートを使用してください。ストアを選択した場合、このルートは現在のリポジトリではなく、ストアを指します。 -
差分仕様を見つける
差分仕様のパスの取得元として使用するのは、ステータス JSON の
artifactPaths.specs.existingOutputPathsのみです。specsエントリがない場合、またはexistingOutputPathsが空の場合は、同期対象の差分仕様がないことを報告し、他のアーティファクトからパスを推測せず、アーティファクトの指示を要求したりメイン仕様を書き換えたりせずに終了します。呼び出し側が対象を絞り込んでいない限り、
existingOutputPaths内のすべてのパスを同期します。対象を絞り込む場合は、existingOutputPathsに含まれる完全な項目を明示的に列挙し、その絶対パスをそのままコピーします。アーカイブ処理ではこれをインラインで行います。ユーザーも同様に指定できます(たとえば、/specs/billing/invoices/spec.mdで終わる項目を選択します)。 その後は指定されたパスのみを同期し、残りの差分仕様には手を加えません。一括アーカイブでは、実装を見つけられなかった差分は対象から除外されます。それでも同期すると、呼び出し側が意図的に対象から外したメイン仕様を書き換えることになります。絞り込んだ選択内容は手順 4 まで維持し、すべてのパスに対象を広げ直してはいけません。指定されたパスがexistingOutputPathsに含まれていない場合は、そのパスを報告して終了します。黙って除外してはいけません。指定リストが空の場合は、同期対象がないことを報告し、メイン仕様を書き換えずに終了します。各差分仕様ファイルには、次のようなセクションが含まれます。
## ADDED Requirements- 追加する新しい要件## MODIFIED Requirements- 変更する既存の要件## REMOVED Requirements- 削除する要件## RENAMED Requirements- 名前を変更する要件(FROM:/TO: 形式)
差分仕様が見つからない場合は、その旨をユーザーに伝えて終了します。
-
各デルタ仕様に従ってメイン仕様を更新する
最初にメイン仕様を書き込む前に、現在の仕様ルールのスナップショットを1つ取得します。
- archive がこのワークフローをインラインで呼び出し、
openspec instructions specs --change "<name>" --jsonから有効なスナップショットを提供している場合は、それを再利用し、同じ指示を再取得しないでください。 - それ以外の場合は、選択したルートと同じフラグを使って、今すぐこのコマンドを1回実行します。
- 直接の検索がゼロ以外で終了するか、無効なアーティファクト指示の JSON を返した場合は、エラーを報告し、メイン仕様を書き込む前に停止します。この失敗をルールセットが存在しないものとして扱わないでください。
rulesが省略された有効なレスポンスは、アーティファクトルールが設定されていないことを意味し、既存のセマンティックマージを続行します。
返された
rulesは、このマージによって生成されるメイン仕様の内容と形式にのみ適用します。アーティファクトルールは操作手順ではなく、選択したルート、デルタパス、CLI チェック、ワークフローの手順を変更できません。そのテキストは制約として使用し、メイン仕様や概要にそのまま転記しないでください。手順3で選択した各機能デルタ仕様パスについて、メイン仕様を更新します。対象は
existingOutputPathsの全リスト、または呼び出し元が指定した場合は絞り込まれたサブセットです(これらはリポジトリではなく、選択したストアに属する場合があります)。a. デルタ仕様を読み、意図された変更を把握します。
b.
<planningHome.root>/openspec/specs/<capability-path>/spec.mdにあるメイン仕様を読みます(まだ存在しない場合もあります)。c. 適切に変更を適用します:
ADDED 要件:
- 要件がメイン仕様に存在しない場合 → 追加します
- 要件がすでに存在する場合 → 一致するよう更新します(暗黙の MODIFIED として扱います)
MODIFIED 要件:
- メイン仕様内で要件を見つけます
- 変更を適用します。たとえば、次のような変更があります。
- メイン仕様にまだないシナリオを追加する
- 既存のシナリオを変更する
- 要件の説明を変更する
- デルタで言及されていないシナリオや内容は保持します。
REMOVED 要件:
- 要件ブロック全体をメイン仕様から削除します
- 機能を廃止します。以下の条件をすべて満たす場合に限り、
spec.md全体と、他に何も残っていない場合はそのディレクトリを削除します。- 今回の実行で要件を削除した結果、要件ブロックが残らない。
- 仕様の残りが適切な形式である(
## Purposeが残っている)。 - 同期前からメイン仕様が空ではなかった。何も削除していない場合は変更しない。
- ファイル全体の空白でない行がすべて、タイトル、Purpose、Requirements ヘッダー、または正規の要件のステートメント、シナリオ、フェンス付きの例のいずれかに該当する。
- 変更の
.openspec.yamlでretire_capabilities: trueが宣言されている。 spec.mdが実際の仕様ルート内に解決される(機能ディレクトリのシンボリックリンクをたどって、外部ファイルを削除しない)。 選択した要件を削除すると要件ブロックが残らず、廃止条件のいずれかが満たされない場合は、メイン仕様を変更しないでください。その機能の同期を停止し、阻止条件を報告して、ユーザーに解決方法を伝えてください。空の## Requirementsセクションを決して書き込んだり、残したりしないでください。 不足しているのがマーカーだけの場合は、そのことも伝えてください。廃止を実行可能にするためにユーザーが追加できるのは、そのマーカーだけです。
- ファイルの削除により
## Purposeも削除されます。その他のセクションブロックがあると廃止できません。廃止を報告する際は Purpose に言及してください。仕様が呼び出し元のチェックアウト内にあった場合に限り、貼り付け可能なgit checkoutコマンドを含めます。それ以外の場合は、チェックアウトの範囲に限定した復旧方法を案内します。
RENAMED 要件:
- FROM 要件を見つけ、TO に名前を変更します。
デルタの
## Purpose:- メイン仕様にすでにある Purpose が正式な内容です。変更しないでください(これは
openspec archiveの動作と同じです。警告を出して先に進みます)。 d. まだ存在しない機能の場合は、メイン仕様を新規作成します: <planningHome.root>/openspec/specs/<capability-path>/spec.mdを作成します- Purpose セクションを追加します。差分に
## Purposeの本文がある場合は、そのままコピーします (これはopenspec archiveの動作です)。ない場合に限り、簡潔な TBD プレースホルダーを記述します - ADDED 要件を含む Requirements セクションを追加します
- 以下のメイン仕様フォーマットのリファレンスに従います
- archive がこのワークフローをインラインで呼び出し、
-
更新したメイン仕様を検証する
先ほどと同じ選択済みルートフラグを使って、
openspec validate --specsを実行します。 検証に失敗した場合は問題を報告し、同期が成功したと主張しないでください。 -
概要を表示する
すべての変更を適用した後、次の内容を要約します:
- 更新した機能
- 変更内容(要件の追加/変更/削除/名前変更)
- TBD の Purpose プレースホルダーを残した新しいメイン仕様(そのまま残さず、今すぐ記述できるようにします)
- 廃止した機能。削除した
spec.mdの名前と Purpose、および貼り付けて実行できるgit checkoutコマンド、またはチェックアウト範囲を限定した復元手順を明記します
差分仕様フォーマットのリファレンス
## Purpose
Only on a delta that introduces a brand-new capability. Seeds the new main spec.
## ADDED Requirements
### Requirement: New Feature
The system SHALL do something new.
#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
## MODIFIED Requirements
### Requirement: Existing Feature
The system SHALL keep doing the existing thing, now also handling A.
#### Scenario: Scenario the main spec already has
- **WHEN** user does X
- **THEN** system does Y
#### Scenario: New scenario to add
- **WHEN** user does A
- **THEN** system does B
## REMOVED Requirements
### Requirement: Deprecated Feature
## RENAMED Requirements
- FROM: `### Requirement: Old Name`
- TO: `### Requirement: New Name`
メイン仕様フォーマットのリファレンス
メイン仕様は差分がマージされる先です。差分操作の見出し(## ADDED/MODIFIED/REMOVED/RENAMED Requirements)を含めてはいけません。同期後は、すべての要件が単一の ## Requirements セクションの下に置かれている必要があります。
# <capability> Specification
## Purpose
Short description of what this capability does and why it exists.
## Requirements
### Requirement: New Feature
The system SHALL do something new.
#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
重要な原則:適切なマージ
プログラムによるマージとは異なり、上書きではなくマージします:
- MODIFIED ブロックには、要件全体(本文と、変更後も残るすべてのシナリオ)が含まれます。
openspec validateとopenspec archiveはどちらも、メイン仕様に残っているシナリオを削除した場合はエラーにします。 - 差分で言及されていない内容は、メイン仕様内の既存の順序を保って残します
- 変更を適切にマージするために、適切な判断をしてください
成功時の出力
## Specs Synced: <change-name>
Updated main specs:
**<capability-1>**:
- Added requirement: "New Feature"
- Modified requirement: "Existing Feature" (added 1 scenario)
**<capability-2>**:
- Created new spec file
- Added requirement: "Another Feature"
Main specs are now updated. The change remains active - archive when implementation is complete.
ガードレール
- 変更を加える前に、差分仕様とメイン仕様の両方を読みます
- 差分で言及されていない既存の内容を保持します
- 差分ファイルをそのままメイン仕様にコピーしないでください。差分操作の見出しを含めず、メイン仕様フォーマットのリファレンスに沿った構造を保つよう、内容をマージします
- 不明な点があれば、明確化を求めます
- 変更内容を逐次表示します
- この操作は冪等である必要があります。2 回実行しても同じ結果になります
artifactPaths.specs.existingOutputPathsのみを使用します。無関係な成果物から差分仕様を推測しないでください- 呼び出し元が指定した
existingOutputPathsのサブセットを尊重します。リスト全体に拡張し直してはいけません - 直接同期する場合は仕様の指示を一度取得するか、アーカイブから渡されたスナップショットをインラインで再利用します
- 仕様の指示の応答がゼロ以外の終了コードである場合、または無効な JSON の場合は、メイン仕様への書き込みを行う前に必ず停止します
- 成果物のルールは書き込み対象の仕様にのみ適用し、出力ファイルにコピーしません