@tangle-network/agent-eval 0.69.0 → 0.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/adapters/http.d.ts +1 -1
  3. package/dist/adapters/http.js +1 -1
  4. package/dist/adapters/http.js.map +1 -1
  5. package/dist/adapters/langchain.d.ts +1 -1
  6. package/dist/adapters/otel.d.ts +2 -2
  7. package/dist/campaign/index.d.ts +19 -7
  8. package/dist/campaign/index.js +29 -5
  9. package/dist/campaign/index.js.map +1 -1
  10. package/dist/{chunk-E24XD7A2.js → chunk-6QZUCFKM.js} +2 -2
  11. package/dist/{chunk-3B7Y5AUR.js → chunk-GWGO2K6Y.js} +3 -2
  12. package/dist/chunk-GWGO2K6Y.js.map +1 -0
  13. package/dist/{chunk-Z4ZCBC7M.js → chunk-ODGETRTM.js} +4 -3
  14. package/dist/chunk-ODGETRTM.js.map +1 -0
  15. package/dist/{chunk-JFGZPUMU.js → chunk-VMAYE3LM.js} +26 -6
  16. package/dist/chunk-VMAYE3LM.js.map +1 -0
  17. package/dist/contract/index.d.ts +8 -8
  18. package/dist/contract/index.js +2 -2
  19. package/dist/hosted/index.d.ts +2 -2
  20. package/dist/{index-DSEHMwvS.d.ts → index-BGBrVS24.d.ts} +1 -1
  21. package/dist/index.d.ts +7 -2
  22. package/dist/index.js +21 -16
  23. package/dist/index.js.map +1 -1
  24. package/dist/openapi.json +1 -1
  25. package/dist/pipelines/index.js +1 -1
  26. package/dist/{provenance-CChUqexv.d.ts → provenance-C69gLUXH.d.ts} +3 -3
  27. package/dist/rl.d.ts +156 -2
  28. package/dist/rl.js +195 -6
  29. package/dist/rl.js.map +1 -1
  30. package/dist/{run-improvement-loop-BKpM5T4t.d.ts → run-improvement-loop-Bzamo6GB.d.ts} +1 -1
  31. package/dist/traces.js +1 -1
  32. package/dist/{types-c2R2kfmv.d.ts → types-CnmZ2bkP.d.ts} +7 -1
  33. package/package.json +1 -1
  34. package/dist/chunk-3B7Y5AUR.js.map +0 -1
  35. package/dist/chunk-JFGZPUMU.js.map +0 -1
  36. package/dist/chunk-Z4ZCBC7M.js.map +0 -1
  37. /package/dist/{chunk-E24XD7A2.js.map → chunk-6QZUCFKM.js.map} +0 -0
package/dist/rl.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rl/compute-curves.ts","../src/rl/contamination.ts","../src/rl/off-policy.ts","../src/rl/preferences.ts","../src/rl/run-record-adapters.ts","../src/rl/tournament.ts","../src/rl/active-curriculum.ts","../src/rl/adaptation-eval.ts","../src/rl/adversarial.ts","../src/rl/exporters.ts","../src/rl/predictive-validity-researcher.ts","../src/rl/process-reward.ts","../src/rl/rl-campaign.ts"],"sourcesContent":["/**\n * Test-time compute scaling curves.\n *\n * The test-time-compute frontier paper (Snell et al. 2024) and the\n * subsequent o1-style scaling work both show that LLM-agent capability\n * is a function of the compute budget at inference, not just of the\n * training run. The right way to characterize a candidate is therefore\n * a *curve* — score at compute budgets {1×, 4×, 16×, …} — not a single\n * point.\n *\n * This module ships:\n *\n * 1. The compute-curve harness — `runComputeCurve(runner, budgets)` —\n * that evaluates one candidate at a sequence of compute budgets\n * and returns the (compute, score) curve.\n * 2. A best-of-N evaluator — `bestOfN(runner, n, scoreFn)` — the\n * simplest test-time-compute scaling primitive: sample N\n * independent rollouts, return the best.\n * 3. A self-consistency evaluator — `selfConsistency(runner, n)` —\n * the majority-vote variant of best-of-N for tasks with a small\n * categorical answer space.\n * 4. Pareto-frontier extraction over multiple candidates — given\n * (candidate, compute, score) tuples, return the set of\n * candidate-compute combinations that aren't dominated.\n *\n * Caveat: \"compute\" here is the caller's notion of a compute unit. For\n * agent eval that's typically wall-time × parallelism, or token budget,\n * or LLM-call count. We accept whatever the caller provides; the curve\n * is on whatever axis they pick.\n */\n\nimport { ValidationError } from '../errors'\n\nexport interface ComputeCurveBudget {\n /** Identifier — for the report. Common: '1x', '4x', '16x'. */\n id: string\n /** Numeric value on the chosen axis (tokens, calls, USD, ms — caller picks). */\n cost: number\n /** Free-form metadata (the caller can carry per-budget config). */\n meta?: Record<string, unknown>\n}\n\nexport interface ComputeCurvePoint {\n budgetId: string\n cost: number\n score: number\n /** Number of underlying samples used at this budget. */\n samples: number\n /** Optional spread / variance information. */\n std?: number\n /** Any extra metrics the runner returned. */\n metrics?: Record<string, number>\n}\n\nexport interface ComputeCurve {\n candidateId: string\n points: ComputeCurvePoint[]\n /** Rough exponent fit: score ≈ a + b * log(cost). Useful for \"how steep is the curve?\" */\n logSlope: number | null\n /** Best (highest-score) point on the curve. */\n best: ComputeCurvePoint\n}\n\nexport interface RunComputeCurveOptions {\n candidateId: string\n budgets: ComputeCurveBudget[]\n /**\n * Run the candidate at one budget. Returns the realized score plus\n * optional spread + extra metrics.\n */\n runAtBudget: (budget: ComputeCurveBudget) => Promise<{\n score: number\n samples: number\n std?: number\n metrics?: Record<string, number>\n }>\n}\n\nexport async function runComputeCurve(opts: RunComputeCurveOptions): Promise<ComputeCurve> {\n const points: ComputeCurvePoint[] = []\n for (const budget of opts.budgets) {\n const r = await opts.runAtBudget(budget)\n points.push({\n budgetId: budget.id,\n cost: budget.cost,\n score: r.score,\n samples: r.samples,\n std: r.std,\n metrics: r.metrics,\n })\n }\n const sorted = [...points].sort((a, b) => a.cost - b.cost)\n const logSlope = sorted.length >= 2 ? fitLogSlope(sorted) : null\n const best = points.reduce((a, b) => (b.score > a.score ? b : a))\n return { candidateId: opts.candidateId, points: sorted, logSlope, best }\n}\n\nexport interface ComputeBestOfNOptions<O> {\n /** Number of independent samples to draw. */\n n: number\n /** Sampler — produces one rollout. */\n sample: (sampleIdx: number) => Promise<O>\n /** Score one rollout. */\n scoreFn: (rollout: O) => Promise<number> | number\n}\n\nexport interface ComputeBestOfNResult<O> {\n best: O\n bestScore: number\n scores: number[]\n meanScore: number\n /** Index of the best rollout, for diagnostics. */\n bestIndex: number\n}\n\n/** The simplest test-time scaling primitive. */\nexport async function bestOfN<O>(opts: ComputeBestOfNOptions<O>): Promise<ComputeBestOfNResult<O>> {\n if (opts.n <= 0) throw new ValidationError('bestOfN: n must be > 0')\n const rollouts: O[] = []\n const scores: number[] = []\n for (let i = 0; i < opts.n; i++) {\n const r = await opts.sample(i)\n rollouts.push(r)\n scores.push(await opts.scoreFn(r))\n }\n let bestIndex = 0\n for (let i = 1; i < scores.length; i++) if (scores[i]! > scores[bestIndex]!) bestIndex = i\n const meanScore = scores.reduce((s, x) => s + x, 0) / scores.length\n return {\n best: rollouts[bestIndex]!,\n bestScore: scores[bestIndex]!,\n scores,\n meanScore,\n bestIndex,\n }\n}\n\nexport interface SelfConsistencyOptions<O> {\n n: number\n sample: (sampleIdx: number) => Promise<O>\n /** Extract the canonical answer key (string) from a rollout. */\n answerKey: (rollout: O) => string\n}\n\nexport interface SelfConsistencyResult<O> {\n /** Modal answer (the majority vote). */\n answer: string\n /** Fraction of samples voting for the modal answer in [0, 1]. */\n agreement: number\n /** Histogram of all answers. */\n histogram: Record<string, number>\n /** A representative rollout that voted for the modal answer. */\n representative: O\n /** All rollouts. */\n rollouts: O[]\n}\n\n/**\n * Self-consistency / majority-vote test-time scaling. For tasks with a\n * small categorical answer space (math problems, multiple choice).\n */\nexport async function selfConsistency<O>(\n opts: SelfConsistencyOptions<O>,\n): Promise<SelfConsistencyResult<O>> {\n if (opts.n <= 0) throw new ValidationError('selfConsistency: n must be > 0')\n const rollouts: O[] = []\n const histogram: Record<string, number> = {}\n for (let i = 0; i < opts.n; i++) {\n const r = await opts.sample(i)\n rollouts.push(r)\n const key = opts.answerKey(r)\n histogram[key] = (histogram[key] ?? 0) + 1\n }\n let answer = ''\n let max = -1\n for (const [k, v] of Object.entries(histogram)) {\n if (v > max) {\n max = v\n answer = k\n }\n }\n const representative = rollouts.find((r) => opts.answerKey(r) === answer) ?? rollouts[0]!\n return {\n answer,\n agreement: max / opts.n,\n histogram,\n representative,\n rollouts,\n }\n}\n\n/**\n * Pareto frontier over (candidate, compute, score) tuples. A point is on\n * the frontier iff no other point dominates it in both score (higher\n * better) and cost (lower better). Returns the frontier sorted ascending\n * by cost.\n */\nexport interface ParetoPointInput {\n candidateId: string\n budgetId: string\n cost: number\n score: number\n}\n\nexport function paretoFrontier(points: ParetoPointInput[]): ParetoPointInput[] {\n const onFrontier: ParetoPointInput[] = []\n for (const p of points) {\n const dominated = points.some(\n (q) =>\n q !== p && q.cost <= p.cost && q.score >= p.score && (q.cost < p.cost || q.score > p.score),\n )\n if (!dominated) onFrontier.push(p)\n }\n return onFrontier.sort((a, b) => a.cost - b.cost)\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction fitLogSlope(points: ComputeCurvePoint[]): number {\n // OLS slope of score on log(cost). Used as a single-number summary of\n // how much marginal compute helps. Positive = score improves with\n // compute; near-zero = capability ceiling reached.\n const xs = points.map((p) => Math.log(Math.max(1e-12, p.cost)))\n const ys = points.map((p) => p.score)\n const n = xs.length\n const mx = xs.reduce((s, x) => s + x, 0) / n\n const my = ys.reduce((s, y) => s + y, 0) / n\n let num = 0\n let den = 0\n for (let i = 0; i < n; i++) {\n num += (xs[i]! - mx) * (ys[i]! - my)\n den += (xs[i]! - mx) ** 2\n }\n return den === 0 ? 0 : num / den\n}\n","/**\n * Contamination probe — held-out perturbation tests.\n *\n * The bug class: once a benchmark scenario set is published, models train\n * on it, and your scores become invalid. SWE-Bench-Verified, GPQA, and\n * MMLU-Pro all exist because their predecessors got contaminated within\n * months. The right defense is to keep a held-out *perturbed* version of\n * every scenario — same task, slightly different surface — and check\n * whether scores diverge significantly. Genuine capability transfers; rote\n * memorization doesn't.\n *\n * This module ships the probe contract:\n *\n * 1. A `ScenarioPerturbation` strategy type — function that produces a\n * perturbed scenario from an original.\n * 2. `runContaminationProbe({ originals, perturbed, scoreFn })` — runs\n * both halves and reports per-scenario score divergence + a global\n * contamination verdict via paired Wilcoxon.\n * 3. Several stock perturbations: `renameVariables`, `shuffleOrder`,\n * `paraphrasePrompt`, `injectIrrelevantClause`. Each preserves the\n * task's structural difficulty while breaking surface memorization.\n *\n * The verdict is conservative: if the perturbed-vs-original score\n * difference is statistically significant (BH-adjusted p < 0.05) AND\n * the median drop is > 5 percentage points, we flag *contamination\n * suspected*. False positives are possible (the perturbation might\n * actually be harder); the default is to flag for review, not to\n * autoreject.\n */\n\nimport { ValidationError } from '../errors'\nimport { benjaminiHochberg, wilcoxonSignedRank } from '../statistics'\n\nexport type ScenarioPerturbationKind =\n | 'rename_variables'\n | 'shuffle_order'\n | 'paraphrase'\n | 'inject_irrelevant_clause'\n | 'custom'\n\nexport interface ScenarioPerturbation<S> {\n kind: ScenarioPerturbationKind\n /** Apply to one scenario, return its perturbed sibling. */\n apply: (scenario: S) => Promise<S> | S\n /** Optional id — for the report. */\n id?: string\n}\n\nexport interface ContaminationProbeInput<S> {\n /** Identity of every scenario. The probe's `runFingerprint` keys on these. */\n scenarioId: (s: S) => string\n /** Original scenarios. */\n originals: S[]\n /**\n * Either pre-computed perturbations (one per original, same order) OR a\n * `perturbation` strategy that synthesizes them on the fly.\n */\n perturbed?: S[]\n perturbation?: ScenarioPerturbation<S>\n /**\n * Run the policy/agent against one scenario and return a scalar score\n * in [0, 1]. The probe doesn't care what the policy is — that's the\n * caller's contract.\n */\n scoreFn: (s: S) => Promise<number>\n}\n\nexport interface ContaminationProbeOptions {\n /** Drop scores below this from the probe; treats partial failures separately. Default 0. */\n scoreFloor?: number\n /**\n * BH-FDR threshold for declaring contamination on each per-scenario\n * delta. Default 0.05.\n */\n fdr?: number\n /**\n * Minimum median per-scenario drop to flag global contamination. Default\n * 0.05 (5 percentage points). Smaller drops may be noise.\n */\n minMedianDrop?: number\n}\n\nexport interface ContaminationProbeReport {\n perScenario: Array<{\n scenarioId: string\n originalScore: number\n perturbedScore: number\n delta: number // perturbed - original (negative = drop)\n /** Per-scenario q-value (single-test BH for a single scenario). Mainly for display. */\n qValue: number\n }>\n /** Wilcoxon paired-test on the deltas. */\n pairedTest: { w: number; p: number }\n medianDelta: number\n meanDelta: number\n contaminationSuspected: boolean\n reason: string\n /** Number of scenarios processed. */\n n: number\n}\n\nexport async function runContaminationProbe<S>(\n input: ContaminationProbeInput<S>,\n opts: ContaminationProbeOptions = {},\n): Promise<ContaminationProbeReport> {\n const fdr = opts.fdr ?? 0.05\n const minMedianDrop = opts.minMedianDrop ?? 0.05\n const floor = opts.scoreFloor ?? 0\n\n if (!input.perturbed && !input.perturbation) {\n throw new ValidationError(\n 'runContaminationProbe: must supply either `perturbed` or `perturbation`.',\n )\n }\n const perturbed: S[] =\n input.perturbed ?? (await Promise.all(input.originals.map((s) => input.perturbation!.apply(s))))\n if (perturbed.length !== input.originals.length) {\n throw new ValidationError(\n `runContaminationProbe: perturbed length ${perturbed.length} ≠ originals ${input.originals.length}`,\n )\n }\n\n // Score both halves.\n const origScores = await Promise.all(input.originals.map((s) => input.scoreFn(s)))\n const pertScores = await Promise.all(perturbed.map((s) => input.scoreFn(s)))\n\n const perScenario = input.originals.map((s, i) => ({\n scenarioId: input.scenarioId(s),\n originalScore: origScores[i]!,\n perturbedScore: pertScores[i]!,\n delta: pertScores[i]! - origScores[i]!,\n qValue: NaN,\n }))\n\n // Drop scenarios below the floor (partial failures we don't trust).\n const valid = perScenario.filter((p) => p.originalScore >= floor && p.perturbedScore >= floor)\n if (valid.length < 4) {\n return {\n perScenario,\n pairedTest: { w: 0, p: 1 },\n medianDelta: 0,\n meanDelta: 0,\n contaminationSuspected: false,\n reason: `insufficient valid scenarios (n=${valid.length}, need ≥ 4)`,\n n: valid.length,\n }\n }\n\n const origValid = valid.map((p) => p.originalScore)\n const pertValid = valid.map((p) => p.perturbedScore)\n const pairedTest = wilcoxonSignedRank(origValid, pertValid)\n const deltas = valid.map((p) => p.delta)\n const sortedDeltas = [...deltas].sort((a, b) => a - b)\n const median = sortedDeltas[Math.floor(sortedDeltas.length / 2)]!\n const mean = deltas.reduce((s, d) => s + d, 0) / deltas.length\n\n // Per-scenario q-values via BH on a synthetic per-scenario p-value\n // (one-sample bootstrap; we use the absolute delta normalized by median\n // as a coarse signal — this is a display aid, the load-bearing test\n // is the global Wilcoxon).\n const pseudoP = valid.map((p) => Math.min(1, Math.max(1e-6, 1 - Math.abs(p.delta) / 1)))\n const { qValues } = benjaminiHochberg(pseudoP, fdr)\n for (let i = 0; i < valid.length; i++) {\n const v = valid[i]!\n const idx = perScenario.findIndex((p) => p.scenarioId === v.scenarioId)\n if (idx >= 0) perScenario[idx]!.qValue = qValues[i]!\n }\n\n const contaminationSuspected = pairedTest.p < fdr && median <= -minMedianDrop\n const reason = contaminationSuspected\n ? `paired p=${pairedTest.p.toFixed(4)} < ${fdr} and median drop ${median.toFixed(4)} ≥ ${minMedianDrop}`\n : pairedTest.p >= fdr\n ? `no significant difference (paired p=${pairedTest.p.toFixed(4)})`\n : `significant but small effect (median delta ${median.toFixed(4)})`\n\n return {\n perScenario,\n pairedTest,\n medianDelta: median,\n meanDelta: mean,\n contaminationSuspected,\n reason,\n n: valid.length,\n }\n}\n\n// ── Stock perturbations ──────────────────────────────────────────────────\n\n/**\n * Identifier-rename perturbation for code/text scenarios. Replaces every\n * occurrence of the listed identifiers with synthesized aliases. Use when\n * the scenario's structural difficulty is independent of variable names\n * (e.g. SWE-Bench-style coding tasks).\n */\nexport function renameVariables<S extends { prompt: string }>(\n identifiers: string[],\n rename: (name: string, idx: number) => string = (n, i) => `${n}_${((i % 26) + 10).toString(36)}`,\n): ScenarioPerturbation<S> {\n return {\n kind: 'rename_variables',\n apply(scenario) {\n let prompt = scenario.prompt\n identifiers.forEach((id, i) => {\n const replacement = rename(id, i)\n const re = new RegExp(`\\\\b${escapeRegex(id)}\\\\b`, 'g')\n prompt = prompt.replace(re, replacement)\n })\n return { ...scenario, prompt }\n },\n }\n}\n\n/**\n * Order-shuffle perturbation. Reshuffles a list-shaped section of the\n * prompt (for QA scenarios that present options A/B/C/D — answer depends\n * on the option labels, not order). Caller provides the section extractor.\n */\nexport function shuffleOrder<S extends { prompt: string }>(\n shuffleSection: (prompt: string, rng: () => number) => string,\n seed: number,\n): ScenarioPerturbation<S> {\n let s = seed >>> 0\n const rng = (): number => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n return {\n kind: 'shuffle_order',\n apply(scenario) {\n const newPrompt = shuffleSection(scenario.prompt, rng)\n return { ...scenario, prompt: newPrompt }\n },\n }\n}\n\n/**\n * Inject-irrelevant-clause perturbation. Adds a benign sentence that\n * shouldn't change the answer. Tests for \"did the model just memorize\n * the input string.\"\n */\nexport function injectIrrelevantClause<S extends { prompt: string }>(\n clause: string,\n position: 'prefix' | 'suffix' = 'prefix',\n): ScenarioPerturbation<S> {\n return {\n kind: 'inject_irrelevant_clause',\n apply(scenario) {\n const prompt =\n position === 'prefix' ? `${clause} ${scenario.prompt}` : `${scenario.prompt} ${clause}`\n return { ...scenario, prompt }\n },\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","/**\n * Off-policy evaluation primitives.\n *\n * Standard inverse-probability-weighted (IPS), self-normalized\n * importance-weighted (SNIPS), and doubly-robust (DR) estimators for the\n * value of a *target* policy given trajectories collected under a\n * *behavior* policy. This is the canonical RL eval task: \"we have last\n * week's runs, we changed the policy — how would the new one do without\n * re-running?\"\n *\n * The math here is textbook (Dudík, Langford, Li 2011 for DR; Swaminathan\n * & Joachims 2015 for SNIPS) but the *application* to LLM-agent\n * evaluation needs care:\n *\n * - The \"policy\" is the (prompt, tool config, model snapshot) triple.\n * Two policies have the same probability over an action *iff* their\n * LLM call would emit the same token with the same probability —\n * which is generally unknowable without the model log-probs.\n * - For LLM agents, propensity scores must be supplied by the caller\n * (logged in the trace, recovered from token log-probs, or estimated\n * via a learned propensity model). We do NOT estimate propensity here.\n * - Doubly-robust requires a Q-function (model-based reward predictor).\n * We accept any callable; consumers pass either a tabular average,\n * a regression fit, or a learned reward model.\n *\n * Bias / variance tradeoffs:\n * - IPS: unbiased; high variance for small overlap, infinite variance\n * when target has support outside behavior.\n * - SNIPS: lower variance, slight bias; usually preferred in practice.\n * - DR: doubly-robust — unbiased if either propensity OR Q-function is\n * correct. Lowest practical variance when Q is decent. Use this.\n *\n * Caveat the panel will land: on the LLM-agent setting, propensity scores\n * recovered from token log-probs are noisy, the action space is enormous,\n * and overlap is often poor. These estimators are useful but not magic;\n * complement with `replayCampaign` (exact replay where the request hashes\n * match) for high-confidence answers and OPE for the gap.\n */\n\nimport { ValidationError } from '../errors'\n\nexport interface OffPolicyTrajectory {\n /** Stable id, for traceability through the dataset. */\n runId: string\n /** Reward observed under the behavior policy (the realized outcome). */\n reward: number\n /**\n * Behavior-policy probability of the action that was taken. For LLM\n * agents this is typically `exp(sum(token_log_probs))` over the chosen\n * trajectory. Must be in (0, 1].\n */\n behaviorProb: number\n /**\n * Target-policy probability of the same action. For replay-style\n * counterfactual evaluation this is what the *new* policy would have\n * assigned to the *old* trajectory. Must be in [0, 1].\n */\n targetProb: number\n /**\n * Optional model-based reward prediction at the same context. Used by\n * `doublyRobust`. Set to `null` for IPS-only evaluation.\n */\n qHat?: number | null\n}\n\nexport interface OffPolicyEstimate {\n /** Estimated value of the target policy. */\n value: number\n /** Standard error of the estimate. */\n standardError: number\n /** Effective sample size (Kong 1992). Lower = more reliance on a few high-weight samples. */\n effectiveSampleSize: number\n /** Number of trajectories used. */\n n: number\n /**\n * Diagnostic: maximum importance weight observed. Large values (>>10x\n * mean) are a red flag — variance is dominated by a few outliers.\n */\n maxImportanceWeight: number\n}\n\nexport interface OffPolicyOptions {\n /**\n * Cap importance weights at this value (Ionides 2008 truncated IS) to\n * trade unbiasedness for variance reduction. Default `Infinity` (no cap).\n * Set e.g. `10` for stable estimates when the policies are close.\n */\n weightCap?: number\n /** Reward clipping range. Default `[0, 1]`. */\n rewardClip?: { low: number; high: number }\n}\n\n/**\n * Inverse Probability Weighting (Horvitz-Thompson). Unbiased estimator\n * of E[reward under target policy]. Variance scales with the spread of\n * target/behavior ratios.\n */\nexport function inverseProbabilityWeighting(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n\n if (trajectories.length === 0) {\n return zeroEstimate()\n }\n\n const weights: number[] = []\n const weightedRewards: number[] = []\n let maxW = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(\n `inverseProbabilityWeighting: behaviorProb must be > 0 (runId=${t.runId})`,\n )\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n const r = clamp(t.reward, clip.low, clip.high)\n weights.push(w)\n weightedRewards.push(w * r)\n if (w > maxW) maxW = w\n }\n const n = weights.length\n const value = weightedRewards.reduce((s, x) => s + x, 0) / n\n const variance = weightedRewards.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1)\n const sumW = weights.reduce((s, w) => s + w, 0)\n const sumW2 = weights.reduce((s, w) => s + w * w, 0)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n\n return {\n value,\n standardError: Math.sqrt(variance / n),\n effectiveSampleSize: effN,\n n,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Self-Normalized Importance Sampling. Lower variance than vanilla IPS at\n * the cost of small bias (vanishing as N grows). The right default for\n * LLM-agent evaluation where overlap is often poor.\n */\nexport function selfNormalizedImportanceWeighting(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n if (trajectories.length === 0) return zeroEstimate()\n\n const weights: number[] = []\n const rewards: number[] = []\n let maxW = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(\n `selfNormalizedImportanceWeighting: behaviorProb must be > 0 (runId=${t.runId})`,\n )\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n weights.push(w)\n rewards.push(clamp(t.reward, clip.low, clip.high))\n if (w > maxW) maxW = w\n }\n const sumW = weights.reduce((s, w) => s + w, 0)\n const sumWR = weights.reduce((s, w, i) => s + w * rewards[i]!, 0)\n const value = sumW === 0 ? 0 : sumWR / sumW\n const sumW2 = weights.reduce((s, w) => s + w * w, 0)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n // Influence-function-based SE for SNIPS (Owen 2013, Ch. 9).\n const phi = weights.map((w, i) => w * (rewards[i]! - value))\n const variance = phi.reduce((s, x) => s + x * x, 0) / Math.max(1, sumW * sumW)\n return {\n value,\n standardError: Math.sqrt(variance),\n effectiveSampleSize: effN,\n n: trajectories.length,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Doubly-robust off-policy estimator (Dudík, Langford, Li 2011).\n *\n * V_DR = (1/N) * sum_i [ q_hat_i + (target_prob_i / behavior_prob_i) * (r_i - q_hat_i) ]\n *\n * Unbiased if EITHER:\n * - the importance ratios are correct (IPS-style validity), OR\n * - the Q-hat function is correct (model-based validity).\n *\n * In practice both are imperfect, but the residual bias is the *product*\n * of both errors — much smaller than either alone. This is why DR is the\n * default in production OPE pipelines.\n *\n * Requires `qHat` on every trajectory. If any are `null`, the estimator\n * falls back to SNIPS for those entries (loud-fallback behavior; the\n * report's `n` reflects the full set but `effectiveSampleSize` accounts\n * for the lost variance reduction).\n */\nexport function doublyRobust(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n if (trajectories.length === 0) return zeroEstimate()\n\n const contributions: number[] = []\n let maxW = 0\n let sumW = 0\n let sumW2 = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(`doublyRobust: behaviorProb must be > 0 (runId=${t.runId})`)\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n const r = clamp(t.reward, clip.low, clip.high)\n const q =\n typeof t.qHat === 'number' && Number.isFinite(t.qHat)\n ? clamp(t.qHat, clip.low, clip.high)\n : null\n if (q === null) {\n contributions.push(w * r) // fallback: IPS for this entry\n } else {\n contributions.push(q + w * (r - q))\n }\n if (w > maxW) maxW = w\n sumW += w\n sumW2 += w * w\n }\n const n = contributions.length\n const value = contributions.reduce((s, x) => s + x, 0) / n\n const variance = contributions.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n return {\n value,\n standardError: Math.sqrt(variance / n),\n effectiveSampleSize: effN,\n n,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Convenience: run all three estimators and return them side-by-side.\n * The recommended diagnostic — agreement across estimators is a much\n * stronger signal than any single one.\n */\nexport function offPolicyEstimateAll(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): { ips: OffPolicyEstimate; snips: OffPolicyEstimate; dr: OffPolicyEstimate } {\n return {\n ips: inverseProbabilityWeighting(trajectories, opts),\n snips: selfNormalizedImportanceWeighting(trajectories, opts),\n dr: doublyRobust(trajectories, opts),\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction zeroEstimate(): OffPolicyEstimate {\n return { value: 0, standardError: 0, effectiveSampleSize: 0, n: 0, maxImportanceWeight: 0 }\n}\n\nfunction clamp(x: number, lo: number, hi: number): number {\n if (!Number.isFinite(x)) return lo\n return Math.max(lo, Math.min(hi, x))\n}\n","/**\n * Preference dataset extraction — bridge from `RunRecord[]` to RL training.\n *\n * Production RLHF / DPO / KTO / SimPO pipelines need preference triples:\n * `(prompt, chosen, rejected)`. The campaign artifact already contains the\n * ingredients — every (variantId, scenarioId, seed) cell is a candidate\n * that ran the same prompt against the same scenario, scored by the same\n * judge — but turning that into a clean preference dataset requires\n * deciding *what counts as a preference*.\n *\n * This module ships three preference-extraction strategies with explicit\n * tradeoffs, plus a unified output type compatible with HuggingFace TRL,\n * Anthropic finetuning JSONL, and OpenAI fine-tuning APIs. The strategies\n * are deliberately not auto-magical — picking the wrong one corrupts the\n * gradient.\n *\n * Strategies:\n *\n * 1. **`paired-by-scenario-and-seed`** — exact-match comparisons. For\n * each scenario × seed pair, compare every (variantA, variantB) on\n * that exact (scenario, seed). Matches scenarios so the comparison\n * isolates variant effects. Highest signal-to-noise; smallest\n * dataset (only matched pairs count).\n *\n * 2. **`paired-by-scenario`** — looser matching. For each scenario,\n * compare every (variantA, variantB) where both have ≥ 1 run on the\n * same scenario. Aggregates across seeds to compute mean scores per\n * (variant, scenario), then forms preferences from the means. More\n * data, lower per-pair signal.\n *\n * 3. **`top-vs-bottom`** — coarsest. Within each scenario, the highest-\n * scoring run is `chosen`, the lowest is `rejected`. Smallest dataset\n * per scenario but biggest score gap per pair. Useful for early\n * bootstrapping when you have few variants.\n *\n * The output `PreferenceTriple` is *agent-eval-canonical* but trivially\n * mappable to TRL's `DPODataset` shape (`prompt`, `chosen`, `rejected`)\n * via the `toTRLFormat` helper.\n */\n\nimport type { RunRecord } from '../run-record'\n\nexport type PreferenceStrategy =\n | 'paired-by-scenario-and-seed'\n | 'paired-by-scenario'\n | 'top-vs-bottom'\n\nexport interface PreferenceTriple {\n /** The scenario (input) the variants were run against. */\n scenarioId: string\n /** RunRecord ids on each side, for traceability. */\n chosenRunId: string\n rejectedRunId: string\n /** Variant ids — load-bearing for the RL update. */\n chosenVariantId: string\n rejectedVariantId: string\n /** The score gap between chosen and rejected. Larger = stronger signal. */\n marginScore: number\n /**\n * Optional `(chosen_score, rejected_score)` pair for soft-margin DPO\n * variants. Omitted for `top-vs-bottom` runs that don't carry meaningful\n * scalar gaps.\n */\n scores?: { chosen: number; rejected: number }\n /** Tie-breaker — when multiple seeds match this scenario, the one used. */\n seed?: number\n /**\n * Free-form metadata propagated from the run records — e.g. original\n * prompt-hash, model, etc. Lets the RL trainer reconstruct the prompt.\n */\n meta: {\n chosenPromptHash: string\n rejectedPromptHash: string\n chosenConfigHash: string\n rejectedConfigHash: string\n chosenModel: string\n rejectedModel: string\n }\n}\n\nexport interface ExtractPreferencesOptions {\n strategy?: PreferenceStrategy\n /**\n * Minimum score gap required to admit a pair. Pairs below this are\n * dropped — they're noise, not signal. Default 0.05 (5% of [0,1]).\n */\n minMargin?: number\n /**\n * Optional split tag filter — restrict to runs from one split. Default\n * `'holdout'` (the canonical \"real\" signal).\n */\n splitTag?: RunRecord['splitTag']\n /**\n * Optional reward extractor that overrides `outcome.holdoutScore` /\n * `outcome.searchScore`. Use to drive preferences off a verifiable\n * reward instead of the headline score.\n */\n rewardOf?: (run: RunRecord) => number | null\n}\n\nexport interface PreferenceExtractionReport {\n pairs: PreferenceTriple[]\n /** Number of (scenario, seed) cells inspected. */\n cellsInspected: number\n /** Number of pairs filtered by `minMargin`. */\n pairsBelowMargin: number\n /** Number of cells with only one variant (no comparison possible). */\n cellsSingleton: number\n /** Strategy used. */\n strategy: PreferenceStrategy\n}\n\nconst SPLIT_TAG_DEFAULT: RunRecord['splitTag'] = 'holdout'\n\nconst DEFAULT_REWARD = (run: RunRecord): number | null => {\n const v = run.outcome.holdoutScore ?? run.outcome.searchScore\n return typeof v === 'number' && Number.isFinite(v) ? v : null\n}\n\n/**\n * Convert `RunRecord[]` to preference triples for RL training.\n *\n * Returns a structured report so callers can see how much data was\n * dropped and why (low-margin pairs, singleton cells). For production\n * pipelines, you usually want to:\n *\n * 1. Run a campaign producing 5–10 variants × 50–200 scenarios × 3 seeds\n * 2. Call this with `strategy: 'paired-by-scenario-and-seed'` and a\n * verifiable-reward extractor as `rewardOf`\n * 3. Pass `report.pairs` to `toTRLFormat` and pipe to your DPO trainer\n */\nexport function extractPreferences(\n runs: RunRecord[],\n opts: ExtractPreferencesOptions = {},\n): PreferenceExtractionReport {\n const strategy = opts.strategy ?? 'paired-by-scenario-and-seed'\n const minMargin = opts.minMargin ?? 0.05\n const splitTag = opts.splitTag ?? SPLIT_TAG_DEFAULT\n const rewardOf = opts.rewardOf ?? DEFAULT_REWARD\n\n const filtered = runs.filter((r) => r.splitTag === splitTag)\n const scoredEntries: Array<{ run: RunRecord; score: number }> = []\n for (const run of filtered) {\n const s = rewardOf(run)\n if (s === null) continue\n scoredEntries.push({ run, score: s })\n }\n\n const pairs: PreferenceTriple[] = []\n let pairsBelowMargin = 0\n let cellsSingleton = 0\n let cellsInspected = 0\n\n if (strategy === 'paired-by-scenario-and-seed') {\n // Group by (scenarioId, seed). Canonical key is `run.scenarioId`,\n // populated by `runEvalCampaign` and the adapters; falls back to\n // `outcome.raw.scenario_id` then `experimentId` when absent.\n const groups = new Map<string, Array<{ run: RunRecord; score: number }>>()\n for (const e of scoredEntries) {\n const sid = scenarioOf(e.run)\n const key = `${sid}::${e.run.seed}`\n const arr = groups.get(key) ?? []\n arr.push(e)\n groups.set(key, arr)\n }\n\n for (const [key, members] of groups.entries()) {\n cellsInspected++\n if (members.length < 2) {\n cellsSingleton++\n continue\n }\n for (let i = 0; i < members.length; i++) {\n for (let j = i + 1; j < members.length; j++) {\n const a = members[i]!\n const b = members[j]!\n if (a.run.candidateId === b.run.candidateId) continue\n const result = makePair(a, b, key.split('::')[0]!, minMargin)\n if (result.kind === 'admit') pairs.push(result.pair)\n else pairsBelowMargin++\n }\n }\n }\n } else if (strategy === 'paired-by-scenario') {\n // Group by scenarioId → average per (variantId, scenarioId) across seeds.\n const byScenarioVariant = new Map<\n string,\n Map<string, { run: RunRecord; sum: number; n: number }>\n >()\n for (const e of scoredEntries) {\n const sid = scenarioOf(e.run)\n let perScenario = byScenarioVariant.get(sid)\n if (!perScenario) {\n perScenario = new Map()\n byScenarioVariant.set(sid, perScenario)\n }\n const cur = perScenario.get(e.run.candidateId)\n if (cur) {\n cur.sum += e.score\n cur.n++\n } else perScenario.set(e.run.candidateId, { run: e.run, sum: e.score, n: 1 })\n }\n for (const [sid, perVariant] of byScenarioVariant.entries()) {\n cellsInspected++\n const arr = [...perVariant.entries()].map(([vid, agg]) => ({\n run: agg.run,\n score: agg.sum / agg.n,\n variantId: vid,\n }))\n if (arr.length < 2) {\n cellsSingleton++\n continue\n }\n for (let i = 0; i < arr.length; i++) {\n for (let j = i + 1; j < arr.length; j++) {\n const result = makePair(arr[i]!, arr[j]!, sid, minMargin)\n if (result.kind === 'admit') pairs.push(result.pair)\n else pairsBelowMargin++\n }\n }\n }\n } else {\n // top-vs-bottom: per scenario, top vs bottom only.\n const byScenario = new Map<string, Array<{ run: RunRecord; score: number }>>()\n for (const e of scoredEntries) {\n const sid = scenarioOf(e.run)\n const arr = byScenario.get(sid) ?? []\n arr.push(e)\n byScenario.set(sid, arr)\n }\n for (const [sid, arr] of byScenario.entries()) {\n cellsInspected++\n if (arr.length < 2) {\n cellsSingleton++\n continue\n }\n const sorted = [...arr].sort((a, b) => a.score - b.score)\n const top = sorted[sorted.length - 1]!\n const bot = sorted[0]!\n if (top.run.candidateId === bot.run.candidateId) {\n cellsSingleton++\n continue\n }\n const result = makePair(bot, top, sid, minMargin)\n if (result.kind === 'admit') pairs.push(result.pair)\n else pairsBelowMargin++\n }\n }\n\n return { pairs, cellsInspected, pairsBelowMargin, cellsSingleton, strategy }\n}\n\n/**\n * TRL-compatible export. TRL's `DPODataset` is `{ prompt, chosen, rejected }`\n * but the prompt isn't stored on the RunRecord — only its hash. The caller\n * passes a `promptOf(promptHash)` lookup that the TRL trainer can use.\n */\nexport function toTRLFormat(\n triples: PreferenceTriple[],\n promptOf: (hash: string) => string,\n): Array<{ prompt: string; chosen: string; rejected: string }> {\n return triples.map((t) => ({\n prompt: promptOf(t.meta.chosenPromptHash),\n chosen: t.meta.chosenPromptHash, // caller substitutes the model output via the runId map\n rejected: t.meta.rejectedPromptHash,\n }))\n}\n\n/**\n * Anthropic finetuning JSONL export — `{ system, user, assistant_chosen, assistant_rejected }`\n * shape. Same caveat as TRL: prompt + outputs are content the caller has\n * to map back from the run record / raw event log.\n */\nexport function toAnthropicFormat(\n triples: PreferenceTriple[],\n): Array<{ scenarioId: string; chosenRunId: string; rejectedRunId: string; margin: number }> {\n return triples.map((t) => ({\n scenarioId: t.scenarioId,\n chosenRunId: t.chosenRunId,\n rejectedRunId: t.rejectedRunId,\n margin: t.marginScore,\n }))\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction makePair(\n a: { run: RunRecord; score: number },\n b: { run: RunRecord; score: number },\n scenarioId: string,\n minMargin: number,\n): { kind: 'admit'; pair: PreferenceTriple } | { kind: 'reject' } {\n const margin = Math.abs(a.score - b.score)\n if (margin < minMargin) return { kind: 'reject' }\n const [chosen, rejected] = a.score > b.score ? [a, b] : [b, a]\n return {\n kind: 'admit',\n pair: {\n scenarioId,\n chosenRunId: chosen.run.runId,\n rejectedRunId: rejected.run.runId,\n chosenVariantId: chosen.run.candidateId,\n rejectedVariantId: rejected.run.candidateId,\n marginScore: chosen.score - rejected.score,\n scores: { chosen: chosen.score, rejected: rejected.score },\n seed: chosen.run.seed === rejected.run.seed ? chosen.run.seed : undefined,\n meta: {\n chosenPromptHash: chosen.run.promptHash,\n rejectedPromptHash: rejected.run.promptHash,\n chosenConfigHash: chosen.run.configHash,\n rejectedConfigHash: rejected.run.configHash,\n chosenModel: chosen.run.model,\n rejectedModel: rejected.run.model,\n },\n },\n }\n}\n\n/**\n * Canonical scenario key for a RunRecord. Three-tier fallback:\n * 1. `run.scenarioId` — populated by `runEvalCampaign` and every adapter\n * 2. `run.outcome.raw.scenario_id` — string or numeric, when present\n * 3. `run.experimentId` — worst-case bucket\n */\nfunction scenarioOf(run: RunRecord): string {\n if (typeof run.scenarioId === 'string' && run.scenarioId.length > 0) return run.scenarioId\n const fromRaw = run.outcome.raw.scenario_id\n if (typeof fromRaw === 'number' && Number.isFinite(fromRaw)) return String(fromRaw)\n if (typeof fromRaw === 'string') return fromRaw\n return run.experimentId\n}\n","/**\n * Adapters: convert measurement outputs into the canonical `RunRecord[]`\n * artifact that `replayCache`, `pairedEvalueSequence`, and\n * `rubricPredictiveValidity` consume. Two sources:\n * - `campaignToRunRecords` — the campaign substrate's per-cell results\n * (the modern path: `runCampaign` / `runImprovementLoop` → records).\n * - `verificationReportToRunRecord` — a `MultiLayerVerifier` report.\n *\n * Adapters are thin and explicit — every mandatory `RunRecord` field comes\n * from a caller-supplied context (`commitSha`, `model`, `promptHash`,\n * `configHash`) plus the cell's runtime data. The validator still rejects\n * bare-alias model strings — the caller snapshot-pins.\n */\n\nimport type { CampaignResult } from '../campaign'\nimport type { LayerResult, VerificationReport } from '../multi-layer-verifier'\nimport type { RunRecord, RunSplitTag } from '../run-record'\n\nexport interface AdapterContext {\n /** Logical experiment id — typically the campaign or sweep identifier. */\n experimentId: string\n /** Snapshot model id (e.g. `claude-sonnet-4-6@2025-04-15`). */\n model: string\n /** Git SHA the harness was run from. */\n commitSha: string\n /** Hash of the effective prompt sent to the model. */\n promptHash: string\n /** Hash of the effective config (model, temperature, tools, judges, splits). */\n configHash: string\n /** Default split tag. Default `'search'`. */\n splitTag?: RunSplitTag\n /** Default cost in USD when the source doesn't record one. Default `0`. */\n defaultCostUsd?: number\n}\n\n/**\n * Convert a `CampaignResult` into canonical `RunRecord[]` — one record per\n * scored cell. The cell's mean judge composite becomes the split score; every\n * judge dimension is carried through to `outcome.raw`. A cell that errored\n * becomes a record with `failureMode: 'cell_error'` (kept, not dropped — an\n * unscored cell is signal). `candidateId` identifies the measured surface\n * (defaults to the campaign manifest hash).\n */\nexport function campaignToRunRecords(\n campaign: CampaignResult,\n ctx: AdapterContext & { candidateId?: string },\n): RunRecord[] {\n const splitTag = ctx.splitTag ?? 'search'\n const candidateId = ctx.candidateId ?? campaign.manifestHash\n return campaign.cells.map((cell) => {\n const composites = Object.values(cell.judgeScores).map((s) => s.composite)\n const score =\n composites.length > 0 ? composites.reduce((a, b) => a + b, 0) / composites.length : 0\n const raw: Record<string, number> = { rep: cell.rep, duration_ms: cell.durationMs }\n for (const judge of Object.values(cell.judgeScores)) {\n for (const [dim, value] of Object.entries(judge.dimensions)) {\n if (Number.isFinite(value)) raw[`dim.${dim}`] = value\n }\n }\n if (typeof cell.generation === 'number') raw.generation = cell.generation\n const outcome: RunRecord['outcome'] = { raw }\n if (splitTag === 'holdout') outcome.holdoutScore = score\n else outcome.searchScore = score\n return {\n runId: cell.cellId,\n experimentId: ctx.experimentId,\n candidateId,\n seed: cell.seed,\n model: ctx.model,\n promptHash: ctx.promptHash,\n configHash: ctx.configHash,\n commitSha: ctx.commitSha,\n wallMs: cell.durationMs,\n costUsd: Number.isFinite(cell.costUsd) ? cell.costUsd : (ctx.defaultCostUsd ?? 0),\n tokenUsage: { input: 0, output: 0 },\n outcome,\n failureMode: cell.error ? 'cell_error' : undefined,\n splitTag,\n scenarioId: cell.scenarioId,\n }\n })\n}\n\n/**\n * Convert a `MultiLayerVerifier` `VerificationReport` into a `RunRecord`.\n * `outcome.searchScore` (or `holdoutScore`) is `report.blendedScore`;\n * `outcome.raw` carries every layer's score + a pass indicator; `failureMode`\n * is the first failing layer's reason.\n */\nexport function verificationReportToRunRecord(\n report: VerificationReport,\n ctx: AdapterContext & { candidateId: string; scenarioId?: string },\n opts: { runId?: string } = {},\n): RunRecord {\n const splitTag = ctx.splitTag ?? 'search'\n const runId = opts.runId ?? `run-${ctx.candidateId}-${ctx.experimentId}-${report.startedAt}`\n\n const raw: Record<string, number> = {\n pass_count: report.passCount,\n fail_count: report.failCount,\n error_count: report.errorCount,\n skipped_count: report.skippedCount,\n duration_ms: report.durationMs,\n blended_score: report.blendedScore,\n }\n for (const layer of report.layers) {\n if (typeof layer.score === 'number') raw[`layer.${layer.layer}`] = layer.score\n raw[`layer_${layer.layer}_pass`] = layer.status === 'pass' ? 1 : 0\n if (layer.diagnostics) {\n for (const [k, v] of Object.entries(layer.diagnostics)) {\n if (typeof v === 'number' && Number.isFinite(v)) raw[`layer.${layer.layer}.${k}`] = v\n }\n }\n }\n\n const firstFail = report.layers.find((l) => l.status === 'fail' || l.status === 'error')\n const outcome: RunRecord['outcome'] = { raw }\n if (splitTag === 'holdout') outcome.holdoutScore = report.blendedScore\n else outcome.searchScore = report.blendedScore\n\n return {\n runId,\n experimentId: ctx.experimentId,\n candidateId: ctx.candidateId,\n seed: 0,\n model: ctx.model,\n promptHash: ctx.promptHash,\n configHash: ctx.configHash,\n commitSha: ctx.commitSha,\n wallMs: report.durationMs,\n costUsd: ctx.defaultCostUsd ?? 0,\n tokenUsage: { input: 0, output: 0 },\n outcome,\n failureMode: firstFail ? failureModeFromLayer(firstFail) : undefined,\n splitTag,\n scenarioId: ctx.scenarioId,\n }\n}\n\nfunction failureModeFromLayer(layer: LayerResult): string {\n if (layer.status === 'error') return `layer_${layer.layer}_error`\n if (layer.status === 'fail') return `layer_${layer.layer}_fail`\n if (layer.status === 'timeout') return `layer_${layer.layer}_timeout`\n return `layer_${layer.layer}_${layer.status}`\n}\n","/**\n * Bradley-Terry / Elo tournament evaluation.\n *\n * For multi-candidate sweeps, comparing every candidate's score against\n * a fixed comparator wastes information — the comparator becomes a high-\n * variance reference and rank flips between near-tied middle-rank\n * candidates are dominated by noise. Pairwise tournaments fix this:\n * every (i, j) pair contributes a comparison to a Bradley-Terry MLE that\n * estimates each candidate's strength on a unified scale.\n *\n * For online updating (rolling campaigns where new candidates arrive\n * over time), we also ship classical Elo with configurable K-factor.\n *\n * References:\n * - Bradley, R. A., Terry, M. E. (1952). Rank analysis of incomplete\n * block designs. Biometrika, 39(3/4), 324–345.\n * - Hunter, D. R. (2004). MM algorithms for generalized Bradley-Terry\n * models. Annals of Statistics, 32(1), 384–406. (The MLE algorithm\n * used here.)\n * - Elo, A. E. (1978). The Rating of Chess Players, Past and Present.\n *\n * This is a useful primitive because most LLM-eval communities (Chatbot\n * Arena, AlpacaEval, ELO-style ablation) have converged on pairwise\n * tournament eval as the most sample-efficient and most rank-stable\n * method when you have many candidates.\n */\n\nexport interface PairwiseOutcome {\n /** Winner candidate id. */\n winner: string\n /** Loser candidate id. */\n loser: string\n /**\n * Optional draw flag. When true, both candidates get half-credit\n * (Bradley-Terry handles draws as half-wins for each side).\n */\n draw?: boolean\n /**\n * Optional weight — useful if some pairwise comparisons are stronger\n * signals than others (e.g. a paired test with a wider score gap is\n * a more confident comparison). Default 1.\n */\n weight?: number\n}\n\nexport interface BradleyTerryRating {\n candidateId: string\n /** Latent strength θ ≥ 0 from the BT MLE. */\n strength: number\n /** Log-strength = log(θ) — interpretable on a linear scale. */\n logStrength: number\n /** Number of pairwise comparisons this candidate appears in. */\n n: number\n /** Win count (+ 0.5 per draw). */\n wins: number\n}\n\nexport interface BradleyTerryFit {\n ratings: BradleyTerryRating[]\n /** Iterations of the MM algorithm before convergence. */\n iterations: number\n /** Final maximum |θ_new - θ_old| / θ_old. */\n finalDelta: number\n converged: boolean\n}\n\n/**\n * Bradley-Terry MLE via Hunter's MM algorithm.\n *\n * Iteration: θ_i^new = W_i / Σ_{j ≠ i} N_ij / (θ_i + θ_j)\n * where W_i = wins by i (+ 0.5 per draw), N_ij = total comparisons.\n *\n * Returns log-strengths normalized so the smallest is 0 (any constant\n * offset is unobservable in BT — only differences are identified).\n */\nexport function fitBradleyTerry(\n outcomes: PairwiseOutcome[],\n opts: { tolerance?: number; maxIterations?: number; smoothing?: number } = {},\n): BradleyTerryFit {\n const tol = opts.tolerance ?? 1e-6\n const maxIter = opts.maxIterations ?? 256\n // Small positive default — Hunter's MM degenerates when a candidate has\n // zero wins (θ → 0 → log → -∞). 0.1 is negligible against real win counts\n // (~1 win / 10 comparisons) and keeps the iteration well-conditioned.\n // Override to 0 if the comparison set is guaranteed strongly connected.\n const smoothing = opts.smoothing ?? 0.1\n\n const candidates = new Set<string>()\n for (const o of outcomes) {\n candidates.add(o.winner)\n candidates.add(o.loser)\n }\n const ids = [...candidates].sort()\n const idx = new Map(ids.map((id, i) => [id, i]))\n const n = ids.length\n if (n === 0) return { ratings: [], iterations: 0, finalDelta: 0, converged: true }\n if (n === 1) {\n return {\n ratings: [{ candidateId: ids[0]!, strength: 1, logStrength: 0, n: 0, wins: 0 }],\n iterations: 0,\n finalDelta: 0,\n converged: true,\n }\n }\n\n // Build win matrix W[i][j] = (weighted) wins of i over j, plus half for draws.\n // Build comparison matrix N[i][j] = total weighted comparisons between i and j.\n const W: number[][] = Array.from({ length: n }, () => new Array<number>(n).fill(0))\n const N: number[][] = Array.from({ length: n }, () => new Array<number>(n).fill(0))\n for (const o of outcomes) {\n const i = idx.get(o.winner)!\n const j = idx.get(o.loser)!\n const w = o.weight ?? 1\n if (o.draw) {\n W[i]![j]! += 0.5 * w\n W[j]![i]! += 0.5 * w\n } else {\n W[i]![j]! += w\n }\n N[i]![j]! += w\n N[j]![i]! += w\n }\n\n // Per-candidate total wins.\n const winsTotal = new Array<number>(n).fill(0)\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) winsTotal[i]! += W[i]![j]!\n winsTotal[i]! += smoothing // tiny smoothing to keep θ positive\n }\n const compsTotal = new Array<number>(n).fill(0)\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) compsTotal[i]! += N[i]![j]!\n }\n\n // MM iterations.\n let theta = new Array<number>(n).fill(1)\n let iter = 0\n let delta = Infinity\n for (; iter < maxIter; iter++) {\n const newTheta = new Array<number>(n)\n for (let i = 0; i < n; i++) {\n let denom = 0\n for (let j = 0; j < n; j++) {\n if (j === i) continue\n if (N[i]![j]! === 0) continue\n denom += N[i]![j]! / (theta[i]! + theta[j]!)\n }\n newTheta[i] = denom === 0 ? theta[i]! : winsTotal[i]! / denom\n }\n // Normalize so geometric mean = 1 (numerical stability).\n let logSum = 0\n for (let i = 0; i < n; i++) logSum += Math.log(Math.max(1e-300, newTheta[i]!))\n const norm = Math.exp(logSum / n)\n for (let i = 0; i < n; i++) newTheta[i] = newTheta[i]! / norm\n\n delta = 0\n for (let i = 0; i < n; i++) {\n const d = Math.abs(newTheta[i]! - theta[i]!) / Math.max(1e-12, theta[i]!)\n if (d > delta) delta = d\n }\n theta = newTheta\n if (delta < tol) break\n }\n\n const minLog = Math.min(...theta.map((t) => Math.log(Math.max(1e-300, t))))\n const ratings: BradleyTerryRating[] = ids.map((id, i) => ({\n candidateId: id,\n strength: theta[i]!,\n logStrength: Math.log(Math.max(1e-300, theta[i]!)) - minLog,\n n: compsTotal[i]!,\n wins: winsTotal[i]! - smoothing,\n }))\n\n return {\n ratings: ratings.sort((a, b) => b.strength - a.strength),\n iterations: iter,\n finalDelta: delta,\n converged: delta < tol,\n }\n}\n\n/**\n * Online Elo updates. Use when comparisons arrive over time and you want\n * a running rating without re-fitting the full BT MLE on every update.\n *\n * Initialize ratings to `defaultRating` (1500 by default). Each call to\n * `applyEloUpdate` mutates the map in place and returns the deltas so\n * the caller can log per-comparison rating changes.\n */\nexport interface EloOptions {\n /** Default rating for unseen candidates. Default 1500. */\n defaultRating?: number\n /** K-factor controls the step size. Default 32 (FIDE-ish). */\n kFactor?: number\n}\n\nexport function applyEloUpdate(\n ratings: Map<string, number>,\n outcome: PairwiseOutcome,\n opts: EloOptions = {},\n): { winnerDelta: number; loserDelta: number } {\n const defaultRating = opts.defaultRating ?? 1500\n const k = opts.kFactor ?? 32\n\n const rW = ratings.get(outcome.winner) ?? defaultRating\n const rL = ratings.get(outcome.loser) ?? defaultRating\n\n const expectedW = 1 / (1 + 10 ** ((rL - rW) / 400))\n const scoreW = outcome.draw ? 0.5 : 1\n const scoreL = outcome.draw ? 0.5 : 0\n const w = outcome.weight ?? 1\n\n const winnerDelta = k * w * (scoreW - expectedW)\n const loserDelta = k * w * (scoreL - (1 - expectedW))\n\n ratings.set(outcome.winner, rW + winnerDelta)\n ratings.set(outcome.loser, rL + loserDelta)\n\n return { winnerDelta, loserDelta }\n}\n\n/**\n * Build pairwise outcomes from the campaign artifact: for every scenario\n * shared by two candidates, the higher-scoring run wins. Useful when you\n * want a tournament view of an existing campaign without an additional\n * pairwise judge call.\n */\nexport interface BuildPairwiseFromCampaignInput {\n runs: Array<{\n candidateId: string\n /** Stable identifier for the matching unit (typically scenarioId). */\n matchKey: string\n score: number\n }>\n /**\n * Tied-score margin. Below this, the comparison is a draw. Default 0\n * (no ties).\n */\n drawMargin?: number\n}\n\nexport function buildPairwiseFromCampaign(\n input: BuildPairwiseFromCampaignInput,\n): PairwiseOutcome[] {\n const drawMargin = input.drawMargin ?? 0\n const byKey = new Map<string, Array<{ candidateId: string; score: number }>>()\n for (const r of input.runs) {\n const arr = byKey.get(r.matchKey) ?? []\n arr.push({ candidateId: r.candidateId, score: r.score })\n byKey.set(r.matchKey, arr)\n }\n const outcomes: PairwiseOutcome[] = []\n for (const arr of byKey.values()) {\n for (let i = 0; i < arr.length; i++) {\n for (let j = i + 1; j < arr.length; j++) {\n const a = arr[i]!\n const b = arr[j]!\n if (a.candidateId === b.candidateId) continue\n const margin = Math.abs(a.score - b.score)\n if (margin <= drawMargin) {\n outcomes.push({ winner: a.candidateId, loser: b.candidateId, draw: true, weight: 1 })\n } else {\n const [winner, loser] = a.score > b.score ? [a, b] : [b, a]\n outcomes.push({ winner: winner.candidateId, loser: loser.candidateId, weight: margin })\n }\n }\n }\n }\n return outcomes\n}\n","/**\n * Adaptive curriculum / active scenario selection.\n *\n * Fixed scenario sets waste sample budget on cells the policy already\n * passes (no information left) and cells the policy never passes (no\n * gradient available either). Active learning over scenarios fixes this\n * by allocating the next sample budget to cells where the policy's\n * outcome is *uncertain* — those carry the most decision-relevant signal.\n *\n * This module ships two complementary strategies:\n *\n * 1. **Variance-based** — score each (variant, scenario) cell by the\n * empirical variance of past observations. Allocate next-round budget\n * proportional to variance. Standard active-learning-by-uncertainty\n * heuristic; works well when the policy is non-deterministic and\n * cells differ in observation noise.\n *\n * 2. **Bandit-based (Thompson sampling)** — model each (variant,\n * scenario) cell as a Beta-Bernoulli arm; sample a posterior; pick\n * cells whose posterior mean is closest to the per-scenario decision\n * threshold. The right primitive when scenarios are\n * \"pass/fail\" rather than continuous, and when promotion gates fire\n * at a known threshold (e.g., 0.5).\n *\n * The output is a *next-round budget allocation* — a list of (variant,\n * scenario, count) triples. The consumer's matrix runner consumes the\n * allocation, runs those cells, feeds the new observations back. Loop.\n *\n * Out of scope (deliberate): scenario *generation* — that's the\n * adversarial primitive's job. This module allocates over an existing\n * scenario pool.\n */\n\nimport type { RunRecord } from '../run-record'\n\nexport interface CellObservation {\n variantId: string\n scenarioId: string\n /** Observed score in [0, 1]. */\n score: number\n /** For Bernoulli arms — derive from the score with a threshold if needed. */\n pass?: boolean\n}\n\nexport interface CurriculumAllocation {\n variantId: string\n scenarioId: string\n /** How many additional reps to run on this cell. */\n count: number\n /** Strategy-specific reason for the allocation. */\n reason: string\n}\n\nexport interface VarianceCurriculumOptions {\n /** Total reps to allocate across all cells. */\n budget: number\n /**\n * Smoothing prior on variance — keeps the allocator from concentrating\n * on a cell with one observation just because its 1-sample variance is\n * 0. Default 0.05.\n */\n variancePrior?: number\n /**\n * Minimum reps per cell — even when the variance estimate is low, give\n * every cell at least this many. Default 1.\n */\n floorPerCell?: number\n}\n\n/**\n * Variance-proportional allocation. For each cell, estimate variance from\n * past observations + a prior, then allocate the budget proportional to\n * (sqrt(variance) + 1/sqrt(n)) — a classical optimal-allocation rule\n * (Neyman 1934) that balances \"explore noisy cells\" with \"explore\n * under-sampled cells.\"\n */\nexport function varianceBasedCurriculum(\n observations: CellObservation[],\n candidateCells: Array<{ variantId: string; scenarioId: string }>,\n opts: VarianceCurriculumOptions,\n): CurriculumAllocation[] {\n const variancePrior = opts.variancePrior ?? 0.05\n const floor = opts.floorPerCell ?? 1\n const budget = opts.budget\n\n const grouped = new Map<string, number[]>()\n for (const o of observations) {\n const k = `${o.variantId}::${o.scenarioId}`\n const arr = grouped.get(k) ?? []\n arr.push(o.score)\n grouped.set(k, arr)\n }\n\n const cellStats = candidateCells.map((c) => {\n const k = `${c.variantId}::${c.scenarioId}`\n const samples = grouped.get(k) ?? []\n const n = samples.length\n const mean = n === 0 ? 0.5 : samples.reduce((s, v) => s + v, 0) / n\n const variance =\n n < 2\n ? variancePrior\n : samples.reduce((s, v) => s + (v - mean) ** 2, 0) / (n - 1) + variancePrior\n // Neyman optimal allocation: weight ∝ √variance; add √(1/n) to break\n // ties toward under-sampled cells.\n const weight = Math.sqrt(variance) + 1 / Math.sqrt(Math.max(1, n))\n return { variantId: c.variantId, scenarioId: c.scenarioId, n, mean, variance, weight }\n })\n\n // Reserve floor*N for the floor; allocate the rest proportional to weight.\n const floorTotal = floor * cellStats.length\n if (floorTotal >= budget) {\n const each = Math.max(1, Math.floor(budget / Math.max(1, cellStats.length)))\n return cellStats.map((c) => ({\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n count: each,\n reason: `floor allocation (budget tight; n=${c.n})`,\n }))\n }\n const remaining = budget - floorTotal\n const totalWeight = cellStats.reduce((s, c) => s + c.weight, 0)\n return cellStats.map((c) => {\n const proportional = totalWeight === 0 ? 0 : Math.round((c.weight / totalWeight) * remaining)\n return {\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n count: floor + proportional,\n reason: `variance ${c.variance.toFixed(3)} (n=${c.n}, mean=${c.mean.toFixed(3)})`,\n }\n })\n}\n\nexport interface ThompsonCurriculumOptions {\n budget: number\n /**\n * The per-scenario decision threshold. Cells whose posterior mean is\n * closest to this get the most budget — that's where the next observation\n * has the highest information value for the gate decision. Default 0.5.\n */\n decisionThreshold?: number\n /** Beta prior parameters. Default α=β=1 (uniform). */\n priorAlpha?: number\n priorBeta?: number\n /** Seed the Thompson sampler. Default unset (Math.random). */\n seed?: number\n}\n\n/**\n * Thompson-sampling-style allocation for pass/fail cells. For each cell:\n *\n * - Maintain Beta(α + passes, β + failures) posterior on pass-rate\n * - Allocation weight ∝ exp(-((sampledMean - threshold) / σ)^2):\n * cells whose sampled posterior straddles the decision boundary get\n * the most weight; cells already clearly above or below get less.\n *\n * This is the right primitive when promotion gates fire at a known\n * threshold and you want to sharpen the posterior near the boundary.\n */\nexport function thompsonCurriculum(\n observations: CellObservation[],\n candidateCells: Array<{ variantId: string; scenarioId: string }>,\n opts: ThompsonCurriculumOptions,\n): CurriculumAllocation[] {\n const threshold = opts.decisionThreshold ?? 0.5\n const alpha0 = opts.priorAlpha ?? 1\n const beta0 = opts.priorBeta ?? 1\n const rng = makeRng(opts.seed)\n\n const grouped = new Map<string, { passes: number; failures: number }>()\n for (const o of observations) {\n const k = `${o.variantId}::${o.scenarioId}`\n const cur = grouped.get(k) ?? { passes: 0, failures: 0 }\n const pass = o.pass ?? o.score >= threshold\n if (pass) cur.passes += 1\n else cur.failures += 1\n grouped.set(k, cur)\n }\n\n const stats = candidateCells.map((c) => {\n const k = `${c.variantId}::${c.scenarioId}`\n const cur = grouped.get(k) ?? { passes: 0, failures: 0 }\n const a = alpha0 + cur.passes\n const b = beta0 + cur.failures\n // Sample a single Beta draw — the Thompson signal.\n const sampled = sampleBeta(a, b, rng)\n const distance = Math.abs(sampled - threshold)\n // Information-near-threshold weight: closer = higher.\n // Use Gaussian-shaped kernel with σ tuned to posterior std.\n const variance = (a * b) / ((a + b) ** 2 * (a + b + 1))\n const sigma = Math.max(0.05, Math.sqrt(variance))\n const weight = Math.exp(-((distance / sigma) ** 2))\n return {\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n n: cur.passes + cur.failures,\n sampled,\n sigma,\n weight,\n a,\n b,\n }\n })\n\n const totalWeight = stats.reduce((s, c) => s + c.weight, 0)\n return stats.map((c) => {\n const proportional = totalWeight === 0 ? 0 : Math.round((c.weight / totalWeight) * opts.budget)\n return {\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n count: Math.max(0, proportional),\n reason: `Beta(${c.a.toFixed(1)},${c.b.toFixed(1)}) sample=${c.sampled.toFixed(3)} (target ${threshold})`,\n }\n })\n}\n\n/** Convenience: extract `CellObservation[]` directly from `RunRecord[]`. */\nexport function observationsFromRunRecords(\n runs: RunRecord[],\n opts: { passThreshold?: number; useHoldout?: boolean } = {},\n): CellObservation[] {\n const threshold = opts.passThreshold ?? 0.5\n const useHoldout = opts.useHoldout ?? true\n const out: CellObservation[] = []\n for (const r of runs) {\n if (!r.scenarioId) continue\n const score = useHoldout\n ? (r.outcome.holdoutScore ?? r.outcome.searchScore)\n : (r.outcome.searchScore ?? r.outcome.holdoutScore)\n if (typeof score !== 'number' || !Number.isFinite(score)) continue\n out.push({\n variantId: r.candidateId,\n scenarioId: r.scenarioId,\n score,\n pass: score >= threshold,\n })\n }\n return out\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction makeRng(seed?: number): () => number {\n if (seed === undefined) return Math.random\n let s = seed >>> 0\n return () => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/**\n * Sample from Beta(α, β) via the Marsaglia–Tsang method using two Gamma\n * variates. Accuracy is good for α, β > 1; we floor the parameters at 1\n * to avoid degenerate cases.\n */\nfunction sampleBeta(alpha: number, beta: number, rng: () => number): number {\n const a = Math.max(1, alpha)\n const b = Math.max(1, beta)\n const x = sampleGamma(a, rng)\n const y = sampleGamma(b, rng)\n return x / (x + y)\n}\n\nfunction sampleGamma(shape: number, rng: () => number): number {\n // Marsaglia–Tsang for shape ≥ 1.\n const d = shape - 1 / 3\n const c = 1 / Math.sqrt(9 * d)\n while (true) {\n let x: number\n let v: number\n do {\n const u1 = rng() || 1e-12\n const u2 = rng() || 1e-12\n // Box-Muller for a normal sample.\n x = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)\n v = 1 + c * x\n } while (v <= 0)\n v = v * v * v\n const u = rng()\n if (u < 1 - 0.0331 * x ** 4) return d * v\n if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) return d * v\n }\n}\n","/**\n * Sample-efficient adaptation evaluation.\n *\n * For foundation-model-based agents, the load-bearing capability isn't\n * raw end-state performance — it's *how fast the agent reaches that\n * performance from cold start*. The same model with a worse prompt that\n * adapts in 5 demonstrations beats the same model with a better prompt\n * that needs 50. Standard meta-learning eval (Finn et al., MAML, RL² lit)\n * reports an *adaptation curve*: score after k=0, 1, 2, 4, 8, 16, …\n * in-context examples or fine-tune steps.\n *\n * This module ships:\n *\n * 1. `runAdaptationCurve` — given a runner that takes k demonstrations\n * and returns a score, produce the (k, score) curve.\n * 2. `compareAdaptationCurves` — paired comparison across two policies.\n * Returns per-k delta with bootstrap CIs and an \"area-under-curve\"\n * summary statistic.\n * 3. `firstPassK` — for pass/fail evaluation, the minimum k at which\n * the policy reliably passes (≥ pass-rate threshold over reps).\n *\n * Use cases:\n * - Compare two prompt designs that have similar end-state performance\n * but different in-context efficiency.\n * - Decide between fine-tuning and prompting based on adaptation cost.\n * - Detect when a policy \"memorizes\" k=0 inputs vs. genuinely adapts.\n */\n\nexport interface AdaptationRunner<S> {\n /**\n * Runs the policy on `scenario` with `k` demonstrations. Returns a\n * scalar score in [0, 1]. The runner is responsible for any caching;\n * the harness calls it once per (scenario, k, rep) cell.\n */\n run(args: { scenario: S; k: number; rep: number }): Promise<number>\n}\n\nexport interface RunAdaptationCurveOptions<S> {\n scenarios: S[]\n /** Number-of-shots to evaluate at. Default `[0, 1, 2, 4, 8, 16]`. */\n ks?: number[]\n /** Reps per (scenario, k) cell. Default 3. */\n reps?: number\n runner: AdaptationRunner<S>\n /** Pass-rate threshold for `firstPassK` reporting. Default 0.5. */\n passThreshold?: number\n}\n\nexport interface AdaptationPoint {\n k: number\n meanScore: number\n passRate: number\n std: number\n n: number\n /** Per-scenario means at this k. */\n perScenario: Array<{ scenarioId: string; meanScore: number; passes: number; total: number }>\n}\n\nexport interface AdaptationCurve {\n points: AdaptationPoint[]\n /**\n * Smallest `k` at which `passRate ≥ passThreshold`. `null` if no `k`\n * tested reaches it.\n */\n firstPassK: number | null\n /**\n * Area under the (k, meanScore) curve, normalized by max-k. A\n * single-number summary of \"how well does this policy adapt from\n * cold-start to fully-conditioned.\" Higher = better adapter.\n */\n adaptationArea: number\n}\n\nexport async function runAdaptationCurve<S extends { scenarioId?: string }>(\n opts: RunAdaptationCurveOptions<S>,\n): Promise<AdaptationCurve> {\n const ks = opts.ks ?? [0, 1, 2, 4, 8, 16]\n const reps = opts.reps ?? 3\n const passThreshold = opts.passThreshold ?? 0.5\n const sortedKs = [...ks].sort((a, b) => a - b)\n\n const points: AdaptationPoint[] = []\n for (const k of sortedKs) {\n const perScenario: AdaptationPoint['perScenario'] = []\n const allScores: number[] = []\n let totalPasses = 0\n let totalAttempts = 0\n for (const scenario of opts.scenarios) {\n const sid = scenario.scenarioId ?? `scenario-${opts.scenarios.indexOf(scenario)}`\n const scores: number[] = []\n let passes = 0\n for (let r = 0; r < reps; r++) {\n const score = await opts.runner.run({ scenario, k, rep: r })\n scores.push(score)\n if (score >= passThreshold) passes++\n allScores.push(score)\n if (score >= passThreshold) totalPasses++\n totalAttempts++\n }\n const meanS = scores.reduce((s, v) => s + v, 0) / scores.length\n perScenario.push({ scenarioId: sid, meanScore: meanS, passes, total: scores.length })\n }\n const meanScore = allScores.reduce((s, v) => s + v, 0) / Math.max(1, allScores.length)\n const variance =\n allScores.length < 2\n ? 0\n : allScores.reduce((s, v) => s + (v - meanScore) ** 2, 0) / (allScores.length - 1)\n points.push({\n k,\n meanScore,\n passRate: totalPasses / Math.max(1, totalAttempts),\n std: Math.sqrt(variance),\n n: allScores.length,\n perScenario,\n })\n }\n\n const firstPassK = points.find((p) => p.passRate >= passThreshold)?.k ?? null\n const maxK = sortedKs[sortedKs.length - 1] ?? 1\n // Trapezoidal area under the (k, meanScore) curve, normalized by k-range.\n let area = 0\n for (let i = 1; i < points.length; i++) {\n const x1 = points[i - 1]!.k\n const x2 = points[i]!.k\n const y1 = points[i - 1]!.meanScore\n const y2 = points[i]!.meanScore\n area += ((y1 + y2) / 2) * (x2 - x1)\n }\n const adaptationArea = maxK === 0 ? 0 : area / maxK\n\n return { points, firstPassK, adaptationArea }\n}\n\nexport interface CompareCurvesResult {\n perK: Array<{\n k: number\n deltaMean: number\n aLow: number\n aHigh: number\n bLow: number\n bHigh: number\n }>\n areaDelta: number\n firstPassKDelta: number | null\n /** Verdict: 'a_better' | 'b_better' | 'similar'. */\n verdict: 'a_better' | 'b_better' | 'similar'\n /** Rationale, ready to render. */\n rationale: string\n}\n\n/**\n * Paired comparison of two adaptation curves. Per-k deltas with 95%\n * bootstrap CIs (constructed from each curve's `perScenario` per-k means\n * — the bootstrap unit is the scenario, not the rep).\n */\nexport function compareAdaptationCurves(\n a: AdaptationCurve,\n b: AdaptationCurve,\n opts: { confidence?: number; bootstrapResamples?: number; seed?: number } = {},\n): CompareCurvesResult {\n const conf = opts.confidence ?? 0.95\n const resamples = opts.bootstrapResamples ?? 500\n const rng = makeRng(opts.seed)\n\n const perK: CompareCurvesResult['perK'] = []\n for (const ap of a.points) {\n const bp = b.points.find((p) => p.k === ap.k)\n if (!bp) continue\n const aMeans = ap.perScenario.map((s) => s.meanScore)\n const bMeans = bp.perScenario.map((s) => s.meanScore)\n const aCi = bootstrapMeanCi(aMeans, resamples, conf, rng)\n const bCi = bootstrapMeanCi(bMeans, resamples, conf, rng)\n perK.push({\n k: ap.k,\n deltaMean: ap.meanScore - bp.meanScore,\n aLow: aCi.low,\n aHigh: aCi.high,\n bLow: bCi.low,\n bHigh: bCi.high,\n })\n }\n\n const areaDelta = a.adaptationArea - b.adaptationArea\n const firstPassKDelta =\n a.firstPassK !== null && b.firstPassK !== null\n ? b.firstPassK - a.firstPassK // smaller k for a means a adapts faster (positive delta)\n : null\n\n // Composite verdict: positive area delta + most per-k deltas in same\n // direction → that side wins. Within ε of zero on both → similar.\n const meanDelta = perK.reduce((s, p) => s + p.deltaMean, 0) / Math.max(1, perK.length)\n let verdict: CompareCurvesResult['verdict']\n if (Math.abs(meanDelta) < 0.02 && Math.abs(areaDelta) < 0.02) verdict = 'similar'\n else if (meanDelta > 0 && areaDelta > 0) verdict = 'a_better'\n else if (meanDelta < 0 && areaDelta < 0) verdict = 'b_better'\n else verdict = 'similar'\n\n const rationale =\n `mean per-k delta=${meanDelta.toFixed(3)}, area delta=${areaDelta.toFixed(3)}` +\n (firstPassKDelta !== null ? `, first-pass-k delta=${firstPassKDelta}` : '')\n\n return { perK, areaDelta, firstPassKDelta, verdict, rationale }\n}\n\n/** First k at which the curve's per-scenario pass rate reliably hits the threshold. */\nexport function firstPassK(curve: AdaptationCurve, threshold = 0.5): number | null {\n return curve.points.find((p) => p.passRate >= threshold)?.k ?? null\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction makeRng(seed?: number): () => number {\n if (seed === undefined) return Math.random\n let s = seed >>> 0\n return () => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\nfunction bootstrapMeanCi(\n xs: number[],\n resamples: number,\n confidence: number,\n rng: () => number,\n): { low: number; high: number } {\n if (xs.length < 2) return { low: xs[0] ?? 0, high: xs[0] ?? 0 }\n const samples = new Array<number>(resamples)\n for (let b = 0; b < resamples; b++) {\n let sum = 0\n for (let i = 0; i < xs.length; i++) sum += xs[Math.floor(rng() * xs.length)]!\n samples[b] = sum / xs.length\n }\n samples.sort((a, b) => a - b)\n const alpha = 1 - confidence\n return {\n low: samples[Math.floor((alpha / 2) * resamples)]!,\n high: samples[Math.min(resamples - 1, Math.ceil((1 - alpha / 2) * resamples) - 1)]!,\n }\n}\n","/**\n * Adversarial scenario search.\n *\n * Capability evaluation on a fixed scenario set measures performance on\n * the distribution someone curated. Production failure modes live in the\n * tail — inputs the curator didn't think of, or actively avoided. The\n * adversarial-search primitive actively looks for them: starting from a\n * pool of scenarios where the policy already passes, it mutates them\n * (paraphrase, edge-case substitution, compositional combination) and\n * keeps the mutations that *break* the policy.\n *\n * This is not magic. It's the simplest version of the loop that AdA\n * (Open-Ended Adaptation, DeepMind 2023), POET, and Anthropic's\n * auto-jailbreak rigs all run: hill-climb against a failure indicator,\n * keep the survivors, repeat. We ship the harness; consumers supply the\n * mutation strategies and the failure detector.\n *\n * Why ship this in agent-eval and not as a separate red-team tool: every\n * piece of the standard adversarial loop is already in this package\n * (`runEvalCampaign` for the matrix run, `RawProviderSink` for capture,\n * `assertRunCaptured` for integrity, `pairedEvalueSequence` for stop\n * criteria). The adversarial primitive is just the *scenario-mutation\n * meta-loop* on top of that machinery.\n */\n\nexport interface AdversarialScenario<S> {\n /** Stable id — used for deduplication and lineage tracking. */\n id: string\n /** Generation index — 0 for seeds, 1 for first round of mutations, etc. */\n generation: number\n /** Lineage — id of the parent scenario this was mutated from, if any. */\n parentId: string | null\n scenario: S\n /** Score on the policy under test. Lower = adversarial signal. */\n score: number | null\n /** Strategy that produced this mutation, for diagnostics. */\n mutationStrategy: string | null\n}\n\nexport interface AdversarialMutation<S> {\n id: string\n /**\n * Mutate one scenario. Return null to skip; return one or more new\n * scenarios. The harness deduplicates by `mutateScenarioId(scenario)`.\n */\n mutate(parent: S, rng: () => number): Promise<S[]> | S[]\n}\n\nexport interface AdversarialSearchOptions<S> {\n /** Initial scenarios — typically those the policy currently passes. */\n seeds: S[]\n /** Stable identifier extraction. */\n mutateScenarioId: (s: S) => string\n /** Mutation strategies. */\n mutations: AdversarialMutation<S>[]\n /**\n * Run the policy under test against one scenario, return a scalar score\n * in [0, 1]. Lower = adversarial signal.\n */\n scoreFn: (s: S) => Promise<number>\n /**\n * Threshold below which a scenario counts as a \"failure\" worth keeping.\n * Default 0.5.\n */\n failureThreshold?: number\n /** Number of mutation rounds. Default 3. */\n rounds?: number\n /** Children per parent per round. Default 4. */\n childrenPerParent?: number\n /** Maximum total scenarios examined. Default Infinity. */\n budget?: number\n /** Seed for the deterministic RNG. Default 1. */\n seed?: number\n}\n\nexport interface AdversarialSearchReport<S> {\n scenarios: AdversarialScenario<S>[]\n /** Discovered failures sorted by score ascending. */\n failures: AdversarialScenario<S>[]\n /** Round-by-round counts. */\n byGeneration: Array<{ generation: number; total: number; failures: number; meanScore: number }>\n /** Total scoreFn invocations consumed. */\n scoreCalls: number\n}\n\nexport async function adversarialScenarioSearch<S>(\n opts: AdversarialSearchOptions<S>,\n): Promise<AdversarialSearchReport<S>> {\n const failureThreshold = opts.failureThreshold ?? 0.5\n const rounds = opts.rounds ?? 3\n const children = opts.childrenPerParent ?? 4\n const budget = opts.budget ?? Number.POSITIVE_INFINITY\n const seed = opts.seed ?? 1\n const rng = mulberry32(seed)\n\n const scenarios: AdversarialScenario<S>[] = []\n const seen = new Set<string>()\n let scoreCalls = 0\n\n // Seed generation.\n for (const s of opts.seeds) {\n const id = opts.mutateScenarioId(s)\n if (seen.has(id)) continue\n seen.add(id)\n if (scoreCalls >= budget) break\n const score = await opts.scoreFn(s)\n scoreCalls++\n scenarios.push({\n id,\n generation: 0,\n parentId: null,\n scenario: s,\n score,\n mutationStrategy: null,\n })\n }\n\n // Mutation rounds.\n for (let g = 1; g <= rounds; g++) {\n if (scoreCalls >= budget) break\n const parents = scenarios.filter((s) => s.generation === g - 1)\n for (const parent of parents) {\n for (const mutation of opts.mutations) {\n if (scoreCalls >= budget) break\n const produced = await mutation.mutate(parent.scenario, rng)\n const childArr = Array.isArray(produced) ? produced : [produced]\n for (let k = 0; k < Math.min(children, childArr.length); k++) {\n if (scoreCalls >= budget) break\n const child = childArr[k]!\n const cid = opts.mutateScenarioId(child)\n if (seen.has(cid)) continue\n seen.add(cid)\n const cscore = await opts.scoreFn(child)\n scoreCalls++\n scenarios.push({\n id: cid,\n generation: g,\n parentId: parent.id,\n scenario: child,\n score: cscore,\n mutationStrategy: mutation.id,\n })\n }\n }\n }\n }\n\n const failures = scenarios\n .filter((s) => s.score !== null && s.score < failureThreshold)\n .sort((a, b) => (a.score ?? 0) - (b.score ?? 0))\n\n const byGeneration: AdversarialSearchReport<S>['byGeneration'] = []\n const maxGen = scenarios.reduce((m, s) => Math.max(m, s.generation), 0)\n for (let g = 0; g <= maxGen; g++) {\n const gens = scenarios.filter((s) => s.generation === g)\n if (gens.length === 0) continue\n const fails = gens.filter((s) => s.score !== null && s.score < failureThreshold).length\n const meanScore = gens.reduce((sum, s) => sum + (s.score ?? 0), 0) / gens.length\n byGeneration.push({ generation: g, total: gens.length, failures: fails, meanScore })\n }\n\n return { scenarios, failures, byGeneration, scoreCalls }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction mulberry32(seed: number): () => number {\n let s = seed >>> 0\n return () => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n","/**\n * Trainer-format exporters.\n *\n * agent-eval produces canonical artifacts (`RunRecord[]`, `PreferenceTriple[]`,\n * `StepReward[]`, `PrmTrainingTriple[]`). RL training pipelines consume\n * different shapes — Hugging Face TRL, Prime Intellect's prime-rl, OpenAI\n * fine-tuning, Anthropic finetuning, OpenRLHF, verl. Each has its own\n * JSONL conventions. Rather than ship N adapters, this module ships the\n * canonical formats most production pipelines accept and ergonomic helpers\n * for the rest.\n *\n * Shapes:\n * - **DPO / IPO / KTO** — `{prompt, chosen, rejected}` JSONL. Consumed\n * by HuggingFace TRL, prime-rl's offline DPO, OpenRLHF.\n * - **GRPO offline** — `{prompt, completions[], rewards[]}` JSONL.\n * Consumed by prime-rl GRPO, verl, OpenRLHF.\n * - **SFT** — `{messages[]}` JSONL with chosen completion as the final\n * assistant turn. Consumed by HF SFT trainers, OpenAI fine-tuning,\n * Anthropic finetuning.\n * - **PRM** — `{prompt, prefix_steps[], chosen_step, rejected_step}` JSONL.\n * Consumed by Lightman-style PRM trainers and prime-rl's PRM mode.\n *\n * Why ship this in agent-eval rather than a separate adapter package: the\n * canonical artifacts (`RunRecord[]`, `PreferenceTriple[]`, etc.) are\n * agent-eval's contract; without first-party exporters consumers reverse-\n * engineer the mapping every release. The exporters codify it.\n *\n * The exporters take callbacks for any field that isn't on the canonical\n * artifact (specifically: prompt + completion text, since the package\n * stores only their hashes by design — full text is the consumer's\n * trace store / raw event log).\n */\n\nimport type { RunRecord } from '../run-record'\nimport type { PreferenceTriple } from './preferences'\nimport type { PrmTrainingTriple, StepReward } from './process-reward'\n\n// ── DPO / IPO / KTO ──────────────────────────────────────────────────────\n\nexport interface DpoLookups {\n /** Resolve the prompt text for a run (typically from a trace store / raw event sink). */\n promptOf: (runId: string) => string | Promise<string>\n /** Resolve the assistant completion text for a run. */\n completionOf: (runId: string) => string | Promise<string>\n}\n\nexport interface DpoExportRow {\n prompt: string\n chosen: string\n rejected: string\n /** Carried-through margin. Some KTO / IPO variants use this. */\n margin?: number\n /** Free-form metadata for downstream filtering / sharding. */\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert preference triples to TRL-compatible DPO rows. The shape\n * `{prompt, chosen, rejected}` is the canonical HuggingFace DPODataset\n * entry; every major DPO trainer accepts it.\n */\nexport async function toDpoRows(\n triples: PreferenceTriple[],\n lookups: DpoLookups,\n): Promise<DpoExportRow[]> {\n const out: DpoExportRow[] = []\n for (const t of triples) {\n const [prompt, chosen, rejected] = await Promise.all([\n Promise.resolve(lookups.promptOf(t.chosenRunId)),\n Promise.resolve(lookups.completionOf(t.chosenRunId)),\n Promise.resolve(lookups.completionOf(t.rejectedRunId)),\n ])\n out.push({\n prompt,\n chosen,\n rejected,\n margin: t.marginScore,\n meta: {\n scenarioId: t.scenarioId,\n chosenVariantId: t.chosenVariantId,\n rejectedVariantId: t.rejectedVariantId,\n chosenRunId: t.chosenRunId,\n rejectedRunId: t.rejectedRunId,\n chosenModel: t.meta.chosenModel,\n rejectedModel: t.meta.rejectedModel,\n },\n })\n }\n return out\n}\n\n/** Serialize DPO rows as JSONL. One line per row. */\nexport function toDpoJsonl(rows: DpoExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── GRPO offline ─────────────────────────────────────────────────────────\n\nexport interface GrpoLookups {\n promptOf: (runId: string) => string | Promise<string>\n completionOf: (runId: string) => string | Promise<string>\n /** Optional: derive a custom reward from the run. Defaults to score. */\n rewardOf?: (run: RunRecord) => number | null\n}\n\nexport interface GrpoExportRow {\n prompt: string\n completions: string[]\n rewards: number[]\n /** runIds in the same order as `completions[]` for traceability. */\n runIds: string[]\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert RunRecord[] grouped by `(scenarioId)` into GRPO offline rows —\n * one row per scenario, with one completion per run on that scenario.\n *\n * GRPO (Shao et al. 2024 / DeepSeek-R1) trains on relative advantages\n * within a group of completions for the same prompt; this is the\n * canonical input format.\n */\nexport async function toGrpoRows(\n runs: RunRecord[],\n lookups: GrpoLookups,\n): Promise<GrpoExportRow[]> {\n const rewardOf = lookups.rewardOf ?? defaultReward\n const grouped = new Map<string, RunRecord[]>()\n for (const r of runs) {\n const sid = r.scenarioId ?? r.experimentId\n const arr = grouped.get(sid) ?? []\n arr.push(r)\n grouped.set(sid, arr)\n }\n\n const rows: GrpoExportRow[] = []\n for (const [scenarioId, group] of grouped.entries()) {\n if (group.length === 0) continue\n // Resolve prompt once per group (assumes all runs in a group share the prompt).\n const prompt = await Promise.resolve(lookups.promptOf(group[0]!.runId))\n const completions: string[] = []\n const rewards: number[] = []\n const runIds: string[] = []\n for (const r of group) {\n const reward = rewardOf(r)\n if (reward === null) continue\n const completion = await Promise.resolve(lookups.completionOf(r.runId))\n completions.push(completion)\n rewards.push(reward)\n runIds.push(r.runId)\n }\n if (completions.length === 0) continue\n rows.push({\n prompt,\n completions,\n rewards,\n runIds,\n meta: {\n scenarioId,\n n: completions.length,\n meanReward: rewards.reduce((s, x) => s + x, 0) / rewards.length,\n },\n })\n }\n return rows\n}\n\nexport function toGrpoJsonl(rows: GrpoExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── SFT ──────────────────────────────────────────────────────────────────\n\nexport interface SftLookups {\n promptOf: (runId: string) => string | Promise<string>\n completionOf: (runId: string) => string | Promise<string>\n /** Optional system message. Default omits. */\n systemOf?: (run: RunRecord) => string | null | undefined\n /** Filter — return false to skip the run (e.g., low score, failed cases). */\n include?: (run: RunRecord) => boolean\n}\n\nexport interface SftExportRow {\n messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert RunRecord[] into Hugging Face / OpenAI / Anthropic-style\n * conversational SFT rows. By default every record becomes one row;\n * pass `include` to filter (e.g., keep only `score >= 0.8` for\n * rejection-sampling SFT).\n */\nexport async function toSftRows(runs: RunRecord[], lookups: SftLookups): Promise<SftExportRow[]> {\n const include = lookups.include ?? (() => true)\n const rows: SftExportRow[] = []\n for (const r of runs) {\n if (!include(r)) continue\n const system = lookups.systemOf?.(r)\n const [prompt, completion] = await Promise.all([\n Promise.resolve(lookups.promptOf(r.runId)),\n Promise.resolve(lookups.completionOf(r.runId)),\n ])\n const messages: SftExportRow['messages'] = []\n if (system) messages.push({ role: 'system', content: system })\n messages.push({ role: 'user', content: prompt })\n messages.push({ role: 'assistant', content: completion })\n rows.push({\n messages,\n meta: {\n runId: r.runId,\n candidateId: r.candidateId,\n scenarioId: r.scenarioId,\n score: r.outcome.holdoutScore ?? r.outcome.searchScore,\n model: r.model,\n },\n })\n }\n return rows\n}\n\nexport function toSftJsonl(rows: SftExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── PRM ──────────────────────────────────────────────────────────────────\n\nexport interface PrmLookups {\n /** Resolve the prompt text for a run. */\n promptOf: (runId: string) => string | Promise<string>\n /** Resolve the trajectory step text for a (runId, spanId) pair. */\n stepTextOf: (runId: string, spanId: string) => string | Promise<string>\n /** Optional: sequence of prefix span ids leading up to the divergence. */\n prefixOf?: (runId: string, prefixStepIndex: number) => string[] | Promise<string[]>\n}\n\nexport interface PrmExportRow {\n prompt: string\n /** Span ids for the steps before divergence — caller resolves text via `stepTextOf`. */\n prefixSpanIds: string[]\n prefixStepText: string[]\n chosenStep: string\n rejectedStep: string\n chosenReward: number\n rejectedReward: number\n marginScore: number\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert PRM training triples to JSONL rows. Caller's `stepTextOf`\n * callback resolves span text from the consumer's trace store.\n */\nexport async function toPrmRows(\n triples: PrmTrainingTriple[],\n lookups: PrmLookups,\n): Promise<PrmExportRow[]> {\n const rows: PrmExportRow[] = []\n for (const t of triples) {\n const prompt = await Promise.resolve(lookups.promptOf(t.prefixRunId))\n const prefixSpanIds = lookups.prefixOf\n ? await Promise.resolve(lookups.prefixOf(t.prefixRunId, t.prefixStepIndex))\n : []\n const prefixStepText: string[] = []\n for (const spanId of prefixSpanIds) {\n prefixStepText.push(await Promise.resolve(lookups.stepTextOf(t.prefixRunId, spanId)))\n }\n const chosenStep = await Promise.resolve(lookups.stepTextOf(t.prefixRunId, t.chosenSpanId))\n const rejectedStep = await Promise.resolve(\n lookups.stepTextOf(t.rejectedRunId, t.rejectedSpanId),\n )\n rows.push({\n prompt,\n prefixSpanIds,\n prefixStepText,\n chosenStep,\n rejectedStep,\n chosenReward: t.chosenReward,\n rejectedReward: t.rejectedReward,\n marginScore: t.marginScore,\n meta: {\n prefixRunId: t.prefixRunId,\n rejectedRunId: t.rejectedRunId,\n prefixStepIndex: t.prefixStepIndex,\n },\n })\n }\n return rows\n}\n\nexport function toPrmJsonl(rows: PrmExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── Step rewards (for value-function regression) ─────────────────────────\n\nexport interface StepRewardJsonlRow {\n runId: string\n spanId: string\n stepIndex: number\n reward: number\n determinism: 'deterministic' | 'probabilistic'\n weight: number\n}\n\nexport function stepRewardsToJsonl(stepRewards: StepReward[]): string {\n const rows: StepRewardJsonlRow[] = stepRewards.map((s) => ({\n runId: s.runId,\n spanId: s.spanId,\n stepIndex: s.stepIndex,\n reward: s.reward,\n determinism: s.determinism,\n weight: s.weight ?? 1,\n }))\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction defaultReward(run: RunRecord): number | null {\n const v = run.outcome.holdoutScore ?? run.outcome.searchScore\n return typeof v === 'number' && Number.isFinite(v) ? v : null\n}\n","/**\n * `PredictiveValidityResearcher` — concrete `Researcher` implementation\n * that drives selection from outcome-anchored predictive validity.\n *\n * Each method:\n *\n * - `inspectFailures(runs)` — synthesizes failure modes from the\n * bottom-quartile of `RunRecord`s on the configured proxy reward.\n * - `proposeChange(failures)` — proposes steering changes that target\n * the rubrics with the lowest predictive validity (decorative ones).\n * Either reduce their weight in the composite, or recalibrate them.\n * - `applyChange(changes, baseline)` — merges the proposed steering\n * into the experiment plan.\n * - `evaluateChange(plan)` — re-runs the predictive-validity check on\n * the post-change runs and reports the delta.\n *\n * The result is a closed loop: the rubric weights drift toward the ones\n * that actually predict deployment outcomes, automatically. Pair with\n * `runRLCampaign` for the full auto-research story.\n */\n\nimport type { GateDecision } from '../held-out-gate'\nimport type { OutcomeStore } from '../meta-eval/outcome-store'\nimport {\n type RubricPredictiveValidityReport,\n rubricPredictiveValidity,\n} from '../meta-eval/rubric-predictive-validity'\nimport type {\n ExperimentPlan,\n ExperimentResult,\n FailureMode,\n Researcher,\n SteeringChange,\n} from '../researcher'\nimport type { RunRecord } from '../run-record'\n\nexport interface PredictiveValidityResearcherOptions {\n outcomes: OutcomeStore\n outcomeMetrics: string[]\n /** Score threshold below which a run counts as a \"failure.\" Default 0.5. */\n failureThreshold?: number\n /** Spearman bucket below which a rubric is \"decorative.\" Default 0.4. */\n decorativeThreshold?: number\n /** Optional steering-namespace prefix for proposed changes. Default `'rubric_weight'`. */\n steeringNamespace?: string\n /** Override the rubric set the researcher inspects. Default: every numeric `outcome.raw` key seen. */\n rubrics?: string[]\n /**\n * Snapshot stash hook — called with the most recent predictive-validity\n * report. Useful when a downstream system wants to log rubric drift over\n * time. Default no-op.\n */\n onReport?: (report: RubricPredictiveValidityReport) => void | Promise<void>\n}\n\n/**\n * Concrete `Researcher` driven by `rubricPredictiveValidity`. The brain:\n * rubrics that don't predict deployment outcomes don't earn weight.\n */\nexport class PredictiveValidityResearcher implements Researcher {\n private opts: PredictiveValidityResearcherOptions\n private lastReport: RubricPredictiveValidityReport | null = null\n\n constructor(opts: PredictiveValidityResearcherOptions) {\n this.opts = opts\n }\n\n async inspectFailures(runs: RunRecord[]): Promise<FailureMode[]> {\n const threshold = this.opts.failureThreshold ?? 0.5\n const failures: FailureMode[] = []\n const failingRuns = runs.filter((r) => {\n const score = r.outcome.holdoutScore ?? r.outcome.searchScore\n return typeof score === 'number' && score < threshold\n })\n if (failingRuns.length === 0) return failures\n\n // Group failures by candidateId — the researcher's primary handle is\n // \"this candidate is producing low-scoring outputs in this scenario.\"\n const grouped = new Map<string, RunRecord[]>()\n for (const r of failingRuns) {\n const arr = grouped.get(r.candidateId) ?? []\n arr.push(r)\n grouped.set(r.candidateId, arr)\n }\n\n for (const [candidateId, group] of grouped.entries()) {\n const meanScore =\n group.reduce((s, r) => {\n const x = r.outcome.holdoutScore ?? r.outcome.searchScore ?? 0\n return s + x\n }, 0) / group.length\n failures.push({\n code: `low-score-${candidateId}`,\n description: `${candidateId} scored < ${threshold} on ${group.length} run(s) (mean ${meanScore.toFixed(3)})`,\n evidence: {\n runIds: group.slice(0, 8).map((r) => r.runId),\n samples: group.length,\n },\n })\n }\n return failures\n }\n\n async proposeChange(failures: FailureMode[]): Promise<SteeringChange[]> {\n if (failures.length === 0) return []\n\n // Without a prior report, return a single \"collect more outcome data\"\n // change — the researcher refuses to reweight rubrics from zero evidence.\n if (this.lastReport === null) {\n return [\n {\n kind: 'threshold',\n payload: { directive: 'researcher.collect-more-outcomes' },\n rationale:\n 'predictive-validity researcher has no prior report; cannot recommend rubric reweighting until at least one report exists',\n },\n ]\n }\n\n const decorativeThreshold = this.opts.decorativeThreshold ?? 0.4\n const changes: SteeringChange[] = []\n\n for (const ranking of this.lastReport.ranked) {\n if (ranking.verdict === 'load_bearing') continue\n if (Math.abs(ranking.spearman) >= decorativeThreshold) continue\n changes.push({\n kind: 'reviewer_prompt',\n payload: {\n rubric: ranking.rubric,\n action: 'down-weight',\n spearman: ranking.spearman,\n bestOutcome: ranking.bestOutcome,\n },\n rationale: `predictive-validity Spearman=${ranking.spearman.toFixed(3)} vs ${ranking.bestOutcome} (decorative); recommend down-weighting`,\n expectedDelta: -Math.max(0, 0.05 - Math.abs(ranking.spearman)),\n })\n }\n for (const ranking of this.lastReport.ranked.slice(0, 1)) {\n if (ranking.verdict !== 'load_bearing') continue\n changes.push({\n kind: 'reviewer_prompt',\n payload: {\n rubric: ranking.rubric,\n action: 'up-weight',\n spearman: ranking.spearman,\n bestOutcome: ranking.bestOutcome,\n },\n rationale: `predictive-validity Spearman=${ranking.spearman.toFixed(3)} vs ${ranking.bestOutcome} (load-bearing); recommend up-weighting`,\n expectedDelta: Math.max(0, Math.abs(ranking.spearman) - 0.5) * 0.1,\n })\n }\n return changes\n }\n\n async applyChange(changes: SteeringChange[], baseline: ExperimentPlan): Promise<ExperimentPlan> {\n // Merge proposed changes into the plan's `changes` array, preserving\n // any changes the baseline already had.\n return {\n ...baseline,\n changes: [...baseline.changes, ...changes],\n }\n }\n\n async evaluateChange(plan: ExperimentPlan): Promise<ExperimentResult> {\n // The researcher contract takes a *plan* and returns a *result* —\n // implementations that only understand re-scoring runs can produce a\n // \"no-op\" gate decision and let the caller drive the actual sweep.\n // Real evaluators (CallbackResearcher) execute the plan; we report.\n const emptyGate: GateDecision = {\n promote: false,\n candidateId: plan.proposedCandidateId,\n baselineId: plan.baselineCandidateId,\n evidence: {\n productiveRuns: 0,\n medianPairedDelta: 0,\n pairedCI: { low: 0, high: 0 },\n pairedPValue: 1,\n searchScore: 0,\n holdoutScore: 0,\n overfitGap: 0,\n baselineOverfitGap: 0,\n medianCandidateCost: Number.NaN,\n medianBaselineCost: Number.NaN,\n },\n reason:\n 'predictive-validity researcher does not execute plans; the caller is expected to run the sweep and call rubricPredictiveValidity directly with the resulting RunRecord[].',\n rejectionCode: 'few_runs',\n }\n return {\n plan,\n runs: [],\n gateDecision: emptyGate,\n }\n }\n\n /**\n * Run the predictive-validity check explicitly against a fresh RunRecord\n * set. Updates the researcher's cached report so subsequent\n * `proposeChange` calls have evidence to draw from.\n */\n async runValidityCheck(runs: RunRecord[]): Promise<RubricPredictiveValidityReport> {\n const report = await rubricPredictiveValidity({\n runs,\n outcomes: this.opts.outcomes,\n outcomeMetrics: this.opts.outcomeMetrics,\n rubrics: this.opts.rubrics,\n })\n if (this.opts.onReport) await this.opts.onReport(report)\n this.lastReport = report\n return report\n }\n\n /**\n * Force-feed a predictive-validity report into the researcher state —\n * useful when the consumer ran the report out-of-band and wants the\n * researcher's later proposals informed by it.\n */\n setReport(report: RubricPredictiveValidityReport): void {\n this.lastReport = report\n }\n\n getLastReport(): RubricPredictiveValidityReport | null {\n return this.lastReport\n }\n}\n","/**\n * Process reward extraction — step-level credit assignment from trace spans.\n *\n * RL on long-horizon agents needs *step-level* rewards, not run-level\n * ones. The classic credit-assignment problem (Sutton & Barto) requires\n * knowing which sub-decisions in a trajectory contributed to the\n * outcome. Modern systems (DeepSeek-R1, OpenAI o-series, Lightman et al.\n * \"Let's Verify Step by Step\" 2023) train *process reward models* (PRMs)\n * that score every step, then do RL with the PRM as the reward signal.\n *\n * This module extracts `StepReward[]` from trace spans — one per\n * meaningful step — and ships:\n *\n * 1. `extractStepRewards(store, runId, opts)` — span → step-reward\n * conversion using configurable per-span scorers (LLM judge over the\n * span output, deterministic checkers, or a learned PRM).\n * 2. `runwiseStepRewardSummary(stepRewards)` — aggregate the per-step\n * signal into a credit-assignment-aware run-level score.\n * 3. `prmTrainingPairs(stepRewards, options)` — produce the\n * `(prefix, suffix_chosen, suffix_rejected)` triples that PRM\n * training pipelines consume.\n *\n * What we ship: the *extraction* and *aggregation* infrastructure plus\n * the data shape PRM training expects. We do NOT ship the actual PRM\n * training (gradient descent over a transformer is out of scope for a\n * TS package). The interface is the contract; downstream consumers wire\n * their preferred trainer.\n *\n * Caveat the panel will land: this is descriptive credit assignment\n * (which steps correlate with outcome), not causal credit assignment\n * (which steps caused outcome). For causal claims you need\n * counterfactual rollouts or a learned dynamics model. Future work; the\n * descriptive version is what production PRM training actually uses.\n */\n\nimport type { Span } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface StepReward {\n /** Trace span this reward attaches to. */\n spanId: string\n runId: string\n /** Index in the trajectory (0-based, in started-at order). */\n stepIndex: number\n /** Span kind (typically 'tool', 'llm', 'judge'). */\n kind: Span['kind']\n /** Span name — for the consumer's downstream filtering. */\n name: string\n /** Step-level reward in [0, 1]. */\n reward: number\n /**\n * Determinism class. Mirrors the verifiable-reward distinction:\n * deterministic = test/compile/schema check; probabilistic = LLM judge.\n */\n determinism: 'deterministic' | 'probabilistic'\n /** Optional rationale / evidence — the trainer typically discards. */\n rationale?: string\n /** Optional weight — how much this step contributes to credit assignment. */\n weight?: number\n}\n\nexport interface StepScorer {\n /** Span kinds this scorer applies to. */\n appliesTo: Span['kind'][]\n /** Returns null to skip the span; returns a `StepReward` shape (without index/runId/spanId, which are filled in). */\n score(span: Span): Promise<Omit<StepReward, 'spanId' | 'runId' | 'stepIndex'>> | null | undefined\n}\n\nexport interface ExtractStepRewardsOptions {\n /**\n * Ordered list of scorers. Each span runs through scorers in order;\n * the first non-null result wins. If no scorer applies, the span is\n * skipped (not all spans are training-worthy).\n */\n scorers: StepScorer[]\n /** Optional filter — return null to drop the span entirely before scoring. */\n preFilter?: (span: Span) => boolean\n}\n\nexport async function extractStepRewards(\n store: TraceStore,\n runId: string,\n opts: ExtractStepRewardsOptions,\n): Promise<StepReward[]> {\n const spans = await store.spans({ runId })\n const ordered = [...spans].sort((a, b) => a.startedAt - b.startedAt)\n const out: StepReward[] = []\n let idx = 0\n for (const span of ordered) {\n if (opts.preFilter && !opts.preFilter(span)) continue\n let scored: Awaited<ReturnType<StepScorer['score']>> = null\n for (const s of opts.scorers) {\n if (!s.appliesTo.includes(span.kind)) continue\n const r = await s.score(span)\n if (r) {\n scored = r\n break\n }\n }\n if (!scored) continue\n out.push({\n spanId: span.spanId,\n runId,\n stepIndex: idx++,\n kind: span.kind,\n name: span.name,\n reward: scored.reward,\n determinism: scored.determinism,\n rationale: scored.rationale,\n weight: scored.weight,\n })\n }\n return out\n}\n\nexport interface RunwiseStepSummary {\n runId: string\n totalSteps: number\n meanReward: number\n /** Sum-of-rewards (weighted by `weight ?? 1`). Use as the run-level proxy. */\n sumWeightedReward: number\n /** Fraction of steps where reward < 0.5 — proxy for \"where the policy was wrong.\" */\n failureFraction: number\n /** Maximum drop in reward between consecutive steps — diagnoses a step where things went sideways. */\n worstStepDelta: number\n worstStepIndex: number | null\n}\n\nexport function runwiseStepRewardSummary(stepRewards: StepReward[]): RunwiseStepSummary {\n if (stepRewards.length === 0) {\n return {\n runId: '',\n totalSteps: 0,\n meanReward: 0,\n sumWeightedReward: 0,\n failureFraction: 0,\n worstStepDelta: 0,\n worstStepIndex: null,\n }\n }\n const runId = stepRewards[0]!.runId\n let sumW = 0\n let sumWR = 0\n let failures = 0\n let worstDelta = 0\n let worstIdx: number | null = null\n let prev = stepRewards[0]!.reward\n for (let i = 0; i < stepRewards.length; i++) {\n const s = stepRewards[i]!\n const w = s.weight ?? 1\n sumW += w\n sumWR += w * s.reward\n if (s.reward < 0.5) failures++\n if (i > 0) {\n const delta = s.reward - prev\n if (delta < worstDelta) {\n worstDelta = delta\n worstIdx = i\n }\n prev = s.reward\n } else {\n prev = s.reward\n }\n }\n return {\n runId,\n totalSteps: stepRewards.length,\n meanReward: sumW === 0 ? 0 : sumWR / sumW,\n sumWeightedReward: sumWR,\n failureFraction: failures / stepRewards.length,\n worstStepDelta: worstDelta,\n worstStepIndex: worstIdx,\n }\n}\n\nexport interface PrmTrainingTriple {\n /** Prefix run-id (or composite key) — the trajectory up to step k-1. */\n prefixRunId: string\n prefixStepIndex: number\n /** The step that came next on a high-reward trajectory. */\n chosenSpanId: string\n chosenReward: number\n /** A step from a divergent low-reward trajectory at the same prefix length. */\n rejectedSpanId: string\n rejectedReward: number\n /** The prefix run came from this run; the rejected step came from `rejectedRunId`. */\n rejectedRunId: string\n marginScore: number\n}\n\n/**\n * Build PRM training triples. The shape: pair runs that share an early\n * prefix (same scenario, same first N steps) and diverge later — at the\n * point of divergence, the high-reward run's next step is `chosen`, the\n * low-reward run's next step is `rejected`. This is the canonical PRM\n * training data shape from Lightman et al. and DeepSeek-R1 process\n * supervision.\n *\n * Implementation note: we don't have a way to detect \"same prefix\" in\n * the general agent setting (token-level prefixes require hashing model\n * outputs). The current heuristic groups by `(scenarioId, prefixSpanName\n * sequence)` — runs are paired when their first K span names match. For\n * production use this should be replaced with a proper trajectory-prefix\n * hash; the heuristic is good enough for early-stage scaffolding.\n */\nexport function prmTrainingPairs(\n stepRewardsByRun: Map<string, StepReward[]>,\n opts: { minMargin?: number; minPrefixLength?: number } = {},\n): PrmTrainingTriple[] {\n const minMargin = opts.minMargin ?? 0.2\n const minPrefix = opts.minPrefixLength ?? 1\n const runs = [...stepRewardsByRun.entries()].map(([runId, steps]) => ({ runId, steps }))\n const triples: PrmTrainingTriple[] = []\n\n for (let i = 0; i < runs.length; i++) {\n for (let j = i + 1; j < runs.length; j++) {\n const a = runs[i]!\n const b = runs[j]!\n const minLen = Math.min(a.steps.length, b.steps.length)\n if (minLen < minPrefix + 1) continue\n\n // Find the first index where the trajectories diverge: either by\n // step structure (kind/name mismatch) OR by reward gap ≥ minMargin.\n // Names that match but rewards that differ ARE divergence — that's\n // the canonical PRM training case (same step structure, different\n // outcomes via state/context).\n let divergenceIdx = -1\n for (let k = 0; k < minLen; k++) {\n const sa = a.steps[k]!\n const sb = b.steps[k]!\n const structuralDivergence = sa.kind !== sb.kind || sa.name !== sb.name\n const rewardGap = Math.abs(sa.reward - sb.reward)\n if (structuralDivergence || rewardGap >= minMargin) {\n divergenceIdx = k\n break\n }\n }\n if (divergenceIdx < 0) continue\n if (divergenceIdx < minPrefix) continue\n\n const aNext = a.steps[divergenceIdx]!\n const bNext = b.steps[divergenceIdx]!\n const margin = Math.abs(aNext.reward - bNext.reward)\n if (margin < minMargin) continue\n\n const chosen = aNext.reward > bNext.reward ? aNext : bNext\n const rejected = aNext.reward > bNext.reward ? bNext : aNext\n const chosenRun = aNext.reward > bNext.reward ? a.runId : b.runId\n const rejectedRun = aNext.reward > bNext.reward ? b.runId : a.runId\n triples.push({\n prefixRunId: chosenRun,\n prefixStepIndex: divergenceIdx - 1,\n chosenSpanId: chosen.spanId,\n chosenReward: chosen.reward,\n rejectedSpanId: rejected.spanId,\n rejectedReward: rejected.reward,\n rejectedRunId: rejectedRun,\n marginScore: chosen.reward - rejected.reward,\n })\n }\n }\n return triples\n}\n","/**\n * `runRLCampaign` — top-level orchestrator that runs the matrix and\n * produces every RL-ready artifact in one call.\n *\n * Wires:\n * 1. `runEvalCampaign` for the matrix run (capture, integrity, hooks)\n * 2. `extractVerifiableReward` over each run, separating deterministic\n * from probabilistic reward sources for the trainer\n * 3. `extractPreferences` to produce DPO/PPO/KTO triples\n * 4. `evaluateInterimReleaseConfidence` over paired deltas (anytime-valid)\n * 5. `rubricPredictiveValidity` against an outcome store, when provided\n * 6. `detectRewardHacking` as a standing hygiene check\n * 7. Trainer-format export rows ready for prime-rl / TRL / verl\n *\n * The output `RLCampaignResult` is a single, audit-ready artifact: every\n * stage's output is in there. The consumer's downstream fits in a single\n * line: pass `result.preferences` to their DPO trainer, `result.grpoRows`\n * to GRPO, `result.runs` plus `result.rewardSignals` to a custom RL loop.\n */\n\nimport {\n type EvalCampaignOptions,\n type EvalCampaignResult,\n runEvalCampaign,\n} from '../eval-campaign'\nimport type { OutcomeStore } from '../meta-eval/outcome-store'\nimport {\n type RubricPredictiveValidityReport,\n rubricPredictiveValidity,\n} from '../meta-eval/rubric-predictive-validity'\nimport type { RunRecord } from '../run-record'\nimport { evaluateInterimReleaseConfidence, type InterimReleaseConfidence } from '../sequential'\nimport {\n type DpoExportRow,\n type DpoLookups,\n type GrpoExportRow,\n type GrpoLookups,\n type SftExportRow,\n type SftLookups,\n toDpoRows,\n toGrpoRows,\n toSftRows,\n} from './exporters'\nimport {\n type ExtractPreferencesOptions,\n extractPreferences,\n type PreferenceExtractionReport,\n} from './preferences'\nimport { detectRewardHacking, type RewardHackingReport } from './reward-hacking'\nimport {\n extractVerifiableRewardsFromRecords,\n type VerifiableReward,\n type VerifiableRewardExtractionOptions,\n} from './verifiable-reward'\n\nexport interface RunRLCampaignOptions<V> extends EvalCampaignOptions<V> {\n /** Preference-extraction options. Default uses paired-by-scenario-and-seed with min-margin 0.05. */\n preferences?: ExtractPreferencesOptions\n /** Verifiable-reward extraction options. */\n verifiableReward?: VerifiableRewardExtractionOptions\n /** Outcome store + metric names — when supplied, runs `rubricPredictiveValidity` post-campaign. */\n outcomeStore?: OutcomeStore\n outcomeMetrics?: string[]\n /** Anytime-valid sequential evaluation options. */\n sequential?: { alpha?: number; bound?: number; rope?: { low: number; high: number } }\n /** Trainer-format export lookups. When provided, the orchestrator builds the corresponding rows. */\n trainerExport?: {\n dpo?: DpoLookups\n grpo?: GrpoLookups\n sft?: SftLookups\n }\n}\n\nexport interface RLCampaignResult<V> {\n campaign: EvalCampaignResult\n /** Per-run verifiable reward (deterministic when available, probabilistic fallback otherwise). */\n rewardSignals: Array<{ runId: string; reward: VerifiableReward | null }>\n /** Preference extraction report. */\n preferences: PreferenceExtractionReport\n /** Anytime-valid interim verdict over the paired deltas (vs comparator). */\n interimConfidence: InterimReleaseConfidence | null\n /** Standing reward-hacking hygiene check. */\n rewardHacking: RewardHackingReport\n /** Predictive validity, when an outcome store was supplied. */\n predictiveValidity: RubricPredictiveValidityReport | null\n /** Trainer-export rows, populated only for the formats the caller requested via `trainerExport`. */\n trainerRows: {\n dpo?: DpoExportRow[]\n grpo?: GrpoExportRow[]\n sft?: SftExportRow[]\n }\n /**\n * One-line top-level summary the consumer can log.\n */\n summary: string\n /**\n * Convenience type-tag — consumers can branch on `result.kind`.\n */\n kind: 'agent-eval-rl-campaign'\n unusedVariant?: V\n}\n\nexport async function runRLCampaign<V>(\n opts: RunRLCampaignOptions<V>,\n): Promise<RLCampaignResult<V>> {\n // ── 1. Run the matrix ──────────────────────────────────────────────\n const campaign = await runEvalCampaign(opts)\n\n // ── 2. Extract reward signals (deterministic-first) ────────────────\n const rewardSignals = extractVerifiableRewardsFromRecords(\n campaign.runs,\n opts.verifiableReward ?? {},\n )\n\n // ── 3. Extract preference triples ──────────────────────────────────\n const preferences = extractPreferences(campaign.runs, {\n strategy: opts.preferences?.strategy ?? 'paired-by-scenario-and-seed',\n minMargin: opts.preferences?.minMargin ?? 0.05,\n splitTag: opts.preferences?.splitTag ?? opts.splitTag ?? 'holdout',\n rewardOf: opts.preferences?.rewardOf,\n })\n\n // ── 4. Sequential / anytime-valid interim verdict ──────────────────\n let interimConfidence: InterimReleaseConfidence | null = null\n if (opts.report?.comparator) {\n const comparator = opts.report.comparator\n const deltaSeries = collectPairedDeltaSeries(campaign.runs, comparator)\n if (deltaSeries.some((s) => s.deltas.length > 0)) {\n interimConfidence = evaluateInterimReleaseConfidence({\n deltaSeries,\n alpha: opts.sequential?.alpha,\n bound: opts.sequential?.bound,\n rope: opts.sequential?.rope ?? opts.report?.rope,\n })\n }\n }\n\n // ── 5. Standing reward-hacking hygiene ─────────────────────────────\n const rewardHacking = detectRewardHacking({\n runs: campaign.runs,\n verifiableRewardOptions: opts.verifiableReward,\n })\n\n // ── 6. Predictive validity (when outcomes are supplied) ────────────\n let predictiveValidity: RubricPredictiveValidityReport | null = null\n if (opts.outcomeStore && opts.outcomeMetrics && opts.outcomeMetrics.length > 0) {\n predictiveValidity = await rubricPredictiveValidity({\n runs: campaign.runs,\n outcomes: opts.outcomeStore,\n outcomeMetrics: opts.outcomeMetrics,\n })\n }\n\n // ── 7. Trainer-format export ───────────────────────────────────────\n const trainerRows: RLCampaignResult<V>['trainerRows'] = {}\n if (opts.trainerExport?.dpo) {\n trainerRows.dpo = await toDpoRows(preferences.pairs, opts.trainerExport.dpo)\n }\n if (opts.trainerExport?.grpo) {\n trainerRows.grpo = await toGrpoRows(campaign.runs, opts.trainerExport.grpo)\n }\n if (opts.trainerExport?.sft) {\n trainerRows.sft = await toSftRows(campaign.runs, opts.trainerExport.sft)\n }\n\n const summary = buildSummary({\n campaign,\n preferences,\n interimConfidence,\n rewardHacking,\n predictiveValidity,\n })\n\n return {\n campaign,\n rewardSignals,\n preferences,\n interimConfidence,\n rewardHacking,\n predictiveValidity,\n trainerRows,\n summary,\n kind: 'agent-eval-rl-campaign',\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction collectPairedDeltaSeries(\n runs: RunRecord[],\n comparator: string,\n): Array<{ candidateId: string; deltas: number[] }> {\n // Pair on (scenarioId, seed). For each candidate that isn't the comparator,\n // compute candidate.score - comparator.score on matching cells.\n const baseline = new Map<string, number>()\n for (const r of runs) {\n if (r.candidateId !== comparator) continue\n const sid = r.scenarioId ?? r.experimentId\n const score = r.outcome.holdoutScore ?? r.outcome.searchScore\n if (typeof score !== 'number' || !Number.isFinite(score)) continue\n baseline.set(`${sid}::${r.seed}`, score)\n }\n const byCandidate = new Map<string, number[]>()\n for (const r of runs) {\n if (r.candidateId === comparator) continue\n const sid = r.scenarioId ?? r.experimentId\n const score = r.outcome.holdoutScore ?? r.outcome.searchScore\n if (typeof score !== 'number' || !Number.isFinite(score)) continue\n const baseScore = baseline.get(`${sid}::${r.seed}`)\n if (typeof baseScore !== 'number') continue\n const arr = byCandidate.get(r.candidateId) ?? []\n arr.push(score - baseScore)\n byCandidate.set(r.candidateId, arr)\n }\n return [...byCandidate.entries()].map(([candidateId, deltas]) => ({ candidateId, deltas }))\n}\n\nfunction buildSummary(args: {\n campaign: EvalCampaignResult\n preferences: PreferenceExtractionReport\n interimConfidence: InterimReleaseConfidence | null\n rewardHacking: RewardHackingReport\n predictiveValidity: RubricPredictiveValidityReport | null\n}): string {\n const c = args.campaign\n const lines = [\n `${c.campaignId}: ${c.runs.length} successful runs / ${c.failedRuns.length} failed (fingerprint ${c.campaignFingerprint.slice(0, 12)}…)`,\n `preferences: ${args.preferences.pairs.length} (${args.preferences.strategy}, ${args.preferences.pairsBelowMargin} below margin)`,\n ]\n if (args.interimConfidence) {\n lines.push(\n `sequential verdict: ${args.interimConfidence.recommendation.decision}` +\n (args.interimConfidence.recommendation.candidateId\n ? ` ${args.interimConfidence.recommendation.candidateId}`\n : ''),\n )\n }\n lines.push(\n `reward-hacking: ${args.rewardHacking.verdict} (${args.rewardHacking.findings.length} signals checked)`,\n )\n if (args.predictiveValidity) {\n const top = args.predictiveValidity.ranked[0]\n lines.push(\n `top-rubric: ${top?.rubric ?? 'none'} ρ=${(top?.spearman ?? 0).toFixed(2)} (${top?.verdict ?? 'no data'})`,\n )\n }\n return lines.join(' | ')\n}\n\n// Re-export `runEvalCampaign` so consumers can pick the lower-level\n// primitive without flipping import paths.\nexport { runEvalCampaign } from '../eval-campaign'\n"],"mappings":"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","names":["firstPassK","makeRng"]}
1
+ {"version":3,"sources":["../src/rl/compute-curves.ts","../src/rl/contamination.ts","../src/rl/off-policy.ts","../src/rl/preferences.ts","../src/rl/run-record-adapters.ts","../src/rl/tournament.ts","../src/rl/active-curriculum.ts","../src/rl/adaptation-eval.ts","../src/rl/adversarial.ts","../src/rl/corpus.ts","../src/rl/exporters.ts","../src/rl/dataset.ts","../src/rl/predictive-validity-researcher.ts","../src/rl/process-reward.ts","../src/rl/rl-campaign.ts"],"sourcesContent":["/**\n * Test-time compute scaling curves.\n *\n * The test-time-compute frontier paper (Snell et al. 2024) and the\n * subsequent o1-style scaling work both show that LLM-agent capability\n * is a function of the compute budget at inference, not just of the\n * training run. The right way to characterize a candidate is therefore\n * a *curve* — score at compute budgets {1×, 4×, 16×, …} — not a single\n * point.\n *\n * This module ships:\n *\n * 1. The compute-curve harness — `runComputeCurve(runner, budgets)` —\n * that evaluates one candidate at a sequence of compute budgets\n * and returns the (compute, score) curve.\n * 2. A best-of-N evaluator — `bestOfN(runner, n, scoreFn)` — the\n * simplest test-time-compute scaling primitive: sample N\n * independent rollouts, return the best.\n * 3. A self-consistency evaluator — `selfConsistency(runner, n)` —\n * the majority-vote variant of best-of-N for tasks with a small\n * categorical answer space.\n * 4. Pareto-frontier extraction over multiple candidates — given\n * (candidate, compute, score) tuples, return the set of\n * candidate-compute combinations that aren't dominated.\n *\n * Caveat: \"compute\" here is the caller's notion of a compute unit. For\n * agent eval that's typically wall-time × parallelism, or token budget,\n * or LLM-call count. We accept whatever the caller provides; the curve\n * is on whatever axis they pick.\n */\n\nimport { ValidationError } from '../errors'\n\nexport interface ComputeCurveBudget {\n /** Identifier — for the report. Common: '1x', '4x', '16x'. */\n id: string\n /** Numeric value on the chosen axis (tokens, calls, USD, ms — caller picks). */\n cost: number\n /** Free-form metadata (the caller can carry per-budget config). */\n meta?: Record<string, unknown>\n}\n\nexport interface ComputeCurvePoint {\n budgetId: string\n cost: number\n score: number\n /** Number of underlying samples used at this budget. */\n samples: number\n /** Optional spread / variance information. */\n std?: number\n /** Any extra metrics the runner returned. */\n metrics?: Record<string, number>\n}\n\nexport interface ComputeCurve {\n candidateId: string\n points: ComputeCurvePoint[]\n /** Rough exponent fit: score ≈ a + b * log(cost). Useful for \"how steep is the curve?\" */\n logSlope: number | null\n /** Best (highest-score) point on the curve. */\n best: ComputeCurvePoint\n}\n\nexport interface RunComputeCurveOptions {\n candidateId: string\n budgets: ComputeCurveBudget[]\n /**\n * Run the candidate at one budget. Returns the realized score plus\n * optional spread + extra metrics.\n */\n runAtBudget: (budget: ComputeCurveBudget) => Promise<{\n score: number\n samples: number\n std?: number\n metrics?: Record<string, number>\n }>\n}\n\nexport async function runComputeCurve(opts: RunComputeCurveOptions): Promise<ComputeCurve> {\n const points: ComputeCurvePoint[] = []\n for (const budget of opts.budgets) {\n const r = await opts.runAtBudget(budget)\n points.push({\n budgetId: budget.id,\n cost: budget.cost,\n score: r.score,\n samples: r.samples,\n std: r.std,\n metrics: r.metrics,\n })\n }\n const sorted = [...points].sort((a, b) => a.cost - b.cost)\n const logSlope = sorted.length >= 2 ? fitLogSlope(sorted) : null\n const best = points.reduce((a, b) => (b.score > a.score ? b : a))\n return { candidateId: opts.candidateId, points: sorted, logSlope, best }\n}\n\nexport interface ComputeBestOfNOptions<O> {\n /** Number of independent samples to draw. */\n n: number\n /** Sampler — produces one rollout. */\n sample: (sampleIdx: number) => Promise<O>\n /** Score one rollout. */\n scoreFn: (rollout: O) => Promise<number> | number\n}\n\nexport interface ComputeBestOfNResult<O> {\n best: O\n bestScore: number\n scores: number[]\n meanScore: number\n /** Index of the best rollout, for diagnostics. */\n bestIndex: number\n}\n\n/** The simplest test-time scaling primitive. */\nexport async function bestOfN<O>(opts: ComputeBestOfNOptions<O>): Promise<ComputeBestOfNResult<O>> {\n if (opts.n <= 0) throw new ValidationError('bestOfN: n must be > 0')\n const rollouts: O[] = []\n const scores: number[] = []\n for (let i = 0; i < opts.n; i++) {\n const r = await opts.sample(i)\n rollouts.push(r)\n scores.push(await opts.scoreFn(r))\n }\n let bestIndex = 0\n for (let i = 1; i < scores.length; i++) if (scores[i]! > scores[bestIndex]!) bestIndex = i\n const meanScore = scores.reduce((s, x) => s + x, 0) / scores.length\n return {\n best: rollouts[bestIndex]!,\n bestScore: scores[bestIndex]!,\n scores,\n meanScore,\n bestIndex,\n }\n}\n\nexport interface SelfConsistencyOptions<O> {\n n: number\n sample: (sampleIdx: number) => Promise<O>\n /** Extract the canonical answer key (string) from a rollout. */\n answerKey: (rollout: O) => string\n}\n\nexport interface SelfConsistencyResult<O> {\n /** Modal answer (the majority vote). */\n answer: string\n /** Fraction of samples voting for the modal answer in [0, 1]. */\n agreement: number\n /** Histogram of all answers. */\n histogram: Record<string, number>\n /** A representative rollout that voted for the modal answer. */\n representative: O\n /** All rollouts. */\n rollouts: O[]\n}\n\n/**\n * Self-consistency / majority-vote test-time scaling. For tasks with a\n * small categorical answer space (math problems, multiple choice).\n */\nexport async function selfConsistency<O>(\n opts: SelfConsistencyOptions<O>,\n): Promise<SelfConsistencyResult<O>> {\n if (opts.n <= 0) throw new ValidationError('selfConsistency: n must be > 0')\n const rollouts: O[] = []\n const histogram: Record<string, number> = {}\n for (let i = 0; i < opts.n; i++) {\n const r = await opts.sample(i)\n rollouts.push(r)\n const key = opts.answerKey(r)\n histogram[key] = (histogram[key] ?? 0) + 1\n }\n let answer = ''\n let max = -1\n for (const [k, v] of Object.entries(histogram)) {\n if (v > max) {\n max = v\n answer = k\n }\n }\n const representative = rollouts.find((r) => opts.answerKey(r) === answer) ?? rollouts[0]!\n return {\n answer,\n agreement: max / opts.n,\n histogram,\n representative,\n rollouts,\n }\n}\n\n/**\n * Pareto frontier over (candidate, compute, score) tuples. A point is on\n * the frontier iff no other point dominates it in both score (higher\n * better) and cost (lower better). Returns the frontier sorted ascending\n * by cost.\n */\nexport interface ParetoPointInput {\n candidateId: string\n budgetId: string\n cost: number\n score: number\n}\n\nexport function paretoFrontier(points: ParetoPointInput[]): ParetoPointInput[] {\n const onFrontier: ParetoPointInput[] = []\n for (const p of points) {\n const dominated = points.some(\n (q) =>\n q !== p && q.cost <= p.cost && q.score >= p.score && (q.cost < p.cost || q.score > p.score),\n )\n if (!dominated) onFrontier.push(p)\n }\n return onFrontier.sort((a, b) => a.cost - b.cost)\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction fitLogSlope(points: ComputeCurvePoint[]): number {\n // OLS slope of score on log(cost). Used as a single-number summary of\n // how much marginal compute helps. Positive = score improves with\n // compute; near-zero = capability ceiling reached.\n const xs = points.map((p) => Math.log(Math.max(1e-12, p.cost)))\n const ys = points.map((p) => p.score)\n const n = xs.length\n const mx = xs.reduce((s, x) => s + x, 0) / n\n const my = ys.reduce((s, y) => s + y, 0) / n\n let num = 0\n let den = 0\n for (let i = 0; i < n; i++) {\n num += (xs[i]! - mx) * (ys[i]! - my)\n den += (xs[i]! - mx) ** 2\n }\n return den === 0 ? 0 : num / den\n}\n","/**\n * Contamination probe — held-out perturbation tests.\n *\n * The bug class: once a benchmark scenario set is published, models train\n * on it, and your scores become invalid. SWE-Bench-Verified, GPQA, and\n * MMLU-Pro all exist because their predecessors got contaminated within\n * months. The right defense is to keep a held-out *perturbed* version of\n * every scenario — same task, slightly different surface — and check\n * whether scores diverge significantly. Genuine capability transfers; rote\n * memorization doesn't.\n *\n * This module ships the probe contract:\n *\n * 1. A `ScenarioPerturbation` strategy type — function that produces a\n * perturbed scenario from an original.\n * 2. `runContaminationProbe({ originals, perturbed, scoreFn })` — runs\n * both halves and reports per-scenario score divergence + a global\n * contamination verdict via paired Wilcoxon.\n * 3. Several stock perturbations: `renameVariables`, `shuffleOrder`,\n * `paraphrasePrompt`, `injectIrrelevantClause`. Each preserves the\n * task's structural difficulty while breaking surface memorization.\n *\n * The verdict is conservative: if the perturbed-vs-original score\n * difference is statistically significant (BH-adjusted p < 0.05) AND\n * the median drop is > 5 percentage points, we flag *contamination\n * suspected*. False positives are possible (the perturbation might\n * actually be harder); the default is to flag for review, not to\n * autoreject.\n */\n\nimport { ValidationError } from '../errors'\nimport { benjaminiHochberg, wilcoxonSignedRank } from '../statistics'\n\nexport type ScenarioPerturbationKind =\n | 'rename_variables'\n | 'shuffle_order'\n | 'paraphrase'\n | 'inject_irrelevant_clause'\n | 'custom'\n\nexport interface ScenarioPerturbation<S> {\n kind: ScenarioPerturbationKind\n /** Apply to one scenario, return its perturbed sibling. */\n apply: (scenario: S) => Promise<S> | S\n /** Optional id — for the report. */\n id?: string\n}\n\nexport interface ContaminationProbeInput<S> {\n /** Identity of every scenario. The probe's `runFingerprint` keys on these. */\n scenarioId: (s: S) => string\n /** Original scenarios. */\n originals: S[]\n /**\n * Either pre-computed perturbations (one per original, same order) OR a\n * `perturbation` strategy that synthesizes them on the fly.\n */\n perturbed?: S[]\n perturbation?: ScenarioPerturbation<S>\n /**\n * Run the policy/agent against one scenario and return a scalar score\n * in [0, 1]. The probe doesn't care what the policy is — that's the\n * caller's contract.\n */\n scoreFn: (s: S) => Promise<number>\n}\n\nexport interface ContaminationProbeOptions {\n /** Drop scores below this from the probe; treats partial failures separately. Default 0. */\n scoreFloor?: number\n /**\n * BH-FDR threshold for declaring contamination on each per-scenario\n * delta. Default 0.05.\n */\n fdr?: number\n /**\n * Minimum median per-scenario drop to flag global contamination. Default\n * 0.05 (5 percentage points). Smaller drops may be noise.\n */\n minMedianDrop?: number\n}\n\nexport interface ContaminationProbeReport {\n perScenario: Array<{\n scenarioId: string\n originalScore: number\n perturbedScore: number\n delta: number // perturbed - original (negative = drop)\n /** Per-scenario q-value (single-test BH for a single scenario). Mainly for display. */\n qValue: number\n }>\n /** Wilcoxon paired-test on the deltas. */\n pairedTest: { w: number; p: number }\n medianDelta: number\n meanDelta: number\n contaminationSuspected: boolean\n reason: string\n /** Number of scenarios processed. */\n n: number\n}\n\nexport async function runContaminationProbe<S>(\n input: ContaminationProbeInput<S>,\n opts: ContaminationProbeOptions = {},\n): Promise<ContaminationProbeReport> {\n const fdr = opts.fdr ?? 0.05\n const minMedianDrop = opts.minMedianDrop ?? 0.05\n const floor = opts.scoreFloor ?? 0\n\n if (!input.perturbed && !input.perturbation) {\n throw new ValidationError(\n 'runContaminationProbe: must supply either `perturbed` or `perturbation`.',\n )\n }\n const perturbed: S[] =\n input.perturbed ?? (await Promise.all(input.originals.map((s) => input.perturbation!.apply(s))))\n if (perturbed.length !== input.originals.length) {\n throw new ValidationError(\n `runContaminationProbe: perturbed length ${perturbed.length} ≠ originals ${input.originals.length}`,\n )\n }\n\n // Score both halves.\n const origScores = await Promise.all(input.originals.map((s) => input.scoreFn(s)))\n const pertScores = await Promise.all(perturbed.map((s) => input.scoreFn(s)))\n\n const perScenario = input.originals.map((s, i) => ({\n scenarioId: input.scenarioId(s),\n originalScore: origScores[i]!,\n perturbedScore: pertScores[i]!,\n delta: pertScores[i]! - origScores[i]!,\n qValue: NaN,\n }))\n\n // Drop scenarios below the floor (partial failures we don't trust).\n const valid = perScenario.filter((p) => p.originalScore >= floor && p.perturbedScore >= floor)\n if (valid.length < 4) {\n return {\n perScenario,\n pairedTest: { w: 0, p: 1 },\n medianDelta: 0,\n meanDelta: 0,\n contaminationSuspected: false,\n reason: `insufficient valid scenarios (n=${valid.length}, need ≥ 4)`,\n n: valid.length,\n }\n }\n\n const origValid = valid.map((p) => p.originalScore)\n const pertValid = valid.map((p) => p.perturbedScore)\n const pairedTest = wilcoxonSignedRank(origValid, pertValid)\n const deltas = valid.map((p) => p.delta)\n const sortedDeltas = [...deltas].sort((a, b) => a - b)\n const median = sortedDeltas[Math.floor(sortedDeltas.length / 2)]!\n const mean = deltas.reduce((s, d) => s + d, 0) / deltas.length\n\n // Per-scenario q-values via BH on a synthetic per-scenario p-value\n // (one-sample bootstrap; we use the absolute delta normalized by median\n // as a coarse signal — this is a display aid, the load-bearing test\n // is the global Wilcoxon).\n const pseudoP = valid.map((p) => Math.min(1, Math.max(1e-6, 1 - Math.abs(p.delta) / 1)))\n const { qValues } = benjaminiHochberg(pseudoP, fdr)\n for (let i = 0; i < valid.length; i++) {\n const v = valid[i]!\n const idx = perScenario.findIndex((p) => p.scenarioId === v.scenarioId)\n if (idx >= 0) perScenario[idx]!.qValue = qValues[i]!\n }\n\n const contaminationSuspected = pairedTest.p < fdr && median <= -minMedianDrop\n const reason = contaminationSuspected\n ? `paired p=${pairedTest.p.toFixed(4)} < ${fdr} and median drop ${median.toFixed(4)} ≥ ${minMedianDrop}`\n : pairedTest.p >= fdr\n ? `no significant difference (paired p=${pairedTest.p.toFixed(4)})`\n : `significant but small effect (median delta ${median.toFixed(4)})`\n\n return {\n perScenario,\n pairedTest,\n medianDelta: median,\n meanDelta: mean,\n contaminationSuspected,\n reason,\n n: valid.length,\n }\n}\n\n// ── Stock perturbations ──────────────────────────────────────────────────\n\n/**\n * Identifier-rename perturbation for code/text scenarios. Replaces every\n * occurrence of the listed identifiers with synthesized aliases. Use when\n * the scenario's structural difficulty is independent of variable names\n * (e.g. SWE-Bench-style coding tasks).\n */\nexport function renameVariables<S extends { prompt: string }>(\n identifiers: string[],\n rename: (name: string, idx: number) => string = (n, i) => `${n}_${((i % 26) + 10).toString(36)}`,\n): ScenarioPerturbation<S> {\n return {\n kind: 'rename_variables',\n apply(scenario) {\n let prompt = scenario.prompt\n identifiers.forEach((id, i) => {\n const replacement = rename(id, i)\n const re = new RegExp(`\\\\b${escapeRegex(id)}\\\\b`, 'g')\n prompt = prompt.replace(re, replacement)\n })\n return { ...scenario, prompt }\n },\n }\n}\n\n/**\n * Order-shuffle perturbation. Reshuffles a list-shaped section of the\n * prompt (for QA scenarios that present options A/B/C/D — answer depends\n * on the option labels, not order). Caller provides the section extractor.\n */\nexport function shuffleOrder<S extends { prompt: string }>(\n shuffleSection: (prompt: string, rng: () => number) => string,\n seed: number,\n): ScenarioPerturbation<S> {\n let s = seed >>> 0\n const rng = (): number => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n return {\n kind: 'shuffle_order',\n apply(scenario) {\n const newPrompt = shuffleSection(scenario.prompt, rng)\n return { ...scenario, prompt: newPrompt }\n },\n }\n}\n\n/**\n * Inject-irrelevant-clause perturbation. Adds a benign sentence that\n * shouldn't change the answer. Tests for \"did the model just memorize\n * the input string.\"\n */\nexport function injectIrrelevantClause<S extends { prompt: string }>(\n clause: string,\n position: 'prefix' | 'suffix' = 'prefix',\n): ScenarioPerturbation<S> {\n return {\n kind: 'inject_irrelevant_clause',\n apply(scenario) {\n const prompt =\n position === 'prefix' ? `${clause} ${scenario.prompt}` : `${scenario.prompt} ${clause}`\n return { ...scenario, prompt }\n },\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","/**\n * Off-policy evaluation primitives.\n *\n * Standard inverse-probability-weighted (IPS), self-normalized\n * importance-weighted (SNIPS), and doubly-robust (DR) estimators for the\n * value of a *target* policy given trajectories collected under a\n * *behavior* policy. This is the canonical RL eval task: \"we have last\n * week's runs, we changed the policy — how would the new one do without\n * re-running?\"\n *\n * The math here is textbook (Dudík, Langford, Li 2011 for DR; Swaminathan\n * & Joachims 2015 for SNIPS) but the *application* to LLM-agent\n * evaluation needs care:\n *\n * - The \"policy\" is the (prompt, tool config, model snapshot) triple.\n * Two policies have the same probability over an action *iff* their\n * LLM call would emit the same token with the same probability —\n * which is generally unknowable without the model log-probs.\n * - For LLM agents, propensity scores must be supplied by the caller\n * (logged in the trace, recovered from token log-probs, or estimated\n * via a learned propensity model). We do NOT estimate propensity here.\n * - Doubly-robust requires a Q-function (model-based reward predictor).\n * We accept any callable; consumers pass either a tabular average,\n * a regression fit, or a learned reward model.\n *\n * Bias / variance tradeoffs:\n * - IPS: unbiased; high variance for small overlap, infinite variance\n * when target has support outside behavior.\n * - SNIPS: lower variance, slight bias; usually preferred in practice.\n * - DR: doubly-robust — unbiased if either propensity OR Q-function is\n * correct. Lowest practical variance when Q is decent. Use this.\n *\n * Caveat the panel will land: on the LLM-agent setting, propensity scores\n * recovered from token log-probs are noisy, the action space is enormous,\n * and overlap is often poor. These estimators are useful but not magic;\n * complement with `replayCampaign` (exact replay where the request hashes\n * match) for high-confidence answers and OPE for the gap.\n */\n\nimport { ValidationError } from '../errors'\n\nexport interface OffPolicyTrajectory {\n /** Stable id, for traceability through the dataset. */\n runId: string\n /** Reward observed under the behavior policy (the realized outcome). */\n reward: number\n /**\n * Behavior-policy probability of the action that was taken. For LLM\n * agents this is typically `exp(sum(token_log_probs))` over the chosen\n * trajectory. Must be in (0, 1].\n */\n behaviorProb: number\n /**\n * Target-policy probability of the same action. For replay-style\n * counterfactual evaluation this is what the *new* policy would have\n * assigned to the *old* trajectory. Must be in [0, 1].\n */\n targetProb: number\n /**\n * Optional model-based reward prediction at the same context. Used by\n * `doublyRobust`. Set to `null` for IPS-only evaluation.\n */\n qHat?: number | null\n}\n\nexport interface OffPolicyEstimate {\n /** Estimated value of the target policy. */\n value: number\n /** Standard error of the estimate. */\n standardError: number\n /** Effective sample size (Kong 1992). Lower = more reliance on a few high-weight samples. */\n effectiveSampleSize: number\n /** Number of trajectories used. */\n n: number\n /**\n * Diagnostic: maximum importance weight observed. Large values (>>10x\n * mean) are a red flag — variance is dominated by a few outliers.\n */\n maxImportanceWeight: number\n}\n\nexport interface OffPolicyOptions {\n /**\n * Cap importance weights at this value (Ionides 2008 truncated IS) to\n * trade unbiasedness for variance reduction. Default `Infinity` (no cap).\n * Set e.g. `10` for stable estimates when the policies are close.\n */\n weightCap?: number\n /** Reward clipping range. Default `[0, 1]`. */\n rewardClip?: { low: number; high: number }\n}\n\n/**\n * Inverse Probability Weighting (Horvitz-Thompson). Unbiased estimator\n * of E[reward under target policy]. Variance scales with the spread of\n * target/behavior ratios.\n */\nexport function inverseProbabilityWeighting(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n\n if (trajectories.length === 0) {\n return zeroEstimate()\n }\n\n const weights: number[] = []\n const weightedRewards: number[] = []\n let maxW = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(\n `inverseProbabilityWeighting: behaviorProb must be > 0 (runId=${t.runId})`,\n )\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n const r = clamp(t.reward, clip.low, clip.high)\n weights.push(w)\n weightedRewards.push(w * r)\n if (w > maxW) maxW = w\n }\n const n = weights.length\n const value = weightedRewards.reduce((s, x) => s + x, 0) / n\n const variance = weightedRewards.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1)\n const sumW = weights.reduce((s, w) => s + w, 0)\n const sumW2 = weights.reduce((s, w) => s + w * w, 0)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n\n return {\n value,\n standardError: Math.sqrt(variance / n),\n effectiveSampleSize: effN,\n n,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Self-Normalized Importance Sampling. Lower variance than vanilla IPS at\n * the cost of small bias (vanishing as N grows). The right default for\n * LLM-agent evaluation where overlap is often poor.\n */\nexport function selfNormalizedImportanceWeighting(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n if (trajectories.length === 0) return zeroEstimate()\n\n const weights: number[] = []\n const rewards: number[] = []\n let maxW = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(\n `selfNormalizedImportanceWeighting: behaviorProb must be > 0 (runId=${t.runId})`,\n )\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n weights.push(w)\n rewards.push(clamp(t.reward, clip.low, clip.high))\n if (w > maxW) maxW = w\n }\n const sumW = weights.reduce((s, w) => s + w, 0)\n const sumWR = weights.reduce((s, w, i) => s + w * rewards[i]!, 0)\n const value = sumW === 0 ? 0 : sumWR / sumW\n const sumW2 = weights.reduce((s, w) => s + w * w, 0)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n // Influence-function-based SE for SNIPS (Owen 2013, Ch. 9).\n const phi = weights.map((w, i) => w * (rewards[i]! - value))\n const variance = phi.reduce((s, x) => s + x * x, 0) / Math.max(1, sumW * sumW)\n return {\n value,\n standardError: Math.sqrt(variance),\n effectiveSampleSize: effN,\n n: trajectories.length,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Doubly-robust off-policy estimator (Dudík, Langford, Li 2011).\n *\n * V_DR = (1/N) * sum_i [ q_hat_i + (target_prob_i / behavior_prob_i) * (r_i - q_hat_i) ]\n *\n * Unbiased if EITHER:\n * - the importance ratios are correct (IPS-style validity), OR\n * - the Q-hat function is correct (model-based validity).\n *\n * In practice both are imperfect, but the residual bias is the *product*\n * of both errors — much smaller than either alone. This is why DR is the\n * default in production OPE pipelines.\n *\n * Requires `qHat` on every trajectory. If any are `null`, the estimator\n * falls back to SNIPS for those entries (loud-fallback behavior; the\n * report's `n` reflects the full set but `effectiveSampleSize` accounts\n * for the lost variance reduction).\n */\nexport function doublyRobust(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n if (trajectories.length === 0) return zeroEstimate()\n\n const contributions: number[] = []\n let maxW = 0\n let sumW = 0\n let sumW2 = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(`doublyRobust: behaviorProb must be > 0 (runId=${t.runId})`)\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n const r = clamp(t.reward, clip.low, clip.high)\n const q =\n typeof t.qHat === 'number' && Number.isFinite(t.qHat)\n ? clamp(t.qHat, clip.low, clip.high)\n : null\n if (q === null) {\n contributions.push(w * r) // fallback: IPS for this entry\n } else {\n contributions.push(q + w * (r - q))\n }\n if (w > maxW) maxW = w\n sumW += w\n sumW2 += w * w\n }\n const n = contributions.length\n const value = contributions.reduce((s, x) => s + x, 0) / n\n const variance = contributions.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n return {\n value,\n standardError: Math.sqrt(variance / n),\n effectiveSampleSize: effN,\n n,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Convenience: run all three estimators and return them side-by-side.\n * The recommended diagnostic — agreement across estimators is a much\n * stronger signal than any single one.\n */\nexport function offPolicyEstimateAll(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): { ips: OffPolicyEstimate; snips: OffPolicyEstimate; dr: OffPolicyEstimate } {\n return {\n ips: inverseProbabilityWeighting(trajectories, opts),\n snips: selfNormalizedImportanceWeighting(trajectories, opts),\n dr: doublyRobust(trajectories, opts),\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction zeroEstimate(): OffPolicyEstimate {\n return { value: 0, standardError: 0, effectiveSampleSize: 0, n: 0, maxImportanceWeight: 0 }\n}\n\nfunction clamp(x: number, lo: number, hi: number): number {\n if (!Number.isFinite(x)) return lo\n return Math.max(lo, Math.min(hi, x))\n}\n","/**\n * Preference dataset extraction — bridge from `RunRecord[]` to RL training.\n *\n * Production RLHF / DPO / KTO / SimPO pipelines need preference triples:\n * `(prompt, chosen, rejected)`. The campaign artifact already contains the\n * ingredients — every (variantId, scenarioId, seed) cell is a candidate\n * that ran the same prompt against the same scenario, scored by the same\n * judge — but turning that into a clean preference dataset requires\n * deciding *what counts as a preference*.\n *\n * This module ships three preference-extraction strategies with explicit\n * tradeoffs, plus a unified output type compatible with HuggingFace TRL,\n * Anthropic finetuning JSONL, and OpenAI fine-tuning APIs. The strategies\n * are deliberately not auto-magical — picking the wrong one corrupts the\n * gradient.\n *\n * Strategies:\n *\n * 1. **`paired-by-scenario-and-seed`** — exact-match comparisons. For\n * each scenario × seed pair, compare every (variantA, variantB) on\n * that exact (scenario, seed). Matches scenarios so the comparison\n * isolates variant effects. Highest signal-to-noise; smallest\n * dataset (only matched pairs count).\n *\n * 2. **`paired-by-scenario`** — looser matching. For each scenario,\n * compare every (variantA, variantB) where both have ≥ 1 run on the\n * same scenario. Aggregates across seeds to compute mean scores per\n * (variant, scenario), then forms preferences from the means. More\n * data, lower per-pair signal.\n *\n * 3. **`top-vs-bottom`** — coarsest. Within each scenario, the highest-\n * scoring run is `chosen`, the lowest is `rejected`. Smallest dataset\n * per scenario but biggest score gap per pair. Useful for early\n * bootstrapping when you have few variants.\n *\n * The output `PreferenceTriple` is *agent-eval-canonical* but trivially\n * mappable to TRL's `DPODataset` shape (`prompt`, `chosen`, `rejected`)\n * via the `toTRLFormat` helper.\n */\n\nimport type { RunRecord } from '../run-record'\n\nexport type PreferenceStrategy =\n | 'paired-by-scenario-and-seed'\n | 'paired-by-scenario'\n | 'top-vs-bottom'\n\nexport interface PreferenceTriple {\n /** The scenario (input) the variants were run against. */\n scenarioId: string\n /** RunRecord ids on each side, for traceability. */\n chosenRunId: string\n rejectedRunId: string\n /** Variant ids — load-bearing for the RL update. */\n chosenVariantId: string\n rejectedVariantId: string\n /** The score gap between chosen and rejected. Larger = stronger signal. */\n marginScore: number\n /**\n * Optional `(chosen_score, rejected_score)` pair for soft-margin DPO\n * variants. Omitted for `top-vs-bottom` runs that don't carry meaningful\n * scalar gaps.\n */\n scores?: { chosen: number; rejected: number }\n /** Tie-breaker — when multiple seeds match this scenario, the one used. */\n seed?: number\n /**\n * Free-form metadata propagated from the run records — e.g. original\n * prompt-hash, model, etc. Lets the RL trainer reconstruct the prompt.\n */\n meta: {\n chosenPromptHash: string\n rejectedPromptHash: string\n chosenConfigHash: string\n rejectedConfigHash: string\n chosenModel: string\n rejectedModel: string\n }\n}\n\nexport interface ExtractPreferencesOptions {\n strategy?: PreferenceStrategy\n /**\n * Minimum score gap required to admit a pair. Pairs below this are\n * dropped — they're noise, not signal. Default 0.05 (5% of [0,1]).\n */\n minMargin?: number\n /**\n * Optional split tag filter — restrict to runs from one split. Default\n * `'holdout'` (the canonical \"real\" signal).\n */\n splitTag?: RunRecord['splitTag']\n /**\n * Optional reward extractor that overrides `outcome.holdoutScore` /\n * `outcome.searchScore`. Use to drive preferences off a verifiable\n * reward instead of the headline score.\n */\n rewardOf?: (run: RunRecord) => number | null\n}\n\nexport interface PreferenceExtractionReport {\n pairs: PreferenceTriple[]\n /** Number of (scenario, seed) cells inspected. */\n cellsInspected: number\n /** Number of pairs filtered by `minMargin`. */\n pairsBelowMargin: number\n /** Number of cells with only one variant (no comparison possible). */\n cellsSingleton: number\n /** Strategy used. */\n strategy: PreferenceStrategy\n}\n\nconst SPLIT_TAG_DEFAULT: RunRecord['splitTag'] = 'holdout'\n\nconst DEFAULT_REWARD = (run: RunRecord): number | null => {\n const v = run.outcome.holdoutScore ?? run.outcome.searchScore\n return typeof v === 'number' && Number.isFinite(v) ? v : null\n}\n\n/**\n * Convert `RunRecord[]` to preference triples for RL training.\n *\n * Returns a structured report so callers can see how much data was\n * dropped and why (low-margin pairs, singleton cells). For production\n * pipelines, you usually want to:\n *\n * 1. Run a campaign producing 5–10 variants × 50–200 scenarios × 3 seeds\n * 2. Call this with `strategy: 'paired-by-scenario-and-seed'` and a\n * verifiable-reward extractor as `rewardOf`\n * 3. Pass `report.pairs` to `toTRLFormat` and pipe to your DPO trainer\n */\nexport function extractPreferences(\n runs: RunRecord[],\n opts: ExtractPreferencesOptions = {},\n): PreferenceExtractionReport {\n const strategy = opts.strategy ?? 'paired-by-scenario-and-seed'\n const minMargin = opts.minMargin ?? 0.05\n const splitTag = opts.splitTag ?? SPLIT_TAG_DEFAULT\n const rewardOf = opts.rewardOf ?? DEFAULT_REWARD\n\n const filtered = runs.filter((r) => r.splitTag === splitTag)\n const scoredEntries: Array<{ run: RunRecord; score: number }> = []\n for (const run of filtered) {\n const s = rewardOf(run)\n if (s === null) continue\n scoredEntries.push({ run, score: s })\n }\n\n const pairs: PreferenceTriple[] = []\n let pairsBelowMargin = 0\n let cellsSingleton = 0\n let cellsInspected = 0\n\n if (strategy === 'paired-by-scenario-and-seed') {\n // Group by (scenarioId, seed). Canonical key is `run.scenarioId`,\n // populated by `runEvalCampaign` and the adapters; falls back to\n // `outcome.raw.scenario_id` then `experimentId` when absent.\n const groups = new Map<string, Array<{ run: RunRecord; score: number }>>()\n for (const e of scoredEntries) {\n const sid = scenarioOf(e.run)\n const key = `${sid}::${e.run.seed}`\n const arr = groups.get(key) ?? []\n arr.push(e)\n groups.set(key, arr)\n }\n\n for (const [key, members] of groups.entries()) {\n cellsInspected++\n if (members.length < 2) {\n cellsSingleton++\n continue\n }\n for (let i = 0; i < members.length; i++) {\n for (let j = i + 1; j < members.length; j++) {\n const a = members[i]!\n const b = members[j]!\n if (a.run.candidateId === b.run.candidateId) continue\n const result = makePair(a, b, key.split('::')[0]!, minMargin)\n if (result.kind === 'admit') pairs.push(result.pair)\n else pairsBelowMargin++\n }\n }\n }\n } else if (strategy === 'paired-by-scenario') {\n // Group by scenarioId → average per (variantId, scenarioId) across seeds.\n const byScenarioVariant = new Map<\n string,\n Map<string, { run: RunRecord; sum: number; n: number }>\n >()\n for (const e of scoredEntries) {\n const sid = scenarioOf(e.run)\n let perScenario = byScenarioVariant.get(sid)\n if (!perScenario) {\n perScenario = new Map()\n byScenarioVariant.set(sid, perScenario)\n }\n const cur = perScenario.get(e.run.candidateId)\n if (cur) {\n cur.sum += e.score\n cur.n++\n } else perScenario.set(e.run.candidateId, { run: e.run, sum: e.score, n: 1 })\n }\n for (const [sid, perVariant] of byScenarioVariant.entries()) {\n cellsInspected++\n const arr = [...perVariant.entries()].map(([vid, agg]) => ({\n run: agg.run,\n score: agg.sum / agg.n,\n variantId: vid,\n }))\n if (arr.length < 2) {\n cellsSingleton++\n continue\n }\n for (let i = 0; i < arr.length; i++) {\n for (let j = i + 1; j < arr.length; j++) {\n const result = makePair(arr[i]!, arr[j]!, sid, minMargin)\n if (result.kind === 'admit') pairs.push(result.pair)\n else pairsBelowMargin++\n }\n }\n }\n } else {\n // top-vs-bottom: per scenario, top vs bottom only.\n const byScenario = new Map<string, Array<{ run: RunRecord; score: number }>>()\n for (const e of scoredEntries) {\n const sid = scenarioOf(e.run)\n const arr = byScenario.get(sid) ?? []\n arr.push(e)\n byScenario.set(sid, arr)\n }\n for (const [sid, arr] of byScenario.entries()) {\n cellsInspected++\n if (arr.length < 2) {\n cellsSingleton++\n continue\n }\n const sorted = [...arr].sort((a, b) => a.score - b.score)\n const top = sorted[sorted.length - 1]!\n const bot = sorted[0]!\n if (top.run.candidateId === bot.run.candidateId) {\n cellsSingleton++\n continue\n }\n const result = makePair(bot, top, sid, minMargin)\n if (result.kind === 'admit') pairs.push(result.pair)\n else pairsBelowMargin++\n }\n }\n\n return { pairs, cellsInspected, pairsBelowMargin, cellsSingleton, strategy }\n}\n\n/**\n * TRL-compatible export. TRL's `DPODataset` is `{ prompt, chosen, rejected }`\n * but the prompt isn't stored on the RunRecord — only its hash. The caller\n * passes a `promptOf(promptHash)` lookup that the TRL trainer can use.\n */\nexport function toTRLFormat(\n triples: PreferenceTriple[],\n promptOf: (hash: string) => string,\n): Array<{ prompt: string; chosen: string; rejected: string }> {\n return triples.map((t) => ({\n prompt: promptOf(t.meta.chosenPromptHash),\n chosen: t.meta.chosenPromptHash, // caller substitutes the model output via the runId map\n rejected: t.meta.rejectedPromptHash,\n }))\n}\n\n/**\n * Anthropic finetuning JSONL export — `{ system, user, assistant_chosen, assistant_rejected }`\n * shape. Same caveat as TRL: prompt + outputs are content the caller has\n * to map back from the run record / raw event log.\n */\nexport function toAnthropicFormat(\n triples: PreferenceTriple[],\n): Array<{ scenarioId: string; chosenRunId: string; rejectedRunId: string; margin: number }> {\n return triples.map((t) => ({\n scenarioId: t.scenarioId,\n chosenRunId: t.chosenRunId,\n rejectedRunId: t.rejectedRunId,\n margin: t.marginScore,\n }))\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction makePair(\n a: { run: RunRecord; score: number },\n b: { run: RunRecord; score: number },\n scenarioId: string,\n minMargin: number,\n): { kind: 'admit'; pair: PreferenceTriple } | { kind: 'reject' } {\n const margin = Math.abs(a.score - b.score)\n if (margin < minMargin) return { kind: 'reject' }\n const [chosen, rejected] = a.score > b.score ? [a, b] : [b, a]\n return {\n kind: 'admit',\n pair: {\n scenarioId,\n chosenRunId: chosen.run.runId,\n rejectedRunId: rejected.run.runId,\n chosenVariantId: chosen.run.candidateId,\n rejectedVariantId: rejected.run.candidateId,\n marginScore: chosen.score - rejected.score,\n scores: { chosen: chosen.score, rejected: rejected.score },\n seed: chosen.run.seed === rejected.run.seed ? chosen.run.seed : undefined,\n meta: {\n chosenPromptHash: chosen.run.promptHash,\n rejectedPromptHash: rejected.run.promptHash,\n chosenConfigHash: chosen.run.configHash,\n rejectedConfigHash: rejected.run.configHash,\n chosenModel: chosen.run.model,\n rejectedModel: rejected.run.model,\n },\n },\n }\n}\n\n/**\n * Canonical scenario key for a RunRecord. Three-tier fallback:\n * 1. `run.scenarioId` — populated by `runEvalCampaign` and every adapter\n * 2. `run.outcome.raw.scenario_id` — string or numeric, when present\n * 3. `run.experimentId` — worst-case bucket\n */\nfunction scenarioOf(run: RunRecord): string {\n if (typeof run.scenarioId === 'string' && run.scenarioId.length > 0) return run.scenarioId\n const fromRaw = run.outcome.raw.scenario_id\n if (typeof fromRaw === 'number' && Number.isFinite(fromRaw)) return String(fromRaw)\n if (typeof fromRaw === 'string') return fromRaw\n return run.experimentId\n}\n","/**\n * Adapters: convert measurement outputs into the canonical `RunRecord[]`\n * artifact that `replayCache`, `pairedEvalueSequence`, and\n * `rubricPredictiveValidity` consume. Two sources:\n * - `campaignToRunRecords` — the campaign substrate's per-cell results\n * (the modern path: `runCampaign` / `runImprovementLoop` → records).\n * - `verificationReportToRunRecord` — a `MultiLayerVerifier` report.\n *\n * Adapters are thin and explicit — every mandatory `RunRecord` field comes\n * from a caller-supplied context (`commitSha`, `model`, `promptHash`,\n * `configHash`) plus the cell's runtime data. The validator still rejects\n * bare-alias model strings — the caller snapshot-pins.\n */\n\nimport type { CampaignResult } from '../campaign'\nimport type { LayerResult, VerificationReport } from '../multi-layer-verifier'\nimport type { RunRecord, RunSplitTag } from '../run-record'\n\nexport interface AdapterContext {\n /** Logical experiment id — typically the campaign or sweep identifier. */\n experimentId: string\n /** Snapshot model id (e.g. `claude-sonnet-4-6@2025-04-15`). */\n model: string\n /** Git SHA the harness was run from. */\n commitSha: string\n /** Hash of the effective prompt sent to the model. */\n promptHash: string\n /** Hash of the effective config (model, temperature, tools, judges, splits). */\n configHash: string\n /** Default split tag. Default `'search'`. */\n splitTag?: RunSplitTag\n /** Default cost in USD when the source doesn't record one. Default `0`. */\n defaultCostUsd?: number\n}\n\n/**\n * Convert a `CampaignResult` into canonical `RunRecord[]` — one record per\n * scored cell. The cell's mean judge composite becomes the split score; every\n * judge dimension is carried through to `outcome.raw`. A cell that errored\n * becomes a record with `failureMode: 'cell_error'` (kept, not dropped — an\n * unscored cell is signal). `candidateId` identifies the measured surface\n * (defaults to the campaign manifest hash).\n */\nexport function campaignToRunRecords(\n campaign: CampaignResult,\n ctx: AdapterContext & { candidateId?: string },\n): RunRecord[] {\n const splitTag = ctx.splitTag ?? 'search'\n const candidateId = ctx.candidateId ?? campaign.manifestHash\n return campaign.cells.map((cell) => {\n const composites = Object.values(cell.judgeScores).map((s) => s.composite)\n const score =\n composites.length > 0 ? composites.reduce((a, b) => a + b, 0) / composites.length : 0\n const raw: Record<string, number> = { rep: cell.rep, duration_ms: cell.durationMs }\n for (const judge of Object.values(cell.judgeScores)) {\n for (const [dim, value] of Object.entries(judge.dimensions)) {\n if (Number.isFinite(value)) raw[`dim.${dim}`] = value\n }\n }\n if (typeof cell.generation === 'number') raw.generation = cell.generation\n const outcome: RunRecord['outcome'] = { raw }\n if (splitTag === 'holdout') outcome.holdoutScore = score\n else outcome.searchScore = score\n return {\n runId: cell.cellId,\n experimentId: ctx.experimentId,\n candidateId,\n seed: cell.seed,\n model: ctx.model,\n promptHash: ctx.promptHash,\n configHash: ctx.configHash,\n commitSha: ctx.commitSha,\n wallMs: cell.durationMs,\n costUsd: Number.isFinite(cell.costUsd) ? cell.costUsd : (ctx.defaultCostUsd ?? 0),\n tokenUsage: { input: 0, output: 0 },\n outcome,\n failureMode: cell.error ? 'cell_error' : undefined,\n splitTag,\n scenarioId: cell.scenarioId,\n }\n })\n}\n\n/**\n * Convert a `MultiLayerVerifier` `VerificationReport` into a `RunRecord`.\n * `outcome.searchScore` (or `holdoutScore`) is `report.blendedScore`;\n * `outcome.raw` carries every layer's score + a pass indicator; `failureMode`\n * is the first failing layer's reason.\n */\nexport function verificationReportToRunRecord(\n report: VerificationReport,\n ctx: AdapterContext & { candidateId: string; scenarioId?: string },\n opts: { runId?: string } = {},\n): RunRecord {\n const splitTag = ctx.splitTag ?? 'search'\n const runId = opts.runId ?? `run-${ctx.candidateId}-${ctx.experimentId}-${report.startedAt}`\n\n const raw: Record<string, number> = {\n pass_count: report.passCount,\n fail_count: report.failCount,\n error_count: report.errorCount,\n skipped_count: report.skippedCount,\n duration_ms: report.durationMs,\n blended_score: report.blendedScore,\n }\n for (const layer of report.layers) {\n if (typeof layer.score === 'number') raw[`layer.${layer.layer}`] = layer.score\n raw[`layer_${layer.layer}_pass`] = layer.status === 'pass' ? 1 : 0\n if (layer.diagnostics) {\n for (const [k, v] of Object.entries(layer.diagnostics)) {\n if (typeof v === 'number' && Number.isFinite(v)) raw[`layer.${layer.layer}.${k}`] = v\n }\n }\n }\n\n const firstFail = report.layers.find((l) => l.status === 'fail' || l.status === 'error')\n const outcome: RunRecord['outcome'] = { raw }\n if (splitTag === 'holdout') outcome.holdoutScore = report.blendedScore\n else outcome.searchScore = report.blendedScore\n\n return {\n runId,\n experimentId: ctx.experimentId,\n candidateId: ctx.candidateId,\n seed: 0,\n model: ctx.model,\n promptHash: ctx.promptHash,\n configHash: ctx.configHash,\n commitSha: ctx.commitSha,\n wallMs: report.durationMs,\n costUsd: ctx.defaultCostUsd ?? 0,\n tokenUsage: { input: 0, output: 0 },\n outcome,\n failureMode: firstFail ? failureModeFromLayer(firstFail) : undefined,\n splitTag,\n scenarioId: ctx.scenarioId,\n }\n}\n\nfunction failureModeFromLayer(layer: LayerResult): string {\n if (layer.status === 'error') return `layer_${layer.layer}_error`\n if (layer.status === 'fail') return `layer_${layer.layer}_fail`\n if (layer.status === 'timeout') return `layer_${layer.layer}_timeout`\n return `layer_${layer.layer}_${layer.status}`\n}\n","/**\n * Bradley-Terry / Elo tournament evaluation.\n *\n * For multi-candidate sweeps, comparing every candidate's score against\n * a fixed comparator wastes information — the comparator becomes a high-\n * variance reference and rank flips between near-tied middle-rank\n * candidates are dominated by noise. Pairwise tournaments fix this:\n * every (i, j) pair contributes a comparison to a Bradley-Terry MLE that\n * estimates each candidate's strength on a unified scale.\n *\n * For online updating (rolling campaigns where new candidates arrive\n * over time), we also ship classical Elo with configurable K-factor.\n *\n * References:\n * - Bradley, R. A., Terry, M. E. (1952). Rank analysis of incomplete\n * block designs. Biometrika, 39(3/4), 324–345.\n * - Hunter, D. R. (2004). MM algorithms for generalized Bradley-Terry\n * models. Annals of Statistics, 32(1), 384–406. (The MLE algorithm\n * used here.)\n * - Elo, A. E. (1978). The Rating of Chess Players, Past and Present.\n *\n * This is a useful primitive because most LLM-eval communities (Chatbot\n * Arena, AlpacaEval, ELO-style ablation) have converged on pairwise\n * tournament eval as the most sample-efficient and most rank-stable\n * method when you have many candidates.\n */\n\nexport interface PairwiseOutcome {\n /** Winner candidate id. */\n winner: string\n /** Loser candidate id. */\n loser: string\n /**\n * Optional draw flag. When true, both candidates get half-credit\n * (Bradley-Terry handles draws as half-wins for each side).\n */\n draw?: boolean\n /**\n * Optional weight — useful if some pairwise comparisons are stronger\n * signals than others (e.g. a paired test with a wider score gap is\n * a more confident comparison). Default 1.\n */\n weight?: number\n}\n\nexport interface BradleyTerryRating {\n candidateId: string\n /** Latent strength θ ≥ 0 from the BT MLE. */\n strength: number\n /** Log-strength = log(θ) — interpretable on a linear scale. */\n logStrength: number\n /** Number of pairwise comparisons this candidate appears in. */\n n: number\n /** Win count (+ 0.5 per draw). */\n wins: number\n}\n\nexport interface BradleyTerryFit {\n ratings: BradleyTerryRating[]\n /** Iterations of the MM algorithm before convergence. */\n iterations: number\n /** Final maximum |θ_new - θ_old| / θ_old. */\n finalDelta: number\n converged: boolean\n}\n\n/**\n * Bradley-Terry MLE via Hunter's MM algorithm.\n *\n * Iteration: θ_i^new = W_i / Σ_{j ≠ i} N_ij / (θ_i + θ_j)\n * where W_i = wins by i (+ 0.5 per draw), N_ij = total comparisons.\n *\n * Returns log-strengths normalized so the smallest is 0 (any constant\n * offset is unobservable in BT — only differences are identified).\n */\nexport function fitBradleyTerry(\n outcomes: PairwiseOutcome[],\n opts: { tolerance?: number; maxIterations?: number; smoothing?: number } = {},\n): BradleyTerryFit {\n const tol = opts.tolerance ?? 1e-6\n const maxIter = opts.maxIterations ?? 256\n // Small positive default — Hunter's MM degenerates when a candidate has\n // zero wins (θ → 0 → log → -∞). 0.1 is negligible against real win counts\n // (~1 win / 10 comparisons) and keeps the iteration well-conditioned.\n // Override to 0 if the comparison set is guaranteed strongly connected.\n const smoothing = opts.smoothing ?? 0.1\n\n const candidates = new Set<string>()\n for (const o of outcomes) {\n candidates.add(o.winner)\n candidates.add(o.loser)\n }\n const ids = [...candidates].sort()\n const idx = new Map(ids.map((id, i) => [id, i]))\n const n = ids.length\n if (n === 0) return { ratings: [], iterations: 0, finalDelta: 0, converged: true }\n if (n === 1) {\n return {\n ratings: [{ candidateId: ids[0]!, strength: 1, logStrength: 0, n: 0, wins: 0 }],\n iterations: 0,\n finalDelta: 0,\n converged: true,\n }\n }\n\n // Build win matrix W[i][j] = (weighted) wins of i over j, plus half for draws.\n // Build comparison matrix N[i][j] = total weighted comparisons between i and j.\n const W: number[][] = Array.from({ length: n }, () => new Array<number>(n).fill(0))\n const N: number[][] = Array.from({ length: n }, () => new Array<number>(n).fill(0))\n for (const o of outcomes) {\n const i = idx.get(o.winner)!\n const j = idx.get(o.loser)!\n const w = o.weight ?? 1\n if (o.draw) {\n W[i]![j]! += 0.5 * w\n W[j]![i]! += 0.5 * w\n } else {\n W[i]![j]! += w\n }\n N[i]![j]! += w\n N[j]![i]! += w\n }\n\n // Per-candidate total wins.\n const winsTotal = new Array<number>(n).fill(0)\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) winsTotal[i]! += W[i]![j]!\n winsTotal[i]! += smoothing // tiny smoothing to keep θ positive\n }\n const compsTotal = new Array<number>(n).fill(0)\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) compsTotal[i]! += N[i]![j]!\n }\n\n // MM iterations.\n let theta = new Array<number>(n).fill(1)\n let iter = 0\n let delta = Infinity\n for (; iter < maxIter; iter++) {\n const newTheta = new Array<number>(n)\n for (let i = 0; i < n; i++) {\n let denom = 0\n for (let j = 0; j < n; j++) {\n if (j === i) continue\n if (N[i]![j]! === 0) continue\n denom += N[i]![j]! / (theta[i]! + theta[j]!)\n }\n newTheta[i] = denom === 0 ? theta[i]! : winsTotal[i]! / denom\n }\n // Normalize so geometric mean = 1 (numerical stability).\n let logSum = 0\n for (let i = 0; i < n; i++) logSum += Math.log(Math.max(1e-300, newTheta[i]!))\n const norm = Math.exp(logSum / n)\n for (let i = 0; i < n; i++) newTheta[i] = newTheta[i]! / norm\n\n delta = 0\n for (let i = 0; i < n; i++) {\n const d = Math.abs(newTheta[i]! - theta[i]!) / Math.max(1e-12, theta[i]!)\n if (d > delta) delta = d\n }\n theta = newTheta\n if (delta < tol) break\n }\n\n const minLog = Math.min(...theta.map((t) => Math.log(Math.max(1e-300, t))))\n const ratings: BradleyTerryRating[] = ids.map((id, i) => ({\n candidateId: id,\n strength: theta[i]!,\n logStrength: Math.log(Math.max(1e-300, theta[i]!)) - minLog,\n n: compsTotal[i]!,\n wins: winsTotal[i]! - smoothing,\n }))\n\n return {\n ratings: ratings.sort((a, b) => b.strength - a.strength),\n iterations: iter,\n finalDelta: delta,\n converged: delta < tol,\n }\n}\n\n/**\n * Online Elo updates. Use when comparisons arrive over time and you want\n * a running rating without re-fitting the full BT MLE on every update.\n *\n * Initialize ratings to `defaultRating` (1500 by default). Each call to\n * `applyEloUpdate` mutates the map in place and returns the deltas so\n * the caller can log per-comparison rating changes.\n */\nexport interface EloOptions {\n /** Default rating for unseen candidates. Default 1500. */\n defaultRating?: number\n /** K-factor controls the step size. Default 32 (FIDE-ish). */\n kFactor?: number\n}\n\nexport function applyEloUpdate(\n ratings: Map<string, number>,\n outcome: PairwiseOutcome,\n opts: EloOptions = {},\n): { winnerDelta: number; loserDelta: number } {\n const defaultRating = opts.defaultRating ?? 1500\n const k = opts.kFactor ?? 32\n\n const rW = ratings.get(outcome.winner) ?? defaultRating\n const rL = ratings.get(outcome.loser) ?? defaultRating\n\n const expectedW = 1 / (1 + 10 ** ((rL - rW) / 400))\n const scoreW = outcome.draw ? 0.5 : 1\n const scoreL = outcome.draw ? 0.5 : 0\n const w = outcome.weight ?? 1\n\n const winnerDelta = k * w * (scoreW - expectedW)\n const loserDelta = k * w * (scoreL - (1 - expectedW))\n\n ratings.set(outcome.winner, rW + winnerDelta)\n ratings.set(outcome.loser, rL + loserDelta)\n\n return { winnerDelta, loserDelta }\n}\n\n/**\n * Build pairwise outcomes from the campaign artifact: for every scenario\n * shared by two candidates, the higher-scoring run wins. Useful when you\n * want a tournament view of an existing campaign without an additional\n * pairwise judge call.\n */\nexport interface BuildPairwiseFromCampaignInput {\n runs: Array<{\n candidateId: string\n /** Stable identifier for the matching unit (typically scenarioId). */\n matchKey: string\n score: number\n }>\n /**\n * Tied-score margin. Below this, the comparison is a draw. Default 0\n * (no ties).\n */\n drawMargin?: number\n}\n\nexport function buildPairwiseFromCampaign(\n input: BuildPairwiseFromCampaignInput,\n): PairwiseOutcome[] {\n const drawMargin = input.drawMargin ?? 0\n const byKey = new Map<string, Array<{ candidateId: string; score: number }>>()\n for (const r of input.runs) {\n const arr = byKey.get(r.matchKey) ?? []\n arr.push({ candidateId: r.candidateId, score: r.score })\n byKey.set(r.matchKey, arr)\n }\n const outcomes: PairwiseOutcome[] = []\n for (const arr of byKey.values()) {\n for (let i = 0; i < arr.length; i++) {\n for (let j = i + 1; j < arr.length; j++) {\n const a = arr[i]!\n const b = arr[j]!\n if (a.candidateId === b.candidateId) continue\n const margin = Math.abs(a.score - b.score)\n if (margin <= drawMargin) {\n outcomes.push({ winner: a.candidateId, loser: b.candidateId, draw: true, weight: 1 })\n } else {\n const [winner, loser] = a.score > b.score ? [a, b] : [b, a]\n outcomes.push({ winner: winner.candidateId, loser: loser.candidateId, weight: margin })\n }\n }\n }\n }\n return outcomes\n}\n","/**\n * Adaptive curriculum / active scenario selection.\n *\n * Fixed scenario sets waste sample budget on cells the policy already\n * passes (no information left) and cells the policy never passes (no\n * gradient available either). Active learning over scenarios fixes this\n * by allocating the next sample budget to cells where the policy's\n * outcome is *uncertain* — those carry the most decision-relevant signal.\n *\n * This module ships two complementary strategies:\n *\n * 1. **Variance-based** — score each (variant, scenario) cell by the\n * empirical variance of past observations. Allocate next-round budget\n * proportional to variance. Standard active-learning-by-uncertainty\n * heuristic; works well when the policy is non-deterministic and\n * cells differ in observation noise.\n *\n * 2. **Bandit-based (Thompson sampling)** — model each (variant,\n * scenario) cell as a Beta-Bernoulli arm; sample a posterior; pick\n * cells whose posterior mean is closest to the per-scenario decision\n * threshold. The right primitive when scenarios are\n * \"pass/fail\" rather than continuous, and when promotion gates fire\n * at a known threshold (e.g., 0.5).\n *\n * The output is a *next-round budget allocation* — a list of (variant,\n * scenario, count) triples. The consumer's matrix runner consumes the\n * allocation, runs those cells, feeds the new observations back. Loop.\n *\n * Out of scope (deliberate): scenario *generation* — that's the\n * adversarial primitive's job. This module allocates over an existing\n * scenario pool.\n */\n\nimport type { RunRecord } from '../run-record'\n\nexport interface CellObservation {\n variantId: string\n scenarioId: string\n /** Observed score in [0, 1]. */\n score: number\n /** For Bernoulli arms — derive from the score with a threshold if needed. */\n pass?: boolean\n}\n\nexport interface CurriculumAllocation {\n variantId: string\n scenarioId: string\n /** How many additional reps to run on this cell. */\n count: number\n /** Strategy-specific reason for the allocation. */\n reason: string\n}\n\nexport interface VarianceCurriculumOptions {\n /** Total reps to allocate across all cells. */\n budget: number\n /**\n * Smoothing prior on variance — keeps the allocator from concentrating\n * on a cell with one observation just because its 1-sample variance is\n * 0. Default 0.05.\n */\n variancePrior?: number\n /**\n * Minimum reps per cell — even when the variance estimate is low, give\n * every cell at least this many. Default 1.\n */\n floorPerCell?: number\n}\n\n/**\n * Variance-proportional allocation. For each cell, estimate variance from\n * past observations + a prior, then allocate the budget proportional to\n * (sqrt(variance) + 1/sqrt(n)) — a classical optimal-allocation rule\n * (Neyman 1934) that balances \"explore noisy cells\" with \"explore\n * under-sampled cells.\"\n */\nexport function varianceBasedCurriculum(\n observations: CellObservation[],\n candidateCells: Array<{ variantId: string; scenarioId: string }>,\n opts: VarianceCurriculumOptions,\n): CurriculumAllocation[] {\n const variancePrior = opts.variancePrior ?? 0.05\n const floor = opts.floorPerCell ?? 1\n const budget = opts.budget\n\n const grouped = new Map<string, number[]>()\n for (const o of observations) {\n const k = `${o.variantId}::${o.scenarioId}`\n const arr = grouped.get(k) ?? []\n arr.push(o.score)\n grouped.set(k, arr)\n }\n\n const cellStats = candidateCells.map((c) => {\n const k = `${c.variantId}::${c.scenarioId}`\n const samples = grouped.get(k) ?? []\n const n = samples.length\n const mean = n === 0 ? 0.5 : samples.reduce((s, v) => s + v, 0) / n\n const variance =\n n < 2\n ? variancePrior\n : samples.reduce((s, v) => s + (v - mean) ** 2, 0) / (n - 1) + variancePrior\n // Neyman optimal allocation: weight ∝ √variance; add √(1/n) to break\n // ties toward under-sampled cells.\n const weight = Math.sqrt(variance) + 1 / Math.sqrt(Math.max(1, n))\n return { variantId: c.variantId, scenarioId: c.scenarioId, n, mean, variance, weight }\n })\n\n // Reserve floor*N for the floor; allocate the rest proportional to weight.\n const floorTotal = floor * cellStats.length\n if (floorTotal >= budget) {\n const each = Math.max(1, Math.floor(budget / Math.max(1, cellStats.length)))\n return cellStats.map((c) => ({\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n count: each,\n reason: `floor allocation (budget tight; n=${c.n})`,\n }))\n }\n const remaining = budget - floorTotal\n const totalWeight = cellStats.reduce((s, c) => s + c.weight, 0)\n return cellStats.map((c) => {\n const proportional = totalWeight === 0 ? 0 : Math.round((c.weight / totalWeight) * remaining)\n return {\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n count: floor + proportional,\n reason: `variance ${c.variance.toFixed(3)} (n=${c.n}, mean=${c.mean.toFixed(3)})`,\n }\n })\n}\n\nexport interface ThompsonCurriculumOptions {\n budget: number\n /**\n * The per-scenario decision threshold. Cells whose posterior mean is\n * closest to this get the most budget — that's where the next observation\n * has the highest information value for the gate decision. Default 0.5.\n */\n decisionThreshold?: number\n /** Beta prior parameters. Default α=β=1 (uniform). */\n priorAlpha?: number\n priorBeta?: number\n /** Seed the Thompson sampler. Default unset (Math.random). */\n seed?: number\n}\n\n/**\n * Thompson-sampling-style allocation for pass/fail cells. For each cell:\n *\n * - Maintain Beta(α + passes, β + failures) posterior on pass-rate\n * - Allocation weight ∝ exp(-((sampledMean - threshold) / σ)^2):\n * cells whose sampled posterior straddles the decision boundary get\n * the most weight; cells already clearly above or below get less.\n *\n * This is the right primitive when promotion gates fire at a known\n * threshold and you want to sharpen the posterior near the boundary.\n */\nexport function thompsonCurriculum(\n observations: CellObservation[],\n candidateCells: Array<{ variantId: string; scenarioId: string }>,\n opts: ThompsonCurriculumOptions,\n): CurriculumAllocation[] {\n const threshold = opts.decisionThreshold ?? 0.5\n const alpha0 = opts.priorAlpha ?? 1\n const beta0 = opts.priorBeta ?? 1\n const rng = makeRng(opts.seed)\n\n const grouped = new Map<string, { passes: number; failures: number }>()\n for (const o of observations) {\n const k = `${o.variantId}::${o.scenarioId}`\n const cur = grouped.get(k) ?? { passes: 0, failures: 0 }\n const pass = o.pass ?? o.score >= threshold\n if (pass) cur.passes += 1\n else cur.failures += 1\n grouped.set(k, cur)\n }\n\n const stats = candidateCells.map((c) => {\n const k = `${c.variantId}::${c.scenarioId}`\n const cur = grouped.get(k) ?? { passes: 0, failures: 0 }\n const a = alpha0 + cur.passes\n const b = beta0 + cur.failures\n // Sample a single Beta draw — the Thompson signal.\n const sampled = sampleBeta(a, b, rng)\n const distance = Math.abs(sampled - threshold)\n // Information-near-threshold weight: closer = higher.\n // Use Gaussian-shaped kernel with σ tuned to posterior std.\n const variance = (a * b) / ((a + b) ** 2 * (a + b + 1))\n const sigma = Math.max(0.05, Math.sqrt(variance))\n const weight = Math.exp(-((distance / sigma) ** 2))\n return {\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n n: cur.passes + cur.failures,\n sampled,\n sigma,\n weight,\n a,\n b,\n }\n })\n\n const totalWeight = stats.reduce((s, c) => s + c.weight, 0)\n return stats.map((c) => {\n const proportional = totalWeight === 0 ? 0 : Math.round((c.weight / totalWeight) * opts.budget)\n return {\n variantId: c.variantId,\n scenarioId: c.scenarioId,\n count: Math.max(0, proportional),\n reason: `Beta(${c.a.toFixed(1)},${c.b.toFixed(1)}) sample=${c.sampled.toFixed(3)} (target ${threshold})`,\n }\n })\n}\n\n/** Convenience: extract `CellObservation[]` directly from `RunRecord[]`. */\nexport function observationsFromRunRecords(\n runs: RunRecord[],\n opts: { passThreshold?: number; useHoldout?: boolean } = {},\n): CellObservation[] {\n const threshold = opts.passThreshold ?? 0.5\n const useHoldout = opts.useHoldout ?? true\n const out: CellObservation[] = []\n for (const r of runs) {\n if (!r.scenarioId) continue\n const score = useHoldout\n ? (r.outcome.holdoutScore ?? r.outcome.searchScore)\n : (r.outcome.searchScore ?? r.outcome.holdoutScore)\n if (typeof score !== 'number' || !Number.isFinite(score)) continue\n out.push({\n variantId: r.candidateId,\n scenarioId: r.scenarioId,\n score,\n pass: score >= threshold,\n })\n }\n return out\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction makeRng(seed?: number): () => number {\n if (seed === undefined) return Math.random\n let s = seed >>> 0\n return () => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/**\n * Sample from Beta(α, β) via the Marsaglia–Tsang method using two Gamma\n * variates. Accuracy is good for α, β > 1; we floor the parameters at 1\n * to avoid degenerate cases.\n */\nfunction sampleBeta(alpha: number, beta: number, rng: () => number): number {\n const a = Math.max(1, alpha)\n const b = Math.max(1, beta)\n const x = sampleGamma(a, rng)\n const y = sampleGamma(b, rng)\n return x / (x + y)\n}\n\nfunction sampleGamma(shape: number, rng: () => number): number {\n // Marsaglia–Tsang for shape ≥ 1.\n const d = shape - 1 / 3\n const c = 1 / Math.sqrt(9 * d)\n while (true) {\n let x: number\n let v: number\n do {\n const u1 = rng() || 1e-12\n const u2 = rng() || 1e-12\n // Box-Muller for a normal sample.\n x = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2)\n v = 1 + c * x\n } while (v <= 0)\n v = v * v * v\n const u = rng()\n if (u < 1 - 0.0331 * x ** 4) return d * v\n if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) return d * v\n }\n}\n","/**\n * Sample-efficient adaptation evaluation.\n *\n * For foundation-model-based agents, the load-bearing capability isn't\n * raw end-state performance — it's *how fast the agent reaches that\n * performance from cold start*. The same model with a worse prompt that\n * adapts in 5 demonstrations beats the same model with a better prompt\n * that needs 50. Standard meta-learning eval (Finn et al., MAML, RL² lit)\n * reports an *adaptation curve*: score after k=0, 1, 2, 4, 8, 16, …\n * in-context examples or fine-tune steps.\n *\n * This module ships:\n *\n * 1. `runAdaptationCurve` — given a runner that takes k demonstrations\n * and returns a score, produce the (k, score) curve.\n * 2. `compareAdaptationCurves` — paired comparison across two policies.\n * Returns per-k delta with bootstrap CIs and an \"area-under-curve\"\n * summary statistic.\n * 3. `firstPassK` — for pass/fail evaluation, the minimum k at which\n * the policy reliably passes (≥ pass-rate threshold over reps).\n *\n * Use cases:\n * - Compare two prompt designs that have similar end-state performance\n * but different in-context efficiency.\n * - Decide between fine-tuning and prompting based on adaptation cost.\n * - Detect when a policy \"memorizes\" k=0 inputs vs. genuinely adapts.\n */\n\nexport interface AdaptationRunner<S> {\n /**\n * Runs the policy on `scenario` with `k` demonstrations. Returns a\n * scalar score in [0, 1]. The runner is responsible for any caching;\n * the harness calls it once per (scenario, k, rep) cell.\n */\n run(args: { scenario: S; k: number; rep: number }): Promise<number>\n}\n\nexport interface RunAdaptationCurveOptions<S> {\n scenarios: S[]\n /** Number-of-shots to evaluate at. Default `[0, 1, 2, 4, 8, 16]`. */\n ks?: number[]\n /** Reps per (scenario, k) cell. Default 3. */\n reps?: number\n runner: AdaptationRunner<S>\n /** Pass-rate threshold for `firstPassK` reporting. Default 0.5. */\n passThreshold?: number\n}\n\nexport interface AdaptationPoint {\n k: number\n meanScore: number\n passRate: number\n std: number\n n: number\n /** Per-scenario means at this k. */\n perScenario: Array<{ scenarioId: string; meanScore: number; passes: number; total: number }>\n}\n\nexport interface AdaptationCurve {\n points: AdaptationPoint[]\n /**\n * Smallest `k` at which `passRate ≥ passThreshold`. `null` if no `k`\n * tested reaches it.\n */\n firstPassK: number | null\n /**\n * Area under the (k, meanScore) curve, normalized by max-k. A\n * single-number summary of \"how well does this policy adapt from\n * cold-start to fully-conditioned.\" Higher = better adapter.\n */\n adaptationArea: number\n}\n\nexport async function runAdaptationCurve<S extends { scenarioId?: string }>(\n opts: RunAdaptationCurveOptions<S>,\n): Promise<AdaptationCurve> {\n const ks = opts.ks ?? [0, 1, 2, 4, 8, 16]\n const reps = opts.reps ?? 3\n const passThreshold = opts.passThreshold ?? 0.5\n const sortedKs = [...ks].sort((a, b) => a - b)\n\n const points: AdaptationPoint[] = []\n for (const k of sortedKs) {\n const perScenario: AdaptationPoint['perScenario'] = []\n const allScores: number[] = []\n let totalPasses = 0\n let totalAttempts = 0\n for (const scenario of opts.scenarios) {\n const sid = scenario.scenarioId ?? `scenario-${opts.scenarios.indexOf(scenario)}`\n const scores: number[] = []\n let passes = 0\n for (let r = 0; r < reps; r++) {\n const score = await opts.runner.run({ scenario, k, rep: r })\n scores.push(score)\n if (score >= passThreshold) passes++\n allScores.push(score)\n if (score >= passThreshold) totalPasses++\n totalAttempts++\n }\n const meanS = scores.reduce((s, v) => s + v, 0) / scores.length\n perScenario.push({ scenarioId: sid, meanScore: meanS, passes, total: scores.length })\n }\n const meanScore = allScores.reduce((s, v) => s + v, 0) / Math.max(1, allScores.length)\n const variance =\n allScores.length < 2\n ? 0\n : allScores.reduce((s, v) => s + (v - meanScore) ** 2, 0) / (allScores.length - 1)\n points.push({\n k,\n meanScore,\n passRate: totalPasses / Math.max(1, totalAttempts),\n std: Math.sqrt(variance),\n n: allScores.length,\n perScenario,\n })\n }\n\n const firstPassK = points.find((p) => p.passRate >= passThreshold)?.k ?? null\n const maxK = sortedKs[sortedKs.length - 1] ?? 1\n // Trapezoidal area under the (k, meanScore) curve, normalized by k-range.\n let area = 0\n for (let i = 1; i < points.length; i++) {\n const x1 = points[i - 1]!.k\n const x2 = points[i]!.k\n const y1 = points[i - 1]!.meanScore\n const y2 = points[i]!.meanScore\n area += ((y1 + y2) / 2) * (x2 - x1)\n }\n const adaptationArea = maxK === 0 ? 0 : area / maxK\n\n return { points, firstPassK, adaptationArea }\n}\n\nexport interface CompareCurvesResult {\n perK: Array<{\n k: number\n deltaMean: number\n aLow: number\n aHigh: number\n bLow: number\n bHigh: number\n }>\n areaDelta: number\n firstPassKDelta: number | null\n /** Verdict: 'a_better' | 'b_better' | 'similar'. */\n verdict: 'a_better' | 'b_better' | 'similar'\n /** Rationale, ready to render. */\n rationale: string\n}\n\n/**\n * Paired comparison of two adaptation curves. Per-k deltas with 95%\n * bootstrap CIs (constructed from each curve's `perScenario` per-k means\n * — the bootstrap unit is the scenario, not the rep).\n */\nexport function compareAdaptationCurves(\n a: AdaptationCurve,\n b: AdaptationCurve,\n opts: { confidence?: number; bootstrapResamples?: number; seed?: number } = {},\n): CompareCurvesResult {\n const conf = opts.confidence ?? 0.95\n const resamples = opts.bootstrapResamples ?? 500\n const rng = makeRng(opts.seed)\n\n const perK: CompareCurvesResult['perK'] = []\n for (const ap of a.points) {\n const bp = b.points.find((p) => p.k === ap.k)\n if (!bp) continue\n const aMeans = ap.perScenario.map((s) => s.meanScore)\n const bMeans = bp.perScenario.map((s) => s.meanScore)\n const aCi = bootstrapMeanCi(aMeans, resamples, conf, rng)\n const bCi = bootstrapMeanCi(bMeans, resamples, conf, rng)\n perK.push({\n k: ap.k,\n deltaMean: ap.meanScore - bp.meanScore,\n aLow: aCi.low,\n aHigh: aCi.high,\n bLow: bCi.low,\n bHigh: bCi.high,\n })\n }\n\n const areaDelta = a.adaptationArea - b.adaptationArea\n const firstPassKDelta =\n a.firstPassK !== null && b.firstPassK !== null\n ? b.firstPassK - a.firstPassK // smaller k for a means a adapts faster (positive delta)\n : null\n\n // Composite verdict: positive area delta + most per-k deltas in same\n // direction → that side wins. Within ε of zero on both → similar.\n const meanDelta = perK.reduce((s, p) => s + p.deltaMean, 0) / Math.max(1, perK.length)\n let verdict: CompareCurvesResult['verdict']\n if (Math.abs(meanDelta) < 0.02 && Math.abs(areaDelta) < 0.02) verdict = 'similar'\n else if (meanDelta > 0 && areaDelta > 0) verdict = 'a_better'\n else if (meanDelta < 0 && areaDelta < 0) verdict = 'b_better'\n else verdict = 'similar'\n\n const rationale =\n `mean per-k delta=${meanDelta.toFixed(3)}, area delta=${areaDelta.toFixed(3)}` +\n (firstPassKDelta !== null ? `, first-pass-k delta=${firstPassKDelta}` : '')\n\n return { perK, areaDelta, firstPassKDelta, verdict, rationale }\n}\n\n/** First k at which the curve's per-scenario pass rate reliably hits the threshold. */\nexport function firstPassK(curve: AdaptationCurve, threshold = 0.5): number | null {\n return curve.points.find((p) => p.passRate >= threshold)?.k ?? null\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction makeRng(seed?: number): () => number {\n if (seed === undefined) return Math.random\n let s = seed >>> 0\n return () => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\nfunction bootstrapMeanCi(\n xs: number[],\n resamples: number,\n confidence: number,\n rng: () => number,\n): { low: number; high: number } {\n if (xs.length < 2) return { low: xs[0] ?? 0, high: xs[0] ?? 0 }\n const samples = new Array<number>(resamples)\n for (let b = 0; b < resamples; b++) {\n let sum = 0\n for (let i = 0; i < xs.length; i++) sum += xs[Math.floor(rng() * xs.length)]!\n samples[b] = sum / xs.length\n }\n samples.sort((a, b) => a - b)\n const alpha = 1 - confidence\n return {\n low: samples[Math.floor((alpha / 2) * resamples)]!,\n high: samples[Math.min(resamples - 1, Math.ceil((1 - alpha / 2) * resamples) - 1)]!,\n }\n}\n","/**\n * Adversarial scenario search.\n *\n * Capability evaluation on a fixed scenario set measures performance on\n * the distribution someone curated. Production failure modes live in the\n * tail — inputs the curator didn't think of, or actively avoided. The\n * adversarial-search primitive actively looks for them: starting from a\n * pool of scenarios where the policy already passes, it mutates them\n * (paraphrase, edge-case substitution, compositional combination) and\n * keeps the mutations that *break* the policy.\n *\n * This is not magic. It's the simplest version of the loop that AdA\n * (Open-Ended Adaptation, DeepMind 2023), POET, and Anthropic's\n * auto-jailbreak rigs all run: hill-climb against a failure indicator,\n * keep the survivors, repeat. We ship the harness; consumers supply the\n * mutation strategies and the failure detector.\n *\n * Why ship this in agent-eval and not as a separate red-team tool: every\n * piece of the standard adversarial loop is already in this package\n * (`runEvalCampaign` for the matrix run, `RawProviderSink` for capture,\n * `assertRunCaptured` for integrity, `pairedEvalueSequence` for stop\n * criteria). The adversarial primitive is just the *scenario-mutation\n * meta-loop* on top of that machinery.\n */\n\nexport interface AdversarialScenario<S> {\n /** Stable id — used for deduplication and lineage tracking. */\n id: string\n /** Generation index — 0 for seeds, 1 for first round of mutations, etc. */\n generation: number\n /** Lineage — id of the parent scenario this was mutated from, if any. */\n parentId: string | null\n scenario: S\n /** Score on the policy under test. Lower = adversarial signal. */\n score: number | null\n /** Strategy that produced this mutation, for diagnostics. */\n mutationStrategy: string | null\n}\n\nexport interface AdversarialMutation<S> {\n id: string\n /**\n * Mutate one scenario. Return null to skip; return one or more new\n * scenarios. The harness deduplicates by `mutateScenarioId(scenario)`.\n */\n mutate(parent: S, rng: () => number): Promise<S[]> | S[]\n}\n\nexport interface AdversarialSearchOptions<S> {\n /** Initial scenarios — typically those the policy currently passes. */\n seeds: S[]\n /** Stable identifier extraction. */\n mutateScenarioId: (s: S) => string\n /** Mutation strategies. */\n mutations: AdversarialMutation<S>[]\n /**\n * Run the policy under test against one scenario, return a scalar score\n * in [0, 1]. Lower = adversarial signal.\n */\n scoreFn: (s: S) => Promise<number>\n /**\n * Threshold below which a scenario counts as a \"failure\" worth keeping.\n * Default 0.5.\n */\n failureThreshold?: number\n /** Number of mutation rounds. Default 3. */\n rounds?: number\n /** Children per parent per round. Default 4. */\n childrenPerParent?: number\n /** Maximum total scenarios examined. Default Infinity. */\n budget?: number\n /** Seed for the deterministic RNG. Default 1. */\n seed?: number\n}\n\nexport interface AdversarialSearchReport<S> {\n scenarios: AdversarialScenario<S>[]\n /** Discovered failures sorted by score ascending. */\n failures: AdversarialScenario<S>[]\n /** Round-by-round counts. */\n byGeneration: Array<{ generation: number; total: number; failures: number; meanScore: number }>\n /** Total scoreFn invocations consumed. */\n scoreCalls: number\n}\n\nexport async function adversarialScenarioSearch<S>(\n opts: AdversarialSearchOptions<S>,\n): Promise<AdversarialSearchReport<S>> {\n const failureThreshold = opts.failureThreshold ?? 0.5\n const rounds = opts.rounds ?? 3\n const children = opts.childrenPerParent ?? 4\n const budget = opts.budget ?? Number.POSITIVE_INFINITY\n const seed = opts.seed ?? 1\n const rng = mulberry32(seed)\n\n const scenarios: AdversarialScenario<S>[] = []\n const seen = new Set<string>()\n let scoreCalls = 0\n\n // Seed generation.\n for (const s of opts.seeds) {\n const id = opts.mutateScenarioId(s)\n if (seen.has(id)) continue\n seen.add(id)\n if (scoreCalls >= budget) break\n const score = await opts.scoreFn(s)\n scoreCalls++\n scenarios.push({\n id,\n generation: 0,\n parentId: null,\n scenario: s,\n score,\n mutationStrategy: null,\n })\n }\n\n // Mutation rounds.\n for (let g = 1; g <= rounds; g++) {\n if (scoreCalls >= budget) break\n const parents = scenarios.filter((s) => s.generation === g - 1)\n for (const parent of parents) {\n for (const mutation of opts.mutations) {\n if (scoreCalls >= budget) break\n const produced = await mutation.mutate(parent.scenario, rng)\n const childArr = Array.isArray(produced) ? produced : [produced]\n for (let k = 0; k < Math.min(children, childArr.length); k++) {\n if (scoreCalls >= budget) break\n const child = childArr[k]!\n const cid = opts.mutateScenarioId(child)\n if (seen.has(cid)) continue\n seen.add(cid)\n const cscore = await opts.scoreFn(child)\n scoreCalls++\n scenarios.push({\n id: cid,\n generation: g,\n parentId: parent.id,\n scenario: child,\n score: cscore,\n mutationStrategy: mutation.id,\n })\n }\n }\n }\n }\n\n const failures = scenarios\n .filter((s) => s.score !== null && s.score < failureThreshold)\n .sort((a, b) => (a.score ?? 0) - (b.score ?? 0))\n\n const byGeneration: AdversarialSearchReport<S>['byGeneration'] = []\n const maxGen = scenarios.reduce((m, s) => Math.max(m, s.generation), 0)\n for (let g = 0; g <= maxGen; g++) {\n const gens = scenarios.filter((s) => s.generation === g)\n if (gens.length === 0) continue\n const fails = gens.filter((s) => s.score !== null && s.score < failureThreshold).length\n const meanScore = gens.reduce((sum, s) => sum + (s.score ?? 0), 0) / gens.length\n byGeneration.push({ generation: g, total: gens.length, failures: fails, meanScore })\n }\n\n return { scenarios, failures, byGeneration, scoreCalls }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction mulberry32(seed: number): () => number {\n let s = seed >>> 0\n return () => {\n s = (s + 0x6d2b79f5) >>> 0\n let t = s\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n","/**\n * RL corpus — the durable, append-only accumulation of graded RunRecords that\n * every eval run deposits BY DEFAULT.\n *\n * The dataset is the free exhaust of the normal eval process: we run evals\n * constantly to get an agent production-ready, and those runs already produce\n * graded trajectories. Instead of writing them to an ephemeral run dir and\n * throwing them away, `appendToCorpus` accumulates them into a durable corpus;\n * `buildDatasetFromCorpus` later harvests the whole corpus into a publishable\n * bundle. No separate data-collection campaign — the data accrues from work we\n * do anyway. This is the \"best things for free by our process\" layer.\n *\n * Trajectory text rides on the record as top-level `prompt` / `completion`\n * (what the eval harnesses capture; the RunRecord validator ignores the extra\n * keys). The harvest reads them directly — no trace store round-trip needed.\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport type { RunRecord } from '../run-record'\nimport { buildRlDataset, type RlDatasetBundle, type RlDatasetConfig } from './dataset'\n\n/** A corpus record is a RunRecord carrying the trajectory text the harness\n * captured. `prompt`/`completion` are top-level (the validator ignores extras). */\nexport type CorpusRecord = RunRecord & { prompt?: string; completion?: string }\n\nexport interface CorpusAppendResult {\n appended: number\n /** Skipped because a record with the same runId was already in the corpus\n * (idempotent appends — NOT re-run collapsing; re-runs get fresh runIds). */\n skipped: number\n total: number\n}\n\n/**\n * Append graded records to the corpus (append-only JSONL). Deduplicates by\n * `runId` against what's already on disk so re-running the same harness is\n * idempotent. Creates the file and parent dir. This is the call every eval\n * harness makes by default after producing its records.\n */\nexport function appendToCorpus(records: CorpusRecord[], corpusPath: string): CorpusAppendResult {\n mkdirSync(dirname(corpusPath), { recursive: true })\n const existing = existsSync(corpusPath) ? readCorpus(corpusPath) : []\n const seen = new Set(existing.map((r) => r.runId))\n const lines: string[] = []\n let appended = 0\n let skipped = 0\n for (const r of records) {\n if (seen.has(r.runId)) {\n skipped++\n continue\n }\n seen.add(r.runId)\n lines.push(JSON.stringify(r))\n appended++\n }\n if (lines.length > 0) appendFileSync(corpusPath, `${lines.join('\\n')}\\n`)\n return { appended, skipped, total: existing.length + appended }\n}\n\n/** Read the full corpus. Returns [] if the corpus does not exist yet. */\nexport function readCorpus(corpusPath: string): CorpusRecord[] {\n if (!existsSync(corpusPath)) return []\n const out: CorpusRecord[] = []\n for (const line of readFileSync(corpusPath, 'utf8').split('\\n')) {\n if (line.trim()) out.push(JSON.parse(line) as CorpusRecord)\n }\n return out\n}\n\nfunction rewardOf(r: CorpusRecord): number {\n const v = r.outcome.holdoutScore ?? r.outcome.searchScore\n return typeof v === 'number' && Number.isFinite(v) ? v : 0\n}\n\nexport interface HarvestOptions {\n /** Keep only records scoring >= this (rejection-sampling for SFT). */\n minScore?: number\n /** Keep only these splits (e.g. ['holdout'] for an eval-only dataset). */\n splits?: RunRecord['splitTag'][]\n}\n\n/**\n * Harvest the accumulated corpus into a publishable RL dataset bundle. Reads\n * trajectory text from each record's top-level `prompt`/`completion`; records\n * missing either are excluded (a graded score with no trajectory can't train).\n * Optionally filters by score / split. Throws (via buildRlDataset) if nothing\n * survives — an empty dataset must never be published.\n */\nexport async function buildDatasetFromCorpus(\n corpusPath: string,\n config: RlDatasetConfig,\n opts: HarvestOptions = {},\n): Promise<RlDatasetBundle> {\n let records = readCorpus(corpusPath).filter(\n (r) => typeof r.prompt === 'string' && typeof r.completion === 'string',\n )\n if (opts.splits) records = records.filter((r) => opts.splits!.includes(r.splitTag))\n if (opts.minScore != null) records = records.filter((r) => rewardOf(r) >= opts.minScore!)\n\n const text = new Map(\n records.map((r) => [r.runId, { prompt: r.prompt!, completion: r.completion! }]),\n )\n const lookups = {\n promptOf: (id: string) => text.get(id)?.prompt ?? '',\n completionOf: (id: string) => text.get(id)?.completion ?? '',\n }\n return buildRlDataset(records, lookups, config)\n}\n","/**\n * Trainer-format exporters.\n *\n * agent-eval produces canonical artifacts (`RunRecord[]`, `PreferenceTriple[]`,\n * `StepReward[]`, `PrmTrainingTriple[]`). RL training pipelines consume\n * different shapes — Hugging Face TRL, Prime Intellect's prime-rl, OpenAI\n * fine-tuning, Anthropic finetuning, OpenRLHF, verl. Each has its own\n * JSONL conventions. Rather than ship N adapters, this module ships the\n * canonical formats most production pipelines accept and ergonomic helpers\n * for the rest.\n *\n * Shapes:\n * - **DPO / IPO / KTO** — `{prompt, chosen, rejected}` JSONL. Consumed\n * by HuggingFace TRL, prime-rl's offline DPO, OpenRLHF.\n * - **GRPO offline** — `{prompt, completions[], rewards[]}` JSONL.\n * Consumed by prime-rl GRPO, verl, OpenRLHF.\n * - **SFT** — `{messages[]}` JSONL with chosen completion as the final\n * assistant turn. Consumed by HF SFT trainers, OpenAI fine-tuning,\n * Anthropic finetuning.\n * - **PRM** — `{prompt, prefix_steps[], chosen_step, rejected_step}` JSONL.\n * Consumed by Lightman-style PRM trainers and prime-rl's PRM mode.\n *\n * Why ship this in agent-eval rather than a separate adapter package: the\n * canonical artifacts (`RunRecord[]`, `PreferenceTriple[]`, etc.) are\n * agent-eval's contract; without first-party exporters consumers reverse-\n * engineer the mapping every release. The exporters codify it.\n *\n * The exporters take callbacks for any field that isn't on the canonical\n * artifact (specifically: prompt + completion text, since the package\n * stores only their hashes by design — full text is the consumer's\n * trace store / raw event log).\n */\n\nimport type { RunRecord } from '../run-record'\nimport type { PreferenceTriple } from './preferences'\nimport type { PrmTrainingTriple, StepReward } from './process-reward'\n\n// ── DPO / IPO / KTO ──────────────────────────────────────────────────────\n\nexport interface DpoLookups {\n /** Resolve the prompt text for a run (typically from a trace store / raw event sink). */\n promptOf: (runId: string) => string | Promise<string>\n /** Resolve the assistant completion text for a run. */\n completionOf: (runId: string) => string | Promise<string>\n}\n\nexport interface DpoExportRow {\n prompt: string\n chosen: string\n rejected: string\n /** Carried-through margin. Some KTO / IPO variants use this. */\n margin?: number\n /** Free-form metadata for downstream filtering / sharding. */\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert preference triples to TRL-compatible DPO rows. The shape\n * `{prompt, chosen, rejected}` is the canonical HuggingFace DPODataset\n * entry; every major DPO trainer accepts it.\n */\nexport async function toDpoRows(\n triples: PreferenceTriple[],\n lookups: DpoLookups,\n): Promise<DpoExportRow[]> {\n const out: DpoExportRow[] = []\n for (const t of triples) {\n const [prompt, chosen, rejected] = await Promise.all([\n Promise.resolve(lookups.promptOf(t.chosenRunId)),\n Promise.resolve(lookups.completionOf(t.chosenRunId)),\n Promise.resolve(lookups.completionOf(t.rejectedRunId)),\n ])\n out.push({\n prompt,\n chosen,\n rejected,\n margin: t.marginScore,\n meta: {\n scenarioId: t.scenarioId,\n chosenVariantId: t.chosenVariantId,\n rejectedVariantId: t.rejectedVariantId,\n chosenRunId: t.chosenRunId,\n rejectedRunId: t.rejectedRunId,\n chosenModel: t.meta.chosenModel,\n rejectedModel: t.meta.rejectedModel,\n },\n })\n }\n return out\n}\n\n/** Serialize DPO rows as JSONL. One line per row. */\nexport function toDpoJsonl(rows: DpoExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── GRPO offline ─────────────────────────────────────────────────────────\n\nexport interface GrpoLookups {\n promptOf: (runId: string) => string | Promise<string>\n completionOf: (runId: string) => string | Promise<string>\n /** Optional: derive a custom reward from the run. Defaults to score. */\n rewardOf?: (run: RunRecord) => number | null\n}\n\nexport interface GrpoExportRow {\n prompt: string\n completions: string[]\n rewards: number[]\n /** runIds in the same order as `completions[]` for traceability. */\n runIds: string[]\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert RunRecord[] grouped by `(scenarioId)` into GRPO offline rows —\n * one row per scenario, with one completion per run on that scenario.\n *\n * GRPO (Shao et al. 2024 / DeepSeek-R1) trains on relative advantages\n * within a group of completions for the same prompt; this is the\n * canonical input format.\n */\nexport async function toGrpoRows(\n runs: RunRecord[],\n lookups: GrpoLookups,\n): Promise<GrpoExportRow[]> {\n const rewardOf = lookups.rewardOf ?? defaultReward\n const grouped = new Map<string, RunRecord[]>()\n for (const r of runs) {\n const sid = r.scenarioId ?? r.experimentId\n const arr = grouped.get(sid) ?? []\n arr.push(r)\n grouped.set(sid, arr)\n }\n\n const rows: GrpoExportRow[] = []\n for (const [scenarioId, group] of grouped.entries()) {\n if (group.length === 0) continue\n // Resolve prompt once per group (assumes all runs in a group share the prompt).\n const prompt = await Promise.resolve(lookups.promptOf(group[0]!.runId))\n const completions: string[] = []\n const rewards: number[] = []\n const runIds: string[] = []\n for (const r of group) {\n const reward = rewardOf(r)\n if (reward === null) continue\n const completion = await Promise.resolve(lookups.completionOf(r.runId))\n completions.push(completion)\n rewards.push(reward)\n runIds.push(r.runId)\n }\n if (completions.length === 0) continue\n rows.push({\n prompt,\n completions,\n rewards,\n runIds,\n meta: {\n scenarioId,\n n: completions.length,\n meanReward: rewards.reduce((s, x) => s + x, 0) / rewards.length,\n },\n })\n }\n return rows\n}\n\nexport function toGrpoJsonl(rows: GrpoExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── SFT ──────────────────────────────────────────────────────────────────\n\nexport interface SftLookups {\n promptOf: (runId: string) => string | Promise<string>\n completionOf: (runId: string) => string | Promise<string>\n /** Optional system message. Default omits. */\n systemOf?: (run: RunRecord) => string | null | undefined\n /** Filter — return false to skip the run (e.g., low score, failed cases). */\n include?: (run: RunRecord) => boolean\n}\n\nexport interface SftExportRow {\n messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert RunRecord[] into Hugging Face / OpenAI / Anthropic-style\n * conversational SFT rows. By default every record becomes one row;\n * pass `include` to filter (e.g., keep only `score >= 0.8` for\n * rejection-sampling SFT).\n */\nexport async function toSftRows(runs: RunRecord[], lookups: SftLookups): Promise<SftExportRow[]> {\n const include = lookups.include ?? (() => true)\n const rows: SftExportRow[] = []\n for (const r of runs) {\n if (!include(r)) continue\n const system = lookups.systemOf?.(r)\n const [prompt, completion] = await Promise.all([\n Promise.resolve(lookups.promptOf(r.runId)),\n Promise.resolve(lookups.completionOf(r.runId)),\n ])\n const messages: SftExportRow['messages'] = []\n if (system) messages.push({ role: 'system', content: system })\n messages.push({ role: 'user', content: prompt })\n messages.push({ role: 'assistant', content: completion })\n rows.push({\n messages,\n meta: {\n runId: r.runId,\n candidateId: r.candidateId,\n scenarioId: r.scenarioId,\n score: r.outcome.holdoutScore ?? r.outcome.searchScore,\n model: r.model,\n },\n })\n }\n return rows\n}\n\nexport function toSftJsonl(rows: SftExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── PRM ──────────────────────────────────────────────────────────────────\n\nexport interface PrmLookups {\n /** Resolve the prompt text for a run. */\n promptOf: (runId: string) => string | Promise<string>\n /** Resolve the trajectory step text for a (runId, spanId) pair. */\n stepTextOf: (runId: string, spanId: string) => string | Promise<string>\n /** Optional: sequence of prefix span ids leading up to the divergence. */\n prefixOf?: (runId: string, prefixStepIndex: number) => string[] | Promise<string[]>\n}\n\nexport interface PrmExportRow {\n prompt: string\n /** Span ids for the steps before divergence — caller resolves text via `stepTextOf`. */\n prefixSpanIds: string[]\n prefixStepText: string[]\n chosenStep: string\n rejectedStep: string\n chosenReward: number\n rejectedReward: number\n marginScore: number\n meta?: Record<string, unknown>\n}\n\n/**\n * Convert PRM training triples to JSONL rows. Caller's `stepTextOf`\n * callback resolves span text from the consumer's trace store.\n */\nexport async function toPrmRows(\n triples: PrmTrainingTriple[],\n lookups: PrmLookups,\n): Promise<PrmExportRow[]> {\n const rows: PrmExportRow[] = []\n for (const t of triples) {\n const prompt = await Promise.resolve(lookups.promptOf(t.prefixRunId))\n const prefixSpanIds = lookups.prefixOf\n ? await Promise.resolve(lookups.prefixOf(t.prefixRunId, t.prefixStepIndex))\n : []\n const prefixStepText: string[] = []\n for (const spanId of prefixSpanIds) {\n prefixStepText.push(await Promise.resolve(lookups.stepTextOf(t.prefixRunId, spanId)))\n }\n const chosenStep = await Promise.resolve(lookups.stepTextOf(t.prefixRunId, t.chosenSpanId))\n const rejectedStep = await Promise.resolve(\n lookups.stepTextOf(t.rejectedRunId, t.rejectedSpanId),\n )\n rows.push({\n prompt,\n prefixSpanIds,\n prefixStepText,\n chosenStep,\n rejectedStep,\n chosenReward: t.chosenReward,\n rejectedReward: t.rejectedReward,\n marginScore: t.marginScore,\n meta: {\n prefixRunId: t.prefixRunId,\n rejectedRunId: t.rejectedRunId,\n prefixStepIndex: t.prefixStepIndex,\n },\n })\n }\n return rows\n}\n\nexport function toPrmJsonl(rows: PrmExportRow[]): string {\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── Step rewards (for value-function regression) ─────────────────────────\n\nexport interface StepRewardJsonlRow {\n runId: string\n spanId: string\n stepIndex: number\n reward: number\n determinism: 'deterministic' | 'probabilistic'\n weight: number\n}\n\nexport function stepRewardsToJsonl(stepRewards: StepReward[]): string {\n const rows: StepRewardJsonlRow[] = stepRewards.map((s) => ({\n runId: s.runId,\n spanId: s.spanId,\n stepIndex: s.stepIndex,\n reward: s.reward,\n determinism: s.determinism,\n weight: s.weight ?? 1,\n }))\n return rows.map((r) => JSON.stringify(r)).join('\\n') + (rows.length > 0 ? '\\n' : '')\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction defaultReward(run: RunRecord): number | null {\n const v = run.outcome.holdoutScore ?? run.outcome.searchScore\n return typeof v === 'number' && Number.isFinite(v) ? v : null\n}\n","/**\n * RL dataset packaging + datasheet — the publishable, sellable bundle.\n *\n * The format exporters (`toGrpoRows` / `toSftRows` / `toDpoRows`) already\n * produce trainer-ready shapes (prime-rl GRPO, TRL DPO, conversational SFT).\n * What turns that into a dataset someone can PUBLISH or BUY is the provenance\n * + a datasheet: which models produced it, which prompt/agent versions, how the\n * reward was derived (deterministic verifiable vs probabilistic judge — the\n * credibility axis a buyer checks first), the split discipline, the reward\n * distribution, the quality gates, the license, and the intended/out-of-scope\n * uses. This module computes those facts from the `RunRecord[]` and renders a\n * \"Datasheet for Datasets\" (Gebru et al. 2018) card alongside the format files.\n *\n * It composes the existing `rl/exporters` — it does not reimplement any trainer\n * format. The renderers token-identity step (DeepSeek/Kimi/Qwen tokenization\n * with per-token loss masks) is a downstream Python stage that consumes the\n * `messages`/`completions` this bundle emits.\n */\n\nimport type { RunRecord, RunSplitTag } from '../run-record'\nimport {\n type DpoLookups,\n type GrpoLookups,\n type SftLookups,\n toDpoJsonl,\n toDpoRows,\n toGrpoJsonl,\n toGrpoRows,\n toSftJsonl,\n toSftRows,\n} from './exporters'\nimport type { PreferenceTriple } from './preferences'\n\nexport type RewardKind = 'deterministic' | 'probabilistic' | 'mixed'\nexport type DatasetFormat = 'grpo' | 'sft' | 'dpo'\n\n/** Caller-declared context — the qualitative half of the datasheet that can't\n * be computed from records. */\nexport interface RlDatasetConfig {\n name: string\n version: string\n /** Product/task domain, e.g. 'legal-m&a', 'tax-1040'. */\n domain: string\n /** SPDX id or a named commercial license. Required — an unlicensed dataset\n * cannot be published or sold. */\n license: string\n /** How the reward was produced. `kind: 'deterministic'` (a test/schema/XPath\n * decided it) is the credibility signal; 'probabilistic' = LLM-judge. */\n reward: { kind: RewardKind; source: string; description: string }\n intendedUse: string\n outOfScope: string\n limitations: string\n /** ISO timestamp — passed in (the substrate forbids Date.now()). */\n createdAtIso: string\n /** Default: ['grpo', 'sft']. */\n formats?: DatasetFormat[]\n /** Quality gates already run, recorded on the card for the buyer. */\n qualityGates?: {\n contaminationProbe?: 'passed' | 'failed' | 'not-run'\n dedup?: boolean\n verifiableRewardFilter?: boolean\n }\n}\n\nexport interface RewardStats {\n n: number\n mean: number\n median: number\n min: number\n max: number\n std: number\n}\n\nexport interface RlDatasetStats {\n records: number\n /** Record count per split — a publishable dataset must declare its holdout. */\n splits: Record<RunSplitTag, number>\n reward: RewardStats\n /** Distinct snapshot-pinned models that produced the trajectories. */\n models: string[]\n /** Distinct effective-prompt hashes (the agent profile/prompt versions). */\n promptHashes: string[]\n commitShas: string[]\n totalTokens: { input: number; output: number }\n totalCostUsd: number\n}\n\nexport interface RlDatasetManifest extends RlDatasetConfig {\n formats: DatasetFormat[]\n rowCounts: Partial<Record<DatasetFormat, number>>\n stats: RlDatasetStats\n}\n\nexport interface RlDatasetBundle {\n manifest: RlDatasetManifest\n /** Relative filename -> contents. Write these to a directory to publish. */\n files: Record<string, string>\n}\n\nfunction reward(r: RunRecord): number | null {\n const v = r.outcome.holdoutScore ?? r.outcome.searchScore\n return typeof v === 'number' && Number.isFinite(v) ? v : null\n}\n\nfunction distinct(xs: string[]): string[] {\n return [...new Set(xs)].sort()\n}\n\nfunction computeRewardStats(values: number[]): RewardStats {\n if (values.length === 0) return { n: 0, mean: 0, median: 0, min: 0, max: 0, std: 0 }\n const sorted = [...values].sort((a, b) => a - b)\n const n = sorted.length\n const mean = sorted.reduce((s, x) => s + x, 0) / n\n const mid = Math.floor(n / 2)\n const median = n % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!\n const variance = sorted.reduce((s, x) => s + (x - mean) ** 2, 0) / n\n return { n, mean, median, min: sorted[0]!, max: sorted[n - 1]!, std: Math.sqrt(variance) }\n}\n\nfunction computeStats(records: RunRecord[]): RlDatasetStats {\n const splits: Record<RunSplitTag, number> = { search: 0, dev: 0, holdout: 0 }\n let inTok = 0\n let outTok = 0\n let cost = 0\n const rewards: number[] = []\n for (const r of records) {\n splits[r.splitTag] = (splits[r.splitTag] ?? 0) + 1\n inTok += r.tokenUsage.input\n outTok += r.tokenUsage.output\n cost += r.costUsd\n const rw = reward(r)\n if (rw !== null) rewards.push(rw)\n }\n return {\n records: records.length,\n splits,\n reward: computeRewardStats(rewards),\n models: distinct(records.map((r) => r.model)),\n promptHashes: distinct(records.map((r) => r.promptHash)),\n commitShas: distinct(records.map((r) => r.commitSha)),\n totalTokens: { input: inTok, output: outTok },\n totalCostUsd: cost,\n }\n}\n\n/**\n * Package graded `RunRecord[]` into a publishable RL dataset bundle: the\n * trainer-format JSONL files + a manifest + a datasheet. DPO requires\n * pre-extracted preference triples (pass `preferences`); GRPO/SFT derive from\n * the records directly via the supplied lookups. Throws on an empty corpus —\n * an empty dataset must never be published.\n */\nexport async function buildRlDataset(\n records: RunRecord[],\n lookups: GrpoLookups & SftLookups,\n config: RlDatasetConfig,\n preferences?: { triples: PreferenceTriple[]; lookups: DpoLookups },\n): Promise<RlDatasetBundle> {\n if (records.length === 0) {\n throw new Error('buildRlDataset: no records — refusing to package an empty dataset')\n }\n const formats = config.formats ?? ['grpo', 'sft']\n const files: Record<string, string> = {}\n const rowCounts: Partial<Record<DatasetFormat, number>> = {}\n\n if (formats.includes('grpo')) {\n const rows = await toGrpoRows(records, lookups)\n files['train.grpo.jsonl'] = toGrpoJsonl(rows)\n rowCounts.grpo = rows.length\n }\n if (formats.includes('sft')) {\n const rows = await toSftRows(records, lookups)\n files['train.sft.jsonl'] = toSftJsonl(rows)\n rowCounts.sft = rows.length\n }\n if (formats.includes('dpo')) {\n if (!preferences) {\n throw new Error(\"buildRlDataset: format 'dpo' requires `preferences` (triples + lookups)\")\n }\n const rows = await toDpoRows(preferences.triples, preferences.lookups)\n files['train.dpo.jsonl'] = toDpoJsonl(rows)\n rowCounts.dpo = rows.length\n }\n\n const manifest: RlDatasetManifest = {\n ...config,\n formats,\n rowCounts,\n stats: computeStats(records),\n }\n files['manifest.json'] = `${JSON.stringify(manifest, null, 2)}\\n`\n files['DATASHEET.md'] = datasheetToMarkdown(manifest)\n return { manifest, files }\n}\n\nfunction pct(x: number): string {\n return `${(x * 100).toFixed(1)}%`\n}\n\n/** Render the \"Datasheet for Datasets\" card — the artifact a buyer reads. */\nexport function datasheetToMarkdown(m: RlDatasetManifest): string {\n const s = m.stats\n const total = s.records || 1\n const splitLines = (['search', 'dev', 'holdout'] as RunSplitTag[])\n .map((k) => ` - \\`${k}\\`: ${s.splits[k]} (${pct(s.splits[k] / total)})`)\n .join('\\n')\n const deterministic = m.reward.kind === 'deterministic'\n return [\n `# Dataset: ${m.name} \\`v${m.version}\\``,\n '',\n `**Domain:** ${m.domain} · **Created:** ${m.createdAtIso} · **License:** ${m.license}`,\n '',\n '## Reward provenance',\n `- **Kind:** ${m.reward.kind}${deterministic ? ' ✅ (decidable — not judge-noise)' : ''}`,\n `- **Source:** ${m.reward.source}`,\n `- **Description:** ${m.reward.description}`,\n '',\n '## Composition',\n `- **Records (trajectories):** ${s.records}`,\n `- **Formats:** ${m.formats.map((f) => `${f} (${m.rowCounts[f] ?? 0} rows)`).join(', ')}`,\n '- **Splits:**',\n splitLines,\n '',\n '## Reward distribution',\n `- n=${s.reward.n} · mean=${s.reward.mean.toFixed(3)} · median=${s.reward.median.toFixed(3)} · min=${s.reward.min.toFixed(3)} · max=${s.reward.max.toFixed(3)} · std=${s.reward.std.toFixed(3)}`,\n '',\n '## Provenance',\n `- **Models:** ${s.models.join(', ')}`,\n `- **Prompt/agent versions (sha256):** ${s.promptHashes.length} distinct`,\n `- **Commits:** ${s.commitShas.join(', ')}`,\n `- **Tokens:** ${s.totalTokens.input} in / ${s.totalTokens.output} out · **Cost:** $${s.totalCostUsd.toFixed(2)}`,\n '',\n '## Quality gates',\n `- Contamination probe: ${m.qualityGates?.contaminationProbe ?? 'not-run'}`,\n `- Dedup: ${m.qualityGates?.dedup ? 'yes' : 'no'} · Verifiable-reward filter: ${m.qualityGates?.verifiableRewardFilter ? 'yes' : 'no'}`,\n '',\n '## Recommended uses',\n m.intendedUse,\n '',\n '## Out of scope',\n m.outOfScope,\n '',\n '## Limitations',\n m.limitations,\n '',\n '## Token rendering',\n 'For RL/SFT training, tokenize with the per-model renderer (DeepSeek-V3 / Kimi-K2 / Qwen3) to preserve token identity and per-token loss masks across tool-call turns — see `renderers` (PrimeIntellect). The `messages` / `completions` here are the renderer input.',\n '',\n ].join('\\n')\n}\n","/**\n * `PredictiveValidityResearcher` — concrete `Researcher` implementation\n * that drives selection from outcome-anchored predictive validity.\n *\n * Each method:\n *\n * - `inspectFailures(runs)` — synthesizes failure modes from the\n * bottom-quartile of `RunRecord`s on the configured proxy reward.\n * - `proposeChange(failures)` — proposes steering changes that target\n * the rubrics with the lowest predictive validity (decorative ones).\n * Either reduce their weight in the composite, or recalibrate them.\n * - `applyChange(changes, baseline)` — merges the proposed steering\n * into the experiment plan.\n * - `evaluateChange(plan)` — re-runs the predictive-validity check on\n * the post-change runs and reports the delta.\n *\n * The result is a closed loop: the rubric weights drift toward the ones\n * that actually predict deployment outcomes, automatically. Pair with\n * `runRLCampaign` for the full auto-research story.\n */\n\nimport type { GateDecision } from '../held-out-gate'\nimport type { OutcomeStore } from '../meta-eval/outcome-store'\nimport {\n type RubricPredictiveValidityReport,\n rubricPredictiveValidity,\n} from '../meta-eval/rubric-predictive-validity'\nimport type {\n ExperimentPlan,\n ExperimentResult,\n FailureMode,\n Researcher,\n SteeringChange,\n} from '../researcher'\nimport type { RunRecord } from '../run-record'\n\nexport interface PredictiveValidityResearcherOptions {\n outcomes: OutcomeStore\n outcomeMetrics: string[]\n /** Score threshold below which a run counts as a \"failure.\" Default 0.5. */\n failureThreshold?: number\n /** Spearman bucket below which a rubric is \"decorative.\" Default 0.4. */\n decorativeThreshold?: number\n /** Optional steering-namespace prefix for proposed changes. Default `'rubric_weight'`. */\n steeringNamespace?: string\n /** Override the rubric set the researcher inspects. Default: every numeric `outcome.raw` key seen. */\n rubrics?: string[]\n /**\n * Snapshot stash hook — called with the most recent predictive-validity\n * report. Useful when a downstream system wants to log rubric drift over\n * time. Default no-op.\n */\n onReport?: (report: RubricPredictiveValidityReport) => void | Promise<void>\n}\n\n/**\n * Concrete `Researcher` driven by `rubricPredictiveValidity`. The brain:\n * rubrics that don't predict deployment outcomes don't earn weight.\n */\nexport class PredictiveValidityResearcher implements Researcher {\n private opts: PredictiveValidityResearcherOptions\n private lastReport: RubricPredictiveValidityReport | null = null\n\n constructor(opts: PredictiveValidityResearcherOptions) {\n this.opts = opts\n }\n\n async inspectFailures(runs: RunRecord[]): Promise<FailureMode[]> {\n const threshold = this.opts.failureThreshold ?? 0.5\n const failures: FailureMode[] = []\n const failingRuns = runs.filter((r) => {\n const score = r.outcome.holdoutScore ?? r.outcome.searchScore\n return typeof score === 'number' && score < threshold\n })\n if (failingRuns.length === 0) return failures\n\n // Group failures by candidateId — the researcher's primary handle is\n // \"this candidate is producing low-scoring outputs in this scenario.\"\n const grouped = new Map<string, RunRecord[]>()\n for (const r of failingRuns) {\n const arr = grouped.get(r.candidateId) ?? []\n arr.push(r)\n grouped.set(r.candidateId, arr)\n }\n\n for (const [candidateId, group] of grouped.entries()) {\n const meanScore =\n group.reduce((s, r) => {\n const x = r.outcome.holdoutScore ?? r.outcome.searchScore ?? 0\n return s + x\n }, 0) / group.length\n failures.push({\n code: `low-score-${candidateId}`,\n description: `${candidateId} scored < ${threshold} on ${group.length} run(s) (mean ${meanScore.toFixed(3)})`,\n evidence: {\n runIds: group.slice(0, 8).map((r) => r.runId),\n samples: group.length,\n },\n })\n }\n return failures\n }\n\n async proposeChange(failures: FailureMode[]): Promise<SteeringChange[]> {\n if (failures.length === 0) return []\n\n // Without a prior report, return a single \"collect more outcome data\"\n // change — the researcher refuses to reweight rubrics from zero evidence.\n if (this.lastReport === null) {\n return [\n {\n kind: 'threshold',\n payload: { directive: 'researcher.collect-more-outcomes' },\n rationale:\n 'predictive-validity researcher has no prior report; cannot recommend rubric reweighting until at least one report exists',\n },\n ]\n }\n\n const decorativeThreshold = this.opts.decorativeThreshold ?? 0.4\n const changes: SteeringChange[] = []\n\n for (const ranking of this.lastReport.ranked) {\n if (ranking.verdict === 'load_bearing') continue\n if (Math.abs(ranking.spearman) >= decorativeThreshold) continue\n changes.push({\n kind: 'reviewer_prompt',\n payload: {\n rubric: ranking.rubric,\n action: 'down-weight',\n spearman: ranking.spearman,\n bestOutcome: ranking.bestOutcome,\n },\n rationale: `predictive-validity Spearman=${ranking.spearman.toFixed(3)} vs ${ranking.bestOutcome} (decorative); recommend down-weighting`,\n expectedDelta: -Math.max(0, 0.05 - Math.abs(ranking.spearman)),\n })\n }\n for (const ranking of this.lastReport.ranked.slice(0, 1)) {\n if (ranking.verdict !== 'load_bearing') continue\n changes.push({\n kind: 'reviewer_prompt',\n payload: {\n rubric: ranking.rubric,\n action: 'up-weight',\n spearman: ranking.spearman,\n bestOutcome: ranking.bestOutcome,\n },\n rationale: `predictive-validity Spearman=${ranking.spearman.toFixed(3)} vs ${ranking.bestOutcome} (load-bearing); recommend up-weighting`,\n expectedDelta: Math.max(0, Math.abs(ranking.spearman) - 0.5) * 0.1,\n })\n }\n return changes\n }\n\n async applyChange(changes: SteeringChange[], baseline: ExperimentPlan): Promise<ExperimentPlan> {\n // Merge proposed changes into the plan's `changes` array, preserving\n // any changes the baseline already had.\n return {\n ...baseline,\n changes: [...baseline.changes, ...changes],\n }\n }\n\n async evaluateChange(plan: ExperimentPlan): Promise<ExperimentResult> {\n // The researcher contract takes a *plan* and returns a *result* —\n // implementations that only understand re-scoring runs can produce a\n // \"no-op\" gate decision and let the caller drive the actual sweep.\n // Real evaluators (CallbackResearcher) execute the plan; we report.\n const emptyGate: GateDecision = {\n promote: false,\n candidateId: plan.proposedCandidateId,\n baselineId: plan.baselineCandidateId,\n evidence: {\n productiveRuns: 0,\n medianPairedDelta: 0,\n pairedCI: { low: 0, high: 0 },\n pairedPValue: 1,\n searchScore: 0,\n holdoutScore: 0,\n overfitGap: 0,\n baselineOverfitGap: 0,\n medianCandidateCost: Number.NaN,\n medianBaselineCost: Number.NaN,\n },\n reason:\n 'predictive-validity researcher does not execute plans; the caller is expected to run the sweep and call rubricPredictiveValidity directly with the resulting RunRecord[].',\n rejectionCode: 'few_runs',\n }\n return {\n plan,\n runs: [],\n gateDecision: emptyGate,\n }\n }\n\n /**\n * Run the predictive-validity check explicitly against a fresh RunRecord\n * set. Updates the researcher's cached report so subsequent\n * `proposeChange` calls have evidence to draw from.\n */\n async runValidityCheck(runs: RunRecord[]): Promise<RubricPredictiveValidityReport> {\n const report = await rubricPredictiveValidity({\n runs,\n outcomes: this.opts.outcomes,\n outcomeMetrics: this.opts.outcomeMetrics,\n rubrics: this.opts.rubrics,\n })\n if (this.opts.onReport) await this.opts.onReport(report)\n this.lastReport = report\n return report\n }\n\n /**\n * Force-feed a predictive-validity report into the researcher state —\n * useful when the consumer ran the report out-of-band and wants the\n * researcher's later proposals informed by it.\n */\n setReport(report: RubricPredictiveValidityReport): void {\n this.lastReport = report\n }\n\n getLastReport(): RubricPredictiveValidityReport | null {\n return this.lastReport\n }\n}\n","/**\n * Process reward extraction — step-level credit assignment from trace spans.\n *\n * RL on long-horizon agents needs *step-level* rewards, not run-level\n * ones. The classic credit-assignment problem (Sutton & Barto) requires\n * knowing which sub-decisions in a trajectory contributed to the\n * outcome. Modern systems (DeepSeek-R1, OpenAI o-series, Lightman et al.\n * \"Let's Verify Step by Step\" 2023) train *process reward models* (PRMs)\n * that score every step, then do RL with the PRM as the reward signal.\n *\n * This module extracts `StepReward[]` from trace spans — one per\n * meaningful step — and ships:\n *\n * 1. `extractStepRewards(store, runId, opts)` — span → step-reward\n * conversion using configurable per-span scorers (LLM judge over the\n * span output, deterministic checkers, or a learned PRM).\n * 2. `runwiseStepRewardSummary(stepRewards)` — aggregate the per-step\n * signal into a credit-assignment-aware run-level score.\n * 3. `prmTrainingPairs(stepRewards, options)` — produce the\n * `(prefix, suffix_chosen, suffix_rejected)` triples that PRM\n * training pipelines consume.\n *\n * What we ship: the *extraction* and *aggregation* infrastructure plus\n * the data shape PRM training expects. We do NOT ship the actual PRM\n * training (gradient descent over a transformer is out of scope for a\n * TS package). The interface is the contract; downstream consumers wire\n * their preferred trainer.\n *\n * Caveat the panel will land: this is descriptive credit assignment\n * (which steps correlate with outcome), not causal credit assignment\n * (which steps caused outcome). For causal claims you need\n * counterfactual rollouts or a learned dynamics model. Future work; the\n * descriptive version is what production PRM training actually uses.\n */\n\nimport type { Span } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\n\nexport interface StepReward {\n /** Trace span this reward attaches to. */\n spanId: string\n runId: string\n /** Index in the trajectory (0-based, in started-at order). */\n stepIndex: number\n /** Span kind (typically 'tool', 'llm', 'judge'). */\n kind: Span['kind']\n /** Span name — for the consumer's downstream filtering. */\n name: string\n /** Step-level reward in [0, 1]. */\n reward: number\n /**\n * Determinism class. Mirrors the verifiable-reward distinction:\n * deterministic = test/compile/schema check; probabilistic = LLM judge.\n */\n determinism: 'deterministic' | 'probabilistic'\n /** Optional rationale / evidence — the trainer typically discards. */\n rationale?: string\n /** Optional weight — how much this step contributes to credit assignment. */\n weight?: number\n}\n\nexport interface StepScorer {\n /** Span kinds this scorer applies to. */\n appliesTo: Span['kind'][]\n /** Returns null to skip the span; returns a `StepReward` shape (without index/runId/spanId, which are filled in). */\n score(span: Span): Promise<Omit<StepReward, 'spanId' | 'runId' | 'stepIndex'>> | null | undefined\n}\n\nexport interface ExtractStepRewardsOptions {\n /**\n * Ordered list of scorers. Each span runs through scorers in order;\n * the first non-null result wins. If no scorer applies, the span is\n * skipped (not all spans are training-worthy).\n */\n scorers: StepScorer[]\n /** Optional filter — return null to drop the span entirely before scoring. */\n preFilter?: (span: Span) => boolean\n}\n\nexport async function extractStepRewards(\n store: TraceStore,\n runId: string,\n opts: ExtractStepRewardsOptions,\n): Promise<StepReward[]> {\n const spans = await store.spans({ runId })\n const ordered = [...spans].sort((a, b) => a.startedAt - b.startedAt)\n const out: StepReward[] = []\n let idx = 0\n for (const span of ordered) {\n if (opts.preFilter && !opts.preFilter(span)) continue\n let scored: Awaited<ReturnType<StepScorer['score']>> = null\n for (const s of opts.scorers) {\n if (!s.appliesTo.includes(span.kind)) continue\n const r = await s.score(span)\n if (r) {\n scored = r\n break\n }\n }\n if (!scored) continue\n out.push({\n spanId: span.spanId,\n runId,\n stepIndex: idx++,\n kind: span.kind,\n name: span.name,\n reward: scored.reward,\n determinism: scored.determinism,\n rationale: scored.rationale,\n weight: scored.weight,\n })\n }\n return out\n}\n\nexport interface RunwiseStepSummary {\n runId: string\n totalSteps: number\n meanReward: number\n /** Sum-of-rewards (weighted by `weight ?? 1`). Use as the run-level proxy. */\n sumWeightedReward: number\n /** Fraction of steps where reward < 0.5 — proxy for \"where the policy was wrong.\" */\n failureFraction: number\n /** Maximum drop in reward between consecutive steps — diagnoses a step where things went sideways. */\n worstStepDelta: number\n worstStepIndex: number | null\n}\n\nexport function runwiseStepRewardSummary(stepRewards: StepReward[]): RunwiseStepSummary {\n if (stepRewards.length === 0) {\n return {\n runId: '',\n totalSteps: 0,\n meanReward: 0,\n sumWeightedReward: 0,\n failureFraction: 0,\n worstStepDelta: 0,\n worstStepIndex: null,\n }\n }\n const runId = stepRewards[0]!.runId\n let sumW = 0\n let sumWR = 0\n let failures = 0\n let worstDelta = 0\n let worstIdx: number | null = null\n let prev = stepRewards[0]!.reward\n for (let i = 0; i < stepRewards.length; i++) {\n const s = stepRewards[i]!\n const w = s.weight ?? 1\n sumW += w\n sumWR += w * s.reward\n if (s.reward < 0.5) failures++\n if (i > 0) {\n const delta = s.reward - prev\n if (delta < worstDelta) {\n worstDelta = delta\n worstIdx = i\n }\n prev = s.reward\n } else {\n prev = s.reward\n }\n }\n return {\n runId,\n totalSteps: stepRewards.length,\n meanReward: sumW === 0 ? 0 : sumWR / sumW,\n sumWeightedReward: sumWR,\n failureFraction: failures / stepRewards.length,\n worstStepDelta: worstDelta,\n worstStepIndex: worstIdx,\n }\n}\n\nexport interface PrmTrainingTriple {\n /** Prefix run-id (or composite key) — the trajectory up to step k-1. */\n prefixRunId: string\n prefixStepIndex: number\n /** The step that came next on a high-reward trajectory. */\n chosenSpanId: string\n chosenReward: number\n /** A step from a divergent low-reward trajectory at the same prefix length. */\n rejectedSpanId: string\n rejectedReward: number\n /** The prefix run came from this run; the rejected step came from `rejectedRunId`. */\n rejectedRunId: string\n marginScore: number\n}\n\n/**\n * Build PRM training triples. The shape: pair runs that share an early\n * prefix (same scenario, same first N steps) and diverge later — at the\n * point of divergence, the high-reward run's next step is `chosen`, the\n * low-reward run's next step is `rejected`. This is the canonical PRM\n * training data shape from Lightman et al. and DeepSeek-R1 process\n * supervision.\n *\n * Implementation note: we don't have a way to detect \"same prefix\" in\n * the general agent setting (token-level prefixes require hashing model\n * outputs). The current heuristic groups by `(scenarioId, prefixSpanName\n * sequence)` — runs are paired when their first K span names match. For\n * production use this should be replaced with a proper trajectory-prefix\n * hash; the heuristic is good enough for early-stage scaffolding.\n */\nexport function prmTrainingPairs(\n stepRewardsByRun: Map<string, StepReward[]>,\n opts: { minMargin?: number; minPrefixLength?: number } = {},\n): PrmTrainingTriple[] {\n const minMargin = opts.minMargin ?? 0.2\n const minPrefix = opts.minPrefixLength ?? 1\n const runs = [...stepRewardsByRun.entries()].map(([runId, steps]) => ({ runId, steps }))\n const triples: PrmTrainingTriple[] = []\n\n for (let i = 0; i < runs.length; i++) {\n for (let j = i + 1; j < runs.length; j++) {\n const a = runs[i]!\n const b = runs[j]!\n const minLen = Math.min(a.steps.length, b.steps.length)\n if (minLen < minPrefix + 1) continue\n\n // Find the first index where the trajectories diverge: either by\n // step structure (kind/name mismatch) OR by reward gap ≥ minMargin.\n // Names that match but rewards that differ ARE divergence — that's\n // the canonical PRM training case (same step structure, different\n // outcomes via state/context).\n let divergenceIdx = -1\n for (let k = 0; k < minLen; k++) {\n const sa = a.steps[k]!\n const sb = b.steps[k]!\n const structuralDivergence = sa.kind !== sb.kind || sa.name !== sb.name\n const rewardGap = Math.abs(sa.reward - sb.reward)\n if (structuralDivergence || rewardGap >= minMargin) {\n divergenceIdx = k\n break\n }\n }\n if (divergenceIdx < 0) continue\n if (divergenceIdx < minPrefix) continue\n\n const aNext = a.steps[divergenceIdx]!\n const bNext = b.steps[divergenceIdx]!\n const margin = Math.abs(aNext.reward - bNext.reward)\n if (margin < minMargin) continue\n\n const chosen = aNext.reward > bNext.reward ? aNext : bNext\n const rejected = aNext.reward > bNext.reward ? bNext : aNext\n const chosenRun = aNext.reward > bNext.reward ? a.runId : b.runId\n const rejectedRun = aNext.reward > bNext.reward ? b.runId : a.runId\n triples.push({\n prefixRunId: chosenRun,\n prefixStepIndex: divergenceIdx - 1,\n chosenSpanId: chosen.spanId,\n chosenReward: chosen.reward,\n rejectedSpanId: rejected.spanId,\n rejectedReward: rejected.reward,\n rejectedRunId: rejectedRun,\n marginScore: chosen.reward - rejected.reward,\n })\n }\n }\n return triples\n}\n","/**\n * `runRLCampaign` — top-level orchestrator that runs the matrix and\n * produces every RL-ready artifact in one call.\n *\n * Wires:\n * 1. `runEvalCampaign` for the matrix run (capture, integrity, hooks)\n * 2. `extractVerifiableReward` over each run, separating deterministic\n * from probabilistic reward sources for the trainer\n * 3. `extractPreferences` to produce DPO/PPO/KTO triples\n * 4. `evaluateInterimReleaseConfidence` over paired deltas (anytime-valid)\n * 5. `rubricPredictiveValidity` against an outcome store, when provided\n * 6. `detectRewardHacking` as a standing hygiene check\n * 7. Trainer-format export rows ready for prime-rl / TRL / verl\n *\n * The output `RLCampaignResult` is a single, audit-ready artifact: every\n * stage's output is in there. The consumer's downstream fits in a single\n * line: pass `result.preferences` to their DPO trainer, `result.grpoRows`\n * to GRPO, `result.runs` plus `result.rewardSignals` to a custom RL loop.\n */\n\nimport {\n type EvalCampaignOptions,\n type EvalCampaignResult,\n runEvalCampaign,\n} from '../eval-campaign'\nimport type { OutcomeStore } from '../meta-eval/outcome-store'\nimport {\n type RubricPredictiveValidityReport,\n rubricPredictiveValidity,\n} from '../meta-eval/rubric-predictive-validity'\nimport type { RunRecord } from '../run-record'\nimport { evaluateInterimReleaseConfidence, type InterimReleaseConfidence } from '../sequential'\nimport {\n type DpoExportRow,\n type DpoLookups,\n type GrpoExportRow,\n type GrpoLookups,\n type SftExportRow,\n type SftLookups,\n toDpoRows,\n toGrpoRows,\n toSftRows,\n} from './exporters'\nimport {\n type ExtractPreferencesOptions,\n extractPreferences,\n type PreferenceExtractionReport,\n} from './preferences'\nimport { detectRewardHacking, type RewardHackingReport } from './reward-hacking'\nimport {\n extractVerifiableRewardsFromRecords,\n type VerifiableReward,\n type VerifiableRewardExtractionOptions,\n} from './verifiable-reward'\n\nexport interface RunRLCampaignOptions<V> extends EvalCampaignOptions<V> {\n /** Preference-extraction options. Default uses paired-by-scenario-and-seed with min-margin 0.05. */\n preferences?: ExtractPreferencesOptions\n /** Verifiable-reward extraction options. */\n verifiableReward?: VerifiableRewardExtractionOptions\n /** Outcome store + metric names — when supplied, runs `rubricPredictiveValidity` post-campaign. */\n outcomeStore?: OutcomeStore\n outcomeMetrics?: string[]\n /** Anytime-valid sequential evaluation options. */\n sequential?: { alpha?: number; bound?: number; rope?: { low: number; high: number } }\n /** Trainer-format export lookups. When provided, the orchestrator builds the corresponding rows. */\n trainerExport?: {\n dpo?: DpoLookups\n grpo?: GrpoLookups\n sft?: SftLookups\n }\n}\n\nexport interface RLCampaignResult<V> {\n campaign: EvalCampaignResult\n /** Per-run verifiable reward (deterministic when available, probabilistic fallback otherwise). */\n rewardSignals: Array<{ runId: string; reward: VerifiableReward | null }>\n /** Preference extraction report. */\n preferences: PreferenceExtractionReport\n /** Anytime-valid interim verdict over the paired deltas (vs comparator). */\n interimConfidence: InterimReleaseConfidence | null\n /** Standing reward-hacking hygiene check. */\n rewardHacking: RewardHackingReport\n /** Predictive validity, when an outcome store was supplied. */\n predictiveValidity: RubricPredictiveValidityReport | null\n /** Trainer-export rows, populated only for the formats the caller requested via `trainerExport`. */\n trainerRows: {\n dpo?: DpoExportRow[]\n grpo?: GrpoExportRow[]\n sft?: SftExportRow[]\n }\n /**\n * One-line top-level summary the consumer can log.\n */\n summary: string\n /**\n * Convenience type-tag — consumers can branch on `result.kind`.\n */\n kind: 'agent-eval-rl-campaign'\n unusedVariant?: V\n}\n\nexport async function runRLCampaign<V>(\n opts: RunRLCampaignOptions<V>,\n): Promise<RLCampaignResult<V>> {\n // ── 1. Run the matrix ──────────────────────────────────────────────\n const campaign = await runEvalCampaign(opts)\n\n // ── 2. Extract reward signals (deterministic-first) ────────────────\n const rewardSignals = extractVerifiableRewardsFromRecords(\n campaign.runs,\n opts.verifiableReward ?? {},\n )\n\n // ── 3. Extract preference triples ──────────────────────────────────\n const preferences = extractPreferences(campaign.runs, {\n strategy: opts.preferences?.strategy ?? 'paired-by-scenario-and-seed',\n minMargin: opts.preferences?.minMargin ?? 0.05,\n splitTag: opts.preferences?.splitTag ?? opts.splitTag ?? 'holdout',\n rewardOf: opts.preferences?.rewardOf,\n })\n\n // ── 4. Sequential / anytime-valid interim verdict ──────────────────\n let interimConfidence: InterimReleaseConfidence | null = null\n if (opts.report?.comparator) {\n const comparator = opts.report.comparator\n const deltaSeries = collectPairedDeltaSeries(campaign.runs, comparator)\n if (deltaSeries.some((s) => s.deltas.length > 0)) {\n interimConfidence = evaluateInterimReleaseConfidence({\n deltaSeries,\n alpha: opts.sequential?.alpha,\n bound: opts.sequential?.bound,\n rope: opts.sequential?.rope ?? opts.report?.rope,\n })\n }\n }\n\n // ── 5. Standing reward-hacking hygiene ─────────────────────────────\n const rewardHacking = detectRewardHacking({\n runs: campaign.runs,\n verifiableRewardOptions: opts.verifiableReward,\n })\n\n // ── 6. Predictive validity (when outcomes are supplied) ────────────\n let predictiveValidity: RubricPredictiveValidityReport | null = null\n if (opts.outcomeStore && opts.outcomeMetrics && opts.outcomeMetrics.length > 0) {\n predictiveValidity = await rubricPredictiveValidity({\n runs: campaign.runs,\n outcomes: opts.outcomeStore,\n outcomeMetrics: opts.outcomeMetrics,\n })\n }\n\n // ── 7. Trainer-format export ───────────────────────────────────────\n const trainerRows: RLCampaignResult<V>['trainerRows'] = {}\n if (opts.trainerExport?.dpo) {\n trainerRows.dpo = await toDpoRows(preferences.pairs, opts.trainerExport.dpo)\n }\n if (opts.trainerExport?.grpo) {\n trainerRows.grpo = await toGrpoRows(campaign.runs, opts.trainerExport.grpo)\n }\n if (opts.trainerExport?.sft) {\n trainerRows.sft = await toSftRows(campaign.runs, opts.trainerExport.sft)\n }\n\n const summary = buildSummary({\n campaign,\n preferences,\n interimConfidence,\n rewardHacking,\n predictiveValidity,\n })\n\n return {\n campaign,\n rewardSignals,\n preferences,\n interimConfidence,\n rewardHacking,\n predictiveValidity,\n trainerRows,\n summary,\n kind: 'agent-eval-rl-campaign',\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction collectPairedDeltaSeries(\n runs: RunRecord[],\n comparator: string,\n): Array<{ candidateId: string; deltas: number[] }> {\n // Pair on (scenarioId, seed). For each candidate that isn't the comparator,\n // compute candidate.score - comparator.score on matching cells.\n const baseline = new Map<string, number>()\n for (const r of runs) {\n if (r.candidateId !== comparator) continue\n const sid = r.scenarioId ?? r.experimentId\n const score = r.outcome.holdoutScore ?? r.outcome.searchScore\n if (typeof score !== 'number' || !Number.isFinite(score)) continue\n baseline.set(`${sid}::${r.seed}`, score)\n }\n const byCandidate = new Map<string, number[]>()\n for (const r of runs) {\n if (r.candidateId === comparator) continue\n const sid = r.scenarioId ?? r.experimentId\n const score = r.outcome.holdoutScore ?? r.outcome.searchScore\n if (typeof score !== 'number' || !Number.isFinite(score)) continue\n const baseScore = baseline.get(`${sid}::${r.seed}`)\n if (typeof baseScore !== 'number') continue\n const arr = byCandidate.get(r.candidateId) ?? []\n arr.push(score - baseScore)\n byCandidate.set(r.candidateId, arr)\n }\n return [...byCandidate.entries()].map(([candidateId, deltas]) => ({ candidateId, deltas }))\n}\n\nfunction buildSummary(args: {\n campaign: EvalCampaignResult\n preferences: PreferenceExtractionReport\n interimConfidence: InterimReleaseConfidence | null\n rewardHacking: RewardHackingReport\n predictiveValidity: RubricPredictiveValidityReport | null\n}): string {\n const c = args.campaign\n const lines = [\n `${c.campaignId}: ${c.runs.length} successful runs / ${c.failedRuns.length} failed (fingerprint ${c.campaignFingerprint.slice(0, 12)}…)`,\n `preferences: ${args.preferences.pairs.length} (${args.preferences.strategy}, ${args.preferences.pairsBelowMargin} below margin)`,\n ]\n if (args.interimConfidence) {\n lines.push(\n `sequential verdict: ${args.interimConfidence.recommendation.decision}` +\n (args.interimConfidence.recommendation.candidateId\n ? ` ${args.interimConfidence.recommendation.candidateId}`\n : ''),\n )\n }\n lines.push(\n `reward-hacking: ${args.rewardHacking.verdict} (${args.rewardHacking.findings.length} signals checked)`,\n )\n if (args.predictiveValidity) {\n const top = args.predictiveValidity.ranked[0]\n lines.push(\n `top-rubric: ${top?.rubric ?? 'none'} ρ=${(top?.spearman ?? 0).toFixed(2)} (${top?.verdict ?? 'no data'})`,\n )\n }\n return lines.join(' | ')\n}\n\n// Re-export `runEvalCampaign` so consumers can pick the lower-level\n// primitive without flipping import paths.\nexport { runEvalCampaign } from '../eval-campaign'\n"],"mappings":"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","names":["rewardOf","firstPassK","makeRng","rewardOf","reward"]}