@tangle-network/agent-eval 0.110.1 → 0.112.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 +20 -0
- package/dist/analyst/index.d.ts +3 -3
- package/dist/analyst/index.js +8 -4
- package/dist/analyst/index.js.map +1 -1
- package/dist/belief-state/index.js +1 -1
- package/dist/benchmarks/index.js +8 -8
- package/dist/builder-eval/index.js +1 -1
- package/dist/campaign/index.d.ts +3 -3
- package/dist/campaign/index.js +7 -7
- package/dist/{chunk-X6NIXVOD.js → chunk-3LDPUYAC.js} +2 -2
- package/dist/{chunk-XRGOKCMO.js → chunk-4FRTXH2M.js} +3 -3
- package/dist/{chunk-N22ZO7FV.js → chunk-7QPK6W7R.js} +2 -2
- package/dist/{chunk-QFGTU7MT.js → chunk-BOLYPSAE.js} +4 -4
- package/dist/{chunk-7NX6ZSBG.js → chunk-DWLIGZBX.js} +145 -42
- package/dist/chunk-DWLIGZBX.js.map +1 -0
- package/dist/{chunk-6MFFKPZ4.js → chunk-EMKORATZ.js} +2 -2
- package/dist/{chunk-2IY4ILP4.js → chunk-HJWNHCD5.js} +57 -2
- package/dist/chunk-HJWNHCD5.js.map +1 -0
- package/dist/{chunk-OW47B5WA.js → chunk-LVTGFSHF.js} +2 -2
- package/dist/{chunk-GBI5J5DB.js → chunk-QQVYMBCZ.js} +6 -6
- package/dist/{chunk-J4AKLZEV.js → chunk-RCXMWGRY.js} +5 -5
- package/dist/{chunk-6HFYGEZ3.js → chunk-RT2AFUXM.js} +2 -2
- package/dist/{chunk-XMSYF4A7.js → chunk-VC43KQCK.js} +24 -1
- package/dist/chunk-VC43KQCK.js.map +1 -0
- package/dist/{chunk-T6W5ADLG.js → chunk-VLNGPUJJ.js} +2 -2
- package/dist/{chunk-6PL5MGDL.js → chunk-WZOIFFG2.js} +2 -2
- package/dist/{chunk-3PFZBGMR.js → chunk-XNCF3JU3.js} +2 -2
- package/dist/{chunk-PLOMR3HP.js → chunk-YWGKQARF.js} +2 -2
- package/dist/contract/index.d.ts +3 -3
- package/dist/contract/index.js +8 -8
- package/dist/index.d.ts +123 -6
- package/dist/index.js +474 -214
- package/dist/index.js.map +1 -1
- package/dist/meta-eval/index.d.ts +1 -1
- package/dist/meta-eval/index.js +2 -2
- package/dist/openapi.json +1 -1
- package/dist/pipelines/index.js +2 -2
- package/dist/{policy-edit-D2bBDZDf.d.ts → policy-edit-az2qRmvN.d.ts} +1 -1
- package/dist/{provenance-CyxkvEi9.d.ts → provenance-KhY8ESVM.d.ts} +1 -1
- package/dist/reporting.d.ts +1 -1
- package/dist/reporting.js +4 -4
- package/dist/rl.js +5 -5
- package/dist/{run-campaign-PNHAJIT2.js → run-campaign-HJQEDCJQ.js} +3 -3
- package/dist/{semantic-concept-judge-D7z6JCLZ.d.ts → semantic-concept-judge-CpzbtwD0.d.ts} +29 -1
- package/dist/{statistics-D88peojY.d.ts → statistics-CDfpwIdX.d.ts} +13 -1
- package/package.json +2 -2
- package/dist/chunk-2IY4ILP4.js.map +0 -1
- package/dist/chunk-7NX6ZSBG.js.map +0 -1
- package/dist/chunk-XMSYF4A7.js.map +0 -1
- /package/dist/{chunk-X6NIXVOD.js.map → chunk-3LDPUYAC.js.map} +0 -0
- /package/dist/{chunk-XRGOKCMO.js.map → chunk-4FRTXH2M.js.map} +0 -0
- /package/dist/{chunk-N22ZO7FV.js.map → chunk-7QPK6W7R.js.map} +0 -0
- /package/dist/{chunk-QFGTU7MT.js.map → chunk-BOLYPSAE.js.map} +0 -0
- /package/dist/{chunk-6MFFKPZ4.js.map → chunk-EMKORATZ.js.map} +0 -0
- /package/dist/{chunk-OW47B5WA.js.map → chunk-LVTGFSHF.js.map} +0 -0
- /package/dist/{chunk-GBI5J5DB.js.map → chunk-QQVYMBCZ.js.map} +0 -0
- /package/dist/{chunk-J4AKLZEV.js.map → chunk-RCXMWGRY.js.map} +0 -0
- /package/dist/{chunk-6HFYGEZ3.js.map → chunk-RT2AFUXM.js.map} +0 -0
- /package/dist/{chunk-T6W5ADLG.js.map → chunk-VLNGPUJJ.js.map} +0 -0
- /package/dist/{chunk-6PL5MGDL.js.map → chunk-WZOIFFG2.js.map} +0 -0
- /package/dist/{chunk-3PFZBGMR.js.map → chunk-XNCF3JU3.js.map} +0 -0
- /package/dist/{chunk-PLOMR3HP.js.map → chunk-YWGKQARF.js.map} +0 -0
- /package/dist/{run-campaign-PNHAJIT2.js.map → run-campaign-HJQEDCJQ.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
checkBehavioralCanary,
|
|
10
10
|
checkCanaries,
|
|
11
11
|
runBehavioralCanaries
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BOLYPSAE.js";
|
|
13
13
|
import {
|
|
14
14
|
BENCHMARK_SPLIT_SEED,
|
|
15
15
|
benchmarks_exports,
|
|
16
16
|
deterministicSplit
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-VLNGPUJJ.js";
|
|
18
18
|
import {
|
|
19
19
|
DEFAULT_RULES,
|
|
20
20
|
buildTrajectory,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
computeToolUseMetrics,
|
|
24
24
|
iqr,
|
|
25
25
|
welchsTTest
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-YWGKQARF.js";
|
|
27
27
|
import {
|
|
28
28
|
analyzeSeries
|
|
29
29
|
} from "./chunk-BOD4O7OF.js";
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
llmJudge,
|
|
60
60
|
parseCorrectnessResponse,
|
|
61
61
|
verifyCompletion
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-QQVYMBCZ.js";
|
|
63
63
|
import {
|
|
64
64
|
DEFAULT_MUTATION_PRIMITIVES,
|
|
65
65
|
DEFAULT_RED_TEAM_CORPUS,
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
scoreRedTeamOutput,
|
|
84
84
|
surfaceContentHash,
|
|
85
85
|
toolNamesForRun
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-RCXMWGRY.js";
|
|
87
87
|
import {
|
|
88
88
|
MODEL_PRICING,
|
|
89
89
|
MetricsCollector,
|
|
@@ -102,7 +102,7 @@ import {
|
|
|
102
102
|
fileVerdictCache,
|
|
103
103
|
inMemoryVerdictCache,
|
|
104
104
|
summarizeBackendIntegrity
|
|
105
|
-
} from "./chunk-
|
|
105
|
+
} from "./chunk-XNCF3JU3.js";
|
|
106
106
|
import {
|
|
107
107
|
DEFAULT_COMPLEXITY_WEIGHTS,
|
|
108
108
|
FindingsStore,
|
|
@@ -118,11 +118,11 @@ import {
|
|
|
118
118
|
defaultIsMaterial,
|
|
119
119
|
diffFindings,
|
|
120
120
|
runSemanticConceptJudge
|
|
121
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-4FRTXH2M.js";
|
|
122
122
|
import {
|
|
123
123
|
buildDefaultAnalystRegistry,
|
|
124
124
|
computeTraceMetrics
|
|
125
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-LVTGFSHF.js";
|
|
126
126
|
import {
|
|
127
127
|
DEFAULT_RUN_SCORE_WEIGHTS,
|
|
128
128
|
POLICY_EDIT_AXES,
|
|
@@ -139,7 +139,7 @@ import {
|
|
|
139
139
|
policyEditsFromFindings,
|
|
140
140
|
scorePolicyEditReadiness,
|
|
141
141
|
validatePolicyEdit
|
|
142
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-HJWNHCD5.js";
|
|
143
143
|
import {
|
|
144
144
|
AnalystRegistry,
|
|
145
145
|
DEFAULT_TRACE_ANALYST_KINDS,
|
|
@@ -151,7 +151,7 @@ import {
|
|
|
151
151
|
createTraceAnalystKind,
|
|
152
152
|
makeFinding,
|
|
153
153
|
renderPriorFindings
|
|
154
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-DWLIGZBX.js";
|
|
155
155
|
import {
|
|
156
156
|
allCriticalPassed,
|
|
157
157
|
controlFailureClassFromVerification,
|
|
@@ -179,11 +179,11 @@ import {
|
|
|
179
179
|
evaluateReleaseConfidence,
|
|
180
180
|
judgeReplayGate,
|
|
181
181
|
renderReleaseReport
|
|
182
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-RT2AFUXM.js";
|
|
183
183
|
import {
|
|
184
184
|
runEvalCampaign
|
|
185
|
-
} from "./chunk-
|
|
186
|
-
import "./chunk-
|
|
185
|
+
} from "./chunk-WZOIFFG2.js";
|
|
186
|
+
import "./chunk-7QPK6W7R.js";
|
|
187
187
|
import {
|
|
188
188
|
evaluateInterimReleaseConfidence,
|
|
189
189
|
pairedEvalueSequence
|
|
@@ -194,7 +194,7 @@ import {
|
|
|
194
194
|
paretoChart,
|
|
195
195
|
researchReport,
|
|
196
196
|
summaryTable
|
|
197
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-EMKORATZ.js";
|
|
198
198
|
import {
|
|
199
199
|
benjaminiHochberg,
|
|
200
200
|
bonferroni,
|
|
@@ -207,6 +207,7 @@ import {
|
|
|
207
207
|
corpusInterRaterAgreement,
|
|
208
208
|
corpusInterRaterAgreementFromJudgeScores,
|
|
209
209
|
eProcess,
|
|
210
|
+
holm,
|
|
210
211
|
interRaterReliability,
|
|
211
212
|
interpretCliffs,
|
|
212
213
|
mannWhitneyU,
|
|
@@ -232,7 +233,7 @@ import {
|
|
|
232
233
|
weightedMean,
|
|
233
234
|
wilcoxonSignedRank,
|
|
234
235
|
wilson
|
|
235
|
-
} from "./chunk-
|
|
236
|
+
} from "./chunk-VC43KQCK.js";
|
|
236
237
|
import {
|
|
237
238
|
FileSystemTraceStore,
|
|
238
239
|
InMemoryTraceStore,
|
|
@@ -1300,6 +1301,412 @@ async function runE2EWorkflow(client, name, workflow) {
|
|
|
1300
1301
|
};
|
|
1301
1302
|
}
|
|
1302
1303
|
|
|
1304
|
+
// src/paired-arms.ts
|
|
1305
|
+
function pairArms(rows, opts) {
|
|
1306
|
+
const { baselineArm, treatmentArm } = opts;
|
|
1307
|
+
if (baselineArm === treatmentArm) {
|
|
1308
|
+
throw new ValidationError(
|
|
1309
|
+
`pairArms: baselineArm and treatmentArm are both '${baselineArm}' \u2014 an arm cannot be compared to itself`
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
const byArm = /* @__PURE__ */ new Map();
|
|
1313
|
+
const armsSeen = /* @__PURE__ */ new Set();
|
|
1314
|
+
for (const row of rows) {
|
|
1315
|
+
armsSeen.add(row.arm);
|
|
1316
|
+
if (row.arm !== baselineArm && row.arm !== treatmentArm) continue;
|
|
1317
|
+
const byKey = byArm.get(row.arm) ?? /* @__PURE__ */ new Map();
|
|
1318
|
+
const group = byKey.get(row.pairKey) ?? [];
|
|
1319
|
+
group.push(row);
|
|
1320
|
+
byKey.set(row.pairKey, group);
|
|
1321
|
+
byArm.set(row.arm, byKey);
|
|
1322
|
+
}
|
|
1323
|
+
for (const arm of [baselineArm, treatmentArm]) {
|
|
1324
|
+
if (!byArm.has(arm)) {
|
|
1325
|
+
const seen = [...armsSeen].sort().join(", ") || "<none>";
|
|
1326
|
+
throw new ValidationError(`pairArms: no rows for arm '${arm}' (arms present: ${seen})`);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
const baselineByKey = byArm.get(baselineArm);
|
|
1330
|
+
const treatmentByKey = byArm.get(treatmentArm);
|
|
1331
|
+
const allKeys = [.../* @__PURE__ */ new Set([...baselineByKey.keys(), ...treatmentByKey.keys()])].sort();
|
|
1332
|
+
const pairs = [];
|
|
1333
|
+
const unpairedBaseline = [];
|
|
1334
|
+
const unpairedTreatment = [];
|
|
1335
|
+
for (const pairKey2 of allKeys) {
|
|
1336
|
+
const b = baselineByKey.get(pairKey2) ?? [];
|
|
1337
|
+
const t = treatmentByKey.get(pairKey2) ?? [];
|
|
1338
|
+
if (b.length <= 1 && t.length <= 1) {
|
|
1339
|
+
if (b.length === 1 && t.length === 1) {
|
|
1340
|
+
pairs.push({ pairKey: pairKey2, repIndex: 0, baseline: b[0], treatment: t[0] });
|
|
1341
|
+
} else {
|
|
1342
|
+
unpairedBaseline.push(...b);
|
|
1343
|
+
unpairedTreatment.push(...t);
|
|
1344
|
+
}
|
|
1345
|
+
continue;
|
|
1346
|
+
}
|
|
1347
|
+
const bByRep = indexByRepKey(b, pairKey2, baselineArm);
|
|
1348
|
+
const tByRep = indexByRepKey(t, pairKey2, treatmentArm);
|
|
1349
|
+
const repKeys = [.../* @__PURE__ */ new Set([...bByRep.keys(), ...tByRep.keys()])].sort();
|
|
1350
|
+
let repIndex = 0;
|
|
1351
|
+
for (const repKey of repKeys) {
|
|
1352
|
+
const baseline = bByRep.get(repKey);
|
|
1353
|
+
const treatment = tByRep.get(repKey);
|
|
1354
|
+
if (baseline !== void 0 && treatment !== void 0) {
|
|
1355
|
+
pairs.push({ pairKey: pairKey2, repIndex: repIndex++, baseline, treatment });
|
|
1356
|
+
} else if (baseline !== void 0) {
|
|
1357
|
+
unpairedBaseline.push(baseline);
|
|
1358
|
+
} else if (treatment !== void 0) {
|
|
1359
|
+
unpairedTreatment.push(treatment);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return { pairs, unpairedBaseline, unpairedTreatment };
|
|
1364
|
+
}
|
|
1365
|
+
function indexByRepKey(group, pairKey2, arm) {
|
|
1366
|
+
const byRep = /* @__PURE__ */ new Map();
|
|
1367
|
+
for (const row of group) {
|
|
1368
|
+
if (row.repKey === void 0) {
|
|
1369
|
+
throw new ValidationError(
|
|
1370
|
+
`pairArms: pairKey '${pairKey2}' has multiple reps in an arm, but a row in arm '${arm}' is missing repKey \u2014 multi-rep items require an explicit repKey on every row so reps pair by identity (pairing reps by outcome or by index would bias the paired statistics)`
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
if (byRep.has(row.repKey)) {
|
|
1374
|
+
throw new ValidationError(
|
|
1375
|
+
`pairArms: duplicate repKey '${row.repKey}' for pairKey '${pairKey2}' in arm '${arm}' \u2014 (pairKey, repKey) must uniquely identify a rep within an arm`
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1378
|
+
byRep.set(row.repKey, row);
|
|
1379
|
+
}
|
|
1380
|
+
return byRep;
|
|
1381
|
+
}
|
|
1382
|
+
function comparePairedArms(rows, opts) {
|
|
1383
|
+
const { pairs, unpairedBaseline, unpairedTreatment } = pairArms(rows, opts);
|
|
1384
|
+
let correctness = null;
|
|
1385
|
+
const baselinePass = [];
|
|
1386
|
+
const treatmentPass = [];
|
|
1387
|
+
for (const pair of pairs) {
|
|
1388
|
+
if (pair.baseline.pass === void 0 || pair.treatment.pass === void 0) continue;
|
|
1389
|
+
baselinePass.push(pair.baseline.pass ? 1 : 0);
|
|
1390
|
+
treatmentPass.push(pair.treatment.pass ? 1 : 0);
|
|
1391
|
+
}
|
|
1392
|
+
if (baselinePass.length > 0) {
|
|
1393
|
+
const mc = mcnemar(baselinePass, treatmentPass);
|
|
1394
|
+
correctness = {
|
|
1395
|
+
b10: mc.b,
|
|
1396
|
+
b01: mc.c,
|
|
1397
|
+
mcnemar: mc,
|
|
1398
|
+
riskDifference: pairedRiskDifference(baselinePass, treatmentPass)
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
const metricNames = opts.metricNames ?? [
|
|
1402
|
+
...new Set(
|
|
1403
|
+
pairs.flatMap((p) => [
|
|
1404
|
+
...Object.keys(p.baseline.metrics ?? {}),
|
|
1405
|
+
...Object.keys(p.treatment.metrics ?? {})
|
|
1406
|
+
])
|
|
1407
|
+
)
|
|
1408
|
+
].sort();
|
|
1409
|
+
const metricDeltas = metricNames.map((name) => {
|
|
1410
|
+
const before = [];
|
|
1411
|
+
const after = [];
|
|
1412
|
+
let nMissing = 0;
|
|
1413
|
+
for (const pair of pairs) {
|
|
1414
|
+
const b = metricValue(pair.baseline, name);
|
|
1415
|
+
const t = metricValue(pair.treatment, name);
|
|
1416
|
+
if (b === void 0 || t === void 0) {
|
|
1417
|
+
nMissing++;
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
before.push(b);
|
|
1421
|
+
after.push(t);
|
|
1422
|
+
}
|
|
1423
|
+
const bootstrapCi2 = before.length === 0 ? null : pairedBootstrap(before, after, opts.bootstrap);
|
|
1424
|
+
return {
|
|
1425
|
+
name,
|
|
1426
|
+
n: before.length,
|
|
1427
|
+
nMissing,
|
|
1428
|
+
medianDelta: bootstrapCi2 === null ? Number.NaN : bootstrapCi2.median,
|
|
1429
|
+
meanDelta: bootstrapCi2 === null ? Number.NaN : bootstrapCi2.mean,
|
|
1430
|
+
bootstrapCi: bootstrapCi2,
|
|
1431
|
+
wilcoxon: before.length === 0 ? null : wilcoxonSignedRank(before, after)
|
|
1432
|
+
};
|
|
1433
|
+
});
|
|
1434
|
+
return {
|
|
1435
|
+
nPairs: pairs.length,
|
|
1436
|
+
nUnpairedBaseline: unpairedBaseline.length,
|
|
1437
|
+
nUnpairedTreatment: unpairedTreatment.length,
|
|
1438
|
+
correctness,
|
|
1439
|
+
metricDeltas
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
function metricValue(row, name) {
|
|
1443
|
+
const v = row.metrics?.[name];
|
|
1444
|
+
if (v === void 0) return void 0;
|
|
1445
|
+
if (!Number.isFinite(v)) {
|
|
1446
|
+
throw new ValidationError(
|
|
1447
|
+
`comparePairedArms: non-finite value for metric '${name}' on pairKey '${row.pairKey}' (arm '${row.arm}'): ${v}`
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
return v;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
// src/clustered-paired-binary.ts
|
|
1454
|
+
var DEFAULT_BOOTSTRAP_RESAMPLES = 1e4;
|
|
1455
|
+
var DEFAULT_SIGN_FLIP_RESAMPLES = 1e5;
|
|
1456
|
+
var MAX_RESAMPLES = 1e6;
|
|
1457
|
+
var DEFAULT_EXACT_CLUSTER_LIMIT = 20;
|
|
1458
|
+
var SIGN_FLIP_SEED_SALT = 2654435769;
|
|
1459
|
+
function clusteredPairedBinary(rows, options) {
|
|
1460
|
+
const config = validateOptions(options);
|
|
1461
|
+
const projected = projectSelectedRows(rows, options);
|
|
1462
|
+
const paired = pairArms(projected, {
|
|
1463
|
+
baselineArm: options.baselineArm,
|
|
1464
|
+
treatmentArm: options.treatmentArm
|
|
1465
|
+
});
|
|
1466
|
+
const matchedPairs = paired.pairs.map((pair) => {
|
|
1467
|
+
const baseline = pair.baseline;
|
|
1468
|
+
const treatment = pair.treatment;
|
|
1469
|
+
if (baseline.clusterKey !== treatment.clusterKey) {
|
|
1470
|
+
throw new ValidationError(
|
|
1471
|
+
`clusteredPairedBinary: pairKey '${pair.pairKey}' rep ${pair.repIndex} crosses clusters ('${baseline.clusterKey}' vs '${treatment.clusterKey}')`
|
|
1472
|
+
);
|
|
1473
|
+
}
|
|
1474
|
+
return {
|
|
1475
|
+
pairKey: pair.pairKey,
|
|
1476
|
+
repIndex: pair.repIndex,
|
|
1477
|
+
clusterKey: baseline.clusterKey,
|
|
1478
|
+
baseline: baseline.original,
|
|
1479
|
+
treatment: treatment.original,
|
|
1480
|
+
baselinePass: baseline.pass,
|
|
1481
|
+
treatmentPass: treatment.pass
|
|
1482
|
+
};
|
|
1483
|
+
});
|
|
1484
|
+
const unpairedBaseline = paired.unpairedBaseline.map(
|
|
1485
|
+
(row) => row.original
|
|
1486
|
+
);
|
|
1487
|
+
const unpairedTreatment = paired.unpairedTreatment.map(
|
|
1488
|
+
(row) => row.original
|
|
1489
|
+
);
|
|
1490
|
+
if (matchedPairs.length === 0) {
|
|
1491
|
+
return { matchedPairs, unpairedBaseline, unpairedTreatment, statistics: null };
|
|
1492
|
+
}
|
|
1493
|
+
const clusters = summarizeClusters(matchedPairs);
|
|
1494
|
+
const b10 = clusters.reduce((sum4, cluster) => sum4 + cluster.b10, 0);
|
|
1495
|
+
const b01 = clusters.reduce((sum4, cluster) => sum4 + cluster.b01, 0);
|
|
1496
|
+
const taskWeightedRiskDifference = (b10 - b01) / matchedPairs.length;
|
|
1497
|
+
const equalClusterMean = mean(clusters.map((cluster) => cluster.meanDifference));
|
|
1498
|
+
const bootstrap = clusters.length < 2 ? null : clusterBootstrap(clusters, config);
|
|
1499
|
+
const signFlip = clusterSignFlip(clusters, config);
|
|
1500
|
+
return {
|
|
1501
|
+
matchedPairs,
|
|
1502
|
+
unpairedBaseline,
|
|
1503
|
+
unpairedTreatment,
|
|
1504
|
+
statistics: {
|
|
1505
|
+
nPairs: matchedPairs.length,
|
|
1506
|
+
nClusters: clusters.length,
|
|
1507
|
+
b10,
|
|
1508
|
+
b01,
|
|
1509
|
+
taskWeightedRiskDifference,
|
|
1510
|
+
equalClusterMean,
|
|
1511
|
+
clusters,
|
|
1512
|
+
bootstrap,
|
|
1513
|
+
signFlip
|
|
1514
|
+
}
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
function validateOptions(options) {
|
|
1518
|
+
assertNonEmptyString("baselineArm", options.baselineArm);
|
|
1519
|
+
assertNonEmptyString("treatmentArm", options.treatmentArm);
|
|
1520
|
+
if (options.baselineArm === options.treatmentArm) {
|
|
1521
|
+
throw new ValidationError(
|
|
1522
|
+
`clusteredPairedBinary: baselineArm and treatmentArm are both '${options.baselineArm}'`
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
if (!Number.isInteger(options.seed)) {
|
|
1526
|
+
throw new ValidationError(`clusteredPairedBinary: seed must be an integer, got ${options.seed}`);
|
|
1527
|
+
}
|
|
1528
|
+
const confidence = options.confidence ?? 0.95;
|
|
1529
|
+
if (!Number.isFinite(confidence) || confidence <= 0 || confidence >= 1) {
|
|
1530
|
+
throw new ValidationError(
|
|
1531
|
+
`clusteredPairedBinary: confidence must be in (0,1), got ${confidence}`
|
|
1532
|
+
);
|
|
1533
|
+
}
|
|
1534
|
+
const bootstrapResamples = options.bootstrapResamples ?? DEFAULT_BOOTSTRAP_RESAMPLES;
|
|
1535
|
+
assertResampleCount("bootstrapResamples", bootstrapResamples);
|
|
1536
|
+
const rawMinimumBootstrapResamples = 2 / (1 - confidence);
|
|
1537
|
+
const minimumBootstrapResamples = Math.ceil(
|
|
1538
|
+
rawMinimumBootstrapResamples - Number.EPSILON * Math.max(1, rawMinimumBootstrapResamples) * 8
|
|
1539
|
+
);
|
|
1540
|
+
if (bootstrapResamples < minimumBootstrapResamples) {
|
|
1541
|
+
throw new ValidationError(
|
|
1542
|
+
`clusteredPairedBinary: bootstrapResamples must be at least ${minimumBootstrapResamples} for confidence ${confidence} so both interval tails are represented, got ${bootstrapResamples}`
|
|
1543
|
+
);
|
|
1544
|
+
}
|
|
1545
|
+
const signFlipResamples = options.signFlipResamples ?? DEFAULT_SIGN_FLIP_RESAMPLES;
|
|
1546
|
+
assertResampleCount("signFlipResamples", signFlipResamples);
|
|
1547
|
+
const exactClusterLimit = options.exactClusterLimit ?? DEFAULT_EXACT_CLUSTER_LIMIT;
|
|
1548
|
+
if (!Number.isInteger(exactClusterLimit) || exactClusterLimit < 0 || exactClusterLimit > DEFAULT_EXACT_CLUSTER_LIMIT) {
|
|
1549
|
+
throw new ValidationError(
|
|
1550
|
+
`clusteredPairedBinary: exactClusterLimit must be an integer in [0,${DEFAULT_EXACT_CLUSTER_LIMIT}], got ${exactClusterLimit}`
|
|
1551
|
+
);
|
|
1552
|
+
}
|
|
1553
|
+
const alternative = options.alternative ?? "two-sided";
|
|
1554
|
+
if (alternative !== "two-sided" && alternative !== "greater" && alternative !== "less") {
|
|
1555
|
+
throw new ValidationError(
|
|
1556
|
+
`clusteredPairedBinary: alternative must be 'two-sided', 'greater', or 'less', got ${String(alternative)}`
|
|
1557
|
+
);
|
|
1558
|
+
}
|
|
1559
|
+
return {
|
|
1560
|
+
seed: options.seed,
|
|
1561
|
+
confidence,
|
|
1562
|
+
bootstrapResamples,
|
|
1563
|
+
alternative,
|
|
1564
|
+
exactClusterLimit,
|
|
1565
|
+
signFlipResamples
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
function assertResampleCount(name, value) {
|
|
1569
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
1570
|
+
throw new ValidationError(
|
|
1571
|
+
`clusteredPairedBinary: ${name} must be a positive integer, got ${value}`
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
if (value > MAX_RESAMPLES) {
|
|
1575
|
+
throw new ValidationError(
|
|
1576
|
+
`clusteredPairedBinary: ${name} must not exceed ${MAX_RESAMPLES}, got ${value}`
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
function projectSelectedRows(rows, options) {
|
|
1581
|
+
const projected = [];
|
|
1582
|
+
for (const original of rows) {
|
|
1583
|
+
const arm = options.arm(original);
|
|
1584
|
+
assertNonEmptyString("arm", arm);
|
|
1585
|
+
if (arm !== options.baselineArm && arm !== options.treatmentArm) continue;
|
|
1586
|
+
const pairKey2 = options.pairKey(original);
|
|
1587
|
+
const clusterKey = options.clusterKey(original);
|
|
1588
|
+
const pass = options.pass(original);
|
|
1589
|
+
const repKey = options.repKey?.(original);
|
|
1590
|
+
assertNonEmptyString("pairKey", pairKey2);
|
|
1591
|
+
assertNonEmptyString("clusterKey", clusterKey);
|
|
1592
|
+
if (typeof pass !== "boolean") {
|
|
1593
|
+
throw new ValidationError(
|
|
1594
|
+
`clusteredPairedBinary: pass accessor must return boolean for pairKey '${pairKey2}'`
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1597
|
+
if (repKey !== void 0) assertNonEmptyString("repKey", repKey);
|
|
1598
|
+
projected.push({ pairKey: pairKey2, clusterKey, arm, pass, repKey, original });
|
|
1599
|
+
}
|
|
1600
|
+
return projected;
|
|
1601
|
+
}
|
|
1602
|
+
function assertNonEmptyString(name, value) {
|
|
1603
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1604
|
+
throw new ValidationError(
|
|
1605
|
+
`clusteredPairedBinary: ${name} accessor must return a non-empty string`
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
function summarizeClusters(pairs) {
|
|
1610
|
+
const byCluster = /* @__PURE__ */ new Map();
|
|
1611
|
+
for (const pair of pairs) {
|
|
1612
|
+
const summary = byCluster.get(pair.clusterKey) ?? { nPairs: 0, b10: 0, b01: 0 };
|
|
1613
|
+
summary.nPairs++;
|
|
1614
|
+
if (pair.treatmentPass && !pair.baselinePass) summary.b10++;
|
|
1615
|
+
else if (pair.baselinePass && !pair.treatmentPass) summary.b01++;
|
|
1616
|
+
byCluster.set(pair.clusterKey, summary);
|
|
1617
|
+
}
|
|
1618
|
+
return [...byCluster.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([clusterKey, summary]) => ({
|
|
1619
|
+
clusterKey,
|
|
1620
|
+
...summary,
|
|
1621
|
+
meanDifference: (summary.b10 - summary.b01) / summary.nPairs
|
|
1622
|
+
}));
|
|
1623
|
+
}
|
|
1624
|
+
function clusterBootstrap(clusters, config) {
|
|
1625
|
+
const rng = mulberry32(config.seed);
|
|
1626
|
+
const samples = new Array(config.bootstrapResamples);
|
|
1627
|
+
for (let draw = 0; draw < config.bootstrapResamples; draw++) {
|
|
1628
|
+
let differenceSum = 0;
|
|
1629
|
+
let pairCount = 0;
|
|
1630
|
+
for (let index = 0; index < clusters.length; index++) {
|
|
1631
|
+
const cluster = clusters[Math.floor(rng() * clusters.length)];
|
|
1632
|
+
differenceSum += cluster.b10 - cluster.b01;
|
|
1633
|
+
pairCount += cluster.nPairs;
|
|
1634
|
+
}
|
|
1635
|
+
samples[draw] = differenceSum / pairCount;
|
|
1636
|
+
}
|
|
1637
|
+
samples.sort((a, b) => a - b);
|
|
1638
|
+
const alpha = 1 - config.confidence;
|
|
1639
|
+
const lowerIndex = Math.floor(alpha / 2 * config.bootstrapResamples);
|
|
1640
|
+
const upperIndex = Math.min(
|
|
1641
|
+
config.bootstrapResamples - 1,
|
|
1642
|
+
Math.ceil((1 - alpha / 2) * config.bootstrapResamples) - 1
|
|
1643
|
+
);
|
|
1644
|
+
return {
|
|
1645
|
+
statistic: "task-weighted-risk-difference",
|
|
1646
|
+
lower: samples[lowerIndex],
|
|
1647
|
+
upper: samples[Math.max(lowerIndex, upperIndex)],
|
|
1648
|
+
confidence: config.confidence,
|
|
1649
|
+
resamples: config.bootstrapResamples,
|
|
1650
|
+
seed: config.seed
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function clusterSignFlip(clusters, config) {
|
|
1654
|
+
const clusterTotals = clusters.map((cluster) => cluster.b10 - cluster.b01);
|
|
1655
|
+
const nonZero = clusterTotals.filter((delta) => delta !== 0);
|
|
1656
|
+
const totalPairs = clusters.reduce((sum4, cluster) => sum4 + cluster.nPairs, 0);
|
|
1657
|
+
const statistic = clusterTotals.reduce((sum4, delta) => sum4 + delta, 0) / totalPairs;
|
|
1658
|
+
if (nonZero.length <= config.exactClusterLimit) {
|
|
1659
|
+
const assignments = 2 ** nonZero.length;
|
|
1660
|
+
let extreme2 = 0;
|
|
1661
|
+
for (let mask = 0; mask < assignments; mask++) {
|
|
1662
|
+
let sum4 = 0;
|
|
1663
|
+
for (let index = 0; index < nonZero.length; index++) {
|
|
1664
|
+
sum4 += (mask & 2 ** index ? 1 : -1) * nonZero[index];
|
|
1665
|
+
}
|
|
1666
|
+
const permuted = sum4 / totalPairs;
|
|
1667
|
+
if (isExtreme(permuted, statistic, config.alternative)) extreme2++;
|
|
1668
|
+
}
|
|
1669
|
+
return {
|
|
1670
|
+
statistic,
|
|
1671
|
+
pValue: extreme2 / assignments,
|
|
1672
|
+
alternative: config.alternative,
|
|
1673
|
+
method: "exact",
|
|
1674
|
+
assignments,
|
|
1675
|
+
nClusters: clusters.length,
|
|
1676
|
+
nNonZeroClusters: nonZero.length,
|
|
1677
|
+
seed: null
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
const signFlipSeed = (config.seed ^ SIGN_FLIP_SEED_SALT) >>> 0;
|
|
1681
|
+
const rng = mulberry32(signFlipSeed);
|
|
1682
|
+
let extreme = 0;
|
|
1683
|
+
for (let draw = 0; draw < config.signFlipResamples; draw++) {
|
|
1684
|
+
let sum4 = 0;
|
|
1685
|
+
for (const delta of nonZero) sum4 += (rng() < 0.5 ? -1 : 1) * delta;
|
|
1686
|
+
const permuted = sum4 / totalPairs;
|
|
1687
|
+
if (isExtreme(permuted, statistic, config.alternative)) extreme++;
|
|
1688
|
+
}
|
|
1689
|
+
return {
|
|
1690
|
+
statistic,
|
|
1691
|
+
pValue: (extreme + 1) / (config.signFlipResamples + 1),
|
|
1692
|
+
alternative: config.alternative,
|
|
1693
|
+
method: "monte-carlo",
|
|
1694
|
+
assignments: config.signFlipResamples,
|
|
1695
|
+
nClusters: clusters.length,
|
|
1696
|
+
nNonZeroClusters: nonZero.length,
|
|
1697
|
+
seed: signFlipSeed
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
function isExtreme(candidate, observed, alternative) {
|
|
1701
|
+
const tolerance = Number.EPSILON * Math.max(1, Math.abs(observed)) * 16;
|
|
1702
|
+
if (alternative === "greater") return candidate >= observed - tolerance;
|
|
1703
|
+
if (alternative === "less") return candidate <= observed + tolerance;
|
|
1704
|
+
return Math.abs(candidate) >= Math.abs(observed) - tolerance;
|
|
1705
|
+
}
|
|
1706
|
+
function mean(values) {
|
|
1707
|
+
return values.reduce((sum4, value) => sum4 + value, 0) / values.length;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1303
1710
|
// src/convergence.ts
|
|
1304
1711
|
var ConvergenceTracker = class {
|
|
1305
1712
|
criteria;
|
|
@@ -2501,155 +2908,6 @@ function liveProofToReleaseTrace(config, trajectory, durationMs) {
|
|
|
2501
2908
|
};
|
|
2502
2909
|
}
|
|
2503
2910
|
|
|
2504
|
-
// src/paired-arms.ts
|
|
2505
|
-
function pairArms(rows, opts) {
|
|
2506
|
-
const { baselineArm, treatmentArm } = opts;
|
|
2507
|
-
if (baselineArm === treatmentArm) {
|
|
2508
|
-
throw new ValidationError(
|
|
2509
|
-
`pairArms: baselineArm and treatmentArm are both '${baselineArm}' \u2014 an arm cannot be compared to itself`
|
|
2510
|
-
);
|
|
2511
|
-
}
|
|
2512
|
-
const byArm = /* @__PURE__ */ new Map();
|
|
2513
|
-
const armsSeen = /* @__PURE__ */ new Set();
|
|
2514
|
-
for (const row of rows) {
|
|
2515
|
-
armsSeen.add(row.arm);
|
|
2516
|
-
if (row.arm !== baselineArm && row.arm !== treatmentArm) continue;
|
|
2517
|
-
const byKey = byArm.get(row.arm) ?? /* @__PURE__ */ new Map();
|
|
2518
|
-
const group = byKey.get(row.pairKey) ?? [];
|
|
2519
|
-
group.push(row);
|
|
2520
|
-
byKey.set(row.pairKey, group);
|
|
2521
|
-
byArm.set(row.arm, byKey);
|
|
2522
|
-
}
|
|
2523
|
-
for (const arm of [baselineArm, treatmentArm]) {
|
|
2524
|
-
if (!byArm.has(arm)) {
|
|
2525
|
-
const seen = [...armsSeen].sort().join(", ") || "<none>";
|
|
2526
|
-
throw new ValidationError(`pairArms: no rows for arm '${arm}' (arms present: ${seen})`);
|
|
2527
|
-
}
|
|
2528
|
-
}
|
|
2529
|
-
const baselineByKey = byArm.get(baselineArm);
|
|
2530
|
-
const treatmentByKey = byArm.get(treatmentArm);
|
|
2531
|
-
const allKeys = [.../* @__PURE__ */ new Set([...baselineByKey.keys(), ...treatmentByKey.keys()])].sort();
|
|
2532
|
-
const pairs = [];
|
|
2533
|
-
const unpairedBaseline = [];
|
|
2534
|
-
const unpairedTreatment = [];
|
|
2535
|
-
for (const pairKey2 of allKeys) {
|
|
2536
|
-
const b = baselineByKey.get(pairKey2) ?? [];
|
|
2537
|
-
const t = treatmentByKey.get(pairKey2) ?? [];
|
|
2538
|
-
if (b.length <= 1 && t.length <= 1) {
|
|
2539
|
-
if (b.length === 1 && t.length === 1) {
|
|
2540
|
-
pairs.push({ pairKey: pairKey2, repIndex: 0, baseline: b[0], treatment: t[0] });
|
|
2541
|
-
} else {
|
|
2542
|
-
unpairedBaseline.push(...b);
|
|
2543
|
-
unpairedTreatment.push(...t);
|
|
2544
|
-
}
|
|
2545
|
-
continue;
|
|
2546
|
-
}
|
|
2547
|
-
const bByRep = indexByRepKey(b, pairKey2, baselineArm);
|
|
2548
|
-
const tByRep = indexByRepKey(t, pairKey2, treatmentArm);
|
|
2549
|
-
const repKeys = [.../* @__PURE__ */ new Set([...bByRep.keys(), ...tByRep.keys()])].sort();
|
|
2550
|
-
let repIndex = 0;
|
|
2551
|
-
for (const repKey of repKeys) {
|
|
2552
|
-
const baseline = bByRep.get(repKey);
|
|
2553
|
-
const treatment = tByRep.get(repKey);
|
|
2554
|
-
if (baseline !== void 0 && treatment !== void 0) {
|
|
2555
|
-
pairs.push({ pairKey: pairKey2, repIndex: repIndex++, baseline, treatment });
|
|
2556
|
-
} else if (baseline !== void 0) {
|
|
2557
|
-
unpairedBaseline.push(baseline);
|
|
2558
|
-
} else if (treatment !== void 0) {
|
|
2559
|
-
unpairedTreatment.push(treatment);
|
|
2560
|
-
}
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
return { pairs, unpairedBaseline, unpairedTreatment };
|
|
2564
|
-
}
|
|
2565
|
-
function indexByRepKey(group, pairKey2, arm) {
|
|
2566
|
-
const byRep = /* @__PURE__ */ new Map();
|
|
2567
|
-
for (const row of group) {
|
|
2568
|
-
if (row.repKey === void 0) {
|
|
2569
|
-
throw new ValidationError(
|
|
2570
|
-
`pairArms: pairKey '${pairKey2}' has multiple reps in an arm, but a row in arm '${arm}' is missing repKey \u2014 multi-rep items require an explicit repKey on every row so reps pair by identity (pairing reps by outcome or by index would bias the paired statistics)`
|
|
2571
|
-
);
|
|
2572
|
-
}
|
|
2573
|
-
if (byRep.has(row.repKey)) {
|
|
2574
|
-
throw new ValidationError(
|
|
2575
|
-
`pairArms: duplicate repKey '${row.repKey}' for pairKey '${pairKey2}' in arm '${arm}' \u2014 (pairKey, repKey) must uniquely identify a rep within an arm`
|
|
2576
|
-
);
|
|
2577
|
-
}
|
|
2578
|
-
byRep.set(row.repKey, row);
|
|
2579
|
-
}
|
|
2580
|
-
return byRep;
|
|
2581
|
-
}
|
|
2582
|
-
function comparePairedArms(rows, opts) {
|
|
2583
|
-
const { pairs, unpairedBaseline, unpairedTreatment } = pairArms(rows, opts);
|
|
2584
|
-
let correctness = null;
|
|
2585
|
-
const baselinePass = [];
|
|
2586
|
-
const treatmentPass = [];
|
|
2587
|
-
for (const pair of pairs) {
|
|
2588
|
-
if (pair.baseline.pass === void 0 || pair.treatment.pass === void 0) continue;
|
|
2589
|
-
baselinePass.push(pair.baseline.pass ? 1 : 0);
|
|
2590
|
-
treatmentPass.push(pair.treatment.pass ? 1 : 0);
|
|
2591
|
-
}
|
|
2592
|
-
if (baselinePass.length > 0) {
|
|
2593
|
-
const mc = mcnemar(baselinePass, treatmentPass);
|
|
2594
|
-
correctness = {
|
|
2595
|
-
b10: mc.b,
|
|
2596
|
-
b01: mc.c,
|
|
2597
|
-
mcnemar: mc,
|
|
2598
|
-
riskDifference: pairedRiskDifference(baselinePass, treatmentPass)
|
|
2599
|
-
};
|
|
2600
|
-
}
|
|
2601
|
-
const metricNames = opts.metricNames ?? [
|
|
2602
|
-
...new Set(
|
|
2603
|
-
pairs.flatMap((p) => [
|
|
2604
|
-
...Object.keys(p.baseline.metrics ?? {}),
|
|
2605
|
-
...Object.keys(p.treatment.metrics ?? {})
|
|
2606
|
-
])
|
|
2607
|
-
)
|
|
2608
|
-
].sort();
|
|
2609
|
-
const metricDeltas = metricNames.map((name) => {
|
|
2610
|
-
const before = [];
|
|
2611
|
-
const after = [];
|
|
2612
|
-
let nMissing = 0;
|
|
2613
|
-
for (const pair of pairs) {
|
|
2614
|
-
const b = metricValue(pair.baseline, name);
|
|
2615
|
-
const t = metricValue(pair.treatment, name);
|
|
2616
|
-
if (b === void 0 || t === void 0) {
|
|
2617
|
-
nMissing++;
|
|
2618
|
-
continue;
|
|
2619
|
-
}
|
|
2620
|
-
before.push(b);
|
|
2621
|
-
after.push(t);
|
|
2622
|
-
}
|
|
2623
|
-
const bootstrapCi2 = before.length === 0 ? null : pairedBootstrap(before, after, opts.bootstrap);
|
|
2624
|
-
return {
|
|
2625
|
-
name,
|
|
2626
|
-
n: before.length,
|
|
2627
|
-
nMissing,
|
|
2628
|
-
medianDelta: bootstrapCi2 === null ? Number.NaN : bootstrapCi2.median,
|
|
2629
|
-
meanDelta: bootstrapCi2 === null ? Number.NaN : bootstrapCi2.mean,
|
|
2630
|
-
bootstrapCi: bootstrapCi2,
|
|
2631
|
-
wilcoxon: before.length === 0 ? null : wilcoxonSignedRank(before, after)
|
|
2632
|
-
};
|
|
2633
|
-
});
|
|
2634
|
-
return {
|
|
2635
|
-
nPairs: pairs.length,
|
|
2636
|
-
nUnpairedBaseline: unpairedBaseline.length,
|
|
2637
|
-
nUnpairedTreatment: unpairedTreatment.length,
|
|
2638
|
-
correctness,
|
|
2639
|
-
metricDeltas
|
|
2640
|
-
};
|
|
2641
|
-
}
|
|
2642
|
-
function metricValue(row, name) {
|
|
2643
|
-
const v = row.metrics?.[name];
|
|
2644
|
-
if (v === void 0) return void 0;
|
|
2645
|
-
if (!Number.isFinite(v)) {
|
|
2646
|
-
throw new ValidationError(
|
|
2647
|
-
`comparePairedArms: non-finite value for metric '${name}' on pairKey '${row.pairKey}' (arm '${row.arm}'): ${v}`
|
|
2648
|
-
);
|
|
2649
|
-
}
|
|
2650
|
-
return v;
|
|
2651
|
-
}
|
|
2652
|
-
|
|
2653
2911
|
// src/pr-review-benchmark.ts
|
|
2654
2912
|
var DEFAULT_PR_REVIEW_SCORE_WEIGHTS = {
|
|
2655
2913
|
recall: 4,
|
|
@@ -2714,12 +2972,12 @@ function summarizePrReviewBenchmark(scores2) {
|
|
|
2714
2972
|
source,
|
|
2715
2973
|
caseCount: sourceScores.length,
|
|
2716
2974
|
commentCount: sum(sourceScores.map((score) => score.commentCount)),
|
|
2717
|
-
aggregateMean:
|
|
2718
|
-
recallMean:
|
|
2719
|
-
precisionMean:
|
|
2720
|
-
actionabilityMean:
|
|
2721
|
-
severityCalibrationMean:
|
|
2722
|
-
lowNoiseMean:
|
|
2975
|
+
aggregateMean: mean2(sourceScores.map((score) => score.aggregate)),
|
|
2976
|
+
recallMean: mean2(sourceScores.map((score) => score.recall)),
|
|
2977
|
+
precisionMean: mean2(sourceScores.map((score) => score.precision)),
|
|
2978
|
+
actionabilityMean: mean2(sourceScores.map((score) => score.actionability)),
|
|
2979
|
+
severityCalibrationMean: mean2(sourceScores.map((score) => score.severityCalibration)),
|
|
2980
|
+
lowNoiseMean: mean2(sourceScores.map((score) => score.lowNoise))
|
|
2723
2981
|
})).sort((a, b) => b.aggregateMean - a.aggregateMean);
|
|
2724
2982
|
}
|
|
2725
2983
|
function aggregatePrReviewScore(dimensions, weights = {}) {
|
|
@@ -2815,7 +3073,7 @@ function normalizeTerm(input) {
|
|
|
2815
3073
|
function normalizePath(input) {
|
|
2816
3074
|
return input.replace(/^\.\/+/, "");
|
|
2817
3075
|
}
|
|
2818
|
-
function
|
|
3076
|
+
function mean2(values) {
|
|
2819
3077
|
return values.length ? sum(values) / values.length : 0;
|
|
2820
3078
|
}
|
|
2821
3079
|
function sum(values) {
|
|
@@ -3605,10 +3863,10 @@ function summarizeHarnessResults(results) {
|
|
|
3605
3863
|
return {
|
|
3606
3864
|
variant,
|
|
3607
3865
|
runs,
|
|
3608
|
-
aggregateMean:
|
|
3609
|
-
passRate:
|
|
3610
|
-
costUsdMean:
|
|
3611
|
-
wallSecondsMean:
|
|
3866
|
+
aggregateMean: mean3(runs.map((r) => r.aggregate)),
|
|
3867
|
+
passRate: mean3(runs.map((r) => r.score.success)),
|
|
3868
|
+
costUsdMean: mean3(runs.map((r) => r.score.costUsd)),
|
|
3869
|
+
wallSecondsMean: mean3(runs.map((r) => r.score.wallSeconds)),
|
|
3612
3870
|
scoreMean: meanRunScore(runs.map((r) => r.score))
|
|
3613
3871
|
};
|
|
3614
3872
|
}).sort((a, b) => b.aggregateMean - a.aggregateMean);
|
|
@@ -3645,22 +3903,22 @@ async function mapLimit(items, limit, fn) {
|
|
|
3645
3903
|
);
|
|
3646
3904
|
return results;
|
|
3647
3905
|
}
|
|
3648
|
-
function
|
|
3906
|
+
function mean3(values) {
|
|
3649
3907
|
return values.length ? values.reduce((sum4, value) => sum4 + value, 0) / values.length : 0;
|
|
3650
3908
|
}
|
|
3651
3909
|
function meanRunScore(scores2) {
|
|
3652
3910
|
return {
|
|
3653
|
-
success:
|
|
3654
|
-
goalProgress:
|
|
3655
|
-
repoGroundedness:
|
|
3656
|
-
driftPenalty:
|
|
3657
|
-
toolUseQuality:
|
|
3658
|
-
patchQuality:
|
|
3659
|
-
testReality:
|
|
3660
|
-
finalGate:
|
|
3661
|
-
reviewerBlockers:
|
|
3662
|
-
costUsd:
|
|
3663
|
-
wallSeconds:
|
|
3911
|
+
success: mean3(scores2.map((s) => s.success)),
|
|
3912
|
+
goalProgress: mean3(scores2.map((s) => s.goalProgress)),
|
|
3913
|
+
repoGroundedness: mean3(scores2.map((s) => s.repoGroundedness)),
|
|
3914
|
+
driftPenalty: mean3(scores2.map((s) => s.driftPenalty)),
|
|
3915
|
+
toolUseQuality: mean3(scores2.map((s) => s.toolUseQuality)),
|
|
3916
|
+
patchQuality: mean3(scores2.map((s) => s.patchQuality)),
|
|
3917
|
+
testReality: mean3(scores2.map((s) => s.testReality)),
|
|
3918
|
+
finalGate: mean3(scores2.map((s) => s.finalGate)),
|
|
3919
|
+
reviewerBlockers: mean3(scores2.map((s) => s.reviewerBlockers)),
|
|
3920
|
+
costUsd: mean3(scores2.map((s) => s.costUsd)),
|
|
3921
|
+
wallSeconds: mean3(scores2.map((s) => s.wallSeconds)),
|
|
3664
3922
|
notes: scores2.flatMap((s) => s.notes ?? [])
|
|
3665
3923
|
};
|
|
3666
3924
|
}
|
|
@@ -4865,9 +5123,9 @@ function median(sorted) {
|
|
|
4865
5123
|
const mid = Math.floor(n / 2);
|
|
4866
5124
|
return n % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
|
|
4867
5125
|
}
|
|
4868
|
-
function stddev(values,
|
|
5126
|
+
function stddev(values, mean7) {
|
|
4869
5127
|
if (values.length < 2) return 0;
|
|
4870
|
-
const variance = values.reduce((acc, v) => acc + (v -
|
|
5128
|
+
const variance = values.reduce((acc, v) => acc + (v - mean7) ** 2, 0) / values.length;
|
|
4871
5129
|
return Math.sqrt(variance);
|
|
4872
5130
|
}
|
|
4873
5131
|
function computeExperimentStats(reps, thresholds) {
|
|
@@ -4893,15 +5151,15 @@ function computeExperimentStats(reps, thresholds) {
|
|
|
4893
5151
|
return r.score;
|
|
4894
5152
|
});
|
|
4895
5153
|
const sorted = [...scores2].sort((a, b) => a - b);
|
|
4896
|
-
const
|
|
4897
|
-
const sd = stddev(scores2,
|
|
5154
|
+
const mean7 = scores2.reduce((s, v) => s + v, 0) / n;
|
|
5155
|
+
const sd = stddev(scores2, mean7);
|
|
4898
5156
|
const spread = iqr(scores2);
|
|
4899
5157
|
const rated = reps.filter((r) => typeof r.passed === "boolean");
|
|
4900
5158
|
const passRate = rated.length === 0 ? null : rated.filter((r) => r.passed).length / rated.length;
|
|
4901
5159
|
const stable = spread < t.iqrUnstableAbove && sd < t.stddevUnstableAbove;
|
|
4902
5160
|
return {
|
|
4903
5161
|
median: median(sorted),
|
|
4904
|
-
mean:
|
|
5162
|
+
mean: mean7,
|
|
4905
5163
|
min: sorted[0],
|
|
4906
5164
|
max: sorted[n - 1],
|
|
4907
5165
|
iqr: spread,
|
|
@@ -5072,7 +5330,7 @@ var ExperimentTracker = class {
|
|
|
5072
5330
|
};
|
|
5073
5331
|
|
|
5074
5332
|
// src/leaderboard.ts
|
|
5075
|
-
function
|
|
5333
|
+
function mean4(xs) {
|
|
5076
5334
|
return xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : null;
|
|
5077
5335
|
}
|
|
5078
5336
|
function leaderboard(records, opts) {
|
|
@@ -5099,10 +5357,10 @@ function leaderboard(records, opts) {
|
|
|
5099
5357
|
n: rs.length,
|
|
5100
5358
|
passRate: ci.estimate,
|
|
5101
5359
|
passRateCi95: [ci.lower, ci.upper],
|
|
5102
|
-
meanCostUsd:
|
|
5103
|
-
meanTokensIn:
|
|
5104
|
-
meanTokensOut:
|
|
5105
|
-
meanWallMs:
|
|
5360
|
+
meanCostUsd: mean4(rs.map((r) => r.costUsd)),
|
|
5361
|
+
meanTokensIn: mean4(rs.map((r) => r.tokenUsage.input)),
|
|
5362
|
+
meanTokensOut: mean4(rs.map((r) => r.tokenUsage.output)),
|
|
5363
|
+
meanWallMs: mean4(rs.map((r) => r.wallMs))
|
|
5106
5364
|
};
|
|
5107
5365
|
});
|
|
5108
5366
|
rows.sort(
|
|
@@ -6659,12 +6917,12 @@ async function paraphraseRobustness(prompt, mutators, scoreFn, options = {}) {
|
|
|
6659
6917
|
variantScores.push({ mutator: id, score, mutated });
|
|
6660
6918
|
all.push(score);
|
|
6661
6919
|
}
|
|
6662
|
-
const
|
|
6663
|
-
const variance = all.reduce((a, v) => a + (v -
|
|
6920
|
+
const mean7 = all.reduce((a, b) => a + b, 0) / all.length;
|
|
6921
|
+
const variance = all.reduce((a, v) => a + (v - mean7) ** 2, 0) / all.length;
|
|
6664
6922
|
const stdDev = Math.sqrt(variance);
|
|
6665
|
-
const ref = Math.abs(
|
|
6923
|
+
const ref = Math.abs(mean7) > 1e-9 ? Math.abs(mean7) : 1;
|
|
6666
6924
|
const robustness = Math.max(0, 1 - stdDev / ref);
|
|
6667
|
-
return { originalScore, variantScores, meanScore:
|
|
6925
|
+
return { originalScore, variantScores, meanScore: mean7, stdDev, robustness };
|
|
6668
6926
|
}
|
|
6669
6927
|
var lowercaseMutator = (p) => p.toLowerCase();
|
|
6670
6928
|
var sentenceReorderMutator = (p, seed) => {
|
|
@@ -6730,8 +6988,8 @@ async function paraphraseRobustnessScenarios(args) {
|
|
|
6730
6988
|
});
|
|
6731
6989
|
scores2.push(out.score);
|
|
6732
6990
|
}
|
|
6733
|
-
const
|
|
6734
|
-
deltas[m.name] =
|
|
6991
|
+
const mean7 = scores2.reduce((a, b) => a + b, 0) / scores2.length;
|
|
6992
|
+
deltas[m.name] = mean7 - originalScore;
|
|
6735
6993
|
paraphrasedAll.push(...scores2);
|
|
6736
6994
|
}
|
|
6737
6995
|
const paraphrasedMean = paraphrasedAll.length === 0 ? originalScore : paraphrasedAll.reduce((a, b) => a + b, 0) / paraphrasedAll.length;
|
|
@@ -7149,8 +7407,8 @@ async function proposeSynthesisTargets(dataset, traceStore, options = {}) {
|
|
|
7149
7407
|
const sRuns = runs.filter((r) => r.scenarioId === s.id);
|
|
7150
7408
|
const scores2 = sRuns.map((r) => r.outcome?.score).filter((x) => typeof x === "number");
|
|
7151
7409
|
if (scores2.length < 3) continue;
|
|
7152
|
-
const
|
|
7153
|
-
const variance = scores2.reduce((a, b) => a + (b -
|
|
7410
|
+
const mean7 = scores2.reduce((a, b) => a + b, 0) / scores2.length;
|
|
7411
|
+
const variance = scores2.reduce((a, b) => a + (b - mean7) ** 2, 0) / scores2.length;
|
|
7154
7412
|
if (variance > varianceThreshold) {
|
|
7155
7413
|
targets.push({
|
|
7156
7414
|
reason: "high-variance",
|
|
@@ -8666,7 +8924,7 @@ function decideReferenceReplayPromotion(baseline, candidate, policy = {}) {
|
|
|
8666
8924
|
regressions
|
|
8667
8925
|
};
|
|
8668
8926
|
}
|
|
8669
|
-
const requiredMeanDelta =
|
|
8927
|
+
const requiredMeanDelta = mean5(compared.map((item) => item.f1Delta));
|
|
8670
8928
|
if (requiredMeanDelta < minF1Delta) {
|
|
8671
8929
|
return {
|
|
8672
8930
|
promote: false,
|
|
@@ -8902,7 +9160,7 @@ function clamp013(value) {
|
|
|
8902
9160
|
function sum2(values) {
|
|
8903
9161
|
return values.reduce((acc, value) => acc + value, 0);
|
|
8904
9162
|
}
|
|
8905
|
-
function
|
|
9163
|
+
function mean5(values) {
|
|
8906
9164
|
return values.length ? sum2(values) / values.length : 0;
|
|
8907
9165
|
}
|
|
8908
9166
|
function formatPct(value) {
|
|
@@ -9356,10 +9614,10 @@ var HeldOutGate = class {
|
|
|
9356
9614
|
afterHoldout.push(run.outcome.holdoutScore);
|
|
9357
9615
|
}
|
|
9358
9616
|
const productiveRuns = beforeHoldout.length;
|
|
9359
|
-
const candidateSearchMean =
|
|
9360
|
-
const candidateHoldoutMean =
|
|
9361
|
-
const baselineSearchMean =
|
|
9362
|
-
const baselineHoldoutMean =
|
|
9617
|
+
const candidateSearchMean = mean6(scores(candidate, "searchScore", "search"));
|
|
9618
|
+
const candidateHoldoutMean = mean6(scores(candidate, "holdoutScore", "holdout"));
|
|
9619
|
+
const baselineSearchMean = mean6(scores(baseline, "searchScore", "search"));
|
|
9620
|
+
const baselineHoldoutMean = mean6(scores(baseline, "holdoutScore", "holdout"));
|
|
9363
9621
|
const overfitGap = safeDiff(candidateSearchMean, candidateHoldoutMean);
|
|
9364
9622
|
const baselineOverfitGap = safeDiff(baselineSearchMean, baselineHoldoutMean);
|
|
9365
9623
|
const medianCandidateCost = medianFinite(candidate.map((r) => r.costUsd));
|
|
@@ -9471,7 +9729,7 @@ function scores(runs, field, splitFilter) {
|
|
|
9471
9729
|
}
|
|
9472
9730
|
return out;
|
|
9473
9731
|
}
|
|
9474
|
-
function
|
|
9732
|
+
function mean6(xs) {
|
|
9475
9733
|
if (xs.length === 0) return Number.NaN;
|
|
9476
9734
|
return xs.reduce((s, x) => s + x, 0) / xs.length;
|
|
9477
9735
|
}
|
|
@@ -9511,9 +9769,9 @@ function passOrthogonality(input) {
|
|
|
9511
9769
|
sims.push(cosineSimilarity(vectors[i], vectors[j]));
|
|
9512
9770
|
}
|
|
9513
9771
|
}
|
|
9514
|
-
const
|
|
9772
|
+
const mean7 = sims.length === 0 ? 0 : sims.reduce((a, b) => a + b, 0) / sims.length;
|
|
9515
9773
|
return {
|
|
9516
|
-
orthogonality: Math.max(0, Math.min(1, 1 -
|
|
9774
|
+
orthogonality: Math.max(0, Math.min(1, 1 - mean7)),
|
|
9517
9775
|
passCount: passes.length,
|
|
9518
9776
|
similarities: sims
|
|
9519
9777
|
};
|
|
@@ -11530,6 +11788,7 @@ export {
|
|
|
11530
11788
|
classifyFailure,
|
|
11531
11789
|
classifyTreatment,
|
|
11532
11790
|
cliffsDelta,
|
|
11791
|
+
clusteredPairedBinary,
|
|
11533
11792
|
codeExecutionJudge,
|
|
11534
11793
|
cohensD,
|
|
11535
11794
|
coherenceJudge,
|
|
@@ -11668,6 +11927,7 @@ export {
|
|
|
11668
11927
|
hashScenarios,
|
|
11669
11928
|
hashToUnit,
|
|
11670
11929
|
hiddenGrade,
|
|
11930
|
+
holm,
|
|
11671
11931
|
htmlContainsElement,
|
|
11672
11932
|
httpGithubClient,
|
|
11673
11933
|
improvementVerdict,
|