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.
@@ -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 { newEvalId, validateEvalRequest } from "./request.js";
10
- export async function runEval({ evalId = newEvalId(), request, root, env = process.env, harborExecutable, signal, onEvent }) {
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 evalDirectory = await ensureDir(path.join(statePaths(root).evals, evalId));
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 summarizeTrialRefs(trials) {
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