レベル6: AIベースの視覚的検証
最終手段の階層 — L4もL5もアサーションに到達できない場合にAIが問題解決の可否を判断する。
🚨 Danger
L6は最終手段です。 日常的な利用は想定しておらず、CIゲートには絶対に使ってはいけません。AIによる判定は非決定論的でコストがかかり、実行間で再現できません。L4(E2E)が書けないかつL5(決定論的視覚検証)でアサーションに届かない場合にのみ使用してください。Playwrightスペックや算出スタイルアサーションで表現できるのであれば、そちらを使ってください。
レベル6がテストするもの
レベル6はAIサブエージェントによる視覚的な判定を生成します。サブエージェントはタスクごとのテストフロースキル(手順と判定基準)とブラウザ駆動スキルを読み込み、UIを操作して構造化されたPASS/FAILと証跡を返します。判定そのものが結果であり、その背後に決定論的なアサーションは存在しません。
これはL5と根本的に異なります:
| レベル | 判定の仕組み | 決定論的か |
|---|---|---|
| L5 | 算出スタイルチェック、または閾値に対するスクリーンショットのピクセル差分 | はい |
| L6 | AIサブエージェントがスクリーンショット/計測値を見て判断する | いいえ |
L6は、L5がアサーションする「正しい対象」を捕捉すること自体が困難な、残余的な問題のためのものです。
L6にエスカレーションするタイミング
エスカレーションするのは、両方が真の場合だけです:
- L4(E2E)が書けない。 UIが複雑、ステートフル、またはcanvasベースで、Playwrightからクリーンに操作できない。例:ズーム可能なフォトエディタ、自由描画のサーフェス、リサイズ可能オブジェクトを伴う多層コンポジット、各ステップが前段の変換に依存するドラッグ・スナップ・リサイズ操作。
- L5(決定論的視覚検証)がアサーションに届かない。 算出スタイルチェックが適用できない(対象が
<canvas>のため)。スクリーンショットのピクセル差分はノイズが多すぎる(アンチエイリアス、サブピクセルレンダリング、アニメーション途中)。DOMのbounding rectが、canvas描画コンテンツの視覚的サイズを露出しない。
どちらか片方しか真でない場合、正しい答えはもう一方の階層であり、L6ではありません。
実例: キャンバス間の画像サイズの一致
動機となった事例は、独立したカメラ/ズーム変換スタックを持つ2つのcanvasベースのステージから構成されるWebアプリでした。ユーザーは1つ目のキャンバスに画像をドロップし、クリップ矩形でフレーミングしてから2つ目のキャンバスへ進み、クリップされた領域内で引き続き画像を編集できます。視覚的な要件は、ハンドオフ後も画像が含まれるキャンバスに対して同じ実効サイズで表示されることでした。
バグの状況 — 画像が2つ目のキャンバスに対して間違ったサイズでレンダリングされる:
ステージA(1つ目のキャンバス、期待される状態): 暗い灰色のアプリクロームの中に白いキャンバス。緑の矩形はユーザーのクリップ選択。赤い四角は配置された画像で、クリップの中央に位置している。

ステージB(2つ目のキャンバス、バグのある状態): 2つ目のキャンバスはクリップ矩形の寸法でレンダリングされているが、配置された画像はステージAと同じ物理ピクセルサイズで描画されている — そのため、より小さくなったキャンバスに対して画像が視覚的に大きく見える。画像とキャンバスの比率が2つのステージで異なってしまっている。

L4もL5もクリーンに動かなかった理由:
- L4は書けなかった: ドロップ先がDOM要素ではなく、canvasの描画面だった。どちらのステージも独自のカメラ変換、ズーム、パン状態を持つ。決定論的なE2Eを書くには、両方の変換スタックをリバースエンジニアリングしてようやくハンドオフ後の視覚的サイズをアサートできる状態だった。何度試してもフレーキーなスペックしか得られなかった。
- L5はアサーションに届かなかった: どちらのステージにも、画像の安定したbounding rectを返すDOM要素が存在しなかった。スクリーンショットのピクセル差分はcanvasのアンチエイリアスのせいでノイズが多すぎた。
現実解は、手順を文書化したタスク固有のテストフロースキル(フィクスチャをドロップ → ステージAをスクリーンショット → 次のステージへ進む → ステージBをスクリーンショット → 両キャンバスの内部状態フックを読み出し)と、それを読み込んで実行し、比率の計測値と両方のスクリーンショットを添えてPASS/FAILを返すAIサブエージェントでした。
L6が想定するのはこの種のケースであり、これだけです。
/verify-ui-ai の使い方
L6のエントリーポイントは、プロジェクトスコープのスキル /verify-ui-ai です(英語版のスキルドキュメント: /verify-ui-ai)。2つの段階で動作します:
- タスクごとのテストフロースキルを作成する —
.claude/skills/test-flow-<topic>/SKILL.mdに以下を記述:- 正確なシナリオ(セレクタ、フィクスチャのパス、ビューポートサイズ)
- 取得するもの(スクリーンショット、内部状態の読み出し)
- 判定基準(機械的に判定できる部分は明示的な許容範囲を、避けがたい部分のみAI判断でPASS/FAIL)
- 出力スキーマ(サブエージェントが返さなければならない名前付きフィールド)
- 検証用サブエージェントをAgentツールで起動する。 サブエージェントはテストフロースキルとブラウザ駆動スキル(
/verify-uiを優先、/headless-browserをフォールバック)を読み込み、手順を実行し、構造化された判定を返します。
テストフロースキルが耐久性のある成果物です。以降の実行はそれを再利用し、手順は固定され、サブエージェントは毎回同じコンテキストを得ます。
プロジェクトスコープのテストフロースキルを優先する
テストフロースキルは $HOME/.claude/skills/(個人スコープのみ)ではなく、.claude/skills/test-flow-<topic>/(プロジェクトスコープ、リポジトリにコミットする)以下に作成してください。理由:
- 判定手順はコードベースのテスト戦略の一部です。チームがそれを見て、レビューし、UIの進化に合わせて更新できる必要があります。
- 個人スコープのスキルは判定のドリフトを生みます — 別の手順で「同じ」テストを実行するチームメイトは、比較不能な結果を出します。
- プロジェクトスコープのスキルは、リポジトリの他のトラッキングされたスキルを配線する
setup:doc-skillスクリプトに自動で取り込まれます。
可能なら決定論的スペックと組み合わせる
L6は単発の証跡ツールです。難しい問題を1回クリアするだけです。長期的なカバレッジには、部分的であっても決定論的なスペックが必要です。機能するパターン:
- サーフェスの一部を機械的に固定する。 L4でcanvasのマウントとドロップ受け入れを検証できるが視覚結果は検証できない場合、L4スペックは検証可能な範囲だけで書き、残差にL6を使う。
- AIの判定をスナップショット化する。 L6がPASSしたら、スクリーンショット+判定+プロンプトをPRかトラッキングされた証跡ディレクトリに保存する。将来のリグレッションでは、再度L6を呼ぶ前にスナップショットと比較できる。
- 計測値を抽出する。 L6の実行が数値比率(例:「ステージBの画像幅/ステージAの画像幅 = 1.02」)を算出する場合、その数値は後で内部状態フック経由のL5アサーションに変換できる — 描画サーフェス自体がDOMに不透明なままでも。
リスクと制約
- 非決定論的。 同じフローでも実行ごとに異なる判定を返す可能性があります。単発のPASSは1つのデータ点として扱ってください。
- コストがかかる。 L6の実行ごとにサブエージェントが起動し、ブラウザを操作し、トークンを消費します。ローカル実行でもコストは無視できず、CIで回せばコストは急速かつ予測不能に膨らみます。
- ハルシネーションのリスク。 テストフロースキルの判定基準が曖昧だと、AIジャッジは壊れたUIに対して自信を持ってPASSを返すことがあります。判定基準は可能なかぎり明示的な閾値で締め、真に主観的な部分にのみAI判断を残してください。
- 判定のドリフト。 モデルのバージョンが変わると、同じ手順でもエッジケースの判定が変わる場合があります。手順はテストフロースキルにロックし、即席プロンプトに基準をインライン化しないこと。
- 再現不能。 失敗したL6実行を決定論的にリプレイしてデバッグすることはできません。出力スキーマにスクリーンショットと内部状態ダンプを含めておき、判定が再現できなくても失敗を調査できるようにしてください。
監査のために結果をアーカイブする
L6の判定は再実行できないため、証跡をアーカイブしてください。スクリーンショット、構造化された判定、サブエージェントが実行したプロンプト、内部状態ダンプを保存します。将来のメンテナが「これは本当にPASSしたことがあるのか?」と問うとき、テストを再実行するのではなく、アーティファクトを見つけられる必要があります。
デフォルトの保存先は、作業の発端となったGitHub issueまたはPRのコメントにしてください。L6を実行するたびにスクリーンショットは溜まっていきます。それをリポジトリにコミットすれば、ワーキングツリーが際限なく膨らみ、cloneも次第に遅くなります。issue/PRコメントなら、証跡は作業のスレッドに永続的に紐付き、リポジトリはスリムなまま保たれ、レビュアもコメントを遡って各検証ラウンドの様子を確認できます。
リポジトリ側の代替手段 — evidence/ ディレクトリのような形 — は、issue/PRコメントが選択肢にない場合(内部リポジトリで集中的なissueトラッカーがない場合や、証跡がコードと一緒に運ばれる必要がある場合など)に有効なプロジェクト選択です。プロジェクトがそのパターンを採用しているなら、それに従ってください。特定のポリシーがなければ、issue/PRコメントに投稿してください。
L6が代替にならないケース
| 状況 | L6ではなくこちらを使う |
|---|---|
| 通常のDOMサーフェスでのCSS/レイアウトリグレッション | L5(/verify-ui + スクリーンショット) |
| 通常のDOMサーフェスでのインタラクティブフロー | L4(Playwrightスペック) |
| ロジックの正しさ | L1(ユニットテスト) |
| CIにおける継続的なリグレッションゲート | 決定論的スペック — 理想より狭くてもL4/L5/L1のいずれかを1本書いておく |
| PR前のクイックな健全性チェック | L5 — L6は日常的な利用には高価すぎる |
L6が居場所を得るのは、検証対象の特定のサーフェスに対して他の選択肢が真に書けない場合だけです。