@tangle-network/agent-eval 0.124.0 → 0.126.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 +60 -35
- package/README.md +270 -189
- package/dist/analyst/index.d.ts +15 -145
- package/dist/analyst/index.js +33 -47
- package/dist/analyst/index.js.map +1 -1
- package/dist/benchmarks/index.d.ts +45 -162
- package/dist/benchmarks/index.js +8 -9
- package/dist/campaign/index.d.ts +3655 -5365
- package/dist/campaign/index.js +21 -95
- package/dist/{chunk-R226UZOI.js → chunk-474LBSOX.js} +2 -2
- package/dist/{chunk-W5B3ZGP3.js → chunk-4B7ZZHPX.js} +8 -6
- package/dist/{chunk-W5B3ZGP3.js.map → chunk-4B7ZZHPX.js.map} +1 -1
- package/dist/{chunk-DT7OXY3C.js → chunk-CM4OILD2.js} +535 -846
- package/dist/chunk-CM4OILD2.js.map +1 -0
- package/dist/{chunk-HM6V7F3M.js → chunk-FO7HEH76.js} +3 -3
- package/dist/chunk-IILEIWGW.js +635 -0
- package/dist/chunk-IILEIWGW.js.map +1 -0
- package/dist/{chunk-EQUK3RFS.js → chunk-J5SQWP6Y.js} +8 -5
- package/dist/chunk-J5SQWP6Y.js.map +1 -0
- package/dist/chunk-KO2PZOGP.js +4637 -0
- package/dist/chunk-KO2PZOGP.js.map +1 -0
- package/dist/{chunk-4Y7AAATF.js → chunk-LKKT3IVV.js} +574 -81
- package/dist/chunk-LKKT3IVV.js.map +1 -0
- package/dist/chunk-M7AH34KV.js +155 -0
- package/dist/chunk-M7AH34KV.js.map +1 -0
- package/dist/chunk-NTOV7RU5.js +7152 -0
- package/dist/chunk-NTOV7RU5.js.map +1 -0
- package/dist/{chunk-QFQZ3U3X.js → chunk-OCFJACJU.js} +2 -2
- package/dist/{chunk-GID26AN4.js → chunk-P22LJ3Y2.js} +4 -6
- package/dist/{chunk-GID26AN4.js.map → chunk-P22LJ3Y2.js.map} +1 -1
- package/dist/{chunk-SJT4OBVL.js → chunk-SDPM6554.js} +3 -3
- package/dist/{chunk-D5JZ7UDZ.js → chunk-UCLVDLCH.js} +136 -50
- package/dist/chunk-UCLVDLCH.js.map +1 -0
- package/dist/chunk-UI4YMIN2.js +105 -0
- package/dist/chunk-UI4YMIN2.js.map +1 -0
- package/dist/chunk-VBQ3CRKH.js +291 -0
- package/dist/chunk-VBQ3CRKH.js.map +1 -0
- package/dist/{chunk-JKDNAOF5.js → chunk-W4L6C2XT.js} +2 -2
- package/dist/{chunk-GRCDRKII.js → chunk-WS3NZZQQ.js} +58 -20
- package/dist/chunk-WS3NZZQQ.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/contract/index.d.ts +3221 -3094
- package/dist/contract/index.js +173 -42
- package/dist/contract/index.js.map +1 -1
- package/dist/control.js +2 -3
- package/dist/fuzz.d.ts +14 -1
- package/dist/fuzz.js +1 -1
- package/dist/hosted/index.d.ts +8 -1
- package/dist/index.d.ts +208 -690
- package/dist/index.js +185 -500
- package/dist/index.js.map +1 -1
- package/dist/openapi.json +1 -1
- package/dist/rl.d.ts +5 -100
- package/dist/rl.js +4 -5
- package/dist/rl.js.map +1 -1
- package/dist/rollout/index.d.ts +9 -1
- package/dist/rollout/index.js +6 -6
- package/dist/{run-campaign-I3JXKVAK.js → run-campaign-LVFKZCEU.js} +3 -3
- package/dist/supervisor-run/index.d.ts +156 -4
- package/dist/supervisor-run/index.js +14 -2
- package/dist/traces.js +2 -3
- package/dist/wire/index.d.ts +14 -1
- package/dist/wire/index.js +3 -3
- package/docs/campaign-proposers.md +363 -168
- package/docs/design/loop-taxonomy.md +142 -190
- package/docs/design.md +1 -1
- package/docs/distributed-driver.md +8 -11
- package/docs/feature-guide.md +20 -19
- package/docs/knowledge-readiness.md +2 -5
- package/docs/multi-shot-optimization.md +35 -27
- package/docs/rollout.md +5 -5
- package/package.json +4 -4
- package/dist/chunk-4Y7AAATF.js.map +0 -1
- package/dist/chunk-5PVZVCZB.js +0 -9190
- package/dist/chunk-5PVZVCZB.js.map +0 -1
- package/dist/chunk-A6GT67HT.js +0 -550
- package/dist/chunk-A6GT67HT.js.map +0 -1
- package/dist/chunk-D5JZ7UDZ.js.map +0 -1
- package/dist/chunk-DT7OXY3C.js.map +0 -1
- package/dist/chunk-EQUK3RFS.js.map +0 -1
- package/dist/chunk-GC4ATIKK.js +0 -317
- package/dist/chunk-GC4ATIKK.js.map +0 -1
- package/dist/chunk-GRCDRKII.js.map +0 -1
- package/dist/chunk-LOW3U7JZ.js +0 -328
- package/dist/chunk-LOW3U7JZ.js.map +0 -1
- package/dist/chunk-MGGFVCJ7.js +0 -288
- package/dist/chunk-MGGFVCJ7.js.map +0 -1
- package/dist/chunk-PMITBABE.js +0 -3841
- package/dist/chunk-PMITBABE.js.map +0 -1
- package/dist/chunk-R7ZRE2KV.js +0 -138
- package/dist/chunk-R7ZRE2KV.js.map +0 -1
- /package/dist/{chunk-R226UZOI.js.map → chunk-474LBSOX.js.map} +0 -0
- /package/dist/{chunk-HM6V7F3M.js.map → chunk-FO7HEH76.js.map} +0 -0
- /package/dist/{chunk-QFQZ3U3X.js.map → chunk-OCFJACJU.js.map} +0 -0
- /package/dist/{chunk-SJT4OBVL.js.map → chunk-SDPM6554.js.map} +0 -0
- /package/dist/{chunk-JKDNAOF5.js.map → chunk-W4L6C2XT.js.map} +0 -0
- /package/dist/{run-campaign-I3JXKVAK.js.map → run-campaign-LVFKZCEU.js.map} +0 -0
package/dist/chunk-MGGFVCJ7.js
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ROLLOUT_SCHEMA
|
|
3
|
-
} from "./chunk-MAX3TN3C.js";
|
|
4
|
-
import {
|
|
5
|
-
buildTrajectory
|
|
6
|
-
} from "./chunk-RZTMDUO7.js";
|
|
7
|
-
|
|
8
|
-
// src/rollout/mint.ts
|
|
9
|
-
var asText = (v, scrub) => {
|
|
10
|
-
const s = typeof v === "string" ? v : JSON.stringify(v);
|
|
11
|
-
return scrub(s ?? "");
|
|
12
|
-
};
|
|
13
|
-
function projectStep(span, scrub) {
|
|
14
|
-
const base = {
|
|
15
|
-
kind: span.kind,
|
|
16
|
-
name: scrub(span.name),
|
|
17
|
-
status: span.status,
|
|
18
|
-
durationMs: span.endedAt !== void 0 ? span.endedAt - span.startedAt : void 0
|
|
19
|
-
};
|
|
20
|
-
if (span.kind === "llm") {
|
|
21
|
-
const llm = span;
|
|
22
|
-
const last = llm.messages[llm.messages.length - 1];
|
|
23
|
-
if (last) base.input = scrub(last.content);
|
|
24
|
-
if (llm.output !== void 0) base.output = scrub(llm.output);
|
|
25
|
-
} else if (span.kind === "tool") {
|
|
26
|
-
const tool = span;
|
|
27
|
-
base.input = asText(tool.args, scrub);
|
|
28
|
-
if (tool.result !== void 0) base.output = asText(tool.result, scrub);
|
|
29
|
-
}
|
|
30
|
-
return base;
|
|
31
|
-
}
|
|
32
|
-
function finalConversation(spans, scrub) {
|
|
33
|
-
const llms = spans.filter((s) => s.kind === "llm");
|
|
34
|
-
const last = llms[llms.length - 1];
|
|
35
|
-
if (!last) return [];
|
|
36
|
-
const messages = last.messages.map((m) => ({
|
|
37
|
-
role: m.role,
|
|
38
|
-
content: scrub(m.content)
|
|
39
|
-
}));
|
|
40
|
-
if (last.output !== void 0 && last.output !== "") {
|
|
41
|
-
messages.push({ role: "assistant", content: scrub(last.output) });
|
|
42
|
-
}
|
|
43
|
-
return messages;
|
|
44
|
-
}
|
|
45
|
-
function rolloutReward(record) {
|
|
46
|
-
const gated = record.outcome.realness?.gated === true;
|
|
47
|
-
const raw = record.outcome.holdoutScore ?? record.outcome.searchScore ?? 0;
|
|
48
|
-
return { reward: gated ? 0 : raw, gated };
|
|
49
|
-
}
|
|
50
|
-
function rewardSource(record) {
|
|
51
|
-
if (record.outcome.holdoutScore !== void 0) return "run-record/holdout-score";
|
|
52
|
-
if (record.outcome.searchScore !== void 0) return "run-record/search-score";
|
|
53
|
-
return "run-record/unscored";
|
|
54
|
-
}
|
|
55
|
-
var SPLIT_FROM_TAG = {
|
|
56
|
-
search: "search",
|
|
57
|
-
dev: "dev",
|
|
58
|
-
holdout: "holdout"
|
|
59
|
-
};
|
|
60
|
-
function mintLine(record, steps, messages, options, capturedAt, gap) {
|
|
61
|
-
const { reward, gated } = rolloutReward(record);
|
|
62
|
-
const uncaptured = record.costProvenance?.kind === "uncaptured";
|
|
63
|
-
return {
|
|
64
|
-
schema: ROLLOUT_SCHEMA,
|
|
65
|
-
rollout_id: record.runId,
|
|
66
|
-
parent_rollout_id: null,
|
|
67
|
-
run_id: record.runId,
|
|
68
|
-
experiment_id: record.experimentId,
|
|
69
|
-
candidate_id: record.candidateId,
|
|
70
|
-
generation: null,
|
|
71
|
-
candidate_index: null,
|
|
72
|
-
role: options.role ?? "agent",
|
|
73
|
-
task: {
|
|
74
|
-
suite: options.suite ?? record.experimentId,
|
|
75
|
-
instance_id: record.scenarioId ?? record.experimentId,
|
|
76
|
-
split: SPLIT_FROM_TAG[record.splitTag],
|
|
77
|
-
seed: record.seed,
|
|
78
|
-
rep: 0
|
|
79
|
-
},
|
|
80
|
-
policy: {
|
|
81
|
-
harness: null,
|
|
82
|
-
harness_version: null,
|
|
83
|
-
model: record.model,
|
|
84
|
-
provider: null,
|
|
85
|
-
profile_commit: record.commitSha,
|
|
86
|
-
prompt_hash: record.promptHash,
|
|
87
|
-
config_hash: record.configHash,
|
|
88
|
-
agent_profile_cell_id: record.agentProfile?.cellId ?? null,
|
|
89
|
-
sampling: null
|
|
90
|
-
},
|
|
91
|
-
messages,
|
|
92
|
-
tool_defs: [],
|
|
93
|
-
...steps.length > 0 ? { steps } : {},
|
|
94
|
-
outcome: {
|
|
95
|
-
reward,
|
|
96
|
-
reward_source: rewardSource(record),
|
|
97
|
-
verdict: null,
|
|
98
|
-
metrics: { ...record.outcome.raw },
|
|
99
|
-
is_completed: true,
|
|
100
|
-
is_truncated: false,
|
|
101
|
-
error: null,
|
|
102
|
-
realness_gated: gated
|
|
103
|
-
},
|
|
104
|
-
cost: {
|
|
105
|
-
usd: uncaptured ? null : record.costUsd,
|
|
106
|
-
tokens_in: record.tokenUsage.input,
|
|
107
|
-
tokens_out: record.tokenUsage.output,
|
|
108
|
-
tokens_reasoning: record.tokenUsage.reasoning ?? null,
|
|
109
|
-
cache_read: record.tokenUsage.cached ?? null,
|
|
110
|
-
cache_write: record.tokenUsage.cacheWrite ?? null,
|
|
111
|
-
wall_s: Math.round(record.wallMs / 1e3)
|
|
112
|
-
},
|
|
113
|
-
artifacts: { patch_path: null, run_dir: null, transcript_ref: null },
|
|
114
|
-
provenance: {
|
|
115
|
-
captured_at: capturedAt,
|
|
116
|
-
capture: "mint",
|
|
117
|
-
...gap !== void 0 ? { gap } : {}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
async function mintRolloutRows(records, store, options = {}) {
|
|
122
|
-
const scrub = options.scrub ?? ((t) => t);
|
|
123
|
-
const capturedAt = (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
124
|
-
const rows = [];
|
|
125
|
-
const missingTraces = [];
|
|
126
|
-
for (const record of records) {
|
|
127
|
-
const trajectory = await buildTrajectory(store, record.runId);
|
|
128
|
-
if (trajectory.steps.length === 0) {
|
|
129
|
-
missingTraces.push(record.runId);
|
|
130
|
-
rows.push(
|
|
131
|
-
mintLine(record, [], [], options, capturedAt, "no trace spans recorded for this runId")
|
|
132
|
-
);
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
let steps = trajectory.steps.map((s) => projectStep(s.span, scrub));
|
|
136
|
-
if (options.maxSteps !== void 0 && steps.length > options.maxSteps) {
|
|
137
|
-
const head = Math.ceil(options.maxSteps / 2);
|
|
138
|
-
const tail = options.maxSteps - head;
|
|
139
|
-
steps = [...steps.slice(0, head), ...steps.slice(steps.length - tail)];
|
|
140
|
-
}
|
|
141
|
-
const conversation = finalConversation(
|
|
142
|
-
trajectory.steps.map((s) => s.span),
|
|
143
|
-
scrub
|
|
144
|
-
);
|
|
145
|
-
const gap = conversation.length === 0 ? "trace has no llm spans \u2014 no conversation to inline" : void 0;
|
|
146
|
-
rows.push(mintLine(record, steps, conversation, options, capturedAt, gap));
|
|
147
|
-
}
|
|
148
|
-
return { rows, missingTraces };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// src/rollout/readers/claude-jsonl.ts
|
|
152
|
-
import { readdir, readFile } from "fs/promises";
|
|
153
|
-
import { homedir } from "os";
|
|
154
|
-
import { join } from "path";
|
|
155
|
-
var DEFAULT_CLAUDE_PROJECTS_DIR = join(homedir(), ".claude", "projects");
|
|
156
|
-
function claudeProjectSlug(cwd) {
|
|
157
|
-
return cwd.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
158
|
-
}
|
|
159
|
-
async function findClaudeTranscripts(cwd, projectsDir = DEFAULT_CLAUDE_PROJECTS_DIR) {
|
|
160
|
-
const dir = join(projectsDir, claudeProjectSlug(cwd));
|
|
161
|
-
const names = await readdir(dir).catch(() => []);
|
|
162
|
-
return names.filter((n) => n.endsWith(".jsonl")).sort().map((n) => ({ sessionId: n.replace(/\.jsonl$/, ""), path: join(dir, n) }));
|
|
163
|
-
}
|
|
164
|
-
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
165
|
-
function blockText(content) {
|
|
166
|
-
if (typeof content === "string") return content;
|
|
167
|
-
if (!Array.isArray(content)) return "";
|
|
168
|
-
return content.filter(
|
|
169
|
-
(b) => isRecord(b) && b.type === "text" && typeof b.text === "string"
|
|
170
|
-
).map((b) => b.text).join("\n");
|
|
171
|
-
}
|
|
172
|
-
async function readClaudeTranscript(path) {
|
|
173
|
-
const raw = await readFile(path, "utf8");
|
|
174
|
-
const messages = [];
|
|
175
|
-
const usage = { tokensIn: 0, tokensOut: 0, cacheRead: 0, cacheWrite: 0 };
|
|
176
|
-
let startedAt = null;
|
|
177
|
-
let endedAt = null;
|
|
178
|
-
let model = null;
|
|
179
|
-
let lastAssistantApiId = null;
|
|
180
|
-
let lastAssistantIndex = -1;
|
|
181
|
-
for (const line of raw.split("\n")) {
|
|
182
|
-
if (!line.trim()) continue;
|
|
183
|
-
let entry;
|
|
184
|
-
try {
|
|
185
|
-
const parsed = JSON.parse(line);
|
|
186
|
-
if (!isRecord(parsed)) continue;
|
|
187
|
-
entry = parsed;
|
|
188
|
-
} catch {
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
if (entry.type !== "user" && entry.type !== "assistant") continue;
|
|
192
|
-
if (entry.isSidechain === true) continue;
|
|
193
|
-
const message = entry.message;
|
|
194
|
-
if (!isRecord(message)) continue;
|
|
195
|
-
if (typeof entry.timestamp === "string") {
|
|
196
|
-
if (startedAt === null) startedAt = entry.timestamp;
|
|
197
|
-
endedAt = entry.timestamp;
|
|
198
|
-
}
|
|
199
|
-
if (entry.type === "user") {
|
|
200
|
-
lastAssistantApiId = null;
|
|
201
|
-
lastAssistantIndex = -1;
|
|
202
|
-
const content2 = message.content;
|
|
203
|
-
if (typeof content2 === "string") {
|
|
204
|
-
messages.push({ role: "user", content: content2 });
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
if (!Array.isArray(content2)) continue;
|
|
208
|
-
let userText = "";
|
|
209
|
-
for (const block of content2) {
|
|
210
|
-
if (!isRecord(block)) continue;
|
|
211
|
-
if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
|
|
212
|
-
messages.push({
|
|
213
|
-
role: "tool",
|
|
214
|
-
tool_call_id: block.tool_use_id,
|
|
215
|
-
content: blockText(block.content) || (typeof block.content === "string" ? block.content : "")
|
|
216
|
-
});
|
|
217
|
-
} else if (block.type === "text" && typeof block.text === "string") {
|
|
218
|
-
userText += (userText.length > 0 ? "\n" : "") + block.text;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (userText.length > 0) messages.push({ role: "user", content: userText });
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
if (typeof message.model === "string") model = message.model;
|
|
225
|
-
const apiId = typeof message.id === "string" ? message.id : null;
|
|
226
|
-
const continuesTurn = apiId !== null && apiId === lastAssistantApiId && lastAssistantIndex >= 0;
|
|
227
|
-
const msgUsage = message.usage;
|
|
228
|
-
if (isRecord(msgUsage) && !continuesTurn) {
|
|
229
|
-
usage.tokensIn += typeof msgUsage.input_tokens === "number" ? msgUsage.input_tokens : 0;
|
|
230
|
-
usage.tokensOut += typeof msgUsage.output_tokens === "number" ? msgUsage.output_tokens : 0;
|
|
231
|
-
usage.cacheRead += typeof msgUsage.cache_read_input_tokens === "number" ? msgUsage.cache_read_input_tokens : 0;
|
|
232
|
-
usage.cacheWrite += typeof msgUsage.cache_creation_input_tokens === "number" ? msgUsage.cache_creation_input_tokens : 0;
|
|
233
|
-
}
|
|
234
|
-
const content = message.content;
|
|
235
|
-
if (!Array.isArray(content)) continue;
|
|
236
|
-
let reasoning = "";
|
|
237
|
-
let text = "";
|
|
238
|
-
const toolCalls = [];
|
|
239
|
-
for (const block of content) {
|
|
240
|
-
if (!isRecord(block)) continue;
|
|
241
|
-
if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking.length > 0) {
|
|
242
|
-
reasoning += (reasoning.length > 0 ? "\n" : "") + block.thinking;
|
|
243
|
-
} else if (block.type === "text" && typeof block.text === "string") {
|
|
244
|
-
text += (text.length > 0 ? "\n" : "") + block.text;
|
|
245
|
-
} else if (block.type === "tool_use" && typeof block.id === "string") {
|
|
246
|
-
toolCalls.push({
|
|
247
|
-
id: block.id,
|
|
248
|
-
type: "function",
|
|
249
|
-
function: {
|
|
250
|
-
name: typeof block.name === "string" ? block.name : "unknown",
|
|
251
|
-
arguments: JSON.stringify(block.input ?? {})
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (reasoning.length === 0 && text.length === 0 && toolCalls.length === 0) continue;
|
|
257
|
-
if (continuesTurn) {
|
|
258
|
-
const prev = messages[lastAssistantIndex];
|
|
259
|
-
if (text.length > 0) prev.content = prev.content === null ? text : `${prev.content}
|
|
260
|
-
${text}`;
|
|
261
|
-
if (reasoning.length > 0) {
|
|
262
|
-
prev.reasoning_content = prev.reasoning_content === void 0 ? reasoning : `${prev.reasoning_content}
|
|
263
|
-
${reasoning}`;
|
|
264
|
-
}
|
|
265
|
-
if (toolCalls.length > 0) prev.tool_calls = [...prev.tool_calls ?? [], ...toolCalls];
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
messages.push({
|
|
269
|
-
role: "assistant",
|
|
270
|
-
content: text.length > 0 ? text : null,
|
|
271
|
-
...reasoning.length > 0 ? { reasoning_content: reasoning } : {},
|
|
272
|
-
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
273
|
-
});
|
|
274
|
-
lastAssistantApiId = apiId;
|
|
275
|
-
lastAssistantIndex = messages.length - 1;
|
|
276
|
-
}
|
|
277
|
-
return { messages, usage, startedAt, endedAt, model };
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export {
|
|
281
|
-
rolloutReward,
|
|
282
|
-
mintRolloutRows,
|
|
283
|
-
DEFAULT_CLAUDE_PROJECTS_DIR,
|
|
284
|
-
claudeProjectSlug,
|
|
285
|
-
findClaudeTranscripts,
|
|
286
|
-
readClaudeTranscript
|
|
287
|
-
};
|
|
288
|
-
//# sourceMappingURL=chunk-MGGFVCJ7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rollout/mint.ts","../src/rollout/readers/claude-jsonl.ts"],"sourcesContent":["/**\n * Rollout minting — `tangle.rollout.v1` lines joined from the records the\n * substrate ALREADY keeps. There is no separate rollout store: a rollout\n * is the JOIN of a RunRecord (identity, provenance, cost, outcome) with\n * its trace (spans share `runId`), projected into the canonical line.\n *\n * Composition, not duplication:\n * - identity/provenance → `RunRecord` (candidateId, splitTag, agentProfile, hashes)\n * - step structure → `buildTrajectory` over the shared TraceStore\n * - preference-pair export → `feedbackTrajectoryToOptimizerRow` (feedback-trajectory.ts)\n * - PRM / reward-model → `reward-model-export.ts`\n *\n * Anti-Goodhart invariant: a run whose `outcome.realness.gated` is true\n * is never exported with a positive reward — the gate travels into the\n * training data (`reward` forced to 0, `realness_gated: true`), so a\n * fine-tune cannot learn from gamed successes.\n *\n * Records without spans become labeled GAP LINES (messages: [],\n * provenance.gap) — present in the output AND surfaced in\n * `missingTraces`; a capture gap is a finding, never a silent omission.\n */\n\nimport type { RunRecord } from '../run-record'\nimport type { LlmSpan, Message, Span, ToolSpan } from '../trace/schema'\nimport type { TraceStore } from '../trace/store'\nimport { buildTrajectory } from '../trajectory'\nimport {\n type ChatMessage,\n ROLLOUT_SCHEMA,\n type RolloutLine,\n type RolloutRole,\n type RolloutSplit,\n type RolloutStep,\n} from './schema'\n\n/** Redactor applied to every exported string (secrets, PII). Identity by default. */\nexport type RolloutScrubber = (text: string) => string\n\nexport interface MintRolloutOptions {\n scrub?: RolloutScrubber\n /** Cap steps per line (longest runs first drop middle steps). Default: no cap. */\n maxSteps?: number\n /** Role recorded on every minted line. Default 'agent' (a solo eval run). */\n role?: RolloutRole\n /** Task suite label. Default: the record's `experimentId`. */\n suite?: string\n /** Injected clock for deterministic output. */\n now?: () => Date\n}\n\nexport interface MintRolloutResult {\n rows: RolloutLine[]\n /** runIds that had a RunRecord but no spans — emitted as gap lines AND listed here. */\n missingTraces: string[]\n}\n\nconst asText = (v: unknown, scrub: RolloutScrubber): string => {\n const s = typeof v === 'string' ? v : JSON.stringify(v)\n return scrub(s ?? '')\n}\n\nfunction projectStep(span: Span, scrub: RolloutScrubber): RolloutStep {\n const base: RolloutStep = {\n kind: span.kind,\n name: scrub(span.name),\n status: span.status,\n durationMs: span.endedAt !== undefined ? span.endedAt - span.startedAt : undefined,\n }\n if (span.kind === 'llm') {\n const llm = span as LlmSpan\n const last = llm.messages[llm.messages.length - 1]\n if (last) base.input = scrub(last.content)\n if (llm.output !== undefined) base.output = scrub(llm.output)\n } else if (span.kind === 'tool') {\n const tool = span as ToolSpan\n base.input = asText(tool.args, scrub)\n if (tool.result !== undefined) base.output = asText(tool.result, scrub)\n }\n return base\n}\n\n/** The final llm span's history + output is the completed conversation. */\nfunction finalConversation(spans: Span[], scrub: RolloutScrubber): ChatMessage[] {\n const llms = spans.filter((s): s is LlmSpan => s.kind === 'llm')\n const last = llms[llms.length - 1]\n if (!last) return []\n const messages: ChatMessage[] = last.messages.map((m: Message) => ({\n role: m.role,\n content: scrub(m.content),\n }))\n if (last.output !== undefined && last.output !== '') {\n messages.push({ role: 'assistant', content: scrub(last.output) })\n }\n return messages\n}\n\nexport function rolloutReward(record: RunRecord): { reward: number; gated: boolean } {\n const gated = record.outcome.realness?.gated === true\n const raw = record.outcome.holdoutScore ?? record.outcome.searchScore ?? 0\n return { reward: gated ? 0 : raw, gated }\n}\n\nfunction rewardSource(record: RunRecord): string {\n if (record.outcome.holdoutScore !== undefined) return 'run-record/holdout-score'\n if (record.outcome.searchScore !== undefined) return 'run-record/search-score'\n return 'run-record/unscored'\n}\n\nconst SPLIT_FROM_TAG: Record<RunRecord['splitTag'], RolloutSplit> = {\n search: 'search',\n dev: 'dev',\n holdout: 'holdout',\n}\n\nfunction mintLine(\n record: RunRecord,\n steps: RolloutStep[],\n messages: ChatMessage[],\n options: MintRolloutOptions,\n capturedAt: string,\n gap?: string,\n): RolloutLine {\n const { reward, gated } = rolloutReward(record)\n const uncaptured = record.costProvenance?.kind === 'uncaptured'\n return {\n schema: ROLLOUT_SCHEMA,\n rollout_id: record.runId,\n parent_rollout_id: null,\n run_id: record.runId,\n experiment_id: record.experimentId,\n candidate_id: record.candidateId,\n generation: null,\n candidate_index: null,\n role: options.role ?? 'agent',\n task: {\n suite: options.suite ?? record.experimentId,\n instance_id: record.scenarioId ?? record.experimentId,\n split: SPLIT_FROM_TAG[record.splitTag],\n seed: record.seed,\n rep: 0,\n },\n policy: {\n harness: null,\n harness_version: null,\n model: record.model,\n provider: null,\n profile_commit: record.commitSha,\n prompt_hash: record.promptHash,\n config_hash: record.configHash,\n agent_profile_cell_id: record.agentProfile?.cellId ?? null,\n sampling: null,\n },\n messages,\n tool_defs: [],\n ...(steps.length > 0 ? { steps } : {}),\n outcome: {\n reward,\n reward_source: rewardSource(record),\n verdict: null,\n metrics: { ...record.outcome.raw },\n is_completed: true,\n is_truncated: false,\n error: null,\n realness_gated: gated,\n },\n cost: {\n usd: uncaptured ? null : record.costUsd,\n tokens_in: record.tokenUsage.input,\n tokens_out: record.tokenUsage.output,\n tokens_reasoning: record.tokenUsage.reasoning ?? null,\n cache_read: record.tokenUsage.cached ?? null,\n cache_write: record.tokenUsage.cacheWrite ?? null,\n wall_s: Math.round(record.wallMs / 1000),\n },\n artifacts: { patch_path: null, run_dir: null, transcript_ref: null },\n provenance: {\n captured_at: capturedAt,\n capture: 'mint',\n ...(gap !== undefined ? { gap } : {}),\n },\n }\n}\n\n/**\n * Join RunRecords with their traces into canonical rollout lines. Records\n * without spans are emitted as labeled gap lines and reported in\n * `missingTraces` — a capture gap is a finding, not a silent omission.\n */\nexport async function mintRolloutRows(\n records: RunRecord[],\n store: TraceStore,\n options: MintRolloutOptions = {},\n): Promise<MintRolloutResult> {\n const scrub = options.scrub ?? ((t) => t)\n const capturedAt = (options.now?.() ?? new Date()).toISOString()\n const rows: RolloutLine[] = []\n const missingTraces: string[] = []\n for (const record of records) {\n const trajectory = await buildTrajectory(store, record.runId)\n if (trajectory.steps.length === 0) {\n missingTraces.push(record.runId)\n rows.push(\n mintLine(record, [], [], options, capturedAt, 'no trace spans recorded for this runId'),\n )\n continue\n }\n let steps = trajectory.steps.map((s) => projectStep(s.span, scrub))\n if (options.maxSteps !== undefined && steps.length > options.maxSteps) {\n // Keep the head and tail — the middle of a long run is the least\n // informative for outcome attribution.\n const head = Math.ceil(options.maxSteps / 2)\n const tail = options.maxSteps - head\n steps = [...steps.slice(0, head), ...steps.slice(steps.length - tail)]\n }\n const conversation = finalConversation(\n trajectory.steps.map((s) => s.span),\n scrub,\n )\n const gap =\n conversation.length === 0 ? 'trace has no llm spans — no conversation to inline' : undefined\n rows.push(mintLine(record, steps, conversation, options, capturedAt, gap))\n }\n return { rows, missingTraces }\n}\n","/**\n * Backfill reader over Claude Code project transcripts\n * (~/.claude/projects/<cwd-slug>/<sessionId>.jsonl) → canonical\n * chat-with-tools messages plus per-session token usage.\n *\n * Transcript lines consumed: type:\"user\" (string content or content blocks —\n * text + tool_result) and type:\"assistant\" (content blocks — thinking, text,\n * tool_use; message.usage carries tokens). Sidechain lines (isSidechain=true,\n * subagent threads) are separate invocations and are excluded from the main\n * transcript. Everything else (queue-operation, attachment, last-prompt…) is\n * transport metadata, not conversation.\n */\n\nimport { readdir, readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport type { ChatMessage, ChatToolCall } from '../schema'\n\nexport const DEFAULT_CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects')\n\n/** Claude Code's project-directory slug for a working directory. */\nexport function claudeProjectSlug(cwd: string): string {\n return cwd.replace(/[^a-zA-Z0-9-]/g, '-')\n}\n\nexport interface ClaudeTranscriptRef {\n sessionId: string\n path: string\n}\n\n/** Transcript files recorded for sessions launched from `cwd`. */\nexport async function findClaudeTranscripts(\n cwd: string,\n projectsDir: string = DEFAULT_CLAUDE_PROJECTS_DIR,\n): Promise<ClaudeTranscriptRef[]> {\n const dir = join(projectsDir, claudeProjectSlug(cwd))\n const names = await readdir(dir).catch(() => [])\n return names\n .filter((n) => n.endsWith('.jsonl'))\n .sort()\n .map((n) => ({ sessionId: n.replace(/\\.jsonl$/, ''), path: join(dir, n) }))\n}\n\nexport interface ClaudeUsageTotals {\n tokensIn: number\n tokensOut: number\n cacheRead: number\n cacheWrite: number\n}\n\nexport interface ClaudeTranscript {\n messages: ChatMessage[]\n usage: ClaudeUsageTotals\n /** Timestamp of the first conversation line; null = empty transcript. */\n startedAt: string | null\n endedAt: string | null\n model: string | null\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v)\n\nfunction blockText(content: unknown): string {\n if (typeof content === 'string') return content\n if (!Array.isArray(content)) return ''\n return content\n .filter(\n (b): b is Record<string, unknown> =>\n isRecord(b) && b.type === 'text' && typeof b.text === 'string',\n )\n .map((b) => b.text as string)\n .join('\\n')\n}\n\n/** Parse one transcript jsonl into canonical messages + usage totals. */\nexport async function readClaudeTranscript(path: string): Promise<ClaudeTranscript> {\n const raw = await readFile(path, 'utf8')\n const messages: ChatMessage[] = []\n const usage: ClaudeUsageTotals = { tokensIn: 0, tokensOut: 0, cacheRead: 0, cacheWrite: 0 }\n let startedAt: string | null = null\n let endedAt: string | null = null\n let model: string | null = null\n // Claude Code writes one jsonl line PER CONTENT BLOCK of an API message,\n // repeating message.id and usage on each — merge blocks into one canonical\n // assistant turn and count usage once per API message id.\n let lastAssistantApiId: string | null = null\n let lastAssistantIndex = -1\n\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue\n let entry: Record<string, unknown>\n try {\n const parsed: unknown = JSON.parse(line)\n if (!isRecord(parsed)) continue\n entry = parsed\n } catch {\n continue\n }\n if (entry.type !== 'user' && entry.type !== 'assistant') continue\n if (entry.isSidechain === true) continue\n const message = entry.message\n if (!isRecord(message)) continue\n if (typeof entry.timestamp === 'string') {\n if (startedAt === null) startedAt = entry.timestamp\n endedAt = entry.timestamp\n }\n\n if (entry.type === 'user') {\n lastAssistantApiId = null\n lastAssistantIndex = -1\n const content = message.content\n if (typeof content === 'string') {\n messages.push({ role: 'user', content })\n continue\n }\n if (!Array.isArray(content)) continue\n // A user line may interleave tool_result blocks (answers to the prior\n // assistant tool_use) with plain text; preserve order.\n let userText = ''\n for (const block of content) {\n if (!isRecord(block)) continue\n if (block.type === 'tool_result' && typeof block.tool_use_id === 'string') {\n messages.push({\n role: 'tool',\n tool_call_id: block.tool_use_id,\n content:\n blockText(block.content) || (typeof block.content === 'string' ? block.content : ''),\n })\n } else if (block.type === 'text' && typeof block.text === 'string') {\n userText += (userText.length > 0 ? '\\n' : '') + block.text\n }\n }\n if (userText.length > 0) messages.push({ role: 'user', content: userText })\n continue\n }\n\n // assistant\n if (typeof message.model === 'string') model = message.model\n const apiId = typeof message.id === 'string' ? message.id : null\n const continuesTurn = apiId !== null && apiId === lastAssistantApiId && lastAssistantIndex >= 0\n const msgUsage = message.usage\n if (isRecord(msgUsage) && !continuesTurn) {\n usage.tokensIn += typeof msgUsage.input_tokens === 'number' ? msgUsage.input_tokens : 0\n usage.tokensOut += typeof msgUsage.output_tokens === 'number' ? msgUsage.output_tokens : 0\n usage.cacheRead +=\n typeof msgUsage.cache_read_input_tokens === 'number' ? msgUsage.cache_read_input_tokens : 0\n usage.cacheWrite +=\n typeof msgUsage.cache_creation_input_tokens === 'number'\n ? msgUsage.cache_creation_input_tokens\n : 0\n }\n const content = message.content\n if (!Array.isArray(content)) continue\n let reasoning = ''\n let text = ''\n const toolCalls: ChatToolCall[] = []\n for (const block of content) {\n if (!isRecord(block)) continue\n if (\n block.type === 'thinking' &&\n typeof block.thinking === 'string' &&\n block.thinking.length > 0\n ) {\n reasoning += (reasoning.length > 0 ? '\\n' : '') + block.thinking\n } else if (block.type === 'text' && typeof block.text === 'string') {\n text += (text.length > 0 ? '\\n' : '') + block.text\n } else if (block.type === 'tool_use' && typeof block.id === 'string') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: {\n name: typeof block.name === 'string' ? block.name : 'unknown',\n arguments: JSON.stringify(block.input ?? {}),\n },\n })\n }\n }\n if (reasoning.length === 0 && text.length === 0 && toolCalls.length === 0) continue\n if (continuesTurn) {\n const prev = messages[lastAssistantIndex]!\n if (text.length > 0) prev.content = prev.content === null ? text : `${prev.content}\\n${text}`\n if (reasoning.length > 0) {\n prev.reasoning_content =\n prev.reasoning_content === undefined\n ? reasoning\n : `${prev.reasoning_content}\\n${reasoning}`\n }\n if (toolCalls.length > 0) prev.tool_calls = [...(prev.tool_calls ?? []), ...toolCalls]\n continue\n }\n messages.push({\n role: 'assistant',\n content: text.length > 0 ? text : null,\n ...(reasoning.length > 0 ? { reasoning_content: reasoning } : {}),\n ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),\n })\n lastAssistantApiId = apiId\n lastAssistantIndex = messages.length - 1\n }\n\n return { messages, usage, startedAt, endedAt, model }\n}\n"],"mappings":"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","names":["content"]}
|