@cef-ai/cli 4.1.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/dist/build/lints.d.ts +12 -0
  3. package/dist/build/lints.d.ts.map +1 -1
  4. package/dist/build/lints.js +23 -0
  5. package/dist/build/lints.js.map +1 -1
  6. package/dist/cli-program.d.ts +7 -0
  7. package/dist/cli-program.d.ts.map +1 -1
  8. package/dist/cli-program.js +61 -8
  9. package/dist/cli-program.js.map +1 -1
  10. package/dist/commands/build.d.ts.map +1 -1
  11. package/dist/commands/build.js +11 -1
  12. package/dist/commands/build.js.map +1 -1
  13. package/dist/commands/eval.d.ts +113 -1
  14. package/dist/commands/eval.d.ts.map +1 -1
  15. package/dist/commands/eval.js +360 -5
  16. package/dist/commands/eval.js.map +1 -1
  17. package/dist/commands/eval.test.js +267 -3
  18. package/dist/commands/eval.test.js.map +1 -1
  19. package/dist/commands/push.d.ts +55 -0
  20. package/dist/commands/push.d.ts.map +1 -1
  21. package/dist/commands/push.js +80 -5
  22. package/dist/commands/push.js.map +1 -1
  23. package/dist/commands/release-cli.d.ts +77 -0
  24. package/dist/commands/release-cli.d.ts.map +1 -0
  25. package/dist/commands/release-cli.js +543 -0
  26. package/dist/commands/release-cli.js.map +1 -0
  27. package/dist/commands/release-view.d.ts +118 -0
  28. package/dist/commands/release-view.d.ts.map +1 -0
  29. package/dist/commands/release-view.js +321 -0
  30. package/dist/commands/release-view.js.map +1 -0
  31. package/dist/commands/release.d.ts +132 -0
  32. package/dist/commands/release.d.ts.map +1 -0
  33. package/dist/commands/release.js +198 -0
  34. package/dist/commands/release.js.map +1 -0
  35. package/dist/lib/ddc.d.ts +29 -0
  36. package/dist/lib/ddc.d.ts.map +1 -1
  37. package/dist/lib/ddc.js +37 -1
  38. package/dist/lib/ddc.js.map +1 -1
  39. package/dist/lib/env.d.ts +6 -0
  40. package/dist/lib/env.d.ts.map +1 -1
  41. package/dist/lib/env.js +12 -0
  42. package/dist/lib/env.js.map +1 -1
  43. package/dist/lib/eval-target.d.ts +39 -3
  44. package/dist/lib/eval-target.d.ts.map +1 -1
  45. package/dist/lib/eval-target.js +68 -8
  46. package/dist/lib/eval-target.js.map +1 -1
  47. package/dist/lib/eval-target.test.js +36 -3
  48. package/dist/lib/eval-target.test.js.map +1 -1
  49. package/dist/lib/registry-read.d.ts +27 -0
  50. package/dist/lib/registry-read.d.ts.map +1 -0
  51. package/dist/lib/registry-read.js +93 -0
  52. package/dist/lib/registry-read.js.map +1 -0
  53. package/dist/lib/release-review.d.ts +30 -0
  54. package/dist/lib/release-review.d.ts.map +1 -0
  55. package/dist/lib/release-review.js +72 -0
  56. package/dist/lib/release-review.js.map +1 -0
  57. package/dist/lib/vault-publish.d.ts +3 -1
  58. package/dist/lib/vault-publish.d.ts.map +1 -1
  59. package/dist/lib/vault-publish.js +5 -3
  60. package/dist/lib/vault-publish.js.map +1 -1
  61. package/package.json +6 -6
@@ -1,5 +1,7 @@
1
1
  import type { Command } from "commander";
2
- import { type Case, type DatasetSummary, type EvalStore, type Experiment, type ExperimentComparison, type ExperimentProgress, type Header, type Limits, type ResultCompatibility, type ResultField, type WorkflowTarget } from "@cef-ai/eval";
2
+ import { type Case, type DatasetSummary, type EvalStore, type Experiment, type ExperimentComparison, type ExperimentProgress, type Header, type Limits, type ResultCompatibility, type ResultField, type RunRecord, type RunStreamEvent, type VersionHistoryEntry, type WorkflowTarget } from "@cef-ai/eval";
3
+ import { type VaultAccess } from "../lib/eval-vault.js";
4
+ import { type OrchestratorPort } from "../lib/eval-target.js";
3
5
  import { type LocalWorkflowOptions } from "../lib/eval-workflow.js";
4
6
  export declare const VERSIONS_FILE = ".versions.json";
5
7
  /** Where datasets live in a workflow's folder. */
@@ -67,6 +69,52 @@ export declare function evalImport(opts: {
67
69
  cut?: string | boolean;
68
70
  dryRun?: boolean;
69
71
  }): Promise<ImportSummary>;
72
+ export interface CaptureResult {
73
+ dataset: string;
74
+ /** The cases that were (or, under `dryRun`, would be) added. */
75
+ added: Case[];
76
+ /**
77
+ * Contexts that produced no case, each with why: no `workflow.start`, or
78
+ * already captured as an existing case's `source.context` (a re-run).
79
+ */
80
+ skipped: string[];
81
+ }
82
+ /**
83
+ * Build eval cases from real runs — the CLI equivalent of ROC's "Add from
84
+ * executions". For each context it reads the run's event stream from the vault
85
+ * (`vaultEvents`; no orchestrator, no `--as-pubkey`) and WRITES the resulting
86
+ * cases:
87
+ * - input = the run's `workflow.start` event payload (an inline `graph` dropped);
88
+ * - output = the `workflow.completed` event whose `runId` matches this run
89
+ * (older runners that stamp no `runId` are not matched), turned into
90
+ * the expectation to be edited afterwards.
91
+ * `--workflow-version` is stamped on each case's `source` but does NOT change the
92
+ * read scope. Unlike ROC's `captureRun`, which reads the runner's first task,
93
+ * this reads the `workflow.start` event.
94
+ *
95
+ * IDEMPOTENT: a context already recorded as a case's `source.context` is skipped,
96
+ * so re-running the same contexts writes nothing; the same context named twice in
97
+ * one call yields one case (the first occurrence).
98
+ *
99
+ * PLAN THEN WRITE, like ROC's `planCases`: every case is built and its id
100
+ * resolved before anything is saved, and `--id` is validated up front (format,
101
+ * single context, not already taken) before any event is read, so a refusal never
102
+ * leaves half the runs written. A run with no `workflow.start` cannot become a
103
+ * case — it is skipped with a note, not fatal. `dryRun` stops after planning.
104
+ * Auto ids come from the context (`slugCaseId`) and are made unique against the
105
+ * dataset's live, archived and deleted ids and the batch so far; the write itself
106
+ * uses `addCase`, which refuses an id that already exists.
107
+ */
108
+ export declare function evalCapture(opts: {
109
+ store: EvalStore;
110
+ vaultEvents: (context: string) => Promise<RunStreamEvent[]>;
111
+ workflowId: string;
112
+ dataset: string;
113
+ contexts: string[];
114
+ id?: string;
115
+ workflowVersion?: string;
116
+ dryRun?: boolean;
117
+ }): Promise<CaptureResult>;
70
118
  export interface PullResult {
71
119
  dir: string;
72
120
  cases: number;
@@ -199,6 +247,51 @@ export declare function evalCompare(opts: {
199
247
  base: string;
200
248
  candidate: string;
201
249
  }): Promise<ExperimentComparison>;
250
+ /** One experiment with its per-case run records. Found by id alone (no workflow needed), like `compare`. */
251
+ export declare function evalShow(opts: {
252
+ store: EvalStore;
253
+ id: string;
254
+ }): Promise<{
255
+ experiment: Experiment;
256
+ runs: RunRecord[];
257
+ }>;
258
+ /**
259
+ * Mark a stuck/running experiment cancelled — the CLI equivalent of ROC's
260
+ * "Mark cancelled". Found by id alone (no workflow needed), like `show`. A vault
261
+ * write: any workflow-version pin the experiment holds is left to expire on its
262
+ * own, so no pin is released here. Returns both the experiment as it was and as
263
+ * it is now, so the caller can tell "we cancelled it" from "it was already
264
+ * terminal" or "it turned out complete and was recorded done".
265
+ */
266
+ export declare function evalCancel(opts: {
267
+ store: EvalStore;
268
+ experiment: string;
269
+ }): Promise<{
270
+ before: Experiment;
271
+ after: Experiment;
272
+ }>;
273
+ /** Make `experiment` the dataset's baseline, or clear it with `reset`. */
274
+ export declare function evalBaseline(opts: {
275
+ store: EvalStore;
276
+ workflowId: string;
277
+ dataset: string;
278
+ experiment?: string;
279
+ reset?: boolean;
280
+ }): Promise<Header>;
281
+ /** The dataset's versions, newest first, each with what changed and how many experiments ran it. */
282
+ export declare function evalVersions(opts: {
283
+ store: EvalStore;
284
+ workflowId: string;
285
+ dataset: string;
286
+ }): Promise<VersionHistoryEntry[]>;
287
+ /** Archive a case (hide it from new versions) or, with `undo`, unarchive it. */
288
+ export declare function evalArchive(opts: {
289
+ store: EvalStore;
290
+ workflowId: string;
291
+ dataset: string;
292
+ caseId: string;
293
+ undo?: boolean;
294
+ }): Promise<void>;
202
295
  /**
203
296
  * The Result a workflow version declares, read off its graph:
204
297
  * - the live deployment row's `params.graph` when the version is the live
@@ -223,14 +316,33 @@ export declare function resultFieldsFor(opts: {
223
316
  }>;
224
317
  /** A plain fixed-width table. */
225
318
  export declare function table(headers: string[], rows: Array<Array<string | number | null | undefined>>): string;
319
+ /** One line per run: case, repeat, verdict, and the failing fields or the error. */
320
+ export declare function formatCases(runs: RunRecord[]): string;
226
321
  export declare function formatDatasets(list: DatasetSummary[]): string;
227
322
  export declare function formatExperiments(list: Experiment[], baselineId?: string): string;
228
323
  export declare function formatExperiment(e: Experiment): string;
324
+ /** An experiment's per-case runs, one row each (case, repeat, status, verdict, cost). */
325
+ export declare function formatRunRecords(runs: RunRecord[]): string;
326
+ /** A dataset's version history, newest first — the columns of ROC's History table. */
327
+ export declare function formatVersionHistory(list: VersionHistoryEntry[]): string;
229
328
  /** "Dataset changed between these experiments: …" — or nothing when it did not. */
230
329
  export declare function formatDatasetDiff(c: Pick<ExperimentComparison, "datasetDiff" | "comparedOn">): string | null;
231
330
  export declare function formatResultCheck(r: ResultCheck): string[];
232
331
  export declare function formatCompatibility(r: ResultCompatibility, version: string): string[];
233
332
  export declare function formatComparison(c: ExperimentComparison): string;
333
+ /** What {@link openTarget} reads of the options. */
334
+ export interface TargetOptions {
335
+ env?: string;
336
+ asPubkey?: string;
337
+ accessToken?: string;
338
+ orchestrator?: string;
339
+ }
340
+ /** The Node target: vault-api for events, the orchestrator for jobs and deployments. */
341
+ export declare function openTarget(o: TargetOptions, vault: VaultAccess, scope: string, workflowId: string, fetchImpl?: typeof fetch): {
342
+ target: WorkflowTarget;
343
+ orchestrator: OrchestratorPort;
344
+ agentId: string;
345
+ };
234
346
  export declare function addEvalCommands(program: Command, opts: {
235
347
  onError: (e: unknown) => never;
236
348
  fetchImpl?: typeof fetch;
@@ -1 +1 @@
1
- {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/commands/eval.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,14 @@
8
8
  * cef eval run <dataset> [--dataset-version N] [--workflow-version v] [--repeats 3] [--concurrency 4] [--baseline exp]
9
9
  * cef eval experiments [dataset] experiment history
10
10
  * cef eval compare <a> <b> how experiment b differs from a
11
+ * cef eval show <experiment> one experiment's results, per case
12
+ * cef eval cancel <experiment> --yes mark a stuck/running experiment cancelled (ROC's "Mark cancelled")
13
+ * cef eval baseline <dataset> [exp] [--reset] set (or clear) the dataset's baseline
14
+ * cef eval versions <dataset> the dataset's version history
15
+ * cef eval archive <dataset> <caseId> [--undo] hide a case from new versions
16
+ * cef eval check <dataset> [--workflow-version v] Result-compatibility check (what run prints first)
17
+ * cef eval capture <dataset> <context...> [--id c] [--workflow-version v] [--dry-run]
18
+ * build cases from real runs (ROC's "Add from executions")
11
19
  *
12
20
  * Every command is about one workflow: `--workflow <id>`, by default the one
13
21
  * `cef.config.ts` (or the build output) in the current directory declares.
@@ -35,11 +43,11 @@
35
43
  */
36
44
  import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
37
45
  import path from "node:path";
38
- import { canonicalJson, casesFromTable, checkResultCompatibility, compareExperiments, createDataset, cutVersion, deleteCase, findExperiment, getCaseRevision, getHeader, getVersion, listArchivedCaseIds, listCaseRevisions, listDatasets, listDeletedCaseIds, listExperiments, listRunRecords, listVersions, listWorkflows, loadWorkingSet, parseCase, parseDelimited, parseHeader, resultFieldsFromGraph, runExperiment, saveCase, sha256Hex, unarchiveCase, undeleteCase, updateHeader, } from "@cef-ai/eval";
46
+ import { addCase, archiveCase, canonicalJson, caseFromRun, capturedFromEvents, casesFromTable, checkResultCompatibility, compareExperiments, createDataset, cutVersion, deleteCase, findExperiment, getCaseRevision, getHeader, isCaseId, listCaseIds, slugCaseId, uniqueCaseId, getVersion, listArchivedCaseIds, listCaseRevisions, listDatasets, listDeletedCaseIds, listExperiments, listRunRecords, listVersions, listWorkflows, loadWorkingSet, markCancelled, parseCase, parseDelimited, parseHeader, resultFieldsFromGraph, runExperiment, saveCase, setBaseline, sha256Hex, unarchiveCase, undeleteCase, updateHeader, versionHistory, } from "@cef-ai/eval";
39
47
  import { Browse, Events } from "@cef-ai/vault-sdk/internal";
40
48
  import { loadWallet } from "../lib/eval-auth.js";
41
49
  import { openVault, vaultEvalStore } from "../lib/eval-vault.js";
42
- import { fetchOrchestrator, getDeploymentSet, nodeWorkflowTarget, workflowAgentId, } from "../lib/eval-target.js";
50
+ import { allEvents, fetchOrchestrator, getDeploymentSet, liveOf, nodeWorkflowTarget, workflowAgentId, } from "../lib/eval-target.js";
43
51
  import { DEFAULT_WORKFLOW_SCOPE, localGraph, localWorkflowScope, resolveWorkflowId, } from "../lib/eval-workflow.js";
44
52
  import { envConfig } from "../lib/env.js";
45
53
  /* ------------------------------------------------------------------------ */
@@ -147,6 +155,88 @@ export async function evalImport(opts) {
147
155
  }
148
156
  return { created, added, skipped, warnings, ...(cut ? { cut } : {}) };
149
157
  }
158
+ /**
159
+ * Build eval cases from real runs — the CLI equivalent of ROC's "Add from
160
+ * executions". For each context it reads the run's event stream from the vault
161
+ * (`vaultEvents`; no orchestrator, no `--as-pubkey`) and WRITES the resulting
162
+ * cases:
163
+ * - input = the run's `workflow.start` event payload (an inline `graph` dropped);
164
+ * - output = the `workflow.completed` event whose `runId` matches this run
165
+ * (older runners that stamp no `runId` are not matched), turned into
166
+ * the expectation to be edited afterwards.
167
+ * `--workflow-version` is stamped on each case's `source` but does NOT change the
168
+ * read scope. Unlike ROC's `captureRun`, which reads the runner's first task,
169
+ * this reads the `workflow.start` event.
170
+ *
171
+ * IDEMPOTENT: a context already recorded as a case's `source.context` is skipped,
172
+ * so re-running the same contexts writes nothing; the same context named twice in
173
+ * one call yields one case (the first occurrence).
174
+ *
175
+ * PLAN THEN WRITE, like ROC's `planCases`: every case is built and its id
176
+ * resolved before anything is saved, and `--id` is validated up front (format,
177
+ * single context, not already taken) before any event is read, so a refusal never
178
+ * leaves half the runs written. A run with no `workflow.start` cannot become a
179
+ * case — it is skipped with a note, not fatal. `dryRun` stops after planning.
180
+ * Auto ids come from the context (`slugCaseId`) and are made unique against the
181
+ * dataset's live, archived and deleted ids and the batch so far; the write itself
182
+ * uses `addCase`, which refuses an id that already exists.
183
+ */
184
+ export async function evalCapture(opts) {
185
+ if (opts.id !== undefined && opts.contexts.length !== 1) {
186
+ throw new Error("[cef eval] --id names one case; pass a single context");
187
+ }
188
+ if (!(await getHeader(opts.store, opts.workflowId, opts.dataset))) {
189
+ throw new Error(`[cef eval] workflow "${opts.workflowId}" has no dataset "${opts.dataset}"`);
190
+ }
191
+ // Every id a new case may not take: live, archived and deleted alike; plus the
192
+ // working set, to skip contexts already captured as a case's source.
193
+ const [live, deleted, working] = await Promise.all([
194
+ listCaseIds(opts.store, opts.workflowId, opts.dataset, { includeArchived: true }),
195
+ listDeletedCaseIds(opts.store, opts.workflowId, opts.dataset),
196
+ loadWorkingSet(opts.store, opts.workflowId, opts.dataset),
197
+ ]);
198
+ const taken = new Set([...live, ...deleted]);
199
+ // `--id` up front, before any event is read: format, and not already taken.
200
+ if (opts.id !== undefined) {
201
+ if (!isCaseId(opts.id))
202
+ throw new Error(`[cef eval] "${opts.id}" is not a case id`);
203
+ if (taken.has(opts.id))
204
+ throw new Error(`[cef eval] "${opts.id}" already exists in ${opts.dataset}`);
205
+ }
206
+ const captured = new Set(working.cases.map(({ case: c }) => c.source?.context).filter((c) => !!c));
207
+ const planned = [];
208
+ const skipped = [];
209
+ const seen = new Set();
210
+ for (const context of opts.contexts) {
211
+ if (seen.has(context))
212
+ continue; // the same context twice in one call → one case
213
+ seen.add(context);
214
+ if (captured.has(context)) {
215
+ skipped.push(`${context}: already captured as a case — nothing to add`);
216
+ continue;
217
+ }
218
+ const run = capturedFromEvents(await opts.vaultEvents(context), context, opts.workflowVersion);
219
+ if (run.problem) {
220
+ skipped.push(`${context}: ${run.problem}`);
221
+ continue;
222
+ }
223
+ const id = opts.id ?? uniqueCaseId(slugCaseId(context), taken);
224
+ taken.add(id);
225
+ planned.push(caseFromRun({
226
+ input: run.input,
227
+ context,
228
+ ...(run.output != null ? { output: run.output } : {}),
229
+ ...(run.workflowVersion ? { workflowVersion: run.workflowVersion } : {}),
230
+ id,
231
+ }));
232
+ }
233
+ // `addCase` refuses an id that already exists, so a derived or `--id` id that
234
+ // collides errors instead of appending a revision to someone else's case.
235
+ if (!opts.dryRun)
236
+ for (const c of planned)
237
+ await addCase(opts.store, opts.workflowId, opts.dataset, c);
238
+ return { dataset: opts.dataset, added: planned, skipped };
239
+ }
150
240
  /** The pulled state in the repo dir, when it is this dataset's. */
151
241
  async function readState(dir, dataset) {
152
242
  const raw = (await readJsonFile(path.join(datasetDir(dir, dataset), VERSIONS_FILE)));
@@ -466,6 +556,73 @@ export async function evalCompare(opts) {
466
556
  };
467
557
  return compareExperiments(await load(opts.base), await load(opts.candidate));
468
558
  }
559
+ /** One experiment with its per-case run records. Found by id alone (no workflow needed), like `compare`. */
560
+ export async function evalShow(opts) {
561
+ const experiment = await findExperiment(opts.store, opts.id);
562
+ if (!experiment)
563
+ throw new Error(`[cef eval] experiment "${opts.id}" not found`);
564
+ return { experiment, runs: await listRunRecords(opts.store, experiment.workflowId, experiment.id) };
565
+ }
566
+ /**
567
+ * Mark a stuck/running experiment cancelled — the CLI equivalent of ROC's
568
+ * "Mark cancelled". Found by id alone (no workflow needed), like `show`. A vault
569
+ * write: any workflow-version pin the experiment holds is left to expire on its
570
+ * own, so no pin is released here. Returns both the experiment as it was and as
571
+ * it is now, so the caller can tell "we cancelled it" from "it was already
572
+ * terminal" or "it turned out complete and was recorded done".
573
+ */
574
+ export async function evalCancel(opts) {
575
+ const before = await findExperiment(opts.store, opts.experiment);
576
+ if (!before)
577
+ throw new Error(`[cef eval] experiment "${opts.experiment}" not found`);
578
+ // The default no-op releasePin: the CLI does not hold or release pins.
579
+ const after = await markCancelled(opts.store, before.workflowId, opts.experiment, undefined);
580
+ return { before, after };
581
+ }
582
+ /** Make `experiment` the dataset's baseline, or clear it with `reset`. */
583
+ export async function evalBaseline(opts) {
584
+ if (opts.experiment && opts.reset) {
585
+ throw new Error("[cef eval] pass an experiment or --reset, not both");
586
+ }
587
+ if (!opts.reset && !opts.experiment) {
588
+ throw new Error("[cef eval] baseline <experiment> is required (or --reset to clear the baseline)");
589
+ }
590
+ if (!opts.reset) {
591
+ // A baseline is this dataset's own experiment — a typo or another dataset's id is refused.
592
+ const exp = await findExperiment(opts.store, opts.experiment);
593
+ if (!exp)
594
+ throw new Error(`[cef eval] experiment "${opts.experiment}" not found`);
595
+ if (exp.workflowId !== opts.workflowId || exp.dataset !== opts.dataset) {
596
+ throw new Error(`[cef eval] experiment "${opts.experiment}" is not an experiment of ${opts.workflowId}/${opts.dataset}`);
597
+ }
598
+ }
599
+ // `null` clears it; `setBaseline` also checks the id's format.
600
+ return setBaseline(opts.store, opts.workflowId, opts.dataset, opts.reset ? null : opts.experiment);
601
+ }
602
+ /** The dataset's versions, newest first, each with what changed and how many experiments ran it. */
603
+ export async function evalVersions(opts) {
604
+ // A missing dataset has no versions either way; say so, rather than "No versions." as if it existed.
605
+ if (!(await getHeader(opts.store, opts.workflowId, opts.dataset))) {
606
+ throw new Error(`[cef eval] workflow "${opts.workflowId}" has no dataset "${opts.dataset}"`);
607
+ }
608
+ return versionHistory(opts.store, opts.workflowId, opts.dataset);
609
+ }
610
+ /** Archive a case (hide it from new versions) or, with `undo`, unarchive it. */
611
+ export async function evalArchive(opts) {
612
+ // The case must exist in the dataset — live, archived or deleted — so --undo on a
613
+ // typo is refused rather than printing "✓ Unarchived" for a case that never was.
614
+ const [ids, deleted] = await Promise.all([
615
+ listCaseIds(opts.store, opts.workflowId, opts.dataset, { includeArchived: true }),
616
+ listDeletedCaseIds(opts.store, opts.workflowId, opts.dataset),
617
+ ]);
618
+ if (!ids.includes(opts.caseId) && !deleted.includes(opts.caseId)) {
619
+ throw new Error(`[cef eval] dataset "${opts.dataset}" has no case "${opts.caseId}"`);
620
+ }
621
+ if (opts.undo)
622
+ await unarchiveCase(opts.store, opts.workflowId, opts.dataset, opts.caseId);
623
+ else
624
+ await archiveCase(opts.store, opts.workflowId, opts.dataset, opts.caseId);
625
+ }
469
626
  /**
470
627
  * The Result a workflow version declares, read off its graph:
471
628
  * - the live deployment row's `params.graph` when the version is the live
@@ -501,6 +658,18 @@ export function table(headers, rows) {
501
658
  const pct = (n) => (n === null || n === undefined ? null : `${Math.round(n * 1000) / 10}%`);
502
659
  const ms = (n) => (n === null || n === undefined ? null : n >= 1000 ? `${(n / 1000).toFixed(1)}s` : `${n}ms`);
503
660
  const plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
661
+ /** One line per run: case, repeat, verdict, and the failing fields or the error. */
662
+ export function formatCases(runs) {
663
+ if (runs.length === 0)
664
+ return "No runs.";
665
+ return table(["case", "#", "status", "verdict", "why"], runs.map((r) => [
666
+ r.caseId,
667
+ r.repeat,
668
+ r.status,
669
+ r.pass === null ? "n/a" : r.pass ? "pass" : "FAIL",
670
+ r.error ?? r.scores.filter((s) => s.pass === false).map((s) => `${s.name}=${JSON.stringify(s.value)}`).join(", "),
671
+ ]));
672
+ }
504
673
  export function formatDatasets(list) {
505
674
  if (!list.length)
506
675
  return "No datasets.";
@@ -535,6 +704,23 @@ export function formatExperiment(e) {
535
704
  : []),
536
705
  ].join("\n");
537
706
  }
707
+ /** An experiment's per-case runs, one row each (case, repeat, status, verdict, cost). */
708
+ export function formatRunRecords(runs) {
709
+ if (!runs.length)
710
+ return "No runs.";
711
+ const verdict = (r) => (r.pass === null ? "–" : r.pass ? "pass" : "FAIL");
712
+ return table(["CASE", "REPEAT", "STATUS", "VERDICT", "OUTCOME", "DURATION", "TOKENS"], [...runs]
713
+ .sort((a, b) => a.caseId.localeCompare(b.caseId) || a.repeat - b.repeat)
714
+ .map((r) => [r.caseId, r.repeat, r.status, verdict(r), r.outcome, ms(r.metrics.durationMs), r.metrics.totalTokens]));
715
+ }
716
+ /** A dataset's version history, newest first — the columns of ROC's History table. */
717
+ export function formatVersionHistory(list) {
718
+ if (!list.length)
719
+ return "No versions.";
720
+ // Compact change counts against the previous version: added / edited / removed.
721
+ const changes = (v) => `+${v.diff.added.length} ~${v.diff.edited.length} -${v.diff.removed.length}`;
722
+ return table(["VERSION", "CREATED", "CASES", "CHANGES", "EXPERIMENTS", "NOTE"], list.map((v) => [`v${v.version}`, v.createdAt.replace("T", " ").slice(0, 16), v.cases, changes(v), v.experiments, v.note]));
723
+ }
538
724
  /** "Dataset changed between these experiments: …" — or nothing when it did not. */
539
725
  export function formatDatasetDiff(c) {
540
726
  const d = c.datasetDiff;
@@ -630,7 +816,7 @@ function withDir(cmd) {
630
816
  return cmd.option("--dir <dir>", "Directory holding the workflow's datasets", DEFAULT_DATASETS_DIR);
631
817
  }
632
818
  /** The Node target: vault-api for events, the orchestrator for jobs and deployments. */
633
- function openTarget(o, vault, scope, workflowId, fetchImpl) {
819
+ export function openTarget(o, vault, scope, workflowId, fetchImpl) {
634
820
  const env = envConfig(o.env);
635
821
  const asPubKey = o.asPubkey ?? process.env.CEF_AS_PUBKEY;
636
822
  if (!asPubKey)
@@ -754,6 +940,40 @@ export function addEvalCommands(program, opts) {
754
940
  opts.onError(e);
755
941
  }
756
942
  });
943
+ withWorkflow(ev.command("capture <dataset> <context...>")
944
+ .description("Build cases from real runs' input and output, and add them to the dataset (ROC's \"Add from executions\")"))
945
+ .option("--id <caseId>", "Name the case (only with a single context); otherwise derived from the context")
946
+ .option("--workflow-version <v>", "Stamp this workflow version on each case's source")
947
+ .option("--dry-run", "Build and print what would be added, write nothing")
948
+ .action(async (dataset, contexts, o) => {
949
+ try {
950
+ const workflowId = await workflowOf(o);
951
+ // Reads the run's events from the vault and writes cases: no wallet, no orchestrator, no --as-pubkey.
952
+ const vault = await openVault(o, undefined, opts.fetchImpl);
953
+ const scope = await scopeOf(o, workflowId);
954
+ const store = vaultEvalStore(vault, scope);
955
+ const browse = new Browse(vault.http);
956
+ const reader = {
957
+ events: (context, cursor) => browse.listStreamEvents(vault.vaultId, scope, context, { limit: 200, ...(cursor ? { cursor } : {}) }),
958
+ };
959
+ const r = await evalCapture({
960
+ store, vaultEvents: (context) => allEvents(reader, context),
961
+ workflowId, dataset, contexts,
962
+ ...(o.id !== undefined ? { id: o.id } : {}),
963
+ ...(o.workflowVersion ? { workflowVersion: o.workflowVersion } : {}),
964
+ dryRun: !!o.dryRun,
965
+ });
966
+ print(o.json, r, () => [
967
+ o.dryRun ? "• Dry run — nothing written" : null,
968
+ `${o.dryRun ? "Would add" : "✓ Added"} ${plural(r.added.length, "case")}`
969
+ + (r.added.length ? `: ${r.added.map((c) => c.id).join(", ")}` : ""),
970
+ ...(r.skipped.length ? [" skipped:", ...r.skipped.map((s) => ` ${s}`)] : []),
971
+ ].filter((l) => l !== null).join("\n"));
972
+ }
973
+ catch (e) {
974
+ opts.onError(e);
975
+ }
976
+ });
757
977
  withDir(withWorkflow(ev.command("pull <dataset>").description("Write a dataset's live cases to the repo dir")))
758
978
  .option("--force", "Overwrite case files edited locally since the last pull/push")
759
979
  .action(async (dataset, o) => {
@@ -831,8 +1051,7 @@ export function addEvalCommands(program, opts) {
831
1051
  if (!header)
832
1052
  throw new Error(`[cef eval] workflow "${workflowId}" has no dataset "${dataset}"`);
833
1053
  const { target, orchestrator, agentId } = openTarget(o, vault, scope, workflowId, opts.fetchImpl);
834
- const liveRow = (await getDeploymentSet(orchestrator, agentId))?.deployments
835
- .find((d) => d.targeting === "" && d.enabled !== false);
1054
+ const liveRow = liveOf((await getDeploymentSet(orchestrator, agentId))?.deployments).row;
836
1055
  const live = liveRow?.version ?? null;
837
1056
  const workflowVersion = o.workflowVersion ?? live ?? "latest";
838
1057
  const isLive = o.workflowVersion === undefined || o.workflowVersion === live;
@@ -867,6 +1086,23 @@ export function addEvalCommands(program, opts) {
867
1086
  opts.onError(e);
868
1087
  }
869
1088
  });
1089
+ withWorkflow(ev.command("cases <experiment>").description("An experiment's runs, case by case (the failed ones with --failed)"))
1090
+ .option("--failed", "Only the runs that failed or errored")
1091
+ .action(async (experiment, o) => {
1092
+ try {
1093
+ const workflowId = await workflowOf(o).catch(() => undefined);
1094
+ const store = await openStore(o, workflowId);
1095
+ const exp = await findExperiment(store, experiment);
1096
+ if (!exp)
1097
+ throw new Error(`[cef eval] experiment "${experiment}" not found`);
1098
+ const runs = (await listRunRecords(store, exp.workflowId, exp.id))
1099
+ .filter((r) => !o.failed || r.pass === false || r.status !== "done");
1100
+ print(o.json, runs, () => formatCases(runs));
1101
+ }
1102
+ catch (e) {
1103
+ opts.onError(e);
1104
+ }
1105
+ });
870
1106
  withWorkflow(ev.command("experiments [dataset]").description("The workflow's experiment history (one dataset's, when named)"))
871
1107
  .action(async (dataset, o) => {
872
1108
  try {
@@ -891,5 +1127,124 @@ export function addEvalCommands(program, opts) {
891
1127
  opts.onError(e);
892
1128
  }
893
1129
  });
1130
+ // An experiment id is global, so the workflow is optional here (as in `compare`).
1131
+ withWorkflow(ev.command("show <experiment>").description("One experiment's results: summary, per-field accuracy and per-case runs"))
1132
+ .action(async (experiment, o) => {
1133
+ try {
1134
+ const workflowId = await workflowOf(o).catch(() => undefined);
1135
+ const { experiment: exp, runs } = await evalShow({ store: await openStore(o, workflowId), id: experiment });
1136
+ print(o.json, { experiment: exp, runs }, () => [formatExperiment(exp), "", formatRunRecords(runs)].join("\n"));
1137
+ }
1138
+ catch (e) {
1139
+ opts.onError(e);
1140
+ }
1141
+ });
1142
+ // An experiment id is global, so the workflow is optional here (as in `show`).
1143
+ withWorkflow(ev.command("cancel <experiment>")
1144
+ .description("Mark a stuck/running experiment cancelled (the CLI's \"Mark cancelled\")"))
1145
+ .option("--yes", "Confirm: write the experiment record cancelled now")
1146
+ .addHelpText("after", "\ncancel writes the experiment record now. Only do this if nothing is still running it\n"
1147
+ + "(a ROC tab or another \"cef eval run --resume\") — that would flip it back to done/error.\n"
1148
+ + "Pass --yes to confirm.\n"
1149
+ + "\nWrites only the experiment record. A workflow-version pin it may hold is not released here;\n"
1150
+ + "it expires on its own (~6h).")
1151
+ .action(async (experiment, o) => {
1152
+ try {
1153
+ // Refuse until confirmed: cancelling a record that is still being run flips it back.
1154
+ if (!o.yes) {
1155
+ throw new Error("[cef eval] cancel writes the experiment record now. Only do this if nothing is still running it "
1156
+ + "(a ROC tab or another \"cef eval run --resume\") — that would flip it back to done/error. "
1157
+ + "Pass --yes to confirm.");
1158
+ }
1159
+ const workflowId = await workflowOf(o).catch(() => undefined);
1160
+ const store = await openStore(o, workflowId);
1161
+ const { before, after } = await evalCancel({ store, experiment });
1162
+ // The message turns on what it was before: --json carries the resulting record.
1163
+ print(o.json, after, () => before.status !== "running"
1164
+ ? `• Experiment ${experiment} is ${before.status} — nothing to cancel`
1165
+ : after.status === "done"
1166
+ ? `✓ Experiment ${experiment} was already complete — recorded as done`
1167
+ : `✓ Experiment ${experiment} cancelled`);
1168
+ }
1169
+ catch (e) {
1170
+ opts.onError(e);
1171
+ }
1172
+ });
1173
+ // `[experiment]` is optional so `--reset` needs no placeholder; it is required otherwise.
1174
+ withWorkflow(ev.command("baseline <dataset> [experiment]").description("Set the dataset's baseline experiment (--reset to clear it)"))
1175
+ .option("--reset", "Clear the dataset's baseline")
1176
+ .action(async (dataset, experiment, o) => {
1177
+ try {
1178
+ const workflowId = await workflowOf(o);
1179
+ const store = await openStore(o, workflowId);
1180
+ const header = await evalBaseline({ store, workflowId, dataset, ...(experiment ? { experiment } : {}), reset: !!o.reset });
1181
+ print(o.json, header, () => o.reset ? `✓ Baseline for ${dataset} reset` : `✓ Baseline for ${dataset} set to ${experiment}`);
1182
+ }
1183
+ catch (e) {
1184
+ opts.onError(e);
1185
+ }
1186
+ });
1187
+ withWorkflow(ev.command("versions <dataset>").description("The dataset's version history"))
1188
+ .action(async (dataset, o) => {
1189
+ try {
1190
+ const workflowId = await workflowOf(o);
1191
+ const store = await openStore(o, workflowId);
1192
+ const list = await evalVersions({ store, workflowId, dataset });
1193
+ print(o.json, list, () => formatVersionHistory(list));
1194
+ }
1195
+ catch (e) {
1196
+ opts.onError(e);
1197
+ }
1198
+ });
1199
+ withWorkflow(ev.command("archive <dataset> <caseId>")
1200
+ .description("Archive a case: hide it from new versions (cef eval push --restore also unarchives from the repo dir)"))
1201
+ .option("--undo", "Unarchive the case instead")
1202
+ .action(async (dataset, caseId, o) => {
1203
+ try {
1204
+ const workflowId = await workflowOf(o);
1205
+ const store = await openStore(o, workflowId);
1206
+ await evalArchive({ store, workflowId, dataset, caseId, undo: !!o.undo });
1207
+ print(o.json, { dataset, caseId, archived: !o.undo }, () => (o.undo ? `✓ Unarchived ${caseId}` : `✓ Archived ${caseId}`));
1208
+ }
1209
+ catch (e) {
1210
+ opts.onError(e);
1211
+ }
1212
+ });
1213
+ withWorkflow(ev.command("check <dataset>").description("Check the dataset's live cases against the workflow version's declared Result"))
1214
+ .option("--workflow-version <v>", "Workflow version (default: the live one)")
1215
+ .option("--as-pubkey <hex>", "Agent service pubkey the workflow belongs to ($CEF_AS_PUBKEY); needed only to resolve the live version (not with --workflow-version)")
1216
+ .option("--orchestrator <url>", "Orchestrator base URL ($CEF_ENDPOINT; default from --env)")
1217
+ .action(async (dataset, o) => {
1218
+ try {
1219
+ const workflowId = await workflowOf(o);
1220
+ // No wallet needed to read: the vault takes an access token.
1221
+ const vault = await openVault(o, undefined, opts.fetchImpl);
1222
+ const scope = await scopeOf(o, workflowId);
1223
+ const store = vaultEvalStore(vault, scope);
1224
+ const header = await getHeader(store, workflowId, dataset);
1225
+ if (!header)
1226
+ throw new Error(`[cef eval] workflow "${workflowId}" has no dataset "${dataset}"`);
1227
+ let workflowVersion;
1228
+ let result;
1229
+ if (o.workflowVersion) {
1230
+ // A named version resolves from the LOCAL graph (cef.config.ts or dist/) — no
1231
+ // orchestrator, so no --as-pubkey.
1232
+ workflowVersion = o.workflowVersion;
1233
+ result = await resultFieldsFor({ workflowId, workflowVersion, local: local() });
1234
+ }
1235
+ else {
1236
+ // The live version: through the orchestrator (needs --as-pubkey), as `run` does.
1237
+ const { orchestrator, agentId } = openTarget(o, vault, scope, workflowId, opts.fetchImpl);
1238
+ const liveRow = liveOf((await getDeploymentSet(orchestrator, agentId))?.deployments).row;
1239
+ workflowVersion = liveRow?.version ?? "latest";
1240
+ result = await resultFieldsFor({ workflowId, workflowVersion, ...(liveRow ? { liveRow } : {}), local: local() });
1241
+ }
1242
+ const check = await evalResultCheck({ store, workflowId, dataset, workflowVersion, result });
1243
+ print(o.json, check, () => formatResultCheck(check).join("\n"));
1244
+ }
1245
+ catch (e) {
1246
+ opts.onError(e);
1247
+ }
1248
+ });
894
1249
  }
895
1250
  //# sourceMappingURL=eval.js.map