AIの報告を、そのまま信じないための検証術

AIの報告を、そのまま信じないための検証術

「テストは全件成功しました」という報告と、実際に全件が実行されたかどうかは別の事柄です。前々回、そう書きました。第3回は、その差をどう埋めているかという話です。

結論を先に書きます。検証コマンドそのものが誤っていることのほうが、TAKTの報告が誤っていることより多いのです。

1. 「0件でした」は、実行できていないことの言い換えかもしれない

型チェック(tsc --noEmit)のエラー件数を grep -c 'error TS' で数え、「0件」という結果を得たとします。安心していいでしょうか。

安心できません。 tsc がそもそも起動していなくても、エラー行は0件になります。「エラーが無い」と「実行できていない」を、件数の確認では区別できません。

実際にこの環境では、npx tsc --noEmit を実行すると npx という名前の npm スクリプトへ解決されてしまうという癖がありました。TAKT の側からも「npx tsc は shim に阻まれて実行できない」という報告が出ていたにもかかわらず、grep -c による確認では「0件」という、矛盾に気づけない結果が返ってきました。

対処は、件数ではなく終了コードで判定することでした。

npm --prefix backend run build   # 終了コード0を確認する
npm --prefix frontend run build

npm run buildtsc を含み、型チェックとビルドの成立を同時に確かめられます。判定は必ず exit=0 かどうかで行い、エラー件数の grep は判定に使いません。

2. 報告の数字には「範囲」が付いていないことがある

TAKTが「12.6節の3エンドポイントは5件」と報告したとします。この「5件」を、そのままファイル全体の期待値として書いてよいでしょうか。

よくありません。 実際にこの数字をそのままファイル全体の期待値として書いたところ、実測は6件(節内5件+節外1件)でした。誤っていたのは期待値の側であり、TAKTの報告は最初から正確でした。「節内で5件」なのか「ファイル全体で6件」なのか、スコープを書かずに数字だけを転記したことが原因です。

これ以降、期待値には必ず範囲を添えています。「12.6節内で5件」「ファイル全体で6件」のように、どこを数えた数字かを明示します。

3. grep -c が向いていない場面がある

検証コマンドの誤りは、思わぬところに潜んでいます。実際に踏んだ落とし穴を3つ挙げます。

落とし穴 何が起きるか
grep -c "文字列" で1行あたりの出現回数を数える 1行に複数回現れても「1行」としか数えない。実測は str.count() を使う
grep -c で「削除されたか」「網羅されているか」を判定する 削除済みの語がコメントや注記に残っていれば0件にならない。該当行を表示して目で確かめる必要がある
行頭を ^ で始まる正規表現で数える 引用行(> で始まる行)やインデント行を取りこぼす

さらに、「文字列を含む行数」と「その文字列が処理されている箇所の数」は別物です。 ある回では、「403エラーは2箇所」というTAKTの報告から grep -c "ACCOUNT_DISABLED" の期待値を2と書きましたが、実測は5でした。内訳は返却が2、JSDocコメントが1、通常のコメントが2。grep -c は文字列を含む行を機械的に数えるだけで、それがコード上どの種類の記述かは判別しません。

これらはすべて独立した事例として起きましたが、共通する結論は一つです。実測が期待値と食い違ったとき、まず疑うのは検証コマンドの側です。

4. 負の結論は、検索の書式を変えてから述べる

grep -ln "vi.mock('react')" を実行し、0件という結果を得たとします。「このテストの書き方は存在しない」と結論づけてよいでしょうか。

よくありません。 実際にこの検索で0件だったため、そう述べかけたことがありました。しかし書式の揺れ(引用符の種類・スペースの有無など)を含めて検索し直すと、対象のコードベース全体で60件以上見つかり、当初参照していた該当ファイルも実在しました。

「存在しない」「前例がない」という負の結論は、一度の検索だけで述べません。 別の書式で再検索してから述べます。これは前節の原則の具体化でもあります——検索条件そのものが、見たいものを取りこぼしていないかを先に疑います。

一覧を絞り込んで確認するときも同様の失敗が起きます。マイグレーションファイルの一覧を grep '006' で絞り込んだところ、0070 が視界から外れ、TAKTの「既存の最大は0070」という報告を誤って疑ったことがありました。実測すると0070は実在し、TAKTの報告は正しかったのです。絞り込みの条件が、見たいものそのものを除外していないかを確かめます。

5. すべてを検証し直すわけではない

ここまでの原則は「報告値を無検証で期待値へ写さない」という話であって、報告のすべてを追試するという意味ではありません。 TAKTが実行して結果が出ているコマンドを、こちらで流し直しても同じ結果が出るだけで、往復が増えるだけです。

検証する範囲は、次の3つに限定しています。

対象
報告に書かれていない事項 「警告メッセージが2種類あるか」が報告に無い
TAKTが「未確認」と明示した事項 「ライブラリの挙動は未確認」と書かれている
結論を左右する数値(期待値へ転記するもの) 件数・行番号・イメージID

TAKTが実行済みのコマンド(型チェック・テストの実行)は再実行しません。

この線引きには経緯があります。ある回で、build-stepの報告に対して7ブロックもの検証コマンドを提示したことがありましたが、大半はTAKTが実行済みの内容をなぞる追試でした。「TAKTと同じテストを実施し、当然同じ結果という繰り返しが続いている」という指摘を受け、手を動かすのは人であり、工程数は人の実行回数で数えるという考え方に是正しました。この考え方は第7回で改めて扱います。

6. まとめ——疑うべきは、報告ではなく確認手段

この回で挙げた事例に共通する構造は、実はどれも同じです。AIの報告が誤っていたのではなく、それを検証するために書いたコマンドの側が、数えたいものと違うものを数えていました。

grep -c は行数を数え、str.count() は出現回数を数えます。^ で始まる正規表現は、引用符やインデントの前に別の文字がある行を取りこぼします。件数の一致は、実行できたことの証明にはなりません。それぞれ、道具の性質を忘れて「数字が合えば正しい」と早合点したところに誤りが生まれています。

検証術とは、結局のところ「何を数えているか」を常に問い直す作業です。


次回(第4回):壊れる前に止める——完了確認11項目の設計。誤りが実害になる前に検知されている理由を、書き込み前の自己検査という仕組みの側から書きます。

動画作成には自信があります!

このサイトを任されることになりました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

PAGE TOP