@tangle-network/agent-eval 0.117.1 → 0.118.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 (143) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/analyst/index.d.ts +2772 -21
  3. package/dist/analyst/index.js +7 -6
  4. package/dist/analyst/index.js.map +1 -1
  5. package/dist/belief-state/index.d.ts +706 -10
  6. package/dist/belief-state/index.js +2 -1
  7. package/dist/belief-state/index.js.map +1 -1
  8. package/dist/benchmarks/index.d.ts +958 -14
  9. package/dist/benchmarks/index.js +12 -10
  10. package/dist/builder-eval/index.d.ts +449 -4
  11. package/dist/builder-eval/index.js +4 -3
  12. package/dist/builder-eval/index.js.map +1 -1
  13. package/dist/campaign/index.d.ts +4275 -73
  14. package/dist/campaign/index.js +12 -10
  15. package/dist/{chunk-VF3XSYTI.js → chunk-33JA4TFA.js} +6 -6
  16. package/dist/{chunk-4JLWXDYA.js → chunk-3EHHMC6E.js} +2 -2
  17. package/dist/{chunk-CCZIVI3F.js → chunk-BFW56GTT.js} +2 -2
  18. package/dist/{chunk-YZPO4UHR.js → chunk-DP3BBMYJ.js} +100 -143
  19. package/dist/chunk-DP3BBMYJ.js.map +1 -0
  20. package/dist/{chunk-E4BUPP7Z.js → chunk-HKUCJ437.js} +38 -66
  21. package/dist/chunk-HKUCJ437.js.map +1 -0
  22. package/dist/{chunk-HZHNRYHK.js → chunk-K6N6XJJX.js} +2 -2
  23. package/dist/chunk-KSDQVPLR.js +286 -0
  24. package/dist/chunk-KSDQVPLR.js.map +1 -0
  25. package/dist/chunk-MA6HLL3S.js +65 -0
  26. package/dist/chunk-MA6HLL3S.js.map +1 -0
  27. package/dist/{chunk-MGEHEHSN.js → chunk-OIIMMLRB.js} +11 -11
  28. package/dist/{chunk-DXZRATT5.js → chunk-OYZAPX5G.js} +3 -3
  29. package/dist/chunk-PXE2VKMX.js +140 -0
  30. package/dist/chunk-PXE2VKMX.js.map +1 -0
  31. package/dist/{chunk-JSJZ4PJ6.js → chunk-Q442S5AS.js} +17 -17
  32. package/dist/{chunk-ODVOOEWQ.js → chunk-QBRSJK47.js} +2 -2
  33. package/dist/{chunk-S2F4J57L.js → chunk-QKEGNI5B.js} +77 -32
  34. package/dist/chunk-QKEGNI5B.js.map +1 -0
  35. package/dist/{chunk-5UF54T55.js → chunk-S3UZOQ5Y.js} +34 -7
  36. package/dist/chunk-S3UZOQ5Y.js.map +1 -0
  37. package/dist/{chunk-FQNLDL4D.js → chunk-SVH2ANFD.js} +136 -4
  38. package/dist/chunk-SVH2ANFD.js.map +1 -0
  39. package/dist/{chunk-GQCZRZ7L.js → chunk-U5CHZ5M3.js} +9 -9
  40. package/dist/{chunk-TVVP3ZZQ.js → chunk-VQMK5FMP.js} +2 -1
  41. package/dist/{chunk-TVVP3ZZQ.js.map → chunk-VQMK5FMP.js.map} +1 -1
  42. package/dist/chunk-WDHBCA3M.js +31 -0
  43. package/dist/chunk-WDHBCA3M.js.map +1 -0
  44. package/dist/{chunk-HQPHZGL6.js → chunk-YLMUS4MM.js} +9 -9
  45. package/dist/{chunk-LQUTGLOZ.js → chunk-ZET2UAYW.js} +15 -65
  46. package/dist/chunk-ZET2UAYW.js.map +1 -0
  47. package/dist/contract/index.d.ts +4012 -38
  48. package/dist/contract/index.js +56 -29
  49. package/dist/contract/index.js.map +1 -1
  50. package/dist/control.d.ts +1013 -9
  51. package/dist/control.js +4 -3
  52. package/dist/fuzz.d.ts +194 -4
  53. package/dist/fuzz.js +3 -3
  54. package/dist/hosted/index.d.ts +498 -17
  55. package/dist/index.d.ts +10982 -1286
  56. package/dist/index.js +97 -80
  57. package/dist/index.js.map +1 -1
  58. package/dist/matrix/index.d.ts +139 -4
  59. package/dist/meta-eval/index.d.ts +862 -15
  60. package/dist/meta-eval/index.js +2 -1
  61. package/dist/meta-eval/index.js.map +1 -1
  62. package/dist/multishot/index.d.ts +214 -14
  63. package/dist/openapi.json +1 -1
  64. package/dist/pipelines/index.d.ts +392 -7
  65. package/dist/pipelines/index.js +5 -3
  66. package/dist/pipelines/index.js.map +1 -1
  67. package/dist/reporting.d.ts +1277 -17
  68. package/dist/rl.d.ts +2359 -28
  69. package/dist/rl.js +6 -5
  70. package/dist/rl.js.map +1 -1
  71. package/dist/storyboard/index.d.ts +86 -1
  72. package/dist/trace-attributes.d.ts +16 -0
  73. package/dist/trace-attributes.js +32 -0
  74. package/dist/trace-attributes.js.map +1 -0
  75. package/dist/traces.d.ts +1970 -697
  76. package/dist/traces.js +49 -32
  77. package/dist/wire/index.d.ts +655 -9
  78. package/docs/insight-report.md +44 -0
  79. package/package.json +9 -3
  80. package/dist/adversarial-B7loGVVX.d.ts +0 -19
  81. package/dist/analyst-C8HHvfJp.d.ts +0 -88
  82. package/dist/analyze-runs--2x39HZ7.d.ts +0 -81
  83. package/dist/baseline-DKq3gJpP.d.ts +0 -141
  84. package/dist/calibration-C8MTS7cw.d.ts +0 -101
  85. package/dist/chunk-5UF54T55.js.map +0 -1
  86. package/dist/chunk-E4BUPP7Z.js.map +0 -1
  87. package/dist/chunk-FQNLDL4D.js.map +0 -1
  88. package/dist/chunk-LQUTGLOZ.js.map +0 -1
  89. package/dist/chunk-S2F4J57L.js.map +0 -1
  90. package/dist/chunk-YZPO4UHR.js.map +0 -1
  91. package/dist/code-agent-session-CjZsVd19.d.ts +0 -87
  92. package/dist/control-6vuGfmDH.d.ts +0 -258
  93. package/dist/cost-ledger-DWy3XdJc.d.ts +0 -183
  94. package/dist/dataset-NENEzRgk.d.ts +0 -115
  95. package/dist/default-registry-DaK8b3fv.d.ts +0 -155
  96. package/dist/emitter-CjD7vUwv.d.ts +0 -122
  97. package/dist/errors-oeQrLqXC.d.ts +0 -74
  98. package/dist/failure-cluster-DOAcSJ87.d.ts +0 -76
  99. package/dist/feedback-trajectory-BUnM58xL.d.ts +0 -348
  100. package/dist/gepa-eESocoDi.d.ts +0 -642
  101. package/dist/index-PdX4VnPA.d.ts +0 -423
  102. package/dist/insight-report-DY4nDW9Q.d.ts +0 -310
  103. package/dist/integrity-DqlBiLyK.d.ts +0 -81
  104. package/dist/judge-calibration-7C-IDmKr.d.ts +0 -145
  105. package/dist/kind-factory-ClZmO25A.d.ts +0 -171
  106. package/dist/llm-client-qoDd18Qz.d.ts +0 -289
  107. package/dist/multi-layer-verifier-BsqKuLyN.d.ts +0 -150
  108. package/dist/off-policy-DiwuKKg7.d.ts +0 -132
  109. package/dist/outcome-store-rnXLEqSn.d.ts +0 -63
  110. package/dist/policy-edit-wG9uFEFm.d.ts +0 -455
  111. package/dist/pre-registration-BWQhJ3vz.d.ts +0 -761
  112. package/dist/provenance-DpjwyseI.d.ts +0 -541
  113. package/dist/query-CF7PG61p.d.ts +0 -35
  114. package/dist/raw-provider-sink-C46HDghv.d.ts +0 -132
  115. package/dist/release-report-C8G2i5Xi.d.ts +0 -236
  116. package/dist/researcher-C8XyxQsu.d.ts +0 -387
  117. package/dist/rubric-predictive-validity-p49lLVrE.d.ts +0 -105
  118. package/dist/run-record-BDH49H2E.d.ts +0 -360
  119. package/dist/runtime-trajectory-DGBIUt4B.d.ts +0 -49
  120. package/dist/schema-B3Q3l9Z_.d.ts +0 -201
  121. package/dist/semantic-concept-judge-CXnPEJbf.d.ts +0 -723
  122. package/dist/sequential-5iSVfzl2.d.ts +0 -139
  123. package/dist/series-convergence-D5OWMBg6.d.ts +0 -33
  124. package/dist/statistics-KUnG73jH.d.ts +0 -494
  125. package/dist/storage-DrX3v_5B.d.ts +0 -50
  126. package/dist/store-C1YxJDEK.d.ts +0 -248
  127. package/dist/store-DGqD0Pyo.d.ts +0 -116
  128. package/dist/summary-report-C5bKFfm-.d.ts +0 -445
  129. package/dist/test-graded-scenario-B0ybnPY7.d.ts +0 -166
  130. package/dist/types-BSw1rOUB.d.ts +0 -634
  131. package/dist/types-BUxNaJ8c.d.ts +0 -108
  132. package/dist/types-BkfcQnxV.d.ts +0 -313
  133. package/dist/verdict-C9MlYujm.d.ts +0 -35
  134. /package/dist/{chunk-VF3XSYTI.js.map → chunk-33JA4TFA.js.map} +0 -0
  135. /package/dist/{chunk-4JLWXDYA.js.map → chunk-3EHHMC6E.js.map} +0 -0
  136. /package/dist/{chunk-CCZIVI3F.js.map → chunk-BFW56GTT.js.map} +0 -0
  137. /package/dist/{chunk-HZHNRYHK.js.map → chunk-K6N6XJJX.js.map} +0 -0
  138. /package/dist/{chunk-MGEHEHSN.js.map → chunk-OIIMMLRB.js.map} +0 -0
  139. /package/dist/{chunk-DXZRATT5.js.map → chunk-OYZAPX5G.js.map} +0 -0
  140. /package/dist/{chunk-JSJZ4PJ6.js.map → chunk-Q442S5AS.js.map} +0 -0
  141. /package/dist/{chunk-ODVOOEWQ.js.map → chunk-QBRSJK47.js.map} +0 -0
  142. /package/dist/{chunk-GQCZRZ7L.js.map → chunk-U5CHZ5M3.js.map} +0 -0
  143. /package/dist/{chunk-HQPHZGL6.js.map → chunk-YLMUS4MM.js.map} +0 -0
@@ -1,445 +0,0 @@
1
- import { R as RunRecord } from './run-record-BDH49H2E.js';
2
- import { F as FailureClusterReport } from './failure-cluster-DOAcSJ87.js';
3
-
4
- /**
5
- * HeldOutGate — first-class held-out paired-delta promotion gate.
6
- *
7
- * Encodes the "honesty override" pattern that lived inline in
8
- * `~/webb/redteam/scripts/agent-eval-autoresearch.ts:138–171`.
9
- * The optimizer's best-guess is one thing; what we should actually
10
- * ship is another. The gate is the line between them.
11
- *
12
- * A candidate is promoted iff ALL three pass:
13
- *
14
- * 1. **Productive runs**: the candidate has at least
15
- * `minProductiveRuns` paired observations on items where BOTH
16
- * candidate and baseline produced a real (non-silent) score.
17
- * 2. **Paired delta**: the lower bound of the bootstrap CI on the
18
- * median per-item delta (candidate − baseline) on the HOLDOUT
19
- * split is strictly greater than `pairedDeltaThreshold`.
20
- * 3. **Overfit gap**: the candidate's gap between search-split
21
- * score and holdout-split score is no worse (more positive)
22
- * than the baseline's gap by more than `overfitGapThreshold`.
23
- * "Better on search, worse on holdout" is the canonical
24
- * overfit pattern; this catches it.
25
- *
26
- * The decision carries a machine-readable `rejectionCode` plus an
27
- * `evidence` block with every number the gate looked at, so the
28
- * downstream researcher / paper / dashboard can re-derive the
29
- * verdict without re-running.
30
- *
31
- * See also:
32
- * - `src/statistics.ts` for `pairedBootstrap` + `wilcoxonSignedRank`
33
- * - `src/run-record.ts` for the input row schema
34
- * - `src/reference-replay.ts` for the older, reference-replay-
35
- * specific promotion path (still useful for replay-style evals).
36
- */
37
-
38
- type HeldOutGateRejectionCode = 'few_runs' | 'negative_delta' | 'overfit_gap' | 'cost_ceiling';
39
- interface HeldOutGateConfig {
40
- /** Minimum number of paired (candidate, baseline) holdout observations
41
- * required before the gate will even consider promoting. Default 3. */
42
- minProductiveRuns?: number;
43
- /** The bootstrap-CI lower bound on the median paired holdout delta
44
- * must exceed this to promote. Default 0. */
45
- pairedDeltaThreshold?: number;
46
- /** Maximum allowed worsening of (search − holdout) gap relative to
47
- * baseline. Default 0.15 (i.e. candidate may overfit by up to 15
48
- * absolute score points more than baseline before rejection). */
49
- overfitGapThreshold?: number;
50
- /** Stable label of the baseline candidate. Required — paper-grade
51
- * evaluation never compares two unlabelled candidates. */
52
- baselineKey: string;
53
- /** Confidence level for the bootstrap CI. Default 0.95. */
54
- confidence?: number;
55
- /** Bootstrap resamples. Default 2000. */
56
- bootstrapResamples?: number;
57
- /** Optional deterministic seed for the bootstrap. Default undefined
58
- * (Math.random). */
59
- seed?: number;
60
- /**
61
- * Hard ceiling on the candidate's median per-task USD cost. When the
62
- * candidate clears the quality gates (paired-delta + overfit-gap) but
63
- * its median cost exceeds this number, the gate rejects with
64
- * `cost_ceiling`. Default `undefined` = no cost ceiling, behaving
65
- * exactly like the pre-cost gate.
66
- *
67
- * This exists because "we ship the better prompt" is only an honest
68
- * pitch when the better prompt also fits a customer-stated budget.
69
- * Cost is read from `RunRecord.costUsd` (already mandatory on every
70
- * run) so no new schema is required.
71
- */
72
- costPerTaskCeiling?: number;
73
- }
74
- interface GateEvidence {
75
- /** Number of paired (candidate, baseline) holdout observations used. */
76
- productiveRuns: number;
77
- /** Median of (candidate − baseline) paired holdout deltas. */
78
- medianPairedDelta: number;
79
- /** Bootstrap CI on the median paired holdout delta. */
80
- pairedCI: {
81
- low: number;
82
- high: number;
83
- };
84
- /** Wilcoxon signed-rank p-value on the paired holdout deltas. */
85
- pairedPValue: number;
86
- /** Mean candidate score on the search split (NaN if none). */
87
- searchScore: number;
88
- /** Mean candidate score on the holdout split (NaN if none). */
89
- holdoutScore: number;
90
- /** Candidate (search − holdout) gap. */
91
- overfitGap: number;
92
- /** Baseline (search − holdout) gap. */
93
- baselineOverfitGap: number;
94
- /** Median per-task USD cost across the candidate's runs. Recorded
95
- * even when no `costPerTaskCeiling` is configured so downstream
96
- * dashboards (intelligence.tangle.tools) can render \$/task per
97
- * generation regardless of gating policy. */
98
- medianCandidateCost: number;
99
- /** Median per-task USD cost across the baseline runs, for
100
- * symmetric reporting. */
101
- medianBaselineCost: number;
102
- }
103
- interface GateDecision {
104
- /** Final promote/no-promote verdict. */
105
- promote: boolean;
106
- /** The candidate that was evaluated. */
107
- candidateId: string;
108
- /** The baseline it was compared against. */
109
- baselineId: string;
110
- /** Every number the gate looked at, for audit + paper export. */
111
- evidence: GateEvidence;
112
- /** Human-readable reason. */
113
- reason: string;
114
- /** Machine-readable rejection code, or null on promote. */
115
- rejectionCode: HeldOutGateRejectionCode | null;
116
- }
117
- /**
118
- * Held-out paired-delta promotion gate. Construct once with config,
119
- * call `evaluate(candidateRuns, baselineRuns)` per (candidate,
120
- * baseline) pair. Stateless across calls.
121
- */
122
- declare class HeldOutGate {
123
- private readonly minProductiveRuns;
124
- private readonly pairedDeltaThreshold;
125
- private readonly overfitGapThreshold;
126
- private readonly baselineKey;
127
- private readonly confidence;
128
- private readonly resamples;
129
- private readonly seed?;
130
- private readonly costPerTaskCeiling?;
131
- constructor(config: HeldOutGateConfig);
132
- /** Decide whether `candidate` should replace `baseline`. Pairing
133
- * is by (experimentId, seed) — identical experiment + seed pairs
134
- * the candidate run with the matching baseline run. Pairs without
135
- * a holdout score on both sides are dropped. */
136
- evaluate(candidate: RunRecord[], baseline: RunRecord[]): GateDecision;
137
- }
138
-
139
- /**
140
- * Reporting helpers — production summaries and paper-quality figures — sit alongside `reporter.ts` rather
141
- * than replacing it.
142
- *
143
- * Three artefacts:
144
- *
145
- * - `summaryTable` Markdown table of per-candidate means,
146
- * 95% bootstrap CIs, BH-adjusted Wilcoxon
147
- * p-values, and Cohen's d versus a
148
- * comparator candidate.
149
- * - `paretoChart` Abstract spec for a cost vs quality
150
- * scatter, with gate decisions overlaid.
151
- * Returns numbers + labels — caller
152
- * chooses the plotting library.
153
- * - `gainHistogram`
154
- * Per-item paired holdout deltas as a
155
- * histogram spec (bins + counts + median +
156
- * CI). Same "data, not images" contract.
157
- *
158
- * The figure types are PlotSpecs — JSON-friendly, library-agnostic.
159
- * They aren't React components and they aren't PNGs; they are
160
- * what you'd hand to vega-lite, plotly, matplotlib, or your own
161
- * Canvas renderer to draw the actual figure.
162
- */
163
-
164
- interface SummaryTableOptions {
165
- /** Comparator candidate id. Wilcoxon + Cohen's d are computed
166
- * versus this candidate. Required for paired stats columns. */
167
- comparator?: string;
168
- /** Which split to read scores from. Default 'holdout'. */
169
- split?: 'search' | 'holdout';
170
- /** Confidence level for the bootstrap CI on the mean. Default 0.95. */
171
- confidence?: number;
172
- /** FDR for BH adjustment of the comparison p-values. Default 0.05. */
173
- fdr?: number;
174
- }
175
- interface SummaryTableRow {
176
- candidateId: string;
177
- n: number;
178
- mean: number;
179
- ciLow: number;
180
- ciHigh: number;
181
- /** BH-adjusted q-value vs comparator. NaN if no comparator. */
182
- qValue: number;
183
- /** Cohen's d vs comparator. NaN if no comparator. */
184
- cohensD: number;
185
- }
186
- interface SummaryTable {
187
- rows: SummaryTableRow[];
188
- comparator: string | null;
189
- split: 'search' | 'holdout';
190
- /** Pre-rendered markdown — drop into a paper or PR. */
191
- markdown: string;
192
- }
193
- /**
194
- * Table 1 helper. Buckets runs by `candidateId`, computes mean +
195
- * bootstrap CI on the chosen split, and (when a comparator is given)
196
- * BH-adjusted Wilcoxon p + Cohen's d versus that comparator.
197
- */
198
- declare function summaryTable(runs: RunRecord[], opts?: SummaryTableOptions): SummaryTable;
199
- interface ParetoPoint {
200
- candidateId: string;
201
- /** Mean USD cost per run on the chosen split. */
202
- cost: number;
203
- /** Mean score on the chosen split. */
204
- quality: number;
205
- /** Number of runs that informed this point. */
206
- n: number;
207
- /** Whether this candidate is on the Pareto frontier — high
208
- * quality, low cost, no dominator. */
209
- onFrontier: boolean;
210
- /** Optional gate verdict for this candidate, if a `GateDecision`
211
- * for it was passed in. */
212
- gate?: 'promote' | 'reject_few_runs' | 'reject_negative_delta' | 'reject_overfit_gap' | null;
213
- }
214
- interface ParetoFigureSpec {
215
- kind: 'pareto-cost-quality';
216
- split: 'search' | 'holdout';
217
- points: ParetoPoint[];
218
- axes: {
219
- x: 'costUsd';
220
- y: 'score';
221
- };
222
- }
223
- /**
224
- * Cost vs quality scatter spec. `gateDecisions` is keyed by
225
- * candidate id; if present, every point picks up the gate verdict
226
- * for overlay.
227
- */
228
- declare function paretoChart(runs: RunRecord[], opts?: {
229
- split?: 'search' | 'holdout';
230
- gateDecisions?: Record<string, GateDecision>;
231
- }): ParetoFigureSpec;
232
- interface GainDistributionBin {
233
- /** Inclusive lower edge. */
234
- lo: number;
235
- /** Exclusive upper edge (or inclusive if it's the last bin). */
236
- hi: number;
237
- /** Number of pairs whose delta lands in this bin. */
238
- count: number;
239
- }
240
- interface GainDistributionFigureSpec {
241
- kind: 'gain-distribution';
242
- candidateId: string;
243
- comparator: string;
244
- split: 'search' | 'holdout';
245
- /** Number of pairs used. */
246
- n: number;
247
- bins: GainDistributionBin[];
248
- median: number;
249
- ci: {
250
- low: number;
251
- high: number;
252
- };
253
- }
254
- interface GainDistributionOptions {
255
- /** Number of histogram bins. Default 11 (so the centre is exact at 0). */
256
- bins?: number;
257
- /** Which split to use. Default 'holdout'. */
258
- split?: 'search' | 'holdout';
259
- /** Confidence level for the CI. Default 0.95. */
260
- confidence?: number;
261
- /** Bootstrap resamples. Default 2000. */
262
- resamples?: number;
263
- /** Deterministic seed. */
264
- seed?: number;
265
- }
266
- /**
267
- * Held-out improvement distribution: per-pair delta (candidate −
268
- * comparator), histogrammed. Includes the bootstrap CI on the median
269
- * delta — same primitive the promotion gate uses.
270
- */
271
- declare function gainHistogram(runs: RunRecord[], candidateId: string, comparator: string, opts?: GainDistributionOptions): GainDistributionFigureSpec;
272
- type ResearchReportDecision = 'promote' | 'hold' | 'reject' | 'equivalent' | 'needs_more_data';
273
- /**
274
- * Hard floor below which a paired comparison is treated as uninformative
275
- * regardless of `minPairs`. Mirrors the lower limit on Wilcoxon signed-rank
276
- * exact tables; below this the test has no power to separate effect sizes.
277
- */
278
- declare const RESEARCH_REPORT_HARD_PAIR_FLOOR = 6;
279
- interface ResearchReportOptions {
280
- /** Human-readable report title. */
281
- title?: string;
282
- /** Comparator candidate id. Required for statistical decision guidance. */
283
- comparator?: string;
284
- /** Which split to use for the primary decision. Default 'holdout'. */
285
- split?: 'search' | 'holdout';
286
- /** Confidence level used by lower-level report helpers. Default 0.95. */
287
- confidence?: number;
288
- /** FDR threshold for q-values. Default 0.05. */
289
- fdr?: number;
290
- /**
291
- * Soft floor on paired observations before issuing a directional
292
- * promote / reject. Below this we report `needs_more_data` and surface the
293
- * minimum detectable effect at the current N. Default 20 — chosen so the
294
- * Wilcoxon signed-rank approximation is reasonable and so the paired
295
- * bootstrap CI has non-degenerate coverage. Hard floor is enforced at
296
- * `RESEARCH_REPORT_HARD_PAIR_FLOOR` (6) regardless of this value.
297
- */
298
- minPairs?: number;
299
- /**
300
- * Region of Practical Equivalence on the paired delta. When a candidate's
301
- * paired-delta CI is fully contained in `[low, high]`, the decision is
302
- * `equivalent` rather than `hold`. Sourced from the domain owner — there is
303
- * no statistically-defensible default.
304
- */
305
- rope?: {
306
- low: number;
307
- high: number;
308
- };
309
- /**
310
- * Power for the minimum detectable effect (MDE) reported on each candidate.
311
- * Default 0.8.
312
- */
313
- mdePower?: number;
314
- /**
315
- * Two-sided alpha for the MDE. Default matches `fdr` so the reported MDE
316
- * lines up with the test the report actually runs.
317
- */
318
- mdeAlpha?: number;
319
- /** Optional held-out gate decisions keyed by candidate id. */
320
- gateDecisions?: Record<string, GateDecision>;
321
- /** Optional failure clusters from failureClusterView. */
322
- failureClusters?: FailureClusterReport;
323
- /** Build gain histograms for these candidates. Defaults to all non-comparator candidates. */
324
- candidateIds?: string[];
325
- /** Deterministic bootstrap seed passed to gainHistogram and the posterior helper. */
326
- seed?: number;
327
- /** Report timestamp. Defaults to current time. */
328
- generatedAt?: string;
329
- /**
330
- * Hash of a preregistered protocol (e.g. `signManifest({...}).contentHash`).
331
- * Embedded verbatim in the report so the analysis can be cited as the
332
- * preregistered one rather than a post-hoc fishing expedition.
333
- */
334
- preregistrationHash?: string;
335
- }
336
- interface ResearchReportRecommendation {
337
- decision: ResearchReportDecision;
338
- candidateId: string | null;
339
- rationale: string[];
340
- risks: string[];
341
- nextActions: string[];
342
- }
343
- interface ResearchReportCandidate {
344
- candidateId: string;
345
- n: number;
346
- mean: number;
347
- ciLow: number;
348
- ciHigh: number;
349
- qValue: number;
350
- cohensD: number;
351
- meanDeltaVsComparator: number | null;
352
- pairedN: number;
353
- medianGain: number | null;
354
- meanGain: number | null;
355
- gainCi: {
356
- low: number;
357
- high: number;
358
- } | null;
359
- /**
360
- * Bayesian-bootstrap-style posterior summaries on the paired delta. Computed
361
- * from the same resamples that produce the gain CI; interpretable as
362
- * "fraction of resamples in which the candidate beats the comparator on
363
- * matched pairs."
364
- */
365
- prGreaterThanZero: number | null;
366
- prInRope: number | null;
367
- /**
368
- * Minimum detectable effect (in score units) at the candidate's paired N,
369
- * the configured power, and the configured alpha. Standardised by the
370
- * observed paired-delta SD and inverted via `requiredSampleSize`. Reported
371
- * for every candidate so a `needs_more_data` verdict is actionable.
372
- */
373
- mde: number | null;
374
- onParetoFrontier: boolean;
375
- gate?: ParetoPoint['gate'];
376
- decision: ResearchReportDecision;
377
- decisionReason: string;
378
- }
379
- interface ResearchReportMethodology {
380
- /**
381
- * Plain-language assumptions the report depends on. Read these first when
382
- * deciding whether the verdict is load-bearing for a launch decision.
383
- */
384
- assumptions: string[];
385
- /** Tests and estimators the verdict was computed from. */
386
- methods: string[];
387
- /** Alternatives the author considered and why this report didn't take them. */
388
- alternatives: string[];
389
- /** Failure modes — when this report should NOT drive a decision. */
390
- whenNotToApply: string[];
391
- /** Citations for the methodological choices above. */
392
- citations: string[];
393
- }
394
- interface ResearchReport {
395
- kind: 'agent-eval-research-report';
396
- title: string;
397
- generatedAt: string;
398
- split: 'search' | 'holdout';
399
- comparator: string | null;
400
- /**
401
- * SHA-256 over the canonicalised set of `(runId, candidateId, split)` triples
402
- * the report was computed from, plus the comparator and split. Stable across
403
- * key insertion order; recomputable by the reader to verify provenance.
404
- */
405
- runFingerprint: string;
406
- preregistrationHash: string | null;
407
- rope: {
408
- low: number;
409
- high: number;
410
- } | null;
411
- executiveSummary: string[];
412
- recommendation: ResearchReportRecommendation;
413
- candidates: ResearchReportCandidate[];
414
- summary: SummaryTable;
415
- charts: {
416
- pareto: ParetoFigureSpec;
417
- gains: GainDistributionFigureSpec[];
418
- };
419
- methodology: ResearchReportMethodology;
420
- failureClusters?: FailureClusterReport;
421
- markdown: string;
422
- html: string;
423
- }
424
- /**
425
- * Executive research report for CPO / AI-lead / launch-review consumption.
426
- *
427
- * Composes:
428
- * - `summaryTable` marginal stats with BH-FDR-adjusted q-values
429
- * - `paretoChart` cost-vs-quality frontier with gate overlay
430
- * - `gainHistogram` per-candidate paired-delta distribution
431
- * - paired posterior (this file): bootstrap CI on median, Pr(Δ>0),
432
- * Pr(Δ∈ROPE), MDE at the configured power
433
- *
434
- * Decisions are made on paired evidence — never on marginal means alone —
435
- * and respect any held-out gate decision the caller passes through. The
436
- * report embeds a SHA-256 fingerprint of the input run set and, optionally,
437
- * the hash of a preregistered protocol so a downstream reader can verify
438
- * provenance and that the analysis was the preregistered one.
439
- *
440
- * Async because the fingerprint uses Web Crypto via `hashJson`; deterministic
441
- * for any fixed `runs`, `seed`, and ROPE.
442
- */
443
- declare function researchReport(runs: RunRecord[], opts?: ResearchReportOptions): Promise<ResearchReport>;
444
-
445
- export { type GainDistributionBin as G, HeldOutGate as H, type ParetoFigureSpec as P, RESEARCH_REPORT_HARD_PAIR_FLOOR as R, type SummaryTable as S, type GainDistributionFigureSpec as a, type GainDistributionOptions as b, type ParetoPoint as c, type ResearchReport as d, type ResearchReportCandidate as e, type ResearchReportDecision as f, type ResearchReportMethodology as g, type ResearchReportOptions as h, type ResearchReportRecommendation as i, type SummaryTableOptions as j, type SummaryTableRow as k, gainHistogram as l, type GateDecision as m, type GateEvidence as n, type HeldOutGateConfig as o, paretoChart as p, type HeldOutGateRejectionCode as q, researchReport as r, summaryTable as s };
@@ -1,166 +0,0 @@
1
- import { T as TraceEmitter } from './emitter-CjD7vUwv.js';
2
- import { R as Run, F as FailureClass } from './schema-B3Q3l9Z_.js';
3
- import { T as TraceStore } from './store-DGqD0Pyo.js';
4
-
5
- /**
6
- * SandboxHarness — executes a scenario in an isolated environment and
7
- * emits a rich SandboxSpan into the trace.
8
- *
9
- * Two built-in drivers:
10
- * - `SubprocessSandboxDriver` — spawn in a local cwd with env vars.
11
- * Fast, no dependencies, fine for unit tests and most CI gates.
12
- * - `DockerSandboxDriver` — lifted from tangle-router's sandbox path;
13
- * shells out to `docker run`. Stronger isolation, slower startup.
14
- *
15
- * Consumers implement `SandboxDriver` for custom backends (Firecracker,
16
- * Cloudflare sandbox product, etc.). The harness doesn't care which.
17
- */
18
-
19
- interface HarnessConfig {
20
- /** Setup command (e.g. "pnpm install"). Non-zero exit fails the run. */
21
- setupCommand?: string;
22
- /** Run command (e.g. "pnpm build"). */
23
- runCommand?: string;
24
- /** Test command (e.g. "pnpm test --run"). Drives the test count + pass count. */
25
- testCommand?: string;
26
- /** Absolute cwd for the subprocess driver. Ignored by docker driver. */
27
- cwd?: string;
28
- /** Max wall-clock per phase in ms. Default 10 minutes. */
29
- timeoutMs?: number;
30
- /**
31
- * Cap on captured stdout+stderr bytes per phase. A runaway process can
32
- * otherwise grow the in-memory buffer without bound. Once hit, further
33
- * output is dropped and `outputTruncated` is set. Default 16 MiB.
34
- */
35
- maxOutputBytes?: number;
36
- /** Image for the docker driver. */
37
- image?: string;
38
- /** Extra env vars (validated; shell-escaped). */
39
- env?: Record<string, string>;
40
- /** Parser for the test output — maps stdout/stderr/exit code → pass count. */
41
- testParser?: TestOutputParser;
42
- }
43
- interface TestOutputParser {
44
- id: string;
45
- parse(stdout: string, stderr: string, exitCode: number): {
46
- testsTotal: number;
47
- testsPassed: number;
48
- } | undefined;
49
- }
50
- interface SandboxResult {
51
- phase: 'setup' | 'run' | 'test';
52
- exitCode: number;
53
- stdout: string;
54
- stderr: string;
55
- wallMs: number;
56
- testsTotal?: number;
57
- testsPassed?: number;
58
- /**
59
- * True when the process was killed because it exceeded `timeoutMs`. A
60
- * SIGKILLed child can still close with exit code 0; callers MUST treat
61
- * a timed-out phase as a hard failure regardless of `exitCode`, never
62
- * as a pass. `undefined`/`false` means the process completed on its own.
63
- */
64
- killedByTimeout?: boolean;
65
- /**
66
- * True when captured stdout/stderr hit `maxOutputBytes` and further
67
- * output was dropped. The result is still returned (the process was
68
- * not killed for this), but downstream parsers see truncated text.
69
- */
70
- outputTruncated?: boolean;
71
- }
72
- interface SandboxDriver {
73
- id: string;
74
- exec(phase: SandboxResult['phase'], command: string, config: HarnessConfig): Promise<SandboxResult>;
75
- }
76
- /** Vitest default summary line: "Tests X passed | Y failed". */
77
- declare const vitestTestParser: TestOutputParser;
78
- /** Pytest default: "collected N items" + " X passed, Y failed". */
79
- declare const pytestTestParser: TestOutputParser;
80
- /** Jest: "Tests: X passed, Y total" (and optional failed). */
81
- declare const jestTestParser: TestOutputParser;
82
- /** Composite parser — tries a list of parsers in order. */
83
- declare function composeParsers(...parsers: TestOutputParser[]): TestOutputParser;
84
- interface SubprocessSandboxDriverOptions {
85
- /**
86
- * Default cwd for all `exec` calls. Used when the per-call `HarnessConfig`
87
- * does not set its own `cwd`. Lets callers bind the driver to a working
88
- * directory once instead of spreading cwd into every harness config —
89
- * useful when the harness config is constructed far from the call site
90
- * (e.g. starter-foundry's promoter passes a static HarnessConfig per
91
- * family taxonomy but needs a per-run composed-scaffold cwd).
92
- */
93
- cwd?: string;
94
- /**
95
- * Default env merged into every `exec` call's env (per-call `HarnessConfig.env`
96
- * still wins on key collision). Same ergonomic rationale as `cwd` above.
97
- */
98
- env?: Record<string, string>;
99
- }
100
- declare class SubprocessSandboxDriver implements SandboxDriver {
101
- id: string;
102
- private defaultCwd?;
103
- private defaultEnv?;
104
- constructor(options?: SubprocessSandboxDriverOptions);
105
- exec(phase: SandboxResult['phase'], command: string, config: HarnessConfig): Promise<SandboxResult>;
106
- }
107
- declare class DockerSandboxDriver implements SandboxDriver {
108
- id: string;
109
- exec(phase: SandboxResult['phase'], command: string, config: HarnessConfig): Promise<SandboxResult>;
110
- }
111
- interface SandboxHarnessResult {
112
- passed: boolean;
113
- setup?: SandboxResult;
114
- run?: SandboxResult;
115
- test?: SandboxResult;
116
- totalWallMs: number;
117
- /** Final score — 0 when no tests; otherwise testsPassed/testsTotal. */
118
- score: number;
119
- }
120
- declare class SandboxHarness {
121
- private driver;
122
- constructor(driver?: SandboxDriver);
123
- run(config: HarnessConfig, emitter: TraceEmitter): Promise<SandboxHarnessResult>;
124
- }
125
-
126
- /**
127
- * TestGradedScenario — a scenario whose score comes from a test suite.
128
- *
129
- * This is the SWE-bench pattern generalized. The scenario ships:
130
- * - fixture data (setup instructions)
131
- * - a test command the harness runs
132
- * - optional assertion overrides
133
- *
134
- * The runner emits a run, delegates to SandboxHarness, records the
135
- * outcome, and returns a structured verdict. Consumers bind their own
136
- * agent execution to this contract.
137
- */
138
-
139
- interface TestGradedScenario {
140
- id: string;
141
- description?: string;
142
- harness: HarnessConfig;
143
- /** Optional pass threshold in 0..1 (default 1.0 = all tests must pass). */
144
- passThreshold?: number;
145
- /** Provenance for dataset tracking. */
146
- datasetVersion?: string;
147
- /** Free-form tags (difficulty, category, etc.). */
148
- tags?: Record<string, string>;
149
- }
150
- interface TestGradedRunOptions {
151
- variantId?: string;
152
- driver?: SandboxDriver;
153
- /** Metadata recorded on the Run (codeSha, promptSha, modelFingerprint, seed). */
154
- provenance?: Pick<Run, 'codeSha' | 'promptSha' | 'modelFingerprint' | 'seed' | 'envFingerprint'>;
155
- }
156
- interface TestGradedRunResult {
157
- runId: string;
158
- scenario: TestGradedScenario;
159
- harness: SandboxHarnessResult;
160
- pass: boolean;
161
- score: number;
162
- failureClass?: FailureClass;
163
- }
164
- declare function runTestGradedScenario(scenario: TestGradedScenario, store: TraceStore, options?: TestGradedRunOptions): Promise<TestGradedRunResult>;
165
-
166
- export { DockerSandboxDriver as D, type HarnessConfig as H, type SandboxDriver as S, type TestGradedScenario as T, type SandboxHarnessResult as a, type TestGradedRunResult as b, SandboxHarness as c, type SandboxResult as d, SubprocessSandboxDriver as e, type SubprocessSandboxDriverOptions as f, type TestGradedRunOptions as g, type TestOutputParser as h, composeParsers as i, jestTestParser as j, pytestTestParser as p, runTestGradedScenario as r, vitestTestParser as v };