Δがどれくらい大きければ、スキルが役に立つと言えますか?
公式ドキュメントに決まった数値はない。両極端ははっきりしている。両方1.0なら、そのケースはプラグインの価値を測れておらず(Claudeはもともとできる)、スキル固有の知識が必要なケースに替えるべきだ。Δがゼロに近くtool_used: Skillのグレーダーが失敗しているなら、多くはdescriptionが自然な言い回しで選ばれていないので、まずdescriptionを直す。実行が3回しかないためΔ自体にノイズがあり、小さな差を1回見ただけで読み込みすぎない。
CIはすべて緑なのに、Δがマイナスなのはなぜですか?
終了コードが見るのは、with側のスコアが--thresholdに達したかどうかだけだからだ。Δは報告されるが、終了コードを変えることはない。Δの退行でパイプラインを失敗させたいなら、--jsonで結果を出力し、withとwithoutのスコアを読んで判断する検査を自分で書く必要がある。また、既定のしきい値は1.0で、通常は必要に応じて下げることになる。そうしないと、不完全なケースが1つあるだけで全体がexit 1になる。
エンジニアではなく予算だけを見ています。評価1回の費用はどれくらいですか?
ケースの数とグレーダーの種類によるため、ドキュメントに決まった金額はない。構造ははっきりしている。1ケースは既定で6回のエージェント実行で、ジャッジを使うグレーダーの追加呼び出しも加わり、すべてプランの使用量やAPIの請求に計上される。実務では、まず--max-cost-usdで上限を設定し、日々の反復では片側(--ablation none)とコストのかからないグレーダーを使い、完全な比較はリリース前に回すようチームに頼むとよい。
スキルがテストを通ったからといって、役に立つとは限らない。Claudeはそれがなくても同じくらいうまく答えるかもしれないからだ。claude Plugin evalの設計の要点はここにある。各テストケースは、プラグインを読み込んだ状態で実行したあと、プラグインをまったく読み込まない状態でもう一度実行され、2つのスコアの差が、プラグインが実際に貢献した分になる。このコマンドにはClaude Code v2.1.269以降が必要で、gitがある場合は2.31以降が必要だ。
評価セットはプラグイン内のevals/ディレクトリに置く。各ケースはサブディレクトリで、prompt.md(ユーザーが入力しそうな一文と実行の上限)と、graders/配下の1つ以上のファイルを含む。推奨される出発点はclaude plugin eval initで、対話セッションが開き、プラグインを読み、「良い結果とは何か」を尋ね、プラグインが反応すべき/すべきでないプロンプトを提案し、グレーダーを設計して一度試走し、プロンプトごとにケースのディレクトリを書き出す。手で書くならclaude plugin eval init --bare first-caseで空のテンプレートができる。コミットメッセージを作るスキル向けの、公式ドキュメントのprompt.mdの例は次のとおり。
---
max_turns: 10
allowed_tools: [Read, Glob, Grep, Skill]
---
Write me a commit message for this change: I renamed getUser to fetchUser and updated the three call sites.
プロンプトは、スキル名を直接挙げるのではなく、ユーザーが自然に言う形で書く点に注意。もう1つのグレーダーは、答えが本当にそのスキルから出たかを確認する(your-skill-nameはスキルのディレクトリ名に置き換える)。
---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:[\w-]+:)?your-skill-name"'
---
非決定的なエージェントを1回動かしても多くはわからないので、各ケースは既定で3回実行される。1回の実行のスコアは通ったグレーダーの割合(重み付け可)、ケースのスコアは3回の平均で、--threshold(既定1.0)に達すれば合格だ。ベースラインがあるとスコアは2つになる。WITH(プラグインあり)とW/OUT(なし)で、その差がΔだ。公式ドキュメントははっきり書いている。プラグインの有無にかかわらず1.0なら、そのケースを通したのはプラグインではない。
グレーダーは6種類。regex、tool_used、tool_order、file_existsはトランスクリプトとファイルから計算され、費用はかからない。llmとbaselineはジャッジモデルを呼び、llmは3票中2票以上のPASSが必要だ。独自コードのグレーダーはない。また、「スキルが呼ばれた」というtool_used: Skillのグレーダーはプラグインなしでは絶対に通らないため、2つの条件を比べる際はスコアから除外され(scored: false)、with側では合否の目安として表示されるだけになる。
サマリーの各行はCASE WITH W/OUT Δ RUNS COST NOTESで、report.htmlも生成される。公式ドキュメントによれば、最もよくある最初の発見は、Δがゼロに近く、同時にtool_used: Skillのグレーダーが失敗していることで、自然な言い回しではClaudeがそのスキルを選んでいないという意味だ。その場合はスキルのdescriptionを調整し、再実行して比べる。逆の落とし穴もある。Skillのグレーダーは通っているのにΔがマイナスなら、まずジャッジを疑う。小さなジャッジモデルは、書式が違うだけの正しい答えを誤って不合格にすることがある。--judge-model sonnetで再実行し、ルーブリックを具体的なPASS/FAIL条件で書く。
1つのケースを繰り返し調整するなら、claude plugin eval . --case <case-name> --runs 1 --ablation noneで片側を1回だけ実行できる。ただし1回の実行はノイズが大きいと公式も注意しており、変更は既定の3回で確認する必要がある。
1ケースは、プラグインありが3回、なしが3回の計6回のエージェント実行に、llmまたはbaselineグレーダー1つにつき1回の実行あたり3回の短いジャッジ呼び出しが加わる。これらは自分の認証情報で動き、プランの使用量やAPIの請求に計上される。コマンドが報告する費用は定価ベースの見積もりだ。費用を予測しやすくする公式の助言は、変更のたびに回す素早いテストにはジャッジを呼ばないグレーダーだけを使う、Δが不要なら--ablation noneを使う(コストが半分になる)、--max-cost-usdで上限を設ける、というものだ。私の意見(公式の方針ではなく推奨)としては、日々の反復は片側とコストのかからないグレーダーで行い、2つの条件を完全に比べるのはリリース前かモデル変更時だけにするのがよい。
公式のCIの例は、結果をJSONで保存し、信頼確認のプロンプトで止まらないよう--trust-pluginを渡し、スコアを時系列で比べられるよう両方のモデルを固定し、レポートはローカルに留め、費用の上限を設ける。
claude plugin eval . \
--trust-plugin \
--json results.json \
--threshold 0.8 \
--model claude-sonnet-5 \
--judge-model claude-haiku-4-5 \
--no-publish \
--max-cost-usd 20
終了コードの意味は次のとおり。0=すべてのケースがしきい値に達し、すべてのケースファイルが読み込めた。1=しきい値未満のケースがある、ケースファイルの読み込みに失敗した、ケースが見つからない、実行を開始できない、プラグインのディレクトリが未信頼で--trust-pluginがない、またはオプションが不正。2=部分的な実行(費用の上限に達した、または認証情報が拒否された)。130=中断。143=終了させられた(CIのタイムアウトなど)。
誤解しやすい点が2つある。1つ目は、しきい値が比べるのはwith側のスコアだけだということ。2つ目は、Δは報告されるが、終了コードを変えることは決してないということだ。つまりCIが全部緑でも、プラグインがまだ価値を生んでいるとは限らない。「Δの退行」を止めたいなら、--jsonの出力を自分で読んで判断する必要がある。また、既定のしきい値が1.0なので、不完全なケースが1つでもあればexit 1になり、通常は必要に応じて下げることになる。CIではinitが質問のために端末を必要とするため、init --bareを使う。
partialと表示されないので、退行のように見える。結論を出す前にNOTES欄やJSON内のエラーを確認する。公式ドキュメントはまた、会話の中で1つのスキルを反復改善するskill-creatorプラグインも同様の比較を行うが、独自のevals/evals.json形式を使い、2つのツールは互いのケースファイルを読めないと述べている。