@tangle-network/agent-eval 0.135.1 → 0.135.2
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/CHANGELOG.md +17 -0
- package/dist/{analyze-runs-DMo3Lb_y.d.ts → analyze-runs-Cda5Xkj1.d.ts} +3 -3
- package/dist/{analyze-runs-DMo3Lb_y.d.ts.map → analyze-runs-Cda5Xkj1.d.ts.map} +1 -1
- package/dist/{analyze-runs-qk8op0tN.js → analyze-runs-jjCmF8pU.js} +14 -7
- package/dist/analyze-runs-jjCmF8pU.js.map +1 -0
- package/dist/{baseline-BaPxoROc.js → baseline-BUeFcgrn.js} +2 -2
- package/dist/{baseline-BaPxoROc.js.map → baseline-BUeFcgrn.js.map} +1 -1
- package/dist/benchmarks/index.d.ts +1 -1
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-DwFrCrCS.js → benchmarks-Mtu251Jz.js} +3 -3
- package/dist/{benchmarks-DwFrCrCS.js.map → benchmarks-Mtu251Jz.js.map} +1 -1
- package/dist/builder-eval/index.js +1 -1
- package/dist/campaign/index.d.ts +2 -2
- package/dist/campaign/index.js +2 -2
- package/dist/{campaign-B0oyngTs.js → campaign-RVIqtJh0.js} +5 -5
- package/dist/{campaign-B0oyngTs.js.map → campaign-RVIqtJh0.js.map} +1 -1
- package/dist/{client-BIyh1RCr.d.ts → client-DcvgkaZi.d.ts} +13 -4
- package/dist/client-DcvgkaZi.d.ts.map +1 -0
- package/dist/contract/index.d.ts +3 -3
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +17 -5
- package/dist/contract/index.js.map +1 -1
- package/dist/{eval-campaign-aMG73hvX.js → eval-campaign-Cc8WZJ6b.js} +2 -2
- package/dist/{eval-campaign-aMG73hvX.js.map → eval-campaign-Cc8WZJ6b.js.map} +1 -1
- package/dist/hosted/index.d.ts +1 -1
- package/dist/{index-BoJNQR6n.d.ts → index-B4Fjfo5U.d.ts} +93 -15
- package/dist/index-B4Fjfo5U.d.ts.map +1 -0
- package/dist/{index-C21xKtxu.d.ts → index-CQsJcqch.d.ts} +3 -3
- package/dist/{index-C21xKtxu.d.ts.map → index-CQsJcqch.d.ts.map} +1 -1
- package/dist/{index-DSC51roc2.d.ts → index-DSC51roc.d.ts} +1 -1
- package/dist/index-DSC51roc.d.ts.map +1 -0
- package/dist/index.d.ts +41 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +131 -53
- package/dist/index.js.map +1 -1
- package/dist/matrix/index.d.ts +1 -1
- package/dist/meta-eval/index.d.ts +1 -2
- package/dist/meta-eval/index.d.ts.map +1 -1
- package/dist/meta-eval/index.js +2 -2
- package/dist/multishot/index.d.ts +1 -1
- package/dist/openapi.json +1 -1
- package/dist/{paired-arms-CA_8pN01.js → paired-arms-BbFKrAU-.js} +2 -2
- package/dist/{paired-arms-CA_8pN01.js.map → paired-arms-BbFKrAU-.js.map} +1 -1
- package/dist/pipelines/index.js +2 -2
- package/dist/{release-report-BVZBmRZp.js → release-report-DooPguBc.js} +4 -3
- package/dist/{release-report-BVZBmRZp.js.map → release-report-DooPguBc.js.map} +1 -1
- package/dist/{release-report-CuULWKyk.d.ts → release-report-DpBxGGI1.d.ts} +2 -2
- package/dist/{release-report-CuULWKyk.d.ts.map → release-report-DpBxGGI1.d.ts.map} +1 -1
- package/dist/reporting.d.ts +3 -3
- package/dist/reporting.js +4 -4
- package/dist/{researcher-DVtruQ9U.d.ts → researcher-Doo95b50.d.ts} +2 -2
- package/dist/{researcher-DVtruQ9U.d.ts.map → researcher-Doo95b50.d.ts.map} +1 -1
- package/dist/{reward-hacking-DCdRK9TY.js → reward-hacking-a-kYs0-i.js} +2 -2
- package/dist/{reward-hacking-DCdRK9TY.js.map → reward-hacking-a-kYs0-i.js.map} +1 -1
- package/dist/rl.d.ts +45 -3
- package/dist/rl.d.ts.map +1 -1
- package/dist/rl.js +108 -22
- package/dist/rl.js.map +1 -1
- package/dist/{rubric-predictive-validity-D6Q6n9oq.js → rubric-predictive-validity-BJf-8ejY.js} +2 -2
- package/dist/{rubric-predictive-validity-D6Q6n9oq.js.map → rubric-predictive-validity-BJf-8ejY.js.map} +1 -1
- package/dist/{skillopt-optimization-method-C9yGg-4C.js → skillopt-optimization-method-0UmPD6aP.js} +340 -54
- package/dist/skillopt-optimization-method-0UmPD6aP.js.map +1 -0
- package/dist/{skillopt-optimization-method-DJ3l4w8W.d.ts → skillopt-optimization-method-CwSYkv35.d.ts} +39 -9
- package/dist/skillopt-optimization-method-CwSYkv35.d.ts.map +1 -0
- package/dist/{statistics-D_4Snl-5.d.ts → statistics-CKOqre5S.d.ts} +329 -3
- package/dist/statistics-CKOqre5S.d.ts.map +1 -0
- package/dist/{statistics-RwRNu2__.js → statistics-CnGCLLqc.js} +315 -2
- package/dist/statistics-CnGCLLqc.js.map +1 -0
- package/dist/{summary-report-BxtossFi.js → summary-report-BEk8OFLs.js} +11 -6
- package/dist/summary-report-BEk8OFLs.js.map +1 -0
- package/dist/{summary-report-DGp0-_XO.d.ts → summary-report-CPMINBqs.d.ts} +182 -7
- package/dist/summary-report-CPMINBqs.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/analyze-runs-qk8op0tN.js.map +0 -1
- package/dist/client-BIyh1RCr.d.ts.map +0 -1
- package/dist/index-BoJNQR6n.d.ts.map +0 -1
- package/dist/index-DSC51roc2.d.ts.map +0 -1
- package/dist/judge-calibration-DFtEMlde.d.ts +0 -146
- package/dist/judge-calibration-DFtEMlde.d.ts.map +0 -1
- package/dist/skillopt-optimization-method-C9yGg-4C.js.map +0 -1
- package/dist/skillopt-optimization-method-DJ3l4w8W.d.ts.map +0 -1
- package/dist/statistics-D_4Snl-5.d.ts.map +0 -1
- package/dist/statistics-RwRNu2__.js.map +0 -1
- package/dist/summary-report-BxtossFi.js.map +0 -1
- package/dist/summary-report-DGp0-_XO.d.ts.map +0 -1
package/dist/matrix/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { t as DefaultVerdict } from "../verdict-Dps8_okt.js";
|
|
2
|
-
import { a as MatrixCell, i as MatrixAxis, n as AxisSummary, o as MatrixResult, r as CellResult, s as RunAgentMatrixOptions, t as runAgentMatrix } from "../index-
|
|
2
|
+
import { a as MatrixCell, i as MatrixAxis, n as AxisSummary, o as MatrixResult, r as CellResult, s as RunAgentMatrixOptions, t as runAgentMatrix } from "../index-DSC51roc.js";
|
|
3
3
|
export { type AxisSummary, type CellResult, type DefaultVerdict, type MatrixAxis, type MatrixCell, type MatrixResult, type RunAgentMatrixOptions, runAgentMatrix };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { f as Run } from "../schema-BtVldJ3T.js";
|
|
2
2
|
import { s as TraceStore } from "../store-CT9YIIve.js";
|
|
3
|
-
import {
|
|
4
|
-
import { a as CorpusAgreementReport } from "../statistics-D_4Snl-5.js";
|
|
3
|
+
import { Ct as GoldenItem, St as ContinuousCalibrationResult, a as CorpusAgreementReport, bt as ContinuousAgreement, vt as CalibrationResult, yt as CandidateScore } from "../statistics-CKOqre5S.js";
|
|
5
4
|
import { a as OutcomeFilter, i as InMemoryOutcomeStore, n as FileSystemOutcomeStore, o as OutcomeStore, r as FileSystemOutcomeStoreOptions, t as DeploymentOutcome } from "../outcome-store-BYHIuO0e.js";
|
|
6
5
|
import { n as SeriesConvergenceResult, t as SeriesConvergenceOptions } from "../series-convergence-ofsqPWhs.js";
|
|
7
6
|
import { a as rubricPredictiveValidity, i as RubricRanking, n as RubricPredictiveValidityInput, r as RubricPredictiveValidityReport, t as RubricOutcomePair } from "../rubric-predictive-validity-C1dCLcvb.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/meta-eval/correlation-study.ts","../../src/meta-eval/calibration.ts","../../src/meta-eval/sentinel.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/meta-eval/correlation-study.ts","../../src/meta-eval/calibration.ts","../../src/meta-eval/sentinel.ts"],"mappings":";;;;;;;UAiBiB;EACf;;EAEA,WAAW,KAAK,KAAK,OAAO,eAAe;;UAG5B;EACf;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;;EAEA;IAAe;IAAe;;;EAE9B;;UAGe;EACf,OAAO;EACP;EACA;;UAGe;;EAEf;;EAEA,gBAAgB;;EAEhB;;EAEA;;iBAGoB,iBACpB,YAAY,YACZ,cAAc,cACd,aAAa,kBACb,8BACA,UAAS,0BACR,QAAQ;;;UCjDM;EACf;EACA;EACA;EACA;EACA;;EAEA;;UAGe;EACf;EACA;EACA;EACA,MAAM;;EAEN;;EAEA;;UAGe;EACf;;EAEA;;EAEA;IAAU;IAAY;;;UAGP;EACf;EACA;;iBAGoB,iBACpB,YAAY,YACZ,cAAc,cACd,YAAY,gBACZ,uBACA,UAAS,qBACR,QAAQ;iBAgCK,qBACd,YAAY,mBACZ,oBACA,uBACA,UAAS,qBACR;;;cCtCU;KAED,6BAA6B;UAExB;;EAEf;;EAEA;;EAEA;;UAGe;;EAEf;EACA;;EAEA;;;;;;;EAOA,SAAS;;;UAIM;EACf;EACA;EACA;;;iBAcc,yBAAyB,UAAU,kBAAkB;;;;;;iBAiCrD,wBACd,QAAQ,oBAAoB,6BAC5B,MAAM,eACL;;;;;;;;iBAmBa,sBACd,QAAQ,wBAAwB,qBAChC,MAAM,eACL;UAYc;;EAEf;;;;;;;;;iBAUc,wBACd,QAAQ,kBACR,QAAQ,cACR,MAAM,cACN,UAAS,qBACR;UA4Cc;EACf,OAAO,UAAU,mBAAmB;;EAEpC,QAAQ,mBAAmB,QAAQ;;iBAGrB,sBAAsB,UAAS,qBAA0B;;;;;;;iBAqBzD,kBAAkB,eAAe;UA0ChC;;EAEf;;EAEA;;EAEA;;EAEA;;UAGe;;EAEf;EACA,aAAa;;EAEb,cAAc;;UAGC;EACf;EACA,QAAQ;;EAER,OAAO;;EAEP;;EAEA;;EAEA;EACA;EACA;;UAGe;EACf,UAAU;EACV;EACA;;;;;;;EAOA;;iBAKc,oBACd,SAAS,oBACT,MAAM,uBACL;UA6Gc;EACf;EACA;;;;;;;;;;iBAWc,gBAAgB,QAAQ,iBAAiB"}
|
package/dist/meta-eval/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { s as ValidationError } from "../errors-8YnH8WlF.js";
|
|
2
|
-
import {
|
|
2
|
+
import { L as pearsonR, V as spearmanR } from "../statistics-CnGCLLqc.js";
|
|
3
3
|
import { o as llmSpans, t as aggregateLlm } from "../query-Di7eEQ79.js";
|
|
4
4
|
import { t as analyzeSeries } from "../series-convergence-CjO2QdRW.js";
|
|
5
|
-
import { t as rubricPredictiveValidity } from "../rubric-predictive-validity-
|
|
5
|
+
import { t as rubricPredictiveValidity } from "../rubric-predictive-validity-BJf-8ejY.js";
|
|
6
6
|
import { n as InMemoryOutcomeStore, t as FileSystemOutcomeStore } from "../outcome-store-ChBKlTd_.js";
|
|
7
7
|
//#region src/meta-eval/calibration.ts
|
|
8
8
|
async function calibrationCurve(traceStore, outcomeStore, evalMetric, outcomeMetric, options = {}) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { p as CostProvenance } from "../cost-ledger-fGS_u_O1.js";
|
|
2
2
|
import { w as JudgeScore } from "../types-DiWLru6Z.js";
|
|
3
|
-
import { o as MatrixResult } from "../index-
|
|
3
|
+
import { o as MatrixResult } from "../index-DSC51roc.js";
|
|
4
4
|
import { AgentProfile } from "@tangle-network/agent-interface";
|
|
5
5
|
//#region src/multishot/types.d.ts
|
|
6
6
|
interface MultishotMessage {
|
package/dist/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "@tangle-network/agent-eval — wire protocol",
|
|
5
|
-
"version": "0.135.
|
|
5
|
+
"version": "0.135.2",
|
|
6
6
|
"description": "HTTP and stdio RPC interface to agent-eval. The TypeScript runtime is the source of truth; this spec is the contract that cross-language clients (Python, Rust, Go) generate from.\n\nWire-protocol version: 1.0.0. Bumps on breaking changes to request/response schemas.",
|
|
7
7
|
"contact": {
|
|
8
8
|
"name": "Tangle Network",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s as ValidationError } from "./errors-8YnH8WlF.js";
|
|
2
|
-
import {
|
|
2
|
+
import { A as pairedRiskDifference, E as pairedBootstrap, W as wilcoxonSignedRank, b as mcnemar } from "./statistics-CnGCLLqc.js";
|
|
3
3
|
//#region src/paired-arms.ts
|
|
4
4
|
/**
|
|
5
5
|
* Matched-pair arm comparison — "did the treatment arm beat the baseline arm
|
|
@@ -257,4 +257,4 @@ function metricValue(row, name) {
|
|
|
257
257
|
//#endregion
|
|
258
258
|
export { pairArms as n, pairRunRecords as r, comparePairedArms as t };
|
|
259
259
|
|
|
260
|
-
//# sourceMappingURL=paired-arms-
|
|
260
|
+
//# sourceMappingURL=paired-arms-BbFKrAU-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paired-arms-CA_8pN01.js","names":[],"sources":["../src/paired-arms.ts"],"sourcesContent":["/**\n * Matched-pair arm comparison — \"did the treatment arm beat the baseline arm\n * on the SAME work items?\"\n *\n * An arm A/B over run records is only trustworthy when it is PAIRED: the same\n * task/scenario/seed evaluated under both arms, compared item-by-item, so\n * inter-item difficulty variance cancels instead of masquerading as an arm\n * effect. This module owns the two error-prone steps every consumer otherwise\n * hand-rolls:\n *\n * 1. Pairing — matching rows across arms by `pairKey` (and by `repKey`\n * within multi-rep items), with leftovers REPORTED rather than silently\n * dropped (a silently unbalanced pairing biases every paired statistic\n * downstream). Pairing never keys on outcome content: matching reps by\n * their outcomes deflates discordant-pair counts and makes McNemar\n * anti-conservative, so reps pair only by (`pairKey`, `repKey`) identity.\n * 2. Composition — feeding the matched pairs to the correct paired\n * estimators that already live in `statistics`: `mcnemar` +\n * `pairedRiskDifference` for pass/fail, `pairedBootstrap` +\n * `wilcoxonSignedRank` for continuous metrics. No statistic is\n * re-implemented here.\n *\n * The row shape is deliberately structural — callers project a `RunRecord`\n * (or any record) into `{ pairKey, arm, pass?, metrics? }`. Arm names are\n * caller-supplied parameters; the module ships no domain literal.\n */\n\nimport { ValidationError } from './errors'\nimport type { RunRecord } from './run-record'\nimport type { McNemarResult, PairedBootstrapOptions, PairedBootstrapResult } from './statistics'\nimport {\n mcnemar,\n pairedBootstrap,\n pairedRiskDifference,\n type RiskDifferenceResult,\n wilcoxonSignedRank,\n} from './statistics'\n\n/** One arm observation of one work item. Structural on purpose: callers\n * project their own record type (e.g. a `RunRecord`) into this shape. */\nexport interface PairedArmRow {\n /** Matching key — rows sharing a `pairKey` across both arms form pairs\n * (typically the task/scenario/seed identity). */\n pairKey: string\n /** Rep identity within a `pairKey` (e.g. a seed or rep number). Required on\n * every row of a `pairKey` that has more than one rep in either arm; reps\n * then pair only on exact (`pairKey`, `repKey`) match, never on outcome\n * content. Optional when each arm has at most one rep of the item. */\n repKey?: string\n /** Arm label this row was produced under. */\n arm: string\n /** Binary outcome; omit when the comparison has no pass/fail notion. */\n pass?: boolean\n /** Named numeric measurements (score, cost, latency, …). */\n metrics?: Record<string, number>\n}\n\nexport interface PairArmsOptions {\n /** Arm treated as the control side of every pair. */\n baselineArm: string\n /** Arm treated as the treatment side of every pair. */\n treatmentArm: string\n}\n\n/** One matched (baseline, treatment) observation of the same work item. */\nexport interface MatchedPair {\n pairKey: string\n /** 0-based position of this pair within its `pairKey`, ordered by sorted\n * `repKey` (always 0 for a single-rep item). The rep identity itself is on\n * the rows (`baseline.repKey` / `treatment.repKey`). */\n repIndex: number\n baseline: PairedArmRow\n treatment: PairedArmRow\n}\n\nexport interface PairArmsResult {\n /** Matched pairs, ordered by (`pairKey`, `repIndex`). */\n pairs: MatchedPair[]\n /** Baseline rows left without a treatment counterpart — reported, never\n * silently dropped. */\n unpairedBaseline: PairedArmRow[]\n /** Treatment rows left without a baseline counterpart. */\n unpairedTreatment: PairedArmRow[]\n}\n\n/**\n * Match rows across two arms into (baseline, treatment) pairs by `pairKey`.\n *\n * A `pairKey` with at most one row per arm pairs directly, no `repKey`\n * needed. A `pairKey` with multiple reps in either arm requires `repKey` on\n * every one of its rows, and reps pair only on exact (`pairKey`, `repKey`)\n * match — pairing is keyed purely on row identity, never on outcome content\n * (outcome-keyed matching deflates discordant counts and biases McNemar), and\n * is therefore independent of input order. Reps whose `repKey` has no\n * counterpart in the other arm, and items present in only one arm, land in\n * the unpaired lists — reported, never truncated.\n *\n * Fail-loud: throws when either named arm has zero rows (an unknown arm\n * name would otherwise read as \"everything unpaired\"), when the two arm\n * names are equal, when a multi-rep `pairKey` has a row without `repKey`, or\n * when a (`pairKey`, arm) group repeats a `repKey` (the match would be\n * ambiguous).\n */\nexport function pairArms(rows: readonly PairedArmRow[], opts: PairArmsOptions): PairArmsResult {\n const { baselineArm, treatmentArm } = opts\n if (baselineArm === treatmentArm) {\n throw new ValidationError(\n `pairArms: baselineArm and treatmentArm are both '${baselineArm}' — an arm cannot be compared to itself`,\n )\n }\n\n // arm → pairKey → rows\n const byArm = new Map<string, Map<string, PairedArmRow[]>>()\n const armsSeen = new Set<string>()\n for (const row of rows) {\n armsSeen.add(row.arm)\n if (row.arm !== baselineArm && row.arm !== treatmentArm) continue\n const byKey = byArm.get(row.arm) ?? new Map<string, PairedArmRow[]>()\n const group = byKey.get(row.pairKey) ?? []\n group.push(row)\n byKey.set(row.pairKey, group)\n byArm.set(row.arm, byKey)\n }\n\n for (const arm of [baselineArm, treatmentArm]) {\n if (!byArm.has(arm)) {\n const seen = [...armsSeen].sort().join(', ') || '<none>'\n throw new ValidationError(`pairArms: no rows for arm '${arm}' (arms present: ${seen})`)\n }\n }\n\n const baselineByKey = byArm.get(baselineArm)!\n const treatmentByKey = byArm.get(treatmentArm)!\n\n const allKeys = [...new Set([...baselineByKey.keys(), ...treatmentByKey.keys()])].sort()\n const pairs: MatchedPair[] = []\n const unpairedBaseline: PairedArmRow[] = []\n const unpairedTreatment: PairedArmRow[] = []\n for (const pairKey of allKeys) {\n const b = baselineByKey.get(pairKey) ?? []\n const t = treatmentByKey.get(pairKey) ?? []\n\n if (b.length <= 1 && t.length <= 1) {\n if (b.length === 1 && t.length === 1) {\n const baseline = b[0]!\n const treatment = t[0]!\n if (baseline.repKey !== undefined || treatment.repKey !== undefined) {\n if (\n baseline.repKey === undefined ||\n treatment.repKey === undefined ||\n baseline.repKey !== treatment.repKey\n ) {\n unpairedBaseline.push(baseline)\n unpairedTreatment.push(treatment)\n continue\n }\n }\n pairs.push({ pairKey, repIndex: 0, baseline, treatment })\n } else {\n unpairedBaseline.push(...b)\n unpairedTreatment.push(...t)\n }\n continue\n }\n\n const bByRep = indexByRepKey(b, pairKey, baselineArm)\n const tByRep = indexByRepKey(t, pairKey, treatmentArm)\n const repKeys = [...new Set([...bByRep.keys(), ...tByRep.keys()])].sort()\n let repIndex = 0\n for (const repKey of repKeys) {\n const baseline = bByRep.get(repKey)\n const treatment = tByRep.get(repKey)\n if (baseline !== undefined && treatment !== undefined) {\n pairs.push({ pairKey, repIndex: repIndex++, baseline, treatment })\n } else if (baseline !== undefined) {\n unpairedBaseline.push(baseline)\n } else if (treatment !== undefined) {\n unpairedTreatment.push(treatment)\n }\n }\n }\n\n return { pairs, unpairedBaseline, unpairedTreatment }\n}\n\n/** Index a multi-rep (pairKey, arm) group by `repKey`, enforcing that every\n * row carries one and that no repKey repeats within the group. */\nfunction indexByRepKey(\n group: readonly PairedArmRow[],\n pairKey: string,\n arm: string,\n): Map<string, PairedArmRow> {\n const byRep = new Map<string, PairedArmRow>()\n for (const row of group) {\n if (row.repKey === undefined) {\n throw new ValidationError(\n `pairArms: pairKey '${pairKey}' has multiple reps in an arm, but a row in arm '${arm}' ` +\n `is missing repKey — multi-rep items require an explicit repKey on every row so reps ` +\n `pair by identity (pairing reps by outcome or by index would bias the paired statistics)`,\n )\n }\n if (byRep.has(row.repKey)) {\n throw new ValidationError(\n `pairArms: duplicate repKey '${row.repKey}' for pairKey '${pairKey}' in arm '${arm}' — ` +\n `(pairKey, repKey) must uniquely identify a rep within an arm`,\n )\n }\n byRep.set(row.repKey, row)\n }\n return byRep\n}\n\n/** Paired pass/fail comparison over the pairs where BOTH sides carry `pass`. */\nexport interface PairedCorrectness {\n /** Discordant pairs where the treatment passed and the baseline failed. */\n b10: number\n /** Discordant pairs where the baseline passed and the treatment failed. */\n b01: number\n /** Exact McNemar significance over the paired outcomes (`b === b10`, `c === b01`). */\n mcnemar: McNemarResult\n /** Paired effect size: p(treatment) − p(baseline) with a paired-variance CI. */\n riskDifference: RiskDifferenceResult\n}\n\n/** Paired delta summary for one named metric (delta = treatment − baseline). */\nexport interface PairedMetricDelta {\n name: string\n /** Pairs where BOTH sides carry a finite value for this metric. */\n n: number\n /** Pairs where at least one side does not carry the metric. */\n nMissing: number\n /** Median paired delta, or null when `n === 0`. */\n medianDelta: number | null\n /** Mean paired delta, or null when `n === 0`. */\n meanDelta: number | null\n /** Bootstrap CI on the paired delta (`pairedBootstrap`); null when\n * `n === 0` — a zero-width [0, 0] interval on no data would read as a\n * measured tight null. */\n bootstrapCi: PairedBootstrapResult | null\n /** Wilcoxon signed-rank test on the paired deltas; null when `n === 0`. */\n wilcoxon: { w: number; p: number } | null\n}\n\nexport interface ComparePairedArmsOptions extends PairArmsOptions {\n /** Metrics to compare. Default: every metric name observed on any matched\n * pair, sorted. A name that appears on no pair is still reported (with\n * `n = 0`) so a misspelled metric is visible instead of vanishing. */\n metricNames?: string[]\n /** Passed through to `pairedBootstrap` — set `seed` for reproducible CIs. */\n bootstrap?: PairedBootstrapOptions\n}\n\nexport interface PairedArmsComparison {\n nPairs: number\n nUnpairedBaseline: number\n nUnpairedTreatment: number\n /** null when no matched pair carries `pass` on both sides — a pass/fail\n * verdict over rows that never measured pass/fail would be fabricated. */\n correctness: PairedCorrectness | null\n metricDeltas: PairedMetricDelta[]\n}\n\n/**\n * Full matched-pair arm comparison: pair via {@link pairArms}, then compose\n * the paired estimators from `statistics` over the matched pairs.\n *\n * Correctness uses only the pairs where both sides carry `pass` (`mcnemar.n`\n * is that subset's size); each metric uses only the pairs where both sides\n * carry a finite value for it, with the remainder counted in `nMissing`.\n * Deltas are treatment − baseline throughout.\n *\n * Fail-loud: inherits {@link pairArms}'s unknown-arm throw, and throws on a\n * non-finite metric value — silently treating corrupt telemetry as \"metric\n * absent\" would misreport it as missing coverage.\n */\nexport function comparePairedArms(\n rows: readonly PairedArmRow[],\n opts: ComparePairedArmsOptions,\n): PairedArmsComparison {\n const { pairs, unpairedBaseline, unpairedTreatment } = pairArms(rows, opts)\n\n let correctness: PairedCorrectness | null = null\n const baselinePass: number[] = []\n const treatmentPass: number[] = []\n for (const pair of pairs) {\n if (pair.baseline.pass === undefined || pair.treatment.pass === undefined) continue\n baselinePass.push(pair.baseline.pass ? 1 : 0)\n treatmentPass.push(pair.treatment.pass ? 1 : 0)\n }\n if (baselinePass.length > 0) {\n const mc = mcnemar(baselinePass, treatmentPass)\n correctness = {\n b10: mc.b,\n b01: mc.c,\n mcnemar: mc,\n riskDifference: pairedRiskDifference(baselinePass, treatmentPass),\n }\n }\n\n const metricNames =\n opts.metricNames ??\n [\n ...new Set(\n pairs.flatMap((p) => [\n ...Object.keys(p.baseline.metrics ?? {}),\n ...Object.keys(p.treatment.metrics ?? {}),\n ]),\n ),\n ].sort()\n\n const metricDeltas: PairedMetricDelta[] = metricNames.map((name) => {\n const before: number[] = []\n const after: number[] = []\n let nMissing = 0\n for (const pair of pairs) {\n const b = metricValue(pair.baseline, name)\n const t = metricValue(pair.treatment, name)\n if (b === undefined || t === undefined) {\n nMissing++\n continue\n }\n before.push(b)\n after.push(t)\n }\n const bootstrapCi = before.length === 0 ? null : pairedBootstrap(before, after, opts.bootstrap)\n return {\n name,\n n: before.length,\n nMissing,\n medianDelta: bootstrapCi?.median ?? null,\n meanDelta: bootstrapCi?.mean ?? null,\n bootstrapCi,\n wilcoxon: before.length === 0 ? null : wilcoxonSignedRank(before, after),\n }\n })\n\n return {\n nPairs: pairs.length,\n nUnpairedBaseline: unpairedBaseline.length,\n nUnpairedTreatment: unpairedTreatment.length,\n correctness,\n metricDeltas,\n }\n}\n\nexport interface MatchedRunRecordPair {\n pairKey: string\n repKey: string\n baseline: RunRecord\n treatment: RunRecord\n}\n\nexport interface PairRunRecordsResult {\n pairs: MatchedRunRecordPair[]\n unpairedBaseline: RunRecord[]\n unpairedTreatment: RunRecord[]\n}\n\ninterface RunRecordArmRow extends PairedArmRow {\n run: RunRecord\n repKey: string\n}\n\n/**\n * Pair two RunRecord arms by the identity of the evaluated work:\n * `(experimentId, scenarioId, seed)`.\n *\n * Falling back to array order, candidate id, or experiment id can compare\n * different tasks and fabricate lift. Duplicate identities throw.\n */\nexport function pairRunRecords(\n baselineRuns: readonly RunRecord[],\n treatmentRuns: readonly RunRecord[],\n): PairRunRecordsResult {\n const baselineRows = runRecordArmRows(baselineRuns, 'baseline')\n const treatmentRows = runRecordArmRows(treatmentRuns, 'treatment')\n validateRunRecordArmRows(baselineRows, 'baseline')\n validateRunRecordArmRows(treatmentRows, 'treatment')\n if (baselineRows.length === 0 || treatmentRows.length === 0) {\n return {\n pairs: [],\n unpairedBaseline: baselineRows.map((row) => row.run),\n unpairedTreatment: treatmentRows.map((row) => row.run),\n }\n }\n\n const result = pairArms([...baselineRows, ...treatmentRows], {\n baselineArm: 'baseline',\n treatmentArm: 'treatment',\n })\n return {\n pairs: result.pairs.map((pair) => {\n const baseline = pair.baseline as RunRecordArmRow\n const treatment = pair.treatment as RunRecordArmRow\n return {\n pairKey: pair.pairKey,\n repKey: baseline.repKey,\n baseline: baseline.run,\n treatment: treatment.run,\n }\n }),\n unpairedBaseline: result.unpairedBaseline.map((row) => (row as RunRecordArmRow).run),\n unpairedTreatment: result.unpairedTreatment.map((row) => (row as RunRecordArmRow).run),\n }\n}\n\nfunction runRecordArmRows(runs: readonly RunRecord[], arm: string): RunRecordArmRow[] {\n return runs.map((run) => {\n const scenarioId = run.scenarioId.trim()\n if (!scenarioId) {\n throw new ValidationError(\n `pairRunRecords: run '${run.runId}' is missing scenarioId; paired comparisons require explicit scenario identity`,\n )\n }\n return {\n pairKey: JSON.stringify([run.experimentId, scenarioId]),\n repKey: String(run.seed),\n arm,\n run,\n }\n })\n}\n\nfunction validateRunRecordArmRows(rows: readonly RunRecordArmRow[], arm: string): void {\n const byPairKey = new Map<string, RunRecordArmRow[]>()\n for (const row of rows) {\n const group = byPairKey.get(row.pairKey) ?? []\n group.push(row)\n byPairKey.set(row.pairKey, group)\n }\n for (const [pairKey, group] of byPairKey) {\n if (group.length > 1) indexByRepKey(group, pairKey, arm)\n }\n}\n\nfunction metricValue(row: PairedArmRow, name: string): number | undefined {\n const v = row.metrics?.[name]\n if (v === undefined) return undefined\n if (!Number.isFinite(v)) {\n throw new ValidationError(\n `comparePairedArms: non-finite value for metric '${name}' on pairKey '${row.pairKey}' (arm '${row.arm}'): ${v}`,\n )\n }\n return v\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"paired-arms-BbFKrAU-.js","names":[],"sources":["../src/paired-arms.ts"],"sourcesContent":["/**\n * Matched-pair arm comparison — \"did the treatment arm beat the baseline arm\n * on the SAME work items?\"\n *\n * An arm A/B over run records is only trustworthy when it is PAIRED: the same\n * task/scenario/seed evaluated under both arms, compared item-by-item, so\n * inter-item difficulty variance cancels instead of masquerading as an arm\n * effect. This module owns the two error-prone steps every consumer otherwise\n * hand-rolls:\n *\n * 1. Pairing — matching rows across arms by `pairKey` (and by `repKey`\n * within multi-rep items), with leftovers REPORTED rather than silently\n * dropped (a silently unbalanced pairing biases every paired statistic\n * downstream). Pairing never keys on outcome content: matching reps by\n * their outcomes deflates discordant-pair counts and makes McNemar\n * anti-conservative, so reps pair only by (`pairKey`, `repKey`) identity.\n * 2. Composition — feeding the matched pairs to the correct paired\n * estimators that already live in `statistics`: `mcnemar` +\n * `pairedRiskDifference` for pass/fail, `pairedBootstrap` +\n * `wilcoxonSignedRank` for continuous metrics. No statistic is\n * re-implemented here.\n *\n * The row shape is deliberately structural — callers project a `RunRecord`\n * (or any record) into `{ pairKey, arm, pass?, metrics? }`. Arm names are\n * caller-supplied parameters; the module ships no domain literal.\n */\n\nimport { ValidationError } from './errors'\nimport type { RunRecord } from './run-record'\nimport type { McNemarResult, PairedBootstrapOptions, PairedBootstrapResult } from './statistics'\nimport {\n mcnemar,\n pairedBootstrap,\n pairedRiskDifference,\n type RiskDifferenceResult,\n wilcoxonSignedRank,\n} from './statistics'\n\n/** One arm observation of one work item. Structural on purpose: callers\n * project their own record type (e.g. a `RunRecord`) into this shape. */\nexport interface PairedArmRow {\n /** Matching key — rows sharing a `pairKey` across both arms form pairs\n * (typically the task/scenario/seed identity). */\n pairKey: string\n /** Rep identity within a `pairKey` (e.g. a seed or rep number). Required on\n * every row of a `pairKey` that has more than one rep in either arm; reps\n * then pair only on exact (`pairKey`, `repKey`) match, never on outcome\n * content. Optional when each arm has at most one rep of the item. */\n repKey?: string\n /** Arm label this row was produced under. */\n arm: string\n /** Binary outcome; omit when the comparison has no pass/fail notion. */\n pass?: boolean\n /** Named numeric measurements (score, cost, latency, …). */\n metrics?: Record<string, number>\n}\n\nexport interface PairArmsOptions {\n /** Arm treated as the control side of every pair. */\n baselineArm: string\n /** Arm treated as the treatment side of every pair. */\n treatmentArm: string\n}\n\n/** One matched (baseline, treatment) observation of the same work item. */\nexport interface MatchedPair {\n pairKey: string\n /** 0-based position of this pair within its `pairKey`, ordered by sorted\n * `repKey` (always 0 for a single-rep item). The rep identity itself is on\n * the rows (`baseline.repKey` / `treatment.repKey`). */\n repIndex: number\n baseline: PairedArmRow\n treatment: PairedArmRow\n}\n\nexport interface PairArmsResult {\n /** Matched pairs, ordered by (`pairKey`, `repIndex`). */\n pairs: MatchedPair[]\n /** Baseline rows left without a treatment counterpart — reported, never\n * silently dropped. */\n unpairedBaseline: PairedArmRow[]\n /** Treatment rows left without a baseline counterpart. */\n unpairedTreatment: PairedArmRow[]\n}\n\n/**\n * Match rows across two arms into (baseline, treatment) pairs by `pairKey`.\n *\n * A `pairKey` with at most one row per arm pairs directly, no `repKey`\n * needed. A `pairKey` with multiple reps in either arm requires `repKey` on\n * every one of its rows, and reps pair only on exact (`pairKey`, `repKey`)\n * match — pairing is keyed purely on row identity, never on outcome content\n * (outcome-keyed matching deflates discordant counts and biases McNemar), and\n * is therefore independent of input order. Reps whose `repKey` has no\n * counterpart in the other arm, and items present in only one arm, land in\n * the unpaired lists — reported, never truncated.\n *\n * Fail-loud: throws when either named arm has zero rows (an unknown arm\n * name would otherwise read as \"everything unpaired\"), when the two arm\n * names are equal, when a multi-rep `pairKey` has a row without `repKey`, or\n * when a (`pairKey`, arm) group repeats a `repKey` (the match would be\n * ambiguous).\n */\nexport function pairArms(rows: readonly PairedArmRow[], opts: PairArmsOptions): PairArmsResult {\n const { baselineArm, treatmentArm } = opts\n if (baselineArm === treatmentArm) {\n throw new ValidationError(\n `pairArms: baselineArm and treatmentArm are both '${baselineArm}' — an arm cannot be compared to itself`,\n )\n }\n\n // arm → pairKey → rows\n const byArm = new Map<string, Map<string, PairedArmRow[]>>()\n const armsSeen = new Set<string>()\n for (const row of rows) {\n armsSeen.add(row.arm)\n if (row.arm !== baselineArm && row.arm !== treatmentArm) continue\n const byKey = byArm.get(row.arm) ?? new Map<string, PairedArmRow[]>()\n const group = byKey.get(row.pairKey) ?? []\n group.push(row)\n byKey.set(row.pairKey, group)\n byArm.set(row.arm, byKey)\n }\n\n for (const arm of [baselineArm, treatmentArm]) {\n if (!byArm.has(arm)) {\n const seen = [...armsSeen].sort().join(', ') || '<none>'\n throw new ValidationError(`pairArms: no rows for arm '${arm}' (arms present: ${seen})`)\n }\n }\n\n const baselineByKey = byArm.get(baselineArm)!\n const treatmentByKey = byArm.get(treatmentArm)!\n\n const allKeys = [...new Set([...baselineByKey.keys(), ...treatmentByKey.keys()])].sort()\n const pairs: MatchedPair[] = []\n const unpairedBaseline: PairedArmRow[] = []\n const unpairedTreatment: PairedArmRow[] = []\n for (const pairKey of allKeys) {\n const b = baselineByKey.get(pairKey) ?? []\n const t = treatmentByKey.get(pairKey) ?? []\n\n if (b.length <= 1 && t.length <= 1) {\n if (b.length === 1 && t.length === 1) {\n const baseline = b[0]!\n const treatment = t[0]!\n if (baseline.repKey !== undefined || treatment.repKey !== undefined) {\n if (\n baseline.repKey === undefined ||\n treatment.repKey === undefined ||\n baseline.repKey !== treatment.repKey\n ) {\n unpairedBaseline.push(baseline)\n unpairedTreatment.push(treatment)\n continue\n }\n }\n pairs.push({ pairKey, repIndex: 0, baseline, treatment })\n } else {\n unpairedBaseline.push(...b)\n unpairedTreatment.push(...t)\n }\n continue\n }\n\n const bByRep = indexByRepKey(b, pairKey, baselineArm)\n const tByRep = indexByRepKey(t, pairKey, treatmentArm)\n const repKeys = [...new Set([...bByRep.keys(), ...tByRep.keys()])].sort()\n let repIndex = 0\n for (const repKey of repKeys) {\n const baseline = bByRep.get(repKey)\n const treatment = tByRep.get(repKey)\n if (baseline !== undefined && treatment !== undefined) {\n pairs.push({ pairKey, repIndex: repIndex++, baseline, treatment })\n } else if (baseline !== undefined) {\n unpairedBaseline.push(baseline)\n } else if (treatment !== undefined) {\n unpairedTreatment.push(treatment)\n }\n }\n }\n\n return { pairs, unpairedBaseline, unpairedTreatment }\n}\n\n/** Index a multi-rep (pairKey, arm) group by `repKey`, enforcing that every\n * row carries one and that no repKey repeats within the group. */\nfunction indexByRepKey(\n group: readonly PairedArmRow[],\n pairKey: string,\n arm: string,\n): Map<string, PairedArmRow> {\n const byRep = new Map<string, PairedArmRow>()\n for (const row of group) {\n if (row.repKey === undefined) {\n throw new ValidationError(\n `pairArms: pairKey '${pairKey}' has multiple reps in an arm, but a row in arm '${arm}' ` +\n `is missing repKey — multi-rep items require an explicit repKey on every row so reps ` +\n `pair by identity (pairing reps by outcome or by index would bias the paired statistics)`,\n )\n }\n if (byRep.has(row.repKey)) {\n throw new ValidationError(\n `pairArms: duplicate repKey '${row.repKey}' for pairKey '${pairKey}' in arm '${arm}' — ` +\n `(pairKey, repKey) must uniquely identify a rep within an arm`,\n )\n }\n byRep.set(row.repKey, row)\n }\n return byRep\n}\n\n/** Paired pass/fail comparison over the pairs where BOTH sides carry `pass`. */\nexport interface PairedCorrectness {\n /** Discordant pairs where the treatment passed and the baseline failed. */\n b10: number\n /** Discordant pairs where the baseline passed and the treatment failed. */\n b01: number\n /** Exact McNemar significance over the paired outcomes (`b === b10`, `c === b01`). */\n mcnemar: McNemarResult\n /** Paired effect size: p(treatment) − p(baseline) with a paired-variance CI. */\n riskDifference: RiskDifferenceResult\n}\n\n/** Paired delta summary for one named metric (delta = treatment − baseline). */\nexport interface PairedMetricDelta {\n name: string\n /** Pairs where BOTH sides carry a finite value for this metric. */\n n: number\n /** Pairs where at least one side does not carry the metric. */\n nMissing: number\n /** Median paired delta, or null when `n === 0`. */\n medianDelta: number | null\n /** Mean paired delta, or null when `n === 0`. */\n meanDelta: number | null\n /** Bootstrap CI on the paired delta (`pairedBootstrap`); null when\n * `n === 0` — a zero-width [0, 0] interval on no data would read as a\n * measured tight null. */\n bootstrapCi: PairedBootstrapResult | null\n /** Wilcoxon signed-rank test on the paired deltas; null when `n === 0`. */\n wilcoxon: { w: number; p: number } | null\n}\n\nexport interface ComparePairedArmsOptions extends PairArmsOptions {\n /** Metrics to compare. Default: every metric name observed on any matched\n * pair, sorted. A name that appears on no pair is still reported (with\n * `n = 0`) so a misspelled metric is visible instead of vanishing. */\n metricNames?: string[]\n /** Passed through to `pairedBootstrap` — set `seed` for reproducible CIs. */\n bootstrap?: PairedBootstrapOptions\n}\n\nexport interface PairedArmsComparison {\n nPairs: number\n nUnpairedBaseline: number\n nUnpairedTreatment: number\n /** null when no matched pair carries `pass` on both sides — a pass/fail\n * verdict over rows that never measured pass/fail would be fabricated. */\n correctness: PairedCorrectness | null\n metricDeltas: PairedMetricDelta[]\n}\n\n/**\n * Full matched-pair arm comparison: pair via {@link pairArms}, then compose\n * the paired estimators from `statistics` over the matched pairs.\n *\n * Correctness uses only the pairs where both sides carry `pass` (`mcnemar.n`\n * is that subset's size); each metric uses only the pairs where both sides\n * carry a finite value for it, with the remainder counted in `nMissing`.\n * Deltas are treatment − baseline throughout.\n *\n * Fail-loud: inherits {@link pairArms}'s unknown-arm throw, and throws on a\n * non-finite metric value — silently treating corrupt telemetry as \"metric\n * absent\" would misreport it as missing coverage.\n */\nexport function comparePairedArms(\n rows: readonly PairedArmRow[],\n opts: ComparePairedArmsOptions,\n): PairedArmsComparison {\n const { pairs, unpairedBaseline, unpairedTreatment } = pairArms(rows, opts)\n\n let correctness: PairedCorrectness | null = null\n const baselinePass: number[] = []\n const treatmentPass: number[] = []\n for (const pair of pairs) {\n if (pair.baseline.pass === undefined || pair.treatment.pass === undefined) continue\n baselinePass.push(pair.baseline.pass ? 1 : 0)\n treatmentPass.push(pair.treatment.pass ? 1 : 0)\n }\n if (baselinePass.length > 0) {\n const mc = mcnemar(baselinePass, treatmentPass)\n correctness = {\n b10: mc.b,\n b01: mc.c,\n mcnemar: mc,\n riskDifference: pairedRiskDifference(baselinePass, treatmentPass),\n }\n }\n\n const metricNames =\n opts.metricNames ??\n [\n ...new Set(\n pairs.flatMap((p) => [\n ...Object.keys(p.baseline.metrics ?? {}),\n ...Object.keys(p.treatment.metrics ?? {}),\n ]),\n ),\n ].sort()\n\n const metricDeltas: PairedMetricDelta[] = metricNames.map((name) => {\n const before: number[] = []\n const after: number[] = []\n let nMissing = 0\n for (const pair of pairs) {\n const b = metricValue(pair.baseline, name)\n const t = metricValue(pair.treatment, name)\n if (b === undefined || t === undefined) {\n nMissing++\n continue\n }\n before.push(b)\n after.push(t)\n }\n const bootstrapCi = before.length === 0 ? null : pairedBootstrap(before, after, opts.bootstrap)\n return {\n name,\n n: before.length,\n nMissing,\n medianDelta: bootstrapCi?.median ?? null,\n meanDelta: bootstrapCi?.mean ?? null,\n bootstrapCi,\n wilcoxon: before.length === 0 ? null : wilcoxonSignedRank(before, after),\n }\n })\n\n return {\n nPairs: pairs.length,\n nUnpairedBaseline: unpairedBaseline.length,\n nUnpairedTreatment: unpairedTreatment.length,\n correctness,\n metricDeltas,\n }\n}\n\nexport interface MatchedRunRecordPair {\n pairKey: string\n repKey: string\n baseline: RunRecord\n treatment: RunRecord\n}\n\nexport interface PairRunRecordsResult {\n pairs: MatchedRunRecordPair[]\n unpairedBaseline: RunRecord[]\n unpairedTreatment: RunRecord[]\n}\n\ninterface RunRecordArmRow extends PairedArmRow {\n run: RunRecord\n repKey: string\n}\n\n/**\n * Pair two RunRecord arms by the identity of the evaluated work:\n * `(experimentId, scenarioId, seed)`.\n *\n * Falling back to array order, candidate id, or experiment id can compare\n * different tasks and fabricate lift. Duplicate identities throw.\n */\nexport function pairRunRecords(\n baselineRuns: readonly RunRecord[],\n treatmentRuns: readonly RunRecord[],\n): PairRunRecordsResult {\n const baselineRows = runRecordArmRows(baselineRuns, 'baseline')\n const treatmentRows = runRecordArmRows(treatmentRuns, 'treatment')\n validateRunRecordArmRows(baselineRows, 'baseline')\n validateRunRecordArmRows(treatmentRows, 'treatment')\n if (baselineRows.length === 0 || treatmentRows.length === 0) {\n return {\n pairs: [],\n unpairedBaseline: baselineRows.map((row) => row.run),\n unpairedTreatment: treatmentRows.map((row) => row.run),\n }\n }\n\n const result = pairArms([...baselineRows, ...treatmentRows], {\n baselineArm: 'baseline',\n treatmentArm: 'treatment',\n })\n return {\n pairs: result.pairs.map((pair) => {\n const baseline = pair.baseline as RunRecordArmRow\n const treatment = pair.treatment as RunRecordArmRow\n return {\n pairKey: pair.pairKey,\n repKey: baseline.repKey,\n baseline: baseline.run,\n treatment: treatment.run,\n }\n }),\n unpairedBaseline: result.unpairedBaseline.map((row) => (row as RunRecordArmRow).run),\n unpairedTreatment: result.unpairedTreatment.map((row) => (row as RunRecordArmRow).run),\n }\n}\n\nfunction runRecordArmRows(runs: readonly RunRecord[], arm: string): RunRecordArmRow[] {\n return runs.map((run) => {\n const scenarioId = run.scenarioId.trim()\n if (!scenarioId) {\n throw new ValidationError(\n `pairRunRecords: run '${run.runId}' is missing scenarioId; paired comparisons require explicit scenario identity`,\n )\n }\n return {\n pairKey: JSON.stringify([run.experimentId, scenarioId]),\n repKey: String(run.seed),\n arm,\n run,\n }\n })\n}\n\nfunction validateRunRecordArmRows(rows: readonly RunRecordArmRow[], arm: string): void {\n const byPairKey = new Map<string, RunRecordArmRow[]>()\n for (const row of rows) {\n const group = byPairKey.get(row.pairKey) ?? []\n group.push(row)\n byPairKey.set(row.pairKey, group)\n }\n for (const [pairKey, group] of byPairKey) {\n if (group.length > 1) indexByRepKey(group, pairKey, arm)\n }\n}\n\nfunction metricValue(row: PairedArmRow, name: string): number | undefined {\n const v = row.metrics?.[name]\n if (v === undefined) return undefined\n if (!Number.isFinite(v)) {\n throw new ValidationError(\n `comparePairedArms: non-finite value for metric '${name}' on pairKey '${row.pairKey}' (arm '${row.arm}'): ${v}`,\n )\n }\n return v\n}\n"],"mappings":"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"}
|
package/dist/pipelines/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as executionTrackByLane } from "../execution-tracks-CpgFPpS5.js";
|
|
2
|
-
import {
|
|
2
|
+
import { L as pearsonR, g as interRaterReliability } from "../statistics-CnGCLLqc.js";
|
|
3
3
|
import { s as isToolSpan } from "../schema-CRhEY1SO.js";
|
|
4
4
|
import { t as buildTrajectory } from "../trajectory-D_7rLrvE.js";
|
|
5
|
-
import { t as compareToBaseline } from "../baseline-
|
|
5
|
+
import { t as compareToBaseline } from "../baseline-BUeFcgrn.js";
|
|
6
6
|
import { i as hasCapturedToolArgs, l as toolSpans, n as argHash, o as llmSpans, s as runFailureClass, t as aggregateLlm } from "../query-Di7eEQ79.js";
|
|
7
7
|
import { n as DEFAULT_RULES, r as classifyFailure, t as computeToolUseMetrics } from "../tool-use-metrics-DEGMKycK.js";
|
|
8
8
|
//#region src/pipelines/budget-breach.ts
|
|
@@ -2,7 +2,7 @@ import { c as VerificationError, s as ValidationError } from "./errors-8YnH8WlF.
|
|
|
2
2
|
import { r as observedSplitScore, t as isRealnessGated } from "./reward-nw2xZGZG.js";
|
|
3
3
|
import { t as FAILURE_CLASSES } from "./schema-CRhEY1SO.js";
|
|
4
4
|
import { s as validateRunRecord } from "./run-record-BIwU2wdV.js";
|
|
5
|
-
import { a as summaryTable } from "./summary-report-
|
|
5
|
+
import { a as summaryTable } from "./summary-report-BEk8OFLs.js";
|
|
6
6
|
//#region src/release-confidence.ts
|
|
7
7
|
const DEFAULT_THRESHOLDS = {
|
|
8
8
|
requireCorpus: true,
|
|
@@ -425,7 +425,8 @@ function bootstrapCi(baseline, candidate, options = {}) {
|
|
|
425
425
|
const ciLower = deltas[Math.max(0, lowerIdx)];
|
|
426
426
|
const ciUpper = deltas[Math.min(iterations - 1, upperIdx)];
|
|
427
427
|
let verdict;
|
|
428
|
-
if (ciLower
|
|
428
|
+
if (!Number.isFinite(ciLower) || !Number.isFinite(ciUpper) || ciLower === ciUpper) verdict = "INCONCLUSIVE";
|
|
429
|
+
else if (ciLower > 0) verdict = "ADVANCE";
|
|
429
430
|
else if (ciUpper < 0) verdict = "REVERT";
|
|
430
431
|
else if (delta >= 0) verdict = "KEEP";
|
|
431
432
|
else verdict = "INCONCLUSIVE";
|
|
@@ -600,4 +601,4 @@ function duration(value) {
|
|
|
600
601
|
//#endregion
|
|
601
602
|
export { evaluateReleaseConfidence as a, assertReleaseConfidence as i, bootstrapCi as n, judgeReplayGate as r, renderReleaseReport as t };
|
|
602
603
|
|
|
603
|
-
//# sourceMappingURL=release-report-
|
|
604
|
+
//# sourceMappingURL=release-report-DooPguBc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-report-BVZBmRZp.js","names":[],"sources":["../src/release-confidence.ts","../src/promotion-gate.ts","../src/release-report.ts"],"sourcesContent":["/**\n * Release confidence gate.\n *\n * This is the production-facing composition layer over the lower-level\n * primitives:\n * - Dataset manifests prove corpus/version coverage.\n * - RunRecord rows prove reproducible search/holdout outcomes.\n * - Multi-shot trace evidence carries turn counts and ASI diagnostics.\n * - HeldOutGate decisions remain the paired promotion authority.\n *\n * The gate is intentionally pure and conservative. Missing declared evidence\n * fails closed instead of being treated as a neutral zero.\n */\n\nimport type { DatasetManifest, DatasetScenario, DatasetSplit } from './dataset'\nimport { ValidationError, VerificationError } from './errors'\nimport type { GateDecision } from './held-out-gate'\nimport { isRealnessGated, observedSplitScore } from './rollout/reward'\nimport { type RunRecord, type RunSplitTag, validateRunRecord } from './run-record'\nimport { FAILURE_CLASSES, type FailureClass } from './trace/schema'\n\n/** Severity of an actionable finding attached to a run/trace. */\nexport type AsiSeverity = 'info' | 'warning' | 'error' | 'critical'\n\n/** Actionable side-info — a diagnosed finding the loop can act on. */\nexport interface ActionableSideInfo {\n /** Stable expectation/check id when available. */\n expectationId?: string\n /** Human-readable diagnosis of what happened. */\n message: string\n severity?: AsiSeverity\n /** Concrete trace excerpt, file path, tool call, screenshot id, etc. */\n evidence?: string\n /** Prompt/tool/context surface likely responsible. */\n responsibleSurface?: string\n /** Suggested fix in natural language. */\n suggestion?: string\n /** Whether this expectation was satisfied. Defaults to false for ASI rows. */\n matched?: boolean\n metadata?: Record<string, unknown>\n}\n\nexport type ReleaseConfidenceStatus = 'pass' | 'warn' | 'fail'\nexport type ReleaseConfidenceAxisName =\n | 'corpus'\n | 'quality'\n | 'reliability'\n | 'generalization'\n | 'diagnostics'\n | 'efficiency'\n\nexport interface ReleaseTraceEvidence {\n scenarioId: string\n candidateId?: string\n split?: RunSplitTag\n score?: number\n ok?: boolean\n turnCount?: number\n costUsd?: number\n durationMs?: number\n /** Canonical task-failure class. Free-form detail belongs in ASI. */\n failureClass?: FailureClass\n asi?: ActionableSideInfo[]\n metadata?: Record<string, unknown>\n}\n\nexport interface ReleaseConfidenceThresholds {\n /** Require a Dataset manifest or explicit scenarios. Default true. */\n requireCorpus?: boolean\n minScenarioCount?: number\n minSearchRuns?: number\n minHoldoutRuns?: number\n /** Require at least one holdout scenario/run. Default true. */\n requireHoldout?: boolean\n minPassRate?: number\n minMeanScore?: number\n /** Search mean may exceed holdout mean by at most this much. */\n maxOverfitGap?: number\n maxMeanCostUsd?: number\n maxP95WallMs?: number\n /** Low-score/failed rows must carry ASI. Default true. */\n requireAsiForFailures?: boolean\n /** Score below this is considered a failure for ASI coverage. Default 0.5. */\n failureScoreThreshold?: number\n}\n\nexport interface ReleaseConfidenceInput {\n target: string\n candidateId?: string\n baselineId?: string\n dataset?: DatasetManifest\n scenarios?: readonly DatasetScenario[]\n runs?: readonly RunRecord[]\n traces?: readonly ReleaseTraceEvidence[]\n gateDecision?: GateDecision | null\n thresholds?: ReleaseConfidenceThresholds\n}\n\nexport interface ReleaseConfidenceAxis {\n name: ReleaseConfidenceAxisName\n status: ReleaseConfidenceStatus\n score: number | null\n detail: string\n}\n\nexport interface ReleaseConfidenceIssue {\n axis: ReleaseConfidenceAxisName\n severity: 'critical' | 'warning'\n code: string\n detail: string\n}\n\nexport interface ReleaseConfidenceMetrics {\n scenarioCount: number\n /** Search rows with a finite search score. */\n searchRuns: number\n /** Holdout rows with a finite holdout score. */\n holdoutRuns: number\n /** Runs with neither a split-matched score nor an explicit task failure. */\n unscoredRuns: number\n /** Run rows, or trace rows when no runs exist, with no classified terminal result. */\n unclassifiedTerminalRuns: number\n /** Run rows, or trace rows when no runs exist, that ended unsuccessfully. */\n terminalFailureRuns: number\n /** Success fraction when every run or fallback trace row has a classified result. */\n reliabilityRate: number | null\n passRate: number | null\n meanScore: number | null\n searchMeanScore: number | null\n holdoutMeanScore: number | null\n overfitGap: number | null\n meanCostUsd: number | null\n p95WallMs: number | null\n failedRows: number\n failuresWithAsi: number\n singleShotTraces: number\n multiShotTraces: number\n splitCounts: Record<DatasetSplit, number>\n domainCounts: Record<string, number>\n failureClassCounts: Partial<Record<FailureClass, number>>\n responsibleSurfaceCounts: Record<string, number>\n /**\n * Runs excluded from `passRate` because the authenticity gate flagged them as\n * gamed. Surfaced, never silent: a release whose pass rate is computed over a\n * shrunken denominator has to say by how much, or the exclusion is just a\n * different way of hiding the same runs.\n */\n realnessGatedRuns: number\n}\n\nexport interface ReleaseConfidenceScorecard {\n target: string\n candidateId: string | null\n baselineId: string | null\n status: ReleaseConfidenceStatus\n promote: boolean\n axes: ReleaseConfidenceAxis[]\n issues: ReleaseConfidenceIssue[]\n metrics: ReleaseConfidenceMetrics\n dataset: DatasetManifest | null\n gateDecision: GateDecision | null\n summary: string\n}\n\nconst DEFAULT_THRESHOLDS: Required<ReleaseConfidenceThresholds> = {\n requireCorpus: true,\n minScenarioCount: 1,\n minSearchRuns: 1,\n minHoldoutRuns: 1,\n requireHoldout: true,\n minPassRate: 0.8,\n minMeanScore: 0.7,\n maxOverfitGap: 0.15,\n maxMeanCostUsd: Number.POSITIVE_INFINITY,\n maxP95WallMs: Number.POSITIVE_INFINITY,\n requireAsiForFailures: true,\n failureScoreThreshold: 0.5,\n}\n\nexport function evaluateReleaseConfidence(\n input: ReleaseConfidenceInput,\n): ReleaseConfidenceScorecard {\n const thresholds = { ...DEFAULT_THRESHOLDS, ...input.thresholds }\n const candidateId = input.candidateId ?? null\n const runs = filterCandidate(\n (input.runs ?? []).map(validateRunRecord),\n candidateId,\n input.baselineId,\n )\n const traces = filterTraceCandidate(\n (input.traces ?? []).map(validateReleaseTraceEvidence),\n candidateId,\n input.baselineId,\n )\n const scenarios = input.scenarios ?? []\n const scenarioCount = input.dataset?.scenarioCount ?? scenarios.length\n const splitCounts = input.dataset?.splitCounts ?? countScenarioSplits(scenarios)\n const searchScores = scoresFor(runs, 'search')\n const holdoutScores = scoresFor(runs, 'holdout')\n const runScores = runs.map(runSplitScore).filter(isFiniteNumber)\n const traceScores = traces.map((t) => t.score).filter(isFiniteNumber)\n const scoreUniverse = runs.length > 0 ? runScores : traceScores\n const qualityRuns = runs.filter((run) => runSplitScore(run) !== undefined)\n const unscoredRuns = runs.filter(\n (run) =>\n runSplitScore(run) === undefined &&\n !hasExplicitTaskFailure(run) &&\n !isFailedTerminalOutcome(run.terminalOutcome),\n ).length\n // Realness-gated runs are EXCLUDED from the pass rate — numerator AND\n // denominator — and the count of what was dropped ships beside the rate as\n // `metrics.realnessGatedRuns`. Counting a gamed run as a pass made faking a\n // success the cheapest way to improve a release scorecard; scoring it 0\n // instead would be the other error, silently deflating the rate with a run\n // the gate says carries no usable verdict at all.\n const honestRuns = runs.filter((run) => !isRealnessGated(run))\n const passOutcomes =\n runs.length > 0\n ? honestRuns.map((run) => runPassOutcome(run, thresholds.failureScoreThreshold))\n : traces.map((trace) => tracePassOutcome(trace, thresholds.failureScoreThreshold))\n const reliabilityRows =\n runs.length > 0\n ? runs.map((run) => terminalSuccess(run.terminalOutcome))\n : traces.map((trace) => trace.ok)\n const unclassifiedTerminalRuns = reliabilityRows.filter((outcome) => outcome === undefined).length\n const terminalFailureRuns = reliabilityRows.filter((outcome) => outcome === false).length\n const reliabilityRate =\n reliabilityRows.length === 0 || unclassifiedTerminalRuns > 0\n ? null\n : (reliabilityRows.length - terminalFailureRuns) / reliabilityRows.length\n const searchRuns = qualityRuns.filter((r) => r.splitTag === 'search').length\n const holdoutRuns = qualityRuns.filter((r) => r.splitTag === 'holdout').length\n const failed = failedRows(runs, traces, thresholds.failureScoreThreshold)\n const searchMeanScore = meanOrNull(searchScores)\n const holdoutMeanScore = meanOrNull(holdoutScores)\n const runCosts = runs.flatMap((run) =>\n run.costProvenance.kind === 'uncaptured' ? [] : [run.costProvenance.usd],\n )\n const traceCosts = traces.map((trace) => trace.costUsd).filter(isFiniteNumber)\n const meanCostUsd =\n runs.length > 0\n ? runCosts.length === runs.length\n ? meanOrNull(runCosts)\n : null\n : meanOrNull(traceCosts)\n const wallTimes =\n runs.length > 0\n ? runs.map((run) => run.wallMs)\n : traces.map((trace) => trace.durationMs).filter(isFiniteNumber)\n const metrics: ReleaseConfidenceMetrics = {\n scenarioCount,\n searchRuns,\n holdoutRuns,\n unscoredRuns,\n unclassifiedTerminalRuns,\n terminalFailureRuns,\n reliabilityRate,\n passRate: passOutcomeRate(passOutcomes),\n realnessGatedRuns: runs.length - honestRuns.length,\n meanScore: meanOrNull(scoreUniverse),\n searchMeanScore,\n holdoutMeanScore,\n overfitGap: diffOrNull(searchMeanScore, holdoutMeanScore),\n meanCostUsd,\n p95WallMs: percentileOrNull(wallTimes, 0.95),\n failedRows: failed.length,\n failuresWithAsi: failed.filter((row) => row.hasAsi).length,\n singleShotTraces: traces.filter((t) => t.turnCount === 1).length,\n multiShotTraces: traces.filter((t) => (t.turnCount ?? 0) > 1).length,\n splitCounts,\n domainCounts: countDomains(scenarios),\n failureClassCounts: countFailureClasses(runs, traces, thresholds.failureScoreThreshold),\n responsibleSurfaceCounts: countResponsibleSurfaces(traces),\n }\n\n const issues: ReleaseConfidenceIssue[] = []\n checkCorpus(input, thresholds, metrics, issues)\n checkQuality(thresholds, metrics, issues)\n checkReliability(metrics, issues)\n checkGeneralization(input.gateDecision ?? null, thresholds, metrics, issues)\n checkDiagnostics(thresholds, metrics, issues)\n checkEfficiency(thresholds, metrics, issues)\n\n const axes = buildAxes(metrics, thresholds, issues)\n const status = issues.some((i) => i.severity === 'critical')\n ? 'fail'\n : issues.length > 0\n ? 'warn'\n : 'pass'\n\n return {\n target: input.target,\n candidateId,\n baselineId: input.baselineId ?? null,\n status,\n promote: status === 'pass' && (input.gateDecision ? input.gateDecision.promote : true),\n axes,\n issues,\n metrics,\n dataset: input.dataset ?? null,\n gateDecision: input.gateDecision ?? null,\n summary: renderSummary(input.target, status, metrics, issues),\n }\n}\n\nexport function assertReleaseConfidence(input: ReleaseConfidenceInput): ReleaseConfidenceScorecard {\n const scorecard = evaluateReleaseConfidence(input)\n if (scorecard.status === 'fail') {\n throw new VerificationError(scorecard.summary)\n }\n return scorecard\n}\n\nfunction filterCandidate(\n runs: readonly RunRecord[],\n candidateId: string | null,\n baselineId?: string,\n): RunRecord[] {\n if (candidateId) return runs.filter((r) => r.candidateId === candidateId)\n if (baselineId) return runs.filter((r) => r.candidateId !== baselineId)\n return [...runs]\n}\n\nfunction filterTraceCandidate(\n traces: readonly ReleaseTraceEvidence[],\n candidateId: string | null,\n baselineId?: string,\n): ReleaseTraceEvidence[] {\n if (candidateId)\n return traces.filter((t) => t.candidateId === undefined || t.candidateId === candidateId)\n if (baselineId)\n return traces.filter((t) => t.candidateId === undefined || t.candidateId !== baselineId)\n return [...traces]\n}\n\nfunction validateReleaseTraceEvidence(\n trace: ReleaseTraceEvidence,\n index: number,\n): ReleaseTraceEvidence {\n const value = trace as unknown as Record<string, unknown>\n if (Object.hasOwn(value, 'failureMode')) {\n throw new ValidationError(\n `traces[${index}].failureMode is not supported; use canonical failureClass`,\n )\n }\n if (trace.failureClass !== undefined && !FAILURE_CLASSES.includes(trace.failureClass)) {\n throw new ValidationError(\n `traces[${index}].failureClass must be one of ${FAILURE_CLASSES.join(', ')}`,\n )\n }\n return trace\n}\n\nfunction checkCorpus(\n input: ReleaseConfidenceInput,\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (thresholds.requireCorpus && !input.dataset && (input.scenarios?.length ?? 0) === 0) {\n issues.push({\n axis: 'corpus',\n severity: 'critical',\n code: 'missing_corpus',\n detail: 'No Dataset manifest or scenarios supplied.',\n })\n }\n if (metrics.scenarioCount < thresholds.minScenarioCount) {\n issues.push({\n axis: 'corpus',\n severity: 'critical',\n code: 'few_scenarios',\n detail: `${metrics.scenarioCount} scenario(s) < min ${thresholds.minScenarioCount}.`,\n })\n }\n if (thresholds.requireHoldout && metrics.splitCounts.holdout === 0) {\n issues.push({\n axis: 'corpus',\n severity: 'critical',\n code: 'missing_holdout_split',\n detail: 'Corpus has no holdout scenarios.',\n })\n }\n}\n\nfunction checkQuality(\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (metrics.searchRuns < thresholds.minSearchRuns) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'few_search_runs',\n detail: `${metrics.searchRuns} search run(s) < min ${thresholds.minSearchRuns}.`,\n })\n }\n if (metrics.unscoredRuns > 0) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'unscored_runs',\n detail: `${metrics.unscoredRuns} supplied run(s) have no task result.`,\n })\n }\n if (metrics.passRate === null || metrics.meanScore === null) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'missing_quality_scores',\n detail: 'No task-quality scores are available for pass-rate and mean-score checks.',\n })\n }\n if (metrics.passRate !== null && metrics.passRate < thresholds.minPassRate) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'low_pass_rate',\n detail: `passRate ${fmt(metrics.passRate)} < ${fmt(thresholds.minPassRate)}.`,\n })\n }\n if (metrics.meanScore !== null && metrics.meanScore < thresholds.minMeanScore) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'low_mean_score',\n detail: `meanScore ${fmt(metrics.meanScore)} < ${fmt(thresholds.minMeanScore)}.`,\n })\n }\n}\n\nfunction checkReliability(\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (metrics.reliabilityRate === null) {\n issues.push({\n axis: 'reliability',\n severity: 'critical',\n code: 'missing_reliability_evidence',\n detail:\n metrics.unclassifiedTerminalRuns > 0\n ? `${metrics.unclassifiedTerminalRuns} supplied run(s) have no classified terminal result.`\n : 'No classified terminal results are available.',\n })\n }\n if (metrics.terminalFailureRuns > 0) {\n issues.push({\n axis: 'reliability',\n severity: 'critical',\n code: 'terminal_run_failures',\n detail: `${metrics.terminalFailureRuns} run(s) ended failed, cancelled, or incomplete.`,\n })\n }\n}\n\nfunction checkGeneralization(\n gateDecision: GateDecision | null,\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (thresholds.requireHoldout && metrics.holdoutRuns < thresholds.minHoldoutRuns) {\n issues.push({\n axis: 'generalization',\n severity: 'critical',\n code: 'few_holdout_runs',\n detail: `${metrics.holdoutRuns} holdout run(s) < min ${thresholds.minHoldoutRuns}.`,\n })\n }\n if (metrics.overfitGap !== null && metrics.overfitGap > thresholds.maxOverfitGap) {\n issues.push({\n axis: 'generalization',\n severity: 'critical',\n code: 'overfit_gap',\n detail: `search-holdout gap ${fmt(metrics.overfitGap)} > ${fmt(thresholds.maxOverfitGap)}.`,\n })\n }\n if (gateDecision && !gateDecision.promote) {\n issues.push({\n axis: 'generalization',\n severity: 'critical',\n code: `gate_${gateDecision.rejectionCode ?? 'reject'}`,\n detail: gateDecision.reason,\n })\n }\n}\n\nfunction checkDiagnostics(\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (!thresholds.requireAsiForFailures) return\n if (metrics.failedRows > metrics.failuresWithAsi) {\n issues.push({\n axis: 'diagnostics',\n severity: 'critical',\n code: 'missing_failure_asi',\n detail: `${metrics.failedRows - metrics.failuresWithAsi} failed row(s) have no actionable side information.`,\n })\n }\n}\n\nfunction checkEfficiency(\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (Number.isFinite(thresholds.maxMeanCostUsd) && metrics.meanCostUsd === null) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'missing_cost',\n detail: 'A finite cost limit was configured but no cost evidence is available.',\n })\n } else if (metrics.meanCostUsd !== null && metrics.meanCostUsd > thresholds.maxMeanCostUsd) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'cost_budget',\n detail: `meanCostUsd ${fmt(metrics.meanCostUsd)} > ${fmt(thresholds.maxMeanCostUsd)}.`,\n })\n }\n if (Number.isFinite(thresholds.maxP95WallMs) && metrics.p95WallMs === null) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'missing_latency',\n detail: 'A finite latency limit was configured but no latency evidence is available.',\n })\n } else if (metrics.p95WallMs !== null && metrics.p95WallMs > thresholds.maxP95WallMs) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'latency_budget',\n detail: `p95WallMs ${fmt(metrics.p95WallMs)} > ${fmt(thresholds.maxP95WallMs)}.`,\n })\n }\n}\n\nfunction buildAxes(\n metrics: ReleaseConfidenceMetrics,\n thresholds: Required<ReleaseConfidenceThresholds>,\n issues: ReleaseConfidenceIssue[],\n): ReleaseConfidenceAxis[] {\n return [\n axis(\n 'corpus',\n issues,\n bounded(metrics.scenarioCount / Math.max(1, thresholds.minScenarioCount)),\n `${metrics.scenarioCount} scenarios; holdout=${metrics.splitCounts.holdout}`,\n ),\n axis(\n 'quality',\n issues,\n metrics.passRate === null || metrics.meanScore === null\n ? null\n : Math.min(metrics.passRate, metrics.meanScore),\n `passRate=${fmt(metrics.passRate)} meanScore=${fmt(metrics.meanScore)}`,\n ),\n axis(\n 'reliability',\n issues,\n metrics.reliabilityRate,\n `successRate=${fmt(metrics.reliabilityRate)} terminalFailures=${metrics.terminalFailureRuns} unclassified=${metrics.unclassifiedTerminalRuns}`,\n ),\n axis(\n 'generalization',\n issues,\n gapScore(metrics.overfitGap, thresholds.maxOverfitGap),\n `holdoutRuns=${metrics.holdoutRuns} overfitGap=${fmt(metrics.overfitGap)}`,\n ),\n axis(\n 'diagnostics',\n issues,\n metrics.failedRows === 0 ? 1 : metrics.failuresWithAsi / metrics.failedRows,\n `failuresWithAsi=${metrics.failuresWithAsi}/${metrics.failedRows}`,\n ),\n axis(\n 'efficiency',\n issues,\n efficiencyScore(metrics, thresholds),\n `meanCostUsd=${fmt(metrics.meanCostUsd)} p95WallMs=${fmt(metrics.p95WallMs)}`,\n ),\n ]\n}\n\nfunction axis(\n name: ReleaseConfidenceAxisName,\n issues: ReleaseConfidenceIssue[],\n score: number | null,\n detail: string,\n): ReleaseConfidenceAxis {\n const own = issues.filter((i) => i.axis === name)\n const status = own.some((i) => i.severity === 'critical')\n ? 'fail'\n : own.length > 0\n ? 'warn'\n : 'pass'\n return { name, status, score: score === null ? null : bounded(score), detail }\n}\n\nfunction countScenarioSplits(scenarios: readonly DatasetScenario[]): Record<DatasetSplit, number> {\n const counts: Record<DatasetSplit, number> = { train: 0, dev: 0, test: 0, holdout: 0 }\n for (const scenario of scenarios) counts[scenario.split ?? 'train']++\n return counts\n}\n\nfunction countDomains(scenarios: readonly DatasetScenario[]): Record<string, number> {\n const out: Record<string, number> = {}\n for (const scenario of scenarios) {\n const domain = scenario.tags?.domain ?? scenario.tags?.category ?? 'uncategorized'\n out[domain] = (out[domain] ?? 0) + 1\n }\n return out\n}\n\nfunction countFailureClasses(\n runs: readonly RunRecord[],\n traces: readonly ReleaseTraceEvidence[],\n threshold: number,\n): Partial<Record<FailureClass, number>> {\n const out: Partial<Record<FailureClass, number>> = {}\n for (const run of runs) {\n // Ungated: a failure-mode census counts what the runs REPORTED, which is\n // the only way a gamed run's inflated score is visible at all. It is not a\n // promotion number — `passRate` is, and that one excludes gated runs and\n // publishes the excluded count as `metrics.realnessGatedRuns`.\n if (runPassOutcome(run, threshold) === false) {\n const failureClass =\n run.failureClass !== undefined && run.failureClass !== 'success'\n ? run.failureClass\n : 'unknown'\n out[failureClass] = (out[failureClass] ?? 0) + 1\n }\n }\n for (const trace of traces) {\n if (tracePassOutcome(trace, threshold) === false) {\n const failureClass =\n trace.failureClass !== undefined && trace.failureClass !== 'success'\n ? trace.failureClass\n : 'unknown'\n out[failureClass] = (out[failureClass] ?? 0) + 1\n }\n }\n return out\n}\n\nfunction countResponsibleSurfaces(traces: readonly ReleaseTraceEvidence[]): Record<string, number> {\n const out: Record<string, number> = {}\n for (const trace of traces) {\n for (const asi of trace.asi ?? []) {\n const surface = asi.responsibleSurface ?? 'unknown'\n out[surface] = (out[surface] ?? 0) + 1\n }\n }\n return out\n}\n\nfunction failedRows(\n runs: readonly RunRecord[],\n traces: readonly ReleaseTraceEvidence[],\n threshold: number,\n): Array<{ hasAsi: boolean }> {\n const out: Array<{ hasAsi: boolean }> = []\n for (const run of runs) {\n if (runPassOutcome(run, threshold) === false) {\n const asiMetric = run.outcome.raw.asi\n out.push({ hasAsi: typeof asiMetric === 'number' && asiMetric > 0 })\n }\n }\n for (const trace of traces) {\n if (tracePassOutcome(trace, threshold) === false) {\n out.push({ hasAsi: (trace.asi?.length ?? 0) > 0 })\n }\n }\n return out\n}\n\nfunction passOutcomeRate(outcomes: readonly (boolean | null)[]): number | null {\n const classified = outcomes.filter((outcome): outcome is boolean => outcome !== null)\n if (classified.length === 0) return null\n return classified.filter(Boolean).length / classified.length\n}\n\nfunction runPassOutcome(run: RunRecord, threshold: number): boolean | null {\n if (hasExplicitTaskFailure(run)) return false\n const score = runSplitScore(run)\n return score === undefined ? null : score >= threshold\n}\n\nfunction hasExplicitTaskFailure(run: RunRecord): boolean {\n return run.failureClass !== undefined && run.failureClass !== 'success'\n}\n\nfunction tracePassOutcome(trace: ReleaseTraceEvidence, threshold: number): boolean | null {\n if (trace.failureClass !== undefined && trace.failureClass !== 'success') return false\n if (trace.ok === false) return false\n if (isFiniteNumber(trace.score)) return trace.score >= threshold\n return trace.ok === true ? true : null\n}\n\nfunction isFailedTerminalOutcome(\n outcome: RunRecord['terminalOutcome'],\n): outcome is 'failed' | 'cancelled' | 'incomplete' {\n return outcome === 'failed' || outcome === 'cancelled' || outcome === 'incomplete'\n}\n\nfunction terminalSuccess(outcome: RunRecord['terminalOutcome']): boolean | undefined {\n if (outcome === 'succeeded') return true\n if (isFailedTerminalOutcome(outcome)) return false\n return undefined\n}\n\nfunction scoresFor(runs: readonly RunRecord[], split: RunSplitTag): number[] {\n return runs\n .filter((run) => run.splitTag === split)\n .map(runSplitScore)\n .filter(isFiniteNumber)\n}\n\n/**\n * RAW and split-exact (`observedSplitScore`): this feeds the per-split means,\n * the overfit gap, and the pass threshold — descriptions of what the runs\n * reported. A gamed run inflating them is visible next to `realnessGatedRuns`,\n * and the promotion number (`passRate`) excludes gated runs entirely.\n */\nfunction runSplitScore(run: RunRecord): number | undefined {\n const score = observedSplitScore(run, run.splitTag === 'holdout' ? 'holdout' : 'search')\n return isFiniteNumber(score) ? score : undefined\n}\n\nfunction meanOrNull(xs: readonly number[]): number | null {\n if (xs.length === 0) return null\n return xs.reduce((sum, x) => sum + x, 0) / xs.length\n}\n\nfunction percentileOrNull(xs: readonly number[], p: number): number | null {\n if (xs.length === 0) return null\n const sorted = [...xs].sort((a, b) => a - b)\n return sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(p * sorted.length) - 1))]!\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction diffOrNull(a: number | null, b: number | null): number | null {\n if (a === null || b === null) return null\n return a - b\n}\n\nfunction gapScore(gap: number | null, maxGap: number): number | null {\n if (gap === null) return null\n if (maxGap <= 0) return gap <= 0 ? 1 : 0\n return bounded(1 - Math.max(0, gap) / maxGap)\n}\n\nfunction efficiencyScore(\n metrics: ReleaseConfidenceMetrics,\n thresholds: Required<ReleaseConfidenceThresholds>,\n): number | null {\n const cost = Number.isFinite(thresholds.maxMeanCostUsd)\n ? metrics.meanCostUsd === null\n ? null\n : bounded(thresholds.maxMeanCostUsd / Math.max(metrics.meanCostUsd, 1e-12))\n : 1\n const latency = Number.isFinite(thresholds.maxP95WallMs)\n ? metrics.p95WallMs === null\n ? null\n : bounded(thresholds.maxP95WallMs / Math.max(metrics.p95WallMs, 1e-12))\n : 1\n if (cost === null || latency === null) return null\n return Math.min(cost, latency)\n}\n\nfunction bounded(x: number): number {\n if (!Number.isFinite(x)) return 0\n return Math.max(0, Math.min(1, x))\n}\n\nfunction renderSummary(\n target: string,\n status: ReleaseConfidenceStatus,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): string {\n const prefix = `release confidence ${status}: ${target}`\n const metricText = `scenarios=${metrics.scenarioCount} searchRuns=${metrics.searchRuns} holdoutRuns=${metrics.holdoutRuns} passRate=${fmt(metrics.passRate)} meanScore=${fmt(metrics.meanScore)}`\n if (issues.length === 0) return `${prefix}; ${metricText}`\n return `${prefix}; ${metricText}; issues=${issues.map((i) => i.code).join(',')}`\n}\n\nfunction fmt(x: number | null): string {\n if (x === null) return 'n/a'\n return x.toFixed(4)\n}\n","/**\n * Bootstrap-CI promotion gate.\n *\n * In any iterative-improvement loop (GEPA, prompt evolution, dataset\n * curation), the question is \"did this generation actually improve, or are\n * we celebrating noise?\". With small N and noisy outcomes, point-estimate\n * deltas lie. Bootstrap confidence intervals tell the operator whether the\n * delta is real before code or prompts get promoted.\n *\n * This module is pure functions — no I/O, no model calls. Easy to unit-test\n * and to compose into any verdict gate.\n *\n * Default gate:\n * - Bootstrap mean baseline vs candidate (1k resamples).\n * - Compute the delta distribution; pass if the lower CI bound > 0.\n * - Tunable confidence (default 95%) and resample count.\n *\n * Verdict semantics intentionally match the existing `experiments.jsonl`\n * vocabulary:\n * - ADVANCE: candidate's CI lower bound > baseline mean (real win)\n * - KEEP: overlap, but candidate point estimate >= baseline (neutral)\n * - REVERT: candidate's CI upper bound < baseline mean (real regression)\n * - INCONCLUSIVE: not enough samples or CI straddles zero with no signal\n */\n\nexport type Verdict = 'ADVANCE' | 'KEEP' | 'REVERT' | 'INCONCLUSIVE'\n\nexport interface BootstrapResult {\n baselineMean: number\n candidateMean: number\n /** candidateMean - baselineMean, point estimate. */\n delta: number\n /** Lower bound of the (1 - alpha) CI on the delta. */\n ciLower: number\n /** Upper bound of the (1 - alpha) CI on the delta. */\n ciUpper: number\n /** Number of bootstrap resamples used. */\n iterations: number\n alpha: number\n verdict: Verdict\n}\n\nexport interface BootstrapOptions {\n /** Confidence level alpha (default 0.05 → 95% CI). */\n alpha?: number\n /** Number of resamples (default 1000). */\n iterations?: number\n /**\n * Minimum total samples (baseline + candidate) below which we always\n * return INCONCLUSIVE — bootstrap with too few samples is meaningless.\n * Default 6 (combined).\n */\n minTotalSamples?: number\n /** RNG seed for reproducibility. Default: Math.random. */\n seed?: number\n}\n\n/**\n * Compute the bootstrap CI on (candidateMean - baselineMean) and a verdict.\n *\n * Uses simple percentile bootstrap on the difference of resampled means.\n * That's the standard non-parametric primitive — no distributional\n * assumptions, robust to skew, easy to reason about.\n */\nexport function bootstrapCi(\n baseline: number[],\n candidate: number[],\n options: BootstrapOptions = {},\n): BootstrapResult {\n const alpha = options.alpha ?? 0.05\n const iterations = options.iterations ?? 1000\n const minTotal = options.minTotalSamples ?? 6\n const rng = mulberry32(options.seed ?? hashSeed(baseline, candidate))\n\n const baselineMean = mean(baseline)\n const candidateMean = mean(candidate)\n const delta = candidateMean - baselineMean\n\n if (\n baseline.length + candidate.length < minTotal ||\n baseline.length === 0 ||\n candidate.length === 0\n ) {\n return {\n baselineMean,\n candidateMean,\n delta,\n ciLower: -Infinity,\n ciUpper: Infinity,\n iterations: 0,\n alpha,\n verdict: 'INCONCLUSIVE',\n }\n }\n\n const deltas: number[] = new Array(iterations)\n for (let i = 0; i < iterations; i++) {\n const bResample = resample(baseline, rng)\n const cResample = resample(candidate, rng)\n deltas[i] = mean(cResample) - mean(bResample)\n }\n deltas.sort((a, b) => a - b)\n const lowerIdx = Math.floor((alpha / 2) * iterations)\n const upperIdx = Math.floor((1 - alpha / 2) * iterations) - 1\n const ciLower = deltas[Math.max(0, lowerIdx)]!\n const ciUpper = deltas[Math.min(iterations - 1, upperIdx)]!\n\n let verdict: Verdict\n if (ciLower > 0) verdict = 'ADVANCE'\n else if (ciUpper < 0) verdict = 'REVERT'\n else if (delta >= 0) verdict = 'KEEP'\n else verdict = 'INCONCLUSIVE'\n\n return {\n baselineMean,\n candidateMean,\n delta,\n ciLower,\n ciUpper,\n iterations,\n alpha,\n verdict,\n }\n}\n\nfunction mean(xs: number[]): number {\n if (xs.length === 0) return 0\n let s = 0\n for (const x of xs) s += x\n return s / xs.length\n}\n\nfunction resample(xs: number[], rng: () => number): number[] {\n const out = new Array(xs.length)\n for (let i = 0; i < xs.length; i++) out[i] = xs[Math.floor(rng() * xs.length)]\n return out\n}\n\n/** Mulberry32 — fast deterministic PRNG. Stable across runs given the same seed. */\nfunction mulberry32(seed: number): () => number {\n let t = seed >>> 0\n return () => {\n t += 0x6d2b79f5\n let r = t\n r = Math.imul(r ^ (r >>> 15), r | 1)\n r ^= r + Math.imul(r ^ (r >>> 7), r | 61)\n return ((r ^ (r >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** Stable seed derived from the inputs — same data → same CI bounds. */\nfunction hashSeed(a: number[], b: number[]): number {\n let h = 2166136261\n for (const x of [...a, ...b]) {\n const view = new Float64Array([x])\n const bytes = new Uint8Array(view.buffer)\n for (const byte of bytes) {\n h ^= byte\n h = Math.imul(h, 16777619)\n }\n }\n return h >>> 0\n}\n\n/**\n * Judge-replay promotion gate.\n *\n * The cheap inner-loop judge that drives an evolution run is by definition\n * fast and noisy. When you're about to promote a winning variant to the\n * canonical default, you want a STRONGER judge (a more expensive model, a\n * human grader, a separately-trained reward model) to confirm the win\n * generalises beyond the inner loop.\n *\n * This helper takes raw winner + baseline outputs, scores both through the\n * stronger judge, and applies `bootstrapCi`. ADVANCE means the stronger\n * judge agrees the winner is real with the configured confidence. Doesn't\n * matter what shape your \"output\" is — pass a string, an object, anything\n * the judge can read.\n */\nexport interface JudgeReplayGateArgs<TOutput> {\n baselineOutputs: TOutput[]\n candidateOutputs: TOutput[]\n /** Stronger judge — async to allow LLM calls. Return a 0..N scalar score. */\n judge: (output: TOutput) => Promise<number> | number\n alpha?: number\n iterations?: number\n /** RNG seed for reproducibility. */\n seed?: number\n /** Maximum concurrent judge calls. Default 4. */\n judgeConcurrency?: number\n}\n\n/**\n * Confirm a candidate's win with a stronger judge: score baseline and candidate outputs independently, then bootstrap a CI to verify the lift generalises beyond the inner loop.\n */\nexport async function judgeReplayGate<TOutput>(\n args: JudgeReplayGateArgs<TOutput>,\n): Promise<BootstrapResult & { baselineSamples: number; candidateSamples: number }> {\n const concurrency = args.judgeConcurrency ?? 4\n const baselineScores = await scoreAll(args.baselineOutputs, args.judge, concurrency)\n const candidateScores = await scoreAll(args.candidateOutputs, args.judge, concurrency)\n const ci = bootstrapCi(baselineScores, candidateScores, {\n ...(args.alpha !== undefined ? { alpha: args.alpha } : {}),\n ...(args.iterations !== undefined ? { iterations: args.iterations } : {}),\n ...(args.seed !== undefined ? { seed: args.seed } : {}),\n })\n return {\n ...ci,\n baselineSamples: baselineScores.length,\n candidateSamples: candidateScores.length,\n }\n}\n\nasync function scoreAll<TOutput>(\n outputs: TOutput[],\n judge: (output: TOutput) => Promise<number> | number,\n concurrency: number,\n): Promise<number[]> {\n const results: number[] = new Array(outputs.length)\n let next = 0\n async function worker(): Promise<void> {\n while (true) {\n const i = next++\n if (i >= outputs.length) return\n const v = await judge(outputs[i]!)\n results[i] = Number.isFinite(v) ? v : 0\n }\n }\n await Promise.all(Array.from({ length: Math.max(1, concurrency) }, () => worker()))\n return results\n}\n","import type { ReleaseConfidenceScorecard } from './release-confidence'\nimport type { RunRecord } from './run-record'\nimport { summaryTable } from './summary-report'\n\nexport interface RenderReleaseReportOptions {\n title?: string\n runs?: readonly RunRecord[]\n comparator?: string\n traceAnalystFindings?: readonly string[]\n nextActions?: readonly string[]\n}\n\nexport function renderReleaseReport(\n scorecard: ReleaseConfidenceScorecard,\n options: RenderReleaseReportOptions = {},\n): string {\n const title = options.title ?? `Release Report: ${scorecard.target}`\n const lines: string[] = []\n lines.push(`# ${title}`)\n lines.push('')\n lines.push(`Status: **${scorecard.status.toUpperCase()}**`)\n lines.push(`Promote: **${scorecard.promote ? 'yes' : 'no'}**`)\n if (scorecard.candidateId) lines.push(`Candidate: \\`${scorecard.candidateId}\\``)\n if (scorecard.baselineId) lines.push(`Baseline: \\`${scorecard.baselineId}\\``)\n lines.push('')\n lines.push(scorecard.summary)\n lines.push('')\n\n lines.push('## Metrics')\n lines.push('')\n lines.push('| Metric | Value |')\n lines.push('|---|---:|')\n lines.push(`| Scenarios | ${scorecard.metrics.scenarioCount} |`)\n lines.push(`| Search runs | ${scorecard.metrics.searchRuns} |`)\n lines.push(`| Holdout runs | ${scorecard.metrics.holdoutRuns} |`)\n lines.push(`| Unscored runs | ${scorecard.metrics.unscoredRuns} |`)\n lines.push(`| Terminal failures | ${scorecard.metrics.terminalFailureRuns} |`)\n lines.push(`| Pass rate | ${pct(scorecard.metrics.passRate)} |`)\n lines.push(`| Mean score | ${num(scorecard.metrics.meanScore)} |`)\n lines.push(`| Search mean | ${num(scorecard.metrics.searchMeanScore)} |`)\n lines.push(`| Holdout mean | ${num(scorecard.metrics.holdoutMeanScore)} |`)\n lines.push(`| Overfit gap | ${num(scorecard.metrics.overfitGap)} |`)\n lines.push(`| Mean cost | $${num(scorecard.metrics.meanCostUsd)} |`)\n lines.push(`| p95 wall time | ${duration(scorecard.metrics.p95WallMs)} |`)\n lines.push('')\n\n if (scorecard.issues.length > 0) {\n lines.push('## Issues')\n lines.push('')\n for (const issue of scorecard.issues) {\n lines.push(`- **${issue.severity}** \\`${issue.code}\\` (${issue.axis}): ${issue.detail}`)\n }\n lines.push('')\n }\n\n const surfaces = entries(scorecard.metrics.responsibleSurfaceCounts)\n if (surfaces.length > 0) {\n lines.push('## Responsible Surfaces')\n lines.push('')\n for (const [surface, count] of surfaces) lines.push(`- ${surface}: ${count}`)\n lines.push('')\n }\n\n const failures = entries(scorecard.metrics.failureClassCounts)\n if (failures.length > 0) {\n lines.push('## Failure Classes')\n lines.push('')\n for (const [mode, count] of failures) lines.push(`- ${mode}: ${count}`)\n lines.push('')\n }\n\n if (options.runs && options.runs.length > 0) {\n lines.push('## Run Summary')\n lines.push('')\n lines.push(\n summaryTable([...options.runs], {\n comparator: options.comparator ?? scorecard.baselineId ?? undefined,\n split: 'holdout',\n }).markdown,\n )\n lines.push('')\n }\n\n if (options.traceAnalystFindings && options.traceAnalystFindings.length > 0) {\n lines.push('## TraceAnalyst Findings')\n lines.push('')\n for (const finding of options.traceAnalystFindings) lines.push(`- ${finding}`)\n lines.push('')\n }\n\n const nextActions = options.nextActions ?? defaultNextActions(scorecard)\n if (nextActions.length > 0) {\n lines.push('## Next Actions')\n lines.push('')\n for (const action of nextActions) lines.push(`- ${action}`)\n lines.push('')\n }\n\n return `${lines.join('\\n').trimEnd()}\\n`\n}\n\nfunction defaultNextActions(scorecard: ReleaseConfidenceScorecard): string[] {\n if (scorecard.promote) return ['Promote the candidate and keep canaries enabled.']\n return scorecard.issues\n .filter((issue) => issue.severity === 'critical')\n .map((issue) => `Resolve ${issue.code}: ${issue.detail}`)\n}\n\nfunction entries(values: Record<string, number>): Array<[string, number]> {\n return Object.entries(values)\n .filter(([, count]) => count > 0)\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n}\n\nfunction pct(value: number | null): string {\n return value === null ? 'n/a' : `${(value * 100).toFixed(1)}%`\n}\n\nfunction num(value: number | null): string {\n return value === null ? 'n/a' : value.toFixed(3)\n}\n\nfunction duration(value: number | null): string {\n return value === null ? 'n/a' : `${Math.round(value)} ms`\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"release-report-DooPguBc.js","names":[],"sources":["../src/release-confidence.ts","../src/promotion-gate.ts","../src/release-report.ts"],"sourcesContent":["/**\n * Release confidence gate.\n *\n * This is the production-facing composition layer over the lower-level\n * primitives:\n * - Dataset manifests prove corpus/version coverage.\n * - RunRecord rows prove reproducible search/holdout outcomes.\n * - Multi-shot trace evidence carries turn counts and ASI diagnostics.\n * - HeldOutGate decisions remain the paired promotion authority.\n *\n * The gate is intentionally pure and conservative. Missing declared evidence\n * fails closed instead of being treated as a neutral zero.\n */\n\nimport type { DatasetManifest, DatasetScenario, DatasetSplit } from './dataset'\nimport { ValidationError, VerificationError } from './errors'\nimport type { GateDecision } from './held-out-gate'\nimport { isRealnessGated, observedSplitScore } from './rollout/reward'\nimport { type RunRecord, type RunSplitTag, validateRunRecord } from './run-record'\nimport { FAILURE_CLASSES, type FailureClass } from './trace/schema'\n\n/** Severity of an actionable finding attached to a run/trace. */\nexport type AsiSeverity = 'info' | 'warning' | 'error' | 'critical'\n\n/** Actionable side-info — a diagnosed finding the loop can act on. */\nexport interface ActionableSideInfo {\n /** Stable expectation/check id when available. */\n expectationId?: string\n /** Human-readable diagnosis of what happened. */\n message: string\n severity?: AsiSeverity\n /** Concrete trace excerpt, file path, tool call, screenshot id, etc. */\n evidence?: string\n /** Prompt/tool/context surface likely responsible. */\n responsibleSurface?: string\n /** Suggested fix in natural language. */\n suggestion?: string\n /** Whether this expectation was satisfied. Defaults to false for ASI rows. */\n matched?: boolean\n metadata?: Record<string, unknown>\n}\n\nexport type ReleaseConfidenceStatus = 'pass' | 'warn' | 'fail'\nexport type ReleaseConfidenceAxisName =\n | 'corpus'\n | 'quality'\n | 'reliability'\n | 'generalization'\n | 'diagnostics'\n | 'efficiency'\n\nexport interface ReleaseTraceEvidence {\n scenarioId: string\n candidateId?: string\n split?: RunSplitTag\n score?: number\n ok?: boolean\n turnCount?: number\n costUsd?: number\n durationMs?: number\n /** Canonical task-failure class. Free-form detail belongs in ASI. */\n failureClass?: FailureClass\n asi?: ActionableSideInfo[]\n metadata?: Record<string, unknown>\n}\n\nexport interface ReleaseConfidenceThresholds {\n /** Require a Dataset manifest or explicit scenarios. Default true. */\n requireCorpus?: boolean\n minScenarioCount?: number\n minSearchRuns?: number\n minHoldoutRuns?: number\n /** Require at least one holdout scenario/run. Default true. */\n requireHoldout?: boolean\n minPassRate?: number\n minMeanScore?: number\n /** Search mean may exceed holdout mean by at most this much. */\n maxOverfitGap?: number\n maxMeanCostUsd?: number\n maxP95WallMs?: number\n /** Low-score/failed rows must carry ASI. Default true. */\n requireAsiForFailures?: boolean\n /** Score below this is considered a failure for ASI coverage. Default 0.5. */\n failureScoreThreshold?: number\n}\n\nexport interface ReleaseConfidenceInput {\n target: string\n candidateId?: string\n baselineId?: string\n dataset?: DatasetManifest\n scenarios?: readonly DatasetScenario[]\n runs?: readonly RunRecord[]\n traces?: readonly ReleaseTraceEvidence[]\n gateDecision?: GateDecision | null\n thresholds?: ReleaseConfidenceThresholds\n}\n\nexport interface ReleaseConfidenceAxis {\n name: ReleaseConfidenceAxisName\n status: ReleaseConfidenceStatus\n score: number | null\n detail: string\n}\n\nexport interface ReleaseConfidenceIssue {\n axis: ReleaseConfidenceAxisName\n severity: 'critical' | 'warning'\n code: string\n detail: string\n}\n\nexport interface ReleaseConfidenceMetrics {\n scenarioCount: number\n /** Search rows with a finite search score. */\n searchRuns: number\n /** Holdout rows with a finite holdout score. */\n holdoutRuns: number\n /** Runs with neither a split-matched score nor an explicit task failure. */\n unscoredRuns: number\n /** Run rows, or trace rows when no runs exist, with no classified terminal result. */\n unclassifiedTerminalRuns: number\n /** Run rows, or trace rows when no runs exist, that ended unsuccessfully. */\n terminalFailureRuns: number\n /** Success fraction when every run or fallback trace row has a classified result. */\n reliabilityRate: number | null\n passRate: number | null\n meanScore: number | null\n searchMeanScore: number | null\n holdoutMeanScore: number | null\n overfitGap: number | null\n meanCostUsd: number | null\n p95WallMs: number | null\n failedRows: number\n failuresWithAsi: number\n singleShotTraces: number\n multiShotTraces: number\n splitCounts: Record<DatasetSplit, number>\n domainCounts: Record<string, number>\n failureClassCounts: Partial<Record<FailureClass, number>>\n responsibleSurfaceCounts: Record<string, number>\n /**\n * Runs excluded from `passRate` because the authenticity gate flagged them as\n * gamed. Surfaced, never silent: a release whose pass rate is computed over a\n * shrunken denominator has to say by how much, or the exclusion is just a\n * different way of hiding the same runs.\n */\n realnessGatedRuns: number\n}\n\nexport interface ReleaseConfidenceScorecard {\n target: string\n candidateId: string | null\n baselineId: string | null\n status: ReleaseConfidenceStatus\n promote: boolean\n axes: ReleaseConfidenceAxis[]\n issues: ReleaseConfidenceIssue[]\n metrics: ReleaseConfidenceMetrics\n dataset: DatasetManifest | null\n gateDecision: GateDecision | null\n summary: string\n}\n\nconst DEFAULT_THRESHOLDS: Required<ReleaseConfidenceThresholds> = {\n requireCorpus: true,\n minScenarioCount: 1,\n minSearchRuns: 1,\n minHoldoutRuns: 1,\n requireHoldout: true,\n minPassRate: 0.8,\n minMeanScore: 0.7,\n maxOverfitGap: 0.15,\n maxMeanCostUsd: Number.POSITIVE_INFINITY,\n maxP95WallMs: Number.POSITIVE_INFINITY,\n requireAsiForFailures: true,\n failureScoreThreshold: 0.5,\n}\n\nexport function evaluateReleaseConfidence(\n input: ReleaseConfidenceInput,\n): ReleaseConfidenceScorecard {\n const thresholds = { ...DEFAULT_THRESHOLDS, ...input.thresholds }\n const candidateId = input.candidateId ?? null\n const runs = filterCandidate(\n (input.runs ?? []).map(validateRunRecord),\n candidateId,\n input.baselineId,\n )\n const traces = filterTraceCandidate(\n (input.traces ?? []).map(validateReleaseTraceEvidence),\n candidateId,\n input.baselineId,\n )\n const scenarios = input.scenarios ?? []\n const scenarioCount = input.dataset?.scenarioCount ?? scenarios.length\n const splitCounts = input.dataset?.splitCounts ?? countScenarioSplits(scenarios)\n const searchScores = scoresFor(runs, 'search')\n const holdoutScores = scoresFor(runs, 'holdout')\n const runScores = runs.map(runSplitScore).filter(isFiniteNumber)\n const traceScores = traces.map((t) => t.score).filter(isFiniteNumber)\n const scoreUniverse = runs.length > 0 ? runScores : traceScores\n const qualityRuns = runs.filter((run) => runSplitScore(run) !== undefined)\n const unscoredRuns = runs.filter(\n (run) =>\n runSplitScore(run) === undefined &&\n !hasExplicitTaskFailure(run) &&\n !isFailedTerminalOutcome(run.terminalOutcome),\n ).length\n // Realness-gated runs are EXCLUDED from the pass rate — numerator AND\n // denominator — and the count of what was dropped ships beside the rate as\n // `metrics.realnessGatedRuns`. Counting a gamed run as a pass made faking a\n // success the cheapest way to improve a release scorecard; scoring it 0\n // instead would be the other error, silently deflating the rate with a run\n // the gate says carries no usable verdict at all.\n const honestRuns = runs.filter((run) => !isRealnessGated(run))\n const passOutcomes =\n runs.length > 0\n ? honestRuns.map((run) => runPassOutcome(run, thresholds.failureScoreThreshold))\n : traces.map((trace) => tracePassOutcome(trace, thresholds.failureScoreThreshold))\n const reliabilityRows =\n runs.length > 0\n ? runs.map((run) => terminalSuccess(run.terminalOutcome))\n : traces.map((trace) => trace.ok)\n const unclassifiedTerminalRuns = reliabilityRows.filter((outcome) => outcome === undefined).length\n const terminalFailureRuns = reliabilityRows.filter((outcome) => outcome === false).length\n const reliabilityRate =\n reliabilityRows.length === 0 || unclassifiedTerminalRuns > 0\n ? null\n : (reliabilityRows.length - terminalFailureRuns) / reliabilityRows.length\n const searchRuns = qualityRuns.filter((r) => r.splitTag === 'search').length\n const holdoutRuns = qualityRuns.filter((r) => r.splitTag === 'holdout').length\n const failed = failedRows(runs, traces, thresholds.failureScoreThreshold)\n const searchMeanScore = meanOrNull(searchScores)\n const holdoutMeanScore = meanOrNull(holdoutScores)\n const runCosts = runs.flatMap((run) =>\n run.costProvenance.kind === 'uncaptured' ? [] : [run.costProvenance.usd],\n )\n const traceCosts = traces.map((trace) => trace.costUsd).filter(isFiniteNumber)\n const meanCostUsd =\n runs.length > 0\n ? runCosts.length === runs.length\n ? meanOrNull(runCosts)\n : null\n : meanOrNull(traceCosts)\n const wallTimes =\n runs.length > 0\n ? runs.map((run) => run.wallMs)\n : traces.map((trace) => trace.durationMs).filter(isFiniteNumber)\n const metrics: ReleaseConfidenceMetrics = {\n scenarioCount,\n searchRuns,\n holdoutRuns,\n unscoredRuns,\n unclassifiedTerminalRuns,\n terminalFailureRuns,\n reliabilityRate,\n passRate: passOutcomeRate(passOutcomes),\n realnessGatedRuns: runs.length - honestRuns.length,\n meanScore: meanOrNull(scoreUniverse),\n searchMeanScore,\n holdoutMeanScore,\n overfitGap: diffOrNull(searchMeanScore, holdoutMeanScore),\n meanCostUsd,\n p95WallMs: percentileOrNull(wallTimes, 0.95),\n failedRows: failed.length,\n failuresWithAsi: failed.filter((row) => row.hasAsi).length,\n singleShotTraces: traces.filter((t) => t.turnCount === 1).length,\n multiShotTraces: traces.filter((t) => (t.turnCount ?? 0) > 1).length,\n splitCounts,\n domainCounts: countDomains(scenarios),\n failureClassCounts: countFailureClasses(runs, traces, thresholds.failureScoreThreshold),\n responsibleSurfaceCounts: countResponsibleSurfaces(traces),\n }\n\n const issues: ReleaseConfidenceIssue[] = []\n checkCorpus(input, thresholds, metrics, issues)\n checkQuality(thresholds, metrics, issues)\n checkReliability(metrics, issues)\n checkGeneralization(input.gateDecision ?? null, thresholds, metrics, issues)\n checkDiagnostics(thresholds, metrics, issues)\n checkEfficiency(thresholds, metrics, issues)\n\n const axes = buildAxes(metrics, thresholds, issues)\n const status = issues.some((i) => i.severity === 'critical')\n ? 'fail'\n : issues.length > 0\n ? 'warn'\n : 'pass'\n\n return {\n target: input.target,\n candidateId,\n baselineId: input.baselineId ?? null,\n status,\n promote: status === 'pass' && (input.gateDecision ? input.gateDecision.promote : true),\n axes,\n issues,\n metrics,\n dataset: input.dataset ?? null,\n gateDecision: input.gateDecision ?? null,\n summary: renderSummary(input.target, status, metrics, issues),\n }\n}\n\nexport function assertReleaseConfidence(input: ReleaseConfidenceInput): ReleaseConfidenceScorecard {\n const scorecard = evaluateReleaseConfidence(input)\n if (scorecard.status === 'fail') {\n throw new VerificationError(scorecard.summary)\n }\n return scorecard\n}\n\nfunction filterCandidate(\n runs: readonly RunRecord[],\n candidateId: string | null,\n baselineId?: string,\n): RunRecord[] {\n if (candidateId) return runs.filter((r) => r.candidateId === candidateId)\n if (baselineId) return runs.filter((r) => r.candidateId !== baselineId)\n return [...runs]\n}\n\nfunction filterTraceCandidate(\n traces: readonly ReleaseTraceEvidence[],\n candidateId: string | null,\n baselineId?: string,\n): ReleaseTraceEvidence[] {\n if (candidateId)\n return traces.filter((t) => t.candidateId === undefined || t.candidateId === candidateId)\n if (baselineId)\n return traces.filter((t) => t.candidateId === undefined || t.candidateId !== baselineId)\n return [...traces]\n}\n\nfunction validateReleaseTraceEvidence(\n trace: ReleaseTraceEvidence,\n index: number,\n): ReleaseTraceEvidence {\n const value = trace as unknown as Record<string, unknown>\n if (Object.hasOwn(value, 'failureMode')) {\n throw new ValidationError(\n `traces[${index}].failureMode is not supported; use canonical failureClass`,\n )\n }\n if (trace.failureClass !== undefined && !FAILURE_CLASSES.includes(trace.failureClass)) {\n throw new ValidationError(\n `traces[${index}].failureClass must be one of ${FAILURE_CLASSES.join(', ')}`,\n )\n }\n return trace\n}\n\nfunction checkCorpus(\n input: ReleaseConfidenceInput,\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (thresholds.requireCorpus && !input.dataset && (input.scenarios?.length ?? 0) === 0) {\n issues.push({\n axis: 'corpus',\n severity: 'critical',\n code: 'missing_corpus',\n detail: 'No Dataset manifest or scenarios supplied.',\n })\n }\n if (metrics.scenarioCount < thresholds.minScenarioCount) {\n issues.push({\n axis: 'corpus',\n severity: 'critical',\n code: 'few_scenarios',\n detail: `${metrics.scenarioCount} scenario(s) < min ${thresholds.minScenarioCount}.`,\n })\n }\n if (thresholds.requireHoldout && metrics.splitCounts.holdout === 0) {\n issues.push({\n axis: 'corpus',\n severity: 'critical',\n code: 'missing_holdout_split',\n detail: 'Corpus has no holdout scenarios.',\n })\n }\n}\n\nfunction checkQuality(\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (metrics.searchRuns < thresholds.minSearchRuns) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'few_search_runs',\n detail: `${metrics.searchRuns} search run(s) < min ${thresholds.minSearchRuns}.`,\n })\n }\n if (metrics.unscoredRuns > 0) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'unscored_runs',\n detail: `${metrics.unscoredRuns} supplied run(s) have no task result.`,\n })\n }\n if (metrics.passRate === null || metrics.meanScore === null) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'missing_quality_scores',\n detail: 'No task-quality scores are available for pass-rate and mean-score checks.',\n })\n }\n if (metrics.passRate !== null && metrics.passRate < thresholds.minPassRate) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'low_pass_rate',\n detail: `passRate ${fmt(metrics.passRate)} < ${fmt(thresholds.minPassRate)}.`,\n })\n }\n if (metrics.meanScore !== null && metrics.meanScore < thresholds.minMeanScore) {\n issues.push({\n axis: 'quality',\n severity: 'critical',\n code: 'low_mean_score',\n detail: `meanScore ${fmt(metrics.meanScore)} < ${fmt(thresholds.minMeanScore)}.`,\n })\n }\n}\n\nfunction checkReliability(\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (metrics.reliabilityRate === null) {\n issues.push({\n axis: 'reliability',\n severity: 'critical',\n code: 'missing_reliability_evidence',\n detail:\n metrics.unclassifiedTerminalRuns > 0\n ? `${metrics.unclassifiedTerminalRuns} supplied run(s) have no classified terminal result.`\n : 'No classified terminal results are available.',\n })\n }\n if (metrics.terminalFailureRuns > 0) {\n issues.push({\n axis: 'reliability',\n severity: 'critical',\n code: 'terminal_run_failures',\n detail: `${metrics.terminalFailureRuns} run(s) ended failed, cancelled, or incomplete.`,\n })\n }\n}\n\nfunction checkGeneralization(\n gateDecision: GateDecision | null,\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (thresholds.requireHoldout && metrics.holdoutRuns < thresholds.minHoldoutRuns) {\n issues.push({\n axis: 'generalization',\n severity: 'critical',\n code: 'few_holdout_runs',\n detail: `${metrics.holdoutRuns} holdout run(s) < min ${thresholds.minHoldoutRuns}.`,\n })\n }\n if (metrics.overfitGap !== null && metrics.overfitGap > thresholds.maxOverfitGap) {\n issues.push({\n axis: 'generalization',\n severity: 'critical',\n code: 'overfit_gap',\n detail: `search-holdout gap ${fmt(metrics.overfitGap)} > ${fmt(thresholds.maxOverfitGap)}.`,\n })\n }\n if (gateDecision && !gateDecision.promote) {\n issues.push({\n axis: 'generalization',\n severity: 'critical',\n code: `gate_${gateDecision.rejectionCode ?? 'reject'}`,\n detail: gateDecision.reason,\n })\n }\n}\n\nfunction checkDiagnostics(\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (!thresholds.requireAsiForFailures) return\n if (metrics.failedRows > metrics.failuresWithAsi) {\n issues.push({\n axis: 'diagnostics',\n severity: 'critical',\n code: 'missing_failure_asi',\n detail: `${metrics.failedRows - metrics.failuresWithAsi} failed row(s) have no actionable side information.`,\n })\n }\n}\n\nfunction checkEfficiency(\n thresholds: Required<ReleaseConfidenceThresholds>,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): void {\n if (Number.isFinite(thresholds.maxMeanCostUsd) && metrics.meanCostUsd === null) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'missing_cost',\n detail: 'A finite cost limit was configured but no cost evidence is available.',\n })\n } else if (metrics.meanCostUsd !== null && metrics.meanCostUsd > thresholds.maxMeanCostUsd) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'cost_budget',\n detail: `meanCostUsd ${fmt(metrics.meanCostUsd)} > ${fmt(thresholds.maxMeanCostUsd)}.`,\n })\n }\n if (Number.isFinite(thresholds.maxP95WallMs) && metrics.p95WallMs === null) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'missing_latency',\n detail: 'A finite latency limit was configured but no latency evidence is available.',\n })\n } else if (metrics.p95WallMs !== null && metrics.p95WallMs > thresholds.maxP95WallMs) {\n issues.push({\n axis: 'efficiency',\n severity: 'critical',\n code: 'latency_budget',\n detail: `p95WallMs ${fmt(metrics.p95WallMs)} > ${fmt(thresholds.maxP95WallMs)}.`,\n })\n }\n}\n\nfunction buildAxes(\n metrics: ReleaseConfidenceMetrics,\n thresholds: Required<ReleaseConfidenceThresholds>,\n issues: ReleaseConfidenceIssue[],\n): ReleaseConfidenceAxis[] {\n return [\n axis(\n 'corpus',\n issues,\n bounded(metrics.scenarioCount / Math.max(1, thresholds.minScenarioCount)),\n `${metrics.scenarioCount} scenarios; holdout=${metrics.splitCounts.holdout}`,\n ),\n axis(\n 'quality',\n issues,\n metrics.passRate === null || metrics.meanScore === null\n ? null\n : Math.min(metrics.passRate, metrics.meanScore),\n `passRate=${fmt(metrics.passRate)} meanScore=${fmt(metrics.meanScore)}`,\n ),\n axis(\n 'reliability',\n issues,\n metrics.reliabilityRate,\n `successRate=${fmt(metrics.reliabilityRate)} terminalFailures=${metrics.terminalFailureRuns} unclassified=${metrics.unclassifiedTerminalRuns}`,\n ),\n axis(\n 'generalization',\n issues,\n gapScore(metrics.overfitGap, thresholds.maxOverfitGap),\n `holdoutRuns=${metrics.holdoutRuns} overfitGap=${fmt(metrics.overfitGap)}`,\n ),\n axis(\n 'diagnostics',\n issues,\n metrics.failedRows === 0 ? 1 : metrics.failuresWithAsi / metrics.failedRows,\n `failuresWithAsi=${metrics.failuresWithAsi}/${metrics.failedRows}`,\n ),\n axis(\n 'efficiency',\n issues,\n efficiencyScore(metrics, thresholds),\n `meanCostUsd=${fmt(metrics.meanCostUsd)} p95WallMs=${fmt(metrics.p95WallMs)}`,\n ),\n ]\n}\n\nfunction axis(\n name: ReleaseConfidenceAxisName,\n issues: ReleaseConfidenceIssue[],\n score: number | null,\n detail: string,\n): ReleaseConfidenceAxis {\n const own = issues.filter((i) => i.axis === name)\n const status = own.some((i) => i.severity === 'critical')\n ? 'fail'\n : own.length > 0\n ? 'warn'\n : 'pass'\n return { name, status, score: score === null ? null : bounded(score), detail }\n}\n\nfunction countScenarioSplits(scenarios: readonly DatasetScenario[]): Record<DatasetSplit, number> {\n const counts: Record<DatasetSplit, number> = { train: 0, dev: 0, test: 0, holdout: 0 }\n for (const scenario of scenarios) counts[scenario.split ?? 'train']++\n return counts\n}\n\nfunction countDomains(scenarios: readonly DatasetScenario[]): Record<string, number> {\n const out: Record<string, number> = {}\n for (const scenario of scenarios) {\n const domain = scenario.tags?.domain ?? scenario.tags?.category ?? 'uncategorized'\n out[domain] = (out[domain] ?? 0) + 1\n }\n return out\n}\n\nfunction countFailureClasses(\n runs: readonly RunRecord[],\n traces: readonly ReleaseTraceEvidence[],\n threshold: number,\n): Partial<Record<FailureClass, number>> {\n const out: Partial<Record<FailureClass, number>> = {}\n for (const run of runs) {\n // Ungated: a failure-mode census counts what the runs REPORTED, which is\n // the only way a gamed run's inflated score is visible at all. It is not a\n // promotion number — `passRate` is, and that one excludes gated runs and\n // publishes the excluded count as `metrics.realnessGatedRuns`.\n if (runPassOutcome(run, threshold) === false) {\n const failureClass =\n run.failureClass !== undefined && run.failureClass !== 'success'\n ? run.failureClass\n : 'unknown'\n out[failureClass] = (out[failureClass] ?? 0) + 1\n }\n }\n for (const trace of traces) {\n if (tracePassOutcome(trace, threshold) === false) {\n const failureClass =\n trace.failureClass !== undefined && trace.failureClass !== 'success'\n ? trace.failureClass\n : 'unknown'\n out[failureClass] = (out[failureClass] ?? 0) + 1\n }\n }\n return out\n}\n\nfunction countResponsibleSurfaces(traces: readonly ReleaseTraceEvidence[]): Record<string, number> {\n const out: Record<string, number> = {}\n for (const trace of traces) {\n for (const asi of trace.asi ?? []) {\n const surface = asi.responsibleSurface ?? 'unknown'\n out[surface] = (out[surface] ?? 0) + 1\n }\n }\n return out\n}\n\nfunction failedRows(\n runs: readonly RunRecord[],\n traces: readonly ReleaseTraceEvidence[],\n threshold: number,\n): Array<{ hasAsi: boolean }> {\n const out: Array<{ hasAsi: boolean }> = []\n for (const run of runs) {\n if (runPassOutcome(run, threshold) === false) {\n const asiMetric = run.outcome.raw.asi\n out.push({ hasAsi: typeof asiMetric === 'number' && asiMetric > 0 })\n }\n }\n for (const trace of traces) {\n if (tracePassOutcome(trace, threshold) === false) {\n out.push({ hasAsi: (trace.asi?.length ?? 0) > 0 })\n }\n }\n return out\n}\n\nfunction passOutcomeRate(outcomes: readonly (boolean | null)[]): number | null {\n const classified = outcomes.filter((outcome): outcome is boolean => outcome !== null)\n if (classified.length === 0) return null\n return classified.filter(Boolean).length / classified.length\n}\n\nfunction runPassOutcome(run: RunRecord, threshold: number): boolean | null {\n if (hasExplicitTaskFailure(run)) return false\n const score = runSplitScore(run)\n return score === undefined ? null : score >= threshold\n}\n\nfunction hasExplicitTaskFailure(run: RunRecord): boolean {\n return run.failureClass !== undefined && run.failureClass !== 'success'\n}\n\nfunction tracePassOutcome(trace: ReleaseTraceEvidence, threshold: number): boolean | null {\n if (trace.failureClass !== undefined && trace.failureClass !== 'success') return false\n if (trace.ok === false) return false\n if (isFiniteNumber(trace.score)) return trace.score >= threshold\n return trace.ok === true ? true : null\n}\n\nfunction isFailedTerminalOutcome(\n outcome: RunRecord['terminalOutcome'],\n): outcome is 'failed' | 'cancelled' | 'incomplete' {\n return outcome === 'failed' || outcome === 'cancelled' || outcome === 'incomplete'\n}\n\nfunction terminalSuccess(outcome: RunRecord['terminalOutcome']): boolean | undefined {\n if (outcome === 'succeeded') return true\n if (isFailedTerminalOutcome(outcome)) return false\n return undefined\n}\n\nfunction scoresFor(runs: readonly RunRecord[], split: RunSplitTag): number[] {\n return runs\n .filter((run) => run.splitTag === split)\n .map(runSplitScore)\n .filter(isFiniteNumber)\n}\n\n/**\n * RAW and split-exact (`observedSplitScore`): this feeds the per-split means,\n * the overfit gap, and the pass threshold — descriptions of what the runs\n * reported. A gamed run inflating them is visible next to `realnessGatedRuns`,\n * and the promotion number (`passRate`) excludes gated runs entirely.\n */\nfunction runSplitScore(run: RunRecord): number | undefined {\n const score = observedSplitScore(run, run.splitTag === 'holdout' ? 'holdout' : 'search')\n return isFiniteNumber(score) ? score : undefined\n}\n\nfunction meanOrNull(xs: readonly number[]): number | null {\n if (xs.length === 0) return null\n return xs.reduce((sum, x) => sum + x, 0) / xs.length\n}\n\nfunction percentileOrNull(xs: readonly number[], p: number): number | null {\n if (xs.length === 0) return null\n const sorted = [...xs].sort((a, b) => a - b)\n return sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(p * sorted.length) - 1))]!\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction diffOrNull(a: number | null, b: number | null): number | null {\n if (a === null || b === null) return null\n return a - b\n}\n\nfunction gapScore(gap: number | null, maxGap: number): number | null {\n if (gap === null) return null\n if (maxGap <= 0) return gap <= 0 ? 1 : 0\n return bounded(1 - Math.max(0, gap) / maxGap)\n}\n\nfunction efficiencyScore(\n metrics: ReleaseConfidenceMetrics,\n thresholds: Required<ReleaseConfidenceThresholds>,\n): number | null {\n const cost = Number.isFinite(thresholds.maxMeanCostUsd)\n ? metrics.meanCostUsd === null\n ? null\n : bounded(thresholds.maxMeanCostUsd / Math.max(metrics.meanCostUsd, 1e-12))\n : 1\n const latency = Number.isFinite(thresholds.maxP95WallMs)\n ? metrics.p95WallMs === null\n ? null\n : bounded(thresholds.maxP95WallMs / Math.max(metrics.p95WallMs, 1e-12))\n : 1\n if (cost === null || latency === null) return null\n return Math.min(cost, latency)\n}\n\nfunction bounded(x: number): number {\n if (!Number.isFinite(x)) return 0\n return Math.max(0, Math.min(1, x))\n}\n\nfunction renderSummary(\n target: string,\n status: ReleaseConfidenceStatus,\n metrics: ReleaseConfidenceMetrics,\n issues: ReleaseConfidenceIssue[],\n): string {\n const prefix = `release confidence ${status}: ${target}`\n const metricText = `scenarios=${metrics.scenarioCount} searchRuns=${metrics.searchRuns} holdoutRuns=${metrics.holdoutRuns} passRate=${fmt(metrics.passRate)} meanScore=${fmt(metrics.meanScore)}`\n if (issues.length === 0) return `${prefix}; ${metricText}`\n return `${prefix}; ${metricText}; issues=${issues.map((i) => i.code).join(',')}`\n}\n\nfunction fmt(x: number | null): string {\n if (x === null) return 'n/a'\n return x.toFixed(4)\n}\n","/**\n * Bootstrap-CI promotion gate.\n *\n * In any iterative-improvement loop (GEPA, prompt evolution, dataset\n * curation), the question is \"did this generation actually improve, or are\n * we celebrating noise?\". With small N and noisy outcomes, point-estimate\n * deltas lie. Bootstrap confidence intervals tell the operator whether the\n * delta is real before code or prompts get promoted.\n *\n * This module is pure functions — no I/O, no model calls. Easy to unit-test\n * and to compose into any verdict gate.\n *\n * Default gate:\n * - Bootstrap mean baseline vs candidate (1k resamples).\n * - Compute the delta distribution; pass if the lower CI bound > 0.\n * - Tunable confidence (default 95%) and resample count.\n *\n * Verdict semantics intentionally match the existing `experiments.jsonl`\n * vocabulary:\n * - ADVANCE: candidate's CI lower bound > baseline mean (real win)\n * - KEEP: overlap, but candidate point estimate >= baseline (neutral)\n * - REVERT: candidate's CI upper bound < baseline mean (real regression)\n * - INCONCLUSIVE: not enough samples or CI straddles zero with no signal\n */\n\nexport type Verdict = 'ADVANCE' | 'KEEP' | 'REVERT' | 'INCONCLUSIVE'\n\nexport interface BootstrapResult {\n baselineMean: number\n candidateMean: number\n /** candidateMean - baselineMean, point estimate. */\n delta: number\n /** Lower bound of the (1 - alpha) CI on the delta. */\n ciLower: number\n /** Upper bound of the (1 - alpha) CI on the delta. */\n ciUpper: number\n /** Number of bootstrap resamples used. */\n iterations: number\n alpha: number\n verdict: Verdict\n}\n\nexport interface BootstrapOptions {\n /** Confidence level alpha (default 0.05 → 95% CI). */\n alpha?: number\n /** Number of resamples (default 1000). */\n iterations?: number\n /**\n * Minimum total samples (baseline + candidate) below which we always\n * return INCONCLUSIVE — bootstrap with too few samples is meaningless.\n * Default 6 (combined).\n */\n minTotalSamples?: number\n /** RNG seed for reproducibility. Default: Math.random. */\n seed?: number\n}\n\n/**\n * Compute the bootstrap CI on (candidateMean - baselineMean) and a verdict.\n *\n * Uses simple percentile bootstrap on the difference of resampled means.\n * That's the standard non-parametric primitive — no distributional\n * assumptions, robust to skew, easy to reason about.\n */\nexport function bootstrapCi(\n baseline: number[],\n candidate: number[],\n options: BootstrapOptions = {},\n): BootstrapResult {\n const alpha = options.alpha ?? 0.05\n const iterations = options.iterations ?? 1000\n const minTotal = options.minTotalSamples ?? 6\n const rng = mulberry32(options.seed ?? hashSeed(baseline, candidate))\n\n const baselineMean = mean(baseline)\n const candidateMean = mean(candidate)\n const delta = candidateMean - baselineMean\n\n if (\n baseline.length + candidate.length < minTotal ||\n baseline.length === 0 ||\n candidate.length === 0\n ) {\n return {\n baselineMean,\n candidateMean,\n delta,\n ciLower: -Infinity,\n ciUpper: Infinity,\n iterations: 0,\n alpha,\n verdict: 'INCONCLUSIVE',\n }\n }\n\n const deltas: number[] = new Array(iterations)\n for (let i = 0; i < iterations; i++) {\n const bResample = resample(baseline, rng)\n const cResample = resample(candidate, rng)\n deltas[i] = mean(cResample) - mean(bResample)\n }\n deltas.sort((a, b) => a - b)\n const lowerIdx = Math.floor((alpha / 2) * iterations)\n const upperIdx = Math.floor((1 - alpha / 2) * iterations) - 1\n const ciLower = deltas[Math.max(0, lowerIdx)]!\n const ciUpper = deltas[Math.min(iterations - 1, upperIdx)]!\n\n let verdict: Verdict\n // A ZERO-WIDTH interval is an absence of evidence, not a certainty. Constant\n // arms make every resample identical, so pass/fail data promotes on nothing:\n // [0,0,0] vs [1,1,1] is six samples, clears the `minTotalSamples` floor, and\n // yields [1, 1] — an \"ADVANCE\" carrying no information about how far the\n // estimate could be wrong. Same rule as `pairedDeltaTest`, one estimator over.\n if (!Number.isFinite(ciLower) || !Number.isFinite(ciUpper) || ciLower === ciUpper) {\n verdict = 'INCONCLUSIVE'\n } else if (ciLower > 0) verdict = 'ADVANCE'\n else if (ciUpper < 0) verdict = 'REVERT'\n else if (delta >= 0) verdict = 'KEEP'\n else verdict = 'INCONCLUSIVE'\n\n return {\n baselineMean,\n candidateMean,\n delta,\n ciLower,\n ciUpper,\n iterations,\n alpha,\n verdict,\n }\n}\n\nfunction mean(xs: number[]): number {\n if (xs.length === 0) return 0\n let s = 0\n for (const x of xs) s += x\n return s / xs.length\n}\n\nfunction resample(xs: number[], rng: () => number): number[] {\n const out = new Array(xs.length)\n for (let i = 0; i < xs.length; i++) out[i] = xs[Math.floor(rng() * xs.length)]\n return out\n}\n\n/** Mulberry32 — fast deterministic PRNG. Stable across runs given the same seed. */\nfunction mulberry32(seed: number): () => number {\n let t = seed >>> 0\n return () => {\n t += 0x6d2b79f5\n let r = t\n r = Math.imul(r ^ (r >>> 15), r | 1)\n r ^= r + Math.imul(r ^ (r >>> 7), r | 61)\n return ((r ^ (r >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** Stable seed derived from the inputs — same data → same CI bounds. */\nfunction hashSeed(a: number[], b: number[]): number {\n let h = 2166136261\n for (const x of [...a, ...b]) {\n const view = new Float64Array([x])\n const bytes = new Uint8Array(view.buffer)\n for (const byte of bytes) {\n h ^= byte\n h = Math.imul(h, 16777619)\n }\n }\n return h >>> 0\n}\n\n/**\n * Judge-replay promotion gate.\n *\n * The cheap inner-loop judge that drives an evolution run is by definition\n * fast and noisy. When you're about to promote a winning variant to the\n * canonical default, you want a STRONGER judge (a more expensive model, a\n * human grader, a separately-trained reward model) to confirm the win\n * generalises beyond the inner loop.\n *\n * This helper takes raw winner + baseline outputs, scores both through the\n * stronger judge, and applies `bootstrapCi`. ADVANCE means the stronger\n * judge agrees the winner is real with the configured confidence. Doesn't\n * matter what shape your \"output\" is — pass a string, an object, anything\n * the judge can read.\n */\nexport interface JudgeReplayGateArgs<TOutput> {\n baselineOutputs: TOutput[]\n candidateOutputs: TOutput[]\n /** Stronger judge — async to allow LLM calls. Return a 0..N scalar score. */\n judge: (output: TOutput) => Promise<number> | number\n alpha?: number\n iterations?: number\n /** RNG seed for reproducibility. */\n seed?: number\n /** Maximum concurrent judge calls. Default 4. */\n judgeConcurrency?: number\n}\n\n/**\n * Confirm a candidate's win with a stronger judge: score baseline and candidate outputs independently, then bootstrap a CI to verify the lift generalises beyond the inner loop.\n */\nexport async function judgeReplayGate<TOutput>(\n args: JudgeReplayGateArgs<TOutput>,\n): Promise<BootstrapResult & { baselineSamples: number; candidateSamples: number }> {\n const concurrency = args.judgeConcurrency ?? 4\n const baselineScores = await scoreAll(args.baselineOutputs, args.judge, concurrency)\n const candidateScores = await scoreAll(args.candidateOutputs, args.judge, concurrency)\n const ci = bootstrapCi(baselineScores, candidateScores, {\n ...(args.alpha !== undefined ? { alpha: args.alpha } : {}),\n ...(args.iterations !== undefined ? { iterations: args.iterations } : {}),\n ...(args.seed !== undefined ? { seed: args.seed } : {}),\n })\n return {\n ...ci,\n baselineSamples: baselineScores.length,\n candidateSamples: candidateScores.length,\n }\n}\n\nasync function scoreAll<TOutput>(\n outputs: TOutput[],\n judge: (output: TOutput) => Promise<number> | number,\n concurrency: number,\n): Promise<number[]> {\n const results: number[] = new Array(outputs.length)\n let next = 0\n async function worker(): Promise<void> {\n while (true) {\n const i = next++\n if (i >= outputs.length) return\n const v = await judge(outputs[i]!)\n results[i] = Number.isFinite(v) ? v : 0\n }\n }\n await Promise.all(Array.from({ length: Math.max(1, concurrency) }, () => worker()))\n return results\n}\n","import type { ReleaseConfidenceScorecard } from './release-confidence'\nimport type { RunRecord } from './run-record'\nimport { summaryTable } from './summary-report'\n\nexport interface RenderReleaseReportOptions {\n title?: string\n runs?: readonly RunRecord[]\n comparator?: string\n traceAnalystFindings?: readonly string[]\n nextActions?: readonly string[]\n}\n\nexport function renderReleaseReport(\n scorecard: ReleaseConfidenceScorecard,\n options: RenderReleaseReportOptions = {},\n): string {\n const title = options.title ?? `Release Report: ${scorecard.target}`\n const lines: string[] = []\n lines.push(`# ${title}`)\n lines.push('')\n lines.push(`Status: **${scorecard.status.toUpperCase()}**`)\n lines.push(`Promote: **${scorecard.promote ? 'yes' : 'no'}**`)\n if (scorecard.candidateId) lines.push(`Candidate: \\`${scorecard.candidateId}\\``)\n if (scorecard.baselineId) lines.push(`Baseline: \\`${scorecard.baselineId}\\``)\n lines.push('')\n lines.push(scorecard.summary)\n lines.push('')\n\n lines.push('## Metrics')\n lines.push('')\n lines.push('| Metric | Value |')\n lines.push('|---|---:|')\n lines.push(`| Scenarios | ${scorecard.metrics.scenarioCount} |`)\n lines.push(`| Search runs | ${scorecard.metrics.searchRuns} |`)\n lines.push(`| Holdout runs | ${scorecard.metrics.holdoutRuns} |`)\n lines.push(`| Unscored runs | ${scorecard.metrics.unscoredRuns} |`)\n lines.push(`| Terminal failures | ${scorecard.metrics.terminalFailureRuns} |`)\n lines.push(`| Pass rate | ${pct(scorecard.metrics.passRate)} |`)\n lines.push(`| Mean score | ${num(scorecard.metrics.meanScore)} |`)\n lines.push(`| Search mean | ${num(scorecard.metrics.searchMeanScore)} |`)\n lines.push(`| Holdout mean | ${num(scorecard.metrics.holdoutMeanScore)} |`)\n lines.push(`| Overfit gap | ${num(scorecard.metrics.overfitGap)} |`)\n lines.push(`| Mean cost | $${num(scorecard.metrics.meanCostUsd)} |`)\n lines.push(`| p95 wall time | ${duration(scorecard.metrics.p95WallMs)} |`)\n lines.push('')\n\n if (scorecard.issues.length > 0) {\n lines.push('## Issues')\n lines.push('')\n for (const issue of scorecard.issues) {\n lines.push(`- **${issue.severity}** \\`${issue.code}\\` (${issue.axis}): ${issue.detail}`)\n }\n lines.push('')\n }\n\n const surfaces = entries(scorecard.metrics.responsibleSurfaceCounts)\n if (surfaces.length > 0) {\n lines.push('## Responsible Surfaces')\n lines.push('')\n for (const [surface, count] of surfaces) lines.push(`- ${surface}: ${count}`)\n lines.push('')\n }\n\n const failures = entries(scorecard.metrics.failureClassCounts)\n if (failures.length > 0) {\n lines.push('## Failure Classes')\n lines.push('')\n for (const [mode, count] of failures) lines.push(`- ${mode}: ${count}`)\n lines.push('')\n }\n\n if (options.runs && options.runs.length > 0) {\n lines.push('## Run Summary')\n lines.push('')\n lines.push(\n summaryTable([...options.runs], {\n comparator: options.comparator ?? scorecard.baselineId ?? undefined,\n split: 'holdout',\n }).markdown,\n )\n lines.push('')\n }\n\n if (options.traceAnalystFindings && options.traceAnalystFindings.length > 0) {\n lines.push('## TraceAnalyst Findings')\n lines.push('')\n for (const finding of options.traceAnalystFindings) lines.push(`- ${finding}`)\n lines.push('')\n }\n\n const nextActions = options.nextActions ?? defaultNextActions(scorecard)\n if (nextActions.length > 0) {\n lines.push('## Next Actions')\n lines.push('')\n for (const action of nextActions) lines.push(`- ${action}`)\n lines.push('')\n }\n\n return `${lines.join('\\n').trimEnd()}\\n`\n}\n\nfunction defaultNextActions(scorecard: ReleaseConfidenceScorecard): string[] {\n if (scorecard.promote) return ['Promote the candidate and keep canaries enabled.']\n return scorecard.issues\n .filter((issue) => issue.severity === 'critical')\n .map((issue) => `Resolve ${issue.code}: ${issue.detail}`)\n}\n\nfunction entries(values: Record<string, number>): Array<[string, number]> {\n return Object.entries(values)\n .filter(([, count]) => count > 0)\n .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n}\n\nfunction pct(value: number | null): string {\n return value === null ? 'n/a' : `${(value * 100).toFixed(1)}%`\n}\n\nfunction num(value: number | null): string {\n return value === null ? 'n/a' : value.toFixed(3)\n}\n\nfunction duration(value: number | null): string {\n return value === null ? 'n/a' : `${Math.round(value)} ms`\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { o as FailureClass } from "./schema-BtVldJ3T.js";
|
|
2
2
|
import { a as RunRecord, s as RunSplitTag } from "./run-record-DcObtIGh.js";
|
|
3
3
|
import { a as DatasetScenario, o as DatasetSplit, r as DatasetManifest } from "./dataset-BvtnC8Dc.js";
|
|
4
|
-
import {
|
|
4
|
+
import { x as GateDecision } from "./summary-report-CPMINBqs.js";
|
|
5
5
|
//#region src/release-confidence.d.ts
|
|
6
6
|
/** Severity of an actionable finding attached to a run/trace. */
|
|
7
7
|
type AsiSeverity = 'info' | 'warning' | 'error' | 'critical';
|
|
@@ -241,4 +241,4 @@ interface RenderReleaseReportOptions {
|
|
|
241
241
|
declare function renderReleaseReport(scorecard: ReleaseConfidenceScorecard, options?: RenderReleaseReportOptions): string;
|
|
242
242
|
//#endregion
|
|
243
243
|
export { ReleaseConfidenceStatus as _, JudgeReplayGateArgs as a, assertReleaseConfidence as b, judgeReplayGate as c, ReleaseConfidenceAxis as d, ReleaseConfidenceAxisName as f, ReleaseConfidenceScorecard as g, ReleaseConfidenceMetrics as h, BootstrapResult as i, ActionableSideInfo as l, ReleaseConfidenceIssue as m, renderReleaseReport as n, Verdict as o, ReleaseConfidenceInput as p, BootstrapOptions as r, bootstrapCi as s, RenderReleaseReportOptions as t, AsiSeverity as u, ReleaseConfidenceThresholds as v, evaluateReleaseConfidence as x, ReleaseTraceEvidence as y };
|
|
244
|
-
//# sourceMappingURL=release-report-
|
|
244
|
+
//# sourceMappingURL=release-report-DpBxGGI1.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"release-report-
|
|
1
|
+
{"version":3,"file":"release-report-DpBxGGI1.d.ts","names":[],"sources":["../src/release-confidence.ts","../src/promotion-gate.ts","../src/release-report.ts"],"mappings":";;;;;;KAsBY;;UAGK;;EAEf;;EAEA;EACA,WAAW;;EAEX;;EAEA;;EAEA;;EAEA;EACA,WAAW;;KAGD;KACA;UAQK;EACf;EACA;EACA,QAAQ;EACR;EACA;EACA;EACA;EACA;;EAEA,eAAe;EACf,MAAM;EACN,WAAW;;UAGI;;EAEf;EACA;EACA;EACA;;EAEA;EACA;EACA;;EAEA;EACA;EACA;;EAEA;;EAEA;;UAGe;EACf;EACA;EACA;EACA,UAAU;EACV,qBAAqB;EACrB,gBAAgB;EAChB,kBAAkB;EAClB,eAAe;EACf,aAAa;;UAGE;EACf,MAAM;EACN,QAAQ;EACR;EACA;;UAGe;EACf,MAAM;EACN;EACA;EACA;;UAGe;EACf;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,aAAa,OAAO;EACpB,cAAc;EACd,oBAAoB,QAAQ,OAAO;EACnC,0BAA0B;;;;;;;EAO1B;;UAGe;EACf;EACA;EACA;EACA,QAAQ;EACR;EACA,MAAM;EACN,QAAQ;EACR,SAAS;EACT,SAAS;EACT,cAAc;EACd;;iBAkBc,0BACd,OAAO,yBACN;iBA4Ha,wBAAwB,OAAO,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;KCxR5D;UAEK;EACf;EACA;;EAEA;;EAEA;;EAEA;;EAEA;EACA;EACA,SAAS;;UAGM;;EAEf;;EAEA;;;;;;EAMA;;EAEA;;;;;;;;;iBAUc,YACd,oBACA,qBACA,UAAS,mBACR;;;;;;;;;;;;;;;;UAsHc,oBAAoB;EACnC,iBAAiB;EACjB,kBAAkB;;EAElB,QAAQ,QAAQ,YAAY;EAC5B;EACA;;EAEA;;EAEA;;;;;iBAMoB,gBAAgB,SACpC,MAAM,oBAAoB,WACzB,QAAQ;EAAoB;EAAyB;;;;UCxMvC;EACf;EACA,gBAAgB;EAChB;EACA;EACA;;iBAGc,oBACd,WAAW,4BACX,UAAS"}
|
package/dist/reporting.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as paretoChart, a as ParetoPoint, c as ResearchReportCandidate, d as ResearchReportOptions, f as ResearchReportRecommendation, g as gainHistogram, h as SummaryTableRow, i as ParetoFigureSpec, l as ResearchReportDecision, m as SummaryTableOptions, n as GainDistributionFigureSpec, o as RESEARCH_REPORT_HARD_PAIR_FLOOR, p as SummaryTable, r as GainDistributionOptions, s as ResearchReport, t as GainDistributionBin, u as ResearchReportMethodology, v as researchReport, y as summaryTable } from "./summary-report-
|
|
3
|
-
import { _ as ReleaseConfidenceStatus, a as JudgeReplayGateArgs, b as assertReleaseConfidence, c as judgeReplayGate, d as ReleaseConfidenceAxis, f as ReleaseConfidenceAxisName, g as ReleaseConfidenceScorecard, h as ReleaseConfidenceMetrics, i as BootstrapResult, m as ReleaseConfidenceIssue, n as renderReleaseReport, o as Verdict, p as ReleaseConfidenceInput, r as BootstrapOptions, s as bootstrapCi, t as RenderReleaseReportOptions, v as ReleaseConfidenceThresholds, x as evaluateReleaseConfidence, y as ReleaseTraceEvidence } from "./release-report-
|
|
1
|
+
import { N as benjaminiHochberg, Q as pairedBootstrap, gt as wilcoxonSignedRank, v as PairedBootstrapOptions, y as PairedBootstrapResult } from "./statistics-CKOqre5S.js";
|
|
2
|
+
import { _ as paretoChart, a as ParetoPoint, c as ResearchReportCandidate, d as ResearchReportOptions, f as ResearchReportRecommendation, g as gainHistogram, h as SummaryTableRow, i as ParetoFigureSpec, l as ResearchReportDecision, m as SummaryTableOptions, n as GainDistributionFigureSpec, o as RESEARCH_REPORT_HARD_PAIR_FLOOR, p as SummaryTable, r as GainDistributionOptions, s as ResearchReport, t as GainDistributionBin, u as ResearchReportMethodology, v as researchReport, y as summaryTable } from "./summary-report-CPMINBqs.js";
|
|
3
|
+
import { _ as ReleaseConfidenceStatus, a as JudgeReplayGateArgs, b as assertReleaseConfidence, c as judgeReplayGate, d as ReleaseConfidenceAxis, f as ReleaseConfidenceAxisName, g as ReleaseConfidenceScorecard, h as ReleaseConfidenceMetrics, i as BootstrapResult, m as ReleaseConfidenceIssue, n as renderReleaseReport, o as Verdict, p as ReleaseConfidenceInput, r as BootstrapOptions, s as bootstrapCi, t as RenderReleaseReportOptions, v as ReleaseConfidenceThresholds, x as evaluateReleaseConfidence, y as ReleaseTraceEvidence } from "./release-report-DpBxGGI1.js";
|
|
4
4
|
import { a as PairedEvalueStep, c as pairedEvalueSequence, i as PairedEvalueSequence, n as InterimReleaseConfidenceInput, o as SequentialDecision, r as PairedEvalueOptions, s as evaluateInterimReleaseConfidence, t as InterimReleaseConfidence } from "./sequential-CYwq6Ff_.js";
|
|
5
5
|
import { a as rubricPredictiveValidity, i as RubricRanking, n as RubricPredictiveValidityInput, r as RubricPredictiveValidityReport, t as RubricOutcomePair } from "./rubric-predictive-validity-C1dCLcvb.js";
|
|
6
6
|
export { type BootstrapOptions, type BootstrapResult, type GainDistributionBin, type GainDistributionFigureSpec, type GainDistributionOptions, type InterimReleaseConfidence, type InterimReleaseConfidenceInput, type JudgeReplayGateArgs, type PairedBootstrapOptions, type PairedBootstrapResult, type PairedEvalueOptions, type PairedEvalueSequence, type PairedEvalueStep, type ParetoFigureSpec, type ParetoPoint, RESEARCH_REPORT_HARD_PAIR_FLOOR, type ReleaseConfidenceAxis, type ReleaseConfidenceAxisName, type ReleaseConfidenceInput, type ReleaseConfidenceIssue, type ReleaseConfidenceMetrics, type ReleaseConfidenceScorecard, type ReleaseConfidenceStatus, type ReleaseConfidenceThresholds, type ReleaseTraceEvidence, type RenderReleaseReportOptions, type ResearchReport, type ResearchReportCandidate, type ResearchReportDecision, type ResearchReportMethodology, type ResearchReportOptions, type ResearchReportRecommendation, type RubricOutcomePair, type RubricPredictiveValidityInput, type RubricPredictiveValidityReport, type RubricRanking, type SequentialDecision, type SummaryTable, type SummaryTableOptions, type SummaryTableRow, type Verdict, assertReleaseConfidence, benjaminiHochberg, bootstrapCi, evaluateInterimReleaseConfidence, evaluateReleaseConfidence, gainHistogram, judgeReplayGate, pairedBootstrap, pairedEvalueSequence, paretoChart, renderReleaseReport, researchReport, rubricPredictiveValidity, summaryTable, wilcoxonSignedRank };
|
package/dist/reporting.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as evaluateReleaseConfidence, i as assertReleaseConfidence, n as bootstrapCi, r as judgeReplayGate, t as renderReleaseReport } from "./release-report-
|
|
3
|
-
import { a as summaryTable, i as researchReport, n as gainHistogram, r as paretoChart, t as RESEARCH_REPORT_HARD_PAIR_FLOOR } from "./summary-report-
|
|
1
|
+
import { E as pairedBootstrap, W as wilcoxonSignedRank, s as benjaminiHochberg } from "./statistics-CnGCLLqc.js";
|
|
2
|
+
import { a as evaluateReleaseConfidence, i as assertReleaseConfidence, n as bootstrapCi, r as judgeReplayGate, t as renderReleaseReport } from "./release-report-DooPguBc.js";
|
|
3
|
+
import { a as summaryTable, i as researchReport, n as gainHistogram, r as paretoChart, t as RESEARCH_REPORT_HARD_PAIR_FLOOR } from "./summary-report-BEk8OFLs.js";
|
|
4
4
|
import { n as pairedEvalueSequence, t as evaluateInterimReleaseConfidence } from "./sequential-Br0mAPHA.js";
|
|
5
|
-
import { t as rubricPredictiveValidity } from "./rubric-predictive-validity-
|
|
5
|
+
import { t as rubricPredictiveValidity } from "./rubric-predictive-validity-BJf-8ejY.js";
|
|
6
6
|
export { RESEARCH_REPORT_HARD_PAIR_FLOOR, assertReleaseConfidence, benjaminiHochberg, bootstrapCi, evaluateInterimReleaseConfidence, evaluateReleaseConfidence, gainHistogram, judgeReplayGate, pairedBootstrap, pairedEvalueSequence, paretoChart, renderReleaseReport, researchReport, rubricPredictiveValidity, summaryTable, wilcoxonSignedRank };
|
|
@@ -5,7 +5,7 @@ import { s as TraceStore } from "./store-CT9YIIve.js";
|
|
|
5
5
|
import { i as TraceEmitter, t as RunCompleteHook } from "./emitter-DGQGoLyj.js";
|
|
6
6
|
import { a as RunIntegrityReport, n as RunIntegrityExpectations } from "./integrity-rmVhXWA7.js";
|
|
7
7
|
import { o as LlmClientOptions, u as LlmRouteRequirements } from "./llm-client-BiK4HW0u.js";
|
|
8
|
-
import {
|
|
8
|
+
import { d as ResearchReportOptions, s as ResearchReport, x as GateDecision } from "./summary-report-CPMINBqs.js";
|
|
9
9
|
//#region src/eval-campaign.d.ts
|
|
10
10
|
interface CampaignVariant<V> {
|
|
11
11
|
id: string;
|
|
@@ -312,4 +312,4 @@ declare class NoopResearcher implements Researcher {
|
|
|
312
312
|
}
|
|
313
313
|
//#endregion
|
|
314
314
|
export { EvalCampaignResult as _, FailureMode as a, SteeringChange as c, CampaignRunContext as d, CampaignRunOutcome as f, EvalCampaignOptions as g, CampaignVariant as h, ExperimentResult as i, CampaignFactoryParams as l, CampaignScenario as m, CallbackResearcherOptions as n, NoopResearcher as o, CampaignRunner as p, ExperimentPlan as r, Researcher as s, CallbackResearcher as t, CampaignIntegrityPolicy as u, FailedRun as v, runEvalCampaign as y };
|
|
315
|
-
//# sourceMappingURL=researcher-
|
|
315
|
+
//# sourceMappingURL=researcher-Doo95b50.d.ts.map
|