動いているコードの周りに Hora Kit を被せる
「Hora Kit の設計」シリーズの 9 本目。弊社が 100 万行近いシステムを Hora Kit で安定して開発できているのは、動いているコードの周りに後から Kit を被せたからです。既存リポジトリの履歴もブランチも設定も奪わずに、Hora Kit を既存プロジェクトへ適用する手順を書きます。
1. はじめに
この記事は、弊社(Open Reach Tech)が OSS にした AI 開発フレームワーク『Hora Kit』の設計を解説するシリーズの 9 本目です。メイン記事はこちらです。
本当の意味での自動開発を実現するための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を「決める側」、残りを「作る側」と呼んでいて、この記事でもその呼び方を使います。
メイン記事で「100 万行近いシステムでも安定して開発できている」と書きました。そのシステムは、Hora Kit で最初から作ったものではありません。動いているコードの周りに、後から Kit を被せたものです。
「新規なら試せるけど、うちは既存のコードが山ほどある」という方が多いと思うので、この記事ではその「被せる」手順を書きます。
2. 既存リポジトリは何ひとつ奪われない
先に安心してもらいたいことを書いておきます。既存リポジトリは何ひとつ奪われません。履歴もブランチも設定もコードもそのままです。Hora Kit はそれらの外側に立ち、仕様書と計画と記録を持つリポジトリとして加わります。

myproject-app/ ← キット。specs/ .hora/ .claude/ を持つ。アプリコードは持たない
legacy-api/ ← 既存のバックエンド。手つかず
admin-console/ ← 既存のフロントエンド。手つかず
ディレクトリ名は変えなくて構いません。仕様書のリポジトリ構成表に Directory 列があって、そこで名前を宣言します。
3. 最初に決めるのは 1 つの問いだけ
手順に入る前に、1 つだけ決めます。仕様書とコードが食い違ったとき、どちらが正しいのか、という問いです。
as-built(実装が正) | to-spec(仕様が正) | |
|---|---|---|
| あなたの状況 | 製品は動いていて、その動きがあなたの望むもの。現状を版として固定し、そこから育てる | 誰かが書いた仕様に向けて実装の途中。残りの距離を詰める |
| 仕様書が記述するもの | 今日動いている製品 | あるべき製品 |
| 質問の量 | 数個と、検収掃引 1 回 | 全関所が走り、コードを仕様へ突き合わせて直す |
答えは仕様書の 1 行、Existing assets 節の Authority: に書かれます。この記事の残りは、この答えで分岐します。動いている製品をそのまま正として育てたいなら as-built、仕様が先にあって実装が追いついていないなら to-spec で、ほとんどの既存プロジェクトは前者になると思います。
4. 6 つの手順
docs の「短くまとめると」を、弊社の言葉で要約します。
まず、hora-boilerplate から <myproject>-app を作り、既存リポジトリを中に移します。入れ子にするのは git の要求ではなく、Claude Code のセッションが作業ディレクトリの外に書けないという要求です。
次に、既存の文書を持ち込みます。要件一覧や API リファレンスのように「仕様そのもの」なら specs/1.0.0/sources/ へ、モックアップや古い設計書のように「仕様を説明するもの」なら annex/ へ、作ってほしいものは request/ へ、自分の言葉のままで入れます。実装リポジトリの中へはリンクしないでください。gitignore 済みなので、リンクは静かに切れます。
3 番目に、上の as-built / to-spec を決めます。
4 番目に /hora-spec が、既存を読んだ上で仕様書を書きます。ステージ 0 がリポジトリと置かれた文書を読み、仕様とコードの食い違いを全件記録します。as-built なら、導出された built: の表をまず丸ごと提示し、そのあと機能ごとに選択式で確認します。ユースケースと受入基準は動いているシステムから草案されるので、あなたは訂正するだけです。「まだ終わっていない」と答えた機能だけが to-spec になります。
5 番目に /hora を走らせます。/hora-setup は適用済みの行に対して clone を飛ばし、埋まっていない値だけを埋め、実物ツリーを読んで .hora/tree/ に控えます。人が既に埋めたものは上書きされません。続いて /hora-plan が計画を書くので、ここで built: が正しいかを確認します。
| 間違え方 | どうなるか |
|---|---|
built: と宣言したが実は作られていない | 検収が落とし、印が解除され、本当に作られる。安全な方向 |
| 宣言しなかったが実は作られている | 動くコードに対して 17 の関所が走る。壊れはしないが、時間が無駄になる |
最後に、最初の検収掃引です。「既に作られている」と宣言された機能は、作り方を述べた 17 の関所を飛ばしますが、検収には必ず入ります。つまり適用後の最初の掃引は、既存製品全体を、その製品自身が掲げるユースケースに対して受入レビューすることになります。
5. 指摘が出ることを見込め。それが価値そのもの
docs は「指摘が出ることを見込んでください。そしてそれが、適用した価値そのものです」と書いています。
メイン記事に「Hora を導入した後に、潜在的なバグとセキュリティの脆弱性が多く見つかった」と書きましたが、既存製品に対して最初に走るのがこの掃引なので、見つかるのはここからです。
各指摘は「どの機能の、どの関所に戻すか」を書きます。適用済み機能の built before Hora Kit was adopted と印された区間に着地した場合、その印は解除されます。直さなければならないコードは、結局のところ単に受け継いだものではなかった、という扱いです。影響する一番手前の関所から、本当に作り直します。
これが、既存製品がキットの水準まで引き上げられていく仕組みです。一度に 1 つの不足だけ、しかも不足が実際に示された箇所だけを直します。
6. 最初の実行は、環境で止まる
最初の掃引の手順 1 で止まる可能性が高く、それは正常です。
関所 17 はローカルの E2E 環境を作るためにあって、既存プロジェクトはたいてい何かしら(compose ファイル、シードスクリプト)を持っていますが、前提条件をまだ満たしていません。アプリの背後で全サービスが動き、各ロールでサインインでき、レビュー可能なデータがある、という条件です。それを直してから再実行してください。
ここで飛ばしたくなる気持ちは分かりますが、飛ばさないでください。フロントエンド単体でレビューすると、得ていない合格を報告することになります。
7. 除外リストが見た目より重要な理由
適用手順の中で、抜けたときの損害が大きく、しかも静かなのはここだけです。
.gitignore とルートの eslint.config.js は、実装リポジトリを名前で除外しています(*-backend*/、*-frontend*/)。legacy-api/ のような名前はどちらにも当たりません。
| 起きること | 気づく経路 | |
|---|---|---|
.gitignore | バックエンド全体が追跡され、キットのリポジトリにコミットされる | git status を読むまで無い。その時点で既にコミット済み |
eslint.config.js | ルートの lint が、自分のものではない設定のリポジトリを走査する | 大量の違反 |
/hora-setup は宣言された Directory ごとに 1 行ずつ両ファイルに追記し、追記したことを報告します。それが起きたかどうかは、報告を見て確認してください。
8. 気をつけること
docs が挙げている注意のうち、既存プロジェクトで踏みやすいものを挙げます。
boilerplate のタグが既存コードより新しいことがあります。委譲されるスキルは現在の規約を述べるので、同じリポジトリの中で新しいコードが古いコードと違って見えます。これは想定内です。
既存のテストは、通すために弱められません。スキップも削除も緩和もしません。既存テストが落ちたなら、それは迂回すべき障害ではなく指摘として扱われます。
main に直接コミットしないでください。キットのリポジトリでは main-guard.yml が守りますが、既存リポジトリにはその防壁が無いかもしれません。
9. まとめ
既存プロジェクトへの適用で手に入るのは「残りをキットが作ってくれる」ではありません。それは後の話です。最初に手に入るのは、この製品が今何をできるのかという事実です。どこに到達でき、何が揃っていて、失敗したときに本当のことを言うか。
弊社にとって、100 万行近いシステムの「今何ができるか」を、人の記憶ではなく検収の記録で持てることが、適用の最大の価値です。レガシーコードに AI をどう入れるか悩んでいる方の参考になれば幸いです。
原典はこちらです。 https://github.com/openreachtech/hora-core/blob/main/docs/adopting.ja.md