AIが書いたコードを、私は読まない。それでも重大なバグを2件見つけた

紙にはこう書いてあった。

異常の有無:有

手書きで、はっきりと。その紙の写真を読み取るために私が作った仕組みは、こう返してきた。

✅ 判定した3件に異常はありませんでした

異常があると書いてある紙を見て、異常はありませんと答えた。

このバグを見つけたとき、私はコードを1行も読んでいない。読めないからだ。それでも見つかった。この記事は、コードが読めない側の検証方法の話をする。

「AIコードのレビュー観点5つ」は、私には実行できない

「AI 生成 コード 検証」で検索すると、良い記事がたくさん出てくる。ブラックボックステストとホワイトボックステストの違い、境界値、nullや想定外の型、非同期処理のエラー。どれも正しい。

ただ、全部コードが読める人向けに書かれている。分岐を追える、変数の中身を想像できる、テストコードを自分で書ける。その前提で成立している話だ。

私は会社員で、副業でネットショップと小さなツールを作っている。コードはほぼ全部Claude Codeが書いていて、私が書くのは日本語の指示だけだ(この体制の全体像はこちら)。画面に流れてくるコードは、正直、雰囲気しか分からない。

その私が、コードレビューの記事をいくら読んでも、実行できる項目はゼロだった。

だから諦めて、逆側からやることにした。 コードは見ない。入れるものを見る。

やったこと:手書きの紙を3枚、わざと違う品質で用意した

作っていたのは、手書きの記録紙をスマホで撮って送ると、未記入や異常を指摘して返してくれる道具だ。作業日報や点検表のような、毎日書かれてそのあと誰かがExcelに打ち直している、あの紙が対象になる。

8月24日、動作確認のために紙を3枚用意した。ポイントはここで、わざと品質を変えた

用意した紙 何を確かめたかったか
A:ていねいに書いた1枚 ふつうに動くか
B:急いで書いた1枚(異常あり) 汚い字でも読めるか・異常を拾えるか
C:空欄のある1枚 書いていない欄を見つけられるか

3枚を通して、AとBとCで返ってきた文章を並べた。それだけだ。コードは開いていない。

結果、BとCの両方でバグが出た。

見つかったバグ1:正しいことしか言っていないのに、全体としては嘘

Bの紙は、冒頭に書いた「異常の有無:有」の紙だ。返ってきたのが「判定した3件に異常はありませんでした」。

このとき私が引っかかったのは、日本語のほうだった。

判定した3件に異常はありませんでした(9件読み取り)

9件読み取って、3件しか判定していない。 残りの6件はどこへ行った。

AIに「読み取った9件のうち、判定していない6件は何か」と聞いたら、そこに「異常の有無:有」が入っていた。判定するルールが設定されていなかったので、集計から静かに外れていた。

嘘は言っていない。判定した3件については、本当に異常がなかった。判定対象から外れた6件のうち1件が、いちばん見落としてはいけない「異常の有無:有」だった。それを言わなかっただけだ。

ここは分けて書いておきたい。間違っていること自体は、紙と返事を見比べれば分かる。「有」と書いてある紙に「異常なし」と返ってきたのだから、コードは関係ない。

ただ、なぜそうなったのかを追えたのは、9と3という数字が並んでいたからだ。「異常はありませんでした」の一行だけが出る画面だったら、私は「読み取りをミスったのかな」で止まって、原因にたどり着けなかった。私がやったのは引き算だけだ。

見つかったバグ2:誰も書いていない欄が「異常なし」に化けた

Cの紙で出たほうが、ずっと怖かった。

日本の帳票には、こういう欄が大量にある。

異常の有無: 無 ・ 有

「無」と「有」が印刷されていて、どちらかに丸をつける形式だ。Cの紙では、この欄に誰も丸をつけていなかった。ただの空欄。

仕組みは、そこから「無」という文字を拾ってきた。印刷されている「無」を、誰かが記入した答えだと思ったのだ。 そして「異常なし」と結論した。

紙の上には、誰の意思も存在していない。にもかかわらず、記録には「異常なし」と残る。

人間なら一目で空欄だと分かる。その区別を、私はAIへの指示に書いていなかった。「丸が付いていない選択肢は、答えとして拾わないで」と後から書いたら、ちゃんと区別するようになった。

私が「空欄のある紙」をわざわざ用意していなければ、この経路は一度も通らなかった。

なぜ、うまくいく例だけでは見つからなかったのか

ここが今回いちばん腹に落ちたところだ。

Aの紙——ていねいに書いた1枚——は、最初から完璧に動いていた。 ✅が返ってきて、読み取りも全項目正確で、これは良いものができたと思った。

もしAだけで確認を終えていたら、私は2つのバグを抱えたまま公開していた。しかも厄介なのは、バグを抱えたまま、それらしい報告書は毎日出続けることだ。エラーも出ない。画面も崩れない。ただ、中身が間違っている。

AIに実装を任せていると、出てくるものはいつも整っている。整っているから、動いたと思ってしまう。私が確認していたのは「動いたかどうか」で、「間違ったときに、間違ったと言えるかどうか」ではなかった。

以前Claude Codeで副業を作った話に、事故は人間の手作業に集中する、と書いた。あれは半分だった。残り半分の事故は、人間が確認をサボった場所に集中する。

コードが読めない人の検証チェックリスト

用意した紙A・B・Cと、先に書いた正解、実際に返ってきた返事を並べた表。Aはていねいに書いた1枚で期待どおり。Bは「異常あり」の1枚で異常1件が出るはずが「異常はありませんでした」と返り不一致。Cは空欄のある1枚で未記入が出るはずが、空欄の「無」を読んで異常なしと返り不一致

今回のことを踏まえて、私が次からやることを5つに絞った。専門知識はいらない。

1. 入れる前に、正解を1行で書いておく

これが一番効く。紙を渡す前に「Bは異常1件と返るはず」「Cは未記入2件のはず」と、期待する返事を先にメモしておく。

順番が逆だと、必ず負ける。返ってきた文章を見てから「合ってるかな」と考えると、整った日本語に引きずられるからだ。実際「判定した3件に異常はありませんでした」は、読み物としては完璧だった。先に正解を書いておけば、比べるだけで済む。

2. いちばん汚い入力を、最初に作る

きれいな入力は最後でいい。順番を逆にする。写真なら暗いもの・傾いたもの・欠けたもの、文章なら短すぎるもの・長すぎるもの、フォームなら全部空欄のもの。うまくいく例は、うまくいくことしか教えてくれない。

3. 数字が2つ並んでいるか確認する

「異常はありませんでした」だけでは検証できない。「9件読み取って、3件判定した」のように母数と処理数が並んでいると、素人でも引き算ができる。数字が1つしか出ていない画面を見たら、「全部でいくつあって、そのうちいくつ処理したのか出して」とAIに追加させる。これが今回いちばん効いた。

4. 「空欄」を必ず1回試す

入力しない、選ばない、送らない。人間が一目で分かる「何もない」を、機械は思わぬ形で埋めてくる。今回の「印刷された無」がまさにそれだった。

5. 「わかりません」と言えるか確かめる

判断できないものを渡して、無理に答えを出さないか見る。今回の道具は、修正後に「担当者名を『山口健』と読んだが自信がない」と申告して人間に投げ返してきた。断定しない返事ができるかどうかが、この手の道具の信用そのものだと思っている。

残る仕事は「正解と、失敗のさせ方を決める係」だった

AIに任せる範囲を広げるほど、自分の仕事が何なのか分からなくなる時期がある。私もそうだった。コードは書かない、調べ物もしない、文章も下書きはAIが出す。

今回やったことを並べてみたら、はっきりした。

どれもコードの中身とは関係がない。 そして4つとも、AIには決められない。AIは渡された素材に対して最善を尽くすが、「何が正解か」と「どこで失敗してほしいか」は外から与えるしかないからだ。きれいな紙しか渡さなければ、きれいな紙で動くものが返ってくる。手抜きではなく、そういう仕組みだ。

急いで書くと字がどうなるか、面倒な欄はどこが空欄になりがちか。それを知っているのは、その紙が使われる現場を想像できる人間のほうだ。コードが読めないことは、この仕事の妨げにならない。

私はしばらく、この係でやっていくつもりだ。


関連記事

同じ日の出来事を、作り手の側から書いたnote記事(「異常あり」と書かれた紙が「異常なし」で返ってきた話。もう1件のバグと、それを直したら別の経路が開いた顛末まで) → Claude Codeで副業は作れる。詰まるのは作ったあとだった会社員の副業ECを、AIエージェントに「ほぼ任せて」回している話副業の固定費は月8,300円だったAIで副業を回すのに買った道具は3つ