コンテンツにスキップ

言語の選択

現在の言語: 日本語

良い仕様を書く

仕様を白紙から書くことはほとんどありません。平易な言葉で変更内容を説明すると、/opsx:propose が要件とシナリオを下書きし、あなたがそれを良い内容に仕上げます。このページでは最後の部分、つまり「良い仕様」とは何か、AI をどのように導けばよいかを説明します。

このページは変更のレビューと対になるものです。レビューでは下書きの弱点を見つけ、執筆では良い仕様を構成する要素を理解します。

仕様はコードではなく動作を表す

Section titled “仕様はコードではなく動作を表す”

仕様では、システムが 何をするか を誰でも確認できる言葉で記述します。どのように構築するかは記述しません。仕様は 要件(動作を述べる文)と、それを証明する具体例である シナリオ で構成されます。

### Requirement: セッションタイムアウト
システムは、30分間操作がなければセッションを期限切れにしなければならない。
#### Scenario: アイドルタイムアウト
- GIVEN 認証済みのセッションがある
- WHEN 何も操作せずに30分が経過する
- THEN セッションが無効になり、ユーザーは再認証しなければならない

キュー、ライブラリ、テーブルスキーマなどの 実現方法 は design.md またはコードに記述してください。動作と実装を1つの要件に混在させると、要件をテストできなくなり、コードを変更した時点で古くなり始めます。

良い要件とは、1つの動作を誰かに渡してテストしてもらえるほど明確に記述したものです。

  • 1つの文に SHALL/MUST を1つ。 要件に「さらに〜も」といった節が3つあるなら、実際には3つの要件です。分割してください。

  • 観測可能であること。 コードの外にいる人でも、要件を満たしているか判断できる必要があります。「アップロードが10 MBを超えたとき、システムはエラーバナーを表示しなければならない」は観測可能です。「システムは大きなアップロードを適切に処理しなければならない」はそうではありません。

  • 適切な強さであること。 OpenSpec で使う RFC 2119 キーワードには、それぞれ異なる意味があります。

    キーワード 意味
    MUST / SHALL 絶対に満たすべき要件。交渉の余地はありません。
    SHOULD 正当な例外を認める強い推奨。
    MAY 本当に任意の事項。

    既定では MUST/SHALL を使ってください。「そうしない正当な理由がない限り」と本当に意図するときに限り、SHOULD を使います。

要件の判定基準は、コードを一度も見たことがないテスターでも、合格したか判断できるか です。できない場合は、さらに明確にしてください。

シナリオによって要件が役立つものになります。それぞれが自動テストにできる具体的な GIVEN / WHEN / THEN です。

  • 対応する要件を検証する。 要件を別の言葉で言い換えただけのシナリオでは、何もテストできません。具体的な状況と結果を記述してください。
  • 正常系だけでなく、重要なケースを網羅する。 正常なログインは簡単です。空の入力、期限切れのトークン、2回目のクリック、問題が起きるケースこそバグが潜んでおり、シナリオが最も役立つ場面です。
  • タイトルでケースを示す。 「Scenario: 期限切れトークンを拒否する」なら対象範囲がすぐ分かりますが、「Scenario: テスト2」では分かりません。

承認前に 壊れていたら最も困るケースは何か を考え、そのケースがシナリオに含まれているか確認するとよいでしょう。

change では、3種類の節を使って仕様の変更を記述します。適切な種類を使うことで、アーカイブ後の仕様を正確に保てます。

  • ## ADDED Requirements — これまで存在しなかった新しい動作。
  • ## MODIFIED Requirements — すでに存在し、変更される動作。新しい内容をすべて記載してください。変更点を短く補足するとレビュアーに役立ちます。
  • ## REMOVED Requirements — 廃止する動作と、その理由。

アーカイブ時に ADDED はメイン仕様に追加され、MODIFIED は古い内容を置き換え、REMOVED は削除されます。ある機能の最後の要件を削除すると、その機能は廃止になります。空の仕様を残すのではなく、アーカイブによって openspec/specs/<capability>/spec.md が削除されます。ファイルを削除する唯一のアーカイブ手順であるため、明示的な指定が必要です。change の .openspec.yaml に、必要な schema: とともに retire_capabilities: true を追加してください。指定がなければ、アーカイブは中断してその旨を知らせます。廃止ではファイル全体が削除されるため、仕様にタイトル、## Purpose、要件ブロック以外の内容(## Notes 節や要件下のコメントなど)がある場合も拒否されます。中断メッセージには該当行が示されます。それらを ## Purpose または要件に移すか、仕様を手動で削除してください。呼び出し元のチェックアウトにある仕様の場合、アーカイブの出力にはコミット済みファイルを復元する git checkout コマンドも示されます。選択した store の場合は、チェックアウト範囲に応じた復旧手順が示されます。実際には新しい変更を ADDED とすると競合する要件が2つでき、既存の動作を MODIFIED として記述すると置き換える内容がなくなります。迷ったら現在の仕様を開き、要件がすでに存在するかを確認してください。

もう1つ知っておくとよい節があります。差分で新しい機能を作成するときは、## Purpose を付けて、機能の目的を1〜2文で記述してください。アーカイブではこれが作成されるメイン仕様の Purpose になります。省略すると TBD のプレースホルダーが作られ、手動で記入する必要があります。既存の仕様には Purpose があるため、差分側に記述しても無視されます。既存仕様の Purpose を変更するには、openspec/specs/<capability-path>/spec.md を直接編集してください。ここで <capability-path> は specs/ からの相対ディレクトリです。例として、フラットなプロジェクトでは user-auth、ドメイン別に整理したプロジェクトでは identity/user-auth です。

仕様を書くときに最もよくある失敗は、要件の表現が悪いことではありません。1つの change で3つの変更をしようとすることです。

良い change は、1文で言える目的を1つ持ちます。 「ダークモードの切り替えを追加する」「ログインエンドポイントにレート制限を設ける」「セッションを Cookie から移行する」などです。説明に「それから」や「さらに」が何度も必要なら、分割する合図です。

change が大きすぎる兆候:

  • 提案の範囲が、無関係な機能のリストのようになっている。
  • レビューに半日かかりそうで、誰もレビューしない。
  • 2人で作業すると競合を避けられない。
  • タスクの半分だけでも単独でリリースできる。

小さな change はレビューしやすく、集中した1回の作業で実装しやすく、アーカイブだけが残る6か月後にも理解しやすくなります。複数の change を並行して進めることもできます。変更の編集と反復とワークフローを参照してください。

逆のケースもあります。1行のタイプミス修正に、3つの要件と設計ドキュメントは必要ありません。作業の重要度に応じて手順を調整してください。

最初の下書きは /opsx:propose が作るため、得られる結果の質は、伝える内容の質に左右されます。要件を手書きする必要はありません。AI に適切な方向を示してください。

  • 目的と境界を伝える。 「初回読み込み時は OS 設定に従うダークモード切り替えを追加する — 既存のテーマ API には触れない。」 対象外の範囲も対象範囲と同じくらい重要です。
  • 重視するケースを挙げる。 「すでに手動でテーマを選択したユーザーのシナリオも必ず含めてください。」 AI は指定された内容をカバーします。
  • その後に編集する。 通常の Markdown なので、曖昧な SHALL を明確にし、何も検証しないシナリオを削除し、抜けたケースを追加できます。AI に 「タイムアウト要件が曖昧なので、30分に固定してください」 と依頼することもできます。

下書きし、磨き、繰り返します。数回繰り返せば、信頼できる仕様が完成します。それが目的です。

  • 各要件は、SHALL/MUST を使って記述した観測可能な動作1つである。
  • 要件に実装の詳細が含まれていない。
  • 各要件に、それを実際に検証するシナリオが1つ以上ある。
  • 正常系だけでなく、重要な境界ケースやエラーケースにもシナリオがある。
  • 現在の仕様に対して ADDED / MODIFIED / REMOVED を正しく使っている。
  • change 全体に、1文で表せる目的が1つある。

HagiCode

HagiCode は構造化ワークフロー、マルチエージェント実行、Hero Dungeon ビューを備えたエージェント型コーディングワークスペースです。

よりスマートで速く、楽しいエージェント型ワークフローで、使いやすいソフトウェアを形にします。

HagiCode ライトテーマのメイン画面
  • Smart構造化ワークフローは意図をアイデアから変更のリリースまで実行可能な道筋にします。
  • Efficientマルチエージェントのワークフローで調査、実装、レビューを並行して進めます。
  • FunHero Dungeon により長時間のコーディングを視覚的で協力的な体験にします。
HagiCode を見る