はじめに
AI にコードを書かせる開発が当たり前になってきました。私も個人開発の SaaS で、実装のほとんどを Claude Code に任せています。仕様書(spec)を書いて渡し、実装させ、テストで検証する——このループ自体はうまく回っていました。
テストは全部緑。CI 相当のローカル検査も全部パス。数字の上では健全そのもの。
でも、ふと不安になったんです。
この「緑」、本当に本物を見てるのか?
そこで週末を使って、Claude の最新モデル Fable 5 に開発環境そのものを総点検させてみました。結果から言うと——4つの重大な穴が見つかりました。テストが全部緑のまま、その裏に。
この記事では、私がやった総点検の方法(コピペで使えるプロンプト付き)と、見つかったものを共有します。あなたの環境でも、この土日でぜひ試してみてください。
私の開発環境(前提)
規模感が伝わるように、環境だけ簡単に:
- 個人開発の SaaS(TypeScript / React / Node のモノレポ)
- 実装は Claude Code に委任。私は spec を書いて渡し、成果物をレビューする役
- ローカルに 20 以上の検査ゲート(型チェック・unit テスト・golden テスト・ビルド検証など)を束ねた「全部検査」スクリプトがあり、これが全緑でないとマージしない運用
- テストは数百本、golden(期待出力の固定)も多数
つまり「AI 駆動開発としてはそれなりに検査を整備してきたつもり」の環境です。それでも穴があった、というのが今回の話です。
総点検の設計 — 一番大事なのは「検査と被検査の分離」
最初に考えたのは、「Claude Code に自分の環境を点検させて、問題点を報告させればいい」でした。
これはダメです。 理由は単純で、実装した本人(と同じ AI)に自己採点させると、無意識に甘くなるから。「これは意図的な設計です」「実用上問題ありません」——自己弁護が混ざった報告は、点検として信用できません。
そこで役割を2つに分けました:
- 証拠収集係(Claude Code): リポジトリの中で、事実だけを集める。grep の生出力、コードの現物、テストの一覧。評価・自己採点・弁護は書くの禁止
- 評価係(チャット側の Fable 5): 集まった証拠を、コードを持たない外部の目で精査し、格付けする
健康診断で言えば、検査技師と診断医を分ける感じです。これを私は「検査と被検査の分離」と呼んでいます。
手順1: 証拠収集プロンプト(コピペ用)
Claude Code に投げたプロンプトの骨格がこれです。自分の環境に合わせて調整してください:
# 依頼: 開発環境の総点検・証拠収集【調査のみ・実装ゼロ・評価不要】
## この依頼の性質
- 本依頼は証拠収集のみ。別の審査者が外部の目で精査するための生の材料を集める。
- 重要: 評価・自己採点・弁護をしない。「これは正しく実装されている」
「ベストプラクティスに沿っている」等の判断コメントは書かない。
事実(コードの現物・grep 結果・数字・一覧)だけを report に載せる。
- 都合の悪い事実(穴・不整合・TODO・握りつぶしている警告)こそ価値がある。
見つけたものは加工せずそのまま載せること。
## 軸1: テストハーネスの実態
- 全検査ゲートの一覧(名前/実行コマンド/何が壊れたら赤になるか)
- テストが「本物」を検査しているかの確認材料:
- jest.mock 等でモックしている対象の全列挙(特に本番データ・本番設定を
モックで差し替えているテスト)
- 実物でなく「設定の写し」「ロジックの再実装」を検査しているテストの有無
- skip/only/todo の grep(無効化されたまま放置の検査がないか)
- E2E・実ブラウザテストの有無と、それが実際に実行されているか
(存在するが実行環境がなく走っていない、はよくある罠)
## 軸2: LLM 呼び出しの実態(AI 機能があるなら)
- LLM を呼ぶ箇所の全列挙(目的/入力に何が入るか/出力がどこへ流れるか)
- ユーザー入力がプロンプトに到達する経路(サニタイズ・長さ制限の有無)
- timeout/retry/レート制限/コストガードの実装の有無(現物)
- LLM 出力をそのまま画面に表示する箇所(XSS 面)・ファイルに書く箇所
## 軸3: プロンプトの管理実態
- 全プロンプトの原文(どこに置かれ、変更したら何かのテストが赤になるか)
## 軸4: 開発プロセスの実態
- 運用ルールの正本がどこにあるか(散在・重複・矛盾があればそのまま列挙)
- ルールと実運用の乖離(「CI 緑を確認」等、実態と合っていない記述)
## 報告
上記を事実のみで report にまとめる。コード抜粋は加工せず、grep は生の出力で。
「X には検査がない」のような自覚している穴の記載が最も価値のある証拠。
完了後に停止し、審査を待つ。
ポイントは3つ:
- 「評価するな、事実だけ出せ」を繰り返し明示する(これがないと自己弁護が混ざる)
- 「都合の悪い事実こそ価値」と宣言する(AI は空気を読んで穴を隠しがち)
- モック・写し・実行されていない検査、を名指しで探させる(後述する典型的な穴のパターン)
私の場合、これで約3,000行の証拠レポートが上がってきました。
手順2: Fable 5 に外部の目で精査させる
集まった証拠を、コードを持たないチャット側の Fable 5 に渡して精査させます。
添付は私の開発環境の総点検・証拠レポートです。
あなたは外部の審査者として、実装者の自己評価を一切信用せず、
証拠だけから以下を判定してください:
1. 各所見の格付け(重大/要注意/健全)と、その根拠
2. 「テストは緑だが本物を見ていない」パターンの検出
3. 修正の優先順位(何から直すべきか・なぜか)
励ましや水増しは不要です。本当の現在地が知りたい。
ここで Fable 5 を使う意味が出ます。3,000行の証拠を「どのテストがどの実装を見ているか」「この grep 結果は何を意味するか」まで構造ごと突き合わせて読む必要があり、精査の深さがそのまま点検の質になるからです。
見つかったもの — テスト全緑の裏にあった4つの穴
穴1: テストが「偽物の世界」で走っていた 🔴
一番衝撃だったのがこれです。UI 側のテスト20数ファイルが、本番のマスタデータを一切読まず、空のモックで走っていた。
jest.mock('@/data/xxx', () => ({ ITEMS: [] })); // 全ファイルこれ
理由はビルドツール依存の import がテスト環境で動かないという技術的事情で、個々のテストとしては正当なモックです。でも結果として、「本物のデータ × 本物のロジック」の組み合わせは、どのテストも一度も見ていなかった。テストは数百本、全部緑。全部、偽物の世界の緑でした。
穴2: 「検査してるフリ」のテスト 🔴
あるテストは、検査対象のロジックをテスト内で自前で再実装(写経)して、その写経の出力を検査していました。本物の画面は一切描画しない。
実際に本物の画面を壊してみたら——このテストは緑のままでした。写経は無傷だから。
私はこれを「wrong-layer green(間違った層の緑)」と呼ぶことにしました。実物ではなく、実物の写し(設定のコピー・ロジックの再実装・ソースの文字列切り貼り)を検査しているテストは、実物が壊れても緑を出し続けます。
穴3: 実ブラウザのテストが「一度も走っていなかった」 🔴
実ブラウザで製品を一周する E2E テストは、存在していました。ただし CI 専用の設定で、その CI は事情により停止中。つまり存在するだけで、実行回数ゼロ。
「テストがある」と「テストが走っている」は別物でした。しかも後で計測したら、ローカル実行のコストはたった数秒。「E2E は重いから CI だけ」というのは思い込みで、測っていなかっただけでした。
穴4: ユーザー入力が無防備に画面へ 🔴
ユーザー入力を含む Markdown を HTML 化して画面表示する経路に、サニタイズがゼロ(XSS)。これは AI 云々以前の古典的な穴ですが、機能開発を優先しているとこういう横断的な防御は誰も見ていない、の典型でした。
おまけ: プロンプトが何にも固定されていなかった 🟡
LLM に渡すプロンプト内の安全上の重要文言(「あなたは提案だけ・決定はしない」系の束縛)が、1文字変えても全テスト緑。約束が静かに消えても誰も気づけない状態でした。
直し方にもルールを作った — 「対照実験なしで着地しない」
見つけた穴を直すとき、1つルールを課しました:
必ず「昔すり抜けた破壊」を新旧両方のテストに当てて、「旧: 緑のまま/新: 赤」を同時に観測してから完了とする
たとえば穴2(写経テスト)の修正では、過去に実際にすり抜けた破壊と同じ破壊を再現し、「写経テストは緑のまま・新しい実描画テストは赤」を同時に記録しました。穴3(E2E)では、「unit テストも型チェックもビルドも全部緑のまま、実ブラウザテストだけが捕まえる破壊」を実測しました。
こうすると「直しました」が自己申告でなく、証明としてリポジトリに残ります。
この土日でやるなら — 最小手順まとめ
- 土曜午前: 上の証拠収集プロンプトを自分の環境向けに調整して、Claude Code(Fable 5)に投げる。評価禁止・事実のみ、を忘れずに
- 土曜午後: 上がってきた証拠を、別セッションの Fable 5 に渡して外部審査させる。「励まし不要・本当の現在地が知りたい」と添える
- 日曜: 重大判定が出たものから直す。直すときは「昔すり抜けた壊し方で、新しいテストが赤くなること」を確認してから完了にする
チェックリスト(私の環境で実際に穴だったもの):
- テストは本番のデータ・設定を読んでいるか?(モックの中身を見る)
- 実物でなく「写し」(設定コピー・ロジック再実装・文字列切り貼り)を検査しているテストはないか?
- E2E は実際に走っているか?(存在と実行は別)
- ユーザー入力 → 画面表示の経路にサニタイズはあるか?
- プロンプトの重要文言は、変えたら何かが赤くなるか?
- 運用ルールの文書は実態と一致しているか?
まとめ
- 「テスト全緑」は何も保証しない。問うべきは緑の数ではなく、その緑が本物を見ているか
- 点検は「検査と被検査の分離」で。実装した AI に自己採点させず、証拠だけ集めさせて別の目で審査する
- 直すときは対照実験で。「昔すり抜けた破壊を、新しい番人は捕まえる」を実測してから着地する
- AI に実装を任せる時代こそ、これが効く。弱い検査は AI に嘘の緑を学ばせる。土台が先、知能は後
私の環境ではこの総点検と修正一式が、Fable 5 との共同作業で実質2日で終わりました。見つかった穴はどれも、放置すれば数ヶ月後にもっと高くつくものばかりでした。
あなたの環境の「緑」は、本物を見ていますか? この土日、確かめてみてください。