
影響範囲調査をCIに組み込む──CARE設計の思考ログ
前回の記事では、1四半期に発生した9件のインシデントを分析し、「暗黙的な依存の見落とし」が根本原因だという結論を出した。
そこで提唱したアプローチは3つ。
- 案 A(リアクティブ型): 変更時に都度調べる
- 案 B(プロアクティブ型): 常に依存マップを維持する
- 案 C(自動化型): CI で自動検知する
でも、「アプローチの方向性」を書いただけで、「どうやって実現するか」まで踏み込めていなかった。今回はその続き。実際にどう設計を進めたかの思考ログ。
チェックリストから始めようとしたら、すぐ限界が見えた
最初に考えたのは、PR テンプレートにデータ影響チェック項目を追加するという案だった。手軽だし、今日から始められる。
でも、前回分析した根本原因を思い出すと、「調べようと思えば調べられたが、調べるべきだという認識がなかった」だった。
これって要するに、知らないものはチェックできないということだ。
「新旧テーブルの同期確認」という項目があったとしても、自分が担当している変更が新旧テーブルに関係しているとそもそも知らなければ、そのチェックボックスをスルーしてしまう。チェックリストは「何を調べるべきか」を知っていることが前提の仕組みなので、今回の問題の構造にはフィットしない。
加えて、忙しい時期にはそもそもチェック自体が形骸化する。これは経験則として、みんな持っているんじゃないかと思う。
「防ぐコスト」と「リカバリーコスト」を並べて考えた
チェックリストが難しいなら、構造を作り変えるアーキテクチャ改修がある。たとえば、複数サービスが直接参照している共有 DB のテーブルを API 経由に統一するとか。確かに根本的な解決にはなる。
でも、これは開発投資がかなり大きい。
そこで一度、9件のインシデントのリカバリーコストをちゃんと並べて見てみた。
| # | 障害の性質 | 復旧方法 | リカバリーコスト感 |
|---|---|---|---|
| 大半のインシデント | データ整合性、設定ミス、パフォーマンス | データ修正、設定変更、index 追加 | 低〜中 |
| 1件だけ特殊 | 誤ったビジネスアクションが実行された | 事実を取り消せない性質がある | 高(不可逆) |
大半のインシデントは、数時間〜1日で復旧できている。全ユーザーに影響しても、停止時間は短い。
一方で、1件だけ性質が違うインシデントがあった。誤った状態でビジネスプロセスが進んでしまったタイプで、「その事実を元に戻す」こと自体が難しい。
この整理から、投資判断の軸が見えてきた。
「防ぐコスト」 vs 「リカバリーコスト + ビジネスダメージ」
→ 大半のインシデント: リカバリーの方が安い → 検知・復旧に投資
→ 不可逆なビジネス影響があるもの: 防ぐ方が安い → そこだけ防御
→ 両方に対して最小コストで効果を出す方法が必要アーキテクチャの大改修をしなくても、もっと現実的な解がありそうだと思い直した。
既存の CI 基盤に乗せるという発想
そのとき、「そういえば今の CI でコードの複雑度チェックをやっているな」という話になった。
PR が作られると CI が動いて、自動的にコード品質の指標を出して PR にコメントする仕組みが既にある。
これを応用すれば良いんじゃないか、という発想。
「このファイルやテーブルに変更が入ったとき、別のどこかも確認が必要」というマッピングをルールとして持っておいて、PR の変更内容と照合する。
これが CARE(Context-Aware Review Engine)の原型。名前も含めて、自分で考えたコンセプトだ。
ポイントが2つある。
ポイント1: 「何を調べるべきか」と「実際に調べる作業」を分ける
前回の根本原因に立ち返ると、問題は2層構造だった。
- 認識の問題: 調べるべきだと気づかなかった
- 実行の問題: 気づいたとしても、複数リポジトリを横断して調べる物理的コストが高い
チェックリストは認識の問題を一部解決しようとするが、実行の問題は解決しない。人が調べなければいけない状態は変わらない。
CARE の役割分担はこう。
- 「何を調べるべきか」 → マッピングルールとして人間が育てる
- 「実際に調べる作業」 → LLM が担う
人間は知見を蓄積することに集中して、調査作業そのものは LLM に任せる。
ポイント2: 自己強化ループになっている
ルールに合致しない PR があったとき、ただ何もしないのでは勿体ない。そこで LLM に変更内容を分析させて「このパターン、レビュー観点として登録した方が良くないですか?」と提案させる。
開発者は Accept / Skip で判断するだけ。
これで、使えば使うほどルールが充実するループが生まれる。インシデントが起きなくても、日常の PR からルールが育っていく。
ルール管理をどう設計するか
ここで一番悩んだのが、ルールの管理場所だった。
案 A: 各リポジトリに分散配置(各リポジトリに .care/review-points.yaml を持つ)
良い点は、そのリポジトリの開発者が自然に更新できること。コードと一緒に PR を出せる。
悪い点は、今回のインシデントの大半が「リポジトリをまたいだ影響」だったこと。分散配置だと、クロスリポジトリの観点が書きにくい。
案 B: 集中リポジトリで管理
repo-care-rules/
├── product-a/
│ ├── api.yaml
│ └── batch.yaml
├── product-b/
│ └── main.yaml
└── cross-service/
└── shared-tables.yaml一番防ぎたい問題が「リポジトリ間の依存」なので、一箇所で管理する方が自然。クロスリポジトリの観点も素直に書ける。ルールの全体像が見渡せる。
デメリットは、コード変更とルール変更が別 PR になること。でも、ルール変更はコード変更とは違うライフサイクルで更新されることも多いので、それはそれで良いかもしれない。
今回の問題の構造から考えると、案 B の集中管理が妥当という結論になった。
陳腐化を防ぐ仕組みも設計した
ルールを集中管理しても、更新されなければ意味がない。「定期的に見直しましょう」は機能しないと、経験上わかっている。
必要なのは、更新が自然に発生する仕組み。
考えたのは3つの経路。
経路1: PR 駆動(日常の開発フロー)
リスクシグナルがある PR でルールに合致しない場合、LLM が自動でルール追加を提案する。開発者は Accept/Skip で判断するだけ。日常の開発フローの中で自然にルールが増えていく。
経路2: インシデント駆動
障害報告のテンプレートに2〜3個の質問を追加する軽いプロセス。
- このインシデントは PR 起因か?
- CARE ルールがあれば防げたか?
- どんなルールがあれば防げたか?
Yes の場合、LLM が障害報告の内容からルールのドラフトを自動生成する。ポストモーテムのような重い会議体は不要。復旧直後が一番原因を理解しているタイミングなので、そこで機械的にキャプチャする。
経路3: 手動追加
上の2つで拾えないものは、開発者が直接追加する。これは最後の手段。
ルールには origin を記録する
各ルールに「なぜこのルールが存在するのか」を記録することが重要だと思っている。
- trigger:
tables: ["shared_table_name"]
prompt: |
このテーブルは複数サービスから参照されています。
スキーマ変更時、他サービスへの影響を確認してください。
origin:
incident: "YYYY-MM-DD 発生の障害名"
date: "2026-04-XX"これがないと:
- なぜこのルールがあるのかわからない → 消していいのか判断できない
- リニューアルが完了して不要になったルールを判別できない
ルールをコードと同じように Git 管理して、変更履歴を追えるようにする。「誰かが Wiki に書いた」ではなく「誰がなぜ変えたかがコミット履歴に残る」状態にする。
過去9件のインシデントへの有効性を検証した
設計がある程度固まったところで、「実際にこの仕組みが9件のインシデントを防げたか」をシミュレーションしてみた。
| # | 障害の種類 | CARE で防げたか | 調査内容 |
|---|---|---|---|
| 1 | 新旧テーブル同期漏れ(データ処理系) | Yes | 差分更新/全件更新の仕様差をコードから発見できる |
| 2 | 依存ライブラリのバージョン互換性 | Likely | package.json の変更で互換性リスクのあるライブラリを調査可能 |
| 3 | 新旧テーブルの状態遷移不整合 | Yes | 旧テーブルのみ更新されている事実をコードから発見できる |
| 4 | JOIN クエリのパフォーマンス | Yes | JOIN 対象テーブルの index 有無を DB 情報から確認可能 |
| 5 | インフラ設定変更による実行環境の差異 | Likely | 設定ファイルの変更を検知し実行環境との照合が可能 |
| 6 | データ移行タイミングのラグ | No | PR 起因でない作業は対象外 |
| 7 | 共有テーブルのスキーマ変更波及 | Yes | 別リポジトリのコードを検索して依存を発見できる |
| 8 | サーバーリソースの競合 | Likely | インフラ設定変更を検知しメモリ使用率との照合が可能 |
| 9 | レガシー API からの JOIN 参照 | Yes | レガシー API のコードを検索して発見できる |
9件中6〜7件に有効。PR 起因でない作業(#6 のデータ移行)は構造的に対象外。
進め方: 最初から全自動にしない
実装フェーズの話になったとき、「最初から Webhook で自動トリガーする必要はない」という判断になった。
| Phase | 内容 | 投資規模 |
|---|---|---|
| 1. 基盤構築 + 手動検証 | Jenkins 上に LLM エージェントの実行環境を構築する。Webhook 等の自動トリガーはまだ入れず、手動で実行。過去のインシデント PR や日常の PR を対象にレポートの質と有効性を評価する。 | 小 |
| 2. 判断 | 手動運用の実績をもとに、自動トリガーの範囲とコストを判断する | — |
| 3. 自動化 | Webhook 連携による自動トリガー、ルールの集中リポジトリ構築、対象リポジトリの段階的拡大 | 中 |
Phase 1 で実行環境を先に揃えておくことで、自動化に進む際は Webhook を繋ぐだけで移行できる。検証環境と本番環境で挙動が違う、みたいな問題も起きない。
LLM をエージェントとして動かすコストについても、最初は手動トリガーなので PR ごとにかかるコストを実際に測りながら判断できる。全 PR に対して実行するか、リスクシグナルに該当する PR だけに絞るかは、実績を見てから決める。
現時点での率直な評価
CARE で解決しようとしている問題は2つ。
- 「調べるべきだという認識がなかった」→ ルールが担う
- 「調べたくても横断検索が難しかった」→ LLM が担う
前回の分析で、根本原因は「認識」と「実行」の両方にあると整理した。CARE はその両方を、既存の CI 基盤の延長線上で、現実的なコストで解決できる可能性がある。
一方で、定着するかどうかはまだわからない。特に「ルールが育ち続けるか」という点。CARE の自己強化ループが実際に機能するかは、Phase 1 の検証で確認する必要がある。
まだ設計の段階で、これから試すところ。引き続き検討の経緯を書いていく。
この記事は役に立ちましたか?

この記事が、何かの整理につながったら
コーヒー1杯分の応援をもらえると嬉しいです。
あなたへのおすすめ
