@axlsdk/eval 0.18.0 → 0.18.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/README.md +80 -13
- package/dist/{chunk-BWBX5YVQ.js → chunk-66EYSYQS.js} +29 -11
- package/dist/chunk-66EYSYQS.js.map +1 -0
- package/dist/cli.cjs +56 -13
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +31 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +29 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -2
- package/dist/index.d.ts +79 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-BWBX5YVQ.js.map +0 -1
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/bootstrap.ts","../src/utils.ts","../src/compare.ts","../src/scorer.ts","../src/score-item.ts","../src/runner.ts","../src/rescore.ts","../src/multi-run.ts","../src/cli-utils.ts","../src/cli-validate.ts","../src/cli-args.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readdirSync, statSync } from 'node:fs';\nimport { readFile as readFileAsync, writeFile as writeFileAsync, mkdir } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { AxlRuntime, EvalExecuteWorkflow } from '@axlsdk/axl';\nimport { evalCompare, evaluateScorerErrorRateGate } from './compare.js';\nimport { runEval } from './runner.js';\nimport { rescore } from './rescore.js';\nimport { aggregateRuns } from './multi-run.js';\nimport type { MultiRunSummary } from './multi-run.js';\nimport type { EvalConfig, EvalResult } from './types.js';\nimport {\n findConfig,\n resolveRuntime,\n importModule,\n registerConditions,\n pickDefault,\n pickExport,\n expandGlob,\n CONFIG_CANDIDATES,\n} from './cli-utils.js';\nimport { validateEvalConfig } from './cli-validate.js';\nimport { parseEvalArgs, envInt } from './cli-args.js';\nimport { scorerCounts } from './utils.js';\n\n/**\n * Refuse to certify a comparison and exit non-zero, with one consistent\n * message format. Routes both the scorer-filtered guard and the\n * `--max-scorer-error-rate` failure-rate gate through a single path so the\n * \"why CI failed\" line always reads the same.\n */\nfunction refuseToGate(reason: string): never {\n console.error(`[axl-eval] Refusing to gate: ${reason}`);\n process.exit(1);\n}\n\n/**\n * Read a scorer's `scored`/`failed` counts from a summary entry, falling back\n * to recomputing from `items` when the fields are absent (pre-0.18.0\n * artifacts). `items` is omitted for multi-run summaries that carry no items —\n * there the fields are authoritative (summed by `aggregateRuns`).\n */\nfunction scorerSampleCounts(\n entry: { scored?: number; failed?: number },\n name: string,\n items?: EvalResult['items'],\n): { scored: number; failed: number } {\n if (entry.scored != null && entry.failed != null) {\n return { scored: entry.scored, failed: entry.failed };\n }\n if (items) return scorerCounts(items, name);\n return { scored: entry.scored ?? 0, failed: entry.failed ?? 0 };\n}\n\n/** Install a SIGINT/SIGTERM handler that aborts an in-flight eval gracefully.\n * First signal: aborts the controller so runEval / rescore propagate cancellation\n * through ScorerContext.signal into in-flight provider.chat calls. The eval\n * unwinds normally and runtime.shutdown() runs in the `finally` block.\n * Second signal: hard exit — the user has signalled twice; cleanup is hung\n * or taking too long, so we abandon gracefulness rather than appear frozen. */\nfunction installAbortHandler(controller: AbortController): void {\n let signalled = false;\n const onSignal = (sig: NodeJS.Signals) => {\n if (signalled) {\n console.error(`\\n[axl-eval] Second ${sig} — forcing exit.`);\n process.exit(130);\n }\n signalled = true;\n console.error(`\\n[axl-eval] ${sig} received — cancelling eval (press again to force exit)...`);\n controller.abort();\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {\n console.log(`\nUsage:\n axl-eval <path> Run eval file(s)\n axl-eval <path> --runs <n> Run eval N times (multi-run)\n axl-eval <path> --output <file> Save results to JSON\n axl-eval <path> --config <file> Use config file for runtime\n axl-eval <path> --conditions <list> Node.js import conditions (comma-separated)\n axl-eval <path> --concurrency <n> Override item concurrency (flag > env\n AXL_EVAL_CONCURRENCY > config > 5).\n Max concurrent scorer calls is\n concurrency x scorerConcurrency (the\n per-eval scorerConcurrency defaults to 5).\n axl-eval <path> --scorers <a,b> Run only the named scorers (single eval\n file only). Stamps the result as a\n subset so compare won't treat it as a\n full baseline.\n axl-eval <path> --capture-traces Populate EvalItem.traces on every item\n (success + failure). Adds memory\n overhead proportional to dataset size\n x turns x agents; off by default.\n axl-eval rescore <results> <eval-file> Re-run scorers on saved outputs\n axl-eval compare <a> <b> Compare two eval result files\n axl-eval compare <a> <b> --threshold <v> Set regression threshold (global or per-scorer)\n axl-eval compare <a> <b> --fail-on-regression Exit 1 if regressions\n axl-eval compare <a> <b> --max-scorer-error-rate <0..1> Exit 1 if a scorer's\n failure rate exceeds the limit on\n either side (deterministic scorers\n tolerate zero failures). Always warns\n when either side rests on a thinned\n sample, even without this flag.\n\nConfig auto-detection (when --config is not specified):\n ${CONFIG_CANDIDATES.join(' -> ')}\n\nWhen a config is found, the exported AxlRuntime is passed to executeWorkflow\nand cost is tracked automatically via runtime.trackCost().\nWhen no config is found, a bare AxlRuntime is created (providers from env vars).\n`);\n process.exit(0);\n }\n\n if (args[0] === 'compare') {\n // `compare` is pure computation — no LLM calls, no AbortSignal plumbing needed.\n await runCompare(args.slice(1));\n return;\n }\n\n // SIGINT/SIGTERM aborts in-flight LLM calls (eval + rescore) instead of leaving\n // the process to hard-exit mid-request, which would skip runtime.shutdown() and\n // leak streaming-buffer state.\n const controller = new AbortController();\n installAbortHandler(controller);\n\n if (args[0] === 'rescore') {\n await runRescore(args.slice(1), controller.signal);\n return;\n }\n\n await runEvalCommand(args, controller.signal);\n}\n\nfunction parseThresholdArg(args: string[]): Record<string, number> | number | undefined {\n const idx = args.indexOf('--threshold');\n if (idx === -1 || idx + 1 >= args.length) return undefined;\n const value = args[idx + 1];\n\n // Global numeric threshold: --threshold 0.05\n if (/^[\\d.]+$/.test(value)) return parseFloat(value);\n\n // Per-scorer map: --threshold accuracy=0,tone=0.1\n const map: Record<string, number> = {};\n for (const pair of value.split(',')) {\n const [key, val] = pair.split('=');\n if (key && val != null) map[key.trim()] = parseFloat(val.trim());\n }\n return Object.keys(map).length > 0 ? map : undefined;\n}\n\n/**\n * Parse `--max-scorer-error-rate <0..1>`. Returns the numeric limit, or\n * `undefined` when the flag is absent. Exits non-zero on a malformed value\n * (fail loud — a typo'd gate threshold must not silently disable the gate).\n */\nfunction parseMaxScorerErrorRate(args: string[]): number | undefined {\n const idx = args.indexOf('--max-scorer-error-rate');\n if (idx === -1) return undefined;\n if (idx + 1 >= args.length) {\n console.error('Error: --max-scorer-error-rate requires a value in [0, 1]');\n process.exit(1);\n }\n const raw = args[idx + 1];\n // Strict numeric parse — `parseFloat('0.5abc')` returns 0.5 and `parseFloat('0,5')`\n // returns 0, both of which would silently set an unintended gate threshold. Reject\n // anything that isn't a clean decimal (matches `parseThresholdArg`'s guard).\n const n = /^\\d*\\.?\\d+$/.test(raw.trim()) ? Number(raw) : NaN;\n if (!Number.isFinite(n) || n < 0 || n > 1) {\n console.error(`Error: --max-scorer-error-rate must be a number in [0, 1], got \"${raw}\"`);\n process.exit(1);\n }\n return n;\n}\n\n/**\n * If a raw compare input (single result or multi-run array) was produced by a\n * `--scorers` filtered run, return the scorer names it ran; otherwise undefined.\n * Reads the first run's metadata — a multi-run group shares the same stamp.\n */\nfunction scorerFilteredScorers(r: EvalResult | EvalResult[]): string[] | undefined {\n const first = Array.isArray(r) ? r[0] : r;\n const meta = first?.metadata;\n if (!meta || meta.scorerFiltered !== true) return undefined;\n return Array.isArray(meta.scorersRun) ? (meta.scorersRun as string[]) : [];\n}\n\nasync function runCompare(args: string[]) {\n const failOnRegression = args.includes('--fail-on-regression');\n const thresholds = parseThresholdArg(args);\n const maxScorerErrorRate = parseMaxScorerErrorRate(args);\n // Exclude flags and the values consumed by value-taking flags so neither a\n // threshold nor an error-rate value is mistaken for a result file path.\n const valueFlags = new Set(['--threshold', '--max-scorer-error-rate']);\n const files = args.filter(\n (a, i) => !a.startsWith('--') && !(i > 0 && valueFlags.has(args[i - 1])),\n );\n\n if (files.length !== 2) {\n console.error(\n 'Usage: axl-eval compare <baseline.json> <candidate.json> [--threshold <value>] [--fail-on-regression] [--max-scorer-error-rate <0..1>]',\n );\n process.exit(1);\n }\n\n const baselineRaw = JSON.parse(await readFileAsync(files[0], 'utf-8'));\n const candidateRaw = JSON.parse(await readFileAsync(files[1], 'utf-8'));\n const baseline: EvalResult | EvalResult[] = baselineRaw;\n const candidate: EvalResult | EvalResult[] = candidateRaw;\n\n // A scorer-filtered result (CLI `--scorers`) tested only a subset of scorers,\n // so it isn't a sound baseline/candidate for a full comparison. Check this\n // BEFORE evalCompare(): a subset-vs-full comparison has mismatched scorer sets\n // and evalCompare() would throw a generic \"different scorers\" error that never\n // mentions --scorers. Warn loudly here so the cause is actionable; under\n // `--fail-on-regression`, refuse outright (a swallowed stderr line wouldn't\n // actually prevent the footgun).\n const filteredSides = (\n [\n ['baseline', baseline],\n ['candidate', candidate],\n ] as const\n ).filter(([, r]) => scorerFilteredScorers(r) != null);\n for (const [side, r] of filteredSides) {\n const ran = scorerFilteredScorers(r);\n const ranStr = ran && ran.length ? ` (ran: ${ran.join(', ')})` : '';\n console.error(\n `[axl-eval] WARNING: ${side} was run with --scorers — it tested only a subset${ranStr}, so this comparison is incomplete.`,\n );\n }\n if (failOnRegression && filteredSides.length > 0) {\n refuseToGate(\n `${filteredSides.map(([s]) => s).join(', ')} was run with --scorers (a scorer subset); re-run without --scorers for a complete baseline.`,\n );\n }\n\n const compareOptions = thresholds != null ? { thresholds } : undefined;\n const comparison = evalCompare(baseline, candidate, compareOptions);\n\n console.log(\n `\\nCompare: baseline (${comparison.baseline.id.slice(0, 8)}) -> candidate (${comparison.candidate.id.slice(0, 8)})\\n`,\n );\n\n const scorerNames = Object.keys(comparison.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 6);\n const hasCI = scorerNames.some((n) => comparison.scorers[n].ci != null);\n\n const ciHeader = hasCI ? ' CI 95% Sig' : '';\n const ciRule = hasCI ? ' ---------------- ---' : '';\n console.log(` ${'Scorer'.padEnd(maxNameLen)} Baseline Candidate Delta Change${ciHeader}`);\n console.log(` ${''.padEnd(maxNameLen, '-')} -------- --------- -------- ------${ciRule}`);\n\n for (const name of scorerNames) {\n const s = comparison.scorers[name];\n const sign = s.delta > 0 ? '+' : '';\n let line = ` ${name.padEnd(maxNameLen)} ${s.baselineMean.toFixed(3).padStart(8)} ${s.candidateMean.toFixed(3).padStart(9)} ${(sign + s.delta.toFixed(3)).padStart(8)} ${(sign + s.deltaPercent.toFixed(1) + '%').padStart(6)}`;\n if (hasCI) {\n if (s.ci) {\n const lo = (s.ci.lower >= 0 ? '+' : '') + s.ci.lower.toFixed(4);\n const hi = (s.ci.upper >= 0 ? '+' : '') + s.ci.upper.toFixed(4);\n const sig = s.significant ? ' *' : ' ';\n line += ` [${lo}, ${hi}]${sig}`;\n } else {\n line += ' —'.padEnd(22);\n }\n }\n console.log(line);\n }\n\n if (comparison.timing) {\n const t = comparison.timing;\n const sign = t.delta > 0 ? '+' : '';\n console.log(\n `\\n Timing: baseline ${(t.baselineMean / 1000).toFixed(2)}s -> candidate ${(t.candidateMean / 1000).toFixed(2)}s (${sign}${t.deltaPercent.toFixed(1)}%)`,\n );\n }\n if (comparison.cost) {\n const c = comparison.cost;\n const sign = c.delta > 0 ? '+' : '';\n console.log(\n ` Cost: baseline $${c.baselineTotal.toFixed(2)} -> candidate $${c.candidateTotal.toFixed(2)} (${sign}${c.deltaPercent.toFixed(1)}%)`,\n );\n }\n\n const baselineRef = Array.isArray(baseline) ? baseline[0] : baseline;\n const stable = Math.max(\n 0,\n baselineRef.items.length - comparison.regressions.length - comparison.improvements.length,\n );\n console.log(\n `\\n Regressions: ${comparison.regressions.length} | Improvements: ${comparison.improvements.length} | Stable: ${stable}\\n`,\n );\n\n // Scorer failure-rate signal. Always WARN loudly when either side rests on a\n // thinned sample (a scorer ran and failed on some items) — a regression check\n // computed over survivors can look green while half the judges errored. Only\n // REFUSE to gate when the user opted in with `--max-scorer-error-rate` AND a\n // scorer is over tolerance (type-aware: deterministic scorers tolerate zero\n // failures, LLM judges use the flag value), or a scorer produced no scored\n // items at all on a side (a zero-sample mean can't be certified).\n let sawThinnedSample = false;\n for (const name of scorerNames) {\n const s = comparison.scorers[name];\n const bFailed = s.baselineFailed ?? 0;\n const cFailed = s.candidateFailed ?? 0;\n if (bFailed > 0 || cFailed > 0) {\n sawThinnedSample = true;\n const bAtt = (s.baselineScored ?? 0) + bFailed;\n const cAtt = (s.candidateScored ?? 0) + cFailed;\n console.error(\n `[axl-eval] WARNING: scorer \"${name}\" failed on some items ` +\n `(baseline ${bFailed}/${bAtt}, candidate ${cFailed}/${cAtt}); ` +\n `the means above are computed over the surviving sample.`,\n );\n }\n }\n // Tell the user how to make the advisory warning blocking (when they haven't).\n if (sawThinnedSample && maxScorerErrorRate == null) {\n console.error(\n `[axl-eval] (advisory — pass --max-scorer-error-rate <0..1> to fail CI on a thinned sample)`,\n );\n }\n\n // Gate-side refusal (opt-in). The decision lives in evaluateScorerErrorRateGate\n // (pure + unit-tested) so the same type-aware tolerance + zero-sample logic\n // isn't re-implemented here and at the source-side gate in runEval.\n if (maxScorerErrorRate != null) {\n const reason = evaluateScorerErrorRateGate(comparison, maxScorerErrorRate);\n if (reason) refuseToGate(reason);\n }\n\n if (failOnRegression && comparison.regressions.length > 0) {\n // When CI is available, only fail on significant regressions\n const hasSignificance = scorerNames.some((n) => comparison.scorers[n].significant != null);\n if (hasSignificance) {\n const hasSignificantRegression = scorerNames.some(\n (n) => comparison.scorers[n].significant === true && comparison.scorers[n].delta < 0,\n );\n if (hasSignificantRegression) process.exit(1);\n } else {\n process.exit(1);\n }\n }\n}\n\nasync function runRescore(args: string[], signal: AbortSignal) {\n const { outputPath, configArg, conditions, concurrency, scorerNames, paths } =\n parseEvalArgs(args);\n\n if (paths.length < 2) {\n console.error('Usage: axl-eval rescore <results.json> <eval-file> [--output <file>]');\n process.exit(1);\n }\n\n // --scorers is a run-command-only filter — rescore always re-runs the full\n // scorer set from the eval file. Fail loudly rather than silently ignoring it\n // (it parses as a known flag, so it wouldn't trip the unknown-flag guard).\n if (scorerNames?.length) {\n console.error(\n 'Error: --scorers is not supported with rescore; pass a scorer subset in the eval file instead.',\n );\n process.exit(1);\n }\n\n // Honor the same item-concurrency override as the run command (flag > env).\n // scorerConcurrency keeps its rescore default (5).\n const itemConcurrency = concurrency ?? envInt('AXL_EVAL_CONCURRENCY');\n\n const [resultsPath, evalFilePath] = paths;\n const raw = JSON.parse(await readFileAsync(resultsPath, 'utf-8'));\n const results: EvalResult[] = Array.isArray(raw) ? raw : [raw];\n\n const runtime = await getRuntime(configArg, conditions);\n try {\n const mod = await importModule(path.resolve(evalFilePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n if (!evalConfig || typeof evalConfig !== 'object') {\n console.error(\n `Error: ${evalFilePath} does not export an eval config object — got ${evalConfig === null ? 'null' : typeof evalConfig}.`,\n );\n process.exit(1);\n }\n if (!Array.isArray(evalConfig.scorers) || evalConfig.scorers.length === 0) {\n console.error(`Error: ${evalFilePath} does not export a non-empty scorers array.`);\n process.exit(1);\n }\n\n const rescored: EvalResult[] = [];\n for (const resultData of results) {\n if (signal.aborted) break;\n rescored.push(\n await rescore(resultData, evalConfig.scorers, runtime, {\n signal,\n ...(itemConcurrency != null ? { concurrency: itemConcurrency } : {}),\n }),\n );\n }\n\n for (const r of rescored) {\n console.log('\\n' + formatTable(r) + '\\n');\n }\n\n if (outputPath) {\n const output = Array.isArray(raw) ? rescored : rescored[0];\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Rescored results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n}\n\n/**\n * Resolve a CLI path argument into a list of eval files.\n *\n * Accepts:\n * - An explicit file path (`path/to/foo.eval.ts`)\n * - A directory (lists `*.eval.[mc]?[jt]sx?` inside, non-recursive)\n * - A glob pattern: `evals/*.eval.ts`, `evals/**\\/*.eval.ts`, `**\\/*.eval.ts`\n *\n * Glob expansion mirrors the studio eval-loader's so users get the same\n * behavior in both places. Without it, users running on Windows or with\n * quoted patterns hit confusing \"file not found\" errors when the shell\n * couldn't expand the glob.\n */\nfunction collectEvalFiles(p: string): string[] {\n if (p.includes('*')) return expandGlob(p, process.cwd());\n const resolved = path.resolve(p);\n try {\n const stat = statSync(resolved);\n if (stat.isDirectory()) {\n const entries = readdirSync(resolved);\n return entries\n .filter((e) => /\\.eval\\.[mc]?[jt]sx?$/.test(e))\n .map((e) => path.join(resolved, e));\n }\n return [resolved];\n } catch {\n return [resolved];\n }\n}\n\n/** Render observed workflows for a terse header line. Multiple → comma-separated. */\nfunction formatWorkflows(workflows: unknown): string {\n if (!Array.isArray(workflows) || workflows.length === 0) return '(unknown)';\n return (workflows as unknown[]).filter((w): w is string => typeof w === 'string').join(', ');\n}\n\nfunction formatTable(result: EvalResult): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(result.summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 8;\n\n lines.push(\n `Eval: ${formatWorkflows(result.metadata.workflows)} x ${result.dataset} (${result.summary.count} items)`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean'.padStart(colWidth)} ${'Min'.padStart(colWidth)} ${'Max'.padStart(colWidth)} ${'p50'.padStart(colWidth)} ${'p95'.padStart(colWidth)}`,\n );\n\n const ruleLen = maxNameLen + 2 + (colWidth + 2) * 5;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = result.summary.scorers[name];\n const { scored, failed } = scorerSampleCounts(s, name, result.items);\n // Loud trailing annotation when a scorer ran and failed on some items: the\n // mean rests on a thinned sample. Shown only when failed > 0 so clean runs\n // stay uncluttered.\n const annotation =\n failed > 0 ? ` (${scored}/${scored + failed} scored, ${failed} failed)` : '';\n // Detect scorers with no valid scores (all items errored → computeStats([]) → all zeros)\n if (scored === 0) {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)}${annotation}`,\n );\n } else {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${s.mean.toFixed(2).padStart(colWidth)} ${s.min.toFixed(2).padStart(colWidth)} ${s.max.toFixed(2).padStart(colWidth)} ${s.p50.toFixed(2).padStart(colWidth)} ${s.p95.toFixed(2).padStart(colWidth)}${annotation}`,\n );\n }\n }\n\n if (result.summary.timing) {\n const t = result.summary.timing;\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${(t.mean / 1000).toFixed(2).padStart(colWidth)}s ${(t.p50 / 1000).toFixed(2).padStart(colWidth)}s ${(t.p95 / 1000).toFixed(2).padStart(colWidth)}s`,\n );\n }\n\n const durationSec = (result.duration / 1000).toFixed(1);\n const costStr = result.totalCost > 0 ? `$${result.totalCost.toFixed(2)}` : '$0.00';\n lines.push('');\n lines.push(\n ` Failures: ${result.summary.failures}/${result.summary.count} | Cost: ${costStr} | Duration: ${durationSec}s`,\n );\n\n const itemsWithErrors = result.items.filter((i) => i.scorerErrors?.length);\n if (itemsWithErrors.length > 0) {\n const uniqueErrors = [...new Set(itemsWithErrors.flatMap((i) => i.scorerErrors!))];\n lines.push('');\n lines.push(\n ` Scorer errors (${itemsWithErrors.length}/${result.summary.count} items affected):`,\n );\n for (const err of uniqueErrors.slice(0, 5)) {\n lines.push(` - ${err}`);\n }\n if (uniqueErrors.length > 5) {\n lines.push(` ... and ${uniqueErrors.length - 5} more`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatMultiRunTable(summary: MultiRunSummary): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 16;\n\n lines.push(\n `Eval: ${formatWorkflows(summary.workflows)} x ${summary.dataset} \\u2014 ${summary.runCount} runs`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean \\u00b1 Std'.padStart(colWidth)} ${'Min'.padStart(8)} ${'Max'.padStart(8)}`,\n );\n const ruleLen = maxNameLen + 2 + colWidth + 2 + 8 + 2 + 8;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = summary.scorers[name];\n const meanStd = `${s.mean.toFixed(3)} \\u00b1 ${s.std.toFixed(3)}`;\n // Multi-run summaries have no items, so the summed scored/failed fields are\n // authoritative (no fallback recompute possible). Annotate when failed > 0.\n const { scored, failed } = scorerSampleCounts(s, name);\n const annotation =\n failed > 0 ? ` (${scored}/${scored + failed} scored, ${failed} failed)` : '';\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${meanStd.padStart(colWidth)} ${s.min.toFixed(3).padStart(8)} ${s.max.toFixed(3).padStart(8)}${annotation}`,\n );\n }\n\n if (summary.timing) {\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${((summary.timing.mean / 1000).toFixed(2) + ' \\u00b1 ' + (summary.timing.std / 1000).toFixed(2) + 's').padStart(colWidth)}`,\n );\n }\n\n const costStr = summary.totalCost > 0 ? `$${summary.totalCost.toFixed(2)}` : '$0.00';\n const durationStr = (summary.totalDuration / 1000).toFixed(1);\n lines.push('');\n lines.push(` Total Cost: ${costStr} | Total Duration: ${durationStr}s`);\n\n return lines.join('\\n');\n}\n\n/**\n * Print each degraded scorer (set by `runEval` when `failOnScorerErrorRate`\n * tripped) to stderr and return whether the run was degraded, so the caller can\n * count the file as failed (→ non-zero exit). Quiet when nothing degraded.\n */\nfunction reportDegraded(result: EvalResult, label: string): boolean {\n const d = result.summary.degraded;\n if (!d || d.length === 0) return false;\n for (const x of d) {\n const attempted = x.scored + x.failed;\n const limitStr =\n x.type === 'deterministic'\n ? 'deterministic zero-tolerance'\n : `${(x.limit * 100).toFixed(1)}% limit`;\n console.error(\n `[axl-eval] DEGRADED: ${label} scorer \"${x.scorer}\" (${x.type}) failed ` +\n `${(x.rate * 100).toFixed(1)}% (${x.failed}/${attempted}), over the ${limitStr}.`,\n );\n }\n return true;\n}\n\n/**\n * A run where EVERY item errored in the workflow (0 succeeded) produced no valid\n * output to score — the eval is meaningless and must never pass CI green. This\n * is distinct from (and complementary to) the scorer failure-rate gate: that one\n * is about a flaky/failing *scorer*, this is about a broken *workflow*. The\n * scorer gate deliberately ignores a zero-sample scorer (nothing ran), so without\n * this guard a 100%-workflow-error run exits 0 — a silent-green trap.\n *\n * Non-configurable on purpose: a 0%-success eval is unambiguously broken, so this\n * always fails. (A configurable `failOnItemErrorRate` for PARTIAL workflow-failure\n * gating is a reasonable future opt-in; the per-item failure count is already shown\n * loudly in the table either way.) Returns whether the run was a total wipeout.\n */\nfunction reportTotalWipeout(result: EvalResult, label: string): boolean {\n const { count, failures } = result.summary;\n if (count === 0 || failures < count) return false;\n console.error(\n `[axl-eval] FAILED: ${label} — all ${count} item(s) errored in the workflow ` +\n `(0 succeeded); the eval produced no scorable output.`,\n );\n return true;\n}\n\n// ── Runtime resolution ─────────────────────────────────────────────\n\nasync function resolveRuntimeFromConfig(configPath: string): Promise<AxlRuntime> {\n try {\n const mod = await importModule(configPath, import.meta.url);\n const runtime = resolveRuntime(mod) as AxlRuntime;\n\n if (!runtime || typeof runtime.execute !== 'function') {\n console.error(`Config must export a default AxlRuntime instance.`);\n if (runtime) {\n const keys = Object.keys(runtime as object)\n .slice(0, 5)\n .join(', ');\n console.error(` Got: ${typeof runtime}${keys ? ` with keys: { ${keys} }` : ''}`);\n }\n console.error(\n `Example:\\n import { AxlRuntime } from '@axlsdk/axl';\\n export default new AxlRuntime({ ... });`,\n );\n process.exit(1);\n }\n\n return runtime;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n /Cannot use import statement|Unexpected reserved word|top-level await|exports is not defined/.test(\n msg,\n )\n ) {\n const ext = path.extname(configPath);\n console.error(`[axl-eval] Config failed to load due to a CJS/ESM compatibility issue.`);\n if (ext === '.ts' || ext === '.tsx') {\n console.error(\n ` Tip: try renaming to .mts to force ESM format, or ensure tsx is installed and up to date.`,\n );\n } else {\n console.error(` Tip: add \"type\": \"module\" to your package.json.`);\n }\n console.error();\n }\n console.error(`Failed to load config:`, err);\n process.exit(1);\n }\n}\n\nasync function getRuntime(configArg?: string, conditions?: string[]): Promise<AxlRuntime> {\n // Register import conditions before any config loading\n if (conditions && conditions.length > 0) {\n await registerConditions(conditions);\n }\n\n // 1. Explicit --config\n if (configArg) {\n const configPath = path.resolve(process.cwd(), configArg);\n const stat = statSync(configPath, { throwIfNoEntry: false });\n if (!stat?.isFile()) {\n console.error(`Config file not found: ${configPath}`);\n process.exit(1);\n }\n console.error(`[axl-eval] Loading config from ${configPath}`);\n return resolveRuntimeFromConfig(configPath);\n }\n\n // 2. Auto-detect\n const found = findConfig(process.cwd());\n if (found) {\n console.error(`[axl-eval] Auto-detected config: ${found}`);\n return resolveRuntimeFromConfig(found);\n }\n\n // 3. Bare runtime (providers from env vars)\n const { AxlRuntime } = await import('@axlsdk/axl');\n return new AxlRuntime();\n}\n\n// ── Main eval command ──────────────────────────────────────────────\n\nasync function runEvalCommand(args: string[], signal: AbortSignal) {\n const {\n outputPath,\n configArg,\n conditions,\n runs,\n captureTraces,\n concurrency,\n scorerNames,\n paths,\n } = parseEvalArgs(args);\n\n if (paths.length === 0) {\n console.error('Error: No eval file path provided');\n process.exit(1);\n }\n\n const evalFiles: string[] = [];\n for (const p of paths) {\n evalFiles.push(...collectEvalFiles(p));\n }\n\n if (evalFiles.length === 0) {\n console.error('Error: No eval files found');\n process.exit(1);\n }\n\n // --scorers is single-file only — filtering by name across a glob/dir of evals\n // with different scorer sets is ambiguous. Fail fast, before importing any\n // module, rather than discovering the conflict mid-loop.\n if (scorerNames?.length && evalFiles.length > 1) {\n console.error(`Error: --scorers requires a single eval file (matched ${evalFiles.length}).`);\n process.exit(1);\n }\n\n const runtime = await getRuntime(configArg, conditions);\n const results: EvalResult[] = [];\n let failedFiles = 0;\n\n try {\n for (const filePath of evalFiles) {\n // Short-circuit if the user aborted between eval files. The in-flight eval\n // unwinds on its own via runEval({ signal }); this prevents starting the next one.\n if (signal.aborted) break;\n try {\n const mod = await importModule(path.resolve(filePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n const validationError = validateEvalConfig(evalConfig);\n if (validationError) {\n console.error(`Error: ${filePath} ${validationError}`);\n failedFiles++;\n continue;\n }\n\n // Concurrency override precedence: flag > env > config > default.\n // Mutating evalConfig in place mirrors how this loop already stamps\n // result.metadata. `concurrency` is pure scheduling — never changes\n // results — so a per-run override is always safe.\n evalConfig.concurrency =\n concurrency ?? envInt('AXL_EVAL_CONCURRENCY') ?? evalConfig.concurrency ?? 5;\n\n // --scorers: run a subset of scorers for a focused iteration loop.\n // (The single-file guard already ran before the loop.) Validate-then-\n // filter so the error lists every available name.\n if (scorerNames?.length) {\n const available = evalConfig.scorers.map((s) => s.name);\n const unknown = scorerNames.filter((n) => !available.includes(n));\n if (unknown.length) {\n console.error(\n `Error: --scorers: unknown scorer(s): ${unknown.join(', ')}. Available: ${available.join(', ')}`,\n );\n process.exit(1);\n }\n evalConfig.scorers = evalConfig.scorers.filter((s) => scorerNames.includes(s.name));\n if (evalConfig.scorers.length === 0) {\n console.error('Error: --scorers matched no scorers.');\n process.exit(1);\n }\n }\n\n // Resolve executeWorkflow: custom export > registered workflow > error\n // Walk the ESM/CJS interop chain symmetrically with the default export\n // so named exports stay visible when tsx loads the eval module as CJS.\n const exported = pickExport<unknown>(mod, 'executeWorkflow');\n\n // Validate that the export, if present, is callable. Catches the\n // `export const executeWorkflow = 'foo'` typo at the boundary instead\n // of crashing deep inside trackExecution with a confusing stack.\n let customExecute: EvalExecuteWorkflow | undefined;\n if (typeof exported === 'function') {\n customExecute = exported as EvalExecuteWorkflow;\n } else if (exported !== undefined) {\n console.error(\n `[axl-eval] Error: ${filePath} exports executeWorkflow but it is ${typeof exported}, not a function.`,\n );\n failedFiles++;\n continue;\n }\n\n let executeWorkflow: EvalExecuteWorkflow;\n\n if (customExecute) {\n // Wrap custom executeWorkflow with trackExecution for cost + metadata attribution\n executeWorkflow = async (input, rt) => {\n const {\n result,\n cost: trackedCost,\n metadata,\n } = await runtime.trackExecution(async () => {\n return customExecute(input, rt);\n });\n return {\n output: result.output,\n cost: result.cost ?? trackedCost,\n metadata: result.metadata ?? metadata,\n };\n };\n } else if (runtime.getWorkflow(evalConfig.workflow)) {\n // No executeWorkflow exported but workflow is registered — use runtime.execute()\n executeWorkflow = async (input) => {\n const { result, cost, metadata } = await runtime.trackExecution(async () => {\n return runtime.execute(evalConfig.workflow, input);\n });\n return { output: result, cost, metadata };\n };\n } else {\n // Fail loudly. The previous identity-passthrough fallback silently\n // produced all-zero scores in CI — exactly the kind of footgun the\n // \"fail loudly, not silently\" rule is meant to prevent. If you\n // genuinely want identity, export it explicitly:\n // export const executeWorkflow = async (input) => ({ output: input });\n //\n // Surface what WAS exported (top-level + .default) so users\n // recognize a typo like `execute_workflow` and can spot the\n // CJS-interop case that motivates this whole code path: when tsx\n // loads a `.ts` file as CJS, all named exports land on\n // `mod.default.<name>`. The chain walk above already handled this,\n // but a user who removed `executeWorkflow` will see exactly what\n // export names ARE present.\n const exportShape = (() => {\n const top = Object.keys(mod).filter((k) => k !== 'default');\n const fromDefault =\n mod.default && typeof mod.default === 'object'\n ? Object.keys(mod.default as Record<string, unknown>)\n : [];\n const all = [...new Set([...top, ...fromDefault])];\n return all.length > 0 ? `Found exports: [${all.join(', ')}].` : '';\n })();\n console.error(\n `[axl-eval] Error: ${filePath} does not export an executeWorkflow function ` +\n `and no workflow named \"${evalConfig.workflow}\" is registered on the runtime.\\n` +\n (exportShape ? ` ${exportShape}\\n` : '') +\n ` Add either:\\n` +\n ` export async function executeWorkflow(input, runtime) { ... }\\n` +\n ` or register the workflow on your runtime via runtime.registerWorkflow(workflow).\\n` +\n ` Tip: if your eval previously worked, your package.json may be missing\\n` +\n ` \"type\": \"module\" — tsx loads .ts as CJS, putting named exports on\\n` +\n ` mod.default.<name>. The CLI handles that interop, but if you renamed\\n` +\n ` or removed the export the file path is your fix.`,\n );\n failedFiles++;\n continue;\n }\n\n // When --capture-traces is set, forward it to runEval so the runner\n // wraps each item's execution in a nested trackExecution({ captureTraces: true }).\n // This populates EvalItem.traces on both success (via tracked.traces)\n // and failure (via the axlCapturedTraces side-channel on the thrown\n // error). Nested trackExecution scopes walk the AsyncLocalStorage\n // parent chain, so the outer trackExecution above still observes\n // cost/metadata correctly.\n // Always pass the SIGINT-driven signal so Ctrl+C aborts in-flight\n // workflows + scorer LLM calls instead of dropping the connection mid-request.\n const runOptions = { signal, ...(captureTraces ? { captureTraces: true } : {}) };\n\n // Stamp filtered runs so a scorer-subset result can't be silently used\n // as a full baseline. `compare` warns (and refuses to gate) on it. Must\n // be applied to EVERY run in a multi-run batch — Studio's multi-run\n // builder spreads only run[0]'s metadata.\n const scorersRun = scorerNames?.length ? evalConfig.scorers.map((s) => s.name) : undefined;\n const stampFiltered = (result: EvalResult) => {\n if (scorersRun) {\n result.metadata.scorerFiltered = true;\n result.metadata.scorersRun = scorersRun;\n }\n };\n\n if (runs > 1) {\n // Multi-run mode. Buffer per-run results locally so we can mark the\n // batch correctly before committing to outer `results[]`. The\n // original bug was the opposite: results pushed eagerly per-run, a\n // throw mid-batch left partial results posing as a complete run\n // (no `fromPartialBatch` marker, aggregate never ran). The fix ISN'T\n // to throw the partials away — those runs cost money and have\n // statistical signal. Instead we preserve them with explicit\n // partial-batch metadata, aggregate over what completed, and exit\n // non-zero so CI knows the batch wasn't clean.\n const { randomUUID } = await import('node:crypto');\n const runGroupId = randomUUID();\n const runResults: EvalResult[] = [];\n let runFailure: Error | undefined;\n\n for (let r = 0; r < runs; r++) {\n if (signal.aborted) break;\n console.error(`[axl-eval] Run ${r + 1}/${runs}...`);\n try {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n result.metadata.runGroupId = runGroupId;\n result.metadata.runIndex = r;\n stampFiltered(result);\n runResults.push(result);\n } catch (err) {\n runFailure = err instanceof Error ? err : new Error(String(err));\n console.error(`[axl-eval] Run ${r + 1}/${runs} failed: ${runFailure.message}`);\n // Stop attempting further runs — we don't know whether this is\n // transient (rate limit) or permanent (auth failure), and\n // burning more API calls speculatively is hostile. Preserve\n // what completed.\n break;\n }\n }\n\n if (runResults.length === 0) {\n // Nothing completed — surface as a per-file failure. No partial\n // artifact to write; the outer try/catch error message would\n // duplicate the \"Run 1/N failed\" line we already printed, so\n // increment and continue without re-throwing.\n console.error(\n `[axl-eval] Aborting ${filePath}: no runs completed (${runFailure?.message ?? 'unknown failure'}).`,\n );\n failedFiles++;\n continue;\n }\n\n const partial = runResults.length < runs;\n if (partial) {\n // Mark every completed run so any consumer reading\n // `result.metadata` sees the partial-batch context. `aggregateRuns`\n // computes statistics over `runResults.length`, which is the\n // honest sample size to report.\n //\n // The flag is `fromPartialBatch` — a per-run marker meaning\n // \"this run came from a batch that did not complete.\" It is\n // NOT named `partialBatch` because that read as \"this run is\n // partial,\" and a defensive consumer wrote\n // `if (run.metadata.partialBatch) skipThisRun()`, throwing\n // away successful work that cost real money. The flag describes\n // the BATCH the run belongs to, not the run itself.\n //\n // `runFailure?.message` can be empty (e.g. `new Error('')` from a\n // misbehaving provider); fall back to `String(runFailure)` so the\n // banner never renders a blank \"Stopped after:\" line. Skip the\n // field entirely if both are empty so `buildMultiRunResult`'s\n // empty-string filter doesn't have to defensively guess.\n const failureMsg = runFailure\n ? runFailure.message || String(runFailure) || undefined\n : undefined;\n for (const r of runResults) {\n r.metadata.fromPartialBatch = true;\n r.metadata.batchCompleted = runResults.length;\n r.metadata.batchAttempted = runs;\n if (failureMsg) r.metadata.batchFailure = failureMsg;\n }\n console.error(\n `[axl-eval] PARTIAL: ${runResults.length} of ${runs} runs completed for ${filePath}.`,\n );\n failedFiles++;\n }\n\n const summary = aggregateRuns(runResults);\n console.log('\\n' + formatMultiRunTable(summary) + '\\n');\n for (const r of runResults) results.push(r);\n\n // Failure-rate gate (opt-in via failOnScorerErrorRate) + total-wipeout\n // guard (always). Report every run; count the file as failed unless it\n // was already counted as a partial batch above (avoids double-count).\n let anyFailing = false;\n for (const r of runResults) {\n // Call both (no short-circuit) so each prints its own diagnostic.\n const wipeout = reportTotalWipeout(r, filePath);\n const degraded = reportDegraded(r, filePath);\n if (wipeout || degraded) anyFailing = true;\n }\n if (anyFailing && !partial) failedFiles++;\n } else {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n stampFiltered(result);\n results.push(result);\n\n console.log('\\n' + formatTable(result) + '\\n');\n // Total-wipeout guard (always) + scorer failure-rate gate (opt-in). They\n // are mutually exclusive (a wipeout has no scored items, so no scorer can\n // be degraded), but report both for clarity; either fails the file.\n const wipeout = reportTotalWipeout(result, filePath);\n const degraded = reportDegraded(result, filePath);\n if (wipeout || degraded) failedFiles++;\n }\n } catch (err) {\n console.error(\n `Error running eval ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n failedFiles++;\n }\n }\n\n if (outputPath && results.length > 0) {\n const output = results.length === 1 ? results[0] : results;\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n\n // Exit non-zero if any eval file failed to load/run. Previously we only\n // exited non-zero when zero evals succeeded, which silently masked\n // misconfigured files in mixed-success runs (a CI footgun).\n if (failedFiles > 0 || results.length === 0) {\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","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","export 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/**\n * Count, for one scorer across a set of items, how many produced a valid score\n * (`scored`) vs ran-and-failed (`failed`). The single source of truth for the\n * failure-rate trust signal, shared by `runEval`, `rescore`, and `evalCompare`.\n *\n * The discriminator is `scoreDetails[name].duration`: `scoreItem` sets it\n * whenever a scorer actually executes (success, throw, or out-of-range), but a\n * scorer skipped by cancellation keeps its pre-seeded `{ score: null }` with NO\n * duration. So a `null` score WITH a duration is a genuine failure, while a\n * `null` score WITHOUT one was never attempted (cancellation) and belongs in\n * neither bucket — making `scored + failed` the honest \"attempted\" denominator\n * for a failure rate (it can be `<` the 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 }>;\n }[],\n name: string,\n): { scored: number; failed: number } {\n let scored = 0;\n let failed = 0;\n for (const i of items) {\n if (i.error) continue;\n if (i.scores[name] != null) scored++;\n else if (i.scoreDetails?.[name]?.duration != null) failed++;\n }\n return { scored, failed };\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","import type {\n EvalResult,\n EvalComparison,\n EvalCompareOptions,\n EvalRegression,\n EvalImprovement,\n} from './types.js';\nimport { pairedBootstrapCI } from './bootstrap.js';\nimport { scorerCounts, evaluateScorerTolerance, round } from './utils.js';\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 for (const run of baselineRuns) {\n const c = scorerCounts(run.items, name);\n baselineScored += c.scored;\n baselineFailed += c.failed;\n }\n let candidateScored = 0;\n let candidateFailed = 0;\n for (const run of candidateRuns) {\n const c = scorerCounts(run.items, name);\n candidateScored += c.scored;\n candidateFailed += c.failed;\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 };\n\n // Compute bootstrap CI when we have enough paired data\n const diffs = pairedDiffs[name];\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 entry.n = diffs.length;\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 let cost: EvalComparison['cost'];\n const baselineAvgCost =\n baselineRuns.reduce((sum, r) => sum + r.totalCost, 0) / baselineRuns.length;\n const candidateAvgCost =\n candidateRuns.reduce((sum, r) => sum + r.totalCost, 0) / candidateRuns.length;\n if (baselineAvgCost > 0 || candidateAvgCost > 0) {\n const deltaRaw = candidateAvgCost - baselineAvgCost;\n const delta = round(deltaRaw);\n const deltaPercent = baselineAvgCost > 0 ? round((deltaRaw / baselineAvgCost) * 100) : 0;\n cost = {\n baselineTotal: round(baselineAvgCost),\n candidateTotal: round(candidateAvgCost),\n delta,\n deltaPercent,\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 if (cost && 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 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 — typically every one of its\n // items errored in the workflow (or was skipped), not necessarily a fault\n // of the scorer itself. Either way a mean over zero samples can't be certified.\n return `scorer \"${name}\" has no scored items on ${side} (its items errored or were skipped) — 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","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\nexport type ScorerConfig<TOutput = unknown, TInput = unknown, TAnnotations = unknown> = {\n name: string;\n description: string;\n score: ScorerFn<TOutput, TInput, TAnnotations>;\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};\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 };\n}\n","import type { Scorer, ScorerContext } from './scorer.js';\nimport { normalizeScorerResult, extractScorerErrorCost } from './scorer.js';\nimport type { EvalItem } from './types.js';\nimport { round, mapWithConcurrency } from './utils.js';\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/**\n * Score one item's `output` with every scorer in `scorers`, running up to\n * `scorerConcurrency` of them at once. Mutates `item.scores`,\n * `item.scoreDetails`, `item.scorerErrors`, and `item.scorerCost` in place, and\n * returns the per-item scorer cost so the caller can fold it into its own\n * running total (`totalCost += await scoreItem(...)`).\n *\n * This is the single source of truth for the scoring inner loop, shared by\n * `runEval` and `rescore` — both previously carried a byte-identical copy, so a\n * determinism or cancellation fix had to be made twice.\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 * Cancellation: a scorer not yet started when `signal` aborts is skipped; an\n * in-flight scorer whose call rejects with an `AbortError` is treated as\n * cancellation (leaves its pre-seeded `null`, records no error) — narrowed to\n * the error identity so a genuine bug in another scorer that happens to throw\n * while a sibling triggered the abort is still reported, not swallowed.\n */\nexport async function scoreItem(\n item: ScorableItem,\n scorers: readonly Scorer<unknown, unknown, unknown>[],\n scorerConcurrency: number,\n scorerContext: ScorerContext,\n signal?: AbortSignal,\n): Promise<number> {\n const scoreDetails = (item.scoreDetails ??= {});\n for (const s of scorers) {\n item.scores[s.name] = null;\n scoreDetails[s.name] = { score: null };\n }\n\n let itemScorerCost = 0;\n const scorerErrorsByName: Record<string, string> = {};\n\n await mapWithConcurrency(scorers, scorerConcurrency, async (scorer) => {\n if (signal?.aborted) return;\n const scorerStart = Date.now();\n try {\n const raw = await scorer.score(item.output, item.input, item.annotations, scorerContext);\n const scorerResult = normalizeScorerResult(raw);\n\n if (scorerResult.cost != null) {\n itemScorerCost += scorerResult.cost;\n }\n\n const scorerDuration = Date.now() - scorerStart;\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 ${JSON.stringify(item.input)}`;\n item.scores[scorer.name] = null;\n scoreDetails[scorer.name] = {\n score: null,\n metadata: scorerResult.metadata,\n duration: scorerDuration,\n cost: scorerResult.cost,\n };\n } else {\n item.scores[scorer.name] = round(scorerResult.score);\n scoreDetails[scorer.name] = {\n score: round(scorerResult.score),\n metadata: scorerResult.metadata,\n duration: scorerDuration,\n cost: scorerResult.cost,\n };\n }\n } catch (err) {\n // A cancelled call (AbortError) is not a scoring failure — leave the\n // pre-seeded null and record nothing.\n if ((err as { name?: string })?.name === 'AbortError') return;\n const errCost = extractScorerErrorCost(err);\n if (errCost != null) itemScorerCost += errCost;\n scorerErrorsByName[scorer.name] =\n `Scorer \"${scorer.name}\" threw: ${err instanceof Error ? err.message : String(err)}`;\n item.scores[scorer.name] = null;\n scoreDetails[scorer.name] = {\n score: null,\n duration: Date.now() - scorerStart,\n cost: errCost,\n };\n }\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 item.scorerCost = itemScorerCost > 0 ? itemScorerCost : undefined;\n return itemScorerCost;\n}\n","import type { AxlRuntime } from '@axlsdk/axl';\nimport type { EvalConfig, EvalResult, EvalItem, EvalSummary, RunEvalOptions } 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} from './utils.js';\nimport { scoreItem } from './score-item.js';\nimport { randomUUID } from 'node:crypto';\n\nfunction parseCost(cost: string): number {\n const match = cost.match(/^\\$?([\\d.]+)$/);\n if (!match) throw new Error(`Invalid cost format: \"${cost}\"`);\n return parseFloat(match[1]);\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 * Negative costs are rejected because (a) cost is a USD amount and negative\n * values are nonsensical, and (b) a negative cost would silently shrink\n * `totalCost` below the budget limit check at the processItem level,\n * letting a buggy/malicious workflow run unbounded. `0` is preserved\n * because free operations on paid models are valid.\n *\n * When a user-supplied value is rejected (present but invalid), we log\n * once per item via `console.warn` so the type violation is visible\n * rather than silently swallowed.\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}. Falling back to tracked cost (or undefined).`,\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\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 const items = await config.dataset.getItems();\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 const budgetLimit = config.budget ? parseCost(config.budget) : undefined;\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 let totalCost = 0;\n let budgetExceeded = false;\n\n async function processItem(item: (typeof items)[0], itemIndex: number): Promise<void> {\n if (options?.signal?.aborted) {\n evalItems[itemIndex] = {\n input: item.input,\n annotations: item.annotations,\n output: null,\n error: 'Cancelled',\n scores: {},\n };\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n return;\n }\n\n if (budgetExceeded) {\n evalItems[itemIndex] = {\n input: item.input,\n annotations: item.annotations,\n output: null,\n error: 'Budget exceeded',\n scores: {},\n };\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 try {\n // When captureTraces is on, wrap the user's executeWorkflow in\n // trackExecution so we get a per-item TraceEvent[] scoped via\n // AsyncLocalStorage. trackExecution's scope walks the parent chain, so\n // any nested trackExecution (e.g. from the CLI) continues to work.\n if (options?.captureTraces) {\n const tracked = await runtime.trackExecution(\n async () => executeWorkflow(item.input, runtime),\n { captureTraces: true },\n );\n evalItem.duration = Date.now() - itemStart;\n evalItem.output = tracked.result.output;\n // Prefer user-returned cost/metadata; fall back to tracked values.\n // Type-guarded so a non-number cost (e.g. `{ cost: 'free' }`) or a\n // non-object metadata (e.g. an array or scalar) doesn't silently\n // corrupt downstream math or shape expectations.\n evalItem.cost = extractUserCost(tracked.result) ?? tracked.cost;\n evalItem.metadata = extractUserMetadata(tracked.result) ?? tracked.metadata;\n if (tracked.traces && tracked.traces.length > 0) {\n evalItem.traces = tracked.traces;\n }\n if (evalItem.cost != null) {\n totalCost += evalItem.cost;\n }\n } else {\n const result = await executeWorkflow(item.input, runtime);\n evalItem.duration = Date.now() - itemStart;\n evalItem.output = result.output;\n evalItem.cost = extractUserCost(result);\n const meta = extractUserMetadata(result);\n if (meta) evalItem.metadata = meta;\n if (evalItem.cost != null) {\n totalCost += evalItem.cost;\n }\n }\n } catch (err) {\n evalItem.duration = Date.now() - itemStart;\n evalItem.error = err instanceof Error ? err.message : String(err);\n // Failed items are exactly when per-item traces are most valuable —\n // recover them from the captured-traces side-channel `trackExecution`\n // attaches to the error on the failure path.\n if (options?.captureTraces) {\n const captured = (err as { axlCapturedTraces?: unknown }).axlCapturedTraces;\n if (Array.isArray(captured) && captured.length > 0) {\n evalItem.traces = captured as EvalItem['traces'];\n }\n }\n evalItems[itemIndex] = evalItem;\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n return;\n }\n\n if (budgetLimit != null && totalCost > budgetLimit) {\n budgetExceeded = true;\n }\n\n // Score the item's output with all scorers (bounded fan-out). scoreItem\n // owns the determinism + cancellation + cost logic shared with rescore();\n // it returns the per-item scorer cost to fold into the running total.\n // NB: keep the await on its own line — `totalCost += await …` would read\n // totalCost BEFORE suspending, losing updates across concurrent items.\n const itemScorerCost = await scoreItem(\n evalItem,\n config.scorers,\n scorerConcurrency,\n scorerContext,\n options?.signal,\n );\n totalCost += itemScorerCost;\n evalItems[itemIndex] = evalItem;\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n }\n\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 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 } = scorerCounts(evalItems, name);\n scorerStats[name] = { ...computeStats(scores), scored, failed };\n }\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. We never throw — the result is still\n // useful; we flag it and let the CLI/consumer decide the exit code. Invalid\n // limits are ignored loudly so a typo can't silently disable 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 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 // 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 trackExecution'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,\n duration: Date.now() - startTime,\n items: evalItems,\n summary: {\n count: items.length,\n failures,\n scorers: scorerStats,\n timing,\n ...(degraded ? { degraded } : {}),\n },\n };\n}\n","import type { AxlRuntime } from '@axlsdk/axl';\nimport type { EvalResult, EvalItem, 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 { 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\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 */\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 concurrency = options?.concurrency ?? 5;\n const scorerConcurrency = options?.scorerConcurrency ?? 5;\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 let totalCost = 0;\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 (runner.ts) so cancellation behaves the same\n // in both 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 scores: {},\n };\n return;\n }\n\n // Pass through error items without scoring\n if (original.error) {\n rescored[itemIndex] = {\n input: original.input,\n annotations: original.annotations,\n output: original.output,\n error: original.error,\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 scores: {},\n scoreDetails: {},\n };\n\n // Same shared scoring path as runEval — determinism, cancellation, and cost\n // accounting all live in scoreItem. Keep the await off the `+=` line so the\n // read-modify-write isn't split by suspension across concurrent items.\n const itemScorerCost = await scoreItem(\n item,\n scorers,\n scorerConcurrency,\n scorerContext,\n options?.signal,\n );\n totalCost += itemScorerCost;\n rescored[itemIndex] = item;\n }\n\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 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 } = scorerCounts(rescored, name);\n scorerStats[name] = { ...computeStats(scores), scored, failed };\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: randomUUID(),\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,\n duration: Date.now() - startTime,\n items: rescored,\n summary: { count: result.items.length, failures, scorers: scorerStats },\n };\n}\n","import type { EvalResult } from './types.js';\nimport { randomUUID } from 'node:crypto';\nimport { round } from './utils.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 totalCost: number;\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 }\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\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 };\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 totalDuration: round(totalDuration),\n scorers,\n timing,\n };\n}\n","/**\n * CLI utilities for `axl-eval`.\n *\n * The actual implementations of the loader, glob, and config-detection\n * helpers live in `@axlsdk/axl`'s `cli-internals` so a fix to (e.g.) the\n * tsx loader registration applies to both axl-eval and axl-studio\n * atomically. This file is now a thin re-export plus the symmetric\n * module-resolution helpers from `@axlsdk/axl`.\n */\n\nexport {\n resolveRuntime,\n pickDefault,\n pickExport,\n CONFIG_CANDIDATES,\n findConfig,\n needsTsxLoader,\n importModule,\n expandGlob,\n registerConditions,\n} from '@axlsdk/axl';\n","import type { EvalConfig } from './types.js';\n\n/**\n * Validate an eval config's required fields and produce a diagnostic string\n * if invalid. Returns `undefined` when the config passes.\n *\n * Returns a single-line message tail (caller prepends the file path) so the\n * full error reads like: `Error: <file> <message>`.\n *\n * Goes beyond a falsy check to:\n * - catch `scorers: []` which previously silently ran with no scorers\n * - reject scorers arrays that contain non-callable entries (e.g. typo\n * `scorers: [null, undefined]` would crash deep inside `runEval`)\n * - reject non-string `workflow` (downstream `runtime.getWorkflow(...)`\n * would silently miss it)\n * - reject non-object `dataset` (must be a `dataset()` factory result)\n * - provide a `Got: { keys: [...] }` hint so users can spot typos like\n * `scorerS` vs `scorers` immediately\n *\n * Lives in its own module so unit tests can import it without triggering\n * `cli.ts`'s `main()` at module load time.\n */\nexport function validateEvalConfig(cfg: unknown): string | undefined {\n if (!cfg || typeof cfg !== 'object') {\n return `does not export a valid eval config — got ${cfg === null ? 'null' : typeof cfg}.`;\n }\n const c = cfg as Partial<EvalConfig>;\n const missing: string[] = [];\n if (!c.workflow) missing.push('workflow');\n if (!c.dataset) missing.push('dataset');\n if (!c.scorers) missing.push('scorers');\n\n if (missing.length > 0) {\n const keys = Object.keys(c as object).slice(0, 10);\n const got = keys.length > 0 ? ` Got: { ${keys.join(', ')} }.` : '';\n return `does not export a valid eval config (missing ${missing.join(', ')}).${got}`;\n }\n\n if (typeof c.workflow !== 'string') {\n return `exports a non-string workflow (got ${typeof c.workflow}) — workflow must be the registered workflow name.`;\n }\n if (typeof c.dataset !== 'object' || Array.isArray(c.dataset)) {\n return `exports a non-object dataset (got ${Array.isArray(c.dataset) ? 'array' : typeof c.dataset}) — use the dataset() factory.`;\n }\n if (typeof (c.dataset as { getItems?: unknown }).getItems !== 'function') {\n return `exports a dataset without a getItems() method — use the dataset() factory.`;\n }\n if (!Array.isArray(c.scorers) || c.scorers.length === 0) {\n return `exports an empty scorers array — at least one scorer is required.`;\n }\n const badScorerIdx = c.scorers.findIndex(\n (s) => !s || typeof (s as { score?: unknown }).score !== 'function',\n );\n if (badScorerIdx !== -1) {\n return `exports a scorers array with a non-scorer entry at index ${badScorerIdx} — each scorer must have a score() method (use the scorer() factory).`;\n }\n // Concurrency knobs must be positive integers when present. The worker pool\n // defensively clamps non-positive/non-finite values to 1 at runtime, but a\n // config that wrote `concurrency: 0` (or NaN via `Number(env)`) almost\n // certainly has a bug — surface it loudly, matching the `--concurrency` flag.\n for (const key of ['concurrency', 'scorerConcurrency'] as const) {\n const v = (c as Record<string, unknown>)[key];\n if (v !== undefined && (typeof v !== 'number' || !Number.isInteger(v) || v < 1)) {\n return `exports an invalid ${key} (${typeof v === 'number' ? v : typeof v}) — must be a positive integer.`;\n }\n }\n // The failure-rate gate must fail loud on a bad value, symmetric with the\n // `--max-scorer-error-rate` flag. Without this, a typo (e.g. `5` meaning \"5%\")\n // only `console.warn`s at runtime and silently disables the gate the user\n // explicitly opted into — the exact silent-no-op the feature exists to catch.\n {\n const v = (c as Record<string, unknown>).failOnScorerErrorRate;\n if (v !== undefined && (typeof v !== 'number' || !Number.isFinite(v) || v < 0 || v > 1)) {\n return `exports an invalid failOnScorerErrorRate (${typeof v === 'number' ? v : typeof v}) — must be a number between 0 and 1.`;\n }\n }\n return undefined;\n}\n","/**\n * Argument parsing for the `axl-eval` CLI, factored out of `cli.ts` so it can be\n * unit-tested without importing `cli.ts` (whose module body runs `main()` on\n * import).\n */\n\nexport const KNOWN_FLAGS = new Set([\n '--output',\n '--config',\n '--conditions',\n '--fail-on-regression',\n '--threshold',\n '--runs',\n '--capture-traces',\n '--concurrency',\n '--scorers',\n]);\n\n/**\n * The subset of flags `parseEvalArgs` consumes a following value for. NOT every\n * value-taking flag in the CLI: `--threshold` takes a value too but is parsed\n * by `runCompare`'s own parser, not here. Every entry MUST also be in\n * {@link KNOWN_FLAGS} — a value-flag missing from KNOWN_FLAGS would be rejected\n * as \"unknown\", and one missing from VALUE_FLAGS would silently swallow its\n * value into `paths`. A test asserts `VALUE_FLAGS ⊆ KNOWN_FLAGS`.\n */\nexport const VALUE_FLAGS = new Set([\n '--output',\n '--config',\n '--conditions',\n '--runs',\n '--concurrency',\n '--scorers',\n]);\n\nexport type ParsedEvalArgs = {\n outputPath?: string;\n configArg?: string;\n conditions: string[];\n runs: number;\n captureTraces: boolean;\n /** Item-level concurrency override (flag value). Clamped to >= 1. */\n concurrency?: number;\n /** Scorer names from `--scorers` (deduped, in first-seen order). */\n scorerNames?: string[];\n paths: string[];\n};\n\n/**\n * Read a positive integer from an environment variable. Returns `undefined`\n * when the var is absent, non-numeric, or `<= 0`, so a malformed value falls\n * through to the next precedence tier rather than poisoning the run.\n */\nexport function envInt(name: string): number | undefined {\n const raw = process.env[name];\n if (raw == null || raw === '') return undefined;\n const n = parseInt(raw, 10);\n if (!Number.isFinite(n) || n <= 0) return undefined;\n return n;\n}\n\nexport function parseEvalArgs(args: string[]): ParsedEvalArgs {\n let outputPath: string | undefined;\n let configArg: string | undefined;\n let conditions: string[] = [];\n let runs = 1;\n let captureTraces = false;\n let concurrency: number | undefined;\n let scorerNames: string[] | undefined;\n const paths: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (VALUE_FLAGS.has(arg)) {\n if (i + 1 >= args.length) {\n console.error(`Error: ${arg} requires a value`);\n process.exit(1);\n }\n const value = args[++i];\n if (arg === '--output') outputPath = value;\n else if (arg === '--config') configArg = value;\n else if (arg === '--runs') runs = Math.max(1, parseInt(value, 10) || 1);\n else if (arg === '--concurrency') {\n // Clamp to a floor of 1 with a warning (matches `--runs`' clamp ethos\n // but surfaces the typo). A `0` here would otherwise spawn zero workers.\n // Note the intentional asymmetry with `envInt` above: an explicit flag\n // typo is worth a warning, whereas a malformed ambient env var falls\n // through silently to the next precedence tier.\n const n = parseInt(value, 10);\n if (!Number.isFinite(n) || n <= 0) {\n console.error(`[axl-eval] Ignoring invalid --concurrency \"${value}\"; using 1.`);\n concurrency = 1;\n } else {\n concurrency = n;\n }\n } else if (arg === '--scorers') {\n scorerNames = [\n ...new Set(\n value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n ),\n ];\n } else {\n conditions = value\n .split(',')\n .map((c) => c.trim())\n .filter(Boolean);\n }\n } else if (arg === '--capture-traces') {\n // Boolean flag — no value consumed.\n captureTraces = true;\n } else if (arg.startsWith('--')) {\n if (!KNOWN_FLAGS.has(arg)) {\n console.error(`Unknown flag: ${arg}`);\n process.exit(1);\n }\n } else {\n paths.push(arg);\n }\n }\n\n return {\n outputPath,\n configArg,\n conditions,\n runs,\n captureTraces,\n concurrency,\n scorerNames,\n paths,\n };\n}\n"],"mappings":"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","names":["round","round","round","import_node_crypto","import_node_crypto","round","readFileAsync","writeFileAsync","randomUUID"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/bootstrap.ts","../src/utils.ts","../src/compare.ts","../src/scorer.ts","../src/score-item.ts","../src/runner.ts","../src/rescore.ts","../src/multi-run.ts","../src/cli-utils.ts","../src/cli-validate.ts","../src/cli-args.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readdirSync, statSync } from 'node:fs';\nimport { readFile as readFileAsync, writeFile as writeFileAsync, mkdir } from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { AxlRuntime, EvalExecuteWorkflow } from '@axlsdk/axl';\nimport { evalCompare, evaluateScorerErrorRateGate } from './compare.js';\nimport { runEval } from './runner.js';\nimport { rescore } from './rescore.js';\nimport { aggregateRuns } from './multi-run.js';\nimport type { MultiRunSummary } from './multi-run.js';\nimport type { EvalConfig, EvalResult } from './types.js';\nimport {\n findConfig,\n resolveRuntime,\n importModule,\n registerConditions,\n pickDefault,\n pickExport,\n expandGlob,\n CONFIG_CANDIDATES,\n} from './cli-utils.js';\nimport { validateEvalConfig } from './cli-validate.js';\nimport { parseEvalArgs, envInt } from './cli-args.js';\nimport { scorerCounts } from './utils.js';\n\n/**\n * Refuse to certify a comparison and exit non-zero, with one consistent\n * message format. Routes both the scorer-filtered guard and the\n * `--max-scorer-error-rate` failure-rate gate through a single path so the\n * \"why CI failed\" line always reads the same.\n */\nfunction refuseToGate(reason: string): never {\n console.error(`[axl-eval] Refusing to gate: ${reason}`);\n process.exit(1);\n}\n\n/**\n * Read a scorer's `scored`/`failed` counts from a summary entry, falling back\n * to recomputing from `items` when the fields are absent (pre-0.18.0\n * artifacts). `items` is omitted for multi-run summaries that carry no items —\n * there the fields are authoritative (summed by `aggregateRuns`).\n */\nfunction scorerSampleCounts(\n entry: { scored?: number; failed?: number; skipped?: number },\n name: string,\n items?: EvalResult['items'],\n): { scored: number; failed: number; skipped: number } {\n if (entry.scored != null && entry.failed != null) {\n // `scored`/`failed` are authoritative; `skipped` was added later, so an\n // 0.18.0-era artifact may carry the first two without it — recompute that one\n // field from items when we can, else 0.\n const skipped = entry.skipped ?? (items ? scorerCounts(items, name).skipped : 0);\n return { scored: entry.scored, failed: entry.failed, skipped };\n }\n if (items) return scorerCounts(items, name);\n return { scored: entry.scored ?? 0, failed: entry.failed ?? 0, skipped: entry.skipped ?? 0 };\n}\n\n/** Install a SIGINT/SIGTERM handler that aborts an in-flight eval gracefully.\n * First signal: aborts the controller so runEval / rescore propagate cancellation\n * through ScorerContext.signal into in-flight provider.chat calls. The eval\n * unwinds normally and runtime.shutdown() runs in the `finally` block.\n * Second signal: hard exit — the user has signalled twice; cleanup is hung\n * or taking too long, so we abandon gracefulness rather than appear frozen. */\nfunction installAbortHandler(controller: AbortController): void {\n let signalled = false;\n const onSignal = (sig: NodeJS.Signals) => {\n if (signalled) {\n console.error(`\\n[axl-eval] Second ${sig} — forcing exit.`);\n process.exit(130);\n }\n signalled = true;\n console.error(`\\n[axl-eval] ${sig} received — cancelling eval (press again to force exit)...`);\n controller.abort();\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {\n console.log(`\nUsage:\n axl-eval <path> Run eval file(s)\n axl-eval <path> --runs <n> Run eval N times (multi-run)\n axl-eval <path> --output <file> Save results to JSON\n axl-eval <path> --config <file> Use config file for runtime\n axl-eval <path> --conditions <list> Node.js import conditions (comma-separated)\n axl-eval <path> --concurrency <n> Override item concurrency (flag > env\n AXL_EVAL_CONCURRENCY > config > 5).\n Max concurrent scorer calls is\n concurrency x scorerConcurrency (the\n per-eval scorerConcurrency defaults to 5).\n axl-eval <path> --scorers <a,b> Run only the named scorers (single eval\n file only). Stamps the result as a\n subset so compare won't treat it as a\n full baseline.\n axl-eval <path> --capture-traces Populate EvalItem.traces on every item\n (success + failure). Adds memory\n overhead proportional to dataset size\n x turns x agents; off by default.\n axl-eval rescore <results> <eval-file> Re-run scorers on saved outputs\n axl-eval compare <a> <b> Compare two eval result files\n axl-eval compare <a> <b> --threshold <v> Set regression threshold (global or per-scorer)\n axl-eval compare <a> <b> --fail-on-regression Exit 1 if regressions\n axl-eval compare <a> <b> --max-scorer-error-rate <0..1> Exit 1 if a scorer's\n failure rate exceeds the limit on\n either side (deterministic scorers\n tolerate zero failures). Always warns\n when either side rests on a thinned\n sample, even without this flag.\n\nConfig auto-detection (when --config is not specified):\n ${CONFIG_CANDIDATES.join(' -> ')}\n\nWhen a config is found, the exported AxlRuntime is passed to executeWorkflow\nand cost is tracked automatically via runtime.trackCost().\nWhen no config is found, a bare AxlRuntime is created (providers from env vars).\n`);\n process.exit(0);\n }\n\n if (args[0] === 'compare') {\n // `compare` is pure computation — no LLM calls, no AbortSignal plumbing needed.\n await runCompare(args.slice(1));\n return;\n }\n\n // SIGINT/SIGTERM aborts in-flight LLM calls (eval + rescore) instead of leaving\n // the process to hard-exit mid-request, which would skip runtime.shutdown() and\n // leak streaming-buffer state.\n const controller = new AbortController();\n installAbortHandler(controller);\n\n if (args[0] === 'rescore') {\n await runRescore(args.slice(1), controller.signal);\n return;\n }\n\n await runEvalCommand(args, controller.signal);\n}\n\nfunction parseThresholdArg(args: string[]): Record<string, number> | number | undefined {\n const idx = args.indexOf('--threshold');\n if (idx === -1 || idx + 1 >= args.length) return undefined;\n const value = args[idx + 1];\n\n // Global numeric threshold: --threshold 0.05\n if (/^[\\d.]+$/.test(value)) return parseFloat(value);\n\n // Per-scorer map: --threshold accuracy=0,tone=0.1\n const map: Record<string, number> = {};\n for (const pair of value.split(',')) {\n const [key, val] = pair.split('=');\n if (key && val != null) map[key.trim()] = parseFloat(val.trim());\n }\n return Object.keys(map).length > 0 ? map : undefined;\n}\n\n/**\n * Parse `--max-scorer-error-rate <0..1>`. Returns the numeric limit, or\n * `undefined` when the flag is absent. Exits non-zero on a malformed value\n * (fail loud — a typo'd gate threshold must not silently disable the gate).\n */\nfunction parseMaxScorerErrorRate(args: string[]): number | undefined {\n const idx = args.indexOf('--max-scorer-error-rate');\n if (idx === -1) return undefined;\n if (idx + 1 >= args.length) {\n console.error('Error: --max-scorer-error-rate requires a value in [0, 1]');\n process.exit(1);\n }\n const raw = args[idx + 1];\n // Strict numeric parse — `parseFloat('0.5abc')` returns 0.5 and `parseFloat('0,5')`\n // returns 0, both of which would silently set an unintended gate threshold. Reject\n // anything that isn't a clean decimal (matches `parseThresholdArg`'s guard).\n const n = /^\\d*\\.?\\d+$/.test(raw.trim()) ? Number(raw) : NaN;\n if (!Number.isFinite(n) || n < 0 || n > 1) {\n console.error(`Error: --max-scorer-error-rate must be a number in [0, 1], got \"${raw}\"`);\n process.exit(1);\n }\n return n;\n}\n\n/**\n * If a raw compare input (single result or multi-run array) was produced by a\n * `--scorers` filtered run, return the scorer names it ran; otherwise undefined.\n * Reads the first run's metadata — a multi-run group shares the same stamp.\n */\nfunction scorerFilteredScorers(r: EvalResult | EvalResult[]): string[] | undefined {\n const first = Array.isArray(r) ? r[0] : r;\n const meta = first?.metadata;\n if (!meta || meta.scorerFiltered !== true) return undefined;\n return Array.isArray(meta.scorersRun) ? (meta.scorersRun as string[]) : [];\n}\n\nasync function runCompare(args: string[]) {\n const failOnRegression = args.includes('--fail-on-regression');\n const thresholds = parseThresholdArg(args);\n const maxScorerErrorRate = parseMaxScorerErrorRate(args);\n // Exclude flags and the values consumed by value-taking flags so neither a\n // threshold nor an error-rate value is mistaken for a result file path.\n const valueFlags = new Set(['--threshold', '--max-scorer-error-rate']);\n const files = args.filter(\n (a, i) => !a.startsWith('--') && !(i > 0 && valueFlags.has(args[i - 1])),\n );\n\n if (files.length !== 2) {\n console.error(\n 'Usage: axl-eval compare <baseline.json> <candidate.json> [--threshold <value>] [--fail-on-regression] [--max-scorer-error-rate <0..1>]',\n );\n process.exit(1);\n }\n\n const baselineRaw = JSON.parse(await readFileAsync(files[0], 'utf-8'));\n const candidateRaw = JSON.parse(await readFileAsync(files[1], 'utf-8'));\n const baseline: EvalResult | EvalResult[] = baselineRaw;\n const candidate: EvalResult | EvalResult[] = candidateRaw;\n\n // A scorer-filtered result (CLI `--scorers`) tested only a subset of scorers,\n // so it isn't a sound baseline/candidate for a full comparison. Check this\n // BEFORE evalCompare(): a subset-vs-full comparison has mismatched scorer sets\n // and evalCompare() would throw a generic \"different scorers\" error that never\n // mentions --scorers. Warn loudly here so the cause is actionable; under\n // `--fail-on-regression`, refuse outright (a swallowed stderr line wouldn't\n // actually prevent the footgun).\n const filteredSides = (\n [\n ['baseline', baseline],\n ['candidate', candidate],\n ] as const\n ).filter(([, r]) => scorerFilteredScorers(r) != null);\n for (const [side, r] of filteredSides) {\n const ran = scorerFilteredScorers(r);\n const ranStr = ran && ran.length ? ` (ran: ${ran.join(', ')})` : '';\n console.error(\n `[axl-eval] WARNING: ${side} was run with --scorers — it tested only a subset${ranStr}, so this comparison is incomplete.`,\n );\n }\n if (failOnRegression && filteredSides.length > 0) {\n refuseToGate(\n `${filteredSides.map(([s]) => s).join(', ')} was run with --scorers (a scorer subset); re-run without --scorers for a complete baseline.`,\n );\n }\n\n const compareOptions = thresholds != null ? { thresholds } : undefined;\n const comparison = evalCompare(baseline, candidate, compareOptions);\n\n console.log(\n `\\nCompare: baseline (${comparison.baseline.id.slice(0, 8)}) -> candidate (${comparison.candidate.id.slice(0, 8)})\\n`,\n );\n\n const scorerNames = Object.keys(comparison.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 6);\n const hasCI = scorerNames.some((n) => comparison.scorers[n].ci != null);\n\n const ciHeader = hasCI ? ' CI 95% Sig' : '';\n const ciRule = hasCI ? ' ---------------- ---' : '';\n console.log(` ${'Scorer'.padEnd(maxNameLen)} Baseline Candidate Delta Change${ciHeader}`);\n console.log(` ${''.padEnd(maxNameLen, '-')} -------- --------- -------- ------${ciRule}`);\n\n for (const name of scorerNames) {\n const s = comparison.scorers[name];\n const sign = s.delta > 0 ? '+' : '';\n let line = ` ${name.padEnd(maxNameLen)} ${s.baselineMean.toFixed(3).padStart(8)} ${s.candidateMean.toFixed(3).padStart(9)} ${(sign + s.delta.toFixed(3)).padStart(8)} ${(sign + s.deltaPercent.toFixed(1) + '%').padStart(6)}`;\n if (hasCI) {\n if (s.ci) {\n const lo = (s.ci.lower >= 0 ? '+' : '') + s.ci.lower.toFixed(4);\n const hi = (s.ci.upper >= 0 ? '+' : '') + s.ci.upper.toFixed(4);\n const sig = s.significant ? ' *' : ' ';\n line += ` [${lo}, ${hi}]${sig}`;\n } else {\n line += ' —'.padEnd(22);\n }\n }\n console.log(line);\n }\n\n if (comparison.timing) {\n const t = comparison.timing;\n const sign = t.delta > 0 ? '+' : '';\n console.log(\n `\\n Timing: baseline ${(t.baselineMean / 1000).toFixed(2)}s -> candidate ${(t.candidateMean / 1000).toFixed(2)}s (${sign}${t.deltaPercent.toFixed(1)}%)`,\n );\n }\n if (comparison.cost) {\n const c = comparison.cost;\n const sign = c.delta > 0 ? '+' : '';\n console.log(\n ` Cost: baseline $${c.baselineTotal.toFixed(2)} -> candidate $${c.candidateTotal.toFixed(2)} (${sign}${c.deltaPercent.toFixed(1)}%)`,\n );\n }\n\n const baselineRef = Array.isArray(baseline) ? baseline[0] : baseline;\n const stable = Math.max(\n 0,\n baselineRef.items.length - comparison.regressions.length - comparison.improvements.length,\n );\n console.log(\n `\\n Regressions: ${comparison.regressions.length} | Improvements: ${comparison.improvements.length} | Stable: ${stable}\\n`,\n );\n\n // Scorer failure-rate signal. Always WARN loudly when either side rests on a\n // thinned sample (a scorer ran and failed on some items) — a regression check\n // computed over survivors can look green while half the judges errored. Only\n // REFUSE to gate when the user opted in with `--max-scorer-error-rate` AND a\n // scorer is over tolerance (type-aware: deterministic scorers tolerate zero\n // failures, LLM judges use the flag value), or a scorer produced no scored\n // items at all on a side (a zero-sample mean can't be certified).\n let sawThinnedSample = false;\n for (const name of scorerNames) {\n const s = comparison.scorers[name];\n const bFailed = s.baselineFailed ?? 0;\n const cFailed = s.candidateFailed ?? 0;\n if (bFailed > 0 || cFailed > 0) {\n sawThinnedSample = true;\n const bAtt = (s.baselineScored ?? 0) + bFailed;\n const cAtt = (s.candidateScored ?? 0) + cFailed;\n console.error(\n `[axl-eval] WARNING: scorer \"${name}\" failed on some items ` +\n `(baseline ${bFailed}/${bAtt}, candidate ${cFailed}/${cAtt}); ` +\n `the means above are computed over the surviving sample.`,\n );\n }\n // Conditional scorers (`applies`) skip N/A items. Skips never move the\n // delta (excluded from both means), but they make the two per-side means\n // cover different applicable subsets when the sides skipped different COUNTS,\n // OR the same count of DIFFERENT items — the latter shows up as a paired\n // shortfall: fewer items scored on BOTH sides (`n`) than either side scored\n // alone. (`bSkipped !== cSkipped` alone would miss the disjoint-but-equal\n // case.) Note it (advisory only; not a gate; failures are covered by the\n // separate WARNING above).\n const bSkipped = s.baselineSkipped ?? 0;\n const cSkipped = s.candidateSkipped ?? 0;\n const pairedN = s.n ?? 0;\n const minScored = Math.min(s.baselineScored ?? 0, s.candidateScored ?? 0);\n const skipsDiverge =\n (bSkipped > 0 || cSkipped > 0) && (bSkipped !== cSkipped || pairedN < minScored);\n if (skipsDiverge) {\n console.error(\n `[axl-eval] NOTE: scorer \"${name}\" applies to different subsets per side ` +\n `(baseline ${bSkipped} N/A, candidate ${cSkipped} N/A; ${pairedN} item(s) scored on both); ` +\n `the two means cover different applicable subsets, so compare the delta with care.`,\n );\n }\n }\n // Tell the user how to make the advisory warning blocking (when they haven't).\n if (sawThinnedSample && maxScorerErrorRate == null) {\n console.error(\n `[axl-eval] (advisory — pass --max-scorer-error-rate <0..1> to fail CI on a thinned sample)`,\n );\n }\n\n // Gate-side refusal (opt-in). The decision lives in evaluateScorerErrorRateGate\n // (pure + unit-tested) so the same type-aware tolerance + zero-sample logic\n // isn't re-implemented here and at the source-side gate in runEval.\n if (maxScorerErrorRate != null) {\n const reason = evaluateScorerErrorRateGate(comparison, maxScorerErrorRate);\n if (reason) refuseToGate(reason);\n }\n\n if (failOnRegression && comparison.regressions.length > 0) {\n // When CI is available, only fail on significant regressions\n const hasSignificance = scorerNames.some((n) => comparison.scorers[n].significant != null);\n if (hasSignificance) {\n const hasSignificantRegression = scorerNames.some(\n (n) => comparison.scorers[n].significant === true && comparison.scorers[n].delta < 0,\n );\n if (hasSignificantRegression) process.exit(1);\n } else {\n process.exit(1);\n }\n }\n}\n\nasync function runRescore(args: string[], signal: AbortSignal) {\n const { outputPath, configArg, conditions, concurrency, scorerNames, paths } =\n parseEvalArgs(args);\n\n if (paths.length < 2) {\n console.error('Usage: axl-eval rescore <results.json> <eval-file> [--output <file>]');\n process.exit(1);\n }\n\n // --scorers is a run-command-only filter — rescore always re-runs the full\n // scorer set from the eval file. Fail loudly rather than silently ignoring it\n // (it parses as a known flag, so it wouldn't trip the unknown-flag guard).\n if (scorerNames?.length) {\n console.error(\n 'Error: --scorers is not supported with rescore; pass a scorer subset in the eval file instead.',\n );\n process.exit(1);\n }\n\n // Honor the same item-concurrency override as the run command (flag > env).\n // scorerConcurrency keeps its rescore default (5).\n const itemConcurrency = concurrency ?? envInt('AXL_EVAL_CONCURRENCY');\n\n const [resultsPath, evalFilePath] = paths;\n const raw = JSON.parse(await readFileAsync(resultsPath, 'utf-8'));\n const results: EvalResult[] = Array.isArray(raw) ? raw : [raw];\n\n const runtime = await getRuntime(configArg, conditions);\n try {\n const mod = await importModule(path.resolve(evalFilePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n if (!evalConfig || typeof evalConfig !== 'object') {\n console.error(\n `Error: ${evalFilePath} does not export an eval config object — got ${evalConfig === null ? 'null' : typeof evalConfig}.`,\n );\n process.exit(1);\n }\n if (!Array.isArray(evalConfig.scorers) || evalConfig.scorers.length === 0) {\n console.error(`Error: ${evalFilePath} does not export a non-empty scorers array.`);\n process.exit(1);\n }\n\n const rescored: EvalResult[] = [];\n for (const resultData of results) {\n if (signal.aborted) break;\n rescored.push(\n await rescore(resultData, evalConfig.scorers, runtime, {\n signal,\n ...(itemConcurrency != null ? { concurrency: itemConcurrency } : {}),\n }),\n );\n }\n\n for (const r of rescored) {\n console.log('\\n' + formatTable(r) + '\\n');\n }\n\n if (outputPath) {\n const output = Array.isArray(raw) ? rescored : rescored[0];\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Rescored results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n}\n\n/**\n * Resolve a CLI path argument into a list of eval files.\n *\n * Accepts:\n * - An explicit file path (`path/to/foo.eval.ts`)\n * - A directory (lists `*.eval.[mc]?[jt]sx?` inside, non-recursive)\n * - A glob pattern: `evals/*.eval.ts`, `evals/**\\/*.eval.ts`, `**\\/*.eval.ts`\n *\n * Glob expansion mirrors the studio eval-loader's so users get the same\n * behavior in both places. Without it, users running on Windows or with\n * quoted patterns hit confusing \"file not found\" errors when the shell\n * couldn't expand the glob.\n */\nfunction collectEvalFiles(p: string): string[] {\n if (p.includes('*')) return expandGlob(p, process.cwd());\n const resolved = path.resolve(p);\n try {\n const stat = statSync(resolved);\n if (stat.isDirectory()) {\n const entries = readdirSync(resolved);\n return entries\n .filter((e) => /\\.eval\\.[mc]?[jt]sx?$/.test(e))\n .map((e) => path.join(resolved, e));\n }\n return [resolved];\n } catch {\n return [resolved];\n }\n}\n\n/** Render observed workflows for a terse header line. Multiple → comma-separated. */\nfunction formatWorkflows(workflows: unknown): string {\n if (!Array.isArray(workflows) || workflows.length === 0) return '(unknown)';\n return (workflows as unknown[]).filter((w): w is string => typeof w === 'string').join(', ');\n}\n\nfunction formatTable(result: EvalResult): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(result.summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 8;\n\n lines.push(\n `Eval: ${formatWorkflows(result.metadata.workflows)} x ${result.dataset} (${result.summary.count} items)`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean'.padStart(colWidth)} ${'Min'.padStart(colWidth)} ${'Max'.padStart(colWidth)} ${'p50'.padStart(colWidth)} ${'p95'.padStart(colWidth)}`,\n );\n\n const ruleLen = maxNameLen + 2 + (colWidth + 2) * 5;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = result.summary.scorers[name];\n const { scored, failed, skipped } = scorerSampleCounts(s, name, result.items);\n // Loud trailing annotation: `failed > 0` means the mean rests on a thinned\n // sample; `skipped > 0` (an `applies`-conditional scorer) labels items the\n // scorer deliberately didn't run — crucial so a fully-skipped scorer (all\n // `--`) reads as \"N/A\" rather than \"broken\". Both shown only when non-zero so\n // clean, unconditional runs stay uncluttered.\n const annotationParts: string[] = [];\n if (failed > 0) annotationParts.push(`${scored}/${scored + failed} scored, ${failed} failed`);\n if (skipped > 0) annotationParts.push(`${skipped} N/A`);\n const annotation = annotationParts.length > 0 ? ` (${annotationParts.join(', ')})` : '';\n // Detect scorers with no valid scores (all items errored → computeStats([]) → all zeros)\n if (scored === 0) {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)} ${'--'.padStart(colWidth)}${annotation}`,\n );\n } else {\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${s.mean.toFixed(2).padStart(colWidth)} ${s.min.toFixed(2).padStart(colWidth)} ${s.max.toFixed(2).padStart(colWidth)} ${s.p50.toFixed(2).padStart(colWidth)} ${s.p95.toFixed(2).padStart(colWidth)}${annotation}`,\n );\n }\n }\n\n if (result.summary.timing) {\n const t = result.summary.timing;\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${(t.mean / 1000).toFixed(2).padStart(colWidth)}s ${(t.p50 / 1000).toFixed(2).padStart(colWidth)}s ${(t.p95 / 1000).toFixed(2).padStart(colWidth)}s`,\n );\n }\n\n const durationSec = (result.duration / 1000).toFixed(1);\n const costStr = result.totalCost > 0 ? `$${result.totalCost.toFixed(2)}` : '$0.00';\n lines.push('');\n lines.push(\n ` Failures: ${result.summary.failures}/${result.summary.count} | Cost: ${costStr} | Duration: ${durationSec}s`,\n );\n\n const itemsWithErrors = result.items.filter((i) => i.scorerErrors?.length);\n if (itemsWithErrors.length > 0) {\n const uniqueErrors = [...new Set(itemsWithErrors.flatMap((i) => i.scorerErrors!))];\n lines.push('');\n lines.push(\n ` Scorer errors (${itemsWithErrors.length}/${result.summary.count} items affected):`,\n );\n for (const err of uniqueErrors.slice(0, 5)) {\n lines.push(` - ${err}`);\n }\n if (uniqueErrors.length > 5) {\n lines.push(` ... and ${uniqueErrors.length - 5} more`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatMultiRunTable(summary: MultiRunSummary): string {\n const lines: string[] = [];\n const scorerNames = Object.keys(summary.scorers);\n const maxNameLen = Math.max(...scorerNames.map((n) => n.length), 'Scorer'.length);\n const colWidth = 16;\n\n lines.push(\n `Eval: ${formatWorkflows(summary.workflows)} x ${summary.dataset} \\u2014 ${summary.runCount} runs`,\n );\n lines.push(\n ` ${'Scorer'.padEnd(maxNameLen)} ${'Mean \\u00b1 Std'.padStart(colWidth)} ${'Min'.padStart(8)} ${'Max'.padStart(8)}`,\n );\n const ruleLen = maxNameLen + 2 + colWidth + 2 + 8 + 2 + 8;\n lines.push(' ' + '\\u2500'.repeat(ruleLen));\n\n for (const name of scorerNames) {\n const s = summary.scorers[name];\n const meanStd = `${s.mean.toFixed(3)} \\u00b1 ${s.std.toFixed(3)}`;\n // Multi-run summaries have no items, so the summed scored/failed fields are\n // authoritative (no fallback recompute possible). Annotate when failed > 0.\n const { scored, failed } = scorerSampleCounts(s, name);\n const annotation =\n failed > 0 ? ` (${scored}/${scored + failed} scored, ${failed} failed)` : '';\n lines.push(\n ` ${name.padEnd(maxNameLen)} ${meanStd.padStart(colWidth)} ${s.min.toFixed(3).padStart(8)} ${s.max.toFixed(3).padStart(8)}${annotation}`,\n );\n }\n\n if (summary.timing) {\n lines.push(\n ` ${'Timing'.padEnd(maxNameLen)} ${((summary.timing.mean / 1000).toFixed(2) + ' \\u00b1 ' + (summary.timing.std / 1000).toFixed(2) + 's').padStart(colWidth)}`,\n );\n }\n\n const costStr = summary.totalCost > 0 ? `$${summary.totalCost.toFixed(2)}` : '$0.00';\n const durationStr = (summary.totalDuration / 1000).toFixed(1);\n lines.push('');\n lines.push(` Total Cost: ${costStr} | Total Duration: ${durationStr}s`);\n\n return lines.join('\\n');\n}\n\n/**\n * Print each degraded scorer (set by `runEval` when `failOnScorerErrorRate`\n * tripped) to stderr and return whether the run was degraded, so the caller can\n * count the file as failed (→ non-zero exit). Quiet when nothing degraded.\n */\nfunction reportDegraded(result: EvalResult, label: string): boolean {\n const d = result.summary.degraded;\n if (!d || d.length === 0) return false;\n for (const x of d) {\n const attempted = x.scored + x.failed;\n const limitStr =\n x.type === 'deterministic'\n ? 'deterministic zero-tolerance'\n : `${(x.limit * 100).toFixed(1)}% limit`;\n console.error(\n `[axl-eval] DEGRADED: ${label} scorer \"${x.scorer}\" (${x.type}) failed ` +\n `${(x.rate * 100).toFixed(1)}% (${x.failed}/${attempted}), over the ${limitStr}.`,\n );\n }\n return true;\n}\n\n/**\n * Advisory (non-fatal): a conditional scorer (`applies`) that ended up applicable\n * to ZERO items — every item was skipped as N/A, nothing scored or failed. Its\n * mean is a meaningless empty-sample 0 and the failure-rate gate can't assess it\n * (a zero-sample scorer is never `degraded`). That's almost always a\n * misconfiguration: an over-strict predicate, a dataset missing the flagged\n * items, or a predicate that forgot to `return`. The `(N N/A)` table annotation\n * hints at it, but a fully-skipped GATE scorer would otherwise exit 0 with no\n * stderr signal — this closes that silent-green hole without changing the exit\n * code (skips are legitimately conditional; we inform, we don't fail).\n */\nfunction reportFullySkippedScorers(result: EvalResult, label: string): void {\n for (const [name, entry] of Object.entries(result.summary.scorers)) {\n const { scored, failed, skipped } = scorerSampleCounts(entry, name, result.items);\n if (skipped > 0 && scored + failed === 0) {\n console.error(\n `[axl-eval] NOTE: ${label} scorer \"${name}\" was not applicable to any item ` +\n `(${skipped} N/A, 0 scored) — its mean is not meaningful. Check the scorer's ` +\n `\\`applies\\` predicate and dataset if you expected it to run.`,\n );\n }\n }\n}\n\n/**\n * A run where EVERY item errored in the workflow (0 succeeded) produced no valid\n * output to score — the eval is meaningless and must never pass CI green. This\n * is distinct from (and complementary to) the scorer failure-rate gate: that one\n * is about a flaky/failing *scorer*, this is about a broken *workflow*. The\n * scorer gate deliberately ignores a zero-sample scorer (nothing ran), so without\n * this guard a 100%-workflow-error run exits 0 — a silent-green trap.\n *\n * Non-configurable on purpose: a 0%-success eval is unambiguously broken, so this\n * always fails. (A configurable `failOnItemErrorRate` for PARTIAL workflow-failure\n * gating is a reasonable future opt-in; the per-item failure count is already shown\n * loudly in the table either way.) Returns whether the run was a total wipeout.\n */\nfunction reportTotalWipeout(result: EvalResult, label: string): boolean {\n const { count, failures } = result.summary;\n if (count === 0 || failures < count) return false;\n console.error(\n `[axl-eval] FAILED: ${label} — all ${count} item(s) errored in the workflow ` +\n `(0 succeeded); the eval produced no scorable output.`,\n );\n return true;\n}\n\n// ── Runtime resolution ─────────────────────────────────────────────\n\nasync function resolveRuntimeFromConfig(configPath: string): Promise<AxlRuntime> {\n try {\n const mod = await importModule(configPath, import.meta.url);\n const runtime = resolveRuntime(mod) as AxlRuntime;\n\n if (!runtime || typeof runtime.execute !== 'function') {\n console.error(`Config must export a default AxlRuntime instance.`);\n if (runtime) {\n const keys = Object.keys(runtime as object)\n .slice(0, 5)\n .join(', ');\n console.error(` Got: ${typeof runtime}${keys ? ` with keys: { ${keys} }` : ''}`);\n }\n console.error(\n `Example:\\n import { AxlRuntime } from '@axlsdk/axl';\\n export default new AxlRuntime({ ... });`,\n );\n process.exit(1);\n }\n\n return runtime;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (\n /Cannot use import statement|Unexpected reserved word|top-level await|exports is not defined/.test(\n msg,\n )\n ) {\n const ext = path.extname(configPath);\n console.error(`[axl-eval] Config failed to load due to a CJS/ESM compatibility issue.`);\n if (ext === '.ts' || ext === '.tsx') {\n console.error(\n ` Tip: try renaming to .mts to force ESM format, or ensure tsx is installed and up to date.`,\n );\n } else {\n console.error(` Tip: add \"type\": \"module\" to your package.json.`);\n }\n console.error();\n }\n console.error(`Failed to load config:`, err);\n process.exit(1);\n }\n}\n\nasync function getRuntime(configArg?: string, conditions?: string[]): Promise<AxlRuntime> {\n // Register import conditions before any config loading\n if (conditions && conditions.length > 0) {\n await registerConditions(conditions);\n }\n\n // 1. Explicit --config\n if (configArg) {\n const configPath = path.resolve(process.cwd(), configArg);\n const stat = statSync(configPath, { throwIfNoEntry: false });\n if (!stat?.isFile()) {\n console.error(`Config file not found: ${configPath}`);\n process.exit(1);\n }\n console.error(`[axl-eval] Loading config from ${configPath}`);\n return resolveRuntimeFromConfig(configPath);\n }\n\n // 2. Auto-detect\n const found = findConfig(process.cwd());\n if (found) {\n console.error(`[axl-eval] Auto-detected config: ${found}`);\n return resolveRuntimeFromConfig(found);\n }\n\n // 3. Bare runtime (providers from env vars)\n const { AxlRuntime } = await import('@axlsdk/axl');\n return new AxlRuntime();\n}\n\n// ── Main eval command ──────────────────────────────────────────────\n\nasync function runEvalCommand(args: string[], signal: AbortSignal) {\n const {\n outputPath,\n configArg,\n conditions,\n runs,\n captureTraces,\n concurrency,\n scorerNames,\n paths,\n } = parseEvalArgs(args);\n\n if (paths.length === 0) {\n console.error('Error: No eval file path provided');\n process.exit(1);\n }\n\n const evalFiles: string[] = [];\n for (const p of paths) {\n evalFiles.push(...collectEvalFiles(p));\n }\n\n if (evalFiles.length === 0) {\n console.error('Error: No eval files found');\n process.exit(1);\n }\n\n // --scorers is single-file only — filtering by name across a glob/dir of evals\n // with different scorer sets is ambiguous. Fail fast, before importing any\n // module, rather than discovering the conflict mid-loop.\n if (scorerNames?.length && evalFiles.length > 1) {\n console.error(`Error: --scorers requires a single eval file (matched ${evalFiles.length}).`);\n process.exit(1);\n }\n\n const runtime = await getRuntime(configArg, conditions);\n const results: EvalResult[] = [];\n let failedFiles = 0;\n\n try {\n for (const filePath of evalFiles) {\n // Short-circuit if the user aborted between eval files. The in-flight eval\n // unwinds on its own via runEval({ signal }); this prevents starting the next one.\n if (signal.aborted) break;\n try {\n const mod = await importModule(path.resolve(filePath), import.meta.url);\n const evalConfig = pickDefault<EvalConfig>(mod);\n\n const validationError = validateEvalConfig(evalConfig);\n if (validationError) {\n console.error(`Error: ${filePath} ${validationError}`);\n failedFiles++;\n continue;\n }\n\n // Concurrency override precedence: flag > env > config > default.\n // Mutating evalConfig in place mirrors how this loop already stamps\n // result.metadata. `concurrency` is pure scheduling — never changes\n // results — so a per-run override is always safe.\n evalConfig.concurrency =\n concurrency ?? envInt('AXL_EVAL_CONCURRENCY') ?? evalConfig.concurrency ?? 5;\n\n // --scorers: run a subset of scorers for a focused iteration loop.\n // (The single-file guard already ran before the loop.) Validate-then-\n // filter so the error lists every available name.\n if (scorerNames?.length) {\n const available = evalConfig.scorers.map((s) => s.name);\n const unknown = scorerNames.filter((n) => !available.includes(n));\n if (unknown.length) {\n console.error(\n `Error: --scorers: unknown scorer(s): ${unknown.join(', ')}. Available: ${available.join(', ')}`,\n );\n process.exit(1);\n }\n evalConfig.scorers = evalConfig.scorers.filter((s) => scorerNames.includes(s.name));\n if (evalConfig.scorers.length === 0) {\n console.error('Error: --scorers matched no scorers.');\n process.exit(1);\n }\n }\n\n // Resolve executeWorkflow: custom export > registered workflow > error\n // Walk the ESM/CJS interop chain symmetrically with the default export\n // so named exports stay visible when tsx loads the eval module as CJS.\n const exported = pickExport<unknown>(mod, 'executeWorkflow');\n\n // Validate that the export, if present, is callable. Catches the\n // `export const executeWorkflow = 'foo'` typo at the boundary instead\n // of crashing deep inside trackExecution with a confusing stack.\n let customExecute: EvalExecuteWorkflow | undefined;\n if (typeof exported === 'function') {\n customExecute = exported as EvalExecuteWorkflow;\n } else if (exported !== undefined) {\n console.error(\n `[axl-eval] Error: ${filePath} exports executeWorkflow but it is ${typeof exported}, not a function.`,\n );\n failedFiles++;\n continue;\n }\n\n let executeWorkflow: EvalExecuteWorkflow;\n\n if (customExecute) {\n // Wrap custom executeWorkflow with trackExecution for cost + metadata attribution\n executeWorkflow = async (input, rt) => {\n const {\n result,\n cost: trackedCost,\n metadata,\n } = await runtime.trackExecution(async () => {\n return customExecute(input, rt);\n });\n return {\n output: result.output,\n cost: result.cost ?? trackedCost,\n metadata: result.metadata ?? metadata,\n };\n };\n } else if (runtime.getWorkflow(evalConfig.workflow)) {\n // No executeWorkflow exported but workflow is registered — use runtime.execute()\n executeWorkflow = async (input) => {\n const { result, cost, metadata } = await runtime.trackExecution(async () => {\n return runtime.execute(evalConfig.workflow, input);\n });\n return { output: result, cost, metadata };\n };\n } else {\n // Fail loudly. The previous identity-passthrough fallback silently\n // produced all-zero scores in CI — exactly the kind of footgun the\n // \"fail loudly, not silently\" rule is meant to prevent. If you\n // genuinely want identity, export it explicitly:\n // export const executeWorkflow = async (input) => ({ output: input });\n //\n // Surface what WAS exported (top-level + .default) so users\n // recognize a typo like `execute_workflow` and can spot the\n // CJS-interop case that motivates this whole code path: when tsx\n // loads a `.ts` file as CJS, all named exports land on\n // `mod.default.<name>`. The chain walk above already handled this,\n // but a user who removed `executeWorkflow` will see exactly what\n // export names ARE present.\n const exportShape = (() => {\n const top = Object.keys(mod).filter((k) => k !== 'default');\n const fromDefault =\n mod.default && typeof mod.default === 'object'\n ? Object.keys(mod.default as Record<string, unknown>)\n : [];\n const all = [...new Set([...top, ...fromDefault])];\n return all.length > 0 ? `Found exports: [${all.join(', ')}].` : '';\n })();\n console.error(\n `[axl-eval] Error: ${filePath} does not export an executeWorkflow function ` +\n `and no workflow named \"${evalConfig.workflow}\" is registered on the runtime.\\n` +\n (exportShape ? ` ${exportShape}\\n` : '') +\n ` Add either:\\n` +\n ` export async function executeWorkflow(input, runtime) { ... }\\n` +\n ` or register the workflow on your runtime via runtime.registerWorkflow(workflow).\\n` +\n ` Tip: if your eval previously worked, your package.json may be missing\\n` +\n ` \"type\": \"module\" — tsx loads .ts as CJS, putting named exports on\\n` +\n ` mod.default.<name>. The CLI handles that interop, but if you renamed\\n` +\n ` or removed the export the file path is your fix.`,\n );\n failedFiles++;\n continue;\n }\n\n // When --capture-traces is set, forward it to runEval so the runner\n // wraps each item's execution in a nested trackExecution({ captureTraces: true }).\n // This populates EvalItem.traces on both success (via tracked.traces)\n // and failure (via the axlCapturedTraces side-channel on the thrown\n // error). Nested trackExecution scopes walk the AsyncLocalStorage\n // parent chain, so the outer trackExecution above still observes\n // cost/metadata correctly.\n // Always pass the SIGINT-driven signal so Ctrl+C aborts in-flight\n // workflows + scorer LLM calls instead of dropping the connection mid-request.\n const runOptions = { signal, ...(captureTraces ? { captureTraces: true } : {}) };\n\n // Stamp filtered runs so a scorer-subset result can't be silently used\n // as a full baseline. `compare` warns (and refuses to gate) on it. Must\n // be applied to EVERY run in a multi-run batch — Studio's multi-run\n // builder spreads only run[0]'s metadata.\n const scorersRun = scorerNames?.length ? evalConfig.scorers.map((s) => s.name) : undefined;\n const stampFiltered = (result: EvalResult) => {\n if (scorersRun) {\n result.metadata.scorerFiltered = true;\n result.metadata.scorersRun = scorersRun;\n }\n };\n\n if (runs > 1) {\n // Multi-run mode. Buffer per-run results locally so we can mark the\n // batch correctly before committing to outer `results[]`. The\n // original bug was the opposite: results pushed eagerly per-run, a\n // throw mid-batch left partial results posing as a complete run\n // (no `fromPartialBatch` marker, aggregate never ran). The fix ISN'T\n // to throw the partials away — those runs cost money and have\n // statistical signal. Instead we preserve them with explicit\n // partial-batch metadata, aggregate over what completed, and exit\n // non-zero so CI knows the batch wasn't clean.\n const { randomUUID } = await import('node:crypto');\n const runGroupId = randomUUID();\n const runResults: EvalResult[] = [];\n let runFailure: Error | undefined;\n\n for (let r = 0; r < runs; r++) {\n if (signal.aborted) break;\n console.error(`[axl-eval] Run ${r + 1}/${runs}...`);\n try {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n result.metadata.runGroupId = runGroupId;\n result.metadata.runIndex = r;\n stampFiltered(result);\n runResults.push(result);\n } catch (err) {\n runFailure = err instanceof Error ? err : new Error(String(err));\n console.error(`[axl-eval] Run ${r + 1}/${runs} failed: ${runFailure.message}`);\n // Stop attempting further runs — we don't know whether this is\n // transient (rate limit) or permanent (auth failure), and\n // burning more API calls speculatively is hostile. Preserve\n // what completed.\n break;\n }\n }\n\n if (runResults.length === 0) {\n // Nothing completed — surface as a per-file failure. No partial\n // artifact to write; the outer try/catch error message would\n // duplicate the \"Run 1/N failed\" line we already printed, so\n // increment and continue without re-throwing.\n console.error(\n `[axl-eval] Aborting ${filePath}: no runs completed (${runFailure?.message ?? 'unknown failure'}).`,\n );\n failedFiles++;\n continue;\n }\n\n const partial = runResults.length < runs;\n if (partial) {\n // Mark every completed run so any consumer reading\n // `result.metadata` sees the partial-batch context. `aggregateRuns`\n // computes statistics over `runResults.length`, which is the\n // honest sample size to report.\n //\n // The flag is `fromPartialBatch` — a per-run marker meaning\n // \"this run came from a batch that did not complete.\" It is\n // NOT named `partialBatch` because that read as \"this run is\n // partial,\" and a defensive consumer wrote\n // `if (run.metadata.partialBatch) skipThisRun()`, throwing\n // away successful work that cost real money. The flag describes\n // the BATCH the run belongs to, not the run itself.\n //\n // `runFailure?.message` can be empty (e.g. `new Error('')` from a\n // misbehaving provider); fall back to `String(runFailure)` so the\n // banner never renders a blank \"Stopped after:\" line. Skip the\n // field entirely if both are empty so `buildMultiRunResult`'s\n // empty-string filter doesn't have to defensively guess.\n const failureMsg = runFailure\n ? runFailure.message || String(runFailure) || undefined\n : undefined;\n for (const r of runResults) {\n r.metadata.fromPartialBatch = true;\n r.metadata.batchCompleted = runResults.length;\n r.metadata.batchAttempted = runs;\n if (failureMsg) r.metadata.batchFailure = failureMsg;\n }\n console.error(\n `[axl-eval] PARTIAL: ${runResults.length} of ${runs} runs completed for ${filePath}.`,\n );\n failedFiles++;\n }\n\n const summary = aggregateRuns(runResults);\n console.log('\\n' + formatMultiRunTable(summary) + '\\n');\n for (const r of runResults) results.push(r);\n\n // Failure-rate gate (opt-in via failOnScorerErrorRate) + total-wipeout\n // guard (always). Report every run; count the file as failed unless it\n // was already counted as a partial batch above (avoids double-count).\n let anyFailing = false;\n for (const r of runResults) {\n // Call both (no short-circuit) so each prints its own diagnostic.\n const wipeout = reportTotalWipeout(r, filePath);\n const degraded = reportDegraded(r, filePath);\n reportFullySkippedScorers(r, filePath); // advisory only\n if (wipeout || degraded) anyFailing = true;\n }\n if (anyFailing && !partial) failedFiles++;\n } else {\n const result = await runEval(evalConfig, executeWorkflow, runtime, runOptions);\n stampFiltered(result);\n results.push(result);\n\n console.log('\\n' + formatTable(result) + '\\n');\n // Total-wipeout guard (always) + scorer failure-rate gate (opt-in). They\n // are mutually exclusive (a wipeout has no scored items, so no scorer can\n // be degraded), but report both for clarity; either fails the file.\n const wipeout = reportTotalWipeout(result, filePath);\n const degraded = reportDegraded(result, filePath);\n reportFullySkippedScorers(result, filePath); // advisory only\n if (wipeout || degraded) failedFiles++;\n }\n } catch (err) {\n console.error(\n `Error running eval ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n failedFiles++;\n }\n }\n\n if (outputPath && results.length > 0) {\n const output = results.length === 1 ? results[0] : results;\n const outputDir = path.dirname(path.resolve(outputPath));\n await mkdir(outputDir, { recursive: true });\n await writeFileAsync(outputPath, JSON.stringify(output, null, 2), 'utf-8');\n console.log(`Results saved to ${outputPath}`);\n }\n } finally {\n await runtime.shutdown().catch(() => {});\n }\n\n // Exit non-zero if any eval file failed to load/run. Previously we only\n // exited non-zero when zero evals succeeded, which silently masked\n // misconfigured files in mixed-success runs (a CI footgun).\n if (failedFiles > 0 || results.length === 0) {\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n","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","export 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/**\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 }>;\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 if (i.scores[name] != null) scored++;\n else if (i.scoreDetails?.[name]?.skipped === true) skipped++;\n else if (i.scoreDetails?.[name]?.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","import type {\n EvalResult,\n EvalComparison,\n EvalCompareOptions,\n EvalRegression,\n EvalImprovement,\n} from './types.js';\nimport { pairedBootstrapCI } from './bootstrap.js';\nimport { scorerCounts, evaluateScorerTolerance, round } from './utils.js';\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 let cost: EvalComparison['cost'];\n const baselineAvgCost =\n baselineRuns.reduce((sum, r) => sum + r.totalCost, 0) / baselineRuns.length;\n const candidateAvgCost =\n candidateRuns.reduce((sum, r) => sum + r.totalCost, 0) / candidateRuns.length;\n if (baselineAvgCost > 0 || candidateAvgCost > 0) {\n const deltaRaw = candidateAvgCost - baselineAvgCost;\n const delta = round(deltaRaw);\n const deltaPercent = baselineAvgCost > 0 ? round((deltaRaw / baselineAvgCost) * 100) : 0;\n cost = {\n baselineTotal: round(baselineAvgCost),\n candidateTotal: round(candidateAvgCost),\n delta,\n deltaPercent,\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 if (cost && 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","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 applies?: ScorerApplies<TOutput, TInput, TAnnotations>;\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 applies?: ScorerApplies<TOutput, TInput, TAnnotations>;\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","import type { Scorer, ScorerContext } from './scorer.js';\nimport { normalizeScorerResult, extractScorerErrorCost } from './scorer.js';\nimport type { EvalItem } from './types.js';\nimport { round, mapWithConcurrency } from './utils.js';\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/**\n * Score one item's `output` with every scorer in `scorers`, running up to\n * `scorerConcurrency` of them at once. Mutates `item.scores`,\n * `item.scoreDetails`, `item.scorerErrors`, and `item.scorerCost` in place, and\n * returns the per-item scorer cost so the caller can fold it into its own\n * running total (`totalCost += await scoreItem(...)`).\n *\n * This is the single source of truth for the scoring inner loop, shared by\n * `runEval` and `rescore` — both previously carried a byte-identical copy, so a\n * determinism or cancellation fix had to be made twice.\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 * Cancellation: a scorer not yet started when `signal` aborts is skipped; an\n * in-flight scorer whose call rejects with an `AbortError` is treated as\n * cancellation (leaves its pre-seeded `null`, records no error) — narrowed to\n * the error identity so a genuine bug in another scorer that happens to throw\n * while a sibling triggered the abort is still reported, not swallowed.\n */\nexport async function scoreItem(\n item: ScorableItem,\n scorers: readonly Scorer<unknown, unknown, unknown>[],\n scorerConcurrency: number,\n scorerContext: ScorerContext,\n signal?: AbortSignal,\n): Promise<number> {\n const scoreDetails = (item.scoreDetails ??= {});\n for (const s of scorers) {\n item.scores[s.name] = null;\n scoreDetails[s.name] = { score: null };\n }\n\n let itemScorerCost = 0;\n const scorerErrorsByName: Record<string, string> = {};\n\n await mapWithConcurrency(scorers, scorerConcurrency, async (scorer) => {\n if (signal?.aborted) return;\n const scorerStart = Date.now();\n try {\n // Applicability gate: a conditional scorer declares which items it applies\n // to via `applies`. A `false` verdict skips it entirely — no provider call\n // for an llmScorer — and records it as NEITHER scored nor failed via the\n // positive `skipped` marker (no `duration`, so the duration heuristic in\n // `scorerCounts` can't misread it as a failure). A predicate that THROWS is\n // a bug, not a skip: it falls through to the catch below and is recorded as\n // a scorer failure (with a duration), never silently swallowed.\n if (scorer.applies && !scorer.applies(item.output, item.input, item.annotations)) {\n item.scores[scorer.name] = null;\n scoreDetails[scorer.name] = { score: null, skipped: true };\n return;\n }\n\n const raw = await scorer.score(item.output, item.input, item.annotations, scorerContext);\n const scorerResult = normalizeScorerResult(raw);\n\n if (scorerResult.cost != null) {\n itemScorerCost += scorerResult.cost;\n }\n\n const scorerDuration = Date.now() - scorerStart;\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 ${JSON.stringify(item.input)}`;\n item.scores[scorer.name] = null;\n scoreDetails[scorer.name] = {\n score: null,\n metadata: scorerResult.metadata,\n duration: scorerDuration,\n cost: scorerResult.cost,\n };\n } else {\n item.scores[scorer.name] = round(scorerResult.score);\n scoreDetails[scorer.name] = {\n score: round(scorerResult.score),\n metadata: scorerResult.metadata,\n duration: scorerDuration,\n cost: scorerResult.cost,\n };\n }\n } catch (err) {\n // A cancelled call (AbortError) is not a scoring failure — leave the\n // pre-seeded null and record nothing.\n if ((err as { name?: string })?.name === 'AbortError') return;\n const errCost = extractScorerErrorCost(err);\n if (errCost != null) itemScorerCost += errCost;\n scorerErrorsByName[scorer.name] =\n `Scorer \"${scorer.name}\" threw: ${err instanceof Error ? err.message : String(err)}`;\n item.scores[scorer.name] = null;\n scoreDetails[scorer.name] = {\n score: null,\n duration: Date.now() - scorerStart,\n cost: errCost,\n };\n }\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 item.scorerCost = itemScorerCost > 0 ? itemScorerCost : undefined;\n return itemScorerCost;\n}\n","import type { AxlRuntime } from '@axlsdk/axl';\nimport type { EvalConfig, EvalResult, EvalItem, EvalSummary, RunEvalOptions } 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} from './utils.js';\nimport { scoreItem } from './score-item.js';\nimport { randomUUID } from 'node:crypto';\n\nfunction parseCost(cost: string): number {\n const match = cost.match(/^\\$?([\\d.]+)$/);\n if (!match) throw new Error(`Invalid cost format: \"${cost}\"`);\n return parseFloat(match[1]);\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 * Negative costs are rejected because (a) cost is a USD amount and negative\n * values are nonsensical, and (b) a negative cost would silently shrink\n * `totalCost` below the budget limit check at the processItem level,\n * letting a buggy/malicious workflow run unbounded. `0` is preserved\n * because free operations on paid models are valid.\n *\n * When a user-supplied value is rejected (present but invalid), we log\n * once per item via `console.warn` so the type violation is visible\n * rather than silently swallowed.\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}. Falling back to tracked cost (or undefined).`,\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\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 const items = await config.dataset.getItems();\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 const budgetLimit = config.budget ? parseCost(config.budget) : undefined;\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 let totalCost = 0;\n let budgetExceeded = false;\n\n async function processItem(item: (typeof items)[0], itemIndex: number): Promise<void> {\n if (options?.signal?.aborted) {\n evalItems[itemIndex] = {\n input: item.input,\n annotations: item.annotations,\n output: null,\n error: 'Cancelled',\n scores: {},\n };\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n return;\n }\n\n if (budgetExceeded) {\n evalItems[itemIndex] = {\n input: item.input,\n annotations: item.annotations,\n output: null,\n error: 'Budget exceeded',\n scores: {},\n };\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 try {\n // When captureTraces is on, wrap the user's executeWorkflow in\n // trackExecution so we get a per-item TraceEvent[] scoped via\n // AsyncLocalStorage. trackExecution's scope walks the parent chain, so\n // any nested trackExecution (e.g. from the CLI) continues to work.\n if (options?.captureTraces) {\n const tracked = await runtime.trackExecution(\n async () => executeWorkflow(item.input, runtime),\n { captureTraces: true },\n );\n evalItem.duration = Date.now() - itemStart;\n evalItem.output = tracked.result.output;\n // Prefer user-returned cost/metadata; fall back to tracked values.\n // Type-guarded so a non-number cost (e.g. `{ cost: 'free' }`) or a\n // non-object metadata (e.g. an array or scalar) doesn't silently\n // corrupt downstream math or shape expectations.\n evalItem.cost = extractUserCost(tracked.result) ?? tracked.cost;\n evalItem.metadata = extractUserMetadata(tracked.result) ?? tracked.metadata;\n if (tracked.traces && tracked.traces.length > 0) {\n evalItem.traces = tracked.traces;\n }\n if (evalItem.cost != null) {\n totalCost += evalItem.cost;\n }\n } else {\n const result = await executeWorkflow(item.input, runtime);\n evalItem.duration = Date.now() - itemStart;\n evalItem.output = result.output;\n evalItem.cost = extractUserCost(result);\n const meta = extractUserMetadata(result);\n if (meta) evalItem.metadata = meta;\n if (evalItem.cost != null) {\n totalCost += evalItem.cost;\n }\n }\n } catch (err) {\n evalItem.duration = Date.now() - itemStart;\n evalItem.error = err instanceof Error ? err.message : String(err);\n // Failed items are exactly when per-item traces are most valuable —\n // recover them from the captured-traces side-channel `trackExecution`\n // attaches to the error on the failure path.\n if (options?.captureTraces) {\n const captured = (err as { axlCapturedTraces?: unknown }).axlCapturedTraces;\n if (Array.isArray(captured) && captured.length > 0) {\n evalItem.traces = captured as EvalItem['traces'];\n }\n }\n evalItems[itemIndex] = evalItem;\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n return;\n }\n\n if (budgetLimit != null && totalCost > budgetLimit) {\n budgetExceeded = true;\n }\n\n // Score the item's output with all scorers (bounded fan-out). scoreItem\n // owns the determinism + cancellation + cost logic shared with rescore();\n // it returns the per-item scorer cost to fold into the running total.\n // NB: keep the await on its own line — `totalCost += await …` would read\n // totalCost BEFORE suspending, losing updates across concurrent items.\n const itemScorerCost = await scoreItem(\n evalItem,\n config.scorers,\n scorerConcurrency,\n scorerContext,\n options?.signal,\n );\n totalCost += itemScorerCost;\n evalItems[itemIndex] = evalItem;\n options?.onProgress?.({ type: 'item_done', itemIndex, totalItems: items.length });\n }\n\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 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 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. We never throw — the result is still\n // useful; we flag it and let the CLI/consumer decide the exit code. Invalid\n // limits are ignored loudly so a typo can't silently disable 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 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 // 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 trackExecution'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,\n duration: Date.now() - startTime,\n items: evalItems,\n summary: {\n count: items.length,\n failures,\n scorers: scorerStats,\n timing,\n ...(degraded ? { degraded } : {}),\n },\n };\n}\n","import type { AxlRuntime } from '@axlsdk/axl';\nimport type { EvalResult, EvalItem, 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 { 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\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 */\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 concurrency = options?.concurrency ?? 5;\n const scorerConcurrency = options?.scorerConcurrency ?? 5;\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 let totalCost = 0;\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 (runner.ts) so cancellation behaves the same\n // in both 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 scores: {},\n };\n return;\n }\n\n // Pass through error items without scoring\n if (original.error) {\n rescored[itemIndex] = {\n input: original.input,\n annotations: original.annotations,\n output: original.output,\n error: original.error,\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 scores: {},\n scoreDetails: {},\n };\n\n // Same shared scoring path as runEval — determinism, cancellation, and cost\n // accounting all live in scoreItem. Keep the await off the `+=` line so the\n // read-modify-write isn't split by suspension across concurrent items.\n const itemScorerCost = await scoreItem(\n item,\n scorers,\n scorerConcurrency,\n scorerContext,\n options?.signal,\n );\n totalCost += itemScorerCost;\n rescored[itemIndex] = item;\n }\n\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 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: randomUUID(),\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,\n duration: Date.now() - startTime,\n items: rescored,\n summary: { count: result.items.length, failures, scorers: scorerStats },\n };\n}\n","import type { EvalResult } from './types.js';\nimport { randomUUID } from 'node:crypto';\nimport { round } from './utils.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 totalCost: number;\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 totalDuration: round(totalDuration),\n scorers,\n timing,\n };\n}\n","/**\n * CLI utilities for `axl-eval`.\n *\n * The actual implementations of the loader, glob, and config-detection\n * helpers live in `@axlsdk/axl`'s `cli-internals` so a fix to (e.g.) the\n * tsx loader registration applies to both axl-eval and axl-studio\n * atomically. This file is now a thin re-export plus the symmetric\n * module-resolution helpers from `@axlsdk/axl`.\n */\n\nexport {\n resolveRuntime,\n pickDefault,\n pickExport,\n CONFIG_CANDIDATES,\n findConfig,\n needsTsxLoader,\n importModule,\n expandGlob,\n registerConditions,\n} from '@axlsdk/axl';\n","import type { EvalConfig } from './types.js';\n\n/**\n * Validate an eval config's required fields and produce a diagnostic string\n * if invalid. Returns `undefined` when the config passes.\n *\n * Returns a single-line message tail (caller prepends the file path) so the\n * full error reads like: `Error: <file> <message>`.\n *\n * Goes beyond a falsy check to:\n * - catch `scorers: []` which previously silently ran with no scorers\n * - reject scorers arrays that contain non-callable entries (e.g. typo\n * `scorers: [null, undefined]` would crash deep inside `runEval`)\n * - reject non-string `workflow` (downstream `runtime.getWorkflow(...)`\n * would silently miss it)\n * - reject non-object `dataset` (must be a `dataset()` factory result)\n * - provide a `Got: { keys: [...] }` hint so users can spot typos like\n * `scorerS` vs `scorers` immediately\n *\n * Lives in its own module so unit tests can import it without triggering\n * `cli.ts`'s `main()` at module load time.\n */\nexport function validateEvalConfig(cfg: unknown): string | undefined {\n if (!cfg || typeof cfg !== 'object') {\n return `does not export a valid eval config — got ${cfg === null ? 'null' : typeof cfg}.`;\n }\n const c = cfg as Partial<EvalConfig>;\n const missing: string[] = [];\n if (!c.workflow) missing.push('workflow');\n if (!c.dataset) missing.push('dataset');\n if (!c.scorers) missing.push('scorers');\n\n if (missing.length > 0) {\n const keys = Object.keys(c as object).slice(0, 10);\n const got = keys.length > 0 ? ` Got: { ${keys.join(', ')} }.` : '';\n return `does not export a valid eval config (missing ${missing.join(', ')}).${got}`;\n }\n\n if (typeof c.workflow !== 'string') {\n return `exports a non-string workflow (got ${typeof c.workflow}) — workflow must be the registered workflow name.`;\n }\n if (typeof c.dataset !== 'object' || Array.isArray(c.dataset)) {\n return `exports a non-object dataset (got ${Array.isArray(c.dataset) ? 'array' : typeof c.dataset}) — use the dataset() factory.`;\n }\n if (typeof (c.dataset as { getItems?: unknown }).getItems !== 'function') {\n return `exports a dataset without a getItems() method — use the dataset() factory.`;\n }\n if (!Array.isArray(c.scorers) || c.scorers.length === 0) {\n return `exports an empty scorers array — at least one scorer is required.`;\n }\n const badScorerIdx = c.scorers.findIndex(\n (s) => !s || typeof (s as { score?: unknown }).score !== 'function',\n );\n if (badScorerIdx !== -1) {\n return `exports a scorers array with a non-scorer entry at index ${badScorerIdx} — each scorer must have a score() method (use the scorer() factory).`;\n }\n // Concurrency knobs must be positive integers when present. The worker pool\n // defensively clamps non-positive/non-finite values to 1 at runtime, but a\n // config that wrote `concurrency: 0` (or NaN via `Number(env)`) almost\n // certainly has a bug — surface it loudly, matching the `--concurrency` flag.\n for (const key of ['concurrency', 'scorerConcurrency'] as const) {\n const v = (c as Record<string, unknown>)[key];\n if (v !== undefined && (typeof v !== 'number' || !Number.isInteger(v) || v < 1)) {\n return `exports an invalid ${key} (${typeof v === 'number' ? v : typeof v}) — must be a positive integer.`;\n }\n }\n // The failure-rate gate must fail loud on a bad value, symmetric with the\n // `--max-scorer-error-rate` flag. Without this, a typo (e.g. `5` meaning \"5%\")\n // only `console.warn`s at runtime and silently disables the gate the user\n // explicitly opted into — the exact silent-no-op the feature exists to catch.\n {\n const v = (c as Record<string, unknown>).failOnScorerErrorRate;\n if (v !== undefined && (typeof v !== 'number' || !Number.isFinite(v) || v < 0 || v > 1)) {\n return `exports an invalid failOnScorerErrorRate (${typeof v === 'number' ? v : typeof v}) — must be a number between 0 and 1.`;\n }\n }\n return undefined;\n}\n","/**\n * Argument parsing for the `axl-eval` CLI, factored out of `cli.ts` so it can be\n * unit-tested without importing `cli.ts` (whose module body runs `main()` on\n * import).\n */\n\nexport const KNOWN_FLAGS = new Set([\n '--output',\n '--config',\n '--conditions',\n '--fail-on-regression',\n '--threshold',\n '--runs',\n '--capture-traces',\n '--concurrency',\n '--scorers',\n]);\n\n/**\n * The subset of flags `parseEvalArgs` consumes a following value for. NOT every\n * value-taking flag in the CLI: `--threshold` takes a value too but is parsed\n * by `runCompare`'s own parser, not here. Every entry MUST also be in\n * {@link KNOWN_FLAGS} — a value-flag missing from KNOWN_FLAGS would be rejected\n * as \"unknown\", and one missing from VALUE_FLAGS would silently swallow its\n * value into `paths`. A test asserts `VALUE_FLAGS ⊆ KNOWN_FLAGS`.\n */\nexport const VALUE_FLAGS = new Set([\n '--output',\n '--config',\n '--conditions',\n '--runs',\n '--concurrency',\n '--scorers',\n]);\n\nexport type ParsedEvalArgs = {\n outputPath?: string;\n configArg?: string;\n conditions: string[];\n runs: number;\n captureTraces: boolean;\n /** Item-level concurrency override (flag value). Clamped to >= 1. */\n concurrency?: number;\n /** Scorer names from `--scorers` (deduped, in first-seen order). */\n scorerNames?: string[];\n paths: string[];\n};\n\n/**\n * Read a positive integer from an environment variable. Returns `undefined`\n * when the var is absent, non-numeric, or `<= 0`, so a malformed value falls\n * through to the next precedence tier rather than poisoning the run.\n */\nexport function envInt(name: string): number | undefined {\n const raw = process.env[name];\n if (raw == null || raw === '') return undefined;\n const n = parseInt(raw, 10);\n if (!Number.isFinite(n) || n <= 0) return undefined;\n return n;\n}\n\nexport function parseEvalArgs(args: string[]): ParsedEvalArgs {\n let outputPath: string | undefined;\n let configArg: string | undefined;\n let conditions: string[] = [];\n let runs = 1;\n let captureTraces = false;\n let concurrency: number | undefined;\n let scorerNames: string[] | undefined;\n const paths: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (VALUE_FLAGS.has(arg)) {\n if (i + 1 >= args.length) {\n console.error(`Error: ${arg} requires a value`);\n process.exit(1);\n }\n const value = args[++i];\n if (arg === '--output') outputPath = value;\n else if (arg === '--config') configArg = value;\n else if (arg === '--runs') runs = Math.max(1, parseInt(value, 10) || 1);\n else if (arg === '--concurrency') {\n // Clamp to a floor of 1 with a warning (matches `--runs`' clamp ethos\n // but surfaces the typo). A `0` here would otherwise spawn zero workers.\n // Note the intentional asymmetry with `envInt` above: an explicit flag\n // typo is worth a warning, whereas a malformed ambient env var falls\n // through silently to the next precedence tier.\n const n = parseInt(value, 10);\n if (!Number.isFinite(n) || n <= 0) {\n console.error(`[axl-eval] Ignoring invalid --concurrency \"${value}\"; using 1.`);\n concurrency = 1;\n } else {\n concurrency = n;\n }\n } else if (arg === '--scorers') {\n scorerNames = [\n ...new Set(\n value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean),\n ),\n ];\n } else {\n conditions = value\n .split(',')\n .map((c) => c.trim())\n .filter(Boolean);\n }\n } else if (arg === '--capture-traces') {\n // Boolean flag — no value consumed.\n captureTraces = true;\n } else if (arg.startsWith('--')) {\n if (!KNOWN_FLAGS.has(arg)) {\n console.error(`Unknown flag: ${arg}`);\n process.exit(1);\n }\n } else {\n paths.push(arg);\n }\n }\n\n return {\n outputPath,\n configArg,\n conditions,\n runs,\n captureTraces,\n concurrency,\n scorerNames,\n paths,\n };\n}\n"],"mappings":"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","names":["round","round","round","import_node_crypto","import_node_crypto","round","readFileAsync","writeFileAsync","randomUUID"]}
|