Expoスキル評価ツール
plugins/expo/skills/ 内のスキルについて、トリガー精度、生成コード品質、およびExpo Goでのランタイムレンダリングを評価します。
必要条件: macOS(Xcode、iOSシミュレータ)、1つ以上のAVDを備えたAndroid SDK、および bun。その他のデバイスツールは想定していません。
ワークスペースルート: /private/tmp/expo-skill-eval-<skill-name>/iteration-N/ (例: /private/tmp/expo-skill-eval-expo-ui/iteration-4/)。
開始前 — スコープの明確化
以下のすべてを、パイプライン作業の前に事前に確認してください — どれもスキップしないでください (リクエストですでに指定されている項目のみスキップ)。これらを、各回4件以下の質問からなる AskUserQuestion 呼び出しにまとめ、以下の順序で行ってください:
- 評価するスキル (リクエストから明確でない場合)。
- プロンプト — 評価を駆動するプロンプト。ビルトインプロンプト (スキルの評価ケース由来) は デフォルトですべて選択; 必要に応じて削除、カスタムテキストプロンプトの追加、またはアップロードされたスクリーンショットからの作成 (スキルが再現すべきターゲットUI) が可能です。プロンプトを参照。
- 検証内容 — 3つのオプションから複数選択: ランタイム+スクリーンショット / トリガー精度 / コードチェック(デバイス不要)。検証内容を参照。
- Expo SDK — 最新 (デフォルト、自動検出) または固定バージョン。
- ランナー — Expo Go (デフォルト) または開発ビルド。
- プラットフォーム — iOS / Android / ウェブ (常に3つすべてを提示)。
claude -pの権限フラグ — スキップ権限 (デフォルト) または編集のみ許可。- ビューワーの配信方法 — ローカルのみ (デフォルト) または共有可能なアーティファクトを公開。
- トリガー精度が選択された場合 — 公開された
expoプラグインが無効 (または未インストール) であることを確認。
各項目の詳細は後述。項目4〜6 (SDK、ランナー、プラットフォーム) は1回の AskUserQuestion 呼び出しにまとめるのが自然です。
評価するスキルがリクエストから不明な場合、plugins/expo/skills/ から利用可能なスキルを一覧表示し、どれを評価するか尋ねてください。
テスト対象スキルの読み込み方法 — フェーズごとに2つのメカニズム (グローバルに選択するのではありません): 実行者リファレンスは ファイルパス (SKILL_PATH = plugins/expo/skills/<skill>/SKILL.md、明示的に読み取り) でそれを参照し、トリガー評価はそれを プラグイン (--plugin-dir plugins/expo、モデルが説明から自動選択できるように) として読み込みます。どちらも ローカル、リポジトリ内 のバージョンを指します — それがあなたが評価しているものです。ハーネスセッション自体を 起動 するために特別なフラグは必要ありません (ハーネスはリポジトリパスでスキルを見つけます); メカニズムはハーネスが生成する claude -p サブプロセスに適用されます。各フェーズが異なる理由については、ステップ1と3を参照。トリガー評価がスコープ内にある場合の前提条件チェック (必須): 公開された expo プラグインがインストール/有効になっている場合は、ハーネスを起動する前に (/plugin 経由で) 無効にし、後に再び有効にします。1回の無効化は、このセッションと生成された claude -p サブプロセスの両方が継承するグローバル設定の変更です。トリガー評価で必要な理由: そのフェーズは --plugin-dir 経由でローカルスキルを読み込み、2つ目のインストール済み expo と競合します — モデルは 公開された expo:expo-ui をトリガーする可能性があり、検出はツールコール名しか認識しないため、ローカルの編集ではなく公開された説明を通知してスコアリングしてしまいます (競合はエラーになる可能性もあります)。実行 / ランタイム / 静的フェーズは影響を受けません — テスト対象スキルをローカルの SKILL_PATH で --plugin-dir なしで読み取るため、トリガー評価がない実行では無効化をスキップできます。expo を無効にしても expo-skill-eval (スタンドアロンプロジェクトスキルで、expo プラグインの一部ではない) は無効にならないため、ハーネスは使用可能なままです。
これを、評価するスキルを確認するのと同じ方法で、事前の明示的な確認としてユーザーに提示してください。 トリガー評価がスコープ内にある場合、ユーザーに公開された expo プラグインが無効 (または未インストール) であることを確認するよう依頼し、その後ステップ1を開始します。まだ有効な場合は、一時停止して /plugin で無効にしてもらいます。確認が得られるまでトリガー評価を実行しないでください — ハーネスはインストール済みプラグインを単独で確実に検出できません (グローバルプラグイン設定や claude plugin list の読み取りはプロンプトを表示する可能性があるため)。これは自動チェックではなく手動確認です。
プロンプトの選択 — ビルトイン、カスタム、またはターゲットスクリーンショット。 プロンプトは実行 (スキルあり/スキルなし) を駆動する入力であり、検証内容とは別のものです。AskUserQuestion で確認します (リクエストですでにプロンプトが指定されている場合はスキップ):
- ビルトインプロンプト — テスト対象スキル (その
SKILL.md+references/) とreferences/runtime-matrix.mdを読み取って生成する代表的なプロンプトで、スキルの標準的なユースケースをカバーします。(スキルがすでにevals/evals.jsonに評価ケースを同梱している場合は、そのpromptフィールドも取り込みます — しかしほとんどのスキルはそうではないため、通常はそれらを導出します。) デフォルトですべて選択 して、デフォルトの実行でスキルの標準ケースを実行するようにします; ユーザーが任意のものを選択解除できるようにします。 - カスタムテキストプロンプト — ユーザーが入力する1回限りのプロンプト。専用のオプションスロットを設けないでください:
AskUserQuestionは自動的に 「何か入力」 / その他のエントリを追加し、そこに入力されたものはすべてカスタムテキストケースになります。 - アップロードされたスクリーンショットから作成 — ユーザーが ターゲットスクリーンショット (再現するUI) へのパスを提供します。実行者はそれを開くように指示されます —
claude -pはReadツールでPNGを読み取ります — そしてそれに一致するアプリをビルドします; ケースはパスをreference_imageとして記録し、採点は生成されたアプリをそのターゲットと比較します (ステップ6)。これはUIスキルのための最も強力なビジュアルテストです: 「これをビルドして。」
この優先順位で AskUserQuestion の質問1回あたり4オプションの上限を尊重してください (回避すべきバグ: 4つのスロットが埋まるとアップロードオプションが通知なくドロップされること):
- 「アップロードされたスクリーンショットから作成」用のスロットを常に確保してください。 それがビジュアル評価の要点であり、決してドロップされるオプションであってはなりません。
- 明示的な「カスタムテキストプロンプト」オプションを追加しないでください — 自動の「何か入力」/ その他のエントリですでにカバーされています。
- 残りの最大3つのスロットをビルトイン/代表的なプロンプトで埋め、デフォルトで選択します。3つを超える場合は、それらを1つのデフォルト選択済みの 「すべてのビルトインプロンプト (デフォルト)」 オプションにまとめ、短いフォローアップでサブセット選択を提供して、アップロードオプションがまだ収まるようにします。
複数選択として提示します。「アップロードされたスクリーンショットから作成」が選択された場合、フォローアップでターゲット画像パスを尋ねます。選択された各プロンプト (ビルトイン、入力、または画像) は、1つの評価ケースになります (スキルあり/スキルなしで実行)。
検証内容を常に確認してください (リクエストで明確でない限り)。以下のオプションを提示し、ユーザーに1つ以上選択させます (デフォルトはスキルの references/runtime-matrix.md エントリに基づいて太字で示します):
| オプション | 機能 | デフォルトとして推奨する場合 |
|---|---|---|
| ランタイム+スクリーンショット | 完全パイプライン: フィクスチャ → 実行者 → 静的ゲート → iOS/Androidでアプリを実行しスクリーンショットを取得。ランナー (Expo Go または開発ビルド) は別の質問 — ここでは指定しない。 | アプリ画面をレンダリングするスキル (references/runtime-matrix.md の expo-go/dev-build 行) のデフォルト。起動済みシミュレータ/エミュレータが必要。 |
| トリガー精度 | claude -p 経由で現実的なプロンプトを実行し、スキルが読み取られるかを確認。再現率を測定 (トリガーすべきクエリのみ)。 | 単独チェックとして常に有用。 |
| コードチェック (デバイス不要) | tsc --noEmit + diff認識リント + expo export、さらに採点者は提供するカスタム期待値に対して生成コードをチェック。デバイス不要。 | static-only および n/a スキルのデフォルト、およびアプリを実行せずにコードパターン (正しいインポートパス、Host ラッパーなど) を検証したい場合。 |
| これらを1つの複数選択質問として提示 — 「何を検証しますか?」 これらはグレーディングの次元 (構築されたものをどのように評価するか) であり、プロンプトフェーズ (何を構築するか) とは異なります。ユーザーは任意の組み合わせを選択できます。プロンプトがアップロードされたスクリーンショットの場合 ( プロンプト参照)、「ランタイム+スクリーンショット」 を含めて、ハーネスが生成されたアプリをキャプチャし、採点者がターゲットに対してスコアリングできるようにします。 |
推奨する前に references/runtime-matrix.md を読み、スキルのデフォルトモードを見つけてください。リクエストですでにモードが指定されている場合 (例: 「トリガーするかだけ確認」、「デバイスで実行」)、質問をスキップして先に進みます。
Expo SDKバージョンを選択 — 一度だけ、事前に。 bash /abs/path/expo-skill-eval/scripts/latest-sdk.sh で最新を検出します (メジャーバージョンを出力、例: 56。内部的に bun を使用して npm view expo dist-tags --json を実行し、JSON.parse/semver でメジャーバージョンを読み取ります。これはbashスクリプトルールの対象のため、レジストリクエストを自分でインライン実行しないでください (プロンプトが表示されます))。その後 AskUserQuestion で確認: デフォルトはその最新SDK、またはユーザーが古いバージョンを固定できるようにします (例: バージョン固有の問題を再現するため)。選択したバージョンを、フィクスチャが構築されるすべての場所で使用します — make-fixture.sh に <sdk> 引数として渡し、各評価ケースの runtime.sdk に書き込みます。リクエストですでにバージョンが指定されている場合 (「SDK 54で評価」)、検出をスキップしてそれを使用します。
デフォルトは最新 — デバイスに expo start がインストールするExpo Goとの互換性を維持します。デバイスのインストール済みExpo Goよりも古いSDKを固定すると、expo start が「推奨されるExpo Goバージョンをインストールしますか?」とプロンプトを表示しようとします。TTYがない場合 (スナップショットスクリプトは /dev/null から stdin を読み取る)、Input is required, but 'npx expo' is in non-interactive mode でエラーになり、すべてのスナップショットが失敗します。したがって、シミュレータ/エミュレータに一致するExpo Goも事前にインストールする場合にのみ、古いSDKを固定してください — それ以外の場合は最新のままにします。
ランナーを選択 — Expo Go (デフォルト) または開発ビルド。 AskUserQuestion で質問します (リクエストですでに指定されている場合はスキップ):
- Expo Go (デフォルト) — スナップショットスクリプトは
expo start --ios/expo start --androidでそのままアプリを実行します。高速 (ネイティブコンパイルなし)、Expo Goがバンドルするもの (SDK 56以降の@expo/uiを含む) なら何でも実行できます。カスタムネイティブコード (expo-modules、configプラグイン、Expo Goに含まれないネイティブ依存関係) は実行できません。 - 開発ビルド — スナップショットスクリプトは代わりに
expo run:ios/expo run:androidを実行し、フィクスチャごとにネイティブ開発クライアントをコンパイルします。カスタムネイティブコードを必要とするスキル (そうでなければstatic-onlyとなるケース) に使用します。はるかに低速 —expo runは各フィクスチャをプリビルドしてネイティブコンパイルします (数分かかり、特に最初のビルド)。完全なiOS/Androidビルドツールチェーンが必要。ディスク使用量が多い: 各フィクスチャのネイティブビルドは数GBです。スナップショットフェーズは各フィクスチャの後にclean-fixture.shを実行してピーク使用量を約1ビルドに抑えますが、それでも開発ビルド実行では評価ケースを減らし、単一プラットフォームを推奨し、数GBの空き容量を確保してください。clean-fixture.shはフィクスチャごとのビルド出力 (node_modules、ios、android、.expo、dist、およびフィクスチャのiOS DerivedData) を削除し、アプリソース+gitは保持します。開発ビルドディスクのレバレッジは 評価ケースの削減 + 単一プラットフォーム です — フィクスチャごとのビルド出力のみを回収し、共有依存関係キャッシュには触れないため、何も再ダウンロードされません。
選択内容を EXPO_SKILL_EVAL_RUNNER 環境変数 (expo-go デフォルト、または dev-build) を介してスナップショットスクリプトに渡し、各評価ケースの runtime.mode (expo-go または dev-build) に反映させます。ステップ5を参照。
プラットフォームを選択 — スキルに関係なく常に質問。 iOS / Android / ウェブ (複数選択) を AskUserQuestion で提供。デフォルトは iOS + Android ですが、常にウェブをオプションとして提示 — スキルで事前にフィルタリングしないでください。ウェブはほとんどのスキルで有効な選択肢です: @expo/ui のユニバーサルコンポーネント (Host、Row、Column、Button、List、…) はウェブ上でレンダリングされ、expo-dom、NativeWind/Tailwind、APIルート、およびプレーンなReact Nativeも同様です。ウェブに表示されない唯一のものは、プラットフォーム固有のネイティブツリー (@expo/ui/swift-ui や @expo/ui/jetpack-compose) で、これはそこで空白をレンダリングします — そしてその空白自体が有用なシグナルであるため、それでもユーザーの判断です。ウェブは snapshot-web.sh (expo start --web + Playwright/Chromium) を介して実行されます。ランナーに関係なく (expo run はネイティブ専用。ウェブ開発ビルドはありません)。そして最も経験の少ないパスです。選択したセットを各評価ケースの runtime.platforms に書き込み、run_snapshots.py でループさせます。
claude -p サブプロセスの実行方法を確認 — 開始前に1回だけ。 AskUserQuestion で、--dangerously-skip-permissions で実行してよいか尋ね、この実行のすべてのサブプロセスに同じ回答を適用します (実行中に再プロンプトしない):
- 権限をスキップ (推奨) —
--dangerously-skip-permissionsを渡します。各サブプロセスは/private/tmp/expo-skill-eval-*下の使い捨てフィクスチャ内で無人実行され、プロンプトなしでファイル書き込みやセットアップコマンドの実行が可能です。 - 編集のみ許可 — 代わりに
--permission-mode acceptEditsを渡します。Bash/インストールは自動拒否 (TTYなし) されるため、一部の評価で部分的な出力が発生する可能性があります。
どちらのフラグもなしの claude -p はファイルをまったく書き込めません。リクエストですでに設定が指定されている場合 (「権限をスキップ」、「dangerousフラグを使用しない」)、質問をスキップします。
結果ビューワーの配信方法を確認 — 開始前に1回だけ。 claude.ai への公開は外向けであるため、実行中に驚かせることがないよう、同じ事前の AskUserQuestion (権限フラグと一緒に) で尋ねます:
- ローカルのみ (デフォルト) —
generate_viewer.pyがviewer.htmlを書き込み、ローカルブラウザで開きます。何もマシンの外に出ません。 - 共有可能なアーティファクトを公開 — さらに、ビューワーをclaude.aiアーティファクト (ユーザーがチームメイトと共有できるデフォルトプライベートなウェブページ) として最後にレンダリングします。ユーザーがここでオプトインした場合のみ実行します。
リクエストですでに共有/公開の有無が指定されている場合、質問をスキップします。公開メカニズムについては ビューワー セクションを参照。
評価ケーススキーマ
実行の評価ケース — 選択されたプロンプトごとに1つ — を生成し、<workspace>/iteration-N/evals.json に書き込みます (ビューワーはそこから読み取ります)。各ケースは...
[翻訳のため省略]