実験的ワークフローで完了した変更をアーカイブします。
ストアの選択: ユーザーがストア(このマシンに登録されているスタンドアロンの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つだけ存在する場合は自動選択します
- 曖昧な場合は、
openspec list --jsonを実行して利用可能な変更を取得し、ユーザーに一つ選択してもらいます
プロンプトを表示するときは、アクティブな変更のみ(すでにアーカイブされたものを除く)を表示します。 各変更で使用されているスキーマがわかれば含めます。
常に「変更 '' を使用します」と、変更方法(例:
/opsx:archive <other>)を通知します。既存のアーカイブ確認の前に、現在のアーカイブ入力を読み込む:
選択した変更とルートを解決した後、次を実行します:
openspec instructions archive --change "<name>" --jsonこのコマンドには、同じ選択されたルートフラグを維持します。この参照はアドバイザリであり、オプションです。これは追加のプロンプト入力のみを提供するため、アーカイブをブロックしてはなりません。このコマンドが非ゼロで終了したり、無効なJSONを返したりした場合(例えば、このコマンドをまだサポートしていない古いCLIなど)、コンテキストなし、操作ガイダンスなしでアーカイブワークフローを続行します。エラーを報告したり停止したりしないでください。
成功した応答では、両方のオプションフィールドが省略される場合があります。
contextは必須のプロンプトレベル入力として扱います。読み取り、考慮し、関連するプロジェクトの事実、規則、制約を適用します。operationGuidanceはオプションの追加アドバイスとして扱います。すべてのエントリを読み取り、考慮し、適用可能で組み込みのアーカイブワークフローと互換性のあるエントリに従います。両方のフィールドを、組み込みの手順、明示的なユーザーの選択、解決されたパス、CLIチェック、コマンド契約とは別に保持します。
contextがこれらの制御入力のいずれかと競合する場合は、競合を報告し、制御側の値を保持します。ガイダンスが適用できない場合、または制御入力と競合する場合は、それに従わず、その理由を説明します。どちらのフィールドからも、置き換えパス、スキップされたプロンプト、またはフラグを推論してはならず、ユーザーが別途要求しない限り、そのテキストをスペック、変更アーティファクト、アーカイブサマリーにそのままコピーしてはなりません。これらはプロンプトレベルの動作契約であり、強制可能なチェックではありません。 -
成果物の完了状態を確認する
openspec status --change "<name>" --jsonを実行して、成果物の完了状態を確認します。JSONを解析して以下を理解します:
schemaName: 使用されているワークフローplanningHome、changeRoot、artifactPaths、actionContext: パスとスコープのコンテキストartifacts: ステータス(done、skipped、またはその他)を持つ成果物のリスト
成果物が
doneでもskippedでもないものがある場合(スキップされた成果物は要件を満たします - 変更がskip_specsを宣言している場合):- 未完了の成果物をリストアップした警告を表示します
- ユーザーに続行してもよいか確認します
- ユーザーが確認した場合は続行します
-
タスクの完了状態を確認する
同じ選択ルートフラグを使用して
openspec list --jsonを実行し、changes内のnameが選択した変更と完全に一致するエントリを見つけます。 ちょうど1つの一致と、非負の整数totalTasksおよびcompletedTasks(completedTasks <= totalTasks)が必要です。CLIは、カスタムアーティファクト名、出力パス、グロブを含む、スキーマの追跡対象タスクファイルを解決します。 未完了タスク =totalTasks - completedTasks。成果物ステータスやトップレベルの
tasks.mdがないことからタスク完了を推論しないでください。ルックアップが失敗したり、無効なJSONを返したり、選択した変更を省略したり重複したり、無効なカウントを返したりした場合は、問題を報告し、同期またはアーカイブする前に停止します。 CLIはx/Xチェックボックス記号のみを完了としてカウントします。他の記号(なじみのないものを含む)は未完了のままです。未完了のタスクが見つかった場合:
- 未完了タスクの数を示す警告を表示します
- ユーザーに続行してもよいか確認します
- ユーザーが確認した場合は続行します
totalTasksがゼロの場合: タスク関連の警告なしで続行します。 -
デルタスペックの同期状態を評価する
ステータスJSONの
artifactPaths.specs.existingOutputPathsを唯一のデルタスペックソースとして使用します。specsエントリがない場合やexistingOutputPathsが空の場合は、同期プロンプトなしで続行し、他の成果物からデルタスペックを推論しないでください。デルタスペックが存在する場合:
- 各デルタスペックを、対応するメインスペック(
<planningHome.root>/openspec/specs/<capability-path>/spec.mdにある。手順2のストア認識型planningHome.rootを使用し、ハードコードされたリポジトリパスは使用しない)と比較します - メインスペックがないことは、自動的に「すでに同期済み」にはなりません。新しい機能の場合、メインスペックは同期の出力であり、入力ではありません:
- デルタに修正(MODIFIED)または名称変更(RENAMED)された要件がある場合、追加(ADDED)要件のみが新しいメインスペックを作成できることを報告し、その機能を同期ブロックとしてマークします。現在のバージョンがない要件を発明してはいけません。
- それ以外の場合、デルタに削除(REMOVED)要件のみがあり、変更の
.openspec.yamlがretire_capabilities: trueを宣言している場合、機能はすでに廃止されています。すでに同期済みとしてカウントし、削除するものが何もないことを警告し、メインスペックを再作成しないでください。このルールは、完了した同期を検証するときにも適用されます。 - それ以外の場合、デルタに追加(ADDED)要件がない場合は、同期が不可能であることを報告し、その機能を同期ブロックとしてマークします。削除(REMOVED)のみのデルタの場合、削除元のメインスペックがないことを警告し、メインスペックツリーを変更しないままにします。
openspec archiveは、マークされていない削除(REMOVED)のみのケースを「Spec must have at least one requirement」で拒否します。 - それ以外の場合、機能は同期が必要としてカウントし、サマリーに名前を付けます(
<capability-path>: 新しいメインスペックが作成されます)。デルタに削除(REMOVED)要件もある場合は、削除元のメインスペックがないため無視されることを警告します。同期は、openspec archiveとまったく同様に、デルタの追加(ADDED)要件からのみメインスペックを作成します。
- どのような変更が適用されるかを決定します(追加、修正、削除、名称変更)
- 1つの機能が同期ブロックされていても、残りの機能の評価を続行します。プロンプトを表示する前に、結合されたサマリーを表示します。
プロンプトオプション:
- 同期ブロックされた機能がある場合: 理由を説明し、「同期せずにアーカイブ」、「キャンセル」のみを提供します
- それ以外の場合、変更が必要な場合: 「今すぐ同期(推奨)」、「同期せずにアーカイブ」
- それ以外の場合、すでに同期済みの場合: 「今すぐアーカイブ」、「それでも同期」、「キャンセル」
回答に応じてルーティング:
- 「キャンセル」 — 停止、アーカイブしない
- 「同期せずにアーカイブ」または「今すぐアーカイブ」 — アーカイブに進む
- 「今すぐ同期」または「それでも同期」 — 同期し、検証する(下記参照)。機能が同期ブロックされている間は同期を開始しないでください。ブロッカーを説明し、利用可能な選択肢を繰り返します。
- その他 — アーカイブする代わりに再度尋ねる
選択された同期がメインスペックを書き込む前に、同じ選択ルートフラグを使用して
openspec instructions specs --change "<name>" --jsonを1回実行します。ゼロの終了ステータスと有効なアーティファクト指示JSONが必要です。ルックアップが失敗したり無効なJSONを返したりした場合は、エラーを報告し、メインスペックを書き込んだり変更を移動したりする前に停止します。省略されたrulesを持つ有効な応答は、ルールなしのケースです。返されたrulesは、このマージによって生成されるメインスペックのコンテンツと形式にのみ適用します。アーカイブガイダンスとして使用したり、CLIの動作を変更したり、ルールテキストを出力ファイルにコピーしたりしないでください。次に、変更 '' に対して
openspec-sync-specsワークフロー(エージェント駆動のインテリジェントマージ)をインラインで実行し、上記のデルタスペック分析と取得したスペックルールスナップショットを渡し、完了するまで待ちます。インライン同期は、そのスナップショットを再利用し、specs指示を再度取得してはいけません。これをバックグラウンドタスクに委任しないでください。手順5が同期の読み取り中にchangeRootを移動させ、変更がアーカイブされ、メインスペックが更新されないままになります。エージェントが委任によってのみ実行できる場合は、同期的に委任し、結果を待ちます。同期が停止またはブロック状態を報告した場合、同期は失敗として扱います。 すぐにアーカイブを停止します。同期後のコンテンツ比較を実行せず、その
changeRootを移動しないでください。 何も移動していないため、ユーザーはブロック状態を修正するか、同期を再実行できます。同期が各メインスペックを書き込んだ後、その構造を正規の同期契約に対して検証します:
- 新しいメインスペックは
# <capability> 仕様というタイトルで始まります。既存のメインスペックは、タイトルをそのまま維持します。 - 確立されたメインスペックの既存の
## Purposeセクションを完全にそのまま保持します。 - 新しいメインスペックの場合、デルタの
## Purposeをそのままコピーします。目的テキストが標準の検証が期待するよりも短い場合のみ警告します。既存の作成済みの目的を再生成したり書き換えたりしないでください。使用可能な## Purposeが提供されていない場合は、既存のTBD目的の動作と警告を使用します。 - デルタスタイルのセクションヘッダー(
## ADDED Requirements、## MODIFIED Requirements、## REMOVED Requirements、## RENAMED Requirements)がメインスペックに残っていないことを検証し、同期ワークフローのフォーマットルールに厳密に従います。 - 同期が書き込んだり変更したりした要件ブロックは、
### Requirement:見出しを使用し、そのシナリオは#### Scenario:見出しを使用します。デルタが言及していないコンテンツはそのままにします。
次に、この手順の先頭から比較を再実行します。これには、明示的に廃止され、スペックがないケースも含め、
artifactPaths.specs.existingOutputPathsにデルタスペックがあるすべての機能に対して、同期が触れたと報告するものだけでなく、すべてを対象とします。成功した同期では、適用すべきものが何も残っていないため、各機能はすでに同期済みと読み取れる必要があります:- 追加(ADDED)された要件が存在する
- 修正(MODIFIED)された要件が、デルタで指定されたシナリオと説明の変更を保持し、他のシナリオはそのまま
- 削除(REMOVED)された要件が削除されている — この同期で機能が廃止された場合(最後の要件が削除され、
## Requirementsが空になった場合)、メインスペックは空のまま残されるのではなく削除されています。 - 名称変更(RENAMED)された要件が新しい名前で存在し、古い名前では存在しない
同期が失敗した場合、または機能のいずれかが一致しない場合は、何が異なるかを報告し、停止します。アーカイブしないでください。何も移動しておらず、
changeRootはそのままなので、ユーザーは不一致を修正するか、同期を再実行してアーカイブを再開できます。 - 各デルタスペックを、対応するメインスペック(
-
アーカイブを実行する
planningHome.changesDirの下にarchiveディレクトリが存在しない場合は作成します:mkdir -p "<planningHome.changesDir>/archive"ターゲット名を生成します: 変更名がすでに
YYYY-MM-DD-プレフィックスで始まっている場合はそのまま使用します。そうでない場合は、現在の日付をYYYY-MM-DD-として先頭に追加します。次に、変更ディレクトリを
archiveに移動します:mv "<changeRoot>" "<planningHome.changesDir>/archive/<target-name>"これにより、変更が同じストア内のアーカイブされた変更のリストに効果的に移動されます。
-
確認する
openspec list --json(該当する場合は--store <id>付き)を実行して変更をリストし、changesにアーカイブした変更が含まれていないことを確認します。ユーザーにアーカイブが完了したことを通知します。
備考:
- このワークフローは、スキップされた機能(
skip_specs: true)を含むアーカイブをサポートします。 - アーカイブをブロックするのではなく、同期についてアドバイスするために
instructions archiveを使用します。 - このワークフローは、変更がアーカイブされる前にすべての変更が適切に統合されることを保証します。
- 同期ワークフローは、エージェント駆動のインテリジェントマージを実行して、デルタからメインスペックを作成または更新します。