ローカル fixture 契約
測定器を固定する
state の投影、質問文、criteria、プロバイダー経路、解決されたモデル ID、判定ルールを同じ記録に保存します。アプリのコードが変わっていなくても、エイリアスの解決先や質問文が変われば測定器は変わっています。
テスト · fixture · CI ゲート · ローカルな実装パターン
Jev のリグレッションテストを実装するための実践ガイド。再現可能な fixture を固定し、schema・判定・副作用を検証し、確率を根拠のある許容差で比較し、CI で有意な diff を止め、ドリフトを診断し、人間のレビューを残します。
役に立つ Jev のリグレッションテストは、保存した prompt ではなく、バージョン付きの「測定器」です。同じマスキング済み state、質問、criteria、プロバイダー経路、解決済みモデルを再生し、型付き判定と必要な副作用は厳密に検証し、確率は帯域または差分で比較します。CI は候補結果を見る前に決めたポリシーだけで止めます。赤いビルドは診断の合図であり、望む答えが出るまで呼び出し続ける許可ではありません。
ここで扱うのはアプリケーション側のテストパターンであり、プロバイダーの保証ではありません。完全な評価アーティファクトと失敗記録を保存し、ラベル付きデータと反復実行から許容差を決め、ベースライン変更を必ずレビューします。月間検索ボリュームの推定値は使用していません。
すべての約束に所有者がいて、初めてテストは信頼できます。
ローカル fixture 契約
state の投影、質問文、criteria、プロバイダー経路、解決されたモデル ID、判定ルールを同じ記録に保存します。アプリのコードが変わっていなくても、エイリアスの解決先や質問文が変われば測定器は変わっています。
ローカルのリリースポリシー
ラベル付きの判定と必要な副作用は厳密に検証します。確率は宣言済みの許容差または帯域で比較し、0.873 が 0.871 になっただけでリリースを止めないでください。
人間の判断
赤い diff は証拠であって、安全性の自動判定ではありません。実行結果を保存し、影響を受けたスライスを確認し、ベースライン更新や許容差の拡大には担当レビュアーを置きます。
fixture は、別のエンジニアが判定を再現し、diff の理由まで説明できる最小完全記録です。
fixture_id安定した ID。行番号を識別子にしない。
state不安定な時刻や秘密情報を除いた、マスキング済みの証拠。
questions実行時に使った正確な type・instructions・criteria。
expected人間のラベルとローカルの pass/review 方針。プロバイダーの約束ではない。
instrument投影、質問、プロバイダー、解決済みモデルのバージョン。
下の JSON は説明用の manifest であり、Jev の設定フォーマットではありません。プロバイダーの生レスポンス、リクエストメタデータ、アダプターのハッシュも隣に保存します。モデルのエイリアスの解決先が変わったら、ベースラインを黙って書き換えず、測定器の変更として記録します。
{
"suite": "refund_completion_v3",
"fixture_id": "completed-017",
"input": {
"state": "Order ORD-1042 was delivered. The refund was issued in full.",
"questions": {
"completed": {
"type": "noul",
"instructions": "Decide whether the refund process is complete.",
"criteria": {
"true": "The evidence says the refund was issued in full.",
"false": "The refund is pending, partial, or not evidenced."
}
}
}
},
"expected": {
"decision": "true",
"pass_min": 0.82,
"review_min": 0.55
},
"instrument": {
"provider": "your-provider",
"model": "pinned-model-id",
"projection_version": "refund-trace-v2",
"question_version": "completion-v3"
}
}型付き出力は検証範囲を狭めますが、通常のテストコードを不要にはしません。
| シグナル | 検証すること | 推奨ゲート |
|---|---|---|
Noul / boolean | ラベル付きの結果は true または false で、確率は宣言した pass/review 帯域に収まること。 | 判定は厳密一致。確率は帯域または許容差で判定。 |
Choice | 選択されたラベルが期待値と一致すること。僅差が危険なら上位 2 候補の差も確認します。 | ラベルは厳密一致。margin の閾値はタスク上の根拠がある場合だけ。 |
Score / rubric | スコアが許容範囲に入り、トレンド分析のために生のスコアも保存すること。 | 範囲または集計値の差で判定し、1 例に過適合しない。 |
アプリの状態 | ワークフローが必要なレコード、ツール呼び出し、キュー、ステータスを実際に作ったこと。説得力のある文言は副作用の証拠ではありません。 | 通常のテストコードで DB・API・UI の状態を厳密に検証。 |
不正なレスポンスでは必ず fail closed にします。タイムアウト、分布の形式不正、フィールド欠落は、否定判定とは別物です。インフラ障害が意味の指標を汚染しないよう、その違いをレポートに残します。
const PROBABILITY_TOLERANCE = 0.05;
function checkCase(baseline, current, expected) {
const decisionChanged = baseline.decision !== current.decision;
const probabilityDelta = Math.abs(
baseline.probability - current.probability,
);
if (current.decision !== expected.decision) {
return { status: 'fail', reason: 'decision changed against the label' };
}
if (decisionChanged && probabilityDelta > PROBABILITY_TOLERANCE) {
return { status: 'fail', reason: 'decision flip exceeded tolerance' };
}
if (probabilityDelta > PROBABILITY_TOLERANCE) {
return { status: 'review', reason: 'probability moved beyond tolerance' };
}
return { status: 'pass', probabilityDelta };
}リスクに合う最小限の方針を使います。以下の数値は例であり、普遍的なデフォルトではありません。
ラベル付き fixture では、選択された choice や boolean が通常のハードアサーションです。0.873 が 0.871 になっただけではリグレッションとは限らず、判定の反転は別のシグナルです。
閾値付き自動化では pass・review・fail の帯域を保存します。ホールドアウトラベルや反復実行で境界を決め、式と分母をゲートの横に置きます。1 回の良い実行を保証に変えないでください。
閾値に近いケースは、自動で許容差を広げるのではなく、レビューまたは再実行へ送ります。重要な判定では flip rate、上位 2 候補の差、スライス別の影響を記録します。
平均、エラー率、キャリブレーション指標を比較するときは、サンプル数とスライス定義も示します。同じセッションや顧客のイベントが相関するなら、独立単位で再サンプリングします。
毎回の変更では小さな決定的契約テストを実行し、ライブプロバイダーの予算は制限した smoke / release スイートに使います。
name: Jev regression suite
on:
pull_request:
push:
branches: [main]
jobs:
jev-regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: pnpm eval:jev -- --fixtures evals/fixtures.jsonl --baseline evals/baseline.json --tolerance 0.05 --write-current artifacts/jev-current.json --markdown artifacts/jev-regression.md
- uses: actions/upload-artifact@v4
if: always()
with:
name: jev-regression-report
path: artifacts/
ワークフローの `eval:jev` は、リポジトリが所有する wrapper の仮名です。コミュニティの harness に似た baseline/tolerance フラグがあっても、プロバイダー公式のインターフェースではありません。wrapper は事前定義した重要ケースまたは集計ゲートでだけ非ゼロ終了し、成功時も失敗時も完全なレポートをアップロードします。
良い失敗レポートは次の行動を明確にし、「緑になるまで再試行」を防ぎます。
| 失敗分類 | 残す証拠 | 次の行動 |
|---|---|---|
| 不正なリクエストまたはパースエラー | ペイロードのハッシュ、schema エラー、レスポンスボディ、アダプターのバージョン。 | 契約を修正し、採点前に互換性のないプロバイダーレスポンスを拒否する。 |
| タイムアウト、レート制限、認証失敗 | HTTP ステータス、request ID、試行回数、バックオフ、プロバイダー/モデルの識別情報。 | まずインフラ障害として分類し、結果なしを偽の判定に変換しない。 |
| 同じ測定器なのにラベル付き判定が変わった | 旧/新のペア出力、確率差、fixture タグ、影響を受けたスライス。 | レビュアーが変化を説明するまで、意味上のリグレッションとして扱う。 |
| fixture またはラベルの欠陥 | マスキング差分、出典、ラベルのプロヴェナンス、レビュー履歴。 | 出典を残して修正し、旧記録も保持する。CI を緑にするために履歴を消さない。 |
旧/新の分布、モデルとプロバイダーの識別情報、fixture タグ、request ID、レイテンシ、リトライメタデータを出力します。結果なしと誤判定を分離し、ベースライン更新は理由付きのレビュー済み変更として残します。
収集と比較は自動化し、リスクの判断は責任者に残します。
fixture がまだ代表的で、正しくマスキングされていることを確認します。製品の挙動が意図的に変わったなら、expected label だけでなく要件と出典を更新します。
集計スコアだけでなく、ペアになった証拠を読みます。重要な失敗では state の投影、質問、criteria、生レスポンスを確認します。
変化が単発か、言語・ソース・重大度・証拠の有無・選択肢数・閾値からの距離など特定のスライスに集中しているかを調べます。
adapter の修正、対象となるインフラ障害の再試行、出典付き fixture 修正、リリース阻止、または担当者と期限を明記したベースライン受け入れのいずれかを選びます。
旧アーティファクトと新アーティファクトを両方残します。ベースラインは意思決定の記録であり、捨てるキャッシュではありません。
確率の閾値を安全証明のように扱わないでください。ローカルゲートが示すのは、この fixture 集、測定器、方針で、このリポジトリが結果をどう扱うかだけです。プロバイダーの精度、将来の安定性、測定範囲外の業務安全性は証明しません。
最低限、安定した fixture ID、マスキング済み state、正確な typed questions と criteria、人間のラベルまたは受け入れ条件、ローカルの判定方針、プロバイダー/モデル/測定器のバージョンを入れます。生レスポンスとリクエストメタデータも隣に保存し、変化を診断できるようにします。
通常は不要です。typed decision と必要な副作用を厳密に検証し、確率の動きは宣言済みの許容差または帯域で比較します。浮動小数点の完全一致スナップショットは脆いものです。許容差はホールドアウトラベル、反復実行の揺れ、誤判定コストから決めます。このページの 0.05 は普遍的なデフォルトではありません。
プルリクエストごとにプロバイダーを呼ばない契約スイートを実行し、固定 fixture で制限したライブ smoke / release スイートを走らせます。現在の実行を保存し、レビュー済みベースラインと比較します。事前定義した重要ケースや集計ゲートだけで止め、失敗時もレポートをアップロードします。wrapper はリポジトリ内に置き、方針をレビュー可能にします。
意味上のリグレッション、意図した要件変更、質問や state 投影の変更、プロバイダー/モデル変更、fixture の欠陥、インフラ障害の誤分類などが考えられます。まず測定器全体と生レスポンスを比較し、レビュアーが原因と行動を説明するまでベースラインを更新しません。
できません。実際に測定した fixture、ラベル、測定器、ゲートについて再現可能な証拠を提供するものです。プロバイダーの保証や、未代表のトラフィックはカバーしません。重要ケースのハードゲート、スライス分析、遅延した人間のラベル、プロダクション監視を追加し、主張の範囲を明記します。
重要ケースの失敗、閾値に近いケース、新規/削除 fixture、特定スライスへの集中、ベースライン変更、プロバイダーやモデルのバージョン変更はレビュー対象です。集計指標が安定していても、重要なケースが反転していないかを確認します。