@theholocron/cli 3.60.0 → 3.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -928,9 +928,15 @@ async function listOrgRepos(org, token, fetchFn) {
928
928
  }
929
929
  async function runClone(input) {
930
930
  const print = input.print ?? ((line) => console.log(line));
931
+ const logger = input.logger ?? getLogger();
931
932
  const fetchFn = input.fetch ?? globalThis.fetch;
932
933
  const dryRun = input.dryRun ?? false;
933
934
  const targetDir = resolve(input.dir ?? join(homedir(), "Code", input.org));
935
+ logger.info({
936
+ org: input.org,
937
+ targetDir,
938
+ dryRun: dryRun || void 0
939
+ }, "clone: start");
934
940
  const exec = input.exec ?? ((cmd, args, opts) => {
935
941
  return { status: spawnSync(cmd, args, {
936
942
  cwd: opts.cwd,
@@ -944,12 +950,17 @@ async function runClone(input) {
944
950
  try {
945
951
  repos = await listOrgRepos(input.org, input.token, fetchFn);
946
952
  } catch (err) {
953
+ const message = err instanceof Error ? err.message : String(err);
954
+ logger.warn({
955
+ org: input.org,
956
+ reason: message
957
+ }, "clone: failed to list org repos");
947
958
  return {
948
959
  status: "fail",
949
960
  cloned: 0,
950
961
  skipped: 0,
951
962
  failed: 0,
952
- message: err instanceof Error ? err.message : String(err)
963
+ message
953
964
  };
954
965
  }
955
966
  let cloned = 0;
@@ -997,8 +1008,16 @@ async function runClone(input) {
997
1008
  }
998
1009
  const summary = `${cloned} cloned, ${skipped} skipped, ${failed} failed`;
999
1010
  print(dryRun ? style.dim(`\n dry-run: ${summary}`) : failed > 0 ? style.fail(`\n ${summary}`) : style.success(`\n ${summary}`));
1011
+ const status = dryRun ? "dry-run" : failed > 0 ? "fail" : "ok";
1012
+ logger[failed > 0 ? "warn" : "info"]({
1013
+ org: input.org,
1014
+ status,
1015
+ cloned,
1016
+ skipped,
1017
+ failed
1018
+ }, "clone: done");
1000
1019
  return {
1001
- status: dryRun ? "dry-run" : failed > 0 ? "fail" : "ok",
1020
+ status,
1002
1021
  cloned,
1003
1022
  skipped,
1004
1023
  failed
@@ -1384,6 +1403,7 @@ async function runNew(input) {
1384
1403
  const cwd = input.cwd ?? process.cwd();
1385
1404
  const org = input.org ?? "theholocron";
1386
1405
  const print = input.print ?? ((line) => console.log(line));
1406
+ const logger = input.logger ?? getLogger();
1387
1407
  const execFn = input.exec ?? defaultExec$3;
1388
1408
  const readFn = input.readFile ?? defaultReadFile;
1389
1409
  const writeFn = input.writeFile ?? defaultWriteFile;
@@ -1392,6 +1412,11 @@ async function runNew(input) {
1392
1412
  const templateRepo = `${org}/${input.type}-template`;
1393
1413
  const newRepo = `${org}/${input.name}`;
1394
1414
  const repoDir = path.join(cwd, input.name);
1415
+ logger.info({
1416
+ repo: newRepo,
1417
+ template: templateRepo,
1418
+ dryRun: input.dryRun || void 0
1419
+ }, "new: start");
1395
1420
  if (input.dryRun) {
1396
1421
  print(` Would create ${newRepo} from template ${templateRepo}`);
1397
1422
  print(` Would clone to ${repoDir}`);
@@ -1400,6 +1425,10 @@ async function runNew(input) {
1400
1425
  if (input.homepage) print(` Would replace <homepage> → "${input.homepage}"`);
1401
1426
  if (input.runtimeEnvironment) print(` Would replace <runtime_environment> → "${input.runtimeEnvironment}"`);
1402
1427
  print(` Would generate holocron.config.ts`);
1428
+ logger.info({
1429
+ repo: newRepo,
1430
+ status: "dry-run"
1431
+ }, "new: done");
1403
1432
  return { status: "dry-run" };
1404
1433
  }
1405
1434
  if (existsSync(repoDir)) throw new NewError(`\`${repoDir}\` already exists — delete it or pick a different name.`);
@@ -1555,6 +1584,12 @@ async function runNew(input) {
1555
1584
  print(` 3. holocron setup # wire up secrets, teams, labels, etc.`);
1556
1585
  print(` 4. git push -u origin HEAD`);
1557
1586
  } else print(` 2. git push -u origin HEAD`);
1587
+ logger.info({
1588
+ repo: newRepo,
1589
+ repoDir,
1590
+ filesPatched,
1591
+ status: "ok"
1592
+ }, "new: done");
1558
1593
  return {
1559
1594
  status: "ok",
1560
1595
  repoDir,
@@ -1565,6 +1600,7 @@ async function runNew(input) {
1565
1600
  //#region src/commands/npm-bump-versions.ts
1566
1601
  async function runNpmBumpVersions(input) {
1567
1602
  const print = input.print ?? ((line) => console.log(line));
1603
+ const logger = input.logger ?? getLogger();
1568
1604
  const cwd = input.cwd ?? process.cwd();
1569
1605
  const { version, dryRun = false } = input;
1570
1606
  const readFile = input.readFile ?? ((p) => readFileSync(p, "utf8"));
@@ -1574,6 +1610,10 @@ async function runNpmBumpVersions(input) {
1574
1610
  const bumped = [];
1575
1611
  const skipped = [];
1576
1612
  print(`Bumping monorepo to ${version}${dryRun ? " (dry-run)" : ""}…`);
1613
+ logger.info({
1614
+ version,
1615
+ dryRun: dryRun || void 0
1616
+ }, "npm bump-versions: start");
1577
1617
  function bumpFile(absPath, label) {
1578
1618
  let pkg;
1579
1619
  try {
@@ -1596,8 +1636,15 @@ async function runNpmBumpVersions(input) {
1596
1636
  try {
1597
1637
  entries = listDir(packagesDir);
1598
1638
  } catch {
1639
+ const status = dryRun ? "dry-run" : "ok";
1640
+ logger.info({
1641
+ version,
1642
+ status,
1643
+ bumped: bumped.length,
1644
+ skipped: skipped.length
1645
+ }, "npm bump-versions: done");
1599
1646
  return {
1600
- status: dryRun ? "dry-run" : "ok",
1647
+ status,
1601
1648
  bumped,
1602
1649
  skipped
1603
1650
  };
@@ -1624,8 +1671,15 @@ async function runNpmBumpVersions(input) {
1624
1671
  }
1625
1672
  bumpFile(pkgFile, `packages/${entry}`);
1626
1673
  }
1674
+ const status = dryRun ? "dry-run" : "ok";
1675
+ logger.info({
1676
+ version,
1677
+ status,
1678
+ bumped: bumped.length,
1679
+ skipped: skipped.length
1680
+ }, "npm bump-versions: done");
1627
1681
  return {
1628
- status: dryRun ? "dry-run" : "ok",
1682
+ status,
1629
1683
  bumped,
1630
1684
  skipped
1631
1685
  };
@@ -1659,6 +1713,7 @@ async function runNpmBumpVersions(input) {
1659
1713
  */
1660
1714
  async function runNpmPublishInitial(input = {}) {
1661
1715
  const print = input.print ?? ((line) => console.log(line));
1716
+ const logger = input.logger ?? getLogger();
1662
1717
  const cwd = input.cwd ?? process.cwd();
1663
1718
  const tag = input.tag ?? "alpha";
1664
1719
  const dryRun = input.dryRun ?? false;
@@ -1679,6 +1734,10 @@ async function runNpmPublishInitial(input = {}) {
1679
1734
  print(`Holocron npm publish-initial${dryRun ? " (dry-run)" : ""}`);
1680
1735
  print(` cwd: ${cwd}`);
1681
1736
  print(` tag: ${tag}`);
1737
+ logger.info({
1738
+ tag,
1739
+ dryRun: dryRun || void 0
1740
+ }, "npm publish-initial: start");
1682
1741
  if (otp) print(` otp: <${otp.length} chars>`);
1683
1742
  print("");
1684
1743
  print(" → verifying npm auth (`npm whoami`)…");
@@ -1686,10 +1745,12 @@ async function runNpmPublishInitial(input = {}) {
1686
1745
  if (whoami.exitCode !== 0) {
1687
1746
  const message = "npm is not authenticated. Run `npm login --auth-type=web` (browser flow, no token stored) or `npm login`, then re-run this command.";
1688
1747
  print(` ✗ ${message}`);
1748
+ const packageNames = input.packages ?? discoverPublicPackages(cwd);
1749
+ logger.warn({ reason: "npm not authenticated" }, "npm publish-initial: done");
1689
1750
  return {
1690
1751
  status: "fail",
1691
1752
  message,
1692
- packageNames: input.packages ?? discoverPublicPackages(cwd)
1753
+ packageNames
1693
1754
  };
1694
1755
  }
1695
1756
  print(` ✓ authed as ${whoami.stdout.trim() || "<unknown>"}`);
@@ -1700,6 +1761,11 @@ async function runNpmPublishInitial(input = {}) {
1700
1761
  print(" … (dry-run) skipping actual publish");
1701
1762
  print(` would run: pnpm ${publishArgs.join(" ")}`);
1702
1763
  printNextSteps$1(print, env, packageNames, repoName);
1764
+ logger.info({
1765
+ tag,
1766
+ status: "dry-run",
1767
+ packages: packageNames.length
1768
+ }, "npm publish-initial: done");
1703
1769
  return {
1704
1770
  status: "dry-run",
1705
1771
  message: "dry-run — no publish executed",
@@ -1717,6 +1783,10 @@ async function runNpmPublishInitial(input = {}) {
1717
1783
  print(" → hint: your npm account requires 2FA for writes. Re-run with `--otp <code>`:");
1718
1784
  print(` pnpm exec tsx packages/cli/src/cli.ts npm publish-initial --otp <6-digit-code>`);
1719
1785
  }
1786
+ logger.warn({
1787
+ tag,
1788
+ reason: message
1789
+ }, "npm publish-initial: done");
1720
1790
  return {
1721
1791
  status: "fail",
1722
1792
  message,
@@ -1725,6 +1795,11 @@ async function runNpmPublishInitial(input = {}) {
1725
1795
  }
1726
1796
  print(" ✓ publish complete");
1727
1797
  printNextSteps$1(print, env, packageNames, repoName);
1798
+ logger.info({
1799
+ tag,
1800
+ status: "ok",
1801
+ packages: packageNames.length
1802
+ }, "npm publish-initial: done");
1728
1803
  return {
1729
1804
  status: "ok",
1730
1805
  packageNames
@@ -2704,6 +2779,7 @@ function resolvePath(template, inputs) {
2704
2779
  function runPluginCreate(input) {
2705
2780
  const cwd = input.cwd ?? process.cwd();
2706
2781
  const print = input.print ?? ((line) => console.log(line));
2782
+ const logger = input.logger ?? getLogger();
2707
2783
  const write = input.writeFile ?? defaultWrite;
2708
2784
  preflight(cwd);
2709
2785
  validateSlug(input.slug);
@@ -2730,6 +2806,11 @@ function runPluginCreate(input) {
2730
2806
  const filesWritten = [];
2731
2807
  print(`Scaffolding @theholocron/holocron-plugin-${inputs.slug}${input.dryRun ? " (dry-run)" : ""}`);
2732
2808
  print(` → ${packageDir}`);
2809
+ logger.info({
2810
+ slug: inputs.slug,
2811
+ capability: inputs.capability,
2812
+ dryRun: input.dryRun || void 0
2813
+ }, "plugin create: start");
2733
2814
  for (const template of TEMPLATES) {
2734
2815
  const resolvedPath = resolvePath(template.path, inputs);
2735
2816
  const filepath = path.join(packageDir, resolvedPath);
@@ -2777,7 +2858,14 @@ function runPluginCreate(input) {
2777
2858
  });
2778
2859
  print(" ✓ scaffold verified");
2779
2860
  } catch (err) {
2780
- print(` ✗ verify failed — ${err instanceof Error ? err.message : String(err)}`);
2861
+ const message = err instanceof Error ? err.message : String(err);
2862
+ print(` ✗ verify failed — ${message}`);
2863
+ logger.warn({
2864
+ slug: inputs.slug,
2865
+ files: filesWritten.length,
2866
+ reason: message,
2867
+ status: "fail"
2868
+ }, "plugin create: done");
2781
2869
  return {
2782
2870
  status: "fail",
2783
2871
  packagePath: packageDir,
@@ -2787,6 +2875,12 @@ function runPluginCreate(input) {
2787
2875
  }
2788
2876
  }
2789
2877
  if (!input.dryRun) printNextSteps(print, inputs);
2878
+ logger.info({
2879
+ slug: inputs.slug,
2880
+ capability: inputs.capability,
2881
+ files: filesWritten.length,
2882
+ status: input.dryRun ? "dry-run" : "ok"
2883
+ }, "plugin create: done");
2790
2884
  return {
2791
2885
  status: "ok",
2792
2886
  packagePath: packageDir,
@@ -2852,6 +2946,7 @@ function printNextSteps(print, inputs) {
2852
2946
  //#region src/commands/secret-set.ts
2853
2947
  async function runSecretSet(input) {
2854
2948
  const print = input.print ?? ((line) => console.log(line));
2949
+ const logger = input.logger ?? getLogger();
2855
2950
  const loader = input.loader ?? new PluginLoader(input.loaded.resolved, input.context);
2856
2951
  await loader.load();
2857
2952
  const dryRun = input.context.dryRun ?? false;
@@ -2874,6 +2969,12 @@ async function runSecretSet(input) {
2874
2969
  const secrets = loader.get("secrets");
2875
2970
  await secrets.setSecret(scope, input.name, value);
2876
2971
  print(` ✓ set ${input.name} via ${secrets.providerName}`);
2972
+ logger.info({
2973
+ key: input.name,
2974
+ scope: describeScope(scope),
2975
+ provider: secrets.providerName,
2976
+ status: "ok"
2977
+ }, `secret set: ${input.name}`);
2877
2978
  return {
2878
2979
  status: "ok",
2879
2980
  name: input.name,
@@ -2882,6 +2983,11 @@ async function runSecretSet(input) {
2882
2983
  } catch (err) {
2883
2984
  const message = err instanceof Error ? err.message : String(err);
2884
2985
  print(` ✗ ${message}`);
2986
+ logger.warn({
2987
+ key: input.name,
2988
+ scope: describeScope(scope),
2989
+ reason: message
2990
+ }, `secret set: ${input.name}`);
2885
2991
  return {
2886
2992
  status: "fail",
2887
2993
  name: input.name,
@@ -4931,25 +5037,50 @@ const defaultExec = (cmd, args, opts) => {
4931
5037
  };
4932
5038
  async function runSkillsInstall(input) {
4933
5039
  const print = input.print ?? ((line) => console.log(line));
5040
+ const logger = input.logger ?? getLogger();
4934
5041
  const config = input.loaded.resolved;
4935
5042
  if (!config.agent || !config.skills?.length) {
4936
5043
  print("Nothing to install — set `agent` and `skills` in holocron.config.ts");
5044
+ logger.info({
5045
+ status: "skip",
5046
+ reason: "no agent/skills configured"
5047
+ }, "skills install: done");
4937
5048
  return;
4938
5049
  }
4939
5050
  if (input.context.dryRun) {
4940
5051
  print(`Would install ${config.skills.length} skill(s) for agent: ${config.agent}`);
4941
5052
  for (const name of config.skills) print(` → would install: ${name}`);
5053
+ logger.info({
5054
+ agent: config.agent,
5055
+ skills: config.skills,
5056
+ status: "dry-run"
5057
+ }, "skills install: done");
4942
5058
  return;
4943
5059
  }
4944
5060
  print(`Installing ${config.skills.length} skill(s) for agent: ${config.agent}`);
5061
+ logger.info({
5062
+ agent: config.agent,
5063
+ count: config.skills.length
5064
+ }, "skills install: start");
4945
5065
  try {
4946
5066
  print(` → ${await installSkills({
4947
5067
  agent: config.agent,
4948
5068
  skills: config.skills,
4949
5069
  repoRoot: input.context.repoRoot
4950
5070
  })}`);
5071
+ logger.info({
5072
+ agent: config.agent,
5073
+ skills: config.skills,
5074
+ status: "ok"
5075
+ }, "skills install: done");
4951
5076
  } catch (err) {
4952
- print(` ✗ ${err instanceof Error ? err.message : String(err)}`);
5077
+ const message = err instanceof Error ? err.message : String(err);
5078
+ print(` ✗ ${message}`);
5079
+ logger.warn({
5080
+ agent: config.agent,
5081
+ reason: message,
5082
+ status: "fail"
5083
+ }, "skills install: done");
4953
5084
  }
4954
5085
  }
4955
5086
  function runSkillsRemove(input) {
@@ -5073,6 +5204,7 @@ async function updateIndexMdxDescription(repoRoot, description, dryRun, readFile
5073
5204
  }
5074
5205
  async function runSyncReadme(input) {
5075
5206
  const { loaded, context, print = console.log, readFileFn = readFile, writeFileFn = writeFile } = input;
5207
+ const logger = input.logger ?? getLogger();
5076
5208
  const { repoRoot, dryRun = false } = context;
5077
5209
  const namespaces = loaded.resolved.env?.namespaces ?? [];
5078
5210
  print(style.header(`Syncing README installation block${dryRun ? " (dry-run)" : ""}…`));
@@ -5082,6 +5214,10 @@ async function runSyncReadme(input) {
5082
5214
  const raw = await readFileFn(join(repoRoot, "package.json"), "utf8");
5083
5215
  pkg = JSON.parse(raw);
5084
5216
  } catch {
5217
+ logger.warn({
5218
+ repoRoot,
5219
+ reason: "could not read package.json"
5220
+ }, "sync readme: done");
5085
5221
  return {
5086
5222
  status: "fail",
5087
5223
  updated: false,
@@ -5103,6 +5239,10 @@ async function runSyncReadme(input) {
5103
5239
  const updated = await updateReadme(repoRoot, generateInstallBlock(pkg), markerSections, dryRun, readFileFn, writeFileFn);
5104
5240
  if (!updated) {
5105
5241
  print(style.warn("README.md not found or has no writable location for installation block"));
5242
+ logger.warn({
5243
+ repoRoot,
5244
+ reason: "README.md not found / no marker block"
5245
+ }, "sync readme: done");
5106
5246
  return {
5107
5247
  status: "fail",
5108
5248
  updated: false,
@@ -5111,8 +5251,14 @@ async function runSyncReadme(input) {
5111
5251
  }
5112
5252
  if (description) await updateIndexMdxDescription(repoRoot, description, dryRun, readFileFn, writeFileFn);
5113
5253
  print(dryRun ? style.hint(" would update README.md") : style.success(" updated README.md"));
5254
+ const status = dryRun ? "dry-run" : "ok";
5255
+ logger.info({
5256
+ repoRoot,
5257
+ status,
5258
+ updated
5259
+ }, "sync readme: done");
5114
5260
  return {
5115
- status: dryRun ? "dry-run" : "ok",
5261
+ status,
5116
5262
  updated
5117
5263
  };
5118
5264
  }
@@ -6217,19 +6363,38 @@ function defaultWalkFiles(dir) {
6217
6363
  }
6218
6364
  async function runUpgradeNode(input) {
6219
6365
  const print = input.print ?? ((line) => console.log(line));
6366
+ const logger = input.logger ?? getLogger();
6220
6367
  const cwd = input.cwd ?? process.cwd();
6221
6368
  const { to, dryRun = false, extra = [] } = input;
6222
6369
  const _readFile = input.readFile ?? ((p) => readFileSync(p, "utf8"));
6223
6370
  const _writeFile = input.writeFile ?? ((p, c) => writeFileSync(p, c));
6224
6371
  const _walkFiles = input.walkFiles ?? defaultWalkFiles;
6225
6372
  const from = input.from ?? detectFrom(cwd, _readFile);
6226
- if (from === null) return {
6227
- status: "fail",
6228
- updated: [],
6229
- message: "could not detect current Node version — pass --from <major>"
6230
- };
6373
+ if (from === null) {
6374
+ const message = "could not detect current Node version — pass --from <major>";
6375
+ logger.warn({
6376
+ to,
6377
+ reason: message
6378
+ }, "upgrade node: done");
6379
+ return {
6380
+ status: "fail",
6381
+ updated: [],
6382
+ message
6383
+ };
6384
+ }
6385
+ logger.info({
6386
+ from,
6387
+ to,
6388
+ dryRun: dryRun || void 0
6389
+ }, "upgrade node: start");
6231
6390
  if (from === to) {
6232
6391
  print(`Already at Node.js ${to} — nothing to do.`);
6392
+ logger.info({
6393
+ from,
6394
+ to,
6395
+ updated: 0,
6396
+ status: "ok"
6397
+ }, "upgrade node: done");
6233
6398
  return {
6234
6399
  status: "ok",
6235
6400
  updated: []
@@ -6253,11 +6418,23 @@ async function runUpgradeNode(input) {
6253
6418
  const rel = abs.startsWith(cwd + "/") ? abs.slice(cwd.length + 1) : abs;
6254
6419
  if (!dryRun) _writeFile(abs, patched);
6255
6420
  print(` ${dryRun ? "~" : "✓"} ${rel}`);
6421
+ logger.debug({
6422
+ file: rel,
6423
+ from,
6424
+ to
6425
+ }, "upgrade node: patched");
6256
6426
  updated.push(rel);
6257
6427
  }
6258
6428
  if (updated.length === 0) print(` · no files contained Node.js ${from} pins`);
6429
+ const status = dryRun ? "dry-run" : "ok";
6430
+ logger.info({
6431
+ from,
6432
+ to,
6433
+ updated: updated.length,
6434
+ status
6435
+ }, "upgrade node: done");
6259
6436
  return {
6260
- status: dryRun ? "dry-run" : "ok",
6437
+ status,
6261
6438
  updated
6262
6439
  };
6263
6440
  }