@tangle-network/agent-eval 0.93.0 → 0.94.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.
Files changed (121) hide show
  1. package/dist/adapters/otel.d.ts +4 -4
  2. package/dist/analyst/index.d.ts +10 -10
  3. package/dist/analyst/index.js +6 -6
  4. package/dist/{analyze-runs-DwCEkpO_.d.ts → analyze-runs-B6Ljo_dI.d.ts} +2 -2
  5. package/dist/{baseline-DE36-Np7.d.ts → baseline-Bbid3WoO.d.ts} +1 -1
  6. package/dist/belief-state/index.d.ts +2 -2
  7. package/dist/belief-state/index.js +1 -1
  8. package/dist/builder-eval/index.d.ts +3 -3
  9. package/dist/builder-eval/index.js +2 -2
  10. package/dist/{calibration-Cpr3WaX3.d.ts → calibration-BPmzuVPk.d.ts} +1 -1
  11. package/dist/campaign/index.d.ts +13 -13
  12. package/dist/campaign/index.js +8 -8
  13. package/dist/{chunk-TWS7AZEY.js → chunk-2K6UUZ7P.js} +2 -2
  14. package/dist/{chunk-Y47J2LJ3.js → chunk-2KNZHH3P.js} +5 -5
  15. package/dist/{chunk-LMZQ2Z4U.js → chunk-56GC6VYO.js} +126 -1
  16. package/dist/chunk-56GC6VYO.js.map +1 -0
  17. package/dist/{chunk-QG2OVF2D.js → chunk-CTBHKLEU.js} +99 -30
  18. package/dist/chunk-CTBHKLEU.js.map +1 -0
  19. package/dist/{chunk-CVVHBFGN.js → chunk-CWNP4DV4.js} +53 -5
  20. package/dist/chunk-CWNP4DV4.js.map +1 -0
  21. package/dist/{chunk-QS3RBQPI.js → chunk-D5KBVULY.js} +2 -2
  22. package/dist/{chunk-ZFIBGEOL.js → chunk-EGPMSBEZ.js} +4 -4
  23. package/dist/{chunk-GSH6QNNS.js → chunk-KW53MSA5.js} +101 -78
  24. package/dist/chunk-KW53MSA5.js.map +1 -0
  25. package/dist/{chunk-UMMZHCPB.js → chunk-MIFZUPEK.js} +7 -5
  26. package/dist/chunk-MIFZUPEK.js.map +1 -0
  27. package/dist/{chunk-XY4DDNEG.js → chunk-MPQWFX6Y.js} +2 -2
  28. package/dist/{chunk-L3JOU6XM.js → chunk-NACM5RS7.js} +3 -3
  29. package/dist/{chunk-D3V5B42D.js → chunk-Q5LIB7BC.js} +7 -4
  30. package/dist/{chunk-D3V5B42D.js.map → chunk-Q5LIB7BC.js.map} +1 -1
  31. package/dist/{chunk-QAY5UIJO.js → chunk-QMUEXQJS.js} +99 -57
  32. package/dist/chunk-QMUEXQJS.js.map +1 -0
  33. package/dist/{chunk-4FBZZIYD.js → chunk-QTMYW64F.js} +2 -2
  34. package/dist/{chunk-6SOJM3VR.js → chunk-SD2YFWQQ.js} +4 -4
  35. package/dist/{chunk-UHMJT4T7.js → chunk-TBDR6PAI.js} +2 -2
  36. package/dist/{chunk-47X6LRCE.js → chunk-UFSG7ACU.js} +10 -7
  37. package/dist/chunk-UFSG7ACU.js.map +1 -0
  38. package/dist/{chunk-CY6U5S3X.js → chunk-URWVKRCS.js} +2 -2
  39. package/dist/{chunk-T375SUOZ.js → chunk-ZOPLCJSY.js} +86 -31
  40. package/dist/chunk-ZOPLCJSY.js.map +1 -0
  41. package/dist/cli.js +2 -2
  42. package/dist/contract/index.d.ts +17 -17
  43. package/dist/contract/index.js +11 -11
  44. package/dist/{control-_Qb7skHX.d.ts → control-D6qwHXIR.d.ts} +4 -4
  45. package/dist/{control-runtime-DuFBYg7A.d.ts → control-runtime-Acf9CGhw.d.ts} +2 -2
  46. package/dist/control.d.ts +5 -5
  47. package/dist/{corpus-BoR-041R.d.ts → corpus-B8A4BDR3.d.ts} +1 -1
  48. package/dist/{counterfactual-Dwibr5IW.d.ts → counterfactual-DlOz8PBx.d.ts} +3 -3
  49. package/dist/{default-registry-zoGHUQEH.d.ts → default-registry-6dhErQbs.d.ts} +2 -2
  50. package/dist/diagnose.d.ts +9 -9
  51. package/dist/diagnose.js +1 -1
  52. package/dist/{emitter-DEZwY14K.d.ts → emitter-C2rqGH_l.d.ts} +1 -1
  53. package/dist/{failure-cluster-CL7IVgkJ.d.ts → failure-cluster-DH9Flgcf.d.ts} +1 -1
  54. package/dist/{feedback-trajectory-D9OVLrg9.d.ts → feedback-trajectory-BxY0cKfs.d.ts} +1 -1
  55. package/dist/governance/index.d.ts +2 -2
  56. package/dist/{harness-optimizer-EnEnQPsr.d.ts → harness-optimizer-mOl9XX_O.d.ts} +1 -1
  57. package/dist/hosted/index.d.ts +4 -4
  58. package/dist/index.d.ts +68 -46
  59. package/dist/index.js +261 -87
  60. package/dist/index.js.map +1 -1
  61. package/dist/{insight-report-BBwvOh6x.d.ts → insight-report-DWl3z9tl.d.ts} +1 -1
  62. package/dist/{integrity-VJ9A7aST.d.ts → integrity-D2t12mMw.d.ts} +1 -1
  63. package/dist/{kind-factory-5b7xXXOr.d.ts → kind-factory-0BhLSI27.d.ts} +1 -1
  64. package/dist/knowledge/index.d.ts +3 -3
  65. package/dist/{llm-client-BeEcAokY.d.ts → llm-client-Bj7g0rqu.d.ts} +31 -0
  66. package/dist/meta-eval/index.d.ts +4 -4
  67. package/dist/meta-eval/index.js +1 -1
  68. package/dist/openapi.json +1 -1
  69. package/dist/pipelines/index.d.ts +6 -6
  70. package/dist/pipelines/index.js +40 -15
  71. package/dist/pipelines/index.js.map +1 -1
  72. package/dist/prm/index.d.ts +11 -7
  73. package/dist/prm/index.js +55 -12
  74. package/dist/prm/index.js.map +1 -1
  75. package/dist/{provenance-LnqRT0sS.d.ts → provenance-P-bCL2Fo.d.ts} +3 -3
  76. package/dist/{query-CqTxMwDw.d.ts → query-B7GGjRox.d.ts} +2 -1
  77. package/dist/{red-team-BXHil6c8.d.ts → red-team-BWdoyleI.d.ts} +1 -1
  78. package/dist/{release-report-euXIV_Sk.d.ts → release-report-BEbWmVYj.d.ts} +1 -1
  79. package/dist/reporting.d.ts +6 -6
  80. package/dist/reporting.js +3 -3
  81. package/dist/{researcher-DE6Gpnb4.d.ts → researcher-B0C2_fVO.d.ts} +5 -5
  82. package/dist/rl.d.ts +10 -10
  83. package/dist/rl.js +4 -4
  84. package/dist/{rubric-BOfxn4ja.d.ts → rubric-Cc6UHvUb.d.ts} +2 -2
  85. package/dist/{run-campaign-RDGAM5KJ.js → run-campaign-7WNXMDSN.js} +3 -3
  86. package/dist/{run-critic-BAIjX99r.d.ts → run-critic-CmMf05uV.d.ts} +1 -1
  87. package/dist/{run-improvement-loop-5z_l5zDz.d.ts → run-improvement-loop-DBahB8Ax.d.ts} +1 -1
  88. package/dist/{semantic-concept-judge-Dn8Z6KEG.d.ts → semantic-concept-judge-B9MgmBnM.d.ts} +3 -3
  89. package/dist/{statistics-C7PozGrZ.d.ts → statistics-CCJpTGOS.d.ts} +117 -2
  90. package/dist/{store-CKUAgsJz.d.ts → store-BcFXE6LG.d.ts} +16 -1
  91. package/dist/{summary-report-DGmUucwQ.d.ts → summary-report-BDOFevaT.d.ts} +1 -1
  92. package/dist/{test-graded-scenario-BdVaPyHT.d.ts → test-graded-scenario-DeODGLra.d.ts} +21 -2
  93. package/dist/traces.d.ts +19 -6
  94. package/dist/traces.js +4 -4
  95. package/dist/{trajectory-GEdXJCL5.d.ts → trajectory-2TkpSEVh.d.ts} +1 -1
  96. package/dist/{types-Croy5h7V.d.ts → types-C7DGg5ex.d.ts} +2 -0
  97. package/dist/{types-2VVIL04s.d.ts → types-Ce17tDlG.d.ts} +2 -2
  98. package/dist/wire/index.d.ts +4 -4
  99. package/dist/wire/index.js +2 -2
  100. package/dist/workflow/index.d.ts +13 -13
  101. package/dist/workflow/index.js +1 -1
  102. package/package.json +1 -1
  103. package/dist/chunk-47X6LRCE.js.map +0 -1
  104. package/dist/chunk-CVVHBFGN.js.map +0 -1
  105. package/dist/chunk-GSH6QNNS.js.map +0 -1
  106. package/dist/chunk-LMZQ2Z4U.js.map +0 -1
  107. package/dist/chunk-QAY5UIJO.js.map +0 -1
  108. package/dist/chunk-QG2OVF2D.js.map +0 -1
  109. package/dist/chunk-T375SUOZ.js.map +0 -1
  110. package/dist/chunk-UMMZHCPB.js.map +0 -1
  111. /package/dist/{chunk-TWS7AZEY.js.map → chunk-2K6UUZ7P.js.map} +0 -0
  112. /package/dist/{chunk-Y47J2LJ3.js.map → chunk-2KNZHH3P.js.map} +0 -0
  113. /package/dist/{chunk-QS3RBQPI.js.map → chunk-D5KBVULY.js.map} +0 -0
  114. /package/dist/{chunk-ZFIBGEOL.js.map → chunk-EGPMSBEZ.js.map} +0 -0
  115. /package/dist/{chunk-XY4DDNEG.js.map → chunk-MPQWFX6Y.js.map} +0 -0
  116. /package/dist/{chunk-L3JOU6XM.js.map → chunk-NACM5RS7.js.map} +0 -0
  117. /package/dist/{chunk-4FBZZIYD.js.map → chunk-QTMYW64F.js.map} +0 -0
  118. /package/dist/{chunk-6SOJM3VR.js.map → chunk-SD2YFWQQ.js.map} +0 -0
  119. /package/dist/{chunk-UHMJT4T7.js.map → chunk-TBDR6PAI.js.map} +0 -0
  120. /package/dist/{chunk-CY6U5S3X.js.map → chunk-URWVKRCS.js.map} +0 -0
  121. /package/dist/{run-campaign-RDGAM5KJ.js.map → run-campaign-7WNXMDSN.js.map} +0 -0
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  checkBehavioralCanary,
10
10
  checkCanaries,
11
11
  runBehavioralCanaries
12
- } from "./chunk-Y47J2LJ3.js";
12
+ } from "./chunk-2KNZHH3P.js";
13
13
  import {
14
14
  classifyEuAiRisk,
15
15
  euAiActReport,
@@ -65,12 +65,12 @@ import {
65
65
  scoreRedTeamOutput,
66
66
  surfaceContentHash,
67
67
  toolNamesForRun
68
- } from "./chunk-ZFIBGEOL.js";
68
+ } from "./chunk-EGPMSBEZ.js";
69
69
  import {
70
70
  BackendIntegrityError,
71
71
  assertRealBackend,
72
72
  summarizeBackendIntegrity
73
- } from "./chunk-TWS7AZEY.js";
73
+ } from "./chunk-2K6UUZ7P.js";
74
74
  import {
75
75
  MODEL_PRICING,
76
76
  MetricsCollector,
@@ -92,7 +92,7 @@ import {
92
92
  computeToolUseMetrics,
93
93
  iqr,
94
94
  welchsTTest
95
- } from "./chunk-L3JOU6XM.js";
95
+ } from "./chunk-NACM5RS7.js";
96
96
  import {
97
97
  analyzeSeries
98
98
  } from "./chunk-BOD4O7OF.js";
@@ -109,7 +109,7 @@ import {
109
109
  pytestTestParser,
110
110
  runTestGradedScenario,
111
111
  vitestTestParser
112
- } from "./chunk-T375SUOZ.js";
112
+ } from "./chunk-ZOPLCJSY.js";
113
113
  import {
114
114
  DEFAULT_COMPLEXITY_WEIGHTS,
115
115
  DEFAULT_RUN_SCORE_WEIGHTS,
@@ -129,11 +129,11 @@ import {
129
129
  diffFindings,
130
130
  resetLockedAppendersForTesting,
131
131
  runSemanticConceptJudge
132
- } from "./chunk-XY4DDNEG.js";
132
+ } from "./chunk-MPQWFX6Y.js";
133
133
  import {
134
134
  buildDefaultAnalystRegistry,
135
135
  computeTraceMetrics
136
- } from "./chunk-UMMZHCPB.js";
136
+ } from "./chunk-MIFZUPEK.js";
137
137
  import {
138
138
  AnalystRegistry,
139
139
  DEFAULT_TRACE_ANALYST_KINDS,
@@ -143,7 +143,7 @@ import {
143
143
  KNOWLEDGE_POISONING_KIND_SPEC,
144
144
  createTraceAnalystKind,
145
145
  renderPriorFindings
146
- } from "./chunk-D3V5B42D.js";
146
+ } from "./chunk-Q5LIB7BC.js";
147
147
  import {
148
148
  controlFailureClassFromVerification,
149
149
  controlRunToRunRecord,
@@ -173,10 +173,10 @@ import {
173
173
  evaluateReleaseConfidence,
174
174
  judgeReplayGate,
175
175
  renderReleaseReport
176
- } from "./chunk-4FBZZIYD.js";
176
+ } from "./chunk-QTMYW64F.js";
177
177
  import {
178
178
  runEvalCampaign
179
- } from "./chunk-GSH6QNNS.js";
179
+ } from "./chunk-KW53MSA5.js";
180
180
  import {
181
181
  LlmCallError,
182
182
  LlmClient,
@@ -188,7 +188,7 @@ import {
188
188
  isTransientLlmError,
189
189
  probeLlm,
190
190
  stripFencedJson
191
- } from "./chunk-CVVHBFGN.js";
191
+ } from "./chunk-CWNP4DV4.js";
192
192
  import {
193
193
  evaluateInterimReleaseConfidence,
194
194
  pairedEvalueSequence
@@ -199,7 +199,7 @@ import {
199
199
  paretoChart,
200
200
  researchReport,
201
201
  summaryTable
202
- } from "./chunk-CY6U5S3X.js";
202
+ } from "./chunk-URWVKRCS.js";
203
203
  import {
204
204
  attributeCounterfactuals,
205
205
  runCounterfactual
@@ -226,20 +226,26 @@ import {
226
226
  interRaterReliability,
227
227
  interpretCliffs,
228
228
  mannWhitneyU,
229
+ mcnemar,
230
+ mcnemarPower,
231
+ mcnemarRequiredN,
229
232
  mulberry32,
230
233
  normalizeScores,
231
234
  pairedBootstrap,
232
235
  pairedMde,
236
+ pairedRiskDifference,
233
237
  pairedTTest,
234
238
  partialCredit,
239
+ passAtK,
235
240
  positionalBias,
236
241
  requiredSampleSize,
237
242
  selfPreference,
238
243
  verbosityBias,
239
244
  weightedComposite,
240
245
  weightedMean,
241
- wilcoxonSignedRank
242
- } from "./chunk-LMZQ2Z4U.js";
246
+ wilcoxonSignedRank,
247
+ wilson
248
+ } from "./chunk-56GC6VYO.js";
243
249
  import {
244
250
  FileSystemTraceStore,
245
251
  InMemoryTraceStore,
@@ -270,7 +276,7 @@ import {
270
276
  scoreTraceInsightReadiness,
271
277
  tokenizeDomainWords,
272
278
  traceAnalystOnRunComplete
273
- } from "./chunk-QG2OVF2D.js";
279
+ } from "./chunk-CTBHKLEU.js";
274
280
  import {
275
281
  DEFAULT_REDACTION_RULES,
276
282
  REDACTION_VERSION,
@@ -286,7 +292,7 @@ import {
286
292
  runFailureClass,
287
293
  runsForScenario,
288
294
  toolSpans
289
- } from "./chunk-47X6LRCE.js";
295
+ } from "./chunk-UFSG7ACU.js";
290
296
  import {
291
297
  FAILURE_CLASSES,
292
298
  TRACE_SCHEMA_VERSION,
@@ -301,7 +307,7 @@ import {
301
307
  TRACE_ANALYST_ACTOR_DESCRIPTION_VERSION,
302
308
  TRACE_ANALYST_SUBAGENT_DESCRIPTION,
303
309
  analyzeTraces
304
- } from "./chunk-UHMJT4T7.js";
310
+ } from "./chunk-TBDR6PAI.js";
305
311
  import {
306
312
  DEFAULT_TRACE_ANALYST_BUDGETS,
307
313
  OtlpFileTraceStore,
@@ -320,7 +326,7 @@ import {
320
326
  readOtlpStatus,
321
327
  stringField,
322
328
  traceAnalystFunctionGroup
323
- } from "./chunk-QAY5UIJO.js";
329
+ } from "./chunk-QMUEXQJS.js";
324
330
  import {
325
331
  RunIntegrityError,
326
332
  assertRunCaptured,
@@ -887,6 +893,14 @@ function parseJudgeResponse(judgeName, resp) {
887
893
  }
888
894
 
889
895
  // src/executor.ts
896
+ function describeShape(content, message) {
897
+ if (message === void 0 || message === null) return "no choices[0].message";
898
+ return `message.content of type ${content === null ? "null" : typeof content}`;
899
+ }
900
+ function errMessage(err) {
901
+ if (err instanceof Error) return `${err.name}: ${err.message}`;
902
+ return String(err);
903
+ }
890
904
  async function executeScenario(tc, scenario, config) {
891
905
  const startTime = Date.now();
892
906
  const model = config.model ?? "gpt-4o";
@@ -907,7 +921,14 @@ async function executeScenario(tc, scenario, config) {
907
921
  temperature: 0.4,
908
922
  maxTokens: 3e3
909
923
  });
910
- const content = resp.choices?.[0]?.message?.content ?? "";
924
+ const message = resp.choices?.[0]?.message;
925
+ const rawContent = message?.content;
926
+ if (message === void 0 || message === null || typeof rawContent !== "string") {
927
+ throw new CaptureIntegrityError(
928
+ `chat response for scenario "${scenario.id}" turn ${i} is malformed: expected choices[0].message.content to be a string, got ${describeShape(rawContent, message)}`
929
+ );
930
+ }
931
+ const content = rawContent;
911
932
  messages.push({ role: "assistant", content });
912
933
  const codeRe = /```(\w+)?\n([\s\S]*?)```/g;
913
934
  let codeMatch = codeRe.exec(content);
@@ -988,26 +1009,44 @@ async function executeScenario(tc, scenario, config) {
988
1009
  const judgeInput = { scenario, turns, artifacts };
989
1010
  const judgeResults = [];
990
1011
  let failedJudges = 0;
991
- for (const judge of config.judges) {
1012
+ const judgeFailures = [];
1013
+ const sleep2 = config.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
1014
+ for (let j = 0; j < config.judges.length; j++) {
1015
+ const judge = config.judges[j];
1016
+ const judgeName = judge.name || `judge[${j}]`;
1017
+ let lastError;
1018
+ let madeAttempts = 0;
992
1019
  for (let attempt = 0; attempt < 3; attempt++) {
1020
+ madeAttempts = attempt + 1;
993
1021
  try {
994
1022
  if (attempt > 0) {
995
1023
  const wait = attempt * 1e4;
996
- console.log(` judge retry ${attempt}/2 (waiting ${wait / 1e3}s)`);
997
- await new Promise((r) => setTimeout(r, wait));
1024
+ console.log(` ${judgeName} retry ${attempt}/2 (waiting ${wait / 1e3}s)`);
1025
+ await sleep2(wait);
998
1026
  }
999
1027
  const scores2 = await judge(tc, judgeInput);
1000
1028
  judgeResults.push(scores2);
1001
- await new Promise((r) => setTimeout(r, 3e3));
1029
+ await sleep2(3e3);
1030
+ lastError = void 0;
1002
1031
  break;
1003
1032
  } catch (err) {
1033
+ lastError = err;
1004
1034
  if (err instanceof JudgeParseError) {
1005
- failedJudges++;
1035
+ console.error(` ${judgeName} unparseable (no retry): ${errMessage(err)}`);
1006
1036
  break;
1007
1037
  }
1008
- if (attempt === 2) failedJudges++;
1038
+ console.error(` ${judgeName} attempt ${attempt} failed: ${errMessage(err)}`);
1039
+ if (!isTransientLlmError(err)) break;
1009
1040
  }
1010
1041
  }
1042
+ if (lastError !== void 0) {
1043
+ failedJudges++;
1044
+ judgeFailures.push({
1045
+ judge: judgeName,
1046
+ attempts: madeAttempts,
1047
+ reason: errMessage(lastError)
1048
+ });
1049
+ }
1011
1050
  }
1012
1051
  const allScores = judgeResults.flat();
1013
1052
  const errorScores = allScores.filter(
@@ -1027,7 +1066,7 @@ async function executeScenario(tc, scenario, config) {
1027
1066
  weight: weightMap.get(s.dimension) ?? 1
1028
1067
  }))
1029
1068
  );
1030
- return {
1069
+ const result = {
1031
1070
  scenarioId: scenario.id,
1032
1071
  persona: scenario.persona,
1033
1072
  turns,
@@ -1038,6 +1077,8 @@ async function executeScenario(tc, scenario, config) {
1038
1077
  totalDurationMs: Date.now() - startTime,
1039
1078
  artifacts
1040
1079
  };
1080
+ if (judgeFailures.length > 0) result.judgeFailures = judgeFailures;
1081
+ return result;
1041
1082
  }
1042
1083
 
1043
1084
  // src/benchmark.ts
@@ -1174,19 +1215,67 @@ var BenchmarkRunner = class {
1174
1215
  };
1175
1216
 
1176
1217
  // src/client.ts
1218
+ var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
1177
1219
  var ProductClient = class {
1178
1220
  baseUrl;
1179
1221
  routes;
1180
1222
  cookies = "";
1223
+ timeoutMs;
1181
1224
  constructor(config) {
1182
1225
  this.baseUrl = config.baseUrl.replace(/\/+$/, "");
1183
1226
  this.routes = config.routes;
1227
+ this.timeoutMs = config.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
1184
1228
  }
1185
1229
  route(name) {
1186
1230
  const path = this.routes[name];
1187
1231
  if (!path) throw new Error(`Route "${name}" not configured`);
1188
1232
  return path;
1189
1233
  }
1234
+ /**
1235
+ * Single HTTP boundary for every JSON request. Aborts after `timeoutMs`,
1236
+ * checks `res.ok` BEFORE parsing, and throws `${method} ${path} failed:
1237
+ * HTTP ${status} — ${body}` on a non-ok response so a 4xx/5xx error body
1238
+ * can never be parsed as a success shape. Callers inspect the resolved
1239
+ * value only after a successful return.
1240
+ */
1241
+ async request(method, path, body) {
1242
+ const controller = new AbortController();
1243
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
1244
+ let res;
1245
+ try {
1246
+ res = await fetch(`${this.baseUrl}${path}`, {
1247
+ method,
1248
+ headers: {
1249
+ ...body ? { "Content-Type": "application/json" } : {},
1250
+ Origin: this.baseUrl,
1251
+ Cookie: this.cookies
1252
+ },
1253
+ ...body ? { body: JSON.stringify(body) } : {},
1254
+ signal: controller.signal
1255
+ });
1256
+ } finally {
1257
+ clearTimeout(timeout);
1258
+ }
1259
+ if (!res.ok) {
1260
+ const text = await res.text().catch(() => "");
1261
+ throw new Error(`${method} ${path} failed: HTTP ${res.status} \u2014 ${text.slice(0, 500)}`);
1262
+ }
1263
+ return res.json();
1264
+ }
1265
+ /**
1266
+ * Read a required collection field. A missing/non-array field is a contract
1267
+ * violation (wrong route, drift, partial body) — surface it loud instead of
1268
+ * masking it as a healthy empty set. A genuinely empty `[]` passes through.
1269
+ */
1270
+ requireArray(res, field) {
1271
+ const value = res[field];
1272
+ if (!Array.isArray(value)) {
1273
+ throw new Error(
1274
+ `Response missing array field "${field}" (got ${typeof value}: ${JSON.stringify(value)?.slice(0, 200)})`
1275
+ );
1276
+ }
1277
+ return value;
1278
+ }
1190
1279
  async signup(name, email, password) {
1191
1280
  const res = await this.post(this.route("signup"), { name, email, password });
1192
1281
  const user = res.user;
@@ -1267,15 +1356,21 @@ var ProductClient = class {
1267
1356
  }
1268
1357
  async getTasks(workspaceId) {
1269
1358
  const res = await this.get(`${this.route("tasks")}?workspaceId=${workspaceId}`);
1270
- return res.tasks ?? [];
1359
+ return this.requireArray(
1360
+ res,
1361
+ "tasks"
1362
+ );
1271
1363
  }
1272
1364
  async getEvents(workspaceId) {
1273
1365
  const res = await this.get(`${this.route("events")}?workspaceId=${workspaceId}`);
1274
- return res.events ?? [];
1366
+ return this.requireArray(res, "events");
1275
1367
  }
1276
1368
  async getApprovals(workspaceId) {
1277
1369
  const res = await this.get(`${this.route("approvals")}?workspaceId=${workspaceId}`);
1278
- return res.actions ?? [];
1370
+ return this.requireArray(
1371
+ res,
1372
+ "actions"
1373
+ );
1279
1374
  }
1280
1375
  async getVaultTree(workspaceId) {
1281
1376
  const res = await this.get(`${this.route("vault")}?workspaceId=${workspaceId}`);
@@ -1287,7 +1382,7 @@ var ProductClient = class {
1287
1382
  if (node.children) extract(node.children);
1288
1383
  }
1289
1384
  }
1290
- extract(res.tree ?? []);
1385
+ extract(this.requireArray(res, "tree"));
1291
1386
  return paths;
1292
1387
  }
1293
1388
  async approveAction(workspaceId, id) {
@@ -1298,40 +1393,19 @@ var ProductClient = class {
1298
1393
  }
1299
1394
  async getGenerations(workspaceId) {
1300
1395
  const res = await this.get(`${this.route("generations")}?workspaceId=${workspaceId}`);
1301
- return res.generations ?? [];
1396
+ return this.requireArray(res, "generations");
1302
1397
  }
1303
1398
  /** Generic GET for custom routes */
1304
1399
  async get(path) {
1305
- const res = await fetch(`${this.baseUrl}${path}`, {
1306
- headers: { Cookie: this.cookies }
1307
- });
1308
- return res.json();
1400
+ return this.request("GET", path);
1309
1401
  }
1310
1402
  /** Generic POST for custom routes */
1311
1403
  async post(path, body) {
1312
- const res = await fetch(`${this.baseUrl}${path}`, {
1313
- method: "POST",
1314
- headers: {
1315
- "Content-Type": "application/json",
1316
- Origin: this.baseUrl,
1317
- Cookie: this.cookies
1318
- },
1319
- body: JSON.stringify(body)
1320
- });
1321
- return res.json();
1404
+ return this.request("POST", path, body);
1322
1405
  }
1323
1406
  /** Generic PATCH for custom routes */
1324
1407
  async patch(path, body) {
1325
- const res = await fetch(`${this.baseUrl}${path}`, {
1326
- method: "PATCH",
1327
- headers: {
1328
- "Content-Type": "application/json",
1329
- Origin: this.baseUrl,
1330
- Cookie: this.cookies
1331
- },
1332
- body: JSON.stringify(body)
1333
- });
1334
- return res.json();
1408
+ return this.request("PATCH", path, body);
1335
1409
  }
1336
1410
  };
1337
1411
  async function runE2EWorkflow(client, name, workflow) {
@@ -3525,6 +3599,7 @@ function ensembleJudge(opts) {
3525
3599
  }
3526
3600
 
3527
3601
  // src/judge-runner.ts
3602
+ import { cpus } from "os";
3528
3603
  var JudgeRunner = class {
3529
3604
  driver;
3530
3605
  constructor(driver = new SubprocessSandboxDriver()) {
@@ -3554,11 +3629,22 @@ var JudgeRunner = class {
3554
3629
  async function runJudgeFleet(specs, options = {}) {
3555
3630
  const runner = new JudgeRunner(options.driver);
3556
3631
  if (options.parallel === false) {
3557
- const results = [];
3558
- for (const spec of specs) results.push(await runner.run(spec));
3559
- return results;
3632
+ const results2 = [];
3633
+ for (const spec of specs) results2.push(await runner.run(spec));
3634
+ return results2;
3635
+ }
3636
+ const concurrency = Math.max(1, options.concurrency ?? cpus().length);
3637
+ const results = new Array(specs.length);
3638
+ let cursor = 0;
3639
+ async function worker() {
3640
+ while (true) {
3641
+ const i = cursor++;
3642
+ if (i >= specs.length) return;
3643
+ results[i] = await runner.run(specs[i]);
3644
+ }
3560
3645
  }
3561
- return await Promise.all(specs.map((spec) => runner.run(spec)));
3646
+ await Promise.all(Array.from({ length: Math.min(concurrency, specs.length) }, () => worker()));
3647
+ return results;
3562
3648
  }
3563
3649
  function compilerJudge(id, config) {
3564
3650
  return { id, kind: "compiler", config };
@@ -6821,8 +6907,15 @@ async function runSelfPlay(proposer, scorer, targets, options = {}) {
6821
6907
 
6822
6908
  // src/command-runner.ts
6823
6909
  import { spawnSync } from "child_process";
6824
- import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
6825
- import { join as join2 } from "path";
6910
+ import {
6911
+ accessSync,
6912
+ existsSync as existsSync3,
6913
+ constants as fsConstants,
6914
+ readdirSync as readdirSync2,
6915
+ readFileSync as readFileSync3,
6916
+ statSync as statSync2
6917
+ } from "fs";
6918
+ import { delimiter, join as join2 } from "path";
6826
6919
  var localCommandRunner = {
6827
6920
  name: "local",
6828
6921
  async run(input) {
@@ -6846,8 +6939,7 @@ var localCommandRunner = {
6846
6939
  };
6847
6940
  },
6848
6941
  async hasBin(name) {
6849
- const r = spawnSync("which", [name], { encoding: "utf8", timeout: 2e3 });
6850
- return r.status === 0 && (r.stdout ?? "").trim().length > 0;
6942
+ return resolveBinOnPath(name) !== null;
6851
6943
  },
6852
6944
  async fileExists(path) {
6853
6945
  return existsSync3(path);
@@ -6855,16 +6947,18 @@ var localCommandRunner = {
6855
6947
  async readFile(path) {
6856
6948
  try {
6857
6949
  return readFileSync3(path, "utf8");
6858
- } catch {
6859
- return null;
6950
+ } catch (err) {
6951
+ if (isErrnoCode(err, "ENOENT")) return null;
6952
+ throw err;
6860
6953
  }
6861
6954
  },
6862
6955
  async readDir(path) {
6863
6956
  let entries;
6864
6957
  try {
6865
6958
  entries = readdirSync2(path);
6866
- } catch {
6867
- return [];
6959
+ } catch (err) {
6960
+ if (isErrnoCode(err, "ENOENT")) return [];
6961
+ throw err;
6868
6962
  }
6869
6963
  const out = [];
6870
6964
  for (const name of entries) {
@@ -6876,12 +6970,43 @@ var localCommandRunner = {
6876
6970
  isFile: st.isFile(),
6877
6971
  sizeBytes: st.isFile() ? st.size : null
6878
6972
  });
6879
- } catch {
6973
+ } catch (err) {
6974
+ if (isErrnoCode(err, "ENOENT")) continue;
6975
+ throw err;
6880
6976
  }
6881
6977
  }
6882
6978
  return out;
6883
6979
  }
6884
6980
  };
6981
+ function isErrnoCode(err, code) {
6982
+ return typeof err === "object" && err !== null && err.code === code;
6983
+ }
6984
+ function resolveBinOnPath(name) {
6985
+ if (name.includes("/") || name.includes("\\")) {
6986
+ return isExecutable(name) ? name : null;
6987
+ }
6988
+ const pathEnv = process.env.PATH ?? "";
6989
+ const dirs = pathEnv.split(delimiter).filter((d) => d.length > 0);
6990
+ const exts = process.platform === "win32" ? (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter((e) => e.length > 0) : [""];
6991
+ for (const dir of dirs) {
6992
+ for (const ext of exts) {
6993
+ const candidate = join2(dir, name + ext);
6994
+ if (isExecutable(candidate)) return candidate;
6995
+ }
6996
+ }
6997
+ return null;
6998
+ }
6999
+ function isExecutable(path) {
7000
+ try {
7001
+ accessSync(path, process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK);
7002
+ return true;
7003
+ } catch (err) {
7004
+ if (isErrnoCode(err, "ENOENT") || isErrnoCode(err, "EACCES") || isErrnoCode(err, "ENOTDIR")) {
7005
+ return false;
7006
+ }
7007
+ throw err;
7008
+ }
7009
+ }
6885
7010
 
6886
7011
  // src/deploy-gate-layer.ts
6887
7012
  function deployGateLayer(input) {
@@ -8997,8 +9122,10 @@ function createSandboxPool(opts) {
8997
9122
  const waiters = [];
8998
9123
  const mutex = new Mutex();
8999
9124
  let nextSlotId = 0;
9125
+ let reserving = 0;
9000
9126
  let totalCheckouts = 0;
9001
9127
  let busyMs = 0;
9128
+ let drained = false;
9002
9129
  const startedAt = Date.now();
9003
9130
  async function acquireSlot() {
9004
9131
  let mintId;
@@ -9008,42 +9135,81 @@ function createSandboxPool(opts) {
9008
9135
  idle.busy = true;
9009
9136
  return idle;
9010
9137
  }
9011
- if (slots.length < opts.size) {
9138
+ if (slots.length + reserving < opts.size) {
9012
9139
  mintId = `slot_${nextSlotId++}`;
9140
+ reserving++;
9013
9141
  return null;
9014
9142
  }
9015
9143
  return null;
9016
9144
  });
9017
9145
  if (ready) return ready;
9018
9146
  if (mintId !== void 0) {
9019
- const resource = await opts.factory.create(mintId);
9147
+ let resource;
9148
+ try {
9149
+ resource = await opts.factory.create(mintId);
9150
+ } catch (err) {
9151
+ await mutex.runExclusive(() => {
9152
+ reserving--;
9153
+ });
9154
+ if (!drained) wakeWaiterToMint();
9155
+ throw err;
9156
+ }
9020
9157
  const state = {
9021
9158
  slot: { id: mintId, resource },
9022
9159
  busy: true
9023
9160
  };
9024
9161
  await mutex.runExclusive(() => {
9025
9162
  slots.push(state);
9163
+ reserving--;
9026
9164
  });
9027
9165
  return state;
9028
9166
  }
9029
- return new Promise((resolve) => {
9030
- waiters.push((s) => {
9031
- s.busy = true;
9032
- resolve(s);
9033
- });
9167
+ return new Promise((resolve, reject) => {
9168
+ waiters.push({ resolve, reject });
9034
9169
  });
9035
9170
  }
9171
+ function handOffCleanSlot(state) {
9172
+ const next = waiters.shift();
9173
+ if (next) {
9174
+ state.busy = true;
9175
+ next.resolve(state);
9176
+ }
9177
+ }
9178
+ function wakeWaiterToMint() {
9179
+ const next = waiters.shift();
9180
+ if (!next) return;
9181
+ acquireSlot().then(next.resolve, next.reject);
9182
+ }
9036
9183
  function releaseSlot(state) {
9037
9184
  void (async () => {
9038
9185
  try {
9039
- if (opts.factory.reset) await opts.factory.reset(state.slot);
9040
- } catch (err) {
9041
- console.warn(`[sandbox-pool] reset failed for slot ${state.slot.id}:`, err);
9186
+ if (opts.factory.reset) {
9187
+ await opts.factory.reset(state.slot);
9188
+ }
9189
+ state.busy = false;
9190
+ if (!drained) handOffCleanSlot(state);
9191
+ } catch (resetErr) {
9192
+ await mutex.runExclusive(() => {
9193
+ const i = slots.indexOf(state);
9194
+ if (i !== -1) slots.splice(i, 1);
9195
+ });
9196
+ try {
9197
+ await opts.factory.destroy(state.slot);
9198
+ } catch (destroyErr) {
9199
+ console.warn(
9200
+ `[sandbox-pool] destroy of dirty slot ${state.slot.id} failed after reset error:`,
9201
+ destroyErr
9202
+ );
9203
+ }
9204
+ console.warn(
9205
+ `[sandbox-pool] reset failed for slot ${state.slot.id} \u2014 slot destroyed, not recycled:`,
9206
+ resetErr
9207
+ );
9208
+ if (!drained) wakeWaiterToMint();
9042
9209
  }
9043
- state.busy = false;
9044
- const next = waiters.shift();
9045
- if (next) next(state);
9046
- })();
9210
+ })().catch((err) => {
9211
+ console.warn(`[sandbox-pool] release of slot ${state.slot.id} faulted:`, err);
9212
+ });
9047
9213
  }
9048
9214
  async function checkout() {
9049
9215
  const state = await acquireSlot();
@@ -9066,13 +9232,15 @@ function createSandboxPool(opts) {
9066
9232
  }
9067
9233
  }
9068
9234
  async function drain() {
9069
- const snapshot = await mutex.runExclusive(() => {
9235
+ drained = true;
9236
+ const { snapshot, pending } = await mutex.runExclusive(() => {
9070
9237
  const taken = slots.splice(0, slots.length);
9071
- for (const w of waiters.splice(0, waiters.length)) {
9072
- void w;
9073
- }
9074
- return taken;
9238
+ const queued = waiters.splice(0, waiters.length);
9239
+ return { snapshot: taken, pending: queued };
9075
9240
  });
9241
+ for (const w of pending) {
9242
+ w.reject(new Error("sandbox pool drained while a checkout was pending"));
9243
+ }
9076
9244
  await Promise.allSettled(snapshot.map((s) => opts.factory.destroy(s.slot)));
9077
9245
  }
9078
9246
  function utilization() {
@@ -10268,6 +10436,9 @@ export {
10268
10436
  mannWhitneyU,
10269
10437
  matchGoldens,
10270
10438
  matchSpan,
10439
+ mcnemar,
10440
+ mcnemarPower,
10441
+ mcnemarRequiredN,
10271
10442
  mergeLayerResults,
10272
10443
  mergeSteeringBundle,
10273
10444
  modelDescriptionBits,
@@ -10286,6 +10457,7 @@ export {
10286
10457
  pairedBootstrap,
10287
10458
  pairedEvalueSequence,
10288
10459
  pairedMde,
10460
+ pairedRiskDifference,
10289
10461
  pairedTTest,
10290
10462
  paraphraseRobustness,
10291
10463
  paraphraseRobustnessScenarios,
@@ -10300,6 +10472,7 @@ export {
10300
10472
  parseRuntimeTrajectoryHookEvent,
10301
10473
  partialCredit,
10302
10474
  partitionHeldOut,
10475
+ passAtK,
10303
10476
  passOrthogonality,
10304
10477
  pixelDeltaRatio,
10305
10478
  planTraceInsightQuestions,
@@ -10440,6 +10613,7 @@ export {
10440
10613
  welchsTTest,
10441
10614
  whitespaceCollapseMutator,
10442
10615
  wilcoxonSignedRank,
10616
+ wilson,
10443
10617
  withAssignedFeedbackSplit,
10444
10618
  withJudgeRetry,
10445
10619
  withOtelPipeline,