要件からコードへ:仕様駆動型開発ワークフロー
インテントから検証済みコードへ、5つのフェーズ
仕様駆動型開発(SDD)は、仕様がプロジェクト開始後に棚に並べるための文書ではなく、ワークフローそのものとして機能する場合に効果的です。ここで重要なのは、大規模な製品要件定義書を作成することではありません。
重要なのは、人間もAIエージェントも本番環境のコードを変更する前に、曖昧さを段階的に減少させるレビュー可能なアーティファクト(成果物)のシーケンスを通過させることです。
SDDの概念についてご存知ない場合は、まず仕様駆動型開発とは何か?をご覧ください。ここでは定義、TDDやBDDとの比較、仕様を真実の源(Source of Truth)として扱う理由について説明しています。本記事はアプリアーキテクチャ)ドキュメントクラスターの運用ガイドです。5つのフェーズを解説し、各アーティファクトに含めるべき内容を示し、AIエージェントの役割を説明し、今日からリポジトリにコピーして使える再利用可能なテンプレートを提供します。

SDDは文書ではなくワークフローです
仕様駆動型開発における最も一般的な失敗モードは、仕様を単なる事務処理(ペーパーワーク)として扱うことです。チームは長い要件定義書を書き、それをWikiに保存し、その後で記憶やチャットスレッドを頼りにコーディングを行います。仕様は存在しますが、それは何もしません。これは「ドキュメント・シアター(形式だけの文書化)」であり、仕様がない場合よりも悪化させるもので、誤った自信を生み出します。
機能するSDDワークフローは、次のフェーズが開始される前にそれぞれがレビューされるアーティファクトの連鎖を生み出します。要件は製品の曖昧さを減らします。設計は技術的な曖昧さを減らします。タスクは実行の曖昧さを減らします。実装は既知のターゲットに対してコードを生成します。検証はチェーンが維持されたことを証明します。どのフェーズでもミスが発見された場合、その時点でアーティファクトを修正し、そこから再実行します。メインブランチに3,000行ものズレ(ドリフト)が適用されるのを待ってからではありません。
このワークフローはツールに依存しません。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つの差分(diff)の代わりに、名前付きの要件にそれぞれ対応する焦点の絞り込まれた変更のシーケンスが得られます。
タスクのサイズと依存関係
良いタスクは、限定されたファイルセットを扱い、1つのエージェントセッションで完了し、検証ステップで終了します。タスクは依存関係を明示的に宣言すべきです。移行タスクは新しいスキーマを読み取るコードの前に実行されます。共有ライブラリの変更はコンシューマーの前に実行されます。認証ミドルウェアの変更は新しい振る舞いに依存するエンドポイントの前に実行されます。
ファイル、検証、およびレビューチェックポイント
各タスクは、変更が予想されるファイル、満たす受入基準、および完了を検証する方法をリストするべきです。検証はテストコマンド、curlの例、またはコピーペースト可能な手順で説明された手動チェックかもしれません。すべてのタスクは人間のレビューチェックポイントで終了します。レビュアーは次のタスクが開始される前に、差分がタスクの説明と一致することを確認します。
最小限のタスクエントリ:
### Task 3 -- Add rate-limit middleware
**Depends on:** Task 1 (schema), Task 2 (repository)
**Files:** middleware/ratelimit.go, middleware/ratelimit_test.go, server.go
**Satisfies:** AC-2 (429 over limit), AC-3 (limit headers in response)
**Validate:** `go test ./middleware/...` passes; curl over limit returns 429 with Retry-After
**Review checkpoint:** Confirm middleware runs after auth, before handler
生成されたタスクの爆発に注意してください。AIエージェントは数秒で50個のタスク計画を生成できます。その多くは冗長か、効率的にレビューするには細かすぎます。中規模機能のための有用なタスクリストは、50個ではなく、5〜15個のアイテムであることがよくあります。
フェーズ4 – 1つずつタスクを実装する
実装はあえて狭い範囲に限定されます。1つのタスクを選び、そのタスクに必要なコンテキストのみをエージェントに与え、検証が通過するまで停止します。タスク間のコンテキストリセットはバグではなく機能です。それらは以前の仮設が後の作業を汚染するのを防ぎ、差分をレビュー可能な状態に保ちます。
仕様スタックからの制約を適用する
実装エージェントは、要件仕様、設計計画、現在のタスクの説明、およびプロジェクトレベルの制約を読むべきです。制約は、ほとんどのチームがスキップする最も投資回収率の高いセクションです。それらはエージェントに何をすべきでないかを伝えます – 無関係なモジュールのリファクタリングは行わない、この機能の外で公開APIシグネチャを変更しない、計画を更新せずに新しい依存関係を導入しない。
現実が異なる場合、計画を更新する
実装は驚きをもたらします。ライブラリが想定された振る舞いをサポートしていない。移行が予想より時間がかかる。受入基準にエッジケースが欠けている。そのような場合、継続する前に仕様を更新してください。要件または計画を修正し、クイックレビューを経て、修正されたアーティファクトに対して実装を再開します。仕様から沈黙して逸脱するコードは、ドリフトを恒久的にする方法です。
フェーズ5 – 仕様に対して検証する
検証は、SDDがその価値を証明する場所です。それなしでは、仕様は単なる練習です。それがあった場合、仕様はリリースされたコードに対してチェックできる契約となります。
自動化されたチェック
CIでフルテストスイート、リント、型チェックを実行します。実用的なスタートポイントが必要な場合は、GitHub Actionsチートシート)のパターンを使用してパイプラインにこれらを接続します。自動化されたチェックは回帰をキャッチします。しかし、正しく構築された誤った機能はキャッチしません。これが、受入基準のレビューがまだ重要である理由です。
受入基準と手動レビュー
要件仕様からの各受入基準を walkthrough します。それぞれを満たした、失敗した、または理由付けとともに延期したとしてマークします。手動レビューは、テストが flawed な仕様に合わせて書かれていたために見逃したUXの問題、セキュリティのギャップ、誤った振る舞いをキャッチします。
仕様からコードへの差分
最終的な検証ステップは、実装を設計計画と比較します。変更されたファイルは計画が予測したファイルと一致しましたか? コード内のアーキテクチャ決定は記録された決定と一致しましたか? 差分内の予期せぬファイルはシグナルです – 計画が不完全だったか、エージェントが逸脱したかのどちらかです。両方ともマージ前に対応を要します。AI開発における仕様、テスト、コードの同期維持)はこの1回限りの差分レビューを、繰り返し可能なトレーステーブルとCIチェックのセットに変え、ドリフトが誰かが確認を思い出す時だけでなく、すべてのPRでキャッチされるようにします。
| 検証レイヤー | キャッチするもの |
|---|---|
| ユニットおよび統合テスト | 範囲内の回帰と誤ったロジック |
| リントおよび型チェック | スタイルの問題と型エラー |
| 受入基準のwalkthrough | 仕様に従って構築された誤った振る舞い |
| 仕様からコードへの差分 | アーキテクチャのドリフトと範囲の拡大 |
ワークフローにおけるAIエージェントの役割
AIエージェントは各フェーズの加速器であり、レビューの代替ではありません。生産的なパターンは、ドラフト、レビュー、洗練、そして進むことです。エージェントに問題記述から要件仕様のドラフトを作成させ、その後、目標、非目標、受入基準が正しいまで意図を編集します。エージェントに承認された要件から設計計画のドラフトを作成させ、その後、コードが存在する前にアーキテクチャ決定をレビューします。エージェントに1つずつタスクスライスを実装させ、次のタスクが開始される前に各差分を承認します。
エージェントは、特に最初のドラフトとボイラープレートテストの生成に有用です。人間は、特に誤った目標、不安全なアーキテクチャ、微妙な範囲拡大をキャッチするのに有用です。ワークフローは、いずれかの側がスキップされると失敗します – エージェントが仕様なしで実装する場合、または人間がコードに対してそれらを検証することなく仕様を書く場合。
このワークフロー記事はあえてツールに依存しません。ツール固有の実行ガイド(エディタ設定、スラッシュコマンド、エージェント設定)はAI開発ツール)クラスターの下にあります。プロセスの柱は、アーティファクトがベンダーよりも重要であるため、ここでのドキュメントプラクティス下にあります。
仕様駆動型開発を殺す一般的なミステーク
検証前の巨大な仕様。 プロトタイプまたはスパイク(調査用コード)の前に書かれた30ページの要件定義書は、SDDではなくウォーターフォール形式の文書です。次のフェーズの曖昧さを取り除く最小限の仕様を書き、早期に仮定を検証します。すべての機能が5フェーズのループを必要とするわけではありません – 仕様駆動型開発 vs ビーブコーディング)は、いつ軽量の構造で十分かが説明されています。
曖昧な受入基準。 「高速」、「クリーン」、「ユーザーフレンドリー」といった形容詞は受入基準ではありません。それらを測定可能な振る舞いに置き換えます。テストできないものは、AIエージェントを使用する場合特に、信頼して実装できません。
非目標の欠落。 非目標なしでは、エージェントはデフォルトで範囲を拡大します。キャッシュレイヤーを追加し、隣接モジュールをリファクタリングし、要求しなかった依存関係を導入します。非目標は、事前に「ノー」と言う方法です。
設計フェーズにテスト計画がない。 実装後にのみ書かれたテストは、意図されたものではなく、構築されたものを確認する傾向があります。計画は、最初の本番ファイル変更前に、どの受入基準がどのテストタイプに対応するかを名指しすべきです。
フェーズ境界でのレビューをスキップする。 計画前の仕様レビュー。タスク前の計画レビュー。実装前のタスクレビュー。各ゲートは安価です。大きなマージ後のドリフト修正は高価です。
生成されたタスクの爆放任する。 50項目のAI生成タスクリストをスケジュールではなく、最初のドラフトとして扱います。冗長なアイテムをマージし、大きすぎるものを分割し、要件に対応しないタスクを削除します。
SDDは、各フェーズが曖昧さを減少させる場合に機能します。文書を生み出す場合に失敗します。
再利用可能なテンプレート
これらをリポジトリにコピーし、適応してください。仕様を機能ブランチと一緒に保管し、プルリクエストでレビューし、エージェントと人間が同じソースを読むようにバージョン管理に保管します。
要件テンプレート
# Feature -- [name]
## Problem
## Users
## Goals
## Non-goals
## Acceptance criteria
## Open questions
設計テンプレート
# Design -- [feature name]
## Summary
## Affected modules
## Data model changes
## API contracts
## Migrations
## Security
## Observability
## Test strategy
## Risks and mitigations
タスクリストテンプレート
# Tasks -- [feature name]
## Task 1 -- [title]
Depends on:
Files:
Satisfies:
Validate:
Review checkpoint:
## Task 2 -- [title]
...
検証チェックリスト
# Validation -- [feature name]
## Automated
- [ ] All tests pass
- [ ] Lint clean
- [ ] Type check clean
## Acceptance criteria
- [ ] AC-1 --
- [ ] AC-2 --
## Spec-to-code
- [ ] Changed files match plan
- [ ] No undocumented architectural changes
- [ ] Spec updated if implementation differed
結論
仕様駆動型開発は、より多くの文書を書くことではありません。それは、各ステップにレビューゲートを持つことで、仕様化、計画、タスク、実装、検証を通過することです。各フェーズは、前のフェーズよりも次のアクター(人間またはエージェント)にとって推測を少なくすべきです。
小さく始めます。1つの中規模機能でフルワークフローを実行します。アーティファクトをリポジトリ内のMarkdownで保管します。現実が逸脱する場合、仕様を更新します。マージ前に検証します。チェーンが機能する場合、ドリフトが少なくなり、レビュー可能な差分が小さくなり、セッションリセットとチーム手渡りを超えて存続する意図の耐性記録が得られます。
チェーンが文書化になる場合、範囲を削減します – レビューではありません。検証された2ページの仕様は、誰も読まない30ページの仕様よりも優れています。
有用なリンク
- GitHub Spec Kit documentation – 類似する仕様-計画-タスク-実装ループを実装するオープンソースツールキット
- Martin Fowler on Spec-Driven Development tools – Kiro、Spec Kit、Tesslの分析