🔁

コーディングエージェントで試す仕様駆動開発

に公開
2025/12/23

本記事は、個人の検証メモとして「仕様駆動開発(Spec-Driven Development)」とコーディングエージェントを組み合わせた開発フローを試しているリポジトリの紹介です。

TL;DR

要件→設計→タスク→実装を“テキストのパイプライン”として固定化し、実装はコーディングエージェントに委ねる。人間は仕様の品質(曖昧さ解消・優先度・受け入れ条件)と意思決定に集中する。

  • 分割の狙い:Requirements(何を満たす)/Design(どう作る)/Tasks(どう進める)で責任とレビュー観点を分離し、解釈ブレを減らす
  • 運用の肝:タスクはレイヤー単位でまとめず、ユーザーストーリーの最小動作単位に分割してHuman-in-the-loopを小さく回す
  • 品質のガードレール:TDD必須+YAGNIのルール化で「実行されない不要コード」を抑制する
  • レビュー最適化:PRレビューを5〜10分で終えられる前提で、PRテンプレ+確認手順を整備する
  • 引き継ぎ:Decision Logで重要な判断と理由を記録し、次タスクのコンテキストをつなぐ

進め方を「要件→設計→タスク」に分ける理由

開発の進め方を次のステップに分けて扱います。

  1. Steering Documents(方針)
  2. Requirements(要件)
  3. Design(設計)
  4. Tasks(タスク分解)
  5. Implementation(実装)

分ける意図は、責任とレビュー観点を分離することです。

  • Requirements:何を満たすべきか(ユーザー価値・制約・受け入れ条件)
  • Design:どう作るか(データ・API・画面遷移・例外・権限など)
  • Tasks:どう進めるか(順序・粒度・完了定義・検証手順)

生成AIに実装させるとき、「要件だけ」だと解釈の余地が広すぎます。
一方で「設計だけ」だと、何のための設計か(価値・優先度・受け入れ条件)が揺らぎます。
タスクまで落とすことで、実装範囲と完了条件が固定され、レビュー可能になります。


実装をコーディングエージェントに委ねる、という設計

このプロジェクトの特徴は、実装を"会話の延長"ではなく"仕様に対する作業"として扱うことです。

  • 人間:仕様の確定、優先度付け、曖昧さの解消、レビュー基準の整備
  • コーディングエージェント:タスクに沿った変更の作成、検証コマンドの実行、差分の提示

ここで重要なのは「人間が楽をする」ことよりも、「人間が判断すべき場所を前に寄せる」ことです。
判断が必要な箇所を仕様段階で明確化し、実装はそれに従って淡々と進める——上流の曖昧さを下流で吸収しない設計を目指します。


失敗から学んだこと:タスク設計とレビューの落とし穴

ここからは、実際に検証を進める中で直面した失敗と、その解消例を紹介します。

失敗談①:レビューがしにくかった(粒度の問題)

問題:レイヤー単位でまとめて実装してしまった

例えば、CRUDや検索機能のある「マスタ機能」を作るとき、アーキテクチャの依存関係に従って Repository → Application Service → Presentation → フロントエンド の順に実装していくタスク定義が作られることがあります。

方向性は正しいのですが、実際には次のような「粒度の大きすぎるタスク」が作られ、失敗しました。

  • 1つのタスクで Repository 側の CRUD メソッド群と、検索用の Query Service をまとめて実装する
  • 次のタスクで Application Service 側の UseCase をまとめて複数ファイル作成する
  • 次のタスクで Presentation 側の複数エンドポイントをまとめて公開する
  • 最後にフロントエンドをまとめて一気に作成する

これだとPRの差分が大きくなり、レビューに時間がかかります。さらに、問題の発見が機能完成の終盤になり、修正コストも大きくなります。
Human-in-the-loopを小さく回して、間違いをなるべく早い段階で修正することが重要です。

解消例:ユーザーストーリー単位でのタスク分割

タスク計画を「レイヤー単位の塊」ではなく、「ユーザーストーリーの最小動作単位」で切るようにプロンプトを改善しました。
docs/specs/[feature-name]/tasks/ を次の構成で分割して作成させることで、動作可能な最小単位でレビューを進められます。

docs/specs/[feature-name]/tasks/
├── 00_overview.md       # 全体概要、前提条件、依存関係グラフ
├── 01_setup.md          # Phase 1: 環境セットアップ
├── 02_foundation.md     # Phase 2: 基盤構築(共通コンポーネント)
├── 03_story_01.md       # Phase 3: ユーザーストーリー1 (MVP)
├── 04_story_02.md       # Phase 4: ユーザーストーリー2
├── ...                  # 以降のストーリー
└── 99_integration.md    # Phase N: 統合・仕上げ

失敗談②:不要な振る舞いを実装してしまう

問題:一見必要そうだが実行されないコード

一見必要そうな機能や引数が実装されていますが、実際は実行されることがないコードが生成されてしまっていました。この問題が繰り返されると、コードを保守していく上で致命的な問題となります。

対策:TDDとYAGNIの「ルール化」

エージェントの"賢さ"に期待するのではなく、作業手順として余計な実装が入りにくい型を作ることが重要です。
具体的には、以下のガイドラインを設けました。

## タスク実行ガイドライン

### 生成AIへの指示原則
1. **1タスク = 1コンテキスト**: 各タスクは独立して実行可能な単位
2. **TDD必須**: テスト作成 → テスト失敗確認 → 実装 → テスト成功
3. **最小実装**: YAGNI原則に従い、要件で求められた機能のみを実装
4. **既存コード活用**: 新規実装前に必ず既存コンポーネント・ユーティリティを確認
5. **依存順実装**: アーキテクチャの依存方向に従い、内側レイヤーから実装

改善の効果:PRレビュー時間の短縮

上記の問題を解消した効果として、PRのレビューに掛かる時間が5〜10分程度に短縮されました。

コーディングエージェントと人で実装を進める上で重要なポイントは、PRのレビューに掛かる時間でした。

実装は依存関係がなく並列で進めても問題がない機能を同時に進めていきます。
1つのタスクをコーディングエージェントに依頼してからPRが作成されるまでに20分前後の時間が掛かり、2つを並列で回していきます。

そのため、PRをレビューしてマージし、次のタスクの実装へ効率的に回していくには5〜10分でレビューを終える必要があります。ここは人が行うべきことなので、人にやさしく、ボトルネックにならないように進める必要があります。


人にやさしいレビューのための2つの工夫

工夫①:PRテンプレート

PRには、対応したタスクと変更サマリを書かせます。特に重要なのが、コーディングエージェントに「人間が確認すべき事項」をリストアップしてもらうことです。さらに確認手順も出してもらうことで、レビューが迷子になりにくくなります。

## Summary
<!-- このPRで実施した変更内容を日本語で記載してください。 -->
<!-- 背景、目的、実装内容などを含めて説明してください。 -->

## Task File(s)
<!-- このPRで処理したタスクファイルを記載してください。 -->
<!-- 例: docs/specs/<feature-name>/tasks/03_story_01.md -->
- [ ] docs/specs/<feature-name>/tasks/<task-file-name>.md

## Checklist for Human
<!-- 人が直接確認すべき事項をここに記載してください。 -->

### Test Plan
<!-- レビュアーが確認すべきテスト手順を日本語で記載してください。 -->
1. 環境のセットアップ手順
2. 動作確認の手順
3. 期待する結果

工夫②:Decision Log(意思決定ログ)

もう一つは、実装のハンドオフ時に Decision Log(意思決定ログ) を出しておいてもらうよう指示することです。

  • 実装時に見つかった問題に対して、どう判断し何を決めたかを書く
  • レビュー時に重要な決定の背景・理由を把握できる
  • 暗黙的になりがちな知識を表面化し、次タスクのコンテキスト接続に使う
# Decision Log: {Feature Name}

> **このドキュメントの目的**: 機能実装タスク実行中に発生した重要な意思決定、設計変更、および後続タスクへの引き継ぎ事項を記録する。
> **運用ルール**:
> 1. Feature単位で1つのファイルを作成する (`docs/specs/[feature-name]/decision-log.md`)
> 2. タスク実行中に重要な決定をした場合に追記する

---

## Log Entries

### [YYYY-MM-DD] {Task ID}: {Title of Decision}

**Context & Problem**
<!--
  なぜその決定が必要だったのか?直面した課題や状況。
  実装中に判明した仕様の曖昧さや、技術的な制約など。
-->

**Decision**
<!--
  どのような決定をしたか?
  例: "XではなくYを使用することにした", "Zの設計を変更した", "スコープを縮小した"
-->

**Rationale**
<!--
  その決定に至った理由。
  代替案との比較や、ユーザーとの合意内容。
-->

**Impact & Action Items**
<!--
  この決定が後続タスクや他の機能に与える影響。
  必要なアクション(タスクの修正、ドキュメントの更新など)。
-->
- [ ] Task X.X.X の修正が必要
- [ ] design.md の更新が必要
- [ ] {Other Action}

まとめ

要件→設計→タスクを整備し、実装をコーディングエージェントに委ねる。
これはコーディングエージェント活用の話であると同時に、「仕様を資産化して開発を運用する」話でもあります。

検証を通じて見えてきたのは、以下のポイントです:

  1. タスク粒度はユーザーストーリー単位で:レイヤー単位ではなく、動作可能な最小単位で分割する
  2. TDDとYAGNIの明示:不要なコードの生成を防ぎ、テストで仕様を担保する
  3. PRレビューを5〜10分に:Human-in-the-loopを効率的に回すための設計
  4. Decision Logでコンテキストを引き継ぐ:暗黙知を表面化し、タスク間のメモリとして活用する

これらのガードレール(スコープ、禁止事項、承認、検証手順)を「プロンプト・テンプレート・フォルダ構成」に埋め込むことで、エージェントを安全かつ効率的に動かす運用を目指しています。


Appendix:DevinへのHandoff(実装計画の自動生成とログ更新)

コーディングエージェントのプロンプトは直接タスクファイルを入れるのではなく、タスクを元に「実装計画」を立ててから実装に進む形にしています。

タスクをそのまま実装に投げずに、最新のコードベースの現状(既存の実装パターン、命名、依存関係、テスト方針)と、必要に応じて 外部ドキュメント(Context7等のMCP経由)も踏まえて「実装計画」を生成してから実装に進むことです。これにより、古い前提や“それっぽい想像”で実装がズレるリスクを下げます。

  • ローカルでタスクを元に、最新のコードベースや外部ドキュメント(Context7等のMCP)を参照して実装計画を作る
  • コピペしてコーディングエージェントに渡し、実装を進める

この「実装計画を立てる」という点を、毎回人間がコピペで組み立て続けるのはコストが高いので、Devin(コーディングエージェント)側に“動的に”やってもらうhandoffプロンプトを用意しています。

@r06-acsim/acsim-spec-driven-sandbox
agent: @acsim-spec-driven-sandbox/src/agents/spec.agent.md
prompt: @acsim-spec-driven-sandbox/src/prompts/create-implementation-plan.prompt.md
feature: {featureName}

1. {agent} 定義を読み込む
2. {feature} の次に着手する未完了タスクファイルを特定する
3. タスクファイルを {prompt} に渡して実装プロンプトを生成する
4. 生成された実装プロンプトに従って実装する
5. PR作成後に @acsim-spec-driven-sandbox/.github/prompts/updateTaskTrackingIssue.prompt.md を使用してタスク管理Issueを更新する

Discussion