@tangle-network/agent-eval 0.65.0 → 0.66.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.
- package/CHANGELOG.md +12 -0
- package/dist/adapters/otel.d.ts +1 -1
- package/dist/campaign/index.d.ts +4 -3
- package/dist/campaign/index.js +18 -19
- package/dist/campaign/index.js.map +1 -1
- package/dist/{chunk-7TPYV2ER.js → chunk-6XQIEUQ2.js} +140 -7
- package/dist/chunk-6XQIEUQ2.js.map +1 -0
- package/dist/{chunk-HKINEDRZ.js → chunk-DFS3FEXO.js} +3 -2
- package/dist/chunk-DFS3FEXO.js.map +1 -0
- package/dist/{chunk-4ODZXQV2.js → chunk-Q56RRLEC.js} +635 -2
- package/dist/chunk-Q56RRLEC.js.map +1 -0
- package/dist/chunk-RDK3P4JE.js +482 -0
- package/dist/chunk-RDK3P4JE.js.map +1 -0
- package/dist/contract/index.d.ts +10 -8
- package/dist/contract/index.js +11 -12
- package/dist/contract/index.js.map +1 -1
- package/dist/hosted/index.d.ts +1 -1
- package/dist/hosted/index.js +1 -1
- package/dist/{index-CzhtwYBT.d.ts → index-DSEHMwvS.d.ts} +4 -2
- package/dist/index.d.ts +246 -3
- package/dist/index.js +292 -2
- package/dist/index.js.map +1 -1
- package/dist/openapi.json +1 -1
- package/dist/provenance-BZUFC1_D.d.ts +292 -0
- package/dist/{registry-DPly4_hZ.d.ts → registry-BzAEvqAt.d.ts} +1 -1
- package/dist/{run-campaign-5J3ED2UJ.js → run-campaign-BVY3RGAZ.js} +2 -3
- package/dist/{provenance-lqyLpOYR.d.ts → run-improvement-loop-BKpM5T4t.d.ts} +51 -329
- package/package.json +1 -1
- package/dist/chunk-4ODZXQV2.js.map +0 -1
- package/dist/chunk-7TPYV2ER.js.map +0 -1
- package/dist/chunk-CZRKD2X2.js +0 -1104
- package/dist/chunk-CZRKD2X2.js.map +0 -1
- package/dist/chunk-E22YUOAL.js +0 -111
- package/dist/chunk-E22YUOAL.js.map +0 -1
- package/dist/chunk-HKINEDRZ.js.map +0 -1
- /package/dist/{run-campaign-5J3ED2UJ.js.map → run-campaign-BVY3RGAZ.js.map} +0 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runCanaries,
|
|
3
|
+
scoreRedTeamOutput
|
|
4
|
+
} from "./chunk-Q56RRLEC.js";
|
|
5
|
+
import {
|
|
6
|
+
runCampaign,
|
|
7
|
+
summarizeBackendIntegrity
|
|
8
|
+
} from "./chunk-6XQIEUQ2.js";
|
|
9
|
+
import {
|
|
10
|
+
detectRewardHacking
|
|
11
|
+
} from "./chunk-YV7J7X5N.js";
|
|
12
|
+
|
|
13
|
+
// src/campaign/drivers/evolutionary.ts
|
|
14
|
+
function evolutionaryDriver(opts) {
|
|
15
|
+
return {
|
|
16
|
+
kind: `evolutionary:${opts.mutator.kind}`,
|
|
17
|
+
async propose({ currentSurface, findings, populationSize, signal }) {
|
|
18
|
+
return opts.mutator.mutate({
|
|
19
|
+
findings: findings.length > 0 ? findings : opts.findings ?? [],
|
|
20
|
+
currentSurface,
|
|
21
|
+
populationSize,
|
|
22
|
+
signal
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/campaign/gates/compose.ts
|
|
29
|
+
function composeGate(...gates) {
|
|
30
|
+
if (gates.length === 0) {
|
|
31
|
+
throw new Error("composeGate requires at least one gate");
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
name: `composed(${gates.map((g) => g.name).join(",")})`,
|
|
35
|
+
async decide(ctx) {
|
|
36
|
+
const results = [];
|
|
37
|
+
for (const gate of gates) {
|
|
38
|
+
const res = await gate.decide(ctx);
|
|
39
|
+
results.push({ gate, res });
|
|
40
|
+
}
|
|
41
|
+
const decisions = results.map((r) => r.res.decision);
|
|
42
|
+
const overall = decisions.every((d) => d === "ship") ? "ship" : decisions.includes("arch_ceiling") ? "arch_ceiling" : decisions.includes("model_ceiling") ? "model_ceiling" : decisions.includes("hold") ? "hold" : "need_more_work";
|
|
43
|
+
const contributing = results.flatMap(
|
|
44
|
+
(r) => r.res.contributingGates.length > 0 ? r.res.contributingGates : [{ name: r.gate.name, passed: r.res.decision === "ship", detail: r.res }]
|
|
45
|
+
);
|
|
46
|
+
const reasons = results.flatMap(
|
|
47
|
+
(r) => r.res.reasons.map((reason) => `[${r.gate.name}] ${reason}`)
|
|
48
|
+
);
|
|
49
|
+
return {
|
|
50
|
+
decision: overall,
|
|
51
|
+
reasons,
|
|
52
|
+
contributingGates: contributing,
|
|
53
|
+
delta: results[0]?.res.delta
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/campaign/gates/default-production-gate.ts
|
|
60
|
+
function defaultProductionGate(options) {
|
|
61
|
+
const deltaThreshold = options.deltaThreshold ?? 0.5;
|
|
62
|
+
const blockOnGaming = options.blockOnRewardHackingGaming ?? true;
|
|
63
|
+
return {
|
|
64
|
+
name: "defaultProductionGate",
|
|
65
|
+
async decide(ctx) {
|
|
66
|
+
const reasons = [];
|
|
67
|
+
const contributing = [];
|
|
68
|
+
const baselineComposite = meanComposite(
|
|
69
|
+
ctx.baselineArtifacts,
|
|
70
|
+
ctx.baselineJudgeScores ?? ctx.judgeScores,
|
|
71
|
+
options.holdoutScenarios
|
|
72
|
+
);
|
|
73
|
+
const candidateComposite = meanComposite(
|
|
74
|
+
ctx.candidateArtifacts,
|
|
75
|
+
ctx.judgeScores,
|
|
76
|
+
options.holdoutScenarios
|
|
77
|
+
);
|
|
78
|
+
const delta = candidateComposite - baselineComposite;
|
|
79
|
+
const heldoutPass = delta >= deltaThreshold;
|
|
80
|
+
contributing.push({
|
|
81
|
+
name: "heldout-delta",
|
|
82
|
+
passed: heldoutPass,
|
|
83
|
+
detail: { baselineComposite, candidateComposite, delta, deltaThreshold }
|
|
84
|
+
});
|
|
85
|
+
if (!heldoutPass) {
|
|
86
|
+
reasons.push(`heldout delta ${delta.toFixed(3)} < threshold ${deltaThreshold}`);
|
|
87
|
+
}
|
|
88
|
+
const budgetPass = options.budgetUsd === void 0 || ctx.cost.candidate + ctx.cost.baseline <= options.budgetUsd;
|
|
89
|
+
contributing.push({
|
|
90
|
+
name: "budget",
|
|
91
|
+
passed: budgetPass,
|
|
92
|
+
detail: {
|
|
93
|
+
candidateUsd: ctx.cost.candidate,
|
|
94
|
+
baselineUsd: ctx.cost.baseline,
|
|
95
|
+
budgetUsd: options.budgetUsd
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
if (!budgetPass) {
|
|
99
|
+
reasons.push(
|
|
100
|
+
`spend ${(ctx.cost.candidate + ctx.cost.baseline).toFixed(2)} > budget ${options.budgetUsd}`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const redTeamFindings = options.redTeamBattery ? probeRedTeam(ctx.candidateArtifacts, options.redTeamBattery) : { passed: true, findings: [] };
|
|
104
|
+
contributing.push({
|
|
105
|
+
name: "red-team",
|
|
106
|
+
passed: redTeamFindings.passed,
|
|
107
|
+
detail: {
|
|
108
|
+
failures: redTeamFindings.findings.length,
|
|
109
|
+
sample: redTeamFindings.findings.slice(0, 3)
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (!redTeamFindings.passed) {
|
|
113
|
+
reasons.push(`red-team probe failed (${redTeamFindings.findings.length} findings)`);
|
|
114
|
+
}
|
|
115
|
+
let rewardHackingReport = null;
|
|
116
|
+
if (options.recentRuns && options.recentRuns.length >= 10) {
|
|
117
|
+
rewardHackingReport = detectRewardHacking({ runs: options.recentRuns });
|
|
118
|
+
}
|
|
119
|
+
const gamingThreshold = 0.6;
|
|
120
|
+
const gamingFindings = (rewardHackingReport?.findings ?? []).filter(
|
|
121
|
+
(f) => f.severity >= gamingThreshold
|
|
122
|
+
);
|
|
123
|
+
const rewardHackingPass = !rewardHackingReport || !blockOnGaming || gamingFindings.length === 0 && rewardHackingReport.verdict !== "gaming";
|
|
124
|
+
contributing.push({
|
|
125
|
+
name: "reward-hacking",
|
|
126
|
+
passed: rewardHackingPass,
|
|
127
|
+
detail: { report: rewardHackingReport, gamingFindingCount: gamingFindings.length }
|
|
128
|
+
});
|
|
129
|
+
if (!rewardHackingPass) {
|
|
130
|
+
reasons.push(
|
|
131
|
+
`reward-hacking detector flagged ${gamingFindings.length} gaming-severity findings (verdict=${rewardHackingReport.verdict})`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
let canaryReport = null;
|
|
135
|
+
if (options.recentRuns && options.recentRuns.length >= 10) {
|
|
136
|
+
canaryReport = runCanaries(options.recentRuns, {});
|
|
137
|
+
}
|
|
138
|
+
const errorAlerts = (canaryReport?.alerts ?? []).filter((a) => a.severity === "error");
|
|
139
|
+
const canaryPass = errorAlerts.length === 0;
|
|
140
|
+
contributing.push({
|
|
141
|
+
name: "canary",
|
|
142
|
+
passed: canaryPass,
|
|
143
|
+
detail: { totalAlerts: canaryReport?.alerts.length ?? 0, errorAlerts: errorAlerts.length }
|
|
144
|
+
});
|
|
145
|
+
if (!canaryPass) {
|
|
146
|
+
reasons.push(`canary error alerts: ${errorAlerts.length}`);
|
|
147
|
+
}
|
|
148
|
+
const allPassed = contributing.every((c) => c.passed);
|
|
149
|
+
const decision = allPassed ? "ship" : "hold";
|
|
150
|
+
return {
|
|
151
|
+
decision,
|
|
152
|
+
reasons: reasons.length > 0 ? reasons : ["all gates passed"],
|
|
153
|
+
contributingGates: contributing,
|
|
154
|
+
delta
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function meanComposite(artifacts, judgeScoresByCell, scenarios) {
|
|
160
|
+
if (!artifacts || artifacts.size === 0) return 0;
|
|
161
|
+
const scenarioIds = new Set(scenarios.map((s) => s.id));
|
|
162
|
+
const composites = [];
|
|
163
|
+
for (const [cellId, scores] of judgeScoresByCell) {
|
|
164
|
+
const scenarioId = cellId.split(":")[0] ?? "";
|
|
165
|
+
if (!scenarioIds.has(scenarioId)) continue;
|
|
166
|
+
const cellComposites = Object.values(scores).map((s) => s.composite);
|
|
167
|
+
if (cellComposites.length === 0) continue;
|
|
168
|
+
composites.push(cellComposites.reduce((a, b) => a + b, 0) / cellComposites.length);
|
|
169
|
+
}
|
|
170
|
+
if (composites.length === 0) return 0;
|
|
171
|
+
return composites.reduce((a, b) => a + b, 0) / composites.length;
|
|
172
|
+
}
|
|
173
|
+
function probeRedTeam(artifacts, battery) {
|
|
174
|
+
const findings = [];
|
|
175
|
+
for (const [_cellId, artifact] of artifacts) {
|
|
176
|
+
const text = extractText(artifact);
|
|
177
|
+
if (text === void 0) continue;
|
|
178
|
+
for (const rtCase of battery) {
|
|
179
|
+
const finding = scoreRedTeamOutput(text, [], rtCase);
|
|
180
|
+
if (!finding.passed) {
|
|
181
|
+
findings.push({ scenarioId: rtCase.id, reason: finding.reason ?? "red-team probe failed" });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return { passed: findings.length === 0, findings };
|
|
186
|
+
}
|
|
187
|
+
function extractText(artifact) {
|
|
188
|
+
if (typeof artifact === "string") return artifact;
|
|
189
|
+
if (artifact && typeof artifact === "object") {
|
|
190
|
+
const rec = artifact;
|
|
191
|
+
if (typeof rec.text === "string") return rec.text;
|
|
192
|
+
if (typeof rec.output === "string") return rec.output;
|
|
193
|
+
if (typeof rec.content === "string") return rec.content;
|
|
194
|
+
}
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/campaign/presets/run-eval.ts
|
|
199
|
+
async function runEval(opts) {
|
|
200
|
+
return runCampaign(opts);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/campaign/provenance.ts
|
|
204
|
+
import { createHash } from "crypto";
|
|
205
|
+
import { join } from "path";
|
|
206
|
+
function surfaceContentHash(surface) {
|
|
207
|
+
const material = typeof surface === "string" ? surface : JSON.stringify({
|
|
208
|
+
kind: surface.kind,
|
|
209
|
+
worktreeRef: surface.worktreeRef,
|
|
210
|
+
baseRef: surface.baseRef ?? null
|
|
211
|
+
});
|
|
212
|
+
return `sha256:${createHash("sha256").update(material).digest("hex")}`;
|
|
213
|
+
}
|
|
214
|
+
function meanHoldoutComposite(campaign) {
|
|
215
|
+
const xs = [];
|
|
216
|
+
for (const cell of campaign.cells) {
|
|
217
|
+
if (cell.error) continue;
|
|
218
|
+
const cs = Object.values(cell.judgeScores).map((s) => s.composite);
|
|
219
|
+
if (cs.length) xs.push(cs.reduce((a, b) => a + b, 0) / cs.length);
|
|
220
|
+
}
|
|
221
|
+
return xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0;
|
|
222
|
+
}
|
|
223
|
+
function buildLoopProvenanceRecord(args) {
|
|
224
|
+
const integrity = summarizeBackendIntegrity(args.workerRecords);
|
|
225
|
+
const models = [...new Set(args.workerRecords.map((r) => r.model))].sort();
|
|
226
|
+
const candidates = [];
|
|
227
|
+
for (const gen of args.generations) {
|
|
228
|
+
const promotedSet = new Set(gen.promoted);
|
|
229
|
+
const surfaceByHash = new Map(gen.surfaces.map((s) => [s.surfaceHash, s.surface]));
|
|
230
|
+
for (const c of gen.candidates) {
|
|
231
|
+
const surface = surfaceByHash.get(c.surfaceHash);
|
|
232
|
+
const entry = {
|
|
233
|
+
generation: gen.generationIndex,
|
|
234
|
+
surfaceHash: c.surfaceHash,
|
|
235
|
+
contentHash: surface !== void 0 ? surfaceContentHash(surface) : `sha256:${c.surfaceHash}`,
|
|
236
|
+
composite: c.composite,
|
|
237
|
+
promoted: promotedSet.has(c.surfaceHash)
|
|
238
|
+
};
|
|
239
|
+
if (c.label) entry.label = c.label;
|
|
240
|
+
if (c.rationale) entry.rationale = c.rationale;
|
|
241
|
+
candidates.push(entry);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const baselineHoldoutComposite = meanHoldoutComposite(args.baselineOnHoldout);
|
|
245
|
+
const winnerHoldoutComposite = meanHoldoutComposite(args.winnerOnHoldout);
|
|
246
|
+
const record = {
|
|
247
|
+
schema: "tangle.loop-provenance.v1",
|
|
248
|
+
runId: args.runId,
|
|
249
|
+
runDir: args.runDir,
|
|
250
|
+
timestamp: args.timestamp,
|
|
251
|
+
baselineContentHash: surfaceContentHash(args.baselineSurface),
|
|
252
|
+
winnerContentHash: surfaceContentHash(args.winnerSurface),
|
|
253
|
+
diff: args.diff,
|
|
254
|
+
candidates,
|
|
255
|
+
gate: {
|
|
256
|
+
decision: args.gate.decision,
|
|
257
|
+
reasons: args.gate.reasons,
|
|
258
|
+
delta: args.gate.delta,
|
|
259
|
+
contributingGates: args.gate.contributingGates.map((g) => ({
|
|
260
|
+
name: g.name,
|
|
261
|
+
passed: g.passed
|
|
262
|
+
}))
|
|
263
|
+
},
|
|
264
|
+
baselineHoldoutComposite,
|
|
265
|
+
winnerHoldoutComposite,
|
|
266
|
+
heldOutLift: winnerHoldoutComposite - baselineHoldoutComposite,
|
|
267
|
+
backend: {
|
|
268
|
+
verdict: integrity.verdict,
|
|
269
|
+
workerCallCount: integrity.totalRecords,
|
|
270
|
+
models,
|
|
271
|
+
totalInputTokens: integrity.totalInputTokens,
|
|
272
|
+
totalOutputTokens: integrity.totalOutputTokens,
|
|
273
|
+
totalCostUsd: integrity.totalCostUsd
|
|
274
|
+
},
|
|
275
|
+
totalCostUsd: args.totalCostUsd,
|
|
276
|
+
totalDurationMs: args.totalDurationMs
|
|
277
|
+
};
|
|
278
|
+
if (args.winnerLabel) record.winnerLabel = args.winnerLabel;
|
|
279
|
+
if (args.winnerRationale) record.winnerRationale = args.winnerRationale;
|
|
280
|
+
return record;
|
|
281
|
+
}
|
|
282
|
+
var DECISION_OK = ["ship"];
|
|
283
|
+
function hashId(parts) {
|
|
284
|
+
return createHash("sha256").update(parts.join(":")).digest("hex");
|
|
285
|
+
}
|
|
286
|
+
function gateStatus(decision) {
|
|
287
|
+
return DECISION_OK.includes(decision) ? { code: "OK" } : { code: "ERROR", message: `gate decision: ${decision}` };
|
|
288
|
+
}
|
|
289
|
+
function loopProvenanceSpans(record, opts = {}) {
|
|
290
|
+
const traceId = hashId(["trace", record.runId]).slice(0, 32);
|
|
291
|
+
const baseNano = (opts.baseTimeMs ?? (Date.parse(record.timestamp) || Date.now())) * 1e6;
|
|
292
|
+
const endNano = baseNano + Math.max(1, record.totalDurationMs) * 1e6;
|
|
293
|
+
const spans = [];
|
|
294
|
+
const rootSpanId = hashId(["root", record.runId]).slice(0, 16);
|
|
295
|
+
spans.push({
|
|
296
|
+
traceId,
|
|
297
|
+
spanId: rootSpanId,
|
|
298
|
+
name: "improvement-loop",
|
|
299
|
+
startTimeUnixNano: baseNano,
|
|
300
|
+
endTimeUnixNano: endNano,
|
|
301
|
+
attributes: {
|
|
302
|
+
"tangle.runId": record.runId,
|
|
303
|
+
"tangle.runDir": record.runDir,
|
|
304
|
+
"tangle.baselineContentHash": record.baselineContentHash,
|
|
305
|
+
"tangle.winnerContentHash": record.winnerContentHash,
|
|
306
|
+
"tangle.heldOutLift": record.heldOutLift,
|
|
307
|
+
"tangle.gateDecision": record.gate.decision,
|
|
308
|
+
"tangle.backendVerdict": record.backend.verdict,
|
|
309
|
+
"tangle.workerCallCount": record.backend.workerCallCount,
|
|
310
|
+
"tangle.totalCostUsd": record.totalCostUsd
|
|
311
|
+
},
|
|
312
|
+
status: gateStatus(record.gate.decision),
|
|
313
|
+
"tangle.runId": record.runId
|
|
314
|
+
});
|
|
315
|
+
const byGen = /* @__PURE__ */ new Map();
|
|
316
|
+
for (const c of record.candidates) {
|
|
317
|
+
const arr = byGen.get(c.generation) ?? [];
|
|
318
|
+
arr.push(c);
|
|
319
|
+
byGen.set(c.generation, arr);
|
|
320
|
+
}
|
|
321
|
+
for (const [generation, cands] of [...byGen.entries()].sort((a, b) => a[0] - b[0])) {
|
|
322
|
+
const genSpanId = hashId(["gen", record.runId, String(generation)]).slice(0, 16);
|
|
323
|
+
const bestComposite = cands.reduce((m, c) => Math.max(m, c.composite), 0);
|
|
324
|
+
spans.push({
|
|
325
|
+
traceId,
|
|
326
|
+
spanId: genSpanId,
|
|
327
|
+
parentSpanId: rootSpanId,
|
|
328
|
+
name: `generation-${generation}`,
|
|
329
|
+
startTimeUnixNano: baseNano,
|
|
330
|
+
endTimeUnixNano: endNano,
|
|
331
|
+
attributes: {
|
|
332
|
+
"tangle.runId": record.runId,
|
|
333
|
+
"tangle.generation": generation,
|
|
334
|
+
"tangle.populationSize": cands.length,
|
|
335
|
+
"tangle.bestComposite": bestComposite
|
|
336
|
+
},
|
|
337
|
+
"tangle.runId": record.runId,
|
|
338
|
+
"tangle.generation": generation
|
|
339
|
+
});
|
|
340
|
+
for (let i = 0; i < cands.length; i++) {
|
|
341
|
+
const c = cands[i];
|
|
342
|
+
const candSpanId = hashId(["cand", record.runId, String(generation), c.surfaceHash]).slice(
|
|
343
|
+
0,
|
|
344
|
+
16
|
|
345
|
+
);
|
|
346
|
+
const attributes = {
|
|
347
|
+
"tangle.runId": record.runId,
|
|
348
|
+
"tangle.generation": generation,
|
|
349
|
+
"tangle.surfaceHash": c.surfaceHash,
|
|
350
|
+
"tangle.contentHash": c.contentHash,
|
|
351
|
+
"tangle.composite": c.composite,
|
|
352
|
+
"tangle.promoted": c.promoted
|
|
353
|
+
};
|
|
354
|
+
if (c.label) attributes["tangle.candidateLabel"] = c.label;
|
|
355
|
+
if (c.rationale) attributes["tangle.candidateRationale"] = c.rationale;
|
|
356
|
+
spans.push({
|
|
357
|
+
traceId,
|
|
358
|
+
spanId: candSpanId,
|
|
359
|
+
parentSpanId: genSpanId,
|
|
360
|
+
name: `candidate-${c.surfaceHash}`,
|
|
361
|
+
startTimeUnixNano: baseNano,
|
|
362
|
+
endTimeUnixNano: endNano,
|
|
363
|
+
attributes,
|
|
364
|
+
"tangle.runId": record.runId,
|
|
365
|
+
"tangle.generation": generation
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
const gateSpanId = hashId(["gate", record.runId]).slice(0, 16);
|
|
370
|
+
spans.push({
|
|
371
|
+
traceId,
|
|
372
|
+
spanId: gateSpanId,
|
|
373
|
+
parentSpanId: rootSpanId,
|
|
374
|
+
name: "gate-decision",
|
|
375
|
+
startTimeUnixNano: endNano,
|
|
376
|
+
endTimeUnixNano: endNano,
|
|
377
|
+
attributes: {
|
|
378
|
+
"tangle.runId": record.runId,
|
|
379
|
+
"tangle.gateDecision": record.gate.decision,
|
|
380
|
+
"tangle.gateDelta": record.gate.delta ?? record.heldOutLift,
|
|
381
|
+
"tangle.gateReasons": JSON.stringify(record.gate.reasons),
|
|
382
|
+
"tangle.heldOutLift": record.heldOutLift,
|
|
383
|
+
"tangle.baselineHoldoutComposite": record.baselineHoldoutComposite,
|
|
384
|
+
"tangle.winnerHoldoutComposite": record.winnerHoldoutComposite
|
|
385
|
+
},
|
|
386
|
+
status: gateStatus(record.gate.decision),
|
|
387
|
+
"tangle.runId": record.runId
|
|
388
|
+
});
|
|
389
|
+
return spans;
|
|
390
|
+
}
|
|
391
|
+
function provenanceRecordPath(runDir) {
|
|
392
|
+
return join(runDir, "loop-provenance.json");
|
|
393
|
+
}
|
|
394
|
+
function provenanceSpansPath(runDir) {
|
|
395
|
+
return join(runDir, "loop-provenance-spans.jsonl");
|
|
396
|
+
}
|
|
397
|
+
function snapshotFromHoldout(index, surfaceHash, surface, campaign) {
|
|
398
|
+
const cells = campaign.cells.map((cell) => {
|
|
399
|
+
const judgeScores = Object.values(cell.judgeScores);
|
|
400
|
+
const composite = judgeScores.length === 0 ? 0 : judgeScores.reduce((s, j) => s + j.composite, 0) / judgeScores.length;
|
|
401
|
+
const score = {
|
|
402
|
+
scenarioId: cell.scenarioId,
|
|
403
|
+
rep: cell.rep,
|
|
404
|
+
compositeMean: composite,
|
|
405
|
+
dimensions: Object.fromEntries(
|
|
406
|
+
Object.entries(cell.judgeScores).map(([name, s]) => [name, s.dimensions])
|
|
407
|
+
)
|
|
408
|
+
};
|
|
409
|
+
if (cell.error) score.errorMessage = cell.error;
|
|
410
|
+
return score;
|
|
411
|
+
});
|
|
412
|
+
const compositeMean = cells.length === 0 ? 0 : cells.reduce((s, c) => s + c.compositeMean, 0) / cells.length;
|
|
413
|
+
return {
|
|
414
|
+
index,
|
|
415
|
+
surfaceHash,
|
|
416
|
+
surface,
|
|
417
|
+
cells,
|
|
418
|
+
compositeMean,
|
|
419
|
+
costUsd: campaign.aggregates.totalCostUsd,
|
|
420
|
+
durationMs: campaign.durationMs
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function buildEvalRunEvent(args, record) {
|
|
424
|
+
return {
|
|
425
|
+
runId: args.runId,
|
|
426
|
+
runDir: args.runDir,
|
|
427
|
+
timestamp: args.timestamp,
|
|
428
|
+
status: "finished",
|
|
429
|
+
labels: {},
|
|
430
|
+
baseline: snapshotFromHoldout(
|
|
431
|
+
0,
|
|
432
|
+
record.baselineContentHash,
|
|
433
|
+
args.baselineSurface,
|
|
434
|
+
args.baselineOnHoldout
|
|
435
|
+
),
|
|
436
|
+
generations: [
|
|
437
|
+
snapshotFromHoldout(1, record.winnerContentHash, args.winnerSurface, args.winnerOnHoldout)
|
|
438
|
+
],
|
|
439
|
+
gateDecision: args.gate.decision,
|
|
440
|
+
holdoutLift: record.heldOutLift,
|
|
441
|
+
totalCostUsd: args.totalCostUsd,
|
|
442
|
+
totalDurationMs: args.totalDurationMs
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
async function emitLoopProvenance(args) {
|
|
446
|
+
const record = buildLoopProvenanceRecord(args);
|
|
447
|
+
const spans = loopProvenanceSpans(record);
|
|
448
|
+
args.storage.ensureDir(args.runDir);
|
|
449
|
+
const recordPath = provenanceRecordPath(args.runDir);
|
|
450
|
+
const spansPath = provenanceSpansPath(args.runDir);
|
|
451
|
+
args.storage.write(recordPath, JSON.stringify(record, null, 2));
|
|
452
|
+
args.storage.write(spansPath, spans.map((s) => JSON.stringify(s)).join("\n"));
|
|
453
|
+
if (args.hostedClient) {
|
|
454
|
+
try {
|
|
455
|
+
await args.hostedClient.ingestEvalRun(buildEvalRunEvent(args, record));
|
|
456
|
+
} catch (err) {
|
|
457
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
458
|
+
console.warn(`[agent-eval] hosted eval-run ingest failed (continuing): ${msg}`);
|
|
459
|
+
}
|
|
460
|
+
try {
|
|
461
|
+
await args.hostedClient.ingestTraces(spans);
|
|
462
|
+
} catch (err) {
|
|
463
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
464
|
+
console.warn(`[agent-eval] provenance span ingest failed (continuing): ${msg}`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return { record, spans, recordPath, spansPath };
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export {
|
|
471
|
+
evolutionaryDriver,
|
|
472
|
+
composeGate,
|
|
473
|
+
defaultProductionGate,
|
|
474
|
+
runEval,
|
|
475
|
+
surfaceContentHash,
|
|
476
|
+
buildLoopProvenanceRecord,
|
|
477
|
+
loopProvenanceSpans,
|
|
478
|
+
provenanceRecordPath,
|
|
479
|
+
provenanceSpansPath,
|
|
480
|
+
emitLoopProvenance
|
|
481
|
+
};
|
|
482
|
+
//# sourceMappingURL=chunk-RDK3P4JE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/campaign/drivers/evolutionary.ts","../src/campaign/gates/compose.ts","../src/campaign/gates/default-production-gate.ts","../src/campaign/presets/run-eval.ts","../src/campaign/provenance.ts"],"sourcesContent":["/**\n * @experimental\n *\n * `evolutionaryDriver` — adapts a stateless `Mutator` (population mutation:\n * GEPA / AxGEPA / reflective-mutation) into an `ImprovementDriver`. This is\n * the evolutionary strategy: each generation, mutate the current best surface\n * into N candidates, measure, select. No generation memory beyond the current\n * surface; the loop body handles ranking + promotion.\n *\n * The reflective alternative is agent-runtime's `improvementDriver` with a\n * `reflectiveGenerator` / `agenticGenerator`: it reasons over the report +\n * trace findings to propose targeted edits rather than blind mutations. Both\n * conform to `ImprovementDriver`; the improvement loop is identical regardless\n * of which drives it.\n */\n\nimport type { ImprovementDriver, Mutator } from '../types'\n\nexport interface EvolutionaryDriverOptions<TFindings = unknown> {\n mutator: Mutator<TFindings>\n /** External findings fed to the mutator each generation. Default: []. */\n findings?: TFindings[]\n}\n\nexport function evolutionaryDriver<TFindings = unknown>(\n opts: EvolutionaryDriverOptions<TFindings>,\n): ImprovementDriver<TFindings> {\n return {\n kind: `evolutionary:${opts.mutator.kind}`,\n async propose({ currentSurface, findings, populationSize, signal }) {\n return opts.mutator.mutate({\n findings: findings.length > 0 ? findings : (opts.findings ?? []),\n currentSurface,\n populationSize,\n signal,\n })\n },\n }\n}\n","/**\n * @experimental\n *\n * Compose multiple `Gate` implementations — every gate must pass for the\n * composite to ship. Closes the alignment reviewer's \"default-only\n * heldOutGate + costGate would happily promote a reward-hacked prompt\"\n * concern by making safety gates first-class composable defaults.\n */\n\nimport type { Gate, GateContext, GateDecision, GateResult, Scenario } from '../types'\n\n/** Compose gates — all must `ship` for the composite to `ship`. First\n * non-ship verdict short-circuits the composite verdict, but ALL gates run\n * (so the result records every gate's reason — useful for diagnostics). */\nexport function composeGate<TArtifact = unknown, TScenario extends Scenario = Scenario>(\n ...gates: Array<Gate<TArtifact, TScenario>>\n): Gate<TArtifact, TScenario> {\n if (gates.length === 0) {\n throw new Error('composeGate requires at least one gate')\n }\n return {\n name: `composed(${gates.map((g) => g.name).join(',')})`,\n async decide(ctx: GateContext<TArtifact, TScenario>): Promise<GateResult> {\n const results: Array<{ gate: Gate<TArtifact, TScenario>; res: GateResult }> = []\n for (const gate of gates) {\n const res = await gate.decide(ctx)\n results.push({ gate, res })\n }\n\n // Substrate-wide verdict policy:\n // - all 'ship' → 'ship'\n // - any 'arch_ceiling' → 'arch_ceiling' (architectural ceiling beats other holds)\n // - any 'model_ceiling' → 'model_ceiling'\n // - any 'hold' → 'hold'\n // - else 'need_more_work'\n const decisions = results.map((r) => r.res.decision)\n const overall: GateDecision = decisions.every((d) => d === 'ship')\n ? 'ship'\n : decisions.includes('arch_ceiling')\n ? 'arch_ceiling'\n : decisions.includes('model_ceiling')\n ? 'model_ceiling'\n : decisions.includes('hold')\n ? 'hold'\n : 'need_more_work'\n\n const contributing = results.flatMap((r) =>\n r.res.contributingGates.length > 0\n ? r.res.contributingGates\n : [{ name: r.gate.name, passed: r.res.decision === 'ship', detail: r.res }],\n )\n\n const reasons = results.flatMap((r) =>\n r.res.reasons.map((reason) => `[${r.gate.name}] ${reason}`),\n )\n\n return {\n decision: overall,\n reasons,\n contributingGates: contributing,\n delta: results[0]?.res.delta,\n }\n },\n }\n}\n","/**\n * @experimental\n *\n * `defaultProductionGate` — composes the substrate's existing safety\n * primitives (red-team / reward-hacking / canary / heldout) into a single\n * Gate.decide shape. Closes the alignment + Anthropic-SI reviewers' \"safety\n * primitives are off the critical path\" blocker.\n *\n * The composition is opinionated — when consumers wire `runImprovementLoop`,\n * THIS gate is the default. Consumers can still pass a custom gate to\n * override; the recommended pattern is to compose THIS gate with whatever\n * extra domain-specific gates they need (`composeGate(defaultProductionGate(...), customGate)`).\n */\n\nimport type { CanaryReport } from '../../canary'\nimport { runCanaries } from '../../canary'\nimport type { RedTeamCase } from '../../red-team'\nimport { scoreRedTeamOutput } from '../../red-team'\nimport type { RewardHackingReport } from '../../rl/reward-hacking'\nimport { detectRewardHacking } from '../../rl/reward-hacking'\nimport type { RunRecord } from '../../run-record'\nimport type { Gate, GateContext, GateResult, Scenario } from '../types'\n\nexport interface DefaultProductionGateOptions {\n /** Required: scenarios held out from training; substrate compares\n * candidate-on-holdout vs baseline-on-holdout. */\n holdoutScenarios: Scenario[]\n /** Minimum mean-composite improvement required to ship. Default 0.5. */\n deltaThreshold?: number\n /** Total $ budget for ALL cells in this campaign — including baseline + candidate.\n * Composite verdict refuses to ship when spend exceeded budget. */\n budgetUsd?: number\n /** Red-team cases to probe candidate outputs against. When omitted the\n * substrate uses `DEFAULT_RED_TEAM_CORPUS`. Provide a domain-specific\n * battery for tighter coverage. */\n redTeamBattery?: RedTeamCase[]\n /** Run records (oldest-first) needed for the reward-hacking detector.\n * Substrate populates from prior production-loop generations. */\n recentRuns?: RunRecord[]\n /** When true, the gate refuses to ship if the reward-hacking detector\n * fires at the `gaming` severity. Default true. */\n blockOnRewardHackingGaming?: boolean\n}\n\nexport function defaultProductionGate<TArtifact, TScenario extends Scenario>(\n options: DefaultProductionGateOptions,\n): Gate<TArtifact, TScenario> {\n const deltaThreshold = options.deltaThreshold ?? 0.5\n const blockOnGaming = options.blockOnRewardHackingGaming ?? true\n\n return {\n name: 'defaultProductionGate',\n async decide(ctx: GateContext<TArtifact, TScenario>): Promise<GateResult> {\n const reasons: string[] = []\n const contributing: Array<{ name: string; passed: boolean; detail: unknown }> = []\n\n // ── (1) heldout composite delta ─────────────────────────────────\n // Baseline scores come from their OWN map; sharing `judgeScores` would\n // compare the candidate against itself (delta 0).\n const baselineComposite = meanComposite(\n ctx.baselineArtifacts,\n ctx.baselineJudgeScores ?? ctx.judgeScores,\n options.holdoutScenarios,\n )\n const candidateComposite = meanComposite(\n ctx.candidateArtifacts,\n ctx.judgeScores,\n options.holdoutScenarios,\n )\n const delta = candidateComposite - baselineComposite\n const heldoutPass = delta >= deltaThreshold\n contributing.push({\n name: 'heldout-delta',\n passed: heldoutPass,\n detail: { baselineComposite, candidateComposite, delta, deltaThreshold },\n })\n if (!heldoutPass) {\n reasons.push(`heldout delta ${delta.toFixed(3)} < threshold ${deltaThreshold}`)\n }\n\n // ── (2) budget gate ─────────────────────────────────────────────\n const budgetPass =\n options.budgetUsd === undefined ||\n ctx.cost.candidate + ctx.cost.baseline <= options.budgetUsd\n contributing.push({\n name: 'budget',\n passed: budgetPass,\n detail: {\n candidateUsd: ctx.cost.candidate,\n baselineUsd: ctx.cost.baseline,\n budgetUsd: options.budgetUsd,\n },\n })\n if (!budgetPass) {\n reasons.push(\n `spend ${(ctx.cost.candidate + ctx.cost.baseline).toFixed(2)} > budget ${options.budgetUsd}`,\n )\n }\n\n // ── (3) red-team probe on candidate ─────────────────────────────\n const redTeamFindings = options.redTeamBattery\n ? probeRedTeam(ctx.candidateArtifacts, options.redTeamBattery)\n : { passed: true, findings: [] }\n contributing.push({\n name: 'red-team',\n passed: redTeamFindings.passed,\n detail: {\n failures: redTeamFindings.findings.length,\n sample: redTeamFindings.findings.slice(0, 3),\n },\n })\n if (!redTeamFindings.passed) {\n reasons.push(`red-team probe failed (${redTeamFindings.findings.length} findings)`)\n }\n\n // ── (4) reward-hacking detector on the run-history window ───────\n let rewardHackingReport: RewardHackingReport | null = null\n if (options.recentRuns && options.recentRuns.length >= 10) {\n rewardHackingReport = detectRewardHacking({ runs: options.recentRuns })\n }\n // reward-hacking severity is numeric (0..1). \"gaming\" threshold per\n // detectRewardHacking defaults = 0.6. Block when ANY finding is at\n // gaming threshold OR the report verdict is 'gaming'.\n const gamingThreshold = 0.6\n const gamingFindings = (rewardHackingReport?.findings ?? []).filter(\n (f) => f.severity >= gamingThreshold,\n )\n const rewardHackingPass =\n !rewardHackingReport ||\n !blockOnGaming ||\n (gamingFindings.length === 0 && rewardHackingReport.verdict !== 'gaming')\n contributing.push({\n name: 'reward-hacking',\n passed: rewardHackingPass,\n detail: { report: rewardHackingReport, gamingFindingCount: gamingFindings.length },\n })\n if (!rewardHackingPass) {\n reasons.push(\n `reward-hacking detector flagged ${gamingFindings.length} gaming-severity findings (verdict=${rewardHackingReport!.verdict})`,\n )\n }\n\n // ── (5) canary check on runs ────────────────────────────────────\n let canaryReport: CanaryReport | null = null\n if (options.recentRuns && options.recentRuns.length >= 10) {\n canaryReport = runCanaries(options.recentRuns, {})\n }\n // CanarySeverity is 'info' | 'warn' | 'error' — block on 'error'.\n const errorAlerts = (canaryReport?.alerts ?? []).filter((a) => a.severity === 'error')\n const canaryPass = errorAlerts.length === 0\n contributing.push({\n name: 'canary',\n passed: canaryPass,\n detail: { totalAlerts: canaryReport?.alerts.length ?? 0, errorAlerts: errorAlerts.length },\n })\n if (!canaryPass) {\n reasons.push(`canary error alerts: ${errorAlerts.length}`)\n }\n\n // ── Verdict ─────────────────────────────────────────────────────\n const allPassed = contributing.every((c) => c.passed)\n const decision = allPassed ? 'ship' : 'hold'\n\n return {\n decision,\n reasons: reasons.length > 0 ? reasons : ['all gates passed'],\n contributingGates: contributing,\n delta,\n }\n },\n }\n}\n\nfunction meanComposite<TArtifact, TScenario extends Scenario>(\n artifacts: Map<string, TArtifact> | undefined,\n judgeScoresByCell: Map<string, Record<string, { composite: number }>>,\n scenarios: TScenario[],\n): number {\n if (!artifacts || artifacts.size === 0) return 0\n const scenarioIds = new Set(scenarios.map((s) => s.id))\n const composites: number[] = []\n for (const [cellId, scores] of judgeScoresByCell) {\n const scenarioId = cellId.split(':')[0] ?? ''\n if (!scenarioIds.has(scenarioId)) continue\n const cellComposites = Object.values(scores).map((s) => s.composite)\n if (cellComposites.length === 0) continue\n composites.push(cellComposites.reduce((a, b) => a + b, 0) / cellComposites.length)\n }\n if (composites.length === 0) return 0\n return composites.reduce((a, b) => a + b, 0) / composites.length\n}\n\nfunction probeRedTeam<TArtifact>(\n artifacts: Map<string, TArtifact>,\n battery: RedTeamCase[],\n): { passed: boolean; findings: Array<{ scenarioId: string; reason: string }> } {\n const findings: Array<{ scenarioId: string; reason: string }> = []\n for (const [_cellId, artifact] of artifacts) {\n const text = extractText(artifact)\n if (text === undefined) continue\n for (const rtCase of battery) {\n const finding = scoreRedTeamOutput(text, [], rtCase)\n if (!finding.passed) {\n findings.push({ scenarioId: rtCase.id, reason: finding.reason ?? 'red-team probe failed' })\n }\n }\n }\n return { passed: findings.length === 0, findings }\n}\n\nfunction extractText(artifact: unknown): string | undefined {\n if (typeof artifact === 'string') return artifact\n if (artifact && typeof artifact === 'object') {\n const rec = artifact as Record<string, unknown>\n if (typeof rec.text === 'string') return rec.text\n if (typeof rec.output === 'string') return rec.output\n if (typeof rec.content === 'string') return rec.content\n }\n return undefined\n}\n","/**\n * @experimental\n *\n * `runEval` — the simplest preset over `runCampaign`. No optimizer, no\n * gate, no auto-PR. Just: run scenarios through dispatch, score with\n * judges, return CampaignResult.\n *\n * The 80% case for consumers who want a scorecard, not an improvement loop.\n */\n\nimport { type RunCampaignOptions, runCampaign } from '../run-campaign'\nimport type { CampaignResult, Scenario } from '../types'\n\nexport interface RunEvalOptions<TScenario extends Scenario, TArtifact>\n extends Omit<RunCampaignOptions<TScenario, TArtifact>, 'runDir'> {\n runDir: string\n}\n\nexport async function runEval<TScenario extends Scenario, TArtifact>(\n opts: RunEvalOptions<TScenario, TArtifact>,\n): Promise<CampaignResult<TArtifact, TScenario>> {\n return runCampaign(opts)\n}\n","/**\n * @experimental\n *\n * Loop provenance — the durable, queryable record of WHAT a self-improvement\n * loop did and WHY, plus the OTel spans that let an OTLP collector pivot from\n * an eval-run to the underlying candidate→cell→gate→promote chain.\n *\n * Two artifacts, one source of truth:\n *\n * 1. `LoopProvenanceRecord` — a structured JSON record capturing every\n * candidate (surfaceHash + label + rationale), its measured composite,\n * the gate decision + reasons + delta, the held-out lift, the explicit\n * baseline→candidate diff, and BACKEND PROVENANCE (the\n * `assertRealBackend` verdict + worker call count + model). This is the\n * ingestable audit artifact: the +lift recomputes from it, the \"because\n * Z\" rationale survives in it, and a stub backend is detectable from it.\n *\n * 2. `loopProvenanceSpans()` — the same chain emitted as OTLP-ingestable\n * `TraceSpanEvent`s, pivoted on the substrate's standard\n * `tangle.runId` / `tangle.scenarioId` / `tangle.cellId` /\n * `tangle.generation` attributes (the same pivots `/adapters/otel`\n * reads). The hosted `/v1/ingest/traces` endpoint receives the FULL loop,\n * not just the `cost.*` spans `runCampaign` already emits per cell.\n *\n * The record is built from the substrate's own loop result + the per-call\n * `RunRecord`s the worker emitted — no new measurement, no recomputation that\n * could drift from what the gate actually saw.\n */\n\nimport { createHash } from 'node:crypto'\nimport { join } from 'node:path'\nimport type { HostedClient } from '../hosted/client'\nimport type {\n EvalRunCellScore,\n EvalRunEvent,\n EvalRunGenerationSnapshot,\n TraceSpanEvent,\n} from '../hosted/types'\nimport { summarizeBackendIntegrity } from '../integrity/backend-integrity'\nimport type { RunRecord } from '../run-record'\nimport type { CampaignStorage } from './storage'\nimport type { CampaignResult, GateDecision, GateResult, MutableSurface, Scenario } from './types'\n\n/** Stable sha256 (full hex) of a surface's effective text. Code surfaces hash\n * their worktree+base identity since the content lives in git. Distinct from\n * `surfaceHash` (16-char content fingerprint used as a loop identity key);\n * this is the byte-identical-verifiable content hash the provenance record +\n * `RunRecord.promptHash` carry. */\nexport function surfaceContentHash(surface: MutableSurface): string {\n const material =\n typeof surface === 'string'\n ? surface\n : JSON.stringify({\n kind: surface.kind,\n worktreeRef: surface.worktreeRef,\n baseRef: surface.baseRef ?? null,\n })\n return `sha256:${createHash('sha256').update(material).digest('hex')}`\n}\n\nexport interface LoopProvenanceCandidate {\n /** Generation index this candidate was proposed in. */\n generation: number\n /** 16-char loop-identity fingerprint (matches `GenerationCandidate.surfaceHash`). */\n surfaceHash: string\n /** Full sha256 content hash — byte-identical-verifiable. */\n contentHash: string\n /** Driver label, when the driver returned a `ProposedCandidate`. */\n label?: string\n /** Driver rationale — the \"because Z\". When the driver returned a bare\n * surface (blind mutator) this is absent. */\n rationale?: string\n /** Mean composite this candidate scored on the search split. */\n composite: number\n /** Whether this candidate was promoted out of its generation. */\n promoted: boolean\n}\n\nexport interface LoopProvenanceBackend {\n /** `assertRealBackend`-grade verdict over the worker call records. */\n verdict: 'real' | 'mixed' | 'stub'\n /** Number of worker LLM calls captured (the audit's \"worker call count\"). */\n workerCallCount: number\n /** Distinct model ids observed across worker calls. */\n models: string[]\n totalInputTokens: number\n totalOutputTokens: number\n totalCostUsd: number\n}\n\n/**\n * The durable provenance record. Aligns to the hosted `EvalRunEvent` path but\n * ADDS the rationale + the explicit baseline→candidate diff (both omitted from\n * the bare hosted event) + backend provenance.\n */\nexport interface LoopProvenanceRecord {\n schema: 'tangle.loop-provenance.v1'\n runId: string\n runDir: string\n timestamp: string\n /** Baseline + winner surface content hashes — distinguishable, byte-verifiable. */\n baselineContentHash: string\n winnerContentHash: string\n /** Driver label/rationale for the promoted change. Absent ⇒ winner == baseline. */\n winnerLabel?: string\n winnerRationale?: string\n /** The explicit baseline→winner unified diff the gate decided on. */\n diff: string\n /** Every candidate across every generation, each carrying its rationale. */\n candidates: LoopProvenanceCandidate[]\n /** The gate verdict — decision + reasons + contributing gates + delta. */\n gate: {\n decision: GateDecision\n reasons: string[]\n delta?: number\n contributingGates: Array<{ name: string; passed: boolean }>\n }\n /** baseline-on-holdout composite mean. */\n baselineHoldoutComposite: number\n /** winner-on-holdout composite mean. */\n winnerHoldoutComposite: number\n /** winnerHoldout - baselineHoldout — RECOMPUTABLE from this record. */\n heldOutLift: number\n /** Backend provenance: stub-vs-real verdict + worker call count + models. */\n backend: LoopProvenanceBackend\n totalCostUsd: number\n totalDurationMs: number\n}\n\nexport interface BuildLoopProvenanceArgs<TArtifact, TScenario extends Scenario> {\n runId: string\n runDir: string\n timestamp: string\n baselineSurface: MutableSurface\n winnerSurface: MutableSurface\n winnerLabel?: string\n winnerRationale?: string\n diff: string\n /** Per-generation candidate records straight off the loop result. */\n generations: Array<{\n generationIndex: number\n candidates: Array<{\n surfaceHash: string\n composite: number\n label?: string\n rationale?: string\n }>\n promoted: string[]\n /** Surfaces measured this generation, keyed positionally to candidates so\n * the content hash can be computed from the real surface text. */\n surfaces: Array<{ surfaceHash: string; surface: MutableSurface }>\n }>\n gate: GateResult\n baselineOnHoldout: CampaignResult<TArtifact, TScenario>\n winnerOnHoldout: CampaignResult<TArtifact, TScenario>\n /** Worker call records — the source for backend provenance. */\n workerRecords: ReadonlyArray<RunRecord>\n totalCostUsd: number\n totalDurationMs: number\n}\n\nfunction meanHoldoutComposite<TArtifact, TScenario extends Scenario>(\n campaign: CampaignResult<TArtifact, TScenario>,\n): number {\n const xs: number[] = []\n for (const cell of campaign.cells) {\n if (cell.error) continue\n const cs = Object.values(cell.judgeScores).map((s) => s.composite)\n if (cs.length) xs.push(cs.reduce((a, b) => a + b, 0) / cs.length)\n }\n return xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0\n}\n\n/** Build the durable provenance record from a completed loop result. */\nexport function buildLoopProvenanceRecord<TArtifact, TScenario extends Scenario>(\n args: BuildLoopProvenanceArgs<TArtifact, TScenario>,\n): LoopProvenanceRecord {\n const integrity = summarizeBackendIntegrity(args.workerRecords)\n const models = [...new Set(args.workerRecords.map((r) => r.model))].sort()\n\n const candidates: LoopProvenanceCandidate[] = []\n for (const gen of args.generations) {\n const promotedSet = new Set(gen.promoted)\n const surfaceByHash = new Map(gen.surfaces.map((s) => [s.surfaceHash, s.surface]))\n for (const c of gen.candidates) {\n const surface = surfaceByHash.get(c.surfaceHash)\n const entry: LoopProvenanceCandidate = {\n generation: gen.generationIndex,\n surfaceHash: c.surfaceHash,\n contentHash:\n surface !== undefined ? surfaceContentHash(surface) : `sha256:${c.surfaceHash}`,\n composite: c.composite,\n promoted: promotedSet.has(c.surfaceHash),\n }\n if (c.label) entry.label = c.label\n if (c.rationale) entry.rationale = c.rationale\n candidates.push(entry)\n }\n }\n\n const baselineHoldoutComposite = meanHoldoutComposite(args.baselineOnHoldout)\n const winnerHoldoutComposite = meanHoldoutComposite(args.winnerOnHoldout)\n\n const record: LoopProvenanceRecord = {\n schema: 'tangle.loop-provenance.v1',\n runId: args.runId,\n runDir: args.runDir,\n timestamp: args.timestamp,\n baselineContentHash: surfaceContentHash(args.baselineSurface),\n winnerContentHash: surfaceContentHash(args.winnerSurface),\n diff: args.diff,\n candidates,\n gate: {\n decision: args.gate.decision,\n reasons: args.gate.reasons,\n delta: args.gate.delta,\n contributingGates: args.gate.contributingGates.map((g) => ({\n name: g.name,\n passed: g.passed,\n })),\n },\n baselineHoldoutComposite,\n winnerHoldoutComposite,\n heldOutLift: winnerHoldoutComposite - baselineHoldoutComposite,\n backend: {\n verdict: integrity.verdict,\n workerCallCount: integrity.totalRecords,\n models,\n totalInputTokens: integrity.totalInputTokens,\n totalOutputTokens: integrity.totalOutputTokens,\n totalCostUsd: integrity.totalCostUsd,\n },\n totalCostUsd: args.totalCostUsd,\n totalDurationMs: args.totalDurationMs,\n }\n if (args.winnerLabel) record.winnerLabel = args.winnerLabel\n if (args.winnerRationale) record.winnerRationale = args.winnerRationale\n return record\n}\n\n// ── OTel span emission ──────────────────────────────────────────────────\n\nconst DECISION_OK: GateDecision[] = ['ship']\n\nfunction hashId(parts: string[]): string {\n return createHash('sha256').update(parts.join(':')).digest('hex')\n}\n\nfunction gateStatus(decision: GateDecision): { code: 'OK' | 'ERROR' | 'UNSET'; message?: string } {\n return DECISION_OK.includes(decision)\n ? { code: 'OK' }\n : { code: 'ERROR', message: `gate decision: ${decision}` }\n}\n\n/**\n * Build the loop's OTLP-ingestable spans from a provenance record. One root\n * span per loop (`tangle.runId`), one span per generation, one span per\n * candidate (carrying its surfaceHash + label), and one span for the gate\n * decision (carrying reasons + delta + lift). Candidate + gate spans pivot on\n * the same `tangle.runId` / `tangle.generation` attributes `/adapters/otel`\n * reads, so the hosted collector reconstructs the full tree.\n *\n * Times are synthesized monotonically off a single base so the span tree is\n * orderable; the substrate does not retain per-candidate wall-clock starts.\n */\nexport function loopProvenanceSpans(\n record: LoopProvenanceRecord,\n opts: { baseTimeMs?: number } = {},\n): TraceSpanEvent[] {\n const traceId = hashId(['trace', record.runId]).slice(0, 32)\n const baseNano = (opts.baseTimeMs ?? (Date.parse(record.timestamp) || Date.now())) * 1_000_000\n const endNano = baseNano + Math.max(1, record.totalDurationMs) * 1_000_000\n const spans: TraceSpanEvent[] = []\n\n const rootSpanId = hashId(['root', record.runId]).slice(0, 16)\n spans.push({\n traceId,\n spanId: rootSpanId,\n name: 'improvement-loop',\n startTimeUnixNano: baseNano,\n endTimeUnixNano: endNano,\n attributes: {\n 'tangle.runId': record.runId,\n 'tangle.runDir': record.runDir,\n 'tangle.baselineContentHash': record.baselineContentHash,\n 'tangle.winnerContentHash': record.winnerContentHash,\n 'tangle.heldOutLift': record.heldOutLift,\n 'tangle.gateDecision': record.gate.decision,\n 'tangle.backendVerdict': record.backend.verdict,\n 'tangle.workerCallCount': record.backend.workerCallCount,\n 'tangle.totalCostUsd': record.totalCostUsd,\n },\n status: gateStatus(record.gate.decision),\n 'tangle.runId': record.runId,\n })\n\n // Group candidates by generation for the per-generation parent span.\n const byGen = new Map<number, LoopProvenanceCandidate[]>()\n for (const c of record.candidates) {\n const arr = byGen.get(c.generation) ?? []\n arr.push(c)\n byGen.set(c.generation, arr)\n }\n for (const [generation, cands] of [...byGen.entries()].sort((a, b) => a[0] - b[0])) {\n const genSpanId = hashId(['gen', record.runId, String(generation)]).slice(0, 16)\n const bestComposite = cands.reduce((m, c) => Math.max(m, c.composite), 0)\n spans.push({\n traceId,\n spanId: genSpanId,\n parentSpanId: rootSpanId,\n name: `generation-${generation}`,\n startTimeUnixNano: baseNano,\n endTimeUnixNano: endNano,\n attributes: {\n 'tangle.runId': record.runId,\n 'tangle.generation': generation,\n 'tangle.populationSize': cands.length,\n 'tangle.bestComposite': bestComposite,\n },\n 'tangle.runId': record.runId,\n 'tangle.generation': generation,\n })\n for (let i = 0; i < cands.length; i++) {\n const c = cands[i]!\n const candSpanId = hashId(['cand', record.runId, String(generation), c.surfaceHash]).slice(\n 0,\n 16,\n )\n const attributes: TraceSpanEvent['attributes'] = {\n 'tangle.runId': record.runId,\n 'tangle.generation': generation,\n 'tangle.surfaceHash': c.surfaceHash,\n 'tangle.contentHash': c.contentHash,\n 'tangle.composite': c.composite,\n 'tangle.promoted': c.promoted,\n }\n if (c.label) attributes['tangle.candidateLabel'] = c.label\n if (c.rationale) attributes['tangle.candidateRationale'] = c.rationale\n spans.push({\n traceId,\n spanId: candSpanId,\n parentSpanId: genSpanId,\n name: `candidate-${c.surfaceHash}`,\n startTimeUnixNano: baseNano,\n endTimeUnixNano: endNano,\n attributes,\n 'tangle.runId': record.runId,\n 'tangle.generation': generation,\n })\n }\n }\n\n // Gate span — child of root, carries the decision/reasons/delta the audit\n // needs and pivots back to the run.\n const gateSpanId = hashId(['gate', record.runId]).slice(0, 16)\n spans.push({\n traceId,\n spanId: gateSpanId,\n parentSpanId: rootSpanId,\n name: 'gate-decision',\n startTimeUnixNano: endNano,\n endTimeUnixNano: endNano,\n attributes: {\n 'tangle.runId': record.runId,\n 'tangle.gateDecision': record.gate.decision,\n 'tangle.gateDelta': record.gate.delta ?? record.heldOutLift,\n 'tangle.gateReasons': JSON.stringify(record.gate.reasons),\n 'tangle.heldOutLift': record.heldOutLift,\n 'tangle.baselineHoldoutComposite': record.baselineHoldoutComposite,\n 'tangle.winnerHoldoutComposite': record.winnerHoldoutComposite,\n },\n status: gateStatus(record.gate.decision),\n 'tangle.runId': record.runId,\n })\n\n return spans\n}\n\n// ── Durable emission ─────────────────────────────────────────────────────\n\n/** Canonical durable paths under the run dir. */\nexport function provenanceRecordPath(runDir: string): string {\n return join(runDir, 'loop-provenance.json')\n}\nexport function provenanceSpansPath(runDir: string): string {\n return join(runDir, 'loop-provenance-spans.jsonl')\n}\n\nexport interface EmitLoopProvenanceResult {\n record: LoopProvenanceRecord\n spans: TraceSpanEvent[]\n /** Absolute paths the record + spans were written to, when storage persists. */\n recordPath: string\n spansPath: string\n}\n\nexport interface EmitLoopProvenanceArgs<TArtifact, TScenario extends Scenario>\n extends BuildLoopProvenanceArgs<TArtifact, TScenario> {\n /** Storage the record + spans are written through. */\n storage: CampaignStorage\n /** When set, the spans are also shipped to the hosted `/v1/ingest/traces`\n * endpoint so the collector receives the full loop, not just `cost.*`. */\n hostedClient?: HostedClient\n}\n\n/** Snapshot a held-out campaign into the hosted `EvalRunGenerationSnapshot`\n * shape — per-cell composite + per-judge dimensions, aggregate mean, cost,\n * duration. The dashboard renders these as the baseline → winner comparison. */\nfunction snapshotFromHoldout<TArtifact, TScenario extends Scenario>(\n index: number,\n surfaceHash: string,\n surface: MutableSurface,\n campaign: CampaignResult<TArtifact, TScenario>,\n): EvalRunGenerationSnapshot {\n const cells: EvalRunCellScore[] = campaign.cells.map((cell) => {\n const judgeScores = Object.values(cell.judgeScores)\n const composite =\n judgeScores.length === 0\n ? 0\n : judgeScores.reduce((s, j) => s + j.composite, 0) / judgeScores.length\n const score: EvalRunCellScore = {\n scenarioId: cell.scenarioId,\n rep: cell.rep,\n compositeMean: composite,\n dimensions: Object.fromEntries(\n Object.entries(cell.judgeScores).map(([name, s]) => [name, s.dimensions]),\n ),\n }\n if (cell.error) score.errorMessage = cell.error\n return score\n })\n const compositeMean =\n cells.length === 0 ? 0 : cells.reduce((s, c) => s + c.compositeMean, 0) / cells.length\n return {\n index,\n surfaceHash,\n surface,\n cells,\n compositeMean,\n costUsd: campaign.aggregates.totalCostUsd,\n durationMs: campaign.durationMs,\n }\n}\n\n/** Build the hosted `EvalRunEvent` from the loop args + record — baseline +\n * winner snapshots, gate decision, held-out lift, cost, duration. Shipped to\n * `/v1/ingest/eval-runs` so the run appears in the dashboard's run list (the\n * trace spans, shipped separately, back the per-candidate drill-down). */\nfunction buildEvalRunEvent<TArtifact, TScenario extends Scenario>(\n args: EmitLoopProvenanceArgs<TArtifact, TScenario>,\n record: LoopProvenanceRecord,\n): EvalRunEvent {\n return {\n runId: args.runId,\n runDir: args.runDir,\n timestamp: args.timestamp,\n status: 'finished',\n labels: {},\n baseline: snapshotFromHoldout(\n 0,\n record.baselineContentHash,\n args.baselineSurface,\n args.baselineOnHoldout,\n ),\n generations: [\n snapshotFromHoldout(1, record.winnerContentHash, args.winnerSurface, args.winnerOnHoldout),\n ],\n gateDecision: args.gate.decision,\n holdoutLift: record.heldOutLift,\n totalCostUsd: args.totalCostUsd,\n totalDurationMs: args.totalDurationMs,\n }\n}\n\n/**\n * Build the provenance record + OTel spans and persist them durably under the\n * run dir (and ship spans to a hosted collector when one is wired). Returns\n * both artifacts so the caller can assert on / re-derive from them.\n *\n * Fail-loud: the durable write throws on storage failure (a swallowed write is\n * exactly the \"emitted but lost\" failure this closes). The hosted span ship is\n * the one best-effort leg — its failure is logged, not thrown, so an offline\n * collector never fails the loop (the durable artifact is the source of truth).\n */\nexport async function emitLoopProvenance<TArtifact, TScenario extends Scenario>(\n args: EmitLoopProvenanceArgs<TArtifact, TScenario>,\n): Promise<EmitLoopProvenanceResult> {\n const record = buildLoopProvenanceRecord(args)\n const spans = loopProvenanceSpans(record)\n\n args.storage.ensureDir(args.runDir)\n const recordPath = provenanceRecordPath(args.runDir)\n const spansPath = provenanceSpansPath(args.runDir)\n args.storage.write(recordPath, JSON.stringify(record, null, 2))\n args.storage.write(spansPath, spans.map((s) => JSON.stringify(s)).join('\\n'))\n\n if (args.hostedClient) {\n // Ship BOTH streams so the run is fully visible in the dashboard: the\n // eval-run event (→ run list + baseline/winner/gate/lift) AND the trace\n // spans (→ per-candidate drill-down). Best-effort: an offline collector is\n // logged, never thrown — the durable artifact above is the source of truth.\n try {\n await args.hostedClient.ingestEvalRun(buildEvalRunEvent(args, record))\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // eslint-disable-next-line no-console -- intentional: hosted ingest is best-effort\n console.warn(`[agent-eval] hosted eval-run ingest failed (continuing): ${msg}`)\n }\n try {\n await args.hostedClient.ingestTraces(spans)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // eslint-disable-next-line no-console -- intentional: hosted span ship is best-effort\n console.warn(`[agent-eval] provenance span ingest failed (continuing): ${msg}`)\n }\n }\n\n return { record, spans, recordPath, spansPath }\n}\n"],"mappings":"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","names":[]}
|
package/dist/contract/index.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { S as Scenario, M as MutableSurface, b as DispatchContext, a as JudgeConfig, I as ImprovementDriver, G as Gate } from '../types-c2R2kfmv.js';
|
|
2
2
|
export { C as CampaignAggregates, c as CampaignArtifactWriter, d as CampaignCellResult, e as CampaignCostMeter, f as CampaignResult, g as CampaignTraceWriter, h as CodeSurface, D as Dispatch, i as GateContext, j as GateDecision, k as GateResult, l as GenerationCandidate, m as GenerationRecord, n as JudgeDimension, J as JudgeScore, o as Mutator, O as OptimizerConfig, p as SessionScript } from '../types-c2R2kfmv.js';
|
|
3
|
-
import {
|
|
4
|
-
export { D as DefaultProductionGateOptions, E as EvolutionaryDriverOptions,
|
|
3
|
+
import { L as LoopProvenanceRecord } from '../provenance-BZUFC1_D.js';
|
|
4
|
+
export { D as DefaultProductionGateOptions, E as EvolutionaryDriverOptions, H as HeldOutGateOptions, R as RunEvalOptions, c as composeGate, d as defaultProductionGate, e as evolutionaryDriver, h as heldOutGate, r as runEval } from '../provenance-BZUFC1_D.js';
|
|
5
|
+
import { C as CampaignStorage, R as RunImprovementLoopResult } from '../run-improvement-loop-BKpM5T4t.js';
|
|
6
|
+
export { G as GepaDriverOptions, a as RunCampaignOptions, b as RunImprovementLoopOptions, f as fsCampaignStorage, g as gepaDriver, i as inMemoryCampaignStorage, r as runCampaign, c as runImprovementLoop } from '../run-improvement-loop-BKpM5T4t.js';
|
|
5
7
|
export { D as DeploymentOutcome, F as FileSystemOutcomeStore, b as FileSystemOutcomeStoreOptions, I as InMemoryOutcomeStore, O as OutcomeStore } from '../outcome-store-D6KWmYvj.js';
|
|
6
|
-
import { a as HostedTenant, I as InsightReport, T as TraceSpanEvent } from '../index-
|
|
7
|
-
export { F as FailureClusterInsight, b as InterRaterInsight, J as JudgeInsight, L as LiftInsight, O as OutcomeCorrelationInsight, R as Recommendation, c as ReleaseSummary, S as ScalarDistribution } from '../index-
|
|
8
|
+
import { a as HostedTenant, I as InsightReport, T as TraceSpanEvent } from '../index-DSEHMwvS.js';
|
|
9
|
+
export { F as FailureClusterInsight, b as InterRaterInsight, J as JudgeInsight, L as LiftInsight, O as OutcomeCorrelationInsight, R as Recommendation, c as ReleaseSummary, S as ScalarDistribution } from '../index-DSEHMwvS.js';
|
|
8
10
|
import { R as RunRecord, b as RunSplitTag } from '../run-record-BgTFzO2r.js';
|
|
9
|
-
import { A as AnalystRegistry } from '../registry-
|
|
11
|
+
import { A as AnalystRegistry } from '../registry-BzAEvqAt.js';
|
|
10
12
|
import { a as DatasetScenario } from '../dataset-B2kL-fSM.js';
|
|
11
|
-
import '../llm-client-DbjLfz-K.js';
|
|
12
|
-
import '../errors-Dwqw-T_m.js';
|
|
13
|
-
import '../raw-provider-sink-C46HDghv.js';
|
|
14
13
|
import '../red-team-DW9Ca_tj.js';
|
|
15
14
|
import '../store-CKUAgsJz.js';
|
|
16
15
|
import '../schema-m0gsnbt3.js';
|
|
16
|
+
import '../llm-client-DbjLfz-K.js';
|
|
17
|
+
import '../errors-Dwqw-T_m.js';
|
|
18
|
+
import '../raw-provider-sink-C46HDghv.js';
|
|
17
19
|
import '../summary-report-ByiOUrHj.js';
|
|
18
20
|
import '../failure-cluster-CL7IVgkJ.js';
|
|
19
21
|
import '../judge-calibration-DilmB3Ml.js';
|
package/dist/contract/index.js
CHANGED
|
@@ -3,27 +3,26 @@ import {
|
|
|
3
3
|
defaultProductionGate,
|
|
4
4
|
emitLoopProvenance,
|
|
5
5
|
evolutionaryDriver,
|
|
6
|
-
gepaDriver,
|
|
7
|
-
heldOutGate,
|
|
8
6
|
runEval,
|
|
9
|
-
runImprovementLoop,
|
|
10
7
|
surfaceContentHash
|
|
11
|
-
} from "../chunk-
|
|
12
|
-
import {
|
|
13
|
-
fsCampaignStorage,
|
|
14
|
-
inMemoryCampaignStorage,
|
|
15
|
-
runCampaign
|
|
16
|
-
} from "../chunk-7TPYV2ER.js";
|
|
8
|
+
} from "../chunk-RDK3P4JE.js";
|
|
17
9
|
import {
|
|
18
10
|
createHostedClient
|
|
19
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-DFS3FEXO.js";
|
|
20
12
|
import {
|
|
21
13
|
checkCanaries
|
|
22
14
|
} from "../chunk-SHTXZ4O2.js";
|
|
23
|
-
import "../chunk-4ODZXQV2.js";
|
|
24
15
|
import {
|
|
16
|
+
gepaDriver,
|
|
17
|
+
heldOutGate,
|
|
18
|
+
runImprovementLoop
|
|
19
|
+
} from "../chunk-Q56RRLEC.js";
|
|
20
|
+
import {
|
|
21
|
+
fsCampaignStorage,
|
|
22
|
+
inMemoryCampaignStorage,
|
|
23
|
+
runCampaign,
|
|
25
24
|
summarizeBackendIntegrity
|
|
26
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-6XQIEUQ2.js";
|
|
27
26
|
import "../chunk-YV7J7X5N.js";
|
|
28
27
|
import {
|
|
29
28
|
FileSystemOutcomeStore,
|