← すべての記事

信頼はCode Reviewの中には宿らない

Tenny

著者 Tenny

Cofounder & CTO & AX Designer

公開日 2026 年 6 月 30 日

あなたがなっていたゲート

Agent は、人が読める速度を超えてコードを書く。これは予測ではない。今の基準線だ。1 つの Agent は午後のうちに、チームが 1 週間かけて丁寧に読む量を超えるコードを出荷する。Code Reviewは、書くことと読むことが同じ速度で起こると静かに仮定していた。初めて、その仮定が崩れた。

だから悪い選択肢が 2 つ残る。線を守ってすべてを読み続ければ、チーム全体が後ろに並ぶスロットルになる。通してしまえばレビューはスタンプになる。多くのチームは静かにスタンプを選んだ。最悪なのは、すり抜けるバグではない。見逃したバグは取り戻せる。偽の確信は取り戻せないし、それは予定どおりに量産される。スタンプは信頼の感覚だけをまだ生み出し、あなたはその感覚に乗って出荷する。あなたは信頼づくりに失敗しているのではない。偽物をつくっている。

でも一歩引いてほしい。そもそもゲートは目的ではなかった。必要なのは読むことではない。プロジェクトを制御できていること、そしてそれに根拠ある信頼を持てていること、つまり自分が何を出荷しているかを知っているという立った確信だ。diff を読むことは、いつもただの代理でしかなかった。それ自体と取り違えられただけだ。外部に渡せないのは、制御と信頼だ。それはあなたのものとして残る。 読むことは、それを行うのに最も適した誰か、あるいは何かに渡せる。

書けないなら、読めない

まず、あなたが読んでいたことに価値があった理由から始める。それはあなたが慎重だからではない。レビューの質は、それをする開発者の質で決まる。そして開発者をよくするものは 1 つしかない。手が十分な頻度でコードの中にあり、細部を生きたまま保持していることだ。その生きた理解こそがレビューのエンジンで、読むことはそれが表に出る場所にすぎない。それを奪えば、読むことは空の動作になる。目が行をなぞるだけだ。

Agent の時代は、1 つの理由であなたをその開発者の位置から引き離す。その理由は 2 つの形で現れる。あなたと Agent は、コードに対して同じ払い方をしない。コストモデルが違い、すべてはそこから続く。

リアルタイムでは、その差は速度として見える。Agent はほぼゼロの限界コストで反復する。その中で人間が手で書くと、仕事が待たされる低速レーンになる。正直な一手は止まって Agent を走らせることだ。そしてそうした瞬間、生きた理解は薄れていく。もう自分でそれをつくっていないからだ。

コードベース全体では、同じ差が一貫性として見える。これは追いつけるほど速い人間にも当てはまる。コードベースとは、1 つのコストモデルが下した千の小さな判断の結晶だ。重複がリファクタリングに値するか、どれだけのログがノイズに見合うか、境界が実際にどこに落ちるか。Agent は、疲労や退屈でログを削ったりリファクタリングを飛ばしたりすることなく、その厳密さを均一に保つ。人間が手で入り込むと、より悪いコードを書いているわけではない。ただ別のコストモデルに最適化されたコードを書き、別のモデルに合わせて調整されたシステムへ落とし込むので、システムを読めるものにしていた一貫性が割れる。高いレベルはあなたのものとして残る。システムは何のためにあるのか、どこへ行けるのか、どのリスクを先に見ておく価値があるのか、どのトレードオフを取る価値があるのか。下にある実装の粒度は、コードのコストを払っている側へ落ち着く。

率直に言えば、これはすでにあらゆる場所を支配している体制ではなく、私たちが向かってつくっている特定の体制の中での話だ。プロジェクトが Agent-native になり、Agent がその領域で少なくともあなたと同じくらい強く、コードベースもすでに Agent の粒度でできているなら、人間は速度の面でも粒度の面でも、もう本当にはコードを書けない。そしてコードを書けない人間は、レビューできるほど生きたままそれを保持できない。自然法則ではない。だがその体制の中では結論は硬い。レビューを続けるなら、あなたはもう判断する立場にない行を目で追っているだけになる。Agent がプロジェクトを速くしていないとき、ボトルネックがほとんど常に、まだ手で書き手で読んでいる 1 人の人間である理由もこれだ。信頼でも、方向感でもない。それらは残る。ボトルネックは、まだキーボードに置かれた手だ。

これは新しい話ではない。Agent の時代が、それを無視できなくしただけだ。信頼はCode Reviewの中には宿っていなかった。今も、以前もそうだ。大きなプロジェクトを舵取りする人はコードを読まない。あなたが知る最もシニアなエンジニアは、自分が責任を持つシステムを最後にいつ 1 行ずつ読んだだろうか。彼らは下にいる人への信頼と、おおまかなアーキテクチャの読みで舵を取る。それを無謀とは誰も呼ばない。1 行ずつ読むことは、下の層が払えたものだった。そして払えたことが、信頼することと取り違えられた。Agent の時代は、すべての層を、上の層がずっといた位置へ押し出しただけだ。

では信頼はどこから来ていたのか。長く一緒に働いていて予測できる作者、負荷の下でも保つテストスイート、システムが 100 回動くのを見てきた相棒、問題なく戻ってきた beta、3 回のリリースをまたいで静かなダッシュボード。Code Reviewは、その集合の中でもいつも弱いチャネルの 1 つだった。それが指し示しながら、決して十分には届けられなかったものは、1 つの問いへの答えだった。システム全体はまだ保たれているのか。量が増えても、その問いは消えない。むしろ鋭くなる。そしてそれには、diff ではなかった計器が必要になる。

速いコード、速い腐敗

変化の下でシステムが年を取るほど、あなたのものに見えるプログラムの数は増えていく。若く締まったシステムでは、生き残るものはほとんど同じプログラムだ。手を入れずに年を取らせると、同じ spec、同じ green check なのに、互いに一貫しない実装の巨大な空間がすべて通るようになる。その広がりはエントロピーの一種で、この言葉が正しいのは方向があるからだ。放っておけば、それは増えるだけだ。鋭い境界と正直なテストはそれを削る。近道と重複した source of truth は、それをまた生やす。

これも新しい話ではない。Lehman は 1970 年代に書いていた。使われているプログラムは、誰かが本当に手間を払って抑え込まない限り、リリースを重ねるごとに複雑さを増していく。software rot、code decay。この分野には、ソフトウェアを出荷してきたのと同じくらい長く、そのための言葉があった。新しいのは現象ではない。温度だ。 動くプロダクトは 1 時間で立ち上げられ、翌日には保守不能なものとして放置される。どちらも同じ速度で起こる。Agent がエントロピーを発明したのではない。かつて速度を抑えていたもの、人間がコードを書き読める速さを取り払って、温度を上げただけだ。

速度が方法を追い越すと、緑のシグナルは形を増殖させているシステムを隠してしまうことがある。

エントロピーの上昇は、1 つの喪失として感じられる。自分のシステムをもう予測できない。ここを変える前に、あちらで何が起きるかを言えない。システムへの信頼とは、いつもこれだけだった。それを予測できること。 感覚でも、green check でもない。そのものがどう振る舞うかを知っているという、獲得された確信だ。diff はそれを返してくれない。diff が見せるのは 1 つの変更であり、予測は全体の性質だからだ。だから問いは、ある diff が正しいかどうかではない。全体のエントロピーが上がっているのか、抑えられているのかだ。それは読める。そしてそれを読むのに diff はいらない。

diff を読むのをやめる

では、すべての diff を開かずにエントロピーをどう読むのか。diff は変更を見せる。システムを見せることはできない。 diff を読むのをやめ、システムを読み始める。テストスイートとダッシュボードは、信頼が来ていた場所だった。下にある信号は、システムが動いている最中に、それを今読む方法だ。

レビューは成果物を読む。目の前の変更を 1 行ずつ読む。だが知りたいのは、どれか 1 つの変更の性質ではない。システム全体の性質だ。そしてシステム全体は、誰もファイルを開かなくても、常に自分自身について語っている。信号を出している。あなたはそれを読む。だからレビューが届かなかった場所でこれが働く。レビューは成果物に向けられていたが、知る必要があったことは、そもそも成果物の中になかった。

バグリストは最も直接的だ。予測ではなく、システムがすでに間違った場所の記録だからだ。バグは集まり、その集まりが地図になる。同じモジュールが週をまたいで表に出続け、同じ contract が毎月新しい edge case を増やす。そこからシステムが漏れているからだ。Agent の失敗は特に読みやすい。Agent のミスはたいてい、きれいでなかった入力へ戻っていくからだ。曖昧な contract、ある case を言い残した spec。人間は習慣で補って隙間を隠す。Agent はそこに歩いて入り、場所に印を付ける。

他の信号は、まだ壊れうる場所を報告する。mutation testing は、動いているコードの条件を反転したり branch を消したりして、どれかのテストが赤くなるかを問う。生き残った mutant は、あなたのスイートがまだ祝福している、間違った版のプログラムだ。「テストが通る」と「振る舞いが固定されている」の正確な隙間である。静的な構造は、壊れ始める場所を示す。branch で太った関数は、spec が必要とする以上の状態を持つ。2 か所に保存された事実は、いつか誰かが片方だけを更新し、もう片方を忘れる日を招く。そして Agent が並んで働く場所では、1 つの信号がリアルタイムに出る。変更が衝突するかどうかだ。重要な衝突は、2 つの Agent が隣り合うコードに触ることではない。それは普通の並行作業だ。重要なのは、同じ seam が何度も争われることだ。そこでは境界が間違っている。

地図は、どこを狙うべきかも教える。バグリストが濃く、branch が最も深い場所には、未知のバグも最も濃い。だからそこへテストフレームワークを向ける。coverage の数字を盛るためではなく、絡まった領域に隠れた失敗を洗い出す case をつくるためだ。見つかったバグは、その上でテストが赤から緑へ変わって初めて 1 回分として数える。そうして修正は固定され、静かに戻れなくなる。

しかし green test は無料の品質ではない。多くのスイートがあなたに嘘をつくのはここだ。テストが緑である価値を得るには、そのチェックが硬くなければならない。実際の振る舞いに対して、実際の payload 上で assertion し、本当の regression なら赤くなる必要がある。そして振る舞いが通る path をまたいで完全でなければならない。ある path で通り、別の path が実行されていないなら、それは通っているテストの服を着た未テスト case だ。コードの形を見て、その効果を見ていないテストは、何にも配線されていない green light である。同じ疑いを、すべての信号に向ける。静かなバグリストは、そのモジュールが健全だという意味かもしれないし、誰も使っていないという意味かもしれないし、instrumentation が暗くなったという意味かもしれない。信号がないことは、それが発火したはずだと確立して初めて意味を持つ。だからあなたは、diff に対して捨てようとしていた基準を、それぞれの計器にも課す。失敗できると証明して初めて信頼する。品質はチェックの硬さに宿る。誰かが行を読んだことには宿らない。

これに寄りかかる前に、2 つの正直さが必要だ。第一に、これらの読みの多くは遅れて届く。バグリストはすでに壊れた場所であり、生き残った mutant はすでに持っているテストの隙間だ。腐敗が着地した一拍あとで捕まえる。何も捕まえないスタンプよりはよいが、予防ではない。予防は上流、入力の中へ移る。そして単独の読みは全体像ではない。複数を読み、三角測量させる。第二に、高エントロピーがすべて decay とは限らない。100 個の extension が 1 つの interface を満たす plugin system は、数えれば非常に高エントロピーだが、それは設計が意図どおりに働いているということでもある。信号はエントロピーの場所を示す。どの種類かまでは教えてくれない。その判断は無料ではない。

レビューはイベントであり、信頼は状態である

このすべてが diff から離れなければならなかった理由は、速度よりも深い。レビューは、あなたが保持しようとしているものに対して形が違う。レビューはイベントだ。信頼は状態だ。 イベントは一度起こり、判定を残して消える。あなたが信頼しようとしているシステムの中には何も蓄積されない。状態こそが実際に欲しいものだ。自分のシステムを予測できるという立った確信。そして何も残さないイベントから状態をつくることはできない。これがタイトルの指していた文だ。イベントは状態を住まわせられないので、信頼はCode Reviewの中には宿らない。イベントを 1000 回走らせても、まだそのものは手に入らない。信号は連続しているので、信頼はそこから蓄積する。スタンプには最初からできなかった。

だから、信頼の計器としてのレビューは去る。コードを読むことが消えるのではない。理解が宿る場所へ移る。Agent の時代では、それはコードを書いている Agent であって、あなたではない。細部に何度も手を入れているのは彼らだ。去るのは、あなたがゲートとしてそれを行うことだ。そして人が最初に持ち出す高リスクの case、security boundary、不可逆な release こそ、疲れた人間のスキャンがいつも最も苦手だった場所だ。今それらは、より強いものに乗る。違反を型システムが不可能にする property、assertion が硬い check、読むことが見逃した regression を monitoring が捕まえる staged rollout。

ここで信号を読むことは、観察以上のものになる。それぞれが原因へ戻る。生き残った mutant は、誰も固定していなかった振る舞いを指す。ずれた境界は、1 つの意味を持たなくなった contract を指す。バグリストの cluster はもっと深いところを指す。このコードは有能な model によって書かれている。だからあるモジュールがバグを出し続けるとき、最もありそうな原因は、その model がそこに弱いことではない。そのモジュールの interface が、それに向き合うものすべてを誤導していることだ。バグは、境界が間違っているとシステムが教えている声である。だから、いま作ったテストフレームワークの下でそれをリファクタリングする。そのフレームワークが振る舞いを固定するので、すべての変更は、振る舞いを保っていると証明されるか、本物のバグとして表に出る。

ほとんどの場合、次の一手は「次の diff をもっと厳しくレビューする」ではない。失敗をそのまま扱うことだ。ループへの診断入力として扱う。失敗は model への判決ではない。あなたがきれいにしなかった入力の地図だ。 それは、あなたが与えたどの条件がまだきれいでなかったのかを正確に教える。そう見えると、Agent のミスはそれが生み出す最も価値あるものになる。1 つ 1 つが、ほかの方法では見えなかった隙間へのラベル付きのポインタだからだ。

これは役割で考えると最も感じやすい。アーキテクチャを設計する Agent が失敗する。その原因は、たいてい推論ではない。mission、あなたが向かっている方向が、入力として十分に明確にされていなかったことだ。実装を書く Agent が失敗する。その原因は、たいてい知能ではない。environment、test surface、validation harness が整っていなかったこと、あるいはあなたの引いた境界が Agent を誤導したことだ。あなたの意図に対してテストする Agent は、大事だったものを見逃す。意図が、テストできるほど明確に表現されていなかったからだ。失敗は Agent で止まらない。鎖を上へ移動し、入力へ着地する。あなたが曖昧に言ったこと、つくらなかった surface、柔らかいまま残した boundary へ。

そこでループが閉じる。エントロピーが上がっている場所を読み、それを上げさせた入力まで失敗をたどり、その入力を締める。時にはより鋭い spec にする。時には model を誤導した contract をリファクタリングする。そして最も強い場合には、そもそも失敗が起きない設計に変える。悪い状態を表現不能にする型、あとで check するのではなく構造によって enforced される invariant だ。その最後の一手が届くのは、illegal state として符号化できる失敗だけである。外部要因や timing の失敗、応答しない credential、2 つの service の race は還元できず、前に述べた硬い check と staged rollout に戻る。システムは、誰かがより多くのコードをレビューしたから予測しやすくなるのではない。それぞれの失敗を使って条件をより真にしたから予測しやすくなる。

実践を一文で言えばこうだ。ゲートを守るのをやめ、システムを読み、それに入る入力を締め続ける。Agent が誰よりも速く動き、誰も読み切れなくなったあとで、品質と速度を同じ手の中に保つために、私たちが見つけた唯一の方法だ。

そして 1 つの問いが残る。この文章全体が向かってきた問いだ。あなたがもうゲートではなく、コードを読む人ですらなくなり、一日がシステムを読み、それに入るものを締めることになるなら、人間の仕事とは正確には何なのか。それが次の記事だ。

編集 Alice, Megan & Cindy