@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,17 +1,1277 @@
1
- export { R as RubricOutcomePair, a as RubricPredictiveValidityInput, b as RubricPredictiveValidityReport, c as RubricRanking, r as rubricPredictiveValidity } from './rubric-predictive-validity-p49lLVrE.js';
2
- export { B as BootstrapOptions, a as BootstrapResult, J as JudgeReplayGateArgs, R as ReleaseConfidenceAxis, b as ReleaseConfidenceAxisName, c as ReleaseConfidenceInput, d as ReleaseConfidenceIssue, e as ReleaseConfidenceMetrics, f as ReleaseConfidenceScorecard, g as ReleaseConfidenceStatus, h as ReleaseConfidenceThresholds, i as ReleaseTraceEvidence, j as RenderReleaseReportOptions, V as Verdict, k as assertReleaseConfidence, l as bootstrapCi, m as evaluateReleaseConfidence, n as judgeReplayGate, r as renderReleaseReport } from './release-report-C8G2i5Xi.js';
3
- export { I as InterimReleaseConfidence, a as InterimReleaseConfidenceInput, P as PairedEvalueOptions, b as PairedEvalueSequence, c as PairedEvalueStep, S as SequentialDecision, e as evaluateInterimReleaseConfidence, p as pairedEvalueSequence } from './sequential-5iSVfzl2.js';
4
- export { P as PairedBootstrapOptions, a as PairedBootstrapResult, b as benjaminiHochberg, p as pairedBootstrap, w as wilcoxonSignedRank } from './statistics-KUnG73jH.js';
5
- export { G as GainDistributionBin, a as GainDistributionFigureSpec, b as GainDistributionOptions, P as ParetoFigureSpec, c as ParetoPoint, R as RESEARCH_REPORT_HARD_PAIR_FLOOR, d as ResearchReport, e as ResearchReportCandidate, f as ResearchReportDecision, g as ResearchReportMethodology, h as ResearchReportOptions, i as ResearchReportRecommendation, S as SummaryTable, j as SummaryTableOptions, k as SummaryTableRow, l as gainHistogram, p as paretoChart, r as researchReport, s as summaryTable } from './summary-report-C5bKFfm-.js';
6
- import './run-record-BDH49H2E.js';
7
- import '@tangle-network/agent-interface';
8
- import './errors-oeQrLqXC.js';
9
- import './schema-B3Q3l9Z_.js';
10
- import './outcome-store-rnXLEqSn.js';
11
- import './dataset-NENEzRgk.js';
12
- import './judge-calibration-7C-IDmKr.js';
13
- import './types-BkfcQnxV.js';
14
- import './cost-ledger-DWy3XdJc.js';
15
- import '@tangle-network/tcloud';
16
- import './failure-cluster-DOAcSJ87.js';
17
- import './store-DGqD0Pyo.js';
1
+ type AgentProfileCellSchemaVersion = 'agent-profile-cell/v1';
2
+ type AgentProfileDimensionValue = string | number | boolean | null;
3
+ interface AgentProfileSource {
4
+ /** Runtime/profile contract being fingerprinted, e.g. `agent-interface-profile`. */
5
+ kind: string;
6
+ /** sha256 over the canonical source profile object. */
7
+ hash: string;
8
+ }
9
+ interface AgentProfileHarness {
10
+ id: string;
11
+ version?: string;
12
+ hash?: string;
13
+ }
14
+ interface AgentProfileCell {
15
+ schemaVersion: AgentProfileCellSchemaVersion;
16
+ cellId: string;
17
+ profileId: string;
18
+ sourceProfile: AgentProfileSource;
19
+ harness?: AgentProfileHarness;
20
+ model?: string;
21
+ promptHash?: string;
22
+ dimensions?: Record<string, AgentProfileDimensionValue>;
23
+ }
24
+
25
+ type FailureClass = 'success' | 'reasoning_error' | 'tool_selection_error' | 'tool_argument_error' | 'tool_recovery_failure' | 'hallucination' | 'instruction_following' | 'safety_refusal_miss' | 'policy_violation' | 'budget_exceeded' | 'format_drift' | 'permission_escalation' | 'pii_leak' | 'cost_overrun' | 'timeout' | 'sandbox_failure' | 'missing_user_data' | 'missing_domain_data' | 'missing_codebase_context' | 'missing_runtime_context' | 'missing_credentials' | 'missing_integration_connection' | 'missing_integration_scope' | 'integration_approval_required' | 'integration_auth_expired' | 'integration_provider_failure' | 'bad_integration_manifest' | 'unsafe_integration_write_denied' | 'stale_external_data' | 'bad_retrieval' | 'insufficient_evidence' | 'contradictory_evidence' | 'ambiguous_user_intent' | 'knowledge_readiness_blocked' | 'unknown';
26
+
27
+ /**
28
+ * Paper-grade RunRecord schema + runtime validator.
29
+ *
30
+ * Every run that participates in a promotion gate, paper table, or
31
+ * researcher loop SHOULD be recorded as a `RunRecord`. The mandatory
32
+ * fields are exactly those the paper "Two Loops, Three Roles" requires
33
+ * for reproducibility: who/what/when/cost/seed/hash, plus the search vs
34
+ * holdout split tag and either a `searchScore` or a `holdoutScore`.
35
+ *
36
+ * This is intentionally NOT a replacement for the rich `Run` /
37
+ * `ProposeReviewReport` / `ScenarioResult` types already in the
38
+ * package. Those are runtime structures with full provenance. A
39
+ * `RunRecord` is the analysis-time projection — the JSON-friendly
40
+ * row you'd put in a parquet file or paste into a notebook.
41
+ *
42
+ * Validate at the boundary:
43
+ *
44
+ * const rec = validateRunRecord(rawJson) // throws on missing
45
+ * const ok = isRunRecord(rawJson) // boolean check
46
+ * const rec = parseRunRecordSafe(rawJson) // { ok, value | error }
47
+ *
48
+ * The validator runs in pure TS — zod is intentionally NOT a
49
+ * dependency. Round-trip tested in `tests/run-record.test.ts`.
50
+ */
51
+
52
+ /** Search/dev/holdout split tag. 'search' is the paper-grade alias for the
53
+ * combined train+test pool that the optimizer is allowed to read. */
54
+ type RunSplitTag = 'search' | 'dev' | 'holdout';
55
+ interface RunTokenUsage {
56
+ input: number;
57
+ /** All generated tokens charged as output, including reasoning tokens. */
58
+ output: number;
59
+ /** Reasoning-token subset of `output`, when the provider reports it. */
60
+ reasoning?: number;
61
+ /** Prompt tokens served from a provider cache. */
62
+ cached?: number;
63
+ /** Prompt tokens written into a provider cache. */
64
+ cacheWrite?: number;
65
+ }
66
+ /**
67
+ * How a run's USD amount was obtained.
68
+ *
69
+ * `costUsd` remains mandatory for wire compatibility. New producers should
70
+ * always populate this discriminated union so a missing bill is never
71
+ * mistaken for an observed zero-dollar run. For `uncaptured`, `costUsd` uses
72
+ * the legacy `0` sentinel while this field carries the truthful null.
73
+ */
74
+ type RunCostProvenance = {
75
+ kind: 'observed';
76
+ usd: number;
77
+ } | {
78
+ kind: 'estimated';
79
+ usd: number;
80
+ } | {
81
+ kind: 'uncaptured';
82
+ usd: null;
83
+ };
84
+ interface RunJudgeMetadata {
85
+ model: string;
86
+ promptVersion: string;
87
+ /** [0,1] confidence the judge declared. Constant judge confidence
88
+ * across many runs is a fallback signal (see `canary.ts`). */
89
+ confidence: number;
90
+ /** True if the judge degraded to a fallback path (rules-only,
91
+ * prior-call cache, etc.). The canary uses this to alert. */
92
+ fallback: boolean;
93
+ }
94
+ /**
95
+ * Per-judge / per-dimension breakdown for runs scored by an ensemble of
96
+ * judges over a multi-dimensional rubric.
97
+ *
98
+ * The collapsed `outcome.searchScore` / `holdoutScore` carries the
99
+ * composite the gate uses. The full breakdown belongs here so consumers
100
+ * can answer "which judge disagreed?", "which dimension dragged the
101
+ * composite down?", and "did half the panel fail?" without re-running.
102
+ *
103
+ * `perJudge[judgeId][dim]` is the canonical source; `perDimMean` and
104
+ * `composite` are convenience projections — derivable but precomputed so
105
+ * downstream IRR primitives (`interRaterReliability`,
106
+ * `corpusInterRaterAgreement`) and reporters don't pay the same
107
+ * aggregation twice.
108
+ *
109
+ * Fail-loud discipline: judges that errored out land in `failedJudges`
110
+ * by id. A missing key in `perJudge` is ambiguous (silent zero vs not
111
+ * run); the explicit list makes a partial-failure recorded as such.
112
+ */
113
+ interface JudgeScoresRecord {
114
+ /** Per-judge per-dimension scores. `{ "kimi-k2.6": { helpfulness: 0.8, clarity: 0.7 }, ... }`. */
115
+ perJudge: Record<string, Record<string, number>>;
116
+ /** Per-dim mean across judges. Convenience — derivable from `perJudge`. */
117
+ perDimMean: Record<string, number>;
118
+ /** Composite mean across all dims and judges. Mirrors the score
119
+ * the gate sees on `outcome.searchScore` / `holdoutScore`. */
120
+ composite: number;
121
+ /** Judges that errored or returned an unparseable verdict. Recorded
122
+ * by id (e.g. `['glm-5.1']`) so a partial-failure case is explicit,
123
+ * not inferred from missing keys in `perJudge`. */
124
+ failedJudges?: string[];
125
+ /** Free-form notes the judges emitted (joined across judges or
126
+ * first-judge only — consumer's choice). */
127
+ notes?: string;
128
+ }
129
+ interface RunOutcome {
130
+ /** Score on the search/optimization split. Optional because a
131
+ * holdout-only evaluation only fills `holdoutScore`. */
132
+ searchScore?: number;
133
+ /** Score on the held-out split. Optional because a search-only run
134
+ * only fills `searchScore`. At least one must be present. */
135
+ holdoutScore?: number;
136
+ /** Bag of any other metric the run produced — judge dimensions,
137
+ * pass/fail counters, latency stats, etc. Numeric only — keeps
138
+ * reporters honest. */
139
+ raw: Record<string, number>;
140
+ /** Per-judge / per-dim breakdown. Consumers writing ensemble
141
+ * judgements populate this; substrate primitives like
142
+ * `interRaterReliability` and `corpusInterRaterAgreement` accept
143
+ * these records as input. Optional — single-judge or scalar-only
144
+ * runs leave it unset. */
145
+ judgeScores?: JudgeScoresRecord;
146
+ /** Authenticity / realness verdict — did the run build the REAL thing on the
147
+ * intended infra, or fake it (see `./authenticity`)? Optional: only domains
148
+ * with an authenticity config populate it. Carried in the corpus so the
149
+ * flywheel / off-policy learning can optimize for real completion, not gamed
150
+ * pass-rate. `score` is 0-1; `gated` is the anti-Goodhart flag — a gated run
151
+ * must not count as a real success regardless of `score`. */
152
+ realness?: {
153
+ score: number;
154
+ gated: boolean;
155
+ reason?: string;
156
+ };
157
+ }
158
+ /**
159
+ * Mandatory paper-grade fields for a single evaluation run. Optional
160
+ * fields are extension points; mandatory fields throw if missing.
161
+ *
162
+ * Hash discipline:
163
+ * - `promptHash` is the sha256 of the EFFECTIVE prompt sent to the
164
+ * model (after any steering bundle merge).
165
+ * - `configHash` is the sha256 of the effective run config (model,
166
+ * temperature, tools, judges, splits). The pair (promptHash,
167
+ * configHash) uniquely identifies an experiment cell.
168
+ *
169
+ * Model snapshot discipline:
170
+ * - `model` MUST encode a snapshot version. Bare aliases like
171
+ * `claude-sonnet-4` or `gpt-4o` are banned — they remap silently.
172
+ * Use `claude-sonnet-4-6@2025-04-15` or `gpt-4o-2024-11-20`.
173
+ */
174
+ interface RunRecord {
175
+ /** UUID for the run. */
176
+ runId: string;
177
+ /** Logical experiment grouping (a treatment vs a baseline within
178
+ * the same sweep should share `experimentId`). */
179
+ experimentId: string;
180
+ /** Stable identifier for the candidate (variant) being run. The
181
+ * promotion gate compares two `candidateId`s on matched items. */
182
+ candidateId: string;
183
+ /** RNG seed for the run. Always recorded — silent re-seeding is
184
+ * the most common cause of non-reproducible numbers. */
185
+ seed: number;
186
+ /** Model identifier WITH snapshot version. */
187
+ model: string;
188
+ /** sha256 of the effective prompt (post-steering). */
189
+ promptHash: string;
190
+ /** sha256 of the effective config. */
191
+ configHash: string;
192
+ /** Git SHA the harness was run from. */
193
+ commitSha: string;
194
+ /** End-to-end wall-clock duration in milliseconds. */
195
+ wallMs: number;
196
+ /** Time spent queued before execution started, if known. */
197
+ queueMs?: number;
198
+ /** Total USD cost. Mandatory — runs without a cost number are
199
+ * unbounded by definition and must not be admitted into the gate.
200
+ * `0` is retained as the compatibility sentinel for an uncaptured amount;
201
+ * inspect `costProvenance` before treating it as observed. */
202
+ costUsd: number;
203
+ /** Observed, model-priced estimate, or genuinely uncaptured USD amount.
204
+ * Optional only so existing serialized RunRecords remain valid. */
205
+ costProvenance?: RunCostProvenance;
206
+ /** Token usage breakdown. */
207
+ tokenUsage: RunTokenUsage;
208
+ /** Judge-side metadata, if a judge was used. */
209
+ judgeMetadata?: RunJudgeMetadata;
210
+ /** Per-split scores + raw bag. */
211
+ outcome: RunOutcome;
212
+ /** Canonical, cross-agent failure class drawn from the shared
213
+ * `FAILURE_CLASSES` taxonomy. This is the aggregation key that makes
214
+ * "which failure dominates across the whole fleet" answerable in ONE
215
+ * vocabulary — every agent classifies against the same enum. Producers
216
+ * set it via the substrate classifier; leave unset only when the failure
217
+ * genuinely can't be classified. */
218
+ failureClass?: FailureClass;
219
+ /** Free-form domain-specific failure detail, scoped UNDER `failureClass`
220
+ * (e.g. failureClass='tool_recovery_failure', failureMode='forge_build_unsatisfied').
221
+ * The within-agent drill-down; `failureClass` is the cross-agent key. */
222
+ failureMode?: string;
223
+ /** Which split this run was drawn from. */
224
+ splitTag: RunSplitTag;
225
+ /**
226
+ * Stable scenario identifier the run was scored against. Optional for
227
+ * backwards compatibility, but **strongly recommended**: every primitive
228
+ * that pairs runs by scenario (preferences, paired stats, BT tournament)
229
+ * keys on this. The campaign artifact populates it canonically; legacy
230
+ * runs without it fall back to inference from `outcome.raw.scenario_id`
231
+ * or `experimentId`.
232
+ */
233
+ scenarioId?: string;
234
+ /**
235
+ * Canonical identity for the agent profile cell that produced this row:
236
+ * profile artifact hash plus optional harness/model/prompt/reporting
237
+ * dimensions. Use `agentProfile.cellId` to group persona sweeps and
238
+ * longitudinal reports by the complete source profile, not by a loose
239
+ * candidate label or opaque config hash.
240
+ */
241
+ agentProfile?: AgentProfileCell;
242
+ }
243
+
244
+ /**
245
+ * OutcomeStore — deployment outcomes attached to Run IDs.
246
+ *
247
+ * Outcomes arrive asynchronously from production telemetry after the
248
+ * eval run completed: user ratings, retention flags, conversion events,
249
+ * revenue, support-ticket rate, anything a product team can measure.
250
+ * The store is a peer to TraceStore — separate lifecycle, same runId
251
+ * foreign key.
252
+ *
253
+ * The whole point of this module is to make the meta-eval correlation
254
+ * question computable: `correlate(evalMetric, outcomeMetric) → r, ρ, n, CI`.
255
+ */
256
+ interface DeploymentOutcome {
257
+ runId: string;
258
+ capturedAt: number;
259
+ /** Numeric outcomes keyed by name — retention_7d, csat, revenue_usd, etc. */
260
+ metrics: Record<string, number>;
261
+ /** Dimensions for stratified analysis — cohort, region, user_segment. */
262
+ labels?: Record<string, string>;
263
+ /** Free-form provenance (source system, pipeline version). */
264
+ source?: string;
265
+ }
266
+ interface OutcomeFilter {
267
+ runIds?: string[];
268
+ since?: number;
269
+ until?: number;
270
+ label?: {
271
+ key: string;
272
+ value: string;
273
+ };
274
+ source?: string;
275
+ }
276
+ interface OutcomeStore {
277
+ append(outcome: DeploymentOutcome): Promise<void>;
278
+ /** All outcomes attached to this run (a single run can have many — multiple
279
+ * capture windows over deployment time). */
280
+ forRun(runId: string): Promise<DeploymentOutcome[]>;
281
+ list(filter?: OutcomeFilter): Promise<DeploymentOutcome[]>;
282
+ }
283
+
284
+ /**
285
+ * Rubric predictive validity — does our eval rubric predict deployment
286
+ * outcomes?
287
+ *
288
+ * `correlationStudy` (already in this package) joins a `TraceStore` to an
289
+ * `OutcomeStore` and computes Pearson + Spearman + bootstrap CI for each
290
+ * (eval-metric, outcome-metric) pair. That answers "does X correlate with
291
+ * Y at all." `rubricPredictiveValidity` is the campaign-shaped wrapper
292
+ * around it: take a sequence of `RunRecord`s (the canonical campaign
293
+ * artifact) and a `DeploymentOutcomeStore`, join on `runId`, return a
294
+ * ranked verdict on every rubric whose dimension scores were captured in
295
+ * `outcome.raw`.
296
+ *
297
+ * The point — quoting the methodology doc — is that **without this loop
298
+ * every rubric is faith-based**. Once it's wired, you know which rubrics
299
+ * have earned their promotion power and which ones are decoration.
300
+ *
301
+ * const validity = await rubricPredictiveValidity({
302
+ * runs: lastQuarter,
303
+ * outcomes: shipFlagOutcomeStore,
304
+ * outcomeMetrics: ['revenue_lift', 'retention_30d', 'csat'],
305
+ * rubrics: ['anti_slop', 'semantic_concept', 'tool_recovery'],
306
+ * })
307
+ * for (const r of validity.ranked) {
308
+ * console.log(`${r.rubric} → ${r.bestOutcome}: ρ=${r.spearman.toFixed(2)}`)
309
+ * }
310
+ *
311
+ * The function is intentionally read-only. Use the verdict to deprecate
312
+ * decorative rubrics, re-weight composite scores, or trigger a
313
+ * recalibration sweep when predictive validity drops below a threshold.
314
+ */
315
+
316
+ interface RubricPredictiveValidityInput {
317
+ /**
318
+ * Canonical campaign output. Each record's `outcome.raw[<rubricId>]`
319
+ * provides the eval score; missing keys are silently skipped per pair.
320
+ */
321
+ runs: RunRecord[];
322
+ outcomes: OutcomeStore;
323
+ /**
324
+ * Outcome metric names to evaluate against. Each must appear in at
325
+ * least one `DeploymentOutcome.metrics` keyspace; pairs with too few
326
+ * joined samples are excluded from the result.
327
+ */
328
+ outcomeMetrics: string[];
329
+ /**
330
+ * Rubric ids to evaluate. Must appear as keys in `RunRecord.outcome.raw`.
331
+ * If omitted, every numeric key in `outcome.raw` across the run set is
332
+ * treated as a rubric.
333
+ */
334
+ rubrics?: string[];
335
+ /** Minimum joined-sample count before a pair is reported. Default 8. */
336
+ minSamples?: number;
337
+ /** Bootstrap resamples for CI. Default 500. */
338
+ bootstrapResamples?: number;
339
+ /** Random seed for the bootstrap (mulberry32). Default unset (Math.random). */
340
+ seed?: number;
341
+ /**
342
+ * Reduction when multiple outcomes attach to one runId. Default `'latest'`
343
+ * (most recently captured).
344
+ */
345
+ reduction?: 'latest' | 'mean' | 'max';
346
+ }
347
+ interface RubricOutcomePair {
348
+ rubric: string;
349
+ outcome: string;
350
+ n: number;
351
+ pearson: number;
352
+ spearman: number;
353
+ ci95: {
354
+ low: number;
355
+ high: number;
356
+ };
357
+ /**
358
+ * Verdict bucket. `load_bearing` ≥ 0.7, `informative` ≥ 0.4,
359
+ * `decorative` < 0.4 in absolute correlation. A negative correlation
360
+ * with a desired outcome is also `decorative` — actively misleading
361
+ * is worse than uninformative.
362
+ */
363
+ verdict: 'load_bearing' | 'informative' | 'decorative';
364
+ }
365
+ interface RubricRanking {
366
+ rubric: string;
367
+ /** Outcome metric this rubric correlated best with. */
368
+ bestOutcome: string;
369
+ spearman: number;
370
+ pearson: number;
371
+ n: number;
372
+ verdict: RubricOutcomePair['verdict'];
373
+ }
374
+ interface RubricPredictiveValidityReport {
375
+ pairs: RubricOutcomePair[];
376
+ /** Per-rubric best pair, sorted descending by |spearman|. */
377
+ ranked: RubricRanking[];
378
+ joinedSamples: number;
379
+ skippedRuns: number;
380
+ /** Rubrics that were declared but never produced a usable score. */
381
+ rubricsWithoutData: string[];
382
+ }
383
+ declare function rubricPredictiveValidity(input: RubricPredictiveValidityInput): Promise<RubricPredictiveValidityReport>;
384
+
385
+ /**
386
+ * Bootstrap-CI promotion gate.
387
+ *
388
+ * In any iterative-improvement loop (GEPA, prompt evolution, dataset
389
+ * curation), the question is "did this generation actually improve, or are
390
+ * we celebrating noise?". With small N and noisy outcomes, point-estimate
391
+ * deltas lie. Bootstrap confidence intervals tell the operator whether the
392
+ * delta is real before code or prompts get promoted.
393
+ *
394
+ * This module is pure functions — no I/O, no model calls. Easy to unit-test
395
+ * and to compose into any verdict gate.
396
+ *
397
+ * Default gate:
398
+ * - Bootstrap mean baseline vs candidate (1k resamples).
399
+ * - Compute the delta distribution; pass if the lower CI bound > 0.
400
+ * - Tunable confidence (default 95%) and resample count.
401
+ *
402
+ * Verdict semantics intentionally match the existing `experiments.jsonl`
403
+ * vocabulary:
404
+ * - ADVANCE: candidate's CI lower bound > baseline mean (real win)
405
+ * - KEEP: overlap, but candidate point estimate >= baseline (neutral)
406
+ * - REVERT: candidate's CI upper bound < baseline mean (real regression)
407
+ * - INCONCLUSIVE: not enough samples or CI straddles zero with no signal
408
+ */
409
+ type Verdict = 'ADVANCE' | 'KEEP' | 'REVERT' | 'INCONCLUSIVE';
410
+ interface BootstrapResult {
411
+ baselineMean: number;
412
+ candidateMean: number;
413
+ /** candidateMean - baselineMean, point estimate. */
414
+ delta: number;
415
+ /** Lower bound of the (1 - alpha) CI on the delta. */
416
+ ciLower: number;
417
+ /** Upper bound of the (1 - alpha) CI on the delta. */
418
+ ciUpper: number;
419
+ /** Number of bootstrap resamples used. */
420
+ iterations: number;
421
+ alpha: number;
422
+ verdict: Verdict;
423
+ }
424
+ interface BootstrapOptions {
425
+ /** Confidence level alpha (default 0.05 → 95% CI). */
426
+ alpha?: number;
427
+ /** Number of resamples (default 1000). */
428
+ iterations?: number;
429
+ /**
430
+ * Minimum total samples (baseline + candidate) below which we always
431
+ * return INCONCLUSIVE — bootstrap with too few samples is meaningless.
432
+ * Default 6 (combined).
433
+ */
434
+ minTotalSamples?: number;
435
+ /** RNG seed for reproducibility. Default: Math.random. */
436
+ seed?: number;
437
+ }
438
+ /**
439
+ * Compute the bootstrap CI on (candidateMean - baselineMean) and a verdict.
440
+ *
441
+ * Uses simple percentile bootstrap on the difference of resampled means.
442
+ * That's the standard non-parametric primitive — no distributional
443
+ * assumptions, robust to skew, easy to reason about.
444
+ */
445
+ declare function bootstrapCi(baseline: number[], candidate: number[], options?: BootstrapOptions): BootstrapResult;
446
+ /**
447
+ * Judge-replay promotion gate.
448
+ *
449
+ * The cheap inner-loop judge that drives an evolution run is by definition
450
+ * fast and noisy. When you're about to promote a winning variant to the
451
+ * canonical default, you want a STRONGER judge (a more expensive model, a
452
+ * human grader, a separately-trained reward model) to confirm the win
453
+ * generalises beyond the inner loop.
454
+ *
455
+ * This helper takes raw winner + baseline outputs, scores both through the
456
+ * stronger judge, and applies `bootstrapCi`. ADVANCE means the stronger
457
+ * judge agrees the winner is real with the configured confidence. Doesn't
458
+ * matter what shape your "output" is — pass a string, an object, anything
459
+ * the judge can read.
460
+ */
461
+ interface JudgeReplayGateArgs<TOutput> {
462
+ baselineOutputs: TOutput[];
463
+ candidateOutputs: TOutput[];
464
+ /** Stronger judge — async to allow LLM calls. Return a 0..N scalar score. */
465
+ judge: (output: TOutput) => Promise<number> | number;
466
+ alpha?: number;
467
+ iterations?: number;
468
+ /** RNG seed for reproducibility. */
469
+ seed?: number;
470
+ /** Maximum concurrent judge calls. Default 4. */
471
+ judgeConcurrency?: number;
472
+ }
473
+ /**
474
+ * Confirm a candidate's win with a stronger judge: score baseline and candidate outputs independently, then bootstrap a CI to verify the lift generalises beyond the inner loop.
475
+ */
476
+ declare function judgeReplayGate<TOutput>(args: JudgeReplayGateArgs<TOutput>): Promise<BootstrapResult & {
477
+ baselineSamples: number;
478
+ candidateSamples: number;
479
+ }>;
480
+
481
+ /**
482
+ * Dataset — versioned, sliceable, content-hashed scenario collection.
483
+ *
484
+ * Scenarios stop being ephemeral arrays and become first-class
485
+ * artifacts. Every Dataset carries:
486
+ * - content hash (sha256 over canonicalized scenario array)
487
+ * - provenance (contributor, createdAt, sourceUrl)
488
+ * - split labels (train | dev | test | holdout)
489
+ * - difficulty tiers (easy | medium | hard | extreme)
490
+ * - tags (free-form, per-scenario)
491
+ *
492
+ * `Dataset.slice({ difficulty, split, holdout, seed })` returns a
493
+ * deterministic, reproducible subset. Holdout slices are locked: you
494
+ * can read them but `mutate` throws, which prevents "oh I'll just
495
+ * tweak that one scenario" contamination drift.
496
+ */
497
+ type DatasetSplit = 'train' | 'dev' | 'test' | 'holdout';
498
+ type DatasetDifficulty = 'easy' | 'medium' | 'hard' | 'extreme';
499
+ interface DatasetScenario {
500
+ id: string;
501
+ /** Arbitrary payload; the framework doesn't interpret it. */
502
+ payload: unknown;
503
+ split?: DatasetSplit;
504
+ difficulty?: DatasetDifficulty;
505
+ /** Canary token that MUST NOT round-trip through a correct agent output. */
506
+ canary?: string;
507
+ /**
508
+ * Behavioral-canary forbidden pattern. A string OR a serialized regex
509
+ * (`/.../flags`) that the agent under test MUST NOT emit. Used by
510
+ * {@link import('./canary').checkBehavioralCanary | checkBehavioralCanary},
511
+ * which inverts the contamination-style semantic: presence in the
512
+ * agent output is a LEAK / failure, not a positive signal.
513
+ *
514
+ * Falls back to {@link canary} when omitted.
515
+ */
516
+ forbiddenPattern?: string;
517
+ tags?: Record<string, string>;
518
+ }
519
+ interface DatasetProvenance {
520
+ contributor?: string;
521
+ createdAt: string;
522
+ sourceUrl?: string;
523
+ license?: string;
524
+ description?: string;
525
+ /** Monotonic human-readable version (e.g. "2026.04.20"). */
526
+ version: string;
527
+ }
528
+ interface DatasetManifest {
529
+ name: string;
530
+ provenance: DatasetProvenance;
531
+ /** sha256 hex over canonicalized scenarios. */
532
+ contentHash: string;
533
+ scenarioCount: number;
534
+ splitCounts: Record<DatasetSplit, number>;
535
+ }
536
+
537
+ /**
538
+ * HeldOutGate — first-class held-out paired-delta promotion gate.
539
+ *
540
+ * Encodes the "honesty override" pattern that lived inline in
541
+ * `~/webb/redteam/scripts/agent-eval-autoresearch.ts:138–171`.
542
+ * The optimizer's best-guess is one thing; what we should actually
543
+ * ship is another. The gate is the line between them.
544
+ *
545
+ * A candidate is promoted iff ALL three pass:
546
+ *
547
+ * 1. **Productive runs**: the candidate has at least
548
+ * `minProductiveRuns` paired observations on items where BOTH
549
+ * candidate and baseline produced a real (non-silent) score.
550
+ * 2. **Paired delta**: the lower bound of the bootstrap CI on the
551
+ * median per-item delta (candidate − baseline) on the HOLDOUT
552
+ * split is strictly greater than `pairedDeltaThreshold`.
553
+ * 3. **Overfit gap**: the candidate's gap between search-split
554
+ * score and holdout-split score is no worse (more positive)
555
+ * than the baseline's gap by more than `overfitGapThreshold`.
556
+ * "Better on search, worse on holdout" is the canonical
557
+ * overfit pattern; this catches it.
558
+ *
559
+ * The decision carries a machine-readable `rejectionCode` plus an
560
+ * `evidence` block with every number the gate looked at, so the
561
+ * downstream researcher / paper / dashboard can re-derive the
562
+ * verdict without re-running.
563
+ *
564
+ * See also:
565
+ * - `src/statistics.ts` for `pairedBootstrap` + `wilcoxonSignedRank`
566
+ * - `src/run-record.ts` for the input row schema
567
+ * - `src/reference-replay.ts` for the older, reference-replay-
568
+ * specific promotion path (still useful for replay-style evals).
569
+ */
570
+
571
+ type HeldOutGateRejectionCode = 'few_runs' | 'negative_delta' | 'overfit_gap' | 'cost_ceiling';
572
+ interface GateEvidence {
573
+ /** Number of paired (candidate, baseline) holdout observations used. */
574
+ productiveRuns: number;
575
+ /** Median of (candidate − baseline) paired holdout deltas. */
576
+ medianPairedDelta: number;
577
+ /** Bootstrap CI on the median paired holdout delta. */
578
+ pairedCI: {
579
+ low: number;
580
+ high: number;
581
+ };
582
+ /** Wilcoxon signed-rank p-value on the paired holdout deltas. */
583
+ pairedPValue: number;
584
+ /** Mean candidate score on the search split (NaN if none). */
585
+ searchScore: number;
586
+ /** Mean candidate score on the holdout split (NaN if none). */
587
+ holdoutScore: number;
588
+ /** Candidate (search − holdout) gap. */
589
+ overfitGap: number;
590
+ /** Baseline (search − holdout) gap. */
591
+ baselineOverfitGap: number;
592
+ /** Median per-task USD cost across the candidate's runs. Recorded
593
+ * even when no `costPerTaskCeiling` is configured so downstream
594
+ * dashboards (intelligence.tangle.tools) can render \$/task per
595
+ * generation regardless of gating policy. */
596
+ medianCandidateCost: number;
597
+ /** Median per-task USD cost across the baseline runs, for
598
+ * symmetric reporting. */
599
+ medianBaselineCost: number;
600
+ }
601
+ interface GateDecision {
602
+ /** Final promote/no-promote verdict. */
603
+ promote: boolean;
604
+ /** The candidate that was evaluated. */
605
+ candidateId: string;
606
+ /** The baseline it was compared against. */
607
+ baselineId: string;
608
+ /** Every number the gate looked at, for audit + paper export. */
609
+ evidence: GateEvidence;
610
+ /** Human-readable reason. */
611
+ reason: string;
612
+ /** Machine-readable rejection code, or null on promote. */
613
+ rejectionCode: HeldOutGateRejectionCode | null;
614
+ }
615
+
616
+ /**
617
+ * Release confidence gate.
618
+ *
619
+ * This is the production-facing composition layer over the lower-level
620
+ * primitives:
621
+ * - Dataset manifests prove corpus/version coverage.
622
+ * - RunRecord rows prove reproducible search/holdout outcomes.
623
+ * - Multi-shot trace evidence carries turn counts and ASI diagnostics.
624
+ * - HeldOutGate decisions remain the paired promotion authority.
625
+ *
626
+ * The gate is intentionally pure and conservative. Missing declared evidence
627
+ * fails closed instead of being treated as a neutral zero.
628
+ */
629
+
630
+ /** Severity of an actionable finding attached to a run/trace. */
631
+ type AsiSeverity = 'info' | 'warning' | 'error' | 'critical';
632
+ /** Actionable side-info — a diagnosed finding the loop can act on. */
633
+ interface ActionableSideInfo {
634
+ /** Stable expectation/check id when available. */
635
+ expectationId?: string;
636
+ /** Human-readable diagnosis of what happened. */
637
+ message: string;
638
+ severity?: AsiSeverity;
639
+ /** Concrete trace excerpt, file path, tool call, screenshot id, etc. */
640
+ evidence?: string;
641
+ /** Prompt/tool/context surface likely responsible. */
642
+ responsibleSurface?: string;
643
+ /** Suggested fix in natural language. */
644
+ suggestion?: string;
645
+ /** Whether this expectation was satisfied. Defaults to false for ASI rows. */
646
+ matched?: boolean;
647
+ metadata?: Record<string, unknown>;
648
+ }
649
+ type ReleaseConfidenceStatus = 'pass' | 'warn' | 'fail';
650
+ type ReleaseConfidenceAxisName = 'corpus' | 'quality' | 'generalization' | 'diagnostics' | 'efficiency';
651
+ interface ReleaseTraceEvidence {
652
+ scenarioId: string;
653
+ candidateId?: string;
654
+ split?: RunSplitTag;
655
+ score?: number;
656
+ ok?: boolean;
657
+ turnCount?: number;
658
+ costUsd?: number;
659
+ durationMs?: number;
660
+ failureMode?: string;
661
+ asi?: ActionableSideInfo[];
662
+ metadata?: Record<string, unknown>;
663
+ }
664
+ interface ReleaseConfidenceThresholds {
665
+ /** Require a Dataset manifest or explicit scenarios. Default true. */
666
+ requireCorpus?: boolean;
667
+ minScenarioCount?: number;
668
+ minSearchRuns?: number;
669
+ minHoldoutRuns?: number;
670
+ /** Require at least one holdout scenario/run. Default true. */
671
+ requireHoldout?: boolean;
672
+ minPassRate?: number;
673
+ minMeanScore?: number;
674
+ /** Search mean may exceed holdout mean by at most this much. */
675
+ maxOverfitGap?: number;
676
+ maxMeanCostUsd?: number;
677
+ maxP95WallMs?: number;
678
+ /** Low-score/failed rows must carry ASI. Default true. */
679
+ requireAsiForFailures?: boolean;
680
+ /** Score below this is considered a failure for ASI coverage. Default 0.5. */
681
+ failureScoreThreshold?: number;
682
+ }
683
+ interface ReleaseConfidenceInput {
684
+ target: string;
685
+ candidateId?: string;
686
+ baselineId?: string;
687
+ dataset?: DatasetManifest;
688
+ scenarios?: readonly DatasetScenario[];
689
+ runs?: readonly RunRecord[];
690
+ traces?: readonly ReleaseTraceEvidence[];
691
+ gateDecision?: GateDecision | null;
692
+ thresholds?: ReleaseConfidenceThresholds;
693
+ }
694
+ interface ReleaseConfidenceAxis {
695
+ name: ReleaseConfidenceAxisName;
696
+ status: ReleaseConfidenceStatus;
697
+ score: number;
698
+ detail: string;
699
+ }
700
+ interface ReleaseConfidenceIssue {
701
+ axis: ReleaseConfidenceAxisName;
702
+ severity: 'critical' | 'warning';
703
+ code: string;
704
+ detail: string;
705
+ }
706
+ interface ReleaseConfidenceMetrics {
707
+ scenarioCount: number;
708
+ searchRuns: number;
709
+ holdoutRuns: number;
710
+ passRate: number;
711
+ meanScore: number;
712
+ searchMeanScore: number;
713
+ holdoutMeanScore: number;
714
+ overfitGap: number;
715
+ meanCostUsd: number;
716
+ p95WallMs: number;
717
+ failedRows: number;
718
+ failuresWithAsi: number;
719
+ singleShotTraces: number;
720
+ multiShotTraces: number;
721
+ splitCounts: Record<DatasetSplit, number>;
722
+ domainCounts: Record<string, number>;
723
+ failureModeCounts: Record<string, number>;
724
+ responsibleSurfaceCounts: Record<string, number>;
725
+ }
726
+ interface ReleaseConfidenceScorecard {
727
+ target: string;
728
+ candidateId: string | null;
729
+ baselineId: string | null;
730
+ status: ReleaseConfidenceStatus;
731
+ promote: boolean;
732
+ axes: ReleaseConfidenceAxis[];
733
+ issues: ReleaseConfidenceIssue[];
734
+ metrics: ReleaseConfidenceMetrics;
735
+ dataset: DatasetManifest | null;
736
+ gateDecision: GateDecision | null;
737
+ summary: string;
738
+ }
739
+ declare function evaluateReleaseConfidence(input: ReleaseConfidenceInput): ReleaseConfidenceScorecard;
740
+ declare function assertReleaseConfidence(input: ReleaseConfidenceInput): ReleaseConfidenceScorecard;
741
+
742
+ interface RenderReleaseReportOptions {
743
+ title?: string;
744
+ runs?: readonly RunRecord[];
745
+ comparator?: string;
746
+ traceAnalystFindings?: readonly string[];
747
+ nextActions?: readonly string[];
748
+ }
749
+ declare function renderReleaseReport(scorecard: ReleaseConfidenceScorecard, options?: RenderReleaseReportOptions): string;
750
+
751
+ /**
752
+ * Always-valid sequential evaluation.
753
+ *
754
+ * `researchReport` assumes a single pre-specified analysis. Real
755
+ * consumers run campaigns weekly / nightly / per-PR; each new run silently
756
+ * inflates the false-discovery rate, because the BH-FDR guarantee is for
757
+ * the *first* look, not the 47th. Without time-uniform inference,
758
+ * launch-decision teams either (a) don't peek, which forfeits the cost
759
+ * advantage of stop-when-decisive, or (b) peek and pretend they didn't,
760
+ * which forfeits scientific validity.
761
+ *
762
+ * This module ships **e-value-based confidence sequences** for paired
763
+ * bounded outcomes. The methodology is the predictable plug-in betting
764
+ * martingale of Waudby-Smith & Ramdas (2024) — provably valid at *any*
765
+ * stopping time. Concretely:
766
+ *
767
+ * For paired deltas D_1, D_2, … ∈ [-c, c] with the null H_0: E[D] ≤ 0,
768
+ * a betting fraction λ_i is chosen using only D_{1..i-1} (predictable
769
+ * plug-in), and the running e-value is
770
+ *
771
+ * E_t = ∏_{i=1}^{t} (1 + λ_i · D_i)
772
+ *
773
+ * E_t is a non-negative martingale under H_0 with E[E_t] ≤ 1, so by
774
+ * Ville's inequality, P(∃ t : E_t ≥ 1/α) ≤ α — we can reject the null
775
+ * at any time without inflating the type-I error.
776
+ *
777
+ * Combined with `runEvalCampaign`, every consumer running rolling
778
+ * campaigns gains the ability to ship the moment evidence is decisive,
779
+ * stop-early on dead-on-arrival variants, and accumulate evidence across
780
+ * partial runs without spending the FDR budget. No new sweep is wasted.
781
+ *
782
+ * References:
783
+ * - Howard, S. R., Ramdas, A., McAuliffe, J., Sekhon, J. (2021).
784
+ * Time-uniform, nonparametric, nonasymptotic confidence sequences.
785
+ * Annals of Statistics, 49(2), 1055–1080.
786
+ * - Waudby-Smith, I., Ramdas, A. (2024). Estimating means of bounded
787
+ * random variables by betting. JRSS B, 86(1), 1–27.
788
+ */
789
+ type SequentialDecision = 'promote_now' | 'continue' | 'reject_now' | 'equivalent';
790
+ interface PairedEvalueOptions {
791
+ /**
792
+ * Bound on |delta|. Default 1 (matching most score scales). Must satisfy
793
+ * c > 0; deltas outside [-c, c] are clipped with a warning attached to
794
+ * the return value.
795
+ */
796
+ bound?: number;
797
+ /** Target Type-I error. Default 0.05. */
798
+ alpha?: number;
799
+ /**
800
+ * Region of Practical Equivalence on the *mean* paired delta. When
801
+ * supplied, the verdict can return `'equivalent'` once the running
802
+ * confidence sequence on the mean is fully contained in [low, high].
803
+ */
804
+ rope?: {
805
+ low: number;
806
+ high: number;
807
+ };
808
+ /** Initial bet shrinkage (0 < scale ≤ 1). Default 0.5 — empirically robust. */
809
+ initialBetShrinkage?: number;
810
+ }
811
+ interface PairedEvalueStep {
812
+ /** 1-indexed observation count. */
813
+ t: number;
814
+ delta: number;
815
+ /** Running e-value E_t = ∏ (1 + λ_i · D_i). */
816
+ evalue: number;
817
+ /** Time-uniform p-value at stopping time t. */
818
+ pValue: number;
819
+ /** Lower bound of the empirical Bernstein confidence sequence at level 1-α. */
820
+ csLow: number;
821
+ csHigh: number;
822
+ /** Verdict at this stopping time. */
823
+ decision: SequentialDecision;
824
+ }
825
+ interface PairedEvalueSequence {
826
+ steps: PairedEvalueStep[];
827
+ /** The decision at the final step. */
828
+ finalDecision: SequentialDecision;
829
+ /** Index (1-based) at which a non-`continue` decision first fired, or null. */
830
+ decisionFiredAt: number | null;
831
+ /** True if any deltas were clipped to [-bound, bound]. */
832
+ clipped: boolean;
833
+ }
834
+ /**
835
+ * Run the paired e-value sequence over an in-order delta stream.
836
+ *
837
+ * Use for *streaming* / interim analyses: pass the deltas you have so
838
+ * far, get the verdict at every prefix length. The decision is
839
+ * monotone-stable in the sense that once `'reject_now'` or `'promote_now'`
840
+ * fires, the verdict at later steps remains decisive (the e-value is a
841
+ * non-negative martingale; once it crosses the threshold, it's crossed).
842
+ */
843
+ declare function pairedEvalueSequence(deltas: number[], opts?: PairedEvalueOptions): PairedEvalueSequence;
844
+ interface InterimReleaseConfidenceInput {
845
+ /**
846
+ * One delta series per candidate (paired deltas vs comparator). Order
847
+ * within a series is the order the campaigns were run.
848
+ */
849
+ deltaSeries: Array<{
850
+ candidateId: string;
851
+ deltas: number[];
852
+ }>;
853
+ alpha?: number;
854
+ bound?: number;
855
+ rope?: {
856
+ low: number;
857
+ high: number;
858
+ };
859
+ }
860
+ interface InterimReleaseConfidence {
861
+ candidates: Array<{
862
+ candidateId: string;
863
+ decision: SequentialDecision;
864
+ decisionFiredAt: number | null;
865
+ finalEvalue: number;
866
+ finalPValue: number;
867
+ pairs: number;
868
+ csLow: number;
869
+ csHigh: number;
870
+ }>;
871
+ /**
872
+ * Campaign-level recommendation: pick the strongest 'promote_now', else
873
+ * 'continue' if any candidate is still live, else 'reject_now' if every
874
+ * candidate is dead, else 'equivalent'.
875
+ */
876
+ recommendation: {
877
+ decision: SequentialDecision;
878
+ candidateId: string | null;
879
+ };
880
+ }
881
+ /**
882
+ * Run interim sequential analyses across many candidates at once,
883
+ * preserving the time-uniform α guarantee for each candidate's series and
884
+ * synthesising a campaign-level recommendation. Designed to be called on
885
+ * every campaign tick — the recommendation is anytime-valid.
886
+ */
887
+ declare function evaluateInterimReleaseConfidence(input: InterimReleaseConfidenceInput): InterimReleaseConfidence;
888
+
889
+ /**
890
+ * Wilcoxon signed-rank test — paired non-parametric alternative.
891
+ * Use when the differences aren't normally distributed.
892
+ */
893
+ declare function wilcoxonSignedRank(before: number[], after: number[]): {
894
+ w: number;
895
+ p: number;
896
+ };
897
+ /**
898
+ * Benjamini–Hochberg false discovery rate. Returns adjusted q-values and
899
+ * significance at the target FDR; handles ties and preserves q monotonicity.
900
+ */
901
+ declare function benjaminiHochberg(pValues: number[], fdr?: number): {
902
+ qValues: number[];
903
+ significant: boolean[];
904
+ };
905
+ interface PairedBootstrapResult {
906
+ /** Number of paired observations. */
907
+ n: number;
908
+ /** Median of paired deltas (after − before). */
909
+ median: number;
910
+ /** Mean of paired deltas. */
911
+ mean: number;
912
+ /** Lower bound of the bootstrap CI on the chosen statistic. */
913
+ low: number;
914
+ /** Upper bound of the bootstrap CI on the chosen statistic. */
915
+ high: number;
916
+ /** Confidence level used (e.g. 0.95). */
917
+ confidence: number;
918
+ /** Number of bootstrap resamples used. */
919
+ resamples: number;
920
+ }
921
+ interface PairedBootstrapOptions {
922
+ /** Confidence level. Default 0.95. */
923
+ confidence?: number;
924
+ /** Bootstrap resample count. Default 2000. */
925
+ resamples?: number;
926
+ /** Statistic to bootstrap. Default 'median'. */
927
+ statistic?: 'median' | 'mean';
928
+ /** Deterministic seed. If omitted, uses Math.random(). */
929
+ seed?: number;
930
+ }
931
+ /**
932
+ * Paired bootstrap on (after − before) deltas. Returns a CI on the chosen
933
+ * statistic (median by default); pairs are resampled with replacement. The
934
+ * lower bound is what the promotion gate checks — `low > threshold` means the
935
+ * gain is real at the confidence level. Throws on unequal sample sizes.
936
+ */
937
+ declare function pairedBootstrap(before: number[], after: number[], opts?: PairedBootstrapOptions): PairedBootstrapResult;
938
+
939
+ /**
940
+ * FailureClusterView — groups failed runs by (failureClass, triggerTool,
941
+ * argHash-prefix) so weekly reviews can prioritize the top-N clusters.
942
+ *
943
+ * Each cluster includes: N runs, scenarios affected, representative
944
+ * error message, a proposed mitigation hint (rule → action table).
945
+ */
946
+
947
+ interface FailureCluster {
948
+ failureClass: FailureClass;
949
+ /** Tool name when the trigger was a tool span, else undefined. */
950
+ toolName?: string;
951
+ /** First 16 chars of argHash — clusters similar args. */
952
+ argPrefix?: string;
953
+ /**
954
+ * Source dimension when the trigger was a judge span (e.g. `'format'`,
955
+ * `'safety'`, `'correctness'`). Lets cross-template aggregators
956
+ * group failures by the dimension that fired without overloading
957
+ * `argPrefix`. Optional — clusters without this field deserialize cleanly.
958
+ */
959
+ dimension?: string;
960
+ runCount: number;
961
+ scenarioIds: string[];
962
+ exampleError?: string;
963
+ exampleRunId: string;
964
+ }
965
+ interface FailureClusterReport {
966
+ clusters: FailureCluster[];
967
+ totalFailures: number;
968
+ totalRuns: number;
969
+ }
970
+
971
+ /**
972
+ * Reporting helpers — production summaries and paper-quality figures — sit alongside `reporter.ts` rather
973
+ * than replacing it.
974
+ *
975
+ * Three artefacts:
976
+ *
977
+ * - `summaryTable` Markdown table of per-candidate means,
978
+ * 95% bootstrap CIs, BH-adjusted Wilcoxon
979
+ * p-values, and Cohen's d versus a
980
+ * comparator candidate.
981
+ * - `paretoChart` Abstract spec for a cost vs quality
982
+ * scatter, with gate decisions overlaid.
983
+ * Returns numbers + labels — caller
984
+ * chooses the plotting library.
985
+ * - `gainHistogram`
986
+ * Per-item paired holdout deltas as a
987
+ * histogram spec (bins + counts + median +
988
+ * CI). Same "data, not images" contract.
989
+ *
990
+ * The figure types are PlotSpecs — JSON-friendly, library-agnostic.
991
+ * They aren't React components and they aren't PNGs; they are
992
+ * what you'd hand to vega-lite, plotly, matplotlib, or your own
993
+ * Canvas renderer to draw the actual figure.
994
+ */
995
+
996
+ interface SummaryTableOptions {
997
+ /** Comparator candidate id. Wilcoxon + Cohen's d are computed
998
+ * versus this candidate. Required for paired stats columns. */
999
+ comparator?: string;
1000
+ /** Which split to read scores from. Default 'holdout'. */
1001
+ split?: 'search' | 'holdout';
1002
+ /** Confidence level for the bootstrap CI on the mean. Default 0.95. */
1003
+ confidence?: number;
1004
+ /** FDR for BH adjustment of the comparison p-values. Default 0.05. */
1005
+ fdr?: number;
1006
+ }
1007
+ interface SummaryTableRow {
1008
+ candidateId: string;
1009
+ n: number;
1010
+ mean: number;
1011
+ ciLow: number;
1012
+ ciHigh: number;
1013
+ /** BH-adjusted q-value vs comparator. NaN if no comparator. */
1014
+ qValue: number;
1015
+ /** Cohen's d vs comparator. NaN if no comparator. */
1016
+ cohensD: number;
1017
+ }
1018
+ interface SummaryTable {
1019
+ rows: SummaryTableRow[];
1020
+ comparator: string | null;
1021
+ split: 'search' | 'holdout';
1022
+ /** Pre-rendered markdown — drop into a paper or PR. */
1023
+ markdown: string;
1024
+ }
1025
+ /**
1026
+ * Table 1 helper. Buckets runs by `candidateId`, computes mean +
1027
+ * bootstrap CI on the chosen split, and (when a comparator is given)
1028
+ * BH-adjusted Wilcoxon p + Cohen's d versus that comparator.
1029
+ */
1030
+ declare function summaryTable(runs: RunRecord[], opts?: SummaryTableOptions): SummaryTable;
1031
+ interface ParetoPoint {
1032
+ candidateId: string;
1033
+ /** Mean USD cost per run on the chosen split. */
1034
+ cost: number;
1035
+ /** Mean score on the chosen split. */
1036
+ quality: number;
1037
+ /** Number of runs that informed this point. */
1038
+ n: number;
1039
+ /** Whether this candidate is on the Pareto frontier — high
1040
+ * quality, low cost, no dominator. */
1041
+ onFrontier: boolean;
1042
+ /** Optional gate verdict for this candidate, if a `GateDecision`
1043
+ * for it was passed in. */
1044
+ gate?: 'promote' | 'reject_few_runs' | 'reject_negative_delta' | 'reject_overfit_gap' | null;
1045
+ }
1046
+ interface ParetoFigureSpec {
1047
+ kind: 'pareto-cost-quality';
1048
+ split: 'search' | 'holdout';
1049
+ points: ParetoPoint[];
1050
+ axes: {
1051
+ x: 'costUsd';
1052
+ y: 'score';
1053
+ };
1054
+ }
1055
+ /**
1056
+ * Cost vs quality scatter spec. `gateDecisions` is keyed by
1057
+ * candidate id; if present, every point picks up the gate verdict
1058
+ * for overlay.
1059
+ */
1060
+ declare function paretoChart(runs: RunRecord[], opts?: {
1061
+ split?: 'search' | 'holdout';
1062
+ gateDecisions?: Record<string, GateDecision>;
1063
+ }): ParetoFigureSpec;
1064
+ interface GainDistributionBin {
1065
+ /** Inclusive lower edge. */
1066
+ lo: number;
1067
+ /** Exclusive upper edge (or inclusive if it's the last bin). */
1068
+ hi: number;
1069
+ /** Number of pairs whose delta lands in this bin. */
1070
+ count: number;
1071
+ }
1072
+ interface GainDistributionFigureSpec {
1073
+ kind: 'gain-distribution';
1074
+ candidateId: string;
1075
+ comparator: string;
1076
+ split: 'search' | 'holdout';
1077
+ /** Number of pairs used. */
1078
+ n: number;
1079
+ bins: GainDistributionBin[];
1080
+ median: number;
1081
+ ci: {
1082
+ low: number;
1083
+ high: number;
1084
+ };
1085
+ }
1086
+ interface GainDistributionOptions {
1087
+ /** Number of histogram bins. Default 11 (so the centre is exact at 0). */
1088
+ bins?: number;
1089
+ /** Which split to use. Default 'holdout'. */
1090
+ split?: 'search' | 'holdout';
1091
+ /** Confidence level for the CI. Default 0.95. */
1092
+ confidence?: number;
1093
+ /** Bootstrap resamples. Default 2000. */
1094
+ resamples?: number;
1095
+ /** Deterministic seed. */
1096
+ seed?: number;
1097
+ }
1098
+ /**
1099
+ * Held-out improvement distribution: per-pair delta (candidate −
1100
+ * comparator), histogrammed. Includes the bootstrap CI on the median
1101
+ * delta — same primitive the promotion gate uses.
1102
+ */
1103
+ declare function gainHistogram(runs: RunRecord[], candidateId: string, comparator: string, opts?: GainDistributionOptions): GainDistributionFigureSpec;
1104
+ type ResearchReportDecision = 'promote' | 'hold' | 'reject' | 'equivalent' | 'needs_more_data';
1105
+ /**
1106
+ * Hard floor below which a paired comparison is treated as uninformative
1107
+ * regardless of `minPairs`. Mirrors the lower limit on Wilcoxon signed-rank
1108
+ * exact tables; below this the test has no power to separate effect sizes.
1109
+ */
1110
+ declare const RESEARCH_REPORT_HARD_PAIR_FLOOR = 6;
1111
+ interface ResearchReportOptions {
1112
+ /** Human-readable report title. */
1113
+ title?: string;
1114
+ /** Comparator candidate id. Required for statistical decision guidance. */
1115
+ comparator?: string;
1116
+ /** Which split to use for the primary decision. Default 'holdout'. */
1117
+ split?: 'search' | 'holdout';
1118
+ /** Confidence level used by lower-level report helpers. Default 0.95. */
1119
+ confidence?: number;
1120
+ /** FDR threshold for q-values. Default 0.05. */
1121
+ fdr?: number;
1122
+ /**
1123
+ * Soft floor on paired observations before issuing a directional
1124
+ * promote / reject. Below this we report `needs_more_data` and surface the
1125
+ * minimum detectable effect at the current N. Default 20 — chosen so the
1126
+ * Wilcoxon signed-rank approximation is reasonable and so the paired
1127
+ * bootstrap CI has non-degenerate coverage. Hard floor is enforced at
1128
+ * `RESEARCH_REPORT_HARD_PAIR_FLOOR` (6) regardless of this value.
1129
+ */
1130
+ minPairs?: number;
1131
+ /**
1132
+ * Region of Practical Equivalence on the paired delta. When a candidate's
1133
+ * paired-delta CI is fully contained in `[low, high]`, the decision is
1134
+ * `equivalent` rather than `hold`. Sourced from the domain owner — there is
1135
+ * no statistically-defensible default.
1136
+ */
1137
+ rope?: {
1138
+ low: number;
1139
+ high: number;
1140
+ };
1141
+ /**
1142
+ * Power for the minimum detectable effect (MDE) reported on each candidate.
1143
+ * Default 0.8.
1144
+ */
1145
+ mdePower?: number;
1146
+ /**
1147
+ * Two-sided alpha for the MDE. Default matches `fdr` so the reported MDE
1148
+ * lines up with the test the report actually runs.
1149
+ */
1150
+ mdeAlpha?: number;
1151
+ /** Optional held-out gate decisions keyed by candidate id. */
1152
+ gateDecisions?: Record<string, GateDecision>;
1153
+ /** Optional failure clusters from failureClusterView. */
1154
+ failureClusters?: FailureClusterReport;
1155
+ /** Build gain histograms for these candidates. Defaults to all non-comparator candidates. */
1156
+ candidateIds?: string[];
1157
+ /** Deterministic bootstrap seed passed to gainHistogram and the posterior helper. */
1158
+ seed?: number;
1159
+ /** Report timestamp. Defaults to current time. */
1160
+ generatedAt?: string;
1161
+ /**
1162
+ * Hash of a preregistered protocol (e.g. `signManifest({...}).contentHash`).
1163
+ * Embedded verbatim in the report so the analysis can be cited as the
1164
+ * preregistered one rather than a post-hoc fishing expedition.
1165
+ */
1166
+ preregistrationHash?: string;
1167
+ }
1168
+ interface ResearchReportRecommendation {
1169
+ decision: ResearchReportDecision;
1170
+ candidateId: string | null;
1171
+ rationale: string[];
1172
+ risks: string[];
1173
+ nextActions: string[];
1174
+ }
1175
+ interface ResearchReportCandidate {
1176
+ candidateId: string;
1177
+ n: number;
1178
+ mean: number;
1179
+ ciLow: number;
1180
+ ciHigh: number;
1181
+ qValue: number;
1182
+ cohensD: number;
1183
+ meanDeltaVsComparator: number | null;
1184
+ pairedN: number;
1185
+ medianGain: number | null;
1186
+ meanGain: number | null;
1187
+ gainCi: {
1188
+ low: number;
1189
+ high: number;
1190
+ } | null;
1191
+ /**
1192
+ * Bayesian-bootstrap-style posterior summaries on the paired delta. Computed
1193
+ * from the same resamples that produce the gain CI; interpretable as
1194
+ * "fraction of resamples in which the candidate beats the comparator on
1195
+ * matched pairs."
1196
+ */
1197
+ prGreaterThanZero: number | null;
1198
+ prInRope: number | null;
1199
+ /**
1200
+ * Minimum detectable effect (in score units) at the candidate's paired N,
1201
+ * the configured power, and the configured alpha. Standardised by the
1202
+ * observed paired-delta SD and inverted via `requiredSampleSize`. Reported
1203
+ * for every candidate so a `needs_more_data` verdict is actionable.
1204
+ */
1205
+ mde: number | null;
1206
+ onParetoFrontier: boolean;
1207
+ gate?: ParetoPoint['gate'];
1208
+ decision: ResearchReportDecision;
1209
+ decisionReason: string;
1210
+ }
1211
+ interface ResearchReportMethodology {
1212
+ /**
1213
+ * Plain-language assumptions the report depends on. Read these first when
1214
+ * deciding whether the verdict is load-bearing for a launch decision.
1215
+ */
1216
+ assumptions: string[];
1217
+ /** Tests and estimators the verdict was computed from. */
1218
+ methods: string[];
1219
+ /** Alternatives the author considered and why this report didn't take them. */
1220
+ alternatives: string[];
1221
+ /** Failure modes — when this report should NOT drive a decision. */
1222
+ whenNotToApply: string[];
1223
+ /** Citations for the methodological choices above. */
1224
+ citations: string[];
1225
+ }
1226
+ interface ResearchReport {
1227
+ kind: 'agent-eval-research-report';
1228
+ title: string;
1229
+ generatedAt: string;
1230
+ split: 'search' | 'holdout';
1231
+ comparator: string | null;
1232
+ /**
1233
+ * SHA-256 over the canonicalised set of `(runId, candidateId, split)` triples
1234
+ * the report was computed from, plus the comparator and split. Stable across
1235
+ * key insertion order; recomputable by the reader to verify provenance.
1236
+ */
1237
+ runFingerprint: string;
1238
+ preregistrationHash: string | null;
1239
+ rope: {
1240
+ low: number;
1241
+ high: number;
1242
+ } | null;
1243
+ executiveSummary: string[];
1244
+ recommendation: ResearchReportRecommendation;
1245
+ candidates: ResearchReportCandidate[];
1246
+ summary: SummaryTable;
1247
+ charts: {
1248
+ pareto: ParetoFigureSpec;
1249
+ gains: GainDistributionFigureSpec[];
1250
+ };
1251
+ methodology: ResearchReportMethodology;
1252
+ failureClusters?: FailureClusterReport;
1253
+ markdown: string;
1254
+ html: string;
1255
+ }
1256
+ /**
1257
+ * Executive research report for CPO / AI-lead / launch-review consumption.
1258
+ *
1259
+ * Composes:
1260
+ * - `summaryTable` marginal stats with BH-FDR-adjusted q-values
1261
+ * - `paretoChart` cost-vs-quality frontier with gate overlay
1262
+ * - `gainHistogram` per-candidate paired-delta distribution
1263
+ * - paired posterior (this file): bootstrap CI on median, Pr(Δ>0),
1264
+ * Pr(Δ∈ROPE), MDE at the configured power
1265
+ *
1266
+ * Decisions are made on paired evidence — never on marginal means alone —
1267
+ * and respect any held-out gate decision the caller passes through. The
1268
+ * report embeds a SHA-256 fingerprint of the input run set and, optionally,
1269
+ * the hash of a preregistered protocol so a downstream reader can verify
1270
+ * provenance and that the analysis was the preregistered one.
1271
+ *
1272
+ * Async because the fingerprint uses Web Crypto via `hashJson`; deterministic
1273
+ * for any fixed `runs`, `seed`, and ROPE.
1274
+ */
1275
+ declare function researchReport(runs: RunRecord[], opts?: ResearchReportOptions): Promise<ResearchReport>;
1276
+
1277
+ export { type BootstrapOptions, type BootstrapResult, type GainDistributionBin, type GainDistributionFigureSpec, type GainDistributionOptions, type InterimReleaseConfidence, type InterimReleaseConfidenceInput, type JudgeReplayGateArgs, type PairedBootstrapOptions, type PairedBootstrapResult, type PairedEvalueOptions, type PairedEvalueSequence, type PairedEvalueStep, type ParetoFigureSpec, type ParetoPoint, RESEARCH_REPORT_HARD_PAIR_FLOOR, type ReleaseConfidenceAxis, type ReleaseConfidenceAxisName, type ReleaseConfidenceInput, type ReleaseConfidenceIssue, type ReleaseConfidenceMetrics, type ReleaseConfidenceScorecard, type ReleaseConfidenceStatus, type ReleaseConfidenceThresholds, type ReleaseTraceEvidence, type RenderReleaseReportOptions, type ResearchReport, type ResearchReportCandidate, type ResearchReportDecision, type ResearchReportMethodology, type ResearchReportOptions, type ResearchReportRecommendation, type RubricOutcomePair, type RubricPredictiveValidityInput, type RubricPredictiveValidityReport, type RubricRanking, type SequentialDecision, type SummaryTable, type SummaryTableOptions, type SummaryTableRow, type Verdict, assertReleaseConfidence, benjaminiHochberg, bootstrapCi, evaluateInterimReleaseConfidence, evaluateReleaseConfidence, gainHistogram, judgeReplayGate, pairedBootstrap, pairedEvalueSequence, paretoChart, renderReleaseReport, researchReport, rubricPredictiveValidity, summaryTable, wilcoxonSignedRank };