@tangle-network/agent-eval 0.79.0 → 0.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -19
- package/dist/adapters/http.d.ts +1 -1
- package/dist/adapters/langchain.d.ts +1 -1
- package/dist/adapters/otel.d.ts +1 -1
- package/dist/analyst/index.d.ts +3 -3
- package/dist/belief-state/index.d.ts +188 -0
- package/dist/belief-state/index.js +486 -0
- package/dist/belief-state/index.js.map +1 -0
- package/dist/calibration-Cpr3WaX3.d.ts +101 -0
- package/dist/campaign/index.d.ts +5 -5
- package/dist/chunk-4DIJWVUT.js +131 -0
- package/dist/chunk-4DIJWVUT.js.map +1 -0
- package/dist/chunk-NPCTHQIO.js +91 -0
- package/dist/chunk-NPCTHQIO.js.map +1 -0
- package/dist/contract/index.d.ts +123 -10
- package/dist/contract/index.js +116 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/governance/index.d.ts +1 -1
- package/dist/hosted/index.d.ts +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/meta-eval/index.d.ts +5 -98
- package/dist/meta-eval/index.js +7 -76
- package/dist/meta-eval/index.js.map +1 -1
- package/dist/off-policy-DiwuKKg7.d.ts +132 -0
- package/dist/openapi.json +1 -1
- package/dist/{outcome-store-D6KWmYvj.d.ts → outcome-store-rnXLEqSn.d.ts} +1 -1
- package/dist/{provenance-CEAJI9rm.d.ts → provenance-jG-Gngg8.d.ts} +2 -2
- package/dist/{registry-BmEuU94S.d.ts → registry-BK0Zee01.d.ts} +1 -1
- package/dist/reporting.d.ts +2 -2
- package/dist/rl.d.ts +6 -136
- package/dist/rl.js +6 -120
- package/dist/rl.js.map +1 -1
- package/dist/{rubric-predictive-validity-CWyWWLBg.d.ts → rubric-predictive-validity-CLPuwiUw.d.ts} +1 -1
- package/dist/{run-improvement-loop-Bgu4C59E.d.ts → run-improvement-loop-BAl_aVOZ.d.ts} +1 -1
- package/dist/{semantic-concept-judge-Du4ZVyef.d.ts → semantic-concept-judge-qXEUV2w7.d.ts} +1 -1
- package/dist/{types-QHG0KnkF.d.ts → types-4mm2msnR.d.ts} +1 -1
- package/docs/research/belief-state-agent-eval-roadmap.md +558 -0
- package/docs/research/research-roadmap.md +1 -0
- package/package.json +7 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/contract/self-improve.ts","../../src/contract/analyze-runs.ts","../../src/contract/intake/agent-trace.ts","../../src/contract/intake/feedback-table.ts","../../src/contract/intake/otel-spans.ts"],"sourcesContent":["/**\n * # `selfImprove()` — the LAND-tier one-shot.\n *\n * The cheapest possible call site to run a real closed-loop self-\n * improvement over your agent. Wraps `runImprovementLoop` with smart\n * defaults and a budget-shaped options API; every escape hatch the\n * substrate exposes is reachable from here without losing the\n * one-function feel.\n *\n * Defaults picked to match the LAND-tier story:\n * - In-memory storage (no filesystem touch).\n * - `gepaDriver` reflective mutation with copywriting-flavored primitives\n * (override `driver` or `mutationPrimitives` for any domain).\n * - `defaultProductionGate` with `deltaThreshold: 0.05`.\n * - Held-out split = 25% of scenarios, deterministic by id hash.\n * - 3 generations × population 2 (raise via `budget` for more search).\n * - `autoOnPromote: 'none'` (we don't open PRs unless you ask).\n *\n * Want one-click? Provide `agent` + `scenarios` + `judge`. Done.\n * Want distributed? Pass `cellPlacement` + an `httpDispatch`-backed\n * agent. Want a code-tier surface? Pass a `MutableSurface` + your own\n * `driver`. Same function.\n */\n\nimport { createHash } from 'node:crypto'\nimport { gepaDriver } from '../campaign/drivers/gepa'\nimport { defaultProductionGate } from '../campaign/gates/default-production-gate'\nimport {\n type RunImprovementLoopResult,\n runImprovementLoop,\n} from '../campaign/presets/run-improvement-loop'\nimport {\n emitLoopProvenance,\n type LoopProvenanceRecord,\n surfaceContentHash,\n} from '../campaign/provenance'\nimport {\n type CampaignStorage,\n fsCampaignStorage,\n inMemoryCampaignStorage,\n} from '../campaign/storage'\nimport type {\n CampaignCellResult,\n DispatchContext,\n Gate,\n ImprovementDriver,\n JudgeConfig,\n MutableSurface,\n Scenario,\n} from '../campaign/types'\nimport { createHostedClient, type HostedTenant } from '../hosted/client'\nimport type { EvalRunCellScore, EvalRunEvent, EvalRunGenerationSnapshot } from '../hosted/types'\nimport type { JudgeScoresRecord, RunRecord } from '../run-record'\nimport { analyzeRuns } from './analyze-runs'\nimport type { InsightReport } from './insight-report'\n\nexport interface SelfImproveBudget {\n /** Hard $ ceiling across all cells in baseline + every generation. Cells\n * beyond the ceiling are skipped (cost-aware, not aborted). */\n dollars?: number\n /** How many improvement generations to explore. Default 3. Set 0 to\n * skip improvement entirely (selfImprove becomes a baseline-only run). */\n generations?: number\n /** Candidates the driver proposes per generation. Default 2. */\n populationSize?: number\n /** Max concurrent cells across the loop. Default 2. */\n maxConcurrency?: number\n /** Fraction of `scenarios` held out from training, used for the gate.\n * Default 0.25. Ignored when `holdoutScenarios` is set explicitly. */\n holdoutFraction?: number\n /** Explicit held-out scenarios; overrides `holdoutFraction`. */\n holdoutScenarios?: Scenario[]\n}\n\nexport interface SelfImproveLlm {\n /** Endpoint base URL. Default Tangle Router. */\n baseUrl?: string\n /** Bearer token. Default `process.env.OPENAI_API_KEY`. */\n apiKey?: string\n /** Model id used by `gepaDriver` reflection. Default\n * `anthropic/claude-sonnet-4.6`. */\n model?: string\n}\n\nexport type SelfImproveProgressEvent =\n | { kind: 'baseline.started'; scenarios: number }\n | { kind: 'baseline.completed'; compositeMean: number; durationMs: number }\n | { kind: 'generation.started'; index: number; populationSize: number }\n | { kind: 'generation.completed'; index: number; bestComposite: number; durationMs: number }\n | { kind: 'gate.decided'; decision: string; lift: number }\n\nexport interface SelfImproveOptions<TScenario extends Scenario, TArtifact> {\n /**\n * Your agent — a function that takes the current `MutableSurface`\n * (typically a system prompt the loop is optimizing) plus the\n * scenario + cell ctx, and returns the artifact your judge scores.\n *\n * Same shape as `RunOptimizationOptions.dispatchWithSurface`. Wrap a\n * plain `Dispatch` if you don't have a surface seam:\n *\n * agent: (_surface, scenario, ctx) => yourPlainDispatch(scenario, ctx)\n *\n * That mode evaluates without mutating any surface — useful as a\n * baseline-only run (set `budget.generations = 0`).\n */\n agent: (surface: MutableSurface, scenario: TScenario, ctx: DispatchContext) => Promise<TArtifact>\n\n /** Scenarios to evaluate against. Train/holdout split is computed from\n * these unless `budget.holdoutScenarios` is set explicitly. */\n scenarios: TScenario[]\n\n /** Judge that scores artifacts. Bring your own; use `langchainJudge`\n * from `/adapters/langchain` for a Runnable-shaped one. */\n judge: JudgeConfig<TArtifact, TScenario>\n\n /** Starting surface — system prompt, JSON config, anything `MutableSurface`\n * accepts. The driver mutates this each generation. */\n baselineSurface: MutableSurface\n\n /** Budget + loop shape. All fields optional; defaults pick the LAND-tier\n * story. */\n budget?: SelfImproveBudget\n\n /** Custom driver. Default is `gepaDriver` configured from `llm` +\n * `mutationPrimitives`. */\n driver?: ImprovementDriver\n\n /** Default-driver overrides — used when `driver` is unset. */\n mutationPrimitives?: string[]\n driverTarget?: string\n\n /** Custom gate. Default is `defaultProductionGate` with\n * `deltaThreshold: 0.05` on the held-out split. */\n gate?: Gate<TArtifact, TScenario>\n\n /** LLM config consumed by the default `gepaDriver`. Ignored if you pass\n * your own `driver`. */\n llm?: SelfImproveLlm\n\n /** Storage backend. Default is DURABLE: when a real (non-`mem://`) `runDir`\n * is available, the substrate defaults to `fsCampaignStorage()` so the\n * provenance record + OTel spans survive the call. Pass\n * `inMemoryCampaignStorage()` explicitly to opt OUT (tests, edge runtimes).\n * Default when `runDir` is `mem://...` (or unset): in-memory. */\n storage?: CampaignStorage\n\n /** Run directory (logical for in-memory storage, real path for fs).\n * Default `mem://selfImprove-<timestamp>` (in-memory, non-durable). Pass a\n * real path to persist the provenance record + spans. */\n runDir?: string\n\n /**\n * Worker call records for backend provenance. The agent is opaque to the\n * substrate (it returns an artifact, not token usage), so to capture an\n * `assertRealBackend`-grade verdict + worker call count + model in the\n * provenance record, the agent reports its per-call `RunRecord`s here.\n * Called once after the loop; return the records the agent accumulated.\n * When unset, backend provenance is derived from campaign cells (cost only;\n * verdict will read `stub` without token usage — the honest signal that no\n * token channel was wired).\n */\n collectWorkerRecords?: () => RunRecord[]\n\n /** Fires once the durable provenance record + OTel spans are emitted.\n * Receives the structured record for inline assertions / custom routing. */\n onProvenance?: (record: LoopProvenanceRecord) => void\n\n /** Distributed-driver seam — same as `RunCampaignOptions.cellPlacement`.\n * Returns an opaque placement key the substrate forwards to your agent\n * as `ctx.placement`. Combined with `httpDispatch` from\n * `/adapters/http`, fans cells across regions. */\n cellPlacement?: (input: {\n scenario: TScenario\n rep: number\n generation?: number\n }) => string | undefined\n\n /** Streaming hook — fires on baseline + each generation + gate decision.\n * Consumer routes events wherever (UI, dashboard, logs). */\n onProgress?: (event: SelfImproveProgressEvent) => void\n\n /** Auto-promotion behavior on a ship decision. Default `'none'` — we\n * return the winner; you ship it however you ship. `'pr'` opens a\n * GitHub PR via `openAutoPr`; requires `ghOwner` + `ghRepo`. */\n autoOnPromote?: 'pr' | 'none'\n ghOwner?: string\n ghRepo?: string\n\n /**\n * Opt-in: ship eval-run events to a hosted orchestrator (ours, your\n * self-hosted one, or any compatible implementation of the\n * `docs/hosted-ingest-spec.md` wire format). When set, the substrate\n * POSTs the final `EvalRunEvent` to `${endpoint}/v1/ingest/eval-runs`\n * after the loop completes. Failures are logged but do not fail the\n * loop — local result is always returned.\n *\n * For our orchestrator: `{ endpoint: 'https://orchestrator.tangle.tools/v1', apiKey, tenantId }`.\n *\n * For your self-hosted: any URL serving the wire format. See\n * `examples/hosted-ingest-server/` for the reference receiver.\n */\n hostedTenant?: HostedTenant\n\n /** Free-form labels attached to the hosted event (env, branch, model id,\n * etc.). Ignored when `hostedTenant` is unset. */\n hostedLabels?: Record<string, string>\n}\n\nexport interface SelfImproveResult<TScenario extends Scenario, TArtifact> {\n /** Composite mean across all scenarios, baseline run. */\n baseline: {\n compositeMean: number\n perScenario: Record<string, number>\n }\n /** Composite mean on the held-out set, winner run. */\n winner: {\n compositeMean: number\n perScenario: Record<string, number>\n surface: MutableSurface\n /** Driver label for the promoted change. Absent ⇒ winner == baseline or\n * a bare-surface mutator. */\n label?: string\n /** Driver rationale — the \"because Z\" that motivated the promoted change.\n * Threaded from the driver's `ProposedCandidate` through the loop.\n * Absent ⇒ winner == baseline. */\n rationale?: string\n }\n /** `winner.compositeMean - baselineOnHoldout.compositeMean`. Positive\n * means the gate observed improvement. */\n lift: number\n /** The explicit baseline→winner unified diff. Always present (empty string\n * when winner == baseline). */\n diff: string\n /** Durable, queryable provenance record: candidate→cell→gate→promote chain +\n * rationale + diff + backend provenance. The artifact the hosted ingest\n * path stores; the +lift RECOMPUTES from `record.heldOutLift`. */\n provenance: LoopProvenanceRecord\n /** `defaultProductionGate.decide()` result. */\n gateDecision: 'ship' | 'hold' | 'need_more_work' | 'model_ceiling' | 'arch_ceiling'\n /** Number of generations actually explored (may be less than the\n * budget if the driver gave up early). */\n generationsExplored: number\n /** Wall-clock total. */\n durationMs: number\n /** Total cost across baseline + every generation. */\n totalCostUsd: number\n /**\n * Rigor packet: distributional summary, paired-bootstrap lift CI,\n * judge stats, contamination check, recommendations. Wired through\n * `analyzeRuns()` on the baseline + winner cells of the campaign.\n * Hosted-tier dashboards render this as the v3-vs-v4 decision view.\n */\n insight: InsightReport\n /**\n * Raw substrate result for advanced inspection — full per-generation\n * candidates, full campaign artifacts, all judge scores. Useful for\n * debugging or reporting beyond the summary.\n */\n raw: RunImprovementLoopResult<TArtifact, TScenario>\n}\n\n/**\n * Deterministic train/holdout split by a stable hash of `scenario.id`,\n * so the same scenario set always splits the same way across runs.\n */\nfunction splitTrainHoldout<TScenario extends Scenario>(\n scenarios: TScenario[],\n fraction: number,\n): { train: TScenario[]; holdout: TScenario[] } {\n // Stable fnv-1a-ish hash of the id for ordering.\n function hash(s: string): number {\n let h = 2166136261 >>> 0\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 16777619) >>> 0\n }\n return h\n }\n const sorted = [...scenarios].sort((a, b) => hash(a.id) - hash(b.id))\n const nHoldout = Math.max(1, Math.min(sorted.length - 1, Math.round(sorted.length * fraction)))\n return {\n holdout: sorted.slice(0, nHoldout),\n train: sorted.slice(nHoldout),\n }\n}\n\nfunction meanComposite(byScenario: Record<string, { meanComposite: number }>): {\n compositeMean: number\n perScenario: Record<string, number>\n} {\n const perScenario: Record<string, number> = {}\n const values: number[] = []\n for (const [id, agg] of Object.entries(byScenario)) {\n perScenario[id] = agg.meanComposite\n values.push(agg.meanComposite)\n }\n return {\n compositeMean: values.length === 0 ? 0 : values.reduce((s, v) => s + v, 0) / values.length,\n perScenario,\n }\n}\n\nconst DEFAULT_MUTATION_PRIMITIVES = [\n 'Tighten the hook: lead with the specific user outcome.',\n 'Replace generic adjectives with specific verbs or proof numbers.',\n \"Anchor every claim in something the scenario's brief literally supports.\",\n 'Honor the surface-shape constraint (length, register, audience vocabulary).',\n]\n\n/**\n * One-shot self-improvement loop. See module docstring for defaults +\n * extension points.\n *\n * @example Minimum (LAND tier):\n *\n * const result = await selfImprove({\n * agent: (surface, scenario, ctx) => myAgent(surface, scenario, ctx.signal),\n * scenarios,\n * judge,\n * baselineSurface: DEFAULT_PROMPT,\n * })\n * console.log(`lift: ${result.lift.toFixed(3)} (${result.gateDecision})`)\n *\n * @example Distributed (workers in three regions):\n *\n * await selfImprove({\n * agent: httpDispatch({ resolveUrl: ({ placement }) => REGION_URLS[placement!] }),\n * scenarios,\n * judge,\n * baselineSurface: DEFAULT_PROMPT,\n * cellPlacement: ({ scenario }) => scenario.region,\n * budget: { maxConcurrency: 12 },\n * })\n */\nexport async function selfImprove<TScenario extends Scenario, TArtifact>(\n opts: SelfImproveOptions<TScenario, TArtifact>,\n): Promise<SelfImproveResult<TScenario, TArtifact>> {\n const startedAt = Date.now()\n\n const budget = opts.budget ?? {}\n const generations = budget.generations ?? 3\n const populationSize = budget.populationSize ?? 2\n const maxConcurrency = budget.maxConcurrency ?? 2\n const holdoutFraction = budget.holdoutFraction ?? 0.25\n const costCeiling = budget.dollars\n\n const explicitHoldout = budget.holdoutScenarios\n const { train, holdout } = explicitHoldout\n ? {\n train: opts.scenarios.filter((s) => !explicitHoldout.some((h) => h.id === s.id)),\n holdout: explicitHoldout as TScenario[],\n }\n : splitTrainHoldout(opts.scenarios, holdoutFraction)\n\n if (train.length === 0) {\n throw new Error(\n 'selfImprove: train split is empty. Reduce holdoutFraction or pass more scenarios.',\n )\n }\n if (holdout.length === 0) {\n throw new Error('selfImprove: holdout split is empty. Pass more scenarios.')\n }\n\n const driver: ImprovementDriver =\n opts.driver ??\n gepaDriver({\n llm: {\n baseUrl: opts.llm?.baseUrl ?? 'https://router.tangle.tools/v1',\n apiKey: opts.llm?.apiKey ?? process.env.OPENAI_API_KEY ?? '',\n },\n model: opts.llm?.model ?? 'anthropic/claude-sonnet-4.6',\n target:\n opts.driverTarget ??\n 'agent surface (system prompt or config) being optimized by selfImprove',\n mutationPrimitives: opts.mutationPrimitives ?? DEFAULT_MUTATION_PRIMITIVES,\n })\n\n const gate: Gate<TArtifact, TScenario> =\n opts.gate ??\n defaultProductionGate<TArtifact, TScenario>({\n holdoutScenarios: holdout,\n deltaThreshold: 0.05,\n })\n\n // Durable by default: a real (non-`mem://`) runDir means the caller wants\n // persistence, so default to fs storage — the provenance record + spans\n // survive the call. A `mem://` runDir (or none) stays in-memory. An explicit\n // `storage` always wins (the opt-out path for tests / edge runtimes).\n const runDir = opts.runDir ?? `mem://selfImprove-${startedAt}`\n const isMemRunDir = runDir.startsWith('mem://')\n const storage = opts.storage ?? (isMemRunDir ? inMemoryCampaignStorage() : fsCampaignStorage())\n\n if (opts.onProgress) {\n opts.onProgress({ kind: 'baseline.started', scenarios: opts.scenarios.length })\n }\n\n const result = await runImprovementLoop<TScenario, TArtifact>({\n scenarios: train,\n baselineSurface: opts.baselineSurface,\n dispatchWithSurface: opts.agent,\n driver,\n judges: [opts.judge],\n populationSize,\n maxGenerations: generations,\n holdoutScenarios: holdout,\n gate,\n autoOnPromote: opts.autoOnPromote ?? 'none',\n ghOwner: opts.ghOwner,\n ghRepo: opts.ghRepo,\n storage,\n runDir,\n maxConcurrency,\n cellPlacement: opts.cellPlacement,\n costCeiling,\n })\n\n const baseline = meanComposite(result.baselineOnHoldout.aggregates.byScenario)\n const winnerStats = meanComposite(result.winnerOnHoldout.aggregates.byScenario)\n\n if (opts.onProgress) {\n opts.onProgress({\n kind: 'baseline.completed',\n compositeMean: baseline.compositeMean,\n durationMs: Date.now() - startedAt,\n })\n opts.onProgress({\n kind: 'gate.decided',\n decision: result.gateResult.decision,\n lift: winnerStats.compositeMean - baseline.compositeMean,\n })\n }\n\n const totalCost =\n result.baselineCampaign.aggregates.totalCostUsd +\n result.generations.reduce(\n (sum, gen) =>\n sum + gen.surfaces.reduce((s, sf) => s + sf.campaign.aggregates.totalCostUsd, 0),\n 0,\n )\n\n // Rigor packet: feed baseline + winner cells through analyzeRuns().\n // The two candidates (`baseline` / `winner`) give the lift section a\n // clean paired comparison; per-judge / per-dimension / cost-quality\n // sections populate from the cells' judgeScores.\n const insight = await analyzeRuns({\n runs: [\n ...cellsToRunRecords(result.baselineCampaign.cells, 'baseline', runDir, opts.baselineSurface),\n ...cellsToRunRecords(result.winnerOnHoldout.cells, 'winner', runDir, result.winnerSurface),\n ],\n baselineCandidateId: 'baseline',\n candidateCandidateId: 'winner',\n })\n\n // ── Durable provenance: candidate→cell→gate→promote chain + rationale +\n // diff + backend provenance. Always emitted; the +lift recomputes from it.\n const durationMs = Date.now() - startedAt\n const workerRecords =\n opts.collectWorkerRecords?.() ??\n cellsToRunRecords(result.winnerOnHoldout.cells, 'winner', runDir, result.winnerSurface)\n const { record: provenance } = await emitLoopProvenance<TArtifact, TScenario>({\n runId: `${runDir}#${startedAt}`,\n runDir,\n timestamp: new Date(startedAt).toISOString(),\n baselineSurface: opts.baselineSurface,\n winnerSurface: result.winnerSurface,\n winnerLabel: result.winnerLabel,\n winnerRationale: result.winnerRationale,\n diff: result.promotedDiff,\n generations: result.generations.map((g) => ({\n generationIndex: g.record.generationIndex,\n candidates: g.record.candidates,\n promoted: g.record.promoted,\n surfaces: g.surfaces.map((s) => ({ surfaceHash: s.surfaceHash, surface: s.surface })),\n })),\n gate: result.gateResult,\n baselineOnHoldout: result.baselineOnHoldout,\n winnerOnHoldout: result.winnerOnHoldout,\n workerRecords,\n totalCostUsd: totalCost,\n totalDurationMs: durationMs,\n storage,\n hostedClient: opts.hostedTenant ? createHostedClient(opts.hostedTenant) : undefined,\n })\n if (opts.onProvenance) opts.onProvenance(provenance)\n\n const summary: SelfImproveResult<TScenario, TArtifact> = {\n baseline,\n winner: {\n ...winnerStats,\n surface: result.winnerSurface,\n ...(result.winnerLabel ? { label: result.winnerLabel } : {}),\n ...(result.winnerRationale ? { rationale: result.winnerRationale } : {}),\n },\n lift: winnerStats.compositeMean - baseline.compositeMean,\n diff: result.promotedDiff,\n provenance,\n gateDecision: result.gateResult.decision,\n generationsExplored: result.generations.length,\n durationMs,\n totalCostUsd: totalCost,\n insight,\n raw: result,\n }\n\n // Opt-in hosted ingest. Failures logged but never fail the loop — the\n // local result is always returned. This matches the wedge-doc invariant\n // that LAND-tier never blocks on EXPAND-tier infra.\n if (opts.hostedTenant) {\n try {\n await shipEvalRunToHosted(opts.hostedTenant, opts, summary, result, runDir)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // eslint-disable-next-line no-console -- intentional: hosted-ingest is best-effort\n console.warn(`[agent-eval] hosted ingest failed (continuing): ${msg}`)\n }\n }\n\n return summary\n}\n\nasync function shipEvalRunToHosted<TScenario extends Scenario, TArtifact>(\n tenant: HostedTenant,\n opts: SelfImproveOptions<TScenario, TArtifact>,\n summary: SelfImproveResult<TScenario, TArtifact>,\n raw: RunImprovementLoopResult<TArtifact, TScenario>,\n runDir: string,\n): Promise<void> {\n const client = createHostedClient(tenant)\n\n function snapshotFromCampaign(\n index: number,\n surface: MutableSurface | undefined,\n campaign: RunImprovementLoopResult<TArtifact, TScenario>['baselineCampaign'],\n durationMs: number,\n ): EvalRunGenerationSnapshot {\n const cells: EvalRunCellScore[] = campaign.cells.map((cell) => {\n const judgeScores = Object.values(cell.judgeScores)\n const composite =\n judgeScores.length === 0\n ? 0\n : judgeScores.reduce((s, j) => s + j.composite, 0) / judgeScores.length\n return {\n scenarioId: cell.scenarioId,\n rep: cell.rep,\n compositeMean: composite,\n dimensions: Object.fromEntries(\n Object.entries(cell.judgeScores).map(([name, score]) => [name, score.dimensions]),\n ),\n errorMessage: cell.error ?? undefined,\n }\n })\n const compositeMean =\n cells.length === 0 ? 0 : cells.reduce((s, c) => s + c.compositeMean, 0) / cells.length\n return {\n index,\n surfaceHash:\n typeof surface === 'string'\n ? hashString(surface)\n : hashString(JSON.stringify(surface ?? '')),\n surface,\n cells,\n compositeMean,\n costUsd: campaign.aggregates.totalCostUsd,\n durationMs,\n }\n }\n\n const generations: EvalRunGenerationSnapshot[] = []\n // Baseline as generation 0.\n generations.push(snapshotFromCampaign(0, opts.baselineSurface, raw.baselineCampaign, 0))\n // Improvement generations as 1..N. Substrate stores per-surface campaigns\n // per generation — we summarize the WINNING surface per generation here.\n for (const gen of raw.generations) {\n const winner = gen.surfaces.reduce(\n (best, s) =>\n s.campaign.aggregates.cellsExecuted > 0 &&\n (best === undefined || averageComposite(s.campaign) > averageComposite(best.campaign))\n ? s\n : best,\n gen.surfaces[0],\n )\n if (!winner) continue\n generations.push(\n snapshotFromCampaign(gen.record.generationIndex + 1, winner.surface, winner.campaign, 0),\n )\n }\n\n const event: EvalRunEvent = {\n runId: `${runDir}#${Date.now()}`,\n runDir,\n timestamp: new Date().toISOString(),\n status: 'finished',\n labels: opts.hostedLabels ?? {},\n baseline: generations[0],\n generations,\n gateDecision: summary.gateDecision,\n holdoutLift: summary.lift,\n totalCostUsd: summary.totalCostUsd,\n totalDurationMs: summary.durationMs,\n insightReport: summary.insight,\n }\n\n await client.ingestEvalRun(event)\n}\n\nfunction averageComposite(\n campaign: RunImprovementLoopResult<unknown, Scenario>['baselineCampaign'],\n): number {\n const aggs = Object.values(campaign.aggregates.byScenario)\n return aggs.length === 0 ? 0 : aggs.reduce((s, a) => s + a.meanComposite, 0) / aggs.length\n}\n\nfunction hashString(s: string): string {\n let h = 2166136261 >>> 0\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 16777619) >>> 0\n }\n return h.toString(16).padStart(8, '0')\n}\n\n/**\n * Adapt campaign cells into the `RunRecord` shape `analyzeRuns()` consumes.\n * Each cell becomes one run; `candidateId` is the caller-supplied label so\n * baseline + winner pair cleanly on `(experimentId, seed)`.\n *\n * `promptHash` is the REAL sha256 content hash of the surface this cell ran\n * (baseline vs winner are byte-distinguishable + byte-identical-verifiable);\n * `configHash` is the sha256 of the candidate label so the two candidates'\n * config rows differ. Both were previously the literal `'sha256:cell'`, which\n * made baseline and winner indistinguishable in every downstream record.\n */\nfunction cellsToRunRecords<TArtifact>(\n cells: ReadonlyArray<CampaignCellResult<TArtifact>>,\n candidateId: 'baseline' | 'winner',\n runId: string,\n surface: MutableSurface,\n): RunRecord[] {\n const promptHash = surfaceContentHash(surface)\n const configHash = `sha256:${createHash('sha256').update(candidateId).digest('hex')}`\n return cells.map((cell) => {\n const perJudge: Record<string, Record<string, number>> = {}\n const perDimMeanAccum: Record<string, { sum: number; n: number }> = {}\n let compositeSum = 0\n let compositeCount = 0\n for (const [judgeId, score] of Object.entries(cell.judgeScores)) {\n perJudge[judgeId] = { ...score.dimensions }\n for (const [dim, value] of Object.entries(score.dimensions)) {\n if (!Number.isFinite(value)) continue\n const accum = perDimMeanAccum[dim] ?? { sum: 0, n: 0 }\n accum.sum += value\n accum.n += 1\n perDimMeanAccum[dim] = accum\n }\n if (Number.isFinite(score.composite)) {\n compositeSum += score.composite\n compositeCount += 1\n }\n }\n const perDimMean: Record<string, number> = {}\n for (const [dim, { sum, n }] of Object.entries(perDimMeanAccum)) {\n perDimMean[dim] = n === 0 ? 0 : sum / n\n }\n const composite = compositeCount === 0 ? 0 : compositeSum / compositeCount\n const judgeScores: JudgeScoresRecord = {\n perJudge,\n perDimMean,\n composite,\n }\n return {\n runId: `${runId}::${candidateId}::${cell.cellId}`,\n experimentId: runId,\n candidateId,\n // Pair on (scenarioId, rep) — analyzeRuns pairs on (experimentId, seed).\n // Synthesize a stable seed for that pairing.\n seed:\n cell.rep * 1_000_000 +\n hashString(cell.scenarioId)\n .slice(0, 6)\n .split('')\n .reduce((a, c) => (a * 31 + c.charCodeAt(0)) >>> 0, 0),\n model: 'campaign-cell',\n promptHash,\n configHash,\n commitSha: 'cell',\n wallMs: cell.durationMs,\n costUsd: cell.costUsd,\n tokenUsage: { input: 0, output: 0 },\n outcome: {\n holdoutScore: composite,\n raw: {},\n judgeScores,\n },\n splitTag: 'holdout',\n ...(cell.error ? { failureMode: cell.error } : {}),\n } satisfies RunRecord\n })\n}\n","/**\n * # `analyzeRuns()` — turn a set of agent runs into an actionable decision packet.\n *\n * Wires the substrate's statistical, calibration, clustering, Pareto, and\n * release-confidence primitives into one `InsightReport`. Two top-level\n * entry points use this function:\n *\n * - `selfImprove()` calls it on the campaign output to attach a packet\n * to every run.\n * - Consumers with observed `RunRecord[]` (production traces, gold\n * corpora, approve/reject tables) call it directly via `analyzeRuns()`\n * for analysis without a closed loop.\n *\n * Every section is opt-in based on what the input data supports — the\n * function never invents signal. If runs carry no judge scores, `judges`\n * is empty. If there's no baseline/candidate split, `lift` is undefined.\n * If no `analyst` is wired, `failureClusters` is undefined.\n *\n * The `recommendations` array is the human-readable layer; everything\n * else is the evidence backing each recommendation.\n */\n\nimport type { AnalystRegistry } from '../analyst/registry'\nimport type { AnalystFinding } from '../analyst/types'\nimport { checkCanaries } from '../contamination-guard'\nimport type { DatasetScenario } from '../dataset'\nimport { summarizeBackendIntegrity } from '../integrity/backend-integrity'\nimport type { RunRecord } from '../run-record'\nimport { cohensD, pairedBootstrap, pairedMde, pairedTTest, requiredSampleSize } from '../statistics'\nimport { type ParetoFigureSpec, paretoChart } from '../summary-report'\n\nimport type {\n FailureClusterInsight,\n FailureModeTally,\n InsightReport,\n InterRaterInsight,\n JudgeInsight,\n LiftInsight,\n MetricDelta,\n OutcomeCorrelationInsight,\n PriorPeriodComparison,\n Recommendation,\n ScalarDistribution,\n} from './insight-report'\n\n// ── Public API ───────────────────────────────────────────────────────\n\nexport interface AnalyzeRunsOptions {\n /** The runs to analyze. */\n runs: RunRecord[]\n /** Which split to score against when reading composite from RunOutcome.\n * Default: holdout when ANY run has a `holdoutScore`, else search. */\n split?: 'search' | 'holdout' | 'auto'\n /** Pairwise analysis configuration. When both `baselineCandidateId` and\n * `candidateCandidateId` are present, lift is computed on paired\n * (experimentId, seed) tuples shared between the two sides. */\n baselineCandidateId?: string\n candidateCandidateId?: string\n /** Canary scenarios — checked against every run's raw output for\n * holdout contamination. */\n canaryScenarios?: DatasetScenario[]\n /** Analyst registry for failure clustering. When omitted, the\n * `failureClusters` section is left undefined. */\n analyst?: AnalystRegistry\n /** Downstream outcome metric per run (e.g. engagement rate, approval\n * rate, downstream pass rate). When present, the report includes\n * `outcomeCorrelation` + a simple linear reward model fit. */\n outcomeSignal?: {\n metric: string\n valueByRunId: Record<string, number>\n }\n /** Multi-rater feedback for inter-rater agreement. Each entry is one\n * rater's score for one run. Two or more raters → kappa + disagreement\n * triage list. */\n raterScores?: Array<{ runId: string; rater: string; score: number }>\n /** Number of histogram bins for distributional summaries. Default 12. */\n histogramBins?: number\n /** Decision threshold — the smallest composite lift the caller cares\n * about. Used by the recommendations engine to call ship vs hold.\n * Default 0.02. */\n decisionThreshold?: number\n /** Optional prior-period runs. When set, the report includes\n * `priorPeriodComparison` with per-metric Welch-CI deltas and\n * recommendations fire on statistically significant regressions.\n * The two windows do NOT have to share scenarios — the comparison\n * is two-sample unpaired (the substrate's `lift` field uses paired\n * bootstrap on shared (experimentId, seed) tuples; this is the\n * shape for \"this week vs last week\" rather than \"candidate vs\n * baseline within a campaign\"). */\n baselineRuns?: RunRecord[]\n /** Human-readable label for the baseline window, e.g. \"vs prior 7\n * days\", \"vs v3.1 release\". Surfaces in recommendations + UI. */\n baselineLabel?: string\n}\n\nexport async function analyzeRuns(opts: AnalyzeRunsOptions): Promise<InsightReport> {\n const runs = opts.runs\n const bins = opts.histogramBins ?? 12\n const threshold = opts.decisionThreshold ?? 0.02\n const split = resolveSplit(runs, opts.split ?? 'auto')\n\n const compositeWithIds = runs\n .map((r) => ({ runId: r.runId, score: compositeOf(r, split) }))\n .filter((p) => Number.isFinite(p.score))\n const composite = distributionOf(\n compositeWithIds.map((p) => p.score),\n bins,\n compositeWithIds,\n )\n\n const perDimension = computePerDimension(runs, bins)\n\n const costs = runs.map((r) => r.costUsd).filter(Number.isFinite)\n const costDist = distributionOf(costs, bins)\n const pareto = paretoChart(runs, { split })\n const degraded: { cost?: string; pareto?: string } = {}\n if (costs.length === 0 || costs.every((c) => c === 0)) {\n degraded.cost = diagnoseZeroCost(runs)\n }\n if (pareto.points.length < 2) {\n degraded.pareto =\n pareto.points.length === 0\n ? 'no candidates — Pareto unavailable'\n : 'single candidate — Pareto is a single point, not a frontier'\n }\n const costQuality = {\n cost: costDist,\n pareto,\n ...(degraded.cost || degraded.pareto ? { degraded } : {}),\n }\n\n const judges = computeJudgeInsights(runs)\n\n const interRater = opts.raterScores ? computeInterRater(opts.raterScores) : undefined\n\n const lift = computeLift(runs, opts.baselineCandidateId, opts.candidateCandidateId, split)\n\n const failureClusters = opts.analyst\n ? await computeFailureClusters(runs, opts.analyst, split)\n : undefined\n\n const failureModes = computeFailureModes(runs)\n\n const contamination = opts.canaryScenarios\n ? computeContamination(runs, opts.canaryScenarios)\n : undefined\n\n const outcomeCorrelation = opts.outcomeSignal\n ? computeOutcomeCorrelation(runs, opts.outcomeSignal, split)\n : undefined\n\n const release = buildReleaseScorecard(composite, lift, contamination)\n\n const priorPeriodComparison = opts.baselineRuns\n ? computePriorPeriodComparison(runs, opts.baselineRuns, split, opts.baselineLabel)\n : undefined\n\n const recommendations = buildRecommendations({\n composite,\n judges,\n interRater,\n lift,\n failureClusters,\n failureModes,\n contamination,\n outcomeCorrelation,\n priorPeriodComparison,\n threshold,\n })\n\n return {\n n: runs.length,\n composite,\n perDimension,\n costQuality,\n judges,\n interRater,\n lift,\n failureClusters,\n contamination,\n outcomeCorrelation,\n release,\n ...(failureModes ? { failureModes } : {}),\n ...(priorPeriodComparison ? { priorPeriodComparison } : {}),\n recommendations,\n }\n}\n\n/** Model-free failure tally. Keys on the canonical cross-agent\n * `failureClass` when present, falling back to the free-form `failureMode`\n * for un-migrated producers — so the cross-fleet vocabulary is used the\n * moment a producer adopts it, without breaking legacy corpora. Returns\n * undefined when no run carries either tag. */\n/** Explain a zero-valued cost axis by its root cause, not just \"no signal\".\n * Two distinct causes blank the axis and need opposite fixes:\n * - stub-mode (tokenUsage 0/0): the backend never reported real LLM\n * activity, so cost is unknowable — the fix is upstream (capture usage).\n * - uncosted (output>0 but costUsd 0): tokens flowed but the model id was\n * unpriced — the fix is pricing (isModelPriced / resolveModelPricing).\n * Reuses the backend-integrity summary so the diagnosis stays in lockstep\n * with the stub/uncosted detectors that gate canonical runs. */\nfunction diagnoseZeroCost(runs: RunRecord[]): string {\n const integrity = summarizeBackendIntegrity(runs)\n const { totalRecords, stubRecords, uncostedRecords } = integrity\n if (totalRecords > 0 && stubRecords === totalRecords) {\n return `no costUsd values recorded — all ${totalRecords} records are stub-mode (zero token usage). The backend never reported real LLM activity, so cost cannot be computed; verify the backend actually ran before trusting this corpus.`\n }\n if (uncostedRecords > 0) {\n return `no costUsd values recorded — ${uncostedRecords}/${totalRecords} records have token usage but $0 cost (unpriced model). Check isModelPriced(model) for the run's model id and add it to FAMILY_PRICING.`\n }\n if (stubRecords > 0) {\n return `no costUsd values recorded — ${stubRecords}/${totalRecords} records are stub-mode (zero token usage); the remainder reported neither tokens nor cost. Cost axis carries no signal.`\n }\n return 'no costUsd values recorded — cost axis carries no signal'\n}\n\nfunction computeFailureModes(runs: RunRecord[]): FailureModeTally[] | undefined {\n const counts = new Map<string, number>()\n for (const r of runs) {\n const key = r.failureClass ?? r.failureMode\n if (key) counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n if (counts.size === 0) return undefined\n const n = runs.length\n return [...counts.entries()]\n .map(([mode, count]) => ({ mode, count, share: n > 0 ? count / n : 0 }))\n .sort((a, b) => b.count - a.count || a.mode.localeCompare(b.mode))\n}\n\n// ── Prior-period comparison ─────────────────────────────────────────\n\n/** Direction of the metric — does \"higher current\" mean better or worse?\n * Composite + judge dimensions: higher is better. Cost + duration: lower\n * is better. The recommendations engine flips the sign before judging\n * regressed vs improved. */\ntype MetricDirection = 'higher-is-better' | 'lower-is-better'\n\nfunction computePriorPeriodComparison(\n current: RunRecord[],\n baseline: RunRecord[],\n split: 'search' | 'holdout',\n windowLabel: string | undefined,\n): PriorPeriodComparison | undefined {\n if (current.length === 0 || baseline.length === 0) return undefined\n\n const metrics: Record<string, MetricDelta> = {}\n const directions: Record<string, MetricDirection> = {}\n\n const compositeCurrent = current\n .map((r) => compositeOf(r, split))\n .filter(Number.isFinite) as number[]\n const compositeBaseline = baseline\n .map((r) => compositeOf(r, split))\n .filter(Number.isFinite) as number[]\n if (compositeCurrent.length > 0 && compositeBaseline.length > 0) {\n metrics.composite = welchCompare(compositeBaseline, compositeCurrent)\n directions.composite = 'higher-is-better'\n }\n\n const costCurrent = current.map((r) => r.costUsd).filter(Number.isFinite)\n const costBaseline = baseline.map((r) => r.costUsd).filter(Number.isFinite)\n if (costCurrent.length > 0 && costBaseline.length > 0) {\n metrics.cost = welchCompare(costBaseline, costCurrent)\n directions.cost = 'lower-is-better'\n }\n\n const durCurrent = current.map((r) => r.wallMs).filter(Number.isFinite)\n const durBaseline = baseline.map((r) => r.wallMs).filter(Number.isFinite)\n if (durCurrent.length > 0 && durBaseline.length > 0) {\n metrics.duration = welchCompare(durBaseline, durCurrent)\n directions.duration = 'lower-is-better'\n }\n\n const tokCurrent = current\n .map((r) => (r.tokenUsage.input ?? 0) + (r.tokenUsage.output ?? 0))\n .filter(Number.isFinite)\n const tokBaseline = baseline\n .map((r) => (r.tokenUsage.input ?? 0) + (r.tokenUsage.output ?? 0))\n .filter(Number.isFinite)\n if (tokCurrent.length > 0 && tokBaseline.length > 0) {\n metrics.tokenUsage = welchCompare(tokBaseline, tokCurrent)\n directions.tokenUsage = 'lower-is-better'\n }\n\n // Per-dimension judge comparisons — only for dimensions present in BOTH\n // windows. We use perDimMean since per-judge nesting is finicky for\n // two-sample comparisons across different judge configurations.\n const dimsCurrent = collectPerDimension(current)\n const dimsBaseline = collectPerDimension(baseline)\n for (const dim of Object.keys(dimsCurrent)) {\n const b = dimsBaseline[dim]\n const c = dimsCurrent[dim]\n if (!b || b.length === 0 || !c || c.length === 0) continue\n metrics[`dim.${dim}`] = welchCompare(b, c)\n directions[`dim.${dim}`] = 'higher-is-better'\n }\n\n const regressedMetrics: string[] = []\n const improvedMetrics: string[] = []\n for (const [name, delta] of Object.entries(metrics)) {\n if (!delta.significant) continue\n const dir = directions[name] ?? 'higher-is-better'\n const better = dir === 'higher-is-better' ? delta.delta > 0 : delta.delta < 0\n if (better) improvedMetrics.push(name)\n else regressedMetrics.push(name)\n }\n\n return {\n baselineN: baseline.length,\n currentN: current.length,\n ...(windowLabel ? { windowLabel } : {}),\n metrics,\n regressedMetrics,\n improvedMetrics,\n }\n}\n\n/** Collect per-dimension values across runs (from outcome.judgeScores.perDimMean). */\nfunction collectPerDimension(runs: RunRecord[]): Record<string, number[]> {\n const out: Record<string, number[]> = {}\n for (const r of runs) {\n const perDim = r.outcome.judgeScores?.perDimMean\n if (!perDim) continue\n for (const [dim, value] of Object.entries(perDim)) {\n if (!Number.isFinite(value)) continue\n if (!out[dim]) out[dim] = []\n out[dim].push(value as number)\n }\n }\n return out\n}\n\n/** Two-sample Welch comparison: unequal-variance t-test + CI on the delta\n * + Cohen's d (pooled stddev). Significance = p < 0.05 AND |d| >= 0.2. */\nfunction welchCompare(baseline: number[], current: number[]): MetricDelta {\n const baselineMean = mean(baseline)\n const currentMean = mean(current)\n const baselineVar = sampleVariance(baseline, baselineMean)\n const currentVar = sampleVariance(current, currentMean)\n const baselineN = baseline.length\n const currentN = current.length\n const delta = currentMean - baselineMean\n\n // Welch standard error\n const se = Math.sqrt(baselineVar / baselineN + currentVar / currentN)\n // For 95% CI we use z=1.96 (large-n approximation). Customers running\n // analyzeRuns will typically have n >= 30; the t-correction is\n // negligible vs the practical noise floor.\n const halfWidth = 1.96 * (se > 0 ? se : 0)\n const ci95: [number, number] = [delta - halfWidth, delta + halfWidth]\n\n // p-value via normal approximation to the t-statistic.\n const t = se > 0 ? delta / se : 0\n const pValue = se > 0 ? 2 * (1 - standardNormalCdf(Math.abs(t))) : 1\n\n // Cohen's d — pooled stddev.\n const pooledStddev = Math.sqrt(\n ((baselineN - 1) * baselineVar + (currentN - 1) * currentVar) /\n Math.max(1, baselineN + currentN - 2),\n )\n const cohensD = pooledStddev > 0 ? delta / pooledStddev : 0\n\n // Significance: BOTH p < 0.05 AND |d| >= 0.2 (small-effect threshold).\n const significant = pValue < 0.05 && Math.abs(cohensD) >= 0.2\n\n return {\n current: currentMean,\n baseline: baselineMean,\n delta,\n ci95,\n pValue,\n cohensD,\n baselineN,\n currentN,\n significant,\n }\n}\n\nfunction sampleVariance(xs: number[], xsMean: number): number {\n if (xs.length < 2) return 0\n let s = 0\n for (const x of xs) s += (x - xsMean) ** 2\n return s / (xs.length - 1)\n}\n\n/** Abramowitz & Stegun approximation to Φ(z). Maximum error ~7.5e-8. */\nfunction standardNormalCdf(z: number): number {\n const a1 = 0.254829592\n const a2 = -0.284496736\n const a3 = 1.421413741\n const a4 = -1.453152027\n const a5 = 1.061405429\n const p = 0.3275911\n const sign = z < 0 ? -1 : 1\n const x = Math.abs(z) / Math.SQRT2\n const t = 1 / (1 + p * x)\n const y = 1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-x * x)\n return 0.5 * (1 + sign * y)\n}\n\n// ── Composite + split selection ─────────────────────────────────────\n\nfunction resolveSplit(\n runs: RunRecord[],\n pref: 'search' | 'holdout' | 'auto',\n): 'search' | 'holdout' {\n if (pref !== 'auto') return pref\n const hasHoldout = runs.some((r) => Number.isFinite(r.outcome.holdoutScore))\n return hasHoldout ? 'holdout' : 'search'\n}\n\nfunction compositeOf(run: RunRecord, split: 'search' | 'holdout'): number {\n const primary = split === 'holdout' ? run.outcome.holdoutScore : run.outcome.searchScore\n if (Number.isFinite(primary)) return primary as number\n // Fall through to the other split if the preferred one is missing —\n // analyzeRuns shouldn't refuse to summarise a run just because the\n // caller asked for the split that wasn't recorded.\n const alt = split === 'holdout' ? run.outcome.searchScore : run.outcome.holdoutScore\n return Number.isFinite(alt) ? (alt as number) : Number.NaN\n}\n\n// ── Distribution helpers ────────────────────────────────────────────\n\nfunction distributionOf(\n values: number[],\n bins: number,\n withIds?: Array<{ runId: string; score: number }>,\n): ScalarDistribution {\n if (values.length === 0) {\n return {\n n: 0,\n mean: 0,\n p50: 0,\n p95: 0,\n stddev: 0,\n min: 0,\n max: 0,\n histogram: [],\n }\n }\n const sorted = [...values].sort((a, b) => a - b)\n const n = sorted.length\n const mean = sorted.reduce((s, v) => s + v, 0) / n\n const variance = sorted.reduce((s, v) => s + (v - mean) ** 2, 0) / n\n const stddev = Math.sqrt(variance)\n const tailRuns = withIds\n ? [...withIds].sort((a, b) => a.score - b.score).slice(0, Math.min(5, withIds.length))\n : undefined\n return {\n n,\n mean,\n p50: percentile(sorted, 0.5),\n p95: percentile(sorted, 0.95),\n stddev,\n min: sorted[0]!,\n max: sorted[n - 1]!,\n histogram: histogram(sorted, bins),\n ...(tailRuns ? { tailRuns } : {}),\n }\n}\n\nfunction percentile(sorted: number[], q: number): number {\n if (sorted.length === 0) return 0\n if (sorted.length === 1) return sorted[0]!\n const idx = (sorted.length - 1) * q\n const lo = Math.floor(idx)\n const hi = Math.ceil(idx)\n if (lo === hi) return sorted[lo]!\n const w = idx - lo\n return sorted[lo]! * (1 - w) + sorted[hi]! * w\n}\n\n/** Even-width histogram over the value range. Returns inclusive-lo /\n * exclusive-hi bins (closed on right for the last bin) compatible with\n * the substrate's `GainDistributionBin` shape. */\nfunction histogram(sorted: number[], bins: number): ScalarDistribution['histogram'] {\n if (sorted.length === 0 || bins < 1) return []\n const min = sorted[0]!\n const max = sorted[sorted.length - 1]!\n if (min === max) return [{ lo: min, hi: max, count: sorted.length }]\n const width = (max - min) / bins\n const out: ScalarDistribution['histogram'] = []\n for (let i = 0; i < bins; i++) {\n const lo = min + i * width\n const hi = i === bins - 1 ? max : lo + width\n out.push({ lo, hi, count: 0 })\n }\n for (const v of sorted) {\n const idx = Math.min(bins - 1, Math.floor((v - min) / width))\n out[idx]!.count++\n }\n return out\n}\n\nfunction computePerDimension(runs: RunRecord[], bins: number): Record<string, ScalarDistribution> {\n // JudgeScoresRecord pre-aggregates `perDimMean` (mean across judges per\n // dimension). We collect those means across runs to produce a per-dim\n // distribution at the corpus level. Consumers who want per-judge\n // dimension values reach into `perJudge[judgeId][dim]` themselves.\n const byDim = new Map<string, number[]>()\n for (const run of runs) {\n const scores = run.outcome.judgeScores\n if (!scores) continue\n for (const [dim, value] of Object.entries(scores.perDimMean ?? {})) {\n if (!Number.isFinite(value)) continue\n const arr = byDim.get(dim) ?? []\n arr.push(value)\n byDim.set(dim, arr)\n }\n }\n const out: Record<string, ScalarDistribution> = {}\n for (const [dim, values] of byDim) out[dim] = distributionOf(values, bins)\n return out\n}\n\n// ── Judge insights ──────────────────────────────────────────────────\n\nfunction computeJudgeInsights(runs: RunRecord[]): Record<string, JudgeInsight> {\n // Each judge's per-run mean is the average of its per-dimension scores\n // for that run. We aggregate those means across all runs each judge\n // scored — giving consumers a \"this judge's typical verdict\" reading.\n const out: Record<string, JudgeInsight> = {}\n const byJudge = new Map<string, number[]>()\n for (const run of runs) {\n const scores = run.outcome.judgeScores\n if (!scores?.perJudge) continue\n for (const [judgeId, dims] of Object.entries(scores.perJudge)) {\n const dimValues = Object.values(dims).filter(Number.isFinite) as number[]\n if (dimValues.length === 0) continue\n const judgeMean = dimValues.reduce((s, v) => s + v, 0) / dimValues.length\n const arr = byJudge.get(judgeId) ?? []\n arr.push(judgeMean)\n byJudge.set(judgeId, arr)\n }\n }\n for (const [judgeId, values] of byJudge) {\n out[judgeId] = {\n n: values.length,\n meanScore: values.reduce((s, v) => s + v, 0) / values.length,\n }\n }\n return out\n}\n\n// ── Inter-rater agreement ───────────────────────────────────────────\n\nfunction computeInterRater(\n ratings: Array<{ runId: string; rater: string; score: number }>,\n): InterRaterInsight | undefined {\n const byRun = new Map<string, Array<{ rater: string; score: number }>>()\n for (const r of ratings) {\n if (!Number.isFinite(r.score)) continue\n const list = byRun.get(r.runId) ?? []\n list.push({ rater: r.rater, score: r.score })\n byRun.set(r.runId, list)\n }\n const raters = new Set(ratings.map((r) => r.rater))\n const jointlyRated: string[] = []\n for (const [runId, ratersForRun] of byRun) {\n const seen = new Set(ratersForRun.map((r) => r.rater))\n let all = true\n for (const r of raters) if (!seen.has(r)) all = false\n if (all) jointlyRated.push(runId)\n }\n if (raters.size < 2 || jointlyRated.length === 0) return undefined\n\n const raterList = [...raters].sort()\n const perPair: Record<string, number> = {}\n for (let i = 0; i < raterList.length; i++) {\n for (let j = i + 1; j < raterList.length; j++) {\n const a = raterList[i]!\n const b = raterList[j]!\n const aScores: number[] = []\n const bScores: number[] = []\n for (const runId of jointlyRated) {\n const ratersForRun = byRun.get(runId)!\n const sa = ratersForRun.find((r) => r.rater === a)?.score\n const sb = ratersForRun.find((r) => r.rater === b)?.score\n if (sa !== undefined && sb !== undefined) {\n aScores.push(sa)\n bScores.push(sb)\n }\n }\n perPair[`${a}::${b}`] = pearson(aScores, bScores)\n }\n }\n const pairKappas = Object.values(perPair)\n const kappa =\n pairKappas.length === 0 ? 0 : pairKappas.reduce((s, v) => s + v, 0) / pairKappas.length\n\n const disagreementCases = jointlyRated\n .map((runId) => {\n const ratersForRun = byRun.get(runId)!\n const scores = ratersForRun.map((r) => r.score)\n const range = Math.max(...scores) - Math.min(...scores)\n return { runId, ratings: ratersForRun, range }\n })\n .sort((a, b) => b.range - a.range)\n .slice(0, 20)\n\n return {\n raters: raters.size,\n jointlyRated: jointlyRated.length,\n kappa,\n perPair,\n disagreementCases,\n }\n}\n\nfunction pearson(a: number[], b: number[]): number {\n if (a.length !== b.length || a.length === 0) return 0\n const n = a.length\n const meanA = a.reduce((s, v) => s + v, 0) / n\n const meanB = b.reduce((s, v) => s + v, 0) / n\n let num = 0\n let denomA = 0\n let denomB = 0\n for (let i = 0; i < n; i++) {\n const da = a[i]! - meanA\n const db = b[i]! - meanB\n num += da * db\n denomA += da * da\n denomB += db * db\n }\n const denom = Math.sqrt(denomA * denomB)\n return denom === 0 ? 0 : num / denom\n}\n\n// ── Lift ────────────────────────────────────────────────────────────\n\nfunction computeLift(\n runs: RunRecord[],\n baselineId: string | undefined,\n candidateId: string | undefined,\n split: 'search' | 'holdout',\n): LiftInsight | undefined {\n let bId = baselineId\n let cId = candidateId\n if (!bId || !cId) {\n // Auto-detect: when exactly two distinct candidateIds appear, treat the\n // lower-mean side as baseline.\n const ids = [...new Set(runs.map((r) => r.candidateId))]\n if (ids.length !== 2) return undefined\n const [idA, idB] = ids as [string, string]\n const meanA = mean(runs.filter((r) => r.candidateId === idA).map((r) => compositeOf(r, split)))\n const meanB = mean(runs.filter((r) => r.candidateId === idB).map((r) => compositeOf(r, split)))\n bId = meanA <= meanB ? idA : idB\n cId = meanA <= meanB ? idB : idA\n }\n\n const baseline = runs.filter((r) => r.candidateId === bId)\n const candidate = runs.filter((r) => r.candidateId === cId)\n if (baseline.length === 0 || candidate.length === 0) return undefined\n\n // Pair on (experimentId, seed). When that key doesn't match, fall back\n // to ordinal pairing — common for fresh runs from the same scenario list.\n const baselineByKey = new Map(baseline.map((r) => [pairingKey(r), r]))\n const pairedBaseline: number[] = []\n const pairedCandidate: number[] = []\n let usedKeyPairing = false\n for (const cand of candidate) {\n const b = baselineByKey.get(pairingKey(cand))\n if (b) {\n const bC = compositeOf(b, split)\n const cC = compositeOf(cand, split)\n if (Number.isFinite(bC) && Number.isFinite(cC)) {\n pairedBaseline.push(bC)\n pairedCandidate.push(cC)\n usedKeyPairing = true\n }\n }\n }\n if (!usedKeyPairing) {\n const n = Math.min(baseline.length, candidate.length)\n for (let i = 0; i < n; i++) {\n const bC = compositeOf(baseline[i]!, split)\n const cC = compositeOf(candidate[i]!, split)\n if (Number.isFinite(bC) && Number.isFinite(cC)) {\n pairedBaseline.push(bC)\n pairedCandidate.push(cC)\n }\n }\n }\n if (pairedBaseline.length === 0) return undefined\n\n const baselineMean = mean(pairedBaseline)\n const candidateMean = mean(pairedCandidate)\n const delta = candidateMean - baselineMean\n\n const bootstrap = pairedBootstrap(pairedBaseline, pairedCandidate, {\n confidence: 0.95,\n resamples: 2000,\n statistic: 'mean',\n })\n const tTest = pairedTTest(pairedBaseline, pairedCandidate)\n const d = cohensD(pairedBaseline, pairedCandidate)\n const mde = pairedMde({ nPaired: pairedBaseline.length, power: 0.8, alpha: 0.05 })\n const requiredN = requiredSampleSize({\n effect: Math.max(Math.abs(delta), 1e-6),\n power: 0.8,\n alpha: 0.05,\n })\n\n return {\n baselineMean,\n candidateMean,\n delta,\n ci95: [bootstrap.low, bootstrap.high],\n pValue: tTest.p,\n n: pairedBaseline.length,\n cohensD: d,\n mde,\n requiredN,\n }\n}\n\nfunction pairingKey(r: RunRecord): string {\n return `${r.experimentId}::${r.seed}`\n}\n\nfunction mean(arr: number[]): number {\n return arr.length === 0 ? 0 : arr.reduce((s, v) => s + v, 0) / arr.length\n}\n\n// ── Failure clustering ──────────────────────────────────────────────\n\nasync function computeFailureClusters(\n runs: RunRecord[],\n analyst: AnalystRegistry,\n split: 'search' | 'holdout',\n): Promise<FailureClusterInsight | undefined> {\n const failed = runs.filter((r) => compositeOf(r, split) < 0.5 || r.failureMode !== undefined)\n if (failed.length === 0) return { clusters: [], totalFailures: 0 }\n\n const clusters = new Map<string, { exemplars: string[]; share: number }>()\n for (const run of failed) {\n try {\n const result = await analyst.run(run.runId, {\n kind: 'run-record',\n run,\n } as Parameters<typeof analyst.run>[1])\n for (const finding of result.findings as AnalystFinding[]) {\n const key = finding.area || finding.analyst_id || 'unclassified'\n const c = clusters.get(key) ?? { exemplars: [], share: 0 }\n if (c.exemplars.length < 5) c.exemplars.push(run.runId)\n clusters.set(key, c)\n }\n } catch {\n const c = clusters.get('analyst-error') ?? { exemplars: [], share: 0 }\n if (c.exemplars.length < 5) c.exemplars.push(run.runId)\n clusters.set('analyst-error', c)\n }\n }\n const clusterList = [...clusters.entries()].map(([id, c]) => ({\n id,\n name: id,\n share: c.exemplars.length / failed.length,\n exemplars: c.exemplars,\n }))\n clusterList.sort((a, b) => b.share - a.share)\n return { clusters: clusterList, totalFailures: failed.length }\n}\n\n// ── Contamination ──────────────────────────────────────────────────\n\nfunction computeContamination(\n runs: RunRecord[],\n canaries: DatasetScenario[],\n): InsightReport['contamination'] {\n let leaks = 0\n const details: Array<{ runId: string; canary: string; matched: string }> = []\n for (const run of runs) {\n const output = stringifyOutput(run)\n if (!output) continue\n const leaksHere = checkCanaries(output, canaries)\n for (const leak of leaksHere) {\n leaks++\n details.push({ runId: run.runId, canary: leak.canary, matched: leak.evidence })\n }\n }\n return { leaks, holdoutAuditPassed: leaks === 0, details }\n}\n\nfunction stringifyOutput(run: RunRecord): string | undefined {\n // RunRecord doesn't fix where \"the agent's output\" lives — different\n // consumers stash it differently. We probe the common shapes: the\n // outcome.raw map (numeric only by design — unlikely to contain text),\n // and any string-valued fields tucked under metadata via type casting.\n // Consumers with bespoke shapes pass canaryScenarios only when they\n // know their runs carry a stringifiable surface.\n const metadata = (run as unknown as { metadata?: Record<string, unknown> }).metadata\n if (typeof metadata?.output === 'string') return metadata.output\n if (typeof metadata?.text === 'string') return metadata.text\n return undefined\n}\n\n// ── Outcome correlation + linear reward model ──────────────────────\n\nfunction computeOutcomeCorrelation(\n runs: RunRecord[],\n outcome: { metric: string; valueByRunId: Record<string, number> },\n split: 'search' | 'holdout',\n): OutcomeCorrelationInsight | undefined {\n const xs: number[] = []\n const ys: number[] = []\n for (const run of runs) {\n const y = outcome.valueByRunId[run.runId]\n if (y === undefined || !Number.isFinite(y)) continue\n const x = compositeOf(run, split)\n if (!Number.isFinite(x)) continue\n xs.push(x)\n ys.push(y)\n }\n if (xs.length < 3) return undefined\n\n const p = pearson(xs, ys)\n const s = spearman(xs, ys)\n const meanX = mean(xs)\n const meanY = mean(ys)\n let num = 0\n let denom = 0\n for (let i = 0; i < xs.length; i++) {\n num += (xs[i]! - meanX) * (ys[i]! - meanY)\n denom += (xs[i]! - meanX) ** 2\n }\n const slope = denom === 0 ? 0 : num / denom\n const intercept = meanY - slope * meanX\n const ssTot = ys.reduce((a, y) => a + (y - meanY) ** 2, 0)\n const ssRes = ys.reduce((a, y, i) => a + (y - (intercept + slope * xs[i]!)) ** 2, 0)\n const r2 = ssTot === 0 ? 0 : 1 - ssRes / ssTot\n\n return {\n metric: outcome.metric,\n n: xs.length,\n pearson: p,\n spearman: s,\n rewardModel: { intercept, slope, r2 },\n }\n}\n\nfunction spearman(a: number[], b: number[]): number {\n if (a.length !== b.length || a.length === 0) return 0\n return pearson(rank(a), rank(b))\n}\n\nfunction rank(arr: number[]): number[] {\n const indexed = arr.map((v, i) => ({ v, i }))\n indexed.sort((x, y) => x.v - y.v)\n const ranks = new Array(arr.length).fill(0)\n let i = 0\n while (i < indexed.length) {\n let j = i\n while (j + 1 < indexed.length && indexed[j + 1]!.v === indexed[i]!.v) j++\n const avg = (i + j + 2) / 2\n for (let k = i; k <= j; k++) ranks[indexed[k]!.i] = avg\n i = j + 1\n }\n return ranks\n}\n\n// ── Release confidence scorecard ───────────────────────────────────\n\nfunction buildReleaseScorecard(\n composite: ScalarDistribution,\n lift: LiftInsight | undefined,\n contamination: InsightReport['contamination'],\n): InsightReport['release'] {\n // Synthesise a minimal scorecard from the rolled-up signal. The\n // substrate's `evaluateReleaseConfidence` primitive consumes a richer\n // input shape that callers can produce by wiring SLO definitions; the\n // shape here is the contract `selfImprove`/`analyzeRuns` consumers\n // receive automatically. They can call `evaluateReleaseConfidence`\n // directly when they want SLO-based axis evaluation.\n const axes: InsightReport['release']['axes'] = []\n const liftPass =\n lift === undefined || lift.ci95[0] > 0\n ? ('pass' as const)\n : lift.delta > 0\n ? ('warn' as const)\n : ('fail' as const)\n axes.push({\n name: 'quality-lift',\n status: liftPass,\n detail: lift\n ? `delta=${lift.delta.toFixed(3)}, CI95=[${lift.ci95[0].toFixed(3)}, ${lift.ci95[1].toFixed(3)}], n=${lift.n}`\n : 'no baseline/candidate pair available',\n })\n const contamPass =\n contamination === undefined || contamination.leaks === 0 ? ('pass' as const) : ('fail' as const)\n axes.push({\n name: 'contamination',\n status: contamPass,\n detail: contamination ? `${contamination.leaks} canary leak(s)` : 'no canaries supplied',\n })\n axes.push({\n name: 'composite-distribution',\n status: composite.mean >= 0.5 ? 'pass' : composite.mean >= 0.3 ? 'warn' : 'fail',\n detail: `mean=${composite.mean.toFixed(3)}, p50=${composite.p50.toFixed(3)}, p95=${composite.p95.toFixed(3)} over n=${composite.n}`,\n })\n const status = axes.some((a) => a.status === 'fail')\n ? 'fail'\n : axes.some((a) => a.status === 'warn')\n ? 'warn'\n : 'pass'\n return {\n status,\n axes,\n issues: [],\n }\n}\n\n// ── Recommendations engine ─────────────────────────────────────────\n\ninterface RecommendationContext {\n composite: ScalarDistribution\n judges: Record<string, JudgeInsight>\n interRater?: InterRaterInsight\n lift?: LiftInsight\n failureClusters?: FailureClusterInsight\n failureModes?: FailureModeTally[]\n contamination?: InsightReport['contamination']\n outcomeCorrelation?: OutcomeCorrelationInsight\n priorPeriodComparison?: PriorPeriodComparison\n threshold: number\n}\n\nfunction buildRecommendations(ctx: RecommendationContext): Recommendation[] {\n const out: Recommendation[] = []\n\n // Prior-period regressions — highest customer-impact signal when present.\n // \"Did my last change help?\" with a falsifiable answer.\n if (ctx.priorPeriodComparison) {\n const ppc = ctx.priorPeriodComparison\n const label = ppc.windowLabel ?? 'baseline period'\n for (const name of ppc.regressedMetrics) {\n const d = ppc.metrics[name]\n if (!d) continue\n out.push({\n priority: 'critical',\n kind: 'investigate',\n title: `${name} regressed from ${d.baseline.toFixed(3)} → ${d.current.toFixed(3)} vs ${label}`,\n detail: `Welch CI95 = [${d.ci95[0].toFixed(3)}, ${d.ci95[1].toFixed(3)}], p=${d.pValue.toFixed(4)}, Cohen's d=${d.cohensD.toFixed(2)} (n_current=${d.currentN}, n_baseline=${d.baselineN}). The regression is statistically significant at p<0.05 with at-least-small effect size.`,\n evidencePath: `priorPeriodComparison.metrics.${name}`,\n })\n }\n for (const name of ppc.improvedMetrics) {\n const d = ppc.metrics[name]\n if (!d) continue\n out.push({\n priority: 'low',\n kind: 'ship',\n title: `${name} improved from ${d.baseline.toFixed(3)} → ${d.current.toFixed(3)} vs ${label}`,\n detail: `Welch CI95 = [${d.ci95[0].toFixed(3)}, ${d.ci95[1].toFixed(3)}], p=${d.pValue.toFixed(4)}, Cohen's d=${d.cohensD.toFixed(2)} (n_current=${d.currentN}, n_baseline=${d.baselineN}). Statistically significant improvement worth flagging.`,\n evidencePath: `priorPeriodComparison.metrics.${name}`,\n })\n }\n }\n\n // Composite-distribution branch. Fires when the overall quality signal is\n // poor regardless of lift / contamination / clusters — the customer needs\n // to know they have a problem AND which specific runs to inspect.\n if (ctx.composite.n > 0) {\n if (ctx.composite.mean < 0.3) {\n const tail = ctx.composite.tailRuns ?? []\n const names = tail\n .slice(0, 5)\n .map((t) => `${t.runId}=${t.score.toFixed(3)}`)\n .join(', ')\n out.push({\n priority: 'critical',\n kind: 'investigate',\n title: `Composite mean ${ctx.composite.mean.toFixed(3)} is below the 0.3 floor — the agent is broken on this corpus`,\n detail:\n tail.length > 0\n ? `Worst ${tail.length} run${tail.length === 1 ? '' : 's'} to inspect first: ${names}. Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`\n : `Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`,\n evidencePath: 'composite.tailRuns',\n })\n } else if (ctx.composite.mean < 0.5) {\n const tail = ctx.composite.tailRuns ?? []\n const names = tail\n .slice(0, 3)\n .map((t) => `${t.runId}=${t.score.toFixed(3)}`)\n .join(', ')\n out.push({\n priority: 'high',\n kind: 'investigate',\n title: `Composite mean ${ctx.composite.mean.toFixed(3)} is below 0.5 — investigate the lower tail before claiming the agent is healthy`,\n detail:\n tail.length > 0\n ? `Worst ${tail.length} run${tail.length === 1 ? '' : 's'}: ${names}. Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`\n : `Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`,\n evidencePath: 'composite.tailRuns',\n })\n }\n }\n\n // Dominant-failure-mode branch (model-free). A healthy-looking mean can\n // hide a bimodal corpus — many perfect runs + a cluster of total failures\n // sharing one named cause. Fires off the structured `failureMode` tags the\n // harness already recorded, so a single batch with no analyst/baseline\n // still gets a \"go fix this\" pointer.\n if (ctx.failureModes && ctx.failureModes.length > 0) {\n const top = ctx.failureModes[0]!\n if (top.count >= 3 && top.share >= 0.15) {\n out.push({\n priority: top.share >= 0.25 ? 'high' : 'medium',\n kind: 'investigate',\n title: `'${top.mode}' is the dominant failure mode — ${top.count} runs (${(top.share * 100).toFixed(0)}% of the corpus)`,\n detail: `The mean composite can look acceptable while one named failure dominates the lower tail. ${top.count} of ${ctx.composite.n} runs failed with '${top.mode}'${ctx.failureModes.length > 1 ? ` (next: '${ctx.failureModes[1]!.mode}' ×${ctx.failureModes[1]!.count})` : ''}. Fix this cause first.`,\n evidencePath: 'failureModes',\n })\n }\n }\n\n // Missing-judges branch. The report can't surface per-dimension or\n // calibration signal when `outcome.judgeScores` is empty across the\n // corpus. Tell the customer how to enrich.\n if (Object.keys(ctx.judges).length === 0 && ctx.composite.n > 0) {\n out.push({\n priority: 'medium',\n kind: 'expand-corpus',\n title: 'No judge scores recorded — per-dimension + calibration insights unavailable',\n detail:\n 'Records have no `outcome.judgeScores`. To unlock perDimension, judges, and calibration, attach a Judge run during your eval pass and populate `outcome.judgeScores.perJudge[judgeName][dimension] = score`. See `docs/insight-report.md` for the expected shape.',\n evidencePath: 'judges',\n })\n }\n\n if (ctx.lift) {\n const decisive = ctx.lift.ci95[0] > ctx.threshold\n const inconclusive = ctx.lift.ci95[0] <= ctx.threshold && ctx.lift.ci95[1] > ctx.threshold\n if (decisive) {\n out.push({\n priority: 'critical',\n kind: 'ship',\n title: `Ship — lift ${ctx.lift.delta.toFixed(3)} (95% CI ${ctx.lift.ci95[0].toFixed(3)}..${ctx.lift.ci95[1].toFixed(3)})`,\n detail: `Holdout lift exceeds threshold ${ctx.threshold} with 95% bootstrap confidence (n=${ctx.lift.n}, p=${ctx.lift.pValue.toFixed(4)}, d=${ctx.lift.cohensD.toFixed(2)}).`,\n evidencePath: 'lift',\n })\n } else if (inconclusive) {\n out.push({\n priority: 'high',\n kind: 'expand-corpus',\n title: `Inconclusive — need ~${ctx.lift.requiredN} paired runs (have ${ctx.lift.n}) at current effect size`,\n detail: `CI straddles threshold. Current MDE at 80% power is ${ctx.lift.mde.toFixed(3)}; observed delta is ${ctx.lift.delta.toFixed(3)}.`,\n evidencePath: 'lift',\n })\n } else {\n out.push({\n priority: 'critical',\n kind: 'hold',\n title: `Hold — lift CI lower bound ${ctx.lift.ci95[0].toFixed(3)} is at or below threshold ${ctx.threshold}`,\n detail: `Bootstrap CI provides no statistical evidence the candidate is better. Consider tightening the mutation or expanding the holdout.`,\n evidencePath: 'lift',\n })\n }\n }\n\n if (ctx.contamination && ctx.contamination.leaks > 0) {\n out.push({\n priority: 'critical',\n kind: 'fix',\n title: `${ctx.contamination.leaks} canary leak${ctx.contamination.leaks === 1 ? '' : 's'} detected`,\n detail: `Holdout integrity is compromised. The lift number is unreliable until you investigate.`,\n evidencePath: 'contamination',\n })\n }\n\n if (ctx.interRater && ctx.interRater.kappa < 0.5) {\n out.push({\n priority: 'high',\n kind: 'recalibrate',\n title: `Inter-rater agreement κ=${ctx.interRater.kappa.toFixed(2)} is below 0.5`,\n detail: `Raters disagree on what 'good' looks like. Top disagreement cases listed in interRater.disagreementCases — consider a triage meeting or refining the rubric.`,\n evidencePath: 'interRater',\n })\n }\n\n if (ctx.failureClusters && ctx.failureClusters.clusters.length > 0) {\n const top = ctx.failureClusters.clusters[0]!\n out.push({\n priority: 'high',\n kind: 'investigate',\n title: `Top failure cluster: ${top.name} (${(top.share * 100).toFixed(0)}% of failures)`,\n detail: `${ctx.failureClusters.totalFailures} runs failed. The largest cluster groups ${top.exemplars.length} exemplars under '${top.name}'.`,\n evidencePath: 'failureClusters.clusters[0]',\n })\n }\n\n if (ctx.outcomeCorrelation && Math.abs(ctx.outcomeCorrelation.spearman) < 0.3) {\n out.push({\n priority: 'medium',\n kind: 'recalibrate',\n title: `Judge scores decoupled from ${ctx.outcomeCorrelation.metric} (Spearman ρ=${ctx.outcomeCorrelation.spearman.toFixed(2)})`,\n detail: `Your judges score what they were trained to score, but it isn't predicting downstream ${ctx.outcomeCorrelation.metric}. Consider retraining the judge against ${ctx.outcomeCorrelation.metric} as the gold signal.`,\n evidencePath: 'outcomeCorrelation',\n })\n }\n\n return out\n}\n\n// ── Re-export pareto figure spec for hosted-side rendering ─────────\n\nexport type { ParetoFigureSpec }\n","/**\n * `fromAgentTrace` — provenance correlation from Cursor's Agent Trace spec\n * (https://github.com/cursor/agent-trace, RFC v0.1.0).\n *\n * Agent Trace is NOT a run/quality trace — it carries no outcome, score, or\n * cost. It records *code authorship*: for a VCS revision, which AI model /\n * conversation authored which file ranges. It explicitly disclaims quality\n * assessment — which is exactly what `analyzeRuns` adds.\n *\n * The two layers join on a key the substrate already has: a `RunRecord`\n * carries `commitSha`, and an Agent Trace record is keyed by\n * `vcs.revision`. So this adapter does not produce `RunRecord`s — it builds a\n * provenance index by commit and partitions existing runs by their authoring\n * model. Feed each cohort to `analyzeRuns` (or pass one as `baselineRuns`) to\n * answer the question no run-only trace can: *which authoring agent's code\n * fails / regresses / costs more.*\n *\n * Granularity is commit-level (the SHA join). Per-file/per-line correlation\n * would require runs to record which files they exercised — out of scope.\n */\n\nimport type { RunRecord } from '../../run-record'\n\n// ── Agent Trace record schema (the subset we read) ──────────────────────────\n\nexport type AgentTraceContributorType = 'human' | 'ai' | 'mixed' | 'unknown'\n\nexport interface AgentTraceContributor {\n type: AgentTraceContributorType\n /** models.dev id, e.g. `anthropic/claude-opus-4-5-20251101`. */\n model_id?: string\n}\n\nexport interface AgentTraceRange {\n start_line: number\n end_line: number\n content_hash?: string\n /** Per-range contributor override (agent handoffs). Wins over the\n * conversation-level contributor for these lines. */\n contributor?: AgentTraceContributor\n}\n\nexport interface AgentTraceConversation {\n url?: string\n contributor?: AgentTraceContributor\n ranges: AgentTraceRange[]\n}\n\nexport interface AgentTraceFile {\n path: string\n conversations: AgentTraceConversation[]\n}\n\nexport interface AgentTraceRecord {\n version: string\n id: string\n timestamp: string\n vcs?: { type: string; revision: string }\n tool?: { name?: string; version?: string }\n files: AgentTraceFile[]\n}\n\n// ── Provenance index ─────────────────────────────────────────────────────────\n\n/** Authorship provenance for one VCS revision, aggregated across the record's\n * files/conversations/ranges. */\nexport interface AuthoringProvenance {\n commitSha: string\n /** Unique AI model ids that authored code in this commit (type ai|mixed). */\n aiModels: string[]\n /** Tools that produced the records (e.g. `cursor`). */\n tools: string[]\n conversationCount: number\n fileCount: number\n /** Total attributed lines (sum of range spans). */\n lineCount: number\n /** True if any range was authored (in whole or part) by a human. */\n humanInvolved: boolean\n}\n\nexport type AgentTraceIndex = Map<string, AuthoringProvenance>\n\nfunction rangeLines(r: AgentTraceRange): number {\n return Math.max(0, r.end_line - r.start_line + 1)\n}\n\n/**\n * Build a commit → provenance index from Agent Trace records. Multiple records\n * for the same revision are merged. Records without `vcs.revision` are skipped\n * (the SHA is the join key — without it there is nothing to correlate against).\n */\nexport function parseAgentTrace(records: AgentTraceRecord[]): AgentTraceIndex {\n interface Acc {\n models: Set<string>\n tools: Set<string>\n files: Set<string>\n conversationCount: number\n lineCount: number\n humanInvolved: boolean\n }\n const acc = new Map<string, Acc>()\n\n for (const record of records) {\n const sha = record.vcs?.revision\n if (!sha) continue // the SHA is the join key — nothing to correlate without it\n\n let a = acc.get(sha)\n if (!a) {\n a = {\n models: new Set(),\n tools: new Set(),\n files: new Set(),\n conversationCount: 0,\n lineCount: 0,\n humanInvolved: false,\n }\n acc.set(sha, a)\n }\n\n if (record.tool?.name) a.tools.add(record.tool.name)\n\n for (const file of record.files ?? []) {\n a.files.add(file.path)\n for (const conv of file.conversations ?? []) {\n a.conversationCount += 1\n for (const range of conv.ranges ?? []) {\n // Per-range contributor wins, else the conversation contributor.\n const contributor = range.contributor ?? conv.contributor\n a.lineCount += rangeLines(range)\n if (!contributor) continue\n if (contributor.type === 'human' || contributor.type === 'mixed') {\n a.humanInvolved = true\n }\n if ((contributor.type === 'ai' || contributor.type === 'mixed') && contributor.model_id) {\n a.models.add(contributor.model_id)\n }\n }\n }\n }\n }\n\n const index: AgentTraceIndex = new Map()\n for (const [sha, a] of acc) {\n index.set(sha, {\n commitSha: sha,\n aiModels: [...a.models].sort(),\n tools: [...a.tools].sort(),\n conversationCount: a.conversationCount,\n fileCount: a.files.size,\n lineCount: a.lineCount,\n humanInvolved: a.humanInvolved,\n })\n }\n return index\n}\n\n// ── Run ↔ provenance join ──────────────────────────────────────────────────\n\nexport interface PartitionByAuthoringModelResult {\n /** Runs grouped by each AI model that authored code in the run's commit. A\n * run whose commit had multiple authoring models appears under EACH — the\n * cohorts overlap by construction at commit granularity. */\n byModel: Map<string, RunRecord[]>\n /** Runs whose `commitSha` had no Agent Trace provenance (no record, or no\n * AI authorship). Kept separate — never silently folded into a cohort. */\n unattributed: RunRecord[]\n}\n\n/**\n * Partition runs by the AI model(s) that authored the code at each run's\n * `commitSha`. Feed `byModel.get(modelId)` to `analyzeRuns`, or compare two\n * model cohorts via `analyzeRuns({ runs: a, baselineRuns: b })` for a lift CI\n * on \"model A's code vs model B's code\".\n */\nexport function partitionRunsByAuthoringModel(\n runs: RunRecord[],\n index: AgentTraceIndex,\n): PartitionByAuthoringModelResult {\n const byModel = new Map<string, RunRecord[]>()\n const unattributed: RunRecord[] = []\n\n for (const run of runs) {\n const provenance = index.get(run.commitSha)\n if (!provenance || provenance.aiModels.length === 0) {\n unattributed.push(run)\n continue\n }\n for (const model of provenance.aiModels) {\n const cohort = byModel.get(model) ?? []\n cohort.push(run)\n byModel.set(model, cohort)\n }\n }\n\n return { byModel, unattributed }\n}\n","/**\n * # `intake/feedback-table` — multi-rater approve/reject corpus → `RunRecord[]`.\n *\n * The generic shape behind Obsidian's `#approved` / `#rejected` tags, a\n * Google Sheet, a Postgres `feedback` table, or any CSV with ratings.\n *\n * Caller supplies one row per (run, rater) tuple plus per-run metadata; the\n * adapter rolls them up into the substrate-canonical `RunRecord` shape so\n * `analyzeRuns({ runs, raterScores })` can produce inter-rater agreement,\n * disagreement triage, and downstream recommendations.\n *\n * Per-run `RunRecord.outcome.searchScore` is the rater-mean rating\n * (normalised to 0..1 when scale is supplied); `outcome.raw` carries the\n * per-rater scores keyed by rater id for downstream attribution.\n */\n\nimport type { JudgeScoresRecord, RunOutcome, RunRecord, RunSplitTag } from '../../run-record'\n\nexport interface FeedbackTableRow {\n /** Stable id for this run — the unit a rater scored. Drives pairing\n * across analysis primitives. */\n runId: string\n /** Identifier of the rater that produced this rating. */\n rater: string\n /** The rating itself. Accepts boolean (approve/reject), 0..1 scalar,\n * or any numeric scale — see `scale`. */\n rating: number | boolean\n /** Optional metadata carried through to `RunRecord.outcome.raw` and the\n * custom-shape metadata bag. */\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackTableMeta {\n runId: string\n /** When omitted, defaults to `'feedback-corpus'`. Used to group related\n * runs in `analyzeRuns()` lift analysis. */\n experimentId?: string\n /** When omitted, defaults to `runId` — each run is its own candidate. */\n candidateId?: string\n /** Cost in USD, when available. Set to 0 when unknown — the consumer's\n * cost analysis sections will collapse gracefully. */\n costUsd?: number\n /** Wall-clock ms, when available. Defaults to 0. */\n wallMs?: number\n /** Model identifier including snapshot. Default `unknown@unknown`. */\n model?: string\n /** Optional sha256 of the prompt; default `'sha256:unknown'`. */\n promptHash?: string\n /** Default `'sha256:unknown'`. */\n configHash?: string\n /** Default `'unknown'`. */\n commitSha?: string\n /** Default `'holdout'` — feedback corpora are by nature the holdout\n * signal a closed-loop improvement aims at. */\n splitTag?: RunSplitTag\n /** Free-form metadata available to consumers via the cast-out path on\n * the resulting RunRecord. */\n extras?: Record<string, unknown>\n}\n\nexport interface FromFeedbackTableOptions {\n /** Per-(run, rater) ratings. */\n ratings: FeedbackTableRow[]\n /** Per-run metadata. When a runId appears in `ratings` but not here, the\n * adapter synthesises minimal metadata with defaults documented above. */\n meta?: FeedbackTableMeta[]\n /** Rating scale. Provide `{ min, max }` for non-0..1 numeric scales.\n * Booleans are normalised: true → 1, false → 0. Default: assumes\n * ratings are already 0..1. */\n scale?: { min: number; max: number }\n /** When true, the rater scores are emitted into `raterScores` (a sibling\n * array `analyzeRuns()` accepts) instead of being averaged into the\n * run's `outcome.searchScore`. Default `true` — preserves rater-level\n * signal for inter-rater analysis. */\n emitRaterScores?: boolean\n}\n\nexport interface FromFeedbackTableResult {\n runs: RunRecord[]\n /** Rater-level scores ready to pass into `analyzeRuns({ raterScores })`\n * for inter-rater agreement + disagreement triage. */\n raterScores: Array<{ runId: string; rater: string; score: number }>\n}\n\nexport function fromFeedbackTable(opts: FromFeedbackTableOptions): FromFeedbackTableResult {\n const { ratings, meta = [], scale, emitRaterScores = true } = opts\n const metaByRun = new Map(meta.map((m) => [m.runId, m]))\n\n // Normalise per-rating to a 0..1 score.\n const normalise = (rating: number | boolean): number => {\n if (typeof rating === 'boolean') return rating ? 1 : 0\n if (!Number.isFinite(rating)) return Number.NaN\n if (!scale) return rating\n const { min, max } = scale\n if (max === min) return rating\n return (rating - min) / (max - min)\n }\n\n // Group ratings by runId.\n const byRun = new Map<string, FeedbackTableRow[]>()\n for (const row of ratings) {\n const list = byRun.get(row.runId) ?? []\n list.push(row)\n byRun.set(row.runId, list)\n }\n\n const runs: RunRecord[] = []\n const raterScores: FromFeedbackTableResult['raterScores'] = []\n\n for (const [runId, rowsForRun] of byRun) {\n const normalised = rowsForRun\n .map((r) => ({ rater: r.rater, score: normalise(r.rating) }))\n .filter((r) => Number.isFinite(r.score))\n if (normalised.length === 0) continue\n\n const meanScore = normalised.reduce((s, r) => s + r.score, 0) / normalised.length\n\n const runMeta = metaByRun.get(runId) ?? ({ runId } as FeedbackTableMeta)\n\n const judgeScores: JudgeScoresRecord = {\n perJudge: Object.fromEntries(normalised.map((r) => [r.rater, { rating: r.score }])),\n perDimMean: { rating: meanScore },\n composite: meanScore,\n }\n\n const outcome: RunOutcome = {\n // Feedback corpora ARE the holdout signal — score lands on\n // `holdoutScore` so downstream substrate primitives (`paretoChart`,\n // promotion gates) read it correctly by default.\n holdoutScore: meanScore,\n raw: Object.fromEntries(normalised.map((r) => [`rater:${r.rater}`, r.score])),\n judgeScores,\n }\n\n runs.push({\n runId,\n experimentId: runMeta.experimentId ?? 'feedback-corpus',\n candidateId: runMeta.candidateId ?? runId,\n seed: 0,\n model: runMeta.model ?? 'unknown@unknown',\n promptHash: runMeta.promptHash ?? 'sha256:unknown',\n configHash: runMeta.configHash ?? 'sha256:unknown',\n commitSha: runMeta.commitSha ?? 'unknown',\n wallMs: runMeta.wallMs ?? 0,\n costUsd: runMeta.costUsd ?? 0,\n tokenUsage: { input: 0, output: 0 },\n outcome,\n splitTag: runMeta.splitTag ?? 'holdout',\n } as RunRecord)\n\n if (emitRaterScores) {\n for (const r of normalised) raterScores.push({ runId, rater: r.rater, score: r.score })\n }\n }\n\n return { runs, raterScores }\n}\n","/**\n * # `intake/otel-spans` — OTel `TraceSpanEvent[]` → `RunRecord[]`.\n *\n * Turns an existing observability stream into the substrate-canonical\n * `RunRecord` shape so consumers with logs but no eval discipline can\n * call `analyzeRuns()` against their production traffic immediately.\n *\n * Pivot rule: spans are grouped by `tangle.runId` (the same attribute the\n * hosted-tier wire format uses) or, when absent, by `traceId`. One group\n * becomes one `RunRecord`. The root span (no `parentSpanId`) supplies:\n *\n * - `runId` (the group key)\n * - `wallMs` from `endTimeUnixNano - startTimeUnixNano`\n * - `model` from `gen_ai.request.model` / `llm.model` / `tangle.model`\n * - cost from `cost.usd` / `gen_ai.usage.cost_usd` / `tangle.cost.usd`\n * - token usage from `gen_ai.usage.{input,output}_tokens`\n * - `outcome.searchScore` from `tangle.score` / `eval.score` when\n * present; `outcome.raw` collects every numeric attribute.\n *\n * Spans that ERRORed (`status.code === 'ERROR'`) populate `failureMode`\n * with their `name` so `analyzeRuns()`'s failure clustering sees them.\n */\n\nimport type { TraceSpanEvent } from '../../hosted/types'\nimport type {\n JudgeScoresRecord,\n RunOutcome,\n RunRecord,\n RunSplitTag,\n RunTokenUsage,\n} from '../../run-record'\n\nconst SCORE_KEYS = ['tangle.score', 'eval.score', 'score']\nconst MODEL_KEYS = ['tangle.model', 'gen_ai.request.model', 'llm.model', 'model']\nconst COST_KEYS = ['tangle.cost.usd', 'gen_ai.usage.cost_usd', 'cost.usd', 'cost']\nconst INPUT_TOKEN_KEYS = ['gen_ai.usage.input_tokens', 'tangle.tokens.in', 'tokens.in']\nconst OUTPUT_TOKEN_KEYS = ['gen_ai.usage.output_tokens', 'tangle.tokens.out', 'tokens.out']\nconst PROMPT_HASH_KEYS = ['tangle.prompt_hash', 'prompt.hash']\nconst CONFIG_HASH_KEYS = ['tangle.config_hash', 'config.hash']\n\nexport interface FromOtelSpansOptions {\n spans: TraceSpanEvent[]\n /** Default split tag for synthesized records. Defaults to `'holdout'`. */\n defaultSplit?: RunSplitTag\n /** Default `experimentId` when not present on any span. */\n experimentId?: string\n}\n\nexport function fromOtelSpans(opts: FromOtelSpansOptions): RunRecord[] {\n const { spans, defaultSplit = 'holdout', experimentId = 'otel-corpus' } = opts\n const grouped = groupSpans(spans)\n\n const runs: RunRecord[] = []\n for (const [groupKey, groupSpans] of grouped) {\n const root = findRoot(groupSpans)\n if (!root) continue\n\n const wallMs = Math.max(0, (root.endTimeUnixNano - root.startTimeUnixNano) / 1_000_000)\n const model = readAttrString(groupSpans, MODEL_KEYS) ?? 'unknown@unknown'\n const costUsd = readAttrNumber(groupSpans, COST_KEYS) ?? 0\n const inputTokens = readAttrNumber(groupSpans, INPUT_TOKEN_KEYS) ?? 0\n const outputTokens = readAttrNumber(groupSpans, OUTPUT_TOKEN_KEYS) ?? 0\n const promptHash = readAttrString(groupSpans, PROMPT_HASH_KEYS) ?? 'sha256:unknown'\n const configHash = readAttrString(groupSpans, CONFIG_HASH_KEYS) ?? 'sha256:unknown'\n const score = readAttrNumber(groupSpans, SCORE_KEYS)\n\n const rawNumeric = collectNumericAttrs(groupSpans)\n const tokenUsage: RunTokenUsage = {\n input: inputTokens,\n output: outputTokens,\n }\n\n const judgeScores: JudgeScoresRecord | undefined =\n score !== undefined\n ? {\n perJudge: { 'otel-derived': { score } },\n perDimMean: { score },\n composite: score,\n }\n : undefined\n\n const errorSpan = groupSpans.find((s) => s.status?.code === 'ERROR')\n const outcome: RunOutcome = {\n ...(opts.defaultSplit === 'search' ? { searchScore: score } : { holdoutScore: score }),\n raw: rawNumeric,\n ...(judgeScores ? { judgeScores } : {}),\n }\n\n runs.push({\n runId: groupKey,\n experimentId,\n candidateId: (root.attributes['tangle.candidateId'] as string | undefined) ?? 'otel-default',\n seed: 0,\n model,\n promptHash,\n configHash,\n commitSha: (root.attributes['tangle.commit_sha'] as string | undefined) ?? 'unknown',\n wallMs,\n costUsd,\n tokenUsage,\n outcome,\n splitTag: defaultSplit,\n ...(errorSpan ? { failureMode: errorSpan.name } : {}),\n } as RunRecord)\n }\n return runs\n}\n\n// ── Internal helpers ────────────────────────────────────────────────\n\nfunction groupSpans(spans: TraceSpanEvent[]): Map<string, TraceSpanEvent[]> {\n const m = new Map<string, TraceSpanEvent[]>()\n for (const span of spans) {\n const key = (span['tangle.runId'] as string | undefined) ?? span.traceId\n const list = m.get(key) ?? []\n list.push(span)\n m.set(key, list)\n }\n return m\n}\n\nfunction findRoot(group: TraceSpanEvent[]): TraceSpanEvent | undefined {\n return group.find((s) => !s.parentSpanId) ?? group[0]\n}\n\nfunction readAttrString(spans: TraceSpanEvent[], keys: string[]): string | undefined {\n for (const span of spans) {\n for (const key of keys) {\n const v = span.attributes[key]\n if (typeof v === 'string' && v.length > 0) return v\n }\n }\n return undefined\n}\n\nfunction readAttrNumber(spans: TraceSpanEvent[], keys: string[]): number | undefined {\n for (const span of spans) {\n for (const key of keys) {\n const v = span.attributes[key]\n if (typeof v === 'number' && Number.isFinite(v)) return v\n if (typeof v === 'string') {\n const parsed = Number(v)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n }\n return undefined\n}\n\nfunction collectNumericAttrs(spans: TraceSpanEvent[]): Record<string, number> {\n const raw: Record<string, number> = {}\n for (const span of spans) {\n for (const [k, v] of Object.entries(span.attributes)) {\n if (typeof v === 'number' && Number.isFinite(v)) raw[k] = v\n }\n }\n return raw\n}\n"],"mappings":"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","names":["cohensD","mean","i","groupSpans"]}
|
|
1
|
+
{"version":3,"sources":["../../src/contract/self-improve.ts","../../src/contract/analyze-runs.ts","../../src/contract/diff.ts","../../src/contract/intake/agent-trace.ts","../../src/contract/intake/feedback-table.ts","../../src/contract/intake/otel-spans.ts"],"sourcesContent":["/**\n * # `selfImprove()` — the LAND-tier one-shot.\n *\n * The cheapest possible call site to run a real closed-loop self-\n * improvement over your agent. Wraps `runImprovementLoop` with smart\n * defaults and a budget-shaped options API; every escape hatch the\n * substrate exposes is reachable from here without losing the\n * one-function feel.\n *\n * Defaults picked to match the LAND-tier story:\n * - In-memory storage (no filesystem touch).\n * - `gepaDriver` reflective mutation with copywriting-flavored primitives\n * (override `driver` or `mutationPrimitives` for any domain).\n * - `defaultProductionGate` with `deltaThreshold: 0.05`.\n * - Held-out split = 25% of scenarios, deterministic by id hash.\n * - 3 generations × population 2 (raise via `budget` for more search).\n * - `autoOnPromote: 'none'` (we don't open PRs unless you ask).\n *\n * Want one-click? Provide `agent` + `scenarios` + `judge`. Done.\n * Want distributed? Pass `cellPlacement` + an `httpDispatch`-backed\n * agent. Want a code-tier surface? Pass a `MutableSurface` + your own\n * `driver`. Same function.\n */\n\nimport { createHash } from 'node:crypto'\nimport { gepaDriver } from '../campaign/drivers/gepa'\nimport { defaultProductionGate } from '../campaign/gates/default-production-gate'\nimport {\n type RunImprovementLoopResult,\n runImprovementLoop,\n} from '../campaign/presets/run-improvement-loop'\nimport {\n emitLoopProvenance,\n type LoopProvenanceRecord,\n surfaceContentHash,\n} from '../campaign/provenance'\nimport {\n type CampaignStorage,\n fsCampaignStorage,\n inMemoryCampaignStorage,\n} from '../campaign/storage'\nimport type {\n CampaignCellResult,\n DispatchContext,\n Gate,\n ImprovementDriver,\n JudgeConfig,\n MutableSurface,\n Scenario,\n} from '../campaign/types'\nimport { createHostedClient, type HostedTenant } from '../hosted/client'\nimport type { EvalRunCellScore, EvalRunEvent, EvalRunGenerationSnapshot } from '../hosted/types'\nimport type { JudgeScoresRecord, RunRecord } from '../run-record'\nimport { analyzeRuns } from './analyze-runs'\nimport type { InsightReport } from './insight-report'\n\nexport interface SelfImproveBudget {\n /** Hard $ ceiling across all cells in baseline + every generation. Cells\n * beyond the ceiling are skipped (cost-aware, not aborted). */\n dollars?: number\n /** How many improvement generations to explore. Default 3. Set 0 to\n * skip improvement entirely (selfImprove becomes a baseline-only run). */\n generations?: number\n /** Candidates the driver proposes per generation. Default 2. */\n populationSize?: number\n /** Max concurrent cells across the loop. Default 2. */\n maxConcurrency?: number\n /** Fraction of `scenarios` held out from training, used for the gate.\n * Default 0.25. Ignored when `holdoutScenarios` is set explicitly. */\n holdoutFraction?: number\n /** Explicit held-out scenarios; overrides `holdoutFraction`. */\n holdoutScenarios?: Scenario[]\n}\n\nexport interface SelfImproveLlm {\n /** Endpoint base URL. Default Tangle Router. */\n baseUrl?: string\n /** Bearer token. Default `process.env.OPENAI_API_KEY`. */\n apiKey?: string\n /** Model id used by `gepaDriver` reflection. Default\n * `anthropic/claude-sonnet-4.6`. */\n model?: string\n}\n\nexport type SelfImproveProgressEvent =\n | { kind: 'baseline.started'; scenarios: number }\n | { kind: 'baseline.completed'; compositeMean: number; durationMs: number }\n | { kind: 'generation.started'; index: number; populationSize: number }\n | { kind: 'generation.completed'; index: number; bestComposite: number; durationMs: number }\n | { kind: 'gate.decided'; decision: string; lift: number }\n\nexport interface SelfImproveOptions<TScenario extends Scenario, TArtifact> {\n /**\n * Your agent — a function that takes the current `MutableSurface`\n * (typically a system prompt the loop is optimizing) plus the\n * scenario + cell ctx, and returns the artifact your judge scores.\n *\n * Same shape as `RunOptimizationOptions.dispatchWithSurface`. Wrap a\n * plain `Dispatch` if you don't have a surface seam:\n *\n * agent: (_surface, scenario, ctx) => yourPlainDispatch(scenario, ctx)\n *\n * That mode evaluates without mutating any surface — useful as a\n * baseline-only run (set `budget.generations = 0`).\n */\n agent: (surface: MutableSurface, scenario: TScenario, ctx: DispatchContext) => Promise<TArtifact>\n\n /** Scenarios to evaluate against. Train/holdout split is computed from\n * these unless `budget.holdoutScenarios` is set explicitly. */\n scenarios: TScenario[]\n\n /** Judge that scores artifacts. Bring your own; use `langchainJudge`\n * from `/adapters/langchain` for a Runnable-shaped one. */\n judge: JudgeConfig<TArtifact, TScenario>\n\n /** Starting surface — system prompt, JSON config, anything `MutableSurface`\n * accepts. The driver mutates this each generation. */\n baselineSurface: MutableSurface\n\n /** Budget + loop shape. All fields optional; defaults pick the LAND-tier\n * story. */\n budget?: SelfImproveBudget\n\n /** Custom driver. Default is `gepaDriver` configured from `llm` +\n * `mutationPrimitives`. */\n driver?: ImprovementDriver\n\n /** Default-driver overrides — used when `driver` is unset. */\n mutationPrimitives?: string[]\n driverTarget?: string\n\n /** Custom gate. Default is `defaultProductionGate` with\n * `deltaThreshold: 0.05` on the held-out split. */\n gate?: Gate<TArtifact, TScenario>\n\n /** LLM config consumed by the default `gepaDriver`. Ignored if you pass\n * your own `driver`. */\n llm?: SelfImproveLlm\n\n /** Storage backend. Default is DURABLE: when a real (non-`mem://`) `runDir`\n * is available, the substrate defaults to `fsCampaignStorage()` so the\n * provenance record + OTel spans survive the call. Pass\n * `inMemoryCampaignStorage()` explicitly to opt OUT (tests, edge runtimes).\n * Default when `runDir` is `mem://...` (or unset): in-memory. */\n storage?: CampaignStorage\n\n /** Run directory (logical for in-memory storage, real path for fs).\n * Default `mem://selfImprove-<timestamp>` (in-memory, non-durable). Pass a\n * real path to persist the provenance record + spans. */\n runDir?: string\n\n /**\n * Worker call records for backend provenance. The agent is opaque to the\n * substrate (it returns an artifact, not token usage), so to capture an\n * `assertRealBackend`-grade verdict + worker call count + model in the\n * provenance record, the agent reports its per-call `RunRecord`s here.\n * Called once after the loop; return the records the agent accumulated.\n * When unset, backend provenance is derived from campaign cells (cost only;\n * verdict will read `stub` without token usage — the honest signal that no\n * token channel was wired).\n */\n collectWorkerRecords?: () => RunRecord[]\n\n /** Fires once the durable provenance record + OTel spans are emitted.\n * Receives the structured record for inline assertions / custom routing. */\n onProvenance?: (record: LoopProvenanceRecord) => void\n\n /** Distributed-driver seam — same as `RunCampaignOptions.cellPlacement`.\n * Returns an opaque placement key the substrate forwards to your agent\n * as `ctx.placement`. Combined with `httpDispatch` from\n * `/adapters/http`, fans cells across regions. */\n cellPlacement?: (input: {\n scenario: TScenario\n rep: number\n generation?: number\n }) => string | undefined\n\n /** Streaming hook — fires on baseline + each generation + gate decision.\n * Consumer routes events wherever (UI, dashboard, logs). */\n onProgress?: (event: SelfImproveProgressEvent) => void\n\n /** Auto-promotion behavior on a ship decision. Default `'none'` — we\n * return the winner; you ship it however you ship. `'pr'` opens a\n * GitHub PR via `openAutoPr`; requires `ghOwner` + `ghRepo`. */\n autoOnPromote?: 'pr' | 'none'\n ghOwner?: string\n ghRepo?: string\n\n /**\n * Opt-in: ship eval-run events to a hosted orchestrator (ours, your\n * self-hosted one, or any compatible implementation of the\n * `docs/hosted-ingest-spec.md` wire format). When set, the substrate\n * POSTs the final `EvalRunEvent` to `${endpoint}/v1/ingest/eval-runs`\n * after the loop completes. Failures are logged but do not fail the\n * loop — local result is always returned.\n *\n * For our orchestrator: `{ endpoint: 'https://orchestrator.tangle.tools/v1', apiKey, tenantId }`.\n *\n * For your self-hosted: any URL serving the wire format. See\n * `examples/hosted-ingest-server/` for the reference receiver.\n */\n hostedTenant?: HostedTenant\n\n /** Free-form labels attached to the hosted event (env, branch, model id,\n * etc.). Ignored when `hostedTenant` is unset. */\n hostedLabels?: Record<string, string>\n}\n\nexport interface SelfImproveResult<TScenario extends Scenario, TArtifact> {\n /** Composite mean across all scenarios, baseline run. */\n baseline: {\n compositeMean: number\n perScenario: Record<string, number>\n }\n /** Composite mean on the held-out set, winner run. */\n winner: {\n compositeMean: number\n perScenario: Record<string, number>\n surface: MutableSurface\n /** Driver label for the promoted change. Absent ⇒ winner == baseline or\n * a bare-surface mutator. */\n label?: string\n /** Driver rationale — the \"because Z\" that motivated the promoted change.\n * Threaded from the driver's `ProposedCandidate` through the loop.\n * Absent ⇒ winner == baseline. */\n rationale?: string\n }\n /** `winner.compositeMean - baselineOnHoldout.compositeMean`. Positive\n * means the gate observed improvement. */\n lift: number\n /** The explicit baseline→winner unified diff. Always present (empty string\n * when winner == baseline). */\n diff: string\n /** Durable, queryable provenance record: candidate→cell→gate→promote chain +\n * rationale + diff + backend provenance. The artifact the hosted ingest\n * path stores; the +lift RECOMPUTES from `record.heldOutLift`. */\n provenance: LoopProvenanceRecord\n /** `defaultProductionGate.decide()` result. */\n gateDecision: 'ship' | 'hold' | 'need_more_work' | 'model_ceiling' | 'arch_ceiling'\n /** Number of generations actually explored (may be less than the\n * budget if the driver gave up early). */\n generationsExplored: number\n /** Wall-clock total. */\n durationMs: number\n /** Total cost across baseline + every generation. */\n totalCostUsd: number\n /**\n * Rigor packet: distributional summary, paired-bootstrap lift CI,\n * judge stats, contamination check, recommendations. Wired through\n * `analyzeRuns()` on the baseline + winner cells of the campaign.\n * Hosted-tier dashboards render this as the v3-vs-v4 decision view.\n */\n insight: InsightReport\n /**\n * Raw substrate result for advanced inspection — full per-generation\n * candidates, full campaign artifacts, all judge scores. Useful for\n * debugging or reporting beyond the summary.\n */\n raw: RunImprovementLoopResult<TArtifact, TScenario>\n}\n\n/**\n * Deterministic train/holdout split by a stable hash of `scenario.id`,\n * so the same scenario set always splits the same way across runs.\n */\nfunction splitTrainHoldout<TScenario extends Scenario>(\n scenarios: TScenario[],\n fraction: number,\n): { train: TScenario[]; holdout: TScenario[] } {\n // Stable fnv-1a-ish hash of the id for ordering.\n function hash(s: string): number {\n let h = 2166136261 >>> 0\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 16777619) >>> 0\n }\n return h\n }\n const sorted = [...scenarios].sort((a, b) => hash(a.id) - hash(b.id))\n const nHoldout = Math.max(1, Math.min(sorted.length - 1, Math.round(sorted.length * fraction)))\n return {\n holdout: sorted.slice(0, nHoldout),\n train: sorted.slice(nHoldout),\n }\n}\n\nfunction meanComposite(byScenario: Record<string, { meanComposite: number }>): {\n compositeMean: number\n perScenario: Record<string, number>\n} {\n const perScenario: Record<string, number> = {}\n const values: number[] = []\n for (const [id, agg] of Object.entries(byScenario)) {\n perScenario[id] = agg.meanComposite\n values.push(agg.meanComposite)\n }\n return {\n compositeMean: values.length === 0 ? 0 : values.reduce((s, v) => s + v, 0) / values.length,\n perScenario,\n }\n}\n\nconst DEFAULT_MUTATION_PRIMITIVES = [\n 'Tighten the hook: lead with the specific user outcome.',\n 'Replace generic adjectives with specific verbs or proof numbers.',\n \"Anchor every claim in something the scenario's brief literally supports.\",\n 'Honor the surface-shape constraint (length, register, audience vocabulary).',\n]\n\n/**\n * One-shot self-improvement loop. See module docstring for defaults +\n * extension points.\n *\n * @example Minimum (LAND tier):\n *\n * const result = await selfImprove({\n * agent: (surface, scenario, ctx) => myAgent(surface, scenario, ctx.signal),\n * scenarios,\n * judge,\n * baselineSurface: DEFAULT_PROMPT,\n * })\n * console.log(`lift: ${result.lift.toFixed(3)} (${result.gateDecision})`)\n *\n * @example Distributed (workers in three regions):\n *\n * await selfImprove({\n * agent: httpDispatch({ resolveUrl: ({ placement }) => REGION_URLS[placement!] }),\n * scenarios,\n * judge,\n * baselineSurface: DEFAULT_PROMPT,\n * cellPlacement: ({ scenario }) => scenario.region,\n * budget: { maxConcurrency: 12 },\n * })\n */\nexport async function selfImprove<TScenario extends Scenario, TArtifact>(\n opts: SelfImproveOptions<TScenario, TArtifact>,\n): Promise<SelfImproveResult<TScenario, TArtifact>> {\n const startedAt = Date.now()\n\n const budget = opts.budget ?? {}\n const generations = budget.generations ?? 3\n const populationSize = budget.populationSize ?? 2\n const maxConcurrency = budget.maxConcurrency ?? 2\n const holdoutFraction = budget.holdoutFraction ?? 0.25\n const costCeiling = budget.dollars\n\n const explicitHoldout = budget.holdoutScenarios\n const { train, holdout } = explicitHoldout\n ? {\n train: opts.scenarios.filter((s) => !explicitHoldout.some((h) => h.id === s.id)),\n holdout: explicitHoldout as TScenario[],\n }\n : splitTrainHoldout(opts.scenarios, holdoutFraction)\n\n if (train.length === 0) {\n throw new Error(\n 'selfImprove: train split is empty. Reduce holdoutFraction or pass more scenarios.',\n )\n }\n if (holdout.length === 0) {\n throw new Error('selfImprove: holdout split is empty. Pass more scenarios.')\n }\n\n const driver: ImprovementDriver =\n opts.driver ??\n gepaDriver({\n llm: {\n baseUrl: opts.llm?.baseUrl ?? 'https://router.tangle.tools/v1',\n apiKey: opts.llm?.apiKey ?? process.env.OPENAI_API_KEY ?? '',\n },\n model: opts.llm?.model ?? 'anthropic/claude-sonnet-4.6',\n target:\n opts.driverTarget ??\n 'agent surface (system prompt or config) being optimized by selfImprove',\n mutationPrimitives: opts.mutationPrimitives ?? DEFAULT_MUTATION_PRIMITIVES,\n })\n\n const gate: Gate<TArtifact, TScenario> =\n opts.gate ??\n defaultProductionGate<TArtifact, TScenario>({\n holdoutScenarios: holdout,\n deltaThreshold: 0.05,\n })\n\n // Durable by default: a real (non-`mem://`) runDir means the caller wants\n // persistence, so default to fs storage — the provenance record + spans\n // survive the call. A `mem://` runDir (or none) stays in-memory. An explicit\n // `storage` always wins (the opt-out path for tests / edge runtimes).\n const runDir = opts.runDir ?? `mem://selfImprove-${startedAt}`\n const isMemRunDir = runDir.startsWith('mem://')\n const storage = opts.storage ?? (isMemRunDir ? inMemoryCampaignStorage() : fsCampaignStorage())\n\n if (opts.onProgress) {\n opts.onProgress({ kind: 'baseline.started', scenarios: opts.scenarios.length })\n }\n\n const result = await runImprovementLoop<TScenario, TArtifact>({\n scenarios: train,\n baselineSurface: opts.baselineSurface,\n dispatchWithSurface: opts.agent,\n driver,\n judges: [opts.judge],\n populationSize,\n maxGenerations: generations,\n holdoutScenarios: holdout,\n gate,\n autoOnPromote: opts.autoOnPromote ?? 'none',\n ghOwner: opts.ghOwner,\n ghRepo: opts.ghRepo,\n storage,\n runDir,\n maxConcurrency,\n cellPlacement: opts.cellPlacement,\n costCeiling,\n })\n\n const baseline = meanComposite(result.baselineOnHoldout.aggregates.byScenario)\n const winnerStats = meanComposite(result.winnerOnHoldout.aggregates.byScenario)\n\n if (opts.onProgress) {\n opts.onProgress({\n kind: 'baseline.completed',\n compositeMean: baseline.compositeMean,\n durationMs: Date.now() - startedAt,\n })\n opts.onProgress({\n kind: 'gate.decided',\n decision: result.gateResult.decision,\n lift: winnerStats.compositeMean - baseline.compositeMean,\n })\n }\n\n const totalCost =\n result.baselineCampaign.aggregates.totalCostUsd +\n result.generations.reduce(\n (sum, gen) =>\n sum + gen.surfaces.reduce((s, sf) => s + sf.campaign.aggregates.totalCostUsd, 0),\n 0,\n )\n\n // Rigor packet: feed baseline + winner cells through analyzeRuns().\n // The two candidates (`baseline` / `winner`) give the lift section a\n // clean paired comparison; per-judge / per-dimension / cost-quality\n // sections populate from the cells' judgeScores.\n const insight = await analyzeRuns({\n runs: [\n ...cellsToRunRecords(result.baselineCampaign.cells, 'baseline', runDir, opts.baselineSurface),\n ...cellsToRunRecords(result.winnerOnHoldout.cells, 'winner', runDir, result.winnerSurface),\n ],\n baselineCandidateId: 'baseline',\n candidateCandidateId: 'winner',\n })\n\n // ── Durable provenance: candidate→cell→gate→promote chain + rationale +\n // diff + backend provenance. Always emitted; the +lift recomputes from it.\n const durationMs = Date.now() - startedAt\n const workerRecords =\n opts.collectWorkerRecords?.() ??\n cellsToRunRecords(result.winnerOnHoldout.cells, 'winner', runDir, result.winnerSurface)\n const { record: provenance } = await emitLoopProvenance<TArtifact, TScenario>({\n runId: `${runDir}#${startedAt}`,\n runDir,\n timestamp: new Date(startedAt).toISOString(),\n baselineSurface: opts.baselineSurface,\n winnerSurface: result.winnerSurface,\n winnerLabel: result.winnerLabel,\n winnerRationale: result.winnerRationale,\n diff: result.promotedDiff,\n generations: result.generations.map((g) => ({\n generationIndex: g.record.generationIndex,\n candidates: g.record.candidates,\n promoted: g.record.promoted,\n surfaces: g.surfaces.map((s) => ({ surfaceHash: s.surfaceHash, surface: s.surface })),\n })),\n gate: result.gateResult,\n baselineOnHoldout: result.baselineOnHoldout,\n winnerOnHoldout: result.winnerOnHoldout,\n workerRecords,\n totalCostUsd: totalCost,\n totalDurationMs: durationMs,\n storage,\n hostedClient: opts.hostedTenant ? createHostedClient(opts.hostedTenant) : undefined,\n })\n if (opts.onProvenance) opts.onProvenance(provenance)\n\n const summary: SelfImproveResult<TScenario, TArtifact> = {\n baseline,\n winner: {\n ...winnerStats,\n surface: result.winnerSurface,\n ...(result.winnerLabel ? { label: result.winnerLabel } : {}),\n ...(result.winnerRationale ? { rationale: result.winnerRationale } : {}),\n },\n lift: winnerStats.compositeMean - baseline.compositeMean,\n diff: result.promotedDiff,\n provenance,\n gateDecision: result.gateResult.decision,\n generationsExplored: result.generations.length,\n durationMs,\n totalCostUsd: totalCost,\n insight,\n raw: result,\n }\n\n // Opt-in hosted ingest. Failures logged but never fail the loop — the\n // local result is always returned. This matches the wedge-doc invariant\n // that LAND-tier never blocks on EXPAND-tier infra.\n if (opts.hostedTenant) {\n try {\n await shipEvalRunToHosted(opts.hostedTenant, opts, summary, result, runDir)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // eslint-disable-next-line no-console -- intentional: hosted-ingest is best-effort\n console.warn(`[agent-eval] hosted ingest failed (continuing): ${msg}`)\n }\n }\n\n return summary\n}\n\nasync function shipEvalRunToHosted<TScenario extends Scenario, TArtifact>(\n tenant: HostedTenant,\n opts: SelfImproveOptions<TScenario, TArtifact>,\n summary: SelfImproveResult<TScenario, TArtifact>,\n raw: RunImprovementLoopResult<TArtifact, TScenario>,\n runDir: string,\n): Promise<void> {\n const client = createHostedClient(tenant)\n\n function snapshotFromCampaign(\n index: number,\n surface: MutableSurface | undefined,\n campaign: RunImprovementLoopResult<TArtifact, TScenario>['baselineCampaign'],\n durationMs: number,\n ): EvalRunGenerationSnapshot {\n const cells: EvalRunCellScore[] = campaign.cells.map((cell) => {\n const judgeScores = Object.values(cell.judgeScores)\n const composite =\n judgeScores.length === 0\n ? 0\n : judgeScores.reduce((s, j) => s + j.composite, 0) / judgeScores.length\n return {\n scenarioId: cell.scenarioId,\n rep: cell.rep,\n compositeMean: composite,\n dimensions: Object.fromEntries(\n Object.entries(cell.judgeScores).map(([name, score]) => [name, score.dimensions]),\n ),\n errorMessage: cell.error ?? undefined,\n }\n })\n const compositeMean =\n cells.length === 0 ? 0 : cells.reduce((s, c) => s + c.compositeMean, 0) / cells.length\n return {\n index,\n surfaceHash:\n typeof surface === 'string'\n ? hashString(surface)\n : hashString(JSON.stringify(surface ?? '')),\n surface,\n cells,\n compositeMean,\n costUsd: campaign.aggregates.totalCostUsd,\n durationMs,\n }\n }\n\n const generations: EvalRunGenerationSnapshot[] = []\n // Baseline as generation 0.\n generations.push(snapshotFromCampaign(0, opts.baselineSurface, raw.baselineCampaign, 0))\n // Improvement generations as 1..N. Substrate stores per-surface campaigns\n // per generation — we summarize the WINNING surface per generation here.\n for (const gen of raw.generations) {\n const winner = gen.surfaces.reduce(\n (best, s) =>\n s.campaign.aggregates.cellsExecuted > 0 &&\n (best === undefined || averageComposite(s.campaign) > averageComposite(best.campaign))\n ? s\n : best,\n gen.surfaces[0],\n )\n if (!winner) continue\n generations.push(\n snapshotFromCampaign(gen.record.generationIndex + 1, winner.surface, winner.campaign, 0),\n )\n }\n\n const event: EvalRunEvent = {\n runId: `${runDir}#${Date.now()}`,\n runDir,\n timestamp: new Date().toISOString(),\n status: 'finished',\n labels: opts.hostedLabels ?? {},\n baseline: generations[0],\n generations,\n gateDecision: summary.gateDecision,\n holdoutLift: summary.lift,\n totalCostUsd: summary.totalCostUsd,\n totalDurationMs: summary.durationMs,\n insightReport: summary.insight,\n }\n\n await client.ingestEvalRun(event)\n}\n\nfunction averageComposite(\n campaign: RunImprovementLoopResult<unknown, Scenario>['baselineCampaign'],\n): number {\n const aggs = Object.values(campaign.aggregates.byScenario)\n return aggs.length === 0 ? 0 : aggs.reduce((s, a) => s + a.meanComposite, 0) / aggs.length\n}\n\nfunction hashString(s: string): string {\n let h = 2166136261 >>> 0\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i)\n h = Math.imul(h, 16777619) >>> 0\n }\n return h.toString(16).padStart(8, '0')\n}\n\n/**\n * Adapt campaign cells into the `RunRecord` shape `analyzeRuns()` consumes.\n * Each cell becomes one run; `candidateId` is the caller-supplied label so\n * baseline + winner pair cleanly on `(experimentId, seed)`.\n *\n * `promptHash` is the REAL sha256 content hash of the surface this cell ran\n * (baseline vs winner are byte-distinguishable + byte-identical-verifiable);\n * `configHash` is the sha256 of the candidate label so the two candidates'\n * config rows differ. Both were previously the literal `'sha256:cell'`, which\n * made baseline and winner indistinguishable in every downstream record.\n */\nfunction cellsToRunRecords<TArtifact>(\n cells: ReadonlyArray<CampaignCellResult<TArtifact>>,\n candidateId: 'baseline' | 'winner',\n runId: string,\n surface: MutableSurface,\n): RunRecord[] {\n const promptHash = surfaceContentHash(surface)\n const configHash = `sha256:${createHash('sha256').update(candidateId).digest('hex')}`\n return cells.map((cell) => {\n const perJudge: Record<string, Record<string, number>> = {}\n const perDimMeanAccum: Record<string, { sum: number; n: number }> = {}\n let compositeSum = 0\n let compositeCount = 0\n for (const [judgeId, score] of Object.entries(cell.judgeScores)) {\n perJudge[judgeId] = { ...score.dimensions }\n for (const [dim, value] of Object.entries(score.dimensions)) {\n if (!Number.isFinite(value)) continue\n const accum = perDimMeanAccum[dim] ?? { sum: 0, n: 0 }\n accum.sum += value\n accum.n += 1\n perDimMeanAccum[dim] = accum\n }\n if (Number.isFinite(score.composite)) {\n compositeSum += score.composite\n compositeCount += 1\n }\n }\n const perDimMean: Record<string, number> = {}\n for (const [dim, { sum, n }] of Object.entries(perDimMeanAccum)) {\n perDimMean[dim] = n === 0 ? 0 : sum / n\n }\n const composite = compositeCount === 0 ? 0 : compositeSum / compositeCount\n const judgeScores: JudgeScoresRecord = {\n perJudge,\n perDimMean,\n composite,\n }\n return {\n runId: `${runId}::${candidateId}::${cell.cellId}`,\n experimentId: runId,\n candidateId,\n // Pair on (scenarioId, rep) — analyzeRuns pairs on (experimentId, seed).\n // Synthesize a stable seed for that pairing.\n seed:\n cell.rep * 1_000_000 +\n hashString(cell.scenarioId)\n .slice(0, 6)\n .split('')\n .reduce((a, c) => (a * 31 + c.charCodeAt(0)) >>> 0, 0),\n model: 'campaign-cell',\n promptHash,\n configHash,\n commitSha: 'cell',\n wallMs: cell.durationMs,\n costUsd: cell.costUsd,\n tokenUsage: { input: 0, output: 0 },\n outcome: {\n holdoutScore: composite,\n raw: {},\n judgeScores,\n },\n splitTag: 'holdout',\n ...(cell.error ? { failureMode: cell.error } : {}),\n } satisfies RunRecord\n })\n}\n","/**\n * # `analyzeRuns()` — turn a set of agent runs into an actionable decision packet.\n *\n * Wires the substrate's statistical, calibration, clustering, Pareto, and\n * release-confidence primitives into one `InsightReport`. Two top-level\n * entry points use this function:\n *\n * - `selfImprove()` calls it on the campaign output to attach a packet\n * to every run.\n * - Consumers with observed `RunRecord[]` (production traces, gold\n * corpora, approve/reject tables) call it directly via `analyzeRuns()`\n * for analysis without a closed loop.\n *\n * Every section is opt-in based on what the input data supports — the\n * function never invents signal. If runs carry no judge scores, `judges`\n * is empty. If there's no baseline/candidate split, `lift` is undefined.\n * If no `analyst` is wired, `failureClusters` is undefined.\n *\n * The `recommendations` array is the human-readable layer; everything\n * else is the evidence backing each recommendation.\n */\n\nimport type { AnalystRegistry } from '../analyst/registry'\nimport type { AnalystFinding } from '../analyst/types'\nimport { checkCanaries } from '../contamination-guard'\nimport type { DatasetScenario } from '../dataset'\nimport { summarizeBackendIntegrity } from '../integrity/backend-integrity'\nimport type { RunRecord } from '../run-record'\nimport { cohensD, pairedBootstrap, pairedMde, pairedTTest, requiredSampleSize } from '../statistics'\nimport { type ParetoFigureSpec, paretoChart } from '../summary-report'\n\nimport type {\n FailureClusterInsight,\n FailureModeTally,\n InsightReport,\n InterRaterInsight,\n JudgeInsight,\n LiftInsight,\n MetricDelta,\n OutcomeCorrelationInsight,\n PriorPeriodComparison,\n Recommendation,\n ScalarDistribution,\n} from './insight-report'\n\n// ── Public API ───────────────────────────────────────────────────────\n\nexport interface AnalyzeRunsOptions {\n /** The runs to analyze. */\n runs: RunRecord[]\n /** Which split to score against when reading composite from RunOutcome.\n * Default: holdout when ANY run has a `holdoutScore`, else search. */\n split?: 'search' | 'holdout' | 'auto'\n /** Pairwise analysis configuration. When both `baselineCandidateId` and\n * `candidateCandidateId` are present, lift is computed on paired\n * (experimentId, seed) tuples shared between the two sides. */\n baselineCandidateId?: string\n candidateCandidateId?: string\n /** Canary scenarios — checked against every run's raw output for\n * holdout contamination. */\n canaryScenarios?: DatasetScenario[]\n /** Analyst registry for failure clustering. When omitted, the\n * `failureClusters` section is left undefined. */\n analyst?: AnalystRegistry\n /** Downstream outcome metric per run (e.g. engagement rate, approval\n * rate, downstream pass rate). When present, the report includes\n * `outcomeCorrelation` + a simple linear reward model fit. */\n outcomeSignal?: {\n metric: string\n valueByRunId: Record<string, number>\n }\n /** Multi-rater feedback for inter-rater agreement. Each entry is one\n * rater's score for one run. Two or more raters → kappa + disagreement\n * triage list. */\n raterScores?: Array<{ runId: string; rater: string; score: number }>\n /** Number of histogram bins for distributional summaries. Default 12. */\n histogramBins?: number\n /** Decision threshold — the smallest composite lift the caller cares\n * about. Used by the recommendations engine to call ship vs hold.\n * Default 0.02. */\n decisionThreshold?: number\n /** Optional prior-period runs. When set, the report includes\n * `priorPeriodComparison` with per-metric Welch-CI deltas and\n * recommendations fire on statistically significant regressions.\n * The two windows do NOT have to share scenarios — the comparison\n * is two-sample unpaired (the substrate's `lift` field uses paired\n * bootstrap on shared (experimentId, seed) tuples; this is the\n * shape for \"this week vs last week\" rather than \"candidate vs\n * baseline within a campaign\"). */\n baselineRuns?: RunRecord[]\n /** Human-readable label for the baseline window, e.g. \"vs prior 7\n * days\", \"vs v3.1 release\". Surfaces in recommendations + UI. */\n baselineLabel?: string\n}\n\nexport async function analyzeRuns(opts: AnalyzeRunsOptions): Promise<InsightReport> {\n const runs = opts.runs\n const bins = opts.histogramBins ?? 12\n const threshold = opts.decisionThreshold ?? 0.02\n const split = resolveSplit(runs, opts.split ?? 'auto')\n\n const compositeWithIds = runs\n .map((r) => ({ runId: r.runId, score: compositeOf(r, split) }))\n .filter((p) => Number.isFinite(p.score))\n const composite = distributionOf(\n compositeWithIds.map((p) => p.score),\n bins,\n compositeWithIds,\n )\n\n const perDimension = computePerDimension(runs, bins)\n\n const costs = runs.map((r) => r.costUsd).filter(Number.isFinite)\n const costDist = distributionOf(costs, bins)\n const pareto = paretoChart(runs, { split })\n const degraded: { cost?: string; pareto?: string } = {}\n if (costs.length === 0 || costs.every((c) => c === 0)) {\n degraded.cost = diagnoseZeroCost(runs)\n }\n if (pareto.points.length < 2) {\n degraded.pareto =\n pareto.points.length === 0\n ? 'no candidates — Pareto unavailable'\n : 'single candidate — Pareto is a single point, not a frontier'\n }\n const costQuality = {\n cost: costDist,\n pareto,\n ...(degraded.cost || degraded.pareto ? { degraded } : {}),\n }\n\n const judges = computeJudgeInsights(runs)\n\n const interRater = opts.raterScores ? computeInterRater(opts.raterScores) : undefined\n\n const lift = computeLift(runs, opts.baselineCandidateId, opts.candidateCandidateId, split)\n\n const failureClusters = opts.analyst\n ? await computeFailureClusters(runs, opts.analyst, split)\n : undefined\n\n const failureModes = computeFailureModes(runs)\n\n const contamination = opts.canaryScenarios\n ? computeContamination(runs, opts.canaryScenarios)\n : undefined\n\n const outcomeCorrelation = opts.outcomeSignal\n ? computeOutcomeCorrelation(runs, opts.outcomeSignal, split)\n : undefined\n\n const release = buildReleaseScorecard(composite, lift, contamination)\n\n const priorPeriodComparison = opts.baselineRuns\n ? computePriorPeriodComparison(runs, opts.baselineRuns, split, opts.baselineLabel)\n : undefined\n\n const recommendations = buildRecommendations({\n composite,\n judges,\n interRater,\n lift,\n failureClusters,\n failureModes,\n contamination,\n outcomeCorrelation,\n priorPeriodComparison,\n threshold,\n })\n\n return {\n n: runs.length,\n composite,\n perDimension,\n costQuality,\n judges,\n interRater,\n lift,\n failureClusters,\n contamination,\n outcomeCorrelation,\n release,\n ...(failureModes ? { failureModes } : {}),\n ...(priorPeriodComparison ? { priorPeriodComparison } : {}),\n recommendations,\n }\n}\n\n/** Model-free failure tally. Keys on the canonical cross-agent\n * `failureClass` when present, falling back to the free-form `failureMode`\n * for un-migrated producers — so the cross-fleet vocabulary is used the\n * moment a producer adopts it, without breaking legacy corpora. Returns\n * undefined when no run carries either tag. */\n/** Explain a zero-valued cost axis by its root cause, not just \"no signal\".\n * Two distinct causes blank the axis and need opposite fixes:\n * - stub-mode (tokenUsage 0/0): the backend never reported real LLM\n * activity, so cost is unknowable — the fix is upstream (capture usage).\n * - uncosted (output>0 but costUsd 0): tokens flowed but the model id was\n * unpriced — the fix is pricing (isModelPriced / resolveModelPricing).\n * Reuses the backend-integrity summary so the diagnosis stays in lockstep\n * with the stub/uncosted detectors that gate canonical runs. */\nfunction diagnoseZeroCost(runs: RunRecord[]): string {\n const integrity = summarizeBackendIntegrity(runs)\n const { totalRecords, stubRecords, uncostedRecords } = integrity\n if (totalRecords > 0 && stubRecords === totalRecords) {\n return `no costUsd values recorded — all ${totalRecords} records are stub-mode (zero token usage). The backend never reported real LLM activity, so cost cannot be computed; verify the backend actually ran before trusting this corpus.`\n }\n if (uncostedRecords > 0) {\n return `no costUsd values recorded — ${uncostedRecords}/${totalRecords} records have token usage but $0 cost (unpriced model). Check isModelPriced(model) for the run's model id and add it to FAMILY_PRICING.`\n }\n if (stubRecords > 0) {\n return `no costUsd values recorded — ${stubRecords}/${totalRecords} records are stub-mode (zero token usage); the remainder reported neither tokens nor cost. Cost axis carries no signal.`\n }\n return 'no costUsd values recorded — cost axis carries no signal'\n}\n\nfunction computeFailureModes(runs: RunRecord[]): FailureModeTally[] | undefined {\n const counts = new Map<string, number>()\n for (const r of runs) {\n const key = r.failureClass ?? r.failureMode\n if (key) counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n if (counts.size === 0) return undefined\n const n = runs.length\n return [...counts.entries()]\n .map(([mode, count]) => ({ mode, count, share: n > 0 ? count / n : 0 }))\n .sort((a, b) => b.count - a.count || a.mode.localeCompare(b.mode))\n}\n\n// ── Prior-period comparison ─────────────────────────────────────────\n\n/** Direction of the metric — does \"higher current\" mean better or worse?\n * Composite + judge dimensions: higher is better. Cost + duration: lower\n * is better. The recommendations engine flips the sign before judging\n * regressed vs improved. */\ntype MetricDirection = 'higher-is-better' | 'lower-is-better'\n\nfunction computePriorPeriodComparison(\n current: RunRecord[],\n baseline: RunRecord[],\n split: 'search' | 'holdout',\n windowLabel: string | undefined,\n): PriorPeriodComparison | undefined {\n if (current.length === 0 || baseline.length === 0) return undefined\n\n const metrics: Record<string, MetricDelta> = {}\n const directions: Record<string, MetricDirection> = {}\n\n const compositeCurrent = current\n .map((r) => compositeOf(r, split))\n .filter(Number.isFinite) as number[]\n const compositeBaseline = baseline\n .map((r) => compositeOf(r, split))\n .filter(Number.isFinite) as number[]\n if (compositeCurrent.length > 0 && compositeBaseline.length > 0) {\n metrics.composite = welchCompare(compositeBaseline, compositeCurrent)\n directions.composite = 'higher-is-better'\n }\n\n const costCurrent = current.map((r) => r.costUsd).filter(Number.isFinite)\n const costBaseline = baseline.map((r) => r.costUsd).filter(Number.isFinite)\n if (costCurrent.length > 0 && costBaseline.length > 0) {\n metrics.cost = welchCompare(costBaseline, costCurrent)\n directions.cost = 'lower-is-better'\n }\n\n const durCurrent = current.map((r) => r.wallMs).filter(Number.isFinite)\n const durBaseline = baseline.map((r) => r.wallMs).filter(Number.isFinite)\n if (durCurrent.length > 0 && durBaseline.length > 0) {\n metrics.duration = welchCompare(durBaseline, durCurrent)\n directions.duration = 'lower-is-better'\n }\n\n const tokCurrent = current\n .map((r) => (r.tokenUsage.input ?? 0) + (r.tokenUsage.output ?? 0))\n .filter(Number.isFinite)\n const tokBaseline = baseline\n .map((r) => (r.tokenUsage.input ?? 0) + (r.tokenUsage.output ?? 0))\n .filter(Number.isFinite)\n if (tokCurrent.length > 0 && tokBaseline.length > 0) {\n metrics.tokenUsage = welchCompare(tokBaseline, tokCurrent)\n directions.tokenUsage = 'lower-is-better'\n }\n\n // Per-dimension judge comparisons — only for dimensions present in BOTH\n // windows. We use perDimMean since per-judge nesting is finicky for\n // two-sample comparisons across different judge configurations.\n const dimsCurrent = collectPerDimension(current)\n const dimsBaseline = collectPerDimension(baseline)\n for (const dim of Object.keys(dimsCurrent)) {\n const b = dimsBaseline[dim]\n const c = dimsCurrent[dim]\n if (!b || b.length === 0 || !c || c.length === 0) continue\n metrics[`dim.${dim}`] = welchCompare(b, c)\n directions[`dim.${dim}`] = 'higher-is-better'\n }\n\n const regressedMetrics: string[] = []\n const improvedMetrics: string[] = []\n for (const [name, delta] of Object.entries(metrics)) {\n if (!delta.significant) continue\n const dir = directions[name] ?? 'higher-is-better'\n const better = dir === 'higher-is-better' ? delta.delta > 0 : delta.delta < 0\n if (better) improvedMetrics.push(name)\n else regressedMetrics.push(name)\n }\n\n return {\n baselineN: baseline.length,\n currentN: current.length,\n ...(windowLabel ? { windowLabel } : {}),\n metrics,\n regressedMetrics,\n improvedMetrics,\n }\n}\n\n/** Collect per-dimension values across runs (from outcome.judgeScores.perDimMean). */\nfunction collectPerDimension(runs: RunRecord[]): Record<string, number[]> {\n const out: Record<string, number[]> = {}\n for (const r of runs) {\n const perDim = r.outcome.judgeScores?.perDimMean\n if (!perDim) continue\n for (const [dim, value] of Object.entries(perDim)) {\n if (!Number.isFinite(value)) continue\n if (!out[dim]) out[dim] = []\n out[dim].push(value as number)\n }\n }\n return out\n}\n\n/** Two-sample Welch comparison: unequal-variance t-test + CI on the delta\n * + Cohen's d (pooled stddev). Significance = p < 0.05 AND |d| >= 0.2. */\nfunction welchCompare(baseline: number[], current: number[]): MetricDelta {\n const baselineMean = mean(baseline)\n const currentMean = mean(current)\n const baselineVar = sampleVariance(baseline, baselineMean)\n const currentVar = sampleVariance(current, currentMean)\n const baselineN = baseline.length\n const currentN = current.length\n const delta = currentMean - baselineMean\n\n // Welch standard error\n const se = Math.sqrt(baselineVar / baselineN + currentVar / currentN)\n // For 95% CI we use z=1.96 (large-n approximation). Customers running\n // analyzeRuns will typically have n >= 30; the t-correction is\n // negligible vs the practical noise floor.\n const halfWidth = 1.96 * (se > 0 ? se : 0)\n const ci95: [number, number] = [delta - halfWidth, delta + halfWidth]\n\n // p-value via normal approximation to the t-statistic.\n const t = se > 0 ? delta / se : 0\n const pValue = se > 0 ? 2 * (1 - standardNormalCdf(Math.abs(t))) : 1\n\n // Cohen's d — pooled stddev.\n const pooledStddev = Math.sqrt(\n ((baselineN - 1) * baselineVar + (currentN - 1) * currentVar) /\n Math.max(1, baselineN + currentN - 2),\n )\n const cohensD = pooledStddev > 0 ? delta / pooledStddev : 0\n\n // Significance: BOTH p < 0.05 AND |d| >= 0.2 (small-effect threshold).\n const significant = pValue < 0.05 && Math.abs(cohensD) >= 0.2\n\n return {\n current: currentMean,\n baseline: baselineMean,\n delta,\n ci95,\n pValue,\n cohensD,\n baselineN,\n currentN,\n significant,\n }\n}\n\nfunction sampleVariance(xs: number[], xsMean: number): number {\n if (xs.length < 2) return 0\n let s = 0\n for (const x of xs) s += (x - xsMean) ** 2\n return s / (xs.length - 1)\n}\n\n/** Abramowitz & Stegun approximation to Φ(z). Maximum error ~7.5e-8. */\nfunction standardNormalCdf(z: number): number {\n const a1 = 0.254829592\n const a2 = -0.284496736\n const a3 = 1.421413741\n const a4 = -1.453152027\n const a5 = 1.061405429\n const p = 0.3275911\n const sign = z < 0 ? -1 : 1\n const x = Math.abs(z) / Math.SQRT2\n const t = 1 / (1 + p * x)\n const y = 1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-x * x)\n return 0.5 * (1 + sign * y)\n}\n\n// ── Composite + split selection ─────────────────────────────────────\n\nfunction resolveSplit(\n runs: RunRecord[],\n pref: 'search' | 'holdout' | 'auto',\n): 'search' | 'holdout' {\n if (pref !== 'auto') return pref\n const hasHoldout = runs.some((r) => Number.isFinite(r.outcome.holdoutScore))\n return hasHoldout ? 'holdout' : 'search'\n}\n\nfunction compositeOf(run: RunRecord, split: 'search' | 'holdout'): number {\n const primary = split === 'holdout' ? run.outcome.holdoutScore : run.outcome.searchScore\n if (Number.isFinite(primary)) return primary as number\n // Fall through to the other split if the preferred one is missing —\n // analyzeRuns shouldn't refuse to summarise a run just because the\n // caller asked for the split that wasn't recorded.\n const alt = split === 'holdout' ? run.outcome.searchScore : run.outcome.holdoutScore\n return Number.isFinite(alt) ? (alt as number) : Number.NaN\n}\n\n// ── Distribution helpers ────────────────────────────────────────────\n\nfunction distributionOf(\n values: number[],\n bins: number,\n withIds?: Array<{ runId: string; score: number }>,\n): ScalarDistribution {\n if (values.length === 0) {\n return {\n n: 0,\n mean: 0,\n p50: 0,\n p95: 0,\n stddev: 0,\n min: 0,\n max: 0,\n histogram: [],\n }\n }\n const sorted = [...values].sort((a, b) => a - b)\n const n = sorted.length\n const mean = sorted.reduce((s, v) => s + v, 0) / n\n const variance = sorted.reduce((s, v) => s + (v - mean) ** 2, 0) / n\n const stddev = Math.sqrt(variance)\n const tailRuns = withIds\n ? [...withIds].sort((a, b) => a.score - b.score).slice(0, Math.min(5, withIds.length))\n : undefined\n return {\n n,\n mean,\n p50: percentile(sorted, 0.5),\n p95: percentile(sorted, 0.95),\n stddev,\n min: sorted[0]!,\n max: sorted[n - 1]!,\n histogram: histogram(sorted, bins),\n ...(tailRuns ? { tailRuns } : {}),\n }\n}\n\nfunction percentile(sorted: number[], q: number): number {\n if (sorted.length === 0) return 0\n if (sorted.length === 1) return sorted[0]!\n const idx = (sorted.length - 1) * q\n const lo = Math.floor(idx)\n const hi = Math.ceil(idx)\n if (lo === hi) return sorted[lo]!\n const w = idx - lo\n return sorted[lo]! * (1 - w) + sorted[hi]! * w\n}\n\n/** Even-width histogram over the value range. Returns inclusive-lo /\n * exclusive-hi bins (closed on right for the last bin) compatible with\n * the substrate's `GainDistributionBin` shape. */\nfunction histogram(sorted: number[], bins: number): ScalarDistribution['histogram'] {\n if (sorted.length === 0 || bins < 1) return []\n const min = sorted[0]!\n const max = sorted[sorted.length - 1]!\n if (min === max) return [{ lo: min, hi: max, count: sorted.length }]\n const width = (max - min) / bins\n const out: ScalarDistribution['histogram'] = []\n for (let i = 0; i < bins; i++) {\n const lo = min + i * width\n const hi = i === bins - 1 ? max : lo + width\n out.push({ lo, hi, count: 0 })\n }\n for (const v of sorted) {\n const idx = Math.min(bins - 1, Math.floor((v - min) / width))\n out[idx]!.count++\n }\n return out\n}\n\nfunction computePerDimension(runs: RunRecord[], bins: number): Record<string, ScalarDistribution> {\n // JudgeScoresRecord pre-aggregates `perDimMean` (mean across judges per\n // dimension). We collect those means across runs to produce a per-dim\n // distribution at the corpus level. Consumers who want per-judge\n // dimension values reach into `perJudge[judgeId][dim]` themselves.\n const byDim = new Map<string, number[]>()\n for (const run of runs) {\n const scores = run.outcome.judgeScores\n if (!scores) continue\n for (const [dim, value] of Object.entries(scores.perDimMean ?? {})) {\n if (!Number.isFinite(value)) continue\n const arr = byDim.get(dim) ?? []\n arr.push(value)\n byDim.set(dim, arr)\n }\n }\n const out: Record<string, ScalarDistribution> = {}\n for (const [dim, values] of byDim) out[dim] = distributionOf(values, bins)\n return out\n}\n\n// ── Judge insights ──────────────────────────────────────────────────\n\nfunction computeJudgeInsights(runs: RunRecord[]): Record<string, JudgeInsight> {\n // Each judge's per-run mean is the average of its per-dimension scores\n // for that run. We aggregate those means across all runs each judge\n // scored — giving consumers a \"this judge's typical verdict\" reading.\n const out: Record<string, JudgeInsight> = {}\n const byJudge = new Map<string, number[]>()\n for (const run of runs) {\n const scores = run.outcome.judgeScores\n if (!scores?.perJudge) continue\n for (const [judgeId, dims] of Object.entries(scores.perJudge)) {\n const dimValues = Object.values(dims).filter(Number.isFinite) as number[]\n if (dimValues.length === 0) continue\n const judgeMean = dimValues.reduce((s, v) => s + v, 0) / dimValues.length\n const arr = byJudge.get(judgeId) ?? []\n arr.push(judgeMean)\n byJudge.set(judgeId, arr)\n }\n }\n for (const [judgeId, values] of byJudge) {\n out[judgeId] = {\n n: values.length,\n meanScore: values.reduce((s, v) => s + v, 0) / values.length,\n }\n }\n return out\n}\n\n// ── Inter-rater agreement ───────────────────────────────────────────\n\nfunction computeInterRater(\n ratings: Array<{ runId: string; rater: string; score: number }>,\n): InterRaterInsight | undefined {\n const byRun = new Map<string, Array<{ rater: string; score: number }>>()\n for (const r of ratings) {\n if (!Number.isFinite(r.score)) continue\n const list = byRun.get(r.runId) ?? []\n list.push({ rater: r.rater, score: r.score })\n byRun.set(r.runId, list)\n }\n const raters = new Set(ratings.map((r) => r.rater))\n const jointlyRated: string[] = []\n for (const [runId, ratersForRun] of byRun) {\n const seen = new Set(ratersForRun.map((r) => r.rater))\n let all = true\n for (const r of raters) if (!seen.has(r)) all = false\n if (all) jointlyRated.push(runId)\n }\n if (raters.size < 2 || jointlyRated.length === 0) return undefined\n\n const raterList = [...raters].sort()\n const perPair: Record<string, number> = {}\n for (let i = 0; i < raterList.length; i++) {\n for (let j = i + 1; j < raterList.length; j++) {\n const a = raterList[i]!\n const b = raterList[j]!\n const aScores: number[] = []\n const bScores: number[] = []\n for (const runId of jointlyRated) {\n const ratersForRun = byRun.get(runId)!\n const sa = ratersForRun.find((r) => r.rater === a)?.score\n const sb = ratersForRun.find((r) => r.rater === b)?.score\n if (sa !== undefined && sb !== undefined) {\n aScores.push(sa)\n bScores.push(sb)\n }\n }\n perPair[`${a}::${b}`] = pearson(aScores, bScores)\n }\n }\n const pairKappas = Object.values(perPair)\n const kappa =\n pairKappas.length === 0 ? 0 : pairKappas.reduce((s, v) => s + v, 0) / pairKappas.length\n\n const disagreementCases = jointlyRated\n .map((runId) => {\n const ratersForRun = byRun.get(runId)!\n const scores = ratersForRun.map((r) => r.score)\n const range = Math.max(...scores) - Math.min(...scores)\n return { runId, ratings: ratersForRun, range }\n })\n .sort((a, b) => b.range - a.range)\n .slice(0, 20)\n\n return {\n raters: raters.size,\n jointlyRated: jointlyRated.length,\n kappa,\n perPair,\n disagreementCases,\n }\n}\n\nfunction pearson(a: number[], b: number[]): number {\n if (a.length !== b.length || a.length === 0) return 0\n const n = a.length\n const meanA = a.reduce((s, v) => s + v, 0) / n\n const meanB = b.reduce((s, v) => s + v, 0) / n\n let num = 0\n let denomA = 0\n let denomB = 0\n for (let i = 0; i < n; i++) {\n const da = a[i]! - meanA\n const db = b[i]! - meanB\n num += da * db\n denomA += da * da\n denomB += db * db\n }\n const denom = Math.sqrt(denomA * denomB)\n return denom === 0 ? 0 : num / denom\n}\n\n// ── Lift ────────────────────────────────────────────────────────────\n\nfunction computeLift(\n runs: RunRecord[],\n baselineId: string | undefined,\n candidateId: string | undefined,\n split: 'search' | 'holdout',\n): LiftInsight | undefined {\n let bId = baselineId\n let cId = candidateId\n if (!bId || !cId) {\n // Auto-detect: when exactly two distinct candidateIds appear, treat the\n // lower-mean side as baseline.\n const ids = [...new Set(runs.map((r) => r.candidateId))]\n if (ids.length !== 2) return undefined\n const [idA, idB] = ids as [string, string]\n const meanA = mean(runs.filter((r) => r.candidateId === idA).map((r) => compositeOf(r, split)))\n const meanB = mean(runs.filter((r) => r.candidateId === idB).map((r) => compositeOf(r, split)))\n bId = meanA <= meanB ? idA : idB\n cId = meanA <= meanB ? idB : idA\n }\n\n const baseline = runs.filter((r) => r.candidateId === bId)\n const candidate = runs.filter((r) => r.candidateId === cId)\n if (baseline.length === 0 || candidate.length === 0) return undefined\n\n // Pair on (experimentId, seed). When that key doesn't match, fall back\n // to ordinal pairing — common for fresh runs from the same scenario list.\n const baselineByKey = new Map(baseline.map((r) => [pairingKey(r), r]))\n const pairedBaseline: number[] = []\n const pairedCandidate: number[] = []\n let usedKeyPairing = false\n for (const cand of candidate) {\n const b = baselineByKey.get(pairingKey(cand))\n if (b) {\n const bC = compositeOf(b, split)\n const cC = compositeOf(cand, split)\n if (Number.isFinite(bC) && Number.isFinite(cC)) {\n pairedBaseline.push(bC)\n pairedCandidate.push(cC)\n usedKeyPairing = true\n }\n }\n }\n if (!usedKeyPairing) {\n const n = Math.min(baseline.length, candidate.length)\n for (let i = 0; i < n; i++) {\n const bC = compositeOf(baseline[i]!, split)\n const cC = compositeOf(candidate[i]!, split)\n if (Number.isFinite(bC) && Number.isFinite(cC)) {\n pairedBaseline.push(bC)\n pairedCandidate.push(cC)\n }\n }\n }\n if (pairedBaseline.length === 0) return undefined\n\n const baselineMean = mean(pairedBaseline)\n const candidateMean = mean(pairedCandidate)\n const delta = candidateMean - baselineMean\n\n const bootstrap = pairedBootstrap(pairedBaseline, pairedCandidate, {\n confidence: 0.95,\n resamples: 2000,\n statistic: 'mean',\n })\n const tTest = pairedTTest(pairedBaseline, pairedCandidate)\n const d = cohensD(pairedBaseline, pairedCandidate)\n const mde = pairedMde({ nPaired: pairedBaseline.length, power: 0.8, alpha: 0.05 })\n const requiredN = requiredSampleSize({\n effect: Math.max(Math.abs(delta), 1e-6),\n power: 0.8,\n alpha: 0.05,\n })\n\n return {\n baselineMean,\n candidateMean,\n delta,\n ci95: [bootstrap.low, bootstrap.high],\n pValue: tTest.p,\n n: pairedBaseline.length,\n cohensD: d,\n mde,\n requiredN,\n }\n}\n\nfunction pairingKey(r: RunRecord): string {\n return `${r.experimentId}::${r.seed}`\n}\n\nfunction mean(arr: number[]): number {\n return arr.length === 0 ? 0 : arr.reduce((s, v) => s + v, 0) / arr.length\n}\n\n// ── Failure clustering ──────────────────────────────────────────────\n\nasync function computeFailureClusters(\n runs: RunRecord[],\n analyst: AnalystRegistry,\n split: 'search' | 'holdout',\n): Promise<FailureClusterInsight | undefined> {\n const failed = runs.filter((r) => compositeOf(r, split) < 0.5 || r.failureMode !== undefined)\n if (failed.length === 0) return { clusters: [], totalFailures: 0 }\n\n const clusters = new Map<string, { exemplars: string[]; share: number }>()\n for (const run of failed) {\n try {\n const result = await analyst.run(run.runId, {\n kind: 'run-record',\n run,\n } as Parameters<typeof analyst.run>[1])\n for (const finding of result.findings as AnalystFinding[]) {\n const key = finding.area || finding.analyst_id || 'unclassified'\n const c = clusters.get(key) ?? { exemplars: [], share: 0 }\n if (c.exemplars.length < 5) c.exemplars.push(run.runId)\n clusters.set(key, c)\n }\n } catch {\n const c = clusters.get('analyst-error') ?? { exemplars: [], share: 0 }\n if (c.exemplars.length < 5) c.exemplars.push(run.runId)\n clusters.set('analyst-error', c)\n }\n }\n const clusterList = [...clusters.entries()].map(([id, c]) => ({\n id,\n name: id,\n share: c.exemplars.length / failed.length,\n exemplars: c.exemplars,\n }))\n clusterList.sort((a, b) => b.share - a.share)\n return { clusters: clusterList, totalFailures: failed.length }\n}\n\n// ── Contamination ──────────────────────────────────────────────────\n\nfunction computeContamination(\n runs: RunRecord[],\n canaries: DatasetScenario[],\n): InsightReport['contamination'] {\n let leaks = 0\n const details: Array<{ runId: string; canary: string; matched: string }> = []\n for (const run of runs) {\n const output = stringifyOutput(run)\n if (!output) continue\n const leaksHere = checkCanaries(output, canaries)\n for (const leak of leaksHere) {\n leaks++\n details.push({ runId: run.runId, canary: leak.canary, matched: leak.evidence })\n }\n }\n return { leaks, holdoutAuditPassed: leaks === 0, details }\n}\n\nfunction stringifyOutput(run: RunRecord): string | undefined {\n // RunRecord doesn't fix where \"the agent's output\" lives — different\n // consumers stash it differently. We probe the common shapes: the\n // outcome.raw map (numeric only by design — unlikely to contain text),\n // and any string-valued fields tucked under metadata via type casting.\n // Consumers with bespoke shapes pass canaryScenarios only when they\n // know their runs carry a stringifiable surface.\n const metadata = (run as unknown as { metadata?: Record<string, unknown> }).metadata\n if (typeof metadata?.output === 'string') return metadata.output\n if (typeof metadata?.text === 'string') return metadata.text\n return undefined\n}\n\n// ── Outcome correlation + linear reward model ──────────────────────\n\nfunction computeOutcomeCorrelation(\n runs: RunRecord[],\n outcome: { metric: string; valueByRunId: Record<string, number> },\n split: 'search' | 'holdout',\n): OutcomeCorrelationInsight | undefined {\n const xs: number[] = []\n const ys: number[] = []\n for (const run of runs) {\n const y = outcome.valueByRunId[run.runId]\n if (y === undefined || !Number.isFinite(y)) continue\n const x = compositeOf(run, split)\n if (!Number.isFinite(x)) continue\n xs.push(x)\n ys.push(y)\n }\n if (xs.length < 3) return undefined\n\n const p = pearson(xs, ys)\n const s = spearman(xs, ys)\n const meanX = mean(xs)\n const meanY = mean(ys)\n let num = 0\n let denom = 0\n for (let i = 0; i < xs.length; i++) {\n num += (xs[i]! - meanX) * (ys[i]! - meanY)\n denom += (xs[i]! - meanX) ** 2\n }\n const slope = denom === 0 ? 0 : num / denom\n const intercept = meanY - slope * meanX\n const ssTot = ys.reduce((a, y) => a + (y - meanY) ** 2, 0)\n const ssRes = ys.reduce((a, y, i) => a + (y - (intercept + slope * xs[i]!)) ** 2, 0)\n const r2 = ssTot === 0 ? 0 : 1 - ssRes / ssTot\n\n return {\n metric: outcome.metric,\n n: xs.length,\n pearson: p,\n spearman: s,\n rewardModel: { intercept, slope, r2 },\n }\n}\n\nfunction spearman(a: number[], b: number[]): number {\n if (a.length !== b.length || a.length === 0) return 0\n return pearson(rank(a), rank(b))\n}\n\nfunction rank(arr: number[]): number[] {\n const indexed = arr.map((v, i) => ({ v, i }))\n indexed.sort((x, y) => x.v - y.v)\n const ranks = new Array(arr.length).fill(0)\n let i = 0\n while (i < indexed.length) {\n let j = i\n while (j + 1 < indexed.length && indexed[j + 1]!.v === indexed[i]!.v) j++\n const avg = (i + j + 2) / 2\n for (let k = i; k <= j; k++) ranks[indexed[k]!.i] = avg\n i = j + 1\n }\n return ranks\n}\n\n// ── Release confidence scorecard ───────────────────────────────────\n\nfunction buildReleaseScorecard(\n composite: ScalarDistribution,\n lift: LiftInsight | undefined,\n contamination: InsightReport['contamination'],\n): InsightReport['release'] {\n // Synthesise a minimal scorecard from the rolled-up signal. The\n // substrate's `evaluateReleaseConfidence` primitive consumes a richer\n // input shape that callers can produce by wiring SLO definitions; the\n // shape here is the contract `selfImprove`/`analyzeRuns` consumers\n // receive automatically. They can call `evaluateReleaseConfidence`\n // directly when they want SLO-based axis evaluation.\n const axes: InsightReport['release']['axes'] = []\n const liftPass =\n lift === undefined || lift.ci95[0] > 0\n ? ('pass' as const)\n : lift.delta > 0\n ? ('warn' as const)\n : ('fail' as const)\n axes.push({\n name: 'quality-lift',\n status: liftPass,\n detail: lift\n ? `delta=${lift.delta.toFixed(3)}, CI95=[${lift.ci95[0].toFixed(3)}, ${lift.ci95[1].toFixed(3)}], n=${lift.n}`\n : 'no baseline/candidate pair available',\n })\n const contamPass =\n contamination === undefined || contamination.leaks === 0 ? ('pass' as const) : ('fail' as const)\n axes.push({\n name: 'contamination',\n status: contamPass,\n detail: contamination ? `${contamination.leaks} canary leak(s)` : 'no canaries supplied',\n })\n axes.push({\n name: 'composite-distribution',\n status: composite.mean >= 0.5 ? 'pass' : composite.mean >= 0.3 ? 'warn' : 'fail',\n detail: `mean=${composite.mean.toFixed(3)}, p50=${composite.p50.toFixed(3)}, p95=${composite.p95.toFixed(3)} over n=${composite.n}`,\n })\n const status = axes.some((a) => a.status === 'fail')\n ? 'fail'\n : axes.some((a) => a.status === 'warn')\n ? 'warn'\n : 'pass'\n return {\n status,\n axes,\n issues: [],\n }\n}\n\n// ── Recommendations engine ─────────────────────────────────────────\n\ninterface RecommendationContext {\n composite: ScalarDistribution\n judges: Record<string, JudgeInsight>\n interRater?: InterRaterInsight\n lift?: LiftInsight\n failureClusters?: FailureClusterInsight\n failureModes?: FailureModeTally[]\n contamination?: InsightReport['contamination']\n outcomeCorrelation?: OutcomeCorrelationInsight\n priorPeriodComparison?: PriorPeriodComparison\n threshold: number\n}\n\nfunction buildRecommendations(ctx: RecommendationContext): Recommendation[] {\n const out: Recommendation[] = []\n\n // Prior-period regressions — highest customer-impact signal when present.\n // \"Did my last change help?\" with a falsifiable answer.\n if (ctx.priorPeriodComparison) {\n const ppc = ctx.priorPeriodComparison\n const label = ppc.windowLabel ?? 'baseline period'\n for (const name of ppc.regressedMetrics) {\n const d = ppc.metrics[name]\n if (!d) continue\n out.push({\n priority: 'critical',\n kind: 'investigate',\n title: `${name} regressed from ${d.baseline.toFixed(3)} → ${d.current.toFixed(3)} vs ${label}`,\n detail: `Welch CI95 = [${d.ci95[0].toFixed(3)}, ${d.ci95[1].toFixed(3)}], p=${d.pValue.toFixed(4)}, Cohen's d=${d.cohensD.toFixed(2)} (n_current=${d.currentN}, n_baseline=${d.baselineN}). The regression is statistically significant at p<0.05 with at-least-small effect size.`,\n evidencePath: `priorPeriodComparison.metrics.${name}`,\n })\n }\n for (const name of ppc.improvedMetrics) {\n const d = ppc.metrics[name]\n if (!d) continue\n out.push({\n priority: 'low',\n kind: 'ship',\n title: `${name} improved from ${d.baseline.toFixed(3)} → ${d.current.toFixed(3)} vs ${label}`,\n detail: `Welch CI95 = [${d.ci95[0].toFixed(3)}, ${d.ci95[1].toFixed(3)}], p=${d.pValue.toFixed(4)}, Cohen's d=${d.cohensD.toFixed(2)} (n_current=${d.currentN}, n_baseline=${d.baselineN}). Statistically significant improvement worth flagging.`,\n evidencePath: `priorPeriodComparison.metrics.${name}`,\n })\n }\n }\n\n // Composite-distribution branch. Fires when the overall quality signal is\n // poor regardless of lift / contamination / clusters — the customer needs\n // to know they have a problem AND which specific runs to inspect.\n if (ctx.composite.n > 0) {\n if (ctx.composite.mean < 0.3) {\n const tail = ctx.composite.tailRuns ?? []\n const names = tail\n .slice(0, 5)\n .map((t) => `${t.runId}=${t.score.toFixed(3)}`)\n .join(', ')\n out.push({\n priority: 'critical',\n kind: 'investigate',\n title: `Composite mean ${ctx.composite.mean.toFixed(3)} is below the 0.3 floor — the agent is broken on this corpus`,\n detail:\n tail.length > 0\n ? `Worst ${tail.length} run${tail.length === 1 ? '' : 's'} to inspect first: ${names}. Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`\n : `Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`,\n evidencePath: 'composite.tailRuns',\n })\n } else if (ctx.composite.mean < 0.5) {\n const tail = ctx.composite.tailRuns ?? []\n const names = tail\n .slice(0, 3)\n .map((t) => `${t.runId}=${t.score.toFixed(3)}`)\n .join(', ')\n out.push({\n priority: 'high',\n kind: 'investigate',\n title: `Composite mean ${ctx.composite.mean.toFixed(3)} is below 0.5 — investigate the lower tail before claiming the agent is healthy`,\n detail:\n tail.length > 0\n ? `Worst ${tail.length} run${tail.length === 1 ? '' : 's'}: ${names}. Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`\n : `Histogram p50=${ctx.composite.p50.toFixed(3)}, p95=${ctx.composite.p95.toFixed(3)}.`,\n evidencePath: 'composite.tailRuns',\n })\n }\n }\n\n // Dominant-failure-mode branch (model-free). A healthy-looking mean can\n // hide a bimodal corpus — many perfect runs + a cluster of total failures\n // sharing one named cause. Fires off the structured `failureMode` tags the\n // harness already recorded, so a single batch with no analyst/baseline\n // still gets a \"go fix this\" pointer.\n if (ctx.failureModes && ctx.failureModes.length > 0) {\n const top = ctx.failureModes[0]!\n if (top.count >= 3 && top.share >= 0.15) {\n out.push({\n priority: top.share >= 0.25 ? 'high' : 'medium',\n kind: 'investigate',\n title: `'${top.mode}' is the dominant failure mode — ${top.count} runs (${(top.share * 100).toFixed(0)}% of the corpus)`,\n detail: `The mean composite can look acceptable while one named failure dominates the lower tail. ${top.count} of ${ctx.composite.n} runs failed with '${top.mode}'${ctx.failureModes.length > 1 ? ` (next: '${ctx.failureModes[1]!.mode}' ×${ctx.failureModes[1]!.count})` : ''}. Fix this cause first.`,\n evidencePath: 'failureModes',\n })\n }\n }\n\n // Missing-judges branch. The report can't surface per-dimension or\n // calibration signal when `outcome.judgeScores` is empty across the\n // corpus. Tell the customer how to enrich.\n if (Object.keys(ctx.judges).length === 0 && ctx.composite.n > 0) {\n out.push({\n priority: 'medium',\n kind: 'expand-corpus',\n title: 'No judge scores recorded — per-dimension + calibration insights unavailable',\n detail:\n 'Records have no `outcome.judgeScores`. To unlock perDimension, judges, and calibration, attach a Judge run during your eval pass and populate `outcome.judgeScores.perJudge[judgeName][dimension] = score`. See `docs/insight-report.md` for the expected shape.',\n evidencePath: 'judges',\n })\n }\n\n if (ctx.lift) {\n const decisive = ctx.lift.ci95[0] > ctx.threshold\n const inconclusive = ctx.lift.ci95[0] <= ctx.threshold && ctx.lift.ci95[1] > ctx.threshold\n if (decisive) {\n out.push({\n priority: 'critical',\n kind: 'ship',\n title: `Ship — lift ${ctx.lift.delta.toFixed(3)} (95% CI ${ctx.lift.ci95[0].toFixed(3)}..${ctx.lift.ci95[1].toFixed(3)})`,\n detail: `Holdout lift exceeds threshold ${ctx.threshold} with 95% bootstrap confidence (n=${ctx.lift.n}, p=${ctx.lift.pValue.toFixed(4)}, d=${ctx.lift.cohensD.toFixed(2)}).`,\n evidencePath: 'lift',\n })\n } else if (inconclusive) {\n out.push({\n priority: 'high',\n kind: 'expand-corpus',\n title: `Inconclusive — need ~${ctx.lift.requiredN} paired runs (have ${ctx.lift.n}) at current effect size`,\n detail: `CI straddles threshold. Current MDE at 80% power is ${ctx.lift.mde.toFixed(3)}; observed delta is ${ctx.lift.delta.toFixed(3)}.`,\n evidencePath: 'lift',\n })\n } else {\n out.push({\n priority: 'critical',\n kind: 'hold',\n title: `Hold — lift CI lower bound ${ctx.lift.ci95[0].toFixed(3)} is at or below threshold ${ctx.threshold}`,\n detail: `Bootstrap CI provides no statistical evidence the candidate is better. Consider tightening the mutation or expanding the holdout.`,\n evidencePath: 'lift',\n })\n }\n }\n\n if (ctx.contamination && ctx.contamination.leaks > 0) {\n out.push({\n priority: 'critical',\n kind: 'fix',\n title: `${ctx.contamination.leaks} canary leak${ctx.contamination.leaks === 1 ? '' : 's'} detected`,\n detail: `Holdout integrity is compromised. The lift number is unreliable until you investigate.`,\n evidencePath: 'contamination',\n })\n }\n\n if (ctx.interRater && ctx.interRater.kappa < 0.5) {\n out.push({\n priority: 'high',\n kind: 'recalibrate',\n title: `Inter-rater agreement κ=${ctx.interRater.kappa.toFixed(2)} is below 0.5`,\n detail: `Raters disagree on what 'good' looks like. Top disagreement cases listed in interRater.disagreementCases — consider a triage meeting or refining the rubric.`,\n evidencePath: 'interRater',\n })\n }\n\n if (ctx.failureClusters && ctx.failureClusters.clusters.length > 0) {\n const top = ctx.failureClusters.clusters[0]!\n out.push({\n priority: 'high',\n kind: 'investigate',\n title: `Top failure cluster: ${top.name} (${(top.share * 100).toFixed(0)}% of failures)`,\n detail: `${ctx.failureClusters.totalFailures} runs failed. The largest cluster groups ${top.exemplars.length} exemplars under '${top.name}'.`,\n evidencePath: 'failureClusters.clusters[0]',\n })\n }\n\n if (ctx.outcomeCorrelation && Math.abs(ctx.outcomeCorrelation.spearman) < 0.3) {\n out.push({\n priority: 'medium',\n kind: 'recalibrate',\n title: `Judge scores decoupled from ${ctx.outcomeCorrelation.metric} (Spearman ρ=${ctx.outcomeCorrelation.spearman.toFixed(2)})`,\n detail: `Your judges score what they were trained to score, but it isn't predicting downstream ${ctx.outcomeCorrelation.metric}. Consider retraining the judge against ${ctx.outcomeCorrelation.metric} as the gold signal.`,\n evidencePath: 'outcomeCorrelation',\n })\n }\n\n return out\n}\n\n// ── Re-export pareto figure spec for hosted-side rendering ─────────\n\nexport type { ParetoFigureSpec }\n","/**\n * # `@tangle-network/agent-eval/contract` — eval-run diff primitive.\n *\n * The substrate side of the v-N-versus-v-N+1 dashboard view. Given two\n * `EvalRunEvent`s (or two `EvalRunGenerationSnapshot`s from one run), this\n * returns a normalised diff: per-cell composite + per-judge/per-dimension\n * deltas, surface-hash change, aggregate cost + duration shifts.\n *\n * Consumed by:\n * - The hosted-tier dashboard (intelligence-web) — renders v3 vs v4\n * comparisons of cells × judges × dimensions.\n * - CI reporting — emits a \"shipped: composite +0.07, cost +$1.20\" line\n * in PR review for autonomous-improvement runs.\n * - Any downstream consumer that needs \"what actually changed\" without\n * reimplementing the matching + arithmetic.\n *\n * Cells are matched on the natural composite key `(scenarioId, rep)`.\n * Unmatched cells surface as `removed` / `added` so callers can tell\n * \"this cell got worse\" from \"this cell wasn't run.\"\n */\n\nimport type { GateDecision } from '../campaign/types'\nimport type { EvalRunCellScore, EvalRunEvent, EvalRunGenerationSnapshot } from '../hosted/types'\n\n// ── Types ────────────────────────────────────────────────────────────\n\n/** Per-dimension delta. `before` / `after` are null when the judge did not\n * emit a value for that side. `delta` is `after - before`; null when\n * either side is null. */\nexport interface EvalDimensionDelta {\n before: number | null\n after: number | null\n delta: number | null\n}\n\n/** Per-cell delta, keyed on `(scenarioId, rep)`. */\nexport interface EvalCellScoreDelta {\n scenarioId: string\n rep: number\n compositeBefore: number\n compositeAfter: number\n compositeDelta: number\n /** Per-judge → per-dimension deltas. Outer key = judge name from\n * `EvalRunCellScore.dimensions`; inner key = dimension name. */\n dimensions: Record<string, Record<string, EvalDimensionDelta>>\n}\n\n/** Diff between two generation snapshots — the unit the dashboard renders\n * for a single \"v3 vs v4\" comparison. */\nexport interface EvalGenerationDiff {\n beforeIndex: number\n afterIndex: number\n beforeSurfaceHash: string\n afterSurfaceHash: string\n surfaceChanged: boolean\n /** Cells present in both snapshots, matched on `(scenarioId, rep)`. */\n matched: EvalCellScoreDelta[]\n /** Cells present in `before` but missing from `after`. */\n removed: EvalRunCellScore[]\n /** Cells present in `after` but missing from `before`. */\n added: EvalRunCellScore[]\n /** Aggregate composite mean across all cells in the snapshot. */\n compositeBefore: number\n compositeAfter: number\n compositeDelta: number\n costUsdBefore: number\n costUsdAfter: number\n costUsdDelta: number\n durationMsBefore: number\n durationMsAfter: number\n durationMsDelta: number\n}\n\n/** Diff between two full eval-runs. Includes both baseline-vs-baseline and\n * winner-vs-winner generation diffs when both sides expose them, plus\n * run-level metadata. */\nexport interface EvalRunDiff {\n beforeRunId: string\n afterRunId: string\n beforeTimestamp: string\n afterTimestamp: string\n beforeGateDecision: GateDecision | null\n afterGateDecision: GateDecision | null\n beforeHoldoutLift: number | null\n afterHoldoutLift: number | null\n holdoutLiftDelta: number | null\n beforeTotalCostUsd: number\n afterTotalCostUsd: number\n totalCostUsdDelta: number\n beforeTotalDurationMs: number\n afterTotalDurationMs: number\n totalDurationMsDelta: number\n /** Baseline-vs-baseline diff. Null when either run has no baseline. */\n baselineDiff: EvalGenerationDiff | null\n /** Highest-index-generation comparison. Null when either run has no\n * recorded generations (e.g. baseline-only or errored before any\n * generation completed). */\n winnersDiff: EvalGenerationDiff | null\n}\n\n// ── Implementation ───────────────────────────────────────────────────\n\nfunction keyForCell(cell: EvalRunCellScore): string {\n // JSON-tuple key — `scenarioId` may legitimately contain `::` or any other\n // delimiter, so we use JSON.stringify on a 2-tuple to get an unambiguous,\n // collision-free composite key.\n return JSON.stringify([cell.scenarioId, cell.rep])\n}\n\n/** Build the per-dimension delta map for a matched cell. Each judge name +\n * dimension name encountered on EITHER side appears in the result. */\nfunction diffDimensions(\n before: EvalRunCellScore['dimensions'],\n after: EvalRunCellScore['dimensions'],\n): EvalCellScoreDelta['dimensions'] {\n const out: EvalCellScoreDelta['dimensions'] = {}\n const judges = new Set<string>([...Object.keys(before), ...Object.keys(after)])\n for (const judge of judges) {\n const beforeDims = before[judge] ?? {}\n const afterDims = after[judge] ?? {}\n const dims = new Set<string>([...Object.keys(beforeDims), ...Object.keys(afterDims)])\n const judgeOut: Record<string, EvalDimensionDelta> = {}\n for (const dim of dims) {\n // Coerce non-finite values (NaN, ±Infinity) to null so the diff never\n // surfaces NaN/Infinity to the dashboard. A NaN score is a substrate\n // bug from upstream; the diff treats it as \"no value\" rather than\n // propagating the corruption.\n const rawBefore = beforeDims[dim]\n const rawAfter = afterDims[dim]\n const b = typeof rawBefore === 'number' && Number.isFinite(rawBefore) ? rawBefore : null\n const a = typeof rawAfter === 'number' && Number.isFinite(rawAfter) ? rawAfter : null\n judgeOut[dim] = {\n before: b,\n after: a,\n delta: b !== null && a !== null ? a - b : null,\n }\n }\n out[judge] = judgeOut\n }\n return out\n}\n\n/**\n * Diff two generation snapshots. Cells are matched on `(scenarioId, rep)`;\n * unmatched cells surface in `added` / `removed`. Aggregate fields are\n * recomputed from the snapshot's stored fields, not re-derived from cells —\n * this keeps the diff consistent with whatever aggregation the substrate\n * actually reported.\n */\nexport function diffGenerations(\n before: EvalRunGenerationSnapshot,\n after: EvalRunGenerationSnapshot,\n): EvalGenerationDiff {\n const beforeMap = new Map(before.cells.map((c) => [keyForCell(c), c]))\n const afterMap = new Map(after.cells.map((c) => [keyForCell(c), c]))\n\n const matched: EvalCellScoreDelta[] = []\n const removed: EvalRunCellScore[] = []\n const added: EvalRunCellScore[] = []\n\n for (const [key, beforeCell] of beforeMap) {\n const afterCell = afterMap.get(key)\n if (!afterCell) {\n removed.push(beforeCell)\n continue\n }\n matched.push({\n scenarioId: beforeCell.scenarioId,\n rep: beforeCell.rep,\n compositeBefore: beforeCell.compositeMean,\n compositeAfter: afterCell.compositeMean,\n compositeDelta: afterCell.compositeMean - beforeCell.compositeMean,\n dimensions: diffDimensions(beforeCell.dimensions, afterCell.dimensions),\n })\n }\n for (const [key, afterCell] of afterMap) {\n if (!beforeMap.has(key)) added.push(afterCell)\n }\n\n return {\n beforeIndex: before.index,\n afterIndex: after.index,\n beforeSurfaceHash: before.surfaceHash,\n afterSurfaceHash: after.surfaceHash,\n surfaceChanged: before.surfaceHash !== after.surfaceHash,\n matched,\n removed,\n added,\n compositeBefore: before.compositeMean,\n compositeAfter: after.compositeMean,\n compositeDelta: after.compositeMean - before.compositeMean,\n costUsdBefore: before.costUsd,\n costUsdAfter: after.costUsd,\n costUsdDelta: after.costUsd - before.costUsd,\n durationMsBefore: before.durationMs,\n durationMsAfter: after.durationMs,\n durationMsDelta: after.durationMs - before.durationMs,\n }\n}\n\n/** Highest-index generation, or null if the run recorded none. */\nfunction winnerOf(run: EvalRunEvent): EvalRunGenerationSnapshot | null {\n if (run.generations.length === 0) return null\n let winner = run.generations[0] as EvalRunGenerationSnapshot\n for (const gen of run.generations) {\n if (gen.index > winner.index) winner = gen\n }\n return winner\n}\n\n/**\n * Diff two full eval-runs. Produces baseline-vs-baseline and\n * winner-vs-winner generation diffs when both sides expose them, plus\n * run-level cost / lift / gate-decision deltas.\n */\nexport function diffRuns(before: EvalRunEvent, after: EvalRunEvent): EvalRunDiff {\n const beforeWinner = winnerOf(before)\n const afterWinner = winnerOf(after)\n const baselineDiff =\n before.baseline && after.baseline ? diffGenerations(before.baseline, after.baseline) : null\n const winnersDiff =\n beforeWinner && afterWinner ? diffGenerations(beforeWinner, afterWinner) : null\n\n const beforeLift = before.holdoutLift ?? null\n const afterLift = after.holdoutLift ?? null\n\n return {\n beforeRunId: before.runId,\n afterRunId: after.runId,\n beforeTimestamp: before.timestamp,\n afterTimestamp: after.timestamp,\n beforeGateDecision: before.gateDecision ?? null,\n afterGateDecision: after.gateDecision ?? null,\n beforeHoldoutLift: beforeLift,\n afterHoldoutLift: afterLift,\n holdoutLiftDelta: beforeLift !== null && afterLift !== null ? afterLift - beforeLift : null,\n beforeTotalCostUsd: before.totalCostUsd,\n afterTotalCostUsd: after.totalCostUsd,\n totalCostUsdDelta: after.totalCostUsd - before.totalCostUsd,\n beforeTotalDurationMs: before.totalDurationMs,\n afterTotalDurationMs: after.totalDurationMs,\n totalDurationMsDelta: after.totalDurationMs - before.totalDurationMs,\n baselineDiff,\n winnersDiff,\n }\n}\n\n/**\n * Within-run baseline → winning-generation diff. The natural \"what did the\n * improvement loop produce\" view for a single run. Returns null when the\n * run never reached a generation past baseline (errored early, or the gate\n * shipped the baseline as-is).\n */\nexport function diffRunBaselineToWinner(run: EvalRunEvent): EvalGenerationDiff | null {\n if (!run.baseline) return null\n const winner = winnerOf(run)\n if (!winner || winner.index === run.baseline.index) return null\n return diffGenerations(run.baseline, winner)\n}\n","/**\n * `fromAgentTrace` — provenance correlation from Cursor's Agent Trace spec\n * (https://github.com/cursor/agent-trace, RFC v0.1.0).\n *\n * Agent Trace is NOT a run/quality trace — it carries no outcome, score, or\n * cost. It records *code authorship*: for a VCS revision, which AI model /\n * conversation authored which file ranges. It explicitly disclaims quality\n * assessment — which is exactly what `analyzeRuns` adds.\n *\n * The two layers join on a key the substrate already has: a `RunRecord`\n * carries `commitSha`, and an Agent Trace record is keyed by\n * `vcs.revision`. So this adapter does not produce `RunRecord`s — it builds a\n * provenance index by commit and partitions existing runs by their authoring\n * model. Feed each cohort to `analyzeRuns` (or pass one as `baselineRuns`) to\n * answer the question no run-only trace can: *which authoring agent's code\n * fails / regresses / costs more.*\n *\n * Granularity is commit-level (the SHA join). Per-file/per-line correlation\n * would require runs to record which files they exercised — out of scope.\n */\n\nimport type { RunRecord } from '../../run-record'\n\n// ── Agent Trace record schema (the subset we read) ──────────────────────────\n\nexport type AgentTraceContributorType = 'human' | 'ai' | 'mixed' | 'unknown'\n\nexport interface AgentTraceContributor {\n type: AgentTraceContributorType\n /** models.dev id, e.g. `anthropic/claude-opus-4-5-20251101`. */\n model_id?: string\n}\n\nexport interface AgentTraceRange {\n start_line: number\n end_line: number\n content_hash?: string\n /** Per-range contributor override (agent handoffs). Wins over the\n * conversation-level contributor for these lines. */\n contributor?: AgentTraceContributor\n}\n\nexport interface AgentTraceConversation {\n url?: string\n contributor?: AgentTraceContributor\n ranges: AgentTraceRange[]\n}\n\nexport interface AgentTraceFile {\n path: string\n conversations: AgentTraceConversation[]\n}\n\nexport interface AgentTraceRecord {\n version: string\n id: string\n timestamp: string\n vcs?: { type: string; revision: string }\n tool?: { name?: string; version?: string }\n files: AgentTraceFile[]\n}\n\n// ── Provenance index ─────────────────────────────────────────────────────────\n\n/** Authorship provenance for one VCS revision, aggregated across the record's\n * files/conversations/ranges. */\nexport interface AuthoringProvenance {\n commitSha: string\n /** Unique AI model ids that authored code in this commit (type ai|mixed). */\n aiModels: string[]\n /** Tools that produced the records (e.g. `cursor`). */\n tools: string[]\n conversationCount: number\n fileCount: number\n /** Total attributed lines (sum of range spans). */\n lineCount: number\n /** True if any range was authored (in whole or part) by a human. */\n humanInvolved: boolean\n}\n\nexport type AgentTraceIndex = Map<string, AuthoringProvenance>\n\nfunction rangeLines(r: AgentTraceRange): number {\n return Math.max(0, r.end_line - r.start_line + 1)\n}\n\n/**\n * Build a commit → provenance index from Agent Trace records. Multiple records\n * for the same revision are merged. Records without `vcs.revision` are skipped\n * (the SHA is the join key — without it there is nothing to correlate against).\n */\nexport function parseAgentTrace(records: AgentTraceRecord[]): AgentTraceIndex {\n interface Acc {\n models: Set<string>\n tools: Set<string>\n files: Set<string>\n conversationCount: number\n lineCount: number\n humanInvolved: boolean\n }\n const acc = new Map<string, Acc>()\n\n for (const record of records) {\n const sha = record.vcs?.revision\n if (!sha) continue // the SHA is the join key — nothing to correlate without it\n\n let a = acc.get(sha)\n if (!a) {\n a = {\n models: new Set(),\n tools: new Set(),\n files: new Set(),\n conversationCount: 0,\n lineCount: 0,\n humanInvolved: false,\n }\n acc.set(sha, a)\n }\n\n if (record.tool?.name) a.tools.add(record.tool.name)\n\n for (const file of record.files ?? []) {\n a.files.add(file.path)\n for (const conv of file.conversations ?? []) {\n a.conversationCount += 1\n for (const range of conv.ranges ?? []) {\n // Per-range contributor wins, else the conversation contributor.\n const contributor = range.contributor ?? conv.contributor\n a.lineCount += rangeLines(range)\n if (!contributor) continue\n if (contributor.type === 'human' || contributor.type === 'mixed') {\n a.humanInvolved = true\n }\n if ((contributor.type === 'ai' || contributor.type === 'mixed') && contributor.model_id) {\n a.models.add(contributor.model_id)\n }\n }\n }\n }\n }\n\n const index: AgentTraceIndex = new Map()\n for (const [sha, a] of acc) {\n index.set(sha, {\n commitSha: sha,\n aiModels: [...a.models].sort(),\n tools: [...a.tools].sort(),\n conversationCount: a.conversationCount,\n fileCount: a.files.size,\n lineCount: a.lineCount,\n humanInvolved: a.humanInvolved,\n })\n }\n return index\n}\n\n// ── Run ↔ provenance join ──────────────────────────────────────────────────\n\nexport interface PartitionByAuthoringModelResult {\n /** Runs grouped by each AI model that authored code in the run's commit. A\n * run whose commit had multiple authoring models appears under EACH — the\n * cohorts overlap by construction at commit granularity. */\n byModel: Map<string, RunRecord[]>\n /** Runs whose `commitSha` had no Agent Trace provenance (no record, or no\n * AI authorship). Kept separate — never silently folded into a cohort. */\n unattributed: RunRecord[]\n}\n\n/**\n * Partition runs by the AI model(s) that authored the code at each run's\n * `commitSha`. Feed `byModel.get(modelId)` to `analyzeRuns`, or compare two\n * model cohorts via `analyzeRuns({ runs: a, baselineRuns: b })` for a lift CI\n * on \"model A's code vs model B's code\".\n */\nexport function partitionRunsByAuthoringModel(\n runs: RunRecord[],\n index: AgentTraceIndex,\n): PartitionByAuthoringModelResult {\n const byModel = new Map<string, RunRecord[]>()\n const unattributed: RunRecord[] = []\n\n for (const run of runs) {\n const provenance = index.get(run.commitSha)\n if (!provenance || provenance.aiModels.length === 0) {\n unattributed.push(run)\n continue\n }\n for (const model of provenance.aiModels) {\n const cohort = byModel.get(model) ?? []\n cohort.push(run)\n byModel.set(model, cohort)\n }\n }\n\n return { byModel, unattributed }\n}\n","/**\n * # `intake/feedback-table` — multi-rater approve/reject corpus → `RunRecord[]`.\n *\n * The generic shape behind Obsidian's `#approved` / `#rejected` tags, a\n * Google Sheet, a Postgres `feedback` table, or any CSV with ratings.\n *\n * Caller supplies one row per (run, rater) tuple plus per-run metadata; the\n * adapter rolls them up into the substrate-canonical `RunRecord` shape so\n * `analyzeRuns({ runs, raterScores })` can produce inter-rater agreement,\n * disagreement triage, and downstream recommendations.\n *\n * Per-run `RunRecord.outcome.searchScore` is the rater-mean rating\n * (normalised to 0..1 when scale is supplied); `outcome.raw` carries the\n * per-rater scores keyed by rater id for downstream attribution.\n */\n\nimport type { JudgeScoresRecord, RunOutcome, RunRecord, RunSplitTag } from '../../run-record'\n\nexport interface FeedbackTableRow {\n /** Stable id for this run — the unit a rater scored. Drives pairing\n * across analysis primitives. */\n runId: string\n /** Identifier of the rater that produced this rating. */\n rater: string\n /** The rating itself. Accepts boolean (approve/reject), 0..1 scalar,\n * or any numeric scale — see `scale`. */\n rating: number | boolean\n /** Optional metadata carried through to `RunRecord.outcome.raw` and the\n * custom-shape metadata bag. */\n metadata?: Record<string, unknown>\n}\n\nexport interface FeedbackTableMeta {\n runId: string\n /** When omitted, defaults to `'feedback-corpus'`. Used to group related\n * runs in `analyzeRuns()` lift analysis. */\n experimentId?: string\n /** When omitted, defaults to `runId` — each run is its own candidate. */\n candidateId?: string\n /** Cost in USD, when available. Set to 0 when unknown — the consumer's\n * cost analysis sections will collapse gracefully. */\n costUsd?: number\n /** Wall-clock ms, when available. Defaults to 0. */\n wallMs?: number\n /** Model identifier including snapshot. Default `unknown@unknown`. */\n model?: string\n /** Optional sha256 of the prompt; default `'sha256:unknown'`. */\n promptHash?: string\n /** Default `'sha256:unknown'`. */\n configHash?: string\n /** Default `'unknown'`. */\n commitSha?: string\n /** Default `'holdout'` — feedback corpora are by nature the holdout\n * signal a closed-loop improvement aims at. */\n splitTag?: RunSplitTag\n /** Free-form metadata available to consumers via the cast-out path on\n * the resulting RunRecord. */\n extras?: Record<string, unknown>\n}\n\nexport interface FromFeedbackTableOptions {\n /** Per-(run, rater) ratings. */\n ratings: FeedbackTableRow[]\n /** Per-run metadata. When a runId appears in `ratings` but not here, the\n * adapter synthesises minimal metadata with defaults documented above. */\n meta?: FeedbackTableMeta[]\n /** Rating scale. Provide `{ min, max }` for non-0..1 numeric scales.\n * Booleans are normalised: true → 1, false → 0. Default: assumes\n * ratings are already 0..1. */\n scale?: { min: number; max: number }\n /** When true, the rater scores are emitted into `raterScores` (a sibling\n * array `analyzeRuns()` accepts) instead of being averaged into the\n * run's `outcome.searchScore`. Default `true` — preserves rater-level\n * signal for inter-rater analysis. */\n emitRaterScores?: boolean\n}\n\nexport interface FromFeedbackTableResult {\n runs: RunRecord[]\n /** Rater-level scores ready to pass into `analyzeRuns({ raterScores })`\n * for inter-rater agreement + disagreement triage. */\n raterScores: Array<{ runId: string; rater: string; score: number }>\n}\n\nexport function fromFeedbackTable(opts: FromFeedbackTableOptions): FromFeedbackTableResult {\n const { ratings, meta = [], scale, emitRaterScores = true } = opts\n const metaByRun = new Map(meta.map((m) => [m.runId, m]))\n\n // Normalise per-rating to a 0..1 score.\n const normalise = (rating: number | boolean): number => {\n if (typeof rating === 'boolean') return rating ? 1 : 0\n if (!Number.isFinite(rating)) return Number.NaN\n if (!scale) return rating\n const { min, max } = scale\n if (max === min) return rating\n return (rating - min) / (max - min)\n }\n\n // Group ratings by runId.\n const byRun = new Map<string, FeedbackTableRow[]>()\n for (const row of ratings) {\n const list = byRun.get(row.runId) ?? []\n list.push(row)\n byRun.set(row.runId, list)\n }\n\n const runs: RunRecord[] = []\n const raterScores: FromFeedbackTableResult['raterScores'] = []\n\n for (const [runId, rowsForRun] of byRun) {\n const normalised = rowsForRun\n .map((r) => ({ rater: r.rater, score: normalise(r.rating) }))\n .filter((r) => Number.isFinite(r.score))\n if (normalised.length === 0) continue\n\n const meanScore = normalised.reduce((s, r) => s + r.score, 0) / normalised.length\n\n const runMeta = metaByRun.get(runId) ?? ({ runId } as FeedbackTableMeta)\n\n const judgeScores: JudgeScoresRecord = {\n perJudge: Object.fromEntries(normalised.map((r) => [r.rater, { rating: r.score }])),\n perDimMean: { rating: meanScore },\n composite: meanScore,\n }\n\n const outcome: RunOutcome = {\n // Feedback corpora ARE the holdout signal — score lands on\n // `holdoutScore` so downstream substrate primitives (`paretoChart`,\n // promotion gates) read it correctly by default.\n holdoutScore: meanScore,\n raw: Object.fromEntries(normalised.map((r) => [`rater:${r.rater}`, r.score])),\n judgeScores,\n }\n\n runs.push({\n runId,\n experimentId: runMeta.experimentId ?? 'feedback-corpus',\n candidateId: runMeta.candidateId ?? runId,\n seed: 0,\n model: runMeta.model ?? 'unknown@unknown',\n promptHash: runMeta.promptHash ?? 'sha256:unknown',\n configHash: runMeta.configHash ?? 'sha256:unknown',\n commitSha: runMeta.commitSha ?? 'unknown',\n wallMs: runMeta.wallMs ?? 0,\n costUsd: runMeta.costUsd ?? 0,\n tokenUsage: { input: 0, output: 0 },\n outcome,\n splitTag: runMeta.splitTag ?? 'holdout',\n } as RunRecord)\n\n if (emitRaterScores) {\n for (const r of normalised) raterScores.push({ runId, rater: r.rater, score: r.score })\n }\n }\n\n return { runs, raterScores }\n}\n","/**\n * # `intake/otel-spans` — OTel `TraceSpanEvent[]` → `RunRecord[]`.\n *\n * Turns an existing observability stream into the substrate-canonical\n * `RunRecord` shape so consumers with logs but no eval discipline can\n * call `analyzeRuns()` against their production traffic immediately.\n *\n * Pivot rule: spans are grouped by `tangle.runId` (the same attribute the\n * hosted-tier wire format uses) or, when absent, by `traceId`. One group\n * becomes one `RunRecord`. The root span (no `parentSpanId`) supplies:\n *\n * - `runId` (the group key)\n * - `wallMs` from `endTimeUnixNano - startTimeUnixNano`\n * - `model` from `gen_ai.request.model` / `llm.model` / `tangle.model`\n * - cost from `cost.usd` / `gen_ai.usage.cost_usd` / `tangle.cost.usd`\n * - token usage from `gen_ai.usage.{input,output}_tokens`\n * - `outcome.searchScore` from `tangle.score` / `eval.score` when\n * present; `outcome.raw` collects every numeric attribute.\n *\n * Spans that ERRORed (`status.code === 'ERROR'`) populate `failureMode`\n * with their `name` so `analyzeRuns()`'s failure clustering sees them.\n */\n\nimport type { TraceSpanEvent } from '../../hosted/types'\nimport type {\n JudgeScoresRecord,\n RunOutcome,\n RunRecord,\n RunSplitTag,\n RunTokenUsage,\n} from '../../run-record'\n\nconst SCORE_KEYS = ['tangle.score', 'eval.score', 'score']\nconst MODEL_KEYS = ['tangle.model', 'gen_ai.request.model', 'llm.model', 'model']\nconst COST_KEYS = ['tangle.cost.usd', 'gen_ai.usage.cost_usd', 'cost.usd', 'cost']\nconst INPUT_TOKEN_KEYS = ['gen_ai.usage.input_tokens', 'tangle.tokens.in', 'tokens.in']\nconst OUTPUT_TOKEN_KEYS = ['gen_ai.usage.output_tokens', 'tangle.tokens.out', 'tokens.out']\nconst PROMPT_HASH_KEYS = ['tangle.prompt_hash', 'prompt.hash']\nconst CONFIG_HASH_KEYS = ['tangle.config_hash', 'config.hash']\n\nexport interface FromOtelSpansOptions {\n spans: TraceSpanEvent[]\n /** Default split tag for synthesized records. Defaults to `'holdout'`. */\n defaultSplit?: RunSplitTag\n /** Default `experimentId` when not present on any span. */\n experimentId?: string\n}\n\nexport function fromOtelSpans(opts: FromOtelSpansOptions): RunRecord[] {\n const { spans, defaultSplit = 'holdout', experimentId = 'otel-corpus' } = opts\n const grouped = groupSpans(spans)\n\n const runs: RunRecord[] = []\n for (const [groupKey, groupSpans] of grouped) {\n const root = findRoot(groupSpans)\n if (!root) continue\n\n const wallMs = Math.max(0, (root.endTimeUnixNano - root.startTimeUnixNano) / 1_000_000)\n const model = readAttrString(groupSpans, MODEL_KEYS) ?? 'unknown@unknown'\n const costUsd = readAttrNumber(groupSpans, COST_KEYS) ?? 0\n const inputTokens = readAttrNumber(groupSpans, INPUT_TOKEN_KEYS) ?? 0\n const outputTokens = readAttrNumber(groupSpans, OUTPUT_TOKEN_KEYS) ?? 0\n const promptHash = readAttrString(groupSpans, PROMPT_HASH_KEYS) ?? 'sha256:unknown'\n const configHash = readAttrString(groupSpans, CONFIG_HASH_KEYS) ?? 'sha256:unknown'\n const score = readAttrNumber(groupSpans, SCORE_KEYS)\n\n const rawNumeric = collectNumericAttrs(groupSpans)\n const tokenUsage: RunTokenUsage = {\n input: inputTokens,\n output: outputTokens,\n }\n\n const judgeScores: JudgeScoresRecord | undefined =\n score !== undefined\n ? {\n perJudge: { 'otel-derived': { score } },\n perDimMean: { score },\n composite: score,\n }\n : undefined\n\n const errorSpan = groupSpans.find((s) => s.status?.code === 'ERROR')\n const outcome: RunOutcome = {\n ...(opts.defaultSplit === 'search' ? { searchScore: score } : { holdoutScore: score }),\n raw: rawNumeric,\n ...(judgeScores ? { judgeScores } : {}),\n }\n\n runs.push({\n runId: groupKey,\n experimentId,\n candidateId: (root.attributes['tangle.candidateId'] as string | undefined) ?? 'otel-default',\n seed: 0,\n model,\n promptHash,\n configHash,\n commitSha: (root.attributes['tangle.commit_sha'] as string | undefined) ?? 'unknown',\n wallMs,\n costUsd,\n tokenUsage,\n outcome,\n splitTag: defaultSplit,\n ...(errorSpan ? { failureMode: errorSpan.name } : {}),\n } as RunRecord)\n }\n return runs\n}\n\n// ── Internal helpers ────────────────────────────────────────────────\n\nfunction groupSpans(spans: TraceSpanEvent[]): Map<string, TraceSpanEvent[]> {\n const m = new Map<string, TraceSpanEvent[]>()\n for (const span of spans) {\n const key = (span['tangle.runId'] as string | undefined) ?? span.traceId\n const list = m.get(key) ?? []\n list.push(span)\n m.set(key, list)\n }\n return m\n}\n\nfunction findRoot(group: TraceSpanEvent[]): TraceSpanEvent | undefined {\n return group.find((s) => !s.parentSpanId) ?? group[0]\n}\n\nfunction readAttrString(spans: TraceSpanEvent[], keys: string[]): string | undefined {\n for (const span of spans) {\n for (const key of keys) {\n const v = span.attributes[key]\n if (typeof v === 'string' && v.length > 0) return v\n }\n }\n return undefined\n}\n\nfunction readAttrNumber(spans: TraceSpanEvent[], keys: string[]): number | undefined {\n for (const span of spans) {\n for (const key of keys) {\n const v = span.attributes[key]\n if (typeof v === 'number' && Number.isFinite(v)) return v\n if (typeof v === 'string') {\n const parsed = Number(v)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n }\n return undefined\n}\n\nfunction collectNumericAttrs(spans: TraceSpanEvent[]): Record<string, number> {\n const raw: Record<string, number> = {}\n for (const span of spans) {\n for (const [k, v] of Object.entries(span.attributes)) {\n if (typeof v === 'number' && Number.isFinite(v)) raw[k] = v\n }\n }\n return raw\n}\n"],"mappings":"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","names":["cohensD","mean","i","groupSpans"]}
|