要件定義からコード生成までの仕様に駆動する開発ワークフロー
意図から検証済みのコードへ:5つのフェーズ
仕様駆動型開発(SDD)は、仕様がドキュメントとしてキックオフ後に棚卸しされるものではなく、ワークフローそのものであるときに機能します。目的は、大規模な製品要件定義ドキュメントを作成することではありません。
目的は、人間やAIエージェントが本番コードを変更する前に、それぞれの段階で曖昧さを減少させる、レビュー可能なアーティファクトの連番を通じて進めることです。
SDDが概念的にどのようなものかわからない場合は、定義、TDDおよびBDDとの比較、そして仕様を真のデータ源(Source of Truth)として扱うための根拠については、仕様駆動型開発とは何か?をご覧ください。本記事はアプリアーキテクチャ)のドキュメントクラスターにおける運用ガイドです。5つのフェーズを解説し、各アーティファクトに含めるべき内容を示し、AIエージェントの位置付けを説明し、今日リポジトリにコピーして使用できる再利用可能なテンプレートを提供します。

SDDはドキュメントではなくワークフローです
仕様駆動型開発における最も一般的な失敗モードは、仕様を事務作業(ペーパーワーク)として扱うことです。チームは長い要件定義ドキュメントを作成し、Wikiに保存し、その後、記憶やチャットスレッドに基づいてコーディングします。仕様は存在しますが、何もしません。これは「ドキュメント劇」であり、誤った安心感を醸成するため、仕様がない場合よりも悪いです。
機能するSDDワークフローは、各アーティファクトの連鎖を生成し、次のフェーズが始まる前にそれぞれをレビューします。要件は製品の曖昧さを減らします。設計は技術的な曖昧さを減らします。タスクは実行の曖昧さを減らします。実装は既知のターゲットに対してコードを生成します。検証は連鎖が維持されたことを証明します。どのフェーズでもミスが発見された場合、3000行もの乖離がmainブランチに届いた後ではなく、その時点からアーティファクトを修正して再実行します。
このワークフローはツールに依存しません。Git上のmarkdownファイル、GitHub Spec Kit)、Cursorのプラン、あるいはプレーンテキストエディタと規律あるレビュアーを使って実行できます。重要なのはツールブランドではなく、順序とレビューゲートです。
フェーズ1 – 要件の仕様定義
仕様定義フェーズは、解決すべき問題と「完了」とは何かを定義します。どのように構築するかを意図的に避けます。要件仕様が「Redisのソート済みセットを使用する」と言った瞬間、仕様定義を止めて、間違ったドキュメントで設計を始めてしまいます。実装の詳細は要件から外し、計画(プラン)に記述してください。
問題ステートメントとユーザー
平易な言語で問題を記述した1段落で始めます。影響を受けるユーザーと、問題が痛手となる状況を特定します。良い問題ステートメントは、計画会議に参加していなかったレビュアーが、提案された解決策が実際にその苦痛に対処しているかどうかを判断できるようにします。
APIレート制限機能の例:
フリーティアのAPI消費者は無限のリクエストを送信できるため、コストの急増と有料テナントへのノイズネイバー影響を引き起こしています。プラットフォーム運用者は、手動介入なしで適用可能なキーごとの制限が必要です。
目標、非目標、受入基準
目標は、提供される成果を記述します。非目標は、明確に行わない誘惑的な関連作業を記述します。これらは組み合わせることで、AIツールがそうでなければ「親切に」スコープを拡大する際に、エージェントの創造性を制限します。これは本質的に重要です。
| セクション | 良い例 | 弱い例 |
|---|---|---|
| 目標 | キーごとの制限を超えたリクエストをHTTP 429で拒否する | APIを高速化する |
| 非目標 | テナントごとの請求ダッシュボード | すべてのAPIパフォーマンスを改善する |
| 受入基準 | 認証されていないリクエストはレートチェック実行前に401を受け取る | エンドポイントは安全である |
受入基準は、それぞれが少なくとも1つのテストに対応するほど明確であるべきです。「エンドポイントは安全である」は受入基準ではありません。「認証されていないリクエストはHTTP 401を受け取る」がそうです。具体的な基準を書けない場合、その要件は実装するには依然として曖昧すぎます。
未解決の質問
まだ決まっていないすべての決定をリストします。不明確な質問は失敗の兆しではありません。それらは仕様定義フェーズが役割を果たしている証拠です。設計計画を書く前にそれらを解決しないと、実装時の手戻りコストを支払うことになります。
最小限の要件テンプレート:
## 問題
[1段落:誰が困っているか、なぜ困っているか、そして何がその痛手を引き起こすか。]
## ユーザー
- [主要ユーザーロール]
- [次要ユーザーロール]
## 目標
1. [測定可能な成果]
2. [測定可能な成果]
## 非目標
- [明確にスコープ外]
- [明確にスコープ外]
## 受入基準
- [ ] [検証可能な振る舞い]
- [ ] [検証可能な振る舞い]
## 未解決の質問
- [ ] [計画をブロックする質問]
フェーズ2 – 設計の計画
計画フェーズは、意図を技術的決定に翻訳します。ここがRedisのソート済みセット、モジュールの境界、スキーマ変更、API契約、マイグレーション手順、セキュリティ制約、テスト戦略が所属する場所です。計画は要件仕様とプロジェクトの既存の制約(スタックの選択、決定記録)、AGENTS.mdやプロジェクト憲章などのファイルに保存された慣習)から派生します。
アーキテクチャと影響を受けるモジュール
変更されるモジュール、サービス、またはパッケージを名前付けし、統合パターンを要約します。機能がサービス境界を跨ぐ場合、両側の契約を文書化します。契約が暗黙的な場合、エージェントはAPIを幻覚(ハルシネーション)します。計画の中でそれらを明示的にすることで、捏造されたエンドポイントや間違ったレスポンス形状を防ぎます。
データモデル、API契約、マイグレーション
スキーマ変更、新しいテーブルやフィールド、インデックス要件、後方互換性ルールを文書化します。HTTP APIの場合、メソッド、パス、リクエスト形状、レスポンス形状、エラーコードを記述します。イベントの場合、トピック名、ペイロードスキーマ、配信セマンティクスを記述します。データモデルが変更される場合、マイグレーション手順とロールバックノートを含めます。
セキュリティ、観測可能性、テスト戦略
セキュリティ制約は計画に属し、コードレビューでの後付けではありません。認証要件、認可ルール、入力検証の境界、ログに出現してはいけないデータを注記します。観測可能性は、本番環境で機能が機能していることを確認するために必要なメトリクス、ログ、トレースをカバーすべきです。
テスト戦略は受入基準にリンクします。どの基準がユニットテストを必要とし、どの基準が統合テストを必要とし、どの基準が手動検証を必要とするかを特定します。Goでのユニットテスト)やPythonでのユニットテスト)を使用する場合、追加を想定するパッケージとテストファイルの名前を記載します。テスト戦略のない計画は、本番環境で発見されるギャップを伴って出荷される計画です。
フェーズ3 – 実装タスクの分解
タスクフェーズは、計画を独立して実装、レビュー、検証可能な十分に小さなスライスに分解します。これがエージェント支援開発をレビュー可能にするものです。巨大な1つの差分ではなく、名前付きの要件にそれぞれマッピングされる集中的な変更のシーケンスが得られます。
タスクのサイズと依存関係
良いタスクは、限定されたファイルセットを処理し、1つのエージェントセッションで完了し、検証ステップで終了します。タスクは依存関係を明示的に宣言すべきです。マイグレーションタスクは新しいスキーマを読み取るコードの前に実行されます。共有ライブラリの変更は消費者の前に実行されます。認証ミドルウェアの変更は新しい振る舞いに依存するエンドポイントの前に実行されます。
ファイル、検証、レビューチェックポイント
各タスクは、変更される可能性のあるファイル、満たす受入基準、完了を検証する方法をリストすべきです。検証はテストコマンド、curlの例、コピーペースト可能な手順で記述された手動チェックかもしれません。すべてのタスクは人間のレビューチェックポイントで終了します。レビュアーは、次のタスクが始まる前に、差分がタスクの説明と一致することを確認します。
最小限のタスクエントリ:
### タスク3 -- レート制限ミドルウェアの追加
**依存関係:** タスク1(スキーマ)、タスク2(リポジトリ)
**ファイル:** middleware/ratelimit.go, middleware/ratelimit_test.go, server.go
**満たす:** AC-2(制限超過で429)、AC-3(レスポンスに制限ヘッダー)
**検証:** `go test ./middleware/...`がパスする;制限超過のcurlがRetry-After付きで429を返す
**レビューチェックポイント:** ミドルウェアが認証の後に、ハンドラーの前に実行されることを確認
生成されたタスクの爆発に注意してください。AIエージェントは数秒で50個のタスク計画を生成できます。それらのタスクの多くは冗長か、効率的にレビューするには細かすぎます。中規模機能にとって有用なタスクリストは、50個ではなく、5〜15個のアイテムを持つことがよくあります。
フェーズ4 – 1つずつタスクを実装する
実装は意図的に狭いです。1つのタスクを選び、そのタスクに必要なコンテキストのみをエージェントに与え、検証がパスするところで停止します。タスク間のコンテキストリセットはバグではなく機能です。それらは以前の仮設が後の作業を汚染するのを防ぎ、差分をレビュー可能に保ちます。
仕様スタックからの制約を適用
実装エージェントは、要件仕様、設計計画、現在のタスク説明、プロジェクトレベルの制約を読み取るべきです。制約は、多くのチームがスキップする最もROIが高いセクションです。それらはエージェントに何をしないかを伝えます – 無関係なモジュールのリファクタリングはしない、この機能の外でパブリックAPI署名を変更しない、計画を更新せずに新しい依存関係を導入しない。
現実が異なる場合、計画を更新する
実装は驚きをもたらします。ライブラリが想定された振る舞いをサポートしていない。マイグレーションが予想より時間がかかる。エッジケースが受入基準から欠落していた。そのような場合、続行する前に仕様を更新します。要件または計画を修正し、クイックレビューを受け、修正されたアーティファクトに対して実装を再開します。仕様に静かに逸脱するコードは、乖離を恒久的にする方法です。
フェーズ5 – 仕様に対する検証
検証は、SDDがその価値を証明する場所です。それなしでは、仕様は単なる演習です。それがあることで、仕様は出荷されたコードに対してチェックできる契約になります。
自動チェック
CIでフルテストスイート、リンター、型チェックを実行します。実用的なスタートポイントが必要な場合は、GitHub Actionsチートシート)のパターンを使用してパイプラインに接続します。自動チェックは回帰をキャッチします。しかし、正しく構築された誤った機能をキャッチするわけではないため、受入基準のレビューが依然として重要です。
受入基準と手動レビュー
要件仕様からの各受入基準を walkthrough します。それぞれを満たした、失敗した、または理由付きで延期済みとしてマークします。手動レビューは、テストが flawed な仕様に合わせて書かれていたため見逃したUX問題、セキュリティギャップ、誤った振る舞いをキャッチします。
仕様からコードへの差分
最終的な検証ステップは、実装を設計計画と比較します。変更されたファイルは計画が予測したファイルと一致しましたか?コード内のアーキテクチャ決定は記録された決定と一致しましたか?差分内の予期せぬファイルはシグナルです – 計画が不完全だったか、エージェントが逸脱したかのどちらかです。両方ともマージ前に注意が必要です。
| 検証レイヤー | キャッチするもの |
|---|---|
| ユニットおよび統合テスト | 範囲内での回帰と誤ったロジック |
| リンターと型チェック | スタイルの問題と型エラー |
| 受入基準のwalkthrough | 仕様に沿って構築された誤った振る舞い |
| 仕様からコードへの差分 | アーキテクチャの乖離とスコープクリープ |
ワークフローにおけるAIエージェントの位置付け
AIエージェントは、各フェーズの加速器であり、レビューの代替ではありません。生産的なパターンは、ドラフト、レビュー、洗練、そして進行です。問題記述から要件仕様のドラフトを作成するようエージェントに依頼し、目標、非目標、受入基準が正しいまで意図を編集します。承認された要件から設計計画のドラフトを作成するようエージェントに依頼し、コードが存在する前にアーキテクチャ決定をレビューします。各差分を次のタスク開始前に承認しながら、1つのタスクスライスずつ実装するようエージェントに依頼します。
エージェントは、最初のドラフトとボイラープレートテストの生成に特に有用です。人間は、誤った目標、危険なアーキテクチャ、微妙なスコープクリープをキャッチすることに特に優れています。どちらかがスキップされた場合、ワークフローは失敗します – 仕様なしでエージェントが実装する場合、または人間がコードに対して検証することなく仕様を書く場合。
このワークフロー記事は意図的にツール中立です。エディタ設定、スラッシュコマンド、エージェント設定などのツール固有の実行ガイドは、AI開発ツール)クラスターの下にあります。プロセスの柱は、ベンダーよりもアーティファクトが重要であるため、ここでのドキュメントプラクティスの下にあります。
仕様駆動型開発を殺す一般的なミス
検証前の巨大な仕様。 プロトタイプやスパイクの前に書かれた30ページの要件定義ドキュメントは、SDDではなくウォーターフォールのペーパーワークです。次のフェーズの曖昧さを除去するために必要な最小限の仕様を書き、仮説を早期に検証します。すべての機能が5フェーズループを必要とするわけではありません – 仕様駆動型開発 vs バイブコーディング)が、より軽い構造で十分である時期を説明しています。
曖昧な受入基準。 「高速」、「クリーン」、「ユーザーフレンドリー」といった形容詞は受入基準ではありません。それらを測定可能な振る舞いに置き換えます。テストできないものは、特にAIエージェントを使用する場合、信頼して実装できません。
非目標の欠落。 非目標なしでは、エージェントはデフォルトでスコープを拡大します。キャッシュレイヤーを追加し、隣接モジュールをリファクタリングし、要求していない依存関係を導入します。非目標は、事前に「ノー」と言う方法です。
設計フェーズにテスト計画がない。 実装後にのみ書かれたテストは、意図されたものではなく、構築されたものを確認する傾向があります。計画は、最初の本番ファイル変更前に、どの受入基準がどのテストタイプにマッピングされるべきかを示すべきです。
フェーズ境界でのレビューをスキップ。 計画前の仕様レビュー。タスク前の計画レビュー。実装前のタスクレビュー。各ゲートは安価です。大規模なマージ後の乖離修正は高価です。
生成されたタスクの爆放を許す。 50個のAI生成タスクリストをスケジュールではなく最初のドラフトとして扱います。冗長なアイテムをマージし、オーバーサイズのスプリットを分割し、要件にマッピングしないタスクを削除します。
仕様駆動型開発(SDD)は、各フェーズが曖昧さを減少させる場合に機能します。ペーパーワークを作成する場合は失敗します。
再利用可能なテンプレート
これらをリポジトリにコピーし、適応させてください。仕様を機能ブランチと一緒に保存し、プルリクエストでレビューし、エージェントと人間が同じソースを読むようにバージョン管理に保ちます。
要件テンプレート
# 機能 -- [名前]
## 問題
## ユーザー
## 目標
## 非目標
## 受入基準
## 未解決の質問
設計テンプレート
# 設計 -- [機能名]
## サマリー
## 影響を受けるモジュール
## データモデル変更
## API契約
## マイグレーション
## セキュリティ
## 観測可能性
## テスト戦略
## リスクと緩和策
タスクリストテンプレート
# タスク -- [機能名]
## タスク1 -- [タイトル]
依存関係:
ファイル:
満たす:
検証:
レビューチェックポイント:
## タスク2 -- [タイトル]
...
検証チェックリスト
# 検証 -- [機能名]
## 自動
- [ ] すべてのテストがパス
- [ ] リンタークリーン
- [ ] 型チェッククリーン
## 受入基準
- [ ] AC-1 --
- [ ] AC-2 --
## 仕様からコードへ
- [ ] 変更されたファイルが計画と一致
- [ ] 文書化されていないアーキテクチャ変更なし
- [ ] 実装が異なる場合は仕様を更新
結論
仕様駆動型開発は、より多くのドキュメントを書くことではありません。それは、各ステップにレビューゲートを備えた、仕様定義、計画、タスク、実装、検証を通じて進めることです。各フェーズは、次のアクター – 人間またはエージェント – に、前のフェーズよりも少ない推測を残すべきです。
小さなところから始めます。中規模の機能1つにフルワークフローを実行します。アーティファクトをリポジトリのmarkdownに保ちます。現実が逸脱する場合、仕様を更新します。マージ前に検証します。連鎖が機能する場合、少ない乖離、レビュー可能な小さな差分、セッションリセットとチームの引継ぎに耐える持続的な意図の記録が得られます。
連鎖がペーパーワークになる場合、スコープを削減します – レビューではありません。検証された2ページの仕様は、誰も読まない30ページの仕様より優れています。
有用なリンク
- GitHub Spec Kit ドキュメント – 類似の仕様定義-計画-タスク-実装ループを実装するオープンソースツールキット
- Martin Fowlerによる仕様駆動型開発ツールの分析 – Kiro、Spec Kit、Tesslの分析