テスト · fixture · CI ゲート · ローカルな実装パターン

Jev のリグレッションテスト:再現可能な fixture、許容差、CI ゲート

Jev のリグレッションテストを実装するための実践ガイド。再現可能な fixture を固定し、schema・判定・副作用を検証し、確率を根拠のある許容差で比較し、CI で有意な diff を止め、ドリフトを診断し、人間のレビューを残します。

要点

役に立つ Jev のリグレッションテストは、保存した prompt ではなく、バージョン付きの「測定器」です。同じマスキング済み state、質問、criteria、プロバイダー経路、解決済みモデルを再生し、型付き判定と必要な副作用は厳密に検証し、確率は帯域または差分で比較します。CI は候補結果を見る前に決めたポリシーだけで止めます。赤いビルドは診断の合図であり、望む答えが出るまで呼び出し続ける許可ではありません。

ここで扱うのはアプリケーション側のテストパターンであり、プロバイダーの保証ではありません。完全な評価アーティファクトと失敗記録を保存し、ラベル付きデータと反復実行から許容差を決め、ベースライン変更を必ずレビューします。月間検索ボリュームの推定値は使用していません。

まず境界を引く:プロバイダーとアプリケーション

すべての約束に所有者がいて、初めてテストは信頼できます。

ローカル fixture 契約

測定器を固定する

state の投影、質問文、criteria、プロバイダー経路、解決されたモデル ID、判定ルールを同じ記録に保存します。アプリのコードが変わっていなくても、エイリアスの解決先や質問文が変われば測定器は変わっています。

ローカルのリリースポリシー

浮動小数点ではなく挙動を検証する

ラベル付きの判定と必要な副作用は厳密に検証します。確率は宣言済みの許容差または帯域で比較し、0.873 が 0.871 になっただけでリリースを止めないでください。

人間の判断

レビューをループに残す

赤い diff は証拠であって、安全性の自動判定ではありません。実行結果を保存し、影響を受けたスライスを確認し、ベースライン更新や許容差の拡大には担当レビュアーを置きます。

再現可能な replay fixture を作る

fixture は、別のエンジニアが判定を再現し、diff の理由まで説明できる最小完全記録です。

fixture_id

安定した ID。行番号を識別子にしない。

state

不安定な時刻や秘密情報を除いた、マスキング済みの証拠。

questions

実行時に使った正確な type・instructions・criteria。

expected

人間のラベルとローカルの pass/review 方針。プロバイダーの約束ではない。

instrument

投影、質問、プロバイダー、解決済みモデルのバージョン。

下の JSON は説明用の manifest であり、Jev の設定フォーマットではありません。プロバイダーの生レスポンス、リクエストメタデータ、アダプターのハッシュも隣に保存します。モデルのエイリアスの解決先が変わったら、ベースラインを黙って書き換えず、測定器の変更として記録します。

fixture.json
{
  "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"
  }
}

schema・判定・副作用を分けて検証する

型付き出力は検証範囲を狭めますが、通常のテストコードを不要にはしません。

シグナル検証すること推奨ゲート
Noul / booleanラベル付きの結果は true または false で、確率は宣言した pass/review 帯域に収まること。判定は厳密一致。確率は帯域または許容差で判定。
Choice選択されたラベルが期待値と一致すること。僅差が危険なら上位 2 候補の差も確認します。ラベルは厳密一致。margin の閾値はタスク上の根拠がある場合だけ。
Score / rubricスコアが許容範囲に入り、トレンド分析のために生のスコアも保存すること。範囲または集計値の差で判定し、1 例に過適合しない。
アプリの状態ワークフローが必要なレコード、ツール呼び出し、キュー、ステータスを実際に作ったこと。説得力のある文言は副作用の証拠ではありません。通常のテストコードで DB・API・UI の状態を厳密に検証。

不正なレスポンスでは必ず fail closed にします。タイムアウト、分布の形式不正、フィールド欠落は、否定判定とは別物です。インフラ障害が意味の指標を汚染しないよう、その違いをレポートに残します。

assertions.ts
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 候補の差、スライス別の影響を記録します。

集計を慎重に扱う

平均、エラー率、キャリブレーション指標を比較するときは、サンプル数とスライス定義も示します。同じセッションや顧客のイベントが相関するなら、独立単位で再サンプリングします。

差分を CI ゲートにする

毎回の変更では小さな決定的契約テストを実行し、ライブプロバイダーの予算は制限した smoke / release スイートに使います。

.github/workflows/jev-regression.yml
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、レイテンシ、リトライメタデータを出力します。結果なしと誤判定を分離し、ベースライン更新は理由付きのレビュー済み変更として残します。

人間のレビューもテスト設計の一部

収集と比較は自動化し、リスクの判断は責任者に残します。

  1. 1

    fixture がまだ代表的で、正しくマスキングされていることを確認します。製品の挙動が意図的に変わったなら、expected label だけでなく要件と出典を更新します。

  2. 2

    集計スコアだけでなく、ペアになった証拠を読みます。重要な失敗では state の投影、質問、criteria、生レスポンスを確認します。

  3. 3

    変化が単発か、言語・ソース・重大度・証拠の有無・選択肢数・閾値からの距離など特定のスライスに集中しているかを調べます。

  4. 4

    adapter の修正、対象となるインフラ障害の再試行、出典付き fixture 修正、リリース阻止、または担当者と期限を明記したベースライン受け入れのいずれかを選びます。

  5. 5

    旧アーティファクトと新アーティファクトを両方残します。ベースラインは意思決定の記録であり、捨てるキャッシュではありません。

確率の閾値を安全証明のように扱わないでください。ローカルゲートが示すのは、この fixture 集、測定器、方針で、このリポジトリが結果をどう扱うかだけです。プロバイダーの精度、将来の安定性、測定範囲外の業務安全性は証明しません。

Jev リグレッションテスト FAQ

Jev のリグレッション fixture には何を入れますか?

最低限、安定した fixture ID、マスキング済み state、正確な typed questions と criteria、人間のラベルまたは受け入れ条件、ローカルの判定方針、プロバイダー/モデル/測定器のバージョンを入れます。生レスポンスとリクエストメタデータも隣に保存し、変化を診断できるようにします。

Jev の確率を完全一致で検証すべきですか?

通常は不要です。typed decision と必要な副作用を厳密に検証し、確率の動きは宣言済みの許容差または帯域で比較します。浮動小数点の完全一致スナップショットは脆いものです。許容差はホールドアウトラベル、反復実行の揺れ、誤判定コストから決めます。このページの 0.05 は普遍的なデフォルトではありません。

CI で Jev のリグレッションをゲートするには?

プルリクエストごとにプロバイダーを呼ばない契約スイートを実行し、固定 fixture で制限したライブ smoke / release スイートを走らせます。現在の実行を保存し、レビュー済みベースラインと比較します。事前定義した重要ケースや集計ゲートだけで止め、失敗時もレポートをアップロードします。wrapper はリポジトリ内に置き、方針をレビュー可能にします。

判定が変わったら何を意味しますか?

意味上のリグレッション、意図した要件変更、質問や state 投影の変更、プロバイダー/モデル変更、fixture の欠陥、インフラ障害の誤分類などが考えられます。まず測定器全体と生レスポンスを比較し、レビュアーが原因と行動を説明するまでベースラインを更新しません。

Jev のリグレッションスイートで安全性を証明できますか?

できません。実際に測定した fixture、ラベル、測定器、ゲートについて再現可能な証拠を提供するものです。プロバイダーの保証や、未代表のトラフィックはカバーしません。重要ケースのハードゲート、スライス分析、遅延した人間のラベル、プロダクション監視を追加し、主張の範囲を明記します。

Jev の結果を人間がレビューするのはいつですか?

重要ケースの失敗、閾値に近いケース、新規/削除 fixture、特定スライスへの集中、ベースライン変更、プロバイダーやモデルのバージョン変更はレビュー対象です。集計指標が安定していても、重要なケースが反転していないかを確認します。