第0回 なぜ「通った」を信じてはいけないか

2026-08-20 時点 / 例は bash 5 系・Python 3 + pytest で実行して確認
この回で分かること

この回は研修の導入部で、全文を公開しています。コマンドと出力はすべて手元で実行したものをそのまま載せています。シェルと Python があれば再現できます。

1エージェントは「できたように見えたら」止まる

Claude Code の公式ドキュメントにはこう書かれています — Claude は作業が「終わったように見えた」ときに止まる。 自分で走らせられる検査がなければ、「見た目」が唯一の判断材料になり、あらゆる誤りがあなたの発見待ちになる。

これは Claude 固有の話ではなく、合否を自分で確かめる手段を持たないすべてのエージェントに当てはまります。 そして多くの現場では、そこで人間がレビューに入る。つまり人間が検証ループの一部になっている。コードが書かれる速さが人の読む速さを超えた今、このループは破綻します。

この研修の主張。 「AI の報告を人が確かめる」をやめ、AI にも人にも同じ検査を機械的に通させる。 エージェントに合否を返すものを渡せば、ループはエージェント自身で閉じます。人は検査を設計する側に回る。
2「通った」が嘘になる 3 つの型(手元で再現)

型 1: 終了コードがパイプで消える。 エージェントはしばしば cmd | tail のように出力を絞って実行し、$? を見て「成功」と判断します。

$ false | tail -n 1; echo "rc=$?" rc=0 # false は失敗したのに、tail の成否が返っている $ out=$(false); rc=$?; echo "rc=$rc" rc=1 # パイプを挟まなければ本体の成否が取れる

研究室では Bash の出力を圧縮するフィルタを常用しており(実測で約 8 割削減)、便利な反面成否の判断材料まで削られる。 だから「成否は終了コードと成果物で見る。見た目で判断しない」がルールになっています。

型 2: 検出力のないテスト。 AI にテストも書かせると、「通るテスト」はいくらでも書けます。税込み価格の関数に対して AI が書いたテストを例にします。

# tax.py def price_with_tax(p: int) -> int: return p * 110 // 100 # test_tax.py(AI が生成) from tax import price_with_tax def test_non_negative(): assert price_with_tax(1000) >= 0 def test_runs(): price_with_tax(999)
$ python3 -m pytest -q 2 passed in 0.03s # 税率を 108 に壊す $ sed -i 's/110/108/' tax.py; python3 -m pytest -q 2 passed in 0.01s # 関数の中身を return 0 にしてしまう $ python3 -m pytest -q 2 passed in 0.00s

return 0 でも全テストが通ります。エージェントの報告は「2 件のテストがすべて通りました ✅」。嘘ではないが、何も保証していない。 テストが通っているのは、検出力が無いからかもしれない。 「わざと壊したら落ちるか」を測らない限り、緑が本物かは分かりません(第 3 回: 変異注入)。

型 3: 沈黙する検査器。 型検査器・重いビルド・長い探索は、成功しても、メモリ監視に殺されても、最後に出る 1 行が同じことがあります。 キャッシュ済みのビルドも「何も再検査せずに一瞬で成功」と見える。これは次の節の事故そのものです。

3研究室で起きたこと — OOM kill を 4 回「通った」と報告

2026 年 8 月 8 日、研究室の Agda による形式化(約 1 万行)の型検査をエージェントに走らせました。エージェントは 4 回続けて「型検査が通りました」と報告しました。 実際には、検査器は 47GB のメモリを使ってメモリ監視(earlyoom)に SIGTERM で殺されていた。 成功時も、殺されたときも、ターミナルに出る最後の 1 行は同じ Checking … で、エージェントはそれを成功と読んだのです。

人間も同じ間違いをします。問題は AI ではなく、「見た目」以外の判断材料を渡していなかったことでした。それ以来、研究室では次をルールにしています。

罠何が起きるか対処
OOM kill と成功が区別できない最後の 1 行が同じ成果物の生成で確かめる(.agdai / .vo / .olean / ビルド産物 / DB)
パイプで終了コードが変わるcmd | tail; echo $? は tail の成否out=$(cmd); rc=$?
出力が圧縮されている成否の判断材料も削られる終了コードと成果物で見る
キャッシュ済みビルド何も再検査していないのに一瞬で「成功」キャッシュ済みビルドを検証と呼ばない
緑が本物か分からない検出力が無いだけかもしれない変異注入で「わざと壊したら落ちるか」を測る
「走っていない検査」は「異常なし」と区別がつかない。 だから研究室では、レビューや検査を実行していないときは「⚠ 検査していません」と明示的に書き、エージェントにもそう振る舞わせています。 沈黙を「問題なし」と読ませない — これが運用の基本姿勢です。
4今日からできる最小の対策 — 主張ではなく証拠を出させる

全 8 回のうち、この回だけ読んで帰るなら、これだけ持ち帰ってください。エージェントへの指示に次を足す。

方針弱い指示強い指示
判定条件を渡す「メール検証の関数を書いて」「validateEmail を書いて。a@example.com は true、invalid は false、a@.com は false。実装後にテストを走らせて」
症状と直り方を渡す「ビルドが失敗する」「このエラーでビルドが落ちる:[貼付]。直してビルドが成功することを確認して。エラーを抑制せず根本原因を直して」
再現テストを先に「ログインのバグを直して」「セッション期限切れ後にログインが失敗する。まず失敗するテストを書いて、それから直して」
証拠を出させる「できたら教えて」「実行したコマンド・戻り値・テスト出力を貼って。『成功しました』だけの報告は不可」

証拠を読むほうが、自分で再実行するより速い。そして、見ていなかったセッションにも効きます。 これを「お願い」ではなく機械的な保証(ターンを終わらせないフック、コミットを止めるゲート)に変えていくのが第 2 回以降です。

5この回のまとめと、次回

第 1 回では、受講者が普段使っているエージェントに対して、上の「強い指示」を実際に書き、証拠つきの報告が返ってくるまでを 90 分で体験します。

第 1 回以降は企業研修として実施する予定です(現在は募集していません)。開講時の案内をご希望の方はこちら。
カリキュラム全体を見る → 発展編: Lean/Rocq で AI 生成コードを検証する(第 0 回)→
カリキュラム一覧 第1回 判定条件を渡す(受講者向け)