SPEC.mdの書き方 ── AIが迷わない仕様の作り方
この章は本書の核心だ。「どんなSPEC.mdを書けばAIが意図通りに実装するか」を具体的に解説する。
SPEC.mdの6要素
効果的なSPEC.mdは、以下の6要素で構成される。
1. Outcomes ── 何を達成したいか(ゴール)
2. Scope ── 何を含み、何を含まないか(境界)
3. Constraints ── 制約条件(技術・ビジネス)
4. Prior Decisions ── 既存の決定事項(アーキテクチャ前提)
5. Tasks ── 実装タスクのリスト
6. Verification ── 完了条件・テスト基準
これらを順番に埋めていくと、AIが迷わず実装できる仕様が完成する。
実践:ウィッシュリスト機能のSPEC.md
ECサイトのウィッシュリスト機能を例に、SPEC.mdを一から書いてみよう。
❌ 悪い例(Vibe Codingレベルの指示)
ウィッシュリスト機能を作ってください。
ユーザーが商品を保存できて、後で見られるようにする。
問題:
- どんなデータを保存するのか不明
- 認証は?共有機能は?制限数は?
- 既存のアーキテクチャとどう統合するのか不明
- テスト基準が存在しない
AIはこれを受け取ると「自分なりに最適な実装」を生成する。チームの方針と合わない可能性が高い。
✅ 良い例(SPEC.mdの6要素)
# Feature: ウィッシュリスト管理
## Outcomes(ゴール)
- ログイン済みユーザーが商品をウィッシュリストに追加・削除できる
- ウィッシュリストを公開URLで第三者に共有できる
- 最大100件まで保存可能
## Scope
### In Scope(含む)
- 単一ユーザーのウィッシュリスト(1ユーザー = 1リスト)
- 商品の追加・削除
- Public/Privateの切り替え
- 共有用トークンの生成(UUIDベース)
- 共有URLからの閲覧(認証不要)
### Out of Scope(含まない、明確に除外)
- 複数リストの管理(次フェーズ以降)
- 価格変動の通知アラート(別チームが担当)
- SNSシェア機能(MVP外)
- ゲストユーザーのウィッシュリスト
## Constraints(制約)
- レスポンスタイム: GET /api/wishlist は100ms以内(p95)
- ウィッシュリストの上限: 100件(超えたら409エラー)
- 共有トークン: UUID v4、有効期限なし
- 認証: 既存のJWTミドルウェア(src/middleware/auth.ts)を使用すること
- バリデーション: ZodでAPIエントリポイントを必ず検証
## Prior Decisions(既存の決定事項)
- DB: PostgreSQL + Prisma ORM(Supabase上)
- エラーフォーマット: `{ error: { code: string, message: string } }`
- 認証方式: JWT(AuthorizationヘッダーのBearerトークン)
- 既存の商品テーブル: `products`(id, name, price, imageUrl)
## Tasks(実装タスク)
### バックエンド
1. Prismaスキーマに `wishlists` テーブル追加(userId FK、shareToken unique)
2. Prismaスキーマに `wishlist_items` テーブル追加(wishlistId FK、productId FK)
3. `POST /api/wishlist/items` — 商品追加
4. `DELETE /api/wishlist/items/:productId` — 商品削除
5. `GET /api/wishlist` — 自分のウィッシュリスト取得(認証必要)
6. `GET /api/wishlist/share/:token` — 公開ウィッシュリスト取得(認証不要)
7. `PUT /api/wishlist/visibility` — Public/Private切り替え
### テスト
8. `tests/wishlist.test.ts` — 上記エンドポイントの統合テスト
9. `tests/wishlist.unit.test.ts` — サービス層のユニットテスト
## Verification(完了条件)
- [ ] 全エンドポイントの正常系テストがPASS
- [ ] 上限100件を超えた時に409エラーが返る
- [ ] 未認証アクセスで401エラーが返る(共有URLエンドポイントを除く)
- [ ] `GET /api/wishlist` のレスポンスタイムが100ms以内(DBに50件の場合)
- [ ] 共有URLから認証なしで商品リストを閲覧できる
- [ ] カバレッジ: ビジネスロジック層 80%以上
この仕様を渡せば、AIは「何を作るか」「何を作らないか」「既存コードとどう統合するか」を全て理解した状態で実装できる。
各要素の書き方詳解
Outcomes(ゴール)
「何が達成されれば成功か」をユーザー視点で書く。技術的な実装手段は書かない。
✅ 良い書き方:
「ユーザーが商品を保存し、後から見返せる」
❌ 悪い書き方:
「WishlistテーブルにproductIdとuserIdを保存する」
(実装の詳細はTasksに書く)
Scope(スコープ)
Out of Scopeの明示が最も重要だ。 AIは「この仕様に書いてないことも実装したほうがいいかも」と判断することがある。除外リストを明確にすることでスコープクリープを防ぐ。
✅ Out of Scopeの良い書き方:
「複数リストの管理(次フェーズ以降)」
「価格アラート(別チームが担当)」
「SNSシェア(MVP外、要件確定まで実装不可)」
❌ 悪い書き方:
「高度な機能は後で」(曖昧すぎる)
Constraints(制約)
数値を含めた制約を書く。「速くする」ではなく「100ms以内」。
✅ 制約の良い書き方:
「レスポンスタイム: 100ms以内(p95)」
「上限: ユーザーあたり100件(超えたら409 Conflict)」
「認証: src/middleware/auth.tsの既存実装を使用」
❌ 悪い書き方:
「パフォーマンスに注意」(数値がない)
「適切に認証する」(何を使うかが不明)
Prior Decisions(既存の決定事項)
プロジェクトのアーキテクチャ的な前提を書く。これがないとAIは「自分で決める」モードに入る。
Prior Decisionsに書くべきこと:
- 使うDBとORM
- エラーレスポンスのフォーマット
- 認証方式と使うファイルパス
- 既存テーブルのスキーマ(関連するもの)
- コーディング規約の中で特に重要なもの
Tasks(タスク)
実装の粒度をFile単位で書くのが目安だ。「認証を実装する」は大きすぎる。「src/middleware/auth.tsにJWT検証ロジックを追加する」が適切。
✅ タスクの良い粒度:
「POST /api/wishlist/items エンドポイントを追加」
「Prismaスキーマに wishlists テーブルを追加」
❌ タスクの悪い粒度:
「バックエンドを実装する」(大きすぎる)
「wishlistService.tsのaddItemメソッドの引数を検証」(小さすぎる)
Verification(完了条件)
チェックボックス形式で書き、すべてにテスト可能な基準を設ける。「動作を確認する」ではなく「テストがPASS」が理想。
✅ 良い完了条件:
- [ ] 統合テスト: 全エンドポイントの正常系・異常系がPASS
- [ ] パフォーマンス: 100件のデータで100ms以内
- [ ] セキュリティ: 未認証リクエストで401が返る
❌ 悪い完了条件:
- [ ] 手動でUIを確認する
- [ ] バグがないこと(測定不可能)
SPEC.mdの粒度感
どのくらいの機能を1つのSPEC.mdにまとめるか。
| 粒度 | 規模 | 例 |
|---|---|---|
| Epic SPEC | 2〜4週間の機能群 | 「ユーザー認証システム全体」 |
| Feature SPEC(推奨) | 3〜5日の機能 | 「メール/パスワードログイン」 |
| Task SPEC | 1〜2日の作業 | 「パスワードリセットメール送信」 |
Feature SPECが最もバランスがよい。 それより細かくすると仕様が多すぎてAIが柔軟性を失い、大きすぎると仕様が曖昧になる。
SPEC.mdテンプレート
コピーして使えるテンプレートを用意した。
# Feature: [機能名]
## Outcomes
- [ユーザーが何を達成できるか]
- [ユーザーが何を達成できるか]
## Scope
### In Scope
- [含む機能1]
- [含む機能2]
### Out of Scope
- [含まない機能1](理由: [なぜ除外するか])
- [含まない機能2](理由: [なぜ除外するか])
## Constraints
- [制約1(数値を含む)]
- [制約2]
- [使用する既存モジュール・ファイルパス]
## Prior Decisions
- [アーキテクチャ上の決定1]
- [使用するDB・ORM・ライブラリ]
- [エラーフォーマット等の規約]
## Tasks
### [カテゴリ1]
1. [具体的なタスク(ファイル名を含む)]
2. [具体的なタスク]
### [カテゴリ2]
3. [具体的なタスク]
## Verification
- [ ] [テスト可能な完了条件1]
- [ ] [テスト可能な完了条件2]
- [ ] [パフォーマンス基準(数値)]
- [ ] [カバレッジ目標]
次の章では、このSPEC.mdを使った実際のワークフローを手を動かしながら追っていく。