AIエージェントに「ルールを破らせない」仕組みをどう作ったか——harness-repoとspec-repoによるAI品質制御
複数チームが並行開発するクラウドサービスの開発現場で、AIエージェント(Claude Code)が生成するコードの品質をどう担保しているかをまとめた記事です。CLAUDE.mdでルールを渡すだけでは守られなかった経験から、ルールを「守らせる」harness-repoと、仕様を「AIが生成し、人がレビューする」spec-repoという2つの仕組みを構築しました。その設計と、運用してわかったことを紹介します。
背景 — 開発速度は上がったが、新しい課題も生まれた
対象は、複数チームが機能ドメインごとに並行開発するクラウドサービスです。技術スタックは以下の構成になっています。
| レイヤ | 技術 |
|---|---|
| BE | Go / AppSync / Lambda / DynamoDB |
| FE | Next.js / Apollo Client |
| Infra | AWS SAM / CDK / EventBridge |
2026年初頭からClaude Codeを全チームに展開し、コーディング・レビュー・調査をAIに補助してもらうことで開発速度は大きく向上しました。一方で、速度が上がったぶん新しい課題も顕在化しました。CLAUDE.mdにルールを書いてもAIに強制力を持たせられず、ルールを無視したままコミットが通ってしまう問題です。
課題① CLAUDE.mdには「強制力」がない
実際に起きた問題は次のようなものです。
dynamodb.Scan()を多用 →AccessDeniedExceptionが発生し、関連する更新処理が停止- IAM ManagedPoliciesの上限を超過 → CloudFormationが
CREATE_FAILED - Lambda作成時にAlarmを設定し忘れ → 障害をサイレントに見落とし
- SAM deployを並行実行 →
UPDATE_IN_PROGRESSでロールバック
コードレビューでは人間も見落としますし、CLAUDE.mdに書いてもAIが無視することがあります。チームが増えるほどルール徹底は難しくなります。CLAUDE.mdとHookを比較すると、この違いがはっきりします。
| CLAUDE.md | Hook | |
|---|---|---|
| 動作 | AIが参照するだけ | 物理的にブロック |
| 長文で忘れる | ある | なし |
| AIが無視 | できる | 不可能 |
| コミット通過 | してしまう | 止まる |
指示ファイルに頼るのではなく、差分を機械的にチェックして止める仕組みが必要でした。
課題② 仕様が散らばっていてAIに渡せない
もう一つの課題は、仕様の在り処がバラバラなことでした。
| 場所 | 内容 | 問題 |
|---|---|---|
| Confluence | 設計ドキュメント | 更新が追いつかず古い |
| Slack | 口頭決定・例外 | 拾えない |
| PR description | 変更の意図 | 散在している |
| コード | 実装そのもの | 「なぜ」が不明 |
この結果、「なぜこう作ったか」が追えない、チーム間で仕様認識がズレる、AIに渡す情報が不完全で期待と違うコードが生成される、E2Eテストの自動生成ができない(期待値が言語化されていない)といった問題が起きていました。
解決策の全体像 — harness-repo × spec-repo
この2つの課題に対して、2本柱で対処しました。
- harness-repo:AIを制御する。ルール違反をリアルタイムに検知し、コミットや操作をブロックします。2026年4月から運用中です。
- spec-repo:AIに正しい仕様を渡す。Confluence・Slack・PRからAIが半自動で仕様を生成・整備します。2026年3月から運用中です。
この2つを組み合わせることで、「AI × ルール × 仕様」の三位一体を実現する狙いです。
harness-repo — ルールを「守らせる」仕組み
Hookの動作フロー
harness-repoの中心にあるのがHookです。AIがコミットを実行しようとするとPreToolUseイベントが発火し、Hookスクリプトがdiffをスキャンします。違反があればdenyでブロック、問題がなければallowで実行が進みます。AI自身の判断では回避できない点がポイントです。
実装形態は3種類に分かれています。
- Hook:自動チェック(常時発火)
- Skill:開発者がスラッシュコマンドで呼び出すアシスタント機能
- Agent:特定のイベントをきっかけに自動で動き出すもの
Claude Code・Codex両方に対応するプラグインとして配布しており、一度インストールすれば、あとはgit pullするだけで全チームに最新の内容が反映されます。チームやリポジトリが増えても展開の手間がほとんどかからない点がメリットです。なお、社内・プロジェクト向けに閉じたスキルであるため、現時点ではマーケットプレイス的な自動配布の仕組みは使わず、git pullによるミニマムな配布方式を採用しています。各自のリポジトリでスキルをカスタマイズすることもでき、それが有用だと判断されればハーネス定例で共有したうえでPRを作成し、大元のリポジトリに取り込むかどうかはプロジェクト側で判断する運用です。
実装例:DynamoDB Scan禁止Hook
Hookの重要なポイントは、チェック対象を新しく書いた行だけに限定していることです。既存コードには一切影響しないため、導入時に過去の実装が軒並み引っかかる、という事態を避けられます。
登壇スライドで示された実装イメージは次のようなものです(要点を示す抜粋であり、実際の完全なスクリプトとは異なる可能性があります)。
# ステージ済み差分(*.pb.go 除外)DIFF=$(git diff --cached --unified=0 \ -- '*.go' ':!*.pb.go')SCAN_PATTERN='([a-zA-Z_]+\.Scan\(ctx\ |dynamodb\.ScanInput\{)'# + 行のみ対象 / allow-scan マーカーで除外if echo "$line" | grep -qE "$SCAN_PATTERN"; then # deny レスポンスを stdout に出力fi現在、こうしたHookは23本運用されており、代表例は次の通りです。
| Hook | 検知内容 |
|---|---|
| check-credential-hardcoding | 認証情報・APIキーのハードコード |
| check-iam-managedpolicy-limit | ManagedPolicy上限(10件)超過 |
| check-lambda-alarm-coverage | Lambda新規作成時のAlarm未設定 |
| check-repository-raw-sql | Repository層のRaw SQL新規追加 |
| check-mutation-in-hook-file | hooksファイル外でのuseMutation使用 |
| check-pending-marker | PENDINGマーカー付き仮値のコミット警告 |
インフラ系のルール違反からフロントエンドのコーディング規約、プロセス系のマーカー警告まで幅広いカテゴリをカバーしています。
なお、Hookはあくまで「AIが間違った方向に行かないようにする」ガードレールであり、ルールを増やせば理想的なコードが一発で生成される、という性質のものではありません。実装の質そのものはClaude Codeの他のプラグインと組み合わせて担保する形をとっています。
Agent / Skillの実装例
Agentの代表例はerd-update-pr-creatorです。マイグレーションファイルに変更があるとStop Hookが検知し、Agentが自動起動してER図(dbml)を更新するPRを自動作成します。ERD更新忘れという地味だが重要なタスクを完全自動化できた例です。ほかにapollo-cache-cqrs-reviewerは、ApolloのfetchPolicyやrefetchQueriesがCQRS整合性の前提として適切かをPR上で自動レビューします。
Skill(スラッシュコマンド)の例は以下の通りです。
| Skill | 用途 |
|---|---|
/connect-devdb-dbeaver | SSMポートフォワード+DBeaver接続設定を対話支援 |
/create-harness-issue | ルール違反をGitHub Issueとして起票 |
/claude-static-reviewer | hooks.json / CLAUDE.mdの静的レビュー |
運用サイクルと実績
harness-repoは「発見 → ハーネス化」のサイクルを継続的に回しています。開発中に問題を発見したら/create-harness-issueでIssueを起票し、日次のハーネス定例でレビュー・優先度付けを行い、Hook / Skill / Agentとして実装してPR・マージし、全リポジトリへ自動配布する、という流れです。
2026年6月時点の規模は、累計Issue数115件(うち53件解決済み)、マージ済みPR数55件です。日次定例は継続運用中で、アジェンダ自体もSkillで自動生成しており、準備コストをほぼゼロに抑えています。
なお、実装が完了した後の事後レビューで改善するプロセスが現状の中心で、設計・プラン段階からハーネスの制約を踏まえてAIに提案させる取り組みはまだ発展途上です。手戻りを減らすための改善は継続中です。
spec-repo — 仕様を「AIが生成し、人がレビューする」仕組み
5層構成のリポジトリ
spec-repoは次の5階層で構成されています。
| 階層 | ディレクトリ | 内容 |
|---|---|---|
| 1 | 00_inbox/ | 未整理の一次情報 |
| 2 | 10_evidence/ | Confluence / Slack / PRから抽出したエビデンス |
| 3 | 20_specs/ | 機能仕様(235本) |
| 4 | 30_catalogs/ | 用語集・エラー一覧 |
| 5 | 40_tests/ | テスト期待値 |
なぜ「書かせない」のか
各チームに仕様を書いてもらう運用は、開発スピード優先でどうしても後回しにされ、チームごとに粒度や形式もバラバラになり、書き手と読み手が同じチームに閉じてしまいます。そこでspec-repoでは、AIが一次情報から半自動で生成し、チームはレビューするだけという方針を採っています。
Confluenceは一次情報のまま保持し、そこからspec-repoへ一方向で取り込む形にすることで、開発者がConfluenceに書くだけで二重管理を避けられるようにしています。
AI半自動生成フロー
- 収集:
confluence-collect/slack-collect/github-collectで各所からエビデンスを取得し、10_evidence/に保存 - 仕様反映:
enrich-specスキルでエビデンスを仕様に反映し、20_specs/の設計判断・経緯セクションを更新 - レビュー:チームが差分を確認し、修正・承認
現在の整備状況
仕様ドキュメント数は235本、エビデンス件数は1,600件以上です。Docusaurusで静的サイトとしてホスティングしており、全チームがブラウザから参照できます。生成精度はドラフトから2〜3割の修正で利用できるレベルとのことです。
ハマったポイント / わかったこと
うまくいったこと
- Hookの強制力の高さ:指示ファイルはAIに無視されることがありますが、Hookは物理的にブロックするため確実です
- Issue起票の摩擦を下げたこと:起票のハードルを下げたことで問題発見時の初動がしやすくなり、好循環が生まれています
- プラグイン配布による横展開のしやすさ:
git pullで全リポジトリに反映できます - 日次定例という継続的な場:レビューする習慣が品質維持に効いています
難しかったこと・注意点
- Hookの誤検知は開発を止めてしまう:対策として、警告(warn)から始めてブロック(deny)に昇格する段階的な運用が有効でした
- 仕様整備の最終レビューは人間依存:AIが生成してもボトルネックは人間のレビューになりやすい点は変わりません
- commit hookはローカルのみ有効:本当に強制力を持たせるにはCIへの移行が必要です
- Skill / Agentの品質はプロンプト設計に依存:継続的な改善が前提になります
- 設計・プラン段階でのガード適用はまだ発展途上:現状は実装完了後の事後レビューが中心です
他プロジェクトへの横展開ポイント
最初の一歩はHook1本からで十分です。
- 「これはAIがやりがちだな」と気づく
/create-harness-issueで起票する- Hookとして実装する(シェルスクリプト数十行で書けます)
- プラグインとして配布する
既存のコードベースがすでに育っているプロジェクトでは、グランドファザリング(新規追加行のみをブロック対象にする)方式にすることで、既存実装への影響を気にせず段階的に導入できます。対応ツールはClaude Code / Codexで、Copilotについては現状CIチェックで対応しています。
まとめ
- ルールは**強制する仕組み(Hook)**で守らせる
- 仕様はAIが整備し、人がレビューする
- 改善は**継続的なサイクル(Issue → 定例 → PR)**で回す
AIエージェントを単なる道具ではなく、チームメンバーとして設計するという視点が、今回の取り組みの核になっています。社内でも継続的に改善を進めています。ハーネス設計やAI駆動開発に関するご相談があれば、お気軽にKDDIアイレットへご相談ください。
