概要
AI エージェント(Claude Code など)は、与えた検証境界にぴったり最適化して、そこで止まる。その結果、局所的に正しい修正が「変更箇所と無関係な遠い場所」で静かに壊すことがある。これは「エージェントがミスした」のではなく、指示側が『完了の定義(検証境界)』を狭く与えたために起きる。境界を blast radius(変更の影響範囲)に合わせて広げるのは指示側の責任である。具体的な事故例は Django の on_commit と TestCase を参照。
詳細
なぜ AI 特有の罠なのか(3つの性質)
- 最小差分バイアス — 「diff を局所に絞るほど良い仕事」と方向づけられ、自分から影響範囲を広げない
- 完了宣言バイアス — 指定チェック(新ユニットテストが緑)が通った瞬間「完了」と宣言したがる。ゴールが「テストが緑」であって「変更が安全」ではない
- 暗黙不変条件を見ない — 指示の視界に入っていない前提(例:「このテスト群は on_commit 非依存という契約で高速化した」)は参照しない
指示に組み込む項目
- 変更ではなく blast radius を定義させる — 共有層を変えたら、その経路を叩く呼び出し元とテストを grep で全列挙し、各テストを実行モデル(commit/rollback・sync/async・mock/real)で分類させる
- 依存する/破る不変条件を言語化させる — 新たに依存する前提・破る前提を箇条書きに
- 「テストが緑」を完了基準にしない — 変更経路を実際に実行するテストが、マージ先ブランチ上で新コードを通って緑であることを確認(checkout の鮮度も)
- 「正しいコード」と「安全な変更」を分ける — framework イディオム(on_commit / 非同期 / cache / signal)はテストと本番で挙動が変わる
- 検証は書いた本人にやらせない(敵対的レビュー) — 別コンテキストに「どこで・どの実行モデルのテストを壊すか」だけを探させる
- 「監査 → 修正 → 横断テストスイープ」を1手順に固定 — 横断変更なら PR 時点で全体監査を回す
敵対的レビューは別モデルを使うべきか
「別モデル」より「別コンテキスト+敵対的プロンプト」が本命。バイアスは文脈に宿るので、新規コンテキストに「反証せよ/デフォルトは有罪」と指示するだけで同一モデルでも効く。別モデルが要るのは以下の切り分け次第。
- A. 注意・スコープの盲点(見なかった) — プロンプトで注意を向ければ直る。別モデルはほぼ寄与しない
- B. 共有された誤信念(見たが両方とも間違い) — 同一モデルは新規コンテキストでも同じ誤信念を共有する。ここで初めて別モデルファミリーが効く
最も弱いのは同一モデル・同一コンテキストの自己レビュー。まずそこから脱するのが最優先。
CLAUDE.md への落とし込み
これらは1タスクの指示だけでなく CLAUDE.md に常設ルールとして書ける(むしろ指示し忘れても毎回効く)。汎用語を自プロジェクトの実名(基底クラス・層・監査ジョブ名)に具体化するのがコツ。ただし適用対象のないリポジトリ(Hugo サイト等)に足すのは逆効果でノイズ・キャッシュ効率低下になる。
関連ページ
- Django の on_commit と TestCase — この一般論の具体的な事故例
- Brownfield リファクタリング — 「正しさの後退」を防ぐ安全網の張り方
- 自律改善システムの設計 — 安全ゲートと人間の役割
- 自動テスト修正パイプライン — 横断スイープを手順化した実装
ソース記事
- AI エージェントにリファクタさせるときの「完了の定義」の引き方 — 2026-07-08