Communityコーディング&開発github.com

robsonprod/portfolio

Δスペックの変更をメインスペックに同期します。ユーザーがメインスペックを更新したい場合や「openspec sync」または「opsx sync」と入力した場合に使用します。

portfolio とは?

このスキルは、OpenSpecのデルタスペック(変更仕様)の変更をメインスペックにインテリジェントにマージするエージェント駆動型のワークフローを提供します。単純に上書きするのではなく、要件の追加、変更、削除、リネームを適切に処理し、既存のコンテンツを保持します。特に、Claude CodeやCursorなどのAIエージェントが、ユーザーの明示的な指示(例:「openspec sync」)や会話の文脈に基づいて自動的に同期を実行できるように設計されています。このスキルは、ストア(スタンドアロンのOpenSpecリポジトリ)の選択、プロジェクトの初期化確認、デルタスペックの読み取り、メインスペックへの変更適用、結果の検証、サマリー表示までの一連のステップをカバーします。また、依存関係のない新しい機能の作成、機能の廃止(リタイア)、バリデーションエラーの処理など、エッジケースも考慮しています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/robsonprod/portfolio/tree/HEAD/.claude/skills/openspec-sync-specs

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

変更からデルタスペックをメインスペックに同期します。

これはエージェント駆動型の操作です。デルタスペックを読み取り、メインスペックを直接編集して変更を適用します。これにより、インテリジェントなマージ(例:要件全体をコピーせずにシナリオを追加するなど)が可能になります。

ストアの選択: ユーザーがストア(このマシンに登録されているスタンドアロンの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 オブジェクトはプロジェクトがセットアップされていることを意味します。"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)。各デルタスペックから完全なパスを保持して、そのメインスペックを解決します。

入力: 変更名をオプションで指定します。省略された場合は、会話のコンテキストから推測できるかどうかを確認します。あいまいまたは不明瞭な場合は、利用可能な変更をプロンプトで表示する必要があります。

手順

  1. 変更を選択

    名前が指定されている場合は、それを使用します。それ以外の場合:

    • ユーザーが変更について言及した場合は、会話のコンテキストから推測します
    • アクティブな変更が1つだけ存在する場合は、自動選択します
    • あいまいな場合は、openspec list --json を実行して利用可能な変更を取得し、ユーザーに1つを選択するよう依頼します

    プロンプトを表示するときは、デルタスペック(specs/ ディレクトリ内)を持つ変更を表示します。

    常に「変更 '' を使用しています」と、オーバーライドする方法(例:/opsx:sync <other>)を通知します。

  2. 変更コンテキストを解決

    以下を実行します:

    openspec status --change "<name>" --json
    

    JSONには planningHome.root が含まれています。メインスペックは <planningHome.root>/openspec/specs/ の下にあります。以下のすべてのメインスペックパスには、ハードコードされたリポジトリパスではなく、その(ストア対応の)ルートを使用します。ストアが選択されている場合、それは現在のリポジトリではなくストアを指します。

  3. デルタスペックを検索

    artifactPaths.specs.existingOutputPaths をステータスJSONからデルタスペックパスの唯一のソースとして使用します。specs エントリが欠落しているか、existingOutputPaths が空の場合は、同期するデルタスペックがないことを報告し、他のアーティファクトから推測せず、アーティファクトの指示を要求したりメインスペックを書き込んだりせずに停止します。

    呼び出し元がセットを絞り込まない限り、existingOutputPaths 内のすべてのパスを同期します。呼び出し元は、existingOutputPaths からの完全なエントリの明示的なリストに名前を付けることで絞り込みます。これらの絶対値をそのままコピーします。Archiveはこれをインラインで行い、ユーザーも行うことができます(例:/specs/billing/invoices/spec.md で終わるエントリを選択する)。次に、名前付きパスのみを同期し、残りのデルタスペックはそのままにします。バルクアーカイブは、実装が見つからなかったデルタを除外し、とにかく同期すると、呼び出し元が意図的に保留したメインスペックが書き込まれます。その絞り込まれた選択をステップ4まで引き継ぎます。決して完全なリストに戻さないでください。名前付きパスが existingOutputPaths にない場合は、同期しないでください。それを報告して停止します。静かにドロップしないでください。名前付きリストが空の場合は、同期するものがないことを報告し、メインスペックを書き込まずに停止します。

    各デルタスペックファイルには、次のようなセクションが含まれています。

    • ## ADDED Requirements - 追加する新しい要件
    • ## MODIFIED Requirements - 既存の要件への変更
    • ## REMOVED Requirements - 削除する要件
    • ## RENAMED Requirements - リネームする要件(FROM:/TO: 形式)

    デルタスペックが見つからない場合は、ユーザーに通知して停止します。

  4. 各デルタスペックについて、メインスペックに変更を適用

    最初のメインスペック書き込みの前に、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 にあります(まだ存在しない可能性があります)

    まだ存在しない場合(新しいケイパビリティ)、openspec archive が行うことに一致します。 ADDED要件のみが適用される場合があります。ステップdがそれらからスペックを作成します。 MODIFIEDとRENAMEDには、アクションを実行する要件がないため、そのケイパビリティの同期を停止し、そのメインスペックが存在せず、新しいスペックにはADDEDのみが許可されることを報告します。欠落している要件を発明しないでください。REMOVEDには削除するものがないため、スキップして警告します。

    c. 変更をインテリジェントに適用:

    ADDED Requirements:

    • 要件がメインスペックに存在しない場合 → 追加します
    • 要件がすでに存在する場合 → 一致するように更新します(暗黙のMODIFIEDとして扱います)

    MODIFIED Requirements:

    • メインスペック内の要件を見つけます
    • 変更を適用します。これには以下が含まれます。
      • メインスペックにまだない新しいシナリオの追加
      • 既存のシナリオの変更
      • 要件の説明の変更
    • デルタで言及されていないシナリオ/コンテンツを保持します

    REMOVED Requirements:

    • メインスペックから要件ブロック全体を削除します
    • ケイパビリティを廃止します。次のすべてが当てはまる場合にのみ、spec.md 全体、およびディレクトリに他に何も残っていない場合はディレクトリを削除します。
      1. 今回の実行で要件を削除した結果、要件ブロックが残っていない。
      2. スペックの残りの部分が適切な形式である(まだ ## Purpose がある)。
      3. この同期の前にメインスペックがすでに空ではなかった。何も削除しなかった場合は、何も変更しない。
      4. ファイル内の他のすべての非空白行が、タイトル、Purpose、Requirementsヘッダー、または正規の要件のステートメント、シナリオ、またはフェンスで囲まれた例として説明されている。
      5. 変更の .openspec.yaml が retire_capabilities: true を宣言している。
      6. spec.md が実際のスペックルート内に解決される(ケイパビリティディレクトリのシンボリックリンクをたどって外部ファイルを削除しない)。 選択された要件を削除しても要件ブロックが残らず、廃止条件のいずれかが満たされない場合は、メインスペックを変更しないでください。そのケイパビリティの同期を停止し、ブロックしている条件を報告し、ユーザーにそれを解決する方法を伝えます。空の ## Requirements セクションを書き込んだり、残したりしないでください。マーカーのみが欠落している場合も、それを伝えてください。これはユーザーが廃止を通過させるために追加できる唯一のことです。
    • ファイルを削除すると、その ## Purpose も削除されます。他のセクションブロックは廃止をブロックします。廃止を報告するときにPurposeに名前を付けます。貼り付け可能な git checkout は、スペックが呼び出し元のチェックアウトに存在した場合にのみ含めます。それ以外の場合は、チェックアウトスコープのリカバリガイダンスを提供します。

    RENAMED Requirements:

    • FROM要件を見つけ、TOにリネームします

    デルタ内の ## Purpose:

    • メインスペックにはすでにPurposeがあり、それが信頼できるものです。そのままにしておきます(これが openspec archive の動作です。警告して次に進みます)

    d. ケイパビリティがまだ存在しない場合は、新しいメインスペックを作成:

    • デルタに、そこに配置するADDED要件があり、ステップbでMODIFIEDまたはRENAMED要件がこのケイパビリティをブロックしなかった場合にのみ。それ以外の場合は何も作成せず、スペックディレクトリに触れません。REMOVEDのみのデルタの場合、変更の .openspec.yaml が retire_capabilities: true を宣言している場合は、すでに廃止されているものとして報告し、スペックを再作成せずに続行します。そのマーカーがない場合は、同期がブロックされていることを報告します。openspec archive は「スペックには少なくとも1つの要件が必要です」で拒否します。空のデルタには同期する操作がありません。同様にブロックされているものとして報告します。 空の ## Requirements セクションを書き込まないでください。
    • <planningHome.root>/openspec/specs/<capability-path>/spec.md を作成します
    • Purposeセクションを追加します。デルタに ## Purpose がある場合は、その本文をそのままコピーします(これが openspec archive の動作です)。ない場合は、簡単なTBDプレースホルダーのみを書き込みます
    • ADDED要件を含むRequirementsセクションを追加します
    • 以下のメインスペック形式リファレンスに従います
  5. 更新されたメインスペックを検証

    以前と同じ選択されたルートフラグを使用して openspec validate --specs を実行します。 検証が失敗した場合は、問題を報告し、同期が成功したと主張しないでください。

  6. サマリーを表示

    すべての変更を適用した後、以下を要約します。

    • どのケイパビリティが更新されたか
    • どのような変更が行われたか(要件の追加/変更/削除/リネーム)
    • TBD Purposeプレースホルダーが残された新しいメインスペック。これにより、遅延することなく今すぐ書き込まれます。
    • 廃止されたケイパビリティ。削除された spec.md、そのPurpose、および貼り付け可能な git checkout またはチェックアウトスコープのリカバリガイダンスを指定します。

デルタスペック形式リファレンス

# Spec Delta

## 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 はどちらも、メインスペックがまだ持っているシナリオをドロップするものを拒否します。
  • デルタが言及していないものは、メインスペックの既存の順序で保持します。
  • y

…

[翻訳のため省略]

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

関連スキル