【ITニュース解説】Living Specs in SpecKit
2026年10月17日に「Dev.to」が公開したITニュース「Living Specs in SpecKit」について初心者にもわかりやすく解説しています。
ITニュース概要
開発における仕様書は、コード変更で古くなりがち。SpecKit Companionの「リビングスペック」は、機能ごとの仕様をコードと共に管理し、自動更新や同期で常に最新状態を保つ。これにより、開発者は常に正しい仕様を参照でき、効率的かつ正確な開発が可能になる。
ITニュース解説
システム開発において、機能の仕様(スペック)を明確にすることは非常に重要であるが、従来の開発手法では、この仕様書が時間の経過とともに実態と乖離し、「死んだ」状態になってしまうという課題が長らく存在していた。
かつては、ソフトウェアの機能に変更を加えるたびに、その変更内容を記述した仕様書を作成する「スペック駆動開発」というアプローチが用いられることがあった。この方法では、機能ごとに細かく仕様書が作成され、それがリポジトリ内のフォルダに蓄積されていく。開発者は、新しいコードを書き始める前に、その機能が「何をすべきか」を明確にし、それを計画し、タスクに分割し、最終的に実装するという段階を踏む。このプロセス自体は、開発の方向性を細かく確認しながら進めることができるため、一定の利点があった。実際、この手法を採用したプロジェクトでは、膨大な数の仕様書ファイルが生成されることも珍しくない。
しかし、これらの仕様書には大きな問題があった。それは、一度機能がリリースされてしまうと、その仕様書が更新されることがほとんどないという点である。コードはその後も変更され続けるが、仕様書はその「書かれた日」の情報を保持したまま凍結してしまう。結果として、プロジェクトが進行するにつれて、仕様書と実際のコードの間に大きな隔たりが生じてしまうのだ。
この問題は複数の側面で開発に悪影響を及ぼす。まず、新しい機能開発で既存のダイアログ(画面上の操作要素)に触れる際、以前にそのダイアログに関する仕様書があったとしても、それが現在の状況を反映していないため、開発者は毎回ゼロからそのダイアログの動作やデータモデル、周辺のルールなどを再調査する必要がある。過去に得られた知識や理解が、次の開発に活かされない状態となる。これは特に、AIを活用した開発エージェントにとっても同様で、エージェントは毎回コードから情報を「再学習」しなければならず、効率が低下してしまう。
次に、開発者自身が「この機能は今、具体的にどう動くべきなのだろうか」と疑問に思ったときに、既存の仕様書群の中から最新かつ正確な情報を見つけ出すのが非常に困難になる。「タスク完了機能」がどのように動作するかの仕様を知りたい場合、複数の異なる時期に書かれた仕様書が散在しており、どれが現在のバージョンを記述しているのか判別できないことがある。仕様書は特定の時点での「意図」を記録したスナップショットであり、それが積み重なると文書ではなく単なるアーカイブになってしまうのである。
さらに、AIエージェントがコードを理解しようとする際にも問題が生じる。通常、エージェントは指定されたコードの周辺情報を読み込む。その際、過去の仕様書フォルダは大量かつ古いため、エージェントがそこから現在の正確な情報を探し出すことは現実的ではない。結果として、エージェントはコードそのものから情報を推測するが、そのコードが必ずしも最新の標準や意図を完全に反映しているとは限らない。
これらの課題を解決するために提案されたのが、「Living Spec(リビングスペック)」という新しい概念である。これは、「生きている仕様書」と訳すことができる。従来の、変更ごとに一度だけ書かれ、その後忘れ去られる仕様書とは異なり、リビングスペックは「機能ごと」に一つ作成され、その機能が現在「何をすべきか」を常に記述し続ける。例えば、「請求機能」や「認証機能」といった大きな単位で一つのリビングスペックを持つのである。
リビングスペックの最も重要な特徴は、その「生きている」という性質だ。特定の機能に関わる開発作業が実行されるたびに、リビングスペックはまずロードされ、その機能の現在の要件やシナリオが開発プロセス全体に渡って参照される。そして、作業が完了し機能がリリースされる際には、リビングスペックの内容が自動的に更新される仕組みになっている。これにより、コードの変更に仕様書が常に追従し、常に最新の「機能のあるべき姿」を開発者やAIエージェントに提供する。
具体的な運用方法は次のようになる。まず、プロジェクトのルートディレクトリに living-specs.yml という設定ファイルを作成し、リビングスペック機能を有効にする。このファイルには、プロジェクト内のどの領域(例えば、src/features/profile/**)がどのリビングスペック(例えば、「メンバープロフィール」)に対応するのかを記述する。そして、各リビングスペック自体はMarkdown形式のファイルとして、その機能が満たすべき要件(Requirements)と、その要件を満たすための具体的なシナリオ(Scenarios)を記述する。
このリビングスペックファイルは、例えば src/features/directory-search/directory-search.spec.md のように、それが記述するコードのすぐ隣に配置することが推奨される。これにより、開発者がコードを見ているときに、そのコードが「何をすべきか」を記述した仕様書をすぐに参照できる。AIエージェントも同様に、コードと仕様書を同時に読み込むことで、より正確な理解と効率的な作業が可能となる。
リビングスペックの導入は、段階的に進めることができる。例えば、living-adopt というコマンドを使用すると、プロジェクト内の特定のコード領域を指定し、その領域の既存コードからリビングスペックのドラフト(下書き)を自動的に生成できる。このドラフトは、開発者がレビューし、不足している要件やシナリオを追記することで、完成されたリビングスペックとなる。
リビングスペックの「生きている」状態を保つ最大の仕組みは、開発パイプラインへの統合である。通常の開発フローを通じて機能の変更が行われる際、SpecKitは関連するリビングスペックを自動的にロードし、計画段階から参照する。そして、その機能が完成し、コードがマージされる際に、変更内容がリビングスペックに自動的に「折り畳んで反映される(fold-back)」仕組みが組み込まれている。例えば、新しい要件が追加された場合はリビングスペックに追記され、既存の要件が修正された場合はその部分が置き換えられる。この自動更新プロセスは、コードの変更と同じプルリクエスト(コードレビュー)の中で行われるため、仕様書への変更も開発者によってレビューされ、意図しない変更が適用されるのを防ぐことができる。これにより、手動での仕様書更新漏れを防ぎ、常にコードと仕様書の一貫性を保つことが可能となる。
また、すべての開発作業がSpecKitのパイプラインを通じて行われるとは限らない。急な修正や、AIを使わない探索的な開発など、パイプライン外でコードが変更されることもある。このような場合、コードとリビングスペックの間に「ずれ(drift)」が生じる可能性がある。SpecKit Companionは、このようなずれを自動的に検出し、サイドバーに表示する。開発者は、living-drift コマンドで具体的にどのファイルがずれの原因となっているかを確認し、living-sync コマンドを使ってリビングスペックを手動で更新できる。この手動同期も、既存の記述を尊重し、変更された部分のみを編集するため、開発者が手書きで追記した内容は失われることなく維持される。
リビングスペックは、機能が「どう作られたか」ではなく、「何をすべきか」に焦点を当てる。そのため、コードがリファクタリングされて内部実装が変わっても、機能の外部的な振る舞いが変わらなければ、リビングスペックは修正の必要がない。これにより、仕様書の陳腐化を防ぎ、長期的なメンテナンス性を高めることができる。
最終的に、リビングスペックは開発プロセス全体において、開発者とAIエージェント双方にとっての信頼できる情報源となる。かつては一度書かれたら忘れ去られ、時間の経過とともに価値を失っていた仕様書が、常に最新の状態で開発をガイドし、チーム全体の生産性と品質向上に貢献するのである。過去の失敗から学び、仕様書を「生きさせる」ことで、よりスムーズで効率的なソフトウェア開発が可能となるのだ。