@kb-labs/cli-commands 2.89.0 → 2.93.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.
@@ -1,5 +1,5 @@
1
- import { d as CommandManifest, A as AvailabilityCheck, R as RegisteredCommand, D as DiscoveryResult } from '../discover-Cz7X5bQp.js';
2
- export { b as CacheFile, c as CommandLookupResult, e as CommandModule, f as CommandType, F as FlagDefinition, G as GlobalFlags, g as PackageCacheEntry, P as ProductGroup, _ as __test, h as discoverManifests, i as discoverManifestsByNamespace, j as findCommand, k as findCommandWithType, r as registry, l as resetInProcCache } from '../discover-Cz7X5bQp.js';
1
+ import { d as CommandManifest, A as AvailabilityCheck, R as RegisteredCommand, l as CommandRegistry, D as DiscoveryResult } from '../discover-D_Is1Qqq.js';
2
+ export { b as CacheFile, c as CommandLookupResult, e as CommandModule, f as CommandType, F as FlagDefinition, G as GlobalFlags, g as PackageCacheEntry, P as ProductGroup, _ as __test, h as discoverManifests, i as discoverManifestsByNamespace, j as findCommand, k as findCommandWithType, r as registry, m as resetInProcCache } from '../discover-D_Is1Qqq.js';
3
3
  import { ILogger } from '@kb-labs/core-platform';
4
4
  import '@kb-labs/plugin-contracts';
5
5
 
@@ -47,14 +47,13 @@ declare function preflightManifests(discoveryResults: DiscoveryResult[], logger?
47
47
  /**
48
48
  * Register manifests with shadowing and collision detection
49
49
  */
50
- declare function registerManifests(discoveryResults: DiscoveryResult[], registry: any, // CommandRegistry interface
51
- options?: RegisterManifestsOptions & {
50
+ declare function registerManifests(discoveryResults: DiscoveryResult[], registry: CommandRegistry, options?: RegisterManifestsOptions & {
52
51
  logger?: ILogger;
53
52
  }): Promise<ManifestRegistrationResult>;
54
53
  /**
55
54
  * Dispose all plugins by calling their dispose hooks
56
55
  */
57
- declare function disposeAllPlugins(registry: any, logger?: ILogger): Promise<void>;
56
+ declare function disposeAllPlugins(registry: CommandRegistry, logger?: ILogger): Promise<void>;
58
57
 
59
58
  /**
60
59
  * Execute a registered command.
@@ -62,6 +61,6 @@ declare function disposeAllPlugins(registry: any, logger?: ILogger): Promise<voi
62
61
  * - Unavailable commands return exit code 2.
63
62
  * - Available commands are executed via manifest.loader().
64
63
  */
65
- declare function runCommand(cmd: RegisteredCommand, ctx: any, argv: string[], flags: Record<string, any>): Promise<number>;
64
+ declare function runCommand(cmd: RegisteredCommand, ctx: Record<string, unknown>, argv: string[], flags: Record<string, unknown>): Promise<number>;
66
65
 
67
66
  export { AvailabilityCheck, type CheckRequiresOptions, CommandManifest, DiscoveryResult, type ManifestRegistrationResult, type RegisterManifestsOptions, RegisteredCommand, type SkippedManifest, checkRequires, disposeAllPlugins, preflightManifests, registerManifests, runCommand };
@@ -68,7 +68,7 @@ function checkRequires(manifest, options = {}) {
68
68
  if (isInMonorepo) {
69
69
  continue;
70
70
  }
71
- const errorMessage = err.message || "";
71
+ const errorMessage = (err instanceof Error ? err.message : "") || "";
72
72
  const hasExportsError = errorMessage.includes("exports") || errorMessage.includes("main");
73
73
  if (hasExportsError || errorMessage.includes("Cannot resolve")) {
74
74
  const parts = dep.startsWith("@") ? dep.slice(1).split("/") : [dep];
@@ -251,7 +251,7 @@ var __test = {
251
251
  // resetInProcCache is exported directly (not via __test) since it's part of the public API
252
252
  };
253
253
  function createUnavailableManifest(pkgName, error) {
254
- const rawMsg = (error?.message || String(error) || "").toString();
254
+ const rawMsg = (error instanceof Error ? error.message : String(error) || "").toString();
255
255
  let missing = null;
256
256
  const m1 = rawMsg.match(/Cannot find (?:module|package) '([^']+)'/);
257
257
  const m2 = rawMsg.match(/from ['"]([^'"]+)['"]/);
@@ -272,9 +272,13 @@ function createUnavailableManifest(pkgName, error) {
272
272
  requires,
273
273
  loader: async () => {
274
274
  throw new Error(`Cannot load ${pkgName} CLI manifest. ${rawMsg}`);
275
- }
275
+ },
276
+ // Mark as synthetic so saveCache can skip it — synthetic manifests must never
277
+ // be persisted to disk because they represent transient load failures.
278
+ // Caching them would make the error "stick" until the TTL expires even after
279
+ // the underlying problem (missing build artifact, broken dep) is resolved.
280
+ _synthetic: true
276
281
  };
277
- manifest._synthetic = true;
278
282
  return manifest;
279
283
  }
280
284
  var PACKAGE_JSON = "package.json";
@@ -365,7 +369,7 @@ async function detectNewWorkspacePackages(cwd, cachedPackages) {
365
369
  }
366
370
  }
367
371
  } catch (error) {
368
- log("debug", `[plugins][cache] Workspace scan skipped: ${error?.message || "unknown error"}`);
372
+ log("debug", `[plugins][cache] Workspace scan skipped: ${error instanceof Error ? error.message : "unknown error"}`);
369
373
  }
370
374
  return false;
371
375
  }
@@ -376,7 +380,7 @@ async function loadManifestWithTimeout(manifestPath, pkgName, pkgRoot) {
376
380
  try {
377
381
  return await Promise.race([loadManifest(manifestPath, pkgName, pkgRoot), timeout]);
378
382
  } catch (err) {
379
- if (err.message === "Timeout") {
383
+ if (err instanceof Error && err.message === "Timeout") {
380
384
  log("warn", `Timeout loading manifest from ${pkgName}`);
381
385
  return [];
382
386
  }
@@ -396,10 +400,12 @@ function getNamespaceFromManifest(manifestV2, packageName) {
396
400
  async function loadManifest(manifestPath, pkgName, pkgRoot) {
397
401
  const fileUrl = pathToFileURL(manifestPath).href;
398
402
  const mod = await import(fileUrl);
399
- const manifest = mod.manifest || mod.default;
400
- if (!manifest || typeof manifest !== "object" || manifest.schema !== "kb.plugin/3") {
403
+ const modTyped = mod;
404
+ const rawManifest = modTyped.manifest || modTyped.default;
405
+ if (!rawManifest || typeof rawManifest !== "object" || rawManifest.schema !== "kb.plugin/3") {
401
406
  throw new Error(`Unsupported manifest format in ${pkgName}. Only kb.plugin/3 schema is supported.`);
402
407
  }
408
+ const manifest = rawManifest;
403
409
  const namespace = getNamespaceFromManifest(manifest, pkgName);
404
410
  const manifestDir = path2.dirname(manifestPath);
405
411
  const baseRoot = pkgRoot || manifestDir;
@@ -461,8 +467,9 @@ async function loadConfig(cwd) {
461
467
  }
462
468
  }
463
469
  async function findManifestPath(pkgRoot, pkg) {
464
- if (pkg.kb?.manifest) {
465
- const manifestPath = path2.join(pkgRoot, pkg.kb.manifest);
470
+ const kb = pkg.kb;
471
+ if (kb?.manifest) {
472
+ const manifestPath = path2.join(pkgRoot, kb.manifest);
466
473
  try {
467
474
  await promises.access(manifestPath);
468
475
  return { path: manifestPath, deprecated: false };
@@ -470,8 +477,9 @@ async function findManifestPath(pkgRoot, pkg) {
470
477
  return { path: null, deprecated: false };
471
478
  }
472
479
  }
473
- if (pkg.exports?.["./kb/commands"]) {
474
- const exportPath = pkg.exports["./kb/commands"];
480
+ const exports$1 = pkg.exports;
481
+ if (exports$1?.["./kb/commands"]) {
482
+ const exportPath = exports$1["./kb/commands"];
475
483
  const manifestPath = typeof exportPath === "string" ? exportPath : exportPath.default || exportPath.import;
476
484
  if (manifestPath) {
477
485
  const resolved = path2.resolve(pkgRoot, manifestPath);
@@ -575,20 +583,21 @@ async function discoverProjectLocalPlugins(projectRoot) {
575
583
  }
576
584
  async function loadManifestsForPackages(packageInfos, source, scope) {
577
585
  const loadPromises = packageInfos.map(async ({ pkgRoot, pkg, manifestPath }) => {
586
+ const pkgName = pkg.name;
578
587
  const pkgStart = Date.now();
579
588
  try {
580
- const manifests = await loadManifestWithTimeout(manifestPath, pkg.name, pkgRoot);
589
+ const manifests = await loadManifestWithTimeout(manifestPath, pkgName, pkgRoot);
581
590
  const pkgTime = Date.now() - pkgStart;
582
591
  if (pkgTime > 30) {
583
- log("debug", `[plugins][perf] ${pkg.name} manifest parse: ${pkgTime}ms (budget: 30ms)`);
592
+ log("debug", `[plugins][perf] ${pkgName} manifest parse: ${pkgTime}ms (budget: 30ms)`);
584
593
  }
585
594
  if (manifests.length > 0) {
586
- validateUniqueIds(manifests, pkg.name);
595
+ validateUniqueIds(manifests, pkgName);
587
596
  return {
588
597
  manifests,
589
598
  source,
590
599
  scope,
591
- packageName: pkg.name,
600
+ packageName: pkgName,
592
601
  manifestPath: toPosixPath(manifestPath),
593
602
  pkgRoot: toPosixPath(pkgRoot)
594
603
  };
@@ -596,21 +605,23 @@ async function loadManifestsForPackages(packageInfos, source, scope) {
596
605
  return null;
597
606
  } catch (err) {
598
607
  const pkgTime = Date.now() - pkgStart;
599
- log("debug", `[plugins][perf] ${pkg.name} failed after ${pkgTime}ms`);
608
+ log("debug", `[plugins][perf] ${pkgName} failed after ${pkgTime}ms`);
609
+ const errMsg = err instanceof Error ? err.message : String(err);
610
+ const errCode = err.code ?? "UNKNOWN";
600
611
  log("warn", JSON.stringify({
601
612
  code: "DISCOVERY_MANIFEST_LOAD_FAIL",
602
- packageName: pkg.name,
613
+ packageName: pkgName,
603
614
  manifestPath: toPosixPath(manifestPath),
604
- errorCode: err.code || "UNKNOWN",
605
- errorMessage: err.message,
606
- hint: err.message.includes("Cannot find package") ? "Run: kb devlink apply && pnpm -w build" : "Check manifest syntax and dependencies"
615
+ errorCode: errCode,
616
+ errorMessage: errMsg,
617
+ hint: errMsg.includes("Cannot find package") ? "Run: kb devlink apply && pnpm -w build" : "Check manifest syntax and dependencies"
607
618
  }));
608
- const synthetic = createUnavailableManifest(pkg.name, err);
619
+ const synthetic = createUnavailableManifest(pkgName, err);
609
620
  return {
610
621
  manifests: [synthetic],
611
622
  source,
612
623
  scope,
613
- packageName: pkg.name,
624
+ packageName: pkgName,
614
625
  manifestPath: toPosixPath(manifestPath),
615
626
  pkgRoot: toPosixPath(pkgRoot)
616
627
  };
@@ -631,29 +642,30 @@ async function discoverCurrentPackage(cwd) {
631
642
  if (!pkg) {
632
643
  return null;
633
644
  }
645
+ const pkgName = pkg.name;
634
646
  const manifestInfo = await findManifestPath(cwd, pkg);
635
647
  if (manifestInfo.path) {
636
648
  if (manifestInfo.deprecated) {
637
- log("warn", `[DEPRECATED] ${pkg.name} uses legacy manifest path: ${manifestInfo.path}`);
649
+ log("warn", `[DEPRECATED] ${pkgName} uses legacy manifest path: ${manifestInfo.path}`);
638
650
  log("warn", ` \u2192 Migrate to exports["./kb/commands"] or set kb.commandsManifest in package.json`);
639
651
  }
640
- const manifests = await loadManifestWithTimeout(manifestInfo.path, pkg.name, cwd);
652
+ const manifests = await loadManifestWithTimeout(manifestInfo.path, pkgName, cwd);
641
653
  if (manifests.length > 0) {
642
- validateUniqueIds(manifests, pkg.name);
654
+ validateUniqueIds(manifests, pkgName);
643
655
  return {
644
656
  manifests,
645
657
  source: "workspace",
646
658
  // Current-package fallback fires in installed mode when the user's
647
659
  // project itself exposes a manifest. That maps to the project scope.
648
660
  scope: "project",
649
- packageName: pkg.name,
661
+ packageName: pkgName,
650
662
  manifestPath: toPosixPath(manifestInfo.path),
651
663
  pkgRoot: toPosixPath(cwd)
652
664
  };
653
665
  }
654
666
  }
655
667
  } catch (err) {
656
- log("debug", `No CLI manifest in current package: ${err.message}`);
668
+ log("debug", `No CLI manifest in current package: ${err instanceof Error ? err.message : String(err)}`);
657
669
  }
658
670
  return null;
659
671
  }
@@ -670,7 +682,7 @@ async function discoverNodeModules(cwd) {
670
682
  }
671
683
  const scanEntry = async () => {
672
684
  let pkgRoot;
673
- let pkg;
685
+ let pkg = null;
674
686
  if (entry.name.startsWith("@")) {
675
687
  const scopeDir = path2.join(nmDir, entry.name);
676
688
  try {
@@ -681,29 +693,30 @@ async function discoverNodeModules(cwd) {
681
693
  if (!pkg) {
682
694
  continue;
683
695
  }
696
+ const scopedPkgName = pkg.name;
684
697
  const isPlugin = isPluginPackage(pkg);
685
- if (pkg.name?.startsWith("@kb-labs/")) {
698
+ if (scopedPkgName?.startsWith("@kb-labs/")) {
686
699
  const manifestInfo = await findManifestPath(pkgRoot, pkg);
687
700
  if (manifestInfo.path) {
688
701
  packageInfos.push({ pkgRoot, pkg, manifestPath: manifestInfo.path });
689
702
  }
690
703
  } else if (isPlugin) {
691
- if (config.block?.includes(pkg.name)) {
692
- log("debug", `Plugin ${pkg.name} blocked by config`);
704
+ if (config.block?.includes(scopedPkgName ?? "")) {
705
+ log("debug", `Plugin ${scopedPkgName} blocked by config`);
693
706
  return;
694
707
  }
695
- const isAllowlisted = config.allow?.includes(pkg.name) || config.linked?.includes(pkg.name);
708
+ const isAllowlisted = config.allow?.includes(scopedPkgName ?? "") || config.linked?.includes(scopedPkgName ?? "");
696
709
  if (!isAllowlisted) {
697
- log("debug", `Plugin ${pkg.name} skipped (not allowlisted). Add to kb-labs.config.json plugins.allow or enable via 'kb marketplace enable'`);
710
+ log("debug", `Plugin ${scopedPkgName} skipped (not allowlisted). Add to kb-labs.config.json plugins.allow or enable via 'kb marketplace enable'`);
698
711
  return;
699
712
  }
700
713
  const manifestInfo = await findManifestPath(pkgRoot, pkg);
701
714
  if (manifestInfo.path) {
702
715
  if (manifestInfo.deprecated) {
703
- log("warn", `[DEPRECATED] ${pkg.name} uses legacy manifest path: ${manifestInfo.path}`);
716
+ log("warn", `[DEPRECATED] ${scopedPkgName} uses legacy manifest path: ${manifestInfo.path}`);
704
717
  log("warn", ` \u2192 Migrate to exports["./kb/commands"] or set kb.commandsManifest in package.json`);
705
718
  }
706
- const isLinked = config.linked?.includes(pkg.name);
719
+ const isLinked = config.linked?.includes(scopedPkgName ?? "");
707
720
  packageInfos.push({ pkgRoot, pkg, manifestPath: manifestInfo.path, isLinked });
708
721
  }
709
722
  }
@@ -716,24 +729,25 @@ async function discoverNodeModules(cwd) {
716
729
  if (!pkg) {
717
730
  return;
718
731
  }
732
+ const unscopedPkgName = pkg.name;
719
733
  const isPlugin = isPluginPackage(pkg);
720
734
  if (isPlugin) {
721
- if (config.block?.includes(pkg.name)) {
722
- log("debug", `Plugin ${pkg.name} blocked by config`);
735
+ if (config.block?.includes(unscopedPkgName ?? "")) {
736
+ log("debug", `Plugin ${unscopedPkgName} blocked by config`);
723
737
  return;
724
738
  }
725
- const isAllowlisted = config.allow?.includes(pkg.name) || config.linked?.includes(pkg.name);
739
+ const isAllowlisted = config.allow?.includes(unscopedPkgName ?? "") || config.linked?.includes(unscopedPkgName ?? "");
726
740
  if (!isAllowlisted) {
727
- log("debug", `Plugin ${pkg.name} skipped (not allowlisted). Add to kb-labs.config.json plugins.allow or enable via 'kb marketplace enable'`);
741
+ log("debug", `Plugin ${unscopedPkgName} skipped (not allowlisted). Add to kb-labs.config.json plugins.allow or enable via 'kb marketplace enable'`);
728
742
  return;
729
743
  }
730
744
  const manifestInfo = await findManifestPath(pkgRoot, pkg);
731
745
  if (manifestInfo.path) {
732
746
  if (manifestInfo.deprecated) {
733
- log("warn", `[DEPRECATED] ${pkg.name} uses legacy manifest path: ${manifestInfo.path}`);
747
+ log("warn", `[DEPRECATED] ${unscopedPkgName} uses legacy manifest path: ${manifestInfo.path}`);
734
748
  log("warn", ` \u2192 Migrate to exports["./kb/commands"] or set kb.commandsManifest in package.json`);
735
749
  }
736
- const isLinked = config.linked?.includes(pkg.name);
750
+ const isLinked = config.linked?.includes(unscopedPkgName ?? "");
737
751
  packageInfos.push({ pkgRoot, pkg, manifestPath: manifestInfo.path, isLinked });
738
752
  }
739
753
  }
@@ -743,10 +757,11 @@ async function discoverNodeModules(cwd) {
743
757
  }
744
758
  await Promise.allSettled(scanPromises);
745
759
  const loadPromises = packageInfos.map(async ({ pkgRoot, pkg, manifestPath, isLinked }) => {
760
+ const pkgName = pkg.name;
746
761
  try {
747
- const manifests = await loadManifestWithTimeout(manifestPath, pkg.name, pkgRoot);
762
+ const manifests = await loadManifestWithTimeout(manifestPath, pkgName, pkgRoot);
748
763
  if (manifests.length > 0) {
749
- validateUniqueIds(manifests, pkg.name);
764
+ validateUniqueIds(manifests, pkgName);
750
765
  return {
751
766
  manifests,
752
767
  source: isLinked ? "linked" : "node_modules",
@@ -754,27 +769,29 @@ async function discoverNodeModules(cwd) {
754
769
  // platformRoot === projectRoot so either label is correct; we use
755
770
  // platform to reflect where the manifest physically lives.
756
771
  scope: "platform",
757
- packageName: pkg.name,
772
+ packageName: pkgName,
758
773
  manifestPath: toPosixPath(manifestPath),
759
774
  pkgRoot: toPosixPath(pkgRoot)
760
775
  };
761
776
  }
762
777
  return null;
763
778
  } catch (err) {
779
+ const errMsg = err instanceof Error ? err.message : String(err);
780
+ const errCode = err.code ?? "UNKNOWN";
764
781
  log("warn", JSON.stringify({
765
782
  code: "DISCOVERY_MANIFEST_LOAD_FAIL",
766
- packageName: pkg.name,
783
+ packageName: pkgName,
767
784
  manifestPath: toPosixPath(manifestPath),
768
- errorCode: err.code || "UNKNOWN",
769
- errorMessage: err.message,
770
- hint: err.message.includes("Cannot find package") ? "Run: kb devlink apply && pnpm -w build" : "Check manifest syntax and dependencies"
785
+ errorCode: errCode,
786
+ errorMessage: errMsg,
787
+ hint: errMsg.includes("Cannot find package") ? "Run: kb devlink apply && pnpm -w build" : "Check manifest syntax and dependencies"
771
788
  }));
772
- const synthetic = createUnavailableManifest(pkg.name, err);
789
+ const synthetic = createUnavailableManifest(pkgName, err);
773
790
  return {
774
791
  manifests: [synthetic],
775
792
  source: isLinked ? "linked" : "node_modules",
776
793
  scope: "platform",
777
- packageName: pkg.name,
794
+ packageName: pkgName,
778
795
  manifestPath: toPosixPath(manifestPath),
779
796
  pkgRoot: toPosixPath(pkgRoot)
780
797
  };
@@ -789,7 +806,7 @@ async function discoverNodeModules(cwd) {
789
806
  }
790
807
  return results;
791
808
  } catch (err) {
792
- log("debug", `Could not scan node_modules: ${err.message}`);
809
+ log("debug", `Could not scan node_modules: ${err instanceof Error ? err.message : String(err)}`);
793
810
  return [];
794
811
  }
795
812
  }
@@ -913,7 +930,7 @@ async function isPackageCacheStale(entry, options) {
913
930
  return true;
914
931
  }
915
932
  } catch (error) {
916
- log("debug", `Package cache invalidated: missing package.json for ${entry.result.packageName} (${error?.message || "unknown"})`);
933
+ log("debug", `Package cache invalidated: missing package.json for ${entry.result.packageName} (${error instanceof Error ? error.message : "unknown"})`);
917
934
  return true;
918
935
  }
919
936
  let manifestStat;
@@ -924,7 +941,7 @@ async function isPackageCacheStale(entry, options) {
924
941
  return true;
925
942
  }
926
943
  } catch (error) {
927
- log("debug", `Package cache invalidated: manifest deleted for ${entry.result.packageName} (${error?.message || "unknown"})`);
944
+ log("debug", `Package cache invalidated: manifest deleted for ${entry.result.packageName} (${error instanceof Error ? error.message : "unknown"})`);
928
945
  return true;
929
946
  }
930
947
  if (options.validateHash) {
@@ -935,7 +952,7 @@ async function isPackageCacheStale(entry, options) {
935
952
  return true;
936
953
  }
937
954
  } catch (error) {
938
- log("debug", `Package cache hash validation failed for ${entry.result.packageName}: ${error?.message || "unknown"}`);
955
+ log("debug", `Package cache hash validation failed for ${entry.result.packageName}: ${error instanceof Error ? error.message : "unknown"}`);
939
956
  return true;
940
957
  }
941
958
  }
@@ -981,7 +998,7 @@ async function saveCache(cwd, results, roots) {
981
998
  stateHasher.update(result.packageName);
982
999
  stateHasher.update(manifestHash);
983
1000
  } catch (err) {
984
- log("debug", `Failed to cache package ${result.packageName}: ${err.message}`);
1001
+ log("debug", `Failed to cache package ${result.packageName}: ${err instanceof Error ? err.message : String(err)}`);
985
1002
  }
986
1003
  }
987
1004
  const lockfileHash = await computeLockfileHash(cwd);
@@ -1024,7 +1041,7 @@ async function saveCache(cwd, results, roots) {
1024
1041
  try {
1025
1042
  await promises.writeFile(cachePath, JSON.stringify(cache), "utf8");
1026
1043
  } catch (err) {
1027
- log("debug", `Failed to save cache: ${err.message}`);
1044
+ log("debug", `Failed to save cache: ${err instanceof Error ? err.message : String(err)}`);
1028
1045
  }
1029
1046
  }
1030
1047
  async function discoverManifests(cwd, noCache = false, options = {}) {
@@ -1293,7 +1310,7 @@ function preflightManifests(discoveryResults, logger) {
1293
1310
  validateManifestStructure(manifest);
1294
1311
  allowed.push(manifest);
1295
1312
  } catch (error) {
1296
- const reason = error?.message ? String(error.message) : "Validation failed";
1313
+ const reason = error instanceof Error ? error.message : "Validation failed";
1297
1314
  const manifestId = manifest?.id || manifest?.group || result.packageName || "unknown";
1298
1315
  skipped.push({
1299
1316
  id: manifestId,
@@ -1338,7 +1355,7 @@ async function registerManifests(discoveryResults, registry2, options = {}) {
1338
1355
  try {
1339
1356
  validateManifestStructure(manifest);
1340
1357
  } catch (err) {
1341
- throw new Error(`Validation failed: ${err.message}`);
1358
+ throw new Error(`Validation failed: ${err instanceof Error ? err.message : String(err)}`);
1342
1359
  }
1343
1360
  const normalizedId = normalizeCommandId(manifest.id, namespace);
1344
1361
  if (normalizedId !== manifest.id) {
@@ -1385,7 +1402,8 @@ async function registerManifests(discoveryResults, registry2, options = {}) {
1385
1402
  cmd._disposeHook = manifestModule.dispose;
1386
1403
  }
1387
1404
  } catch (hookError) {
1388
- log2.debug(`Lifecycle hooks unavailable for ${manifest.id}: ${hookError.message}`);
1405
+ const hookMsg = hookError instanceof Error ? hookError.message : String(hookError);
1406
+ log2.debug(`Lifecycle hooks unavailable for ${manifest.id}: ${hookMsg}`);
1389
1407
  }
1390
1408
  const canonicalKey = manifest.group ? `${manifest.group}:${manifest.id}` : manifest.id;
1391
1409
  const existing = globalIds.get(canonicalKey);
@@ -1455,7 +1473,7 @@ async function registerManifests(discoveryResults, registry2, options = {}) {
1455
1473
  registered.push(cmd);
1456
1474
  } catch (error) {
1457
1475
  errors++;
1458
- const reason = error?.message ? String(error.message) : String(error);
1476
+ const reason = error instanceof Error ? error.message : String(error);
1459
1477
  skipped.push({
1460
1478
  id: manifestId,
1461
1479
  source: result.source,
@@ -1487,11 +1505,9 @@ async function disposeAllPlugins(registry2, logger) {
1487
1505
  const disposeHook = cmd._disposeHook;
1488
1506
  if (disposeHook && typeof disposeHook === "function") {
1489
1507
  disposePromises.push(
1490
- Promise.resolve(disposeHook({
1491
- registry: registry2,
1492
- command: cmd
1493
- })).catch((err) => {
1494
- log2.warn(`Dispose hook failed for ${cmd.manifest.id}: ${err.message}`);
1508
+ Promise.resolve(disposeHook()).catch((err) => {
1509
+ const errMsg = err instanceof Error ? err.message : String(err);
1510
+ log2.warn(`Dispose hook failed for ${cmd.manifest.id}: ${errMsg}`);
1495
1511
  })
1496
1512
  );
1497
1513
  }
@@ -1502,8 +1518,9 @@ async function disposeAllPlugins(registry2, logger) {
1502
1518
  // src/registry/run.ts
1503
1519
  async function runCommand(cmd, ctx, argv, flags) {
1504
1520
  if (!cmd.available) {
1505
- if (ctx.presenter?.json) {
1506
- ctx.presenter.json({
1521
+ const presenter = ctx.presenter;
1522
+ if (presenter?.json) {
1523
+ presenter.json({
1507
1524
  ok: false,
1508
1525
  available: false,
1509
1526
  command: cmd.manifest.id,