1 つの機能が通る 18 の関所と 4 つのゲート
「Hora Kit の設計」シリーズの 4 本目。1 つの機能が本番に出るまでに通る 18 の関所(checkpoint)を全部並べ、なぜこの順序なのか、確認に失敗したらどこまで戻るのかを書きます。読み終わる頃には、18 個が「4 回の確認と、その間の作業」に見えてくるはずです。
1. はじめに
この記事は、弊社(Open Reach Tech)が OSS にした AI 開発フレームワーク『Hora Kit』の設計を解説するシリーズの 4 本目です。メイン記事はこちらです。
本当の意味での自動開発を実現するためのAI開発フレームワーク『Hora Kit』をOSSにしました
用語の確認。 Hora Kit で打つコマンドは
/horaの 1 つだけです。/horaが状況に応じて/hora-spec(仕様書を書く)、/hora-setup(実装リポジトリを作る)、/hora-plan(版を確定し、機能一覧と契約を書く)、/hora-build(1 機能を 18 の関所に通す)、/hora-accept(検収する)を順に呼びます。/hora-hotfixだけは/horaが呼ばず、人が直接打ちます。docs はこのうち/hora-specを「決める側」、残りを「作る側」と呼んでいて、この記事でもその呼び方を使います。
メイン記事で「1 つの機能が 18 の関所を通る」と書きました。18 という数字だけ見ると、多すぎるように感じると思います。
この記事ではその 18 個を全部並べて、なぜこの順序なのか、どこで後戻りするのかを書きます。読み終わる頃には、18 個が「4 回の確認と、その間の作業」に見えてくるはずです。
2. 18 の関所、4 つのゲート

まず全体を表にします。関所(checkpoint)の見出しは英語のまま引用しています。/hora-plan が機能ファイルに逐語コピーするものなので、翻訳も圧縮もしてはいけない識別子だからです。
| ゲート | # | 関所 | 何をするか |
|---|---|---|---|
| Spec | 1 | Draft or confirm the specification | 仕様の該当節を確認する |
| 2 | Verify the use cases can be met | 仕様の通りにユースケースを満たせるか | |
| Backend | 3 | DB and API schemas | テーブルとスキーマ |
| 4 | Stub API | スキーマ準拠の stub。フロントはこれに対して作れる | |
| 5 | The modules the implementation needs | 次の関所が import するモジュールを先に揃える | |
| 6 | Actual API | 実装。resolver、サービス、テスト | |
| 7 | Worker | バックグラウンドジョブ。無ければ理由付き n/a | |
| 8 | Security audit | 読み取り専用の監査 | |
| 9 | Verify the use cases again, against the built API | 実際に作られた API に対してユースケースを歩く | |
| Frontend | 10 | Open the frontend | フロントエンドの機能ブランチを切る |
| 11 | Reconfirm UI/UX and the use cases | 画面設計に対してユースケースを歩く | |
| 12 | Component design | コンポーネント設計 | |
| 13 | The frontend modules the implementation needs | 5 と同じ。フロント側 | |
| 14 | API client | 4 の stub に対してクライアントを作る | |
| 15 | UI | 画面 | |
| 16 | Wire the data-fetching logic in | stub から actual API へ切り替え | |
| 17 | Local test environment | E2E 環境。全サービス、全ロール、確認用データ | |
| Acceptance | 18 | Acceptance (E2E and unit both) | /hora-accept に委譲 |
各ゲートの境界で、その行の feature/<id> ブランチが release/<version> にマージされ、.hora/ がコミットされます。
3. 状態は 3 つだけ
各関所は、機能ファイルのチェックボックスとして記録されます。
## Backend gate
- [x] 3. DB and API schemas
- [x] 4. Stub API
- [ ] 5. The modules the implementation needs
...
- [x] 7. Worker <!-- n/a: this feature triggers no background job -->
状態は未通過、通過、理由付きの n/a の 3 つです。理由の無い n/a は状態として認められません。docs はこれを「飛ばした関所が、通った関所の印を被っているだけ」と表現していて、要するに「とりあえずスキップ」を構造的に禁じています。
4. 順序について、意図して決めた 3 つ
18 個の並びには、docs が明記している意図が 3 つあります。
1 つ目は、stub(関所 4)がフロントエンドのゲートより前にあることです。これがあるので、12〜14 は 6 の実装を待たずに「形の正しいもの」に対してクライアントと画面を作れます。16 で actual API に差し替えますが、stub と実装はクラス名と interface を共有しているので、これは書き直しではなくエンドポイントの切り替えで済みます。
2 つ目は、5 と 13 で、次の関所が import するモジュールを先に揃えることです。5 はその前に社内パッケージのカタログ(@openreachtech/hora-ecosystem)を確認して、会社が既に出しているものを再発明しないようにします。実装の途中で「持っていない外部クライアントが要る」と分かって中断する、というのはよくある話ですが、この関所はまさにその中断を消すためにあります。
3 つ目は、2・9・11・18 の 4 つがユースケースに照合することです。これは「3 回下見をして 1 回本番」ではありません。落ち方が違います。
| 関所 | 何が支えているかを検める |
|---|---|
| 2 | 仕様が支えているか |
| 9 | API が支えているか |
| 11 | 画面が支えているか |
| 18 | 製品が支えているか |
弊社が人のレビューを大幅に減らせた理由の 1 つがこれです。同じユースケースを、違う層に対して 4 回歩く。人が 1 回目視するより、こちらのほうが漏れません。
5. 後戻りさせる 4 つの関所
上の 4 つは、実行を後戻りさせられる唯一の関所でもあります。
| 関所 | 何に対して検めるか | 落ちたときの戻り先 |
|---|---|---|
| 2 | ユースケース、仕様の文面通りに | 関所 1(仕様そのものを変える必要がある) |
| 9 | ユースケース、実際に作られた API に対して | 3〜7 のうち変えるべきもの。たいてい 3 |
| 11 | ユースケース、実際に設計された画面に対して | 11 自身、またはユースケースが間違っていたなら 2 |
| 18 | 製品、端から端まで | 不足を生んだ関所。どの機能のものでも |
戻るときは、無効になった関所の印を解除し、解除した中で一番手前まで戻ります。docs には「一度も戻らない実行は、仕様書が異常に完璧か、検証ゲートが仕事をしていないかのどちらかです」とあって、後戻りは異常ではなく正常な動きとして扱われています。
6. 通りすがりに直さない
関所 9 について、docs に「その場でパッチを当てるな」という趣旨の注意があります。メイン記事にも書いた話ですが、ここではもう少し具体的に書きます。
関所 9 でユースケースをなぞっていて、API のレスポンスにフィールドが 1 つ足りないと分かったとします。普通に考えれば、その場でフィールドを足して先に進みたくなります。数分で終わりますし、誰も困らないように見えます。
Hora Kit ではそれをせず、関所 3 まで戻ります。理由は、その時点でフロントエンド側の作業が、別のリポジトリで、古い API 契約に対して始まっているからです。バックエンド側だけでフィールドを足すと、契約と実装が少しずつずれていき、そのずれは後になってから表に出ます。戻るほうが遅く見えますが、ずれた契約を後から突き合わせるよりは速い、というのが Hora Kit の考え方です。
7. 空でないリポジトリでは「作る」ではなく「突き合わせる」
既存プロジェクトに Kit を適用した場合、関所は空のリポジトリに対して走るわけではありません。その場合、各関所は「作る」のではなく「あるべきものと実物を突き合わせる」動きになります。既に満たされていれば通過し、足りなければその分だけ作ります。
この性質が、既存プロジェクトへの適用(シリーズ 9 本目)の土台になっています。
8. ブランチはいつ切られ、いつマージされるか

| 行 | 切る時点 | マージする時点 |
|---|---|---|
backend の feature/<id> | 関所 3 に入るとき | 関所 9 を通過したとき |
frontend の feature/<id> | 関所 10 に入るとき | 関所 17 を通過したとき |
マージは検収(18)の後ではなく、ゲートの境界で行います。検収は全機能に及ぶスイートを走らせるので、そこまで待つとブランチが他の機能の作業をまたいで開きっぱなしになるためです。
関所 17 だけは例外です。E2E 環境はバックエンド行にあって、その機能ブランチは 8 関所前(関所 9)で既にマージ済みです。だからその変更は専用の update/e2e-<what>-for-<feature-id> ブランチに載ります。
9. まとめ
18 個は多く見えますが、やっていることは 4 つです。仕様に対してユースケースを確認し、バックエンドを作って API に対して確認し、フロントエンドを作って画面に対して確認し、最後に製品に対して検収する。関所は、この 4 つの確認が飛ばされないための刻み目です。
弊社が人の目でやっていた確認を、この刻み目に置き換えたことで、人のレビューを大幅に減らせました。18 という数に身構えている方の参考になれば幸いです。
原典はこちらです。 https://github.com/openreachtech/hora-core/blob/main/kit/skills/hora-build/references/checkpoints.mdhttps://github.com/openreachtech/hora-core/blob/main/docs/commands.ja.md