【アドベントカレンダー2025】GitHub CopilotとSpec Kitを使ってSDDの世界を覗き見する

はじめに

こんにちは!ぐるなびでバックエンドエンジニアをしている開発部の寺井です。

十数年PHPを主戦場にしてきましたが、最近Go言語を使ってぐるなびアグリサービスの開発に携わっています。

クリーンアーキテクチャも初めて理解しようとしており……難しい。

この記事では、GitHubが提唱する 「Spec-Driven Development(仕様駆動開発 / SDD)」 と、その実践ツール 「GitHub Spec Kit(speckit)」 を紹介します。仕様と設計原則を明文化し、それを中心に開発を進めることで、AIとの協働でも一貫したアーキテクチャを維持できるようになります。

目次

GitHub Copilotで開発が変わった。でも、何かが足りない。

GitHub Copilotの Agent Mode が登場し、実装をAIに任せられる時代になりました。しかし、こんな壁にぶつかっていませんか?

  • ユースケースにビジネスロジックが漏れ出す
    ドメインモデルに書くべき処理をユースケース層で実装されてやり直しを指示

  • 毎回同じ指示を繰り返す
    「ドメイン層はインフラに依存しないで」と何度も説明、そのうちAIに対して口調が荒くなる

  • チームで使うと出力がバラバラ
    同じ機能でもエンジニアごとに構造が違う(昨日指示したのとも違うぞ!?)

原因は 「仕様が曖昧なままコードを生成している」 ことです。

仕様駆動開発(SDD)と GitHub Spec Kit

「Spec-Driven Development(仕様駆動開発 / SDD)」 は、GitHubが提唱する開発アプローチです。「仕様を最初に明確にし、それを中心に開発を進める」ことで、従来の「コードが真実」を逆転させ、「仕様が真実、コードはその表現」 という Power Inversion を実現します。

AI時代にSDDが重要な理由:

  • AIは曖昧な指示が苦手
    構造化された仕様があれば出力精度が向上

  • 手戻りが減る
    仕様を先に固めれば「これじゃない」が減る

  • ドキュメントと実装の同期
    仕様を起点にすれば常に最新

GitHub Spec Kit(speckit) は、このSDDを実践するツールです:

  • 質問→仕様→計画→タスク→実装 の段階的ワークフロー

  • Constitution(憲章) による一貫したアーキテクチャ管理

  • テンプレート によるAIの暴走防止

1. 仕様駆動開発(SDD)って?(TDD/BDDと何が違うの?)

アジャイル開発の文脈で「テスト駆動開発(TDD)」や「ビヘイビア駆動開発(BDD)」は定番になりました。

ただ、CopilotのAgent Modeで開発していると、

  • テスト設計やシナリオを指示して
  • テストを生成して
  • 実装を生成して

……という“人間が主導するTDD/BDDの手触り”を、そのまま移植するのが難しい場面があります。

AIの活用が進むほど、

  • 実装イメージをある程度持って「仕様書レベルの指示」を出して
  • コーディングを任せてスピードを出す

という状況が増えがちです。

そこで出てくる課題が、冒頭で挙げた 「同じ指示の繰り返し」「指示の履歴が残らない」 です。

SDDは"外側のループ"を回す

SDDは仕様(受入条件)を文章で固め、矛盾・抜けをチェックしてから計画→タスク→実装と進む仕様を中心にした外側のループです。TDDは実装フェーズの内側のループ(Red→Green→Refactor)で品質を積み上げます。

ウォーターフォールとの違い:SDDの仕様書は「AIに読ませるコンテキスト」で変更前提。[NEEDS CLARIFICATION]で不明点を残しながら段階的に明確化するアジャイルなアプローチです。

  • SDDで「何を・なぜ」を合意(AIへのコンテキスト提供)
  • BDDで「受入条件」を読みやすく書く(必要なら)
  • TDDで「どう作るか」を安全に進める

speckitの流れ:従来開発との違い

speckitは、質問(clarify)→仕様(specify)→計画(plan)→タスク(tasks)→実装(implement) という順序で段階的に進めます。各ステップで成果物(spec.md、plan.md、tasks.md等)が生成され、意思決定の履歴が残ります。

SDDのキモ:仕様が真実、コードは表現

SDDでは、「仕様はコードの付属物ではなく、コードを生み出す中心」です。

  • 従来:コードが真実(結果として仕様が古くなる)
  • SDD:仕様が真実、コードは"仕様の表現"(ズレたら仕様を直して再生成)

半年後の改修でも、spec.md を更新して /speckit.plan/speckit.implement で完了。AIが書いたコードを読み解く必要がありません。

テンプレがAIの暴走を抑える

spec.md のルール: - ○ WHAT(何を)・WHY(なぜ)だけ - × HOW(どう作るか)は書かない - ? 不明点は [NEEDS CLARIFICATION] で残す

Phase -1 Gates(実装計画の事前チェック)

  1. Simplicity Gate - プロジェクト数は3つ以内?未来の拡張性を入れていない?

  2. Anti-Abstraction Gate - フレームワークを直接使用?独自抽象レイヤーを作っていない?

  3. Integration-First Gate - API仕様を先に定義している?

ゲートを通らない場合は plan.md に理由を明記して例外申請します。

2. 導入:GitHub Spec Kitの導入

前提:Python 3.11+ と uv

Spec Kit自体はPython製のCLIツールですが、生成されるのはMarkdownファイルです。つまり、プロジェクトの使用言語(Go/PHP/TypeScriptなど)には一切依存しません。Python環境はSpec Kitの実行にのみ必要で、あなたのGoプロジェクトがPythonに汚染されることはありません。

また、uv を使うことで、システムのPython環境を汚さず、Spec Kitを独立した環境で実行できます。

# uv のインストール(未導入なら)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Spec Kit CLI のインストール(uv が仮想環境を自動管理)
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git --python python3.13 --native-tls

# 既存プロジェクトへ初期化(例)
specify init --here --ai copilot --force

※既存プロジェクトに --here で入れる場合、README.md.gitignore 等が競合・上書きされる可能性があるので、事前コミット推奨です(--force は特に注意)。

初期化すると、主に以下が入ってきます。

  • .github/agents/:Copilotのスラッシュコマンド(/speckit.plan など)の“台本”
  • .github/prompts/:agentから参照する文面テンプレ
  • .specify/:憲章(constitution.md)やテンプレ、スクリプト

constitution.md:AIが判断に迷ったときの「意思決定基準」

.specify/memory/constitution.md は、AIに対する自動コードレビュー(Lint)のようなものです。人間がコードレビューで指摘するような「その抽象化、本当に要る?」「これ、プロジェクト増やしすぎじゃない?」という視点を、AIが実装計画を作る段階で自問自答させます。

具体例:constitution.md に書くこと

# このプロジェクトの原則

## 技術スタック
- バックエンド: Go 1.xx系など使用しているバージョンを記載
- データベース: PostgreSQL
- テスト: 標準 testing パッケージ 

## アーキテクチャ原則
- クリーンアーキテクチャを採用
- ドメイン層は外部依存を持たない(インターフェースで依存逆転)
- ユースケース層がドメイン層を呼び出す(逆は禁止)

## コーディング規約
- エラーは必ず errors.Is/As でラップするようにする
- 構造体のフィールドはすべてタグ付き(`json:", `db:"`- テストカバレッジは80%以上

これがConstitutional Gatesとして機能します。/speckit.plan で計画を作る際、AIが以下を自動チェック:

  1. Simplicity Gate - 将来の拡張性は本当に必要?YAGNI原則の遵守

  2. Anti-Abstraction Gate - 過剰な抽象化を避け、標準ライブラリを優先

  3. Integration-First Gate - API仕様を実装前に定義

ゲートを通らない場合は plan.md に理由を明記して例外申請します。これにより「なぜ複雑にしたか」の意思決定が記録に残ります。

3. Agent設定との使い分け(instructions vs agents vs prompts)

ここが「SDDが再現性に効く」ポイントです。

チーム共通のベース指示 .github/copilot-instructions.md

  • 用途:プロジェクト全体で常に守るべきルール
  • 内容:コーディング規約、アーキテクチャ、Git操作ルール
  • 適用:リポジトリ内のすべてのCopilot操作

agents(.github/agents/*.agent.md

Copilotの“左下に出る” /speckit.plan みたいなスラッシュコマンド本体です。

handoffの仕組み:次のステップへの誘導

各agentファイルに handoff設定 を追加することで、次に実行すべきagentへの「バトンタッチ」を定義できます。

handoffを実装した場合の体験(VS Code上)

  1. /speckit.specify で仕様書を作成
  2. Copilotが「仕様書が完成しました。次は実装計画を作りますか?」と クリック可能なボタン を表示
  3. そのボタンをクリックすると /speckit.plan が自動実行
  4. 計画が完成すると、また「次は /speckit.tasks でタスクに分解しますか?」とボタンが出る

agent.mdファイルにこのようなhandoffsを作成しておくと画像のようなボタンが出てきます

handoffs: 
  - label: Phase 1実装開始(Domain層)
    agent: speckit.implement
    prompt: 作成された実装計画書に基づき、Phase 1(Domain層:モデル定義・Repositoryインターフェース)の実装を開始してください。実装完了後、テストを実行して結果を確認してください。

推奨されるhandoffの流れ

  • speckit.clarify.agent.md/speckit.specify を提案
  • speckit.specify.agent.md/speckit.plan を提案
  • speckit.plan.agent.md/speckit.tasks を提案
  • speckit.tasks.agent.md/speckit.implement を提案

handoff機能を実装することで、開発者は「次に何をすべきか」を迷わずに段階的なワークフローを進められます。各段階の成果物(spec.md、plan.md、tasks.md)が明確に残るため、意思決定の履歴が追跡可能になります。

※handoffの実装方法については、GitHub Spec Kitの公式ドキュメントを参照してください。

Spec Kitでは、以下のようなagentファイルが用意されています:

.github/
└── agents/
    ├── speckit.clarify.agent.md
    ├── speckit.specify.agent.md
    ├── speckit.plan.agent.md
    ├── speckit.tasks.agent.md
    ├── speckit.implement.agent.md
    ├── speckit.analyze.agent.md
    └── speckit.checklist.agent.md

デフォルトだと

mdファイル名通りに出力されますが

---
name: 仕様書作成
description: 要望に基づいて詳細な仕様書を作成します。
---

このようにわかりやすい名前に変更することも可能です

prompts(.github/prompts/*.prompt.md

agentの中から参照される/使われることがある文面テンプレ(短いことが多い)です。

  • 「ユーザーにどう聞くか」
  • 「どういう形式で出力させるか」

を揃える場所で、ここを整えると“言い回し”や“出力フォーマット”がチームで揃いやすくなります。

speckit の agents / prompts と合わせると、「台本」「短いテンプレ」「(必要なら)追加ルール」を分割管理しやすくなります。

4. 実演:GraphQLから仕様書を作り出す

ここからが「SDDっぽさ」が一番伝わるところです。

たとえば、GraphQLのAPIを追加したいとします(例としてかなり簡略化)。

type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
}

4-1. /speckit.clarify:まず"質問"を作る

Copilotにいきなり「実装して」と言う前に、仕様を固めるための質問を先に出します。

重要:仕様書すらも、人間がゼロから書く必要はない

SDDと聞くと「仕様書を完璧に書かなきゃ…」とプレッシャーを感じるかもしれません。しかし、/speckit.clarify では、AIと壁打ち対話をするだけで、AIが仕様の叩き台を作ってくれます

実際の操作

> /speckit.clarify GraphQL APIでユーザー情報を取得したい
[Agent] 以下の点を明確にしましょう:
- user(id) でユーザーが見つからない場合、null を返す?エラーにする?
- 認可は必要?(本人のみ?管理者?)
- name は表示名?本名?(更新される?履歴は必要?)
- 監査ログやPIIの扱いは?

[ユーザーが回答]
> NotFoundはnullで返す。認可は不要。nameは表示名で、ユーザーが変更できる。

[Agent] 了解しました。では仕様書の草案を作りましょう。

こういう"埋めるべき穴"が先に見えるので、同じ指示を繰り返す回数が減ります。質問が整理できたら、次は /speckit.specify で仕様書を作成します。

仕様書もAIと対話して固まったものを spec.md に落とさせるだけ。 ゼロから人間が書く必要はありません。これが、SDDへの心理的ハードルを劇的に下げるポイントです。

※この例ではGraphQLを使っていますが、REST APIや単なるGoのStruct定義とメソッド作成でも同様です。仕様駆動開発の本質は「何を作るかを先に明確にする」ことであり、技術スタックには依存しません。

4-2. /speckit.specify で受入条件を明確化

BDDっぽく、Given/When/Thenで書くと読みやすくなります。

例(断片):

  • Given: id=123 のユーザーが存在する
  • When: user(id: "123") を実行する
  • Then: idname を返す

  • Given: id=999 のユーザーが存在しない

  • When: user(id: "999") を実行する
  • Then: null を返す(またはドメインエラーを返す)

ここまでが固まると、実装が変わっても「何を満たせばOKか」が残ります。

また、迷うところは推測せずに spec.md にこう残します。

  • 例:[NEEDS CLARIFICATION: user(id) の NotFound は null?エラー?]

4-3. /speckit.plan/speckit.tasks で実装準備

/speckit.plan で技術方針を決定し、/speckit.tasks でタスクに分解します。

plan.mdには「ドメイン層→ユースケース層→インフラ層」の変更箇所とPhase -1 Gatesのチェック結果が記録されます。tasks.mdでは [P] マーカーで並行実装可能なタスクを明示し、依存関係も管理されます。

生成される成果物の全体像:

specs/
└── 001-user-query-api/
    ├── spec.md              # 要件定義(WHAT/WHY)
    ├── plan.md              # 技術方針・アーキテクチャ
    ├── data-model.md        # データ構造・スキーマ
    ├── contracts/           # API仕様
    │   ├── graphql-schema.graphql
    │   └── rest-endpoints.md
    ├── research.md          # 技術選定の調査結果
    ├── quickstart.md        # 主要な検証シナリオ
    └── tasks.md             # 実装タスクリスト

4-4. /speckit.implement で実装

最後は /speckit.implement で実装します。AIがconstitution.mdとタスクリストに従ってコードを生成し、テストも自動作成します。実装中の判断は implementation-notes.md に記録され、後から見返せます。

変更が生じたら仕様側を更新して /speckit.plan を再実行すれば、変更管理も容易です。

5. 導入のポイント

よくある誤解と真実

誤解 真実
仕様書を書く時間がもったいない 最初に仕様を15分で固める方が、AIと5往復(30分〜1時間)より50%以上短縮
要件が変わるから仕様書は無駄 spec.md更新→/speckit.plan再実行で変更箇所が明確。影響範囲の調査が不要
AIは設計原則を理解できない constitution.md + Phase -1 GatesでAIが自動チェック

導入ステップ

  1. パイロット(1〜2週間) - 小規模な新機能で試す
  2. チーム展開(1〜2ヶ月) - constitution.md合意、仕様レビュー導入
  3. 複数チーム - 成功事例共有、ベストプラクティス蓄積

既存プロジェクト:新機能からSDDを適用し、徐々に範囲を広げることを推奨。

まとめ:SDDを勧めたい理由(AI時代の再現性)

  • Agent Modeの“同じ指示の繰り返し”は、仕様の穴・前提の散逸が原因になりやすい
  • speckitで「質問→仕様→計画→タスク」が型化されると、指示の履歴が成果物として残る
  • TDD/BDDは否定せず、SDDの中に自然に取り込める

まずは小さな機能で、受入条件を1ページに書くところから始めるのがおすすめです。

著者紹介

長年PHP愛を貫いてきたが最近Go言語へ移行気味。愛はあるんです愛は。
この夏北海道に車を持ち込んで2000km旅をしました。また行きたい。