@eigenpal/cli 0.20.2 → 0.20.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/cli.js CHANGED
@@ -94280,7 +94280,7 @@ function cleanDoc(doc) {
94280
94280
  return mapDoc(doc, (currentDoc) => cleanDocFn(currentDoc));
94281
94281
  }
94282
94282
  function replaceEndOfLine(doc, replacement = literalline) {
94283
- return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join2(replacement, currentDoc.split(`
94283
+ return mapDoc(doc, (currentDoc) => typeof currentDoc === "string" ? join3(replacement, currentDoc.split(`
94284
94284
  `)) : currentDoc);
94285
94285
  }
94286
94286
  function canBreakFn(doc) {
@@ -94360,7 +94360,7 @@ function indentIfBreak(contents, options) {
94360
94360
  negate: options.negate
94361
94361
  };
94362
94362
  }
94363
- function join2(separator, docs) {
94363
+ function join3(separator, docs) {
94364
94364
  assertDoc(separator);
94365
94365
  assertDocArray(docs);
94366
94366
  const parts = [];
@@ -95071,7 +95071,7 @@ var init_doc = __esm(() => {
95071
95071
  MODE_FLAT = Symbol("MODE_FLAT");
95072
95072
  DOC_FILL_PRINTED_LENGTH = Symbol("DOC_FILL_PRINTED_LENGTH");
95073
95073
  builders = {
95074
- join: join2,
95074
+ join: join3,
95075
95075
  line,
95076
95076
  softline,
95077
95077
  hardline,
@@ -183861,7 +183861,7 @@ function parse42(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
183861
183861
  }
183862
183862
  return res;
183863
183863
  }
183864
- async function readFile2(file) {
183864
+ async function readFile3(file) {
183865
183865
  if (isUrlString(file)) {
183866
183866
  file = new URL(file);
183867
183867
  }
@@ -184752,7 +184752,7 @@ function defaultResolve(specifier, context = {}) {
184752
184752
  format: defaultGetFormatWithoutErrors(url3, { parentURL })
184753
184753
  };
184754
184754
  }
184755
- function resolve2(specifier, parent) {
184755
+ function resolve22(specifier, parent) {
184756
184756
  if (!parent) {
184757
184757
  throw new Error("Please pass `parent`: `import-meta-resolve` cannot ponyfill that");
184758
184758
  }
@@ -184767,7 +184767,7 @@ function resolve2(specifier, parent) {
184767
184767
  }
184768
184768
  }
184769
184769
  function importFromFile(specifier, parent) {
184770
- const url3 = resolve2(specifier, pathToFileURL4(parent).href);
184770
+ const url3 = resolve22(specifier, pathToFileURL4(parent).href);
184771
184771
  return import(url3);
184772
184772
  }
184773
184773
  function requireFromFile(id, parent) {
@@ -197655,7 +197655,7 @@ ${codeblock}`, options8);
197655
197655
  "\\": "\\"
197656
197656
  };
197657
197657
  KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
197658
- read_file_default = readFile2;
197658
+ read_file_default = readFile3;
197659
197659
  loadConfigFromPackageJson = process.versions.bun ? async function loadConfigFromBunPackageJson(file) {
197660
197660
  const { prettier } = await readBunPackageJson(file);
197661
197661
  return prettier;
@@ -206391,7 +206391,7 @@ import { fileURLToPath as fileURLToPath8 } from "url";
206391
206391
  // package.json
206392
206392
  var package_default = {
206393
206393
  name: "@eigenpal/cli",
206394
- version: "0.20.2",
206394
+ version: "0.20.4",
206395
206395
  description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
206396
206396
  keywords: [
206397
206397
  "eigenpal",
@@ -206646,6 +206646,15 @@ class ApiClient {
206646
206646
  });
206647
206647
  return this.handleResponse(res, url);
206648
206648
  }
206649
+ async patchFormData(path, formData) {
206650
+ const url = this.buildUrl(path);
206651
+ const res = await fetch(url, {
206652
+ method: "PATCH",
206653
+ headers: this.headers(),
206654
+ body: formData
206655
+ });
206656
+ return this.handleResponse(res, url);
206657
+ }
206649
206658
  async delete(path) {
206650
206659
  const url = this.buildUrl(path);
206651
206660
  const res = await fetch(url, {
@@ -209914,6 +209923,10 @@ function zipSync(data, opts) {
209914
209923
  import { existsSync as existsSync8, promises as fs3 } from "node:fs";
209915
209924
  import path8 from "node:path";
209916
209925
 
209926
+ // src/commands/dataset-review-request.ts
209927
+ import { mkdir, readFile as readFile2, stat, writeFile as writeFile2 } from "node:fs/promises";
209928
+ import { basename, dirname as dirname2, isAbsolute, join as join2, relative, resolve } from "node:path";
209929
+
209917
209930
  // src/commands/agents/shared.ts
209918
209931
  init_src();
209919
209932
  import { existsSync as existsSync6, promises as fs } from "node:fs";
@@ -210133,6 +210146,7 @@ function datasetReviewRequestItemsPath(automationId, reviewId, itemId) {
210133
210146
  const base = `${datasetReviewRequestsPath(automationId, reviewId)}/items`;
210134
210147
  return itemId ? `${base}/${itemId}` : base;
210135
210148
  }
210149
+ var REVIEW_EDIT_FILE_MAX_BYTES = 50 * 1024 * 1024;
210136
210150
  function collectRepeatable(val2, prev) {
210137
210151
  return [...prev, val2];
210138
210152
  }
@@ -210146,7 +210160,7 @@ function formatProgress(progress) {
210146
210160
  const total = progress.total ?? remaining;
210147
210161
  return `${remaining}/${total} remaining`;
210148
210162
  }
210149
- function parseFieldDecision(opts) {
210163
+ function parseApprovalDecision(opts, action) {
210150
210164
  if (opts.clear) {
210151
210165
  if (opts.decision !== undefined) {
210152
210166
  throw new Error("pass either --clear or --decision, not both");
@@ -210154,7 +210168,7 @@ function parseFieldDecision(opts) {
210154
210168
  return null;
210155
210169
  }
210156
210170
  if (opts.decision === undefined) {
210157
- throw new Error("--decision or --clear is required when --action field-decision");
210171
+ throw new Error(`--decision or --clear is required when --action ${action}`);
210158
210172
  }
210159
210173
  const normalized = opts.decision.trim().toLowerCase();
210160
210174
  if (normalized === "null" || normalized === "clear") {
@@ -210165,6 +210179,12 @@ function parseFieldDecision(opts) {
210165
210179
  }
210166
210180
  throw new Error("--decision must be approved, rejected, null, or clear");
210167
210181
  }
210182
+ function parseFieldDecision(opts) {
210183
+ return parseApprovalDecision(opts, "field-decision");
210184
+ }
210185
+ function parseFileDecision(opts) {
210186
+ return parseApprovalDecision(opts, "file-decision");
210187
+ }
210168
210188
  function buildReviewItemPatchBody(action, opts) {
210169
210189
  const body = {
210170
210190
  action,
@@ -210174,6 +210194,8 @@ function buildReviewItemPatchBody(action, opts) {
210174
210194
  body.comment = opts.comment;
210175
210195
  if (opts.fieldPath !== undefined)
210176
210196
  body.fieldPath = opts.fieldPath;
210197
+ if (opts.filePath !== undefined)
210198
+ body.filePath = opts.filePath;
210177
210199
  if (action === "edit") {
210178
210200
  if (opts.expectedJson === undefined) {
210179
210201
  throw new Error("--expected-json is required when --action edit");
@@ -210188,10 +210210,91 @@ function buildReviewItemPatchBody(action, opts) {
210188
210210
  }
210189
210211
  body.decision = parseFieldDecision({ decision: opts.decision, clear: opts.clear });
210190
210212
  } else if (opts.decision !== undefined || opts.clear) {
210191
- throw new Error("--decision / --clear are only valid with --action field-decision");
210213
+ if (action !== "file-decision") {
210214
+ throw new Error("--decision / --clear are only valid with --action field-decision or file-decision");
210215
+ }
210216
+ }
210217
+ if (action === "file-decision") {
210218
+ if (!opts.filePath?.trim()) {
210219
+ throw new Error("--file-path is required when --action file-decision");
210220
+ }
210221
+ if (opts.fieldPath !== undefined) {
210222
+ throw new Error("--field-path is only valid with --action comment or field-decision");
210223
+ }
210224
+ if (opts.newPath !== undefined || opts.file !== undefined) {
210225
+ throw new Error("--new-path / --file are only valid with --action edit-file");
210226
+ }
210227
+ if (opts.decision !== undefined || opts.clear) {
210228
+ body.decision = parseFileDecision({ decision: opts.decision, clear: opts.clear });
210229
+ } else if (!opts.comment?.trim()) {
210230
+ throw new Error("pass --decision approved|rejected (or --clear) or a --comment note when --action file-decision");
210231
+ }
210232
+ } else if (opts.filePath !== undefined || opts.newPath !== undefined || opts.file !== undefined) {
210233
+ if (action !== "edit-file") {
210234
+ throw new Error("--file-path / --new-path / --file are only valid with --action file-decision or edit-file");
210235
+ }
210236
+ }
210237
+ if (action === "edit-file") {
210238
+ throw new Error("--action edit-file uploads bytes and needs multipart; use buildReviewItemFileFields");
210192
210239
  }
210193
210240
  return body;
210194
210241
  }
210242
+ function buildReviewItemFileFields(opts) {
210243
+ const hasFilePath = !!opts.filePath?.trim();
210244
+ const hasNewPath = !!opts.newPath?.trim();
210245
+ if (hasFilePath === hasNewPath) {
210246
+ throw new Error("pass exactly one of --file-path (correct an existing expected file) or --new-path (upload a brand-new expected file) when --action edit-file");
210247
+ }
210248
+ if (!opts.file?.trim()) {
210249
+ throw new Error("--file <local path> is required when --action edit-file");
210250
+ }
210251
+ return {
210252
+ ...hasFilePath ? { filePath: opts.filePath.trim() } : {},
210253
+ ...hasNewPath ? { newPath: opts.newPath.trim() } : {},
210254
+ ...opts.comment !== undefined ? { comment: opts.comment } : {},
210255
+ expectedUpdatedAt: opts.expectedUpdatedAt
210256
+ };
210257
+ }
210258
+ function encodeReviewFilePath(path) {
210259
+ const segments = path.replace(/^\/+/, "").split("/");
210260
+ for (const segment of segments) {
210261
+ if (!segment || segment === "." || segment === ".." || segment.includes("\\") || segment.includes("\x00")) {
210262
+ throw new Error(`refusing to download unsafe review file path: ${path}`);
210263
+ }
210264
+ }
210265
+ return segments.map((segment) => encodeURIComponent(segment)).join("/");
210266
+ }
210267
+ function assertSafeReviewExampleName(exampleName) {
210268
+ const segments = exampleName.split("/");
210269
+ for (const segment of segments) {
210270
+ if (!segment || segment === "." || segment === ".." || segment.includes("\\") || segment.includes("\x00")) {
210271
+ throw new Error(`refusing to materialize unsafe review example name: ${exampleName}`);
210272
+ }
210273
+ }
210274
+ return exampleName;
210275
+ }
210276
+ function formatReviewItemFiles(item) {
210277
+ const overlay = item.currentExpectedFiles;
210278
+ const files = overlay ?? item.snapshotManifest?.expectedFiles ?? null;
210279
+ if (!files || files.length === 0)
210280
+ return "-";
210281
+ const decisions = item.fileDecisions ?? {};
210282
+ let approved = 0;
210283
+ let rejected = 0;
210284
+ for (const file of files) {
210285
+ const key = file.path ?? file.name ?? "";
210286
+ const decision = decisions[key]?.decision;
210287
+ if (decision === "approved")
210288
+ approved += 1;
210289
+ else if (decision === "rejected")
210290
+ rejected += 1;
210291
+ }
210292
+ const total = files.length;
210293
+ const decided = approved + rejected;
210294
+ if (decided === 0)
210295
+ return `${total} file${total === 1 ? "" : "s"}, undecided`;
210296
+ return `${approved}/${total} approved${rejected ? `, ${rejected} rejected` : ""}`;
210297
+ }
210195
210298
  function registerDatasetReviewRequestCommands(dataset, resolveAutomation) {
210196
210299
  const reviewRequest = dataset.command("review-request").description("Review dataset ground truth with a human. Snapshot examples for review and poll progress until reviewers finish.").action(() => {
210197
210300
  process.stderr.write("`dataset review-request` requires a subcommand. Run `dataset review-request --help`.\n");
@@ -210234,9 +210337,13 @@ Examples:
210234
210337
 
210235
210338
  Agent loop: create with focus/ignore and per-example notes → poll \`get --json\`
210236
210339
  until \`.progress.complete\` → record per-field decisions and per-example
210237
- approve/reject with comments → read \`events\` → \`dataset pull\` and MANUAL
210238
- per-example reconcile into the live dataset (no auto-apply exists by design;
210239
- reviewers can err) → \`update --status closed\`.
210340
+ approve/reject with comments → \`pull --out <dir>\` to fetch expected files
210341
+ (snapshot or reviewer-corrected) → correct bytes with
210342
+ \`item --action edit-file --file-path <path> --file <local>\` (or
210343
+ \`--new-path\` for brand-new files) → record per-file decisions with notes
210344
+ via \`item --action file-decision\` → read \`events\` → \`dataset pull\` and
210345
+ MANUAL per-example reconcile into the live dataset (no auto-apply exists by
210346
+ design; reviewers can err) → \`update --status closed\`.
210240
210347
 
210241
210348
  \`reject\` is a recommendation only — nothing is deleted by any review endpoint.
210242
210349
  Use \`--json\` from agents; API errors exit non-zero.
@@ -210283,7 +210390,7 @@ Use \`--json\` from agents; API errors exit non-zero.
210283
210390
  const created = payload;
210284
210391
  success(`Created review request ${ui.bold(created.id ?? "(unknown id)")}` + (created.status ? ` ${ui.dim(`(${created.status})`)}` : ""));
210285
210392
  }));
210286
- addJsonFlag(withBaseUrl(reviewRequest.command("get <automation-id> <review-id>"))).description("Fetch one dataset review request with items, progress, focus fields, ignored fields, and events.").action(action(async (automationRef, reviewId, opts) => {
210393
+ addJsonFlag(withBaseUrl(reviewRequest.command("get <automation-id> <review-id>"))).description("Fetch one dataset review request with items, progress, focus fields, ignored fields, expected files, file decisions, and events.").action(action(async (automationRef, reviewId, opts) => {
210287
210394
  const { client, automationId } = await resolveAutomation(automationRef, opts);
210288
210395
  const payload = await client.get(datasetReviewRequestsPath(automationId, reviewId));
210289
210396
  if (opts.json)
@@ -210311,11 +210418,13 @@ Use \`--json\` from agents; API errors exit non-zero.
210311
210418
  console.log(table(detail.items.map((item) => ({
210312
210419
  exampleName: item.exampleName,
210313
210420
  status: item.status,
210314
- inputDrifted: item.inputDrifted ? "yes" : "no"
210421
+ inputDrifted: item.inputDrifted ? "yes" : "no",
210422
+ files: formatReviewItemFiles(item)
210315
210423
  })), [
210316
210424
  { key: "exampleName", header: "example" },
210317
210425
  { key: "status", header: "status" },
210318
- { key: "inputDrifted", header: "inputDrifted" }
210426
+ { key: "inputDrifted", header: "inputDrifted" },
210427
+ { key: "files", header: "files" }
210319
210428
  ]));
210320
210429
  }
210321
210430
  }));
@@ -210374,11 +210483,13 @@ to the dataset — reconcile manually after \`dataset pull\`.
210374
210483
  console.log(table(items.map((item) => ({
210375
210484
  exampleName: item.exampleName,
210376
210485
  status: item.status,
210377
- inputDrifted: item.inputDrifted ? "yes" : "no"
210486
+ inputDrifted: item.inputDrifted ? "yes" : "no",
210487
+ files: formatReviewItemFiles(item)
210378
210488
  })), [
210379
210489
  { key: "exampleName", header: "example" },
210380
210490
  { key: "status", header: "status" },
210381
- { key: "inputDrifted", header: "inputDrifted" }
210491
+ { key: "inputDrifted", header: "inputDrifted" },
210492
+ { key: "files", header: "files" }
210382
210493
  ]));
210383
210494
  }));
210384
210495
  addJsonFlag(withBaseUrl(reviewRequest.command("events <automation-id> <review-id>"))).description("List review activity, including example and field notes.").action(action(async (automationRef, reviewId, opts) => {
@@ -210401,7 +210512,7 @@ to the dataset — reconcile manually after \`dataset pull\`.
210401
210512
  { key: "createdAt", header: "createdAt" }
210402
210513
  ]));
210403
210514
  }));
210404
- addJsonFlag(withBaseUrl(reviewRequest.command("item <automation-id> <review-id> <item-id>"))).description("Approve, reject, reopen, comment, edit, or record a field-decision on one review item.").requiredOption("--action <approve|reject|reopen|comment|edit|field-decision>", "Item action").requiredOption("--expected-updated-at <iso>", "Item updatedAt the client last observed (optimistic concurrency)").option("--comment <text>", "Note stored on the item or field").option("--field-path <path>", "Dotted expected-output path for comment or field-decision").option("--decision <approved|rejected|null>", "Field decision for --action field-decision (null/clear removes it)").option("--clear", "Clear a field decision (sends decision: null)", false).option("--expected-json <json>", "Replacement expected JSON when --action edit").addHelpText("after", `
210515
+ addJsonFlag(withBaseUrl(reviewRequest.command("item <automation-id> <review-id> <item-id>"))).description("Approve, reject, reopen, comment, edit, or record a field- or file-decision on one review item. Upload corrected expected-file bytes with edit-file.").requiredOption("--action <approve|reject|reopen|comment|edit|field-decision|file-decision|edit-file>", "Item action").requiredOption("--expected-updated-at <iso>", "Item updatedAt the client last observed (optimistic concurrency)").option("--comment <text>", "Note stored on the item, field, or file").option("--field-path <path>", "Dotted expected-output path for comment or field-decision").option("--file-path <path>", "Expected-file path for file-decision or edit-file (correct)").option("--new-path <path>", "Expected-file path for edit-file uploads of brand-new reviewer files").option("--file <local path>", "Local file bytes to upload when --action edit-file").option("--decision <approved|rejected|null>", "Field or file decision for --action field-decision or file-decision (null/clear removes it)").option("--clear", "Clear a field or file decision (sends decision: null)", false).option("--expected-json <json>", "Replacement expected JSON when --action edit").addHelpText("after", `
210405
210516
  Examples:
210406
210517
  $ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
210407
210518
  --action field-decision --field-path vendor.iban --decision approved \\
@@ -210409,30 +210520,137 @@ Examples:
210409
210520
  $ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
210410
210521
  --action field-decision --field-path vendor.iban --clear \\
210411
210522
  --expected-updated-at 2026-01-01T00:00:00.000Z --json
210523
+ $ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
210524
+ --action file-decision --file-path expected/report.pdf --decision approved \\
210525
+ --comment "totals match" --expected-updated-at 2026-01-01T00:00:00.000Z --json
210526
+ $ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
210527
+ --action edit-file --file-path expected/report.pdf --file ./report-fixed.pdf \\
210528
+ --comment "fixed total" --expected-updated-at 2026-01-01T00:00:00.000Z --json
210529
+ $ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
210530
+ --action edit-file --new-path expected/appendix.pdf --file ./appendix.pdf \\
210531
+ --expected-updated-at 2026-01-01T00:00:00.000Z --json
210412
210532
  $ eigenpal workflow dataset review-request item wf_abc123 dsr_... dsri_... \\
210413
210533
  --action reject --comment "wrong vendor" \\
210414
210534
  --expected-updated-at 2026-01-01T00:00:00.000Z --json
210415
210535
 
210416
210536
  \`reject\` marks the example as not recommended for the dataset; it does not
210417
- delete anything. \`--clear\` / \`--decision null\` removes a prior field
210418
- decision (API: decision: null). Always pass \`--expected-updated-at\` from
210419
- the item payload you last observed.
210537
+ delete anything. \`--clear\` / \`--decision null\` removes a prior field or
210538
+ file decision (API: decision: null). A file-decision \`--comment\` without a
210539
+ decision is a note and needs an existing decision server-side. \`edit-file\`
210540
+ takes exactly one of \`--file-path\` (correct an existing expected file) or
210541
+ \`--new-path\` (upload a brand-new expected file) plus \`--file\` bytes
210542
+ (50MB cap); it replaces the item overlay entry, never the live dataset.
210543
+ Always pass \`--expected-updated-at\` from the item payload you last observed.
210420
210544
  `).action(action(async (automationRef, reviewId, itemId, opts) => {
210421
210545
  const { client, automationId } = await resolveAutomation(automationRef, opts);
210546
+ const itemPath = datasetReviewRequestItemsPath(automationId, reviewId, itemId);
210547
+ if (opts.action === "edit-file") {
210548
+ const fields = buildReviewItemFileFields({
210549
+ expectedUpdatedAt: opts.expectedUpdatedAt,
210550
+ filePath: opts.filePath,
210551
+ newPath: opts.newPath,
210552
+ file: opts.file,
210553
+ comment: opts.comment
210554
+ });
210555
+ const localPath = resolve(opts.file.trim());
210556
+ const fileStat = await stat(localPath);
210557
+ if (!fileStat.isFile()) {
210558
+ throw new Error(`--file is not a file: ${localPath}`);
210559
+ }
210560
+ if (fileStat.size > REVIEW_EDIT_FILE_MAX_BYTES) {
210561
+ throw new Error(`--file ${localPath} is ${(fileStat.size / 1024 / 1024).toFixed(1)}MB; the edit-file cap is 50MB`);
210562
+ }
210563
+ const bytes = await readFile2(localPath);
210564
+ const form = new FormData;
210565
+ form.set("action", "edit-file");
210566
+ form.set("file", new Blob([bytes], { type: "application/octet-stream" }), basename(localPath));
210567
+ if (fields.filePath !== undefined)
210568
+ form.set("filePath", fields.filePath);
210569
+ if (fields.newPath !== undefined)
210570
+ form.set("newPath", fields.newPath);
210571
+ if (fields.comment !== undefined)
210572
+ form.set("comment", fields.comment);
210573
+ form.set("expectedUpdatedAt", fields.expectedUpdatedAt);
210574
+ const payload = await client.patchFormData(itemPath, form);
210575
+ if (opts.json)
210576
+ return printJson2(payload);
210577
+ const item = payload.item;
210578
+ success(`Updated ${ui.bold(item?.exampleName ?? itemId)}` + (item?.status ? ` ${ui.dim(`(${item.status})`)}` : ""));
210579
+ return;
210580
+ }
210422
210581
  const body = buildReviewItemPatchBody(opts.action, {
210423
210582
  expectedUpdatedAt: opts.expectedUpdatedAt,
210424
210583
  comment: opts.comment,
210425
210584
  fieldPath: opts.fieldPath,
210585
+ filePath: opts.filePath,
210586
+ newPath: opts.newPath,
210587
+ file: opts.file,
210426
210588
  decision: opts.decision,
210427
210589
  clear: opts.clear,
210428
210590
  expectedJson: opts.expectedJson
210429
210591
  });
210430
- const payload = await client.patch(datasetReviewRequestItemsPath(automationId, reviewId, itemId), body);
210592
+ const payload = await client.patch(itemPath, body);
210431
210593
  if (opts.json)
210432
210594
  return printJson2(payload);
210433
210595
  const item = payload.item;
210434
210596
  success(`Updated ${ui.bold(item?.exampleName ?? itemId)}` + (item?.status ? ` ${ui.dim(`(${item.status})`)}` : ""));
210435
210597
  }));
210598
+ addJsonFlag(withBaseUrl(reviewRequest.command("pull <automation-id> <review-id>"))).description("Download review snapshots: per-example expected files (snapshot or reviewer-corrected) plus item JSON.").requiredOption("--out <dir>", "Local directory to materialize the review into").addHelpText("after", `
210599
+ Examples:
210600
+ $ eigenpal workflow dataset review-request pull wf_abc123 dsr_... --out ./review-dsr
210601
+ $ eigenpal workflow dataset review-request pull wf_abc123 dsr_... --out ./review-dsr --json
210602
+
210603
+ Layout (mirrors the dataset archive so reconcile is a copy):
210604
+ <out>/<example>/expected/<path> file bytes; reviewer-corrected when the
210605
+ item has an overlay entry, else the snapshot
210606
+ <out>/<example>/item.json full item payload (status, expected JSON,
210607
+ currentExpectedFiles, fileDecisions)
210608
+
210609
+ There is no write-back: copy approved/edited files and expected JSON into the
210610
+ live dataset example-by-example by hand (reviewers can err), then
210611
+ \`dataset push\`. \`reject\` is a recommendation only — nothing is deleted.
210612
+ `).action(action(async (automationRef, reviewId, opts) => {
210613
+ const { client, automationId } = await resolveAutomation(automationRef, opts);
210614
+ const detail = await client.get(datasetReviewRequestsPath(automationId, reviewId));
210615
+ const items = detail.items ?? [];
210616
+ const outDir = resolve(opts.out);
210617
+ const summary = [];
210618
+ let fileCount = 0;
210619
+ for (const item of items) {
210620
+ if (!item.id || !item.exampleName)
210621
+ continue;
210622
+ const exampleDir = join2(outDir, assertSafeReviewExampleName(item.exampleName));
210623
+ const expectedDir = join2(exampleDir, "expected");
210624
+ await mkdir(expectedDir, { recursive: true });
210625
+ await writeFile2(join2(exampleDir, "item.json"), JSON.stringify(item, null, 2));
210626
+ const paths = (item.currentExpectedFiles?.map((entry) => entry.path) ?? item.snapshotManifest?.expectedFiles?.map((entry) => entry.name) ?? []).filter((path) => !!path);
210627
+ const downloaded = [];
210628
+ for (const filePath of paths) {
210629
+ const encoded = encodeReviewFilePath(filePath);
210630
+ const res = await client.getStream(`${datasetReviewRequestItemsPath(automationId, reviewId, item.id)}/files/${encoded}?kind=expected`);
210631
+ const bytes = new Uint8Array(await res.arrayBuffer());
210632
+ const dest = resolve(expectedDir, ...filePath.split("/"));
210633
+ const rel = relative(expectedDir, dest);
210634
+ if (rel.startsWith("..") || isAbsolute(rel)) {
210635
+ throw new Error(`refusing to write outside ${expectedDir}: ${filePath}`);
210636
+ }
210637
+ await mkdir(dirname2(dest), { recursive: true });
210638
+ await writeFile2(dest, bytes);
210639
+ downloaded.push(filePath);
210640
+ fileCount += 1;
210641
+ }
210642
+ summary.push({
210643
+ exampleName: item.exampleName,
210644
+ itemId: item.id,
210645
+ status: item.status,
210646
+ files: downloaded
210647
+ });
210648
+ }
210649
+ if (opts.json) {
210650
+ return printJson2({ out: outDir, examples: summary, fileCount });
210651
+ }
210652
+ success(`Pulled ${fileCount} expected file${fileCount === 1 ? "" : "s"} ` + `across ${summary.length} example${summary.length === 1 ? "" : "s"} ` + `to ${ui.bold(outDir)}`);
210653
+ }));
210436
210654
  }
210437
210655
 
210438
210656
  // src/commands/agents/validation.ts
@@ -239835,7 +240053,7 @@ function extractXlsxComparableText(filePath) {
239835
240053
 
239836
240054
  // src/lib/execution-artifacts.ts
239837
240055
  import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
239838
- import { join as join4 } from "path";
240056
+ import { join as join5 } from "path";
239839
240057
 
239840
240058
  // src/lib/format.ts
239841
240059
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
@@ -239895,8 +240113,8 @@ function timestampFolderName(payload) {
239895
240113
  }
239896
240114
  async function writeExecutionArtifacts(client, exampleDir, payload) {
239897
240115
  const folderName = timestampFolderName(payload);
239898
- const executionsDir = join4(exampleDir, "executions", folderName);
239899
- const filesDir = join4(executionsDir, "files");
240116
+ const executionsDir = join5(exampleDir, "executions", folderName);
240117
+ const filesDir = join5(executionsDir, "files");
239900
240118
  mkdirSync4(filesDir, { recursive: true });
239901
240119
  const generatedFiles = [];
239902
240120
  const resultArtifacts = await listResultArtifacts(client, payload.executionId);
@@ -239912,7 +240130,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
239912
240130
  const disposition = res.headers.get("Content-Disposition");
239913
240131
  const filename = filenameFromContentDisposition(disposition) ?? name;
239914
240132
  const safe = safeFilename(filename, `file-${i}${filename.includes(".") ? "" : ".bin"}`);
239915
- const destPath = join4(filesDir, safe);
240133
+ const destPath = join5(filesDir, safe);
239916
240134
  const buf = Buffer.from(await res.arrayBuffer());
239917
240135
  writeFileSync6(destPath, buf);
239918
240136
  generatedFiles.push({
@@ -239938,7 +240156,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
239938
240156
  const disposition = res.headers.get("Content-Disposition");
239939
240157
  const filename = filenameFromContentDisposition(disposition) ?? fileId;
239940
240158
  const safe = safeFilename(filename, `file-${i}${filename.includes(".") ? "" : ".bin"}`);
239941
- const destPath = join4(filesDir, safe);
240159
+ const destPath = join5(filesDir, safe);
239942
240160
  const buf = Buffer.from(await res.arrayBuffer());
239943
240161
  writeFileSync6(destPath, buf);
239944
240162
  generatedFiles.push({ fileId, stepName, filename: safe });
@@ -239951,7 +240169,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
239951
240169
  ...payload,
239952
240170
  generatedFiles: generatedFiles.length > 0 ? generatedFiles : undefined
239953
240171
  };
239954
- const outputPath = join4(executionsDir, "output.json");
240172
+ const outputPath = join5(executionsDir, "output.json");
239955
240173
  writeFileSync6(outputPath, JSON.stringify(output, null, 2) + `
239956
240174
  `, "utf-8");
239957
240175
  await formatFileIfAvailable(outputPath);
@@ -240019,11 +240237,11 @@ function gradeAgainstExpected(expected, actual) {
240019
240237
 
240020
240238
  // src/lib/payload.ts
240021
240239
  import { existsSync as existsSync11, readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
240022
- import { join as join6 } from "path";
240240
+ import { join as join7 } from "path";
240023
240241
 
240024
240242
  // src/lib/fs-helpers.ts
240025
240243
  init_src();
240026
- import { extname as extname3, join as join5 } from "path";
240244
+ import { extname as extname3, join as join6 } from "path";
240027
240245
  function guessMimeType(filename) {
240028
240246
  return mimeTypeForExtension(extname3(filename)) ?? "";
240029
240247
  }
@@ -240031,7 +240249,7 @@ function guessMimeType(filename) {
240031
240249
  // src/lib/payload.ts
240032
240250
  var DATASET_EXAMPLES_DIR = ["dataset", "examples"];
240033
240251
  function resolveEvalBaseDir(dir) {
240034
- const candidates = [join6(dir, ...DATASET_EXAMPLES_DIR), join6(...DATASET_EXAMPLES_DIR)];
240252
+ const candidates = [join7(dir, ...DATASET_EXAMPLES_DIR), join7(...DATASET_EXAMPLES_DIR)];
240035
240253
  for (const candidate of candidates) {
240036
240254
  if (existsSync11(candidate))
240037
240255
  return candidate;
@@ -242772,7 +242990,7 @@ import {
242772
242990
  statSync as statSync4,
242773
242991
  writeFileSync as writeFileSync7
242774
242992
  } from "node:fs";
242775
- import { dirname as dirname4, join as join7, relative as relative2, resolve as resolve5 } from "node:path";
242993
+ import { dirname as dirname5, join as join8, relative as relative3, resolve as resolve5 } from "node:path";
242776
242994
  import { fileURLToPath as fileURLToPath6 } from "node:url";
242777
242995
  var TEMPLATE_NAMES = [
242778
242996
  "blank",
@@ -242792,7 +243010,7 @@ function isValidProjectName(name) {
242792
243010
  return /^[a-z0-9][a-z0-9-_]*$/.test(name) && name.length <= 60;
242793
243011
  }
242794
243012
  function resolveTemplatesRoot() {
242795
- const here = dirname4(fileURLToPath6(import.meta.url));
243013
+ const here = dirname5(fileURLToPath6(import.meta.url));
242796
243014
  const srcCandidate = resolve5(here, "..", "..", "templates");
242797
243015
  if (existsSync15(srcCandidate))
242798
243016
  return srcCandidate;
@@ -242810,7 +243028,7 @@ async function init(name, opts) {
242810
243028
  const target = resolve5(process.cwd(), opts.dir ?? name);
242811
243029
  assertSafeTargetDir(target, opts.dir);
242812
243030
  if (existsSync15(target) && readdirSync4(target).length > 0) {
242813
- throw new Error(`Target directory ${relative2(process.cwd(), target)} exists and is not empty.`);
243031
+ throw new Error(`Target directory ${relative3(process.cwd(), target)} exists and is not empty.`);
242814
243032
  }
242815
243033
  let template;
242816
243034
  if (opts.template) {
@@ -242823,12 +243041,12 @@ async function init(name, opts) {
242823
243041
  } else {
242824
243042
  template = await promptForTemplate();
242825
243043
  }
242826
- const sourceRoot = join7(resolveTemplatesRoot(), template);
243044
+ const sourceRoot = join8(resolveTemplatesRoot(), template);
242827
243045
  if (!existsSync15(sourceRoot)) {
242828
243046
  throw new Error(`Template directory missing on disk: ${sourceRoot}`);
242829
243047
  }
242830
243048
  const written = copyTemplate(sourceRoot, target, name);
242831
- const targetDisplay = relative2(process.cwd(), target) || ".";
243049
+ const targetDisplay = relative3(process.cwd(), target) || ".";
242832
243050
  success(`Created ${written} files in ${ui.bold(`${targetDisplay}/`)}`);
242833
243051
  console.log("");
242834
243052
  info("Next steps:");
@@ -242867,15 +243085,15 @@ function copyTemplate(src, dst, projectName) {
242867
243085
  while (stack.length > 0) {
242868
243086
  const dir = stack.pop();
242869
243087
  for (const entry of readdirSync4(dir)) {
242870
- const sourcePath = join7(dir, entry);
242871
- const relativePath = relative2(src, sourcePath);
242872
- const targetPath = join7(dst, relativePath);
243088
+ const sourcePath = join8(dir, entry);
243089
+ const relativePath = relative3(src, sourcePath);
243090
+ const targetPath = join8(dst, relativePath);
242873
243091
  const stats = statSync4(sourcePath);
242874
243092
  if (stats.isDirectory()) {
242875
243093
  stack.push(sourcePath);
242876
243094
  continue;
242877
243095
  }
242878
- mkdirSync5(dirname4(targetPath), { recursive: true });
243096
+ mkdirSync5(dirname5(targetPath), { recursive: true });
242879
243097
  if (isTextFile(sourcePath)) {
242880
243098
  const text = readFileSync15(sourcePath, "utf-8").replaceAll(PLACEHOLDER, projectName);
242881
243099
  writeFileSync7(targetPath, text);
@@ -242957,7 +243175,7 @@ import { promises as fs16 } from "node:fs";
242957
243175
  // src/lib/upload-reusable-file.ts
242958
243176
  import { randomUUID } from "node:crypto";
242959
243177
  import { createReadStream } from "node:fs";
242960
- import { stat as stat2 } from "node:fs/promises";
243178
+ import { stat as stat3 } from "node:fs/promises";
242961
243179
  import path17 from "node:path";
242962
243180
 
242963
243181
  // src/lib/fetch-body.ts
@@ -243208,7 +243426,7 @@ async function uploadReusableFile(client, input) {
243208
243426
  async function resolveUploadSource(input) {
243209
243427
  const contentType = input.mimeType || guessMimeType(input.filename) || "application/octet-stream";
243210
243428
  if ("filePath" in input && input.filePath) {
243211
- const info = await stat2(input.filePath);
243429
+ const info = await stat3(input.filePath);
243212
243430
  if (!info.isFile()) {
243213
243431
  throw new Error(`Upload path is not a file: ${input.filePath}`);
243214
243432
  }
@@ -243763,7 +243981,7 @@ function parseInputFileSpecs(inputFile) {
243763
243981
  // src/lib/format-eigenpal.ts
243764
243982
  import { spawnSync as spawnSync5 } from "child_process";
243765
243983
  import { existsSync as existsSync16, readFileSync as readFileSync16 } from "fs";
243766
- import { join as join8, resolve as resolve6 } from "path";
243984
+ import { join as join9, resolve as resolve6 } from "path";
243767
243985
  var PRETTRC_NAMES = [
243768
243986
  ".prettierrc",
243769
243987
  ".prettierrc.json",
@@ -243776,11 +243994,11 @@ var PRETTRC_NAMES = [
243776
243994
  ];
243777
243995
  function hasPrettierConfig(cwd) {
243778
243996
  for (const name of PRETTRC_NAMES) {
243779
- if (existsSync16(join8(cwd, name)))
243997
+ if (existsSync16(join9(cwd, name)))
243780
243998
  return true;
243781
243999
  }
243782
244000
  try {
243783
- const pkgPath = join8(cwd, "package.json");
244001
+ const pkgPath = join9(cwd, "package.json");
243784
244002
  if (!existsSync16(pkgPath))
243785
244003
  return false;
243786
244004
  const raw = readFileSync16(pkgPath, "utf-8");
@@ -243930,73 +244148,73 @@ import {
243930
244148
  unlinkSync as unlinkSync2,
243931
244149
  writeFileSync as writeFileSync8
243932
244150
  } from "node:fs";
243933
- import { sep as PATH_SEP, dirname as dirname5, join as join10, relative as relative3, resolve as resolve7 } from "node:path";
244151
+ import { sep as PATH_SEP, dirname as dirname6, join as join11, relative as relative4, resolve as resolve7 } from "node:path";
243934
244152
  import { fileURLToPath as fileURLToPath7 } from "node:url";
243935
244153
 
243936
244154
  // src/commands/skill/tools.ts
243937
- import { join as join9 } from "node:path";
244155
+ import { join as join10 } from "node:path";
243938
244156
  var SKILL_NAME = "eigenpal";
243939
244157
  var TOOLS = [
243940
244158
  {
243941
244159
  id: "claude",
243942
244160
  label: "Claude Code",
243943
- relativePath: join9(".claude", "skills", SKILL_NAME),
244161
+ relativePath: join10(".claude", "skills", SKILL_NAME),
243944
244162
  detectPaths: [".claude", "CLAUDE.md"]
243945
244163
  },
243946
244164
  {
243947
244165
  id: "cursor",
243948
244166
  label: "Cursor",
243949
- relativePath: join9(".cursor", "skills", SKILL_NAME),
244167
+ relativePath: join10(".cursor", "skills", SKILL_NAME),
243950
244168
  detectPaths: [".cursor", ".cursorrules"]
243951
244169
  },
243952
244170
  {
243953
244171
  id: "codex",
243954
244172
  label: "Codex",
243955
- relativePath: join9(".codex", "skills", SKILL_NAME),
244173
+ relativePath: join10(".codex", "skills", SKILL_NAME),
243956
244174
  detectPaths: [".codex"]
243957
244175
  },
243958
244176
  {
243959
244177
  id: "gemini",
243960
244178
  label: "Gemini CLI",
243961
- relativePath: join9(".gemini", "skills", SKILL_NAME),
244179
+ relativePath: join10(".gemini", "skills", SKILL_NAME),
243962
244180
  detectPaths: [".gemini", "GEMINI.md"]
243963
244181
  },
243964
244182
  {
243965
244183
  id: "antigravity",
243966
244184
  label: "Antigravity",
243967
- relativePath: join9(".agent", "skills", SKILL_NAME),
244185
+ relativePath: join10(".agent", "skills", SKILL_NAME),
243968
244186
  detectPaths: [".agent"]
243969
244187
  },
243970
244188
  {
243971
244189
  id: "opencode",
243972
244190
  label: "OpenCode",
243973
- relativePath: join9(".opencode", "skills", SKILL_NAME),
244191
+ relativePath: join10(".opencode", "skills", SKILL_NAME),
243974
244192
  detectPaths: [".opencode"]
243975
244193
  },
243976
244194
  {
243977
244195
  id: "pi",
243978
244196
  label: "Pi",
243979
- relativePath: join9(".pi", "skills", SKILL_NAME),
244197
+ relativePath: join10(".pi", "skills", SKILL_NAME),
243980
244198
  detectPaths: [".pi"]
243981
244199
  },
243982
244200
  {
243983
244201
  id: "windsurf",
243984
244202
  label: "Windsurf",
243985
- relativePath: join9(".windsurf", "skills", SKILL_NAME),
244203
+ relativePath: join10(".windsurf", "skills", SKILL_NAME),
243986
244204
  detectPaths: [".windsurf", ".windsurfrules"]
243987
244205
  },
243988
244206
  {
243989
244207
  id: "github-copilot",
243990
244208
  label: "GitHub Copilot",
243991
- relativePath: join9(".github", "skills", SKILL_NAME),
244209
+ relativePath: join10(".github", "skills", SKILL_NAME),
243992
244210
  detectPaths: [
243993
- join9(".github", "copilot-instructions.md"),
243994
- join9(".github", "instructions"),
243995
- join9(".github", "prompts"),
243996
- join9(".github", "agents"),
243997
- join9(".github", "skills"),
243998
- join9(".github", "workflows", "copilot-setup-steps.yml"),
243999
- join9(".github", ".mcp.json")
244211
+ join10(".github", "copilot-instructions.md"),
244212
+ join10(".github", "instructions"),
244213
+ join10(".github", "prompts"),
244214
+ join10(".github", "agents"),
244215
+ join10(".github", "skills"),
244216
+ join10(".github", "workflows", "copilot-setup-steps.yml"),
244217
+ join10(".github", ".mcp.json")
244000
244218
  ]
244001
244219
  }
244002
244220
  ];
@@ -244004,7 +244222,7 @@ var TOOLS = [
244004
244222
  // src/commands/skill/index.ts
244005
244223
  var MANIFEST_NAME = ".eigenpal-manifest.json";
244006
244224
  function resolveSkillSource() {
244007
- const here = dirname5(fileURLToPath7(import.meta.url));
244225
+ const here = dirname6(fileURLToPath7(import.meta.url));
244008
244226
  const srcCandidate = resolve7(here, "..", "..", "skill");
244009
244227
  if (existsSync17(srcCandidate))
244010
244228
  return srcCandidate;
@@ -244016,7 +244234,7 @@ function resolveSkillSource() {
244016
244234
  ${distCandidate}`);
244017
244235
  }
244018
244236
  function defaultClaudeTarget() {
244019
- return join10(process.cwd(), TOOLS[0].relativePath);
244237
+ return join11(process.cwd(), TOOLS[0].relativePath);
244020
244238
  }
244021
244239
  function resolveSkillTarget(opts) {
244022
244240
  return opts.target ?? defaultClaudeTarget();
@@ -244044,12 +244262,12 @@ async function installSkill(opts) {
244044
244262
  let skipped = 0;
244045
244263
  let prompted = 0;
244046
244264
  for (const relativePath of sourceFiles) {
244047
- const sourcePath = join10(source, relativePath);
244048
- const targetPath = join10(target, relativePath);
244265
+ const sourcePath = join11(source, relativePath);
244266
+ const targetPath = join11(target, relativePath);
244049
244267
  const sourceBytes = templateSourceFile(relativePath, readFileSync17(sourcePath), cliVersion);
244050
244268
  const sourceHash = sha256(sourceBytes);
244051
244269
  if (!existsSync17(targetPath)) {
244052
- mkdirSync6(dirname5(targetPath), { recursive: true });
244270
+ mkdirSync6(dirname6(targetPath), { recursive: true });
244053
244271
  writeFileSync8(targetPath, sourceBytes);
244054
244272
  written += 1;
244055
244273
  continue;
@@ -244085,7 +244303,7 @@ async function installSkill(opts) {
244085
244303
  }
244086
244304
  const manifestEntries = [];
244087
244305
  for (const relativePath of sourceFiles) {
244088
- const targetPath = join10(target, relativePath);
244306
+ const targetPath = join11(target, relativePath);
244089
244307
  if (!existsSync17(targetPath))
244090
244308
  continue;
244091
244309
  manifestEntries.push({ path: relativePath, sha256: sha256(readFileSync17(targetPath)) });
@@ -244095,21 +244313,21 @@ async function installSkill(opts) {
244095
244313
  installedAt: new Date().toISOString(),
244096
244314
  files: manifestEntries
244097
244315
  };
244098
- writeFileSync8(join10(target, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
244316
+ writeFileSync8(join11(target, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
244099
244317
  `);
244100
- const displayTarget = relative3(process.cwd(), target) || target;
244318
+ const displayTarget = relative4(process.cwd(), target) || target;
244101
244319
  success(`Installed skill at ${ui.bold(displayTarget)} — ${written} written, ${skipped} unchanged${prompted > 0 ? `, ${prompted} prompted` : ""}.`);
244102
244320
  }
244103
244321
  async function uninstallSkill(opts) {
244104
244322
  const target = resolveSkillTarget(opts);
244105
244323
  const manifest = readManifest(target);
244106
244324
  if (!manifest) {
244107
- error2(`No manifest found at ${join10(target, MANIFEST_NAME)}; nothing to uninstall.`);
244325
+ error2(`No manifest found at ${join11(target, MANIFEST_NAME)}; nothing to uninstall.`);
244108
244326
  process.exit(1);
244109
244327
  }
244110
244328
  if (!opts.yes && isInteractiveStdout()) {
244111
244329
  const proceed = await ue({
244112
- message: `Remove ${manifest.files.length} files from ${relative3(process.cwd(), target) || target}?`,
244330
+ message: `Remove ${manifest.files.length} files from ${relative4(process.cwd(), target) || target}?`,
244113
244331
  initialValue: false
244114
244332
  });
244115
244333
  if (q(proceed) || !proceed) {
@@ -244139,9 +244357,9 @@ async function uninstallSkill(opts) {
244139
244357
  unlinkSync2(path);
244140
244358
  removed += 1;
244141
244359
  }
244142
- rmSync2(join10(target, MANIFEST_NAME), { force: true });
244360
+ rmSync2(join11(target, MANIFEST_NAME), { force: true });
244143
244361
  pruneEmptyDirs(target);
244144
- const displayTarget = relative3(process.cwd(), target) || target;
244362
+ const displayTarget = relative4(process.cwd(), target) || target;
244145
244363
  success(`Uninstalled skill from ${ui.bold(displayTarget)} — ${removed} removed${kept > 0 ? `, ${kept} user-edited kept` : ""}.`);
244146
244364
  }
244147
244365
  async function installSkillTools(opts) {
@@ -244200,14 +244418,14 @@ async function installSkillTools(opts) {
244200
244418
  for (const tool of toInstall) {
244201
244419
  await installSkill({
244202
244420
  source: opts.source,
244203
- target: join10(cwd, tool.relativePath),
244421
+ target: join11(cwd, tool.relativePath),
244204
244422
  force: opts.force,
244205
244423
  yes: opts.yes
244206
244424
  });
244207
244425
  }
244208
244426
  for (const tool of toUninstall) {
244209
244427
  await uninstallSkill({
244210
- target: join10(cwd, tool.relativePath),
244428
+ target: join11(cwd, tool.relativePath),
244211
244429
  yes: true
244212
244430
  });
244213
244431
  }
@@ -244271,7 +244489,7 @@ async function uninstallSkillTools(opts) {
244271
244489
  }
244272
244490
  for (const tool of targets) {
244273
244491
  await uninstallSkill({
244274
- target: join10(cwd, tool.relativePath),
244492
+ target: join11(cwd, tool.relativePath),
244275
244493
  yes: true
244276
244494
  });
244277
244495
  }
@@ -244279,7 +244497,7 @@ async function uninstallSkillTools(opts) {
244279
244497
  function listSkillTools(opts = {}) {
244280
244498
  const cwd = process.cwd();
244281
244499
  const rows = TOOLS.flatMap((tool) => {
244282
- const targetDir = join10(cwd, tool.relativePath);
244500
+ const targetDir = join11(cwd, tool.relativePath);
244283
244501
  const manifest = readManifest(targetDir);
244284
244502
  if (!manifest)
244285
244503
  return [];
@@ -244332,10 +244550,10 @@ function hintFor(tool, installed, detected) {
244332
244550
  return tool.relativePath;
244333
244551
  }
244334
244552
  function isInstalled(cwd, tool) {
244335
- return existsSync17(join10(cwd, tool.relativePath, MANIFEST_NAME));
244553
+ return existsSync17(join11(cwd, tool.relativePath, MANIFEST_NAME));
244336
244554
  }
244337
244555
  function isProjectUsing(cwd, tool) {
244338
- return tool.detectPaths.some((p) => existsSync17(join10(cwd, p)));
244556
+ return tool.detectPaths.some((p) => existsSync17(join11(cwd, p)));
244339
244557
  }
244340
244558
  function listFiles(root) {
244341
244559
  const out = [];
@@ -244343,8 +244561,8 @@ function listFiles(root) {
244343
244561
  while (stack.length > 0) {
244344
244562
  const dir = stack.pop();
244345
244563
  for (const entry of readdirSync5(dir)) {
244346
- const full = join10(dir, entry);
244347
- const rel = relative3(root, full);
244564
+ const full = join11(dir, entry);
244565
+ const rel = relative4(root, full);
244348
244566
  const stats = lstatSync(full);
244349
244567
  if (stats.isDirectory()) {
244350
244568
  stack.push(full);
@@ -244358,7 +244576,7 @@ function listFiles(root) {
244358
244576
  return out.sort();
244359
244577
  }
244360
244578
  function readManifest(target) {
244361
- const path = join10(target, MANIFEST_NAME);
244579
+ const path = join11(target, MANIFEST_NAME);
244362
244580
  if (!existsSync17(path))
244363
244581
  return null;
244364
244582
  try {
@@ -244369,7 +244587,7 @@ function readManifest(target) {
244369
244587
  }
244370
244588
  function readCliVersion() {
244371
244589
  try {
244372
- const here = dirname5(fileURLToPath7(import.meta.url));
244590
+ const here = dirname6(fileURLToPath7(import.meta.url));
244373
244591
  const candidates = [
244374
244592
  resolve7(here, "..", "..", "..", "package.json"),
244375
244593
  resolve7(here, "..", "..", "package.json"),
@@ -244393,7 +244611,7 @@ function pruneEmptyDirs(root) {
244393
244611
  const stack = [];
244394
244612
  const collect = (dir) => {
244395
244613
  for (const entry of readdirSync5(dir)) {
244396
- const full = join10(dir, entry);
244614
+ const full = join11(dir, entry);
244397
244615
  if (lstatSync(full).isDirectory())
244398
244616
  collect(full);
244399
244617
  }
@@ -244408,7 +244626,7 @@ function pruneEmptyDirs(root) {
244408
244626
  }
244409
244627
  }
244410
244628
  async function promptThreeWay(path, source, current) {
244411
- const display = relative3(process.cwd(), path) || path;
244629
+ const display = relative4(process.cwd(), path) || path;
244412
244630
  while (true) {
244413
244631
  const choice = await Ee({
244414
244632
  message: `${display} has been edited locally`,
@@ -245191,7 +245409,7 @@ import path19 from "node:path";
245191
245409
  // src/lib/local-templates.ts
245192
245410
  init_src();
245193
245411
  import { existsSync as existsSync18, promises as fs18, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
245194
- import { basename, dirname as dirname6, isAbsolute, relative as relative4, resolve as resolve8, sep } from "node:path";
245412
+ import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute2, relative as relative5, resolve as resolve8, sep } from "node:path";
245195
245413
 
245196
245414
  // src/lib/office-template.ts
245197
245415
  import { createHash as createHash6 } from "node:crypto";
@@ -245436,11 +245654,11 @@ function resolveWorkflowProjectRoot(workflowFile) {
245436
245654
  if (!existsSync18(abs)) {
245437
245655
  throw new Error(`Workflow file not found: ${abs}`);
245438
245656
  }
245439
- return dirname6(realpathSync3(abs));
245657
+ return dirname7(realpathSync3(abs));
245440
245658
  }
245441
245659
  function isPathInsideRoot(root, target) {
245442
- const rel = relative4(root, target);
245443
- return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
245660
+ const rel = relative5(root, target);
245661
+ return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute2(rel);
245444
245662
  }
245445
245663
  function assertInsideProject(projectRoot, templatePath, resolved) {
245446
245664
  if (isPathInsideRoot(projectRoot, resolved))
@@ -245495,12 +245713,12 @@ async function loadLocalTemplatesForPush(workflowFile, parsedSteps, opts = {}) {
245495
245713
  }
245496
245714
  const absolutePath = resolveWorkflowTemplatePath(workflowFile, ref.templatePath, opts);
245497
245715
  const bytes = await fs18.readFile(absolutePath);
245498
- inspectOfficeTemplateBytes(bytes, basename(absolutePath));
245716
+ inspectOfficeTemplateBytes(bytes, basename2(absolutePath));
245499
245717
  const row = {
245500
245718
  path: ref.templatePath,
245501
245719
  fieldPath: ref.fieldPath,
245502
245720
  absolutePath,
245503
- filename: basename(absolutePath),
245721
+ filename: basename2(absolutePath),
245504
245722
  bytes,
245505
245723
  sha256: sha256Hex(bytes)
245506
245724
  };
@@ -245639,12 +245857,12 @@ function rewriteLocalTemplateYaml(yamlText, resolved) {
245639
245857
 
245640
245858
  // src/commands/workflow/clear.ts
245641
245859
  import { existsSync as existsSync19, readdirSync as readdirSync6, rmSync as rmSync3, statSync as statSync6 } from "fs";
245642
- import { basename as basename2, join as join11 } from "path";
245860
+ import { basename as basename3, join as join12 } from "path";
245643
245861
  var EMPTY_REPORT = { removed: 0, kept: 0, touched: 0 };
245644
245862
  function getDirectoryEntries(path) {
245645
245863
  if (!existsSync19(path))
245646
245864
  return [];
245647
- return readdirSync6(path).filter((entry) => statSync6(join11(path, entry)).isDirectory()).sort();
245865
+ return readdirSync6(path).filter((entry) => statSync6(join12(path, entry)).isDirectory()).sort();
245648
245866
  }
245649
245867
  function removeDirEntriesWithRetention(path, removeAll) {
245650
245868
  const entries = getDirectoryEntries(path);
@@ -245657,7 +245875,7 @@ function removeDirEntriesWithRetention(path, removeAll) {
245657
245875
  for (const entry of entries) {
245658
245876
  if (keepSet.has(entry))
245659
245877
  continue;
245660
- rmSync3(join11(path, entry), { recursive: true, force: true });
245878
+ rmSync3(join12(path, entry), { recursive: true, force: true });
245661
245879
  removed++;
245662
245880
  }
245663
245881
  return { removed, kept: keepSet.size, touched: entries.length };
@@ -245684,7 +245902,7 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
245684
245902
  kept++;
245685
245903
  continue;
245686
245904
  }
245687
- rmSync3(join11(exampleDir, fileName), { force: true });
245905
+ rmSync3(join12(exampleDir, fileName), { force: true });
245688
245906
  removed++;
245689
245907
  }
245690
245908
  return { removed, kept, touched: stampByFile.size };
@@ -245692,17 +245910,17 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
245692
245910
  function getTargetExampleDirs(dir, exampleNames) {
245693
245911
  const baseDir = resolveEvalBaseDir(dir);
245694
245912
  if (!baseDir) {
245695
- error2(`No dataset/examples directory at ${join11(dir, "dataset", "examples")}`);
245913
+ error2(`No dataset/examples directory at ${join12(dir, "dataset", "examples")}`);
245696
245914
  process.exit(1);
245697
245915
  }
245698
- const all = readdirSync6(baseDir).filter((entry) => statSync6(join11(baseDir, entry)).isDirectory());
245916
+ const all = readdirSync6(baseDir).filter((entry) => statSync6(join12(baseDir, entry)).isDirectory());
245699
245917
  if (exampleNames.length === 0)
245700
- return all.map((name) => join11(baseDir, name));
245918
+ return all.map((name) => join12(baseDir, name));
245701
245919
  const matched = all.filter((name) => exampleNames.includes(name));
245702
245920
  if (matched.length === 0) {
245703
245921
  warn(`None of [${exampleNames.join(", ")}] match an example under ./dataset/examples/. ` + `Heads up: the \`clear-local\` positional changed — it used to take a workflow slug, ` + `now it takes example names (or omit to clean every example).`);
245704
245922
  }
245705
- return matched.map((name) => join11(baseDir, name));
245923
+ return matched.map((name) => join12(baseDir, name));
245706
245924
  }
245707
245925
  function runSection(args) {
245708
245926
  let removed = 0;
@@ -245718,7 +245936,7 @@ function runSection(args) {
245718
245936
  kept += report.kept;
245719
245937
  touched += report.touched;
245720
245938
  if (report.touched > 0) {
245721
- const name = basename2(exampleDir);
245939
+ const name = basename3(exampleDir);
245722
245940
  console.log(` ${ui.dim(`${name}:`)} removed ${ui.bold(String(report.removed))} ${args.perExampleNoun}, kept ${report.kept}`);
245723
245941
  }
245724
245942
  }
@@ -245734,8 +245952,8 @@ async function clearEvalOutputs(dir, exampleNames = [], options = {}) {
245734
245952
  const exampleDirs = getTargetExampleDirs(dir, exampleNames);
245735
245953
  runSection({
245736
245954
  exampleDirs,
245737
- clean: (exampleDir) => removeDirEntriesWithRetention(join11(exampleDir, "executions"), removeAll),
245738
- shouldCount: (exampleDir) => existsSync19(join11(exampleDir, "executions")),
245955
+ clean: (exampleDir) => removeDirEntriesWithRetention(join12(exampleDir, "executions"), removeAll),
245956
+ shouldCount: (exampleDir) => existsSync19(join12(exampleDir, "executions")),
245739
245957
  successLabel: "Execution cleanup complete",
245740
245958
  scannedLabel: "examples scanned:",
245741
245959
  seenLabel: "runs seen: ",
@@ -246122,7 +246340,7 @@ function registerStepExecCommands(workflow) {
246122
246340
  // src/commands/workflow/templates.ts
246123
246341
  init_src();
246124
246342
  import { existsSync as existsSync20, promises as fs20 } from "node:fs";
246125
- import { basename as basename3, resolve as resolve9 } from "node:path";
246343
+ import { basename as basename4, resolve as resolve9 } from "node:path";
246126
246344
  function buildClient5(opts) {
246127
246345
  const config = resolveConfig(opts);
246128
246346
  requireApiKey(config);
@@ -246190,7 +246408,7 @@ function registerTemplateCommands(parent) {
246190
246408
  const client = buildClient5(opts);
246191
246409
  const template = await uploadWorkspaceTemplate(client, {
246192
246410
  bytes,
246193
- filename: basename3(filePath),
246411
+ filename: basename4(filePath),
246194
246412
  name: opts.name,
246195
246413
  description: opts.description
246196
246414
  });
@@ -246254,7 +246472,7 @@ function registerTemplateCommands(parent) {
246254
246472
  const bytes = await fs20.readFile(filePath);
246255
246473
  const client = buildClient5(opts);
246256
246474
  const current = await getPublicTemplate(client, templateId);
246257
- const nextInspection = inspectOfficeTemplateBytes(bytes, basename3(filePath));
246475
+ const nextInspection = inspectOfficeTemplateBytes(bytes, basename4(filePath));
246258
246476
  if (current.currentRevision?.sha256 === nextInspection.sha256 || current.sha256 === nextInspection.sha256) {
246259
246477
  if (opts.json) {
246260
246478
  printJson5({ ...current, reused: true });
@@ -246266,7 +246484,7 @@ function registerTemplateCommands(parent) {
246266
246484
  }
246267
246485
  const template = await replaceWorkspaceTemplate(client, templateId, {
246268
246486
  bytes,
246269
- filename: basename3(filePath)
246487
+ filename: basename4(filePath)
246270
246488
  });
246271
246489
  if (opts.json) {
246272
246490
  printJson5(template);
@@ -246306,7 +246524,7 @@ function registerTemplateCommands(parent) {
246306
246524
  throw new Error(`Template file not found: ${filePath}. Pass a local .docx/.xlsx path or a tmpl_… id.`);
246307
246525
  }
246308
246526
  bytes = await fs20.readFile(filePath);
246309
- filename = basename3(filePath);
246527
+ filename = basename4(filePath);
246310
246528
  }
246311
246529
  const rendered = renderLocalOfficeTemplate(bytes, filename, data);
246312
246530
  const { unresolved, unusedDataKeys } = compareTemplateDataKeys(rendered.inspection.tokens, Object.keys(data));
@@ -246345,7 +246563,7 @@ function registerTemplateCommands(parent) {
246345
246563
  // src/commands/workflow/validation.ts
246346
246564
  init_src();
246347
246565
  import { existsSync as existsSync22, readdirSync as readdirSync7, readFileSync as readFileSync19, statSync as statSync7 } from "fs";
246348
- import { join as join12, resolve as resolve10 } from "path";
246566
+ import { join as join13, resolve as resolve10 } from "path";
246349
246567
 
246350
246568
  // src/lib/template-diagnostics.ts
246351
246569
  init_src();
@@ -246752,19 +246970,19 @@ function validateDatasetFolder(root) {
246752
246970
  if (!existsSync22(root)) {
246753
246971
  return [{ field: root, message: "Folder not found." }];
246754
246972
  }
246755
- if (existsSync22(join12(root, "manifest.json"))) {
246973
+ if (existsSync22(join13(root, "manifest.json"))) {
246756
246974
  issues.push({
246757
246975
  field: "manifest.json",
246758
246976
  message: "Top-level manifest.json is the legacy format. Re-export the dataset using the folder convention."
246759
246977
  });
246760
246978
  }
246761
- const examplesDir = join12(root, "examples");
246979
+ const examplesDir = join13(root, "examples");
246762
246980
  if (!existsSync22(examplesDir)) {
246763
246981
  issues.push({ field: "examples/", message: "No examples/ directory found at dataset root." });
246764
246982
  return issues;
246765
246983
  }
246766
246984
  for (const exampleName of readdirSync7(examplesDir)) {
246767
- const exampleFolder = join12(examplesDir, exampleName);
246985
+ const exampleFolder = join13(examplesDir, exampleName);
246768
246986
  if (!isDirSafe(exampleFolder, issues, `examples/${exampleName}`))
246769
246987
  continue;
246770
246988
  if (!NAME_RE.test(exampleName)) {
@@ -246774,7 +246992,7 @@ function validateDatasetFolder(root) {
246774
246992
  });
246775
246993
  continue;
246776
246994
  }
246777
- const inputJsonPath = join12(exampleFolder, "input.json");
246995
+ const inputJsonPath = join13(exampleFolder, "input.json");
246778
246996
  const hasInputJson = existsSync22(inputJsonPath);
246779
246997
  if (!hasInputJson) {
246780
246998
  issues.push({
@@ -246801,8 +247019,8 @@ function validateDatasetFolder(root) {
246801
247019
  });
246802
247020
  continue;
246803
247021
  }
246804
- const inputDir = join12(exampleFolder, "input");
246805
- if (existsSync22(join12(inputDir, "arguments.json"))) {
247022
+ const inputDir = join13(exampleFolder, "input");
247023
+ if (existsSync22(join13(inputDir, "arguments.json"))) {
246806
247024
  issues.push({
246807
247025
  field: `examples/${exampleName}/input/arguments.json`,
246808
247026
  message: "Legacy input/arguments.json is no longer accepted. Use input.json instead."
@@ -246817,8 +247035,8 @@ function validateDatasetFolder(root) {
246817
247035
  })) {
246818
247036
  issues.push(issue);
246819
247037
  }
246820
- const expectedDir = join12(exampleFolder, "expected");
246821
- const expectedJsonPath = join12(exampleFolder, "expected.json");
247038
+ const expectedDir = join13(exampleFolder, "expected");
247039
+ const expectedJsonPath = join13(exampleFolder, "expected.json");
246822
247040
  if (existsSync22(expectedDir)) {
246823
247041
  for (const entry of readdirSync7(expectedDir)) {
246824
247042
  if (entry === "output.json" || entry === "error.json") {
@@ -246828,7 +247046,7 @@ function validateDatasetFolder(root) {
246828
247046
  });
246829
247047
  continue;
246830
247048
  }
246831
- const sub = join12(expectedDir, entry);
247049
+ const sub = join13(expectedDir, entry);
246832
247050
  const field = `examples/${exampleName}/expected/${entry}`;
246833
247051
  let isDir;
246834
247052
  try {
@@ -246884,7 +247102,7 @@ function validateDatasetFolder(root) {
246884
247102
  } else {
246885
247103
  for (const issue of validateFileRefs2({
246886
247104
  refs: collectDatasetFileRefs(parsed),
246887
- filesRoot: join12(exampleFolder, "expected"),
247105
+ filesRoot: join13(exampleFolder, "expected"),
246888
247106
  root: "expected",
246889
247107
  fieldPrefix: `examples/${exampleName}/expected.json`
246890
247108
  })) {
@@ -246937,7 +247155,7 @@ function validateFileRefs2(args) {
246937
247155
  });
246938
247156
  continue;
246939
247157
  }
246940
- if (!existsSync22(join12(args.filesRoot, relative))) {
247158
+ if (!existsSync22(join13(args.filesRoot, relative))) {
246941
247159
  issues.push({
246942
247160
  field: `${args.fieldPrefix}:${ref.jsonPath}`,
246943
247161
  message: `Referenced file does not exist: ${ref.path}.`
@@ -246969,24 +247187,24 @@ async function onlineInvokeIssues(yamlText, opts) {
246969
247187
  }
246970
247188
  function discoverWorkflowProjectRoots(rootPath) {
246971
247189
  const root = resolve10(rootPath);
246972
- if (existsSync22(join12(root, "workflow.yaml")))
247190
+ if (existsSync22(join13(root, "workflow.yaml")))
246973
247191
  return [root];
246974
247192
  const candidates = [
246975
- join12(root, "eigenpal", "workflows"),
246976
- join12(root, "workflows"),
246977
- root.endsWith(join12("eigenpal", "workflows")) ? root : ""
247193
+ join13(root, "eigenpal", "workflows"),
247194
+ join13(root, "workflows"),
247195
+ root.endsWith(join13("eigenpal", "workflows")) ? root : ""
246978
247196
  ].filter(Boolean);
246979
247197
  for (const parent of candidates) {
246980
247198
  if (!existsSync22(parent) || !statSync7(parent).isDirectory())
246981
247199
  continue;
246982
- const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && existsSync22(join12(parent, entry.name, "workflow.yaml"))).map((entry) => join12(parent, entry.name)).sort();
247200
+ const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && existsSync22(join13(parent, entry.name, "workflow.yaml"))).map((entry) => join13(parent, entry.name)).sort();
246983
247201
  if (projects.length > 0)
246984
247202
  return projects;
246985
247203
  }
246986
247204
  return [];
246987
247205
  }
246988
247206
  async function validateProjectRoot(root, opts) {
246989
- const wfFile = join12(root, "workflow.yaml");
247207
+ const wfFile = join13(root, "workflow.yaml");
246990
247208
  const wfResult = validateWorkflowYaml(wfFile);
246991
247209
  const wfPath = relPath(root, wfFile);
246992
247210
  const wfOk = printIssues("workflow.yaml", wfPath, wfResult.issues);
@@ -246994,8 +247212,8 @@ async function validateProjectRoot(root, opts) {
246994
247212
  printSchemaQualityWarnings(wfPath, wfResult.warnings);
246995
247213
  printInvokeOnlineHint(wfResult.invokeStepCount, wfResult.templateStepCount, opts.online);
246996
247214
  }
246997
- const evOk = printIssues("evaluators.yaml", relPath(root, join12(root, "evaluators.yaml")), validateEvaluatorsYaml(join12(root, "evaluators.yaml")));
246998
- const dsOk = printIssues("dataset/", relPath(root, join12(root, "dataset")), validateDatasetFolder(join12(root, "dataset")));
247215
+ const evOk = printIssues("evaluators.yaml", relPath(root, join13(root, "evaluators.yaml")), validateEvaluatorsYaml(join13(root, "evaluators.yaml")));
247216
+ const dsOk = printIssues("dataset/", relPath(root, join13(root, "dataset")), validateDatasetFolder(join13(root, "dataset")));
246999
247217
  const templateOk = wfOk && existsSync22(wfFile) ? await runTemplateDiagnostics(wfFile, wfResult.steps, opts) : true;
247000
247218
  let onlineOk = true;
247001
247219
  if (wfOk && opts.online && existsSync22(wfFile)) {