@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,387 +0,0 @@
1
- import { a as RunSplitTag, c as RunTokenUsage, d as RunJudgeMetadata, J as JudgeScoresRecord, A as AgentProfileCell, e as AgentProfileCellInput, R as RunRecord } from './run-record-BDH49H2E.js';
2
- import { a as LlmClientOptions, b as LlmRouteRequirements } from './llm-client-qoDd18Qz.js';
3
- import { h as ResearchReportOptions, d as ResearchReport, m as GateDecision } from './summary-report-C5bKFfm-.js';
4
- import { T as TraceEmitter, R as RunCompleteHook } from './emitter-CjD7vUwv.js';
5
- import { R as RunIntegrityExpectations, a as RunIntegrityReport } from './integrity-DqlBiLyK.js';
6
- import { R as RawProviderSink } from './raw-provider-sink-C46HDghv.js';
7
- import { F as FailureClass } from './schema-B3Q3l9Z_.js';
8
- import { T as TraceStore } from './store-DGqD0Pyo.js';
9
-
10
- /**
11
- * EvalCampaign — opinionated matrix runner that wires the four
12
- * capture-integrity directives by construction.
13
- *
14
- * The canonical benchmark shape — matrix runner → for each
15
- * (variant, scenario, seed) → start a TraceEmitter → call LLMs → end the
16
- * run → analyze — has a bug class at the integration boundary: raw
17
- * events not captured, route silently wrong, integrity not asserted,
18
- * analyst never run. The directives in `SKILL.md § Capture integrity`
19
- * are the mitigations.
20
- *
21
- * `EvalCampaign` is the structural fix — consumers don't wire the
22
- * integrity surface themselves; the campaign owns it. Specifically:
23
- *
24
- * - calls `assertLlmRoute` once at preflight before any work runs
25
- * - constructs a per-run `TraceStore` and `RawProviderSink` via factories
26
- * - constructs the `TraceEmitter` with `onRunComplete: [analyst hook]`
27
- * - hands the runner an `LlmClientOptions` pre-wired with the sink and
28
- * trace context — the runner can't accidentally call an LLM without
29
- * capturing the raw HTTP envelope
30
- * - calls `assertRunCaptured` after every `endRun` and routes failures
31
- * through a configurable policy (`throw` / `mark_failed` / `log`)
32
- * - assembles per-run `RunRecord`s and runs `researchReport` at the end
33
- * so the campaign artifact is launch-decision-grade by default
34
- * - embeds the campaign fingerprint (a SHA-256 over the canonicalised
35
- * run set) and optional `preregistrationHash` in the report
36
- *
37
- * The runner contract is intentionally narrow: produce a `CampaignRunOutcome`
38
- * given a fully-wired `CampaignRunContext`. Everything orchestration-shaped
39
- * lives in the campaign. This is the inversion-of-control point — consumers
40
- * stop writing matrix runners and start writing scenario-runners.
41
- *
42
- * Out of scope for v1 (tracked in `docs/research-report-methodology.md`):
43
- *
44
- * - Distributed/cluster execution (concurrency is local async)
45
- * - Adaptive sampling / sequential interim looks
46
- * - Resume from partial state across crashes
47
- * - LLM-call retry beyond what `LlmClient` already does
48
- */
49
-
50
- interface CampaignVariant<V> {
51
- id: string;
52
- payload: V;
53
- }
54
- interface CampaignScenario {
55
- scenarioId: string;
56
- /** Free-form metadata propagated to runs and reports. */
57
- tags?: Record<string, string>;
58
- }
59
- interface CampaignRunContext<V> {
60
- /** Stable run id. The campaign generates this; the runner does not. */
61
- runId: string;
62
- /** Logical experiment id (campaignId by default; overridable per-run via opts). */
63
- experimentId: string;
64
- variant: V;
65
- variantId: string;
66
- scenarioId: string;
67
- scenarioTags: Record<string, string>;
68
- seed: number;
69
- splitTag: RunSplitTag;
70
- /**
71
- * The TraceEmitter for this run, with `onRunComplete` hooks pre-wired
72
- * (analyst auto-execution if configured, plus integrity check). The
73
- * runner MUST call `emitter.startRun` before doing any work and either
74
- * `emitter.endRun` or `emitter.abortRun` before returning.
75
- */
76
- emitter: TraceEmitter;
77
- store: TraceStore;
78
- rawSink: RawProviderSink;
79
- /**
80
- * Pre-wired LLM client options — `rawSink` and `traceContext` are populated
81
- * so any `callLlm(req, ctx.llmOpts)` automatically captures raw HTTP. The
82
- * runner can spread additional fields if needed.
83
- */
84
- llmOpts: LlmClientOptions;
85
- }
86
- interface CampaignRunOutcome {
87
- /** Did the run pass? Mirrors `RunOutcome.pass` semantics. */
88
- pass: boolean;
89
- /** Score for the run on its split. Maps to `searchScore` or `holdoutScore`. */
90
- score: number;
91
- /** Mandatory cost in USD. Use 0 + raw.cost_unknown=1 only if truly unknown. */
92
- costUsd: number;
93
- tokenUsage: RunTokenUsage;
94
- /** Snapshot model id (e.g. `claude-sonnet-4-6@2025-04-15`). */
95
- model: string;
96
- /** sha256 of the effective prompt sent to the model. */
97
- promptHash: string;
98
- /** sha256 of the effective config (model, temperature, tools, judges, splits). */
99
- configHash: string;
100
- /** Optional extra numeric metrics to land in `outcome.raw`. */
101
- raw?: Record<string, number>;
102
- /** Canonical cross-agent failure class from the shared `FAILURE_CLASSES`
103
- * taxonomy. Propagated to `RunRecord.failureClass` so campaign runs
104
- * aggregate failures in the same vocabulary as every other producer. */
105
- failureClass?: FailureClass;
106
- /** Optional free-form failure detail, scoped under `failureClass`. */
107
- failureMode?: string;
108
- /** Optional judge metadata when a judge was used. */
109
- judgeMetadata?: RunJudgeMetadata;
110
- /**
111
- * Optional per-judge / per-dim breakdown for ensemble-judged runs.
112
- * Propagated to `outcome.judgeScores` on the resulting `RunRecord`.
113
- * Single-judge or scalar-only runs leave this unset.
114
- */
115
- judgeScores?: JudgeScoresRecord;
116
- /**
117
- * Agent profile cell observed by the runner. When supplied, it overrides
118
- * `EvalCampaignOptions.agentProfile` for this run and must match the
119
- * outcome's `model` and `promptHash`.
120
- */
121
- agentProfile?: AgentProfileCell | AgentProfileCellInput;
122
- }
123
- type CampaignRunner<V> = (ctx: CampaignRunContext<V>) => Promise<CampaignRunOutcome>;
124
- type CampaignIntegrityPolicy = 'throw' | 'mark_failed' | 'log';
125
- interface EvalCampaignOptions<V> {
126
- /**
127
- * Stable id for the campaign. Used as the default `experimentId` on
128
- * every run, and folded into the campaign fingerprint.
129
- */
130
- campaignId: string;
131
- variants: CampaignVariant<V>[];
132
- scenarios: CampaignScenario[];
133
- /** Default `[0, 1, 2]`. */
134
- seeds?: number[];
135
- /** Default `'holdout'` — the split that anchors a launch decision. */
136
- splitTag?: RunSplitTag;
137
- /** Git SHA the campaign is run against. Mandatory; `RunRecord` rejects unset. */
138
- commitSha: string;
139
- /**
140
- * LLM client config. Augmented per-run with `rawSink` and `traceContext`
141
- * before being passed to the runner. The campaign asserts this config
142
- * matches `routeRequirements` once at preflight.
143
- */
144
- llmOpts: LlmClientOptions;
145
- /**
146
- * Default `{ requireExplicitBaseUrl: true, requireAuth: true }` — fail
147
- * loud if the campaign would silently fall back to the public router or
148
- * run unauthenticated. Override with an empty object to disable.
149
- */
150
- routeRequirements?: LlmRouteRequirements;
151
- /**
152
- * Per-run TraceStore factory. Common shape: a fresh store per run keyed
153
- * on `runId`. Implementations that share a store across the campaign
154
- * are valid — the campaign only writes through `emitter`.
155
- */
156
- storeFactory: (params: CampaignFactoryParams) => TraceStore;
157
- /**
158
- * Per-run RawProviderSink factory. Defaults to `FileSystemRawProviderSink`
159
- * rooted at `${workDir}/raw-events/${runId}` if `workDir` is supplied;
160
- * otherwise required. Forensic capture is non-negotiable in a campaign
161
- * run — pass `NoopRawProviderSink` explicitly if you want to opt out.
162
- */
163
- rawSinkFactory?: (params: CampaignFactoryParams) => RawProviderSink;
164
- /**
165
- * Filesystem root for default `rawSinkFactory`. Ignored if
166
- * `rawSinkFactory` is supplied.
167
- */
168
- workDir?: string;
169
- /**
170
- * Extra `onRunComplete` hooks the campaign appends (after its own
171
- * integrity-check hook). Pass `traceAnalystOnRunComplete(...)` here.
172
- */
173
- onRunComplete?: RunCompleteHook[];
174
- /**
175
- * Per-run integrity expectations. Defaults to:
176
- * `{ llmSpansMin: 1, requireRawCoverageOfLlmSpans: true, requireOutcome: true }`.
177
- * Override (e.g. `{ llmSpansMin: 0 }`) for runs that don't call LLMs.
178
- */
179
- integrity?: RunIntegrityExpectations;
180
- /** Behaviour when integrity fails. Default `'mark_failed'`. */
181
- onIntegrityFailure?: CampaignIntegrityPolicy;
182
- /**
183
- * Per-run runner. Receives a fully-wired context; produces an outcome
184
- * the campaign converts into a `RunRecord`.
185
- */
186
- runner: CampaignRunner<V>;
187
- /**
188
- * If set, the campaign computes `researchReport` at the end. `comparator`
189
- * is a `variantId`. Other fields are forwarded verbatim.
190
- */
191
- report?: {
192
- comparator?: string;
193
- } & Omit<ResearchReportOptions, 'comparator' | 'preregistrationHash' | 'generatedAt'>;
194
- /**
195
- * Hash of a signed `HypothesisManifest` (see `pre-registration.ts`).
196
- * Embedded in the campaign fingerprint and the research report.
197
- */
198
- preregistrationHash?: string;
199
- /** Local concurrency. Default `1` (sequential). */
200
- concurrency?: number;
201
- /**
202
- * Override the time source. Tests pass a mock to make wallMs deterministic.
203
- */
204
- now?: () => number;
205
- /** Override the runId generator. Tests pin this. */
206
- runId?: (params: CampaignFactoryParams) => string;
207
- /**
208
- * Agent profile cell for campaign runs. Static profiles can pass an object;
209
- * routers or variant-specific harnesses can pass a factory. The campaign
210
- * stamps the built cell onto every `RunRecord` and rejects profile/model or
211
- * profile/prompt contradictions.
212
- */
213
- agentProfile?: AgentProfileCell | AgentProfileCellInput | ((params: CampaignFactoryParams & {
214
- variant: V;
215
- scenarioTags: Record<string, string>;
216
- }) => AgentProfileCell | AgentProfileCellInput | Promise<AgentProfileCell | AgentProfileCellInput>);
217
- }
218
- interface CampaignFactoryParams {
219
- campaignId: string;
220
- runId: string;
221
- variantId: string;
222
- scenarioId: string;
223
- seed: number;
224
- }
225
- interface FailedRun {
226
- runId: string;
227
- variantId: string;
228
- scenarioId: string;
229
- seed: number;
230
- reason: string;
231
- error?: string;
232
- }
233
- interface EvalCampaignResult {
234
- campaignId: string;
235
- /** SHA-256 over canonicalised `(variantIds, scenarioIds, seeds, comparator, splitTag, baseUrl, provider, preregistrationHash)`. */
236
- campaignFingerprint: string;
237
- preregistrationHash: string | null;
238
- /** Successful runs only. Failed runs land in `failedRuns`. */
239
- runs: RunRecord[];
240
- /** Integrity reports for every successful run. */
241
- integrityReports: RunIntegrityReport[];
242
- failedRuns: FailedRun[];
243
- /** Computed when `report` is set on options. */
244
- report?: ResearchReport;
245
- startedAt: string;
246
- endedAt: string;
247
- }
248
- declare function runEvalCampaign<V>(opts: EvalCampaignOptions<V>): Promise<EvalCampaignResult>;
249
-
250
- /**
251
- * Researcher interface — stable hook for an external autonomous-research
252
- * agent to drive the meta-loop.
253
- *
254
- * Implementations live downstream (typically in a private repo that
255
- * runs the actual LLM). This package ships only the contract + a
256
- * `NoopResearcher` so consumers can wire the surface without being
257
- * forced to implement every method up front.
258
- *
259
- * The four methods mirror the four stages of the paper "Two Loops,
260
- * Three Roles":
261
- *
262
- * inspectFailures — given the observed runs, what failure modes
263
- * are present? (data → diagnosis)
264
- * proposeChange — given diagnosed failure modes, what
265
- * structural changes should we try?
266
- * (diagnosis → plan delta)
267
- * applyChange — fold the proposed deltas into a concrete
268
- * experiment plan against an existing baseline.
269
- * (plan delta → executable plan)
270
- * evaluateChange — run the plan, return runs + the gate verdict.
271
- * (executable plan → verdict)
272
- *
273
- * Composition is the discipline: a Researcher implementation MUST
274
- * keep these four steps separate and inspectable. Conflating
275
- * "diagnose + propose + run" into a single LLM call defeats the
276
- * point of the framework — you can't audit which step lied.
277
- *
278
- * THIS INTERFACE IS STABLE. Breaking changes require a new module
279
- * (e.g. `Researcher2`) so existing implementations keep working.
280
- */
281
-
282
- /** A diagnosed failure mode with the run-IDs that exhibit it. */
283
- interface FailureMode {
284
- /** Short machine-readable code. Must be stable across runs of the
285
- * same researcher to enable longitudinal tracking. */
286
- code: string;
287
- /** Human-readable description for the paper / dashboard. */
288
- description: string;
289
- evidence: {
290
- /** Run IDs (from `RunRecord.runId`) where this failure mode was
291
- * observed. */
292
- runIds: string[];
293
- /** Number of run samples that informed the diagnosis. */
294
- samples: number;
295
- };
296
- }
297
- /** A single steering change the researcher wants to try. */
298
- interface SteeringChange {
299
- kind: 'reviewer_prompt' | 'skill_add' | 'skill_remove' | 'threshold' | 'budget';
300
- /** Implementation-specific payload. Researcher implementations
301
- * define the schema — keep this `unknown` here to avoid coupling
302
- * the public interface to any one researcher's internal model. */
303
- payload: unknown;
304
- /** Why the researcher proposed this change. Goes into the audit
305
- * trail next to the failure-mode evidence. */
306
- rationale: string;
307
- /** Optional self-reported expected delta on the headline metric. */
308
- expectedDelta?: number;
309
- }
310
- /** A single experiment plan, mapped onto the search/holdout splits. */
311
- interface ExperimentPlan {
312
- baselineCandidateId: string;
313
- proposedCandidateId: string;
314
- changes: SteeringChange[];
315
- /** USD ceiling for the entire experiment. The runner must stop
316
- * before exceeding this and report a partial result. */
317
- evaluationBudgetUsd: number;
318
- /** Item IDs (your dataset keys) for the search vs holdout splits. */
319
- splits: {
320
- search: string[];
321
- holdout: string[];
322
- };
323
- }
324
- /** Result of running a plan: every run, plus the gate verdict. */
325
- interface ExperimentResult {
326
- plan: ExperimentPlan;
327
- runs: RunRecord[];
328
- gateDecision: GateDecision;
329
- }
330
- /**
331
- * The researcher loop. Stable, four-step, inspectable.
332
- *
333
- * ┌──────────┐ inspectFailures ┌──────────┐ proposeChange ┌──────────┐
334
- * │ runs │ ─────────────────▶│ failures │ ──────────────▶│ changes │
335
- * └──────────┘ └──────────┘ └────┬─────┘
336
- * │
337
- * ▼
338
- * ┌────────────────┐ applyChange ┌────────┐
339
- * │ ExperimentPlan │ ◀────────────│ base │
340
- * └────────┬───────┘ └────────┘
341
- * │
342
- * evaluateChange ▼
343
- * ┌────────────────┐
344
- * │ ExperimentResult│
345
- * └────────────────┘
346
- */
347
- interface Researcher {
348
- inspectFailures(runs: RunRecord[]): Promise<FailureMode[]>;
349
- proposeChange(failures: FailureMode[]): Promise<SteeringChange[]>;
350
- applyChange(changes: SteeringChange[], baseline: ExperimentPlan): Promise<ExperimentPlan>;
351
- evaluateChange(plan: ExperimentPlan): Promise<ExperimentResult>;
352
- }
353
- interface CallbackResearcherOptions {
354
- inspectFailures: Researcher['inspectFailures'];
355
- proposeChange: Researcher['proposeChange'];
356
- applyChange: Researcher['applyChange'];
357
- evaluateChange: Researcher['evaluateChange'];
358
- }
359
- /**
360
- * Minimal concrete researcher for tests, scripts, and small integrations.
361
- * Larger autonomous researchers can still implement `Researcher` directly.
362
- */
363
- declare class CallbackResearcher implements Researcher {
364
- private readonly callbacks;
365
- constructor(callbacks: CallbackResearcherOptions);
366
- inspectFailures(runs: RunRecord[]): Promise<FailureMode[]>;
367
- proposeChange(failures: FailureMode[]): Promise<SteeringChange[]>;
368
- applyChange(changes: SteeringChange[], baseline: ExperimentPlan): Promise<ExperimentPlan>;
369
- evaluateChange(plan: ExperimentPlan): Promise<ExperimentResult>;
370
- }
371
- /**
372
- * No-op researcher — fails loud on every method. Use as a placeholder
373
- * in code paths that wire the interface but don't have an implementation
374
- * yet. Importantly, this does NOT silently succeed: a no-op researcher
375
- * that returned empty arrays would muffle the loop's signal that
376
- * nobody implemented the brain.
377
- */
378
- declare class NoopResearcher implements Researcher {
379
- private readonly hint;
380
- constructor(hint?: string);
381
- inspectFailures(_runs: RunRecord[]): Promise<FailureMode[]>;
382
- proposeChange(_failures: FailureMode[]): Promise<SteeringChange[]>;
383
- applyChange(_changes: SteeringChange[], _baseline: ExperimentPlan): Promise<ExperimentPlan>;
384
- evaluateChange(_plan: ExperimentPlan): Promise<ExperimentResult>;
385
- }
386
-
387
- export { CallbackResearcher as C, type ExperimentPlan as E, type FailureMode as F, NoopResearcher as N, type Researcher as R, type SteeringChange as S, type ExperimentResult as a, type EvalCampaignResult as b, type EvalCampaignOptions as c, type CallbackResearcherOptions as d, type CampaignFactoryParams as e, type CampaignIntegrityPolicy as f, type CampaignRunContext as g, type CampaignRunOutcome as h, type CampaignRunner as i, type CampaignScenario as j, type CampaignVariant as k, type FailedRun as l, runEvalCampaign as r };
@@ -1,105 +0,0 @@
1
- import { R as RunRecord } from './run-record-BDH49H2E.js';
2
- import { b as OutcomeStore } from './outcome-store-rnXLEqSn.js';
3
-
4
- /**
5
- * Rubric predictive validity — does our eval rubric predict deployment
6
- * outcomes?
7
- *
8
- * `correlationStudy` (already in this package) joins a `TraceStore` to an
9
- * `OutcomeStore` and computes Pearson + Spearman + bootstrap CI for each
10
- * (eval-metric, outcome-metric) pair. That answers "does X correlate with
11
- * Y at all." `rubricPredictiveValidity` is the campaign-shaped wrapper
12
- * around it: take a sequence of `RunRecord`s (the canonical campaign
13
- * artifact) and a `DeploymentOutcomeStore`, join on `runId`, return a
14
- * ranked verdict on every rubric whose dimension scores were captured in
15
- * `outcome.raw`.
16
- *
17
- * The point — quoting the methodology doc — is that **without this loop
18
- * every rubric is faith-based**. Once it's wired, you know which rubrics
19
- * have earned their promotion power and which ones are decoration.
20
- *
21
- * const validity = await rubricPredictiveValidity({
22
- * runs: lastQuarter,
23
- * outcomes: shipFlagOutcomeStore,
24
- * outcomeMetrics: ['revenue_lift', 'retention_30d', 'csat'],
25
- * rubrics: ['anti_slop', 'semantic_concept', 'tool_recovery'],
26
- * })
27
- * for (const r of validity.ranked) {
28
- * console.log(`${r.rubric} → ${r.bestOutcome}: ρ=${r.spearman.toFixed(2)}`)
29
- * }
30
- *
31
- * The function is intentionally read-only. Use the verdict to deprecate
32
- * decorative rubrics, re-weight composite scores, or trigger a
33
- * recalibration sweep when predictive validity drops below a threshold.
34
- */
35
-
36
- interface RubricPredictiveValidityInput {
37
- /**
38
- * Canonical campaign output. Each record's `outcome.raw[<rubricId>]`
39
- * provides the eval score; missing keys are silently skipped per pair.
40
- */
41
- runs: RunRecord[];
42
- outcomes: OutcomeStore;
43
- /**
44
- * Outcome metric names to evaluate against. Each must appear in at
45
- * least one `DeploymentOutcome.metrics` keyspace; pairs with too few
46
- * joined samples are excluded from the result.
47
- */
48
- outcomeMetrics: string[];
49
- /**
50
- * Rubric ids to evaluate. Must appear as keys in `RunRecord.outcome.raw`.
51
- * If omitted, every numeric key in `outcome.raw` across the run set is
52
- * treated as a rubric.
53
- */
54
- rubrics?: string[];
55
- /** Minimum joined-sample count before a pair is reported. Default 8. */
56
- minSamples?: number;
57
- /** Bootstrap resamples for CI. Default 500. */
58
- bootstrapResamples?: number;
59
- /** Random seed for the bootstrap (mulberry32). Default unset (Math.random). */
60
- seed?: number;
61
- /**
62
- * Reduction when multiple outcomes attach to one runId. Default `'latest'`
63
- * (most recently captured).
64
- */
65
- reduction?: 'latest' | 'mean' | 'max';
66
- }
67
- interface RubricOutcomePair {
68
- rubric: string;
69
- outcome: string;
70
- n: number;
71
- pearson: number;
72
- spearman: number;
73
- ci95: {
74
- low: number;
75
- high: number;
76
- };
77
- /**
78
- * Verdict bucket. `load_bearing` ≥ 0.7, `informative` ≥ 0.4,
79
- * `decorative` < 0.4 in absolute correlation. A negative correlation
80
- * with a desired outcome is also `decorative` — actively misleading
81
- * is worse than uninformative.
82
- */
83
- verdict: 'load_bearing' | 'informative' | 'decorative';
84
- }
85
- interface RubricRanking {
86
- rubric: string;
87
- /** Outcome metric this rubric correlated best with. */
88
- bestOutcome: string;
89
- spearman: number;
90
- pearson: number;
91
- n: number;
92
- verdict: RubricOutcomePair['verdict'];
93
- }
94
- interface RubricPredictiveValidityReport {
95
- pairs: RubricOutcomePair[];
96
- /** Per-rubric best pair, sorted descending by |spearman|. */
97
- ranked: RubricRanking[];
98
- joinedSamples: number;
99
- skippedRuns: number;
100
- /** Rubrics that were declared but never produced a usable score. */
101
- rubricsWithoutData: string[];
102
- }
103
- declare function rubricPredictiveValidity(input: RubricPredictiveValidityInput): Promise<RubricPredictiveValidityReport>;
104
-
105
- export { type RubricOutcomePair as R, type RubricPredictiveValidityInput as a, type RubricPredictiveValidityReport as b, type RubricRanking as c, rubricPredictiveValidity as r };