@tangle-network/agent-eval 0.117.0 → 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 +30 -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 +4276 -74
  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-ZUXV7UWZ.js → chunk-Q442S5AS.js} +73 -19
  32. package/dist/{chunk-ZUXV7UWZ.js.map → chunk-Q442S5AS.js.map} +1 -1
  33. package/dist/{chunk-ODVOOEWQ.js → chunk-QBRSJK47.js} +2 -2
  34. package/dist/{chunk-S2F4J57L.js → chunk-QKEGNI5B.js} +77 -32
  35. package/dist/chunk-QKEGNI5B.js.map +1 -0
  36. package/dist/{chunk-5UF54T55.js → chunk-S3UZOQ5Y.js} +34 -7
  37. package/dist/chunk-S3UZOQ5Y.js.map +1 -0
  38. package/dist/{chunk-FQNLDL4D.js → chunk-SVH2ANFD.js} +136 -4
  39. package/dist/chunk-SVH2ANFD.js.map +1 -0
  40. package/dist/{chunk-GQCZRZ7L.js → chunk-U5CHZ5M3.js} +9 -9
  41. package/dist/{chunk-TVVP3ZZQ.js → chunk-VQMK5FMP.js} +2 -1
  42. package/dist/{chunk-TVVP3ZZQ.js.map → chunk-VQMK5FMP.js.map} +1 -1
  43. package/dist/chunk-WDHBCA3M.js +31 -0
  44. package/dist/chunk-WDHBCA3M.js.map +1 -0
  45. package/dist/{chunk-HQPHZGL6.js → chunk-YLMUS4MM.js} +9 -9
  46. package/dist/{chunk-LQUTGLOZ.js → chunk-ZET2UAYW.js} +15 -65
  47. package/dist/chunk-ZET2UAYW.js.map +1 -0
  48. package/dist/contract/index.d.ts +4012 -38
  49. package/dist/contract/index.js +56 -29
  50. package/dist/contract/index.js.map +1 -1
  51. package/dist/control.d.ts +1013 -9
  52. package/dist/control.js +4 -3
  53. package/dist/fuzz.d.ts +194 -4
  54. package/dist/fuzz.js +3 -3
  55. package/dist/hosted/index.d.ts +498 -17
  56. package/dist/index.d.ts +10982 -1286
  57. package/dist/index.js +97 -80
  58. package/dist/index.js.map +1 -1
  59. package/dist/matrix/index.d.ts +139 -4
  60. package/dist/meta-eval/index.d.ts +862 -15
  61. package/dist/meta-eval/index.js +2 -1
  62. package/dist/meta-eval/index.js.map +1 -1
  63. package/dist/multishot/index.d.ts +214 -14
  64. package/dist/openapi.json +1 -1
  65. package/dist/pipelines/index.d.ts +392 -7
  66. package/dist/pipelines/index.js +5 -3
  67. package/dist/pipelines/index.js.map +1 -1
  68. package/dist/reporting.d.ts +1277 -17
  69. package/dist/rl.d.ts +2359 -28
  70. package/dist/rl.js +6 -5
  71. package/dist/rl.js.map +1 -1
  72. package/dist/storyboard/index.d.ts +86 -1
  73. package/dist/trace-attributes.d.ts +16 -0
  74. package/dist/trace-attributes.js +32 -0
  75. package/dist/trace-attributes.js.map +1 -0
  76. package/dist/traces.d.ts +1970 -697
  77. package/dist/traces.js +49 -32
  78. package/dist/wire/index.d.ts +655 -9
  79. package/docs/insight-report.md +44 -0
  80. package/package.json +9 -3
  81. package/dist/adversarial-B7loGVVX.d.ts +0 -19
  82. package/dist/analyst-C8HHvfJp.d.ts +0 -88
  83. package/dist/analyze-runs--2x39HZ7.d.ts +0 -81
  84. package/dist/baseline-DKq3gJpP.d.ts +0 -141
  85. package/dist/calibration-C8MTS7cw.d.ts +0 -101
  86. package/dist/chunk-5UF54T55.js.map +0 -1
  87. package/dist/chunk-E4BUPP7Z.js.map +0 -1
  88. package/dist/chunk-FQNLDL4D.js.map +0 -1
  89. package/dist/chunk-LQUTGLOZ.js.map +0 -1
  90. package/dist/chunk-S2F4J57L.js.map +0 -1
  91. package/dist/chunk-YZPO4UHR.js.map +0 -1
  92. package/dist/code-agent-session-CjZsVd19.d.ts +0 -87
  93. package/dist/control-6vuGfmDH.d.ts +0 -258
  94. package/dist/cost-ledger-DWy3XdJc.d.ts +0 -183
  95. package/dist/dataset-NENEzRgk.d.ts +0 -115
  96. package/dist/default-registry-DaK8b3fv.d.ts +0 -155
  97. package/dist/emitter-CjD7vUwv.d.ts +0 -122
  98. package/dist/errors-oeQrLqXC.d.ts +0 -74
  99. package/dist/failure-cluster-DOAcSJ87.d.ts +0 -76
  100. package/dist/feedback-trajectory-BUnM58xL.d.ts +0 -348
  101. package/dist/gepa-eESocoDi.d.ts +0 -642
  102. package/dist/index-PdX4VnPA.d.ts +0 -423
  103. package/dist/insight-report-DY4nDW9Q.d.ts +0 -310
  104. package/dist/integrity-DqlBiLyK.d.ts +0 -81
  105. package/dist/judge-calibration-7C-IDmKr.d.ts +0 -145
  106. package/dist/kind-factory-ClZmO25A.d.ts +0 -171
  107. package/dist/llm-client-qoDd18Qz.d.ts +0 -289
  108. package/dist/multi-layer-verifier-BsqKuLyN.d.ts +0 -150
  109. package/dist/off-policy-DiwuKKg7.d.ts +0 -132
  110. package/dist/outcome-store-rnXLEqSn.d.ts +0 -63
  111. package/dist/policy-edit-wG9uFEFm.d.ts +0 -455
  112. package/dist/pre-registration-BWQhJ3vz.d.ts +0 -761
  113. package/dist/provenance-DpjwyseI.d.ts +0 -541
  114. package/dist/query-CF7PG61p.d.ts +0 -35
  115. package/dist/raw-provider-sink-C46HDghv.d.ts +0 -132
  116. package/dist/release-report-C8G2i5Xi.d.ts +0 -236
  117. package/dist/researcher-C8XyxQsu.d.ts +0 -387
  118. package/dist/rubric-predictive-validity-p49lLVrE.d.ts +0 -105
  119. package/dist/run-record-BDH49H2E.d.ts +0 -360
  120. package/dist/runtime-trajectory-DGBIUt4B.d.ts +0 -49
  121. package/dist/schema-B3Q3l9Z_.d.ts +0 -201
  122. package/dist/semantic-concept-judge-CXnPEJbf.d.ts +0 -723
  123. package/dist/sequential-5iSVfzl2.d.ts +0 -139
  124. package/dist/series-convergence-D5OWMBg6.d.ts +0 -33
  125. package/dist/statistics-KUnG73jH.d.ts +0 -494
  126. package/dist/storage-DrX3v_5B.d.ts +0 -50
  127. package/dist/store-C1YxJDEK.d.ts +0 -248
  128. package/dist/store-DGqD0Pyo.d.ts +0 -116
  129. package/dist/summary-report-C5bKFfm-.d.ts +0 -445
  130. package/dist/test-graded-scenario-B0ybnPY7.d.ts +0 -166
  131. package/dist/types-BSw1rOUB.d.ts +0 -634
  132. package/dist/types-BUxNaJ8c.d.ts +0 -108
  133. package/dist/types-BkfcQnxV.d.ts +0 -313
  134. package/dist/verdict-C9MlYujm.d.ts +0 -35
  135. /package/dist/{chunk-VF3XSYTI.js.map → chunk-33JA4TFA.js.map} +0 -0
  136. /package/dist/{chunk-4JLWXDYA.js.map → chunk-3EHHMC6E.js.map} +0 -0
  137. /package/dist/{chunk-CCZIVI3F.js.map → chunk-BFW56GTT.js.map} +0 -0
  138. /package/dist/{chunk-HZHNRYHK.js.map → chunk-K6N6XJJX.js.map} +0 -0
  139. /package/dist/{chunk-MGEHEHSN.js.map → chunk-OIIMMLRB.js.map} +0 -0
  140. /package/dist/{chunk-DXZRATT5.js.map → chunk-OYZAPX5G.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,14 +1,958 @@
1
- export { B as BENCHMARK_SPLIT_SEED, a as BenchmarkAdapter, b as BenchmarkDatasetItem, k as BenchmarkDistribution, c as BenchmarkEvaluation, d as BenchmarkFamily, l as BenchmarkMetricCalibrationOptions, m as BenchmarkMetricCalibrationResult, n as BenchmarkReport, e as BenchmarkResponder, o as BenchmarkRunOptions, p as BenchmarkRunResult, f as BenchmarkScenario, q as BenchmarkSliceSummary, g as BenchmarkSource, h as BenchmarkTaskKind, r as BuildStandardRetrievalItemsOptions, R as RetrievalIdAdapterOptions, S as StandardRetrievalArtifact, s as StandardRetrievalDocument, t as StandardRetrievalEvaluationOptions, u as StandardRetrievalPayload, v as StandardRetrievalQrel, w as StandardRetrievalQuery, x as StandardRetrievalResult, y as buildStandardRetrievalItems, z as calibrateBenchmarkMetric, A as createRetrievalIdBenchmarkAdapter, i as deterministicSplit, C as evaluateStandardRetrieval, D as normalizeRetrievedDocumentIds, E as parseBeirCorpusJsonl, F as parseBeirQueriesJsonl, G as parseJsonlRows, H as parseQrels, I as parseTsvRows, J as renderBenchmarkReportMarkdown, K as retrievalMetricsAtCutoff, L as routing, M as runBenchmarkAdapter, N as summarizeBenchmarkCampaign } from '../index-PdX4VnPA.js';
2
- import '../types-BSw1rOUB.js';
3
- import '../policy-edit-wG9uFEFm.js';
4
- import '../run-record-BDH49H2E.js';
5
- import '@tangle-network/agent-interface';
6
- import '../errors-oeQrLqXC.js';
7
- import '../schema-B3Q3l9Z_.js';
8
- import '../store-C1YxJDEK.js';
9
- import '../types-BkfcQnxV.js';
10
- import '../cost-ledger-DWy3XdJc.js';
11
- import '@tangle-network/tcloud';
12
- import '../llm-client-qoDd18Qz.js';
13
- import '../raw-provider-sink-C46HDghv.js';
14
- import '../storage-DrX3v_5B.js';
1
+ type AgentProfileCellSchemaVersion = 'agent-profile-cell/v1';
2
+ type AgentProfileJson = string | number | boolean | null | AgentProfileJson[] | {
3
+ [key: string]: AgentProfileJson;
4
+ };
5
+ type AgentProfileDimensionValue = string | number | boolean | null;
6
+ interface AgentProfileSource {
7
+ /** Runtime/profile contract being fingerprinted, e.g. `agent-interface-profile`. */
8
+ kind: string;
9
+ /** sha256 over the canonical source profile object. */
10
+ hash: string;
11
+ }
12
+ interface AgentProfileHarness {
13
+ id: string;
14
+ version?: string;
15
+ hash?: string;
16
+ }
17
+ interface AgentProfileCell {
18
+ schemaVersion: AgentProfileCellSchemaVersion;
19
+ cellId: string;
20
+ profileId: string;
21
+ sourceProfile: AgentProfileSource;
22
+ harness?: AgentProfileHarness;
23
+ model?: string;
24
+ promptHash?: string;
25
+ dimensions?: Record<string, AgentProfileDimensionValue>;
26
+ }
27
+
28
+ /**
29
+ * Paper-grade RunRecord schema + runtime validator.
30
+ *
31
+ * Every run that participates in a promotion gate, paper table, or
32
+ * researcher loop SHOULD be recorded as a `RunRecord`. The mandatory
33
+ * fields are exactly those the paper "Two Loops, Three Roles" requires
34
+ * for reproducibility: who/what/when/cost/seed/hash, plus the search vs
35
+ * holdout split tag and either a `searchScore` or a `holdoutScore`.
36
+ *
37
+ * This is intentionally NOT a replacement for the rich `Run` /
38
+ * `ProposeReviewReport` / `ScenarioResult` types already in the
39
+ * package. Those are runtime structures with full provenance. A
40
+ * `RunRecord` is the analysis-time projection — the JSON-friendly
41
+ * row you'd put in a parquet file or paste into a notebook.
42
+ *
43
+ * Validate at the boundary:
44
+ *
45
+ * const rec = validateRunRecord(rawJson) // throws on missing
46
+ * const ok = isRunRecord(rawJson) // boolean check
47
+ * const rec = parseRunRecordSafe(rawJson) // { ok, value | error }
48
+ *
49
+ * The validator runs in pure TS — zod is intentionally NOT a
50
+ * dependency. Round-trip tested in `tests/run-record.test.ts`.
51
+ */
52
+
53
+ /** Search/dev/holdout split tag. 'search' is the paper-grade alias for the
54
+ * combined train+test pool that the optimizer is allowed to read. */
55
+ type RunSplitTag = 'search' | 'dev' | 'holdout';
56
+ interface RunTokenUsage {
57
+ input: number;
58
+ /** All generated tokens charged as output, including reasoning tokens. */
59
+ output: number;
60
+ /** Reasoning-token subset of `output`, when the provider reports it. */
61
+ reasoning?: number;
62
+ /** Prompt tokens served from a provider cache. */
63
+ cached?: number;
64
+ /** Prompt tokens written into a provider cache. */
65
+ cacheWrite?: number;
66
+ }
67
+
68
+ type CostChannel = 'agent' | 'judge' | 'verifier' | 'analyst' | 'driver' | (string & {});
69
+ interface CostUsage {
70
+ inputTokens: number;
71
+ outputTokens: number;
72
+ cachedTokens?: number;
73
+ }
74
+ interface CostCallBase {
75
+ callId: string;
76
+ channel: CostChannel;
77
+ phase: string;
78
+ actor: string;
79
+ model: string;
80
+ maximumCostUsd?: number;
81
+ tags?: Record<string, string>;
82
+ timestamp: number;
83
+ }
84
+ interface CostReceipt extends CostCallBase, CostUsage {
85
+ status: 'settled';
86
+ costUsd: number;
87
+ costUnknown: boolean;
88
+ usageUnknown?: boolean;
89
+ pricing?: {
90
+ inputUsdPerThousand: number;
91
+ outputUsdPerThousand: number;
92
+ };
93
+ actualCostUsd?: number;
94
+ error?: string;
95
+ }
96
+ interface CostReceiptInput extends CostUsage {
97
+ model: string;
98
+ actualCostUsd?: number;
99
+ costUnknown?: boolean;
100
+ usageUnknown?: boolean;
101
+ }
102
+ type MaximumCharge = {
103
+ externallyEnforcedMaximumUsd: number;
104
+ } | ({
105
+ model: string;
106
+ } & CostUsage);
107
+ interface RunPaidCallInput<T> {
108
+ callId?: string;
109
+ channel: CostChannel;
110
+ phase: string;
111
+ actor: string;
112
+ /** Used before a provider receipt exists and on failures without one. */
113
+ model?: string;
114
+ tags?: Record<string, string>;
115
+ signal?: AbortSignal;
116
+ /** Provider-enforced dollar maximum, or maximum priced token usage. Required when capped. */
117
+ maximumCharge?: MaximumCharge;
118
+ /** `callId` can be forwarded as the provider's idempotency key. */
119
+ execute(signal: AbortSignal, callId: string): Promise<T>;
120
+ receipt(value: T): CostReceiptInput;
121
+ receiptFromError?(error: Error): CostReceiptInput | undefined;
122
+ }
123
+ type PaidCallResult<T> = {
124
+ succeeded: true;
125
+ callId: string;
126
+ value: T;
127
+ receipt: CostReceipt;
128
+ } | {
129
+ succeeded: false;
130
+ callId?: string;
131
+ error: Error;
132
+ receipt?: CostReceipt;
133
+ };
134
+ interface ChannelRollup {
135
+ channel: CostChannel;
136
+ calls: number;
137
+ inputTokens: number;
138
+ outputTokens: number;
139
+ cachedTokens: number;
140
+ costUsd: number;
141
+ unpricedCalls: number;
142
+ unknownUsageCalls: number;
143
+ }
144
+ interface CostLedgerSummary {
145
+ totalCalls: number;
146
+ pendingCalls: number;
147
+ unresolvedCalls: number;
148
+ reservedCostUsd: number;
149
+ inputTokens: number;
150
+ outputTokens: number;
151
+ cachedTokens: number;
152
+ totalCostUsd: number;
153
+ byChannel: ChannelRollup[];
154
+ unpricedModels: string[];
155
+ fullyPriced: boolean;
156
+ usageComplete: boolean;
157
+ accountingComplete: boolean;
158
+ incompleteReasons: string[];
159
+ }
160
+
161
+ /**
162
+ * LLM client with graceful degrade.
163
+ *
164
+ * OpenAI-compatible `/v1/chat/completions` client with:
165
+ * - Exponential-backoff retry on 429 + 5xx gateway errors (502/503/504).
166
+ * - Retry on transient network errors (fetch failed, AbortError, ECONNRESET).
167
+ * - Graceful json_schema → json_object degrade on 400 with schema-reject body.
168
+ * - Fenced-JSON stripping (```json ... ```) for models that wrap structured output.
169
+ * - Configurable base URL + api key / bearer, works with LiteLLM proxies, OpenAI
170
+ * directly, cli-bridge subscriptions, and any router that speaks the spec.
171
+ *
172
+ * Usage:
173
+ * const { value, result } = await callLlmJson<MyType>(
174
+ * { model: 'gpt-4o', messages: [...], jsonSchema: { name: 'x', schema: {...} } },
175
+ * { baseUrl: 'https://router.tangle.tools/v1', apiKey: process.env.KEY },
176
+ * )
177
+ *
178
+ * This is THE llm-calling seam for agent-eval primitives that need structured
179
+ * output (semantic concept judge, reviewer directives, critic scores). Primitives
180
+ * that need free-form text use `callLlm` and parse output themselves.
181
+ */
182
+
183
+ interface LlmUsage {
184
+ promptTokens: number;
185
+ completionTokens: number;
186
+ totalTokens: number;
187
+ /** False when the provider omitted or malformed prompt/completion usage. */
188
+ captured?: boolean;
189
+ /** Proxies populate this when prompt caching is on. */
190
+ cachedPromptTokens?: number;
191
+ }
192
+ interface LlmCallResult {
193
+ /** The text content of the first choice. Empty string if none. */
194
+ content: string;
195
+ usage: LlmUsage;
196
+ /**
197
+ * Cost in USD. Pulled from proxy's `_response_cost` field when present;
198
+ * `null` when neither the proxy nor the caller can derive it.
199
+ */
200
+ costUsd: number | null;
201
+ /** Model name actually used (echoed from response). */
202
+ model: string;
203
+ /** Wall-clock duration of the HTTP call (last attempt, if retried). */
204
+ durationMs: number;
205
+ /**
206
+ * `finish_reason` echoed from the first choice (`stop`, `length`,
207
+ * `content_filter`, `tool_calls`, ...). `null` when the provider omits it.
208
+ * Exposed so a free-form `callLlm` caller CAN detect a truncated answer
209
+ * (`length`) instead of treating a cut-off completion as complete. Note:
210
+ * `callLlm` does not itself reject on it — acting on this signal is the
211
+ * caller's responsibility (in-repo free-form drivers do not yet enforce it).
212
+ */
213
+ finishReason?: string | null;
214
+ /**
215
+ * True when `content.trim()` is empty. An empty completion is a silent zero
216
+ * for free-form `callLlm` callers; this flag is the signal a caller can
217
+ * inspect to fail loud rather than proceed on an empty string. `callLlm`
218
+ * surfaces it but does not throw on it.
219
+ */
220
+ contentEmpty?: boolean;
221
+ /** Raw response body. */
222
+ raw: Record<string, unknown>;
223
+ }
224
+ type LlmCallMetadata = Pick<LlmCallResult, 'usage' | 'costUsd' | 'model' | 'durationMs'>;
225
+
226
+ /**
227
+ * Analyst contract — the missing orchestration layer over agent-eval's
228
+ * existing analyzers (analyzeTraces, MultiLayerVerifier, RunCritic,
229
+ * SemanticConceptJudge, JudgeFn, ...).
230
+ *
231
+ * Each existing primitive returns its own output shape. The Analyst
232
+ * contract is the single envelope every primitive lifts into, so a
233
+ * registry can run N analysts against a run and a single renderer can
234
+ * compose findings without knowing which analyzer produced them.
235
+ *
236
+ * The contract is intentionally domain-agnostic: nothing here knows
237
+ * about code, voice, RAG, or any particular agent stack. Analysts
238
+ * declare what INPUT KIND they need (a trace store, an artifact dir,
239
+ * a RunRecord, a JudgeInput, or `custom`), and the registry routes
240
+ * the matching input from `AnalystRunInputs`.
241
+ */
242
+
243
+ interface EvidenceRef {
244
+ /**
245
+ * Where the evidence lives. `span` and `event` refer to OTLP trace
246
+ * elements; `artifact` to a file inside the run's artifact tree;
247
+ * `finding` to another AnalystFinding (cross-analyst chaining);
248
+ * `metric` to a named scalar reading the renderer knows how to read.
249
+ */
250
+ kind: 'span' | 'event' | 'artifact' | 'finding' | 'metric';
251
+ uri: string;
252
+ excerpt?: string;
253
+ }
254
+
255
+ type PolicyEditSchemaVersion = 'policy-edit/v1';
256
+ declare const POLICY_EDIT_AXES: readonly ["carrier", "representation", "budget", "sampling", "output_contract", "tool_contract", "routing", "memory", "agent_profile", "deployment_target"];
257
+ type PolicyEditAxis = (typeof POLICY_EDIT_AXES)[number];
258
+ declare const POLICY_EDIT_TARGET_SURFACES: readonly ["prompt", "tool-contract", "runtime-config", "memory", "agent-profile", "code", "deployment"];
259
+ type PolicyEditTargetSurface = (typeof POLICY_EDIT_TARGET_SURFACES)[number];
260
+ type PolicyEditRisk = 'low' | 'medium' | 'high' | 'unknown';
261
+ type PolicyEditGainDirection = 'increase' | 'decrease';
262
+ type PolicyEditGainUnit = 'absolute' | 'relative' | 'percent' | 'score';
263
+ interface PolicyEditTarget {
264
+ surface: PolicyEditTargetSurface;
265
+ /** Stable path inside the target surface, for example `system-prompt:tools`
266
+ * or `budget.maxTurns`. */
267
+ path?: string;
268
+ /** Optional canonical deployment identity. Store the existing cell, not a
269
+ * local profile shape. */
270
+ agentProfileCell?: AgentProfileCell;
271
+ /** Human label when the path is not enough for a readable audit trail. */
272
+ label?: string;
273
+ }
274
+ type PolicyEditChange = {
275
+ kind: 'text';
276
+ mode: 'append' | 'prepend' | 'replace';
277
+ value: string;
278
+ /** Required when `mode === 'replace'`; exact match only. */
279
+ find?: string;
280
+ } | {
281
+ kind: 'json';
282
+ mode: 'set' | 'merge' | 'remove';
283
+ path: string;
284
+ value?: AgentProfileJson;
285
+ };
286
+ interface PolicyEditExpectedGain {
287
+ /** Metric this edit is expected to move, e.g. `holdout.composite`. */
288
+ metric: string;
289
+ direction: PolicyEditGainDirection;
290
+ /** Positive magnitude in the metric's native units. */
291
+ amount: number;
292
+ unit?: PolicyEditGainUnit;
293
+ rationale?: string;
294
+ }
295
+ interface PolicyEditSource {
296
+ findingIds: string[];
297
+ analystIds: string[];
298
+ evidenceRefs: EvidenceRef[];
299
+ /** Mirrors `AnalystFinding.derived_from_judge`; admission rejects it. */
300
+ derivedFromJudge?: boolean;
301
+ }
302
+ interface PolicyEdit {
303
+ schemaVersion: PolicyEditSchemaVersion;
304
+ editId: string;
305
+ axis: PolicyEditAxis;
306
+ target: PolicyEditTarget;
307
+ change: PolicyEditChange;
308
+ claim: string;
309
+ expectedGain: PolicyEditExpectedGain;
310
+ confidence: number;
311
+ risk: PolicyEditRisk;
312
+ source: PolicyEditSource;
313
+ rationale?: string;
314
+ validationPlan?: string;
315
+ metadata?: Record<string, unknown>;
316
+ }
317
+ declare const POLICY_EDIT_CANDIDATE_RECORD_SCHEMA: "tangle.policy-edit-candidate.v1";
318
+ /** JSON-safe attribution carried with a measured candidate and its scores. */
319
+ interface PolicyEditCandidateRecord {
320
+ schema: typeof POLICY_EDIT_CANDIDATE_RECORD_SCHEMA;
321
+ policyEdit: PolicyEdit;
322
+ }
323
+
324
+ /**
325
+ * Pass A substrate types — `runCampaign` is the one primitive every
326
+ * eval flow composes from. Three contracts in this file:
327
+ *
328
+ * - `Scenario` input set
329
+ * - `DispatchFn` how to run one scenario → artifact
330
+ * - `CampaignResult` defined output schema (the contract downstream tools depend on)
331
+ *
332
+ * Three more lifted from earlier substrate work (re-exported):
333
+ *
334
+ * - `JudgeConfig` pluggable dimensional scorer (0.38)
335
+ * - `Mutator` optimization-loop surface mutator
336
+ * - `Gate` promotion gate (`HeldOutGate` and friends adapt to this)
337
+ *
338
+ * No new architecture vs 0.38 — Pass A formalizes the shapes so consumers
339
+ * can build dashboards / CI gates / regression diffs against a stable schema.
340
+ */
341
+
342
+ /** Stable identifier + kind tag for any scenario. Consumers
343
+ * extend with their per-domain payload (persona, task, requirement, ...). */
344
+ interface Scenario {
345
+ id: string;
346
+ kind: string;
347
+ tags?: string[];
348
+ }
349
+ /** Context handed to every dispatch invocation. Scoped — every
350
+ * trace/span carries the cellId, every artifact write lands under the cell's
351
+ * artifact root, the cost meter accumulates per cell. */
352
+ interface DispatchContext {
353
+ cellId: string;
354
+ rep: number;
355
+ generation?: number;
356
+ seed: number;
357
+ signal: AbortSignal;
358
+ trace: CampaignTraceWriter;
359
+ artifacts: CampaignArtifactWriter;
360
+ cost: CampaignCostMeter;
361
+ /** Populated when this run is part of a multi-cycle improvement loop. */
362
+ cycleId?: string;
363
+ /** Populated when the substrate resumed from a prior cache hit. */
364
+ resumedFrom?: string;
365
+ /**
366
+ * Opaque placement key supplied by `RunCampaignOptions.cellPlacement`.
367
+ * The substrate forwards it through unchanged; placement-aware Dispatch
368
+ * implementations (e.g. `httpDispatch` from `/adapters/http`) read it to
369
+ * route the cell to the right worker / region / sandbox. `undefined`
370
+ * when no placement strategy is configured.
371
+ */
372
+ placement?: string;
373
+ }
374
+ /** The canonical judge verdict shape — one declaration, shared by campaign
375
+ * judges and the multishot judge runner (which re-exports this type).
376
+ *
377
+ * Scale is PRODUCER-DEFINED: campaign convention is [0,1]; the legacy
378
+ * multishot runner emits 0-10. Cross-scale comparison must go through
379
+ * `detectScale` (src/campaign/gates/statistical-heldout.ts, used by
380
+ * promotion-policy) — never renormalize a producer's values in place, as
381
+ * downstream thresholds (`composite >= 5` in multishot/matrix.ts, live-soak
382
+ * `>= 7` gates) key on the producer's native scale. */
383
+ interface JudgeScore {
384
+ dimensions: Record<string, number>;
385
+ composite: number;
386
+ notes: string;
387
+ /** Provider metadata for display and diagnostics; accounting uses CostLedger receipts. */
388
+ llmCall?: LlmCallMetadata;
389
+ /** Set when the judge itself failed (call error, unparseable output).
390
+ * `composite`/`dimensions` carry no signal — aggregators MUST exclude
391
+ * failed scores from means instead of folding them into zeros. */
392
+ failed?: true;
393
+ /** Ensemble extras (populated by `ensembleJudge`): max per-dimension
394
+ * spread across surviving judges — the inter-rater signal. */
395
+ maxDisagreement?: number;
396
+ /** Ensemble extras: judge identities whose verdict failed. */
397
+ failedJudges?: string[];
398
+ /** Ensemble extras: each surviving judge's per-dimension scores. */
399
+ perJudge?: Record<string, Record<string, number>>;
400
+ }
401
+ /** Five-valued verdict taxonomy (MOSS-paper alignment). */
402
+ type GateDecision = 'ship' | 'hold' | 'need_more_work' | 'model_ceiling' | 'arch_ceiling';
403
+ interface GateResult {
404
+ decision: GateDecision;
405
+ reasons: string[];
406
+ contributingGates: Array<{
407
+ name: string;
408
+ passed: boolean;
409
+ detail: unknown;
410
+ }>;
411
+ delta?: number;
412
+ }
413
+ /** Scoped trace writer handed to each dispatch — every span
414
+ * auto-tagged with the cellId so traces filter cleanly. */
415
+ interface CampaignTraceWriter {
416
+ span(name: string, attributes?: Record<string, unknown>): TraceSpan;
417
+ flush(): Promise<void>;
418
+ }
419
+ interface TraceSpan {
420
+ end(attributes?: Record<string, unknown>): void;
421
+ setAttribute(key: string, value: unknown): void;
422
+ }
423
+ /** Scoped artifact writer — `write(path, content)` lands under
424
+ * `<runDir>/<cellId>/<path>`. */
425
+ interface CampaignArtifactWriter {
426
+ write(path: string, content: string | Uint8Array): Promise<string>;
427
+ writeJson(path: string, value: unknown): Promise<string>;
428
+ }
429
+ /** Token usage accumulated for a cell. Aliased to the canonical `RunTokenUsage`
430
+ * (run-record.ts, same package) so a cell maps onto a `RunRecord` for the
431
+ * backend-integrity guard with ONE source of truth — a field added to
432
+ * `RunTokenUsage` is a compile error here, not a silent drift. */
433
+ type CampaignTokenUsage = RunTokenUsage;
434
+ /** Cell-scoped paid-call entry point. The dispatch places every paid operation
435
+ * inside `runPaidCall`; the returned provider result supplies one receipt with
436
+ * cost, tokens, and resolved model. Calls made outside this method are not
437
+ * admitted or captured. */
438
+ interface CampaignCostMeter {
439
+ /** The only paid-call path. Returns a typed result; callers must inspect it. */
440
+ runPaidCall<T>(input: Omit<RunPaidCallInput<T>, 'channel' | 'phase' | 'tags'> & {
441
+ channel?: CostChannel;
442
+ }): Promise<PaidCallResult<T>>;
443
+ }
444
+ interface CampaignCellResult<TArtifact> {
445
+ /** Manifest that produced this cell. Resumability refuses to reuse a cell
446
+ * whose manifest differs from the current run. */
447
+ manifestHash?: string;
448
+ cellId: string;
449
+ scenarioId: string;
450
+ rep: number;
451
+ generation?: number;
452
+ artifact: TArtifact;
453
+ judgeScores: Record<string, JudgeScore>;
454
+ costUsd: number;
455
+ /** True when at least one priced receipt used the model table instead of a provider bill. */
456
+ costEstimated?: boolean;
457
+ /** Exact durable receipts required to reuse this cached result. */
458
+ costCallIds?: string[];
459
+ /** Agent-call token usage committed by `ctx.cost.runPaidCall`.
460
+ * `{ input: 0, output: 0 }` when no paid agent call was recorded. */
461
+ tokenUsage: CampaignTokenUsage;
462
+ /** Concrete model from the latest committed agent receipt. Consumed by
463
+ * `buildRunRecord` to pin the model when the declared profile uses a
464
+ * runtime-resolved sentinel. */
465
+ resolvedModel?: string;
466
+ durationMs: number;
467
+ seed: number;
468
+ cached: boolean;
469
+ error?: string;
470
+ }
471
+ interface JudgeAggregate {
472
+ mean: number;
473
+ stdev: number;
474
+ ci95: [number, number];
475
+ n: number;
476
+ }
477
+ interface ScenarioAggregate {
478
+ meanComposite: number;
479
+ ci95: [number, number];
480
+ n: number;
481
+ }
482
+ interface GenerationRecord {
483
+ generationIndex: number;
484
+ candidates: GenerationCandidate[];
485
+ promoted: string[];
486
+ }
487
+ /** One scored candidate surface in a generation. `dimensions` + `scenarios`
488
+ * let a reflective proposer ground its next proposal on WHICH
489
+ * dimensions the candidate is weakest on and WHICH scenarios it best/worst
490
+ * handled — the evidence a blind `Mutator` cannot see. */
491
+ interface GenerationCandidate {
492
+ surfaceHash: string;
493
+ composite: number;
494
+ ci95: [number, number];
495
+ /** Exact surface this candidate mutated. */
496
+ parentSurfaceHash?: string;
497
+ /** Measured search-split composite of the exact parent surface. */
498
+ parentComposite?: number;
499
+ /** Candidate composite minus its parent's composite. Present only when the
500
+ * candidate completed the designed denominator. */
501
+ observedDeltaFromParent?: number;
502
+ /** Whether this candidate had a scorable result for every designed campaign
503
+ * cell and was therefore eligible for ranking, promotion, and Pareto
504
+ * selection. Older externally-authored records may omit this field; loop
505
+ * records always populate it. */
506
+ eligibleForPromotion?: boolean;
507
+ /** Exact denominator receipt for selection eligibility. Scores stay
508
+ * descriptive: an incomplete candidate is retained with its observed score
509
+ * and errors instead of receiving an invented penalty. */
510
+ coverage?: {
511
+ expectedCells: number;
512
+ scorableCells: number;
513
+ unscorableCells: Array<{
514
+ cellId: string;
515
+ reason: string;
516
+ }>;
517
+ };
518
+ /** Mean score per judge dimension across all cells (scenarios × reps ×
519
+ * judges that reported the dimension). */
520
+ dimensions: Record<string, number>;
521
+ /** Per-scenario composite (mean over reps + judges), plus the judge's
522
+ * free-form `notes` for that scenario — the "why it scored low" evidence a
523
+ * reflective proposer grounds its next edit on. Keep `notes` GENERALIZABLE
524
+ * (which checks/lines/dimensions failed and how), NOT case-specific ground
525
+ * truth: leaking expected answers into the prompt is memorization, and the
526
+ * held-out gate would reject it anyway. */
527
+ scenarios: Array<{
528
+ scenarioId: string;
529
+ composite: number;
530
+ notes?: string;
531
+ }>;
532
+ /** Proposer-supplied short label for the change. Present when the proposer
533
+ * returned a `ProposedCandidate`; absent for bare-surface mutators. */
534
+ label?: string;
535
+ /** Proposer-supplied rationale — WHY this candidate was proposed. The
536
+ * "because rationale Z" the audit requires to survive to the result.
537
+ * Present when the proposer returned a `ProposedCandidate`. */
538
+ rationale?: string;
539
+ /** Exact structured cause threaded from the proposer, when available. */
540
+ candidateRecord?: PolicyEditCandidateRecord;
541
+ }
542
+ interface CampaignAggregates {
543
+ byJudge: Record<string, JudgeAggregate>;
544
+ byScenario: Record<string, ScenarioAggregate>;
545
+ /** Canonical campaign accounting, including worker and judge calls. */
546
+ cost: CostLedgerSummary;
547
+ /** Compatibility alias of `cost.totalCostUsd`. */
548
+ totalCostUsd: number;
549
+ cellsExecuted: number;
550
+ cellsSkipped: number;
551
+ cellsCached: number;
552
+ cellsFailed: number;
553
+ }
554
+ interface CampaignResult<TArtifact = unknown, TScenario extends Scenario = Scenario> {
555
+ /** sha256(scenarios, judges, dispatch source ref, optimizer config, seed). Stable identity for reruns. */
556
+ manifestHash: string;
557
+ seed: number;
558
+ startedAt: string;
559
+ endedAt: string;
560
+ durationMs: number;
561
+ cells: Array<CampaignCellResult<TArtifact>>;
562
+ aggregates: CampaignAggregates;
563
+ optimization?: {
564
+ generations: GenerationRecord[];
565
+ winnerSurfaceHash?: string;
566
+ };
567
+ gate?: GateResult;
568
+ prUrl?: string;
569
+ runDir: string;
570
+ artifactsByPath: Record<string, string>;
571
+ /** Substrate strips the input scenarios to id+kind for the result manifest;
572
+ * consumers needing full payload look it up via the original input. The
573
+ * type parameter `TScenario` is propagated for downstream consumers that
574
+ * want narrowed types when extending `CampaignResult`. */
575
+ scenarios: Array<Pick<TScenario, 'id' | 'kind'>>;
576
+ }
577
+
578
+ /**
579
+ * Shared types for the reference benchmark wrappers under
580
+ * `src/benchmarks/`. Each wrapper exports the three functions in
581
+ * `BenchmarkAdapter` plus its own typed `DatasetItem` shape.
582
+ */
583
+
584
+ type BenchmarkTaskKind = 'retrieval' | 'rag-answer' | 'hallucination' | 'kb-improvement' | 'routing' | 'custom';
585
+ type BenchmarkFamily = 'beir' | 'mteb-retrieval' | 'msmarco' | 'trec-dl' | 'miracl' | 'lotte' | 'bright' | 'crag' | 'hotpotqa' | 'kilt' | 'ragtruth' | 'faithbench' | 'first-party' | 'custom';
586
+ interface BenchmarkDatasetItem<TPayload = unknown> {
587
+ /** Stable dataset-local item id (used for split assignment + paper
588
+ * references). Unique within a benchmark. */
589
+ id: string;
590
+ /** Free-form payload. Each benchmark defines its own shape. */
591
+ payload: TPayload;
592
+ /** Optional precomputed split. When absent, adapters use assignSplit(id). */
593
+ split?: RunSplitTag;
594
+ /** Benchmark family this row came from, e.g. `beir` or `crag`. */
595
+ family?: BenchmarkFamily | string;
596
+ /** Benchmark-local task kind, e.g. retrieval vs answer quality. */
597
+ taskKind?: BenchmarkTaskKind | string;
598
+ /** Slice labels such as language, domain, freshness, multihop, long-tail. */
599
+ tags?: string[];
600
+ /** Dataset provenance, version, URL, or license notes. */
601
+ source?: BenchmarkSource;
602
+ metadata?: Record<string, unknown>;
603
+ }
604
+ interface BenchmarkEvaluation {
605
+ /** [0, 1] score for the response on this item. Exact-match
606
+ * benchmarks use 0/1; partial-credit benchmarks may return
607
+ * fractional values. */
608
+ score: number;
609
+ /** Optional pass/fail projection. Defaults to `score > 0` when absent. */
610
+ passed?: boolean;
611
+ /** Numeric sub-metrics. These become report dimensions. */
612
+ dimensions?: Record<string, number>;
613
+ /** Optional bag of raw scoring signals — e.g. parsed numeric
614
+ * answer, regex match, judge sub-scores. */
615
+ raw: Record<string, unknown>;
616
+ notes?: string;
617
+ }
618
+ interface BenchmarkSource {
619
+ name?: string;
620
+ url?: string;
621
+ version?: string;
622
+ license?: string;
623
+ citation?: string;
624
+ }
625
+ /** Common signature implemented by every adapter under `src/benchmarks/*`. */
626
+ interface BenchmarkAdapter<_TItem = unknown, TPayload = unknown, TArtifact = string> {
627
+ /** Stable benchmark id such as `beir/nfcorpus` or `crag/smoke`. */
628
+ id?: string;
629
+ family?: BenchmarkFamily | string;
630
+ taskKind?: BenchmarkTaskKind | string;
631
+ description?: string;
632
+ source?: BenchmarkSource;
633
+ defaultMetric?: string;
634
+ /** Load the dataset for the given split. May hit the network on
635
+ * first call but should be cache-friendly. Adapters that don't
636
+ * ship the dataset itself MUST throw a clearly-marked error
637
+ * pointing the caller at the loader script. */
638
+ loadDataset(split: RunSplitTag): Promise<BenchmarkDatasetItem<TPayload>[]>;
639
+ /** Score a single response. Pure with respect to the inputs. */
640
+ evaluate(item: BenchmarkDatasetItem<TPayload>, artifact: TArtifact): Promise<BenchmarkEvaluation>;
641
+ /** Deterministic split assignment via item id hashing. The
642
+ * fraction of items in each split is implementation-defined but
643
+ * MUST be stable across processes and platforms. */
644
+ assignSplit(itemId: string): RunSplitTag;
645
+ }
646
+ interface BenchmarkScenario<TPayload = unknown> extends Scenario {
647
+ kind: 'benchmark';
648
+ benchmarkId: string;
649
+ family: BenchmarkFamily | string;
650
+ taskKind: BenchmarkTaskKind | string;
651
+ splitTag: RunSplitTag;
652
+ item: BenchmarkDatasetItem<TPayload>;
653
+ }
654
+ type BenchmarkResponder<TPayload = unknown, TArtifact = string> = (input: {
655
+ scenario: BenchmarkScenario<TPayload>;
656
+ item: BenchmarkDatasetItem<TPayload>;
657
+ context: DispatchContext;
658
+ }) => Promise<TArtifact> | TArtifact;
659
+ /** Split-assignment seed shared across all benchmarks. Bumping this
660
+ * value reshuffles every split — do NOT do that lightly. */
661
+ declare const BENCHMARK_SPLIT_SEED = "agent-eval-v1";
662
+ /**
663
+ * Assign an item id to one of `'search' | 'dev' | 'holdout'` using a
664
+ * stable 32-bit hash of `${seed}::${id}`. Default proportions:
665
+ *
666
+ * search: 60% (optimization-readable)
667
+ * dev: 20% (held-out for tuning, leak-on-purpose during dev)
668
+ * holdout:20% (paper-grade held-out, gated reads)
669
+ */
670
+ declare function deterministicSplit(itemId: string, seed?: string): RunSplitTag;
671
+
672
+ interface BenchmarkMetricCalibrationOptions<TPayload = unknown, TArtifact = string> {
673
+ adapter: BenchmarkAdapter<BenchmarkDatasetItem<TPayload>, TPayload, TArtifact>;
674
+ item: BenchmarkDatasetItem<TPayload>;
675
+ weakArtifact: TArtifact;
676
+ strongArtifact: TArtifact;
677
+ maxWeakScore?: number;
678
+ minStrongScore?: number;
679
+ minGap?: number;
680
+ }
681
+ interface BenchmarkMetricCalibrationResult {
682
+ passed: boolean;
683
+ weak: BenchmarkEvaluation;
684
+ strong: BenchmarkEvaluation;
685
+ weakScore: number;
686
+ strongScore: number;
687
+ gap: number;
688
+ reasons: string[];
689
+ }
690
+ declare function calibrateBenchmarkMetric<TPayload = unknown, TArtifact = string>(options: BenchmarkMetricCalibrationOptions<TPayload, TArtifact>): Promise<BenchmarkMetricCalibrationResult>;
691
+
692
+ /**
693
+ * Synthetic routing dataset. 16 tasks across 4 categories. Used as a
694
+ * deterministic, dependency-free benchmark for any router that maps a
695
+ * natural-language request to one of a fixed set of route labels.
696
+ *
697
+ * Format (see `routing/README.md` for prose):
698
+ *
699
+ * {
700
+ * id: stable per-task ID (matches across processes).
701
+ * category: one of the four route labels.
702
+ * prompt: the user-facing request the router must classify.
703
+ * route: the ground-truth route the router should pick.
704
+ * synonyms: other strings that count as a correct answer.
705
+ * hardNegatives:close-but-wrong route labels — used to detect the
706
+ * "always picks the popular route" failure mode.
707
+ * }
708
+ *
709
+ * The four categories are intentionally cross-domain (file ops,
710
+ * math, search, conversation) so a router that collapses to one
711
+ * category is easy to spot.
712
+ */
713
+ interface RoutingItem {
714
+ id: string;
715
+ category: 'file' | 'math' | 'search' | 'chat';
716
+ prompt: string;
717
+ /** Canonical correct route label. */
718
+ route: string;
719
+ /** Alternate route labels that also count as correct. */
720
+ synonyms: string[];
721
+ /** Wrong-but-tempting route labels (for analysis, not grading). */
722
+ hardNegatives: string[];
723
+ }
724
+ declare const ROUTING_DATASET: RoutingItem[];
725
+
726
+ /**
727
+ * Routing benchmark — synthetic, dependency-free, ships in the
728
+ * package. 16 cross-category items in `dataset.ts`. See
729
+ * `routing/README.md` for the format.
730
+ *
731
+ * `evaluate` does case-insensitive exact match against the canonical
732
+ * route plus declared synonyms. The first valid route token in the
733
+ * response wins; everything else is ignored. Wrong answers also
734
+ * report whether they hit a hard negative — useful when triaging
735
+ * "always picks the popular route" failure modes.
736
+ */
737
+
738
+ type RoutingPayload = RoutingItem;
739
+ type RoutingDatasetItem = BenchmarkDatasetItem<RoutingPayload>;
740
+ declare class RoutingAdapter implements BenchmarkAdapter<RoutingDatasetItem, RoutingPayload> {
741
+ readonly id = "first-party/routing";
742
+ readonly family = "first-party";
743
+ readonly taskKind = "routing";
744
+ readonly description = "Synthetic fixed-route classification smoke benchmark";
745
+ readonly defaultMetric = "route_exact_match";
746
+ loadDataset(split: RunSplitTag): Promise<RoutingDatasetItem[]>;
747
+ evaluate(item: RoutingDatasetItem, response: string): Promise<BenchmarkEvaluation>;
748
+ assignSplit(itemId: string): RunSplitTag;
749
+ }
750
+ /**
751
+ * Pull route-shaped tokens out of a model response. Routes look like
752
+ * `category.action` (`fs.write`, `chat.reply`). Bare alphanumerics
753
+ * are not routes, but `category.action` patterns are robust to most
754
+ * model wrappers (JSON output, prose explanations, code fences).
755
+ */
756
+ declare function extractRouteTokens(response: string): string[];
757
+ declare const loadDataset: (split: RunSplitTag) => Promise<RoutingDatasetItem[]>;
758
+ declare const evaluate: (item: RoutingDatasetItem, response: string) => Promise<BenchmarkEvaluation>;
759
+ declare const assignSplit: (itemId: string) => RunSplitTag;
760
+
761
+ declare const index_ROUTING_DATASET: typeof ROUTING_DATASET;
762
+ type index_RoutingAdapter = RoutingAdapter;
763
+ declare const index_RoutingAdapter: typeof RoutingAdapter;
764
+ type index_RoutingDatasetItem = RoutingDatasetItem;
765
+ type index_RoutingItem = RoutingItem;
766
+ type index_RoutingPayload = RoutingPayload;
767
+ declare const index_assignSplit: typeof assignSplit;
768
+ declare const index_evaluate: typeof evaluate;
769
+ declare const index_extractRouteTokens: typeof extractRouteTokens;
770
+ declare const index_loadDataset: typeof loadDataset;
771
+ declare namespace index {
772
+ export { index_ROUTING_DATASET as ROUTING_DATASET, index_RoutingAdapter as RoutingAdapter, type index_RoutingDatasetItem as RoutingDatasetItem, type index_RoutingItem as RoutingItem, type index_RoutingPayload as RoutingPayload, index_assignSplit as assignSplit, index_evaluate as evaluate, index_extractRouteTokens as extractRouteTokens, index_loadDataset as loadDataset };
773
+ }
774
+
775
+ /**
776
+ * `CampaignStorage` — the filesystem seam `runCampaign` writes through
777
+ * (run/cell dirs, the resumability cache, per-cell artifacts, trace spans).
778
+ *
779
+ * The default (`fsCampaignStorage`) is the Node filesystem — identical
780
+ * behavior to the inline `node:fs` calls it replaces, so existing CLI
781
+ * consumers are unaffected. `inMemoryCampaignStorage` keeps everything in a
782
+ * `Map`, so the substrate runs in environments WITHOUT a filesystem
783
+ * (Cloudflare Workers, Deno Deploy, other edge runtimes) — the campaign
784
+ * still produces its `CampaignResult` (cells + aggregates) in memory;
785
+ * artifacts/traces simply aren't persisted to disk.
786
+ *
787
+ * Paths are opaque keys to the in-memory adapter — it does not parse them,
788
+ * so the same `join(...)`-built paths work unchanged across both adapters.
789
+ */
790
+ interface CampaignStorage {
791
+ /** Ensure a directory exists (recursive). No-op for in-memory. */
792
+ ensureDir(dir: string): void;
793
+ /** Does this path exist (as a written file or an ensured dir)? */
794
+ exists(path: string): boolean;
795
+ /** Read a UTF-8 file; `undefined` when missing or unreadable. */
796
+ read(path: string): string | undefined;
797
+ /** Write a file (string or bytes). Parent dir is assumed ensured. */
798
+ write(path: string, content: string | Uint8Array): void;
799
+ /** Append only when the current UTF-8 byte length matches `expectedBytes`.
800
+ * Returns the new length, or undefined when another writer won. */
801
+ append?(path: string, content: string, expectedBytes: number): number | undefined;
802
+ }
803
+
804
+ interface BenchmarkRunOptions<TPayload = unknown, TArtifact = string> {
805
+ adapter: BenchmarkAdapter<BenchmarkDatasetItem<TPayload>, TPayload, TArtifact>;
806
+ respond: BenchmarkResponder<TPayload, TArtifact>;
807
+ splits?: readonly RunSplitTag[];
808
+ runDir: string;
809
+ repo?: string;
810
+ seed?: number;
811
+ reps?: number;
812
+ resumable?: boolean;
813
+ costCeiling?: number;
814
+ maxConcurrency?: number;
815
+ dispatchTimeoutMs?: number;
816
+ expectUsage?: 'assert' | 'warn' | 'off';
817
+ storage?: CampaignStorage;
818
+ now?: () => Date;
819
+ }
820
+ interface BenchmarkReport {
821
+ benchmarkId: string;
822
+ family: BenchmarkFamily | string;
823
+ taskKind: BenchmarkTaskKind | string;
824
+ source?: BenchmarkAdapter['source'];
825
+ runDir: string;
826
+ manifestHash: string;
827
+ seed: number;
828
+ startedAt: string;
829
+ endedAt: string;
830
+ durationMs: number;
831
+ totalItems: number;
832
+ totalCells: number;
833
+ cellsFailed: number;
834
+ cellsCached: number;
835
+ totalCostUsd: number;
836
+ splits: Record<string, BenchmarkSliceSummary>;
837
+ tags: Record<string, BenchmarkSliceSummary>;
838
+ dimensions: Record<string, BenchmarkDistribution>;
839
+ score: BenchmarkDistribution;
840
+ costUsd: BenchmarkDistribution;
841
+ latencyMs: BenchmarkDistribution;
842
+ }
843
+ interface BenchmarkSliceSummary {
844
+ n: number;
845
+ meanScore: number;
846
+ passRate: number;
847
+ score: BenchmarkDistribution;
848
+ costUsd: BenchmarkDistribution;
849
+ latencyMs: BenchmarkDistribution;
850
+ }
851
+ interface BenchmarkDistribution {
852
+ n: number;
853
+ min: number;
854
+ mean: number;
855
+ median: number;
856
+ p90: number;
857
+ max: number;
858
+ }
859
+ interface BenchmarkRunResult<TPayload = unknown, TArtifact = string> {
860
+ scenarios: Array<BenchmarkScenario<TPayload>>;
861
+ campaign: CampaignResult<TArtifact, BenchmarkScenario<TPayload>>;
862
+ report: BenchmarkReport;
863
+ reportJsonPath: string;
864
+ reportMarkdownPath: string;
865
+ }
866
+ declare function runBenchmarkAdapter<TPayload = unknown, TArtifact = string>(options: BenchmarkRunOptions<TPayload, TArtifact>): Promise<BenchmarkRunResult<TPayload, TArtifact>>;
867
+ declare function summarizeBenchmarkCampaign<TPayload, TArtifact>(input: {
868
+ adapter: BenchmarkAdapter<BenchmarkDatasetItem<TPayload>, TPayload, TArtifact>;
869
+ scenarios: Array<BenchmarkScenario<TPayload>>;
870
+ campaign: CampaignResult<TArtifact, BenchmarkScenario<TPayload>>;
871
+ }): BenchmarkReport;
872
+ declare function renderBenchmarkReportMarkdown(report: BenchmarkReport): string;
873
+
874
+ interface StandardRetrievalDocument {
875
+ id: string;
876
+ title?: string;
877
+ text: string;
878
+ metadata?: Record<string, unknown>;
879
+ }
880
+ interface StandardRetrievalQuery {
881
+ id: string;
882
+ text: string;
883
+ metadata?: Record<string, unknown>;
884
+ }
885
+ interface StandardRetrievalQrel {
886
+ queryId: string;
887
+ documentId: string;
888
+ score: number;
889
+ }
890
+ interface StandardRetrievalPayload {
891
+ queryId: string;
892
+ query: string;
893
+ expectedDocumentIds: string[];
894
+ expectedScores: Record<string, number>;
895
+ corpus?: Record<string, StandardRetrievalDocument>;
896
+ metadata?: Record<string, unknown>;
897
+ }
898
+ interface BuildStandardRetrievalItemsOptions {
899
+ benchmarkId: string;
900
+ family: BenchmarkFamily | string;
901
+ queries: readonly StandardRetrievalQuery[];
902
+ qrels: readonly StandardRetrievalQrel[];
903
+ corpus?: readonly StandardRetrievalDocument[];
904
+ includeCorpusInPayload?: boolean;
905
+ source?: BenchmarkSource;
906
+ tags?: readonly string[];
907
+ splitOf?: (queryId: string) => RunSplitTag;
908
+ }
909
+ interface RetrievalIdAdapterOptions extends BuildStandardRetrievalItemsOptions {
910
+ responseIdPattern?: RegExp;
911
+ cutoffs?: readonly number[];
912
+ primaryMetric?: string;
913
+ passMetric?: string;
914
+ passThreshold?: number;
915
+ }
916
+ interface StandardRetrievalResult {
917
+ id?: string;
918
+ documentId?: string;
919
+ docId?: string;
920
+ score?: number;
921
+ }
922
+ type StandardRetrievalArtifact = string | readonly string[] | readonly StandardRetrievalResult[] | {
923
+ ids?: readonly string[];
924
+ documentIds?: readonly string[];
925
+ results?: readonly StandardRetrievalResult[];
926
+ };
927
+ interface StandardRetrievalEvaluationOptions {
928
+ responseIdPattern?: RegExp;
929
+ cutoffs?: readonly number[];
930
+ primaryMetric?: string;
931
+ passMetric?: string;
932
+ passThreshold?: number;
933
+ }
934
+ declare function parseJsonlRows<T = unknown>(text: string): T[];
935
+ declare function parseTsvRows(text: string): string[][];
936
+ declare function parseQrels(text: string): StandardRetrievalQrel[];
937
+ declare function parseBeirCorpusJsonl(text: string): StandardRetrievalDocument[];
938
+ declare function parseBeirQueriesJsonl(text: string): StandardRetrievalQuery[];
939
+ declare function buildStandardRetrievalItems(options: BuildStandardRetrievalItemsOptions): Array<BenchmarkDatasetItem<StandardRetrievalPayload>>;
940
+ declare function createRetrievalIdBenchmarkAdapter(options: RetrievalIdAdapterOptions): BenchmarkAdapter<BenchmarkDatasetItem<StandardRetrievalPayload>, StandardRetrievalPayload, StandardRetrievalArtifact>;
941
+ declare function evaluateStandardRetrieval(payload: StandardRetrievalPayload, artifact: StandardRetrievalArtifact, options?: StandardRetrievalEvaluationOptions): {
942
+ score: number;
943
+ passed: boolean;
944
+ dimensions: Record<string, number>;
945
+ raw: {
946
+ rankedDocumentIds: string[];
947
+ expectedDocumentIds: string[];
948
+ expectedScores: Record<string, number>;
949
+ };
950
+ };
951
+ declare function normalizeRetrievedDocumentIds(artifact: StandardRetrievalArtifact, responseIdPattern?: RegExp): string[];
952
+ declare function retrievalMetricsAtCutoff(input: {
953
+ rankedDocumentIds: readonly string[];
954
+ expectedScores: Record<string, number>;
955
+ cutoff: number;
956
+ }): Record<string, number>;
957
+
958
+ export { BENCHMARK_SPLIT_SEED, type BenchmarkAdapter, type BenchmarkDatasetItem, type BenchmarkDistribution, type BenchmarkEvaluation, type BenchmarkFamily, type BenchmarkMetricCalibrationOptions, type BenchmarkMetricCalibrationResult, type BenchmarkReport, type BenchmarkResponder, type BenchmarkRunOptions, type BenchmarkRunResult, type BenchmarkScenario, type BenchmarkSliceSummary, type BenchmarkSource, type BenchmarkTaskKind, type BuildStandardRetrievalItemsOptions, type RetrievalIdAdapterOptions, type StandardRetrievalArtifact, type StandardRetrievalDocument, type StandardRetrievalEvaluationOptions, type StandardRetrievalPayload, type StandardRetrievalQrel, type StandardRetrievalQuery, type StandardRetrievalResult, buildStandardRetrievalItems, calibrateBenchmarkMetric, createRetrievalIdBenchmarkAdapter, deterministicSplit, evaluateStandardRetrieval, normalizeRetrievedDocumentIds, parseBeirCorpusJsonl, parseBeirQueriesJsonl, parseJsonlRows, parseQrels, parseTsvRows, renderBenchmarkReportMarkdown, retrievalMetricsAtCutoff, index as routing, runBenchmarkAdapter, summarizeBenchmarkCampaign };