公開日: 2026 年 11 月 10 日
MetaMask は、約 190 か国で 1 億回以上ダウンロードされている、セルフカストディ型の金融プラットフォームです。ブラウザ拡張機能はオープンに開発されているため、社内外のコントリビューターから pull リクエストが絶え間なく届きます。
MetaMask の UX エンジニアである Francis Nepomuceno 氏は、これらの pull リクエストの多くをレビューし、コントリビューターがユーザー補助のベスト プラクティスを適用し、最新のウェブ機能を使用できるようにする一貫した方法を求めていました。エディタでは、Chrome の Modern Web Guidance をすでに使用しています。これは、ウェブ プラットフォームのベスト プラクティスとブラウザの互換性データをコーディング エージェントに提供する一連のスキルです。他のコントリビューターにも同じガイダンスを提供するため、彼は、作成者が使用したツールに関係なく、MetaMask のオープンソース リポジトリへのすべての pull リクエストをレビューする bot を設定しました。
課題: 最新のウェブ機能に対応する
最新の HTML と CSS には、ユーザー補助とユーザー エクスペリエンスを向上させる機能が追加され続けていますが、どの機能がブラウザ間で動作するかを追跡するのは困難です。多くのコントリビューターがいる場合、その知識は pull リクエストを開くすべてのユーザーに届く必要があります。
セキュリティの観点からも、MetaMask はデフォルトですべてのサードパーティ依存関係をサンドボックス化するため、ライブラリの代替手段よりもネイティブ ブラウザ機能の方が安価に導入できます。Nepomuceno 氏は、「JavaScript を使用せずにダイアログやプルダウンを使用できるなど、これらの最新の API にアクセスできることは大きなメリットでした」と述べています。
解決策: Modern Web Guidance がすべての pull リクエストをレビューする
2026 年 9 月 16 日、MetaMask/metamask-extension への pull リクエストにより、「仕組み」ページが追加されました。このページには、ほとんどの React FAQ と同じ方法で構築された FAQ が含まれています。
// Before: Custom React state (removes content from DOM)
const [expanded, setExpanded] = useState(false);
<button type="button" aria-expanded={expanded} onClick={() => setExpanded(c => !c)}>
<Text>{question}</Text>
</button>
{expanded ? <Text>{answer}</Text> : null}
約 5 分後、bot がコメントしました。search-hidden-content ガイドを引用して、次の 3 つの点を指摘しました。
- 各回答を条件付きでレンダリングすると、DOM から削除されるため、折りたたまれたテキストはブラウザのページ内検索で見つからず、支援技術で検出するのが難しくなります。
- ネイティブの
<details>/<summary>開示(2020 年以降の Baseline)では、適切なセマンティクスでコンテンツが DOM に保持されます。相互に排他的なパネルの場合、共有のname属性(2024 年以降に新たに利用可能になったベースライン)により、他のパネルが自動的に閉じられます。複数のパネルを開くことができるよくある質問の場合は、この属性を省略します。 - チームが既存の Disclosure コンポーネントを好む場合は、少なくとも
hidden="until-found"と、aria-expandedとアイコンの状態を同期するbeforematchリスナーを使用して、DOM に回答を保持する必要があります。
// After: Native <details> / <summary> disclosure (findable with find-in-page)
<details>
<summary>
<Text>{question}</Text>
</summary>
<Text>{answer}</Text>
</details>
13 分後、作成者は修正をプッシュしました。コンポーネントはネイティブの <details>/<summary> 開示になり、折りたたまれた回答はページ内検索のために DOM に残り、2 つのナビゲーション ボタンはリンクになりました。
このボットは、Modern Web Guidance を実行する Cursor Automation で、Nepomuceno 氏は 3 行のプロンプトで設定しました。2026 年 10 月 21 日まで(5 週間):
- この bot は約 480 件の pull リクエストで実行され、26 人の作成者による 64 件の pull リクエスト(57 件の機能と修正の pull リクエスト、7 件の自動リリースと同期の pull リクエスト)にコメントしました。
- 機能と修正の pull リクエストでは、エンジニアが 22 件の pull リクエストで 43 件の検出結果を修正し、さらに 3 件を部分的に修正しました。
- エンジニアは迅速に対応しました。特定可能な commit を含む 38 件の修正のうち、19 件は 15 分以内に、26 件は 1 時間以内に完了しました。コメントから修正までの所要時間の中央値は 15.2 分でした。
MetaMask が bot をどのように構成したか、何を検出したか、どこでノイズが発生したかについて説明します。
設定は 3 行のプロンプトです。
自動化の構成方法について、Nepomuceno 氏は次のように答えています。「特別な設定は何もありません。簡潔で範囲を絞ったものにしています。」指示全体:
- Run /modern-web-guidance for any client-facing changes
- Run /chrome-extensions for any relevant extension changes
- Comment on the PR only when there are issues to address. Keep the comment focused on actionable items
実際の動作は次のようになります。
- アドバイザリである: 最初の 2 日間、bot は「変更のリクエスト」レビュー(と 1 つの承認)を投稿しました。作成者は、対応を完了すると、それらを却下しました。9 月 18 日以降、すべてのレビューがコメントになっています。マージはブロックされないため、作成者は各提案に対して最終的な判断を下すことができます。
- リポジトリ内の特定のガイドとファイルを引用する: コメントした 64 件の pull リクエスト全体で、bot は 122 件の検出結果を報告しました。機能と修正の pull リクエスト 102 件のうち、63 件は、適用する特定の Modern Web Guidance ガイド(
search-hidden-content、state-aware-sticky-headers、sms-otp-formなど)を指定し、推奨パターンをすでに使用している場合は、リポジトリ内の既存のファイルを指しています。 - pull リクエストが UI に触れない限り、静かなままです。5 週間で約 480 件の pull リクエストのうち、少なくとも 100 件が UI またはクライアント コードに触れ、bot はコメントした pull リクエストごとに平均 2 件の検出結果を報告しました。主にフロントエンド リポジトリを使用するチームでは、より多くのコメントが期待できます。
プロンプト自体は、どのエージェント ランナーでも動作します。Modern Web Guidance は、Cursor、Claude Code、Codex、GitHub Copilot、Antigravity などのコーディング エージェントのスキルまたはプラグインとしてインストールされます。エージェントがスキルを実行すると、API キーを必要とせずにローカル インデックスで一致するガイドを検索し、チームのエージェント ランナーがすでに提供しているモデルを使用して、それらとの差分を確認します。
Modern Web Guidance が検出した、linter では検出できない問題
静的 linter は、単一の要素に属性がないことを報告できますが、以下の検出結果は、インタラクション動作、HTML セマンティクス、ファイル間でコンポーネントがどのように組み合わされるかに関連しています。
取引手数料のフィールドが編集可能に見えるが、入力が無視される
MetaMask の高度な取引手数料設定では、ガスリミット フィールド(取引で消費できるネットワーク手数料の上限)は編集可能に見えましたが、ユーザーの入力は無視されていました。これは、手数料の見積もりがまだ読み込み中であるか、失敗した場合に発生していました。 一方、[保存] ボタンは無効になっており、支援技術が読み取れる説明はありませんでした。
フォームガイドを引用して、bot は 3 つの修正を指摘しました。
- 見積もりが利用できない場合は、ガス上限フィールドを無効にし、表示されるステータス テキストをフィールドに接続して、支援技術が説明を読み取れるようにします。
- 無効になっている [保存] ボタンを同じステータス テキストに接続して、無効になっている理由をスクリーン リーダーが認識できるようにします。
- フィールドを数値入力モードに切り替えて、モバイル ユーザーにテンキーが表示されるようにします。
作成者は、両方の設定モーダルに 3 つの修正すべてを適用し、1 つのコンポーネントに統合しました。
URL が非表示になっているバナーボタン
MetaMask の取引機能の 1 つのステータス バナーで、インラインの「よくある質問」と「MetaMask サポートに問い合わせる」アクションが、リンクではなく JavaScript で新しいタブを開くボタンとして構築されていました。3 分以内に、ボットは HTML ガイドとユーザー補助ガイドを引用して、スクリーン リーダーがそれらをボタンとして読み上げること、ユーザーが URL のコピーやコンテキスト メニューから新しいタブで開くなどのリンク アフォーダンスを失うことを指摘しました。また、MetaMask のコードベースにある既存のバナー コンポーネントを指摘しました。このコンポーネントは、これらのアクションを実際のリンクとしてレンダリングしています。
12 分後、作成者は両方のアクションをリンクに切り替えました。「ガイダンスが採用されると、今後のレビューで参照例として言及されるため、非常に便利です」と Nepomuceno 氏は述べています。
ラベルが別の場所にある確認入力
複数のファイルにまたがって読み取る bot の機能は、複数ステップのフォームでも効果を発揮しました。静的 linter は、各ステップ内のプレースホルダ テキストを含むテキスト フィールドのみを認識し、表示される見出しと手順が親レイアウト コンポーネントに存在することを認識できません。フォームとユーザー補助のガイドを引用して、ボットは、プレースホルダがフィールドの唯一のラベルであること、親レイアウトのステップのタイトルと手順が入力に関連付けられていないこと、エラー メッセージと「コードの再送信」メッセージがスクリーン リーダーに通知されていないことを検出しました。15 分後には 3 つすべてが修正され、後続の pull リクエストでコード入力を 6 つの視覚的な数字ボックスとして再スタイル設定したときも、そのユーザー補助機能の配線はそのまま残りました。
bot が検出したその他の問題
同じ 5 週間のテストから得られたその他の 5 つの調査結果:
- bot の開発エンジニアが見落とした CSS の詳細: Nepomuceno 氏自身の固定ホームタブの pull リクエストでは、コンテナに名前を付けずに CSS スクロール状態クエリをネストし、スクロール中にレイアウトがシフトするように枠線を切り替えていました。bot は状態を認識する固定ヘッダーのガイドを引用し、彼は両方を修正しました。レビューは、アンカーの配置とスクロール状態のクエリに役立つことがわかりました。
- キーストロークの途中でスリッページが上限に達する: カスタム スリッページ入力(ユーザーが取引で許容する価格変動)では、キーストロークごとに 100% を超える値がクランプされ、ユーザーがまだ入力している間に 101 が 100 に変換されていました。フォームのガイドに沿って、修正では、フィールドがフォーカスを失ったときに検証が行われるようにし、目に見える警告バナーを追加しました。
- スクリーン リーダーで使用できなかった読み込みインジケーター: トークンリストの読み込みスケルトンが、ロールのない汎用要素に「読み込み中」ラベルを配置していました。これは ARIA で禁止されています。ボットは、MetaMask のスクリーン リーダー専用パターンをすでに使用しているコードベースの 2 つのコンポーネント(どちらも 6 日前の Modern Web Guidance のレビュー後に更新されたもの)を指摘し、作成者は 8 分後にスケルトンをそのパターンに合わせました。
- 保護されていない非同期アクション: 非同期の [View on provider] ボタンにインフライト ガードがなかったため、ダブルクリックするとタブとバックグラウンド ウォッチャーが重複して開く可能性がありました。作成者は、コメントから 4 分以内にガードを追加しました。
- フォームなしのキーストローク検証: Import NFT ページは、キーストロークごとに検証され、送信セマンティクスの
<form>要素がありませんでした。両方とも、審査から 19 分後に修正されました。
すべてのレビューは公開されます。bot の完全なコメントは、リンクされた各 pull リクエストにあります。GitHub でそれらのすべてを閲覧できます。
修正されなかった問題と、ノイズの多さ
すべての検出結果が取り込まれたわけではありません。次の表は、MetaMask が機能と修正の pull リクエストに関する 102 件の検出結果をどのように集計したかを示しています(さらに 20 件が 7 件のリリースと同期の pull リクエストに反映されました。これらの pull リクエストでは、レビューによってコードが変更されることは想定されていません)。
122 件の検出結果(リリースおよび同期 pull リクエストに関する 20 件を含む)をテーマ別に分類すると、次のようになります。
これらの数字にはいくつかのパターンがあります。
- 1 つのコンポーネント内にとどまる修正は、横断的なユーザー補助の変更よりもはるかに頻繁に適用されます。フォームと HTML の修正は、審査中のコンポーネント内にとどまるため、通常、作成者はすぐに適用します(31 件中 19 件が修正済み)。アクセシビリティに関する検出結果が最も多く(38 件)、修正されたのは 12 件のみでした。通常、修正が pull リクエストの範囲外であったか、まだ存在しない共有デザイン システム コンポーネントが必要であったことが原因です。
- 「その他」は、ウェブ プラットフォームのガイダンスから外れたものです。16 件の検出結果は、デザイン システムの一貫性、ロジックバグ、コピー、テスト品質、ダークモード、コードの衛生状態に関するものでした。3 件が対応され、そのうち 1 件は実際の回帰(フォームの事前入力が機能しなくなるネットワーク リストの変更)でした。16 件のほとんどは無視して問題ないものでしたが、回帰を検出できたことで、簡単に確認する価値があることがわかりました。
- 誤判定は、エージェントがガイドを適用した方法に起因しており、ほとんどのノイズは設定で修正できます。レビューボットは、静的 linter ではなく、差分を読み取るエージェントであるため、誤検出は、周囲のコードの読み取りミスや、リンクされたガイドよりも厳格なルールの適用によって発生しました。リリース ブランチと同期ブランチをスキップし、プロンプトを厳しくして、エージェントがガイドに明示的に記載されているルールに沿うようにすることが、次の調整として明らかです。
Nepomuceno 氏は、チームと審査の所要時間に対する広範な影響について次のように説明しています。
「レビューは本当に役に立ちます。また、Interest Invoker や Popover API などの最新の API をエンジニアが把握し、理解を深めるのにも役立っています。」
「PR のレビュー時間は増えていません。むしろ、減った可能性が高いです。多くのエンジニアは、エージェントを使用してフィードバックに対応しています。Modern Web Guidance が検出した問題は、本来であれば、これらの最新のウェブ技術に精通した人間のレビュアーが必要だったはずです。」
MetaMask のエンジニアである David Murdoch 氏は、ガイダンス自体にも貢献しています。CSS レイアウト ガイドの例の 1 つにエラーがあったとき、彼は問題を報告し、Modern Web Guidance チームは 2 日後に修正をマージしました。
MetaMask が導入を検討しているチームに伝えること
- 書き始める前にガイダンスを読みます。
npx modern-web-guidance@latest search "accordion find in page"を実行して、エージェントがタスクのために取得するガイドを確認します。Modern Web Guidance ガイドの全セットを参照することもできます。 - 3 行のプロンプトと、すでに実行しているエージェントから始めます。スキル(
npx modern-web-guidance@latest install、またはエージェントのプラグイン コマンド)をインストールし、pull リクエストで実行できるものを指定して、対応可能なアクションがある場合にのみコメントし、ガイドに明記されているルールを遵守するように指示します。問題がないときは bot が静かにしているため、MetaMask のエンジニアは今でも bot のコメントを読んでいます。 - 一部の検出結果が未対応になることが想定されます。機能と修正の pull リクエストに関する 102 件の検出結果のうち、43 件が修正され、36 件が拒否されるか、対処されませんでした。この比率は、アドバイザリ レビューボットでは適切に機能しますが、ブロッキング チェックとしては不適切です。
- 人間による審査を継続する。このボットは、ウェブ プラットフォームのセマンティクス、最新の CSS、インタラクション パターンに精通していますが、プロダクトについては知りません。
MetaMask がまだ測定していないこともあります。5 週間が経過した時点で、チームは pull リクエストごとの費用、ランタイム、モデル比較、React コードベース外でのレビューボットの動作を追跡していません。
MetaMask は、3 行の構成で、ほとんどの検出結果に対して特定のガイド(および既存のリポジトリ内の例)を引用するレビューボットを導入しました。承認された提案は通常、1 時間以内に修正されます。