@tangle-network/agent-eval 0.179.0 → 0.181.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +119 -146
- package/dist/adapters/http.d.ts +2 -2
- package/dist/{agent-profile-B7yErX0q.d.ts → agent-profile-CivaSsSy.d.ts} +4 -4
- package/dist/{agent-profile-B7yErX0q.d.ts.map → agent-profile-CivaSsSy.d.ts.map} +1 -1
- package/dist/{agent-profile-cell-0gSi5ffD.js → agent-profile-cell-Cv6UA-W_.js} +20 -57
- package/dist/agent-profile-cell-Cv6UA-W_.js.map +1 -0
- package/dist/{agent-profile-cell-CTOZJUuE.d.ts → agent-profile-cell-s__adRnK.d.ts} +3 -3
- package/dist/agent-profile-cell-s__adRnK.d.ts.map +1 -0
- package/dist/analyst/index.d.ts +10 -10
- package/dist/analyst/index.js +4 -4
- package/dist/ast-CP9ae9B0.js +557 -0
- package/dist/ast-CP9ae9B0.js.map +1 -0
- package/dist/ast-hI-vjW6J.d.ts +457 -0
- package/dist/ast-hI-vjW6J.d.ts.map +1 -0
- package/dist/{benchmark-command-CY6Dg5t5.js → benchmark-command-B57n9vjz.js} +7 -6
- package/dist/{benchmark-command-CY6Dg5t5.js.map → benchmark-command-B57n9vjz.js.map} +1 -1
- package/dist/benchmarks/index.d.ts +4 -4
- package/dist/benchmarks/index.js +3 -3
- package/dist/campaign/index.d.ts +6 -6
- package/dist/campaign/index.js +8 -8
- package/dist/{campaign-BGEurASO.js → campaign-4_ppJW5X.js} +12 -12
- package/dist/{campaign-BGEurASO.js.map → campaign-4_ppJW5X.js.map} +1 -1
- package/dist/{campaign-evidence-D8DBLqLI.js → campaign-evidence-B8oF9xQ6.js} +515 -471
- package/dist/campaign-evidence-B8oF9xQ6.js.map +1 -0
- package/dist/cli.js +5 -8
- package/dist/cli.js.map +1 -1
- package/dist/{client-BlLY6o2w.js → client-CXE-U1SA.js} +3 -1
- package/dist/client-CXE-U1SA.js.map +1 -0
- package/dist/{client-CuQgX33c.d.ts → client-kh2jOjTK.d.ts} +4 -4
- package/dist/{client-CuQgX33c.d.ts.map → client-kh2jOjTK.d.ts.map} +1 -1
- package/dist/contract/index.d.ts +13 -13
- package/dist/contract/index.js +11 -10
- package/dist/contract/index.js.map +1 -1
- package/dist/{default-registry-IGDE9XIC.d.ts → default-registry-BwDSWVzg.d.ts} +6 -6
- package/dist/{default-registry-IGDE9XIC.d.ts.map → default-registry-BwDSWVzg.d.ts.map} +1 -1
- package/dist/{default-registry-BryMEmr8.js → default-registry-aL7xUrUz.js} +2 -2
- package/dist/{default-registry-BryMEmr8.js.map → default-registry-aL7xUrUz.js.map} +1 -1
- package/dist/{define-agent-eval-Cx4Ls9ta.d.ts → define-agent-eval-CwOWWQt_.d.ts} +33 -12
- package/dist/define-agent-eval-CwOWWQt_.d.ts.map +1 -0
- package/dist/{define-agent-eval-Dzidv34q.js → define-agent-eval-Ddu33JH9.js} +134 -67
- package/dist/define-agent-eval-Ddu33JH9.js.map +1 -0
- package/dist/{dspy-rlm-engine-xKiWmj_G.js → dspy-rlm-engine-S53V0HhE.js} +2 -2
- package/dist/{dspy-rlm-engine-xKiWmj_G.js.map → dspy-rlm-engine-S53V0HhE.js.map} +1 -1
- package/dist/{engine-CX8ReXkn.d.ts → engine-DS1cysJy.d.ts} +10 -7
- package/dist/engine-DS1cysJy.d.ts.map +1 -0
- package/dist/{eval-campaign-Cs-7MiCs.js → eval-campaign-aYdtjtJR.js} +4 -4
- package/dist/{eval-campaign-Cs-7MiCs.js.map → eval-campaign-aYdtjtJR.js.map} +1 -1
- package/dist/{exact-types-B7LC1EyX.d.ts → exact-types-BZDe0W2D.d.ts} +2 -2
- package/dist/{exact-types-B7LC1EyX.d.ts.map → exact-types-BZDe0W2D.d.ts.map} +1 -1
- package/dist/experiment/index.d.ts +27 -477
- package/dist/experiment/index.d.ts.map +1 -1
- package/dist/experiment/index.js +95 -559
- package/dist/experiment/index.js.map +1 -1
- package/dist/{experiment-tracker-B3TiF5-u.d.ts → experiment-tracker-C7PfnF4b.d.ts} +2 -2
- package/dist/{experiment-tracker-B3TiF5-u.d.ts.map → experiment-tracker-C7PfnF4b.d.ts.map} +1 -1
- package/dist/{external-optimizer-process-Dlz8YxrT.js → external-optimizer-process-QDRURJAM.js} +3 -3
- package/dist/{external-optimizer-process-Dlz8YxrT.js.map → external-optimizer-process-QDRURJAM.js.map} +1 -1
- package/dist/{external-optimizer-subprocess-q3VzlGAO.js → external-optimizer-subprocess-D4dzUBZI.js} +3 -2
- package/dist/{external-optimizer-subprocess-q3VzlGAO.js.map → external-optimizer-subprocess-D4dzUBZI.js.map} +1 -1
- package/dist/{feedback-trajectory-eHWNv5Aj.d.ts → feedback-trajectory-CXmtITBo.d.ts} +3 -3
- package/dist/{feedback-trajectory-eHWNv5Aj.d.ts.map → feedback-trajectory-CXmtITBo.d.ts.map} +1 -1
- package/dist/hosted/index.d.ts +2 -2
- package/dist/hosted/index.d.ts.map +1 -1
- package/dist/hosted/index.js +1 -1
- package/dist/{index-BxWvILU8.d.ts → index-Bp_6sj3x.d.ts} +109 -56
- package/dist/index-Bp_6sj3x.d.ts.map +1 -0
- package/dist/{index-e7LXeRVa.d.ts → index-CJ3LhKIX.d.ts} +2 -2
- package/dist/{index-e7LXeRVa.d.ts.map → index-CJ3LhKIX.d.ts.map} +1 -1
- package/dist/{index-CbLmrWCa.d.ts → index-DNntP4ch.d.ts} +8 -8
- package/dist/{index-CbLmrWCa.d.ts.map → index-DNntP4ch.d.ts.map} +1 -1
- package/dist/{index-DxNYmx4a.d.ts → index-DoykkxW0.d.ts} +11 -11
- package/dist/{index-DxNYmx4a.d.ts.map → index-DoykkxW0.d.ts.map} +1 -1
- package/dist/index.d.ts +28 -28
- package/dist/index.js +25 -16
- package/dist/index.js.map +1 -1
- package/dist/{insight-report-DETqPc_A.d.ts → insight-report-D1qa0HWs.d.ts} +9 -5
- package/dist/{insight-report-DETqPc_A.d.ts.map → insight-report-D1qa0HWs.d.ts.map} +1 -1
- package/dist/{integrity-DsHWCebQ.js → integrity-DH5ng72x.js} +2 -2
- package/dist/{integrity-DsHWCebQ.js.map → integrity-DH5ng72x.js.map} +1 -1
- package/dist/{integrity-BKTcA-HP.d.ts → integrity-rGOfSUle.d.ts} +2 -2
- package/dist/{integrity-BKTcA-HP.d.ts.map → integrity-rGOfSUle.d.ts.map} +1 -1
- package/dist/{ledger-core-Cs9f7385.js → journal-Cs9f7385.js} +1 -1
- package/dist/journal-Cs9f7385.js.map +1 -0
- package/dist/{judge-calibration-C5CbMYce.d.ts → judge-calibration-DFtEMlde.d.ts} +31 -2
- package/dist/judge-calibration-DFtEMlde.d.ts.map +1 -0
- package/dist/{judge-calibration-BnpVKtnb.js → judge-calibration-DYmaBtJr.js} +48 -2
- package/dist/{judge-calibration-BnpVKtnb.js.map → judge-calibration-DYmaBtJr.js.map} +1 -1
- package/dist/ledger-core/index.d.ts +1 -1
- package/dist/ledger-core/index.js +1 -1
- package/dist/{llm-judge-v80Kmu9g.js → llm-judge-DEFZeSiu.js} +645 -456
- package/dist/llm-judge-DEFZeSiu.js.map +1 -0
- package/dist/{matrix-DeMmnWrP.d.ts → matrix-CyhW-vgJ.d.ts} +2 -2
- package/dist/{matrix-DeMmnWrP.d.ts.map → matrix-CyhW-vgJ.d.ts.map} +1 -1
- package/dist/meta-eval/index.d.ts +138 -7
- package/dist/meta-eval/index.d.ts.map +1 -1
- package/dist/meta-eval/index.js +245 -97
- package/dist/meta-eval/index.js.map +1 -1
- package/dist/{mint-Cc1_zwRQ.js → mint-ySIIkKlV.js} +2 -2
- package/dist/{mint-Cc1_zwRQ.js.map → mint-ySIIkKlV.js.map} +1 -1
- package/dist/multishot/golden/index.d.ts +1 -1
- package/dist/multishot/index.d.ts +2 -2
- package/dist/openapi.json +1 -1
- package/dist/outcome-store-BXlkwMPR.js +131 -0
- package/dist/outcome-store-BXlkwMPR.js.map +1 -0
- package/dist/{outcome-store-BYHIuO0e.d.ts → outcome-store-CNt4iZ67.d.ts} +18 -25
- package/dist/outcome-store-CNt4iZ67.d.ts.map +1 -0
- package/dist/{paired-promotion-decision-CGzg0cI_.d.ts → paired-promotion-decision-DPsMQm-0.d.ts} +13 -7
- package/dist/{paired-promotion-decision-CGzg0cI_.d.ts.map → paired-promotion-decision-DPsMQm-0.d.ts.map} +1 -1
- package/dist/pipelines/index.js +1 -1
- package/dist/{produced-state-Cv0kJJuP.js → produced-state-BHboMaab.js} +3 -3
- package/dist/{produced-state-Cv0kJJuP.js.map → produced-state-BHboMaab.js.map} +1 -1
- package/dist/profile-cell.d.ts +1 -1
- package/dist/profile-cell.js +1 -1
- package/dist/{promotion-policy-DWOm70gx.js → promotion-policy-CDMMxzb6.js} +28 -40
- package/dist/promotion-policy-CDMMxzb6.js.map +1 -0
- package/dist/{registry-ByVld1-5.d.ts → registry-BRbB6Y0v.d.ts} +4 -4
- package/dist/{registry-ByVld1-5.d.ts.map → registry-BRbB6Y0v.d.ts.map} +1 -1
- package/dist/{release-confidence-BAcNYOf1.d.ts → release-confidence-BcqeQTHW.d.ts} +3 -3
- package/dist/{release-confidence-BAcNYOf1.d.ts.map → release-confidence-BcqeQTHW.d.ts.map} +1 -1
- package/dist/{release-confidence-BcGCclTB.js → release-confidence-DMg8n18l.js} +2 -2
- package/dist/{release-confidence-BcGCclTB.js.map → release-confidence-DMg8n18l.js.map} +1 -1
- package/dist/{report-command-DKlXfU5r.js → report-command-V1ecVgAv.js} +27 -3
- package/dist/report-command-V1ecVgAv.js.map +1 -0
- package/dist/reporting.d.ts +4 -4
- package/dist/reporting.js +3 -3
- package/dist/{researcher-jsW1X94L.d.ts → researcher-64T49THL.d.ts} +6 -6
- package/dist/{researcher-jsW1X94L.d.ts.map → researcher-64T49THL.d.ts.map} +1 -1
- package/dist/{reward-hacking-ZXEi9VCq.d.ts → reward-hacking-uzO_ihep.d.ts} +2 -2
- package/dist/{reward-hacking-ZXEi9VCq.d.ts.map → reward-hacking-uzO_ihep.d.ts.map} +1 -1
- package/dist/rl.d.ts +53 -99
- package/dist/rl.d.ts.map +1 -1
- package/dist/rl.js +182 -169
- package/dist/rl.js.map +1 -1
- package/dist/rollout/index.d.ts +1 -1
- package/dist/rollout/index.js +2 -2
- package/dist/{rollout-DmoJVqrF.js → rollout-B-UF5R6w.js} +2 -2
- package/dist/{rollout-DmoJVqrF.js.map → rollout-B-UF5R6w.js.map} +1 -1
- package/dist/rubric-predictive-validity-Bmj2_cll.d.ts +79 -0
- package/dist/rubric-predictive-validity-Bmj2_cll.d.ts.map +1 -0
- package/dist/rubric-predictive-validity-CCK-1B7w.js +178 -0
- package/dist/rubric-predictive-validity-CCK-1B7w.js.map +1 -0
- package/dist/{run-record-DTv1MdjK.d.ts → run-record-BiTWauyO.d.ts} +2 -2
- package/dist/{run-record-DTv1MdjK.d.ts.map → run-record-BiTWauyO.d.ts.map} +1 -1
- package/dist/run-record-Br-Yzt_k.js +464 -0
- package/dist/run-record-Br-Yzt_k.js.map +1 -0
- package/dist/{run-record-DQpSf7t-.js → run-record-DualPTn2.js} +2 -2
- package/dist/{run-record-DQpSf7t-.js.map → run-record-DualPTn2.js.map} +1 -1
- package/dist/{semantic-concept-judge-Bi6_iGqg.js → semantic-concept-judge-Bm5JDEKO.js} +3 -3
- package/dist/{semantic-concept-judge-Bi6_iGqg.js.map → semantic-concept-judge-Bm5JDEKO.js.map} +1 -1
- package/dist/{sequential-B5gXgcyp.js → sequential-DAsyV2T9.js} +42 -25
- package/dist/sequential-DAsyV2T9.js.map +1 -0
- package/dist/{series-convergence-DeG33RpC.d.ts → series-convergence-BnMs_uAr.d.ts} +3 -3
- package/dist/{series-convergence-DeG33RpC.d.ts.map → series-convergence-BnMs_uAr.d.ts.map} +1 -1
- package/dist/{skillopt-optimization-method-C3oYul8v.js → skillopt-optimization-method-CL_0aArC.js} +5 -5
- package/dist/{skillopt-optimization-method-C3oYul8v.js.map → skillopt-optimization-method-CL_0aArC.js.map} +1 -1
- package/dist/{statistical-heldout-0La5ZTlv.d.ts → statistical-heldout-CpVd6FmY.d.ts} +207 -144
- package/dist/statistical-heldout-CpVd6FmY.d.ts.map +1 -0
- package/dist/{store-tool-spans-4J1EDElP.d.ts → store-tool-spans-Dt-YdAuE.d.ts} +6 -6
- package/dist/{store-tool-spans-4J1EDElP.d.ts.map → store-tool-spans-Dt-YdAuE.d.ts.map} +1 -1
- package/dist/{summary-report-gMrbYawB.d.ts → summary-report-D1h4dlrK.d.ts} +3 -3
- package/dist/{summary-report-gMrbYawB.d.ts.map → summary-report-D1h4dlrK.d.ts.map} +1 -1
- package/dist/{summary-report-B16xy9Kd.js → summary-report-e-MaOAHV.js} +2 -2
- package/dist/{summary-report-B16xy9Kd.js.map → summary-report-e-MaOAHV.js.map} +1 -1
- package/dist/supervisor-run/index.d.ts +4 -2
- package/dist/supervisor-run/index.d.ts.map +1 -1
- package/dist/supervisor-run/index.js +3 -3
- package/dist/{terminal-record-Ce9_UjRz.js → terminal-record-BtPwKTSr.js} +58 -26
- package/dist/terminal-record-BtPwKTSr.js.map +1 -0
- package/dist/{tool-groups-2QA0S7dK.d.ts → tool-groups-B2bSNaJB.d.ts} +3 -3
- package/dist/tool-groups-B2bSNaJB.d.ts.map +1 -0
- package/dist/{tool-waste-B9tdWV6g.js → tool-waste-C7MU9u1e.js} +2 -2
- package/dist/{tool-waste-B9tdWV6g.js.map → tool-waste-C7MU9u1e.js.map} +1 -1
- package/dist/trace-repair/index.d.ts +2 -2
- package/dist/traces.d.ts +6 -6
- package/dist/traces.js +1 -1
- package/dist/{types-BmlkCrg0.d.ts → types-BvZoPTGa.d.ts} +3 -3
- package/dist/{types-BmlkCrg0.d.ts.map → types-BvZoPTGa.d.ts.map} +1 -1
- package/dist/{types-gvRsyJLh.d.ts → types-CBbLtr2J.d.ts} +38 -3
- package/dist/{types-gvRsyJLh.d.ts.map → types-CBbLtr2J.d.ts.map} +1 -1
- package/dist/{types-C34V4Vto.d.ts → types-CS0qk_Yp.d.ts} +4 -4
- package/dist/{types-C34V4Vto.d.ts.map → types-CS0qk_Yp.d.ts.map} +1 -1
- package/dist/{types-DzuaM493.d.ts → types-D7gEdPoQ.d.ts} +3 -3
- package/dist/{types-DzuaM493.d.ts.map → types-D7gEdPoQ.d.ts.map} +1 -1
- package/dist/{types-vUdAx2Cj.d.ts → types-lPkDQNqJ.d.ts} +20 -2
- package/dist/{types-vUdAx2Cj.d.ts.map → types-lPkDQNqJ.d.ts.map} +1 -1
- package/dist/wire/index.d.ts +2 -2
- package/docs/adapters-observability.md +14 -0
- package/docs/campaign-proposers.md +86 -128
- package/docs/charter.md +108 -112
- package/docs/concepts.md +157 -69
- package/docs/design/mlbenchmarks-book-review.md +440 -0
- package/docs/design/mlbenchmarks-review/observations.json +713 -0
- package/docs/design/mlbenchmarks-review/probes.mts +476 -0
- package/docs/design/mlbenchmarks-review/sources.json +200 -0
- package/docs/design/self-improvement-evidence-audit.md +263 -0
- package/docs/design.md +2 -1
- package/docs/eval-surface-map.md +95 -42
- package/docs/evaluation-integrity.md +220 -0
- package/docs/experiment.md +111 -55
- package/docs/feature-guide.md +5 -6
- package/docs/hosted-ingest-spec.md +4 -11
- package/docs/insight-report.md +187 -455
- package/docs/outcome-validity.md +182 -0
- package/docs/product-eval-adoption.md +1 -2
- package/docs/research-report-methodology.md +7 -7
- package/docs/search-history-receipts.md +8 -0
- package/docs/statistical-evidence.md +129 -0
- package/docs/verdicts.md +76 -49
- package/package.json +1 -1
- package/dist/agent-profile-cell-0gSi5ffD.js.map +0 -1
- package/dist/agent-profile-cell-CTOZJUuE.d.ts.map +0 -1
- package/dist/campaign-evidence-D8DBLqLI.js.map +0 -1
- package/dist/client-BlLY6o2w.js.map +0 -1
- package/dist/define-agent-eval-Cx4Ls9ta.d.ts.map +0 -1
- package/dist/define-agent-eval-Dzidv34q.js.map +0 -1
- package/dist/engine-CX8ReXkn.d.ts.map +0 -1
- package/dist/index-BxWvILU8.d.ts.map +0 -1
- package/dist/judge-calibration-C5CbMYce.d.ts.map +0 -1
- package/dist/ledger-core-Cs9f7385.js.map +0 -1
- package/dist/llm-judge-v80Kmu9g.js.map +0 -1
- package/dist/outcome-store-BYHIuO0e.d.ts.map +0 -1
- package/dist/outcome-store-ChBKlTd_.js +0 -75
- package/dist/outcome-store-ChBKlTd_.js.map +0 -1
- package/dist/promotion-policy-DWOm70gx.js.map +0 -1
- package/dist/report-command-DKlXfU5r.js.map +0 -1
- package/dist/rubric-predictive-validity-2D5Gw9z9.js +0 -131
- package/dist/rubric-predictive-validity-2D5Gw9z9.js.map +0 -1
- package/dist/rubric-predictive-validity-Dl1dvKCv.d.ts +0 -75
- package/dist/rubric-predictive-validity-Dl1dvKCv.d.ts.map +0 -1
- package/dist/run-record-CR63CpHK.js +0 -216
- package/dist/run-record-CR63CpHK.js.map +0 -1
- package/dist/sequential-B5gXgcyp.js.map +0 -1
- package/dist/statistical-heldout-0La5ZTlv.d.ts.map +0 -1
- package/dist/terminal-record-Ce9_UjRz.js.map +0 -1
- package/dist/tool-groups-2QA0S7dK.d.ts.map +0 -1
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { i as makeRng } from "./internal-BMFSR8Ns.js";
|
|
2
|
-
import { a as spearmanR, r as pearsonR } from "./descriptive-1V17A-qa.js";
|
|
3
|
-
//#region src/meta-eval/rubric-predictive-validity.ts
|
|
4
|
-
async function rubricPredictiveValidity(input) {
|
|
5
|
-
const minSamples = input.minSamples ?? 8;
|
|
6
|
-
const reduction = input.reduction ?? "latest";
|
|
7
|
-
const resamples = input.bootstrapResamples ?? 500;
|
|
8
|
-
const outcomes = await input.outcomes.list();
|
|
9
|
-
const outcomesByRun = /* @__PURE__ */ new Map();
|
|
10
|
-
for (const o of outcomes) {
|
|
11
|
-
const arr = outcomesByRun.get(o.runId) ?? [];
|
|
12
|
-
arr.push(o);
|
|
13
|
-
outcomesByRun.set(o.runId, arr);
|
|
14
|
-
}
|
|
15
|
-
const observedRubrics = /* @__PURE__ */ new Set();
|
|
16
|
-
for (const r of input.runs) for (const k of Object.keys(r.outcome.raw)) observedRubrics.add(k);
|
|
17
|
-
const rubrics = input.rubrics ?? [...observedRubrics];
|
|
18
|
-
const buckets = [];
|
|
19
|
-
for (const r of rubrics) for (const o of input.outcomeMetrics) buckets.push({
|
|
20
|
-
rubric: r,
|
|
21
|
-
outcome: o,
|
|
22
|
-
xs: [],
|
|
23
|
-
ys: []
|
|
24
|
-
});
|
|
25
|
-
let joined = 0;
|
|
26
|
-
let skipped = 0;
|
|
27
|
-
for (const run of input.runs) {
|
|
28
|
-
const os = outcomesByRun.get(run.runId);
|
|
29
|
-
if (!os || os.length === 0) {
|
|
30
|
-
skipped++;
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
let joinedThisRun = false;
|
|
34
|
-
for (const r of rubrics) {
|
|
35
|
-
const x = run.outcome.raw[r];
|
|
36
|
-
if (typeof x !== "number" || !Number.isFinite(x)) continue;
|
|
37
|
-
for (const o of input.outcomeMetrics) {
|
|
38
|
-
const values = os.map((row) => row.metrics[o]).filter((v) => typeof v === "number" && Number.isFinite(v));
|
|
39
|
-
if (values.length === 0) continue;
|
|
40
|
-
const y = reduce(values, os, o, reduction);
|
|
41
|
-
if (y === null) continue;
|
|
42
|
-
const bucket = buckets.find((b) => b.rubric === r && b.outcome === o);
|
|
43
|
-
bucket.xs.push(x);
|
|
44
|
-
bucket.ys.push(y);
|
|
45
|
-
joinedThisRun = true;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (joinedThisRun) joined++;
|
|
49
|
-
}
|
|
50
|
-
const pairs = [];
|
|
51
|
-
for (const b of buckets) {
|
|
52
|
-
if (b.xs.length < minSamples) continue;
|
|
53
|
-
const pearson = pearsonR(b.xs, b.ys);
|
|
54
|
-
const spearman = spearmanR(b.xs, b.ys);
|
|
55
|
-
const ci = bootstrapCi(b.xs, b.ys, resamples, input.seed);
|
|
56
|
-
const verdict = Math.abs(spearman) >= .7 ? "load_bearing" : Math.abs(spearman) >= .4 ? "informative" : "decorative";
|
|
57
|
-
pairs.push({
|
|
58
|
-
rubric: b.rubric,
|
|
59
|
-
outcome: b.outcome,
|
|
60
|
-
n: b.xs.length,
|
|
61
|
-
pearson,
|
|
62
|
-
spearman,
|
|
63
|
-
ci95: ci,
|
|
64
|
-
verdict
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const byRubric = /* @__PURE__ */ new Map();
|
|
68
|
-
for (const p of pairs) {
|
|
69
|
-
const arr = byRubric.get(p.rubric) ?? [];
|
|
70
|
-
arr.push(p);
|
|
71
|
-
byRubric.set(p.rubric, arr);
|
|
72
|
-
}
|
|
73
|
-
const ranked = [...byRubric.entries()].map(([rubric, ps]) => {
|
|
74
|
-
const best = ps.reduce((a, b) => Math.abs(b.spearman) > Math.abs(a.spearman) ? b : a);
|
|
75
|
-
return {
|
|
76
|
-
rubric,
|
|
77
|
-
bestOutcome: best.outcome,
|
|
78
|
-
spearman: best.spearman,
|
|
79
|
-
pearson: best.pearson,
|
|
80
|
-
n: best.n,
|
|
81
|
-
verdict: best.verdict
|
|
82
|
-
};
|
|
83
|
-
}).sort((a, b) => Math.abs(b.spearman) - Math.abs(a.spearman));
|
|
84
|
-
const rubricsWithoutData = rubrics.filter((r) => !byRubric.has(r));
|
|
85
|
-
return {
|
|
86
|
-
pairs,
|
|
87
|
-
ranked,
|
|
88
|
-
joinedSamples: joined,
|
|
89
|
-
skippedRuns: skipped,
|
|
90
|
-
rubricsWithoutData
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function reduce(values, outcomes, metric, kind) {
|
|
94
|
-
if (values.length === 0) return null;
|
|
95
|
-
if (kind === "mean") return values.reduce((s, v) => s + v, 0) / values.length;
|
|
96
|
-
if (kind === "max") return Math.max(...values);
|
|
97
|
-
return [...outcomes].filter((o) => typeof o.metrics[metric] === "number").sort((a, b) => b.capturedAt - a.capturedAt)[0]?.metrics[metric] ?? null;
|
|
98
|
-
}
|
|
99
|
-
function bootstrapCi(xs, ys, iterations, seed) {
|
|
100
|
-
const n = xs.length;
|
|
101
|
-
if (n < 3) return {
|
|
102
|
-
low: NaN,
|
|
103
|
-
high: NaN
|
|
104
|
-
};
|
|
105
|
-
const rng = makeRng(seed, xs, ys);
|
|
106
|
-
const samples = [];
|
|
107
|
-
for (let b = 0; b < iterations; b++) {
|
|
108
|
-
const rx = new Array(n);
|
|
109
|
-
const ry = new Array(n);
|
|
110
|
-
for (let i = 0; i < n; i++) {
|
|
111
|
-
const idx = Math.floor(rng() * n);
|
|
112
|
-
rx[i] = xs[idx];
|
|
113
|
-
ry[i] = ys[idx];
|
|
114
|
-
}
|
|
115
|
-
const r = pearsonR(rx, ry);
|
|
116
|
-
if (Number.isFinite(r)) samples.push(r);
|
|
117
|
-
}
|
|
118
|
-
samples.sort((a, b) => a - b);
|
|
119
|
-
if (samples.length === 0) return {
|
|
120
|
-
low: NaN,
|
|
121
|
-
high: NaN
|
|
122
|
-
};
|
|
123
|
-
return {
|
|
124
|
-
low: samples[Math.floor(.025 * samples.length)],
|
|
125
|
-
high: samples[Math.min(samples.length - 1, Math.floor(.975 * samples.length))]
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
//#endregion
|
|
129
|
-
export { rubricPredictiveValidity as t };
|
|
130
|
-
|
|
131
|
-
//# sourceMappingURL=rubric-predictive-validity-2D5Gw9z9.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rubric-predictive-validity-2D5Gw9z9.js","names":[],"sources":["../src/meta-eval/rubric-predictive-validity.ts"],"sourcesContent":["/**\n * Rubric predictive validity — does our eval rubric predict deployment\n * outcomes?\n *\n * `correlationStudy` (already in this package) joins a `TraceStore` to an\n * `OutcomeStore` and computes Pearson + Spearman + bootstrap CI for each\n * (eval-metric, outcome-metric) pair. That answers \"does X correlate with\n * Y at all.\" `rubricPredictiveValidity` is the campaign-shaped wrapper\n * around it: take a sequence of `RunRecord`s (the canonical campaign\n * artifact) and a `DeploymentOutcomeStore`, join on `runId`, return a\n * ranked verdict on every rubric whose dimension scores were captured in\n * `outcome.raw`.\n *\n * The point — quoting the methodology doc — is that **without this loop\n * every rubric is faith-based**. Once it's wired, you know which rubrics\n * have earned their promotion power and which ones are decoration.\n *\n * const validity = await rubricPredictiveValidity({\n * runs: lastQuarter,\n * outcomes: shipFlagOutcomeStore,\n * outcomeMetrics: ['revenue_lift', 'retention_30d', 'csat'],\n * rubrics: ['anti_slop', 'semantic_concept', 'tool_recovery'],\n * })\n * for (const r of validity.ranked) {\n * console.log(`${r.rubric} → ${r.bestOutcome}: ρ=${r.spearman.toFixed(2)}`)\n * }\n *\n * The function is intentionally read-only. Use the verdict to deprecate\n * decorative rubrics, re-weight composite scores, or trigger a\n * recalibration sweep when predictive validity drops below a threshold.\n */\n\nimport type { RunRecord } from '../run-record'\nimport { pearsonR, spearmanR } from '../statistics'\nimport { makeRng } from '../statistics/internal'\nimport type { DeploymentOutcome, OutcomeStore } from './outcome-store'\n\nexport interface RubricPredictiveValidityInput {\n /**\n * Canonical campaign output. Each record's `outcome.raw[<rubricId>]`\n * provides the eval score; missing keys are silently skipped per pair.\n */\n runs: RunRecord[]\n outcomes: OutcomeStore\n /**\n * Outcome metric names to evaluate against. Each must appear in at\n * least one `DeploymentOutcome.metrics` keyspace; pairs with too few\n * joined samples are excluded from the result.\n */\n outcomeMetrics: string[]\n /**\n * Rubric ids to evaluate. Must appear as keys in `RunRecord.outcome.raw`.\n * If omitted, every numeric key in `outcome.raw` across the run set is\n * treated as a rubric.\n */\n rubrics?: string[]\n /** Minimum joined-sample count before a pair is reported. Default 8. */\n minSamples?: number\n /** Bootstrap resamples for CI. Default 500. */\n bootstrapResamples?: number\n /** Seed for the bootstrap. Absent, the seed is derived from the paired\n * observations, so the same input reproduces the same interval. */\n seed?: number\n /**\n * Reduction when multiple outcomes attach to one runId. Default `'latest'`\n * (most recently captured).\n */\n reduction?: 'latest' | 'mean' | 'max'\n}\n\nexport interface RubricOutcomePair {\n rubric: string\n outcome: string\n n: number\n pearson: number\n spearman: number\n ci95: { low: number; high: number }\n /**\n * Verdict bucket. `load_bearing` ≥ 0.7, `informative` ≥ 0.4,\n * `decorative` < 0.4 in absolute correlation. A negative correlation\n * with a desired outcome is also `decorative` — actively misleading\n * is worse than uninformative.\n */\n verdict: 'load_bearing' | 'informative' | 'decorative'\n}\n\nexport interface RubricRanking {\n rubric: string\n /** Outcome metric this rubric correlated best with. */\n bestOutcome: string\n spearman: number\n pearson: number\n n: number\n verdict: RubricOutcomePair['verdict']\n}\n\nexport interface RubricPredictiveValidityReport {\n pairs: RubricOutcomePair[]\n /** Per-rubric best pair, sorted descending by |spearman|. */\n ranked: RubricRanking[]\n joinedSamples: number\n skippedRuns: number\n /** Rubrics that were declared but never produced a usable score. */\n rubricsWithoutData: string[]\n}\n\nexport async function rubricPredictiveValidity(\n input: RubricPredictiveValidityInput,\n): Promise<RubricPredictiveValidityReport> {\n const minSamples = input.minSamples ?? 8\n const reduction = input.reduction ?? 'latest'\n const resamples = input.bootstrapResamples ?? 500\n\n const outcomes = await input.outcomes.list()\n const outcomesByRun = new Map<string, DeploymentOutcome[]>()\n for (const o of outcomes) {\n const arr = outcomesByRun.get(o.runId) ?? []\n arr.push(o)\n outcomesByRun.set(o.runId, arr)\n }\n\n // Discover rubrics: caller-declared OR every numeric key in outcome.raw\n // observed across runs.\n const observedRubrics = new Set<string>()\n for (const r of input.runs) {\n for (const k of Object.keys(r.outcome.raw)) observedRubrics.add(k)\n }\n const rubrics = input.rubrics ?? [...observedRubrics]\n\n // Collect aligned (x, y) pairs per (rubric, outcome).\n type Bucket = { rubric: string; outcome: string; xs: number[]; ys: number[] }\n const buckets: Bucket[] = []\n for (const r of rubrics) {\n for (const o of input.outcomeMetrics) {\n buckets.push({ rubric: r, outcome: o, xs: [], ys: [] })\n }\n }\n\n let joined = 0\n let skipped = 0\n for (const run of input.runs) {\n const os = outcomesByRun.get(run.runId)\n if (!os || os.length === 0) {\n skipped++\n continue\n }\n let joinedThisRun = false\n for (const r of rubrics) {\n const x = run.outcome.raw[r]\n if (typeof x !== 'number' || !Number.isFinite(x)) continue\n for (const o of input.outcomeMetrics) {\n const values = os\n .map((row) => row.metrics[o])\n .filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n if (values.length === 0) continue\n const y = reduce(values, os, o, reduction)\n if (y === null) continue\n const bucket = buckets.find((b) => b.rubric === r && b.outcome === o)!\n bucket.xs.push(x)\n bucket.ys.push(y)\n joinedThisRun = true\n }\n }\n if (joinedThisRun) joined++\n }\n\n const pairs: RubricOutcomePair[] = []\n for (const b of buckets) {\n if (b.xs.length < minSamples) continue\n const pearson = pearsonR(b.xs, b.ys)\n const spearman = spearmanR(b.xs, b.ys)\n const ci = bootstrapCi(b.xs, b.ys, resamples, input.seed)\n const verdict: RubricOutcomePair['verdict'] =\n Math.abs(spearman) >= 0.7\n ? 'load_bearing'\n : Math.abs(spearman) >= 0.4\n ? 'informative'\n : 'decorative'\n pairs.push({\n rubric: b.rubric,\n outcome: b.outcome,\n n: b.xs.length,\n pearson,\n spearman,\n ci95: ci,\n verdict,\n })\n }\n\n const byRubric = new Map<string, RubricOutcomePair[]>()\n for (const p of pairs) {\n const arr = byRubric.get(p.rubric) ?? []\n arr.push(p)\n byRubric.set(p.rubric, arr)\n }\n const ranked: RubricRanking[] = [...byRubric.entries()]\n .map(([rubric, ps]) => {\n const best = ps.reduce((a, b) => (Math.abs(b.spearman) > Math.abs(a.spearman) ? b : a))\n return {\n rubric,\n bestOutcome: best.outcome,\n spearman: best.spearman,\n pearson: best.pearson,\n n: best.n,\n verdict: best.verdict,\n }\n })\n .sort((a, b) => Math.abs(b.spearman) - Math.abs(a.spearman))\n\n const rubricsWithoutData = rubrics.filter((r) => !byRubric.has(r))\n\n return { pairs, ranked, joinedSamples: joined, skippedRuns: skipped, rubricsWithoutData }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction reduce(\n values: number[],\n outcomes: DeploymentOutcome[],\n metric: string,\n kind: 'latest' | 'mean' | 'max',\n): number | null {\n if (values.length === 0) return null\n if (kind === 'mean') return values.reduce((s, v) => s + v, 0) / values.length\n if (kind === 'max') return Math.max(...values)\n // 'latest'\n const sorted = [...outcomes]\n .filter((o) => typeof o.metrics[metric] === 'number')\n .sort((a, b) => b.capturedAt - a.capturedAt)\n return sorted[0]?.metrics[metric] ?? null\n}\n\nfunction bootstrapCi(\n xs: number[],\n ys: number[],\n iterations: number,\n seed: number | undefined,\n): { low: number; high: number } {\n const n = xs.length\n if (n < 3) return { low: Number.NaN, high: Number.NaN }\n const rng = makeRng(seed, xs, ys)\n const samples: number[] = []\n for (let b = 0; b < iterations; b++) {\n const rx = new Array<number>(n)\n const ry = new Array<number>(n)\n for (let i = 0; i < n; i++) {\n const idx = Math.floor(rng() * n)\n rx[i] = xs[idx]!\n ry[i] = ys[idx]!\n }\n const r = pearsonR(rx, ry)\n if (Number.isFinite(r)) samples.push(r)\n }\n samples.sort((a, b) => a - b)\n if (samples.length === 0) return { low: Number.NaN, high: Number.NaN }\n return {\n low: samples[Math.floor(0.025 * samples.length)]!,\n high: samples[Math.min(samples.length - 1, Math.floor(0.975 * samples.length))]!,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { a as RunRecord } from "./run-record-DTv1MdjK.js";
|
|
2
|
-
import { o as OutcomeStore } from "./outcome-store-BYHIuO0e.js";
|
|
3
|
-
//#region src/meta-eval/rubric-predictive-validity.d.ts
|
|
4
|
-
interface RubricPredictiveValidityInput {
|
|
5
|
-
/**
|
|
6
|
-
* Canonical campaign output. Each record's `outcome.raw[<rubricId>]`
|
|
7
|
-
* provides the eval score; missing keys are silently skipped per pair.
|
|
8
|
-
*/
|
|
9
|
-
runs: RunRecord[];
|
|
10
|
-
outcomes: OutcomeStore;
|
|
11
|
-
/**
|
|
12
|
-
* Outcome metric names to evaluate against. Each must appear in at
|
|
13
|
-
* least one `DeploymentOutcome.metrics` keyspace; pairs with too few
|
|
14
|
-
* joined samples are excluded from the result.
|
|
15
|
-
*/
|
|
16
|
-
outcomeMetrics: string[];
|
|
17
|
-
/**
|
|
18
|
-
* Rubric ids to evaluate. Must appear as keys in `RunRecord.outcome.raw`.
|
|
19
|
-
* If omitted, every numeric key in `outcome.raw` across the run set is
|
|
20
|
-
* treated as a rubric.
|
|
21
|
-
*/
|
|
22
|
-
rubrics?: string[];
|
|
23
|
-
/** Minimum joined-sample count before a pair is reported. Default 8. */
|
|
24
|
-
minSamples?: number;
|
|
25
|
-
/** Bootstrap resamples for CI. Default 500. */
|
|
26
|
-
bootstrapResamples?: number;
|
|
27
|
-
/** Seed for the bootstrap. Absent, the seed is derived from the paired
|
|
28
|
-
* observations, so the same input reproduces the same interval. */
|
|
29
|
-
seed?: number;
|
|
30
|
-
/**
|
|
31
|
-
* Reduction when multiple outcomes attach to one runId. Default `'latest'`
|
|
32
|
-
* (most recently captured).
|
|
33
|
-
*/
|
|
34
|
-
reduction?: 'latest' | 'mean' | 'max';
|
|
35
|
-
}
|
|
36
|
-
interface RubricOutcomePair {
|
|
37
|
-
rubric: string;
|
|
38
|
-
outcome: string;
|
|
39
|
-
n: number;
|
|
40
|
-
pearson: number;
|
|
41
|
-
spearman: number;
|
|
42
|
-
ci95: {
|
|
43
|
-
low: number;
|
|
44
|
-
high: number;
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* Verdict bucket. `load_bearing` ≥ 0.7, `informative` ≥ 0.4,
|
|
48
|
-
* `decorative` < 0.4 in absolute correlation. A negative correlation
|
|
49
|
-
* with a desired outcome is also `decorative` — actively misleading
|
|
50
|
-
* is worse than uninformative.
|
|
51
|
-
*/
|
|
52
|
-
verdict: 'load_bearing' | 'informative' | 'decorative';
|
|
53
|
-
}
|
|
54
|
-
interface RubricRanking {
|
|
55
|
-
rubric: string;
|
|
56
|
-
/** Outcome metric this rubric correlated best with. */
|
|
57
|
-
bestOutcome: string;
|
|
58
|
-
spearman: number;
|
|
59
|
-
pearson: number;
|
|
60
|
-
n: number;
|
|
61
|
-
verdict: RubricOutcomePair['verdict'];
|
|
62
|
-
}
|
|
63
|
-
interface RubricPredictiveValidityReport {
|
|
64
|
-
pairs: RubricOutcomePair[];
|
|
65
|
-
/** Per-rubric best pair, sorted descending by |spearman|. */
|
|
66
|
-
ranked: RubricRanking[];
|
|
67
|
-
joinedSamples: number;
|
|
68
|
-
skippedRuns: number;
|
|
69
|
-
/** Rubrics that were declared but never produced a usable score. */
|
|
70
|
-
rubricsWithoutData: string[];
|
|
71
|
-
}
|
|
72
|
-
declare function rubricPredictiveValidity(input: RubricPredictiveValidityInput): Promise<RubricPredictiveValidityReport>;
|
|
73
|
-
//#endregion
|
|
74
|
-
export { rubricPredictiveValidity as a, RubricRanking as i, RubricPredictiveValidityInput as n, RubricPredictiveValidityReport as r, RubricOutcomePair as t };
|
|
75
|
-
//# sourceMappingURL=rubric-predictive-validity-Dl1dvKCv.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rubric-predictive-validity-Dl1dvKCv.d.ts","names":[],"sources":["../src/meta-eval/rubric-predictive-validity.ts"],"mappings":";;;UAqCiB;;;;;EAKf,MAAM;EACN,UAAU;;;;;;EAMV;;;;;;EAMA;;EAEA;;EAEA;;;EAGA;;;;;EAKA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;IAAQ;IAAa;;;;;;;;EAOrB;;UAGe;EACf;;EAEA;EACA;EACA;EACA;EACA,SAAS;;UAGM;EACf,OAAO;;EAEP,QAAQ;EACR;EACA;;EAEA;;iBAGoB,yBACpB,OAAO,gCACN,QAAQ"}
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { c as validateRunRecord } from "./run-record-DQpSf7t-.js";
|
|
2
|
-
//#region src/campaign/run-record.ts
|
|
3
|
-
/**
|
|
4
|
-
* A campaign cell carried a judge score without a `dimensions` record.
|
|
5
|
-
*
|
|
6
|
-
* Two exported types share the name `JudgeScore`: the campaign verdict
|
|
7
|
-
* (`{ dimensions, composite, notes }` from `@tangle-network/agent-eval/campaign`)
|
|
8
|
-
* and the root export's flat per-dimension row (`{ judgeName, dimension, score }`
|
|
9
|
-
* from `@tangle-network/agent-eval`). Campaign aggregation accepts only the
|
|
10
|
-
* campaign shape; the flat shape previously crashed here with an opaque
|
|
11
|
-
* TypeError deep inside aggregation.
|
|
12
|
-
*/
|
|
13
|
-
var CampaignJudgeScoreShapeError = class extends TypeError {
|
|
14
|
-
constructor(judgeName) {
|
|
15
|
-
super(`campaign cell judge '${judgeName}' carries a score without a 'dimensions' record. Use the campaign JudgeScore ({ dimensions, composite, notes }) from '@tangle-network/agent-eval/campaign'; the root export's JudgeScore ({ judgeName, dimension, score }) is a different type with the same name.`);
|
|
16
|
-
this.name = "CampaignJudgeScoreShapeError";
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Project one campaign cell into the canonical run format.
|
|
21
|
-
*
|
|
22
|
-
* A dispatch error establishes terminal execution failure. A judge error only
|
|
23
|
-
* establishes that quality measurement failed after dispatch completed.
|
|
24
|
-
* Failures without a stage remain unknown. No failure becomes a zero-quality
|
|
25
|
-
* label.
|
|
26
|
-
*/
|
|
27
|
-
function campaignCellToRunRecord(cell, options) {
|
|
28
|
-
const quality = projectCampaignCellQuality(cell);
|
|
29
|
-
const execution = campaignCellExecutionEvidence(cell);
|
|
30
|
-
const judgeErrorCount = Math.max(quality.raw.judge_error_count ?? 0, execution.judgeErrorCount ?? 0);
|
|
31
|
-
const cellCostProvenance = campaignCellCostProvenance(cell);
|
|
32
|
-
const costProvenance = cellCostProvenance.kind === "uncaptured" && options.defaultCostUsd !== void 0 ? {
|
|
33
|
-
kind: "estimated",
|
|
34
|
-
usd: options.defaultCostUsd
|
|
35
|
-
} : cellCostProvenance;
|
|
36
|
-
const costUsd = costProvenance.kind === "uncaptured" ? null : costProvenance.usd;
|
|
37
|
-
const raw = {
|
|
38
|
-
...finiteMetrics(options.raw),
|
|
39
|
-
...quality.raw,
|
|
40
|
-
rep: cell.rep,
|
|
41
|
-
duration_ms: cell.durationMs,
|
|
42
|
-
...costUsd === null ? {} : { cost_usd: costUsd },
|
|
43
|
-
...cellCostProvenance.kind === "uncaptured" ? { cost_known_subtotal_usd: cell.costUsd } : {},
|
|
44
|
-
cost_observed: costProvenance.kind === "observed" ? 1 : 0,
|
|
45
|
-
cost_estimated: costProvenance.kind === "estimated" ? 1 : 0,
|
|
46
|
-
cost_uncaptured: costProvenance.kind === "uncaptured" ? 1 : 0,
|
|
47
|
-
tokens_input: cell.tokenUsage.input,
|
|
48
|
-
tokens_output: cell.tokenUsage.output,
|
|
49
|
-
tokens_known: cell.tokenUsage.tokensKnown === false ? 0 : 1,
|
|
50
|
-
latency_ms: cell.durationMs,
|
|
51
|
-
...execution.executionErrorCount === void 0 ? {} : { execution_error_count: execution.executionErrorCount },
|
|
52
|
-
...judgeErrorCount > 0 ? { judge_error_count: judgeErrorCount } : {},
|
|
53
|
-
...execution.unclassifiedErrorCount === void 0 ? {} : { unclassified_error_count: execution.unclassifiedErrorCount }
|
|
54
|
-
};
|
|
55
|
-
if (typeof cell.generation === "number") raw.generation = cell.generation;
|
|
56
|
-
if (cell.tokenUsage.reasoning !== void 0) raw.tokens_reasoning = cell.tokenUsage.reasoning;
|
|
57
|
-
if (cell.tokenUsage.cached !== void 0) raw.tokens_cached = cell.tokenUsage.cached;
|
|
58
|
-
if (cell.tokenUsage.cacheWrite !== void 0) raw.tokens_cache_write = cell.tokenUsage.cacheWrite;
|
|
59
|
-
if (cell.tokenUsage.tokensKnown !== false && costUsd !== null && costUsd > 0) raw.tokens_per_dollar = (cell.tokenUsage.input + cell.tokenUsage.output) / costUsd;
|
|
60
|
-
if (costUsd !== null && quality.score !== void 0 && quality.score > .01) raw.cost_per_quality = costUsd / quality.score;
|
|
61
|
-
const outcome = {
|
|
62
|
-
raw,
|
|
63
|
-
...quality.judgeScores ? { judgeScores: quality.judgeScores } : {}
|
|
64
|
-
};
|
|
65
|
-
if (quality.score !== void 0) if (options.splitTag === "holdout") outcome.holdoutScore = quality.score;
|
|
66
|
-
else outcome.searchScore = quality.score;
|
|
67
|
-
return validateRunRecord({
|
|
68
|
-
runId: options.runId,
|
|
69
|
-
experimentId: options.experimentId,
|
|
70
|
-
candidateId: options.candidateId,
|
|
71
|
-
seed: options.seed ?? cell.seed,
|
|
72
|
-
model: options.model,
|
|
73
|
-
promptHash: options.promptHash,
|
|
74
|
-
configHash: options.configHash,
|
|
75
|
-
commitSha: options.commitSha,
|
|
76
|
-
wallMs: cell.durationMs,
|
|
77
|
-
costUsd,
|
|
78
|
-
costProvenance,
|
|
79
|
-
tokenUsage: { ...cell.tokenUsage },
|
|
80
|
-
terminalOutcome: execution.terminalOutcome,
|
|
81
|
-
...execution.terminalFailureReason ? { terminalFailureReason: execution.terminalFailureReason } : {},
|
|
82
|
-
outcome,
|
|
83
|
-
splitTag: options.splitTag,
|
|
84
|
-
scenarioId: options.scenarioId ?? cell.scenarioId,
|
|
85
|
-
...options.agentProfile ? { agentProfile: options.agentProfile } : {}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Validate the cost fields that cross campaign cache and RunRecord boundaries.
|
|
90
|
-
* `costUsd` is a known subtotal for uncaptured cells, but it must equal the
|
|
91
|
-
* authoritative total whenever that total is observed or estimated.
|
|
92
|
-
*/
|
|
93
|
-
function campaignCellCostProvenance(cell) {
|
|
94
|
-
if (!Number.isFinite(cell.costUsd) || cell.costUsd < 0) throw new Error(`campaign cell '${cell.cellId}' has invalid costUsd`);
|
|
95
|
-
const provenance = cell.costProvenance;
|
|
96
|
-
if (!provenance || typeof provenance !== "object") throw new Error(`campaign cell '${cell.cellId}' has no costProvenance`);
|
|
97
|
-
if (provenance.kind === "uncaptured") {
|
|
98
|
-
if (provenance.usd !== null) throw new Error(`campaign cell '${cell.cellId}' has invalid uncaptured costProvenance`);
|
|
99
|
-
return {
|
|
100
|
-
kind: "uncaptured",
|
|
101
|
-
usd: null
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
if (provenance.kind !== "observed" && provenance.kind !== "estimated" || !Number.isFinite(provenance.usd) || provenance.usd < 0) throw new Error(`campaign cell '${cell.cellId}' has invalid costProvenance`);
|
|
105
|
-
if (provenance.usd !== cell.costUsd) throw new Error(`campaign cell '${cell.cellId}' has costUsd inconsistent with costProvenance`);
|
|
106
|
-
return {
|
|
107
|
-
kind: provenance.kind,
|
|
108
|
-
usd: provenance.usd
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
function campaignCellExecutionEvidence(cell) {
|
|
112
|
-
if (cell.errorStage === "dispatch") return {
|
|
113
|
-
terminalOutcome: "failed",
|
|
114
|
-
executionErrorCount: 1,
|
|
115
|
-
...cell.error ? { terminalFailureReason: cell.error } : {}
|
|
116
|
-
};
|
|
117
|
-
if (cell.errorStage === "judge") return {
|
|
118
|
-
terminalOutcome: "succeeded",
|
|
119
|
-
executionErrorCount: 0,
|
|
120
|
-
judgeErrorCount: 1
|
|
121
|
-
};
|
|
122
|
-
if (!cell.error) return {
|
|
123
|
-
terminalOutcome: "succeeded",
|
|
124
|
-
executionErrorCount: 0
|
|
125
|
-
};
|
|
126
|
-
return {
|
|
127
|
-
terminalOutcome: "unknown",
|
|
128
|
-
unclassifiedErrorCount: 1
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Produce the only task-quality view used by campaign aggregates and exports.
|
|
133
|
-
*
|
|
134
|
-
* Successful judge results remain available for diagnosis after another judge
|
|
135
|
-
* fails, but a task score exists only for an error-free cell whose reported
|
|
136
|
-
* judge values are all finite.
|
|
137
|
-
*/
|
|
138
|
-
function projectCampaignCellQuality(cell) {
|
|
139
|
-
if (cell.errorStage === "dispatch") return {
|
|
140
|
-
successfulJudgeScores: {},
|
|
141
|
-
failedJudges: [],
|
|
142
|
-
raw: {}
|
|
143
|
-
};
|
|
144
|
-
const perJudge = {};
|
|
145
|
-
const successfulJudgeScores = {};
|
|
146
|
-
const dimensionValues = /* @__PURE__ */ new Map();
|
|
147
|
-
const composites = [];
|
|
148
|
-
const notes = [];
|
|
149
|
-
const failedJudges = new Set(cell.errorStage === "judge" ? [cell.errorJudge ?? "unknown-judge"] : []);
|
|
150
|
-
const raw = {};
|
|
151
|
-
for (const [judgeName, score] of Object.entries(cell.judgeScores)) {
|
|
152
|
-
const dimensionsShape = score.dimensions;
|
|
153
|
-
if (typeof dimensionsShape !== "object" || dimensionsShape === null || Array.isArray(dimensionsShape)) throw new CampaignJudgeScoreShapeError(judgeName);
|
|
154
|
-
const finiteDimensions = Object.values(score.dimensions).every(Number.isFinite);
|
|
155
|
-
if (score.failed || !Number.isFinite(score.composite) || !finiteDimensions) {
|
|
156
|
-
failedJudges.add(judgeName);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
composites.push(score.composite);
|
|
160
|
-
successfulJudgeScores[judgeName] = score;
|
|
161
|
-
const dimensions = { ...score.dimensions };
|
|
162
|
-
perJudge[judgeName] = dimensions;
|
|
163
|
-
for (const [dimension, value] of Object.entries(dimensions)) {
|
|
164
|
-
raw[`${judgeName}.${dimension}`] = value;
|
|
165
|
-
const values = dimensionValues.get(dimension) ?? [];
|
|
166
|
-
values.push(value);
|
|
167
|
-
dimensionValues.set(dimension, values);
|
|
168
|
-
}
|
|
169
|
-
if (score.notes) notes.push(`${judgeName}: ${score.notes}`);
|
|
170
|
-
for (const failedJudge of score.failedJudges ?? []) failedJudges.add(`${judgeName}/${failedJudge}`);
|
|
171
|
-
}
|
|
172
|
-
if (failedJudges.size > 0) raw.judge_error_count = failedJudges.size;
|
|
173
|
-
const sortedFailedJudges = [...failedJudges].sort();
|
|
174
|
-
if (composites.length === 0) return {
|
|
175
|
-
successfulJudgeScores,
|
|
176
|
-
failedJudges: sortedFailedJudges,
|
|
177
|
-
raw
|
|
178
|
-
};
|
|
179
|
-
const composite = mean(composites);
|
|
180
|
-
const perDimMean = Object.fromEntries([...dimensionValues.entries()].map(([dimension, values]) => [dimension, mean(values)]));
|
|
181
|
-
const complete = cell.error === void 0 && cell.errorStage === void 0 && failedJudges.size === 0;
|
|
182
|
-
if (complete) raw.composite = composite;
|
|
183
|
-
return {
|
|
184
|
-
...complete ? { score: composite } : {},
|
|
185
|
-
raw,
|
|
186
|
-
successfulJudgeScores,
|
|
187
|
-
failedJudges: sortedFailedJudges,
|
|
188
|
-
judgeScores: {
|
|
189
|
-
perJudge,
|
|
190
|
-
perDimMean,
|
|
191
|
-
composite,
|
|
192
|
-
...sortedFailedJudges.length > 0 ? { failedJudges: sortedFailedJudges } : {},
|
|
193
|
-
...notes.length > 0 ? { notes: notes.join(" | ") } : {}
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
/** Read the canonical task score without recomputing cell quality. */
|
|
198
|
-
function campaignCellTaskScore(cell) {
|
|
199
|
-
return projectCampaignCellQuality(cell).score;
|
|
200
|
-
}
|
|
201
|
-
/** Read canonical successful judge dimensions without recomputing cell quality. */
|
|
202
|
-
function campaignCellJudgeDimensions(cell) {
|
|
203
|
-
return projectCampaignCellQuality(cell).judgeScores?.perJudge ?? {};
|
|
204
|
-
}
|
|
205
|
-
function finiteMetrics(metrics) {
|
|
206
|
-
const finite = {};
|
|
207
|
-
for (const [key, value] of Object.entries(metrics ?? {})) if (Number.isFinite(value)) finite[key] = value;
|
|
208
|
-
return finite;
|
|
209
|
-
}
|
|
210
|
-
function mean(values) {
|
|
211
|
-
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
212
|
-
}
|
|
213
|
-
//#endregion
|
|
214
|
-
export { campaignCellToRunRecord as a, campaignCellTaskScore as i, campaignCellExecutionEvidence as n, projectCampaignCellQuality as o, campaignCellJudgeDimensions as r, campaignCellCostProvenance as t };
|
|
215
|
-
|
|
216
|
-
//# sourceMappingURL=run-record-CR63CpHK.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run-record-CR63CpHK.js","names":[],"sources":["../src/campaign/run-record.ts"],"sourcesContent":["import type { AgentProfileCell } from '../agent-profile-cell'\nimport type { CostProvenance } from '../cost-ledger'\nimport type {\n JudgeScoresRecord,\n RunOutcome,\n RunRecord,\n RunSplitTag,\n RunTerminalOutcome,\n} from '../run-record'\nimport { validateRunRecord } from '../run-record'\nimport type { CampaignCellResult, JudgeScore } from './types'\n\nexport interface CampaignCellRunRecordOptions {\n runId: string\n experimentId: string\n candidateId: string\n model: string\n promptHash: string\n configHash: string\n commitSha: string\n splitTag: RunSplitTag\n seed?: number\n scenarioId?: string\n defaultCostUsd?: number\n agentProfile?: AgentProfileCell\n raw?: Record<string, number>\n}\n\nexport interface CampaignCellQualityProjection {\n score?: number\n judgeScores?: JudgeScoresRecord\n successfulJudgeScores: Record<string, JudgeScore>\n failedJudges: string[]\n raw: Record<string, number>\n}\n\n/**\n * A campaign cell carried a judge score without a `dimensions` record.\n *\n * Two exported types share the name `JudgeScore`: the campaign verdict\n * (`{ dimensions, composite, notes }` from `@tangle-network/agent-eval/campaign`)\n * and the root export's flat per-dimension row (`{ judgeName, dimension, score }`\n * from `@tangle-network/agent-eval`). Campaign aggregation accepts only the\n * campaign shape; the flat shape previously crashed here with an opaque\n * TypeError deep inside aggregation.\n */\nexport class CampaignJudgeScoreShapeError extends TypeError {\n constructor(judgeName: string) {\n super(\n `campaign cell judge '${judgeName}' carries a score without a 'dimensions' record. ` +\n `Use the campaign JudgeScore ({ dimensions, composite, notes }) from ` +\n `'@tangle-network/agent-eval/campaign'; the root export's JudgeScore ` +\n `({ judgeName, dimension, score }) is a different type with the same name.`,\n )\n this.name = 'CampaignJudgeScoreShapeError'\n }\n}\n\nexport interface CampaignCellExecutionEvidence {\n terminalOutcome: RunTerminalOutcome\n executionErrorCount?: number\n judgeErrorCount?: number\n unclassifiedErrorCount?: number\n terminalFailureReason?: string\n}\n\n/**\n * Project one campaign cell into the canonical run format.\n *\n * A dispatch error establishes terminal execution failure. A judge error only\n * establishes that quality measurement failed after dispatch completed.\n * Failures without a stage remain unknown. No failure becomes a zero-quality\n * label.\n */\nexport function campaignCellToRunRecord<TArtifact>(\n cell: CampaignCellResult<TArtifact>,\n options: CampaignCellRunRecordOptions,\n): RunRecord {\n const quality = projectCampaignCellQuality(cell)\n const execution = campaignCellExecutionEvidence(cell)\n const judgeErrorCount = Math.max(\n quality.raw.judge_error_count ?? 0,\n execution.judgeErrorCount ?? 0,\n )\n const cellCostProvenance = campaignCellCostProvenance(cell)\n const costProvenance: CostProvenance =\n cellCostProvenance.kind === 'uncaptured' && options.defaultCostUsd !== undefined\n ? { kind: 'estimated', usd: options.defaultCostUsd }\n : cellCostProvenance\n const costUsd = costProvenance.kind === 'uncaptured' ? null : costProvenance.usd\n const raw: Record<string, number> = {\n ...finiteMetrics(options.raw),\n ...quality.raw,\n rep: cell.rep,\n duration_ms: cell.durationMs,\n ...(costUsd === null ? {} : { cost_usd: costUsd }),\n // Retain the observed subtotal even when the caller supplies an estimated total.\n ...(cellCostProvenance.kind === 'uncaptured' ? { cost_known_subtotal_usd: cell.costUsd } : {}),\n cost_observed: costProvenance.kind === 'observed' ? 1 : 0,\n cost_estimated: costProvenance.kind === 'estimated' ? 1 : 0,\n cost_uncaptured: costProvenance.kind === 'uncaptured' ? 1 : 0,\n tokens_input: cell.tokenUsage.input,\n tokens_output: cell.tokenUsage.output,\n tokens_known: cell.tokenUsage.tokensKnown === false ? 0 : 1,\n latency_ms: cell.durationMs,\n ...(execution.executionErrorCount === undefined\n ? {}\n : { execution_error_count: execution.executionErrorCount }),\n ...(judgeErrorCount > 0 ? { judge_error_count: judgeErrorCount } : {}),\n ...(execution.unclassifiedErrorCount === undefined\n ? {}\n : { unclassified_error_count: execution.unclassifiedErrorCount }),\n }\n if (typeof cell.generation === 'number') raw.generation = cell.generation\n if (cell.tokenUsage.reasoning !== undefined) {\n raw.tokens_reasoning = cell.tokenUsage.reasoning\n }\n if (cell.tokenUsage.cached !== undefined) raw.tokens_cached = cell.tokenUsage.cached\n if (cell.tokenUsage.cacheWrite !== undefined) {\n raw.tokens_cache_write = cell.tokenUsage.cacheWrite\n }\n if (cell.tokenUsage.tokensKnown !== false && costUsd !== null && costUsd > 0) {\n raw.tokens_per_dollar = (cell.tokenUsage.input + cell.tokenUsage.output) / costUsd\n }\n if (costUsd !== null && quality.score !== undefined && quality.score > 0.01) {\n raw.cost_per_quality = costUsd / quality.score\n }\n\n const outcome: RunOutcome = {\n raw,\n ...(quality.judgeScores ? { judgeScores: quality.judgeScores } : {}),\n }\n if (quality.score !== undefined) {\n if (options.splitTag === 'holdout') outcome.holdoutScore = quality.score\n else outcome.searchScore = quality.score\n }\n\n return validateRunRecord({\n runId: options.runId,\n experimentId: options.experimentId,\n candidateId: options.candidateId,\n seed: options.seed ?? cell.seed,\n model: options.model,\n promptHash: options.promptHash,\n configHash: options.configHash,\n commitSha: options.commitSha,\n wallMs: cell.durationMs,\n costUsd,\n costProvenance,\n tokenUsage: { ...cell.tokenUsage },\n terminalOutcome: execution.terminalOutcome,\n ...(execution.terminalFailureReason\n ? { terminalFailureReason: execution.terminalFailureReason }\n : {}),\n outcome,\n splitTag: options.splitTag,\n scenarioId: options.scenarioId ?? cell.scenarioId,\n ...(options.agentProfile ? { agentProfile: options.agentProfile } : {}),\n })\n}\n\n/**\n * Validate the cost fields that cross campaign cache and RunRecord boundaries.\n * `costUsd` is a known subtotal for uncaptured cells, but it must equal the\n * authoritative total whenever that total is observed or estimated.\n */\nexport function campaignCellCostProvenance<TArtifact>(\n cell: Pick<CampaignCellResult<TArtifact>, 'cellId' | 'costUsd' | 'costProvenance'>,\n): CostProvenance {\n if (!Number.isFinite(cell.costUsd) || cell.costUsd < 0) {\n throw new Error(`campaign cell '${cell.cellId}' has invalid costUsd`)\n }\n const provenance = cell.costProvenance\n if (!provenance || typeof provenance !== 'object') {\n throw new Error(`campaign cell '${cell.cellId}' has no costProvenance`)\n }\n if (provenance.kind === 'uncaptured') {\n if (provenance.usd !== null) {\n throw new Error(`campaign cell '${cell.cellId}' has invalid uncaptured costProvenance`)\n }\n return { kind: 'uncaptured', usd: null }\n }\n if (\n (provenance.kind !== 'observed' && provenance.kind !== 'estimated') ||\n !Number.isFinite(provenance.usd) ||\n provenance.usd < 0\n ) {\n throw new Error(`campaign cell '${cell.cellId}' has invalid costProvenance`)\n }\n if (provenance.usd !== cell.costUsd) {\n throw new Error(`campaign cell '${cell.cellId}' has costUsd inconsistent with costProvenance`)\n }\n return { kind: provenance.kind, usd: provenance.usd }\n}\n\nexport function campaignCellExecutionEvidence<TArtifact>(\n cell: CampaignCellResult<TArtifact>,\n): CampaignCellExecutionEvidence {\n if (cell.errorStage === 'dispatch') {\n return {\n terminalOutcome: 'failed',\n executionErrorCount: 1,\n ...(cell.error ? { terminalFailureReason: cell.error } : {}),\n }\n }\n if (cell.errorStage === 'judge') {\n return {\n terminalOutcome: 'succeeded',\n executionErrorCount: 0,\n judgeErrorCount: 1,\n }\n }\n if (!cell.error) {\n return { terminalOutcome: 'succeeded', executionErrorCount: 0 }\n }\n return {\n terminalOutcome: 'unknown',\n unclassifiedErrorCount: 1,\n }\n}\n\n/**\n * Produce the only task-quality view used by campaign aggregates and exports.\n *\n * Successful judge results remain available for diagnosis after another judge\n * fails, but a task score exists only for an error-free cell whose reported\n * judge values are all finite.\n */\nexport function projectCampaignCellQuality<TArtifact>(\n cell: CampaignCellResult<TArtifact>,\n): CampaignCellQualityProjection {\n if (cell.errorStage === 'dispatch') {\n return { successfulJudgeScores: {}, failedJudges: [], raw: {} }\n }\n\n const perJudge: Record<string, Record<string, number>> = {}\n const successfulJudgeScores: Record<string, JudgeScore> = {}\n const dimensionValues = new Map<string, number[]>()\n const composites: number[] = []\n const notes: string[] = []\n const failedJudges = new Set<string>(\n cell.errorStage === 'judge' ? [cell.errorJudge ?? 'unknown-judge'] : [],\n )\n const raw: Record<string, number> = {}\n\n for (const [judgeName, score] of Object.entries(cell.judgeScores)) {\n const dimensionsShape = (score as { dimensions?: unknown }).dimensions\n if (\n typeof dimensionsShape !== 'object' ||\n dimensionsShape === null ||\n Array.isArray(dimensionsShape)\n ) {\n throw new CampaignJudgeScoreShapeError(judgeName)\n }\n const finiteDimensions = Object.values(score.dimensions).every(Number.isFinite)\n if (score.failed || !Number.isFinite(score.composite) || !finiteDimensions) {\n failedJudges.add(judgeName)\n continue\n }\n\n composites.push(score.composite)\n successfulJudgeScores[judgeName] = score\n const dimensions = { ...score.dimensions }\n perJudge[judgeName] = dimensions\n for (const [dimension, value] of Object.entries(dimensions)) {\n raw[`${judgeName}.${dimension}`] = value\n const values = dimensionValues.get(dimension) ?? []\n values.push(value)\n dimensionValues.set(dimension, values)\n }\n if (score.notes) notes.push(`${judgeName}: ${score.notes}`)\n for (const failedJudge of score.failedJudges ?? []) {\n failedJudges.add(`${judgeName}/${failedJudge}`)\n }\n }\n\n if (failedJudges.size > 0) raw.judge_error_count = failedJudges.size\n const sortedFailedJudges = [...failedJudges].sort()\n if (composites.length === 0) {\n return {\n successfulJudgeScores,\n failedJudges: sortedFailedJudges,\n raw,\n }\n }\n\n const composite = mean(composites)\n const perDimMean = Object.fromEntries(\n [...dimensionValues.entries()].map(([dimension, values]) => [dimension, mean(values)]),\n )\n const complete =\n cell.error === undefined && cell.errorStage === undefined && failedJudges.size === 0\n if (complete) raw.composite = composite\n\n return {\n ...(complete ? { score: composite } : {}),\n raw,\n successfulJudgeScores,\n failedJudges: sortedFailedJudges,\n judgeScores: {\n perJudge,\n perDimMean,\n composite,\n ...(sortedFailedJudges.length > 0 ? { failedJudges: sortedFailedJudges } : {}),\n ...(notes.length > 0 ? { notes: notes.join(' | ') } : {}),\n },\n }\n}\n\n/** Read the canonical task score without recomputing cell quality. */\nexport function campaignCellTaskScore<TArtifact>(\n cell: CampaignCellResult<TArtifact>,\n): number | undefined {\n return projectCampaignCellQuality(cell).score\n}\n\n/** Read canonical successful judge dimensions without recomputing cell quality. */\nexport function campaignCellJudgeDimensions<TArtifact>(\n cell: CampaignCellResult<TArtifact>,\n): Record<string, Record<string, number>> {\n return projectCampaignCellQuality(cell).judgeScores?.perJudge ?? {}\n}\n\nfunction finiteMetrics(metrics: Record<string, number> | undefined): Record<string, number> {\n const finite: Record<string, number> = {}\n for (const [key, value] of Object.entries(metrics ?? {})) {\n if (Number.isFinite(value)) finite[key] = value\n }\n return finite\n}\n\nfunction mean(values: number[]): number {\n return values.reduce((sum, value) => sum + value, 0) / values.length\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sequential-B5gXgcyp.js","names":[],"sources":["../src/campaign/gates/sequential.ts"],"sourcesContent":["/**\n * Anytime-valid sequential promotion gate — an e-process (betting\n * test-martingale, see `eProcess` in `statistics.ts`) over paired\n * per-scenario deltas, so a campaign stops the MOMENT evidence decides\n * instead of burning a fixed-n budget. Decisions remain valid at any\n * data-dependent stopping time (Ville's inequality), which is exactly what\n * fixed-n machinery cannot offer: peeking at a bootstrap CI after every\n * observation and stopping on the first significant peek inflates type-I\n * error far beyond alpha.\n *\n * REPLACES, never layers on, a fixed-n gate. Running `heldoutSignificance`\n * or `paretoSignificanceGate` repeatedly on a growing sample and stopping\n * early is optional stopping no matter how it is dressed up; this gate is\n * the valid way to stop early. Use one or the other per evidence stream.\n *\n * Pre-registration binding: anytime validity holds only for the\n * PRE-REGISTERED statistic. When a `SignedManifest` is bound, the gate takes\n * alpha from `manifest.alpha`, the observation budget from\n * `manifest.preRegisteredN`, orients deltas by `manifest.direction`, and\n * shifts the null boundary by `manifest.minEffect` — re-deciding the same\n * stream under different parameters after seeing data would reopen optional\n * stopping under a fancier name. The manifest's content hash is verified at\n * construction (sync, same `sha256-content` scheme as `signManifest`).\n *\n * Non-iid caveat (stated honestly): the supermartingale guarantee needs each\n * delta's conditional mean under H0 to stay ≤ the null boundary given the\n * past — exchangeable scenario deltas suffice. Scenario streams ordered by\n * difficulty or by scenario family violate this; `decide(ctx)` therefore\n * shuffles the paired deltas with a SEEDED permutation by default (the\n * permutation is data-independent, so bet predictability is preserved).\n * Stratified betting (per-stratum λ) is future work, not implemented here.\n */\n\nimport { manifestContentDigest, type SignedManifest } from '../../pre-registration'\nimport { type EProcessState, eProcess, mulberry32 } from '../../statistics'\nimport type { Gate, GateContext, GateResult, GenerationRecord, Scenario } from '../types'\nimport { pairHoldout } from './statistical-heldout'\n\nexport type SequentialDecision = 'promote' | 'continue' | 'undecided-at-maxN'\n\nexport interface SequentialObservation {\n decision: SequentialDecision\n /** Current e-value (the betting wealth) against H0. */\n eValue: number\n /** Paired deltas consumed so far. */\n n: number\n /** Names the decision basis. For 'undecided-at-maxN' it states explicitly\n * that exhausting the budget is NOT evidence of no effect. */\n reason: string\n}\n\nexport interface SequentialPairedGateOptions {\n /** Type-I budget. With `preRegistration` bound this MUST match\n * `manifest.alpha` (conflict throws). Default 0.05. */\n alpha?: number\n /** Minimum paired deltas before a promote may fire. The stopping rule is\n * \"first n ≥ minN with e-value ≥ 1/alpha\" — still a valid stopping time.\n * Default 5. */\n minN?: number\n /** Pre-registered observation budget. Required unless `preRegistration`\n * supplies it via `preRegisteredN` (conflict throws). */\n maxN?: number\n /** Bet truncation forwarded to `eProcess`. Default 0.5. */\n maxBet?: number\n /** Bound on |delta| in the judge's native scale; deltas are mapped to\n * x = (d/scale + 1)/2 ∈ [0,1]. A delta outside ±scale throws (use\n * `detectScale` to pick 1 vs 100 BEFORE streaming). Default 1. */\n scale?: number\n /** Seed for the data-independent shuffle of paired deltas in `decide(ctx)`\n * (exchangeability guard). Default 1337. */\n shuffleSeed?: number\n /** Bind the pre-registered hypothesis. Verified (content hash) at\n * construction; alpha/maxN/direction/minEffect come FROM the manifest. */\n preRegistration?: SignedManifest\n /** Override the gate name in reports. */\n name?: string\n /** Continue the observe-stream from a `state()` snapshot taken before a\n * restart. The gate's parameters still resolve from this options object\n * (and the manifest); the snapshot must have been recorded under the same\n * alpha, maxBet, and null boundary, and its decision must be one this\n * configuration could have reached at its n, or construction throws.\n * `decide(ctx)` is unaffected — it always runs on a fresh stream. */\n resume?: SequentialStreamState\n}\n\n/** Snapshot of one observe-stream: the e-process state plus the gate's own\n * decision, which applies `minN` and `maxN` on top of the core latch. A\n * gate rebuilt with `resume` from this value continues exactly where the\n * snapshot was taken. */\nexport type SequentialStreamState = EProcessState & { decision: SequentialDecision }\n\nexport interface SequentialPairedGate<TArtifact = unknown, TScenario extends Scenario = Scenario>\n extends Gate<TArtifact, TScenario> {\n /** Streaming entry point: feed one paired per-scenario delta\n * (candidate − baseline, native scale). Each gate instance carries ONE\n * observe-stream; `decide(ctx)` runs on its own fresh stream and never\n * consumes or advances this one. 'promote' is sticky; observing past the\n * pre-registered maxN throws (extending a finished stream after seeing\n * the result reopens optional stopping — start a NEW pre-registered\n * test). */\n observe(delta: number): SequentialObservation\n /** Read-only snapshot of the observe-stream. Pass it back as\n * `resume` to continue the stream after a restart. */\n state(): SequentialStreamState\n}\n\ninterface ResolvedConfig {\n alpha: number\n minN: number\n maxN: number\n maxBet: number\n scale: number\n shuffleSeed: number\n /** 'decrease' negates deltas so \"better\" is always positive. */\n direction: 'increase' | 'decrease'\n /** H0 boundary in x-space: 1/2 + minEffect/(2·scale). */\n nullMean: number\n minEffect: number\n}\n\n/** Sync twin of `verifyManifest`, so gate construction stays synchronous and\n * fails loud before any observation is consumed. The digest scheme belongs to\n * `pre-registration`; this gate only compares. */\nfunction verifyManifestSync(m: SignedManifest): boolean {\n return manifestContentDigest(m) === m.contentHash\n}\n\nfunction resolveConfig(opts: SequentialPairedGateOptions): ResolvedConfig {\n const m = opts.preRegistration\n let alpha: number\n let maxN: number\n let direction: 'increase' | 'decrease'\n let minEffect: number\n if (m) {\n if (!verifyManifestSync(m)) {\n throw new Error(\n `sequentialPairedGate: pre-registration manifest '${m.id}' content hash mismatch (tampered)`,\n )\n }\n if (opts.alpha !== undefined && opts.alpha !== m.alpha) {\n throw new Error(\n `sequentialPairedGate: alpha ${opts.alpha} conflicts with pre-registered alpha ${m.alpha} — ` +\n `the registered statistic is the only one anytime validity covers`,\n )\n }\n if (opts.maxN !== undefined && opts.maxN !== m.preRegisteredN) {\n throw new Error(\n `sequentialPairedGate: maxN ${opts.maxN} conflicts with pre-registered N ${m.preRegisteredN}`,\n )\n }\n alpha = m.alpha\n maxN = m.preRegisteredN\n direction = m.direction\n minEffect = m.minEffect\n } else {\n alpha = opts.alpha ?? 0.05\n if (opts.maxN === undefined) {\n throw new Error(\n 'sequentialPairedGate: maxN is required (or bind a preRegistration manifest whose ' +\n 'preRegisteredN is the budget) — an unbounded stream has no pre-registered budget',\n )\n }\n maxN = opts.maxN\n direction = 'increase'\n minEffect = 0\n }\n const scale = opts.scale ?? 1\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new Error(`sequentialPairedGate: scale must be > 0, got ${scale}`)\n }\n if (!Number.isInteger(maxN) || maxN < 1) {\n throw new Error(`sequentialPairedGate: maxN must be a positive integer, got ${maxN}`)\n }\n const minN = opts.minN ?? 5\n if (!Number.isInteger(minN) || minN < 1 || minN > maxN) {\n throw new Error(\n `sequentialPairedGate: minN must be an integer in [1, maxN=${maxN}], got ${minN}`,\n )\n }\n if (!Number.isFinite(minEffect) || minEffect < 0 || minEffect >= scale) {\n throw new Error(\n `sequentialPairedGate: minEffect must be in [0, scale=${scale}), got ${minEffect}`,\n )\n }\n // H0: mean delta ≤ minEffect. In x = (d/scale + 1)/2 space that is\n // E[x] ≤ 1/2 + minEffect/(2·scale) — a shifted null boundary, NOT a clamp\n // of the observations (clamping is mean-distorting for skewed deltas).\n const nullMean = 0.5 + minEffect / (2 * scale)\n return {\n alpha,\n minN,\n maxN,\n maxBet: opts.maxBet ?? 0.5,\n scale,\n shuffleSeed: opts.shuffleSeed ?? 1337,\n direction,\n nullMean,\n minEffect,\n }\n}\n\ninterface SequentialStream {\n observe(delta: number): SequentialObservation\n state(): SequentialStreamState\n}\n\nconst SEQUENTIAL_DECISIONS: readonly SequentialDecision[] = [\n 'promote',\n 'continue',\n 'undecided-at-maxN',\n]\n\n/** Refuse a snapshot whose gate decision this configuration could not have\n * reached at the snapshot's n. The e-process parameters are checked by\n * `eProcess` itself; this covers the gate's own stopping rule. */\nfunction assertResumableStream(resume: SequentialStreamState, cfg: ResolvedConfig): void {\n const fail = (detail: string): never => {\n throw new Error(`sequentialPairedGate: cannot resume — ${detail}`)\n }\n if (!SEQUENTIAL_DECISIONS.includes(resume.decision)) {\n fail(`unknown decision '${String(resume.decision)}'`)\n }\n if (resume.n > cfg.maxN) {\n fail(`snapshot n=${resume.n} exceeds the pre-registered maxN=${cfg.maxN}`)\n }\n const threshold = 1 / cfg.alpha\n switch (resume.decision) {\n case 'promote':\n if (resume.n < cfg.minN) {\n fail(`decision 'promote' at n=${resume.n} is below minN=${cfg.minN}`)\n }\n break\n case 'undecided-at-maxN':\n if (resume.n !== cfg.maxN) {\n fail(`decision 'undecided-at-maxN' at n=${resume.n} does not match maxN=${cfg.maxN}`)\n }\n break\n case 'continue':\n if (resume.n >= cfg.maxN) {\n fail(`decision 'continue' at n=${resume.n} with maxN=${cfg.maxN}; the stream is finished`)\n }\n if (resume.n >= cfg.minN && resume.wealth >= threshold) {\n fail(\n `decision 'continue' at n=${resume.n} ≥ minN=${cfg.minN} with e-value ` +\n `${resume.wealth} ≥ 1/α=${threshold}; this stream would have promoted`,\n )\n }\n break\n }\n}\n\nfunction makeStream(cfg: ResolvedConfig, resume?: SequentialStreamState): SequentialStream {\n if (resume !== undefined) assertResumableStream(resume, cfg)\n const proc = eProcess({\n alpha: cfg.alpha,\n maxBet: cfg.maxBet,\n nullMean: cfg.nullMean,\n ...(resume === undefined ? {} : { resume }),\n })\n const threshold = 1 / cfg.alpha\n let terminal: SequentialDecision | undefined =\n resume === undefined || resume.decision === 'continue' ? undefined : resume.decision\n return {\n observe(delta: number): SequentialObservation {\n if (terminal === 'undecided-at-maxN') {\n throw new Error(\n `sequentialPairedGate: pre-registered maxN=${cfg.maxN} exhausted — extending the ` +\n 'stream after seeing the result reopens optional stopping; start a NEW ' +\n 'pre-registered test',\n )\n }\n if (!Number.isFinite(delta) || Math.abs(delta) > cfg.scale) {\n throw new Error(\n `sequentialPairedGate: delta ${delta} outside ±scale=${cfg.scale} — pass the judge's ` +\n `native scale explicitly (detectScale helps pick 1 vs 100)`,\n )\n }\n const d = cfg.direction === 'decrease' ? -delta : delta\n const step = proc.update((d / cfg.scale + 1) / 2)\n // Stopping rule: FIRST n ≥ minN with current wealth ≥ 1/alpha — a valid\n // stopping time (measurable w.r.t. the past), sticky once latched. The\n // core's own `decided` latch ignores minN, so the gate re-derives the\n // decision from current wealth here.\n if (terminal === undefined && step.n >= cfg.minN && step.wealth >= threshold) {\n terminal = 'promote'\n }\n if (terminal === 'promote') {\n return {\n decision: 'promote',\n eValue: step.wealth,\n n: step.n,\n reason:\n `e-value ${step.wealth.toFixed(2)} ≥ 1/α=${threshold.toFixed(2)} at n=${step.n} ` +\n `(minN=${cfg.minN}): the paired improvement exceeds ${cfg.minEffect} at anytime-valid ` +\n `level α=${cfg.alpha}`,\n }\n }\n if (step.n >= cfg.maxN) {\n terminal = 'undecided-at-maxN'\n return {\n decision: 'undecided-at-maxN',\n eValue: step.wealth,\n n: step.n,\n reason:\n `undecided at pre-registered maxN=${cfg.maxN} (e-value ${step.wealth.toFixed(2)} < ` +\n `1/α=${threshold.toFixed(2)}). This is NOT evidence of no effect — the effect may be ` +\n 'real but smaller than this budget can detect; re-register with a larger N to test that',\n }\n }\n return {\n decision: 'continue',\n eValue: step.wealth,\n n: step.n,\n reason: `e-value ${step.wealth.toFixed(2)} < 1/α=${threshold.toFixed(2)} at n=${step.n}/${cfg.maxN} — keep observing`,\n }\n },\n state() {\n return { ...proc.state(), decision: terminal ?? 'continue' }\n },\n }\n}\n\n/** Data-independent in-place Fisher–Yates with a seeded PRNG — the permutation\n * depends only on the seed, never the values, so bet predictability survives. */\nfunction seededShuffle<T>(items: T[], seed: number): T[] {\n const rng = mulberry32(seed)\n for (let i = items.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1))\n const tmp = items[i]!\n items[i] = items[j]!\n items[j] = tmp\n }\n return items\n}\n\n/**\n * Anytime-valid sequential paired gate. Conforms to the existing `Gate`\n * contract (`decide(ctx)` consumes candidate vs baseline judge scores via\n * `pairHoldout` — same pairing granularity as the fixed-n gates: full cellId,\n * never scenarioId) and adds a streaming `observe(delta)` entry for campaigns\n * that score cells incrementally and want to stop mid-stream.\n *\n * Decision mapping onto the substrate's five-valued `GateDecision`:\n * - 'promote' → 'ship'\n * - 'continue' → 'need_more_work' (stream ended before maxN with\n * the e-value undecided — more reps could decide)\n * - 'undecided-at-maxN' → 'hold', with the reason stating it is NOT\n * evidence of no effect (never a silent default)\n */\nexport function sequentialPairedGate<TArtifact = unknown, TScenario extends Scenario = Scenario>(\n options: SequentialPairedGateOptions,\n): SequentialPairedGate<TArtifact, TScenario> {\n const cfg = resolveConfig(options)\n const name = options.name ?? 'sequentialPairedGate'\n const manifest = options.preRegistration\n const observeStream = makeStream(cfg, options.resume)\n\n return {\n name,\n observe(delta: number): SequentialObservation {\n return observeStream.observe(delta)\n },\n state() {\n return observeStream.state()\n },\n async decide(ctx: GateContext<TArtifact, TScenario>): Promise<GateResult> {\n if (!ctx.baselineJudgeScores) {\n throw new Error(\n `${name}: ctx.baselineJudgeScores is required — falling back to the candidate's own ` +\n 'scores would compare the candidate against itself (delta 0, silent no-op)',\n )\n }\n const scenarioIds = new Set(ctx.scenarios.map((s) => s.id))\n const paired = pairHoldout(\n ctx.judgeScores,\n ctx.baselineJudgeScores,\n scenarioIds,\n (s) => s.composite,\n )\n const deltas = paired.after.map((a, i) => a - paired.before[i]!)\n seededShuffle(deltas, cfg.shuffleSeed)\n\n const stream = makeStream(cfg)\n let last: SequentialObservation | undefined\n for (const d of deltas) {\n last = stream.observe(d)\n if (last.decision !== 'continue') break\n }\n\n const detail = {\n ...stream.state(),\n minN: cfg.minN,\n maxN: cfg.maxN,\n scale: cfg.scale,\n shuffleSeed: cfg.shuffleSeed,\n direction: cfg.direction,\n minEffect: cfg.minEffect,\n pairedN: deltas.length,\n ...(manifest ? { preRegisteredId: manifest.id, metric: manifest.metric } : {}),\n }\n const meanDelta =\n deltas.length === 0 ? undefined : deltas.reduce((s, d) => s + d, 0) / deltas.length\n\n if (last === undefined) {\n return {\n decision: 'need_more_work',\n reasons: [`${name}: no paired holdout observations — nothing to test`],\n contributingGates: [{ name, status: 'not_evaluated', detail }],\n }\n }\n const decision =\n last.decision === 'promote'\n ? 'ship'\n : last.decision === 'continue'\n ? 'need_more_work'\n : 'hold'\n return {\n decision,\n reasons: [`${name}: ${last.reason}`],\n contributingGates: [\n {\n name,\n status:\n decision === 'ship'\n ? 'pass'\n : decision === 'need_more_work'\n ? 'not_evaluated'\n : 'fail',\n detail,\n },\n ],\n delta: meanDelta,\n }\n },\n }\n}\n\nexport interface SequentialDecideOptions {\n /** Type-I budget for the early-stop evidence. Default 0.05. */\n alpha?: number\n /** Minimum paired deltas before a stop may fire. Default 5. */\n minN?: number\n /** Bet truncation forwarded to `eProcess`. Default 0.5. */\n maxBet?: number\n /** Bound on |per-scenario composite delta|. Default 1. */\n scale?: number\n}\n\nexport interface SequentialDecideFn {\n (args: { history: GenerationRecord[] }): { stop: boolean; reason?: string }\n /** Read-only snapshot of the accumulated e-process (observability + tests). */\n state(): EProcessState\n}\n\n/**\n * `SurfaceProposer.decide` adapter — stops the optimization loop the moment\n * the e-process decides the loop has produced a real improvement, instead of\n * always running `maxGenerations`.\n *\n * Stream: for each generation g ≥ 1, the per-scenario composite deltas of\n * generation g's top candidate vs the generation-0 top candidate (the\n * incumbent the loop set out to beat), paired by scenarioId. H0: no proposed\n * surface improves any scenario's expected composite over the incumbent —\n * under it every delta has conditional mean ≤ 0 and the e-process is valid.\n * Once wealth ≥ 1/alpha the loop stops and hands the winner to the promotion\n * gate (which re-scores on HELD-OUT data — this adapter only spends the\n * exploration budget, it never promotes).\n *\n * Honesty caveats: (1) the incumbent's scores are measured once and shared\n * across all generations' deltas, so type-I control is exact only insofar as\n * those scores approximate the incumbent's true per-scenario means (more reps\n * → tighter); (2) an UNDECIDED process never stops the loop — absence of a\n * crossing is NOT evidence of no effect, so the loop simply runs its normal\n * course. Calling the adapter repeatedly with a growing history consumes each\n * generation exactly once (re-feeding an already-seen record would double-count\n * evidence).\n */\nexport function sequentialDecide(options: SequentialDecideOptions = {}): SequentialDecideFn {\n const alpha = options.alpha ?? 0.05\n const minN = options.minN ?? 5\n const scale = options.scale ?? 1\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new Error(`sequentialDecide: scale must be > 0, got ${scale}`)\n }\n const proc = eProcess({ alpha, maxBet: options.maxBet ?? 0.5, nullMean: 0.5 })\n const threshold = 1 / alpha\n let processedGenerations = 0\n let reference: Map<string, number> | undefined\n let stopped: { stop: true; reason: string } | undefined\n\n const topCandidate = (record: GenerationRecord) => {\n if (record.candidates.length === 0) {\n throw new Error(\n `sequentialDecide: generation ${record.generationIndex} has no candidates — ` +\n 'cannot extract a top candidate',\n )\n }\n return record.candidates.reduce((best, candidate) => {\n if (best.composite === null) return candidate\n if (candidate.composite === null) return best\n return candidate.composite > best.composite ? candidate : best\n })\n }\n\n const decide: SequentialDecideFn = ({ history }) => {\n if (stopped) return stopped\n if (history.length === 0) return { stop: false }\n if (reference === undefined) {\n reference = new Map(\n topCandidate(history[0]!).scenarios.map((s) => [s.scenarioId, s.composite]),\n )\n }\n // Consume only generations not yet seen; start at 1 — generation 0 IS the\n // reference and would contribute all-zero deltas (pure wealth dilution).\n for (let g = Math.max(1, processedGenerations); g < history.length; g++) {\n const top = topCandidate(history[g]!)\n const byScenario = new Map(top.scenarios.map((s) => [s.scenarioId, s.composite]))\n for (const [scenarioId, refComposite] of reference) {\n const candComposite = byScenario.get(scenarioId)\n if (candComposite === undefined) {\n throw new Error(\n `sequentialDecide: generation ${history[g]!.generationIndex} top candidate is missing ` +\n `scenario '${scenarioId}' — generations must score the same scenario set to pair`,\n )\n }\n const delta = candComposite - refComposite\n if (!Number.isFinite(delta) || Math.abs(delta) > scale) {\n throw new Error(\n `sequentialDecide: paired delta ${delta} outside ±scale=${scale} on scenario ` +\n `'${scenarioId}' — pass the composite scale explicitly`,\n )\n }\n const step = proc.update((delta / scale + 1) / 2)\n if (step.n >= minN && step.wealth >= threshold) {\n stopped = {\n stop: true,\n reason:\n `sequential e-process decided at generation ${history[g]!.generationIndex}: ` +\n `e-value ${step.wealth.toFixed(2)} ≥ 1/α=${threshold.toFixed(2)} after n=${step.n} ` +\n 'paired deltas vs the generation-0 incumbent — the improvement is real at ' +\n `α=${alpha}; stop exploring and promote via the gate`,\n }\n processedGenerations = history.length\n return stopped\n }\n }\n }\n processedGenerations = history.length\n return { stop: false }\n }\n decide.state = () => proc.state()\n return decide\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"statistical-heldout-0La5ZTlv.d.ts","names":[],"sources":["../src/statistics/paired-binary.ts","../src/statistics/sequential-eprocess.ts","../src/attestation.ts","../src/experiment/evidence-receipt.ts","../src/experiment/campaign-evidence.ts","../src/pareto.ts","../src/campaign/gates/promotion-policy.ts","../src/campaign/gates/power-preflight.ts","../src/paired-arms.ts","../src/pre-registration.ts","../src/campaign/gates/sequential.ts","../src/campaign/gates/statistical-heldout.ts"],"mappings":"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"}
|