仕様駆動開発で作る汎用シグナル開発ライブラリ
こんにちは。tonicです。
久々の投稿となります。
最近は主に仕様駆動開発というテーマを探求しています。
今回は、マケデコ Advent Calendar 2025の16日目への寄稿として、仕様駆動開発の枠組みでいい感じのPythonライブラリを作る話をしようと思います。
何を作ろうかなーと考えていたのですが、
- 自分を含めた多くの方のトレードbot開発に役立つこと
- ある程度規模の大きい実装が必要になること
といった条件を考慮した結果、「実運用までを綺麗に見通した汎用シグナル開発ライブラリ」を作ってみることにしました。
仕様駆動開発とは
仕様駆動開発(Spec-Driven Development。以下SDD)は、一つの詳細な仕様(Specification)を信頼できる唯一の情報源として定義し、主としてAIエージェントが実装を行う開発手法です。
SDDの思想では、仕様は実行可能であるという立場を取ります。
Claude Codeなどのコーディングエージェントが実用的になったいま、自然言語で定義された完全な仕様があれば、それをコンパイルするようなノリで実装は完成するはず…というような考え方です。
従来のVibe Codingとの違い
Vibe Codingという用語が定着して随分長い時間が経った…ように感じていましたが、実際には結構新しい概念でしたね。これは「やりたいことを自然言語でエージェントに伝えれば、なんかいい感じに作ってくれる」というような意味合いを含む用語です。
ただし、いくら最近のOpus 4.5のような高性能なモデルでも、曖昧な指示からよいものを作るのは困難です。エージェントに大規模な開発を任せたものの、コードの品質が低くレビューもメンテナンスも追いつかなくなった…というのはよくある話だと思います。
一方SDDでは、モデルに入力する指示を厳密な仕様として固めることで、規模の大きいプロジェクトでもエージェント主体の開発フローを回せるようにし、上述のような問題を解決することを目指します。
SDDを支えるSpec Kit
Spec Kitは、GitHubが開発しているSDDを行うためのオープンソースプロジェクトです。
Claude Codeなどの多くのCLIエージェントには、/command のように特別な指示を与えるためのスラッシュコマンドが用意されています。Spec KitはSDDの各フェーズ用にカスタムスラッシュコマンドを実装しており、これを順に使っていくことでエージェントと共に仕様を固めていくことができます。
Spec Kitが提供しているコマンドには、主に以下のようなものがあります。
-
/speckit.specify {your_prompt}- これから作る機能やプロダクトの仕様を定義する
- 技術スタックなどの実装詳細ではなく、目的や要件にフォーカスする
-
/speckit.plan {your_prompt}- 定義した仕様をもとに実装計画・設計を定義する
- アーキテクチャや技術選定など「どう作るか」を整理する
-
/speckit.tasks {your_prompt}- 実装計画を具体的なTODOリストに分解する
-
/speckit.implement {your_prompt}- TODOリストをもとに実装を行う
※後ほど必要なタイミングで触れますが、これ以外にも成果物をレビューする用途のコマンドが複数存在します。
Spec Kitはuvを使って簡単にCLIエージェントに組み込むことができます。
例えばClaude Codeを使っている既存のリポジトリに導入する場合は、以下の手順だけでOKです。
uv tool install specify-cli --from git+https://GitHub.com/GitHub/spec-kit.git
specify init . --ai claude
今回は、SDDに慣れ親しむべく、Spec Kitを使ってQeelというPythonライブラリを開発してみます。
汎用シグナル開発ライブラリ Qeel
そんなわけで、Qeelというライブラリを開発中です。(まだ完成してませんが…)
ライブラリ名は、船を安定させるためのキール(Keel)と、クオンツのQをかけ合わせました。(もちろんLLM考案)
分析~バックテスト~実運用までのシームレスな接続を可能にする、というコンセプトで開発を行っています。このコンセプトだと「バックテストツール」の範疇をはみ出していそうな感じがするので、「汎用シグナル開発ライブラリ」と名乗ることにしました。
いざ、SDD
ここから、Spec Kitで実際に開発を行う流れを追っていきます。
SDDやSpec Kitについて基本から知りたい方は、このセクションを読んでいただければ理解が深まると思います。
一方で、筆者が開発の中で培ったSDDの勘所については、後段のセクションでまとめています。こちらはやや詳細に踏み込んだ内容となっていますので、ご自身の興味に合わせてお読みください。
前提条件
- Spec Kitを使ってSDDを行います。
- SDDの思想のもと、筆者は一切コーディングを行いません。すべて自然言語を通してエージェントに設計と実装を行ってもらいます。
- エージェントはほぼOpus 4.5(2025/12/16現在)を使っています。
開発の流れ
1. specを明確化する
まず、どんなものを作りたいか、可能な限り具体的に要件や仕様を書き起こします。
この時、利用したい技術スタック(ライブラリ、フレームワークなど)は一旦置いておき、要件を具体化することに集中するとよいです。また、文章のフォーマットは適当でよく、箇条書き程度で十分です。
作りたいもののイメージが詳細に言語化できたら、それを /speckit.specify コマンドの入力プロンプトとして渡してあげます。この入力をもとに、エージェントが頑張って仕様(spec.md。以下spec)を書いてくれます。
例えばQeelの初期の設計では、以下のようなプロンプトを specify コマンドに渡しました。
どの程度細かく要件を書き出せばよいか迷ったときなど、参考にしてみてください。
※作成当時の筆者が未熟だったため、このプロンプトでは要件と技術スタックを分離できていません。本当は、利用したい技術スタックについては /speckit.plan のプロンプトに渡してあげる方がよいです。ただ、今回はたまたまこのプロンプトでもいい感じに抽象化してspecを定義してもらえたので、そのまま進んでいます。
2. specをレビューする
/speckit.specify コマンドを実行すると、自動的にこのspec専用のgitブランチに移動します。この後の作業はすべてこのブランチで行います。
生成されたspecは以下のように specs/{branch_name}/spec.md に保存されます。
このspecを、人間の目でレビューしていきます。
この作業は非常に重要です。この後のすべての作業はspecが真だという前提のもとで進行するので、specに不備があると非常に面倒な手戻りが発生してしまいます。自分のイメージと異なる部分があれば、このフェーズでその旨をエージェントに相談して修正してもらいましょう。
また、Spec Kitでは /speckit.clarify コマンドでspecに関する壁打ちを行うことができます。
spec.mdはSpec Kitが想定しているフォーマットに従っているので、慣れないうちは直接編集せず、 clarify コマンドを通して修正を行うのがよいと思います。
ただ、これから作るシステムを思い描いているような段階で、specを完璧に仕上げることは困難です。この後の各フェーズで随時修正が入るものだと考えておきましょう。
このフェーズでは、自分の想定と異なる記述、イメージが湧かない記述を徹底的に潰すことに集中するとよいでしょう。
3. 実装計画を作る
specが思い通りの仕上がりになったら、/speckit.plan コマンドで実装計画や設計書を作っていきます。
利用したいライブラリやツール、フレームワークなどが決まっている場合は、この段階でプロンプトとして入力してあげましょう。
また、「適切な粒度で実装ブランチを分割する想定で計画して」というプロンプトを加えると、機能ごとに綺麗な実装計画を立ててもらいやすくなります。
4. 実装計画をすべてレビューする
/speckit.plan コマンドを実行すると、以下のドキュメント群が生成されます。
-
plan.md: 実装全体の計画、プロジェクトのディレクトリ構造など -
data-model.md: データモデルやスキーマの設計 -
quickstart.md: 動作確認やセットアップ、簡単な使用方法など -
research.md: 技術選定・リサーチ結果と選択技術の根拠 -
contracts/*.md: 基底クラス、API仕様などの規約を定義
例えばQeelでは、コア仕様として以下のディレクトリにこれらのドキュメントが格納されています。
これらのドキュメントのレビューを行っていきます…が、正直このドキュメント量の多さにギョッとされた方も多いのではないでしょうか。
Spec KitはSDDツールの中でもドキュメント過多だと言う指摘があります。実際にこれらのドキュメントすべてに目を通し、修正を行うのは結構しんどいです。
Qeelのコア設計では、エージェントと壁打ちしながらこれらの設計書を仕上げるのに15~20時間ほどかかりました。
ただ、筆者の意見として、少なくとも最初に定義する根幹の設計については、根気強くすべてチェックした方がよいと考えています。仕様駆動開発の思想にあるように、これらのドキュメントは 信頼できる唯一の情報源 ですから、ここを妥協しなければ自ずとよいものが作れるはずです。
エージェントが一発で「信頼できる」ドキュメントを作成してくれればよいのですが…今の技術では、なかなかそうもいかないようです。ただ、後述するように実装フェーズは完全に任せられますから、それだけでも十分な効果があると言えそうです。
今までとは使用する脳の部分が随分異なるので最初は難しいかもしれませんが、我々も新しい環境に順応し、鍛錬を積んでいけるとよいのかもしれません。
少し本筋から逸れてしまいました。
このフェーズでの設計の修正方法については、後段のセクションでもう少し掘り下げます。
5. タスクリストを作る
仕様と設計が整ったら、実装に移るためのタスクリストを作成します。Spec Kitでは /speckit.tasks コマンドでtasks.mdとしてTODOリストを作成することができます。
plan のフェーズで複数のブランチにまたがって実装を行う計画を作成した場合は、 tasks の入力プロンプトに実装したいブランチ名を指定すると、その範囲内のみのTODOリストを作ってくれます。
なお、Spec Kitではシステムが想定するブランチの運用方法があるため、ブランチを分けて開発する場合は少し工夫が必要です。このあたりは後段のセクションで紹介します。
tasks.md が完成したら、 /speckit.analyze コマンドでTODOリストの整合性を評価してもらいましょう。このコマンドはSpec Kitの作業フローの中ではオプションの扱いですが、筆者は必ず実行するようにしています。TODOリストの中身をすべて読むのはかなりきついので、ここだけはエージェントに評価を任せることで妥協している感じです。
分析結果によって必要な修正計画が作成されるので、同じセッションで修正をお願いしましょう。修正計画自体に指摘を行うことも可能です。
6. コンパイル(実装)する
ここまでたどり着いた皆さま、お疲れさまでした。ようやく実装に入ります。とは言っても、このフェーズはほんの一瞬です。 /speckit.implement コマンドを実行すれば、後はエージェントがよしなに作ってくれます。その間にコーヒーでもすすっておきましょう。
実装が完了したら、レビューを行います。
筆者は念のためすべての実装に目を通すようにしていますが、ここは人それぞれだと思います。エージェントにレビューをお願いしてもよいでしょう。
ここまでの流れを繰り返して、システムを作りこんでいくことになります。
Spec Kit × SDDの勘所
ここでは、Spec Kitを使い倒していく中で得られた知見や勘所について、雑多に紹介していきます。
Spec Kitの仕組み
多くのCLIエージェントは、mdなどの形式でスラッシュコマンドをカスタマイズできるようになっています。
例えばClaude Codeでは、.claude/commands 配下に {your_command}.md というファイルを置いてエージェントへの指示をmd形式で記述すれば、 /{your_command} の形で呼び出すことができます。
Spec Kitは、この機能を利用して /speckit.specify などのコマンドを定義しています。つまり、実態としてはコンテキストエンジニアリングを行っているに過ぎないということです。
これらのコマンド定義を覗いてみると、「このshファイルを実行して、仕様に関する情報を取得すること」という趣旨のプロンプトが含まれていることがわかります。shファイルはSpec Kitが提供しているもので、現在のブランチ名から対応するドキュメントを一覧で返す処理などが定義されています。
これをエージェントに呼んでもらうように指示することで、仕様や設計に関するコンテキストを入力にうまく反映できるようになっています。
planコマンドの成果物を修正したいとき
/speckit.plan コマンドでは設計に関する各種ファイルが生成されますが、これらの修正方法に関する具体的な記述はSpec Kitのドキュメントにはあまり見当たりません。
実際、 plan を複数回実行すると、毎回ファイルが上書きされる挙動になるため、このコマンドによる設計のブラッシュアップはできません。
また、 /speckit.clarify はspec.md専用の修正コマンドです。他にも /speckit.analyze がありますが、これは /speckit.tasks でtasks.mdを生成した後にしか使うことができない仕様になっています。TODOリストは設計が変われば大幅に修正しなければならないことが多いため、これを生成する前に各種設計を詰めておきたいところです。
そこで、筆者は上述のSpec Kitの仕組みを利用して、この穴を埋めるコマンドを定義して利用しています。
既に述べた通り、Spec Kitコマンドの実態はプロンプトですから、簡単にコマンドを拡張することができます。例えばエージェントに公式のコマンドを全部読み込ませて、「こういうコマンドを作って」とお願いすれば、よしなに作ってくれます。
筆者は /speckit.review というカスタムコマンドを作成して使っています。このコマンドに設計への指摘や疑問点を入力すれば、その内容の妥当性評価と修正計画を提示してくれるようになっています。
便利なカスタムコマンド集
上述の /speckit.review の他にも、いくつか便利なカスタムコマンドを使っているので、一覧で紹介します。Claude Codeであれば .claude/commands 配下にコピペすれば動くので、ぜひ使ってみてください。
-
/speckit.validate {scope}
- 現在の設計成果物のうち、指定した範囲の機能が
/speckit.tasksフェーズに進める状態かどうかを判定する - そのまま
tasksに進んでOK / 軽微な設計修正が必要 / サブspecを立てるべき の三段階で評価する
- 現在の設計成果物のうち、指定した範囲の機能が
-
/speckit.verify
- 実装済みコードが仕様・設計と整合的かどうかを検証する
- 完了済みタスクに限定してレポートを出力する
-
/speckit.pr-fix {pr_number} {your_prompt}
- Pull Requestのレビューコメントを取得し、設計に照らして修正方針を整理する
- 修正計画が問題なさそうなら、そのまま修正を依頼できる
筆者は、 specify -> clarify -> plan -> validate -> tasks -> analyze -> implement -> verify の順で公式コマンドの間に一つずつ品質ゲートを設けることにより、レビューの負担を軽減しています。
verify 完了後はPull Requestを出してもらい、その内容をGitHubのUI経由で筆者がすべてレビューし、コメントします。その後、 pr-fix で修正を行ってもらいます。
ブランチの扱いについて
Spec Kitでは、 /speckit.specify コマンドの実行時に、ユーザの入力プロンプトから適切なブランチ名が決定され、ブランチ作成と移動が行われます。このブランチ名は、 specs/{branch_name} のようにspecのディレクトリ名と対応するように設定されます。
このようにfeatureブランチを切って開発を行うことが想定されているのですが、ブランチ間でどのようにコンテキストを参照するのかという点については公式ドキュメントにも明確な記載がありません。(あったら教えてください!)
ただし、エージェントが参照すべきspec名は環境変数 SPECIFY_FEATURE で指定できるようになっています。そこで、筆者はこの機能を利用して以下のような運用を行っています。
-
specifyでコアとなる全体仕様を定義する -
planの入力プロンプトで「適切な粒度でブランチを分割して開発する」という文言を入れる - レビュー後、実装したいブランチにチェックアウトし、
SPECIFY_FEATUREをコア仕様のものに設定する - 実装済みのtasks.mdがある場合は、削除またはspecディレクトリ外に移動する
-
validateの入力プロンプトで実装ブランチを指定 - 実装ブランチに関する設計書の修正が完了したら、
tasks以降のフローに進む
このようなフローを組むことで、各機能ブランチの設計にフォーカスしたときに初めて気付く仕様の不備などを、コアspecにフィードバックすることができます。その結果、「信頼できる唯一の情報源」としてのコアspecを徐々に完全にしていくことができます。
なお、筆者はtasks.mdをブランチごとに使い捨てています。
また、6番目の validate の段階でサブspecを定義すべきと判定された場合は、その機能に関するspecを specify コマンドで新たに定義します。
この場合は新たなspecをコンテキストにするため、 SPECIFY_FEATURE 環境変数の指定は不要です。ただし、コア仕様との整合性を保つため、 specify の入力プロンプトにその旨を含めるようにしましょう。
clarifyの質問が鬱陶しいとき
specを明確化するための clarify コマンドは非常に便利で優秀ですが、その内部で「明確化のために最大5つの質問を行うこと」という指示があります。
この影響で、ユーザのプロンプトが詳細で明確化の必要がない時でも、無理やりあまり関係のない質問をしてくることがあります。
そこで、 clarify の入力プロンプトに「クリティカルな不明点がない限り、質問を省略してください」という文言をいれると、不要な質問を省略してくれるようになります。
clarifyでspecを汚さないために
spec.mdには要件や仕様を具体的に記述しますが、本記事でも述べた通り、具体的な技術スタックを盛り込まないようにするのがベストプラクティスとされています。
しかし、clarify コマンドを使用して修正を行っていても、壁打ちしているうちにその前提が崩れることがよくあります。
仕様を具体的にするためには、実装方法を記述するのが手っ取り早くて簡単です。おそらく、人間もエージェントも無意識のうちにこのヒューリスティックを利用してしまっているのだと思います。
ただ、人間側はこの心理的なバイアスをメタ認知することが可能ですので、specを精緻化する際には常にこの問題を意識しておくとよいです。エージェントは指摘すれば直してくれますので、監視の目があれば問題ありません。
おわりに
今回はSDDによる開発風景を書いてみました。いかがでしたか?
あんまり楽になってねえなぁ…という印象を受けた方も多いかもしれません。
確かに、一発のプロンプトで思い通りのものができあがるという世界からは、まだまだ遠いなぁと感じます。
しかし、設計と実装をすべて自分で行う今までのフローと比べれば、実装速度は確実に速くなっていると感じます。
また、きちんと設計に向き合えば、成果物の質も同時に向上できるとも感じています。SDDを実践していて、この点が最も重要な本質なのではないかと考えるようになりました。
それから、今回題材にした Qeel ですが、動くものができたらまた皆さまにご紹介できればと思っています。
それでは皆さん、快適な開発ライフを!
Discussion