@eigenpal/cli 0.5.6 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -467,6 +467,7 @@ actual) { ... }` declaration around your statements. Parameter order is
467
467
 
468
468
  - 71361fd: `workflow get-experiment-status --watch` now prints a per-example failure summary on stderr when the batch finishes with any failed/cancelled execution: example name, top-level error (truncated), and the exact `eigenpal execution get <exec-id>` command to drill into step-by-step detail. Removes the need for the agent to grep through a 1000-line JSON dump to find which example broke and why. `reference/debugging.md` documents the discovery path.
469
469
  - 71361fd: `eigenpal workflow get-experiment-status --watch` now polls until every execution in the batch reaches a terminal state (`completed` / `failed` / `cancelled`), then exits non-zero if any execution failed or was cancelled. Removes the need for agent-side polling loops that didn't notice all-terminal-already and kept ticking. Renders a one-line `N/M terminal (counts)` progress summary on stderr (in-place rewrite when stderr is a TTY), dumps the full JSON on stdout when done. `--interval <s>` and `--max-wait <s>` are configurable; defaults are 5s/30min.
470
+ - 04e4018: Harden hidden Git materialization commands for package-ref installs, frozen lockfile replay, dependency materialization, and source authoring smoke flows.
470
471
  - 71361fd: `install-skill`: multi-tool support via interactive multiselect.
471
472
  - Opens a `@clack/prompts` multiselect picker over supported agent tools
472
473
  (Claude Code, Cursor). Toggle on to install, toggle off to uninstall —
package/dist/cli.js CHANGED
@@ -181601,7 +181601,7 @@ import { fileURLToPath as fileURLToPath6 } from "url";
181601
181601
  // package.json
181602
181602
  var package_default = {
181603
181603
  name: "@eigenpal/cli",
181604
- version: "0.5.6",
181604
+ version: "0.5.7",
181605
181605
  description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
181606
181606
  keywords: [
181607
181607
  "eigenpal",
@@ -184102,7 +184102,20 @@ init_src();
184102
184102
  init_zod();
184103
184103
  var import_yaml2 = __toESM(require_dist(), 1);
184104
184104
  import { spawnSync as spawnSync2 } from "node:child_process";
184105
- import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, realpathSync, statSync } from "node:fs";
184105
+ import { createHash as createHash2 } from "node:crypto";
184106
+ import {
184107
+ existsSync as existsSync3,
184108
+ mkdirSync as mkdirSync2,
184109
+ mkdtempSync,
184110
+ readdirSync,
184111
+ readFileSync as readFileSync3,
184112
+ realpathSync,
184113
+ rmSync,
184114
+ statSync,
184115
+ writeFileSync as writeFileSync2
184116
+ } from "node:fs";
184117
+ import { mkdtemp } from "node:fs/promises";
184118
+ import { tmpdir } from "node:os";
184106
184119
  import path2 from "node:path";
184107
184120
  var SourceRepositorySchema = exports_external.object({
184108
184121
  gitRepositoryPath: exports_external.string(),
@@ -184122,12 +184135,28 @@ var ReleasesSchema = exports_external.object({
184122
184135
  packagePath: exports_external.string(),
184123
184136
  releases: exports_external.array(ReleaseSchema)
184124
184137
  });
184138
+ var CommitShaSchema = exports_external.string().regex(/^[0-9a-f]{40}$/);
184139
+ var InstallLockPackageSchema = exports_external.lazy(() => exports_external.object({
184140
+ packagePath: SourcePackagePathSchema,
184141
+ requestedRef: SourceVersionRefSchema,
184142
+ resolvedRef: exports_external.string().min(1),
184143
+ resolvedTag: exports_external.string().min(1).optional(),
184144
+ commit: CommitShaSchema,
184145
+ dependencies: exports_external.array(InstallLockPackageSchema)
184146
+ }));
184147
+ var InstallLockfileSchema = exports_external.object({
184148
+ lockfileVersion: exports_external.literal(1),
184149
+ eigenpalVersion: exports_external.string().min(1),
184150
+ inputHash: exports_external.string().min(1),
184151
+ root: InstallLockPackageSchema
184152
+ });
184125
184153
  var AuthCheckSchema = exports_external.object({
184126
184154
  ok: exports_external.literal(true),
184127
184155
  email: exports_external.string().email().nullable().optional(),
184128
184156
  name: exports_external.string().nullable().optional(),
184129
184157
  keyId: exports_external.string()
184130
184158
  });
184159
+ var INSTALL_LOCKFILE_NAME = "eigenpal.lock";
184131
184160
  function runGit(args, opts = {}) {
184132
184161
  const env2 = opts.config ? gitAuthEnv(opts.config, opts.env, opts.gitRemoteUrl) : { ...getProcessEnv(), ...opts.env };
184133
184162
  const result = spawnSync2("git", args, {
@@ -184187,6 +184216,11 @@ function sourcePathFromPackageRoot(gitRoot, packageRoot) {
184187
184216
  function resolveGitRoot(dir) {
184188
184217
  return gitOutput(["rev-parse", "--show-toplevel"], dir);
184189
184218
  }
184219
+ function isOrganizationSourceGitRoot(gitRoot) {
184220
+ if (!gitRoot)
184221
+ return false;
184222
+ return Boolean(gitOutput(["remote", "get-url", "origin"], gitRoot)?.match(/\/orgs\/[^/]+\.git$/));
184223
+ }
184190
184224
  function findNearestPackageRoot(startDir, gitRoot) {
184191
184225
  let current = path2.resolve(startDir);
184192
184226
  while (true) {
@@ -184238,6 +184272,250 @@ function releaseTagExists(gitRoot, packagePath, version2) {
184238
184272
  const tag = formatReleaseTag(pathToDottedPackageName(packagePath), version2);
184239
184273
  return gitOutput(["tag", "--list", tag], gitRoot) === tag;
184240
184274
  }
184275
+ function readPackageManifest(packageRoot) {
184276
+ return SourcePackageManifestSchema.parse(readYamlFile(path2.join(packageRoot, "eigenpal.yaml")));
184277
+ }
184278
+ function parsePackageRef(input) {
184279
+ const [rawPackage, rawRef, extra] = input.split("@");
184280
+ if (!rawPackage || extra !== undefined) {
184281
+ throw new Error("Package ref must be <package>[@latest|main|version|range|commit].");
184282
+ }
184283
+ const packagePath = resolvePackagePath(rawPackage);
184284
+ const ref = SourceVersionRefSchema.parse(rawRef || "latest");
184285
+ return { packagePath, ref };
184286
+ }
184287
+ function versionMatchesRange(version2, range) {
184288
+ const parts = semverParts(version2);
184289
+ if (!parts)
184290
+ return false;
184291
+ const rangeParts = range.replace("*", "x").split(".");
184292
+ if (String(parts[0]) !== rangeParts[0])
184293
+ return false;
184294
+ if (rangeParts.length === 2)
184295
+ return rangeParts[1] === "x";
184296
+ if (rangeParts.length !== 3)
184297
+ return false;
184298
+ if (rangeParts[1] === "x")
184299
+ return true;
184300
+ return String(parts[1]) === rangeParts[1];
184301
+ }
184302
+ function listLocalPackageReleases(gitRoot, packagePath) {
184303
+ const tagPrefix = `${pathToDottedPackageName(packagePath)}@`;
184304
+ const output = gitOutput(["tag", "--list", `${tagPrefix}*`], gitRoot) ?? "";
184305
+ return output.split(`
184306
+ `).map((tag) => tag.trim()).filter(Boolean).map((tag) => {
184307
+ const parsed = parseReleaseTag(tag);
184308
+ const commit = gitOutput(["rev-list", "-n", "1", tag], gitRoot) ?? "";
184309
+ return { tag, version: parsed.version, commit };
184310
+ }).sort((left, right) => compareSemverDesc(left.version, right.version));
184311
+ }
184312
+ async function listPackageReleases(input) {
184313
+ if (input.gitRoot) {
184314
+ const local = listLocalPackageReleases(input.gitRoot, input.packagePath);
184315
+ if (local.length > 0)
184316
+ return local;
184317
+ }
184318
+ const client = new ApiClient(input.config);
184319
+ return ReleasesSchema.parse(await client.get("/api/v1/source/releases", { packagePath: input.packagePath })).releases;
184320
+ }
184321
+ function hostedArchiveRequest(input) {
184322
+ const match = input.repository.remoteUrl.match(/^(.*)\/orgs\/([^/]+)\.git$/);
184323
+ if (!match)
184324
+ return null;
184325
+ const [, baseUrl, gitRepositoryPath] = match;
184326
+ return `${baseUrl}/export/orgs/${encodeURIComponent(gitRepositoryPath)}/${encodeURIComponent(input.ref)}/${input.packagePath}`;
184327
+ }
184328
+ async function resolvePackageRef(input) {
184329
+ if (input.ref === "main" || /^[0-9a-f]{40}$/.test(input.ref)) {
184330
+ if (!input.gitRoot) {
184331
+ throw new Error(`Source ref ${input.ref} requires a cloned organization source repository.`);
184332
+ }
184333
+ const commit = gitOutput(["rev-parse", input.ref], input.gitRoot);
184334
+ if (!commit)
184335
+ throw new Error(`Source ref ${input.ref} does not exist.`);
184336
+ return { requestedRef: input.ref, resolvedRef: input.ref, commit };
184337
+ }
184338
+ const releases = await listPackageReleases({
184339
+ config: input.config,
184340
+ gitRoot: input.gitRoot,
184341
+ packagePath: input.packagePath
184342
+ });
184343
+ const release = input.ref === "latest" ? sortReleasesNewestFirst(releases)[0] : /^\d+\.\d+\.\d+$/.test(input.ref) ? releases.find((candidate) => candidate.version === input.ref) : sortReleasesNewestFirst(releases).find((candidate) => versionMatchesRange(candidate.version, input.ref));
184344
+ if (!release) {
184345
+ throw new Error(`No release found for ${input.packagePath}@${input.ref}.`);
184346
+ }
184347
+ return {
184348
+ requestedRef: input.ref,
184349
+ resolvedRef: release.version,
184350
+ resolvedTag: release.tag,
184351
+ commit: release.commit || (input.gitRoot ? gitOutput(["rev-list", "-n", "1", release.tag], input.gitRoot) ?? "" : "")
184352
+ };
184353
+ }
184354
+ function archivePackage(input) {
184355
+ rmSync(input.outDir, { recursive: true, force: true });
184356
+ mkdirSync2(input.outDir, { recursive: true });
184357
+ const tarPath = path2.join(mkdtempSyncCompat("eigenpal-source-archive-"), "package.tar");
184358
+ try {
184359
+ runGit(["archive", "--format=tar", `--output=${tarPath}`, input.ref, input.packagePath], {
184360
+ cwd: input.gitRoot
184361
+ });
184362
+ const extract2 = spawnSync2("tar", ["-xf", tarPath, "--strip-components", String(input.packagePath.split("/").length)], {
184363
+ cwd: input.outDir,
184364
+ encoding: "utf8"
184365
+ });
184366
+ if (extract2.status !== 0)
184367
+ throw new Error(extract2.stderr.trim() || "tar extraction failed");
184368
+ } finally {
184369
+ rmSync(path2.dirname(tarPath), { recursive: true, force: true });
184370
+ }
184371
+ }
184372
+ async function tryHostedArchive(input) {
184373
+ const repository = input.repository ?? (input.gitRoot ? {
184374
+ gitRepositoryPath: "",
184375
+ remoteUrl: gitOutput(["remote", "get-url", "origin"], input.gitRoot) ?? ""
184376
+ } : null);
184377
+ if (!repository)
184378
+ return false;
184379
+ const url2 = hostedArchiveRequest({
184380
+ repository,
184381
+ ref: input.ref,
184382
+ packagePath: input.packagePath
184383
+ });
184384
+ if (!url2)
184385
+ return false;
184386
+ const response = await fetch(url2, {
184387
+ headers: { authorization: `Bearer ${requireApiKey(input.config)}` }
184388
+ }).catch(() => null);
184389
+ if (!response?.ok)
184390
+ return false;
184391
+ rmSync(input.outDir, { recursive: true, force: true });
184392
+ mkdirSync2(input.outDir, { recursive: true });
184393
+ const tarPath = path2.join(mkdtempSyncCompat("eigenpal-hosted-source-"), "package.tar");
184394
+ try {
184395
+ writeFileSync2(tarPath, Buffer.from(await response.arrayBuffer()));
184396
+ const extract2 = spawnSync2("tar", ["-xf", tarPath, "--strip-components", String(input.packagePath.split("/").length)], {
184397
+ cwd: input.outDir,
184398
+ encoding: "utf8"
184399
+ });
184400
+ if (extract2.status !== 0)
184401
+ throw new Error(extract2.stderr.trim() || "tar extraction failed");
184402
+ return true;
184403
+ } finally {
184404
+ rmSync(path2.dirname(tarPath), { recursive: true, force: true });
184405
+ }
184406
+ }
184407
+ function mkdtempSyncCompat(prefix) {
184408
+ return mkdtempSync(path2.join(tmpdir(), prefix));
184409
+ }
184410
+ function dependencyInstallPath(parentRoot, packagePath) {
184411
+ const modulesRoot = path2.resolve(parentRoot, "eigenpal_modules");
184412
+ const destination = path2.resolve(modulesRoot, packagePath);
184413
+ if (destination !== modulesRoot && !destination.startsWith(`${modulesRoot}${path2.sep}`)) {
184414
+ throw new Error(`Dependency path escapes eigenpal_modules: ${packagePath}`);
184415
+ }
184416
+ return destination;
184417
+ }
184418
+ function lockfileInputHash(input) {
184419
+ return createHash2("sha256").update(JSON.stringify(input)).digest("hex");
184420
+ }
184421
+ async function resolvePackageGraph(input) {
184422
+ const seen = input.seen ?? [];
184423
+ const key = `${input.packagePath}@${input.ref}`;
184424
+ if (seen.includes(key)) {
184425
+ throw new Error(`Dependency cycle detected: ${[...seen, key].join(" -> ")}`);
184426
+ }
184427
+ const resolved = await resolvePackageRef(input);
184428
+ const tempDir = await mkdtemp(path2.join(tmpdir(), "eigenpal-install-resolve-"));
184429
+ try {
184430
+ const packageRoot = path2.join(tempDir, "package");
184431
+ const ref = resolved.resolvedTag ?? resolved.resolvedRef;
184432
+ if (input.gitRoot) {
184433
+ archivePackage({
184434
+ gitRoot: input.gitRoot,
184435
+ ref,
184436
+ packagePath: input.packagePath,
184437
+ outDir: packageRoot
184438
+ });
184439
+ } else if (!await tryHostedArchive({
184440
+ config: input.config,
184441
+ repository: input.repository,
184442
+ ref,
184443
+ packagePath: input.packagePath,
184444
+ outDir: packageRoot
184445
+ })) {
184446
+ throw new Error(`Hosted source export unavailable for ${input.packagePath}@${ref}.`);
184447
+ }
184448
+ const manifest = readPackageManifest(packageRoot);
184449
+ const dependencies = "dependencies" in manifest ? Object.entries(manifest.dependencies ?? {}) : [];
184450
+ return {
184451
+ packagePath: input.packagePath,
184452
+ requestedRef: input.ref,
184453
+ resolvedRef: resolved.resolvedRef,
184454
+ ...resolved.resolvedTag ? { resolvedTag: resolved.resolvedTag } : {},
184455
+ commit: resolved.commit,
184456
+ dependencies: await Promise.all(dependencies.map(([dependencyName, version2]) => resolvePackageGraph({
184457
+ config: input.config,
184458
+ gitRoot: input.gitRoot,
184459
+ repository: input.repository,
184460
+ packagePath: workspaceDependencyNameToPackagePath(dependencyName),
184461
+ ref: SourceVersionRefSchema.parse(version2),
184462
+ seen: [...seen, key]
184463
+ })))
184464
+ };
184465
+ } finally {
184466
+ rmSync(tempDir, { recursive: true, force: true });
184467
+ }
184468
+ }
184469
+ async function materializeLockPackage(input) {
184470
+ const ref = input.lockPackage.resolvedTag ?? input.lockPackage.commit;
184471
+ const usedHostedArchive = await tryHostedArchive({
184472
+ config: input.config,
184473
+ gitRoot: input.gitRoot,
184474
+ repository: input.repository,
184475
+ ref,
184476
+ packagePath: input.lockPackage.packagePath,
184477
+ outDir: input.outDir
184478
+ });
184479
+ if (!usedHostedArchive) {
184480
+ if (!input.gitRoot) {
184481
+ throw new Error(`Hosted source export unavailable for ${input.lockPackage.packagePath}@${ref}.`);
184482
+ }
184483
+ warn(`Hosted source export unavailable for ${input.lockPackage.packagePath}; using local git archive.`);
184484
+ archivePackage({
184485
+ gitRoot: input.gitRoot,
184486
+ ref,
184487
+ packagePath: input.lockPackage.packagePath,
184488
+ outDir: input.outDir
184489
+ });
184490
+ }
184491
+ const occupied = new Set;
184492
+ for (const dependency of input.lockPackage.dependencies) {
184493
+ const dependencyPath = dependencyInstallPath(input.outDir, dependency.packagePath);
184494
+ if (occupied.has(dependencyPath)) {
184495
+ throw new Error(`Dependency conflict at ${dependencyPath}`);
184496
+ }
184497
+ occupied.add(dependencyPath);
184498
+ await materializeLockPackage({
184499
+ config: input.config,
184500
+ gitRoot: input.gitRoot,
184501
+ repository: input.repository,
184502
+ lockPackage: dependency,
184503
+ outDir: dependencyPath
184504
+ });
184505
+ }
184506
+ }
184507
+ function writeLockfile(lockfilePath, lockfile) {
184508
+ mkdirSync2(path2.dirname(lockfilePath), { recursive: true });
184509
+ writeFileSync2(lockfilePath, `${JSON.stringify(lockfile, null, 2)}
184510
+ `);
184511
+ }
184512
+ function readLockfile(lockfilePath) {
184513
+ const parsed = InstallLockfileSchema.safeParse(JSON.parse(readFileSync3(lockfilePath, "utf8")));
184514
+ if (!parsed.success) {
184515
+ throw new Error(`Invalid lockfile ${lockfilePath}: ${parsed.error.issues.map((issue2) => `${issue2.path.join(".")}: ${issue2.message}`).join("; ")}`);
184516
+ }
184517
+ return parsed.data;
184518
+ }
184241
184519
  function validatePackageReferences(input) {
184242
184520
  const errors3 = [];
184243
184521
  const dependencies = "dependencies" in input.manifest ? Object.entries(input.manifest.dependencies ?? {}) : [];
@@ -184440,7 +184718,12 @@ function gitCommandCreatesObjects(args) {
184440
184718
  "revert",
184441
184719
  "tag"
184442
184720
  ]);
184443
- return args.some((arg) => objectCreatingCommands.has(arg));
184721
+ const command = gitSubcommandFromArgs(args);
184722
+ if (!command)
184723
+ return false;
184724
+ if (command === "tag" && args.some((arg) => arg === "-l" || arg === "--list"))
184725
+ return false;
184726
+ return objectCreatingCommands.has(command);
184444
184727
  }
184445
184728
  function gitCwdFromArgs(args) {
184446
184729
  let cwd = process.cwd();
@@ -184452,6 +184735,25 @@ function gitCwdFromArgs(args) {
184452
184735
  }
184453
184736
  return cwd;
184454
184737
  }
184738
+ function gitSubcommandFromArgs(args) {
184739
+ const optionsWithValue = new Set(["-C", "-c", "--git-dir", "--work-tree", "--namespace"]);
184740
+ for (let i = 0;i < args.length; i += 1) {
184741
+ const arg = args[i];
184742
+ if (arg === "--")
184743
+ continue;
184744
+ if (optionsWithValue.has(arg)) {
184745
+ i += 1;
184746
+ continue;
184747
+ }
184748
+ if (arg.startsWith("--git-dir=") || arg.startsWith("--work-tree=") || arg.startsWith("--namespace=")) {
184749
+ continue;
184750
+ }
184751
+ if (arg.startsWith("-"))
184752
+ continue;
184753
+ return arg;
184754
+ }
184755
+ return null;
184756
+ }
184455
184757
  async function runGitPassthroughFromArgv(argv) {
184456
184758
  const gitIndex = argv.indexOf("git");
184457
184759
  const separatorIndex = argv.indexOf("--", gitIndex + 1);
@@ -184534,7 +184836,7 @@ function doctor(opts) {
184534
184836
  });
184535
184837
  }
184536
184838
  }
184537
- if (context.packageRoot) {
184839
+ if (context.packageRoot && context.packageRoot !== context.gitRoot) {
184538
184840
  const result = validatePackage(context.packageRoot);
184539
184841
  checks3.push({
184540
184842
  check: "package structure",
@@ -184763,15 +185065,312 @@ async function release(versionOrBump, dir, opts) {
184763
185065
  }
184764
185066
  async function sync(target, opts) {
184765
185067
  const context = resolveGitSourceContext({ dir: opts.dir });
185068
+ if (target?.includes("@")) {
185069
+ throw new Error("Sync always uses latest; do not pass a versioned target.");
185070
+ }
184766
185071
  const packagePath = target ? resolvePackagePath(target) : context.packagePath;
184767
185072
  if (!packagePath) {
184768
185073
  throw new Error("Pass an automation target or run sync inside a source package.");
184769
185074
  }
184770
- if (target?.includes("@")) {
184771
- throw new Error("Sync always uses latest; do not pass a versioned target.");
184772
- }
184773
185075
  await syncLatestAutomation(new ApiClient(resolveConfig(opts)), packagePath);
184774
185076
  }
185077
+ async function install(packageRef, opts) {
185078
+ const config2 = resolveConfig(opts);
185079
+ const context = resolveGitSourceContext();
185080
+ const sourceGitRoot = isOrganizationSourceGitRoot(context.gitRoot) ? context.gitRoot : null;
185081
+ if (sourceGitRoot)
185082
+ checkRepoVersion(sourceGitRoot, false);
185083
+ const installFromLock = async (lockfilePath, packageDestination, explicitRef, repository, expectedPackagePath, explicitGitRoot) => {
185084
+ const lockfile2 = readLockfile(lockfilePath);
185085
+ if (expectedPackagePath && lockfile2.root.packagePath !== expectedPackagePath) {
185086
+ throw new Error(`Lockfile root package ${lockfile2.root.packagePath} does not match requested package ${expectedPackagePath}.`);
185087
+ }
185088
+ const destination = explicitRef ? path2.resolve(opts.out ?? path2.basename(lockfile2.root.packagePath)) : packageDestination;
185089
+ if (!destination)
185090
+ throw new Error("No package context found for lockfile install.");
185091
+ const lockInstallGitRoot = explicitRef ? explicitGitRoot ?? sourceGitRoot : context.gitRoot;
185092
+ if (explicitRef) {
185093
+ await materializeLockPackage({
185094
+ config: config2,
185095
+ gitRoot: lockInstallGitRoot,
185096
+ repository,
185097
+ lockPackage: lockfile2.root,
185098
+ outDir: destination
185099
+ });
185100
+ writeLockfile(path2.join(destination, ".eigenpal", INSTALL_LOCKFILE_NAME), lockfile2);
185101
+ } else {
185102
+ rmSync(path2.join(destination, "eigenpal_modules"), { recursive: true, force: true });
185103
+ for (const dependency of lockfile2.root.dependencies) {
185104
+ await materializeLockPackage({
185105
+ config: config2,
185106
+ gitRoot: lockInstallGitRoot,
185107
+ repository,
185108
+ lockPackage: dependency,
185109
+ outDir: dependencyInstallPath(destination, dependency.packagePath)
185110
+ });
185111
+ }
185112
+ }
185113
+ success2(`Installed from lockfile ${lockfilePath}.`);
185114
+ };
185115
+ if (opts.frozenLockfile) {
185116
+ const explicitRef = Boolean(packageRef);
185117
+ const expectedPackagePath = packageRef ? parsePackageRef(packageRef).packagePath : null;
185118
+ const explicitGitRoot = explicitRef && expectedPackagePath && context.gitRoot ? packageManifestExists(context.gitRoot, expectedPackagePath) ? context.gitRoot : sourceGitRoot : sourceGitRoot;
185119
+ const repository = explicitRef && !explicitGitRoot ? await getSourceRepository(config2) : null;
185120
+ const lockfilePath = opts.lockfile ?? path2.join(packageRef && opts.out ? path2.resolve(opts.out) : context.packageRoot ?? process.cwd(), ".eigenpal", INSTALL_LOCKFILE_NAME);
185121
+ await installFromLock(lockfilePath, context.packageRoot, explicitRef, repository, expectedPackagePath, explicitGitRoot);
185122
+ return;
185123
+ }
185124
+ if (packageRef) {
185125
+ const parsed = parsePackageRef(packageRef);
185126
+ const explicitGitRoot = context.gitRoot && packageManifestExists(context.gitRoot, parsed.packagePath) ? context.gitRoot : sourceGitRoot;
185127
+ const repository = explicitGitRoot ? null : await getSourceRepository(config2);
185128
+ if (parsed.ref === "main")
185129
+ warn("Installing @main uses draft source and is not reproducible.");
185130
+ const intendedLockfile2 = opts.lockfile ?? path2.join(path2.resolve(opts.out ?? path2.basename(parsed.packagePath)), ".eigenpal", INSTALL_LOCKFILE_NAME);
185131
+ const inputHash2 = lockfileInputHash({ packageRef });
185132
+ if (existsSync3(intendedLockfile2)) {
185133
+ const existing = readLockfile(intendedLockfile2);
185134
+ if (existing.inputHash !== inputHash2) {
185135
+ throw new Error(`Existing lockfile ${intendedLockfile2} does not match requested package ref.`);
185136
+ }
185137
+ await installFromLock(intendedLockfile2, null, true, repository, parsed.packagePath);
185138
+ return;
185139
+ }
185140
+ const lockRoot = await resolvePackageGraph({
185141
+ config: config2,
185142
+ gitRoot: explicitGitRoot,
185143
+ repository,
185144
+ packagePath: parsed.packagePath,
185145
+ ref: parsed.ref
185146
+ });
185147
+ const outDir = path2.resolve(opts.out ?? path2.basename(parsed.packagePath));
185148
+ await materializeLockPackage({
185149
+ config: config2,
185150
+ gitRoot: explicitGitRoot,
185151
+ repository,
185152
+ lockPackage: lockRoot,
185153
+ outDir
185154
+ });
185155
+ const lockfile2 = {
185156
+ lockfileVersion: 1,
185157
+ eigenpalVersion: "1.0.0",
185158
+ inputHash: inputHash2,
185159
+ root: lockRoot
185160
+ };
185161
+ writeLockfile(intendedLockfile2, lockfile2);
185162
+ success2(`Installed ${parsed.packagePath}@${lockRoot.resolvedRef} into ${outDir}.`);
185163
+ return;
185164
+ }
185165
+ if (!context.packageRoot || !context.packagePath) {
185166
+ throw new Error("Run git install inside a source package or pass a package ref.");
185167
+ }
185168
+ if (!context.gitRoot) {
185169
+ throw new Error("Run git install inside an organization source repository.");
185170
+ }
185171
+ const manifest = readPackageManifest(context.packageRoot);
185172
+ const dependencies = "dependencies" in manifest ? Object.entries(manifest.dependencies ?? {}) : [];
185173
+ const inputHash = lockfileInputHash({ packagePath: context.packagePath, dependencies });
185174
+ const intendedLockfile = opts.lockfile ?? path2.join(context.packageRoot, ".eigenpal", INSTALL_LOCKFILE_NAME);
185175
+ if (existsSync3(intendedLockfile)) {
185176
+ const existing = readLockfile(intendedLockfile);
185177
+ if (existing.inputHash !== inputHash) {
185178
+ throw new Error(`Existing lockfile ${intendedLockfile} does not match current package inputs.`);
185179
+ }
185180
+ await installFromLock(intendedLockfile, context.packageRoot, false);
185181
+ return;
185182
+ }
185183
+ const root = {
185184
+ packagePath: context.packagePath,
185185
+ requestedRef: "main",
185186
+ resolvedRef: "main",
185187
+ commit: gitOutput(["rev-parse", "HEAD"], context.gitRoot) ?? "",
185188
+ dependencies: await Promise.all(dependencies.map(([dependencyName, version2]) => resolvePackageGraph({
185189
+ config: config2,
185190
+ gitRoot: context.gitRoot,
185191
+ packagePath: workspaceDependencyNameToPackagePath(dependencyName),
185192
+ ref: SourceVersionRefSchema.parse(version2)
185193
+ })))
185194
+ };
185195
+ rmSync(path2.join(context.packageRoot, "eigenpal_modules"), { recursive: true, force: true });
185196
+ for (const dependency of root.dependencies) {
185197
+ await materializeLockPackage({
185198
+ config: config2,
185199
+ gitRoot: context.gitRoot,
185200
+ lockPackage: dependency,
185201
+ outDir: dependencyInstallPath(context.packageRoot, dependency.packagePath)
185202
+ });
185203
+ }
185204
+ const lockfile = {
185205
+ lockfileVersion: 1,
185206
+ eigenpalVersion: "1.0.0",
185207
+ inputHash,
185208
+ root
185209
+ };
185210
+ writeLockfile(intendedLockfile, lockfile);
185211
+ success2(`Installed ${root.dependencies.length} dependencies for ${context.packagePath}.`);
185212
+ }
185213
+ function slugifyPackageSegment(value) {
185214
+ return value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
185215
+ }
185216
+ function packagePathForTemplate(template2, name) {
185217
+ const slug = slugifyPackageSegment(name);
185218
+ if (!slug)
185219
+ throw new Error("Package name must include at least one letter or number.");
185220
+ const rootByTemplate = {
185221
+ agent: "agents",
185222
+ workflow: "workflows",
185223
+ skill: "resources/skills",
185224
+ rule: "resources/rules",
185225
+ knowledge: "resources/knowledge",
185226
+ evaluator: "evaluators"
185227
+ };
185228
+ const root = rootByTemplate[template2];
185229
+ if (!root)
185230
+ throw new Error("Template must be agent, workflow, skill, rule, knowledge, or evaluator.");
185231
+ return SourcePackagePathSchema.parse(`${root}/${slug}`);
185232
+ }
185233
+ function writePackageScaffold(packageRoot, packagePath, name) {
185234
+ const [root, resourceKind] = packagePath.split("/");
185235
+ mkdirSync2(packageRoot, { recursive: true });
185236
+ const title = name.trim();
185237
+ writeFileSync2(path2.join(packageRoot, "eigenpal.yaml"), import_yaml2.default.stringify({ schemaVersion: 1, name: title || path2.basename(packagePath) }));
185238
+ if (root === "agents")
185239
+ writeFileSync2(path2.join(packageRoot, "AGENT.md"), `# ${title}
185240
+
185241
+ `);
185242
+ if (root === "evaluators") {
185243
+ writeFileSync2(path2.join(packageRoot, "evaluator.yaml"), import_yaml2.default.stringify({ schemaVersion: 1, type: "exact-diff", config: {} }));
185244
+ }
185245
+ if (root === "resources" && resourceKind === "skills") {
185246
+ writeFileSync2(path2.join(packageRoot, "SKILL.md"), `# ${title}
185247
+
185248
+ `);
185249
+ }
185250
+ if (root === "resources" && (resourceKind === "rules" || resourceKind === "knowledge")) {
185251
+ writeFileSync2(path2.join(packageRoot, "README.md"), `# ${title}
185252
+
185253
+ `);
185254
+ }
185255
+ }
185256
+ function initPackage(name, opts) {
185257
+ const startDir = path2.resolve(opts.dir ?? process.cwd());
185258
+ const gitRoot = resolveGitRoot(startDir) ?? startDir;
185259
+ mkdirSync2(gitRoot, { recursive: true });
185260
+ if (!existsSync3(path2.join(gitRoot, ".git")))
185261
+ runGit(["init", "-b", "main", gitRoot]);
185262
+ if (!existsSync3(path2.join(gitRoot, "eigenpal.yaml"))) {
185263
+ writeFileSync2(path2.join(gitRoot, "eigenpal.yaml"), `schemaVersion: 1
185264
+ eigenpalVersion: 1.0.0
185265
+ `);
185266
+ }
185267
+ const gitignorePath = path2.join(gitRoot, ".gitignore");
185268
+ const gitignore = existsSync3(gitignorePath) ? readFileSync3(gitignorePath, "utf8") : "";
185269
+ const additions = [".eigenpal/", "eigenpal_modules/"].filter((entry) => !gitignore.includes(entry));
185270
+ if (additions.length > 0)
185271
+ writeFileSync2(gitignorePath, `${gitignore}${gitignore.endsWith(`
185272
+ `) || !gitignore ? "" : `
185273
+ `}${additions.join(`
185274
+ `)}
185275
+ `);
185276
+ const packagePath = packagePathForTemplate(opts.template, name);
185277
+ const packageRoot = path2.join(gitRoot, packagePath);
185278
+ if (existsSync3(packageRoot))
185279
+ throw new Error(`Package already exists: ${packagePath}`);
185280
+ writePackageScaffold(packageRoot, packagePath, name);
185281
+ success2(`Created ${packagePath}.`);
185282
+ }
185283
+ async function pullSource(opts) {
185284
+ const config2 = resolveConfig(opts);
185285
+ const context = resolveGitSourceContext({ dir: opts.dir });
185286
+ if (!context.gitRoot)
185287
+ throw new Error("Not inside a Git repository.");
185288
+ const remoteUrl = gitOutput(["remote", "get-url", "origin"], context.gitRoot);
185289
+ runGit(["pull", "--ff-only", "origin", "main"], {
185290
+ cwd: context.gitRoot,
185291
+ config: config2,
185292
+ gitRemoteUrl: remoteUrl ?? undefined
185293
+ });
185294
+ }
185295
+ function dirtyPackagePaths(gitRoot) {
185296
+ const status = gitOutput(["status", "--porcelain", "--untracked-files=all"], gitRoot) ?? "";
185297
+ const packagePaths = new Set;
185298
+ for (const line of status.split(`
185299
+ `)) {
185300
+ const file2 = line.slice(2).trim().split(" -> ").pop().replace(/\\/g, "/");
185301
+ const parts = file2.split("/");
185302
+ for (let index = parts.length;index >= 2; index -= 1) {
185303
+ const candidate = parts.slice(0, index).join("/");
185304
+ if (SourcePackagePathSchema.safeParse(candidate).success && existsSync3(path2.join(gitRoot, candidate, "eigenpal.yaml"))) {
185305
+ packagePaths.add(candidate);
185306
+ break;
185307
+ }
185308
+ }
185309
+ }
185310
+ return [...packagePaths].sort();
185311
+ }
185312
+ async function commitSource(opts) {
185313
+ if (!opts.message)
185314
+ throw new Error("Commit requires -m <message>.");
185315
+ const config2 = resolveConfig(opts);
185316
+ const context = resolveGitSourceContext({ dir: opts.dir });
185317
+ if (!context.gitRoot)
185318
+ throw new Error("Not inside a Git repository.");
185319
+ checkRepoVersion(context.gitRoot, true);
185320
+ const packagePaths = dirtyPackagePaths(context.gitRoot);
185321
+ if (packagePaths.length === 0) {
185322
+ warn("No source package changes to commit.");
185323
+ return;
185324
+ }
185325
+ for (const packagePath of packagePaths) {
185326
+ const validation = validatePackage(path2.join(context.gitRoot, packagePath));
185327
+ if (!validation.valid) {
185328
+ throw new Error(`Package validation failed for ${packagePath}: ${validation.errors.join("; ")}`);
185329
+ }
185330
+ }
185331
+ const rootFiles = ["eigenpal.yaml", ".gitignore"].filter((file2) => existsSync3(path2.join(context.gitRoot, file2)));
185332
+ runGit(["add", ...rootFiles, ...packagePaths], { cwd: context.gitRoot });
185333
+ const authorEnv = await resolveGitAuthorEnv(config2);
185334
+ runGit(["commit", "-m", opts.message], { cwd: context.gitRoot, env: authorEnv });
185335
+ }
185336
+ async function pushSource(opts) {
185337
+ const config2 = resolveConfig(opts);
185338
+ const context = resolveGitSourceContext({ dir: opts.dir });
185339
+ if (!context.gitRoot)
185340
+ throw new Error("Not inside a Git repository.");
185341
+ const remoteUrl = gitOutput(["remote", "get-url", "origin"], context.gitRoot);
185342
+ runGit(["push", "origin", "main", "--follow-tags"], {
185343
+ cwd: context.gitRoot,
185344
+ config: config2,
185345
+ gitRemoteUrl: remoteUrl ?? undefined
185346
+ });
185347
+ }
185348
+ function upgradeSource(opts) {
185349
+ const context = resolveGitSourceContext({ dir: opts.dir });
185350
+ if (!context.gitRoot)
185351
+ throw new Error("Not inside a Git repository.");
185352
+ const manifestPath = path2.join(context.gitRoot, "eigenpal.yaml");
185353
+ const manifest = readRootManifest(context.gitRoot);
185354
+ if (!manifest.ok)
185355
+ throw new Error(manifest.error);
185356
+ if (manifest.version === "1.0.0") {
185357
+ success2("Repository source schema is already 1.0.0.");
185358
+ return;
185359
+ }
185360
+ if (opts.dryRun) {
185361
+ console.log(`Would upgrade repository source schema from ${manifest.version} to 1.0.0.`);
185362
+ return;
185363
+ }
185364
+ console.log("Source repository changelog:");
185365
+ console.log(`- ${manifest.version} -> 1.0.0: normalize root eigenpal.yaml schema version.`);
185366
+ writeFileSync2(manifestPath, `schemaVersion: 1
185367
+ eigenpalVersion: 1.0.0
185368
+ `);
185369
+ doctor({
185370
+ dir: context.packagePath && context.packageRoot ? context.packageRoot : context.gitRoot
185371
+ });
185372
+ success2(`Upgraded repository source schema from ${manifest.version} to 1.0.0.`);
185373
+ }
184775
185374
  function parseReleaseVersion(value) {
184776
185375
  if (!/^\d+\.\d+\.\d+$/.test(value) && !["patch", "minor", "major"].includes(value)) {
184777
185376
  throw new InvalidArgumentError("version must be X.Y.Z, patch, minor, or major");
@@ -184783,9 +185382,21 @@ function parseType(value) {
184783
185382
  throw new InvalidArgumentError("type must be agent or workflow");
184784
185383
  return value;
184785
185384
  }
185385
+ function parseTemplate(value) {
185386
+ if (!["agent", "workflow", "skill", "rule", "knowledge", "evaluator"].includes(value)) {
185387
+ throw new InvalidArgumentError("template must be agent, workflow, skill, rule, knowledge, or evaluator");
185388
+ }
185389
+ return value;
185390
+ }
184786
185391
  function registerGitCommands(program2) {
184787
185392
  const git = program2.command("git", { hidden: true }).description("Experimental Git-backed source commands.").allowUnknownOption(true).allowExcessArguments(true).argument("[gitArgs...]", "Git arguments after --").action(action(async (gitArgs, opts) => gitPassthrough(gitArgs ?? [], opts)));
184788
185393
  withBaseUrl(git.command("clone")).description("Clone the organization source repository.").option("--out <dir>", "Output directory").action(action(cloneSource));
185394
+ withBaseUrl(git.command("install [packageRef]")).description("Materialize a source package and its workspace dependencies.").option("--out <dir>", "Output directory for an explicit package ref").option("--lockfile <path>", "Lockfile path").option("--frozen-lockfile", "Install exactly from the existing lockfile").action(action(install));
185395
+ git.command("init <name>").description("Create a new source package scaffold.").addOption(new Option("--template <template>", "Package template").argParser(parseTemplate).makeOptionMandatory()).option("--dir <dir>", "Repository directory").action(action(async (name, opts) => initPackage(name, opts)));
185396
+ withBaseUrl(git.command("pull")).description("Pull organization source from origin/main with --ff-only.").option("--dir <dir>", "Repository directory").action(action(pullSource));
185397
+ withBaseUrl(git.command("commit")).description("Validate changed source packages and commit them.").addOption(new Option("-m, --message <message>", "Commit message").makeOptionMandatory()).option("--dir <dir>", "Repository directory").action(action(commitSource));
185398
+ withBaseUrl(git.command("push")).description("Push organization source main and tags.").option("--dir <dir>", "Repository directory").action(action(pushSource));
185399
+ git.command("upgrade").description("Upgrade the source repository schema in place.").option("--dir <dir>", "Repository directory").option("--dry-run", "Print upgrade actions without changing files").action(action(async (opts) => upgradeSource(opts)));
184789
185400
  addJsonFlag(git.command("doctor")).description("Check organization source repository health.").option("--dir <dir>", "Directory to inspect").action(action(async (opts) => doctor(opts)));
184790
185401
  addJsonFlag(git.command("validate [dir]")).description("Validate the nearest source package.").action(action(async (dir, opts) => validate({ ...opts, dir })));
184791
185402
  addJsonFlag(git.command("status")).description("Show source repo and package status.").option("--dir <dir>", "Directory to inspect").action(action(async (opts) => packageStatus(opts)));
@@ -184803,11 +185414,11 @@ init_dist4();
184803
185414
  import {
184804
185415
  copyFileSync,
184805
185416
  existsSync as existsSync4,
184806
- mkdirSync as mkdirSync2,
185417
+ mkdirSync as mkdirSync3,
184807
185418
  readdirSync as readdirSync2,
184808
185419
  readFileSync as readFileSync4,
184809
185420
  statSync as statSync2,
184810
- writeFileSync as writeFileSync2
185421
+ writeFileSync as writeFileSync3
184811
185422
  } from "node:fs";
184812
185423
  import { dirname as dirname2, join as join2, relative, resolve } from "node:path";
184813
185424
  import { fileURLToPath } from "node:url";
@@ -184901,10 +185512,10 @@ function copyTemplate(src, dst, projectName) {
184901
185512
  stack.push(sourcePath);
184902
185513
  continue;
184903
185514
  }
184904
- mkdirSync2(dirname2(targetPath), { recursive: true });
185515
+ mkdirSync3(dirname2(targetPath), { recursive: true });
184905
185516
  if (isTextFile(sourcePath)) {
184906
185517
  const text = readFileSync4(sourcePath, "utf-8").replaceAll(PLACEHOLDER, projectName);
184907
- writeFileSync2(targetPath, text);
185518
+ writeFileSync3(targetPath, text);
184908
185519
  } else {
184909
185520
  copyFileSync(sourcePath, targetPath);
184910
185521
  }
@@ -184935,17 +185546,17 @@ function isTextFile(path3) {
184935
185546
 
184936
185547
  // src/commands/skill.ts
184937
185548
  init_dist4();
184938
- import { createHash as createHash2 } from "node:crypto";
185549
+ import { createHash as createHash3 } from "node:crypto";
184939
185550
  import {
184940
185551
  existsSync as existsSync5,
184941
185552
  lstatSync,
184942
- mkdirSync as mkdirSync3,
185553
+ mkdirSync as mkdirSync4,
184943
185554
  readFileSync as readFileSync5,
184944
185555
  readdirSync as readdirSync3,
184945
- rmSync,
185556
+ rmSync as rmSync2,
184946
185557
  rmdirSync,
184947
185558
  unlinkSync as unlinkSync2,
184948
- writeFileSync as writeFileSync3
185559
+ writeFileSync as writeFileSync4
184949
185560
  } from "node:fs";
184950
185561
  import { sep as PATH_SEP, dirname as dirname3, join as join3, relative as relative2, resolve as resolve2 } from "node:path";
184951
185562
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -185034,7 +185645,7 @@ function resolveSkillTarget(opts) {
185034
185645
  return opts.target ?? defaultClaudeTarget();
185035
185646
  }
185036
185647
  function sha256(buffer) {
185037
- return createHash2("sha256").update(buffer).digest("hex");
185648
+ return createHash3("sha256").update(buffer).digest("hex");
185038
185649
  }
185039
185650
  var CLI_VERSION_PLACEHOLDER = "__CLI_VERSION__";
185040
185651
  function templateSourceFile(relativePath, bytes, cliVersion) {
@@ -185061,8 +185672,8 @@ async function installSkill(opts) {
185061
185672
  const sourceBytes = templateSourceFile(relativePath, readFileSync5(sourcePath), cliVersion);
185062
185673
  const sourceHash = sha256(sourceBytes);
185063
185674
  if (!existsSync5(targetPath)) {
185064
- mkdirSync3(dirname3(targetPath), { recursive: true });
185065
- writeFileSync3(targetPath, sourceBytes);
185675
+ mkdirSync4(dirname3(targetPath), { recursive: true });
185676
+ writeFileSync4(targetPath, sourceBytes);
185066
185677
  written += 1;
185067
185678
  continue;
185068
185679
  }
@@ -185075,7 +185686,7 @@ async function installSkill(opts) {
185075
185686
  const previousEntry = existingManifest?.files.find((f) => f.path === relativePath);
185076
185687
  const userEdited = previousEntry ? previousEntry.sha256 !== targetHash : true;
185077
185688
  if (!userEdited || opts.force) {
185078
- writeFileSync3(targetPath, sourceBytes);
185689
+ writeFileSync4(targetPath, sourceBytes);
185079
185690
  written += 1;
185080
185691
  continue;
185081
185692
  }
@@ -185086,7 +185697,7 @@ async function installSkill(opts) {
185086
185697
  prompted += 1;
185087
185698
  const choice = await promptThreeWay(targetPath, sourceBytes, targetBytes);
185088
185699
  if (choice === "overwrite") {
185089
- writeFileSync3(targetPath, sourceBytes);
185700
+ writeFileSync4(targetPath, sourceBytes);
185090
185701
  written += 1;
185091
185702
  } else {
185092
185703
  skipped += 1;
@@ -185104,7 +185715,7 @@ async function installSkill(opts) {
185104
185715
  installedAt: new Date().toISOString(),
185105
185716
  files: manifestEntries
185106
185717
  };
185107
- writeFileSync3(join3(target, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
185718
+ writeFileSync4(join3(target, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
185108
185719
  `);
185109
185720
  const displayTarget = relative2(process.cwd(), target) || target;
185110
185721
  success2(`Installed skill at ${ui.bold(displayTarget)} — ${written} written, ${skipped} unchanged${prompted > 0 ? `, ${prompted} prompted` : ""}.`);
@@ -185146,7 +185757,7 @@ async function uninstallSkill(opts) {
185146
185757
  unlinkSync2(path3);
185147
185758
  removed += 1;
185148
185759
  }
185149
- rmSync(join3(target, MANIFEST_NAME), { force: true });
185760
+ rmSync2(join3(target, MANIFEST_NAME), { force: true });
185150
185761
  pruneEmptyDirs(target);
185151
185762
  const displayTarget = relative2(process.cwd(), target) || target;
185152
185763
  success2(`Uninstalled skill from ${ui.bold(displayTarget)} — ${removed} removed${kept > 0 ? `, ${kept} user-edited kept` : ""}.`);
@@ -186303,7 +186914,7 @@ async function resolveWorkflowId(client, idOrSlug) {
186303
186914
  }
186304
186915
 
186305
186916
  // src/commands/clear.ts
186306
- import { existsSync as existsSync8, readdirSync as readdirSync5, rmSync as rmSync2, statSync as statSync4 } from "fs";
186917
+ import { existsSync as existsSync8, readdirSync as readdirSync5, rmSync as rmSync3, statSync as statSync4 } from "fs";
186307
186918
  import { basename, join as join7 } from "path";
186308
186919
 
186309
186920
  // src/lib/payload.ts
@@ -186420,7 +187031,7 @@ function removeDirEntriesWithRetention(path3, removeAll) {
186420
187031
  for (const entry of entries) {
186421
187032
  if (keepSet.has(entry))
186422
187033
  continue;
186423
- rmSync2(join7(path3, entry), { recursive: true, force: true });
187034
+ rmSync3(join7(path3, entry), { recursive: true, force: true });
186424
187035
  removed++;
186425
187036
  }
186426
187037
  return { removed, kept: keepSet.size, touched: entries.length };
@@ -186447,7 +187058,7 @@ function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
186447
187058
  kept++;
186448
187059
  continue;
186449
187060
  }
186450
- rmSync2(join7(exampleDir, fileName), { force: true });
187061
+ rmSync3(join7(exampleDir, fileName), { force: true });
186451
187062
  removed++;
186452
187063
  }
186453
187064
  return { removed, kept, touched: stampByFile.size };
@@ -186643,11 +187254,11 @@ async function watchExecution(opts) {
186643
187254
  import { join as join11 } from "path";
186644
187255
 
186645
187256
  // src/lib/execution-artifacts.ts
186646
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
187257
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, readdirSync as readdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
186647
187258
  import { join as join10 } from "path";
186648
187259
 
186649
187260
  // src/lib/format.ts
186650
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
187261
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
186651
187262
  import { extname as extname3, resolve as resolve5 } from "path";
186652
187263
  var PRETTIER_EXTENSIONS = new Set([".json", ".yaml", ".yml"]);
186653
187264
  async function formatFileIfAvailable(filepath) {
@@ -186660,7 +187271,7 @@ async function formatFileIfAvailable(filepath) {
186660
187271
  filepath: resolve5(filepath)
186661
187272
  });
186662
187273
  if (formatted !== content) {
186663
- writeFileSync4(filepath, formatted, "utf-8");
187274
+ writeFileSync5(filepath, formatted, "utf-8");
186664
187275
  }
186665
187276
  } catch (err2) {
186666
187277
  if (env.DEBUG?.includes("prettier")) {
@@ -186694,7 +187305,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
186694
187305
  const folderName = timestampFolderName(payload);
186695
187306
  const executionsDir = join10(exampleDir, "executions", folderName);
186696
187307
  const filesDir = join10(executionsDir, "files");
186697
- mkdirSync4(filesDir, { recursive: true });
187308
+ mkdirSync5(filesDir, { recursive: true });
186698
187309
  const generatedFiles = [];
186699
187310
  const result = payload.result;
186700
187311
  if (isWorkflowResult2(result) && result.files.length > 0) {
@@ -186711,7 +187322,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
186711
187322
  const safe = safeFilename(filename, `file-${i5}${filename.includes(".") ? "" : ".bin"}`);
186712
187323
  const destPath = join10(filesDir, safe);
186713
187324
  const buf = Buffer.from(await res.arrayBuffer());
186714
- writeFileSync5(destPath, buf);
187325
+ writeFileSync6(destPath, buf);
186715
187326
  generatedFiles.push({ fileId, stepName, filename: safe });
186716
187327
  } catch (err2) {
186717
187328
  console.warn(` Warning: could not download file ${fileId}:`, err2);
@@ -186723,7 +187334,7 @@ async function writeExecutionArtifacts(client, exampleDir, payload) {
186723
187334
  generatedFiles: generatedFiles.length > 0 ? generatedFiles : undefined
186724
187335
  };
186725
187336
  const outputPath = join10(executionsDir, "output.json");
186726
- writeFileSync5(outputPath, JSON.stringify(output, null, 2) + `
187337
+ writeFileSync6(outputPath, JSON.stringify(output, null, 2) + `
186727
187338
  `, "utf-8");
186728
187339
  await formatFileIfAvailable(outputPath);
186729
187340
  return executionsDir;
@@ -2,212 +2,6 @@
2
2
 
3
3
  Experimental Git-backed source commands.
4
4
 
5
- ## Contents
5
+ Experimental.
6
6
 
7
- - [Surface](#surface)
8
- - [Commands](#commands)
9
- - [Core](#core)
10
- - [Details](#details)
11
- - [`eigenpal git clone [options]`](#eigenpal-git-clone-options)
12
- - [`eigenpal git doctor [options]`](#eigenpal-git-doctor-options)
13
- - [`eigenpal git validate [options] [dir]`](#eigenpal-git-validate-options-dir)
14
- - [`eigenpal git status [options]`](#eigenpal-git-status-options)
15
- - [`eigenpal git deps [options]`](#eigenpal-git-deps-options)
16
- - [`eigenpal git clean [options]`](#eigenpal-git-clean-options)
17
- - [`eigenpal git list|ls [options]`](#eigenpal-git-listls-options)
18
- - [`eigenpal git show [options] <automation>`](#eigenpal-git-show-options-automation)
19
- - [`eigenpal git versions [options] <package>`](#eigenpal-git-versions-options-package)
20
- - [`eigenpal git release [options] <version> [dir]`](#eigenpal-git-release-options-version-dir)
21
- - [`eigenpal git sync [options] [automation]`](#eigenpal-git-sync-options-automation)
22
-
23
- ## Surface
24
-
25
- ```
26
- git
27
- ├── clone
28
- ├── doctor
29
- ├── validate [dir]
30
- ├── status
31
- ├── deps
32
- ├── clean
33
- ├── list|ls
34
- ├── show <automation>
35
- ├── versions <package>
36
- ├── release <version> [dir]
37
- └── sync [automation]
38
- ```
39
-
40
- ## Commands
41
-
42
- ### Core
43
-
44
- | Command | Description |
45
- | ------------------------------------------------ | ------------------------------------------------------ | ---------------------------- |
46
- | `eigenpal git clone [options]` | Clone the organization source repository. |
47
- | `eigenpal git doctor [options]` | Check organization source repository health. |
48
- | `eigenpal git validate [options] [dir]` | Validate the nearest source package. |
49
- | `eigenpal git status [options]` | Show source repo and package status. |
50
- | `eigenpal git deps [options]` | List package workspace dependencies. |
51
- | `eigenpal git clean [options]` | Require a clean source working tree. |
52
- | `eigenpal git list | ls [options]` | List Git-backed automations. |
53
- | `eigenpal git show [options] <automation>` | Show Git-backed automation details. |
54
- | `eigenpal git versions [options] <package>` | List package release versions. |
55
- | `eigenpal git release [options] <version> [dir]` | Create and push a package release tag. |
56
- | `eigenpal git sync [options] [automation]` | Sync an automation from the latest Git source release. |
57
-
58
- ## Details
59
-
60
- ### `eigenpal git clone [options]`
61
-
62
- Clone the organization source repository.
63
-
64
- ### Options
65
-
66
- | Flag | Required | Default | Description |
67
- | ------------------ | -------- | ------- | ---------------- |
68
- | `--base-url <url>` | no | | Server base URL |
69
- | `--out <dir>` | no | | Output directory |
70
-
71
- ### `eigenpal git doctor [options]`
72
-
73
- Check organization source repository health.
74
-
75
- ### Options
76
-
77
- | Flag | Required | Default | Description |
78
- | ------------- | -------- | ------- | -------------------------------------- |
79
- | `--json` | no | | Output the raw server response as JSON |
80
- | `--dir <dir>` | no | | Directory to inspect |
81
-
82
- ### `eigenpal git validate [options] [dir]`
83
-
84
- Validate the nearest source package.
85
-
86
- ### Arguments
87
-
88
- | Name | Required | Variadic | Description |
89
- | ----- | -------- | -------- | ----------- |
90
- | `dir` | no | no | |
91
-
92
- ### Options
93
-
94
- | Flag | Required | Default | Description |
95
- | -------- | -------- | ------- | -------------------------------------- |
96
- | `--json` | no | | Output the raw server response as JSON |
97
-
98
- ### `eigenpal git status [options]`
99
-
100
- Show source repo and package status.
101
-
102
- ### Options
103
-
104
- | Flag | Required | Default | Description |
105
- | ------------- | -------- | ------- | -------------------------------------- |
106
- | `--json` | no | | Output the raw server response as JSON |
107
- | `--dir <dir>` | no | | Directory to inspect |
108
-
109
- ### `eigenpal git deps [options]`
110
-
111
- List package workspace dependencies.
112
-
113
- ### Options
114
-
115
- | Flag | Required | Default | Description |
116
- | ------------- | -------- | ------- | -------------------------------------- |
117
- | `--json` | no | | Output the raw server response as JSON |
118
- | `--dir <dir>` | no | | Directory to inspect |
119
-
120
- ### `eigenpal git clean [options]`
121
-
122
- Require a clean source working tree.
123
-
124
- ### Options
125
-
126
- | Flag | Required | Default | Description |
127
- | ------------- | -------- | ------- | -------------------- |
128
- | `--dir <dir>` | no | | Directory to inspect |
129
-
130
- ### `eigenpal git list|ls [options]`
131
-
132
- List Git-backed automations.
133
-
134
- ### Options
135
-
136
- | Flag | Required | Default | Description |
137
- | -------------------- | -------- | ------- | -------------------------------------- |
138
- | `--base-url <url>` | no | | Server base URL |
139
- | `--limit <n>` | no | `50` | Page size |
140
- | `--offset <n>` | no | `0` | Page offset |
141
- | `--json` | no | | Output the raw server response as JSON |
142
- | `--type <type>` | no | | Filter by automation type |
143
- | `--search <q>` | no | | Search by slug, name, or description |
144
- | `--include-archived` | no | | Include archived automations |
145
-
146
- ### `eigenpal git show [options] <automation>`
147
-
148
- Show Git-backed automation details.
149
-
150
- ### Arguments
151
-
152
- | Name | Required | Variadic | Description |
153
- | ------------ | -------- | -------- | ----------- |
154
- | `automation` | yes | no | |
155
-
156
- ### Options
157
-
158
- | Flag | Required | Default | Description |
159
- | ------------------ | -------- | ------- | -------------------------------------- |
160
- | `--base-url <url>` | no | | Server base URL |
161
- | `--json` | no | | Output the raw server response as JSON |
162
-
163
- ### `eigenpal git versions [options] <package>`
164
-
165
- List package release versions.
166
-
167
- ### Arguments
168
-
169
- | Name | Required | Variadic | Description |
170
- | --------- | -------- | -------- | ----------- |
171
- | `package` | yes | no | |
172
-
173
- ### Options
174
-
175
- | Flag | Required | Default | Description |
176
- | ------------------ | -------- | ------- | -------------------------------------- |
177
- | `--base-url <url>` | no | | Server base URL |
178
- | `--json` | no | | Output the raw server response as JSON |
179
-
180
- ### `eigenpal git release [options] <version> [dir]`
181
-
182
- Create and push a package release tag.
183
-
184
- ### Arguments
185
-
186
- | Name | Required | Variadic | Description |
187
- | --------- | -------- | -------- | --------------------- |
188
- | `version` | yes | no | Version or bump level |
189
- | `dir` | no | no | Package directory |
190
-
191
- ### Options
192
-
193
- | Flag | Required | Default | Description |
194
- | ------------------------- | -------- | ------- | --------------------- |
195
- | `--base-url <url>` | no | | Server base URL |
196
- | `-m, --message <message>` | yes | | Annotated tag message |
197
-
198
- ### `eigenpal git sync [options] [automation]`
199
-
200
- Sync an automation from the latest Git source release.
201
-
202
- ### Arguments
203
-
204
- | Name | Required | Variadic | Description |
205
- | ------------ | -------- | -------- | ----------- |
206
- | `automation` | no | no | |
207
-
208
- ### Options
209
-
210
- | Flag | Required | Default | Description |
211
- | ------------------ | -------- | ------- | -------------------- |
212
- | `--base-url <url>` | no | | Server base URL |
213
- | `--dir <dir>` | no | | Directory to inspect |
7
+ This command namespace is intentionally not documented in detail yet.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eigenpal/cli",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
4
  "description": "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
5
5
  "keywords": [
6
6
  "eigenpal",