@tangle-network/agent-eval 0.100.2 → 0.101.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 (43) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/adapters/http.d.ts +1 -1
  3. package/dist/adapters/langchain.d.ts +1 -1
  4. package/dist/adapters/otel.d.ts +1 -1
  5. package/dist/campaign/index.d.ts +58 -8
  6. package/dist/campaign/index.js +207 -34
  7. package/dist/campaign/index.js.map +1 -1
  8. package/dist/chunk-63MBSQTX.js +350 -0
  9. package/dist/chunk-63MBSQTX.js.map +1 -0
  10. package/dist/{chunk-G7IB3GJ5.js → chunk-CHIFZIQD.js} +3 -3
  11. package/dist/{chunk-VWQ6PO5O.js → chunk-GUII3E73.js} +54 -1
  12. package/dist/{chunk-VWQ6PO5O.js.map → chunk-GUII3E73.js.map} +1 -1
  13. package/dist/{chunk-2KTBHICD.js → chunk-NK77GPUH.js} +3 -3
  14. package/dist/chunk-NK77GPUH.js.map +1 -0
  15. package/dist/{chunk-QZYXA7ZO.js → chunk-X5OUZB4T.js} +2 -2
  16. package/dist/{chunk-HRGTA6U5.js → chunk-XIOQHCHU.js} +256 -32
  17. package/dist/chunk-XIOQHCHU.js.map +1 -0
  18. package/dist/contract/index.d.ts +6 -6
  19. package/dist/contract/index.js +7 -7
  20. package/dist/{gepa-BRgNnmGZ.d.ts → gepa-CEy1AIWp.d.ts} +36 -2
  21. package/dist/hosted/index.d.ts +1 -1
  22. package/dist/index.d.ts +57 -7
  23. package/dist/index.js +33 -132
  24. package/dist/index.js.map +1 -1
  25. package/dist/multishot/index.d.ts +1 -1
  26. package/dist/openapi.json +1 -1
  27. package/dist/{pre-registration-DB8oDqZJ.d.ts → pre-registration-BjGZf9YA.d.ts} +1 -1
  28. package/dist/product-benchmark/index.d.ts +144 -0
  29. package/dist/product-benchmark/index.js +23 -0
  30. package/dist/{provenance-B0SZw1z2.d.ts → provenance-DdfmVfqR.d.ts} +2 -2
  31. package/dist/rl.d.ts +1 -1
  32. package/dist/{run-campaign-OWCFOEQG.js → run-campaign-HG4WTSDH.js} +4 -2
  33. package/dist/run-campaign-HG4WTSDH.js.map +1 -0
  34. package/dist/{types-Cv1bo4_a.d.ts → types-fWqEJm7h.d.ts} +3 -0
  35. package/docs/concepts.md +1 -0
  36. package/docs/eval-fixtures.md +115 -0
  37. package/docs/feature-guide.md +4 -0
  38. package/package.json +6 -1
  39. package/dist/chunk-2KTBHICD.js.map +0 -1
  40. package/dist/chunk-HRGTA6U5.js.map +0 -1
  41. /package/dist/{chunk-G7IB3GJ5.js.map → chunk-CHIFZIQD.js.map} +0 -0
  42. /package/dist/{chunk-QZYXA7ZO.js.map → chunk-X5OUZB4T.js.map} +0 -0
  43. /package/dist/{run-campaign-OWCFOEQG.js.map → product-benchmark/index.js.map} +0 -0
@@ -0,0 +1,350 @@
1
+ import {
2
+ ValidationError
3
+ } from "./chunk-3BFEG2F6.js";
4
+
5
+ // src/product-benchmark/index.ts
6
+ import { existsSync, readFileSync, statSync } from "fs";
7
+ import { dirname, join } from "path";
8
+ var productBenchmarkSplits = ["practice", "dev", "holdout", "safety", "sentinel"];
9
+ function isObject(value) {
10
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
11
+ }
12
+ function fail(path, message) {
13
+ throw new ValidationError(`${path}: ${message}`);
14
+ }
15
+ function wrapValidationError(path, err) {
16
+ if (err instanceof ValidationError) {
17
+ throw new ValidationError(`${path}: ${err.message}`, { cause: err });
18
+ }
19
+ throw new ValidationError(`${path}: ${err instanceof Error ? err.message : String(err)}`, {
20
+ cause: err
21
+ });
22
+ }
23
+ function expectObject(value, path) {
24
+ if (!isObject(value)) fail(path, "must be an object");
25
+ return value;
26
+ }
27
+ function expectString(value, path) {
28
+ if (typeof value !== "string" || value.trim().length === 0)
29
+ fail(path, "must be a non-empty string");
30
+ return value;
31
+ }
32
+ function expectBoolean(value, path) {
33
+ if (typeof value !== "boolean") fail(path, "must be a boolean");
34
+ return value;
35
+ }
36
+ function expectNumber(value, path, opts = {}) {
37
+ if (typeof value !== "number" || !Number.isFinite(value)) fail(path, "must be a finite number");
38
+ if (opts.integer && !Number.isInteger(value)) fail(path, "must be an integer");
39
+ if (opts.min !== void 0 && value < opts.min) fail(path, `must be >= ${opts.min}`);
40
+ if (opts.max !== void 0 && value > opts.max) fail(path, `must be <= ${opts.max}`);
41
+ return value;
42
+ }
43
+ function expectStringArray(value, path) {
44
+ if (!Array.isArray(value)) fail(path, "must be an array");
45
+ return value.map((entry, index) => expectString(entry, `${path}[${index}]`));
46
+ }
47
+ function expectObjectArray(value, path) {
48
+ if (!Array.isArray(value)) fail(path, "must be an array");
49
+ return value.map((entry, index) => expectObject(entry, `${path}[${index}]`));
50
+ }
51
+ function expectSplit(value, path) {
52
+ const split = expectString(value, path);
53
+ if (!productBenchmarkSplits.includes(split)) {
54
+ fail(path, `must be one of ${productBenchmarkSplits.join(", ")}`);
55
+ }
56
+ return split;
57
+ }
58
+ function optionalString(value, path) {
59
+ if (value === void 0) return void 0;
60
+ return expectString(value, path);
61
+ }
62
+ function expectDimensions(value, path) {
63
+ const obj = expectObject(value, path);
64
+ const out = {};
65
+ for (const [key, raw] of Object.entries(obj)) out[key] = expectNumber(raw, `${path}.${key}`);
66
+ return out;
67
+ }
68
+ function expectRuntimeResolution(value, path) {
69
+ const obj = expectObject(value, path);
70
+ return {
71
+ model: expectString(obj.model, `${path}.model`),
72
+ harness: expectString(obj.harness, `${path}.harness`),
73
+ backend: expectString(obj.backend, `${path}.backend`),
74
+ ...obj.reasoningEffort !== void 0 ? { reasoningEffort: optionalString(obj.reasoningEffort, `${path}.reasoningEffort`) } : {}
75
+ };
76
+ }
77
+ function validateProductBenchmarkManifest(value) {
78
+ const obj = expectObject(value, "manifest");
79
+ if (obj.schemaVersion !== 1) fail("manifest.schemaVersion", "must be 1");
80
+ const repo = expectObject(obj.repo, "manifest.repo");
81
+ const substrate = expectObject(obj.substrate, "manifest.substrate");
82
+ const profiles = expectObjectArray(obj.profiles, "manifest.profiles").map((profile, index) => ({
83
+ id: expectString(profile.id, `manifest.profiles[${index}].id`),
84
+ profileHash: expectString(profile.profileHash, `manifest.profiles[${index}].profileHash`),
85
+ agentProfilePath: expectString(
86
+ profile.agentProfilePath,
87
+ `manifest.profiles[${index}].agentProfilePath`
88
+ )
89
+ }));
90
+ const arms = expectObjectArray(obj.arms, "manifest.arms").map((arm, index) => ({
91
+ id: expectString(arm.id, `manifest.arms[${index}].id`),
92
+ profileId: expectString(arm.profileId, `manifest.arms[${index}].profileId`),
93
+ mutableSurfaces: expectStringArray(
94
+ arm.mutableSurfaces,
95
+ `manifest.arms[${index}].mutableSurfaces`
96
+ ),
97
+ policyAxes: expectObject(arm.policyAxes, `manifest.arms[${index}].policyAxes`)
98
+ }));
99
+ const scenarios = expectObjectArray(obj.scenarios, "manifest.scenarios").map(
100
+ (scenario, index) => ({
101
+ id: expectString(scenario.id, `manifest.scenarios[${index}].id`),
102
+ split: expectSplit(scenario.split, `manifest.scenarios[${index}].split`),
103
+ tags: expectStringArray(scenario.tags, `manifest.scenarios[${index}].tags`),
104
+ sourceAllowedForSynthesis: expectBoolean(
105
+ scenario.sourceAllowedForSynthesis,
106
+ `manifest.scenarios[${index}].sourceAllowedForSynthesis`
107
+ )
108
+ })
109
+ );
110
+ const budgets = expectObject(obj.budgets, "manifest.budgets");
111
+ if (profiles.length === 0) fail("manifest.profiles", "must contain at least one profile");
112
+ if (arms.length === 0) fail("manifest.arms", "must contain at least one arm");
113
+ if (scenarios.length === 0) fail("manifest.scenarios", "must contain at least one scenario");
114
+ assertUnique(
115
+ profiles.map((profile) => profile.id),
116
+ "manifest.profiles.id"
117
+ );
118
+ assertUnique(
119
+ arms.map((arm) => arm.id),
120
+ "manifest.arms.id"
121
+ );
122
+ assertUnique(
123
+ scenarios.map((scenario) => scenario.id),
124
+ "manifest.scenarios.id"
125
+ );
126
+ const profileIds = new Set(profiles.map((profile) => profile.id));
127
+ for (const arm of arms) {
128
+ if (!profileIds.has(arm.profileId))
129
+ fail(`manifest.arms.${arm.id}.profileId`, `unknown profile ${arm.profileId}`);
130
+ }
131
+ return {
132
+ schemaVersion: 1,
133
+ projectId: expectString(obj.projectId, "manifest.projectId"),
134
+ benchmarkId: expectString(obj.benchmarkId, "manifest.benchmarkId"),
135
+ repo: {
136
+ url: expectString(repo.url, "manifest.repo.url"),
137
+ commit: expectString(repo.commit, "manifest.repo.commit"),
138
+ branch: expectString(repo.branch, "manifest.repo.branch")
139
+ },
140
+ substrate: {
141
+ agentEval: expectString(substrate.agentEval, "manifest.substrate.agentEval"),
142
+ agentRuntime: expectString(substrate.agentRuntime, "manifest.substrate.agentRuntime"),
143
+ agentInterface: expectString(substrate.agentInterface, "manifest.substrate.agentInterface"),
144
+ sandbox: expectString(substrate.sandbox, "manifest.substrate.sandbox"),
145
+ ...substrate.agentBench !== void 0 ? { agentBench: expectString(substrate.agentBench, "manifest.substrate.agentBench") } : {}
146
+ },
147
+ profiles,
148
+ arms,
149
+ scenarios,
150
+ budgets: {
151
+ maxUsd: expectNumber(budgets.maxUsd, "manifest.budgets.maxUsd", { min: 0 }),
152
+ maxCells: expectNumber(budgets.maxCells, "manifest.budgets.maxCells", {
153
+ min: 0,
154
+ integer: true
155
+ }),
156
+ maxWallMs: expectNumber(budgets.maxWallMs, "manifest.budgets.maxWallMs", {
157
+ min: 0,
158
+ integer: true
159
+ })
160
+ },
161
+ expectedArtifactDir: expectString(obj.expectedArtifactDir, "manifest.expectedArtifactDir")
162
+ };
163
+ }
164
+ function validateProductBenchmarkRecord(value) {
165
+ const obj = expectObject(value, "record");
166
+ if (obj.schemaVersion !== 1) fail("record.schemaVersion", "must be 1");
167
+ const agentProfile = expectObject(obj.agentProfile, "record.agentProfile");
168
+ const model = expectObject(obj.model, "record.model");
169
+ const backend = expectObject(obj.backend, "record.backend");
170
+ const outcome = expectObject(obj.outcome, "record.outcome");
171
+ const usage = expectObject(obj.usage, "record.usage");
172
+ const integrity = expectObject(obj.integrity, "record.integrity");
173
+ const artifacts = expectObject(obj.artifacts, "record.artifacts");
174
+ const record = {
175
+ schemaVersion: 1,
176
+ projectId: expectString(obj.projectId, "record.projectId"),
177
+ benchmarkId: expectString(obj.benchmarkId, "record.benchmarkId"),
178
+ runId: expectString(obj.runId, "record.runId"),
179
+ scenarioId: expectString(obj.scenarioId, "record.scenarioId"),
180
+ split: expectSplit(obj.split, "record.split"),
181
+ armId: expectString(obj.armId, "record.armId"),
182
+ rep: expectNumber(obj.rep, "record.rep", { min: 1, integer: true }),
183
+ agentProfile: {
184
+ id: expectString(agentProfile.id, "record.agentProfile.id"),
185
+ hash: expectString(agentProfile.hash, "record.agentProfile.hash"),
186
+ path: expectString(agentProfile.path, "record.agentProfile.path"),
187
+ declared: expectRuntimeResolution(agentProfile.declared, "record.agentProfile.declared"),
188
+ resolved: expectRuntimeResolution(agentProfile.resolved, "record.agentProfile.resolved")
189
+ },
190
+ model: {
191
+ provider: expectString(model.provider, "record.model.provider"),
192
+ id: expectString(model.id, "record.model.id")
193
+ },
194
+ backend: {
195
+ kind: expectString(backend.kind, "record.backend.kind"),
196
+ version: expectString(backend.version, "record.backend.version")
197
+ },
198
+ outcome: {
199
+ pass: expectBoolean(outcome.pass, "record.outcome.pass"),
200
+ score: expectNumber(outcome.score, "record.outcome.score", { min: 0, max: 1 }),
201
+ dimensions: expectDimensions(outcome.dimensions, "record.outcome.dimensions"),
202
+ failureMode: outcome.failureMode === null ? null : expectString(outcome.failureMode, "record.outcome.failureMode")
203
+ },
204
+ usage: {
205
+ inputTokens: expectNumber(usage.inputTokens, "record.usage.inputTokens", {
206
+ min: 0,
207
+ integer: true
208
+ }),
209
+ outputTokens: expectNumber(usage.outputTokens, "record.usage.outputTokens", {
210
+ min: 0,
211
+ integer: true
212
+ }),
213
+ costUsd: expectNumber(usage.costUsd, "record.usage.costUsd", { min: 0 }),
214
+ wallMs: expectNumber(usage.wallMs, "record.usage.wallMs", { min: 0, integer: true }),
215
+ toolCalls: expectNumber(usage.toolCalls, "record.usage.toolCalls", { min: 0, integer: true })
216
+ },
217
+ integrity: {
218
+ realBackend: expectBoolean(integrity.realBackend, "record.integrity.realBackend"),
219
+ rawCapture: expectBoolean(integrity.rawCapture, "record.integrity.rawCapture"),
220
+ traceCapture: expectBoolean(integrity.traceCapture, "record.integrity.traceCapture"),
221
+ noStubRows: expectBoolean(integrity.noStubRows, "record.integrity.noStubRows"),
222
+ priced: expectBoolean(integrity.priced, "record.integrity.priced"),
223
+ profileMaterialized: expectBoolean(
224
+ integrity.profileMaterialized,
225
+ "record.integrity.profileMaterialized"
226
+ )
227
+ },
228
+ artifacts: {
229
+ records: expectString(artifacts.records, "record.artifacts.records"),
230
+ traces: expectString(artifacts.traces, "record.artifacts.traces"),
231
+ raws: expectString(artifacts.raws, "record.artifacts.raws"),
232
+ scores: expectString(artifacts.scores, "record.artifacts.scores"),
233
+ workspace: expectString(artifacts.workspace, "record.artifacts.workspace")
234
+ }
235
+ };
236
+ if (record.integrity.realBackend && record.usage.inputTokens + record.usage.outputTokens === 0) {
237
+ fail("record.usage", "realBackend rows must carry non-zero token usage");
238
+ }
239
+ return record;
240
+ }
241
+ function productBenchmarkIntegrityFailures(record) {
242
+ const failures = [];
243
+ for (const [key, value] of Object.entries(record.integrity)) {
244
+ if (!value) failures.push(`${record.runId}:${key}=false`);
245
+ }
246
+ return failures;
247
+ }
248
+ function readProductBenchmarkRecords(path) {
249
+ const lines = readFileSync(path, "utf8").split("\n").map((line) => line.trim()).filter(Boolean);
250
+ const records = [];
251
+ for (const [index, line] of lines.entries()) {
252
+ try {
253
+ records.push(validateProductBenchmarkRecord(JSON.parse(line)));
254
+ } catch (err) {
255
+ wrapValidationError(`${path}:${index + 1}`, err);
256
+ }
257
+ }
258
+ return records;
259
+ }
260
+ function readProductBenchmarkManifest(path) {
261
+ try {
262
+ return validateProductBenchmarkManifest(JSON.parse(readFileSync(path, "utf8")));
263
+ } catch (err) {
264
+ wrapValidationError(path, err);
265
+ }
266
+ }
267
+ function validateProductBenchmarkRun(input) {
268
+ const manifest = readProductBenchmarkManifest(input.manifestPath);
269
+ const records = readProductBenchmarkRecords(input.recordsPath);
270
+ const manifestProjectBench = `${manifest.projectId}/${manifest.benchmarkId}`;
271
+ const integrityFailures = records.flatMap(productBenchmarkIntegrityFailures);
272
+ const missingArtifacts = input.checkArtifacts === false ? [] : records.flatMap(
273
+ (record) => missingArtifactsForRecord(record, input.artifactRoot ?? dirname(input.recordsPath))
274
+ );
275
+ for (const [index, record] of records.entries()) {
276
+ const recordProjectBench = `${record.projectId}/${record.benchmarkId}`;
277
+ if (recordProjectBench !== manifestProjectBench) {
278
+ fail(
279
+ `records[${index}]`,
280
+ `project/benchmark ${recordProjectBench} does not match manifest ${manifestProjectBench}`
281
+ );
282
+ }
283
+ if (!manifest.arms.some((arm) => arm.id === record.armId))
284
+ fail(`records[${index}].armId`, `unknown arm ${record.armId}`);
285
+ if (!manifest.scenarios.some((scenario) => scenario.id === record.scenarioId)) {
286
+ fail(`records[${index}].scenarioId`, `unknown scenario ${record.scenarioId}`);
287
+ }
288
+ }
289
+ return {
290
+ manifestPath: input.manifestPath,
291
+ recordsPath: input.recordsPath,
292
+ records: records.length,
293
+ projects: sortedUnique(records.map((record) => record.projectId)),
294
+ benchmarks: sortedUnique(records.map((record) => record.benchmarkId)),
295
+ arms: sortedUnique(records.map((record) => record.armId)),
296
+ scenarios: sortedUnique(records.map((record) => record.scenarioId)),
297
+ passed: records.filter((record) => record.outcome.pass).length,
298
+ failed: records.filter((record) => !record.outcome.pass).length,
299
+ inputTokens: sum(records, (record) => record.usage.inputTokens),
300
+ outputTokens: sum(records, (record) => record.usage.outputTokens),
301
+ costUsd: sum(records, (record) => record.usage.costUsd),
302
+ wallMs: sum(records, (record) => record.usage.wallMs),
303
+ integrityFailures,
304
+ missingArtifacts
305
+ };
306
+ }
307
+ function missingArtifactsForRecord(record, artifactRoot) {
308
+ const missing = [];
309
+ for (const [key, value] of Object.entries(record.artifacts)) {
310
+ const path = resolveArtifactPath(value, artifactRoot);
311
+ if (!existsSync(path)) missing.push(`${record.runId}:${key}:${value}`);
312
+ }
313
+ return missing;
314
+ }
315
+ function resolveArtifactPath(value, artifactRoot) {
316
+ return value.startsWith("/") ? value : join(artifactRoot, value);
317
+ }
318
+ function assertUnique(values, path) {
319
+ const seen = /* @__PURE__ */ new Set();
320
+ for (const value of values) {
321
+ if (seen.has(value)) fail(path, `duplicate ${value}`);
322
+ seen.add(value);
323
+ }
324
+ }
325
+ function sortedUnique(values) {
326
+ return [...new Set(values)].sort();
327
+ }
328
+ function sum(items, fn) {
329
+ return items.reduce((total, item) => total + fn(item), 0);
330
+ }
331
+ function findProductBenchmarkArtifacts(runDir) {
332
+ const manifestPath = join(runDir, "product-benchmark-manifest.json");
333
+ const recordsPath = join(runDir, "product-benchmark-records.jsonl");
334
+ if (existsSync(manifestPath) && statSync(manifestPath).isFile() && existsSync(recordsPath) && statSync(recordsPath).isFile()) {
335
+ return { manifestPath, recordsPath };
336
+ }
337
+ return null;
338
+ }
339
+
340
+ export {
341
+ productBenchmarkSplits,
342
+ validateProductBenchmarkManifest,
343
+ validateProductBenchmarkRecord,
344
+ productBenchmarkIntegrityFailures,
345
+ readProductBenchmarkRecords,
346
+ readProductBenchmarkManifest,
347
+ validateProductBenchmarkRun,
348
+ findProductBenchmarkArtifacts
349
+ };
350
+ //# sourceMappingURL=chunk-63MBSQTX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/product-benchmark/index.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { ValidationError } from '../errors'\n\nexport const productBenchmarkSplits = ['practice', 'dev', 'holdout', 'safety', 'sentinel'] as const\n\nexport type ProductBenchmarkSplit = (typeof productBenchmarkSplits)[number]\n\nexport interface ProductBenchmarkRepoRef {\n readonly url: string\n readonly commit: string\n readonly branch: string\n}\n\nexport interface ProductBenchmarkSubstrateVersions {\n readonly agentEval: string\n readonly agentRuntime: string\n readonly agentInterface: string\n readonly sandbox: string\n readonly agentBench?: string\n}\n\nexport interface ProductBenchmarkProfileRef {\n readonly id: string\n readonly profileHash: string\n readonly agentProfilePath: string\n}\n\nexport interface ProductBenchmarkArm {\n readonly id: string\n readonly profileId: string\n readonly mutableSurfaces: readonly string[]\n readonly policyAxes: Record<string, unknown>\n}\n\nexport interface ProductBenchmarkScenario {\n readonly id: string\n readonly split: ProductBenchmarkSplit\n readonly tags: readonly string[]\n readonly sourceAllowedForSynthesis: boolean\n}\n\nexport interface ProductBenchmarkBudgets {\n readonly maxUsd: number\n readonly maxCells: number\n readonly maxWallMs: number\n}\n\nexport interface ProductBenchmarkManifest {\n readonly schemaVersion: 1\n readonly projectId: string\n readonly benchmarkId: string\n readonly repo: ProductBenchmarkRepoRef\n readonly substrate: ProductBenchmarkSubstrateVersions\n readonly profiles: readonly ProductBenchmarkProfileRef[]\n readonly arms: readonly ProductBenchmarkArm[]\n readonly scenarios: readonly ProductBenchmarkScenario[]\n readonly budgets: ProductBenchmarkBudgets\n readonly expectedArtifactDir: string\n}\n\nexport interface AgentProfileRuntimeReceipt {\n readonly model: string\n readonly harness: string\n readonly backend: string\n readonly reasoningEffort?: string\n}\n\nexport type RuntimeResolution = AgentProfileRuntimeReceipt\n\nexport interface ProductBenchmarkRecord {\n readonly schemaVersion: 1\n readonly projectId: string\n readonly benchmarkId: string\n readonly runId: string\n readonly scenarioId: string\n readonly split: ProductBenchmarkSplit\n readonly armId: string\n readonly rep: number\n readonly agentProfile: {\n readonly id: string\n readonly hash: string\n readonly path: string\n readonly declared: RuntimeResolution\n readonly resolved: RuntimeResolution\n }\n readonly model: {\n readonly provider: string\n readonly id: string\n }\n readonly backend: {\n readonly kind: string\n readonly version: string\n }\n readonly outcome: {\n readonly pass: boolean\n readonly score: number\n readonly dimensions: Record<string, number>\n readonly failureMode: string | null\n }\n readonly usage: {\n readonly inputTokens: number\n readonly outputTokens: number\n readonly costUsd: number\n readonly wallMs: number\n readonly toolCalls: number\n }\n readonly integrity: {\n readonly realBackend: boolean\n readonly rawCapture: boolean\n readonly traceCapture: boolean\n readonly noStubRows: boolean\n readonly priced: boolean\n readonly profileMaterialized: boolean\n }\n readonly artifacts: {\n readonly records: string\n readonly traces: string\n readonly raws: string\n readonly scores: string\n readonly workspace: string\n }\n}\n\nexport interface ProductBenchmarkRunInput {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly artifactRoot?: string\n readonly checkArtifacts?: boolean\n}\n\nexport interface ProductBenchmarkValidationReport {\n readonly manifestPath: string\n readonly recordsPath: string\n readonly records: number\n readonly projects: readonly string[]\n readonly benchmarks: readonly string[]\n readonly arms: readonly string[]\n readonly scenarios: readonly string[]\n readonly passed: number\n readonly failed: number\n readonly inputTokens: number\n readonly outputTokens: number\n readonly costUsd: number\n readonly wallMs: number\n readonly integrityFailures: readonly string[]\n readonly missingArtifacts: readonly string[]\n}\n\nexport interface ProductBenchmarkArtifactPaths {\n readonly manifestPath: string\n readonly recordsPath: string\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction fail(path: string, message: string): never {\n throw new ValidationError(`${path}: ${message}`)\n}\n\nfunction wrapValidationError(path: string, err: unknown): never {\n if (err instanceof ValidationError) {\n throw new ValidationError(`${path}: ${err.message}`, { cause: err })\n }\n throw new ValidationError(`${path}: ${err instanceof Error ? err.message : String(err)}`, {\n cause: err,\n })\n}\n\nfunction expectObject(value: unknown, path: string): Record<string, unknown> {\n if (!isObject(value)) fail(path, 'must be an object')\n return value\n}\n\nfunction expectString(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.trim().length === 0)\n fail(path, 'must be a non-empty string')\n return value\n}\n\nfunction expectBoolean(value: unknown, path: string): boolean {\n if (typeof value !== 'boolean') fail(path, 'must be a boolean')\n return value\n}\n\nfunction expectNumber(\n value: unknown,\n path: string,\n opts: { readonly min?: number; readonly max?: number; readonly integer?: boolean } = {},\n): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) fail(path, 'must be a finite number')\n if (opts.integer && !Number.isInteger(value)) fail(path, 'must be an integer')\n if (opts.min !== undefined && value < opts.min) fail(path, `must be >= ${opts.min}`)\n if (opts.max !== undefined && value > opts.max) fail(path, `must be <= ${opts.max}`)\n return value\n}\n\nfunction expectStringArray(value: unknown, path: string): string[] {\n if (!Array.isArray(value)) fail(path, 'must be an array')\n return value.map((entry, index) => expectString(entry, `${path}[${index}]`))\n}\n\nfunction expectObjectArray(value: unknown, path: string): Record<string, unknown>[] {\n if (!Array.isArray(value)) fail(path, 'must be an array')\n return value.map((entry, index) => expectObject(entry, `${path}[${index}]`))\n}\n\nfunction expectSplit(value: unknown, path: string): ProductBenchmarkSplit {\n const split = expectString(value, path)\n if (!productBenchmarkSplits.includes(split as ProductBenchmarkSplit)) {\n fail(path, `must be one of ${productBenchmarkSplits.join(', ')}`)\n }\n return split as ProductBenchmarkSplit\n}\n\nfunction optionalString(value: unknown, path: string): string | undefined {\n if (value === undefined) return undefined\n return expectString(value, path)\n}\n\nfunction expectDimensions(value: unknown, path: string): Record<string, number> {\n const obj = expectObject(value, path)\n const out: Record<string, number> = {}\n for (const [key, raw] of Object.entries(obj)) out[key] = expectNumber(raw, `${path}.${key}`)\n return out\n}\n\nfunction expectRuntimeResolution(value: unknown, path: string): RuntimeResolution {\n const obj = expectObject(value, path)\n return {\n model: expectString(obj.model, `${path}.model`),\n harness: expectString(obj.harness, `${path}.harness`),\n backend: expectString(obj.backend, `${path}.backend`),\n ...(obj.reasoningEffort !== undefined\n ? { reasoningEffort: optionalString(obj.reasoningEffort, `${path}.reasoningEffort`) }\n : {}),\n }\n}\n\nexport function validateProductBenchmarkManifest(value: unknown): ProductBenchmarkManifest {\n const obj = expectObject(value, 'manifest')\n if (obj.schemaVersion !== 1) fail('manifest.schemaVersion', 'must be 1')\n const repo = expectObject(obj.repo, 'manifest.repo')\n const substrate = expectObject(obj.substrate, 'manifest.substrate')\n const profiles = expectObjectArray(obj.profiles, 'manifest.profiles').map((profile, index) => ({\n id: expectString(profile.id, `manifest.profiles[${index}].id`),\n profileHash: expectString(profile.profileHash, `manifest.profiles[${index}].profileHash`),\n agentProfilePath: expectString(\n profile.agentProfilePath,\n `manifest.profiles[${index}].agentProfilePath`,\n ),\n }))\n const arms = expectObjectArray(obj.arms, 'manifest.arms').map((arm, index) => ({\n id: expectString(arm.id, `manifest.arms[${index}].id`),\n profileId: expectString(arm.profileId, `manifest.arms[${index}].profileId`),\n mutableSurfaces: expectStringArray(\n arm.mutableSurfaces,\n `manifest.arms[${index}].mutableSurfaces`,\n ),\n policyAxes: expectObject(arm.policyAxes, `manifest.arms[${index}].policyAxes`),\n }))\n const scenarios = expectObjectArray(obj.scenarios, 'manifest.scenarios').map(\n (scenario, index) => ({\n id: expectString(scenario.id, `manifest.scenarios[${index}].id`),\n split: expectSplit(scenario.split, `manifest.scenarios[${index}].split`),\n tags: expectStringArray(scenario.tags, `manifest.scenarios[${index}].tags`),\n sourceAllowedForSynthesis: expectBoolean(\n scenario.sourceAllowedForSynthesis,\n `manifest.scenarios[${index}].sourceAllowedForSynthesis`,\n ),\n }),\n )\n const budgets = expectObject(obj.budgets, 'manifest.budgets')\n if (profiles.length === 0) fail('manifest.profiles', 'must contain at least one profile')\n if (arms.length === 0) fail('manifest.arms', 'must contain at least one arm')\n if (scenarios.length === 0) fail('manifest.scenarios', 'must contain at least one scenario')\n assertUnique(\n profiles.map((profile) => profile.id),\n 'manifest.profiles.id',\n )\n assertUnique(\n arms.map((arm) => arm.id),\n 'manifest.arms.id',\n )\n assertUnique(\n scenarios.map((scenario) => scenario.id),\n 'manifest.scenarios.id',\n )\n const profileIds = new Set(profiles.map((profile) => profile.id))\n for (const arm of arms) {\n if (!profileIds.has(arm.profileId))\n fail(`manifest.arms.${arm.id}.profileId`, `unknown profile ${arm.profileId}`)\n }\n return {\n schemaVersion: 1,\n projectId: expectString(obj.projectId, 'manifest.projectId'),\n benchmarkId: expectString(obj.benchmarkId, 'manifest.benchmarkId'),\n repo: {\n url: expectString(repo.url, 'manifest.repo.url'),\n commit: expectString(repo.commit, 'manifest.repo.commit'),\n branch: expectString(repo.branch, 'manifest.repo.branch'),\n },\n substrate: {\n agentEval: expectString(substrate.agentEval, 'manifest.substrate.agentEval'),\n agentRuntime: expectString(substrate.agentRuntime, 'manifest.substrate.agentRuntime'),\n agentInterface: expectString(substrate.agentInterface, 'manifest.substrate.agentInterface'),\n sandbox: expectString(substrate.sandbox, 'manifest.substrate.sandbox'),\n ...(substrate.agentBench !== undefined\n ? { agentBench: expectString(substrate.agentBench, 'manifest.substrate.agentBench') }\n : {}),\n },\n profiles,\n arms,\n scenarios,\n budgets: {\n maxUsd: expectNumber(budgets.maxUsd, 'manifest.budgets.maxUsd', { min: 0 }),\n maxCells: expectNumber(budgets.maxCells, 'manifest.budgets.maxCells', {\n min: 0,\n integer: true,\n }),\n maxWallMs: expectNumber(budgets.maxWallMs, 'manifest.budgets.maxWallMs', {\n min: 0,\n integer: true,\n }),\n },\n expectedArtifactDir: expectString(obj.expectedArtifactDir, 'manifest.expectedArtifactDir'),\n }\n}\n\nexport function validateProductBenchmarkRecord(value: unknown): ProductBenchmarkRecord {\n const obj = expectObject(value, 'record')\n if (obj.schemaVersion !== 1) fail('record.schemaVersion', 'must be 1')\n const agentProfile = expectObject(obj.agentProfile, 'record.agentProfile')\n const model = expectObject(obj.model, 'record.model')\n const backend = expectObject(obj.backend, 'record.backend')\n const outcome = expectObject(obj.outcome, 'record.outcome')\n const usage = expectObject(obj.usage, 'record.usage')\n const integrity = expectObject(obj.integrity, 'record.integrity')\n const artifacts = expectObject(obj.artifacts, 'record.artifacts')\n const record: ProductBenchmarkRecord = {\n schemaVersion: 1,\n projectId: expectString(obj.projectId, 'record.projectId'),\n benchmarkId: expectString(obj.benchmarkId, 'record.benchmarkId'),\n runId: expectString(obj.runId, 'record.runId'),\n scenarioId: expectString(obj.scenarioId, 'record.scenarioId'),\n split: expectSplit(obj.split, 'record.split'),\n armId: expectString(obj.armId, 'record.armId'),\n rep: expectNumber(obj.rep, 'record.rep', { min: 1, integer: true }),\n agentProfile: {\n id: expectString(agentProfile.id, 'record.agentProfile.id'),\n hash: expectString(agentProfile.hash, 'record.agentProfile.hash'),\n path: expectString(agentProfile.path, 'record.agentProfile.path'),\n declared: expectRuntimeResolution(agentProfile.declared, 'record.agentProfile.declared'),\n resolved: expectRuntimeResolution(agentProfile.resolved, 'record.agentProfile.resolved'),\n },\n model: {\n provider: expectString(model.provider, 'record.model.provider'),\n id: expectString(model.id, 'record.model.id'),\n },\n backend: {\n kind: expectString(backend.kind, 'record.backend.kind'),\n version: expectString(backend.version, 'record.backend.version'),\n },\n outcome: {\n pass: expectBoolean(outcome.pass, 'record.outcome.pass'),\n score: expectNumber(outcome.score, 'record.outcome.score', { min: 0, max: 1 }),\n dimensions: expectDimensions(outcome.dimensions, 'record.outcome.dimensions'),\n failureMode:\n outcome.failureMode === null\n ? null\n : expectString(outcome.failureMode, 'record.outcome.failureMode'),\n },\n usage: {\n inputTokens: expectNumber(usage.inputTokens, 'record.usage.inputTokens', {\n min: 0,\n integer: true,\n }),\n outputTokens: expectNumber(usage.outputTokens, 'record.usage.outputTokens', {\n min: 0,\n integer: true,\n }),\n costUsd: expectNumber(usage.costUsd, 'record.usage.costUsd', { min: 0 }),\n wallMs: expectNumber(usage.wallMs, 'record.usage.wallMs', { min: 0, integer: true }),\n toolCalls: expectNumber(usage.toolCalls, 'record.usage.toolCalls', { min: 0, integer: true }),\n },\n integrity: {\n realBackend: expectBoolean(integrity.realBackend, 'record.integrity.realBackend'),\n rawCapture: expectBoolean(integrity.rawCapture, 'record.integrity.rawCapture'),\n traceCapture: expectBoolean(integrity.traceCapture, 'record.integrity.traceCapture'),\n noStubRows: expectBoolean(integrity.noStubRows, 'record.integrity.noStubRows'),\n priced: expectBoolean(integrity.priced, 'record.integrity.priced'),\n profileMaterialized: expectBoolean(\n integrity.profileMaterialized,\n 'record.integrity.profileMaterialized',\n ),\n },\n artifacts: {\n records: expectString(artifacts.records, 'record.artifacts.records'),\n traces: expectString(artifacts.traces, 'record.artifacts.traces'),\n raws: expectString(artifacts.raws, 'record.artifacts.raws'),\n scores: expectString(artifacts.scores, 'record.artifacts.scores'),\n workspace: expectString(artifacts.workspace, 'record.artifacts.workspace'),\n },\n }\n if (record.integrity.realBackend && record.usage.inputTokens + record.usage.outputTokens === 0) {\n fail('record.usage', 'realBackend rows must carry non-zero token usage')\n }\n return record\n}\n\nexport function productBenchmarkIntegrityFailures(record: ProductBenchmarkRecord): string[] {\n const failures: string[] = []\n for (const [key, value] of Object.entries(record.integrity)) {\n if (!value) failures.push(`${record.runId}:${key}=false`)\n }\n return failures\n}\n\nexport function readProductBenchmarkRecords(path: string): ProductBenchmarkRecord[] {\n const lines = readFileSync(path, 'utf8')\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n const records: ProductBenchmarkRecord[] = []\n for (const [index, line] of lines.entries()) {\n try {\n records.push(validateProductBenchmarkRecord(JSON.parse(line)))\n } catch (err) {\n wrapValidationError(`${path}:${index + 1}`, err)\n }\n }\n return records\n}\n\nexport function readProductBenchmarkManifest(path: string): ProductBenchmarkManifest {\n try {\n return validateProductBenchmarkManifest(JSON.parse(readFileSync(path, 'utf8')))\n } catch (err) {\n wrapValidationError(path, err)\n }\n}\n\nexport function validateProductBenchmarkRun(\n input: ProductBenchmarkRunInput,\n): ProductBenchmarkValidationReport {\n const manifest = readProductBenchmarkManifest(input.manifestPath)\n const records = readProductBenchmarkRecords(input.recordsPath)\n const manifestProjectBench = `${manifest.projectId}/${manifest.benchmarkId}`\n const integrityFailures = records.flatMap(productBenchmarkIntegrityFailures)\n const missingArtifacts =\n input.checkArtifacts === false\n ? []\n : records.flatMap((record) =>\n missingArtifactsForRecord(record, input.artifactRoot ?? dirname(input.recordsPath)),\n )\n for (const [index, record] of records.entries()) {\n const recordProjectBench = `${record.projectId}/${record.benchmarkId}`\n if (recordProjectBench !== manifestProjectBench) {\n fail(\n `records[${index}]`,\n `project/benchmark ${recordProjectBench} does not match manifest ${manifestProjectBench}`,\n )\n }\n if (!manifest.arms.some((arm) => arm.id === record.armId))\n fail(`records[${index}].armId`, `unknown arm ${record.armId}`)\n if (!manifest.scenarios.some((scenario) => scenario.id === record.scenarioId)) {\n fail(`records[${index}].scenarioId`, `unknown scenario ${record.scenarioId}`)\n }\n }\n return {\n manifestPath: input.manifestPath,\n recordsPath: input.recordsPath,\n records: records.length,\n projects: sortedUnique(records.map((record) => record.projectId)),\n benchmarks: sortedUnique(records.map((record) => record.benchmarkId)),\n arms: sortedUnique(records.map((record) => record.armId)),\n scenarios: sortedUnique(records.map((record) => record.scenarioId)),\n passed: records.filter((record) => record.outcome.pass).length,\n failed: records.filter((record) => !record.outcome.pass).length,\n inputTokens: sum(records, (record) => record.usage.inputTokens),\n outputTokens: sum(records, (record) => record.usage.outputTokens),\n costUsd: sum(records, (record) => record.usage.costUsd),\n wallMs: sum(records, (record) => record.usage.wallMs),\n integrityFailures,\n missingArtifacts,\n }\n}\n\nfunction missingArtifactsForRecord(record: ProductBenchmarkRecord, artifactRoot: string): string[] {\n const missing: string[] = []\n for (const [key, value] of Object.entries(record.artifacts)) {\n const path = resolveArtifactPath(value, artifactRoot)\n if (!existsSync(path)) missing.push(`${record.runId}:${key}:${value}`)\n }\n return missing\n}\n\nfunction resolveArtifactPath(value: string, artifactRoot: string): string {\n return value.startsWith('/') ? value : join(artifactRoot, value)\n}\n\nfunction assertUnique(values: readonly string[], path: string): void {\n const seen = new Set<string>()\n for (const value of values) {\n if (seen.has(value)) fail(path, `duplicate ${value}`)\n seen.add(value)\n }\n}\n\nfunction sortedUnique(values: readonly string[]): string[] {\n return [...new Set(values)].sort()\n}\n\nfunction sum<T>(items: readonly T[], fn: (item: T) => number): number {\n return items.reduce((total, item) => total + fn(item), 0)\n}\n\nexport function findProductBenchmarkArtifacts(\n runDir: string,\n): ProductBenchmarkArtifactPaths | null {\n const manifestPath = join(runDir, 'product-benchmark-manifest.json')\n const recordsPath = join(runDir, 'product-benchmark-records.jsonl')\n if (\n existsSync(manifestPath) &&\n statSync(manifestPath).isFile() &&\n existsSync(recordsPath) &&\n statSync(recordsPath).isFile()\n ) {\n return { manifestPath, recordsPath }\n }\n return null\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  runCanaries,
3
3
  scoreRedTeamOutput
4
- } from "./chunk-2KTBHICD.js";
4
+ } from "./chunk-NK77GPUH.js";
5
5
  import {
6
6
  runCampaign
7
- } from "./chunk-HRGTA6U5.js";
7
+ } from "./chunk-XIOQHCHU.js";
8
8
  import {
9
9
  detectRewardHacking
10
10
  } from "./chunk-AIGWQEME.js";
@@ -432,4 +432,4 @@ export {
432
432
  runEval,
433
433
  evolutionaryProposer
434
434
  };
435
- //# sourceMappingURL=chunk-G7IB3GJ5.js.map
435
+ //# sourceMappingURL=chunk-CHIFZIQD.js.map
@@ -656,6 +656,56 @@ function extractProducedState(events) {
656
656
 
657
657
  // src/agent-profile.ts
658
658
  import { createHash } from "crypto";
659
+ import { harnessSupportsModel } from "@tangle-network/agent-interface";
660
+ var CODING_HARNESSES = [
661
+ "opencode",
662
+ "claude-code",
663
+ "codex",
664
+ "kimi-code"
665
+ ];
666
+ function expandProfileAxes(spec) {
667
+ const harnesses = spec.harnesses ?? CODING_HARNESSES;
668
+ if (harnesses.length === 0) throw new ValidationError("expandProfileAxes: no harnesses to sweep");
669
+ const baseModel = spec.base.model?.default;
670
+ const models = spec.models ?? (baseModel ? [baseModel] : []);
671
+ if (models.length === 0) {
672
+ throw new ValidationError(
673
+ "expandProfileAxes: no models to sweep \u2014 base profile has no model.default and none were supplied"
674
+ );
675
+ }
676
+ const out = [];
677
+ const seen = /* @__PURE__ */ new Set();
678
+ for (const harness of harnesses) {
679
+ for (const model of models) {
680
+ if (!spec.keepIncompatible && !harnessSupportsModel(harness, model)) continue;
681
+ const profile = {
682
+ ...spec.base,
683
+ name: `${spec.base.name ?? "agent"}/${harness}/${model}`,
684
+ model: { ...spec.base.model, default: model },
685
+ metadata: { ...spec.base.metadata ?? {}, harness, harnessModel: model }
686
+ };
687
+ const id = agentProfileId(profile);
688
+ if (seen.has(id)) continue;
689
+ seen.add(id);
690
+ out.push(profile);
691
+ }
692
+ }
693
+ if (out.length === 0) {
694
+ throw new ValidationError(
695
+ `expandProfileAxes: every (harness, model) pair was incompatible (harnesses=[${harnesses.join(", ")}], models=[${models.join(", ")}]). Widen the models or pass keepIncompatible.`
696
+ );
697
+ }
698
+ return out;
699
+ }
700
+ function harnessAxisOf(profile) {
701
+ const m = profile.metadata;
702
+ const harness = m?.harness;
703
+ const model = m?.harnessModel;
704
+ if (typeof harness === "string" && typeof model === "string") {
705
+ return { harness, model };
706
+ }
707
+ return void 0;
708
+ }
659
709
  function agentProfileId(profile) {
660
710
  const label = pathSafeProfileLabel(agentProfileDisplayLabel(profile)) ?? "profile";
661
711
  return `${label}-${agentProfileHash(profile).slice(0, 16)}`;
@@ -711,8 +761,11 @@ export {
711
761
  createTokenRecallChecker,
712
762
  llmJudge,
713
763
  extractProducedState,
764
+ CODING_HARNESSES,
765
+ expandProfileAxes,
766
+ harnessAxisOf,
714
767
  agentProfileId,
715
768
  agentProfileModelId,
716
769
  agentProfileHash
717
770
  };
718
- //# sourceMappingURL=chunk-VWQ6PO5O.js.map
771
+ //# sourceMappingURL=chunk-GUII3E73.js.map