agent-hitch 0.2.2 → 0.2.4
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/dist/src/backends/harbor/backend.js +91 -36
- package/dist/src/backends/harbor/backend.js.map +1 -1
- package/dist/src/backends/harbor/dataset-config.js +36 -0
- package/dist/src/backends/harbor/dataset-config.js.map +1 -0
- package/dist/src/cli/commands/eval.js +39 -3
- package/dist/src/cli/commands/eval.js.map +1 -1
- package/dist/src/cli/output.js +2 -1
- package/dist/src/cli/output.js.map +1 -1
- package/dist/src/evals/index.js +4 -2
- package/dist/src/evals/index.js.map +1 -1
- package/dist/src/evals/progress.js +195 -0
- package/dist/src/evals/progress.js.map +1 -0
- package/dist/src/evals/request.js +37 -1
- package/dist/src/evals/request.js.map +1 -1
- package/dist/src/evals/rerun.js +398 -0
- package/dist/src/evals/rerun.js.map +1 -0
- package/dist/src/evals/service.js +101 -6
- package/dist/src/evals/service.js.map +1 -1
- package/dist/src/evals/trial-import.js +113 -59
- package/dist/src/evals/trial-import.js.map +1 -1
- package/docs/schemas/eval-progress.schema.json +61 -0
- package/integrations/harbor/hitch_harbor_agent.py +363 -36
- package/package.json +1 -1
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { loadPreparedArtifact, preparedArtifactDirectory } from "../artifacts/index.js";
|
|
4
|
+
import { runHarborBackend, validateLocalGitTransportManifest, verifyLocalGitTransport, } from "../backends/index.js";
|
|
5
|
+
import { useControllerRuntimeById } from "../controller-runtime/index.js";
|
|
6
|
+
import { HitchError, SCHEMA_VERSION, atomicWriteJSON, ensureDir, invalidInput, readJSON, statePaths, withFileLock } from "../foundation/index.js";
|
|
7
|
+
import { evalTrialKey, readEvalProgress, replaceInvalidEvalProgressTrial, writeEvalProgress } from "./progress.js";
|
|
8
|
+
import { validateEvalId, validateEvalRequest } from "./request.js";
|
|
9
|
+
import { summarizeTrialRefs } from "./service.js";
|
|
10
|
+
import { importEvalTrialRun, importEvalTrialRuns, TrialBundlePendingError, validateEvalTrialReferences } from "./trial-import.js";
|
|
11
|
+
export async function rerunEval(options) {
|
|
12
|
+
if (!options.root)
|
|
13
|
+
throw invalidInput("a Hitch state root is required for eval rerun");
|
|
14
|
+
const evalId = validateEvalId(options.evalId);
|
|
15
|
+
const evalDirectory = path.join(statePaths(options.root).evals, evalId);
|
|
16
|
+
return withFileLock(path.join(evalDirectory, "reruns"), "active", () => rerunEvalLocked({ ...options, evalId, evalDirectory }), { timeoutCode: "eval_rerun_active", timeoutExitCode: 2, ...(options.signal ? { signal: options.signal } : {}) });
|
|
17
|
+
}
|
|
18
|
+
async function rerunEvalLocked(options) {
|
|
19
|
+
const startedAt = new Date().toISOString();
|
|
20
|
+
const rerunId = `rerun_${randomUUID().replaceAll("-", "")}`;
|
|
21
|
+
const rerunDirectory = await ensureDir(path.join(options.evalDirectory, "reruns", rerunId));
|
|
22
|
+
const statePath = path.join(rerunDirectory, "state.json");
|
|
23
|
+
const requestValue = await readJSON(path.join(options.evalDirectory, "request.json"), null);
|
|
24
|
+
if (requestValue === null)
|
|
25
|
+
throw new HitchError(`eval not found: ${options.evalId}`, { code: "eval_not_found", exitCode: 3 });
|
|
26
|
+
const request = await loadPersistedRequest(requestValue);
|
|
27
|
+
const plan = parseRerunPlan(await readJSON(path.join(options.evalDirectory, "plan.json")), options.evalId, request);
|
|
28
|
+
const initialProgress = await readEvalProgress(options.evalDirectory);
|
|
29
|
+
if (initialProgress === null)
|
|
30
|
+
throw unavailable("eval has no task-level progress");
|
|
31
|
+
let progress = initialProgress;
|
|
32
|
+
validateProgressPlan(progress, plan, request, options.evalId);
|
|
33
|
+
const previousResult = await readJSON(path.join(options.evalDirectory, "result.json"), null);
|
|
34
|
+
if (previousResult?.status === "cancelled")
|
|
35
|
+
throw new HitchError("cancelled eval cannot be rerun", { code: "eval_rerun_cancelled", exitCode: 2 });
|
|
36
|
+
const selectedTasks = selectRerunTasks(plan.tasks, progress, options.selector);
|
|
37
|
+
await atomicWriteJSON(path.join(rerunDirectory, "request.json"), {
|
|
38
|
+
schema_version: SCHEMA_VERSION,
|
|
39
|
+
rerun_id: rerunId,
|
|
40
|
+
eval_id: options.evalId,
|
|
41
|
+
mode: options.selector.mode,
|
|
42
|
+
tasks: selectedTasks,
|
|
43
|
+
base_generation: progress.generation,
|
|
44
|
+
created_at: startedAt,
|
|
45
|
+
});
|
|
46
|
+
await writeRerunState(statePath, {
|
|
47
|
+
rerunId,
|
|
48
|
+
evalId: options.evalId,
|
|
49
|
+
status: "running",
|
|
50
|
+
tasks: selectedTasks,
|
|
51
|
+
repairedTasks: [],
|
|
52
|
+
startedAt,
|
|
53
|
+
});
|
|
54
|
+
const repaired = new Set();
|
|
55
|
+
let backendRun;
|
|
56
|
+
try {
|
|
57
|
+
if (selectedTasks.length > 0) {
|
|
58
|
+
const resolvedRevision = await loadResolvedRevision(options.evalDirectory, plan);
|
|
59
|
+
const preparedArtifact = await loadRerunArtifact(options.root, plan);
|
|
60
|
+
const runtimeId = requiredString(plan.controllerRuntime.runtime_id, "plan controller runtime id");
|
|
61
|
+
const runtime = await useControllerRuntimeById(statePaths(options.root), runtimeId.replace(/^sha256:/, ""));
|
|
62
|
+
if (runtime.runtime_id !== runtimeId
|
|
63
|
+
|| runtime.manifest_digest !== requiredString(plan.controllerRuntime.manifest_digest, "plan controller runtime digest")) {
|
|
64
|
+
throw unavailable("controller runtime identity changed");
|
|
65
|
+
}
|
|
66
|
+
const localTransport = await loadLocalTransport(options.evalDirectory, plan, resolvedRevision, options.env, options.signal);
|
|
67
|
+
const backendDirectory = path.join(rerunDirectory, "harbor");
|
|
68
|
+
const harborJobDirectory = path.join(backendDirectory, "job");
|
|
69
|
+
const rerunRefs = [];
|
|
70
|
+
const publish = async (ref) => {
|
|
71
|
+
if (!selectedTasks.includes(ref.task_id) || ref.attempt !== 1) {
|
|
72
|
+
throw new HitchError(`Harbor rerun returned an unselected task: ${ref.task_id}`, { code: "eval_rerun_task_mismatch", exitCode: 12 });
|
|
73
|
+
}
|
|
74
|
+
if (!rerunRefs.some((current) => current.trial_id === ref.trial_id))
|
|
75
|
+
rerunRefs.push(ref);
|
|
76
|
+
if (ref.observation_status !== "valid")
|
|
77
|
+
return;
|
|
78
|
+
await validateEvalTrialReferences(options.root, options.evalId, [ref], {
|
|
79
|
+
benchmarkId: request.benchmark_id,
|
|
80
|
+
benchmarkRevision: request.benchmark_revision,
|
|
81
|
+
});
|
|
82
|
+
const previousGeneration = progress.generation;
|
|
83
|
+
progress = replaceInvalidEvalProgressTrial(progress, ref);
|
|
84
|
+
if (progress.generation === previousGeneration)
|
|
85
|
+
return;
|
|
86
|
+
repaired.add(ref.task_id);
|
|
87
|
+
await writeEvalProgress(options.evalDirectory, progress);
|
|
88
|
+
await writeRerunState(statePath, {
|
|
89
|
+
rerunId,
|
|
90
|
+
evalId: options.evalId,
|
|
91
|
+
status: "running",
|
|
92
|
+
tasks: selectedTasks,
|
|
93
|
+
repairedTasks: [...repaired].sort(),
|
|
94
|
+
startedAt,
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
backendRun = await runHarborBackend({
|
|
98
|
+
evalId: options.evalId,
|
|
99
|
+
evalDirectory: options.evalDirectory,
|
|
100
|
+
backendDirectory,
|
|
101
|
+
taskNames: selectedTasks,
|
|
102
|
+
request,
|
|
103
|
+
root: options.root,
|
|
104
|
+
resolvedRevision,
|
|
105
|
+
runtimeDirectory: runtime.directory,
|
|
106
|
+
runtimeId: runtime.runtime_id,
|
|
107
|
+
preparedArtifact,
|
|
108
|
+
...(localTransport ? { localTransport } : {}),
|
|
109
|
+
env: options.env ?? process.env,
|
|
110
|
+
...(options.harborExecutable === undefined ? {} : { harborExecutable: options.harborExecutable }),
|
|
111
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
112
|
+
...(options.trialBundleGraceMs === undefined ? {} : { trialBundleGraceMs: options.trialBundleGraceMs }),
|
|
113
|
+
onTrialSettled: async (trial, context) => {
|
|
114
|
+
try {
|
|
115
|
+
const ref = await importEvalTrialRun({
|
|
116
|
+
root: options.root,
|
|
117
|
+
evalId: options.evalId,
|
|
118
|
+
evalDirectory: options.evalDirectory,
|
|
119
|
+
harborJobDirectory,
|
|
120
|
+
request,
|
|
121
|
+
resolvedRevision,
|
|
122
|
+
benchmarkId: request.benchmark_id,
|
|
123
|
+
benchmarkRevision: request.benchmark_revision,
|
|
124
|
+
runtimeId: runtime.runtime_id,
|
|
125
|
+
requireCompleteMarker: true,
|
|
126
|
+
allowMissingBundleDiagnostic: context.bundleWaitExpired,
|
|
127
|
+
}, trial, rerunRefs.length, rerunRefs);
|
|
128
|
+
await publish(ref);
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof TrialBundlePendingError)
|
|
133
|
+
return false;
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
const terminalRefs = await importEvalTrialRuns({
|
|
139
|
+
root: options.root,
|
|
140
|
+
evalId: options.evalId,
|
|
141
|
+
evalDirectory: options.evalDirectory,
|
|
142
|
+
harborJobDirectory,
|
|
143
|
+
request,
|
|
144
|
+
resolvedRevision,
|
|
145
|
+
benchmarkId: request.benchmark_id,
|
|
146
|
+
benchmarkRevision: request.benchmark_revision,
|
|
147
|
+
runtimeId: runtime.runtime_id,
|
|
148
|
+
rawResult: backendRun.rawResult,
|
|
149
|
+
}, rerunRefs);
|
|
150
|
+
for (const ref of terminalRefs)
|
|
151
|
+
await publish(ref);
|
|
152
|
+
if (backendRun.backend.process_exit_code !== 0 || backendRun.rawResult === null) {
|
|
153
|
+
throw new HitchError("Harbor rerun failed before producing a complete result", { code: "eval_rerun_harbor_failed", exitCode: 13 });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const result = await finalizeRerun(options.evalDirectory, request, plan, progress, previousResult, backendRun);
|
|
157
|
+
const remaining = invalidTasks(plan.tasks, progress);
|
|
158
|
+
const completedAt = new Date().toISOString();
|
|
159
|
+
const output = {
|
|
160
|
+
schema_version: "1",
|
|
161
|
+
kind: "eval-rerun",
|
|
162
|
+
rerun_id: rerunId,
|
|
163
|
+
eval_id: options.evalId,
|
|
164
|
+
status: "completed",
|
|
165
|
+
selected_tasks: selectedTasks,
|
|
166
|
+
repaired_tasks: [...repaired].sort(),
|
|
167
|
+
remaining_invalid_tasks: remaining,
|
|
168
|
+
eval_status: result.status,
|
|
169
|
+
started_at: startedAt,
|
|
170
|
+
completed_at: completedAt,
|
|
171
|
+
};
|
|
172
|
+
await writeRerunState(statePath, {
|
|
173
|
+
rerunId,
|
|
174
|
+
evalId: options.evalId,
|
|
175
|
+
status: "completed",
|
|
176
|
+
tasks: selectedTasks,
|
|
177
|
+
repairedTasks: output.repaired_tasks,
|
|
178
|
+
startedAt,
|
|
179
|
+
completedAt,
|
|
180
|
+
evalStatus: output.eval_status,
|
|
181
|
+
remainingInvalidTasks: remaining,
|
|
182
|
+
});
|
|
183
|
+
return output;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (progress.generation > 0) {
|
|
187
|
+
await finalizeRerun(options.evalDirectory, request, plan, progress, previousResult, backendRun).catch(() => { });
|
|
188
|
+
}
|
|
189
|
+
await writeRerunState(statePath, {
|
|
190
|
+
rerunId,
|
|
191
|
+
evalId: options.evalId,
|
|
192
|
+
status: "failed",
|
|
193
|
+
tasks: selectedTasks,
|
|
194
|
+
repairedTasks: [...repaired].sort(),
|
|
195
|
+
startedAt,
|
|
196
|
+
completedAt: new Date().toISOString(),
|
|
197
|
+
errorCode: error instanceof HitchError ? error.code : "eval_rerun_failed",
|
|
198
|
+
}).catch(() => { });
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export function selectRerunTasks(tasks, progress, selector) {
|
|
203
|
+
const planned = new Set(tasks);
|
|
204
|
+
if (planned.size !== tasks.length || tasks.some((task) => typeof task !== "string" || task.length === 0)) {
|
|
205
|
+
throw unavailable("eval task plan is invalid");
|
|
206
|
+
}
|
|
207
|
+
const invalid = new Set(invalidTasks(tasks, progress));
|
|
208
|
+
if (selector.mode === "invalid")
|
|
209
|
+
return [...invalid].sort();
|
|
210
|
+
const requested = [...new Set(selector.taskNames)].sort();
|
|
211
|
+
if (requested.length === 0)
|
|
212
|
+
throw invalidInput("eval rerun requires at least one --task");
|
|
213
|
+
for (const task of requested) {
|
|
214
|
+
if (!planned.has(task))
|
|
215
|
+
throw new HitchError(`eval task is not in the plan: ${task}`, { code: "eval_rerun_unknown_task", exitCode: 2 });
|
|
216
|
+
if (!invalid.has(task))
|
|
217
|
+
throw new HitchError(`eval task is already valid: ${task}`, { code: "eval_task_already_valid", exitCode: 2 });
|
|
218
|
+
}
|
|
219
|
+
return requested;
|
|
220
|
+
}
|
|
221
|
+
function invalidTasks(tasks, progress) {
|
|
222
|
+
const byKey = new Map();
|
|
223
|
+
for (const trial of progress.trials) {
|
|
224
|
+
const key = evalTrialKey(trial);
|
|
225
|
+
if (byKey.has(key))
|
|
226
|
+
throw unavailable(`eval has duplicate logical task: ${trial.task_id}`);
|
|
227
|
+
byKey.set(key, trial);
|
|
228
|
+
}
|
|
229
|
+
return [...tasks].filter((task) => byKey.get(`${task}\u00001`)?.observation_status !== "valid").sort();
|
|
230
|
+
}
|
|
231
|
+
function validateProgressPlan(progress, plan, request, evalId) {
|
|
232
|
+
if (progress.eval_id !== evalId)
|
|
233
|
+
throw unavailable("eval progress identity is invalid");
|
|
234
|
+
if (progress.benchmark_id !== request.benchmark_id || progress.benchmark_revision !== request.benchmark_revision) {
|
|
235
|
+
throw unavailable("eval progress benchmark identity changed");
|
|
236
|
+
}
|
|
237
|
+
if (progress.planned_tasks !== plan.tasks.length || progress.planned_trials !== plan.tasks.length) {
|
|
238
|
+
throw unavailable("eval progress does not match the attempts=1 task plan");
|
|
239
|
+
}
|
|
240
|
+
const planned = new Set(plan.tasks);
|
|
241
|
+
for (const trial of progress.trials) {
|
|
242
|
+
if (trial.attempt !== 1 || !planned.has(trial.task_id))
|
|
243
|
+
throw unavailable(`eval progress contains an unplanned task: ${trial.task_id}`);
|
|
244
|
+
}
|
|
245
|
+
invalidTasks(plan.tasks, progress);
|
|
246
|
+
}
|
|
247
|
+
function parseRerunPlan(value, evalId, request) {
|
|
248
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
249
|
+
throw unavailable("eval plan is missing");
|
|
250
|
+
const plan = value;
|
|
251
|
+
if (plan.eval_id !== evalId || plan.schema_version !== "1" || plan.attempts !== 1) {
|
|
252
|
+
throw unavailable("eval rerun requires a schema v1 attempts=1 plan");
|
|
253
|
+
}
|
|
254
|
+
if (plan.dataset !== request.dataset || plan.benchmark_id !== request.benchmark_id
|
|
255
|
+
|| plan.benchmark_revision !== request.benchmark_revision)
|
|
256
|
+
throw unavailable("eval request and plan identity differ");
|
|
257
|
+
if (!Array.isArray(plan.tasks) || plan.tasks.length === 0 || plan.tasks.some((task) => typeof task !== "string" || task.length === 0)) {
|
|
258
|
+
throw unavailable("eval rerun requires a frozen local task plan");
|
|
259
|
+
}
|
|
260
|
+
if (!plan.candidate || typeof plan.candidate !== "object" || Array.isArray(plan.candidate)
|
|
261
|
+
|| !plan.prepared_artifact || typeof plan.prepared_artifact !== "object" || Array.isArray(plan.prepared_artifact)
|
|
262
|
+
|| !plan.controller_runtime || typeof plan.controller_runtime !== "object" || Array.isArray(plan.controller_runtime)) {
|
|
263
|
+
throw unavailable("eval plan is incomplete");
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
tasks: [...plan.tasks],
|
|
267
|
+
candidate: plan.candidate,
|
|
268
|
+
preparedArtifact: plan.prepared_artifact,
|
|
269
|
+
controllerRuntime: plan.controller_runtime,
|
|
270
|
+
...(plan.local_source_transport && typeof plan.local_source_transport === "object" && !Array.isArray(plan.local_source_transport)
|
|
271
|
+
? { localSourceTransport: plan.local_source_transport }
|
|
272
|
+
: {}),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
async function loadPersistedRequest(value) {
|
|
276
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
277
|
+
throw unavailable("eval request is invalid");
|
|
278
|
+
const persisted = value;
|
|
279
|
+
const input = Object.fromEntries(Object.entries(persisted).filter(([key]) => key !== "benchmark_id" && key !== "benchmark_revision"));
|
|
280
|
+
const request = await validateEvalRequest(input);
|
|
281
|
+
if (persisted.benchmark_id !== request.benchmark_id || persisted.benchmark_revision !== request.benchmark_revision) {
|
|
282
|
+
throw unavailable("eval dataset identity changed since the original run");
|
|
283
|
+
}
|
|
284
|
+
return request;
|
|
285
|
+
}
|
|
286
|
+
async function loadResolvedRevision(evalDirectory, plan) {
|
|
287
|
+
const resolution = await readJSON(path.join(evalDirectory, "resolution.json"));
|
|
288
|
+
if (!resolution || resolution.identity !== requiredString(plan.candidate.revision_identity, "candidate revision identity")
|
|
289
|
+
|| resolution.harness_id !== requiredString(plan.candidate.harness_id, "candidate harness id")) {
|
|
290
|
+
throw unavailable("eval resolution identity changed");
|
|
291
|
+
}
|
|
292
|
+
return resolution;
|
|
293
|
+
}
|
|
294
|
+
async function loadRerunArtifact(root, plan) {
|
|
295
|
+
const summary = plan.preparedArtifact;
|
|
296
|
+
const artifactId = requiredString(summary.artifact_id, "prepared artifact id");
|
|
297
|
+
const artifact = await loadPreparedArtifact(preparedArtifactDirectory(root, artifactId), {
|
|
298
|
+
artifact_id: artifactId,
|
|
299
|
+
artifact_integrity: requiredString(summary.artifact_integrity, "prepared artifact integrity"),
|
|
300
|
+
entrypoint_integrity: requiredString(summary.entrypoint_integrity, "prepared artifact entrypoint integrity"),
|
|
301
|
+
harness_id: requiredString(summary.harness_id, "prepared artifact harness id"),
|
|
302
|
+
revision_identity: requiredString(summary.revision_identity, "prepared artifact revision identity"),
|
|
303
|
+
platform: requiredString(summary.platform, "prepared artifact platform"),
|
|
304
|
+
});
|
|
305
|
+
return {
|
|
306
|
+
directory: preparedArtifactDirectory(root, artifact.artifact_id),
|
|
307
|
+
artifact_id: artifact.artifact_id,
|
|
308
|
+
artifact_integrity: requiredString(artifact.artifact_integrity, "artifact integrity"),
|
|
309
|
+
entrypoint_integrity: requiredString(artifact.entrypoint_integrity, "artifact entrypoint integrity"),
|
|
310
|
+
harness_id: artifact.harness_id,
|
|
311
|
+
revision_identity: artifact.revision_identity,
|
|
312
|
+
adapter_version: artifact.adapter_version,
|
|
313
|
+
recipe_version: artifact.recipe_version,
|
|
314
|
+
platform: artifact.platform,
|
|
315
|
+
node_version: artifact.toolchain.node || process.version,
|
|
316
|
+
source_type: artifact.source_type,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
async function loadLocalTransport(evalDirectory, plan, resolution, env, signal) {
|
|
320
|
+
if (plan.localSourceTransport === undefined)
|
|
321
|
+
return undefined;
|
|
322
|
+
const directory = path.join(evalDirectory, "local-source");
|
|
323
|
+
const manifestPath = path.join(directory, "manifest.json");
|
|
324
|
+
const use = {
|
|
325
|
+
directory,
|
|
326
|
+
manifestPath,
|
|
327
|
+
payloadPath: path.join(directory, "payload.pack"),
|
|
328
|
+
resolutionPath: path.join(directory, "resolution.json"),
|
|
329
|
+
manifest: validateLocalGitTransportManifest(await readJSON(manifestPath)),
|
|
330
|
+
};
|
|
331
|
+
await verifyLocalGitTransport(use, {
|
|
332
|
+
expected: {
|
|
333
|
+
harnessId: resolution.harness_id,
|
|
334
|
+
resolutionIdentity: resolution.identity,
|
|
335
|
+
commit: requiredString(resolution.revision.commit, "local source commit"),
|
|
336
|
+
},
|
|
337
|
+
env: env ?? process.env,
|
|
338
|
+
...(signal ? { signal } : {}),
|
|
339
|
+
});
|
|
340
|
+
return use;
|
|
341
|
+
}
|
|
342
|
+
async function finalizeRerun(evalDirectory, request, plan, progress, previousResult, backendRun) {
|
|
343
|
+
const remaining = invalidTasks(plan.tasks, progress);
|
|
344
|
+
const succeeded = remaining.length === 0;
|
|
345
|
+
const completedAt = new Date().toISOString();
|
|
346
|
+
const result = {
|
|
347
|
+
...(previousResult ?? {}),
|
|
348
|
+
schema_version: SCHEMA_VERSION,
|
|
349
|
+
eval_id: progress.eval_id,
|
|
350
|
+
status: succeeded ? "succeeded" : "failed",
|
|
351
|
+
exit_code: succeeded ? 0 : 13,
|
|
352
|
+
...(backendRun ? { backend: backendRun.backend, backend_summary: backendRun.summary } : {}),
|
|
353
|
+
candidate: plan.candidate,
|
|
354
|
+
dataset: request.dataset,
|
|
355
|
+
benchmark_id: request.benchmark_id,
|
|
356
|
+
benchmark_revision: request.benchmark_revision,
|
|
357
|
+
generation: progress.generation,
|
|
358
|
+
trials: progress.trials,
|
|
359
|
+
summary: summarizeTrialRefs(progress.trials),
|
|
360
|
+
...(succeeded ? { error: undefined } : {
|
|
361
|
+
error: {
|
|
362
|
+
code: "eval_has_invalid_tasks",
|
|
363
|
+
message: `eval has invalid or missing tasks: ${remaining.join(", ")}`,
|
|
364
|
+
},
|
|
365
|
+
}),
|
|
366
|
+
started_at: typeof previousResult?.started_at === "string" ? previousResult.started_at : progress.started_at,
|
|
367
|
+
completed_at: completedAt,
|
|
368
|
+
};
|
|
369
|
+
if (succeeded)
|
|
370
|
+
delete result.error;
|
|
371
|
+
await atomicWriteJSON(path.join(evalDirectory, "result.json"), result);
|
|
372
|
+
return result;
|
|
373
|
+
}
|
|
374
|
+
async function writeRerunState(file, input) {
|
|
375
|
+
await atomicWriteJSON(file, {
|
|
376
|
+
schema_version: SCHEMA_VERSION,
|
|
377
|
+
rerun_id: input.rerunId,
|
|
378
|
+
eval_id: input.evalId,
|
|
379
|
+
status: input.status,
|
|
380
|
+
tasks: [...input.tasks],
|
|
381
|
+
repaired_tasks: [...input.repairedTasks],
|
|
382
|
+
...(input.evalStatus ? { eval_status: input.evalStatus } : {}),
|
|
383
|
+
...(input.remainingInvalidTasks ? { remaining_invalid_tasks: [...input.remainingInvalidTasks] } : {}),
|
|
384
|
+
...(input.errorCode ? { error: { code: input.errorCode } } : {}),
|
|
385
|
+
started_at: input.startedAt,
|
|
386
|
+
...(input.completedAt ? { completed_at: input.completedAt } : {}),
|
|
387
|
+
updated_at: input.completedAt ?? new Date().toISOString(),
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
function requiredString(value, label) {
|
|
391
|
+
if (typeof value !== "string" || value.length === 0)
|
|
392
|
+
throw unavailable(`${label} is missing`);
|
|
393
|
+
return value;
|
|
394
|
+
}
|
|
395
|
+
function unavailable(message) {
|
|
396
|
+
return new HitchError(message, { code: "eval_rerun_unavailable", exitCode: 2 });
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=rerun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rerun.js","sourceRoot":"","sources":["../../../src/evals/rerun.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
2
3
|
import { prepareHarness, preparedArtifactDirectory, resolveHarness } from "../artifacts/index.js";
|
|
3
4
|
import { HitchError, SCHEMA_VERSION, atomicWriteJSON, ensureDir, invalidInput, statePaths } from "../foundation/index.js";
|
|
4
5
|
import { parseHarnessReference } from "../revisions/index.js";
|
|
5
6
|
import { buildLocalGitTransport, lockedHarnessRef, runHarborBackend, verifyLocalGitTransport } from "../backends/index.js";
|
|
6
7
|
import { ensureControllerRuntime, writeRuntimeReference } from "../controller-runtime/index.js";
|
|
7
|
-
import { importEvalTrialRuns, validateEvalTrialReferences } from "./trial-import.js";
|
|
8
|
+
import { importEvalTrialRun, importEvalTrialRuns, TrialBundlePendingError, validateEvalTrialReferences } from "./trial-import.js";
|
|
8
9
|
import { EvalEventSink } from "./events.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
10
|
+
import { createEvalProgress, mergeEvalProgressTrial, writeEvalProgress } from "./progress.js";
|
|
11
|
+
import { newEvalId, resolveLocalDatasetTaskIds, validateEvalId, validateEvalRequest } from "./request.js";
|
|
12
|
+
export async function runEval({ evalId = newEvalId(), request, root, env = process.env, harborExecutable, signal, onEvent, trialBundleGraceMs }) {
|
|
11
13
|
if (!root)
|
|
12
14
|
throw invalidInput("a Hitch state root is required for eval");
|
|
15
|
+
evalId = validateEvalId(evalId);
|
|
13
16
|
const normalized = await validateEvalRequest(request);
|
|
14
|
-
const
|
|
17
|
+
const evalsDirectory = await ensureDir(statePaths(root).evals);
|
|
18
|
+
const evalDirectory = path.join(evalsDirectory, evalId);
|
|
19
|
+
try {
|
|
20
|
+
await mkdir(evalDirectory, { mode: 0o700 });
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (error.code === "EEXIST") {
|
|
24
|
+
throw new HitchError(`eval ID already exists: ${evalId}`, { code: "eval_id_conflict", exitCode: 2 });
|
|
25
|
+
}
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
15
28
|
const startedAt = new Date();
|
|
16
29
|
const sink = new EvalEventSink(evalDirectory, evalId, onEvent);
|
|
17
30
|
await sink.open();
|
|
18
31
|
await atomicWriteJSON(path.join(evalDirectory, "request.json"), normalized);
|
|
19
32
|
let result;
|
|
20
33
|
let trialRefs = [];
|
|
34
|
+
let progress = null;
|
|
21
35
|
try {
|
|
22
36
|
sink.emit({ type: "eval.started", backend: normalized.backend, dataset: normalized.dataset });
|
|
23
37
|
const requestedReference = parseHarnessReference(normalized.harness_ref);
|
|
@@ -75,7 +89,10 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
75
89
|
entrypoint_integrity: artifact.entrypoint_integrity,
|
|
76
90
|
harness_id: artifact.harness_id,
|
|
77
91
|
revision_identity: artifact.revision_identity,
|
|
92
|
+
adapter_version: artifact.adapter_version,
|
|
93
|
+
recipe_version: artifact.recipe_version,
|
|
78
94
|
platform: artifact.platform,
|
|
95
|
+
node_version: artifact.toolchain.node || process.version,
|
|
79
96
|
source_type: artifact.source_type,
|
|
80
97
|
};
|
|
81
98
|
sink.emit({
|
|
@@ -95,6 +112,11 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
95
112
|
cache_hit: controllerRuntime.cache_hit,
|
|
96
113
|
reference: runtimeRefFile,
|
|
97
114
|
});
|
|
115
|
+
const localTaskIds = await resolveLocalDatasetTaskIds(normalized.dataset);
|
|
116
|
+
const plannedTasks = localTaskIds?.length ?? null;
|
|
117
|
+
const plannedTrials = plannedTasks === null ? null : plannedTasks * normalized.attempts;
|
|
118
|
+
if (plannedTrials !== null && !Number.isSafeInteger(plannedTrials))
|
|
119
|
+
throw invalidInput("planned trial count exceeds the safe integer range");
|
|
98
120
|
const plan = {
|
|
99
121
|
schema_version: SCHEMA_VERSION,
|
|
100
122
|
eval_id: evalId,
|
|
@@ -112,6 +134,7 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
112
134
|
benchmark_revision: normalized.benchmark_revision,
|
|
113
135
|
attempts: normalized.attempts,
|
|
114
136
|
max_concurrent: normalized.max_concurrent,
|
|
137
|
+
...(localTaskIds === null ? {} : { tasks: localTaskIds }),
|
|
115
138
|
controller_runtime: {
|
|
116
139
|
runtime_id: controllerRuntime.runtime_id,
|
|
117
140
|
manifest_digest: controllerRuntime.manifest_digest,
|
|
@@ -122,11 +145,22 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
122
145
|
};
|
|
123
146
|
await atomicWriteJSON(path.join(evalDirectory, "resolution.json"), resolvedRevision);
|
|
124
147
|
await atomicWriteJSON(path.join(evalDirectory, "plan.json"), plan);
|
|
148
|
+
progress = createEvalProgress({
|
|
149
|
+
evalId,
|
|
150
|
+
benchmarkId: normalized.benchmark_id,
|
|
151
|
+
benchmarkRevision: normalized.benchmark_revision,
|
|
152
|
+
plannedTasks,
|
|
153
|
+
plannedTrials,
|
|
154
|
+
startedAt: startedAt.toISOString(),
|
|
155
|
+
});
|
|
156
|
+
await writeEvalProgress(evalDirectory, progress);
|
|
125
157
|
sink.emit({
|
|
126
158
|
type: "eval.planned",
|
|
127
159
|
harness: resolvedRevision.harness_id,
|
|
128
160
|
revision_identity: resolvedRevision.identity,
|
|
129
161
|
attempts: normalized.attempts,
|
|
162
|
+
planned_tasks: plannedTasks,
|
|
163
|
+
planned_trials: plannedTrials,
|
|
130
164
|
});
|
|
131
165
|
if (localTransport) {
|
|
132
166
|
await verifyLocalGitTransport(localTransport, {
|
|
@@ -152,7 +186,51 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
152
186
|
env,
|
|
153
187
|
...(harborExecutable !== undefined ? { harborExecutable } : {}),
|
|
154
188
|
...(signal ? { signal } : {}),
|
|
189
|
+
...(trialBundleGraceMs === undefined ? {} : { trialBundleGraceMs }),
|
|
155
190
|
emit: (event) => sink.emit(event),
|
|
191
|
+
onTrialSettled: async (trial, context) => {
|
|
192
|
+
try {
|
|
193
|
+
const ref = await importEvalTrialRun({
|
|
194
|
+
root,
|
|
195
|
+
evalId,
|
|
196
|
+
evalDirectory,
|
|
197
|
+
request: normalized,
|
|
198
|
+
resolvedRevision,
|
|
199
|
+
benchmarkId: normalized.benchmark_id,
|
|
200
|
+
benchmarkRevision: normalized.benchmark_revision,
|
|
201
|
+
runtimeId: controllerRuntime.runtime_id,
|
|
202
|
+
requireCompleteMarker: true,
|
|
203
|
+
allowMissingBundleDiagnostic: context.bundleWaitExpired,
|
|
204
|
+
}, trial, progress?.trials.length ?? 0, progress?.trials ?? []);
|
|
205
|
+
if (progress === null)
|
|
206
|
+
throw new Error("eval progress was not initialized");
|
|
207
|
+
const previousGeneration = progress.generation;
|
|
208
|
+
progress = mergeEvalProgressTrial(progress, ref);
|
|
209
|
+
if (progress.generation !== previousGeneration) {
|
|
210
|
+
await validateEvalTrialReferences(root, evalId, [ref], {
|
|
211
|
+
benchmarkId: normalized.benchmark_id,
|
|
212
|
+
benchmarkRevision: normalized.benchmark_revision,
|
|
213
|
+
});
|
|
214
|
+
await writeEvalProgress(evalDirectory, progress);
|
|
215
|
+
sink.emit({
|
|
216
|
+
type: "eval.trial.published",
|
|
217
|
+
trial_id: ref.trial_id,
|
|
218
|
+
task_id: ref.task_id,
|
|
219
|
+
attempt: ref.attempt,
|
|
220
|
+
run_id: ref.run_id,
|
|
221
|
+
observation_status: ref.observation_status,
|
|
222
|
+
settled_trials: progress.trials.length,
|
|
223
|
+
generation: progress.generation,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
if (error instanceof TrialBundlePendingError)
|
|
230
|
+
return false;
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
},
|
|
156
234
|
});
|
|
157
235
|
trialRefs = await importEvalTrialRuns({
|
|
158
236
|
root,
|
|
@@ -164,7 +242,13 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
164
242
|
benchmarkRevision: normalized.benchmark_revision,
|
|
165
243
|
runtimeId: controllerRuntime.runtime_id,
|
|
166
244
|
rawResult: backendRun.rawResult,
|
|
167
|
-
});
|
|
245
|
+
}, progress?.trials ?? []);
|
|
246
|
+
if (progress === null)
|
|
247
|
+
throw new Error("eval progress was not initialized");
|
|
248
|
+
for (const ref of trialRefs)
|
|
249
|
+
progress = mergeEvalProgressTrial(progress, ref);
|
|
250
|
+
await writeEvalProgress(evalDirectory, progress);
|
|
251
|
+
assertBackendTrialSet(backendRun.rawResult, progress.trials);
|
|
168
252
|
await validateEvalTrialReferences(root, evalId, trialRefs, {
|
|
169
253
|
benchmarkId: normalized.benchmark_id,
|
|
170
254
|
benchmarkRevision: normalized.benchmark_revision,
|
|
@@ -182,6 +266,7 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
182
266
|
dataset: normalized.dataset,
|
|
183
267
|
benchmark_id: normalized.benchmark_id,
|
|
184
268
|
benchmark_revision: normalized.benchmark_revision,
|
|
269
|
+
generation: progress.generation,
|
|
185
270
|
trials: trialRefs,
|
|
186
271
|
summary: summarizeTrialRefs(trialRefs),
|
|
187
272
|
backend_summary: backendRun.summary,
|
|
@@ -204,6 +289,7 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
204
289
|
};
|
|
205
290
|
}
|
|
206
291
|
catch (error) {
|
|
292
|
+
trialRefs = progress?.trials ?? trialRefs;
|
|
207
293
|
const typed = error instanceof HitchError;
|
|
208
294
|
result = {
|
|
209
295
|
schema_version: SCHEMA_VERSION,
|
|
@@ -216,6 +302,7 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
216
302
|
},
|
|
217
303
|
benchmark_id: normalized.benchmark_id,
|
|
218
304
|
benchmark_revision: normalized.benchmark_revision,
|
|
305
|
+
...(progress === null ? {} : { generation: progress.generation }),
|
|
219
306
|
trials: trialRefs,
|
|
220
307
|
started_at: startedAt.toISOString(),
|
|
221
308
|
completed_at: new Date().toISOString(),
|
|
@@ -226,7 +313,15 @@ export async function runEval({ evalId = newEvalId(), request, root, env = proce
|
|
|
226
313
|
await sink.close();
|
|
227
314
|
return result;
|
|
228
315
|
}
|
|
229
|
-
function
|
|
316
|
+
function assertBackendTrialSet(rawResult, refs) {
|
|
317
|
+
const trials = Array.isArray(rawResult?.trial_results) ? rawResult.trial_results : [];
|
|
318
|
+
const backendIds = new Set(trials.map((trial) => typeof trial.trial_name === "string" ? trial.trial_name : null).filter((value) => value !== null));
|
|
319
|
+
const refIds = new Set(refs.map((ref) => ref.trial_id));
|
|
320
|
+
if (backendIds.size !== trials.length || backendIds.size !== refIds.size || [...backendIds].some((id) => !refIds.has(id))) {
|
|
321
|
+
throw new Error("Harbor terminal trial set does not match published eval progress");
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
export function summarizeTrialRefs(trials) {
|
|
230
325
|
const valid = trials.filter((trial) => trial.observation_status === "valid" && typeof trial.reward === "number");
|
|
231
326
|
const rewards = valid.map((trial) => trial.reward);
|
|
232
327
|
const aggregate = rewards.length
|