TL;DR
- AIエージェントが仕様を「無視」するのは、会話ログを Source of Truth にしていることが根本原因
- Spec Driven Development (SDD) は、仕様ファイルを正とすることでこの問題を構造的に解決する
- Document First / File as Anchor / Stateless Interaction の 3 原則を守り、バリデータで強制する
- SDDを導入すると、AIは「忘れる存在」から「再現可能な実行者」に変わる
The Pain: AIとの会話は「揮発」する
AIエージェント(Copilot, Gemini, ChatGPTなど)を使っていて、こんな経験はありませんか?
- 「さっきこう決めたよね?」という指示を忘れて古いコードを復活させる。
- 会話が長くなるにつれて、最初の目的(Why)を見失い、枝葉末節(How)にこだわり始める。
- 翌日再開したら、昨日の文脈が完全にリセットされている。
これはAIの記憶力不足ではなく、「会話(Chat Log)」を仕様の拠り所(Source of Truth)にしていることが根本原因です。
チャットログは本質的に「揮発性」が高い情報源です。トークンウィンドウの上限に達すれば古い文脈は押し出され、セッションが切れれば全てが消えます。人間同士の開発でも口頭の合意だけでは齟齬が生まれるのと同じ構造です。
チャット駆動 vs 仕様駆動:問題構造の比較
| 項目 | チャット駆動開発 | 仕様駆動開発 (SDD) |
|---|---|---|
| 情報の永続性 | セッション依存(揮発) | ファイルに永続化 |
| コンテキスト上限 | トークン制限で溢れる | 必要な仕様だけ参照 |
| 再開コスト | 毎回ゼロから説明 | ファイルを読ませるだけ |
| 品質の再現性 | 会話の質に依存 | 仕様の質に依存(レビュー可能) |
| チーム共有 | ログの転送が困難 | Git管理で自然に共有 |
この問題は個人の使い方の話ではなく、開発アーキテクチャの設計問題です。解決策は、情報の置き場所を「チャット」から「ファイル」に移すことです。
The Solution: Spec Driven Development (SDD) の3原則
人間同士の開発と同様、AIとの開発でも「チャット」ではなく「仕様書」を正(SSoT)とする必要があります。これを Spec Driven Development (SDD) と呼びます。SDDの全体像はハブ記事で体系的にまとめています。
原則1: Document First
チャットで指示する前に、まず仕様ファイルを書く(または書かせる)。
「まず書く」と言っても、最初から完璧な仕様書を作る必要はありません。受入条件(Acceptance Criteria)を先に定義し、そこから逆算して仕様を肉付けしていくアプローチが効果的です。この手法については受入条件を先に書くTDD実践で詳しく解説しています。
原則2: File as Anchor
エージェントには常に仕様ファイルを読ませ、「このファイルに従え」と指示する。
仕様ファイルは「過去(Requirements)」「現在(Tasks)」「未来(Design)」の3層に分けて管理すると、更新頻度と安定度に応じた運用が可能になります。具体的なディレクトリ構造はRequirements/Design/Tasksによる時間軸管理術を参照してください。
原則3: Stateless Interaction
チャットログが消えても、仕様ファイルさえあれば作業を再開できるようにする。
この原則が守られていれば、エージェントのセッションが切れても、別のエージェントに切り替えても、同じ仕様を渡すだけで作業を引き継げます。自律エージェントループの設計でも、この「ステートレス性」が自律運用の前提条件として語られています。
The Implementation: バリデータによる強制
単に「仕様書を読んでね」と言うだけでは不十分です。CI/CDやプレコミットフックで、仕様書の整合性を機械的にチェックします。
import sys
from pathlib import Path
import yaml
REQUIRED_FIELDS = ["title", "slug", "date", "description"]
def validate_frontmatter(file_path: str) -> None:
text = Path(file_path).read_text(encoding="utf-8")
if not text.startswith("---"):
raise ValueError(f"{file_path}: missing frontmatter block")
# 最初の '---' ブロックを YAML として解釈する
_, frontmatter_text, *_ = text.split("---", 2)
data = yaml.safe_load(frontmatter_text) or {}
missing = [field for field in REQUIRED_FIELDS if field not in data]
if missing:
raise ValueError(
f"{file_path}: missing required fields: {', '.join(missing)}"
)
if __name__ == "__main__":
for path in sys.argv[1:]:
validate_frontmatter(path)
このように、コードだけでなくドキュメント自体もLintの対象にすることで、AIは「仕様書を無視すると怒られる(テストが通らない)」ことを学習します。
バリデータ導入のポイント
バリデータは「仕様の存在チェック」だけでなく、仕様の品質チェックにまで拡張できます。例えば:
- 必須フィールドの存在確認(上記コード例)
- 受入条件の記述ルール強制(「Given/When/Then」形式の検証)
- 仕様間の整合性チェック(Design が参照する Requirements が存在するか)
このような仕様品質の管理体制を組織レベルで設計するアプローチは、AI時代の仕様品質マネジメントで解説しています。
また、AI生成コードが仕様通りに動くことを担保するテスト戦略はAI生成コードのテスト戦略で体系的にまとめています。
The Takeaway: AIを管理職にするな
「AIに要件定義から全部やらせよう」とすると失敗します。AIは優秀な実務者(Executor)ですが、長期記憶と一貫性を保持する管理者(Manager)としては未熟だからです。
SDDは、人間が「仕様(Spec)」という形で管理権限を握り続け、AIをその枠内で最大限に働かせるための統制フレームワークです。
今日からできる3ステップ
- 仕様テンプレートを1つ作る --
requirements.mdのテンプレートをリポジトリに置く - エージェントへの指示に「この仕様に従え」を追加する -- プロンプトの冒頭で仕様ファイルを読み込ませる
- バリデータを1つ追加する -- 上記Pythonスクリプトをpre-commitフックに設定する
小さく始めて、効果を実感したらSDDシリーズ全体を通して体系的に導入を進めましょう。
