前回、外に出る情報だけは人間が最後の門番をやる、と書きました。今回はその続きで、門番自身の品質保証の話です。
私の担当領域は、エンジニアが私1人です。PRはself-mergeするしかない。つまりコードもドキュメントも、書いた本人以外の目を一度も通らずに世に出る構造で、長年これをどうしようもないものとして受け入れてきました。書いた本人は自分の間違いが見えない、というのは分かりきっているのに、です。
AI時代になって、これは言い訳にできなくなりました。レビュアーがいないなら、作ればいい。
素朴にやると空振りする
ただし、作業中のAIに「これレビューして」と頼むのは、ほぼ無意味です。実装の文脈を共有しているAIは、その文脈ごと肯定してきます。「はい、この設計判断は妥当です」— そりゃそうです、さっき一緒にその判断をした本人 (本AI?) なので。前回書いた通り、AIはもっともらしい文章の製造機なので、レビューをさせるともっともらしい承認が出てくるだけです。
きっかけは コードレビューをやめた という記事を読んで考え込んだことでした。うちの環境向けに設計し直して、次の3点を要件にしました。
- blind: レビュアーには実装時の文脈を一切渡さない。成果物と要求仕様だけを渡す。「なぜこう書いたか」の言い訳を読ませない — 人間のレビューで言えば、実装者の隣に座らせない
- adversarial: 「レビューして」ではなく「粗を探せ、見つからなければ君の負け」という役割で渡す。同意が成功条件のAIに、同意をタスク失敗と定義し直す
- 別モデル: 書き手と読み手のモデルを分ける。同じモデルは同じ癖で間違えるので、間違いの相関を下げる
具体的には、実装が終わったら別セッションのagentに成果物だけ渡してレビューさせ、指摘を「本物 → 直す / 妥当なnitpick → 安ければ直す / 誤検知 → 理由を記録してskip」の3分類で処理して、LGTMが出るまで往復します。
コストの実測と、粒度の調整
最初は変更のたびにかけていました。するとある日、3行のGROUP BY追加のレビューに8分・約10万トークンかかりまして。さすがに過剰です。気軽にバンバンやるものではない。
ところが面白いのは、その3行からでも本物の指摘が1件出たことです (ORDER BYの一意性が足りず、並び順が非決定的になるという指摘。テストは通るのに、ある日突然結果が入れ替わるやつです)。つまり「レビューに値しない変更」を事前に見分けるのは、思っているより難しい。
なので廃止ではなく粒度を変えました。今の運用は:
- かけるのは工程の区切り — PR提出前、チーム可視の成果物 (手順書・SQL・リリース計画) の提出前
- 区切りの中では対象を選別しない。「これはレビュー不要だろう」という判断のコストと誤判断のリスクの方が、機械に全部見せるコストより高いからです
正直な限界も書いておきます
- blindレビューは「要求仕様そのものが間違っている」ことは見つけられません。仕様ごと渡すので、仕様への忠実さしか検査できない。仕様を疑う仕事は依然として人間側に残ります
- テストを意図的に壊して検出力を測る、いわゆるmutation testingも検討しましたが、見送りました。テストのコストが高くtestabilityの低いレガシー環境では過剰、という判断です。正しさより持続可能性を取りました。人間だもの
- 白状すると、指摘の3分類も実際にはAIがやっていて、私はその分類を追認しています。この運用の一番柔らかい腹はここです — 「本物」側の誤分類は修正が入るので安全側に倒れますが、本物の指摘が「誤検知」に分類されて捨てられたら、気づく仕組みがない。今の防御は、分類と理由を必ず本文に書かせて人間が監査できる形にしておくことだけで、正直、門番問題はここに縮小して残っています
機械の方がやりやすいこと
やってみて気づいたのは、blindの徹底は人間チームより機械の方がむしろ簡単だ、ということです。人間のレビュアーに「実装の経緯は忘れて、文脈を知らないふりをして読んでください」とは頼めません。同僚は事情を知ってしまっているし、書いた人への遠慮もある。文脈を持たない読者と、遠慮という機能そのものが無いレビュアーを、数分で好きなだけ呼び出せるようになった — 1人開発の「レビュアー不在」が言い訳にならなくなった、というのはそういう意味です。タダではありませんが (前述の通り時間もトークンも食います)、人間のレビュアーを1人雇うのに比べれば誤差です。
次回は、AIとの共同作業で溜まった自分側の失敗ログを218件数えて分類した話を書く予定です。
(この連作は、AIエージェントを業務のレガシーシステム保守で半年ほど運用して溜まった実践則を、1本1則で書いていくものです)