@tangle-network/agent-eval 0.126.7 → 0.127.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 (129) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +2 -2
  3. package/dist/analyst/index.d.ts +51 -39
  4. package/dist/analyst/index.js +4 -4
  5. package/dist/belief-state/index.d.ts +34 -36
  6. package/dist/belief-state/index.js +2 -2
  7. package/dist/benchmarks/index.d.ts +30 -12
  8. package/dist/benchmarks/index.js +12 -10
  9. package/dist/builder-eval/index.js +1 -1
  10. package/dist/campaign/index.d.ts +432 -146
  11. package/dist/campaign/index.js +11 -9
  12. package/dist/{chunk-ARU2PZFM.js → chunk-424XHVKV.js} +43 -23
  13. package/dist/chunk-424XHVKV.js.map +1 -0
  14. package/dist/{chunk-NUKSVU3W.js → chunk-5DTSBUL2.js} +2 -2
  15. package/dist/{chunk-BTACVO2W.js → chunk-65QETEKG.js} +542 -258
  16. package/dist/chunk-65QETEKG.js.map +1 -0
  17. package/dist/{chunk-CGG5SLH3.js → chunk-ARCFIY7U.js} +2 -2
  18. package/dist/{chunk-P22LJ3Y2.js → chunk-CLELFRQG.js} +6 -4
  19. package/dist/chunk-CLELFRQG.js.map +1 -0
  20. package/dist/{chunk-LUNF2SEL.js → chunk-DJKY2TSY.js} +3 -3
  21. package/dist/chunk-DPUHNQLN.js +232 -0
  22. package/dist/chunk-DPUHNQLN.js.map +1 -0
  23. package/dist/{chunk-IPYXE555.js → chunk-EJGRPCO3.js} +36 -13
  24. package/dist/chunk-EJGRPCO3.js.map +1 -0
  25. package/dist/{chunk-K6IAZZ6L.js → chunk-FA3MFYNA.js} +132 -110
  26. package/dist/chunk-FA3MFYNA.js.map +1 -0
  27. package/dist/chunk-IG35YDN3.js +614 -0
  28. package/dist/chunk-IG35YDN3.js.map +1 -0
  29. package/dist/{chunk-DPZAEKA6.js → chunk-IMGJZBFG.js} +84 -56
  30. package/dist/chunk-IMGJZBFG.js.map +1 -0
  31. package/dist/{chunk-H5UD2323.js → chunk-IN455XKS.js} +53 -1
  32. package/dist/chunk-IN455XKS.js.map +1 -0
  33. package/dist/{chunk-PJQFMIOX.js → chunk-MHELPNRP.js} +31 -1
  34. package/dist/chunk-MHELPNRP.js.map +1 -0
  35. package/dist/{chunk-IILEIWGW.js → chunk-NL33OXEP.js} +41 -36
  36. package/dist/chunk-NL33OXEP.js.map +1 -0
  37. package/dist/{chunk-474LBSOX.js → chunk-OD5NQ2CS.js} +41 -16
  38. package/dist/chunk-OD5NQ2CS.js.map +1 -0
  39. package/dist/{chunk-QOTFXW5L.js → chunk-P5W7RQKK.js} +2 -2
  40. package/dist/{chunk-IR3KBHOY.js → chunk-P6FYH6K4.js} +39 -3
  41. package/dist/chunk-P6FYH6K4.js.map +1 -0
  42. package/dist/{chunk-J5SQWP6Y.js → chunk-PBE2LOSS.js} +18 -2
  43. package/dist/chunk-PBE2LOSS.js.map +1 -0
  44. package/dist/{chunk-E3IADPLG.js → chunk-PRB53E3J.js} +50 -224
  45. package/dist/chunk-PRB53E3J.js.map +1 -0
  46. package/dist/{chunk-X4UCIOTZ.js → chunk-S5YLIBFX.js} +2 -2
  47. package/dist/{chunk-7VYEGHWF.js → chunk-SZLVEKMJ.js} +41 -20
  48. package/dist/chunk-SZLVEKMJ.js.map +1 -0
  49. package/dist/{chunk-LKKT3IVV.js → chunk-TSN7JT6D.js} +6 -4
  50. package/dist/{chunk-LKKT3IVV.js.map → chunk-TSN7JT6D.js.map} +1 -1
  51. package/dist/{chunk-M7AH34KV.js → chunk-UTA2TGC4.js} +32 -16
  52. package/dist/chunk-UTA2TGC4.js.map +1 -0
  53. package/dist/{chunk-MAX3TN3C.js → chunk-UWZZKKU7.js} +7 -19
  54. package/dist/chunk-UWZZKKU7.js.map +1 -0
  55. package/dist/{chunk-ZVCHKKOP.js → chunk-WED5KLZQ.js} +39 -15
  56. package/dist/chunk-WED5KLZQ.js.map +1 -0
  57. package/dist/{chunk-OCFJACJU.js → chunk-X6VOPMLD.js} +74 -14
  58. package/dist/chunk-X6VOPMLD.js.map +1 -0
  59. package/dist/{chunk-MOXWMGPC.js → chunk-Y5CYOL42.js} +159 -70
  60. package/dist/chunk-Y5CYOL42.js.map +1 -0
  61. package/dist/{chunk-FO7HEH76.js → chunk-YJBNWCAA.js} +2 -2
  62. package/dist/chunk-ZPUEEM5U.js +179 -0
  63. package/dist/chunk-ZPUEEM5U.js.map +1 -0
  64. package/dist/{chunk-KE2VWPZX.js → chunk-ZUUWPZCV.js} +3 -3
  65. package/dist/cli.js +4 -4
  66. package/dist/contract/index.d.ts +421 -124
  67. package/dist/contract/index.js +242 -115
  68. package/dist/contract/index.js.map +1 -1
  69. package/dist/control.d.ts +34 -32
  70. package/dist/control.js +2 -2
  71. package/dist/hosted/index.d.ts +142 -41
  72. package/dist/hosted/index.js +23 -1
  73. package/dist/index.d.ts +364 -255
  74. package/dist/index.js +315 -226
  75. package/dist/index.js.map +1 -1
  76. package/dist/meta-eval/index.d.ts +32 -32
  77. package/dist/meta-eval/index.js +2 -2
  78. package/dist/multishot/index.d.ts +1 -0
  79. package/dist/openapi.json +1 -1
  80. package/dist/pipelines/index.js +2 -2
  81. package/dist/reporting.d.ts +97 -74
  82. package/dist/reporting.js +5 -4
  83. package/dist/rl.d.ts +177 -131
  84. package/dist/rl.js +232 -126
  85. package/dist/rl.js.map +1 -1
  86. package/dist/rollout/index.d.ts +53 -63
  87. package/dist/rollout/index.js +7 -5
  88. package/dist/{run-campaign-FFRM3RH5.js → run-campaign-3A2EBYBE.js} +4 -3
  89. package/dist/supervisor-run/index.d.ts +7 -15
  90. package/dist/supervisor-run/index.js +2 -2
  91. package/dist/traces.d.ts +66 -41
  92. package/dist/traces.js +9 -5
  93. package/dist/wire/index.d.ts +1 -0
  94. package/dist/wire/index.js +2 -2
  95. package/docs/concepts.md +18 -1
  96. package/docs/hosted-ingest-spec.md +37 -40
  97. package/docs/insight-report.md +57 -7
  98. package/docs/research-report-methodology.md +20 -21
  99. package/docs/rollout.md +13 -8
  100. package/package.json +4 -3
  101. package/dist/chunk-474LBSOX.js.map +0 -1
  102. package/dist/chunk-7VYEGHWF.js.map +0 -1
  103. package/dist/chunk-ARU2PZFM.js.map +0 -1
  104. package/dist/chunk-BTACVO2W.js.map +0 -1
  105. package/dist/chunk-DPZAEKA6.js.map +0 -1
  106. package/dist/chunk-E3IADPLG.js.map +0 -1
  107. package/dist/chunk-H5UD2323.js.map +0 -1
  108. package/dist/chunk-IILEIWGW.js.map +0 -1
  109. package/dist/chunk-IPYXE555.js.map +0 -1
  110. package/dist/chunk-IR3KBHOY.js.map +0 -1
  111. package/dist/chunk-J5SQWP6Y.js.map +0 -1
  112. package/dist/chunk-K6IAZZ6L.js.map +0 -1
  113. package/dist/chunk-M7AH34KV.js.map +0 -1
  114. package/dist/chunk-MAX3TN3C.js.map +0 -1
  115. package/dist/chunk-MOXWMGPC.js.map +0 -1
  116. package/dist/chunk-OCFJACJU.js.map +0 -1
  117. package/dist/chunk-P22LJ3Y2.js.map +0 -1
  118. package/dist/chunk-PJQFMIOX.js.map +0 -1
  119. package/dist/chunk-ZVCHKKOP.js.map +0 -1
  120. package/dist/chunk-ZZUXHH3R.js +0 -99
  121. package/dist/chunk-ZZUXHH3R.js.map +0 -1
  122. /package/dist/{chunk-NUKSVU3W.js.map → chunk-5DTSBUL2.js.map} +0 -0
  123. /package/dist/{chunk-CGG5SLH3.js.map → chunk-ARCFIY7U.js.map} +0 -0
  124. /package/dist/{chunk-LUNF2SEL.js.map → chunk-DJKY2TSY.js.map} +0 -0
  125. /package/dist/{chunk-QOTFXW5L.js.map → chunk-P5W7RQKK.js.map} +0 -0
  126. /package/dist/{chunk-X4UCIOTZ.js.map → chunk-S5YLIBFX.js.map} +0 -0
  127. /package/dist/{chunk-FO7HEH76.js.map → chunk-YJBNWCAA.js.map} +0 -0
  128. /package/dist/{chunk-KE2VWPZX.js.map → chunk-ZUUWPZCV.js.map} +0 -0
  129. /package/dist/{run-campaign-FFRM3RH5.js.map → run-campaign-3A2EBYBE.js.map} +0 -0
@@ -204,6 +204,7 @@ type CostLedgerHandle = Pick<CostLedger, Exclude<keyof CostLedger, 'listPending'
204
204
  * OpenAI-compatible `/v1/chat/completions` client with:
205
205
  * - Exponential-backoff retry on 429 + 5xx gateway errors (502/503/504).
206
206
  * - Retry on transient network errors (fetch failed, AbortError, ECONNRESET).
207
+ * - One retry at temperature 1 when a model explicitly requires it.
207
208
  * - Graceful json_schema → json_object degrade on 400 with schema-reject body.
208
209
  * - Fenced-JSON stripping (```json ... ```) for models that wrap structured output.
209
210
  * - Configurable base URL + api key / bearer, works with LiteLLM proxies, OpenAI
@@ -333,7 +334,8 @@ type FailureClass = 'success' | 'reasoning_error' | 'tool_selection_error' | 'to
333
334
  * researcher loop SHOULD be recorded as a `RunRecord`. The mandatory
334
335
  * fields are exactly those the paper "Two Loops, Three Roles" requires
335
336
  * for reproducibility: who/what/when/cost/seed/hash, plus the search vs
336
- * holdout split tag and either a `searchScore` or a `holdoutScore`.
337
+ * holdout split tag. A task score is optional because execution-only records
338
+ * must preserve missing labels instead of converting errors into zero quality.
337
339
  *
338
340
  * This is intentionally NOT a replacement for the rich `Run` /
339
341
  * `ProposeReviewReport` / `ScenarioResult` types already in the
@@ -354,6 +356,13 @@ type FailureClass = 'success' | 'reasoning_error' | 'tool_selection_error' | 'to
354
356
  /** Search/dev/holdout split tag. 'search' is the paper-grade alias for the
355
357
  * combined train+test pool that the optimizer is allowed to read. */
356
358
  type RunSplitTag = 'search' | 'dev' | 'holdout';
359
+ /**
360
+ * Explicit execution-lifecycle result for a run.
361
+ *
362
+ * This is separate from task quality (`outcome`) and failure classification.
363
+ * Producers set it only from root-run or process evidence.
364
+ */
365
+ type RunTerminalOutcome = 'succeeded' | 'failed' | 'cancelled' | 'incomplete' | 'unknown';
357
366
  interface RunTokenUsage {
358
367
  input: number;
359
368
  /** All generated tokens charged as output, including reasoning tokens. */
@@ -367,11 +376,6 @@ interface RunTokenUsage {
367
376
  }
368
377
  /**
369
378
  * How a run's USD amount was obtained.
370
- *
371
- * `costUsd` remains mandatory for wire compatibility. New producers should
372
- * always populate this discriminated union so a missing bill is never
373
- * mistaken for an observed zero-dollar run. For `uncaptured`, `costUsd` uses
374
- * the legacy `0` sentinel while this field carries the truthful null.
375
379
  */
376
380
  type RunCostProvenance = {
377
381
  kind: 'observed';
@@ -417,8 +421,8 @@ interface JudgeScoresRecord {
417
421
  perJudge: Record<string, Record<string, number>>;
418
422
  /** Per-dim mean across judges. Convenience — derivable from `perJudge`. */
419
423
  perDimMean: Record<string, number>;
420
- /** Composite mean across all dims and judges. Mirrors the score
421
- * the gate sees on `outcome.searchScore` / `holdoutScore`. */
424
+ /** Composite mean across successful judges. Mirrors the task score only
425
+ * when `failedJudges` is empty. */
422
426
  composite: number;
423
427
  /** Judges that errored or returned an unparseable verdict. Recorded
424
428
  * by id (e.g. `['glm-5.1']`) so a partial-failure case is explicit,
@@ -429,11 +433,11 @@ interface JudgeScoresRecord {
429
433
  notes?: string;
430
434
  }
431
435
  interface RunOutcome {
432
- /** Score on the search/optimization split. Optional because a
433
- * holdout-only evaluation only fills `holdoutScore`. */
436
+ /** Score on the search/optimization split. Optional for holdout-only and
437
+ * execution-only records. */
434
438
  searchScore?: number;
435
- /** Score on the held-out split. Optional because a search-only run
436
- * only fills `searchScore`. At least one must be present. */
439
+ /** Score on the held-out split. Optional for search-only and execution-only
440
+ * records. When both scores are absent, the run is explicitly unlabeled. */
437
441
  holdoutScore?: number;
438
442
  /** Bag of any other metric the run produced — judge dimensions,
439
443
  * pass/fail counters, latency stats, etc. Numeric only — keeps
@@ -497,42 +501,39 @@ interface RunRecord {
497
501
  wallMs: number;
498
502
  /** Time spent queued before execution started, if known. */
499
503
  queueMs?: number;
500
- /** Total USD cost. Mandatory runs without a cost number are
501
- * unbounded by definition and must not be admitted into the gate.
502
- * `0` is retained as the compatibility sentinel for an uncaptured amount;
503
- * inspect `costProvenance` before treating it as observed. */
504
- costUsd: number;
505
- /** Observed, model-priced estimate, or genuinely uncaptured USD amount.
506
- * Optional only so existing serialized RunRecords remain valid. */
507
- costProvenance?: RunCostProvenance;
504
+ /** Total USD cost, or null when the producer could not capture one. */
505
+ costUsd: number | null;
506
+ /** Whether `costUsd` came from billing data, a price calculation, or is unavailable. */
507
+ costProvenance: RunCostProvenance;
508
508
  /** Token usage breakdown. */
509
509
  tokenUsage: RunTokenUsage;
510
+ /** Root-run or process terminal result. Never inferred from a child span. */
511
+ terminalOutcome: RunTerminalOutcome;
512
+ /** Root-run or process failure reason. Valid only for a failed, cancelled,
513
+ * or incomplete terminal result; never populated from a child span. */
514
+ terminalFailureReason?: string;
510
515
  /** Judge-side metadata, if a judge was used. */
511
516
  judgeMetadata?: RunJudgeMetadata;
512
517
  /** Per-split scores + raw bag. */
513
518
  outcome: RunOutcome;
514
- /** Canonical, cross-agent failure class drawn from the shared
519
+ /** Canonical task-failure class drawn from the shared
515
520
  * `FAILURE_CLASSES` taxonomy. This is the aggregation key that makes
516
521
  * "which failure dominates across the whole fleet" answerable in ONE
517
522
  * vocabulary — every agent classifies against the same enum. Producers
518
- * set it via the substrate classifier; leave unset only when the failure
519
- * genuinely can't be classified. */
523
+ * set it only from task-result evidence. Execution errors belong in
524
+ * `outcome.raw.execution_error_count`, even when the run later fails. */
520
525
  failureClass?: FailureClass;
521
- /** Free-form domain-specific failure detail, scoped UNDER `failureClass`
526
+ /** Free-form task-failure detail, scoped UNDER `failureClass`
522
527
  * (e.g. failureClass='tool_recovery_failure', failureMode='forge_build_unsatisfied').
523
- * The within-agent drill-down; `failureClass` is the cross-agent key. */
528
+ * Do not populate this from a child execution error alone. */
524
529
  failureMode?: string;
525
530
  /** Which split this run was drawn from. */
526
531
  splitTag: RunSplitTag;
527
532
  /**
528
- * Stable scenario identifier the run was scored against. Optional for
529
- * backwards compatibility, but **strongly recommended**: every primitive
530
- * that pairs runs by scenario (preferences, paired stats, BT tournament)
531
- * keys on this. The campaign artifact populates it canonically; legacy
532
- * runs without it fall back to inference from `outcome.raw.scenario_id`
533
- * or `experimentId`.
533
+ * Stable scenario identifier the run observed or was scored against.
534
+ * Comparison primitives match this identity rather than input order.
534
535
  */
535
- scenarioId?: string;
536
+ scenarioId: string;
536
537
  /**
537
538
  * Canonical identity for the agent profile cell that produced this row:
538
539
  * profile artifact hash plus optional harness/model/prompt/reporting
@@ -887,6 +888,13 @@ interface OptimizerConfig extends OptimizerConfigBase {
887
888
  }
888
889
  /** Five-valued verdict taxonomy (MOSS-paper alignment). */
889
890
  type GateDecision = 'ship' | 'hold' | 'need_more_work' | 'model_ceiling' | 'arch_ceiling';
891
+ /** Outcome of one check that contributed to a release decision. */
892
+ type GateCheckStatus = 'pass' | 'fail' | 'not_evaluated';
893
+ interface GateContribution {
894
+ name: string;
895
+ status: GateCheckStatus;
896
+ detail: unknown;
897
+ }
890
898
  interface GateContext<TArtifact, TScenario extends Scenario$1> {
891
899
  candidateArtifacts: Map<string, TArtifact>;
892
900
  baselineArtifacts?: Map<string, TArtifact>;
@@ -920,11 +928,7 @@ interface GateContext<TArtifact, TScenario extends Scenario$1> {
920
928
  interface GateResult {
921
929
  decision: GateDecision;
922
930
  reasons: string[];
923
- contributingGates: Array<{
924
- name: string;
925
- passed: boolean;
926
- detail: unknown;
927
- }>;
931
+ contributingGates: GateContribution[];
928
932
  delta?: number;
929
933
  }
930
934
  /** Composable promotion gate. */
@@ -1066,6 +1070,10 @@ interface CampaignCellResult<TArtifact> {
1066
1070
  durationMs: number;
1067
1071
  seed: number;
1068
1072
  cached: boolean;
1073
+ /** Stage that produced `error`. Missing on successful cells. */
1074
+ errorStage?: 'dispatch' | 'judge';
1075
+ /** Judge that threw when `errorStage` is `judge`. */
1076
+ errorJudge?: string;
1069
1077
  error?: string;
1070
1078
  }
1071
1079
  interface JudgeAggregate {
@@ -1090,8 +1098,10 @@ interface GenerationRecord {
1090
1098
  * handled — the evidence a blind `Mutator` cannot see. */
1091
1099
  interface GenerationCandidate {
1092
1100
  surfaceHash: string;
1093
- composite: number;
1094
- ci95: [number, number];
1101
+ /** Mean over complete task-quality scores, or null when none were produced. */
1102
+ composite: number | null;
1103
+ /** Descriptive interval for `composite`, or null when no score exists. */
1104
+ ci95: [number, number] | null;
1095
1105
  /** Exact surface this candidate mutated. */
1096
1106
  parentSurfaceHash?: string;
1097
1107
  /** Measured search-split composite of the exact parent surface. */
@@ -1101,13 +1111,12 @@ interface GenerationCandidate {
1101
1111
  observedDeltaFromParent?: number;
1102
1112
  /** Whether this candidate had a scorable result for every designed campaign
1103
1113
  * cell and was therefore eligible for ranking, promotion, and Pareto
1104
- * selection. Older externally-authored records may omit this field; loop
1105
- * records always populate it. */
1106
- eligibleForPromotion?: boolean;
1114
+ * selection. */
1115
+ eligibleForPromotion: boolean;
1107
1116
  /** Exact denominator receipt for selection eligibility. Scores stay
1108
1117
  * descriptive: an incomplete candidate is retained with its observed score
1109
1118
  * and errors instead of receiving an invented penalty. */
1110
- coverage?: {
1119
+ coverage: {
1111
1120
  expectedCells: number;
1112
1121
  scorableCells: number;
1113
1122
  unscorableCells: Array<{
@@ -1148,10 +1157,18 @@ interface CampaignAggregates {
1148
1157
  cost: CostLedgerSummary;
1149
1158
  /** Compatibility alias of `cost.totalCostUsd`. */
1150
1159
  totalCostUsd: number;
1160
+ /** Cells whose dispatch completed, including cells whose later judge failed. */
1151
1161
  cellsExecuted: number;
1152
1162
  cellsSkipped: number;
1153
1163
  cellsCached: number;
1164
+ /** All non-skipped dispatch, judge, and unclassified cell failures. */
1154
1165
  cellsFailed: number;
1166
+ /** Present on results that record failure stages. */
1167
+ cellsDispatchFailed?: number;
1168
+ /** Present on results that record failure stages. */
1169
+ cellsJudgeFailed?: number;
1170
+ /** Legacy failures whose stage was not recorded. */
1171
+ cellsUnclassifiedFailed?: number;
1155
1172
  }
1156
1173
  interface CampaignResult<TArtifact = unknown, TScenario extends Scenario$1 = Scenario$1> {
1157
1174
  /** sha256(scenarios, judges, dispatch source ref, optimizer config, seed). Stable identity for reruns. */
@@ -1498,7 +1515,7 @@ interface RunOptimizationBaseOptions<TScenario extends Scenario$1, TArtifact> ex
1498
1515
  candidates: Array<{
1499
1516
  surfaceHash: string;
1500
1517
  campaign: CampaignResult<TArtifact, TScenario>;
1501
- composite: number;
1518
+ composite: number | null;
1502
1519
  }>;
1503
1520
  history: GenerationRecord[];
1504
1521
  /** Shared run spend account and receipt attribution phase. */
@@ -2330,6 +2347,86 @@ declare function skillOptOptimizationMethod<TScenario extends Scenario$1, TArtif
2330
2347
  * (so the result records every gate's reason — useful for diagnostics). */
2331
2348
  declare function composeGate<TArtifact = unknown, TScenario extends Scenario$1 = Scenario$1>(...gates: Array<Gate<TArtifact, TScenario>>): Gate<TArtifact, TScenario>;
2332
2349
 
2350
+ /**
2351
+ * Liveness canaries — cheap statistical checks that catch the failure
2352
+ * modes a green test suite never sees.
2353
+ *
2354
+ * Three canary types in this module:
2355
+ *
2356
+ * 1. **Silent judge fallback** — the judge degraded to a fallback
2357
+ * path (rules-only / cached / heuristic) without anyone
2358
+ * noticing. Signature: a string of consecutive runs whose
2359
+ * `judgeMetadata.confidence` equals a known fallback constant
2360
+ * (default 0.30) OR whose `judgeMetadata.fallback` is true.
2361
+ *
2362
+ * 2. **Judge calibration drift** — the judge's confidence
2363
+ * distribution has drifted from a historical window. Two-sample
2364
+ * Kolmogorov-Smirnov test on the recent vs historical confidences,
2365
+ * with the empirical-CDF max-difference statistic.
2366
+ *
2367
+ * 3. **Eval-set distribution shift** — the mix of categories /
2368
+ * buckets in the recent runs differs significantly from the
2369
+ * historical mix. Chi-square test on the binned counts.
2370
+ *
2371
+ * Outputs are alerts. The canary does NOT fail loud the way a test
2372
+ * does — failing tests are reserved for hard correctness violations.
2373
+ * A canary that fires is a *signal* to investigate, not a verdict.
2374
+ *
2375
+ * Why this lives here rather than in `observability.ts`: that module
2376
+ * exports already, and is a pure-fanout-to-Langfuse/Prometheus
2377
+ * adapter. Canaries are statistical detectors, not adapters.
2378
+ */
2379
+
2380
+ interface CanaryOptions {
2381
+ /**
2382
+ * Silent-fallback detection.
2383
+ * - `constant`: confidence value treated as the fallback signal.
2384
+ * Default 0.30 (matches the soft-fail default in
2385
+ * `propose-review.ts`).
2386
+ * - `consecutiveThreshold`: trip the alert after this many
2387
+ * consecutive runs at `constant` (or `fallback === true`).
2388
+ * Default 3.
2389
+ */
2390
+ silentFallback?: {
2391
+ constant?: number;
2392
+ consecutiveThreshold?: number;
2393
+ /** Floating-point tolerance when comparing against `constant`. */
2394
+ epsilon?: number;
2395
+ };
2396
+ /**
2397
+ * Calibration-drift detection.
2398
+ * - `historyWindow`: number of past runs (oldest-first) treated as
2399
+ * the historical baseline. Default 50.
2400
+ * - `recentWindow`: number of recent runs (newest-first) compared
2401
+ * against history. Default 20.
2402
+ * - `ksAlpha`: alpha for the KS statistic vs critical value.
2403
+ * Default 0.05.
2404
+ * - `minRecent`: minimum recent runs required to even attempt the
2405
+ * check. Default 10.
2406
+ */
2407
+ calibrationDrift?: {
2408
+ historyWindow?: number;
2409
+ recentWindow?: number;
2410
+ ksAlpha?: number;
2411
+ minRecent?: number;
2412
+ };
2413
+ /**
2414
+ * Distribution-shift detection.
2415
+ * - `category`: function that maps a run to a categorical bucket.
2416
+ * Required to enable this canary; if omitted the chi-square check
2417
+ * is skipped entirely.
2418
+ * - `chiSquareAlpha`: alpha. Default 0.05.
2419
+ * - `historyWindow`, `recentWindow`, `minRecent`: like above.
2420
+ */
2421
+ distributionShift?: {
2422
+ category: (run: RunRecord) => string | null;
2423
+ chiSquareAlpha?: number;
2424
+ historyWindow?: number;
2425
+ recentWindow?: number;
2426
+ minRecent?: number;
2427
+ };
2428
+ }
2429
+
2333
2430
  /**
2334
2431
  * Dataset — versioned, sliceable, content-hashed scenario collection.
2335
2432
  *
@@ -2401,6 +2498,144 @@ interface RedTeamCase extends DatasetScenario {
2401
2498
  payload: RedTeamPayload;
2402
2499
  }
2403
2500
 
2501
+ /**
2502
+ * Verifiable reward channel.
2503
+ *
2504
+ * For RL on coding / math / theorem-proving / structured-output tasks, the
2505
+ * reward signal is *decidable* — a test passes or fails, a proof checks or
2506
+ * doesn't, an output validates against a schema or doesn't. These rewards
2507
+ * are dramatically more useful for RL training than LLM-judge scores
2508
+ * because they don't drift, can't be Goodhart-gamed by the policy in the
2509
+ * same way, and don't require a separate calibration loop.
2510
+ *
2511
+ * The `MultiLayerVerifier` already produces this signal — it just doesn't
2512
+ * surface it in a shape that's clean enough for RL training. This module
2513
+ * wraps the verifier output so consumers can:
2514
+ *
2515
+ * 1. Extract a clean `VerifiableReward` from a `VerificationReport`
2516
+ * 2. Distinguish *deterministic* rewards (compile, test, schema) from
2517
+ * *probabilistic* rewards (judge) so they can be weighted differently
2518
+ * in the RL training step
2519
+ * 3. Filter `RunRecord[]` to only those with a verifiable reward,
2520
+ * producing the clean training set that DeepSeek-R1-style GRPO and
2521
+ * AlphaProof-style search both depend on
2522
+ *
2523
+ * Why this matters: every credible 2025-2026 frontier RL result on coding
2524
+ * agents leans on verifiable reward (DeepSeek-R1 GRPO on test pass-rate,
2525
+ * o-series RL on math/code, AlphaProof on Lean kernel checking). Mixing
2526
+ * judge scores into the reward signal poisons the gradient. This module
2527
+ * is the seam.
2528
+ */
2529
+
2530
+ type VerifiableRewardSource = 'compile' | 'test' | 'schema' | 'sandbox' | 'judge' | 'composite';
2531
+ interface VerifiableRewardExtractionOptions {
2532
+ /**
2533
+ * Which layers count as deterministic-reward sources. The verifier doesn't
2534
+ * tag layers as "this is verifiable"; the caller declares it via this list
2535
+ * (or via the layer name → source mapping). Default treats common names
2536
+ * (`install`, `typecheck`, `build`, `lint`, `test`, `compile`, `schema`,
2537
+ * `sandbox`) as deterministic.
2538
+ */
2539
+ deterministicLayers?: string[];
2540
+ /**
2541
+ * Map layer name → reward source. Defaults to a sensible string-match.
2542
+ */
2543
+ sourceFor?: (layerName: string) => VerifiableRewardSource;
2544
+ /**
2545
+ * Whether to fall back to a probabilistic (judge) reward when no
2546
+ * deterministic layer produced a numeric score. Default `true`. Set to
2547
+ * `false` for "deterministic-only" training pipelines that should
2548
+ * discard runs without a verifiable signal.
2549
+ */
2550
+ fallbackToJudge?: boolean;
2551
+ /**
2552
+ * Default confidence for probabilistic (judge) rewards when the judge
2553
+ * doesn't report one. Default `0.7`.
2554
+ */
2555
+ judgeConfidenceFloor?: number;
2556
+ }
2557
+
2558
+ /**
2559
+ * Reward hacking / Goodhart detection.
2560
+ *
2561
+ * Goodhart's Law says: when a measure becomes a target, it ceases to be
2562
+ * a good measure. In RLHF and agentic-RL settings this is the dominant
2563
+ * failure mode — the policy learns to produce outputs that score well on
2564
+ * the proxy reward (judge, rubric, test pass-rate) without producing
2565
+ * the underlying capability the proxy was meant to track.
2566
+ *
2567
+ * Krakovna et al. (2020, "Specification Gaming Examples in AI") and the
2568
+ * subsequent RLHF reward-hacking literature (Skalse et al. 2022, Kim et al.
2569
+ * 2023) converge on a few diagnostic signatures:
2570
+ *
2571
+ * 1. **Reward divergence:** the proxy reward grows while the held-out
2572
+ * ground-truth signal stagnates or drops. Predictive validity over
2573
+ * time captures this.
2574
+ * 2. **Distributional shift in outputs:** after RL, the policy produces
2575
+ * outputs that no longer match the reference distribution — usually
2576
+ * because it found a high-reward attractor that's degenerate (e.g.
2577
+ * one-token responses, repetition, formatting tricks).
2578
+ * 3. **Disagreement between independent rewards:** if you train on
2579
+ * reward A and a held-out independent reward B drops sharply, you're
2580
+ * probably hacking A.
2581
+ * 4. **Calibration drift:** the verifiable / deterministic component of
2582
+ * the reward is stable; the probabilistic / judge component drifts up
2583
+ * while the deterministic component doesn't. The judge is being
2584
+ * gamed.
2585
+ *
2586
+ * This module ships explicit detectors for all four signatures, plus a
2587
+ * combined verdict. The output is diagnostic — actionable signals,
2588
+ * not autoreject — because each signature has known false positives
2589
+ * (e.g., a policy that genuinely improves can show distributional shift).
2590
+ *
2591
+ * Differs from `rubricPredictiveValidity` (which is a *standing* check on
2592
+ * whether rubrics correlate with deployment outcomes) — this is a
2593
+ * *temporal* check on whether the reward-vs-truth gap is *widening over
2594
+ * time during a training run*.
2595
+ */
2596
+
2597
+ interface DetectRewardHackingInput {
2598
+ /**
2599
+ * Run records ordered by recency (oldest first). The detector segments
2600
+ * them into prefix/suffix windows to compute "did the gap widen."
2601
+ */
2602
+ runs: RunRecord[];
2603
+ /**
2604
+ * The metric the policy was trained to optimize. Should be present on
2605
+ * `outcome.raw` or `outcome.holdoutScore`. Default reads `outcome.holdoutScore`.
2606
+ */
2607
+ proxyOf?: (run: RunRecord) => number | null;
2608
+ /**
2609
+ * The held-out ground-truth metric. For RL on coding, this is typically
2610
+ * test pass-rate. For RLHF, it's downstream task performance or human
2611
+ * preference. For knowledge tasks, it's an independently-graded score.
2612
+ */
2613
+ truthOf?: (run: RunRecord) => number | null;
2614
+ /**
2615
+ * Independent secondary reward. Used for the `reward_disagreement`
2616
+ * signal. Default uses the verifiable reward extractor (deterministic
2617
+ * sources only).
2618
+ */
2619
+ secondaryRewardOf?: (run: RunRecord) => number | null;
2620
+ /**
2621
+ * Window size — how many of the most recent runs count as the "after"
2622
+ * cohort. Default min(50, half the runs).
2623
+ */
2624
+ windowSize?: number;
2625
+ /**
2626
+ * Severity threshold to flag a signal. Default 0.3 (suspect) and 0.6
2627
+ * (gaming).
2628
+ */
2629
+ thresholds?: {
2630
+ suspect?: number;
2631
+ gaming?: number;
2632
+ };
2633
+ /**
2634
+ * Verifiable-reward options used for the secondary-reward fallback.
2635
+ */
2636
+ verifiableRewardOptions?: VerifiableRewardExtractionOptions;
2637
+ }
2638
+
2404
2639
  /**
2405
2640
  * `defaultProductionGate` — composes the substrate's existing safety
2406
2641
  * primitives (red-team / reward-hacking / canary / heldout) into a single
@@ -2413,6 +2648,10 @@ interface RedTeamCase extends DatasetScenario {
2413
2648
  * extra domain-specific gates they need (`composeGate(defaultProductionGate(...), customGate)`).
2414
2649
  */
2415
2650
 
2651
+ type DefaultProductionGateCheck = 'dimension-regression' | 'budget' | 'red-team' | 'reward-hacking' | 'canary';
2652
+ type DefaultProductionRewardHackingOptions = Omit<DetectRewardHackingInput, 'runs' | 'truthOf'> & {
2653
+ truthOf: NonNullable<DetectRewardHackingInput['truthOf']>;
2654
+ };
2416
2655
  interface DefaultProductionGateOptions {
2417
2656
  /** Required: scenarios held out from training; substrate compares
2418
2657
  * candidate-on-holdout vs baseline-on-holdout. */
@@ -2445,19 +2684,25 @@ interface DefaultProductionGateOptions {
2445
2684
  * native scale. When omitted it auto-scales off observed magnitudes:
2446
2685
  * 0.05 on [0,1], 5 on 0-100. */
2447
2686
  regressionTolerance?: number;
2448
- /** Total $ budget for ALL cells in this campaign — including baseline + candidate.
2449
- * Composite verdict refuses to ship when spend exceeded budget. */
2687
+ /** Total $ budget for the complete improvement run. Requires
2688
+ * `GateContext.costLedger`; missing or incomplete accounting holds. */
2450
2689
  budgetUsd?: number;
2451
- /** Red-team cases to probe candidate outputs against. When omitted the
2452
- * substrate uses `DEFAULT_RED_TEAM_CORPUS`. Provide a domain-specific
2453
- * battery for tighter coverage. */
2690
+ /** Static artifact-screening cases. Only `expected: 'ignore'` cases without
2691
+ * tool assertions are valid because this check does not dispatch case inputs
2692
+ * or observe tool calls. */
2454
2693
  redTeamBattery?: RedTeamCase[];
2455
- /** Run records (oldest-first) needed for the reward-hacking detector.
2456
- * Substrate populates from prior production-loop generations. */
2694
+ /** Shared run history, oldest first. Supplying history does not enable either
2695
+ * monitoring check; configure `rewardHacking` and/or `canary` explicitly. */
2457
2696
  recentRuns?: RunRecord[];
2458
- /** When true, the gate refuses to ship if the reward-hacking detector
2459
- * fires at the `gaming` severity. Default true. */
2460
- blockOnRewardHackingGaming?: boolean;
2697
+ /** Enable reward-hacking monitoring with a caller-owned independent truth channel. */
2698
+ rewardHacking?: DefaultProductionRewardHackingOptions;
2699
+ /** Enable canary monitoring. Pass `{}` to use the canary defaults. */
2700
+ canary?: CanaryOptions;
2701
+ /** Optional checks that must be evaluated even when their normal input is
2702
+ * absent. Configuring a check's input also makes that check required.
2703
+ * Missing evidence always records `not_evaluated`; required unevaluated
2704
+ * checks hold the release decision. Held-out significance is always required. */
2705
+ requiredChecks?: DefaultProductionGateCheck[];
2461
2706
  }
2462
2707
  /**
2463
2708
  * Opinionated production gate composing held-out significance, red-team, reward-hacking, and canary checks into a single `Gate.decide` decision.
@@ -2837,7 +3082,7 @@ interface ParetoPoint {
2837
3082
  onFrontier: boolean;
2838
3083
  /** Optional gate verdict for this candidate, if a `GateDecision`
2839
3084
  * for it was passed in. */
2840
- gate?: 'promote' | 'reject_few_runs' | 'reject_negative_delta' | 'reject_overfit_gap' | null;
3085
+ gate?: 'promote' | 'reject';
2841
3086
  }
2842
3087
  interface ParetoFigureSpec {
2843
3088
  kind: 'pareto-cost-quality';
@@ -2891,8 +3136,8 @@ interface InsightReport {
2891
3136
  /** Number of runs analyzed. */
2892
3137
  n: number;
2893
3138
  /** Runtime facts carried by the run records. These describe execution,
2894
- * not task quality: duration, queueing, token categories, models, and
2895
- * explicitly recorded failures. */
3139
+ * not task quality: duration, queueing, token categories, models,
3140
+ * execution errors, and terminal outcomes. */
2896
3141
  execution: ExecutionInsight;
2897
3142
  /** Composite-score distribution across all runs. Always present. */
2898
3143
  composite: ScalarDistribution;
@@ -2950,10 +3195,9 @@ interface InsightReport {
2950
3195
  * Surfaced metrics: composite, cost, duration, tokenUsage, plus any
2951
3196
  * per-dimension judge metric present in both windows. */
2952
3197
  priorPeriodComparison?: PriorPeriodComparison;
2953
- /** Model-free failure-mode breakdown from `RunRecord.failureMode`, ranked
2954
- * by count descending. Present when any run carries a `failureMode`.
2955
- * Complements `failureClusters` (LLM-semantic) with the structured tags
2956
- * the harness already recorded — actionable with no analyst wired. */
3198
+ /** Model-free task-failure breakdown from `RunRecord.failureClass` or
3199
+ * `failureMode`, ranked by count descending. Tags from successful or
3200
+ * otherwise non-failed tasks are excluded. */
2957
3201
  failureModes?: FailureModeTally[];
2958
3202
  /** Top-N actionable recommendations, ranked by priority. The packet's
2959
3203
  * human-readable layer; the numeric sections are the evidence. */
@@ -3002,15 +3246,46 @@ interface ExecutionInsight {
3002
3246
  events: number;
3003
3247
  reportingRuns: number;
3004
3248
  };
3005
- /** Failure counts remain separate from outcome scores. `reportedErrorEvents`
3006
- * sums `outcome.raw.error_span_count` only where a producer supplied it. */
3007
- failures: {
3249
+ /** Runs with explicit execution-error telemetry. This is independent of
3250
+ * whether the root run ultimately succeeded, failed, or has no terminal
3251
+ * evidence. */
3252
+ executionErrors: {
3008
3253
  runs: number;
3009
- fraction: number;
3010
- reportedErrorEvents: number;
3254
+ /** Share among runs that supplied an execution-error count.
3255
+ * `null` when no run supplied error telemetry. */
3256
+ fraction: number | null;
3257
+ /** Execution-error events reported through the canonical count. */
3258
+ events: number;
3259
+ /** Runs that supplied an execution-error count, including explicit zeroes. */
3011
3260
  reportingRuns: number;
3261
+ /** Exact sum of `outcome.raw.error_span_count`, kept separate from other errors. */
3262
+ errorSpanEvents: number;
3263
+ /** Runs that supplied `outcome.raw.error_span_count`, including explicit zeroes. */
3264
+ errorSpanReportingRuns: number;
3265
+ /**
3266
+ * Error-telemetry coverage crossed with independently reported terminal
3267
+ * outcomes. `unreported` is distinct from a reported zero.
3268
+ */
3269
+ byTerminalOutcome: Record<RunTerminalOutcome, ExecutionErrorOutcomeCell>;
3270
+ };
3271
+ /** Root-run or process outcomes. Missing `RunRecord.terminalOutcome` values
3272
+ * count as `unknown`; child-span status never changes these counts. */
3273
+ terminalOutcomes: {
3274
+ succeeded: number;
3275
+ failed: number;
3276
+ cancelled: number;
3277
+ incomplete: number;
3278
+ unknown: number;
3012
3279
  };
3013
3280
  }
3281
+ interface ExecutionErrorOutcomeCell {
3282
+ /** Runs that explicitly reported one or more execution errors. */
3283
+ withErrors: number;
3284
+ /** Runs that explicitly reported zero execution errors. */
3285
+ withoutErrors: number;
3286
+ /** Runs with no execution-error count from the producer. */
3287
+ unreported: number;
3288
+ }
3014
3289
  interface TokenUsageInsight {
3015
3290
  input: ScalarDistribution;
3016
3291
  output: ScalarDistribution;
@@ -3029,12 +3304,18 @@ interface TokenUsageInsight {
3029
3304
  interface ScalarDistribution {
3030
3305
  /** Sample count after dropping non-finite values. */
3031
3306
  n: number;
3032
- mean: number;
3033
- p50: number;
3034
- p95: number;
3035
- stddev: number;
3036
- min: number;
3037
- max: number;
3307
+ /** Null when `n` is zero. */
3308
+ mean: number | null;
3309
+ /** Null when `n` is zero. */
3310
+ p50: number | null;
3311
+ /** Null when `n` is zero. */
3312
+ p95: number | null;
3313
+ /** Null when `n` is zero. */
3314
+ stddev: number | null;
3315
+ /** Null when `n` is zero. */
3316
+ min: number | null;
3317
+ /** Null when `n` is zero. */
3318
+ max: number | null;
3038
3319
  /** Histogram bins using `agent-eval`'s `gainHistogram` primitive. */
3039
3320
  histogram: GainDistributionBin[];
3040
3321
  /** Worst-N runs by score, ascending. Populated for the composite
@@ -3100,12 +3381,16 @@ interface LiftInsight {
3100
3381
  pValue: number;
3101
3382
  /** Number of paired observations. */
3102
3383
  n: number;
3103
- /** Cohen's d for the delta. */
3104
- cohensD: number;
3384
+ /** Scored baseline observations without a candidate match. */
3385
+ unpairedBaseline: number;
3386
+ /** Scored candidate observations without a baseline match. */
3387
+ unpairedCandidate: number;
3388
+ /** Cohen's dz for paired deltas; null when the observed delta variance is zero. */
3389
+ cohensD: number | null;
3105
3390
  /** Minimum detectable effect at current n, 80% power. */
3106
3391
  mde: number;
3107
- /** Sample size needed to detect the observed delta at 80% power. */
3108
- requiredN: number;
3392
+ /** Paired sample size needed to detect the standardized effect at 80% power. */
3393
+ requiredN: number | null;
3109
3394
  }
3110
3395
  interface FailureClusterInsight {
3111
3396
  /** All clusters identified by the registry, ranked by share descending. */
@@ -3169,7 +3454,7 @@ interface ReleaseSummary {
3169
3454
  status: 'pass' | 'warn' | 'fail';
3170
3455
  axes: Array<{
3171
3456
  name: 'quality-lift' | 'contamination' | 'composite-distribution';
3172
- status: 'pass' | 'warn' | 'fail';
3457
+ status: 'pass' | 'warn' | 'fail' | 'not_evaluated';
3173
3458
  detail: string;
3174
3459
  }>;
3175
3460
  /** Free-form issues surfaced beyond the standard axes. Empty by default;
@@ -3229,9 +3514,8 @@ interface Recommendation {
3229
3514
  * # Hosted-tier wire format — the schema that EVERY orchestrator (ours,
3230
3515
  * a partner's self-hosted one, a future open implementation) must accept.
3231
3516
  *
3232
- * **Stability:** every type in this file is committed under semver. New
3233
- * minors only ADD optional fields. Breaking changes mean a major bump
3234
- * (`HostedWireVersion` literal increment).
3517
+ * This package implements exactly one wire version. Servers reject every
3518
+ * other version instead of translating old payloads.
3235
3519
  *
3236
3520
  * The wire format is two event streams in one transport:
3237
3521
  *
@@ -3257,11 +3541,15 @@ interface EvalRunCellScore {
3257
3541
  scenarioId: string;
3258
3542
  /** Repetition index when reps > 1; 0 for the default. */
3259
3543
  rep: number;
3260
- /** Composite score across all judges + dimensions for this cell. */
3261
- compositeMean: number;
3262
- /** Per-judge per-dimension scores; null where the judge did not run. */
3544
+ /** Composite score across successful judges, or null when unscored. */
3545
+ compositeMean: number | null;
3546
+ /** Per-judge and per-dimension scores; failed or missing judges are absent. */
3263
3547
  dimensions: Record<string, Record<string, number>>;
3264
- /** Per-cell error message if the dispatch threw. Null on success. */
3548
+ /** Root execution result, kept separate from task quality. */
3549
+ terminalOutcome: RunTerminalOutcome;
3550
+ /** Canonical execution-error count, or null when the producer did not measure it. */
3551
+ executionErrorCount: number | null;
3552
+ /** Per-cell dispatch or judge error. Missing on success. */
3265
3553
  errorMessage?: string;
3266
3554
  }
3267
3555
  interface EvalRunGenerationSnapshot {
@@ -3275,8 +3563,8 @@ interface EvalRunGenerationSnapshot {
3275
3563
  surface?: MutableSurface;
3276
3564
  /** Per-cell scores for this generation. */
3277
3565
  cells: EvalRunCellScore[];
3278
- /** Aggregate composite mean across all cells in this generation. */
3279
- compositeMean: number;
3566
+ /** Mean across scored cells, or null when no cell has a task-quality label. */
3567
+ compositeMean: number | null;
3280
3568
  /** Total $ spent across this generation. */
3281
3569
  costUsd: number;
3282
3570
  /** Wall-clock duration of this generation. */
@@ -3316,10 +3604,14 @@ interface EvalRunEvent {
3316
3604
  * paired-bootstrap lift CI, judge stats, inter-rater agreement,
3317
3605
  * contamination check, failure clusters (when an analyst is wired),
3318
3606
  * outcome correlation (when downstream signal is supplied), and the
3319
- * recommendations the dashboard surfaces verbatim. Additive; older
3320
- * clients that don't know about this field continue to work. */
3607
+ * recommendations the dashboard surfaces verbatim. */
3321
3608
  insightReport?: InsightReport;
3322
3609
  }
3610
+ /**
3611
+ * Canonical unsigned 64-bit integer encoded as a base-10 string.
3612
+ * JSON numbers cannot represent OTLP nanosecond timestamps exactly.
3613
+ */
3614
+ type UnixNanoTimestamp = string;
3323
3615
  /**
3324
3616
  * OTel-shape span with a few additional attributes for eval-run pivoting.
3325
3617
  * Compatible with any OTLP collector — `name`, `traceId`, `spanId`,
@@ -3330,11 +3622,11 @@ interface TraceSpanEvent {
3330
3622
  spanId: string;
3331
3623
  parentSpanId?: string;
3332
3624
  name: string;
3333
- startTimeUnixNano: number;
3334
- endTimeUnixNano: number;
3625
+ startTimeUnixNano: UnixNanoTimestamp;
3626
+ endTimeUnixNano: UnixNanoTimestamp;
3335
3627
  attributes: Record<string, string | number | boolean>;
3336
3628
  events?: Array<{
3337
- timeUnixNano: number;
3629
+ timeUnixNano: UnixNanoTimestamp;
3338
3630
  name: string;
3339
3631
  attributes?: Record<string, string | number | boolean>;
3340
3632
  }>;
@@ -3462,8 +3754,8 @@ interface LoopProvenanceCandidate {
3462
3754
  eligibleForPromotion: boolean;
3463
3755
  /** Designed-denominator receipt retained even for incomplete candidates. */
3464
3756
  coverage: NonNullable<GenerationCandidate['coverage']>;
3465
- /** Mean composite this candidate scored on the search split. */
3466
- composite: number;
3757
+ /** Mean composite this candidate scored on the search split, or null when unscorable. */
3758
+ composite: number | null;
3467
3759
  /** Whether this candidate was promoted out of its generation. */
3468
3760
  promoted: boolean;
3469
3761
  }
@@ -3535,11 +3827,7 @@ interface LoopProvenanceRecord {
3535
3827
  decision: GateDecision;
3536
3828
  reasons: string[];
3537
3829
  delta?: number;
3538
- contributingGates: Array<{
3539
- name: string;
3540
- passed: boolean;
3541
- detail: unknown;
3542
- }>;
3830
+ contributingGates: GateContribution[];
3543
3831
  };
3544
3832
  /** Present iff the loop ran with `holdout: 'deferred'` — the held-out
3545
3833
  * comparison was intentionally not measured in this run, so the holdout
@@ -4048,7 +4336,7 @@ declare function verifyCandidateBenchmarkSuite(input: unknown): {
4048
4336
  * `ViewTraceOversized`.
4049
4337
  */
4050
4338
  /** OTLP span kind (subset we actually use). */
4051
- type TraceAnalystSpanKind = 'AGENT' | 'LLM' | 'TOOL' | 'CHAIN' | 'GUARDRAIL' | 'SPAN' | 'UNKNOWN';
4339
+ type TraceAnalystSpanKind = 'AGENT' | 'LLM' | 'TOOL' | 'CHAIN' | 'EVALUATOR' | 'GUARDRAIL' | 'SPAN' | 'UNKNOWN';
4052
4340
  type TraceAnalystSpanStatus = 'OK' | 'ERROR' | 'UNSET';
4053
4341
  /** Subset of OTLP span fields the analyst exposes to the agent. The
4054
4342
  * store's job is to project upstream's full span shape down to this
@@ -4847,7 +5135,8 @@ interface AnalyzeRunsOptions {
4847
5135
  split?: 'search' | 'holdout' | 'auto';
4848
5136
  /** Pairwise analysis configuration. When both `baselineCandidateId` and
4849
5137
  * `candidateCandidateId` are present, lift is computed on paired
4850
- * (experimentId, seed) tuples shared between the two sides. */
5138
+ * (experimentId, scenarioId, seed) identities shared between the two sides.
5139
+ * Unmatched rows remain visible in the lift result. */
4851
5140
  baselineCandidateId?: string;
4852
5141
  candidateCandidateId?: string;
4853
5142
  /** Canary scenarios — checked against every run's raw output for
@@ -4882,7 +5171,7 @@ interface AnalyzeRunsOptions {
4882
5171
  * recommendations fire on statistically significant regressions.
4883
5172
  * The two windows do NOT have to share scenarios — the comparison
4884
5173
  * is two-sample unpaired (the substrate's `lift` field uses paired
4885
- * bootstrap on shared (experimentId, seed) tuples; this is the
5174
+ * bootstrap on shared (experimentId, scenarioId, seed) identities; this is the
4886
5175
  * shape for "this week vs last week" rather than "candidate vs
4887
5176
  * baseline within a campaign"). */
4888
5177
  baselineRuns?: RunRecord[];
@@ -5069,9 +5358,9 @@ interface EvalDimensionDelta {
5069
5358
  interface EvalCellScoreDelta {
5070
5359
  scenarioId: string;
5071
5360
  rep: number;
5072
- compositeBefore: number;
5073
- compositeAfter: number;
5074
- compositeDelta: number;
5361
+ compositeBefore: number | null;
5362
+ compositeAfter: number | null;
5363
+ compositeDelta: number | null;
5075
5364
  /** Per-judge → per-dimension deltas. Outer key = judge name from
5076
5365
  * `EvalRunCellScore.dimensions`; inner key = dimension name. */
5077
5366
  dimensions: Record<string, Record<string, EvalDimensionDelta>>;
@@ -5090,10 +5379,10 @@ interface EvalGenerationDiff {
5090
5379
  removed: EvalRunCellScore[];
5091
5380
  /** Cells present in `after` but missing from `before`. */
5092
5381
  added: EvalRunCellScore[];
5093
- /** Aggregate composite mean across all cells in the snapshot. */
5094
- compositeBefore: number;
5095
- compositeAfter: number;
5096
- compositeDelta: number;
5382
+ /** Aggregate composite mean, null when that snapshot was unscored. */
5383
+ compositeBefore: number | null;
5384
+ compositeAfter: number | null;
5385
+ compositeDelta: number | null;
5097
5386
  costUsdBefore: number;
5098
5387
  costUsdAfter: number;
5099
5388
  costUsdDelta: number;
@@ -5302,6 +5591,7 @@ interface CodeAgentSessionMetrics {
5302
5591
  toolCalls: number;
5303
5592
  toolOutputs: number;
5304
5593
  toolErrors: number;
5594
+ unclassifiedErrors: number;
5305
5595
  patchAttempts: number;
5306
5596
  patchSuccesses: number;
5307
5597
  patchFailures: number;
@@ -5340,7 +5630,6 @@ interface CodeAgentSessionDiagnostic {
5340
5630
  sourcePath?: string;
5341
5631
  entries: number;
5342
5632
  malformedLines: number;
5343
- inferredScore: boolean;
5344
5633
  hasExplicitTerminalSignal: boolean;
5345
5634
  hasFinalOutput: boolean;
5346
5635
  hasQualityLabel: boolean;
@@ -5369,9 +5658,7 @@ interface CodeAgentSessionIntakeOptions {
5369
5658
  configHash?: string;
5370
5659
  commitSha?: string;
5371
5660
  score?: number;
5372
- /** Explicit cost receipt. Use `uncaptured` when the source says dollars
5373
- * were not captured; the adapter will not relabel its compatibility $0
5374
- * sentinel as observed. When omitted, source-reported cost wins, then a
5661
+ /** Explicit cost receipt. When omitted, source-reported cost wins, then a
5375
5662
  * token-priced estimate, then uncaptured. */
5376
5663
  costProvenance?: RunCostProvenance;
5377
5664
  /** Exact executor-owned process result. This is required when a provider's
@@ -5397,8 +5684,8 @@ declare const fromPigraphSession: typeof fromPiSession;
5397
5684
  * `analyzeRuns({ runs, raterScores })` can produce inter-rater agreement,
5398
5685
  * disagreement triage, and downstream recommendations.
5399
5686
  *
5400
- * Per-run `RunRecord.outcome.searchScore` is the rater-mean rating
5401
- * (normalised to 0..1 when scale is supplied); `outcome.raw` carries the
5687
+ * The rater mean is written to the score field matching the run split
5688
+ * (normalised to 0..1 when a scale is supplied); `outcome.raw` carries
5402
5689
  * per-rater scores keyed by rater id for downstream attribution.
5403
5690
  */
5404
5691
 
@@ -5422,9 +5709,10 @@ interface FeedbackTableMeta {
5422
5709
  experimentId?: string;
5423
5710
  /** When omitted, defaults to `runId` — each run is its own candidate. */
5424
5711
  candidateId?: string;
5425
- /** Cost in USD, when available. Set to 0 when unknown — the consumer's
5426
- * cost analysis sections will collapse gracefully. */
5712
+ /** Observed cost in USD, when available. */
5427
5713
  costUsd?: number;
5714
+ /** Stable scenario identity. Defaults to `runId`. */
5715
+ scenarioId?: string;
5428
5716
  /** Wall-clock ms, when available. Defaults to 0. */
5429
5717
  wallMs?: number;
5430
5718
  /** Model identifier including snapshot. Default `unknown@unknown`. */
@@ -5456,9 +5744,8 @@ interface FromFeedbackTableOptions {
5456
5744
  max: number;
5457
5745
  };
5458
5746
  /** When true, the rater scores are emitted into `raterScores` (a sibling
5459
- * array `analyzeRuns()` accepts) instead of being averaged into the
5460
- * run's `outcome.searchScore`. Default `true` preserves rater-level
5461
- * signal for inter-rater analysis. */
5747
+ * array `analyzeRuns()` accepts) in addition to the aggregate run score.
5748
+ * Default `true` preserves rater-level signal for inter-rater analysis. */
5462
5749
  emitRaterScores?: boolean;
5463
5750
  }
5464
5751
  interface FromFeedbackTableResult {
@@ -5490,11 +5777,15 @@ declare function fromFeedbackTable(opts: FromFeedbackTableOptions): FromFeedback
5490
5777
  * - cost from `cost.usd` / `gen_ai.usage.cost_usd` / `tangle.cost.usd`
5491
5778
  * - token usage from model-call input, output, cache-read, and cache-write
5492
5779
  * attributes without double-counting aggregate parent spans
5493
- * - `outcome.searchScore` from `tangle.score` / `eval.score` when
5494
- * present; `outcome.raw` collects every numeric attribute.
5780
+ * - task quality from an explicit `scoreForRun` callback or a designated
5781
+ * evaluation attribute on a root / `EVALUATOR` span; `outcome.raw`
5782
+ * collects every numeric attribute without promoting it to task quality.
5495
5783
  *
5496
- * Spans that ERRORed (`status.code === 'ERROR'`) populate `failureMode`
5497
- * with their `name` so `analyzeRuns()`'s failure clustering sees them.
5784
+ * Errored tool, model, and child-agent spans contribute to execution-error
5785
+ * counts. Root process, guardrail, evaluator, propagated parent, and unknown
5786
+ * errors retain separate counters. Only one failed root can set
5787
+ * `RunRecord.terminalOutcome` and `RunRecord.terminalFailureReason`; a child
5788
+ * error cannot become a task failure.
5498
5789
  */
5499
5790
 
5500
5791
  interface FromOtelSpansOptions {
@@ -5503,7 +5794,13 @@ interface FromOtelSpansOptions {
5503
5794
  defaultSplit?: RunSplitTag;
5504
5795
  /** Default `experimentId` when not present on any span. */
5505
5796
  experimentId?: string;
5797
+ /**
5798
+ * Explicit task-quality score for a logical run. The callback receives
5799
+ * spans in deterministic time/id order. Its value must agree with any
5800
+ * designated score attributes present on root or `EVALUATOR` spans.
5801
+ */
5802
+ scoreForRun?: (runId: string, spans: readonly TraceSpanEvent[]) => number | undefined;
5506
5803
  }
5507
5804
  declare function fromOtelSpans(opts: FromOtelSpansOptions): RunRecord[];
5508
5805
 
5509
- export { type AgentEvalAgent, type AgentEvalEvaluateOptions, type AgentEvalImproveOptions, type AgentTraceContributor, type AgentTraceContributorType, type AgentTraceConversation, type AgentTraceFile, type AgentTraceIndex, type AgentTraceRange, type AgentTraceRecord, type AnalystFinding, type AnalyzeRunsOptions, type AuthoringProvenance, type AxisEvidence, type AxisVerdict, type BuildEvidenceVectorOptions, type CampaignAggregates, type CampaignArtifactWriter, type CampaignCellFailureReceipt, type CampaignCellResult, type CampaignCostMeter, type CampaignResult, type CampaignStorage, type CampaignTraceWriter, type CandidateExperimentExecutionInput, type ChatClient, type CodeAgentSessionAction, type CodeAgentSessionActionKind, type CodeAgentSessionActionStatus, type CodeAgentSessionActionSurface, type CodeAgentSessionDiagnostic, type CodeAgentSessionExecutionReceipt, type CodeAgentSessionIntakeOptions, type CodeAgentSessionIntakeResult, type CodeAgentSessionMetrics, type CodeAgentSessionObservation, type CodeAgentSessionSource, type CodeAgentSessionTerminalStatus, type CodeSurface, type CompareCandidateExperimentOptions, type CompareOptimizationMethodsOptions, type ComparisonCost, type CostLedgerHandle, type CostProvenanceSummary, type CreateChatClientOpts, type DefaultAnalystRegistryOptions, type DefaultProductionGateOptions, type DefineAgentEvalOptions, type DefinedAgentEval, type DeploymentOutcome, type DispatchFn as Dispatch, type DispatchContext, type EvalCellScoreDelta, type EvalDimensionDelta, type EvalGenerationDiff, type EvalReportingSuiteInput, type EvalReportingSuiteOptions, type EvalReportingSuiteResult, type EvalRunDiff, type EvaluatePairedMeasurementsOptions, type EvidenceVector, type ExecutionInsight, type ExecutionReport, type ExternalOptimizationExample, type ExternalTextEvaluationResponse, type ExternalTextOptimizationMethodConfig, type ExternalTextOptimizerContext, type ExternalTextOptimizerResult, type FailureClusterInsight, type FeedbackTableMeta, type FeedbackTableRow, FileSystemOutcomeStore, type FileSystemOutcomeStoreOptions, type FromFeedbackTableOptions, type FromFeedbackTableResult, type FromOtelSpansOptions, type FromRunRecordDirOptions, type FromRunRecordDirResult, type Gate, type GateContext, type GateDecision, type GateResult, type GenerationCandidate, type GenerationRecord, type GepaAdaptiveEngineRun, type GepaEngineOptions, type GepaEngineRun, type GepaOptimizationMethodConfig, type GepaOptimizationRecipe, type GepaRunnerCommand, type HeldOutGateOptions, type HostedTenant, InMemoryOutcomeStore, type InsightReport, type InterRaterInsight, type JudgeConfig, type JudgeDimension, type JudgeInsight, type JudgeScore, type LiftInsight, type LlmJudgeDimension, type LlmJudgeOptions, type MutableSurface, type ObjectiveSource, type OpenAICompatibleOptimizerModel, type OptimizationMethod, type OptimizationMethodComparison, type OptimizationMethodInput, type OptimizationMethodProvenance, type OptimizationMethodResult, type OptimizationPackageSource, type OptimizationProposer, type OptimizationTokenUsage, type OptimizerConfig, type OptimizerModelBudget, type OutcomeCorrelationInsight, type OutcomeStore, type PairedMeasurement, type PairedMeasurementAdapter, type PairedMeasurementEvaluation, type ParetoSignificanceGateOptions, type ParsedCodeAgentJsonl, type PartitionByAuthoringModelResult, type PromotionObjective, type PromotionPolicy, REFERENCE_EQUIVALENCE_INPUT_LIMITS, REFERENCE_EQUIVALENCE_JUDGE_VERSION, type Recommendation, type ReferenceEquivalenceJudgeInput, type ReferenceEquivalenceJudgeOptions, type ReferenceEquivalenceJudgeResult, type ReferenceEquivalenceScenario, type ReleaseSummary, type RunCampaignOptions, type RunCandidateExperimentOptions, type RunEvalOptions, type RunImprovementLoopOptions, type RunImprovementLoopResult, type RunRecordRejection, type ScalarDistribution, type Scenario$1 as Scenario, type SealCandidateBenchmarkSuiteOptions, type SelfImproveBudget, type SelfImproveOptions, type SelfImproveProgressEvent, type SelfImproveResult, SelfImproveRunError, type SessionScript, type SkillOptOptimizationMethodConfig, type SkillOptRunnerCommand, type SkillOptTrainerConfig, type SummarizeExecutionOptions, type SurfaceProposer, type TokenUsageInsight, analyzeRuns, buildDefaultAnalystRegistry, buildEvidenceVector, campaignSplitDigest, compareOptimizationMethods, composeGate, createChatClient, createReferenceEquivalenceJudge, defaultProductionGate, defineAgentEval, diffGenerations, diffRunBaselineToWinner, diffRuns, evalReportingSuite, evaluatePairedMeasurements, externalTextOptimizationMethod, fromClaudeCodeSession, fromCodexSession, fromFeedbackTable, fromKimiCodeSession, fromOpenCodeSession, fromOtelSpans, fromPiSession, fromPigraphSession, fromRunRecordDir, fsCampaignStorage, gepaOptimizationMethod, heldOutGate, inMemoryCampaignStorage, llmJudge, measuredComparisonFromCandidateExperiment, observeCodeAgentSession, paretoPolicy, paretoSignificanceGate, parseAgentTrace, parseCodeAgentJsonl, partitionRunsByAuthoringModel, runCampaign, runCandidateExperiment, runEval, runImprovementLoop, runReferenceEquivalenceJudge, sealCandidateBenchmarkSuite, sealCandidateBenchmarkTask, sealCandidateExperiment, selfImprove, skillOptOptimizationMethod, summarizeExecution, verifyCandidateBenchmarkSuite, verifyCandidateBenchmarkSuiteInputs, verifyCandidateBenchmarkTask, verifyCandidateExperiment, verifyCandidateExperimentComparison };
5806
+ export { type AgentEvalAgent, type AgentEvalEvaluateOptions, type AgentEvalImproveOptions, type AgentTraceContributor, type AgentTraceContributorType, type AgentTraceConversation, type AgentTraceFile, type AgentTraceIndex, type AgentTraceRange, type AgentTraceRecord, type AnalystFinding, type AnalyzeRunsOptions, type AuthoringProvenance, type AxisEvidence, type AxisVerdict, type BuildEvidenceVectorOptions, type CampaignAggregates, type CampaignArtifactWriter, type CampaignCellFailureReceipt, type CampaignCellResult, type CampaignCostMeter, type CampaignResult, type CampaignStorage, type CampaignTraceWriter, type CandidateExperimentExecutionInput, type ChatClient, type CodeAgentSessionAction, type CodeAgentSessionActionKind, type CodeAgentSessionActionStatus, type CodeAgentSessionActionSurface, type CodeAgentSessionDiagnostic, type CodeAgentSessionExecutionReceipt, type CodeAgentSessionIntakeOptions, type CodeAgentSessionIntakeResult, type CodeAgentSessionMetrics, type CodeAgentSessionObservation, type CodeAgentSessionSource, type CodeAgentSessionTerminalStatus, type CodeSurface, type CompareCandidateExperimentOptions, type CompareOptimizationMethodsOptions, type ComparisonCost, type CostLedgerHandle, type CostProvenanceSummary, type CreateChatClientOpts, type DefaultAnalystRegistryOptions, type DefaultProductionGateCheck, type DefaultProductionGateOptions, type DefaultProductionRewardHackingOptions, type DefineAgentEvalOptions, type DefinedAgentEval, type DeploymentOutcome, type DispatchFn as Dispatch, type DispatchContext, type EvalCellScoreDelta, type EvalDimensionDelta, type EvalGenerationDiff, type EvalReportingSuiteInput, type EvalReportingSuiteOptions, type EvalReportingSuiteResult, type EvalRunDiff, type EvaluatePairedMeasurementsOptions, type EvidenceVector, type ExecutionErrorOutcomeCell, type ExecutionInsight, type ExecutionReport, type ExternalOptimizationExample, type ExternalTextEvaluationResponse, type ExternalTextOptimizationMethodConfig, type ExternalTextOptimizerContext, type ExternalTextOptimizerResult, type FailureClusterInsight, type FeedbackTableMeta, type FeedbackTableRow, FileSystemOutcomeStore, type FileSystemOutcomeStoreOptions, type FromFeedbackTableOptions, type FromFeedbackTableResult, type FromOtelSpansOptions, type FromRunRecordDirOptions, type FromRunRecordDirResult, type Gate, type GateCheckStatus, type GateContext, type GateContribution, type GateDecision, type GateResult, type GenerationCandidate, type GenerationRecord, type GepaAdaptiveEngineRun, type GepaEngineOptions, type GepaEngineRun, type GepaOptimizationMethodConfig, type GepaOptimizationRecipe, type GepaRunnerCommand, type HeldOutGateOptions, type HostedTenant, InMemoryOutcomeStore, type InsightReport, type InterRaterInsight, type JudgeConfig, type JudgeDimension, type JudgeInsight, type JudgeScore, type LiftInsight, type LlmJudgeDimension, type LlmJudgeOptions, type MutableSurface, type ObjectiveSource, type OpenAICompatibleOptimizerModel, type OptimizationMethod, type OptimizationMethodComparison, type OptimizationMethodInput, type OptimizationMethodProvenance, type OptimizationMethodResult, type OptimizationPackageSource, type OptimizationProposer, type OptimizationTokenUsage, type OptimizerConfig, type OptimizerModelBudget, type OutcomeCorrelationInsight, type OutcomeStore, type PairedMeasurement, type PairedMeasurementAdapter, type PairedMeasurementEvaluation, type ParetoSignificanceGateOptions, type ParsedCodeAgentJsonl, type PartitionByAuthoringModelResult, type PromotionObjective, type PromotionPolicy, REFERENCE_EQUIVALENCE_INPUT_LIMITS, REFERENCE_EQUIVALENCE_JUDGE_VERSION, type Recommendation, type ReferenceEquivalenceJudgeInput, type ReferenceEquivalenceJudgeOptions, type ReferenceEquivalenceJudgeResult, type ReferenceEquivalenceScenario, type ReleaseSummary, type RunCampaignOptions, type RunCandidateExperimentOptions, type RunEvalOptions, type RunImprovementLoopOptions, type RunImprovementLoopResult, type RunRecordRejection, type ScalarDistribution, type Scenario$1 as Scenario, type SealCandidateBenchmarkSuiteOptions, type SelfImproveBudget, type SelfImproveOptions, type SelfImproveProgressEvent, type SelfImproveResult, SelfImproveRunError, type SessionScript, type SkillOptOptimizationMethodConfig, type SkillOptRunnerCommand, type SkillOptTrainerConfig, type SummarizeExecutionOptions, type SurfaceProposer, type TokenUsageInsight, analyzeRuns, buildDefaultAnalystRegistry, buildEvidenceVector, campaignSplitDigest, compareOptimizationMethods, composeGate, createChatClient, createReferenceEquivalenceJudge, defaultProductionGate, defineAgentEval, diffGenerations, diffRunBaselineToWinner, diffRuns, evalReportingSuite, evaluatePairedMeasurements, externalTextOptimizationMethod, fromClaudeCodeSession, fromCodexSession, fromFeedbackTable, fromKimiCodeSession, fromOpenCodeSession, fromOtelSpans, fromPiSession, fromPigraphSession, fromRunRecordDir, fsCampaignStorage, gepaOptimizationMethod, heldOutGate, inMemoryCampaignStorage, llmJudge, measuredComparisonFromCandidateExperiment, observeCodeAgentSession, paretoPolicy, paretoSignificanceGate, parseAgentTrace, parseCodeAgentJsonl, partitionRunsByAuthoringModel, runCampaign, runCandidateExperiment, runEval, runImprovementLoop, runReferenceEquivalenceJudge, sealCandidateBenchmarkSuite, sealCandidateBenchmarkTask, sealCandidateExperiment, selfImprove, skillOptOptimizationMethod, summarizeExecution, verifyCandidateBenchmarkSuite, verifyCandidateBenchmarkSuiteInputs, verifyCandidateBenchmarkTask, verifyCandidateExperiment, verifyCandidateExperimentComparison };