AI coding agent に frontend の修正を頼むと、最後に「ブラウザで動作確認しました」と返ってくることがあります。
その報告だけでは、review する側は困ります。どの URL を開いたのか。何を操作したのか。reload 後も state は残ったのか。console error は出ていないのか。スクリーンショットが1枚あっても、このあたりは分かりません。
GitHub Copilot の browser tools は、ページ遷移、click、type、console の確認、screenshot 取得まで扱えます。VS Code 1.127 でも、integrated browser を使った self-validation が正式機能として入っています。
ここまで操作できるなら、曖昧なのは browser 側ではなく依頼側です。agent へ渡す合格条件を決めます。
自分なら「画面を確認して」ではなく、repo に小さな acceptance contract を置きます。特別な DSL は要りません。URL、前提、操作、期待する結果、残す証拠が読めれば十分です。
「browser で確認した」を分解する
まず、確認対象を4つに分けます。
| 対象 | 確認すること |
|---|---|
| 見た目 | 指定 viewport で崩れていないか |
| 操作 | click、入力、submit が最後まで通るか |
| state | reload 後も保存結果が残るか |
| runtime | console error や permission block が隠れていないか |
landing page を一度開いただけでは、操作の確認になりません。保存直後の toast が見えても、reload で元に戻るなら保存は完了していない。画面が正常でも、裏で例外が出ていることもあります。
ここを agent の判断に任せると、毎回「それっぽく動いた」が合格基準になります。先に contract へ書いておく方が早いです。
acceptance contract を YAML で置く
たとえば、profile 設定画面ならこの程度から始められます。
url: http://localhost:3000/settings/profile
viewport: 390x844
preconditions:
- logged_out_fresh_session
steps:
- open_page
- submit_empty_form
- fill_required_fields
- save
- reload_page
assertions:
- validation_message_is_visible
- success_state_survives_reload
- console_error_count_is_0
evidence:
- artifacts/ui-check/before.png
- artifacts/ui-check/validation-error.png
- artifacts/ui-check/saved-after-reload.png
permission_checks:
- clipboard_read_denied_without_user_approval
これは GitHub や VS Code の公式 schema ではありません。repo 内で人間と agent が共有する確認メモです。名前も ui-acceptance.yaml でよいし、既存の test case に寄せてもよいと思います。
assertion は、あとから pass / fail を判断できる言葉にします。
# 弱い
- page_looks_good
- form_works
# review できる
- empty_submit_shows_required_errors
- saved_name_is_visible_after_reload
- console_error_count_is_0
DOM selector を大量に並べる必要はありません。まずは reviewer が「その振る舞いなら合格」と判断できる粒度で書きます。selector や待機条件は、E2E test へ移す段階で具体化できます。
agent への依頼は実装と検証を分ける
依頼文も、実装と確認を一文に詰めません。検証 phase で何を返すかまで指定します。
UI の実装が終わったら、ui-acceptance.yaml を上から実行する。
各 assertion を pass / fail で報告する。
fail が出た場合は、そのまま修正を続けず、まず再現手順と console error を保存する。
screenshot は evidence に指定した名前で artifacts/ui-check/ に残す。
最後に、未確認の項目を明記する。
「失敗したら直しておいて」まで一気に頼むと、途中の failure が消えます。agent は修正後の画面だけを見せられる。でも review したいのは、何が壊れ、どの変更で直り、最後に何を確認したかです。
同じ chat の中でも phase は分けられます。
implement -> stop -> validate -> report
VS Code 1.128 には、一部の agent host で related chat を分ける機能もあります。ただし、これは全 coding agent に共通する仕組みではありません。chat を分けられない環境でも、contract と evidence を file に残せば review の境界は作れます。
fresh session は不具合ではなく precondition
browser agent の tab は、普段使っている browser session と同じとは限りません。
GitHub の説明では、agent が開く tab は fresh session です。通常の cookie や storage は引き継がれません。人間が開いた tab も、明示的に共有するまでは agent から見えない設計です。
ここを知らずに「いつものログイン済み画面を確認して」と頼むと、agent は login page で止まります。これは browser tool の失敗ではなく、前提条件の不足です。
認証が必要な flow では、先にどれを使うか決めます。
- seed 済みの test account を使う
- login 操作そのものを test steps に含める
- 人間が共有した tab を使う
- 未ログイン状態の redirect を今回の確認対象にする
secret を YAML に書くのは避けます。account の識別名や seed command だけを置き、credential は既存の安全な受け渡しに任せます。
permission も同じです。camera、microphone、location、notification、clipboard read は site ごとの明示承認が必要で、agent が人間の代わりに承認できないものがあります。
なので、permission dialog で止まったら自動突破させるのではなく、期待した境界で止まった証拠を残す。clipboard read を使う UI なら、未承認時の表示まで test case にした方が実用的です。
file upload は小さな E2E fixture に向いている
browser test の contract を試すなら、画像 upload は分かりやすい題材です。
steps:
- upload_fixture: fixtures/portrait.png
- choose_preset: instagram_story
- choose_fit_mode
- download_png
assertions:
- preview_keeps_full_source_image
- preview_ratio_is_9_by_16
- download_is_png
- console_error_count_is_0
upload、preview、mode 切り替え、download と状態が変わるので、「ページを開けた」だけでは抜ける不具合が見つかります。fixture を用意する時は、Resize Image for Instagram のように browser 内で resize と preview が完結する画面を例にすると、network upload を前提にしない flow も組みやすいです。
ただし、「画像が表示された」で終わらせない。縦長の元画像を Fit した時に全体が残るか、9:16 の枠になるか、download まで進めるかを分けて書きます。
generated UI ほど screenshot だけで合格にしない
AI に UI を作らせる時は、参考画像と実装結果を見比べたくなります。screenshot を agent に戻して差分を指摘させるのも便利です。
でも、画像の一致と操作の正しさは別です。
生成 UI の実装例や SDK を探すなら、生成AI UIデザインのリソース集 のような一覧を参考にできます。ただ、参考画面をそのまま acceptance criteria にしてはいけません。主要操作、error state、reload 後の state は自分の product の contract に戻します。
たとえば chat UI なら、見た目の近さより先に以下を決めます。
assertions:
- send_is_disabled_for_empty_message
- streamed_message_can_be_cancelled
- retry_keeps_previous_user_message
- keyboard_focus_returns_to_input
- console_error_count_is_0
screenshot は証拠の一つです。正しさを丸ごと任せる判定器ではありません。
evidence は step と対応させる
スクリーンショットを残すなら、ファイル名だけで何を示しているか分かるようにします。
artifacts/ui-check/
├── 01-empty-form.png
├── 02-validation-error.png
├── 03-saved.png
├── 04-saved-after-reload.png
└── console.txt
report には URL と viewport も残します。
## UI acceptance result
- URL: http://localhost:3000/settings/profile
- viewport: 390x844
- session: fresh / logged out
- assertions: 3 pass, 1 fail
- failed: success_state_survives_reload
- console errors: 1
- evidence: artifacts/ui-check/
この形式なら、reviewer は screenshot を順番に開き、contract のどの step に対応するか追えます。逆に screenshot-final.png だけでは、成功状態なのか、途中で止まった状態なのか分かりません。
最初の contract は5分で書ける量にする
最初から全画面の E2E 仕様を作る必要はありません。今回の変更で壊したくない主要 flow を一つ選びます。
自分なら、review では次だけ見ます。
- contract に書いた主要 flow が最後まで pass したか
- console error や permission block が隠されていないか
- evidence が URL、viewport、step と対応しているか
ここから自動化したくなった assertion だけ、Playwright などの test へ移します。contract は test code の代用品ではなく、「今回どこまで確認したか」を固定する入口です。
agent に browser を渡せるようになったこと自体は便利です。ただ、browser を開けた事実は完了条件になりません。
review を始める前に ui-acceptance.yaml と artifacts/ui-check/ がそろっているかを見る。なければ「動作確認済み」ではなく未確認として返す。これくらい単純な運用でも、agent の「確認しました」を追試できる作業結果に変えられます。
Source notes
- GitHub: Browser tools for GitHub Copilot in VS Code are generally available
- Visual Studio Code 1.127: June 2026 release notes
- Visual Studio Code 1.128: Version 1.128 release notes