読むだけで直さない監査と、戻り先のある指摘
「Hora Kit の設計」シリーズの 8 本目。書く者と検める者を分け、監査エージェントにはファイルを編集する権限を持たせない。関所 8 のセキュリティ監査と、指摘に必ず戻り先を付ける /hora-accept の検収の仕組みを書きます。同じ AI に書かせてレビューもさせることがなぜ危ないのか、という話でもあります。
1. はじめに
この記事は、弊社(Open Reach Tech)が OSS にした AI 開発フレームワーク『Hora Kit』の設計を解説するシリーズの 8 本目です。メイン記事はこちらです。
本当の意味での自動開発を実現するための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 つとして「セキュリティ監査が読み取り専用のエージェントで走る」と書きました。この記事では、その監査と、最後の検収の仕組みをもう少し詳しく書きます。
AI にコードを書かせるとき、同じ AI にレビューもさせている方は多いと思います。それがなぜ危ないのか、という話でもあります。
2. 書く者と検める者を分ける
Hora Kit には 3 つのエージェントがいます。
| エージェント | 役割 | 持たないもの |
|---|---|---|
hora-implementer | 1 関所ぶん、または 1 単位ぶんのコードとテストを書く | git、.hora/ への書き込み |
hora-verifier | 1 関所の終了条件が本当に満たされているかを検める | ファイル編集ツール |
hora-digester | 装備済みスキル 1 つを、実装エージェントが常駐させられる大きさに要約する | 自分の digest 以外への書き込み |

verifier の定義ファイルには、なぜ編集ツールを持たないのかが書いてあります。同じエージェントに実装と検証の両方をやらせると、落ちるテストを通るまで緩める道が開くから、というのが理由です。AI エージェントは「テストを通す」という目標に向かって最適化するので、この道は放っておくと必ず使われます。
だから verifier にはファイル編集ツールがありません。直せないから、直さない。指示ではなく権限で守る、という考え方です。
3. 反証を探す。分からなければ「未達」
verifier のもう 1 つの特徴は、判定の向きです。
条件が成り立つことを証明しようとせず、成り立たない筋を探します。判断がつかなければ「未達」に倒します。通してしまって後で見つかるほうが高くつくからで、この設計では「後で」というのは数機能先の検収実行を意味し、そこでは原因がもう明らかではありません。
人のレビューはどうしても「たぶん大丈夫」で通しがちです。verifier は「分からなければ落とす」に固定されているので、弊社がコードの確認を人の目からこのエージェントに移せた理由の 1 つがここにあります。
4. 関所 8: 監査は読み取り専用で、丸ごと実行する
関所 8 はセキュリティ監査です。バックエンドのコードを書いた機能では、飛ばせません。
| 委譲先 | 読み取り専用のセキュリティ監査を覆うスキル |
| 実行者 | verifier エージェント。読み取り専用 |
| 終了条件 | この機能のコードに対する指摘が無いか、すべての指摘が修正済みか、明示的に許容され記録されている |
普通の関所では、verifier には規約の digest(要約)が渡されます。関所 8 だけは違って、監査スキルを丸ごと実行し、その出力を報告します。監査の検査項目と指摘基準はスキルにあり、verifier は自分の判断でそれを置き換えません。最初の数項目が綺麗だったからといって早く止めることもしません。
対象は、この機能の変更分だけです。リポジトリ全体ではなく、作業ツリーに立っている変更と、この機能が .hora/contracts/ に宣言した operation と endpoint です。宣言した面を含めているのは意図的で、既存の変更されていないコードへ新しく繋いだ呼び出し元は、変更ファイルだけ見ていると監査から漏れます。認可の抜けは、ちょうどそこで起きます。
5. 修正は別の行為。再監査は修正の範囲だけ
監査は見つけるだけで、直しません。指摘の修正は implementer が行い、そのあとで監査を再実行します。
再実行は修正の範囲に絞られます。各指摘が解消されたことを確認し、修正が触ったファイルと、それが届いた共有面を再監査します。基準は変わらず、見る範囲だけが変わります。
「許容する」を決めるのは AI ではありません。許容した指摘は質問として記録され、静かな合格として残ることはありません。弊社のエンジニアが「この指摘は受け入れる」と決め、その名前とともに記録に残ります。
6. 関所 18: 検収は /hora-accept に委譲する
関所 18 は /hora-accept に委譲されます。やることは 5 手順です。
1. 環境の確認 ローカル E2E コンテナ環境。ライブ実行のときだけ
2. ユニットスイート テスト配置と、スイートを緑にすること(リポジトリごと)。毎回必須
3. シナリオ一覧 E2E テスト仕様
4. 受入レビュー本体 レビュー本体と、その判定基準を、この実行の範囲で
5. UX の指摘 UI/UX 監査。スイープ、または明示的な要求時
手順 2 をレビューより前に置いているのは意図的です。ユニットスイートは安く、落ち方が正確です。同じ欠陥を E2E フロー越しに見つけると、位置の特定にはるかに費用がかかります。
そして、このコマンド自体は判定基準を 1 つも持っていません。レビューが何を見て何で落とすかは委譲先のスキルにあり、このコマンドが決めるのは「対象機能」「委譲の順序」「結果の記録先」だけです。
7. ゲートは絞り、回帰の網は絞らない
機能の関所(18)では、レビューの範囲はその機能に絞ります。ブラウザでのライブ掃引も、明示的に要求されない限りスキップします。
一方でユニットスイートは、全リポジトリで毎回フルに走ります。だから以前の機能を壊す変更は、壊したその実行で落ちます。docs はこれを「ゲートは絞られているが、回帰の網は絞られていない」と表現しています。
版全体のスイープでは、実装済みの全機能をレビューし、必ず製品を駆動します。
8. 得ていない合格を報告しない
手順 1 は準備運動ではなく関門です。レビューは各ロールでサインインし、フローを成功条件まで完了させ、依存を意図的に止めて画面が何と言うかを見ます。フロントエンドを単体で立てただけの相手には、そのどれも意味を持ちません。
製品を駆動する実行でローカルの E2E 環境が無い、あるいは不完全なとき、/hora-accept は lacked-environment を報告して止まります。本当は動いていないものをレビューする代わりに、です。docs によれば、既存プロジェクトへの適用で最初に止まるのはここで、それは正常な動きなので、環境を直してから再実行します。
9. 指摘は必ず「どの関所に戻すか」を書く
検収の指摘には書式があります。
1. #attendance — 月次画面から保存した記録に、日次一覧から到達できない。
戻り先: #attendance の関所 11。
2. #sign-in — セッション切れで、その旨を出さずに空白画面になる。
戻り先: #sign-in の関所 13。
戻り先の無い指摘はメモで、戻り先のある指摘は作業です。戻り先は、関所に立っている機能とは別の機能であることが多く、それが退行の普通の形です。上の例でも、#attendance の検収で #sign-in の関所 13 に戻る指摘が出ています。
何も直さず「この指摘は許容」と決めることもしません。その判断は人のもので、誰が決めたかとともに質問ファイルに入ります。
10. まとめ
この仕組みで弊社が大事だと考えているのは 3 つです。書く者と検める者を分け、検める者から編集権限を取り上げること。監査の対象を「変更分と、宣言した面」に絞ること。指摘に戻り先を書かせること。
同じ AI に書かせてレビューもさせている方は、一度「レビュー側から編集権限を外す」だけでも試してみてください。それだけでも動きが変わると思います。
原典はこちらです。 https://github.com/openreachtech/hora-core/blob/main/kit/agents/hora-verifier.mdhttps://github.com/openreachtech/hora-core/blob/main/docs/commands.ja.md