@axlsdk/eval 0.24.3 → 0.25.1
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.
- package/dist/{chunk-HKEAPM4B.js → chunk-F4MJ26YK.js} +33 -2
- package/dist/chunk-F4MJ26YK.js.map +1 -0
- package/dist/cli.cjs +27 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +25 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -4
- package/dist/index.d.ts +17 -4
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-HKEAPM4B.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -652,15 +652,16 @@ type ModelTimingStats = {
|
|
|
652
652
|
* flattened to `EvalItem.error`. Populated on `failed` items only.
|
|
653
653
|
*
|
|
654
654
|
* When a `ProviderError` is found — the thrown value itself or the first one
|
|
655
|
-
* down its `cause` chain — every field comes from it. Otherwise
|
|
656
|
-
*
|
|
657
|
-
* the
|
|
655
|
+
* down its `cause` chain — every field comes from it. Otherwise a `TimeoutError`
|
|
656
|
+
* contributes only finite numeric breakdown fields. Other errors contribute
|
|
657
|
+
* only the thrown value's `name`. This record never copies an error body or
|
|
658
|
+
* message: either can echo prompt text and is redaction-eligible.
|
|
658
659
|
* `EvalItem.error` keeps the error message as before, which for some providers
|
|
659
660
|
* (a non-JSON error response) embeds the response text — that is outside this
|
|
660
661
|
* record's guarantee.
|
|
661
662
|
*/
|
|
662
663
|
type EvalItemFailure = {
|
|
663
|
-
/** `'ProviderError'`
|
|
664
|
+
/** `'ProviderError'` or `'TimeoutError'` when found, else the thrown value's own `name`. */
|
|
664
665
|
name: string;
|
|
665
666
|
/** Adapter/profile name, e.g. `'openai'`. */
|
|
666
667
|
provider?: string;
|
|
@@ -670,6 +671,18 @@ type EvalItemFailure = {
|
|
|
670
671
|
retryable?: boolean;
|
|
671
672
|
/** Provider request id, when the response carried one. */
|
|
672
673
|
requestId?: string;
|
|
674
|
+
/** Wall time when the ask timed out; absent when no breakdown was reported. */
|
|
675
|
+
elapsedMs?: number;
|
|
676
|
+
/** Graceful work budget consumed after excluded waits. */
|
|
677
|
+
chargedMs?: number;
|
|
678
|
+
/** Reported governor wait summed over completed provider turns (diagnostic only). */
|
|
679
|
+
queuedMs?: number;
|
|
680
|
+
/** Failed provider attempts and non-governor retry backoff. */
|
|
681
|
+
retryMs?: number;
|
|
682
|
+
/** Provider service time. */
|
|
683
|
+
wireMs?: number;
|
|
684
|
+
/** Remaining runtime, gate, and tool time. */
|
|
685
|
+
otherMs?: number;
|
|
673
686
|
};
|
|
674
687
|
type EvalItem = {
|
|
675
688
|
input: unknown;
|
package/dist/index.d.ts
CHANGED
|
@@ -652,15 +652,16 @@ type ModelTimingStats = {
|
|
|
652
652
|
* flattened to `EvalItem.error`. Populated on `failed` items only.
|
|
653
653
|
*
|
|
654
654
|
* When a `ProviderError` is found — the thrown value itself or the first one
|
|
655
|
-
* down its `cause` chain — every field comes from it. Otherwise
|
|
656
|
-
*
|
|
657
|
-
* the
|
|
655
|
+
* down its `cause` chain — every field comes from it. Otherwise a `TimeoutError`
|
|
656
|
+
* contributes only finite numeric breakdown fields. Other errors contribute
|
|
657
|
+
* only the thrown value's `name`. This record never copies an error body or
|
|
658
|
+
* message: either can echo prompt text and is redaction-eligible.
|
|
658
659
|
* `EvalItem.error` keeps the error message as before, which for some providers
|
|
659
660
|
* (a non-JSON error response) embeds the response text — that is outside this
|
|
660
661
|
* record's guarantee.
|
|
661
662
|
*/
|
|
662
663
|
type EvalItemFailure = {
|
|
663
|
-
/** `'ProviderError'`
|
|
664
|
+
/** `'ProviderError'` or `'TimeoutError'` when found, else the thrown value's own `name`. */
|
|
664
665
|
name: string;
|
|
665
666
|
/** Adapter/profile name, e.g. `'openai'`. */
|
|
666
667
|
provider?: string;
|
|
@@ -670,6 +671,18 @@ type EvalItemFailure = {
|
|
|
670
671
|
retryable?: boolean;
|
|
671
672
|
/** Provider request id, when the response carried one. */
|
|
672
673
|
requestId?: string;
|
|
674
|
+
/** Wall time when the ask timed out; absent when no breakdown was reported. */
|
|
675
|
+
elapsedMs?: number;
|
|
676
|
+
/** Graceful work budget consumed after excluded waits. */
|
|
677
|
+
chargedMs?: number;
|
|
678
|
+
/** Reported governor wait summed over completed provider turns (diagnostic only). */
|
|
679
|
+
queuedMs?: number;
|
|
680
|
+
/** Failed provider attempts and non-governor retry backoff. */
|
|
681
|
+
retryMs?: number;
|
|
682
|
+
/** Provider service time. */
|
|
683
|
+
wireMs?: number;
|
|
684
|
+
/** Remaining runtime, gate, and tool time. */
|
|
685
|
+
otherMs?: number;
|
|
673
686
|
};
|
|
674
687
|
type EvalItem = {
|
|
675
688
|
input: unknown;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axlsdk/eval",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Evaluation framework for Axl agentic workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dist"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@axlsdk/axl": "0.
|
|
28
|
+
"@axlsdk/axl": "0.25.1"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"zod": "^4.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bootstrap.ts","../src/utils.ts","../src/accounting.ts","../src/scorer.ts","../src/diagnostics.ts","../src/runner.ts","../src/score-item.ts","../src/compare.ts","../src/rescore.ts","../src/multi-run.ts"],"sourcesContent":["export type BootstrapCIResult = {\n /** Lower bound of the confidence interval. */\n lower: number;\n /** Upper bound of the confidence interval. */\n upper: number;\n /** Mean of the original differences. */\n mean: number;\n /** Proportion of resamples where the mean difference is negative (probability of regression). */\n pRegression: number;\n /** Proportion of resamples where the mean difference is positive (probability of improvement). */\n pImprovement: number;\n};\n\n/**\n * Compute a bootstrap confidence interval on paired differences.\n *\n * Resamples the differences array with replacement, computes the mean of each\n * resample, and returns the percentile-based confidence interval.\n */\nexport function pairedBootstrapCI(\n differences: number[],\n options?: { nResamples?: number; alpha?: number; seed?: number },\n): BootstrapCIResult {\n const n = differences.length;\n if (n === 0) return { lower: 0, upper: 0, mean: 0, pRegression: 0, pImprovement: 0 };\n\n const nResamples = options?.nResamples ?? 1000;\n const alpha = options?.alpha ?? 0.05;\n\n const mean = differences.reduce((a, b) => a + b, 0) / n;\n\n if (n === 1)\n return {\n lower: differences[0],\n upper: differences[0],\n mean,\n pRegression: mean < 0 ? 1 : 0,\n pImprovement: mean > 0 ? 1 : 0,\n };\n\n if (nResamples <= 0)\n return {\n lower: round(mean),\n upper: round(mean),\n mean: round(mean),\n pRegression: mean < 0 ? 1 : 0,\n pImprovement: mean > 0 ? 1 : 0,\n };\n\n // Seeded or random number generator\n const rng = options?.seed != null ? xorshift32(options.seed) : () => Math.random();\n\n const resampleMeans: number[] = new Array(nResamples);\n for (let r = 0; r < nResamples; r++) {\n let sum = 0;\n for (let i = 0; i < n; i++) {\n sum += differences[Math.floor(rng() * n)];\n }\n resampleMeans[r] = sum / n;\n }\n\n resampleMeans.sort((a, b) => a - b);\n\n const lowerIdx = Math.floor((alpha / 2) * nResamples);\n const upperIdx = Math.floor((1 - alpha / 2) * nResamples) - 1;\n\n // Count resamples below/above zero for directional probabilities\n // resampleMeans is already sorted, so binary search for zero\n let belowZero = 0;\n for (let i = 0; i < nResamples; i++) {\n if (resampleMeans[i] < 0) belowZero++;\n else break;\n }\n let aboveZero = 0;\n for (let i = nResamples - 1; i >= 0; i--) {\n if (resampleMeans[i] > 0) aboveZero++;\n else break;\n }\n\n return {\n lower: round(resampleMeans[Math.max(0, lowerIdx)]),\n upper: round(resampleMeans[Math.min(nResamples - 1, upperIdx)]),\n mean: round(mean),\n pRegression: round(belowZero / nResamples),\n pImprovement: round(aboveZero / nResamples),\n };\n}\n\nfunction round(n: number): number {\n return Math.round(n * 10000) / 10000;\n}\n\n/** Simple xorshift32 PRNG for deterministic test behavior. Returns values in [0, 1). */\nfunction xorshift32(seed: number): () => number {\n let state = seed | 0 || 1; // Ensure non-zero\n return () => {\n state ^= state << 13;\n state ^= state >> 17;\n state ^= state << 5;\n return (state >>> 0) / 0x100000000;\n };\n}\n","import type { EvalItemOutcome, ItemErrorRate } from './types.js';\n\nexport function computeStats(scores: number[]): {\n mean: number;\n min: number;\n max: number;\n p50: number;\n p95: number;\n} {\n if (scores.length === 0) return { mean: 0, min: 0, max: 0, p50: 0, p95: 0 };\n const sorted = [...scores].sort((a, b) => a - b);\n const mean = sorted.reduce((a, b) => a + b, 0) / sorted.length;\n const min = sorted[0];\n const max = sorted[sorted.length - 1];\n const p50 = sorted[Math.floor(sorted.length * 0.5)];\n const p95 = sorted[Math.floor(sorted.length * 0.95)];\n return { mean: round(mean), min: round(min), max: round(max), p50: round(p50), p95: round(p95) };\n}\n\nexport function round(n: number): number {\n return Math.round(n * 1000) / 1000;\n}\n\n/** `0.737 → '73.7%'`, `0.05 → '5%'` — one decimal, no trailing zero. */\nexport function formatPercent(rate: number): string {\n return `${Number((rate * 100).toFixed(1))}%`;\n}\n\n/** Default `failOnItemErrorRate`, shared by `runEval` and the compare floor. */\nexport const DEFAULT_ITEM_ERROR_RATE_LIMIT = 0.05;\n\n/** `true` for a usable error-rate limit: a finite number in `[0, 1]`. */\nexport function isErrorRateLimit(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1;\n}\n\n/**\n * The single item-error-rate rule, shared by `runEval` (produce time) and\n * `evaluateItemErrorRateGate` (compare time), so the two can never disagree.\n *\n * Cancelled and budget-stopped items leave the denominator: those runs are\n * reported by their own gates, and counting them here would fail a run twice\n * for one cause. Fires on strictly `>`, so a limit of `1` never fires, and a\n * run with nothing attempted never fires (and reports a rate of `0`, not NaN).\n */\nexport function evaluateItemErrorRate(\n items: Readonly<Record<EvalItemOutcome, number>>,\n count: number,\n limit: number,\n): ItemErrorRate {\n const failed = items.failed;\n const attempted = count - items.cancelled - items.budget_skipped - items.budget_interrupted;\n const rate = attempted > 0 ? failed / attempted : 0;\n return { failed, attempted, rate, limit, exceeded: attempted > 0 && rate > limit };\n}\n\n/**\n * Count, for one scorer across a set of items, how many produced a valid score\n * (`scored`), ran-and-failed (`failed`), or were deliberately skipped by the\n * scorer's `applies` predicate (`skipped`). The single source of truth for the\n * failure-rate trust signal, shared by `runEval`, `rescore`, and `evalCompare`.\n *\n * Three discriminators on the per-scorer `scoreDetails` entry, checked in\n * precedence order so a positive `skipped` marker always wins over the\n * duration heuristic:\n * - a non-null `scores[name]` ⇒ `scored`;\n * - else `skipped === true` (the `applies` predicate returned `false`) ⇒\n * `skipped` — deliberately NOT run, so it belongs in neither the mean nor\n * the failure-rate denominator;\n * - else a `duration` ⇒ `failed` (`scoreItem` stamps it whenever a scorer\n * actually executes: success, throw, or out-of-range);\n * - else (no score, no marker, no duration) the scorer was skipped by\n * cancellation (signal aborted before it started) and belongs in no bucket.\n *\n * So `scored + failed` is the honest \"attempted\" denominator for a failure rate\n * — it excludes both `applies`-skips and cancellations and can be `<` the\n * eligible item count.\n *\n * Items whose WORKFLOW errored (`i.error`) are excluded entirely — the scorers\n * never ran for them, so they're not part of the scorer's sample either way.\n */\nexport function scorerCounts(\n items: readonly {\n error?: string;\n scores: Record<string, number | null>;\n scoreDetails?: Record<string, { duration?: number; skipped?: boolean; outcome?: string }>;\n }[],\n name: string,\n): { scored: number; failed: number; skipped: number } {\n let scored = 0;\n let failed = 0;\n let skipped = 0;\n for (const i of items) {\n if (i.error) continue;\n const detail = i.scoreDetails?.[name];\n // `outcome` is the authoritative classification, so prefer it wherever it\n // exists. The duration heuristic below reconstructs the same taxonomy from\n // the shape of a pre-0.24 artifact, and it is only ever a reconstruction:\n // it reads \"no score and no duration\" as \"never ran\", which is right for a\n // cancellation and wrong for a judge the budget stopped mid-flight. Keeping\n // two independent classifiers in the codebase means a later change to\n // either — say, recording the duration a stopped judge actually spent —\n // silently starts counting budget stops as scorer failures and trips the\n // degradation gate on a run with no scorer defect.\n if (detail?.outcome !== undefined) {\n if (detail.outcome === 'scored') scored++;\n else if (detail.outcome === 'failed') failed++;\n else if (detail.outcome === 'skipped') skipped++;\n // 'cancelled' / 'budget_skipped' / 'budget_interrupted' are in no bucket:\n // they are not a sample of the scorer's reliability.\n continue;\n }\n if (i.scores[name] != null) scored++;\n else if (detail?.skipped === true) skipped++;\n else if (detail?.duration != null) failed++;\n }\n return { scored, failed, skipped };\n}\n\n/** A scorer's failure-rate verdict against a tolerance — see {@link evaluateScorerTolerance}. */\nexport type ScorerToleranceVerdict = {\n /** `scored + failed` — the attempted denominator (excludes cancelled/never-run). */\n attempted: number;\n /** `failed / attempted`, or `0` when nothing was attempted. */\n rate: number;\n /** Over tolerance AND something was actually attempted. */\n exceeds: boolean;\n /** Nothing was attempted (`attempted === 0`) — no basis to certify a rate. */\n zeroSample: boolean;\n};\n\n/**\n * Single source of truth for the type-aware failure-rate decision, shared by the\n * source-side gate (`runEval` → `summary.degraded`) and the gate-side compare\n * gate (`evalCompare` consumers). Deterministic scorers tolerate ZERO failures\n * (a deterministic throw is a bug, not noise); LLM scorers tolerate up to `limit`\n * (`failed / attempted`). `exceeds` is never true when nothing was attempted —\n * callers decide their own policy for `zeroSample` (the runner skips it; the\n * compare gate refuses to certify a zero-sample scorer).\n */\nexport function evaluateScorerTolerance(\n scored: number,\n failed: number,\n type: 'llm' | 'deterministic',\n limit: number,\n): ScorerToleranceVerdict {\n const attempted = scored + failed;\n const rate = attempted === 0 ? 0 : failed / attempted;\n const exceeds = attempted > 0 && (type === 'deterministic' ? failed > 0 : rate > limit);\n return { attempted, rate, exceeds, zeroSample: attempted === 0 };\n}\n\n/**\n * Run `task` over `items` with a bounded worker pool, preserving input order.\n *\n * Results are written to a pre-allocated array at the item's original index, so\n * `results[i]` always corresponds to `items[i]` regardless of completion order.\n *\n * The helper does NOT catch — each `task` must own its try/catch. This is how\n * callers get `Promise.allSettled` semantics (one failing task never rejects\n * the whole batch) while still using a simple worker-pool: a task that resolves\n * (even after internally handling an error) lets the pool continue draining.\n *\n * Concurrency is clamped to `[1, items.length]` in exactly one place here, and\n * non-finite / fractional values are coerced (NaN/Infinity/`2.5` → a sane\n * integer). Callers must NOT pre-clamp with `Math.min(concurrency, items.length)`\n * and pass the result in — a user/env-supplied `0` (or `NaN` from a config like\n * `Number(process.env.X)`) would otherwise yield zero workers while items\n * remain, so `Promise.all` resolves immediately leaving the results array full\n * of holes (and the caller crashes on the `undefined` entries).\n */\nexport async function mapWithConcurrency<T, R = void>(\n items: readonly T[],\n concurrency: number,\n task: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n // Coerce non-finite (NaN/Infinity) to the floor of 1, and floor fractional\n // values, BEFORE clamping — `Math.max(1, NaN)` is `NaN`, which would make\n // `Array.from({ length: NaN })` empty and silently run zero workers.\n const requested = Number.isFinite(concurrency) ? Math.floor(concurrency) : 1;\n const workerCount = items.length === 0 ? 0 : Math.min(Math.max(1, requested), items.length);\n\n let next = 0;\n async function runNext(): Promise<void> {\n while (next < items.length) {\n const i = next++;\n results[i] = await task(items[i], i);\n }\n }\n\n await Promise.all(Array.from({ length: workerCount }, () => runNext()));\n return results;\n}\n","/**\n * Eval-side accounting helpers.\n *\n * The core owns measurement (`@axlsdk/axl`'s `Accounting`, `trackOutcome`,\n * `AdmissionController`). This module owns the three things eval adds on top:\n *\n * - **Scope plumbing** — {@link trackScope} opens a core accounting scope when\n * the runtime has one, and produces an explicitly `uninstrumented` record\n * when it does not. An eval driven by a hand-rolled runtime therefore reports\n * \"we measured nothing\", never a confident `$0`.\n * - **Reading** — {@link readAccounting} turns any `EvalResult`, including a\n * pre-0.24 artifact with no `accounting` at all, into an `EvalAccounting`.\n * An absent record reads `'unverified'` and is NEVER upgraded to `'complete'`.\n * - **Union** — {@link aggregateAccounting} folds several records\n * conservatively: sums of known spend, unions of reasons, and the WORST\n * completeness of any input.\n *\n * Everything here is pure except `trackScope`, which only delegates.\n */\n\nimport { AxlError, isAdmissionDeniedError } from '@axlsdk/axl';\nimport type {\n Accounting,\n AccountingReason,\n AccountingUsage,\n AxlEvent,\n AxlRuntime,\n CostProvenance,\n ModelTimingRollup,\n OperationKind,\n TrackExecutionMetadata,\n TrackOutcomeOptions,\n} from '@axlsdk/axl';\n\nimport type { EvalAccounting, EvalCoverage, EvalResult } from './types.js';\n\nconst USAGE_KEYS: (keyof AccountingUsage)[] = [\n 'inputTokens',\n 'outputTokens',\n 'reasoningTokens',\n 'cachedTokens',\n 'cacheWriteTokens',\n 'audioSeconds',\n];\n\nfunction zeroUsage(): AccountingUsage {\n return {\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cachedTokens: 0,\n cacheWriteTokens: 0,\n audioSeconds: 0,\n };\n}\n\n/** A scope in which nothing paid could happen — structurally complete at $0. */\nexport function emptyAccounting(): Accounting {\n return {\n version: 1,\n currency: 'USD',\n knownCost: 0,\n completeness: 'complete',\n reasons: {},\n usage: zeroUsage(),\n operations: { total: 0, settled: 0, unknown: 0, denied: 0, byKind: {} },\n breakdown: { generation: 0, judging: 0, external: 0 },\n provenance: {},\n };\n}\n\n/**\n * What a scope reports when the runtime cannot measure at all — no\n * `trackOutcome`, so no operation was ever observed.\n *\n * Deliberately `'incomplete'` with reason `'uninstrumented'` rather than a\n * confident `$0`: the work may well have spent money, we simply have no rail\n * to see it on. Callers' own `cost` values land in `callerReport`, never here.\n */\nexport function uninstrumentedAccounting(): Accounting {\n return { ...emptyAccounting(), completeness: 'incomplete', reasons: { uninstrumented: 1 } };\n}\n\n/** The outcome of {@link trackScope}: never a rejection, always an accounting. */\nexport type ScopeOutcome<T> = (\n | { status: 'fulfilled'; value: T }\n | { status: 'rejected'; error: unknown }\n) & {\n accounting: Accounting;\n /** `false` when the runtime had no `trackOutcome` (see {@link uninstrumentedAccounting}). */\n instrumented: boolean;\n metadata?: TrackExecutionMetadata;\n modelTiming?: ModelTimingRollup;\n traces?: AxlEvent[];\n};\n\n/** `true` when this runtime can open a core accounting scope. */\nexport function isInstrumented(runtime: AxlRuntime | undefined): boolean {\n return typeof runtime?.trackOutcome === 'function';\n}\n\n/**\n * Run `fn` inside a core accounting scope, or — on a runtime that has none —\n * run it plainly and report {@link uninstrumentedAccounting}.\n *\n * Never throws: the thrown value comes back verbatim under `status: 'rejected'`\n * so the caller can classify the outcome AND keep the spend that preceded it.\n */\nexport async function trackScope<T>(\n runtime: AxlRuntime,\n fn: () => Promise<T>,\n options?: TrackOutcomeOptions,\n): Promise<ScopeOutcome<T>> {\n if (!isInstrumented(runtime)) {\n try {\n return {\n status: 'fulfilled',\n value: await fn(),\n accounting: uninstrumentedAccounting(),\n instrumented: false,\n };\n } catch (error) {\n return {\n status: 'rejected',\n error,\n accounting: uninstrumentedAccounting(),\n instrumented: false,\n };\n }\n }\n const outcome = await runtime.trackOutcome(fn, options);\n return { ...outcome, instrumented: true };\n}\n\n/**\n * Parse an `EvalConfig.budget` / `--budget` string into a USD limit.\n *\n * Strict by construction: `'$1'`, `'1'` and `'$1.00'` are the accepted forms.\n * Anything else — `'free'`, `'$-1'`, `'$1.2.3'`, `'1e999'`, `''`, `'$ 1'` —\n * throws `AxlError('INVALID_BUDGET')` rather than being coerced by\n * `parseFloat`, which would happily read `'$1.2.3'` as `1.2` and run an eval\n * against a limit the user never wrote.\n */\nexport function parseBudget(budget: string): number {\n const match = typeof budget === 'string' ? budget.match(/^\\$?(\\d+(?:\\.\\d+)?)$/) : null;\n if (!match) {\n throw new AxlError(\n 'INVALID_BUDGET',\n `Invalid budget \"${String(budget)}\": expected a non-negative USD amount like \"$1\" or \"0.50\".`,\n );\n }\n const limit = Number(match[1]);\n if (!Number.isFinite(limit)) {\n throw new AxlError('INVALID_BUDGET', `Invalid budget \"${budget}\": not a finite amount.`);\n }\n return limit;\n}\n\nfunction usableCost(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : 0;\n}\n\n/**\n * Is this thrown value the budget refusing to admit a paid operation?\n *\n * Deliberately **not** `err instanceof AdmissionDeniedError`. Both packages ship\n * dual ESM+CJS, and `AxlRuntime.eval()` reaches this runner through a dynamic\n * `import('@axlsdk/eval')`. A CJS consumer therefore gets the CJS core for its\n * runtime and the ESM core inside the eval package — two copies, two distinct\n * error classes, and an `instanceof` that is `false` for a genuine denial. The\n * consequence is not a crash but something worse: a budget stop silently\n * reclassified as a workflow failure or a judge defect, which is the one\n * distinction the whole outcome taxonomy exists to preserve.\n *\n * The `code`/`name` pair is stable public surface, so it survives the copy\n * boundary. Core owns that structural check (`isAdmissionDeniedError`) because\n * the same hazard applies to any consumer; this re-export keeps eval's call\n * sites on one predicate rather than a second copy of the rule that could drift\n * from it.\n */\nexport function isAdmissionDenied(err: unknown): boolean {\n return isAdmissionDeniedError(err);\n}\n\n/**\n * Read the accounting of any `EvalResult`, including one written before this\n * field existed.\n *\n * A legacy artifact reads `'unverified'`: its `totalCost` is repeated as\n * `knownCost` for continuity, but no operation counts, no usage and no\n * generation/judging split are invented, and it is never reported as\n * `'complete'`. Turning an absent completeness into `'complete'` is exactly the\n * bug that would let a legacy run certify a cost comparison.\n *\n * **The structural identities do not hold on a synthesized record.** For a live\n * record (`'complete'` or `'incomplete'`) `provenance` sums to `knownCost` and\n * `breakdown` splits it. A legacy artifact reports only a single total, so the\n * synthesized record carries `knownCost` with an all-zero `breakdown` and\n * `provenance` — inventing a generation/judging split from a number of unknown\n * origin would be a fabrication. Consumers that render a breakdown must treat\n * `'unverified'` as \"no split available\", not as \"the split is zero\"; the\n * completeness field is what tells them which case they are in.\n */\nexport function readAccounting(result: EvalResult): EvalAccounting {\n if (result?.accounting) return result.accounting;\n const rescored = (result?.metadata as { rescored?: unknown } | undefined)?.rescored === true;\n return {\n ...emptyAccounting(),\n knownCost: usableCost(result?.totalCost),\n completeness: 'unverified',\n scope: rescored ? 'rescore' : 'run',\n };\n}\n\n/**\n * How much work the budget actually refused: cases never started or stopped\n * mid-flight, plus judges that never ran for the same reason.\n *\n * This is the quantity that makes a run short. Spend alone does not: a run can\n * settle exactly on its limit having refused nothing. Missing coverage (a\n * pre-0.24 artifact) reads `0` — an artifact that never recorded outcomes\n * cannot be used to assert that work was refused — and so do missing or\n * negative counts inside a malformed block.\n */\nexport function refusedWork(coverage: EvalCoverage | undefined): number {\n if (!coverage) return 0;\n return (\n refusedIn(coverage.items) +\n Object.values(coverage.scorers ?? {}).reduce((n, s) => n + refusedIn(s), 0)\n );\n}\n\n/**\n * The two refusal counts on one outcome block, read defensively.\n *\n * A persisted artifact reaches the browser through an unchecked cast and can be\n * hand-edited, truncated or written by a third party, so a missing block reads\n * `0` rather than throwing inside a render, and a negative count reads `0`\n * rather than cancelling out a real refusal. The Studio server reducer applies\n * exactly this rule to the same blob; agreement is asserted by the drift\n * tripwire in `packages/axl-studio/src/__tests__/eval-accounting-drift.test.ts`.\n */\nfunction refusedIn(counts: Partial<Record<string, number>> | undefined): number {\n return atLeastZero(counts?.budget_skipped) + atLeastZero(counts?.budget_interrupted);\n}\n\nfunction atLeastZero(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0;\n}\n\n/**\n * `true` when a run's budget both closed AND refused work — the one reading\n * that entitles a consumer to call the run truncated.\n *\n * A closed controller alone is the NORMAL end state of a run whose final\n * settlement lands exactly on its limit, which is exactly how `--budget` is\n * used as a CI threshold. Reporting that as a stop fails a perfect run and\n * prints a self-contradicting message (\"0 never started, 0 stopped mid-flight,\n * 2 completed … incomplete by design\").\n *\n * The argument is structural rather than an `EvalResult` because the three\n * consumers hold different things: the CLI has the result, the Studio server\n * has a persisted blob it parses itself, and the Studio browser mirror has a\n * client-side type. All three can produce `{ budget, coverage }`.\n */\nexport function isBudgetStopped(summary: {\n budget?: { status?: string } | undefined;\n coverage?: EvalCoverage | undefined;\n}): boolean {\n if (summary.budget?.status !== 'closed') return false;\n return refusedWork(summary.coverage) > 0;\n}\n\nfunction addUsage(target: AccountingUsage, source: AccountingUsage | undefined): void {\n if (!source) return;\n for (const key of USAGE_KEYS) {\n const value = source[key];\n if (typeof value === 'number' && Number.isFinite(value)) target[key] += value;\n }\n}\n\nfunction addCounts<K extends string>(\n target: Partial<Record<K, number>>,\n source: Partial<Record<K, number>> | undefined,\n): void {\n if (!source) return;\n for (const [key, count] of Object.entries(source) as [K, unknown][]) {\n if (typeof count === 'number' && Number.isFinite(count)) {\n target[key] = (target[key] ?? 0) + count;\n }\n }\n}\n\n/**\n * Fold several accounting records into one, conservatively.\n *\n * Numbers sum; reasons union with their counts; completeness takes the WORST\n * of the inputs (`unverified` > `incomplete` > `complete`), so a group\n * containing one legacy run is `unverified` as a whole and one incomplete run\n * makes the group incomplete. Inheriting the first input's flags — the bug this\n * exists to prevent — would report a group as complete because run 1 was.\n */\nexport function aggregateAccounting(inputs: readonly Accounting[]): Accounting {\n const out = emptyAccounting();\n let anyUnverified = false;\n let anyIncomplete = false;\n\n for (const input of inputs) {\n if (!input) continue;\n if (input.completeness === 'unverified') anyUnverified = true;\n else if (input.completeness === 'incomplete') anyIncomplete = true;\n\n out.knownCost += usableCost(input.knownCost);\n addUsage(out.usage, input.usage);\n addCounts<AccountingReason>(out.reasons, input.reasons);\n addCounts<OperationKind>(out.operations.byKind, input.operations?.byKind);\n addCounts<CostProvenance>(out.provenance, input.provenance);\n out.operations.total += input.operations?.total ?? 0;\n out.operations.settled += input.operations?.settled ?? 0;\n out.operations.unknown += input.operations?.unknown ?? 0;\n out.operations.denied += input.operations?.denied ?? 0;\n out.breakdown.generation += usableCost(input.breakdown?.generation);\n out.breakdown.judging += usableCost(input.breakdown?.judging);\n out.breakdown.external += usableCost(input.breakdown?.external);\n }\n\n out.completeness = anyUnverified ? 'unverified' : anyIncomplete ? 'incomplete' : 'complete';\n return out;\n}\n","import type { Provider } from '@axlsdk/axl';\n\n/** Result from a scorer that includes metadata beyond the numeric score. */\nexport type ScorerResult = {\n score: number;\n metadata?: Record<string, unknown>;\n cost?: number;\n};\n\n/** Normalize a scorer return value to a ScorerResult. */\nexport function normalizeScorerResult(result: number | ScorerResult): ScorerResult {\n return typeof result === 'number' ? { score: result } : result;\n}\n\n/**\n * Cost contract for thrown scorer errors. A scorer (e.g. `llmScorer`) that\n * incurs provider cost *before* failing attaches that cost to the thrown error\n * via {@link attachScorerErrorCost} so the eval runner still bills it. The\n * cost rides as an enumerable `cost` property (a small, stable public contract\n * custom scorers can also use). These helpers replace scattered `(err as any).cost`\n * reads/writes with one typed, finite-guarded surface.\n */\nexport function attachScorerErrorCost(err: unknown, cost: number | undefined): void {\n if (\n err &&\n typeof err === 'object' &&\n typeof cost === 'number' &&\n Number.isFinite(cost) &&\n cost >= 0\n ) {\n (err as { cost?: number }).cost = cost;\n }\n}\n\n/** Read a non-negative finite cost off a thrown scorer error, or `undefined`. */\nexport function extractScorerErrorCost(err: unknown): number | undefined {\n const v = err && typeof err === 'object' ? (err as { cost?: unknown }).cost : undefined;\n return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? v : undefined;\n}\n\n/** Context passed to scorers by the eval runner. */\nexport type ScorerContext = {\n /** Resolve a provider:model URI to a provider instance and model name. */\n resolveProvider: (modelUri: string) => { provider: Provider; model: string };\n /** Abort signal forwarded from the eval runner; scorers should pass it into provider calls. */\n signal?: AbortSignal;\n};\n\nexport type ScorerFn<TOutput, TInput, TAnnotations> = (\n output: TOutput,\n input: TInput,\n annotations?: TAnnotations,\n) => number | ScorerResult;\n\n/**\n * Applicability predicate for a conditional scorer. Returns `true` if this\n * scorer should run for the given item, `false` to skip it.\n *\n * The eval runner runs every scorer against every item, so a scorer that only\n * applies to a subset (a refusal judge for refusal-expected items, a constraint\n * judge for constrained items, …) declares its scope here. A skipped item is\n * counted as NEITHER `scored` NOR `failed` — it's excluded from the mean AND\n * from the failure-rate denominator, so a conditional scorer stays honest to\n * both. The predicate runs BEFORE the scorer body, so an inapplicable\n * `llmScorer` never makes its provider call.\n *\n * Signature mirrors {@link ScorerFn} (`output, input, annotations`). Applicability\n * usually keys off `input`/`annotations` (e.g. a flag or exercise type), but\n * `output` is available too (e.g. \"only score outputs that refused\"). A\n * predicate that THROWS is a bug, not a skip — it's recorded as a scorer\n * failure, never silently swallowed.\n *\n * The contract is `=> boolean`: return `true` to run, `false` to skip. The\n * runtime is defensively lenient — it coerces with `!verdict`, so a stray falsy\n * value (a predicate that forgot to `return`) skips rather than crashes — but\n * authors should return a real boolean. When deriving from a truthy value,\n * coerce it yourself: `(o, i, a) => !!a.constraints?.length`, not\n * `=> a.constraints?.length` (which is `number | undefined`, a type error). A\n * predicate that accidentally never returns therefore skips EVERY item — but\n * that surfaces conspicuously as a non-zero `skipped` count (the Studio \"N/A\"\n * chip), not as a silently green mean.\n */\nexport type ScorerApplies<TOutput, TInput, TAnnotations> = (\n output: TOutput,\n input: TInput,\n annotations?: TAnnotations,\n) => boolean;\n\nexport type ScorerConfig<TOutput = unknown, TInput = unknown, TAnnotations = unknown> = {\n name: string;\n description: string;\n score: ScorerFn<TOutput, TInput, TAnnotations>;\n /** Optional applicability predicate — see {@link ScorerApplies}. When it\n * returns `false`, the scorer is skipped for that item (counted as neither\n * scored nor failed). Omit to run on every item (the default).\n *\n * Declared with **method syntax** (not a function-valued property) for parity\n * with {@link Scorer.applies}, where the syntax is load-bearing: see the note\n * there and `__tests__/scorer-assignability.test-d.ts`. */\n applies?(output: TOutput, input: TInput, annotations?: TAnnotations): boolean;\n};\n\nexport type Scorer<TOutput = unknown, TInput = unknown, TAnnotations = unknown> = {\n readonly name: string;\n readonly description: string;\n readonly isLlm: boolean;\n score(\n output: TOutput,\n input: TInput,\n annotations?: TAnnotations,\n context?: ScorerContext,\n ): number | ScorerResult | Promise<number | ScorerResult>;\n /** See {@link ScorerApplies}. Evaluated by the runner before {@link score}.\n *\n * Declared with **method syntax** (not a function-valued `ScorerApplies`\n * property) so its parameters are checked bivariantly, exactly like\n * {@link score}. `EvalConfig.scorers` erases the generics to\n * `Scorer<unknown, unknown, unknown>[]`; under `strictFunctionTypes` a\n * property would make those params contravariant, so a concretely-typed\n * `Scorer<…, TInput, TAnnotations>` would no longer be assignable to that\n * array (the 0.18.1 regression). `__tests__/scorer-assignability.test-d.ts`\n * locks this in and is compiled by the `typecheck` gate. */\n applies?(output: TOutput, input: TInput, annotations?: TAnnotations): boolean;\n};\n\nexport function scorer<TOutput = unknown, TInput = unknown, TAnnotations = unknown>(\n config: ScorerConfig<TOutput, TInput, TAnnotations>,\n): Scorer<TOutput, TInput, TAnnotations> {\n return {\n name: config.name,\n description: config.description,\n isLlm: false,\n score: config.score,\n applies: config.applies,\n };\n}\n","/**\n * The eval side of opt-in request capture: the JSONL codec, the manifest an\n * `EvalResult` carries, and the bundle validation that keeps an imported\n * artifact from naming anything but an artifact id.\n *\n * The division of labour with the core is deliberate. `@axlsdk/axl` owns the\n * measurement-adjacent parts — snapshotting the request before dispatch,\n * redaction, byte bounds, the non-blocking queue, and the artifact lifecycle —\n * because all of those must hold for ANY consumer of `trackOutcome`, not just\n * evals. This module owns what is eval-shaped: which run/case/scorer a record\n * belongs to, how a run reports what it managed to capture, and what an\n * exported bundle is allowed to contain.\n *\n * `RequestRecord` is the core record type by alias rather than by copy. Two\n * hand-maintained declarations of a wire format drift, and the drift is\n * invisible until someone tries to read last month's artifact.\n */\n\nimport type { ArtifactManifest, CapturedRequestRecord } from '@axlsdk/axl';\n\n/** One JSONL line of a captured-request artifact. Codec version 1. */\nexport type RequestRecord = CapturedRequestRecord;\n\n/**\n * A pointer from an item or a scorer to one captured operation.\n *\n * `status` is the honest part: `'recorded'` is a complete request/response\n * pair, `'start_only'` is a call that never came back (the one you most want\n * to see), `'truncated'` is a record replaced by a stub because it exceeded the\n * per-record byte bound, and `'omitted'` is an operation capture never reached.\n */\nexport type OperationRef = {\n operationId: string;\n kind: 'chat' | 'stream';\n turn?: number;\n attempt?: number;\n status: 'recorded' | 'start_only' | 'truncated' | 'omitted';\n};\n\n/** What an `EvalResult` says about its captured requests. */\nexport type DiagnosticManifest = {\n version: 1;\n artifactId: string;\n fidelity: 'runtime_request';\n status: ArtifactManifest['status'];\n reason?: string;\n records: number;\n bytes: number;\n redaction: 'applied' | 'none';\n expiresAt?: number;\n};\n\n/** Per-run capture limits, as `runEval`/`rescore` accept them. */\nexport type CaptureRequestsOption =\n | boolean\n | {\n maxRecordBytes?: number;\n maxRunBytes?: number;\n maxQueueBytes?: number;\n };\n\n/**\n * Default bytes a rescore may copy from the source run's artifact.\n *\n * The same ceiling as a run's own capture budget: a rescore's copied evidence\n * should never be able to dwarf the evidence a fresh run is allowed to produce.\n */\nexport const DEFAULT_COPY_MAX_BYTES = 16 * 1024 * 1024;\n\n/** Normalize the option into explicit limits, or `undefined` when capture is off. */\nexport function resolveCaptureLimits(\n option: CaptureRequestsOption | undefined,\n): { maxRecordBytes?: number; maxRunBytes?: number; maxQueueBytes?: number } | undefined {\n if (option === undefined || option === false) return undefined;\n if (option === true) return {};\n return {\n ...(option.maxRecordBytes !== undefined ? { maxRecordBytes: option.maxRecordBytes } : {}),\n ...(option.maxRunBytes !== undefined ? { maxRunBytes: option.maxRunBytes } : {}),\n ...(option.maxQueueBytes !== undefined ? { maxQueueBytes: option.maxQueueBytes } : {}),\n };\n}\n\n/** Build the result-level manifest from the store's finalized manifest. */\nexport function toDiagnosticManifest(manifest: ArtifactManifest): DiagnosticManifest {\n return {\n version: 1,\n artifactId: manifest.artifactId,\n fidelity: 'runtime_request',\n status: manifest.status,\n ...(manifest.reason !== undefined ? { reason: manifest.reason } : {}),\n records: manifest.records,\n bytes: manifest.bytes,\n redaction: manifest.redaction,\n ...(manifest.expiresAt !== undefined ? { expiresAt: manifest.expiresAt } : {}),\n };\n}\n\n/** A manifest for a run whose capture could not be produced at all. */\nexport function unavailableManifest(artifactId: string, reason: string): DiagnosticManifest {\n return {\n version: 1,\n artifactId,\n fidelity: 'runtime_request',\n status: 'unavailable',\n reason,\n records: 0,\n bytes: 0,\n redaction: 'none',\n };\n}\n\n// ---------------------------------------------------------------------------\n// Bundle validation (import path)\n// ---------------------------------------------------------------------------\n\n/** Default ceiling on an imported `.requests.jsonl` sidecar. */\nexport const DEFAULT_SIDECAR_MAX_BYTES = 16 * 1024 * 1024;\n\n/**\n * Per-record ceiling for an imported sidecar.\n *\n * A live capture stubs any record over `maxRecordBytes` (256 KiB by default),\n * so no run this codebase produces emits a line near this. It is set well above\n * that because a caller may raise their own bound, and generously rather than\n * exactly because the point is not to police record size — it is that one\n * 15 MiB line inside a 16 MiB budget is a shape a run cannot produce, and\n * storing it means a single record the reader has to hold whole in memory.\n */\nexport const DEFAULT_SIDECAR_MAX_RECORD_BYTES = 4 * 1024 * 1024;\n\nexport type SidecarValidation =\n | { ok: true; lines: string[]; bytes: number }\n | { ok: false; reason: string };\n\n/**\n * Validate an imported JSONL sidecar before a single byte of it is stored.\n *\n * Imports are the one place where a stranger's JSON reaches this subsystem, so\n * the rules are deliberately narrow: every line must parse, must declare `v: 1`,\n * and must carry the identity fields a reader indexes on. Anything else — a\n * `file://` reference, a `path` field, a record for a codec version we cannot\n * interpret — is refused rather than stored and puzzled over later.\n *\n * Note what is NOT here: nothing in a record can name a filesystem path or a\n * URL to fetch, because the reader never dereferences anything. Records are\n * re-staged under a NEW artifact id owned by the NEW history row, so an\n * imported reference can only ever point at bytes this runtime wrote itself.\n */\nexport function validateRequestSidecar(\n text: unknown,\n options?: { maxBytes?: number; maxRecordBytes?: number },\n): SidecarValidation {\n if (typeof text !== 'string') {\n return { ok: false, reason: 'requests sidecar must be a JSONL string' };\n }\n const maxBytes = options?.maxBytes ?? DEFAULT_SIDECAR_MAX_BYTES;\n const maxRecordBytes = options?.maxRecordBytes ?? DEFAULT_SIDECAR_MAX_RECORD_BYTES;\n const bytes = Buffer.byteLength(text, 'utf-8');\n if (bytes > maxBytes) {\n return { ok: false, reason: `requests sidecar exceeds ${maxBytes} bytes` };\n }\n const lines = text.split('\\n').filter((line) => line.trim() !== '');\n for (let i = 0; i < lines.length; i++) {\n // Bounded per record, not only in total: the whole-body limit alone lets a\n // single 15 MiB line through, which no live capture can produce and which\n // every reader downstream has to hold whole.\n const lineBytes = Buffer.byteLength(lines[i], 'utf-8');\n if (lineBytes > maxRecordBytes) {\n return {\n ok: false,\n reason: `requests sidecar line ${i + 1} exceeds ${maxRecordBytes} bytes`,\n };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(lines[i]);\n } catch {\n return { ok: false, reason: `requests sidecar line ${i + 1} is not valid JSON` };\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return { ok: false, reason: `requests sidecar line ${i + 1} is not an object` };\n }\n const record = parsed as Partial<RequestRecord>;\n if (record.v !== 1) {\n return {\n ok: false,\n reason: `requests sidecar line ${i + 1} declares unsupported codec version ${String(record.v)}`,\n };\n }\n if (typeof record.operationId !== 'string' || record.operationId === '') {\n return { ok: false, reason: `requests sidecar line ${i + 1} has no operationId` };\n }\n if (record.phase !== 'start' && record.phase !== 'attempt' && record.phase !== 'end') {\n return { ok: false, reason: `requests sidecar line ${i + 1} has an unknown phase` };\n }\n }\n return { ok: true, lines, bytes };\n}\n\n/** Parse a validated sidecar into records. */\nexport function parseRequestRecords(lines: readonly string[]): RequestRecord[] {\n return lines.map((line) => JSON.parse(line) as RequestRecord);\n}\n\n/** Encode records back into a sidecar body. */\nexport function serializeRequestRecords(records: readonly RequestRecord[]): string {\n return records.map((record) => JSON.stringify(record)).join('\\n') + (records.length ? '\\n' : '');\n}\n","import type { ArtifactManifest, AxlRuntime, CallTiming, ModelTimingRollup } from '@axlsdk/axl';\nimport { AdmissionController, AxlError, ProviderError, RequestCaptureChannel } from '@axlsdk/axl';\nimport type {\n EvalAccounting,\n EvalConfig,\n EvalCoverage,\n EvalItem,\n EvalItemFailure,\n EvalItemOutcome,\n EvalResult,\n EvalSummary,\n ItemModelTiming,\n RunEvalOptions,\n ScorerOutcome,\n} from './types.js';\nimport type { ScorerContext } from './scorer.js';\nimport type { DegradedScorer } from './types.js';\nimport {\n computeStats,\n mapWithConcurrency,\n scorerCounts,\n evaluateScorerTolerance,\n evaluateItemErrorRate,\n isErrorRateLimit,\n DEFAULT_ITEM_ERROR_RATE_LIMIT,\n} from './utils.js';\nimport { scoreItem } from './score-item.js';\nimport { emptyAccounting, isAdmissionDenied, parseBudget, trackScope } from './accounting.js';\nimport {\n resolveCaptureLimits,\n toDiagnosticManifest,\n unavailableManifest,\n type OperationRef,\n} from './diagnostics.js';\nimport { randomUUID } from 'node:crypto';\n\n/**\n * Metadata keys the runtime MEASURES. A callback that returns one of these is\n * making a claim about work Axl already observed, so the claim is recorded\n * under `EvalItem.callerReport.metadata` instead of overwriting the\n * measurement. Every other caller key still merges into `item.metadata`.\n */\nconst RESERVED_METADATA_KEYS = [\n 'models',\n 'modelCallCounts',\n 'workflows',\n 'workflowCallCounts',\n 'tokens',\n 'agentCalls',\n] as const;\n\nconst ITEM_OUTCOMES: EvalItemOutcome[] = [\n 'completed',\n 'failed',\n 'cancelled',\n 'budget_skipped',\n 'budget_interrupted',\n];\n\nconst SCORER_OUTCOMES: ScorerOutcome[] = [\n 'scored',\n 'failed',\n 'skipped',\n 'cancelled',\n 'budget_skipped',\n 'budget_interrupted',\n];\n\n/**\n * Extract a user-returned cost only if it's a non-negative finite number.\n * Guards against workflows that return `{ cost: 'free' }`, `{ cost: NaN }`,\n * `{ cost: -1 }`, `{ cost: Infinity }`, etc. — the TS type says `cost?: number`\n * but at runtime we can't trust that.\n *\n * This value is recorded on `EvalItem.callerReport.cost` for inspection and is\n * NEVER summed into a total: `item.cost` and `result.totalCost` come from the\n * accounting rail. An invalid value is dropped with one `console.warn` per item\n * so the type violation stays visible.\n */\nfunction extractUserCost(result: unknown, label = 'executeWorkflow'): number | undefined {\n if (result === null || typeof result !== 'object') return undefined;\n const raw = (result as { cost?: unknown }).cost;\n if (raw === undefined) return undefined;\n if (typeof raw === 'number' && Number.isFinite(raw) && raw >= 0) return raw;\n\n console.warn(\n `[axl-eval] Ignoring invalid \\`cost\\` from ${label} return: expected non-negative finite number, got ${typeof raw === 'number' ? String(raw) : typeof raw}. Measured spend is unaffected.`,\n );\n return undefined;\n}\n\n/**\n * Extract a user-returned metadata record only if it's a plain object.\n * Rejects arrays, null, scalars, and exotic object types (Date, Map, Set,\n * Error, class instances) that would satisfy a loose `typeof === 'object'`\n * check but break `Record<string, unknown>` assumptions in downstream\n * consumers (spread, Object.entries, property access).\n */\nfunction extractUserMetadata(\n result: unknown,\n label = 'executeWorkflow',\n): Record<string, unknown> | undefined {\n if (result === null || typeof result !== 'object') return undefined;\n const meta = (result as { metadata?: unknown }).metadata;\n if (meta === undefined) return undefined;\n if (meta === null || typeof meta !== 'object' || Array.isArray(meta)) {\n console.warn(\n `[axl-eval] Ignoring invalid \\`metadata\\` from ${label} return: expected plain object, got ${meta === null ? 'null' : Array.isArray(meta) ? 'array' : typeof meta}.`,\n );\n return undefined;\n }\n // Reject exotic objects (Date, Map, Set, Error, class instances) whose\n // prototype chain differs from Object.prototype. Those pass `typeof ===\n // 'object'` but don't behave like `Record<string, unknown>`.\n const proto = Object.getPrototypeOf(meta);\n if (proto !== Object.prototype && proto !== null) {\n console.warn(\n `[axl-eval] Ignoring invalid \\`metadata\\` from ${label} return: expected plain object, got ${(proto?.constructor?.name as string | undefined) ?? 'exotic object'}.`,\n );\n return undefined;\n }\n return meta as Record<string, unknown>;\n}\n\n/** Split caller metadata into the measured keys it may not overwrite and the rest. */\nfunction splitCallerMetadata(user: Record<string, unknown> | undefined): {\n reserved?: Record<string, unknown>;\n safe?: Record<string, unknown>;\n} {\n if (!user) return {};\n let reserved: Record<string, unknown> | undefined;\n const safe: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(user)) {\n if ((RESERVED_METADATA_KEYS as readonly string[]).includes(key)) {\n (reserved ??= {})[key] = value;\n } else {\n safe[key] = value;\n }\n }\n return { reserved, ...(Object.keys(safe).length > 0 ? { safe } : {}) };\n}\n\nfunction isAbortError(err: unknown): boolean {\n return (err as { name?: string } | undefined)?.name === 'AbortError';\n}\n\n/** A staged capture: the channel records go into, and the artifact holding them. */\ntype StagedCapture = { channel: RequestCaptureChannel; artifactId: string };\n\n/**\n * Reserve the run's diagnostic artifact and open a bounded channel into it.\n *\n * Returns `undefined` when capture is off — the overwhelmingly common case,\n * which must add no artifact, no config requirement, and no field to the\n * result. When capture IS on and the runtime cannot host it, this throws\n * before any work, which is the whole reason it is called this early.\n */\nasync function stageCapture(\n runtime: AxlRuntime,\n ownerId: string,\n option: RunEvalOptions['captureRequests'],\n): Promise<StagedCapture | undefined> {\n const limits = resolveCaptureLimits(option);\n if (!limits) return undefined;\n const staged = await runtime.stageDiagnosticArtifact({ kind: 'eval', id: ownerId });\n return {\n artifactId: staged.artifactId,\n channel: new RequestCaptureChannel({\n sink: staged.sink,\n ...limits,\n // Redaction is the RUNTIME's policy, not the caller's: a run cannot opt\n // out of compliance mode by asking for diagnostics.\n redact: runtime.isRedactEnabled(),\n }),\n };\n}\n\n/**\n * Close the channel, seal the manifest, and hand back what the result should\n * say about its own capture.\n *\n * Every failure path here degrades to an `unavailable` manifest rather than\n * throwing: a diagnostics problem must not destroy a run's measured results.\n */\nasync function finishCapture(\n runtime: AxlRuntime,\n capture: StagedCapture,\n): Promise<ArtifactManifest | undefined> {\n const status = await capture.channel.close();\n try {\n return await runtime.finalizeDiagnosticArtifact(\n capture.artifactId,\n status.status,\n status.reason,\n // What the channel ACTUALLY applied. The store sees only scrubbed bytes\n // and cannot tell, so a manifest without this reports every compliance-\n // mode artifact as unredacted.\n status.redaction,\n );\n } catch {\n return undefined;\n }\n}\n\n/**\n * Discard a staged artifact whose run is about to throw.\n *\n * The lease renewal is a timer the RUNTIME holds, cleared only by finalize,\n * rollback, delete or shutdown. A run that throws between staging and\n * finalizing therefore leaves that timer renewing the lease forever, and an\n * artifact whose lease never expires can never be reclaimed by the sweeper —\n * a permanent directory per failed run, with no self-healing path. Rolling back\n * is what closes it: the bytes go, and so does the timer.\n *\n * Rollback rather than `finalize('interrupted')` because nothing will ever be\n * able to read these bytes: the run threw, so no history row will name them,\n * and only a committed artifact is readable.\n */\nasync function abandonCapture(\n runtime: AxlRuntime,\n capture: StagedCapture | undefined,\n): Promise<void> {\n if (!capture) return;\n // Close first so nothing is still writing into an artifact being removed.\n await capture.channel.close().catch(() => undefined);\n await runtime.rollbackDiagnosticArtifact(capture.artifactId).catch(() => undefined);\n}\n\n/**\n * Attach operation references to the items and judges that produced them.\n *\n * References only. Putting the records themselves on the result is exactly the\n * \"compact artifacts silently grow\" regression this feature exists to avoid --\n * the content lives in the artifact and is fetched deliberately.\n *\n * Grouping nests by case index THEN scorer name rather than using a joined\n * string key: a scorer name may contain any separator, and a mis-split would\n * silently attribute one judge's requests to another.\n */\nexport function attachOperationRefs(\n items: readonly EvalItem[],\n channel: RequestCaptureChannel,\n): void {\n const byItem = new Map<number, OperationRef[]>();\n const byScorer = new Map<number, Map<string, OperationRef[]>>();\n for (const entry of channel.operations()) {\n // An operation with no case index belongs to no item: a provider call made\n // outside the runner's per-item scopes. It stays in the artifact; the\n // result simply does not point at it.\n if (entry.caseIndex === undefined) continue;\n const ref: OperationRef = {\n operationId: entry.operationId,\n kind: entry.kind,\n ...(entry.turn !== undefined ? { turn: entry.turn } : {}),\n ...(entry.attempt !== undefined ? { attempt: entry.attempt } : {}),\n status: entry.status,\n };\n if (entry.scorer !== undefined) {\n const forItem = byScorer.get(entry.caseIndex) ?? new Map<string, OperationRef[]>();\n const list = forItem.get(entry.scorer) ?? [];\n list.push(ref);\n forItem.set(entry.scorer, list);\n byScorer.set(entry.caseIndex, forItem);\n } else {\n const list = byItem.get(entry.caseIndex) ?? [];\n list.push(ref);\n byItem.set(entry.caseIndex, list);\n }\n }\n for (const [caseIndex, operations] of byItem) {\n const item = items[caseIndex];\n if (!item) continue;\n // Merge, never replace: a rescored item already carries the ORIGINAL run's\n // generation refs, and overwriting them would silently erase the evidence\n // this rescore deliberately copied forward the moment any provider call is\n // made inside an item scope but outside a per-scorer one.\n item.diagnostics = { operations: [...(item.diagnostics?.operations ?? []), ...operations] };\n }\n for (const [caseIndex, forItem] of byScorer) {\n for (const [scorer, operations] of forItem) {\n const detail = items[caseIndex]?.scoreDetails?.[scorer];\n if (detail) detail.diagnostics = { operations };\n }\n }\n}\n\n/** How far down a `cause` chain the failure walk looks before giving up. */\nconst MAX_CAUSE_DEPTH = 8;\n\n/**\n * Is this a `ProviderError`? Structural, like `isAdmissionDenied`: core ships\n * dual ESM+CJS and `runtime.eval()` reaches this runner through a dynamic\n * import, so an error thrown by the other copy of the class fails `instanceof`.\n * The `code`/`name` pair is stable public surface on both copies.\n */\nfunction isProviderErrorLike(value: unknown): value is ProviderError {\n if (value instanceof ProviderError) return true;\n if (typeof value !== 'object' || value === null) return false;\n const candidate = value as { code?: unknown; name?: unknown };\n return candidate.code === 'PROVIDER_ERROR' && candidate.name === 'ProviderError';\n}\n\n/**\n * The structured cause of an item failure, read from the thrown value before\n * it is flattened to a message.\n *\n * Walks the thrown value and its `cause` chain — bounded in depth, because a\n * cause chain is caller-built data and may be cyclic — and takes EVERY\n * field from the first `ProviderError` it meets. With none, only the thrown\n * value's `name` is kept. Each field is copied by name with a type check, never\n * by spreading the error, so `body` (which can echo prompt text), `message` and\n * any other property never reach the `failure` record. (`item.error` keeps the\n * message as before; for some providers that includes error-response text.)\n */\nexport function describeItemFailure(thrown: unknown): EvalItemFailure | undefined {\n let current: unknown = thrown;\n // The depth bound is also the cycle guard: a chain that loops back on\n // itself is simply walked until the bound.\n for (let depth = 0; depth <= MAX_CAUSE_DEPTH; depth++) {\n if (typeof current !== 'object' || current === null) break;\n if (isProviderErrorLike(current)) {\n const { name, provider, status, retryable, requestId } = current as Partial<\n Record<'name' | 'provider' | 'status' | 'retryable' | 'requestId', unknown>\n >;\n return {\n name: typeof name === 'string' ? name : 'ProviderError',\n ...(typeof provider === 'string' ? { provider } : {}),\n ...(typeof status === 'number' && Number.isFinite(status) ? { status } : {}),\n ...(typeof retryable === 'boolean' ? { retryable } : {}),\n ...(typeof requestId === 'string' ? { requestId } : {}),\n };\n }\n current = (current as { cause?: unknown }).cause;\n }\n const name = (thrown as { name?: unknown } | null | undefined)?.name;\n return typeof thrown === 'object' && thrown !== null && typeof name === 'string' && name\n ? { name }\n : undefined;\n}\n\nexport async function runEval(\n config: EvalConfig,\n executeWorkflow: (\n input: unknown,\n runtime: AxlRuntime,\n ) => Promise<{ output: unknown; cost?: number; metadata?: Record<string, unknown> }>,\n runtime: AxlRuntime,\n options?: RunEvalOptions,\n): Promise<EvalResult> {\n const startTime = Date.now();\n const id = randomUUID();\n\n // The item gate is default-on, so an unusable limit must fail loudly and\n // before any work: warn-and-skip (the scorer gate's policy) would silently\n // switch the gate off for the whole run.\n const itemErrorRateLimit = config.failOnItemErrorRate ?? DEFAULT_ITEM_ERROR_RATE_LIMIT;\n if (!isErrorRateLimit(itemErrorRateLimit)) {\n throw new AxlError(\n 'INVALID_ITEM_ERROR_RATE',\n `Invalid failOnItemErrorRate (${String(itemErrorRateLimit)}): expected a number in [0, 1]; 1 disables the gate.`,\n );\n }\n\n // Budget FIRST (contracts §11 Q5): a malformed limit must not cost a dataset\n // load, let alone a provider call. `AdmissionController` re-validates the\n // parsed number, so `INVALID_BUDGET` is raised from exactly one place.\n const admission =\n config.budget != null\n ? new AdmissionController({ limit: parseBudget(config.budget) })\n : undefined;\n\n // Capture SECOND, for the same reason: staging throws\n // `DIAGNOSTICS_UNAVAILABLE` when the runtime has no artifact store, and the\n // only useful time to learn that is before any money is spent. The artifact\n // is owned by THIS run's id, which is also the eval history id the caller\n // will save it under.\n const capture = await stageCapture(runtime, id, options?.captureRequests);\n\n let items: Awaited<ReturnType<EvalConfig['dataset']['getItems']>>;\n try {\n items = await config.dataset.getItems();\n } catch (error) {\n // A dataset that reads a missing file, fails a schema parse, or fetches over\n // the network throws here routinely — and the artifact was staged one line\n // ago.\n await abandonCapture(runtime, capture);\n throw error;\n }\n // Snapshot dataset-load diagnostics (e.g. annotation keys the schema dropped)\n // so we can surface them on EvalResult.metadata for any consumer — mirrors the\n // console.warn the dataset already emits. Read synchronously after getItems()\n // (no await between); defensive against hand-rolled Dataset objects that don't\n // expose the field.\n const droppedAnnotationKeys = [...(config.dataset.droppedAnnotationKeys ?? [])];\n const concurrency = config.concurrency ?? 5;\n // Per-item scorer fan-out. Defaults to the same value as item `concurrency`\n // (parallel-by-default), so the worst-case concurrent judge calls is\n // `concurrency × scorerConcurrency`. The provider layer backs off on\n // 429/503/529; users who need a tighter ceiling lower item `concurrency`.\n const scorerConcurrency = config.scorerConcurrency ?? 5;\n\n // Which scheduling decision FIRST observed the budget closing. Set once and\n // never overwritten, so the artifact says what actually stopped the run\n // rather than the last thing to notice.\n let closedBy: 'case' | 'scorer' | 'operation' | undefined;\n const noteClosure = (source: 'case' | 'scorer' | 'operation'): void => {\n if (closedBy === undefined && admission?.closed) closedBy = source;\n };\n\n // Create a scorer context that LLM scorers use to resolve providers.\n const scorerContext: ScorerContext = {\n resolveProvider: (uri: string) => {\n if (typeof runtime.resolveProvider !== 'function') {\n throw new Error(\n `LLM scorers require a runtime with resolveProvider(). ` +\n `Ensure you are using a real AxlRuntime instance, not a mock.`,\n );\n }\n return runtime.resolveProvider(uri);\n },\n signal: options?.signal,\n };\n\n const evalItems: EvalItem[] = new Array(items.length);\n /** Caller claims seen this run — inspection only, never summed. */\n const callerReported = { costItems: 0, costTotal: 0, metadataItems: 0 };\n\n // Run-level per-call latency samples, keyed by effective model URI. Filled\n // synchronously from each item's tracked result and never persisted:\n // `summary.modelTiming` needs real per-call values to produce a real\n // distribution, while `item.timing` keeps only the compact sums. Items run\n // concurrently, but each append is a synchronous push, so no interleaving is\n // possible; sample ORDER across items is arbitrary and irrelevant to stats.\n const runCallSamples = new Map<string, CallTiming[]>();\n /**\n * Split a timing rollup into the compact per-item sums that get persisted and\n * the raw per-call blocks that feed `summary.modelTiming`.\n */\n function absorbTiming(rollup: ModelTimingRollup | undefined, evalItem: EvalItem): void {\n if (!rollup) return;\n const perItem: Record<string, ItemModelTiming> = {};\n for (const [model, bucket] of Object.entries(rollup)) {\n // Explicit field copy, not a rest spread: a rest spread would carry any\n // future core-side field straight into every persisted eval artifact.\n const sums: ItemModelTiming = {\n calls: bucket.calls,\n queuedMs: bucket.queuedMs,\n retryMs: bucket.retryMs,\n wireMs: bucket.wireMs,\n ...(bucket.firstTokenMs !== undefined && bucket.firstTokenCalls !== undefined\n ? { firstTokenMs: bucket.firstTokenMs, firstTokenCalls: bucket.firstTokenCalls }\n : {}),\n };\n perItem[model] = sums;\n // `samples` is opt-in on the core side and the call site below requests\n // it, so it is never actually absent here — but it is typed optional and\n // is treated that way rather than asserted, so a future caller that omits\n // the flag degrades to \"no distribution\" instead of throwing.\n const samples = bucket.samples;\n if (!samples) continue;\n // Appended one at a time rather than by spread: a long-running item can\n // hold thousands of calls, and `push(...arr)` passes them as arguments.\n const pooled = runCallSamples.get(model) ?? [];\n for (const sample of samples) pooled.push(sample);\n runCallSamples.set(model, pooled);\n }\n evalItem.timing = perItem;\n }\n\n /** A case that never started: readable identity, no operations, no spend. */\n function stub(item: (typeof items)[0], outcome: EvalItemOutcome, error: string): EvalItem {\n return {\n input: item.input,\n annotations: item.annotations,\n output: null,\n error,\n outcome,\n accounting: emptyAccounting(),\n cost: 0,\n scorerCost: 0,\n scores: {},\n };\n }\n\n async function processItem(item: (typeof items)[0], itemIndex: number): Promise<void> {\n if (options?.signal?.aborted) {\n evalItems[itemIndex] = stub(item, 'cancelled', 'Cancelled');\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n return;\n }\n\n // Case-level admission (contracts §8.1). A case that has not started is not\n // admitted at all — it costs nothing and keeps its dataset input so index\n // alignment for compare/rescore survives.\n if (admission?.closed) {\n noteClosure('case');\n evalItems[itemIndex] = stub(item, 'budget_skipped', 'Budget exceeded');\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n return;\n }\n\n const evalItem: EvalItem = {\n input: item.input,\n annotations: item.annotations,\n output: null,\n scores: {},\n };\n const itemStart = Date.now();\n\n // One scope per item wrapping BOTH generation and judging, so\n // `item.accounting` is the item's whole cost and its `breakdown` splits the\n // two. The nested scopes below give each half (and each judge) its own\n // purpose; an operation settled in a child is counted exactly once here.\n const itemOutcome = await trackScope(\n runtime,\n async () => {\n const generation = await trackScope(\n runtime,\n async () => executeWorkflow(item.input, runtime),\n {\n purpose: 'generation',\n captureTraces: options?.captureTraces === true,\n captureTimingSamples: true,\n },\n );\n\n evalItem.duration = Date.now() - itemStart;\n absorbTiming(generation.modelTiming, evalItem);\n // Traces are most valuable on the failure path, and `trackOutcome`\n // returns them for a rejected scope too — no side channel needed.\n if (generation.traces && generation.traces.length > 0) {\n evalItem.traces = generation.traces;\n }\n\n if (generation.status === 'rejected') {\n const err = generation.error;\n if (isAdmissionDenied(err)) {\n // The run budget stopped this case mid-flight. Its spend so far is\n // kept — discarding it is exactly how a budget stops being honest.\n noteClosure('operation');\n evalItem.outcome = 'budget_interrupted';\n evalItem.error = 'Budget interrupted';\n } else if (isAbortError(err)) {\n evalItem.outcome = 'cancelled';\n evalItem.error = 'Cancelled';\n } else {\n // Everything else is the workflow's own failure, INCLUDING a nested\n // `ctx.budget` block: that is user logic, not a run-budget stop.\n evalItem.outcome = 'failed';\n const failure = describeItemFailure(err);\n if (failure) evalItem.failure = failure;\n evalItem.error = err instanceof Error ? err.message : String(err);\n if (admission?.closed) noteClosure('case');\n }\n return;\n }\n\n const result = generation.value;\n evalItem.outcome = 'completed';\n evalItem.output = result.output;\n\n // Caller claims are recorded, never substituted for measurement.\n const callerCost = extractUserCost(result);\n if (callerCost !== undefined) {\n (evalItem.callerReport ??= {}).cost = callerCost;\n callerReported.costItems += 1;\n callerReported.costTotal += callerCost;\n }\n const { reserved, safe } = splitCallerMetadata(extractUserMetadata(result));\n if (reserved) {\n (evalItem.callerReport ??= {}).metadata = reserved;\n callerReported.metadataItems += 1;\n }\n if (generation.metadata || safe) {\n evalItem.metadata = { ...generation.metadata, ...safe };\n }\n\n // Attribute a crossing caused by this case's own spend before its\n // judges run, so `closedBy` names the case rather than the first judge\n // that happened to notice.\n if (admission?.closed) noteClosure('case');\n\n await scoreItem(evalItem, config.scorers, {\n runtime,\n scorerContext,\n scorerConcurrency,\n signal: options?.signal,\n admission,\n onClosure: noteClosure,\n });\n },\n {\n purpose: 'generation',\n // Every record produced anywhere under this item — workflow turns,\n // nested asks, tool continuations, judges — is stamped with the case\n // index, which is how the result can point an item at its own requests.\n ...(capture ? { captureCorrelation: { caseIndex: itemIndex } } : {}),\n },\n );\n\n if (itemOutcome.status === 'rejected') throw itemOutcome.error;\n\n evalItem.accounting = itemOutcome.accounting;\n evalItem.cost = itemOutcome.accounting.breakdown.generation;\n evalItem.scorerCost = itemOutcome.accounting.breakdown.judging;\n if (itemOutcome.accounting.completeness !== 'complete') evalItem.unpriced = true;\n\n evalItems[itemIndex] = evalItem;\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n }\n\n // One run scope owns the budget controller, so every operation anywhere\n // inside — generation, judges, tools, memory — checks the same threshold and\n // settles into the same total.\n const runOutcome = await trackScope(\n runtime,\n async () => {\n // processItem writes into the pre-allocated `evalItems` closure array (the\n // source of truth) and returns void — the pool's returned array is ignored.\n await mapWithConcurrency(items, concurrency, (item, i) => processItem(item, i));\n },\n // The capture channel is declared ONCE, at the run scope: its byte budget\n // and pending queue are per RUN, and every nested item/scorer scope\n // inherits it rather than opening a competing budget of its own.\n { admission, ...(capture ? { capture: capture.channel } : {}) },\n );\n if (runOutcome.status === 'rejected') {\n await abandonCapture(runtime, capture);\n throw runOutcome.error;\n }\n\n // Capture is closed AFTER the tracked function has already settled, so a slow\n // or hung sink can never have delayed a provider call — and the channel's own\n // bounds mean `close()` cannot wait indefinitely either.\n let diagnostics: EvalResult['diagnostics'];\n if (capture) {\n try {\n attachOperationRefs(evalItems, capture.channel);\n } catch (error) {\n await abandonCapture(runtime, capture);\n throw error;\n }\n const manifest = await finishCapture(runtime, capture);\n diagnostics = manifest\n ? toDiagnosticManifest(manifest)\n : // An artifact that was never sealed is never committed, so publishing\n // its id would point a reader at bytes the sweeper is about to reclaim.\n unavailableManifest('', 'the diagnostic artifact could not be finalized');\n }\n\n const accounting: EvalAccounting = {\n ...runOutcome.accounting,\n scope: 'run',\n ...(admission\n ? {\n budget: {\n ...admission.snapshot(),\n ...(closedBy ? { closedBy } : {}),\n },\n }\n : {}),\n ...(callerReported.costItems > 0 || callerReported.metadataItems > 0 ? { callerReported } : {}),\n };\n\n // Legacy meaning, deliberately unchanged: items carrying an `error`. That\n // includes budget stops and cancellations, which is why `summary.coverage`\n // exists — read it to separate a model failure from a truncated run.\n const failures = evalItems.filter((i) => i.error).length;\n const scorerNames = config.scorers.map((s) => s.name);\n const scorerStats: EvalSummary['scorers'] = {};\n for (const name of scorerNames) {\n const scores = evalItems\n .filter((i) => !i.error && i.scores[name] != null)\n .map((i) => i.scores[name] as number);\n const { scored, failed, skipped } = scorerCounts(evalItems, name);\n scorerStats[name] = { ...computeStats(scores), scored, failed, skipped };\n }\n\n const coverage = buildCoverage(evalItems, scorerNames);\n\n const scorerTypes: Record<string, string> = {};\n for (const s of config.scorers) {\n scorerTypes[s.name] = s.isLlm ? 'llm' : 'deterministic';\n }\n\n // Failure-rate trust signal (opt-in). When `failOnScorerErrorRate` is set, a\n // scorer is degraded when it's deterministic and failed at all (a failure is\n // a bug, not noise), OR it's an LLM judge whose failure rate over its\n // ATTEMPTED items exceeds tolerance. Budget-skipped judges never attempted\n // anything, so they are in neither side of the ratio. We never throw — the\n // result is still useful; we flag it and let the CLI/consumer decide the exit\n // code. Invalid limits are ignored loudly so a typo can't silently disable\n // the gate.\n let degraded: DegradedScorer[] | undefined;\n const rawLimit = config.failOnScorerErrorRate;\n if (rawLimit != null) {\n if (!Number.isFinite(rawLimit) || rawLimit < 0 || rawLimit > 1) {\n console.warn(\n `[axl-eval] Ignoring invalid failOnScorerErrorRate (${rawLimit}); expected a number in [0, 1].`,\n );\n } else {\n for (const name of scorerNames) {\n const stats = scorerStats[name];\n const scored = stats.scored ?? 0;\n const failed = stats.failed ?? 0;\n const type = scorerTypes[name] === 'llm' ? 'llm' : 'deterministic';\n const limit = type === 'deterministic' ? 0 : rawLimit;\n const verdict = evaluateScorerTolerance(scored, failed, type, limit);\n // A scorer that never ran (zeroSample) isn't degraded at the source — the\n // run produced no basis to judge it. (The compare gate treats zero-sample\n // differently: it refuses to certify it.)\n if (verdict.exceeds) {\n (degraded ??= []).push({ scorer: name, rate: verdict.rate, limit, type, scored, failed });\n }\n }\n }\n }\n\n // Item coverage gate (default-on). Recorded only when something failed, so a\n // clean run's summary and artifact are byte-identical to before the gate.\n const itemErrorRate = evaluateItemErrorRate(coverage.items, items.length, itemErrorRateLimit);\n\n const durations = evalItems.filter((i) => !i.error && i.duration != null).map((i) => i.duration!);\n const timing = durations.length > 0 ? computeStats(durations) : undefined;\n\n // Per-model provider latency: one distribution per field, every sample a real\n // provider call. A ten-call item contributes ten samples, so `wireMs.mean` is\n // the exact call-weighted mean and `wireMs.p95` is a genuine call percentile.\n //\n // This is why the raw `CallTiming` blocks are pooled during the run instead of\n // being re-derived from `item.timing`: per-item sums can yield a mean, but no\n // percentile that describes calls rather than items.\n //\n // `firstTokenMs` runs over the streaming calls only — a non-streaming call is\n // excluded from the sample rather than entered as `0`, which would report a\n // first-token latency no call achieved.\n const modelTiming = buildModelTiming(runCallSamples);\n\n // Aggregate per-model LLM call counts across all items\n const totalModelCalls = new Map<string, number>();\n for (const item of evalItems) {\n const itemCounts = item.metadata?.modelCallCounts;\n if (itemCounts && typeof itemCounts === 'object') {\n for (const [m, count] of Object.entries(itemCounts as Record<string, unknown>)) {\n if (typeof count === 'number')\n totalModelCalls.set(m, (totalModelCalls.get(m) ?? 0) + count);\n }\n } else {\n // Fallback: count unique models per item (for executeWorkflow that doesn't provide call counts)\n const itemModels = item.metadata?.models;\n if (Array.isArray(itemModels)) {\n for (const m of itemModels) {\n if (typeof m === 'string') totalModelCalls.set(m, (totalModelCalls.get(m) ?? 0) + 1);\n }\n }\n }\n }\n\n // models: unique list sorted by total calls (most-called first)\n // modelCounts: total LLM calls per model (e.g., { \"openai:gpt-4o\": 12, \"openai:gpt-4o-mini\": 12 })\n const modelsMeta: Record<string, unknown> = {};\n if (totalModelCalls.size > 0) {\n const sorted = [...totalModelCalls.entries()].sort((a, b) => b[1] - a[1]);\n modelsMeta.models = sorted.map(([m]) => m);\n modelsMeta.modelCounts = Object.fromEntries(sorted);\n }\n\n // Aggregate per-workflow call counts across all items (parallel to models).\n // Workflows come from the runtime's trace-event collection — callers\n // don't specify workflow names anywhere, they just appear because the\n // runtime emits workflow_start events for every execute() call.\n const totalWorkflowCalls = new Map<string, number>();\n for (const item of evalItems) {\n const itemCounts = item.metadata?.workflowCallCounts;\n if (itemCounts && typeof itemCounts === 'object') {\n for (const [w, count] of Object.entries(itemCounts as Record<string, unknown>)) {\n if (typeof count === 'number')\n totalWorkflowCalls.set(w, (totalWorkflowCalls.get(w) ?? 0) + count);\n }\n } else {\n // Fallback: count unique workflows per item\n const itemWorkflows = item.metadata?.workflows;\n if (Array.isArray(itemWorkflows)) {\n for (const w of itemWorkflows) {\n if (typeof w === 'string')\n totalWorkflowCalls.set(w, (totalWorkflowCalls.get(w) ?? 0) + 1);\n }\n }\n }\n }\n\n // Fall back to config.workflow when the callback bypassed the runtime's\n // execute() path entirely (e.g. AxlTestRuntime-based tests). This keeps the\n // metadata.workflows array non-empty for the common test-harness case.\n const workflowsMeta: Record<string, unknown> = {};\n if (totalWorkflowCalls.size > 0) {\n const sorted = [...totalWorkflowCalls.entries()].sort((a, b) => b[1] - a[1]);\n workflowsMeta.workflows = sorted.map(([w]) => w);\n workflowsMeta.workflowCounts = Object.fromEntries(sorted);\n } else if (config.workflow) {\n workflowsMeta.workflows = [config.workflow];\n workflowsMeta.workflowCounts = { [config.workflow]: items.length };\n }\n\n options?.onProgress?.({ type: 'run_done', totalItems: items.length, failures });\n\n return {\n id,\n dataset: config.dataset.name,\n metadata: {\n ...config.metadata,\n scorerTypes,\n ...modelsMeta,\n ...workflowsMeta,\n ...(droppedAnnotationKeys.length > 0 ? { droppedAnnotationKeys } : {}),\n },\n timestamp: new Date().toISOString(),\n totalCost: accounting.knownCost,\n ...(accounting.completeness !== 'complete' ? { unpriced: true as const } : {}),\n accounting,\n ...(diagnostics ? { diagnostics } : {}),\n duration: Date.now() - startTime,\n items: evalItems,\n summary: {\n count: items.length,\n failures,\n coverage,\n scorers: scorerStats,\n timing,\n ...(modelTiming ? { modelTiming } : {}),\n ...(degraded ? { degraded } : {}),\n ...(itemErrorRate.failed > 0 ? { itemErrorRate } : {}),\n },\n };\n}\n\n/**\n * Count every item and every scorer into its outcome bucket, with all keys\n * present (including zeros) so a consumer can render \"0 budget-skipped\" without\n * inferring it from an absent key.\n *\n * Shared with `rescore`, which produces the same discriminants.\n */\nexport function buildCoverage(\n items: readonly EvalItem[],\n scorerNames: readonly string[],\n): EvalCoverage {\n const coverage: EvalCoverage = {\n items: Object.fromEntries(ITEM_OUTCOMES.map((o) => [o, 0])) as EvalCoverage['items'],\n scorers: {},\n };\n for (const name of scorerNames) {\n coverage.scorers[name] = Object.fromEntries(SCORER_OUTCOMES.map((o) => [o, 0])) as Record<\n ScorerOutcome,\n number\n >;\n }\n for (const item of items) {\n // A legacy-shaped item (no `outcome`) is classified by its error, so a\n // reconstructed result still counts consistently.\n const outcome = item.outcome ?? (item.error ? 'failed' : 'completed');\n if (coverage.items[outcome] !== undefined) coverage.items[outcome] += 1;\n for (const name of scorerNames) {\n const detail = item.scoreDetails?.[name];\n if (!detail?.outcome) continue;\n const bucket = coverage.scorers[name];\n if (bucket[detail.outcome] !== undefined) bucket[detail.outcome] += 1;\n }\n }\n return coverage;\n}\n\n/** Per-model per-call distributions from the pooled raw timing blocks. */\nfunction buildModelTiming(\n runCallSamples: Map<string, CallTiming[]>,\n): EvalSummary['modelTiming'] | undefined {\n if (runCallSamples.size === 0) return undefined;\n return Object.fromEntries(\n [...runCallSamples.entries()].map(([model, samples]) => {\n const firstToken = samples.map((s) => s.firstTokenMs).filter((v): v is number => v != null);\n return [\n model,\n {\n calls: samples.length,\n wireMs: computeStats(samples.map((s) => s.wireMs)),\n queuedMs: computeStats(samples.map((s) => s.queuedMs)),\n retryMs: computeStats(samples.map((s) => s.retryMs)),\n // Custom providers may omit the optional field; that call adds 0.\n rateLimitRetries: samples.reduce((sum, s) => sum + (s.rateLimitRetries ?? 0), 0),\n ...(firstToken.length > 0\n ? { firstTokenMs: computeStats(firstToken), firstTokenCalls: firstToken.length }\n : {}),\n },\n ];\n }),\n );\n}\n","import type { AdmissionController, AxlRuntime } from '@axlsdk/axl';\n\nimport type { Scorer, ScorerContext } from './scorer.js';\nimport { normalizeScorerResult, extractScorerErrorCost } from './scorer.js';\nimport type { EvalItem, ScorerDetail, ScorerOutcome } from './types.js';\nimport { round, mapWithConcurrency } from './utils.js';\nimport { isAdmissionDenied, trackScope } from './accounting.js';\n\n/**\n * Render a dataset input for an error message without ever throwing.\n *\n * `JSON.stringify` throws on a circular reference and on a `BigInt`, and this\n * runs on the path that reports a DIFFERENT failure — so a serialization throw\n * here would replace a useful \"scorer returned 7\" message with an unrelated\n * TypeError. Long inputs are truncated because this string lands in\n * `item.scorerErrors`, which is persisted per item.\n */\nfunction describeInput(input: unknown): string {\n let rendered: string;\n try {\n rendered = JSON.stringify(input) ?? String(input);\n } catch {\n rendered = '[unserializable input]';\n }\n return rendered.length > 200 ? `${rendered.slice(0, 200)}…` : rendered;\n}\n\n/** The subset of an `EvalItem` that `scoreItem` reads and mutates. */\ntype ScorableItem = Pick<\n EvalItem,\n 'input' | 'output' | 'annotations' | 'scores' | 'scoreDetails' | 'scorerErrors' | 'scorerCost'\n>;\n\n/** Everything the scoring loop needs from its caller (`runEval` or `rescore`). */\nexport type ScoreItemContext = {\n /** Used to open one accounting scope per scorer, so judging spend is\n * attributable to the judge that incurred it. */\n runtime: AxlRuntime;\n scorerContext: ScorerContext;\n scorerConcurrency: number;\n signal?: AbortSignal;\n /** The run's spend threshold, when one is configured. A closed controller\n * stops PAID judges from starting; deterministic ones still run. */\n admission?: AdmissionController;\n /** Called when this loop is the first place a budget closure was observed. */\n onClosure?: (source: 'scorer' | 'operation') => void;\n};\n\n/**\n * Score one item's `output` with every scorer, running up to\n * `scorerConcurrency` of them at once. Mutates `item.scores`,\n * `item.scoreDetails` and `item.scorerErrors` in place.\n *\n * This is the single source of truth for the scoring inner loop, shared by\n * `runEval` and `rescore`.\n *\n * ## Measurement\n *\n * Each scorer runs in its own accounting scope with `purpose: 'judging'`, so\n * `ScorerDetail.accounting` is that judge's own spend and the enclosing item /\n * run scopes see it exactly once under `breakdown.judging`. A cost the scorer\n * RETURNS is not a measurement: it is used for `ScorerDetail.cost` only when\n * the runtime measured nothing at all, and never enters any total.\n *\n * ## Determinism (independent of scorer completion order)\n * - `scores`/`scoreDetails` keys are pre-seeded in `scorers` order, so JSON key\n * order is stable and a scorer skipped by cancellation is deterministically\n * `null` rather than absent.\n * - `scorerErrors` are collected name-keyed and flattened in `scorers` order.\n *\n * ## Stopping\n * - Cancellation: a scorer not yet started when `signal` aborts is\n * `'cancelled'`; an in-flight call rejecting with an `AbortError` is too —\n * narrowed to the error identity so a genuine bug in a sibling scorer that\n * throws while another triggered the abort is still reported.\n * - Budget: a closed controller makes an LLM judge `'budget_skipped'` (never\n * started, no score, and excluded from the mean — a skipped judge must not\n * be read as having scored 0). Deterministic scorers still run, because\n * free quality signal on already-paid-for output is worth keeping; one that\n * turns out to spend hits a denied operation and is `'budget_interrupted'`.\n */\nexport async function scoreItem(\n item: ScorableItem,\n scorers: readonly Scorer<unknown, unknown, unknown>[],\n context: ScoreItemContext,\n): Promise<void> {\n const scoreDetails = (item.scoreDetails ??= {});\n for (const s of scorers) {\n item.scores[s.name] = null;\n scoreDetails[s.name] = { score: null, outcome: 'cancelled' };\n }\n\n const { runtime, scorerContext, signal, admission } = context;\n const scorerErrorsByName: Record<string, string> = {};\n\n await mapWithConcurrency(scorers, context.scorerConcurrency, async (scorer) => {\n const record = (detail: ScorerDetail, outcome: ScorerOutcome): void => {\n scoreDetails[scorer.name] = { ...detail, outcome };\n };\n\n if (signal?.aborted) {\n record({ score: null }, 'cancelled');\n return;\n }\n\n // Scheduling-level admission (contracts §8.2). A paid judge that has not\n // started yet is refused outright rather than dispatched and denied, so it\n // costs nothing and reports no duration.\n if (admission?.closed && scorer.isLlm) {\n record({ score: null }, 'budget_skipped');\n return;\n }\n\n // Applicability gate: a `false` verdict skips the scorer entirely — no\n // provider call for an llmScorer — and counts as NEITHER scored nor failed.\n // A predicate that THROWS is a bug, not a skip: it falls through to the\n // catch below and is recorded as a scorer failure.\n const scorerStart = Date.now();\n let applicable = true;\n try {\n applicable = !scorer.applies || scorer.applies(item.output, item.input, item.annotations);\n } catch (err) {\n scorerErrorsByName[scorer.name] =\n `Scorer \"${scorer.name}\" threw: ${err instanceof Error ? err.message : String(err)}`;\n record({ score: null, duration: Date.now() - scorerStart }, 'failed');\n return;\n }\n if (!applicable) {\n record({ score: null, skipped: true }, 'skipped');\n return;\n }\n\n const outcome = await trackScope(\n runtime,\n async () => scorer.score(item.output, item.input, item.annotations, scorerContext),\n // The scorer stamp is merged OVER the enclosing item's correlation, so a\n // judge's records keep the case index and add the judge's name -- which is\n // what lets `scoreDetails[name].diagnostics` point at this judge's own\n // calls rather than at the whole item's.\n { purpose: 'judging', captureCorrelation: { scorer: scorer.name } },\n );\n const duration = Date.now() - scorerStart;\n const { accounting } = outcome;\n // A caller-returned cost is a compatibility view of last resort: it is used\n // only when nothing was measured for this scorer AND the runtime has no\n // measurement rail at all. It is never summed anywhere.\n const measured = accounting.operations.total > 0 || accounting.operations.denied > 0;\n // `accounting` rides along only when this scorer's scope actually observed\n // an operation. A deterministic judge would otherwise stamp an all-zero\n // record onto every item of every run for no information — the item's own\n // accounting already covers \"nothing was measured here\".\n const withCost = (detail: ScorerDetail, callerCost: number | undefined): ScorerDetail => ({\n ...detail,\n ...(measured ? { accounting, cost: accounting.knownCost } : {}),\n ...(!measured && !outcome.instrumented && callerCost != null ? { cost: callerCost } : {}),\n });\n\n if (outcome.status === 'rejected') {\n const err = outcome.error;\n // A cancelled call is not a scoring failure — leave the pre-seeded null\n // and record nothing against the scorer's reliability.\n if ((err as { name?: string })?.name === 'AbortError') {\n record(withCost({ score: null, duration }, undefined), 'cancelled');\n return;\n }\n // A denial is the run budget stopping this judge, not a judge defect. Its\n // spend up to the denial is kept, and so is the time it spent before\n // being refused: this judge DID run, so reporting no duration would make\n // it indistinguishable from one that never started.\n if (isAdmissionDenied(err)) {\n context.onClosure?.('operation');\n record(withCost({ score: null, duration }, undefined), 'budget_interrupted');\n return;\n }\n scorerErrorsByName[scorer.name] =\n `Scorer \"${scorer.name}\" threw: ${err instanceof Error ? err.message : String(err)}`;\n record(withCost({ score: null, duration }, extractScorerErrorCost(err)), 'failed');\n if (admission?.closed) context.onClosure?.('scorer');\n return;\n }\n\n // `trackScope` cannot throw, but everything AFTER it can: a scorer may\n // return an exotic object that `normalizeScorerResult` chokes on, and the\n // out-of-range message serializes `item.input`, which throws on a circular\n // or BigInt-bearing input. Unguarded, such a throw escapes the concurrency\n // pool, the item scope and the run scope, and `runEval` loses the ENTIRE\n // run over one bad item. One scorer's failure is one scorer's failure.\n try {\n const scorerResult = normalizeScorerResult(outcome.value);\n const callerCost =\n typeof scorerResult.cost === 'number' &&\n Number.isFinite(scorerResult.cost) &&\n scorerResult.cost >= 0\n ? scorerResult.cost\n : undefined;\n\n if (\n !Number.isFinite(scorerResult.score) ||\n scorerResult.score < 0 ||\n scorerResult.score > 1\n ) {\n scorerErrorsByName[scorer.name] =\n `Scorer \"${scorer.name}\" returned out-of-range score ${scorerResult.score} for input ${describeInput(item.input)}`;\n record(\n withCost({ score: null, metadata: scorerResult.metadata, duration }, callerCost),\n 'failed',\n );\n } else {\n item.scores[scorer.name] = round(scorerResult.score);\n record(\n withCost(\n {\n score: round(scorerResult.score),\n metadata: scorerResult.metadata,\n duration,\n },\n callerCost,\n ),\n 'scored',\n );\n }\n } catch (err) {\n scorerErrorsByName[scorer.name] =\n `Scorer \"${scorer.name}\" threw: ${err instanceof Error ? err.message : String(err)}`;\n record(withCost({ score: null, duration }, undefined), 'failed');\n }\n if (admission?.closed) context.onClosure?.('scorer');\n });\n\n const orderedErrors = scorers\n .map((s) => scorerErrorsByName[s.name])\n .filter((e): e is string => e != null);\n if (orderedErrors.length > 0) item.scorerErrors = orderedErrors;\n}\n","import type {\n EvalResult,\n EvalComparison,\n EvalCompareOptions,\n EvalRegression,\n EvalImprovement,\n ItemErrorRate,\n} from './types.js';\nimport { pairedBootstrapCI } from './bootstrap.js';\nimport {\n scorerCounts,\n evaluateScorerTolerance,\n evaluateItemErrorRate,\n isErrorRateLimit,\n round,\n formatPercent,\n DEFAULT_ITEM_ERROR_RATE_LIMIT,\n} from './utils.js';\nimport { readAccounting } from './accounting.js';\nimport { buildCoverage } from './runner.js';\n\n/**\n * Decide whether two sides' costs are comparable AS SPEND. Returns `null` to\n * certify, or a human-readable refusal reason.\n *\n * Cost certification is deliberately separate from the quality gates: a legacy\n * baseline must not disable regression detection, it must only stop the tool\n * from claiming the candidate is cheaper. The four refusals, in the order a\n * reader would want to hear them:\n *\n * 1. **Not measured** — either side is `incomplete` (some operation had no\n * usable price) or `unverified` (a pre-0.24 artifact). The totals are lower\n * bounds, so their difference is not one.\n * 2. **Different scope** — a `rescore` total covers judging only. Comparing it\n * against a full run's total and reporting a saving is the headline failure\n * this exists to prevent.\n * 3. **Different case coverage** — one side skipped or failed cases the other\n * completed, so it spent less by doing less.\n * 4. **Different scorer coverage** — the same, one judge at a time.\n *\n * Cases and scorers are matched BY INDEX, which is how the rest of `evalCompare`\n * pairs them: two dataset items with identical inputs and different annotations\n * stay two distinct items rather than collapsing into one key.\n */\nfunction certifyCost(\n baselineRuns: EvalResult[],\n candidateRuns: EvalResult[],\n scorerNames: readonly string[],\n): string | null {\n for (const [side, runs] of [\n ['baseline', baselineRuns],\n ['candidate', candidateRuns],\n ] as const) {\n for (const run of runs) {\n const accounting = readAccounting(run);\n if (accounting.completeness === 'unverified') {\n return `${side} run ${run.id} carries no accounting (unverified) — its total is not a measured figure.`;\n }\n if (accounting.completeness === 'incomplete') {\n const reasons = Object.keys(accounting.reasons).join(', ') || 'unknown spend';\n return `${side} run ${run.id} has incomplete accounting (${reasons}) — its total is a lower bound.`;\n }\n }\n }\n\n // Scope is checked on EVERY run, not just the first. A multi-run side can be\n // assembled from history by `runGroupId`, and a group that mixes a run-scope\n // artifact with a judging-only rescore would otherwise pass this gate on\n // run[0] alone and certify a per-run average built from two different\n // denominators — exactly the failure this function exists to refuse.\n const scopes = new Map<string, string>();\n for (const [side, runs] of [\n ['baseline', baselineRuns],\n ['candidate', candidateRuns],\n ] as const) {\n for (const run of runs) {\n const scope = readAccounting(run).scope;\n const seen = scopes.get(side);\n if (seen !== undefined && seen !== scope) {\n return `${side} mixes accounting scopes (\"${seen}\" and \"${scope}\") — a rescore total covers judging only and cannot be averaged with a full run.`;\n }\n scopes.set(side, scope);\n }\n }\n const baselineScope = scopes.get('baseline');\n const candidateScope = scopes.get('candidate');\n if (baselineScope !== candidateScope) {\n return `accounting scope differs (baseline \"${baselineScope}\" vs candidate \"${candidateScope}\") — a rescore total covers judging only.`;\n }\n\n const runCount = Math.min(baselineRuns.length, candidateRuns.length);\n for (let r = 0; r < runCount; r++) {\n const bRun = baselineRuns[r];\n const cRun = candidateRuns[r];\n if (bRun.items.length !== cRun.items.length) {\n return `item counts differ (baseline ${bRun.items.length} vs candidate ${cRun.items.length}) — the runs did different amounts of work.`;\n }\n for (let i = 0; i < bRun.items.length; i++) {\n const bItem = bRun.items[i];\n const cItem = cRun.items[i];\n const bRan = !bItem.error;\n const cRan = !cItem.error;\n if (bRan !== cRan) {\n const stopped = bRan ? cItem : bItem;\n return `case coverage differs at item ${i}: ${bRan ? 'candidate' : 'baseline'} did not complete it (${stopped.outcome ?? stopped.error}) — the cheaper side did less work.`;\n }\n if (!bRan) continue;\n for (const name of scorerNames) {\n const bScored = bItem.scores[name] != null;\n const cScored = cItem.scores[name] != null;\n if (bScored !== cScored) {\n return `scorer coverage differs for \"${name}\" at item ${i}: only ${bScored ? 'baseline' : 'candidate'} produced a score.`;\n }\n }\n }\n }\n\n return null;\n}\n\nconst DEFAULT_LLM_THRESHOLD = 0.05;\nconst DEFAULT_DETERMINISTIC_THRESHOLD = 0;\nconst LEGACY_THRESHOLD = 0.1;\n\nfunction resolveThreshold(\n scorerName: string,\n options: EvalCompareOptions | undefined,\n metadata: Record<string, unknown>,\n): number {\n // Explicit global threshold\n if (typeof options?.thresholds === 'number') return options.thresholds;\n\n // Per-scorer threshold map\n if (options?.thresholds && typeof options.thresholds === 'object') {\n const perScorer = options.thresholds[scorerName];\n if (perScorer != null) return perScorer;\n // Fall through to auto-calibration if scorer not in map\n }\n\n // Auto-calibrate from scorerTypes metadata\n const scorerTypes = metadata.scorerTypes as Record<string, string> | undefined;\n if (scorerTypes && scorerName in scorerTypes) {\n return scorerTypes[scorerName] === 'llm'\n ? DEFAULT_LLM_THRESHOLD\n : DEFAULT_DETERMINISTIC_THRESHOLD;\n }\n\n // Legacy fallback for results without scorerTypes\n return LEGACY_THRESHOLD;\n}\n\nexport function evalCompare(\n baseline: EvalResult | EvalResult[],\n candidate: EvalResult | EvalResult[],\n options?: EvalCompareOptions,\n): EvalComparison {\n const baselineRunsRaw = Array.isArray(baseline) ? baseline : [baseline];\n const candidateRunsRaw = Array.isArray(candidate) ? candidate : [candidate];\n\n if (baselineRunsRaw.length === 0 || candidateRunsRaw.length === 0) {\n throw new Error('Cannot compare empty eval result arrays');\n }\n\n // Truncate both sides to a common run count BEFORE computing anything. The\n // paired bootstrap CI was already restricted to `min(baseline, candidate)`\n // runs (a CI over paired diffs requires equal-length sides), but means /\n // regressions / timing / cost previously used the full-length pool on each\n // side. That hybrid produced an internally inconsistent view: a 5-run\n // baseline vs 2-run candidate showed `delta = mean(5) - mean(2)` next to\n // a CI computed over only 2 paired diffs, so the user couldn't tell the\n // numbers were drawn from different samples. Truncating symmetrically\n // here keeps every per-scorer figure aligned with the CI's sample size,\n // and the `runCount` field on each side surfaces the truncation\n // explicitly so the UI can render \"n=2 of 5 pooled\".\n const runCount = Math.min(baselineRunsRaw.length, candidateRunsRaw.length);\n const baselineRuns = baselineRunsRaw.slice(0, runCount);\n const candidateRuns = candidateRunsRaw.slice(0, runCount);\n\n // Use the first run as representative for metadata, dataset, scorers.\n // `partial` detection downstream still walks the FULL pool so\n // pre-truncation history (`metadata.batchAttempted` from any pooled run)\n // is honored.\n const baselineRef = baselineRunsRaw[0];\n const candidateRef = candidateRunsRaw[0];\n\n if (baselineRef.dataset !== candidateRef.dataset) {\n throw new Error(\n `Cannot compare evals from different datasets: \"${baselineRef.dataset}\" vs \"${candidateRef.dataset}\"`,\n );\n }\n\n const baselineScorerNames = Object.keys(baselineRef.summary.scorers).sort();\n const candidateScorerNames = Object.keys(candidateRef.summary.scorers).sort();\n if (JSON.stringify(baselineScorerNames) !== JSON.stringify(candidateScorerNames)) {\n throw new Error(`Cannot compare evals with different scorers`);\n }\n\n // Collect per-item paired differences for each scorer across all runs (used for bootstrap CI).\n // For multi-run: pool differences from all (baselineRun[r].items[i], candidateRun[r].items[i]) pairs.\n const pairedDiffs: Record<string, number[]> = {};\n for (const name of baselineScorerNames) {\n pairedDiffs[name] = [];\n }\n for (let r = 0; r < runCount; r++) {\n const bRun = baselineRuns[r];\n const cRun = candidateRuns[r];\n const minLength = Math.min(bRun.items.length, cRun.items.length);\n for (let i = 0; i < minLength; i++) {\n const bItem = bRun.items[i];\n const cItem = cRun.items[i];\n if (bItem.error || cItem.error) continue;\n for (const name of baselineScorerNames) {\n const bScore = bItem.scores[name];\n const cScore = cItem.scores[name];\n if (bScore != null && cScore != null) {\n pairedDiffs[name].push(cScore - bScore);\n }\n }\n }\n }\n\n // Compute aggregate means across the truncated runs (matches the CI's sample).\n const baselineMeans: Record<string, number> = {};\n const candidateMeans: Record<string, number> = {};\n for (const name of baselineScorerNames) {\n baselineMeans[name] =\n baselineRuns.reduce((sum, r) => sum + (r.summary.scorers[name]?.mean ?? 0), 0) /\n baselineRuns.length;\n candidateMeans[name] =\n candidateRuns.reduce((sum, r) => sum + (r.summary.scorers[name]?.mean ?? 0), 0) /\n candidateRuns.length;\n }\n\n const scorers: EvalComparison['scorers'] = {};\n for (const name of baselineScorerNames) {\n const bMeanRaw = baselineMeans[name];\n const cMeanRaw = candidateMeans[name];\n const deltaRaw = cMeanRaw - bMeanRaw;\n const bMean = round(bMeanRaw);\n const cMean = round(cMeanRaw);\n const delta = round(deltaRaw);\n const deltaPercent = bMeanRaw > 0 ? round((deltaRaw / bMeanRaw) * 100) : 0;\n const threshold = resolveThreshold(name, options, baselineRef.metadata);\n\n // Per-side scored/failed over the SAME truncated pool the means/CI use, so\n // a gate (`--max-scorer-error-rate`) reads a sample consistent with the\n // displayed numbers. Sum across this side's truncated runs (the\n // `scorerCounts` helper excludes workflow-errored items and counts a\n // ran-and-failed scorer via its `scoreDetails.duration` discriminator).\n let baselineScored = 0;\n let baselineFailed = 0;\n let baselineSkipped = 0;\n for (const run of baselineRuns) {\n const c = scorerCounts(run.items, name);\n baselineScored += c.scored;\n baselineFailed += c.failed;\n baselineSkipped += c.skipped;\n }\n let candidateScored = 0;\n let candidateFailed = 0;\n let candidateSkipped = 0;\n for (const run of candidateRuns) {\n const c = scorerCounts(run.items, name);\n candidateScored += c.scored;\n candidateFailed += c.failed;\n candidateSkipped += c.skipped;\n }\n\n const entry: EvalComparison['scorers'][string] = {\n baselineMean: bMean,\n candidateMean: cMean,\n delta,\n deltaPercent,\n baselineScored,\n baselineFailed,\n candidateScored,\n candidateFailed,\n baselineSkipped,\n candidateSkipped,\n };\n\n // `n` is the PAIRED sample size — items scored on BOTH sides, the only\n // items a difference can be computed for. Always set it (even 0/1), because\n // that's exactly the asymmetric case the labeling needs to surface: the\n // displayed `delta` is built from each side's INDEPENDENT mean (over that\n // side's own scored items), while the CI below is paired. When `n` is small\n // relative to `{baseline,candidate}Scored`, the two rest on different\n // samples. The CI/significance machinery still requires >= 2 paired diffs.\n const diffs = pairedDiffs[name];\n entry.n = diffs.length;\n if (diffs.length >= 2) {\n const ci = pairedBootstrapCI(diffs);\n entry.ci = { lower: ci.lower, upper: ci.upper };\n entry.pRegression = ci.pRegression;\n entry.pImprovement = ci.pImprovement;\n // Significant when CI excludes zero AND delta exceeds practical threshold\n const ciExcludesZero = ci.lower > 0 || ci.upper < 0;\n entry.significant = ciExcludesZero && Math.abs(ci.mean) >= threshold;\n }\n\n scorers[name] = entry;\n }\n\n // Per-item regressions/improvements.\n // For multi-run: average each item's score across runs to get a stable per-item comparison.\n const regressions: EvalRegression[] = [];\n const improvements: EvalImprovement[] = [];\n\n const itemCount = Math.min(\n ...baselineRuns.map((r) => r.items.length),\n ...candidateRuns.map((r) => r.items.length),\n );\n\n for (let i = 0; i < itemCount; i++) {\n // Check if any run has an error for this item\n const hasBaselineError = baselineRuns.some((r) => r.items[i]?.error);\n const hasCandidateError = candidateRuns.some((r) => r.items[i]?.error);\n if (hasBaselineError || hasCandidateError) continue;\n\n for (const name of baselineScorerNames) {\n // Average this item's score across all runs on each side\n const bScores = baselineRuns\n .map((r) => r.items[i]?.scores[name])\n .filter((s): s is number => s != null);\n const cScores = candidateRuns\n .map((r) => r.items[i]?.scores[name])\n .filter((s): s is number => s != null);\n if (bScores.length === 0 || cScores.length === 0) continue;\n\n const bAvg = bScores.reduce((a, b) => a + b, 0) / bScores.length;\n const cAvg = cScores.reduce((a, b) => a + b, 0) / cScores.length;\n const delta = round(cAvg - bAvg);\n const threshold = resolveThreshold(name, options, baselineRef.metadata);\n if (delta < -threshold)\n regressions.push({\n itemIndex: i,\n input: baselineRef.items[i]?.input,\n scorer: name,\n baselineScore: round(bAvg),\n candidateScore: round(cAvg),\n delta,\n });\n else if (delta > threshold)\n improvements.push({\n itemIndex: i,\n input: baselineRef.items[i]?.input,\n scorer: name,\n baselineScore: round(bAvg),\n candidateScore: round(cAvg),\n delta,\n });\n }\n }\n\n // Timing comparison (average across all runs for multi-run)\n let timing: EvalComparison['timing'];\n const baselineTimings = baselineRuns\n .filter((r) => r.summary.timing)\n .map((r) => r.summary.timing!.mean);\n const candidateTimings = candidateRuns\n .filter((r) => r.summary.timing)\n .map((r) => r.summary.timing!.mean);\n if (baselineTimings.length > 0 && candidateTimings.length > 0) {\n const bMean = baselineTimings.reduce((a, b) => a + b, 0) / baselineTimings.length;\n const cMean = candidateTimings.reduce((a, b) => a + b, 0) / candidateTimings.length;\n const delta = round(cMean - bMean);\n const deltaPercent = bMean > 0 ? round(((cMean - bMean) / bMean) * 100) : 0;\n timing = { baselineMean: round(bMean), candidateMean: round(cMean), delta, deltaPercent };\n }\n\n // Cost comparison (per-run average for multi-run).\n //\n // Raw numbers are always reported; what the `certified` flag adds is whether\n // they are comparable AS SPEND. A run that stopped early is cheaper because\n // it did less work, so an uncertified saving is not a saving at all.\n let cost: EvalComparison['cost'];\n const baselineAvgCost =\n baselineRuns.reduce((sum, r) => sum + readAccounting(r).knownCost, 0) / baselineRuns.length;\n const candidateAvgCost =\n candidateRuns.reduce((sum, r) => sum + readAccounting(r).knownCost, 0) / candidateRuns.length;\n // Emit the block whenever EITHER side carries an accounting record, not only\n // when a positive number appeared. Two runs whose every model was unpriced\n // both report `knownCost: 0` with `completeness: 'incomplete'` — the most\n // uncertain comparison there is, and the one that previously printed nothing\n // at all, leaving a reader to conclude the two cost the same. A `$0.00 /\n // $0.00 (not certified: …)` row says what is actually known.\n const hasAccounting = [...baselineRuns, ...candidateRuns].some((r) => r.accounting != null);\n if (baselineAvgCost > 0 || candidateAvgCost > 0 || hasAccounting) {\n const deltaRaw = candidateAvgCost - baselineAvgCost;\n const delta = round(deltaRaw);\n // A percentage change from a zero baseline is not a number. Reporting `0`\n // (or `Infinity`) would read as \"no change\" for a run that went from free\n // to paid, so the field is explicitly null and the absolute delta stands.\n const deltaPercent = baselineAvgCost > 0 ? round((deltaRaw / baselineAvgCost) * 100) : null;\n const verdict = certifyCost(baselineRuns, candidateRuns, baselineScorerNames);\n cost = {\n baselineTotal: round(baselineAvgCost),\n candidateTotal: round(candidateAvgCost),\n delta,\n deltaPercent,\n certified: verdict === null,\n ...(verdict !== null ? { reason: verdict } : {}),\n };\n }\n\n const parts: string[] = [];\n for (const name of baselineScorerNames) {\n const s = scorers[name];\n if (Math.abs(s.delta) > 0.001) {\n const direction = s.delta > 0 ? 'improves' : 'regresses';\n const sign = s.delta > 0 ? '+' : '';\n let sigLabel = '';\n if (s.significant === true) sigLabel = ' (significant)';\n else if (s.significant === false) sigLabel = ' (not significant)';\n parts.push(\n `'${name}' ${direction} by ${sign}${s.deltaPercent.toFixed(1)}% (${s.baselineMean.toFixed(2)} -> ${s.candidateMean.toFixed(2)})${sigLabel}`,\n );\n }\n }\n if (timing && Math.abs(timing.deltaPercent) > 1) {\n const dir = timing.delta > 0 ? 'slower' : 'faster';\n parts.push(`${Math.abs(timing.deltaPercent).toFixed(0)}% ${dir}`);\n }\n // Only a CERTIFIED delta earns a place in the prose summary. \"40% cheaper\"\n // in a one-line verdict carries no room for the refusal reason, so an\n // uncertified saving printed here reads as a measured one; the structured\n // `cost` block still carries both totals and the reason for a reader who\n // wants them.\n if (cost?.certified && cost.deltaPercent !== null && Math.abs(cost.deltaPercent) > 1) {\n const dir = cost.delta > 0 ? 'more expensive' : 'cheaper';\n parts.push(`${Math.abs(cost.deltaPercent).toFixed(0)}% ${dir}`);\n }\n const summaryStr = `candidate ${parts.length > 0 ? parts.join(', ') : 'no meaningful changes'} with ${regressions.length} regressions and ${improvements.length} improvements`;\n\n // Run partial detection against the FULL pre-truncation pool. The user's\n // original selection (e.g. 5 of an attempted 10 runs) determines partial\n // status; the truncation we did above is a stats-consistency concern, not\n // a partial-batch one.\n const baselinePartial = detectPartial(baselineRunsRaw);\n const candidatePartial = detectPartial(candidateRunsRaw);\n\n return {\n baseline: {\n id: baselineRef.id,\n metadata: baselineRef.metadata,\n runCount,\n ...(baselinePartial ? { partial: baselinePartial } : {}),\n },\n candidate: {\n id: candidateRef.id,\n metadata: candidateRef.metadata,\n runCount,\n ...(candidatePartial ? { partial: candidatePartial } : {}),\n },\n scorers,\n timing,\n cost,\n regressions,\n improvements,\n summary: summaryStr,\n };\n}\n\n/**\n * Detect whether one side of a comparison was pooled from a partial batch\n * (or a user-selected subset). Returns `{ completed, attempted }` when the\n * pooled run count is less than the original batch's planned run count\n * (read from `metadata.batchAttempted` on any run in the pool); `undefined`\n * otherwise.\n *\n * The signal is the same regardless of cause (batch failed mid-way vs user\n * cherry-picked from the picker) — both result in a smaller-N pool that\n * the consumer should mark visually so the comparison isn't mistaken for\n * an apples-to-apples run.\n *\n * Walks every run looking for the first finite `batchAttempted` rather than\n * trusting `runs[0]` alone — when a user cherry-picks runs from the compare\n * picker, the array order is the user's order, so the first item may be a\n * legacy single-run with no batch metadata while a sibling carries it.\n *\n * If `runs.length > attempted` (more results than were planned), treats the\n * data as suspicious and returns `undefined` — silently marking it \"complete\"\n * would mask data corruption.\n */\nfunction detectPartial(runs: EvalResult[]): { completed: number; attempted: number } | undefined {\n if (runs.length === 0) return undefined;\n let attempted: number | undefined;\n for (const r of runs) {\n const v = r.metadata?.batchAttempted;\n if (typeof v === 'number' && Number.isFinite(v)) {\n attempted = v;\n break;\n }\n }\n if (attempted === undefined) return undefined;\n if (runs.length >= attempted) return undefined;\n return { completed: runs.length, attempted };\n}\n\n/**\n * Decide whether a comparison should be REFUSED under a gate-side scorer\n * failure-rate limit (`axl-eval compare --max-scorer-error-rate`). Pure and\n * testable — returns a human-readable refusal reason, or `null` to allow.\n *\n * Type-aware via the baseline's `scorerTypes` metadata: a scorer EXPLICITLY\n * marked `'deterministic'` tolerates ZERO failures (a deterministic throw is a\n * bug); everything else — including an unknown/absent type on a pre-`scorerTypes`\n * artifact — uses the LLM `limit`. Defaulting unknown types to LLM (the\n * permissive tier) is deliberate: classifying an old artifact's scorers as\n * deterministic would hard-fail them on the first flake, contradicting the\n * `--max-scorer-error-rate <n>` the user passed. Scorer NAMES are identical\n * across sides (enforced by `evalCompare`), so reading types from the baseline\n * is sufficient.\n *\n * Also refuses a scorer that produced ZERO scored items on a side — a mean over\n * an empty sample can't be certified. Counts come from the same truncated pool\n * `evalCompare` used for the means/CI (`baseline/candidateScored/Failed`).\n */\nexport function evaluateScorerErrorRateGate(\n comparison: EvalComparison,\n maxScorerErrorRate: number,\n): string | null {\n const scorerTypes = (comparison.baseline.metadata?.scorerTypes ?? {}) as Record<string, string>;\n for (const name of Object.keys(comparison.scorers)) {\n const s = comparison.scorers[name];\n const type = scorerTypes[name] === 'deterministic' ? 'deterministic' : 'llm';\n const limit = type === 'deterministic' ? 0 : maxScorerErrorRate;\n for (const side of ['baseline', 'candidate'] as const) {\n const scored = (side === 'baseline' ? s.baselineScored : s.candidateScored) ?? 0;\n const failed = (side === 'baseline' ? s.baselineFailed : s.candidateFailed) ?? 0;\n const skipped = (side === 'baseline' ? s.baselineSkipped : s.candidateSkipped) ?? 0;\n const verdict = evaluateScorerTolerance(scored, failed, type, limit);\n if (verdict.zeroSample) {\n // attempted === 0 means the scorer produced no valid scores AND recorded\n // no ran-and-failed attempts on this side, so a mean over an empty sample\n // can't be certified. Distinguish the likely cause: a fully `applies`-\n // skipped scorer (N/A on every item — a scope/config issue, not a fault)\n // vs. items that errored in the workflow.\n const cause =\n skipped > 0\n ? `every one of its items was N/A (the \\`applies\\` predicate skipped all ${skipped})`\n : `its items errored or produced no score`;\n return `scorer \"${name}\" has no scored items on ${side} (${cause}) — cannot certify a mean over an empty sample.`;\n }\n if (verdict.exceeds) {\n const limitStr =\n type === 'deterministic'\n ? 'deterministic zero-tolerance'\n : `${(limit * 100).toFixed(1)}%`;\n return `scorer \"${name}\" failed ${(verdict.rate * 100).toFixed(1)}% on ${side} (${failed}/${verdict.attempted}), over the ${limitStr} limit.`;\n }\n }\n }\n return null;\n}\n\n/** One compared run's item error rate — see {@link compareItemErrorRates}. */\nexport type SideItemErrorRate = {\n side: 'baseline' | 'candidate';\n /** 0-based position within the side's truncated pool. */\n runIndex: number;\n runId: string;\n /** `true` when the rate was derived from the items of a pre-0.24 artifact. */\n legacy: boolean;\n} & ItemErrorRate;\n\n/**\n * Every compared run's item error rate against `maxItemErrorRate`, over the\n * same truncated pool `evalCompare` compares (the first `min(baseline,\n * candidate)` runs of each side). Each run is evaluated INDIVIDUALLY: pooling\n * would let clean runs dilute one thinned run below the limit.\n *\n * Uses the same rule as `runEval`'s produce-time gate\n * ({@link evaluateItemErrorRate}). A pre-0.24 artifact without\n * `summary.coverage` is evaluated on a rate derived from its items with the\n * legacy rule (`outcome ?? (error ? 'failed' : 'completed')`) — never skipped,\n * which would certify exactly the thinned legacy runs this floor exists to\n * catch. A rescore artifact carries its source's item outcomes, so it is\n * evaluated on them.\n */\nexport function compareItemErrorRates(\n baseline: EvalResult | EvalResult[],\n candidate: EvalResult | EvalResult[],\n maxItemErrorRate: number = DEFAULT_ITEM_ERROR_RATE_LIMIT,\n): SideItemErrorRate[] {\n if (!isErrorRateLimit(maxItemErrorRate)) {\n throw new Error(\n `Invalid maxItemErrorRate (${String(maxItemErrorRate)}): expected a number in [0, 1].`,\n );\n }\n const baselineRuns = Array.isArray(baseline) ? baseline : [baseline];\n const candidateRuns = Array.isArray(candidate) ? candidate : [candidate];\n const runCount = Math.min(baselineRuns.length, candidateRuns.length);\n const rates: SideItemErrorRate[] = [];\n for (const [side, runs] of [\n ['baseline', baselineRuns],\n ['candidate', candidateRuns],\n ] as const) {\n for (let r = 0; r < runCount; r++) {\n const run = runs[r];\n const coverage = run.summary.coverage?.items;\n const legacy = coverage === undefined;\n const verdict = legacy\n ? evaluateItemErrorRate(\n buildCoverage(run.items, []).items,\n run.items.length,\n maxItemErrorRate,\n )\n : evaluateItemErrorRate(coverage, run.summary.count, maxItemErrorRate);\n rates.push({ side, runIndex: r, runId: run.id, legacy, ...verdict });\n }\n }\n return rates;\n}\n\n/** Human-readable description of one run's item error rate, for CLI lines. */\nexport function describeItemErrorRate(rate: SideItemErrorRate, multiRun: boolean): string {\n const which = multiRun ? ` run ${rate.runIndex + 1} (${rate.runId})` : ` (${rate.runId})`;\n const legacy = rate.legacy ? ', derived from the items of a pre-0.24 artifact' : '';\n return (\n `${rate.side}${which} item error rate ${formatPercent(rate.rate)} ` +\n `(${rate.failed}/${rate.attempted} attempted items failed${legacy})`\n );\n}\n\n/**\n * Decide whether a comparison must be REFUSED because a side lost too many\n * items (`axl-eval compare`, default-on at `0.05`, overridden by\n * `--max-item-error-rate`; `1` disables it). Pure and testable — returns a\n * human-readable refusal reason naming coverage and the side, or `null` to\n * allow. See {@link compareItemErrorRates} for the per-run rule.\n *\n * Throws on an invalid limit: the gate is default-on, so a bad value must not\n * quietly disable it.\n */\nexport function evaluateItemErrorRateGate(\n baseline: EvalResult | EvalResult[],\n candidate: EvalResult | EvalResult[],\n maxItemErrorRate: number = DEFAULT_ITEM_ERROR_RATE_LIMIT,\n): string | null {\n const rates = compareItemErrorRates(baseline, candidate, maxItemErrorRate);\n const multiRun = rates.some((r) => r.runIndex > 0);\n const over = rates.find((r) => r.exceeded);\n if (!over) return null;\n return (\n `coverage: ${describeItemErrorRate(over, multiRun)} exceeds the ` +\n `${formatPercent(maxItemErrorRate)} limit — its scores cover only the surviving items. ` +\n `Pass --max-item-error-rate <0..1> to accept a thinned side (1 disables the check).`\n );\n}\n","import type { AxlRuntime, RequestCaptureSink } from '@axlsdk/axl';\nimport { AdmissionController, RequestCaptureChannel } from '@axlsdk/axl';\nimport type { EvalAccounting, EvalItem, EvalResult, EvalSummary } from './types.js';\nimport type { Scorer, ScorerContext } from './scorer.js';\nimport { computeStats, mapWithConcurrency, scorerCounts } from './utils.js';\nimport { scoreItem } from './score-item.js';\nimport { attachOperationRefs, buildCoverage } from './runner.js';\nimport { emptyAccounting, parseBudget, trackScope } from './accounting.js';\nimport {\n DEFAULT_COPY_MAX_BYTES,\n resolveCaptureLimits,\n toDiagnosticManifest,\n unavailableManifest,\n type CaptureRequestsOption,\n} from './diagnostics.js';\nimport { randomUUID } from 'node:crypto';\n\nexport type RescoreOptions = {\n /** Item-level worker-pool size (how many saved items rescore in parallel). Default 5. */\n concurrency?: number;\n /** Per-item scorer fan-out (how many scorers run concurrently within one item).\n * Default 5 — matches `EvalConfig.scorerConcurrency`. Worst-case concurrent\n * judge calls is `concurrency × scorerConcurrency`. */\n scorerConcurrency?: number;\n /** Abort signal forwarded into ScorerContext so in-flight LLM scorer calls can\n * be cancelled mid-flight. Also checked between items to short-circuit\n * remaining work. Mirrors `RunEvalOptions.signal`. */\n signal?: AbortSignal;\n /**\n * Known-spend threshold for the NEW judging work only, e.g. `'$0.10'`.\n *\n * The source run's spend is history: it is recorded under\n * `accounting.source.generation` and is NOT counted toward this limit, so a\n * rescore budget means \"spend at most this much re-judging\", which is the\n * only question a rescore can answer. Same validation and `>=` semantics as\n * `EvalConfig.budget`.\n */\n budget?: string;\n /**\n * Carry the source run's captured requests forward into this rescore, and\n * capture the judge calls this rescore makes.\n *\n * The source artifact is COPIED rather than referenced. Reference counting\n * would make deleting the original run either impossible or silently\n * destructive to every rescore of it; copying costs bytes once and makes each\n * result independently deletable. The copy preserves the ORIGINAL operation\n * ids as provenance, so a reader can still line a record up against the run\n * that produced it — even after that run is gone.\n *\n * Both halves land in ONE artifact and share ONE `maxRunBytes` budget: the\n * copied bytes count against it, so the artifact never grows to twice the\n * bound the caller asked for. A copy that would exceed it is partial and the\n * manifest says `truncated`; a source artifact that no longer exists, or a\n * copy that fails, yields `unavailable` with `artifactId: ''` — never the\n * source's id, which this result does not own. None of it prevents the\n * numeric rescore results from being read.\n */\n captureRequests?: CaptureRequestsOption;\n};\n\n/** A rescore's live capture: the artifact, and the channel judge calls flow into. */\ntype RescoreCapture = {\n artifactId: string;\n channel: RequestCaptureChannel;\n /** Whether the source run's records were actually carried into this artifact. */\n copied: boolean;\n /** Set when the copied source records did not all fit. */\n copyTruncated?: string;\n /**\n * What the SOURCE manifest said about the bytes copied in, when there was a\n * copy. Never the current runtime's policy — see {@link finishCapture}.\n */\n carriedRedaction?: 'applied' | 'none';\n};\n\n/**\n * Share of the run byte bound the copied half may consume.\n *\n * The copy and the judging land in ONE artifact under ONE `maxRunBytes`, so an\n * unbounded copy starves the half a rescore actually produces: a source at the\n * bound would leave the first judge record to trip the limit, and the user who\n * turned capture on specifically to debug a flaky judge would get zero judge\n * records and a reason blaming the run limit. Three quarters is a margin, not a\n * measurement — large enough that the provenance is rarely cut, small enough\n * that judging always has room.\n */\nconst COPY_SHARE_OF_RUN_BOUND = 0.75;\n\nfunction describeFailure(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Is this the runtime saying it cannot host capture at all?\n *\n * Duck-typed on the code, not on `instanceof`: `@axlsdk/axl` legitimately loads\n * twice in one process, and an error thrown by copy A is not an instance of\n * copy B's `AxlError`.\n */\nfunction isDiagnosticsUnavailable(error: unknown): boolean {\n return (error as { code?: unknown } | undefined)?.code === 'DIAGNOSTICS_UNAVAILABLE';\n}\n\n/**\n * Open the rescore's capture: the source run's records copied in, and a channel\n * for the judge calls this rescore is about to make.\n *\n * Both halves live in ONE artifact deliberately. A rescore's evidence is the\n * pair — the requests that produced the outputs, and the requests that scored\n * them — and a result has exactly one `diagnostics.artifactId` to point at.\n *\n * \"Provenance must survive deletion of the source\" is the other requirement, so\n * the source is COPIED rather than referenced: deleting the original run leaves\n * this evidence intact, and the copied records keep the ORIGINAL operation ids\n * so a reader can still tell which run made each call. The manifest's\n * `copiedFrom` carries the other half of the link.\n *\n * A runtime that cannot host capture at all is the ONE failure that throws,\n * and it throws here — before a single judge call — exactly as `runEval` does.\n * Asking for evidence and silently receiving none is worse than being told, and\n * the caller can still rescore without `captureRequests`.\n *\n * Every other failure degrades — a rescore's numbers must stay readable when its\n * diagnostics are not — and every degraded manifest publishes `artifactId: ''`,\n * NEVER the source's. Naming the source would let this result's lifecycle\n * (commit, expiry, delete) reach into another run's artifact.\n */\nasync function beginCapture(\n source: EvalResult,\n ownerId: string,\n runtime: AxlRuntime,\n options: RescoreOptions | undefined,\n): Promise<{ capture?: RescoreCapture; degraded?: EvalResult['diagnostics'] }> {\n const limits = resolveCaptureLimits(options?.captureRequests);\n if (!limits) return {};\n\n const open = (\n artifactId: string,\n sink: RequestCaptureSink,\n carriedBytes: number,\n ): Omit<RescoreCapture, 'copied'> => ({\n artifactId,\n channel: new RequestCaptureChannel({\n sink,\n ...limits,\n carriedBytes,\n // Redaction is the RUNTIME's policy, not the caller's: a rescore cannot\n // opt out of compliance mode by asking for diagnostics.\n redact: runtime.isRedactEnabled(),\n }),\n });\n\n const sourceId = source.diagnostics?.artifactId;\n // Tracked outside the `try` so the degrade path can release an artifact this\n // function staged a line before it threw. Everything after a stage — building\n // the channel, reading the runtime's redact policy — is a throw site, and a\n // staged artifact nobody rolls back holds its lease for `maxHoldMs`.\n let stagedId: string | undefined;\n try {\n if (!sourceId) {\n // Nothing to carry forward, but the judging is still worth recording —\n // it is the only work a rescore actually performs.\n const staged = await runtime.stageDiagnosticArtifact({ kind: 'eval', id: ownerId });\n stagedId = staged.artifactId;\n return { capture: { ...open(staged.artifactId, staged.sink, 0), copied: false } };\n }\n // Headroom for the judging half — see COPY_SHARE_OF_RUN_BOUND.\n const runBound = limits.maxRunBytes ?? DEFAULT_COPY_MAX_BYTES;\n const maxBytes = Math.max(1, Math.floor(runBound * COPY_SHARE_OF_RUN_BOUND));\n const copied = await runtime.copyDiagnosticArtifact(\n sourceId,\n { kind: 'eval', id: ownerId },\n { maxBytes },\n );\n if (!copied) {\n return {\n degraded: unavailableManifest(\n '',\n \"the source run's captured requests are no longer available\",\n ),\n };\n }\n stagedId = copied.artifactId;\n const capture: RescoreCapture = {\n ...open(copied.artifactId, copied.sink, copied.bytes),\n copied: true,\n carriedRedaction: copied.redaction,\n };\n if (copied.truncated) {\n capture.copyTruncated =\n `the copied source records stopped at ${maxBytes} bytes, ` +\n `the share of the ${runBound} byte run limit reserved for them`;\n }\n return { capture };\n } catch (error) {\n if (stagedId !== undefined) {\n await runtime.rollbackDiagnosticArtifact(stagedId).catch(() => undefined);\n }\n if (isDiagnosticsUnavailable(error)) throw error;\n return {\n degraded: unavailableManifest(\n '',\n `the captured requests could not be carried forward: ${describeFailure(error)}`,\n ),\n };\n }\n}\n\n/**\n * Discard a staged artifact whose rescore is about to throw.\n *\n * Rollback stops the runtime's lease-renewal timer as well as removing the\n * bytes. Without it a rescore that throws mid-scoring pins its artifact\n * permanently: the sweeper only reclaims a lease that expired.\n */\nasync function abandonCapture(\n runtime: AxlRuntime,\n capture: RescoreCapture | undefined,\n): Promise<void> {\n if (!capture) return;\n await capture.channel.close().catch(() => undefined);\n await runtime.rollbackDiagnosticArtifact(capture.artifactId).catch(() => undefined);\n}\n\n/**\n * Close the channel and seal the manifest.\n *\n * A finalize that fails degrades to `artifactId: ''` for the same reason the\n * copy paths do: an artifact that was never sealed is never committed, so\n * publishing its id points a reader at bytes the sweeper is about to reclaim.\n */\nasync function finishCapture(\n runtime: AxlRuntime,\n capture: RescoreCapture,\n): Promise<EvalResult['diagnostics']> {\n const status = await capture.channel.close();\n // A complete channel over a partial copy is still a partial artifact — and a\n // truncated one over a partial copy was cut TWICE. Both reasons are kept:\n // \"the copy filled it\" and \"the judging filled it\" are different findings and\n // a reader given only the second cannot tell which half is missing.\n const reason = [capture.copyTruncated, status.reason].filter(Boolean).join('; ') || undefined;\n const truncated = capture.copyTruncated !== undefined || status.status === 'truncated';\n // Precedence, stated once: `unavailable` beats `truncated` beats `complete`.\n // A channel that went unavailable lost records the CAPTURE RAIL could not\n // write; a truncated one stopped at a bound the caller configured. Letting a\n // truncated copy overwrite an unavailable channel tells a reader their own\n // limit dropped the judge records when in fact the sink died — and the joined\n // reason, which still names the sink failure, would contradict the status\n // every Studio and CLI badge keys off (§12.3).\n const finalStatus =\n status.status === 'unavailable' ? 'unavailable' : truncated ? 'truncated' : status.status;\n // Redaction describes the BYTES, and this artifact may hold two kinds: the\n // channel's own records, scrubbed or not by this runtime's policy, and the\n // copied ones, scrubbed or not by whatever policy was in force when the\n // source was written. `applied` may only be claimed when BOTH halves are\n // scrubbed; anything else and a compliance reader exporting this artifact\n // gets raw prompts labelled as clean.\n const redaction =\n status.redaction === 'applied' && (capture.carriedRedaction ?? 'applied') === 'applied'\n ? 'applied'\n : 'none';\n try {\n const manifest = await runtime.finalizeDiagnosticArtifact(\n capture.artifactId,\n finalStatus,\n reason,\n redaction,\n );\n return toDiagnosticManifest(manifest);\n } catch {\n return unavailableManifest('', 'the diagnostic artifact could not be finalized');\n }\n}\n\n/**\n * Re-run scorers on the saved outputs of an existing eval result.\n * Preserves original input/output/annotations. Only re-runs scoring.\n *\n * ## Accounting\n *\n * A rescore opens its OWN scope (`accounting.scope === 'rescore'`) covering\n * only the judging it performs. The original run's generation spend is never\n * added to the new total — a rescore that reported the sum would make a $0.20\n * re-judge of a $0.75 run look like $0.95 of new spend. Instead the source is\n * recorded verbatim under `accounting.source`, so a reader can add them up\n * deliberately, and `source.generation` is `null` when the source artifact\n * predates accounting (never synthesized from `totalCost`).\n */\nexport async function rescore(\n result: EvalResult,\n scorers: Scorer[],\n runtime: AxlRuntime,\n options?: RescoreOptions,\n): Promise<EvalResult> {\n const startTime = Date.now();\n const rescoredId = randomUUID();\n const concurrency = options?.concurrency ?? 5;\n const scorerConcurrency = options?.scorerConcurrency ?? 5;\n // Validated before any scoring work, exactly like `EvalConfig.budget`.\n const admission =\n options?.budget != null\n ? new AdmissionController({ limit: parseBudget(options.budget) })\n : undefined;\n\n let closedBy: 'case' | 'scorer' | 'operation' | undefined;\n const noteClosure = (source: 'case' | 'scorer' | 'operation'): void => {\n if (closedBy === undefined && admission?.closed) closedBy = source;\n };\n\n const scorerContext: ScorerContext = {\n resolveProvider: (uri: string) => {\n if (typeof runtime.resolveProvider !== 'function') {\n throw new Error(\n `LLM scorers require a runtime with resolveProvider(). ` +\n `Ensure you are using a real AxlRuntime instance, not a mock.`,\n );\n }\n return runtime.resolveProvider(uri);\n },\n signal: options?.signal,\n };\n\n const rescored: EvalItem[] = new Array(result.items.length);\n\n // Opened BEFORE any scoring: the judge calls a rescore makes are the work it\n // actually performs, and capturing them afterwards would capture nothing.\n // A runtime that cannot host capture at all throws from here, before a single\n // judge call — the same contract as `runEval`, because asking for evidence\n // and silently receiving none is worse than being told.\n const { capture, degraded } = await beginCapture(result, rescoredId, runtime, options);\n // Whether the source's evidence is actually IN this rescore's artifact — not\n // whether the caller asked for it. An item ref into an artifact that was\n // swept, or into one holding only this rescore's judge calls, is a pointer a\n // reader cannot follow: Studio renders operations that cannot be fetched.\n const carryDiagnostics = capture?.copied === true;\n\n async function rescoreItem(original: EvalItem, itemIndex: number): Promise<void> {\n // Short-circuit if the rescore has been cancelled — matches runEval's\n // between-items signal check so cancellation behaves the same in both\n // paths. In-flight LLM scorer calls additionally abort via\n // scorerContext.signal → provider.chat({ signal }).\n if (options?.signal?.aborted) {\n rescored[itemIndex] = {\n input: original.input,\n annotations: original.annotations,\n output: original.output,\n error: 'cancelled',\n outcome: 'cancelled',\n accounting: emptyAccounting(),\n scores: {},\n };\n return;\n }\n\n // Pass through error items without scoring. The ORIGINAL outcome is kept:\n // whether the source case failed, was cancelled or was stopped by that\n // run's budget is a fact about that run, and a rescore does not re-litigate\n // it. Its accounting stays with the original run too.\n if (original.error) {\n const accounting = emptyAccounting();\n rescored[itemIndex] = {\n input: original.input,\n annotations: original.annotations,\n output: original.output,\n error: original.error,\n ...(original.outcome ? { outcome: original.outcome } : {}),\n // The failure cause is a fact about the source run too.\n ...(original.failure ? { failure: original.failure } : {}),\n accounting,\n // Same rule as a scored item: an item carrying `accounting` always\n // carries both compat views, so no reader falls through to the legacy\n // \"no accounting → trust the caller's number\" branch and reports the\n // SOURCE run's spend as this rescore's. A passthrough did no work, so\n // both are a measured $0; the source's spend lives in the run-level\n // `accounting.source` provenance and nowhere else.\n cost: accounting.breakdown.generation,\n scorerCost: accounting.breakdown.judging,\n scores: {},\n };\n return;\n }\n\n // Preserve per-item traces from the original run: rescore re-runs scorers\n // but leaves the workflow untouched, so the original execution traces\n // remain accurate and useful for diagnosing score changes.\n const item: EvalItem = {\n input: original.input,\n annotations: original.annotations,\n output: original.output,\n metadata: original.metadata,\n traces: original.traces,\n outcome: 'completed',\n // Carried forward VERBATIM, original operation ids included. The rescore\n // did not re-run the workflow, so these still describe the calls that\n // produced this output; reminting the ids would break the only link back\n // to the run that made them. Only carried when the source records were\n // actually copied into this rescore's artifact — a dangling reference is\n // worse than none.\n ...(carryDiagnostics && original.diagnostics ? { diagnostics: original.diagnostics } : {}),\n scores: {},\n scoreDetails: {},\n };\n\n // Same shared scoring path as runEval — determinism, cancellation, budget\n // admission and per-judge accounting all live in scoreItem.\n const itemOutcome = await trackScope(\n runtime,\n async () => {\n await scoreItem(item, scorers, {\n runtime,\n scorerContext,\n scorerConcurrency,\n signal: options?.signal,\n admission,\n onClosure: noteClosure,\n });\n },\n {\n purpose: 'judging',\n // Every record produced under this item is stamped with the case index,\n // which is how a `ScorerDetail` can point at its own judge calls.\n ...(capture ? { captureCorrelation: { caseIndex: itemIndex } } : {}),\n },\n );\n if (itemOutcome.status === 'rejected') throw itemOutcome.error;\n\n item.accounting = itemOutcome.accounting;\n // Both compat views are written whenever `accounting` is (contracts §6, Q8):\n // once an item carries accounting, `cost` is its MEASURED generation spend,\n // which for a rescore is a real, measured $0. Leaving it absent would let a\n // reader take the \"no accounting → read the legacy caller value\" branch and\n // report the source run's generation as spend this rescore incurred.\n item.cost = itemOutcome.accounting.breakdown.generation;\n item.scorerCost = itemOutcome.accounting.breakdown.judging;\n if (itemOutcome.accounting.completeness !== 'complete') item.unpriced = true;\n rescored[itemIndex] = item;\n }\n\n const runOutcome = await trackScope(\n runtime,\n async () => {\n // rescoreItem writes into the pre-allocated `rescored` closure array (the\n // source of truth) and returns void — the pool's returned array is ignored.\n await mapWithConcurrency(result.items, concurrency, (item, i) => rescoreItem(item, i));\n },\n // The channel is declared ONCE, at the run scope: its byte budget and\n // pending queue are per rescore, and every nested item/scorer scope inherits\n // it rather than opening a competing budget of its own.\n { purpose: 'judging', admission, ...(capture ? { capture: capture.channel } : {}) },\n );\n if (runOutcome.status === 'rejected') {\n // The lease renewal is a timer the runtime holds until finalize or\n // rollback. Throwing without rolling back leaves it renewing forever, and\n // an artifact whose lease never expires can never be reclaimed.\n await abandonCapture(runtime, capture);\n throw runOutcome.error;\n }\n\n // `source.generation` means the GENERATION spend this scoring rests on, so a\n // rescore of a rescore must reach past its immediate source to the original\n // run. The intermediate's own accounting is judging-only; storing it under a\n // field named `generation` would tell a reader adding it to the new total\n // that they had recovered total spend, when they would have judging twice and\n // generation never. `runId` still points at the immediate source, which is\n // the artifact this one was actually derived from.\n const sourceAccounting = result.accounting;\n const generation =\n sourceAccounting?.scope === 'rescore'\n ? (sourceAccounting.source?.generation ?? null)\n : (sourceAccounting ?? null);\n\n // Closed AFTER the tracked function settled, so a slow sink can never have\n // delayed a provider call.\n let diagnostics = degraded;\n if (capture) {\n try {\n attachOperationRefs(rescored, capture.channel);\n } catch (error) {\n await abandonCapture(runtime, capture);\n throw error;\n }\n diagnostics = await finishCapture(runtime, capture);\n }\n\n const accounting: EvalAccounting = {\n ...runOutcome.accounting,\n scope: 'rescore',\n // `?? null` is load-bearing: a legacy source has no accounting and must read\n // as \"unknown generation\", never as a synthesized complete record.\n source: { runId: result.id, generation },\n ...(admission\n ? { budget: { ...admission.snapshot(), ...(closedBy ? { closedBy } : {}) } }\n : {}),\n };\n\n const failures = rescored.filter((i) => i.error).length;\n const scorerNames = scorers.map((s) => s.name);\n const scorerStats: EvalSummary['scorers'] = {};\n for (const name of scorerNames) {\n const scores = rescored\n .filter((i) => !i.error && i.scores[name] != null)\n .map((i) => i.scores[name] as number);\n // Same scored/failed surfacing as runEval (table + Studio parity). NOTE:\n // rescore deliberately does NOT support `failOnScorerErrorRate` — it takes\n // RescoreOptions, not EvalConfig, so there's no degradation gate here. The\n // counts are informational; gating belongs to the run that produced output.\n const { scored, failed, skipped } = scorerCounts(rescored, name);\n scorerStats[name] = { ...computeStats(scores), scored, failed, skipped };\n }\n\n const scorerTypes: Record<string, string> = {};\n for (const s of scorers) {\n scorerTypes[s.name] = s.isLlm ? 'llm' : 'deterministic';\n }\n\n return {\n id: rescoredId,\n dataset: result.dataset,\n metadata: (() => {\n // Strip run group membership — rescored results are independent evaluations.\n // metadata.workflows is preserved via ...rest so the rescored result keeps\n // the same workflow attribution as the original.\n //\n // Also strip the scorer-filtered stamp: whether THIS rescore ran a subset\n // is a property of the rescore invocation, not the source run. A full\n // rescore of a `--scorers`-filtered run would otherwise inherit a stale\n // `scorerFiltered: true` + a `scorersRun` listing scorers it didn't even\n // use — falsely tripping the compare gate and the Studio banner.\n const rest: Record<string, unknown> = { ...result.metadata };\n delete rest.runGroupId;\n delete rest.runIndex;\n delete rest.scorerFiltered;\n delete rest.scorersRun;\n const merged: Record<string, unknown> = {\n ...rest,\n rescored: true,\n originalId: result.id,\n scorerTypes,\n };\n // Backward compatibility: pre-0.14 EvalResult artifacts had `workflow`\n // as a top-level string field with no `metadata.workflows`. Migrate it\n // forward so rescored results from old artifacts retain their workflow\n // attribution under the modern shape.\n if (!Array.isArray(merged.workflows)) {\n const legacyWorkflow = (result as { workflow?: unknown }).workflow;\n if (typeof legacyWorkflow === 'string' && legacyWorkflow) {\n merged.workflows = [legacyWorkflow];\n merged.workflowCounts = { [legacyWorkflow]: result.items.length };\n }\n }\n return merged;\n })(),\n timestamp: new Date().toISOString(),\n totalCost: accounting.knownCost,\n ...(accounting.completeness !== 'complete' ? { unpriced: true as const } : {}),\n accounting,\n ...(diagnostics ? { diagnostics } : {}),\n duration: Date.now() - startTime,\n items: rescored,\n summary: {\n count: result.items.length,\n failures,\n coverage: buildCoverage(rescored, scorerNames),\n scorers: scorerStats,\n // A rescore makes no generation calls, so the source run's wall-clock\n // and provider latency are still the only measurements of these items.\n // `modelTiming` cannot be rebuilt from `item.timing` (sums, not per-call\n // samples): carry both forward.\n ...(result.summary.timing ? { timing: { ...result.summary.timing } } : {}),\n ...(result.summary.modelTiming\n ? { modelTiming: structuredClone(result.summary.modelTiming) }\n : {}),\n },\n };\n}\n","import type { Accounting } from '@axlsdk/axl';\nimport type { EvalResult } from './types.js';\nimport { randomUUID } from 'node:crypto';\nimport { round } from './utils.js';\nimport { aggregateAccounting, readAccounting } from './accounting.js';\n\nexport type MultiRunSummary = {\n runGroupId: string;\n runCount: number;\n /**\n * Workflow names observed across all runs in the group, deduped and ordered\n * by first appearance. Parallel to `EvalResult.metadata.workflows`. A homogeneous\n * multi-run group produced by `axl-eval --runs N` typically has one entry;\n * heterogeneous groups (custom callbacks) can have multiple.\n */\n workflows: string[];\n dataset: string;\n /** Compatibility view: the sum of each run's `totalCost`. */\n totalCost: number;\n /**\n * The union of every run's accounting, folded conservatively: known spend and\n * operation counts sum, incompleteness reasons union, and the group takes the\n * WORST completeness in it — one legacy run makes the whole group\n * `'unverified'`, one incomplete run makes it `'incomplete'`. Inheriting\n * run[0]'s flags would report a contaminated group as clean.\n */\n accounting: Accounting;\n totalDuration: number;\n scorers: Record<\n string,\n {\n mean: number;\n std: number;\n min: number;\n max: number;\n /** Total valid scores summed across all runs in the group. */\n scored?: number;\n /** Total ran-and-failed scorer invocations summed across all runs. */\n failed?: number;\n /** Total `applies`-skipped (N/A) items summed across all runs. Excluded\n * from both the mean and the failure-rate denominator. */\n skipped?: number;\n }\n >;\n timing?: { mean: number; std: number };\n};\n\nfunction std(values: number[], mean: number): number {\n if (values.length <= 1) return 0;\n const sumSqDiffs = values.reduce((sum, v) => sum + (v - mean) ** 2, 0);\n return Math.sqrt(sumSqDiffs / (values.length - 1));\n}\n\n/**\n * Aggregate multiple eval runs into a summary with mean +/- std per scorer.\n */\nexport function aggregateRuns(runs: EvalResult[]): MultiRunSummary {\n if (runs.length === 0) throw new Error('Cannot aggregate zero runs');\n\n const runGroupId = (runs[0].metadata.runGroupId as string) ?? randomUUID();\n const { dataset } = runs[0];\n\n // Union workflow names across all runs in the group, first-seen first.\n // Most groups have one, but custom callbacks can produce heterogeneous ones.\n const seenWorkflows = new Set<string>();\n const workflows: string[] = [];\n for (const run of runs) {\n const list = run.metadata.workflows;\n if (Array.isArray(list)) {\n for (const w of list) {\n if (typeof w === 'string' && !seenWorkflows.has(w)) {\n seenWorkflows.add(w);\n workflows.push(w);\n }\n }\n }\n }\n\n const totalCost = runs.reduce((sum, r) => sum + r.totalCost, 0);\n const totalDuration = runs.reduce((sum, r) => sum + r.duration, 0);\n\n // Collect per-scorer means from each run\n const scorerNames = Object.keys(runs[0].summary.scorers);\n const scorers: MultiRunSummary['scorers'] = {};\n\n for (const name of scorerNames) {\n // A run where this scorer scored ZERO items has an empty-sample mean of 0\n // (computeStats([]) → 0), which would drag the aggregate mean-of-means toward\n // 0 as if it were a real 0.0 score. Exclude such runs from the mean/min/max/std\n // — but only when we can tell: `scored` is absent on pre-0.18.0 artifacts, so\n // those runs are kept (old behavior). If EVERY run scored nothing, fall back to\n // all runs so we never divide by zero.\n const contributing = runs.filter((r) => {\n const sc = r.summary.scorers[name]?.scored;\n return sc == null || sc > 0;\n });\n const meanSource = contributing.length > 0 ? contributing : runs;\n const means = meanSource.map((r) => r.summary.scorers[name]?.mean ?? 0);\n const meanOfMeans = means.reduce((a, b) => a + b, 0) / means.length;\n const minMean = Math.min(...means);\n const maxMean = Math.max(...means);\n\n // Sum the per-run sample sizes across ALL runs (they describe the whole\n // group's thinning, independent of which runs contributed to the mean).\n // Read with `?? 0` — old artifacts predate these fields.\n const scored = runs.reduce((sum, r) => sum + (r.summary.scorers[name]?.scored ?? 0), 0);\n const failed = runs.reduce((sum, r) => sum + (r.summary.scorers[name]?.failed ?? 0), 0);\n const skipped = runs.reduce((sum, r) => sum + (r.summary.scorers[name]?.skipped ?? 0), 0);\n\n scorers[name] = {\n mean: round(meanOfMeans),\n std: round(std(means, meanOfMeans)),\n min: round(minMean),\n max: round(maxMean),\n scored,\n failed,\n skipped,\n };\n }\n\n // Timing aggregation\n let timing: MultiRunSummary['timing'];\n const timingMeans = runs.filter((r) => r.summary.timing).map((r) => r.summary.timing!.mean);\n if (timingMeans.length === runs.length && timingMeans.length > 0) {\n const meanTiming = timingMeans.reduce((a, b) => a + b, 0) / timingMeans.length;\n timing = {\n mean: round(meanTiming),\n std: round(std(timingMeans, meanTiming)),\n };\n }\n\n return {\n runGroupId,\n runCount: runs.length,\n workflows,\n dataset,\n totalCost: round(totalCost),\n accounting: aggregateAccounting(runs.map((r) => readAccounting(r))),\n totalDuration: round(totalDuration),\n scorers,\n timing,\n };\n}\n"],"mappings":"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","names":["round","AxlError","scorer","outcome","round","scorer","name","AxlError","round","AdmissionController","RequestCaptureChannel","randomUUID","RequestCaptureChannel","abandonCapture","finishCapture","AdmissionController","accounting","randomUUID","randomUUID","round"]}
|