はじめに
GitHub Spec Kit には、仕様から実装までを段階的に進めるためのコマンド群があります。
基本的な流れは、ざっくり言うと次のようなものです。
/speckit.constitution
/speckit.specify
/speckit.plan
/speckit.tasks
/speckit.implement
この流れに加えて、実装後のコードと仕様・計画・タスクのズレを確認するためのコマンドとして、/speckit.converge があります。
公式の Installation Guide では、/speckit.converge は “Assess codebase against artifacts and append remaining tasks” と説明されています。
また、公式リポジトリの templates/commands/converge.md を見ると、spec.md / plan.md / tasks.md を意図のソースとして読み、現在のコードベースとの差分を確認し、残作業があれば tasks.md に Convergence Phase として追記する、という動作が定義されています。
参考:
ただ、ドキュメントを読んだだけだと、実際にどの程度検出できるのかは分かりにくいです。
そこで今回は、小さな Todo API を題材にして、あえて実装を壊したうえで、/speckit.converge がそのズレを検出し、tasks.md に追加タスクとして記録できるかを試しました。
さらに、その追加タスクを /speckit.implement に渡して、正常に改修できるかも確認しました。
今回確認したこと
今回確認したのは、次の4点です。
1. 実装後のズレを /speckit.converge が検出できるか
2. 検出したズレを tasks.md に追加タスクとして append できるか
3. 追加されたタスクを /speckit.implement で修復できるか
4. 修復後に /speckit.converge で No gaps found になるか
検証は小規模な Todo API に限定しています。
そのため、この記事の内容は「今回の小さな題材ではこう動いた」という実験ログとして読んでください。
使用環境
主な環境は以下です。
| 項目 | バージョン |
|---|---|
| macOS | 26.5.1 |
| Spec Kit | 0.11.3 |
| Claude Code | 2.1.19 |
| VSCode | 1.127.0 |
| Python | 3.14.2 |
| FastAPI | 0.139.0 |
| pytest | 9.1.1 |
Spec Kit のバージョンは、.specify/init-options.json、.specify/integration.json、specify --version で 0.11.3 と確認しました。検証は 2026-07-04 に実施しています。
補足すると、requirements.txt はバージョンをピン留めしていません。上記の Python / FastAPI / pytest は、今回の .venv に実際に入ったバージョンです。
題材にした Todo API
今回の題材は、FastAPIで作った小さな Todo API です。
主な機能は以下です。
POST /todos
- Todoを作成する
- titleは必須
- priorityは任意
- due_dateは任意
- 作成直後は completed=false
GET /todos
- Todo一覧を取得する
- priorityでフィルタできる
PATCH /todos/{todo_id}/complete
- 指定したTodoを完了状態にする
また、due_date については、実行時刻に依存しないように固定の REFERENCE_DATE を使う設計にしました。
今回の記事で主に見るのは、PATCH /todos/{todo_id}/complete に対応する complete_todo の挙動です。
正常な実装
正常な complete_todo は次のような実装です。
def complete_todo(todo_id: int) -> Todo | None:
todo = _todos.get(todo_id)
if todo is None:
return None
updated = todo.model_copy(update={"completed": True})
_todos[todo_id] = updated
return updated
指定された Todo が存在する場合、その Todo の completed を True に更新し、保存したうえで返します。
存在しない場合は None を返し、API側で 404 Not Found に変換します。
この状態では、テストはすべて成功していました。
18 passed
意図的に壊した実装
次に、complete_todo をあえて次のように変更しました。
def complete_todo(todo_id: int) -> Todo | None:
return _todos.get(todo_id)
この実装だと、Todoが存在する場合にそのまま返すだけです。
つまり、APIとしては PATCH /todos/{todo_id}/complete が呼べて、Todoも返ってきます。
しかし、肝心の completed=True への更新が行われません。
「APIは動いているように見えるが、仕様として期待される状態変更が行われていない」というズレを作った形です。
pytest の結果
この状態で pytest -q を実行すると、完了更新に関するテストだけが失敗しました。
17 passed / 1 failed
失敗したのは、指定した Todo だけが completed=True になることを確認するテストです。
FAILED tests/test_todos.py::test_fr008_fr009_complete_only_target_todo
ここでのポイントは、アプリ全体が壊れたわけではなく、完了更新の要求に関係する部分だけが失敗していることです。
/speckit.converge を実行する
この状態で、余計な説明は付けずに /speckit.converge を実行しました。
/speckit.converge
結果として、complete_todo が completed=True に更新していないことが検出されました。
検出結果の要旨は以下です。
pytest -q → 17 passed / 1 failed
新規の乖離を 1 件検出
app/store.py の complete_todo が completed=True へ更新せず、
Todo をそのまま返している。
PATCH /todos/{id}/complete が 200 を返しても完了状態が変わらない。
関連:
- FR-008
- FR-009
- User Story 3
- SC-003
gap-type: partial
severity: HIGH
今回のケースでは、APIや関数自体は存在しています。
しかし、要求されている状態更新が一部満たされていません。
そのため、missing ではなく partial として検出されたのは妥当だと感じました。
tasks.md に追加されたタスク
/speckit.converge の結果、tasks.md の末尾に新しい Convergence Phase が追加されました。
実際には Phase 10: Convergence として、T024 が追加されました。
要旨は以下です。
- [ ] T024 [US3] app/store.py の complete_todo(todo_id) を修正する。
指定された Todo が存在する場合、その Todo の completed を True に更新し、
保存したうえで更新後の Todo を返すようにする。
関連: FR-008, FR-009, US3, SC-003
重要なのは、既存タスクを書き換えるのではなく、append-onlyで新しいタスクとして追記された点です。
完了済みだった既存タスクを未完了に戻すのではなく、次のように扱われていました。
実装後に発見されたズレを、追加の是正タスクとして記録する
この挙動は、実装後の差分管理として分かりやすいです。
/speckit.implement で修復する
次に、追加された T024 のみを対象にして /speckit.implement を実行しました。
指示としては、T024以外の仕様・テスト・既存タスクには触れず、complete_todo の修正だけを行うようにしました。
修復後の complete_todo は、次のように正常な実装に戻りました。
def complete_todo(todo_id: int) -> Todo | None:
todo = _todos.get(todo_id)
if todo is None:
return None
updated = todo.model_copy(update={"completed": True})
_todos[todo_id] = updated
return updated
その後、テストはすべて成功しました。
18 passed
最後にもう一度 /speckit.converge
修復後、最後にもう一度 /speckit.converge を実行しました。
結果は以下です。
No gaps found
pytest -q: 18 passed
Result: Converged
また、ギャップがない場合は tasks.md に空の Convergence Phase を追加することもありませんでした。
これは余計な差分が増えないので、自然な挙動だと思います。
分かったこと
今回の小さな検証では、/speckit.converge について以下が確認できました。
1. 実装と仕様・タスクのズレを検出できた
2. pytestの失敗結果と実装内容をもとに、ズレを特定できた
3. FR / User Story / Success Criteria に紐づけて説明できた
4. tasks.md に append-only で追加タスクを作成できた
5. 追加タスクを /speckit.implement に渡して修復できた
6. 修復後に No gaps found / Converged まで確認できた
特に印象的だったのは、単に「テストが失敗しています」と言うだけではなく、次のように仕様・タスク側の文脈に結びつけてくれた点です。
complete_todo が completed=True に更新していない
FR-008/009 と US3 に関係する
gap-type は partial
severity は HIGH
注意点・限界
一方で、今回の検証だけで過剰に一般化するのは危険です。
今回確認できたのは、あくまで小規模な Todo API における1つの欠陥注入です。
未検証のことも多くあります。
- テストが存在しない欠落をどこまで検出できるか
- 大規模なコードベースでどこまで正確に検出できるか
- 仕様自体が間違っている場合にどうなるか
- 複数の欠陥が同時にある場合にどこまで切り分けられるか
- バグ報告や改修履歴まで含めたトレーサビリティを管理できるか
また、今回の実験は Claude Code / VSCode 上で行っています。
利用するエージェントや実行環境によって挙動が変わる可能性もあります。
まとめ
今回の検証では、/speckit.converge は小規模な Todo API に対して、仕様・タスクと実装・テストのズレを検出し、tasks.md に追加タスクとして append できました。
さらに、その追加タスクを /speckit.implement に渡すことで、該当箇所を修復し、最終的に /speckit.converge で No gaps found になることも確認できました。
つまり、少なくとも今回の範囲では、/speckit.converge は単なるチェックコマンドというより、次のようなループの一部として機能していました。
実装後のズレを検出する
↓
是正タスクとして記録する
↓
implementで修復する
↓
再度convergeで収束確認する
Spec Kitを使う場合、/speckit.implement で終わりにするのではなく、実装後に /speckit.converge を挟むことで、仕様と実装のズレを見直すプロセスを作れそうです。