Spec-Driven Development Loop (SDDL)
オープンソース: https://github.com/xt-mahh/sddl (2026-08-06, MIT License) 完全な方法論+チェッカースクリプト+サンプルプロジェクトはGitHubリポジトリを参照。
概要
SDDLはAIプログラミングを「対話駆動」から「仕様駆動」へとアップグレードします。中核となる約束: 何をするかを最初に明確に定義してからコードを書く — 構造化されたSpecを唯一の真実源とし、二重ループのクローズドループで品質と監査可能性を保証します。
形成ループ(「何をするか」に答える) 派生ループ(「どう正しくするか」に答える)
要件 ──▶ インタビュー ──▶ Spec草稿 ──▶ 凍結Spec ──▶ tests/code/docs ──▶ 収束
└─▶ SQC品質チェック ──┘ └─▶ C1-C4一貫性チェック ─┘
└─▶ 決定点確認 ──┘
なぜSDDLを使うのか: 対話型プログラミングの痛点 — コンテキストのずれ(50ラウンドの会話後に3ラウンド目の合意を忘れる)、複数アーティファクトの非同期(コードは変更されたがテスト/ドキュメントが追従しない)、主観的な受け入れ(「仕様に合致している」ではなく「なんとなく正しい」)。SDDLは安定して全文ロード可能なSpec + 階層化された一貫性チェックでこれら3つを解決します。
使用タイミング
トリガー:
- ユーザーが新規プロジェクト開発、コア機能の作成、システムアーキテクチャの設計を開始する場合
- ユーザーが「まず計画」、「まず設計」、「まず仕様を書く」、「この機能をどう実装するか」と言った場合
- 複数のアーティファクト(コード+テスト+ドキュメント)を同期的に生成する必要があるタスク
- プロジェクトインターフェース数 ≥ 5、またはMustレベルの受け入れ基準 ≥ 5、想定ライフサイクル > 2週間
不適用(直接コードを書き、このスキルは使用しないでください):
- 一回限りのスクリプト / プロトタイプ / POC / 探索的研究コード
- 単一ファイルの小さなツール(インターフェース数 < 5、複数アーティファクトの要件なし)
- ユーザーが明示的に「直接書いて」「すぐに作って」と言った場合
段階的コマンド(本スキルの中核的な対話方法):
| コマンド | フェーズ | 何をするか | 成果物 |
|---|---|---|---|
/sddl:init | 初期化 | ディレクトリ構造を作成、既存コード/要件を読み込む | sddl/ スケルトン + state.yaml |
/sddl:interview | 形成 | 階層化要件インタビュー(L0-L2必須回答) | 要件記述 |
/sddl:spec | 形成 | L1-L5 spec草稿 + 決定点マーキングを生成 | specs/<domain>/spec.yaml |
/sddl:confirm | 形成 | 決定点サマリー clarify 確認 | decisions/<domain>-confirmation.yaml |
/sddl:freeze | 形成 | SQCチェック + 凍結 | spec_status: frozen |
/sddl:derive | 派生 | specから tests/code/docs を派生 | src/ tests/ docs/ |
/sddl:verify | 派生 | C1-C4一貫性チェック + 収束判定 | checks/*.json + 収束/ルーティング |
/sddl:archive | アーカイブ | 変更履歴のアーカイブ、specのマージ | specs/ 更新 + CHANGELOG |
中核原則
- Specは神託だが、異議を唱えられる: 派生中に発見されたspecの欠陥 → 解凍 → 形成ループに戻り修正 → 再凍結(完全な品質ゲートを通過し、迂回しない)
- 決定性を優先: 静的解析/schema/テスト実行で解決できることは、LLMに推測させない
- 収束は工学的システム: ハード条件ゲート + ソフト条件コンセンサス率 + 予算制約 + 人間による最終判断
- 決定点を黙らせない: 曖昧な箇所はAIがデフォルト値を設定 + 決定点としてマークし、ユーザー確認後に凍結
- 進捗はディレクトリ: フェーズ完了 = ファイル存在(Convention over Config)、中断後の復旧は無料
ディレクトリが状態を表す(Convention over Config)
状態ファイルを見なくても、ディレクトリを見れば進捗がわかる。これが本スキルの進捗可視性メカニズムです(git commit をチェックポイントとして併用)。
<project>/
├── sddl/
│ ├── specs/ # 存在 = インタビュー完了、spec生成済み
│ │ └── <domain>/spec.yaml # status: frozen = 凍結完了
│ ├── changes/ # 変更提案(インクリメンタル開発、並行作業可能)
│ ├── decisions/ # 決定点確認記録
│ │ └── <domain>-confirmation.yaml
│ ├── checks/ # チェックレポートアーカイブ(機械可読JSON)
│ │ ├── sqc-<domain>-v1.json
│ │ └── c1-c4-<domain>-v1.json
│ └── state.yaml # 唯一のメタデータ:フェーズポインタ + 予算 + 最新チェック
├── src/ # 派生ループ後に出現
├── tests/ # 派生ループ後に出現
├── docs/ # 派生ループ後に出現(current/planned パーティションを含む)
└── (各フェーズ完了時にgit commit)
state.yaml は最小限(進捗詳細ではなくポインタのみ保存):
spec_status: frozen # interviewing | drafting | reviewing | frozen | evolved
current_phase: derivation # formation | derivation | complete
budget: { formation: 40%, implementation: 12%, revision: 100% }
last_check: { type: sqc, spec: auth-v0.1.0, result: pass, at: 2026-08-06T16:00 }
復旧ルール: スキル再読み込み時にディレクトリをスキャン — specs/ なし = interviewから開始;specs/ ありだが decisions/ なし = confirmから開始;decisions/ ありだが specが frozen でない = freezeから開始;src/ ありだが checks/ なし = deriveから開始;checks/ あり = verifyから開始。
フェーズ完了 = git commit(E支援):各コマンド成功後にコミット(feat(sddl): interview complete)、遡及可能を保証。
二重ループフロー編成
形成ループ(正しいことをする)— 5つのコマンド
/sddl:interview → /sddl:spec → /sddl:confirm → /sddl:freeze
│ │ │ │
└─ 改訂 ──────┴──────┴──────┘
(SQC不合格 / ユーザーが決定点を変更 → 前のステップに戻る、最大5ラウンド)
| コマンド | 主要アクション | チェックポイント |
|---|---|---|
| interview | 階層的質問L0-L2(最大10問必須回答)、要件記述を生成 | 要件記述が完全 |
| spec | L1-L5 spec + 決定点マーキングを生成(曖昧な箇所はDPとして登録) | SQC-defスケルトンが通過 |
| confirm | 決定点サマリー → clarifyで項目ごとに確認(カスタム入力を含む) | 決定点にpendingなし |
| freeze | SQC全チェック + 確認記録への署名 | SQCにblockerなし + frozen |
派生ループ(正しくやる)— 3つのコマンド
/sddl:derive → /sddl:verify → (収束) → 完了
│ │
└─ ルーティング ─┘
(違反 → code/tests/docsを再派生 または 解凍して形成ループに戻る)
| コマンド | 主要アクション | チェックポイント |
|---|---|---|
| derive | specから tests/code/docs を派生 | アーティファクトが実行可能 |
| verify | C1-C4階層チェック + 収束判定 | ハードゲート + ソフトコンセンサス + mustカバレッジ |
| archive | 変更履歴のアーカイブ、specのマージ | CHANGELOG + spec更新 |
チェッカースクリプト(scripts/)— 決定論的エビデンス、意味判断ではない
スクリプトは決定論的エビデンス(型チェック/テスト実行/シンボルテーブル/YAML)のみを担当し、意味論的レビューはエージェントのLLM能力が実行します:
# SQC決定論的チェック(形成ループゲート)— スクリプトは事実を提供
python3 scripts/check_sqc.py sddl/specs/<domain>/spec.yaml --verbose
# C1-C4決定論的チェック(派生ループゲート)— スクリプトは事実を提供
python3 scripts/check_c1_c4.py . --verbose
# 状態復旧(中断後)— ディレクトリをスキャンして現在の進捗 + 次のコマンドを出力
python3 scripts/sddl_status.py .
- 終了コード:0 = pass/converged、1 = fail(CIに組み込み可能)
--jsonで機械可読エビデンスを出力(LLMレビューで参照)
分担原則(重要):
| 層 | 担当 |
|---|---|
| 決定論的エビデンス(ハード条件):スキーマの妥当性/インターフェースの存在/テスト通過/シンボルテーブル | スクリプト |
| 意味論的レビュー(ソフト条件):動作カバレッジ/THENのアサーション可能性/テストの真のカバレッジ/ドキュメントの正確性 | エージェントのLLM(references/llm-review.md参照) |
意味判断にスクリプトのヒューリスティックを使わないでください — 文字列マッチングは偽陰性が爆発します(T1実測C1-sem 0.48)。スクリプトはエビデンス収集器、エージェントが審判です。
どのReferenceをいつ読むか
必要に応じてロードし、一度にすべて読まない(段階的開示):
| シナリオ | 読むもの |
|---|---|
| interviewの実行 | references/formation-loop.md(フェーズ1) |
| specの生成 | references/spec-schema.md + templates/spec-template.yaml |
| SQCチェック | references/sqc-checklist.md(defはスクリプト、semはLLM) |
| 決定点確認 | templates/decision-summary.md |
| アーティファクトの派生 | references/derivation-loop.md(フェーズ1-2) |
| C1-C4チェック | references/checker-matrix.md(defはスクリプト、semはLLM) |
| 意味論的レビュー操作 | references/llm-review.md(中核:LLMがレビューをどう行うか) |
| ルーティング/書き戻し/予算 | references/derivation-loop.md(フェーズ3-5) |
| 変更提案 | references/formation-loop.md(変更管理) |
予算とダウングレード
- 三つの予算:formation(2Mトークン / 5ラウンド)/ implementation(15M / 4 sessions)/ revision(5M、L2は10%消費、L3は25%消費、初回L3は無料)
- 予算はstate.yamlに記録され、各コマンドで更新
- 予算枯渇 → 人手駆動に切り替え、自動ダウングレードはしない(spec品質は基盤)
- ダウングレードパス:D1 意味論的ダウングレード → D2 should/couldをリスクリストに移動 → D3 バリアント縮小 → D4 spec分割 → D5 ベストエフォート納品
体験規範(重要)
- 段階的コマンド: 決して1回の返信で二重ループ全体を実行しない — 各コマンドは独立した対話ユニットであり、間にチェックポイントがある
- 決定点はclarify、カスタム入力は明示的に可視: 各決定点に1つのclarify、影響説明付き;choicesのビジネスオプションは≤3個、4番目は固定で「カスタム入力(Other)」(実測によりclarifyに自動Otherなし、choices上限4、明示的にプレースホルダが必要);質問テキストで「他の値はカスタム入力を選択してください」と促す;ユーザーカスタム値はキャプチャプロトコルで記録(value+reason → specに同期 → 確認記録にmodifiedとマーク);オープンな決定点はchoicesなしのclarifyを直接使用
- 進捗可視: 各コマンドの開始/終了時に現在のフェーズ + 次のステップを報告
- 状態書き込み: 各コマンド終了時にstate.yamlを書き込み + git commit
- チェックレポート: 各チェック(SQC/C1-C4)を
checks/*.jsonに書き込み、人間可読なサマリー + 機械可読な詳細を報告
よくある落とし穴
- 形成ループをスキップして直接派生 — Specが凍結されていないのにコードを書く = 対話型プログラミングに逆戻り。
/sddl:freezeはハードな境界、未凍結では派生不可。 - 決定点を黙って決定 — 曖昧な箇所をDPとしてマークせずにデフォルト値で書く = ユーザーの意図が歪む。「ユーザーに代わって選択」は必ずDPとして登録。
- チェッカーの自己検証ループ — AIが貼ったラベルを信頼する。C1-defは構造逆推論(テストASTの解析)を行う必要があり、ラベルを信頼しない。
- 意味論的チェックの絶対スコア — LLMが0-100点をつけるのは信頼できない。Checklistの二分法 + 投票コンセンサス率(客観的な集計)を使用。
- 書き戻しで品質ゲートをバイパス — specの問題を直接修正 = 自己緩和。解凍 → 形成ループに戻る → 再凍結。
- 状態ファイルの肥大化 — すべての進捗をstate.yamlに書き込む = また「ドキュメントの嘘」に戻る。state.yamlはポインタのみ、詳細はファイル自体に。
- 予算の未記録 — state.yamlの予算を更新しない = コスト管理不能。各コマンド終了時に更新。
- 意味論的チェックに粗い文字列マッチング — T1実測:キーワードマッチングでC1-semが0.48(偽陰性爆発)。優先的にChecklist LLM投票を使用;ヒューリスティックはフォールバックのみとし、かつ意味論的でなければならない(ASTからのアサーション抽出 + 構造化キーワード)、初回結果は信頼できず、人手による再確認が必要。
- テスト間の状態共有漏れ — T1実測:メモリストアがテスト間で共有され、アサーション失敗を引き起こす。派生時には必ず隔離フィクスチャ(autuseリセット)を追加;テストアサーションは公開インターフェースを介して行い、内部の
_storeに直接アクセスしない。 - 純粋なクエリ関数に副作用 — T1実測:
detectDiscrepancyが内部でstatusを変更し、spec B006(draftを維持すべき)に違反。純粋なクエリインターフェース(レポート/クエリを返す)は状態を変更してはならず、C2-semでチェックする。
検証チェックリスト
-
sddl/ディレクトリ構造が正しい(specs/changes/decisions/checks/state.yaml) - spec.yamlがSQC-defを通過(スキーマが妥当/参照が完全/アサーション可能性/決定点カバレッジ)
- 決定点がすべて confirmed/modified/delegated(pendingなし)
- 確認記録に署名済み(overall: approved)
- spec_status: frozen になってから派生に入る
- C1-defで構造逆推論を実施(ラベルを信頼していない)
- ハード条件(C1-def/C2-def/C3/C4b-def)がすべて合格
- ソフト条件のコンセンサス率が基準を満たしている(c1_sem≥0.95 c2_sem≥0.95 c4a≥0.90 c4b_sem≥0.90)
- mustレベルの受け入れ基準を100%カバー
- state.yamlの予算が更新済み
- フェーズ完了のgit commitが実行済み
ワンショットレシピ
ゼロから新規プロジェクト
/sddl:init → /sddl:interview → /sddl:spec → /sddl:confirm → /sddl:freeze
→ /sddl:derive → /sddl:verify → /sddl:archive
既存コードへのspecのバックフィル(リファクタリングプロジェクト)
/sddl:init(既存コードを読み込む)→ /sddl:spec(現状を逆抽出 + 決定点をマーク)
→ /sddl:confirm → /sddl:freeze → /sddl:verify(spec↔codeの一貫性を検証)
インクリメンタル機能開発(specが既に凍結済み)
/sddl:init → changes/<name>/ 提案を作成 → /sddl:confirm(影響を受ける決定点)
→ /sddl:freeze → /sddl:derive → /sddl:verify → /sddl:archive
関連スキル
writing-plans:実装計画の作成(SDDLのchanges/tasks.mdで使用可)test-driven-development:TDDはSDDLの検証手段(C3テスト実行)hermes-agent-skill-authoring:本スキル自身の作成規範