accelint-qrspi-archive について
1 件または複数の OpenSpec 変更をアーカイブし、機能間リンク、仕様インデックス、追記型変更ログを更新するスキルです。OpenSpec のアーカイブ記録を一連の処理として管理するプロジェクト向けです。
主な機能
- 01OpenSpec の単件・一括アーカイブを実行
- 02アーカイブ後に機能間リンクを作成
- 03仕様インデックスを更新
- 04アーカイブ変更をログに追記
- 05アーカイブ前にメタデータと仕様を確認
活用シーン
- 01単一の OpenSpec 変更をアーカイブ
- 02複数の保留中変更をアーカイブ
- 03仕様間のリンクとインデックスを維持
- 04アーカイブに必要な入力を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gohypergiant/ agent-skills --skill accelint-qrspi-archiveインストール後、Claude Code で/accelint-qrspi-archiveを入力して読み込まれたか確認します。
同梱ファイルCHANGELOG.mdREADME.md
詳細
Accelint QRSPI Archive
OpenSpec の変更をアーカイブし、その後、OpenSpec 自体では行わない機能間リンクとインデックス管理を実行します。このスキルは openspec-archive-change または openspec-bulk-archive-change 自体を呼び出します。すでに誰かが変更をアーカイブした後に反応する手順ではなく、変更をアーカイブするためのエントリーポイントです。マージが完全に解決されるまで待ってから、変更が対象としたすべての機能ペアを共通の related: フロントマターリストでリンクし、すべての仕様をまとめた単一のインデックスを最新の状態に保ち、アーカイブされた変更すべてを記録する追記専用の変更履歴に追記します。
クロスリンクはマージの解決後に行う必要があり、解決前には行えません。そのため、このスキルは「マージが発生した」という外部イベントを監視するのではなく、第 1 フェーズとしてネイティブコマンドを自ら実行します。openspec/changes/<slug>/specs/ 内の差分仕様はまだ暫定的なものです。openspec-bulk-archive-change は、機能の仕様が最終的な形になる前に、複数の変更にまたがる競合を時系列順に解決する場合があります。インデックス化する価値があるのは、マージ済みのアーカイブ済み仕様だけです。それより前に算出した内容では、その後も変更される可能性があるコンテンツを対象にリンクすることになります。
このスキルの機能
自動化対象:1 回の呼び出しで 1 つ以上の OpenSpec 変更をアーカイブする全操作です。openspec-archive-change または openspec-bulk-archive-change 自体を呼び出し、その直後に機能間リンクとインデックスのメンテナンスを行います。
対象範囲:「この変更をアーカイブする」から、インデックスの更新までです。このスキルはアーカイブおよび抽出時にネイティブコマンド自体を呼び出します。別の方法でマージが行われるのを事前に待つことはありません。
出力:OpenSpec 独自のマージによってアーカイブされた変更、および更新された related: フロントマターと、対象となったすべての仕様で再生成された ## Related Specs セクション、更新された openspec/specs/INDEX.md(今回の一括処理で対象となった機能について更新するか、ファイルがまだ存在しない初回はプロジェクト全体を対象に新規作成)、さらにアーカイブされた変更ごとに 1 行ずつ追記された openspec/changes/archive/INDEX.md です。
対象外:マージや競合解決のロジック自体を実装すること(これは OpenSpec 独自の処理であり、このスキルは再実装せずネイティブコマンド経由で実行します)、related: エントリを削除すること、初回書き込み後に変更の Status 列を変更すること、既存の変更履歴の行を並べ替えること、またはローカルの仕様ファイルを読み取るために OpenSpec CLI を実行すること(通常のファイル読み取りで十分です。「明示的に対象外」を参照してください)。
前提条件
- OpenSpec CLI がインストールされ、初期化されており、アーカイブする変更が 1 件以上用意されていること。
- サブエージェントのサポートがあること。これは機能ごとの仕様書の作成にのみ必要です。仕様書の作成は常に無条件でサブエージェントとして実行されるため、これは通常の動作に必須の要件であり、大規模なバッチ処理を高速化するための任意の機能ではありません(利用できない場合の縮退時のフォールバックについては「エラー処理」を参照)。アーカイブと抽出では、サブエージェントのサポートの有無にかかわらず、サブエージェントを使用しません。その理由については「アーカイブと抽出」を参照してください。
- 各変更の
openspec/changes/<slug>/design.mdに、specs_touched(空でない機能名のリスト)とdecisions({id, choice, rationale, alternatives}エントリーのリスト)を含む YAML フロントマターがあること。 specs_touchedリストに記載されているすべての機能について、openspec/specs/<capability>/spec.mdの本文に## Purposeまたは### Purpose見出しがあること。このスキルはフロントマターに目的のテキストを重複して記載せず、その見出しを読み取ります。また、正しい動作を書き換えるには、その見出しが実際に存在している必要があります(事前確認の Task B で検証します)。
これらが欠けている場合は、不足している項目を報告し、処理を続行する前に解決できるようユーザーを案内してください。不足しているフィールドに対し、推測したデフォルト値を黙って代用してはいけません。この要件は、仕様書作成に必要なサブエージェントのサポートと、変更対象の仕様書に ## Purpose または ### Purpose 見出しがない場合にも、そのまま適用されます。変更の specs_touched/decisions フロントマターが欠けている場合は、別の方法で対処します。事前確認の Task A では、変更に含まれるファイルから候補を導き出し、書き込む前に作成者の明示的な確認を得ます。ここで即座に処理を停止する必要が実際にはない理由と、それでも推測を黙って行うわけではない理由については、以下の Task A を参照してください。
ワークフローの概要
┌────────────────────────────────────────────────────────────────────────┐
│ Stage Action Output │
├────────────────────────────────────────────────────────────────────────┤
│ 0 Preflight Verify frontmatter + Purpose Go / no-go │
│ headings before touching anything │
│ 1 Archive+Extract Run openspec-archive-change or Change │
│ openspec-bulk-archive-change yourself, records │
│ in this context (never a subagent); │
│ stay with any internal sync branch │
│ until archive's own steps finish, │
│ then read back specs_touched + decisions │
│ 2 Validate Confirm archive records are Checked │
│ structurally complete records │
│ 3 Link Combine new co-touch pairs across New │
│ this batch's changes (no file I/O) partners │
│ 4 Write specs SUBAGENT (one per capability, Updated │
│ always, never inline): merges new specs │
│ partners with existing related:, │
│ sorts, writes frontmatter + body │
│ 5 Specs index Patch specs/INDEX.md for the INDEX.md │
│ capabilities this batch touched │
│ (full rebuild only if the index is │
│ missing) │
│ 6 Change log Append one row per archived change INDEX.md │
│ to changes/archive/INDEX.md (append-only) │
│ 7 Report Summarize what changed Summary │
└────────────────────────────────────────────────────────────────────────┘
Critical: for openspec-bulk-archive-change, validation through reporting run exactly ONCE, after every
merge in the batch has resolved — never once per intermediate merge. Running
early would compute pairs against a specs_touched set that hasn't finished
accumulating cross-change conflicts, and would patch INDEX.md against a
half-finished batch.
Spec writing always delegates to subagents, regardless of batch size — one
capability or forty. This isn't a parallelization optimization that only
kicks in for large batches; it's how this skill keeps raw spec.md contents
out of the parent's context on every run, the same pattern
accelint-qrspi-propose and accelint-qrspi-apply use.
Archive and extraction is the mirror image: it never delegates to a subagent, regardless of
batch size or whether sub-agent support is even available. openspec-archive-change and
openspec-bulk-archive-change are themselves agent-driven, multi-step skills — not a
single deterministic CLI call — and a subagent handed instructions to run openspec-archive-change
has no reliable way to resume that skill's own remaining steps once it
branches internally into something like a separate sync skill, and no way
to surface an interactive prompt back to the user if one comes up. Both of
those are failure modes this skill hit in practice, not hypothetical ones —
see the Archive and Extract section for the full account.
実装手順
エラーが発生しない限り、途中で停止せず、以下の手順を順番に実行してください。
事前確認
目的:仕様書ファイルやインデックスファイルに触れる前に、アーカイブ処理の入力が適切な形式になっていることを確認します。Task A は限定的な例外です。作成者が、導き出した specs_touched/decisions の候補を確認した後、それを design.md に書き込みます。これは、手順 7 で既に存在していることが期待される入力を補う処理です。
-
範囲を特定します。変更名を指定した単一変更のアーカイブ(openspec-archive-change)か、保留中の複数の変更を対象とする一括アーカイブ(openspec-bulk-archive-change)かを確認してください。
-
検証 Task A — design.md のフロントマター。 アーカイブする各変更について、
openspec/changes/<slug>/design.mdを読み、そのフロントマターに空でないspecs_touchedリストと、各エントリーに少なくともidとchoiceが含まれるdecisionsリストがあることを確認してください。--- change: add-live-sync specs_touched: [sync/protocol, ui/status-indicator] decisions: - id: D1 choice: polling with 5s interval rationale: no infra budget for a message broker this quarter alternatives: [websocket push, long polling] ---フロントマターが存在し、形式が正しければ、そのまま続行してください。これは、
specs_touched/decisionsを設計時に書き込むことが想定されているaccelint-qrspi-proposeを経た変更であれば、期待される状態です。変更にこのフロントマターが一貫して存在しない場合は、accelint-qrspi-propose(またはaccelint-qrspi-apply)を修正し、通常のワークフローの一環としてこのブロックを書き込むようにすべきだという兆候です。そうすれば、実行のたびに以下の復旧手順に頼るのではなく、根本で問題を解消できます。変更のフロントマターがない、または形式が正しくない場合でも、このスキルは推測した値を黙って代用しません。その判断を明示的に行うのは変更の作成者であり、このスキルではありません。ただし、明示的な確認を得る方法は、先に進まず停止することだけではありません。多くの場合、欠けているフィールドは変更の作成者自身がすでに記述した資料から補うことができます。
- 候補を導き出します。
specs_touchedについては、変更のproposal.mdにある機能宣言と、openspec/changes/<slug>/specs/配下の差分仕様ディレクトリを確認します。decisionsについては、proposal.mdの Decisions セクション、またはdesign.mdにすでに記載されている決定事項の説明を確認します。 - 確認のために提示します。まだ書き込まないでください。 導き出した候補をユーザーに提示し、(a)記載どおりに承認する、(b)先に編集する、(c)
design.mdを自分で修正して後からこのスキルを再実行できるよう、いったん中断する、のいずれかを選ぶよう求めます。(a)または(b)を選んだ場合に限り、その候補をこのスキルがdesign.mdのフロントマターに書き込む値として確定します。この時点で取得されるのは、形式が整っているケースで提案時に得られる、明示的な作成者の承認と同じものですが、取得のタイミングが一段階後になります。 - 変更に由来する情報から候補を導き出せない場合に限り、候補を提示せず完全に停止します。たとえば、差分仕様ディレクトリが空で、
proposal.mdに機能宣言が一つもない場合です。その場合は、以前と同様に、どの変更でどのフィールドが欠けているのかを正確に報告します。
これは一括アーカイブのバッチ内で変更ごとに評価されます。確認が必要な変更が一つあっても、ほかの変更の事前確認を妨げることはありません。
- 候補を導き出します。
-
検証タスク B — Purpose 見出しの規約。 このバッチのすべての
specs_touchedリストに含まれる各機能について、openspec/specs/<capability>/spec.mdに、その機能の目的を説明する見出しがあるか確認します。許容される見出し(上から順に確認し、最初に一致したものを採用):
## Purposeまたは### Purpose## Overviewまたは### Overview
Overview と Purpose は意味的に同等として扱います。どちらも、その機能が何をするもので、なぜ存在するのかを説明するものであり、インデックスの更新や仕様の作成に必要な情報が得られます。
これらの見出しが一つもない場合: 対応方法をユーザーに尋ねます。
- (a)ひとまずプレースホルダーとして
## Purpose見出しと_Purpose not yet documented_というテキストを追加する - (b)ユーザー自身が先に見出しを追加できるよう、いったん中断する
- (c)仕様の内容を読み、その内容に基づいて
## Purpose見出しを作成する
仕様に有意な内容がある場合は、通常(c)が最適です。エージェントが既存の記述から目的の説明をまとめられます。仕様が未完成のひな形であったり、正確な説明にドメインの専門知識が必要だったりする場合は、(b)が適しています。(a)はすぐに先へ進む必要がある場合の最後の手段ですが、後で修正が必要になります。
注: この確認の対象となるのは、
openspec/specs/<capability>/spec.mdに MAIN 仕様がすでに存在する機能だけです。ステップ 4 に該当する新規機能には MAIN 仕様がまだないため、この確認をスキップします。アーカイブ時に仕様を作成する際、Purpose 見出しも追加されます。 -
specs_touched内の機能について、openspec/specs/<capability>/ディレクトリがまだ存在しないものがあれば、この変更で導入される新規機能として別途記録します。ステップ 19 では既存ファイルの編集ではなく、spec.mdのフロントマターを新たに作成する必要があります。また、ステップ 20 の Purpose 列に記入する値は、参照できる既存情報がないため、ユーザーに手動で指定してもらう必要があります。 -
先へ進む前に、事前確認の概要を報告します。対象範囲の変更、影響を受ける機能、タスク A またはタスク B の結果を含めます。いずれかの変更でタスク A が停止に至った場合(ユーザーが
design.mdを自分で修正するため中断を選んだ場合、または候補を導き出せなかった場合)、その変更についてステップ 6 には進みません。ユーザーが承認したタスク A の候補は、最初から適切なフロントマターが記載されていた場合と同様に、合格として扱います。機能についてタスク B が未完了でも、後で解決すれば問題ありません。ステップ 6~17 では仕様本文に触れないため、ステップ 18 でその機能に到達するまではブロッカーとして扱わず、注意事項としてのみ示します。
アーカイブと抽出(インラインで実行 — サブエージェントは使用しない)
- OpenSpec に実際のマージを実行させ、その後、ステップ 17 および 23 で必要となるデータを読み戻します。サブエージェントには委ねず、このコンテキスト内で直接実行します。
このステップは、バッチサイズやサブエージェントのサポートの有無にかかわらず、サブエージェントとして実行されることはありません。これは、このスキルの
1.0.0の動作を覆す変更です。実際に遭遇した、次の2つの具体的な失敗を踏まえて変更しました。
- openspec-archive-change と openspec-bulk-archive-change は、エージェント主導のスキルであり、決定的な単一の CLI 呼び出しではありません。 プロジェクトの状態を読み取り、同期が必要かどうかを判断し、同期が必要な場合は、残りのアーカイブワークフロー(差分仕様のマージ、変更を
openspec/changes/archive/に移動する処理)を完了する前に、内部で別の同期スキルに引き継ぎます。openspec-archive-change を実行するよう指示されたサブエージェントには、「このアーカイブステップで案内された同期スキルを終えた」ことと、「実際に依頼された作業を終えた」ことを確実に区別する方法がありません。タスクの途中で確認に戻る呼び出し元がいないためです。実際には、まさにこの問題が起きました。サブエージェントは同期ステップを実行して自分の仕事は終わったと判断し、マージに進むことなく制御を返してしまいました。この状況でアーカイブを直接実行すれば、指示を出したエージェント自身が、同期へ分岐する様子を見守ることになります。そのため、その分岐の意味を認識し、同期の完了後にアーカイブの残りのステップを続けられます。これは、人が自分でコマンドを実行するときと同じ一貫性です。 - サブエージェントからユーザーに対話型プロンプトを表示することはできません。 openspec-archive-change と openspec-bulk-archive-change は、定型的な同期の y/n 以外の確認を求める場合があります。特に openspec-bulk-archive-change は、仕様が重複する変更をマージする前に確認を求めることがあります(下記のステップ 2 を参照)。そのようなプロンプトに遭遇したサブエージェントは行き詰まります。質問をユーザーに渡して実際の回答を得ることができず、ユーザーに代わって推測するよりも、処理を進めないほうがよいためです。アーカイブをインラインで実行すれば、そのようなプロンプトはユーザーがすでに参加している同じ会話に表示されます。
その代わりに、次の点を受け入れる必要があります。openspec-archive-change の内部処理、つまり差分仕様とメイン仕様の比較や、一括アーカイブでの変更間の実行順序の解決は、独立したサブエージェントに任せるのではなく、このコンテキスト内で直接行われるため、1.0.0 の設計で意図していたよりも多くの内容がコンテキストに入ります。これは見落としではなく、コンテキストの節約よりも正確性を優先した結果として受け入れているコストです。仕様の作成では、これまでどおり、通常はより大きい機能ごとのファイル内容をサブエージェントに分離するため、このコストはアーカイブステップ自体の範囲に限られます。openspec-archive-change/openspec-bulk-archive-change のスキルではなく、直接 openspec-archive-change/openspec bulk-archive をシェルから実行して回避しないでください。OpenSpec 独自の差分仕様比較とエッジケースの判断はスキル内にあり(bulk-archive の競合解決は、単純な CLI フラグでは再現できません)、これを回避して生の CLI 呼び出しに戻すと、このスキルが維持しようとしているのと同じハイブリッドエージェントの判断力が失われます。
-
対象範囲を判断します。単一の変更をアーカイブする場合(変更名を指定して openspec-archive-change を実行)か、保留中の複数の変更にまたがる一括アーカイブ(openspec-bulk-archive-change)かを判断します。
-
既知の対話型プロンプト — 常に同期します。 openspec-archive-change と openspec-bulk-archive-change の実行中には、たいてい同期するかどうかを尋ねるプロンプトで一時停止します。このプロンプトが表示されるたびに、必ず「はい」と回答してください。これはアーカイブ処理を完了するための定型的な手順であり、ユーザーに判断を求める場面ではありません。自分で回答する対話型プロンプトはこれだけです。
-
適切なスキル呼び出しを実行します。
単一の変更の場合:
Invoke the openspec-archive-change skill.
<change-name>
一括アーカイブの場合:
Invoke the openspec-bulk-archive-change skill.
-
実行が内部で分岐した場合 — 多くの場合、途中で別の同期スキルに処理を引き継ぎます — これはこのコマンドで想定される通常の動作であり、問題が発生した、またはタスクが完了したことを示すものではありません。そのまま続行してください。分岐が完了したら、このセクションの終わりとして扱うのではなく、アーカイブ自体の残りの手順(差分仕様をメインの仕様にマージし、変更を
openspec/changes/archive/に移動する)に戻ります。 -
その他のインタラクティブなプロンプトが表示された場合 — 多くの場合、
openspec-bulk-archive-changeが、重複する仕様に触れる変更をマージする前に確認を求めます — 手順 8 の定型的な同期プロンプトとは異なり、これはユーザーだけが回答できる実際の質問です。ユーザーに直接提示し、回答を待ってから続行してください。 -
この操作ですべてのマージが完全に解決されるまで待ちます。一括アーカイブの場合は、最初の変更だけでなく、バッチ内のすべての変更が対象です。
-
マージで未解決の競合が報告された場合は、直ちに停止してください。解決を試みず、このバッチ内のいかなる変更についても手順 14 に進まないでください。部分的な抽出は、抽出しないよりも悪い結果になります。そうしなければ、停止したバッチと正常に完了したバッチを見分ける方法がないためです。競合の内容をそのままユーザーに報告して停止してください。検証には進まないでください。部分的にマージされたバッチから何かを解析すると、バッチが触れるすべての機能に不正なデータが伝播します。
-
正常にアーカイブされた変更ごとに、新しいアーカイブ先のパスにある
design.mdのフロントマター(例:openspec/changes/archive/2026-03-02-add-live-sync/design.md)を読み取り、次のレコードを作成します。
{
change: "add-live-sync",
date: "2026-03-02", // from the archive folder's own
// YYYY-MM-DD prefix, NEVER from
// anything inside design.md
archivePath: "openspec/changes/archive/2026-03-02-add-live-sync/",
specsTouched: ["sync/protocol", "ui/status-indicator"],
decisions: [{ id: "D1", choice: "polling with 5s interval", ... }]
}
- 検証用に、手順 14 で作成したレコードのリストを変更ごとにまとめて保持します。さらに、未解決の競合が残っていないことを明示的に記録しておきます。
出力:アーカイブされた変更ごとに 1 つのレコード(change、date、archivePath、specsTouched、decisions)。このコンテキスト内で保持し、そのまま検証手順に渡します。
抽出したレコードを検証する
目標:相互リンクの計算に使う前に、アーカイブレコードの構造が正しいことを確認します。これは抽出内容の健全性チェックであり、元データの再検証ではありません(事前確認のタスク A で、アーカイブ実行前に元の design.md のフロントマターが正しい形式であることはすでに確認済みです)。
-
すべてのレコードに空でない
specsTouchedがあり、少なくとも 1 つのdecisionsエントリーでchoiceが設定されていることを確認します。いずれかを満たさないレコードがある場合、問題はアーカイブ中のレコード作成にあります(元データではありません。元データはタスク A ですでに検証済みです)。部分的なレコードのまま先に進まず、その変更のアーカイブを再実行してください。 -
レコードは返されたとおり、正確に変更ごとにまとめて保持します。相互リンクの計算では、単一の変更に含まれる
specs_touched内のペアが計算されます。同じ一括アーカイブのバッチで無関係な 2 つの変更がアーカイブされても、同じタイミングで処理されたというだけで、それぞれの機能が相互に関連することにはなりません。
出力:アーカイブから得られた同一のレコードセット。構造が完全であることを確認済みで、相互リンクの計算と INDEX への追記に使用できます。
相互リンクを計算する(全ペアの和集合)
目標:変更ごとに、その変更内の specs_touched に含まれる相互タッチのペアをすべて計算し、このアーカイブ操作に含まれるすべての変更のペアを、機能ごとに新たに追加される関連項目の 1 つのセットにまとめます。この手順ではファイルに一切触れません。検証済みレコードにすでに含まれている specsTouched のリストを組み合わせるだけです。新しい関連項目を、仕様にすでにある related: エントリー(既存のものは一切削除しません)とマージする処理は、仕様の書き込み中に、そのファイルをすでに開いているサブエージェントが行います。親エージェントが和集合の初期値を作るためだけに仕様のフロントマターを読む必要はありません。仕様を書き込む処理の中で、ファイルの読み取りと同時に行えます。
18. specs_touched: [A, B, C] を含む変更の場合、寄与するペアは自己ペアを除くすべての 2 組み合わせです。つまり、(A,B)、(A,C)、(B,C) です。相互参照には方向性がありません。ペア (A,B) は、同じステップで A に B が関連パートナーとして追加され、同時に B にも A が追加されることを意味します。
- これはファイル I/O に依存しない純粋な計算なので、機能ごとに目視で判断するのではなく、小さな純粋関数として記述するのが適切です。
type ChangeLink = {
readonly change: string;
readonly specsTouched: readonly string[];
};
// All 2-combinations within one change's specs_touched. Pure, no self-pairs,
// no directionality — a co-touch relationship reads the same both ways.
const pairsFromChange = (
link: ChangeLink,
): ReadonlyArray<readonly [string, string]> =>
link.specsTouched.flatMap((a, i) =>
link.specsTouched.slice(i + 1).map((b) => [a, b] as const),
);
// Fold every change's pairs into one partner-set-per-capability map. This
// starts from an empty map every time — it combines pairs ACROSS the
// changes in this batch, not against a spec's on-disk related: list. That
// merge is deliberately left to spec writing, which is the step that opens the file.
const accumulateNewPartners = (
pairsByChange: ReadonlyArray<ReadonlyArray<readonly [string, string]>>,
): ReadonlyMap<string, ReadonlySet<string>> => {
const next = new Map<string, Set<string>>();
for (const pairs of pairsByChange) {
for (const [a, b] of pairs) {
next.set(a, (next.get(a) ?? new Set()).add(b));
next.set(b, (next.get(b) ?? new Set()).add(a));
}
}
return next;
};
-
すべての変更のペアを、空の状態から始めて同じ蓄積マップに追加します。重複する機能に触れる 3 件の変更を含む一括アーカイブでは、スペックの書き込みでファイルに触れる前に 3 件すべてのペアをまとめます。これにより、各機能のサブエージェントは、不完全なデータで 3 回ではなく、新しいパートナーの完全なリストを受け取って 1 回だけ呼び出されます。
-
このマップをそのままスペックの書き込みに渡します。ソートせず、各スペックの既存の
related:リストとのマージも行いません。マージ(ファイル内の既存項目との和集合)と最終的なアルファベット順のソートは、依存対象となるファイルを実際に読み取るスペック書き込みサブエージェントが担当します。
出力:capability -> 新たに追加されたパートナー名 のマップです。各スペックの既存の related: リストとのマージも、ソートもまだ行われていません。どちらもスペックの書き込み時に行います。
スペックのフロントマターと本文を書き込む(サブエージェント、常時)
目標:新たに追加されたパートナーを、変更対象の各スペックの既存の related: リストにマージし、出典情報とともにフロントマターに保存して、一致するように ## Related Specs セクションを再生成します。
変更対象の機能ごとに、必ずサブエージェントを 1 つ起動します。毎回起動し、変更対象の機能数による条件分岐は行いません。新しいパートナーマップが確定すれば、各機能の編集は完全に独立しています(accelint-qrspi-apply がスライスの並列化に利用するのと同じ独立性です)。読み取り、マージ、書き込みをサブエージェント内で行うことで、1 機能のアーカイブでも 40 機能の一括アーカイブでも、そのスペックの全文が親のコンテキストに入るのを防げます。「機能が多ければ並列化し、少なければインラインで編集する」というしきい値ベースの判断にすると、理由もなく実行ごとに親のコンテキストコストが変動します。無条件に委譲すれば、そのコストは一定になります。また、スペックの現在の related: 値を読み取るのは親ではなくこのサブエージェントだけになります。そのため、既存項目とのマージ処理を相互参照の計算ではなく、ここに置くのが適切です。
- 変更対象の機能ごとに、次のプロンプトでサブエージェントを起動します(親が渡すのは相互参照の計算で新たに追加されたパートナー名のみで、最終リストではありません。ファイル内の既存項目とのマージはサブエージェントが行います)。
Update openspec/specs/<capability>/spec.md only. Do not touch any other file.
Read this file's current related: value from its frontmatter (treat it as
empty if the file has no frontmatter yet — this may be a brand-new
capability). Union it with these newly contributed partners:
[<partner>, <partner>, ...]. Never drop an entry that was already there.
Sort the resulting full set alphabetically and write it in flow style on
one line — that's what keeps a no-op run byte-identical and a genuine
addition a clean one-line diff.
Also set:
last_touched_by: <change-name>
last_touched_on: <date>
as plain overwrites of whatever was there before, not an accumulated
history.
Do NOT add capability or purpose fields. The capability name is this
file's own path; purpose already lives in its ## Purpose or ### Purpose heading.
Then regenerate the ## Related Specs section in the body from the same
final, sorted related: list (replace any existing ## Related Specs
content entirely — this section is never hand-maintained).
For each partner in the sorted related: list, read its spec.md file to
extract the purpose heading text. Check for these headings in order:
- ## Purpose or ### Purpose
- ## Overview or ### Overview
Use whichever is found first (Overview and Purpose are semantically equivalent).
Format each line as:
- [<partner>](../<partner>/spec.md) - <Purpose or Overview heading text>
Example format (one entry per line, alphabetically sorted by partner name):
## Related Specs
- [auth-session-store](../auth-session-store/spec.md) - Secure session token storage and retrieval
- [sync-protocol](../sync-protocol/spec.md) - Defines the live-sync wire protocol for real-time updates
The format is: markdown link with partner name as link text, relative
path to its spec.md, then space-dash-space (not em-dash), then the
first sentence or paragraph from that partner's purpose heading (## Purpose, ### Purpose, ## Overview, or ### Overview).
If no ## Related Specs heading exists, insert one at the end of the file.
Report back ONLY: the file path, whether the write was a no-op
(byte-identical to what was already there) or an actual change, the
final related: list you wrote, and an index-ready purpose summary for
this capability derived from its current heading text (from ## Purpose,
### Purpose, ## Overview, or ### Overview — whichever exists). Use a
single concise sentence suitable for a table cell. Prefer the first
sentence if it is already concise; otherwise compress the heading text
to one sentence. You're not writing this back into the spec — just
reading and compressing it so the parent doesn't have to reopen the
file for index updates. Do not return the file's full contents.
-
その機能に既存の
spec.mdがない場合(事前確認のステップ 4 における新規機能)、サブエージェントは既存のフロントマターを読み取る代わりに、空のフロントマターブロックから開始します。それ以外は同じプロンプトです。 -
各サブエージェントの簡潔なレポート(ファイル、変更なし/変更あり、最終的な
related:リスト、インデックス用の Purpose 要約)を収集し、インデックスの更新と報告に使います。インデックスの更新では、ファイルを再度開く代わりに、このレポートのrelated:と Purpose の値をそのまま使用します。最終レポートでは、変更なし/変更ありのステータスのみを使います。書き込みに関するその他の情報を親のコンテキストに入れる必要はありません。変更なしという報告は、この一括処理で実際にはその機能に影響がなかったことを示す想定どおりのシグナルであり、ファイルを再読込して確認する必要はありません。
出力:変更対象のすべての機能について、spec.md がその場で更新される(既存の related: 項目を維持し、新しい項目を追加してソートする)か、変更なしと確認されます。親のコンテキストに入るのは、短いステータス行と、related:/一文の Purpose 要約の値のみです。これらがインデックス更新に必要な小さなデータです。
openspec/specs/INDEX.md を更新する
目標:openspec/specs/INDEX.md を、直前に書き込まれた内容と同期させます。その際、実際に変更された行だけを編集します。すべての機能の spec.md を再スキャンしたり、specs/INDEX.md 全体を読み込んだりすることはありません。仕様書作成サブエージェントは、各自の書き込み作業で変更対象の機能にある現在の related:、last_touched_by、## Purpose/### Purpose 見出しをすでに読み取り、その値を報告します。インデックスの更新では、そのデータを直接再利用するため、openspec/specs/ をもう一度全件スキャンする必要がありません。このバッチで変更したもの以外の機能を確認する場合や、specs/INDEX.md の対象行を1行以上読む場合があるのは、このファイルがまだ存在しないときだけです。既存の状態がないため、定期的に行う更新ではなく、一度だけ全体を生成するのが適切です。
- 通常のケース —
specs/INDEX.mdがすでに存在する場合。 この作業のためにファイル全体をコンテキストに読み込まないでください。実際に変更する行だけを特定して編集します。
- 既存の機能:先頭セルが機能名と完全に一致する行を grep で検索します(一致範囲は先頭の
|と次の|の間に限定します。部分一致ではありません。sync/protocolがsync/protocol-v2に一致してはなりません)。その機能について仕様書作成レポートにある情報(Purpose、related:、last_touched_by)から作成した行で、その1行だけを置き換えます。ファイル内のほかの箇所は読み取りも編集もしません。 - 新規機能(事前確認の手順4による):機能名のセルを grep で検索して、新しい機能名よりアルファベット順で後ろに位置する最初の既存行を特定し、その直前に新しい行を挿入します(最後に位置する場合は末尾に追加します)。挿入の前後に空行を入れないでください。すべてのデータ行を、間に空行を挟まず連続させてください。この場合も編集するのは新しい行1行だけです。挿入位置の特定には行の内容を読み込む必要はなく、機能名の列だけで十分です。
- 変更していない機能の行は、どれも開いたり、一致確認したり、書き換えたりしません。全体を再生成した結果として「同じ内容のまま」なのではなく、この操作では文字どおり一度も触れません。
- 各行は、行をまたいだ幅揃えをせずに作成します。列間は1つの空白で区切ります(
| sync/protocol | Defines the live-sync wire proto | ui/status-indicator | add-live-sync |)。各列の最長の値に合わせて揃えることはしません。Purposeセルには、仕様書の見出しにある段落全文ではなく、仕様書作成サブエージェントが返したインデックス用の要約を再利用し、表のセルに適した簡潔な1文を入れます。
| Capability | Purpose | Related | Last touched by |
| --- | --- | --- | --- |
| sync/protocol | Defines the live-sync wire proto | ui/status-indicator | add-live-sync |
| ui/status-indicator | Renders connection state in UI | sync/protocol | add-live-sync |
Markdown の表は、空白の揃え方にかかわらず正しく表示されます。重要なのはヘッダー区切り行のダッシュの数だけであり、データ行間で空白を一貫させる必要はありません。行をまたいで列を揃えると、各行の空白幅がほかのすべての行の内容の長さに依存します。そのため、1行のテキストの長さが変わるだけで、表全体を書き換えることになります。これは、この設計で避けようとしているコストそのものです。更新した行と変更していない隣接行は、差分表示では少し不揃いに見えます。その代わり、差分は実際に1行だけになります。
- 初回構築のケース —
specs/INDEX.mdがまだ存在しない場合。 適用できる既存状態がなく、変更対象の行だけを追加すると、変更されていない機能は、将来の変更でそれぞれ更新されるまで永久に欠落します。openspec/specs/内のすべてのディレクトリを列挙し、それぞれについて## Purposeまたは### Purpose見出し、related:のフロントマター、last_touched_byを直接読み取ってください。つまり、全件スキャンを行います。この処理はプロジェクトごとに最大1回だけ実行され、このスキルがそのプロジェクトで何かを初めてアーカイブするときに限られます。それ以降のアーカイブでは、手順25を実行します。 - ブートストラップの場合のみ:ステップ27で収集した全件スキャンの結果を使い、ステップ26の行形式に従って
openspec/specs/INDEX.mdを書きます。すべてのデータ行を連続して並べ、行間に空行を入れないでください。ファイルにすでにプロジェクト固有のタイトルや表より前の前置きがある場合は、そのまま残してください。通常の場合(ステップ25)では、編集内容はすでに直接書き込まれているため、別途書き込むステップはありません。
出力:openspec/specs/INDEX.md。今回のバッチで対象となったケイパビリティごとに1行を変更または挿入し(空行は追加しません)、その他の行には一切手を加えません。ファイルがまだ存在しない場合は、プロジェクト全体のすべてのケイパビリティから一度だけ作成し、すべてのデータ行を連続して並べ、行間に空行を入れません。
パッチ適用済みのspecs/INDEX.mdでも、このスキルの制御外の理由で実態と食い違うことがあります。たとえば、アーカイブのワークフロー外でspec.mdが手動編集されたり、ケイパビリティのディレクトリが直接名前変更または削除されたりする場合です。このスキルは、こうした食い違いを検出するために、実行のたびにインデックス全体を再生成することはありません。現在、ほかにもこれを行うものはありません。accelint-archive-synthesisの2つのチェック(decision-driftとstructural-coupling)は、どちらも要約対象のspec.mdファイルと照合して監査するのではなく、specs/INDEX.mdを正として読み取ります。この種の食い違いを検出するには、定期的なコーパス全体のチェックをすでに担っているスキルとして自然な選択肢であるaccelint-archive-synthesisに、インデックス照合チェックを追加する必要がありますが、そのチェックはまだ存在しません。それまでは、これは対応済みではなく、許容された限定的な不足事項です。
openspec/changes/archive/INDEX.mdへの追記
目的:アーカイブされた変更ごとに永続的な行を1つ記録し、既存の表のデータ行の末尾に挿入します。ファイルの末尾に無条件で追加してはいけません。specs INDEXの更新とは異なり、このファイルは履歴であり、履歴は追記専用です。再生成も並べ替えもしません。
- 検証対象の各変更について、次の行を作成します。
| Change | Date | Decision | Specs touched | Status |
| --- | --- | --- | --- | --- |
| add-live-sync | 2026-03-02 | polling with 5s interval | sync/protocol, ui/status-indicator | current |
DateはアーカイブフォルダーのYYYY-MM-DD接頭辞です。検証時に使ったのと同じ情報源を使用し、design.mdから読み取った値は決して使いません。Decisionは、decisions[].choiceから作成する、アーカイブインデックス用の簡潔な要約です。元の記述が冗長な場合は、逐語的にコピーしません。各choiceを既存のアーカイブ行で使われている簡潔な断片形式に書き換えてください。理由、代替案、例、注意事項、説明文をインデックスにコピーしてはいけません。変更に複数の決定が記録されている場合は、まず各choiceを正規化してから、1つだけを選ぶのではなく、セミコロンで連結します(例:polling with 5s interval; client-side dedup on reconnect)。Statusはcurrentと記載します。このスキルは、この初回記載の後、その行もほかの行も含め、この列には二度と触れません。currentからsupersededへの遷移などは、変更をまたぐ文脈から決定が実際に置き換えられた時期を判断できるaccelint-archive-synthesisが担います。このスキルは一度に1つのアーカイブ操作しか扱わないため、その判断を安全に行うことはできません。
- 挿入位置を特定します。表のデータ行の末尾とし、行間に空行を入れません。 ヘッダー行(
| Change | Date | ... |)、区切り行(| --- | --- | ... |)、その後に続く連続したデータ行のブロックを見つけます。新しい行は、そのデータ行ブロックの最後の行の直後に挿入し、新しい行の前に空行を入れません。すべてのデータ行は連続している必要があり、行間に空行を入れてはいけません。空行があると表の構造が壊れるため、決して書き込んではいけません。これはchanges/archive/INDEX.mdとspecs/INDEX.mdの両方に適用されます。 - いずれの INDEX.md テーブルの後にも、メタデータや要約を記述してはいけません。
openspec/changes/archive/INDEX.mdとopenspec/specs/INDEX.mdには、テーブルの前に Markdown のヘッダーや前置き(例:「# Capability Specifications Index」や「# Archive Index」に続く簡単な説明)がある場合があり、その場合は保持する必要があります。前置きの後にテーブル(ヘッダー行、区切り行、データ行)が続き、ファイルは最後のデータ行の直後に終わります。テーブルの後に、次のような一般的ですが禁止されている要素を記述してはいけません。
- 「Total Changes: N」などの行数
- 「Generated: YYYY-MM-DD」などのタイムスタンプ
- 「Status Legend:」などの説明文
- テーブル後の水平線(
---) - その他の文章、メタデータ、要約
以前の実行でいずれかのファイルにこのような後続コンテンツが存在する場合は、削除してください。INDEX.md の正規の形式は、任意の前置き、続いてテーブル、その後ファイル末尾です。最後のデータ行の後には何も記述しません。
-
このスキルの出力ファイルのうち、最初のアーカイブより前に存在しない場合があるのは、このファイルだけです。存在しない場合は、ヘッダー行と区切り行のみ(後続コンテンツなし)で作成してください。
-
既存の行の並べ替え、書式変更、その他の編集は行わないでください。追記のみとすることで、このファイルは信頼できる監査記録になります。過去の行を並べ替えると、git blame を使って、ある決定が前後の決定と比較していつ記録されたかを確認できなくなります。
出力:openspec/changes/archive/INDEX.md。アーカイブした各変更につき新しい行を1行追加し、最後のデータ行の直後に空行を挟まずに挿入します。過去の行には一切手を加えず、すべてのデータ行を空行なしで連続させ、テーブルの後にメタデータや要約を記述せず、最後のデータ行の直後でファイルを終えてください。
報告
- 変更内容を要約してください。
✅ Archive complete: add-live-sync
Specs updated:
- sync/protocol (+ui/status-indicator)
- ui/status-indicator (+sync/protocol)
openspec/specs/INDEX.md updated (2 rows patched)
openspec/changes/archive/INDEX.md: 1 row appended
Next steps:
- Review the diff on touched specs before committing
- related: entries are additive only here — if one looks wrong,
pruning is accelint-archive-synthesis's job, not this skill's
- プリフライトのタスク B が未解決だったために、目的がプレースホルダーのまま残された機能、または作業が省略された機能があれば、差分の中に埋もれさせず、ここで明示してください。
出力:このスキルで変更したすべてのファイルについて、人が読める形式でまとめたもの。
- 統合作業のトリガーしきい値を確認してください — サブエージェントを起動し、アーカイブコーパスの規模や経過期間が
accelint-archive-synthesisの実行を推奨する水準に達しているかを判定してください。トリガーは二重方式とし、変更が50件蓄積した場合、または前回の統合作業から30営業日が経過した場合のいずれか早い方で発動します。
この確認は、単一の変更と一括変更の両方を含む、すべてのアーカイブ処理の後に実行します。これにより、適切な頻度で統合作業の提案が提示されます。この二重トリガー方式は、異なる2つの統合作業のニーズに対応します。変更を短期間に多数アーカイブする、変更の多いプロジェクトでは、判断のずれが深刻になる前に定期的なリントが必要です。一方、変更の少ないプロジェクトでは、変更数が少なくてもアーカイブコーパスを定期的に見直せるよう、期間に基づくリマインダーが必要です。
次のプロンプトでサブエージェントを起動してください。
Check whether accelint-archive-synthesis should run based on dual-trigger thresholds.
Current date: <YYYY-MM-DD from system context>
Thresholds (hard-coded):
- Change threshold: 50 archived changes since last synthesis run
- Time threshold: 30 working days since last synthesis run
Trigger condition: (change_delta >= 50) OR (time_delta >= 30 working days)
Steps:
1. Read openspec/changes/archive/SYNTHESIS-LOG.md if it exists.
- Parse the last line under "## Run History" section
- Extract: checkpoint date (YYYY-MM-DD) and row count (after "checked through row")
- If file doesn't exist or section is empty, this is first-run: no baseline
2. Count current archive size:
- Use: grep -c "^|" openspec/changes/archive/INDEX.md
- Subtract 2 (header and separator rows) = current archived change count
3. Calculate deltas:
- Change delta = current row count - checkpoint row count
- Time delta (working days):
* Calculate calendar days between checkpoint date and current date
* Subtract weekend days (Saturdays and Sundays) in that period
* Result = working days elapsed
4. Apply trigger logic:
- trigger_exceeded = (change_delta >= 50) OR (time_delta >= 30)
Return ONLY this structured response (no explanation):
{
"trigger_exceeded": true/false,
"first_run": true/false,
"change_delta": N,
"time_delta": X,
"last_checkpoint_date": "YYYY-MM-DD" or null,
"last_checkpoint_row": N or 0,
"current_row": N
}
サブエージェントから応答が返されたら、その内容を使って適切な出力を作成してください。
trigger_exceeded = true かつ first_run = false の場合:
⚠️ SYNTHESIS CHECKPOINT THRESHOLD EXCEEDED
You SHOULD run accelint-archive-synthesis now:
- Changes since last synthesis: <change_delta> (threshold: 50)
- Working days since last synthesis: <time_delta> (threshold: 30)
- Last checkpoint: <last_checkpoint_date> at row <last_checkpoint_row>
- Current state: row <current_row>
High-velocity projects need periodic linting before decision drift accumulates
too deeply. Lower-velocity projects need time-based nudges to ensure the
archive corpus gets reviewed periodically even when change volume is low.
Invoke the accelint-archive-synthesis skill to run the synthesis check.
trigger_exceeded = false の場合:
✓ Synthesis check: <change_delta> changes since last run (<last_checkpoint_date>), <time_delta> working days elapsed
Thresholds: 50 changes OR 30 working days, whichever first
first_run = true の場合:
⚠️ SYNTHESIS CHECKPOINT NOTICE
This project has <current_row> archived changes but no synthesis checkpoint exists yet
(openspec/changes/archive/SYNTHESIS-LOG.md not found).
You SHOULD run accelint-archive-synthesis to establish the first baseline.
The synthesis skill will check for decision drift, index reconciliation issues,
and structural coupling across the full archive corpus.
Invoke the accelint-archive-synthesis skill to run the initial synthesis check.
RFC 2119 の SHOULD 表現を使うことで(受動的な「検討してください」という文章ではなく)、エージェントはこれを情報提供ではなく、実行すべき指示として確実に認識できます。サブエージェントが計算の複雑な部分を処理し、出力の書式設定に必要な最小限のデータのみを返します。
主要な原則
クイックリファレンスとしての要約です。各項目の詳しい説明は、実際に適用される箇所(実装手順)または適用が徹底される箇所(絶対にしてはいけないこと)にあります。ここでは一覧のみを示します。
- 相互リンクを行うのは、提案時ではなくアーカイブ時です。 差分仕様は、
/openspec-bulk-archive-changeが競合を順に解決するまでは暫定的なものです。インデックス化に値するのは、マージされアーカイブされた仕様のみです。 specs_touched/decisionsのフロントマターを記述するのは、アーカイブ時ではなく提案時です。 変更自体の設計作業の一環として、この情報を記述するのはaccelint-qrspi-proposeの役割です。Task A の導出・確認パスは、このフローを経ていない変更向けに用意されています。これは作成者の確認が引き続き必要なフォールバックであり、このスキルがデータを取得する際の主要な方法ではありません。- このスキルが行うのは追加のみです。
related:エントリの削除や既存のStatus値の変更は、accelint-archive-synthesisの役割です。どちらにも、このスキルにはない変更間の判断と人による確認が必要です。 - すべての書き込みは冪等です。 ソート済みのフロー形式による
related:と、specs/INDEX.mdの行単位のパッチ適用により、入力に変更がない状態で再実行してもバイト単位で同一になります。そのため、部分的な失敗後に再試行しても、エントリや行が重複することはありません。 specs/INDEX.mdは、この実行で対象となった機能の行ごとにパッチ適用します(初回のブートストラップ時のみ全体を一括生成します)。一方、changes/archive/INDEX.mdは追記のみです。 一方は現在の状態を、もう一方は履歴を示します。これらを逆の方法で扱うと、履歴が破損したり、インデックスが実態から乖離したりします。ディスク上のすべてのspec.mdとspecs/INDEX.mdをコーパス全体にわたって照合する機能は、このスキルにはありません。また、現時点ではaccelint-archive-synthesisにもありません。既存のチェックではインデックスを正として扱い、監査は行っていません。いずれこの課題を解消する価値はありますが、このスキルのアーカイブごとのホットパスで対応する役割ではありません。- 仕様の作成では、例外なく常にサブエージェントに委任します。アーカイブと抽出では、例外なく委任しません。 仕様の作成を常に委任することで、バッチのサイズにかかわらず、親のコンテキストコストを一定に保てます。これは、
accelint-qrspi-proposeとaccelint-qrspi-applyが、ファイルに触れるすべての操作で採用している方針と同じです。アーカイブをインラインで実行するのは、その逆の理由からです。openspec-archive-change//openspec-bulk-archive-changeはエージェント主導であり、実行中に分岐したり、プロンプトを表示したりする場合があります。その分岐を最後までたどったり、プロンプトに回答したりできるのは、ユーザーが実際に利用しているコンテキストだけです。
明示的に対象外
- ローカル仕様の読み取りに OpenSpec CLI を依存させません。
openspec/specs/<capability>/spec.mdは既知のパスにある通常のファイルです。通常のファイル読み取りで十分であり、これほど直接的な処理のために CLI を呼び出す必要はありません。 openspec-archive-change/openspec-bulk-archive-changeスキルの代わりに、openspec archive/openspec bulk-archiveをシェルから呼び出しません。 CLI コマンドをそのまま実行しても、同等の近道にはなりません。OpenSpec 独自の差分仕様の比較と一括アーカイブ時の競合解決が実際に行われるのは、このスキル内です。アーカイブは必ずスキルを通し、生の CLI を直接実行することはありません(「アーカイブと抽出」セクションを参照)。インラインで実行すると、以前のサブエージェント設計が持っていたコンテキスト分離性はすでに一部失われますが、その分離性を、実質的な判断を省略する CLI 呼び出しと引き換えにするのは、改善ではなく悪化です。- エッジごとの関係メタデータはありません。
related:エントリ自体に理由やタイムスタンプは持たせません。そのコンテキストはすでに、元の変更のdesign.mdとchanges/archive/INDEX.mdの該当行に記録されており、必要であれば grep で参照できます。 related:の自動削除はありません。 追加のみです。削除はaccelint-archive-synthesisの役割であり、人間の確認がある場合に限ります。- 関係に方向性はありません。 同時に触れる関係は本質的に対称であるため、常に全ペアとして計算し、依存関係の方向として扱うことはありません。「A が B に依存する」は、このスキルがモデル化する対象ではない別種のエッジです。
specs/INDEX.mdでコーパス全体のドリフトを検出することはありません。 インデックスの更新で変更するのは、このバッチの変更がspecs_touchedで宣言した機能の行だけです。このスキル以外である機能のspec.mdが編集され、その結果INDEX.mdの該当行が古くなっていても、このスキルの通常処理では検出されません。現時点ではaccelint-archive-synthesisでも同様です。意思決定ドリフトと構造的結合のチェックは、どちらもspecs/INDEX.mdを正として読み取り、spec.mdと照合していません。これは実際に認識されている制約であり、このスキルがアーカイブごとの処理コストに取り込むべき作業ではありません。- どちらの INDEX.md テーブルの後にも、メタデータや要約を置きません。
openspec/changes/archive/INDEX.mdとopenspec/specs/INDEX.mdは、テーブルの前に前文を置くことができます(ある場合は保持します)。その後にテーブル(ヘッダー、区切り行、データ行)が続き、ファイルはそこで終わります。テーブルの後に内容を追加することは認められません。禁止される末尾要素の例として、「Total Changes:」、「Generated:」、「Status Legend:」、水平線があります。以前の実行によってこのような内容が残っている場合は削除する必要があります。両ファイルの標準形式は「任意の前文、テーブル、ファイル終端」です。
エラー処理
design.md のフロントマターがない、または不正な場合(タスク A):変更の proposal.md と差分仕様ディレクトリ自体から specs_touched/decisions の候補を導き出し、ユーザーに明示的な確認を求めます。その変更のアーカイブ処理が実行される前に、確認済みの値を design.md に書き戻します。ユーザーが自分で修正するために一時停止することを選んだ場合、または変更自体のファイルから候補をまったく導き出せない場合に限り、フィールド名を示して、その変更のアーカイブ処理の前に停止します。
## Purpose または ### Purpose の見出しがない場合(タスク B):アーカイブ、検証、相互リンクの計算はブロックしません(仕様本文には触れないためです)。ただし、その機能の仕様書の書き込みに進む前に停止し、プレースホルダーを追加するか、先に仕様を修正するようユーザーに求めます。
変更が1つの機能だけに関係する場合:エントリーが1つだけの specs_touched ではペアは0件になります。これは想定どおりであり、エラーではありません。それでも、その機能の仕様書の書き込みは実行します(last_touched_by/last_touched_on を書き込み、一覧に変更がなくても ## Related Specs を再生成します)。また、変更履歴のステップでは、その行を changes/archive/INDEX.md に追加します。
これまで spec.md がなかった新規機能:事前チェック(ステップ 4)と仕様書の書き込み(ステップ 19 のサブステップ 2)で明示的に処理します。サブエージェントは、ファイルがないことをエラーとして扱わず、空のフロントマターブロックから作業を開始します。
ネイティブコマンドで未解決の競合が報告された場合:アーカイブ処理を停止し、抽出に進まず(アーカイブのステップ 8)、競合の内容をそのまま直ちにユーザーに報告します。検証には進みません。
実行中に openspec-archive-change または openspec-bulk-archive-change が内部で別の処理に分岐する場合(最も多いのは、別の同期スキルへの分岐です):これはコマンドの通常の想定動作であり、失敗ではありません。アーカイブのセクションのステップ 4~5 を参照してください。分岐処理の完了後は、アーカイブ処理に残っているステップを続行します。分岐処理中(または実行中のその他の処理)に、通常の同期に関する y/n 以外のプロンプトが表示された場合は、推測で進めず、ユーザーに提示して回答を待ちます。
仕様書の書き込みにサブエージェントを利用できない場合(サブエージェントに対応していない環境など):機能ごとにサブエージェントを1つ使う代わりに、このコンテキストで仕様書の書き込み手順を直接実行します。この場合、実行中に spec.md の内容全体をコンテキストに保持することになると、ユーザーにはっきり警告します。これは仕様書の書き込みに限った代替手段であり、意図された既定の方法ではありません。通常は常に、仕様書の書き込みにサブエージェントを優先して使います。サブエージェントの利用可否にかかわらず、アーカイブ処理は設計上、常にこのコンテキストで実行されるため、この点はアーカイブ処理には影響しません。アーカイブと抽出のセクションを参照してください。
specs/INDEX.md または changes/archive/INDEX.md がまだ存在しない場合:プロジェクトで初めてアーカイブを行う場合は想定どおりです。changes/archive/INDEX.md を新規作成し、ヘッダー行と区切り行だけを記載します。末尾にはいかなる内容も追加しません(ステップ 32)。specs/INDEX.md は、インデックスの初期構築時にすべての機能をもとに新規作成し(ステップ 27)、それ以降の各アーカイブでは行ごとに更新します。
いずれかの INDEX.md ファイルで表の後に禁止された内容がある場合(合計行数、Generated: の日付、ステータスの凡例、水平線など):changes/archive/INDEX.md と specs/INDEX.md の両方から、表の後にあるすべての内容を削除します。両ファイルの標準形式は、任意の前置き、表の順に続き、ファイルの終わりとなります。最後のデータ行の直後で終わり、その後に空行やメタデータを一切置きません。ステップ 30~31 を参照してください。
絶対にしてはいけないこと
エラーが発生しない限り、ワークフローの各ステップの間で決して停止してユーザーの確認を待たないでください — これは、事前チェックから最終レポートまで続く連続したワークフローです。アーカイブが正常に完了したら、すぐに検証へ進み、その後、相互リンクの追加などを行い、最終レポートまで続けてください。正当な停止ポイントは、(1)解決にユーザーの入力が必要なエラーが発生したとき、または(2)事前チェックに失敗したときだけです。openspec-archive-change の完了を、停止して待つ合図として扱わないでください。検証へ続行する合図です。
一括アーカイブ中に、中間のマージごとに検証からレポートまでを実行しないでください — バッチ全体が解決した後に、これらをちょうど1回だけ実行してください。早い段階で実行すると、まだ競合の蓄積が完了していない specs_touched セットに基づいてペアが算出され、未完成のバッチの不完全な行を使って INDEX.md が更新されます。
related: エントリを決して削除しないでください — このスキルで行うのは統合のみです。古く見えるエントリの削除は accelint-archive-synthesis の役割であり、その場合も人間の確認が必要です。
作成者の明示的な確認なしに、導出した specs_touched や decisions の候補を、変更の design.md に決して書き込まないでください — proposal.md と差分仕様から候補を導出する方法(タスクAの復旧手順)は、作業を再開可能にするための便宜であり、その変更が実際にどの機能に影響したかについて作成者自身が判断することの代わりにはなりません。
1行を更新するときに、既存の specs/INDEX.md の行を再度パディングしたり、位置を揃え直したりしないでください — セルのパディングは行ごとに行い、テーブル内で最も幅の広い値に合わせるものではありません。列を視覚的に揃えるためにすべての行の空白に手を加えると、対象行だけを編集するという目的が損なわれ、1行の差分がファイル全体の書き換えに戻ってしまいます。
changes/archive/INDEX.md に既にある Status の値を決して変更しないでください — 作成時に一度だけ current と記入し、その行のその列には以後手を加えないでください。状態の移行は accelint-archive-synthesis の役割です。
openspec/changes/archive/INDEX.md に決定事項の文章全体を決してコピーしないでください — このファイルは簡潔な変更履歴であり、design.md のコピーをもう1つ置く場所ではありません。各決定事項を、アーカイブ行に適した簡潔な断片にまとめてから記入してください。
Date を design.md から決して読み取らないでください — 必ずアーカイブフォルダー自体の YYYY-MM-DD プレフィックスを使ってください。変更がレビューで数週間保留されてからアーカイブされることもあるため、このスキルの実行時には design.md の日付情報が古くなっている可能性があります。
capability や purpose を仕様のフロントマターに決して重複して記載しないでください — どちらもファイル自体のパスと、## Purpose または ### Purpose の見出しに既に存在しています。どちらかを再記載すると、信頼できる情報源が二重になり、いずれ内容が食い違うことになります。
openspec/specs/INDEX.md に Purpose/Overview の段落全体を決して貼り付けないでください — 仕様から段落全体をコピーするのではなく、テーブルのセルに適した簡潔な1文を使ってください。
## Related Specs を手作業で管理しないでください — 直前に書き込んだ related: フロントマターから、必ず全体を再生成してください。これを独立して編集可能な内容として扱うと、フロントマターと本文の記載がずれていきます。
changes/archive/INDEX.md の既存の行を並べ替えたり書き換えたりしないでください — 追加のみ行ってください。このファイルが監査履歴として役立つかどうかは、過去の行が記載されたとおりに保たれているかに完全にかかっています。
どちらの INDEX.md にも、新しい行をファイル末尾への書き込みで追加しないでください — 既存のデータ行の終わりを特定し、新しい行の直前に空行を入れずに、その位置へ挿入してください。これは changes/archive/INDEX.md と specs/INDEX.md の両方に適用されます。
どちらの INDEX.md ファイルでも、データ行の間に空行を入れないでください — すべてのデータ行を、間に空行を挟まず連続させてください。エントリ間の空行はテーブル構造を壊します。これは changes/archive/INDEX.md と specs/INDEX.md の両方に適用されます。
どちらの INDEX.md テーブルの後にも、メタデータや概要を絶対に記述しないでください — openspec/changes/archive/INDEX.md と openspec/specs/INDEX.md には、テーブルの前に前置きがある場合があります(存在する場合はそのまま残してください)。その後にテーブル(ヘッダー、区切り行、データ行)が続き、ファイルはそこで終わります。テーブルの後に「Total Changes:」、「Generated:」、「Status Legend:」、水平線(---)、その他のコンテンツを絶対に記述しないでください。以前の実行でそうしたコンテンツが残っている場合は、削除してください。各ファイルは、最後のデータ行の直後で終わらなければなりません。
related: を並べ替えたり、ブロック形式の YAML にしたりしないでください — フロースタイルで1行にまとめ、アルファベット順に並べてください。これにより、変更のない実行でバイト単位の同一性が保たれ、実際に追加がある場合も、差分が明確でレビューしやすくなります。
openspec-archive-change または openspec-bulk-archive-change の実行中に、同期の確認プロンプトを絶対に拒否、スキップ、再検討しないでください — 常に「はい」と答えてください。このプロンプトは頻繁に表示されます。これはアーカイブ処理を完了するための定型的な手順であり、親コンテキストやユーザーの判断を仰ぐ必要がある決定事項ではありません。
サブエージェントのサポートが利用可能な場合でも、アーカイブと抽出のためにサブエージェントを絶対に起動しないでください — このコンテキスト内で、常に openspec-archive-change または openspec-bulk-archive-change を直接呼び出してください。この指示を受けたサブエージェントには、コマンドが内部で分岐した後(たとえば、別の同期スキルに分岐した場合)に、そのコマンドの残りの手順を確実に再開する方法がありません。また、対話型プロンプトをユーザーに提示する方法もありません。実際に、このどちらも原因となって、このスキルがアーカイブの途中で停止したことがあります。詳しくは「アーカイブと抽出」のセクションを参照してください。
サブエージェントが利用可能な場合、このコンテキストで仕様書の作成を絶対に直接行わないでください — バッチの規模にかかわらず、必ず委任してください。これは大規模なバッチを並列化するためではありません。あらゆる実行で、生の spec.md の内容をオーケストレーション用コンテキストに含めないためです。これは accelint-qrspi-propose と accelint-qrspi-apply が例外なく守るのと同じ方針です。
openspec-archive-change/openspec-bulk-archive-change の実行中の分岐(最も多いのは、独自の同期スキルへの分岐)を、アーカイブ手順の終了として扱わないでください — 分岐が完了したら、コマンドの残りの手順を再開してください。分岐自体がタスクのすべてだと判断してしまうことこそ、そもそもアーカイブをインラインで実行するようになった原因の失敗パターンです。
使用例
シナリオ1:単一変更のアーカイブ
User: Archive the add-live-sync change with cross-linking
Skill: Running preflight checks...
✓ design.md frontmatter valid (specs_touched: sync/protocol, ui/status-indicator)
✓ Both capabilities have a ## Purpose/### Purpose heading
Running openspec-archive-change add-live-sync directly (archive never uses a subagent)...
Sync now? (y/n) → yes
✓ Synced delta specs, resuming openspec-archive-change's remaining steps...
✓ openspec-archive-change add-live-sync merged, archived to
openspec/changes/archive/2026-03-02-add-live-sync/
✓ Extracted: specs_touched, decisions from design.md frontmatter
Computing new co-touch pairs...
- sync/protocol ↔ ui/status-indicator (new pair)
[spawns subagent: sync/protocol] [spawns subagent: ui/status-indicator]
✓ sync/protocol/spec.md: related: [ui/status-indicator] (merged, was empty)
✓ ui/status-indicator/spec.md: related: [sync/protocol] (merged, was empty)
Updating openspec/specs/INDEX.md... (2 rows patched, 12 rows untouched)
Appending to openspec/changes/archive/INDEX.md... (1 row)
✅ Archive complete: add-live-sync
Next steps:
- Review the diff on the two updated specs before committing
- related: entries are additive only — pruning is accelint-archive-synthesis's job
シナリオ2:すでにリンクされている機能に触れる一括アーカイブ
User: Run bulk-archive on the pending changes
Skill: Running preflight checks across 3 pending changes...
✓ All design.md frontmatter valid
⚠ auth/session-store is missing a ## Purpose or ### Purpose heading
How would you like to handle auth/session-store?
(a) Add a placeholder purpose now and continue
(b) Pause so you can add the heading yourself first
User: (b)
Skill: Paused. Add a ## Purpose or ### Purpose heading to openspec/specs/auth/session-store/spec.md,
then re-invoke this skill to continue.
シナリオ3:design.md のフロントマターがない場合に、変更自体のファイルから復元する
User: Archive the enhance-mock-consistency-rule change
Skill: Running preflight checks...
⚠ design.md has no specs_touched or decisions frontmatter
Checking proposal.md and openspec/changes/enhance-mock-consistency-rule/specs/
for a derivable candidate...
Derived from this change's own files:
specs_touched: [testing/mock-consistency]
decisions:
- id: D1
choice: enforce consistency at lint time, not runtime
rationale: catches drift before merge instead of in CI
alternatives: [runtime assertion, manual review checklist]
(a) Confirm this as written
(b) Edit it first
(c) Pause so I can fix design.md myself
User: (a)
Skill: Confirmed. Writing this into design.md's frontmatter, then proceeding...
Running openspec-archive-change enhance-mock-consistency-rule directly...
✓ openspec-archive-change enhance-mock-consistency-rule merged, archived to
openspec/changes/archive/2026-07-07-enhance-mock-consistency-rule/
...
シナリオ4:一括アーカイブで定型外のプロンプトが表示される(スキルでは回答せず、ユーザーに提示する)
User: Run bulk-archive on the pending changes
Skill: Running preflight checks across 2 pending changes...
✓ All design.md frontmatter valid
Running openspec-bulk-archive-change directly (archive never uses a subagent)...
Sync now? (y/n) → yes
⚠ add-dark-mode and update-footer both touch specs/ui/ — archive both,
merging in chronological order? (y/n)
This isn't the routine sync prompt, so I'm not answering it myself —
add-dark-mode and update-footer both touch specs/ui/. Archive both,
merging in chronological order (add-dark-mode, then update-footer)?
User: Yes
Skill: ✓ Archived add-dark-mode, then update-footer, specs/ui/ merged in that order
...
このシナリオは、アーカイブをインラインで実行することで初めて可能になります。openspec-bulk-archive-change を受けたサブエージェントには、順序についての質問をユーザーに伝え、実際の回答を得る方法がありません。そのため、処理が停止するか、推測で進めるしかありません。このコンテキストでアーカイブを実行すれば、実際に回答できる人に質問が届きます。