@cleocode/caamp 2026.5.83 → 2026.5.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CANONICAL_SKILLS_DIR,
4
+ ErrorCategories,
5
+ ErrorCodes,
4
6
  MarketplaceClient,
5
7
  PiHarness,
6
8
  RECOMMENDATION_ERROR_CODES,
9
+ buildEnvelope,
7
10
  checkSkillUpdate,
8
11
  detectAllProviders,
9
12
  detectMcpInstallations,
@@ -12,6 +15,8 @@ import {
12
15
  discoverSkillsMulti,
13
16
  dispatchInstallSkillAcrossProviders,
14
17
  dispatchRemoveSkillAcrossProviders,
18
+ emitError,
19
+ emitJsonError,
15
20
  fetchWithTimeout,
16
21
  formatNetworkError,
17
22
  formatSkillRecommendations,
@@ -20,27 +25,30 @@ import {
20
25
  getSkill,
21
26
  getSkillDir,
22
27
  getTrackedSkills,
28
+ handleFormatError,
23
29
  installBatchWithRollback,
24
30
  installMcpServer,
25
31
  isCatalogAvailable,
26
32
  isHuman,
27
33
  isMarketplaceScoped,
28
- isQuiet,
29
34
  isVerbose,
30
35
  listAllMcpServers,
31
36
  listCanonicalSkills,
32
37
  listMcpServers,
33
38
  listProfiles,
34
39
  listSkills,
40
+ outputSuccess,
35
41
  parseSource,
36
42
  readConfig,
37
43
  readLockFile,
38
44
  recommendSkills,
39
45
  recordSkillInstall,
46
+ registerDoctorBridge,
40
47
  removeMcpServer,
41
48
  removeMcpServerFromAll,
42
49
  removeSkillFromLock,
43
50
  resolveDefaultTargetProviders,
51
+ resolveFormat,
44
52
  resolveProfile,
45
53
  scanDirectory,
46
54
  scanFile,
@@ -52,7 +60,7 @@ import {
52
60
  tokenizeCriteriaValue,
53
61
  updateInstructionsSingleOperation,
54
62
  validateSkill
55
- } from "./chunk-4W35AEYA.js";
63
+ } from "./chunk-QSJSM57K.js";
56
64
  import {
57
65
  buildSkillsMap,
58
66
  checkAllInjections,
@@ -65,7 +73,7 @@ import {
65
73
  groupByInstructFile,
66
74
  injectAll,
67
75
  providerSupports
68
- } from "./chunk-OPUPNLUJ.js";
76
+ } from "./chunk-PGETUTYZ.js";
69
77
  import {
70
78
  CANONICAL_HOOK_EVENTS,
71
79
  buildHookMatrix,
@@ -74,12 +82,12 @@ import {
74
82
  getHookSupport,
75
83
  getProviderSummary,
76
84
  translateToAll
77
- } from "./chunk-SV33CE5X.js";
85
+ } from "./chunk-QKC2JRSG.js";
78
86
  import {
79
87
  buildSkillSubPathCandidates,
80
88
  resolveProviderConfigPath,
81
89
  resolveProviderSkillsDir
82
- } from "./chunk-OCI4RYI5.js";
90
+ } from "./chunk-H5YXR2DC.js";
83
91
 
84
92
  // src/cli.ts
85
93
  import { Command } from "commander";
@@ -153,7 +161,7 @@ function emitSuccess(operation, result, mvi = "standard") {
153
161
  };
154
162
  console.log(JSON.stringify(envelope, null, 2));
155
163
  }
156
- function emitError(operation, error, mvi = "standard") {
164
+ function emitError2(operation, error, mvi = "standard") {
157
165
  let envelope;
158
166
  if (error instanceof LAFSCommandError) {
159
167
  envelope = {
@@ -204,7 +212,7 @@ async function runLafsCommand(command, mvi, action) {
204
212
  const result = await action();
205
213
  emitSuccess(command, result, mvi);
206
214
  } catch (error) {
207
- emitError(command, error, mvi);
215
+ emitError2(command, error, mvi);
208
216
  process.exit(1);
209
217
  }
210
218
  }
@@ -499,117 +507,6 @@ function registerAdvancedCommands(program2) {
499
507
  // src/commands/config.ts
500
508
  import { existsSync } from "fs";
501
509
  import pc from "picocolors";
502
-
503
- // src/core/lafs.ts
504
- import { randomUUID as randomUUID2 } from "crypto";
505
- import { resolveOutputFormat } from "@cleocode/lafs";
506
- function resolveFormat(options) {
507
- return resolveOutputFormat({
508
- jsonFlag: options.jsonFlag ?? false,
509
- humanFlag: (options.humanFlag ?? false) || isHuman(),
510
- projectDefault: options.projectDefault ?? "json"
511
- }).format;
512
- }
513
- function buildEnvelope(operation, mvi, result, error, page = null, sessionId, warnings) {
514
- return {
515
- $schema: "https://lafs.dev/schemas/v1/envelope.schema.json",
516
- _meta: {
517
- specVersion: "1.0.0",
518
- schemaVersion: "1.0.0",
519
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
520
- operation,
521
- requestId: randomUUID2(),
522
- transport: "cli",
523
- strict: true,
524
- mvi,
525
- contextVersion: 0,
526
- ...sessionId && { sessionId },
527
- ...warnings && warnings.length > 0 && { warnings }
528
- },
529
- success: error === null,
530
- result,
531
- error,
532
- page
533
- };
534
- }
535
- function emitError2(operation, mvi, code, message, category, details = {}, exitCode = 1) {
536
- const envelope = buildEnvelope(operation, mvi, null, {
537
- code,
538
- message,
539
- category,
540
- retryable: category === "TRANSIENT" || category === "RATE_LIMIT",
541
- retryAfterMs: null,
542
- details
543
- });
544
- console.error(JSON.stringify(envelope, null, 2));
545
- process.exit(exitCode);
546
- }
547
- function emitJsonError(operation, mvi, code, message, category, details = {}) {
548
- const envelope = buildEnvelope(operation, mvi, null, {
549
- code,
550
- message,
551
- category,
552
- retryable: category === "TRANSIENT" || category === "RATE_LIMIT",
553
- retryAfterMs: null,
554
- details
555
- });
556
- console.error(JSON.stringify(envelope, null, 2));
557
- }
558
- function outputSuccess(operation, mvi, result, page, sessionId, warnings) {
559
- const envelope = buildEnvelope(operation, mvi, result, null, page ?? null, sessionId, warnings);
560
- if (isQuiet() && !envelope.error) {
561
- return;
562
- }
563
- console.log(JSON.stringify(envelope, null, 2));
564
- }
565
- function handleFormatError(error, operation, mvi, jsonFlag) {
566
- const message = error instanceof Error ? error.message : String(error);
567
- if (jsonFlag) {
568
- emitJsonError(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
569
- } else {
570
- console.error(message);
571
- }
572
- process.exit(1);
573
- }
574
- var ErrorCategories = {
575
- VALIDATION: "VALIDATION",
576
- AUTH: "AUTH",
577
- PERMISSION: "PERMISSION",
578
- NOT_FOUND: "NOT_FOUND",
579
- CONFLICT: "CONFLICT",
580
- RATE_LIMIT: "RATE_LIMIT",
581
- TRANSIENT: "TRANSIENT",
582
- INTERNAL: "INTERNAL",
583
- CONTRACT: "CONTRACT",
584
- MIGRATION: "MIGRATION"
585
- };
586
- var ErrorCodes = {
587
- // Format errors
588
- FORMAT_CONFLICT: "E_FORMAT_CONFLICT",
589
- INVALID_JSON: "E_INVALID_JSON",
590
- // Not found errors
591
- SKILL_NOT_FOUND: "E_SKILL_NOT_FOUND",
592
- PROVIDER_NOT_FOUND: "E_PROVIDER_NOT_FOUND",
593
- MCP_SERVER_NOT_FOUND: "E_MCP_SERVER_NOT_FOUND",
594
- FILE_NOT_FOUND: "E_FILE_NOT_FOUND",
595
- // Validation errors
596
- INVALID_INPUT: "E_INVALID_INPUT",
597
- INVALID_CONSTRAINT: "E_INVALID_CONSTRAINT",
598
- INVALID_FORMAT: "E_INVALID_FORMAT",
599
- // Operation errors
600
- INSTALL_FAILED: "E_INSTALL_FAILED",
601
- REMOVE_FAILED: "E_REMOVE_FAILED",
602
- UPDATE_FAILED: "E_UPDATE_FAILED",
603
- VALIDATION_FAILED: "E_VALIDATION_FAILED",
604
- AUDIT_FAILED: "E_AUDIT_FAILED",
605
- // System errors
606
- NETWORK_ERROR: "E_NETWORK_ERROR",
607
- FILE_SYSTEM_ERROR: "E_FILE_SYSTEM_ERROR",
608
- PERMISSION_DENIED: "E_PERMISSION_DENIED",
609
- INTERNAL_ERROR: "E_INTERNAL_ERROR"
610
- };
611
-
612
- // src/commands/config.ts
613
510
  function registerConfigCommand(program2) {
614
511
  const config = program2.command("config").description("View provider configuration");
615
512
  config.command("show").description("Show provider configuration").argument("<provider>", "Provider ID or alias").option("-g, --global", "Show global config").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
@@ -2939,8 +2836,8 @@ function registerPiCommands(program2) {
2939
2836
  }
2940
2837
 
2941
2838
  // src/commands/providers.ts
2942
- import { randomUUID as randomUUID3 } from "crypto";
2943
- import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
2839
+ import { randomUUID as randomUUID2 } from "crypto";
2840
+ import { resolveOutputFormat } from "@cleocode/lafs";
2944
2841
  import pc6 from "picocolors";
2945
2842
  function registerProvidersCommand(program2) {
2946
2843
  const providers = program2.command("providers").description("Manage AI agent providers");
@@ -2949,7 +2846,7 @@ function registerProvidersCommand(program2) {
2949
2846
  const mvi = "standard";
2950
2847
  let format;
2951
2848
  try {
2952
- format = resolveOutputFormat2({
2849
+ format = resolveOutputFormat({
2953
2850
  jsonFlag: opts.json ?? false,
2954
2851
  humanFlag: (opts.human ?? false) || isHuman(),
2955
2852
  projectDefault: "json"
@@ -2999,7 +2896,7 @@ CAMP Provider Registry v${getRegistryVersion()}`));
2999
2896
  const mvi = "standard";
3000
2897
  let format;
3001
2898
  try {
3002
- format = resolveOutputFormat2({
2899
+ format = resolveOutputFormat({
3003
2900
  jsonFlag: opts.json ?? false,
3004
2901
  humanFlag: (opts.human ?? false) || isHuman(),
3005
2902
  projectDefault: "json"
@@ -3055,7 +2952,7 @@ Detected ${installed.length} installed providers:
3055
2952
  const mvi = "standard";
3056
2953
  let format;
3057
2954
  try {
3058
- format = resolveOutputFormat2({
2955
+ format = resolveOutputFormat({
3059
2956
  jsonFlag: opts.json ?? false,
3060
2957
  humanFlag: (opts.human ?? false) || isHuman(),
3061
2958
  projectDefault: "json"
@@ -3128,7 +3025,7 @@ ${provider.toolName}`));
3128
3025
  const mvi = "standard";
3129
3026
  let format;
3130
3027
  try {
3131
- format = resolveOutputFormat2({
3028
+ format = resolveOutputFormat({
3132
3029
  jsonFlag: opts.json ?? false,
3133
3030
  humanFlag: (opts.human ?? false) || isHuman(),
3134
3031
  projectDefault: "json"
@@ -3186,7 +3083,7 @@ ${provider.toolName}`));
3186
3083
  const mvi = "standard";
3187
3084
  let format;
3188
3085
  try {
3189
- format = resolveOutputFormat2({
3086
+ format = resolveOutputFormat({
3190
3087
  jsonFlag: opts.json ?? false,
3191
3088
  humanFlag: (opts.human ?? false) || isHuman(),
3192
3089
  projectDefault: "json"
@@ -3254,7 +3151,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3254
3151
  const mvi = "standard";
3255
3152
  let format;
3256
3153
  try {
3257
- format = resolveOutputFormat2({
3154
+ format = resolveOutputFormat({
3258
3155
  jsonFlag: opts.json ?? false,
3259
3156
  humanFlag: (opts.human ?? false) || isHuman(),
3260
3157
  projectDefault: "json"
@@ -3301,7 +3198,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3301
3198
  const mvi = "standard";
3302
3199
  let format;
3303
3200
  try {
3304
- format = resolveOutputFormat2({
3201
+ format = resolveOutputFormat({
3305
3202
  jsonFlag: opts.json ?? false,
3306
3203
  humanFlag: (opts.human ?? false) || isHuman(),
3307
3204
  projectDefault: "json"
@@ -3349,7 +3246,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3349
3246
  return;
3350
3247
  }
3351
3248
  if (opts.from) {
3352
- const { toCanonical } = await import("./hooks-5EXBKPII.js");
3249
+ const { toCanonical } = await import("./hooks-ZN3C4WCK.js");
3353
3250
  const canonical2 = toCanonical(event, opts.from);
3354
3251
  if (format === "json") {
3355
3252
  const envelope = buildEnvelope2(
@@ -3389,7 +3286,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3389
3286
  }
3390
3287
  process.exit(1);
3391
3288
  }
3392
- const { getMappedProviderIds } = await import("./hooks-5EXBKPII.js");
3289
+ const { getMappedProviderIds } = await import("./hooks-ZN3C4WCK.js");
3393
3290
  const allIds = getMappedProviderIds();
3394
3291
  const translations = translateToAll(canonical, allIds);
3395
3292
  if (format === "json") {
@@ -3432,7 +3329,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3432
3329
  const mvi = "standard";
3433
3330
  let format;
3434
3331
  try {
3435
- format = resolveOutputFormat2({
3332
+ format = resolveOutputFormat({
3436
3333
  jsonFlag: opts.json ?? false,
3437
3334
  humanFlag: (opts.human ?? false) || isHuman(),
3438
3335
  projectDefault: "json"
@@ -3502,7 +3399,7 @@ function buildEnvelope2(operation, mvi, result, error) {
3502
3399
  schemaVersion: "1.0.0",
3503
3400
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3504
3401
  operation,
3505
- requestId: randomUUID3(),
3402
+ requestId: randomUUID2(),
3506
3403
  transport: "cli",
3507
3404
  strict: true,
3508
3405
  mvi,
@@ -3817,10 +3714,308 @@ function registerSkillsCheck(parent) {
3817
3714
  });
3818
3715
  }
3819
3716
 
3820
- // src/commands/skills/find.ts
3821
- import { randomUUID as randomUUID4 } from "crypto";
3822
- import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
3717
+ // src/commands/skills/doctor.ts
3718
+ function registerSkillsDoctor(parent) {
3719
+ const doctor = parent.command("doctor").description("Diagnose and repair the skill storage topology");
3720
+ registerDoctorBridge(doctor);
3721
+ }
3722
+
3723
+ // src/commands/skills/doctor-migrate.ts
3823
3724
  import pc9 from "picocolors";
3725
+
3726
+ // src/core/skills/migration.ts
3727
+ import { execFile } from "child_process";
3728
+ import {
3729
+ cpSync,
3730
+ existsSync as existsSync10,
3731
+ mkdirSync,
3732
+ readdirSync as readdirSync2,
3733
+ rmSync,
3734
+ statSync as statSync3,
3735
+ writeFileSync
3736
+ } from "fs";
3737
+ import { homedir as homedir2 } from "os";
3738
+ import { join as join8 } from "path";
3739
+ import { promisify } from "util";
3740
+ var execFileAsync = promisify(execFile);
3741
+ var LEGACY_MIGRATED_MARKER = ".MIGRATED-TO-CLEO";
3742
+ function defaultMigrationOptions(manifestNames) {
3743
+ const home = homedir2();
3744
+ return {
3745
+ legacyRoot: join8(home, ".local", "share", "agents", "skills"),
3746
+ canonicalRoot: join8(home, ".cleo", "skills"),
3747
+ backupDir: join8(home, ".cleo", "backups", "skills"),
3748
+ manifestNames,
3749
+ now: () => /* @__PURE__ */ new Date(),
3750
+ tarExec: systemTarExec,
3751
+ recordRow: () => void 0
3752
+ };
3753
+ }
3754
+ var systemTarExec = {
3755
+ async create({ archivePath, sourceRoot }) {
3756
+ const parent = join8(sourceRoot, "..");
3757
+ const base = sourceRoot.slice(parent.length + 1);
3758
+ await execFileAsync("tar", ["-czf", archivePath, "-C", parent, base]);
3759
+ },
3760
+ async extract({ archivePath, destinationRoot }) {
3761
+ mkdirSync(destinationRoot, { recursive: true });
3762
+ const parent = join8(destinationRoot, "..");
3763
+ await execFileAsync("tar", ["-xzf", archivePath, "-C", parent]);
3764
+ }
3765
+ };
3766
+ function isAlreadyMigrated(legacyRoot) {
3767
+ if (!existsSync10(legacyRoot)) return true;
3768
+ return existsSync10(join8(legacyRoot, LEGACY_MIGRATED_MARKER));
3769
+ }
3770
+ function listSkillDirs(root) {
3771
+ if (!existsSync10(root)) return [];
3772
+ const entries = readdirSync2(root, { withFileTypes: true });
3773
+ return entries.filter((d) => d.isDirectory() && d.name !== LEGACY_MIGRATED_MARKER).map((d) => d.name).sort();
3774
+ }
3775
+ function planMigration(options) {
3776
+ const start = Date.now();
3777
+ const migrated = [];
3778
+ const skipped = [];
3779
+ if (isAlreadyMigrated(options.legacyRoot)) {
3780
+ return {
3781
+ action: "no-op",
3782
+ migrated,
3783
+ skipped,
3784
+ backupPath: null,
3785
+ legacyRoot: options.legacyRoot,
3786
+ canonicalRoot: options.canonicalRoot,
3787
+ durationMs: Date.now() - start
3788
+ };
3789
+ }
3790
+ const names = listSkillDirs(options.legacyRoot);
3791
+ for (const name of names) {
3792
+ const legacyPath = join8(options.legacyRoot, name);
3793
+ if (!statSync3(legacyPath).isDirectory()) {
3794
+ skipped.push({ name, reason: "not-a-directory", legacyPath });
3795
+ continue;
3796
+ }
3797
+ const destPath = join8(options.canonicalRoot, name);
3798
+ if (existsSync10(destPath)) {
3799
+ skipped.push({ name, reason: "already-present", legacyPath });
3800
+ continue;
3801
+ }
3802
+ migrated.push({
3803
+ name,
3804
+ installPath: destPath,
3805
+ legacyPath,
3806
+ sourceType: options.manifestNames.includes(name) ? "canonical" : "user"
3807
+ });
3808
+ }
3809
+ return {
3810
+ action: "dry-run",
3811
+ migrated,
3812
+ skipped,
3813
+ backupPath: null,
3814
+ legacyRoot: options.legacyRoot,
3815
+ canonicalRoot: options.canonicalRoot,
3816
+ durationMs: Date.now() - start
3817
+ };
3818
+ }
3819
+ function formatBackupTimestamp(now) {
3820
+ const pad = (n) => n.toString().padStart(2, "0");
3821
+ return `${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}-${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`;
3822
+ }
3823
+ function listBackups(backupDir) {
3824
+ if (!existsSync10(backupDir)) return [];
3825
+ const files = readdirSync2(backupDir).filter(
3826
+ (f) => f.startsWith("skills-pre-migrate-") && f.endsWith(".tgz")
3827
+ );
3828
+ files.sort().reverse();
3829
+ return files.map((f) => join8(backupDir, f));
3830
+ }
3831
+ async function runMigration(options) {
3832
+ const start = Date.now();
3833
+ const now = (options.now ?? (() => /* @__PURE__ */ new Date()))();
3834
+ const tar = options.tarExec ?? systemTarExec;
3835
+ const sink = options.recordRow ?? (() => void 0);
3836
+ if (isAlreadyMigrated(options.legacyRoot)) {
3837
+ return {
3838
+ action: "no-op",
3839
+ migrated: [],
3840
+ skipped: [],
3841
+ backupPath: null,
3842
+ legacyRoot: options.legacyRoot,
3843
+ canonicalRoot: options.canonicalRoot,
3844
+ durationMs: Date.now() - start
3845
+ };
3846
+ }
3847
+ const plan = planMigration(options);
3848
+ mkdirSync(options.canonicalRoot, { recursive: true });
3849
+ mkdirSync(options.backupDir, { recursive: true });
3850
+ const backupName = `skills-pre-migrate-${formatBackupTimestamp(now)}.tgz`;
3851
+ const backupPath = join8(options.backupDir, backupName);
3852
+ await tar.create({ archivePath: backupPath, sourceRoot: options.legacyRoot });
3853
+ for (const entry of plan.migrated) {
3854
+ cpSync(entry.legacyPath, entry.installPath, { recursive: true, dereference: false });
3855
+ await sink(entry);
3856
+ }
3857
+ writeFileSync(
3858
+ join8(options.legacyRoot, LEGACY_MIGRATED_MARKER),
3859
+ JSON.stringify(
3860
+ {
3861
+ migratedAt: now.toISOString(),
3862
+ backupPath,
3863
+ canonicalRoot: options.canonicalRoot,
3864
+ entries: plan.migrated.length
3865
+ },
3866
+ null,
3867
+ 2
3868
+ ),
3869
+ "utf-8"
3870
+ );
3871
+ return {
3872
+ action: "migrate",
3873
+ migrated: plan.migrated,
3874
+ skipped: plan.skipped,
3875
+ backupPath,
3876
+ legacyRoot: options.legacyRoot,
3877
+ canonicalRoot: options.canonicalRoot,
3878
+ durationMs: Date.now() - start
3879
+ };
3880
+ }
3881
+ async function runRollback(options) {
3882
+ const start = Date.now();
3883
+ const tar = options.tarExec ?? systemTarExec;
3884
+ const backups = listBackups(options.backupDir);
3885
+ const newest = backups[0];
3886
+ if (!newest) {
3887
+ throw new Error(
3888
+ `No backup tarballs found under ${options.backupDir}. Run "cleo skills migrate" (without --rollback) first.`
3889
+ );
3890
+ }
3891
+ if (existsSync10(options.legacyRoot)) {
3892
+ rmSync(options.legacyRoot, { recursive: true, force: true });
3893
+ }
3894
+ await tar.extract({ archivePath: newest, destinationRoot: options.legacyRoot });
3895
+ return {
3896
+ action: "rollback",
3897
+ migrated: [],
3898
+ skipped: [],
3899
+ backupPath: newest,
3900
+ legacyRoot: options.legacyRoot,
3901
+ canonicalRoot: options.canonicalRoot,
3902
+ durationMs: Date.now() - start
3903
+ };
3904
+ }
3905
+
3906
+ // src/commands/skills/doctor-migrate.ts
3907
+ function buildOptions(opts) {
3908
+ if (opts.__optionsOverride) return opts.__optionsOverride;
3909
+ const manifestNames = opts.__manifestNamesOverride ?? [];
3910
+ return defaultMigrationOptions(manifestNames);
3911
+ }
3912
+ function renderHuman(outcome) {
3913
+ const lines = [];
3914
+ lines.push(pc9.bold(`
3915
+ skills ${outcome.action}`));
3916
+ lines.push(pc9.dim(` legacy: ${outcome.legacyRoot}`));
3917
+ lines.push(pc9.dim(` canonical: ${outcome.canonicalRoot}`));
3918
+ if (outcome.backupPath) {
3919
+ lines.push(pc9.dim(` backup: ${outcome.backupPath}`));
3920
+ }
3921
+ lines.push(pc9.dim(` duration: ${outcome.durationMs}ms`));
3922
+ if (outcome.migrated.length > 0) {
3923
+ lines.push(pc9.green(`
3924
+ Migrated (${outcome.migrated.length}):`));
3925
+ for (const m of outcome.migrated) {
3926
+ lines.push(` + ${pc9.bold(m.name)} ${pc9.dim(`[${m.sourceType}]`)}`);
3927
+ }
3928
+ }
3929
+ if (outcome.skipped.length > 0) {
3930
+ lines.push(pc9.yellow(`
3931
+ Skipped (${outcome.skipped.length}):`));
3932
+ for (const s of outcome.skipped) {
3933
+ lines.push(` ! ${pc9.bold(s.name)} ${pc9.dim(`(${s.reason})`)}`);
3934
+ }
3935
+ }
3936
+ if (outcome.action === "no-op") {
3937
+ lines.push(pc9.dim("\nLegacy store is already migrated (sentinel present)."));
3938
+ }
3939
+ if (outcome.action === "dry-run") {
3940
+ lines.push(pc9.dim("\n(dry run \u2014 no filesystem changes were made)"));
3941
+ }
3942
+ return lines.join("\n");
3943
+ }
3944
+ function registerSkillsDoctorMigrate(parent) {
3945
+ parent.command("migrate").description("Migrate legacy skills (~/.local/share/agents/skills) into ~/.cleo/skills").option("--dry-run", "Preview the plan without writing anything", false).option("--rollback", "Restore from the most recent backup tarball", false).option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
3946
+ const operation = "skills.migrate";
3947
+ const mvi = "standard";
3948
+ let format;
3949
+ try {
3950
+ format = resolveFormat({
3951
+ jsonFlag: opts.json ?? false,
3952
+ humanFlag: (opts.human ?? false) || isHuman(),
3953
+ projectDefault: "json"
3954
+ });
3955
+ } catch (error) {
3956
+ const message = error instanceof Error ? error.message : String(error);
3957
+ emitJsonError(
3958
+ operation,
3959
+ mvi,
3960
+ ErrorCodes.FORMAT_CONFLICT,
3961
+ message,
3962
+ ErrorCategories.VALIDATION
3963
+ );
3964
+ process.exit(1);
3965
+ }
3966
+ if (opts.dryRun && opts.rollback) {
3967
+ const message = "Cannot combine --dry-run with --rollback";
3968
+ if (format === "json") {
3969
+ emitJsonError(
3970
+ operation,
3971
+ mvi,
3972
+ ErrorCodes.INVALID_INPUT,
3973
+ message,
3974
+ ErrorCategories.VALIDATION
3975
+ );
3976
+ } else {
3977
+ console.error(pc9.red(message));
3978
+ }
3979
+ process.exit(1);
3980
+ }
3981
+ const options = buildOptions(opts);
3982
+ try {
3983
+ let outcome;
3984
+ if (opts.rollback) {
3985
+ outcome = await runRollback(options);
3986
+ } else if (opts.dryRun) {
3987
+ outcome = planMigration(options);
3988
+ } else {
3989
+ outcome = await runMigration(options);
3990
+ }
3991
+ if (format === "json") {
3992
+ outputSuccess(operation, mvi, outcome);
3993
+ } else {
3994
+ console.log(renderHuman(outcome));
3995
+ }
3996
+ } catch (error) {
3997
+ const message = error instanceof Error ? error.message : String(error);
3998
+ if (format === "json") {
3999
+ emitJsonError(
4000
+ operation,
4001
+ mvi,
4002
+ ErrorCodes.INTERNAL_ERROR,
4003
+ message,
4004
+ ErrorCategories.MIGRATION,
4005
+ { legacyRoot: options.legacyRoot, canonicalRoot: options.canonicalRoot }
4006
+ );
4007
+ } else {
4008
+ console.error(pc9.red(`migration failed: ${message}`));
4009
+ }
4010
+ process.exit(1);
4011
+ }
4012
+ });
4013
+ }
4014
+
4015
+ // src/commands/skills/find.ts
4016
+ import { randomUUID as randomUUID3 } from "crypto";
4017
+ import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
4018
+ import pc10 from "picocolors";
3824
4019
  var SkillsFindValidationError = class extends Error {
3825
4020
  code;
3826
4021
  constructor(code, message) {
@@ -3851,7 +4046,7 @@ function registerSkillsFind(parent) {
3851
4046
  const mvi = details ? "full" : "standard";
3852
4047
  let format;
3853
4048
  try {
3854
- format = resolveOutputFormat3({
4049
+ format = resolveOutputFormat2({
3855
4050
  jsonFlag: opts.json ?? false,
3856
4051
  humanFlag: (opts.human ?? false) || isHuman(),
3857
4052
  projectDefault: "json"
@@ -3861,7 +4056,7 @@ function registerSkillsFind(parent) {
3861
4056
  if (opts.json) {
3862
4057
  emitJsonError3(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
3863
4058
  } else {
3864
- console.error(pc9.red(message));
4059
+ console.error(pc10.red(message));
3865
4060
  }
3866
4061
  process.exit(1);
3867
4062
  }
@@ -3928,19 +4123,19 @@ function registerSkillsFind(parent) {
3928
4123
  query: query ?? null
3929
4124
  });
3930
4125
  } else {
3931
- console.error(pc9.red(`Recommendation failed: ${message}`));
4126
+ console.error(pc10.red(`Recommendation failed: ${message}`));
3932
4127
  }
3933
4128
  process.exit(1);
3934
4129
  }
3935
4130
  }
3936
4131
  if (!query) {
3937
- console.log(pc9.dim("Usage: caamp skills find <query>"));
4132
+ console.log(pc10.dim("Usage: caamp skills find <query>"));
3938
4133
  return;
3939
4134
  }
3940
4135
  const limit = parseInt(opts.limit, 10);
3941
4136
  const client = new MarketplaceClient();
3942
4137
  if (format === "human") {
3943
- console.log(pc9.dim(`Searching marketplaces for "${query}"...
4138
+ console.log(pc10.dim(`Searching marketplaces for "${query}"...
3944
4139
  `));
3945
4140
  }
3946
4141
  let results;
@@ -3954,7 +4149,7 @@ function registerSkillsFind(parent) {
3954
4149
  limit
3955
4150
  });
3956
4151
  } else {
3957
- console.error(pc9.red(`Marketplace search failed: ${message}`));
4152
+ console.error(pc10.red(`Marketplace search failed: ${message}`));
3958
4153
  }
3959
4154
  process.exit(1);
3960
4155
  }
@@ -3974,21 +4169,21 @@ function registerSkillsFind(parent) {
3974
4169
  return;
3975
4170
  }
3976
4171
  if (results.length === 0) {
3977
- console.log(pc9.yellow("No results found."));
4172
+ console.log(pc10.yellow("No results found."));
3978
4173
  return;
3979
4174
  }
3980
- console.log(pc9.dim(`Found ${results.length} result(s) for "${query}":
4175
+ console.log(pc10.dim(`Found ${results.length} result(s) for "${query}":
3981
4176
  `));
3982
4177
  results.forEach((skill, index) => {
3983
4178
  const num = (index + 1).toString().padStart(2);
3984
- const stars = skill.stars > 0 ? pc9.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
3985
- console.log(` ${pc9.cyan(num)}. ${pc9.bold(skill.scopedName)} ${stars}`);
3986
- console.log(` ${pc9.dim(skill.description?.slice(0, 80) ?? "")}`);
3987
- console.log(` ${pc9.dim(`from ${skill.source}`)}`);
4179
+ const stars = skill.stars > 0 ? pc10.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
4180
+ console.log(` ${pc10.cyan(num)}. ${pc10.bold(skill.scopedName)} ${stars}`);
4181
+ console.log(` ${pc10.dim(skill.description?.slice(0, 80) ?? "")}`);
4182
+ console.log(` ${pc10.dim(`from ${skill.source}`)}`);
3988
4183
  console.log();
3989
4184
  });
3990
- console.log(pc9.dim("Install with: caamp skills install <name>"));
3991
- console.log(pc9.dim("Or select by number: caamp skills install <n>"));
4185
+ console.log(pc10.dim("Install with: caamp skills install <name>"));
4186
+ console.log(pc10.dim("Or select by number: caamp skills install <n>"));
3992
4187
  });
3993
4188
  }
3994
4189
  function formatStars(n) {
@@ -4080,7 +4275,7 @@ function buildEnvelope3(operation, mvi, result, error) {
4080
4275
  schemaVersion: "1.0.0",
4081
4276
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4082
4277
  operation,
4083
- requestId: randomUUID4(),
4278
+ requestId: randomUUID3(),
4084
4279
  transport: "cli",
4085
4280
  strict: true,
4086
4281
  mvi,
@@ -4105,10 +4300,10 @@ function emitJsonError3(operation, mvi, code, message, category, details = {}) {
4105
4300
  }
4106
4301
 
4107
4302
  // src/commands/skills/init.ts
4108
- import { existsSync as existsSync10 } from "fs";
4303
+ import { existsSync as existsSync11 } from "fs";
4109
4304
  import { mkdir, writeFile as writeFile3 } from "fs/promises";
4110
- import { join as join8 } from "path";
4111
- import pc10 from "picocolors";
4305
+ import { join as join9 } from "path";
4306
+ import pc11 from "picocolors";
4112
4307
  function registerSkillsInit(parent) {
4113
4308
  parent.command("init").description("Create a new SKILL.md template").argument("[name]", "Skill name").option("-d, --dir <path>", "Output directory", ".").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
4114
4309
  async (name, opts) => {
@@ -4133,8 +4328,8 @@ function registerSkillsInit(parent) {
4133
4328
  process.exit(1);
4134
4329
  }
4135
4330
  const skillName = name ?? "my-skill";
4136
- const skillDir = join8(opts.dir, skillName);
4137
- if (existsSync10(skillDir)) {
4331
+ const skillDir = join9(opts.dir, skillName);
4332
+ if (existsSync11(skillDir)) {
4138
4333
  const message = `Directory already exists: ${skillDir}`;
4139
4334
  if (format === "json") {
4140
4335
  emitJsonError(
@@ -4148,7 +4343,7 @@ function registerSkillsInit(parent) {
4148
4343
  }
4149
4344
  );
4150
4345
  } else {
4151
- console.error(pc10.red(message));
4346
+ console.error(pc11.red(message));
4152
4347
  }
4153
4348
  process.exit(1);
4154
4349
  }
@@ -4176,7 +4371,7 @@ Provide detailed instructions for the AI agent here.
4176
4371
 
4177
4372
  Show example inputs and expected outputs.
4178
4373
  `;
4179
- await writeFile3(join8(skillDir, "SKILL.md"), template, "utf-8");
4374
+ await writeFile3(join9(skillDir, "SKILL.md"), template, "utf-8");
4180
4375
  const result = {
4181
4376
  name: skillName,
4182
4377
  directory: skillDir,
@@ -4187,18 +4382,18 @@ Show example inputs and expected outputs.
4187
4382
  outputSuccess(operation, mvi, result);
4188
4383
  return;
4189
4384
  }
4190
- console.log(pc10.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
4191
- console.log(pc10.dim("\nNext steps:"));
4192
- console.log(pc10.dim(" 1. Edit SKILL.md with your instructions"));
4193
- console.log(pc10.dim(` 2. Validate: caamp skills validate ${join8(skillDir, "SKILL.md")}`));
4194
- console.log(pc10.dim(` 3. Install: caamp skills install ${skillDir}`));
4385
+ console.log(pc11.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
4386
+ console.log(pc11.dim("\nNext steps:"));
4387
+ console.log(pc11.dim(" 1. Edit SKILL.md with your instructions"));
4388
+ console.log(pc11.dim(` 2. Validate: caamp skills validate ${join9(skillDir, "SKILL.md")}`));
4389
+ console.log(pc11.dim(` 3. Install: caamp skills install ${skillDir}`));
4195
4390
  }
4196
4391
  );
4197
4392
  }
4198
4393
 
4199
4394
  // src/commands/skills/install.ts
4200
- import { existsSync as existsSync11 } from "fs";
4201
- import pc11 from "picocolors";
4395
+ import { existsSync as existsSync12 } from "fs";
4396
+ import pc12 from "picocolors";
4202
4397
  function registerSkillsInstall(parent) {
4203
4398
  parent.command("install").description("Install a skill from GitHub, URL, marketplace, or registered skill library").argument("[source]", "Skill source (GitHub URL, owner/repo, @author/name, skill-name)").option(
4204
4399
  "-a, --agent <name>",
@@ -4241,7 +4436,7 @@ function registerSkillsInstall(parent) {
4241
4436
  if (providers.length === 0) {
4242
4437
  const message = "No target providers found. Use --agent or --all.";
4243
4438
  if (format === "json") {
4244
- emitError2(
4439
+ emitError(
4245
4440
  operation,
4246
4441
  mvi,
4247
4442
  ErrorCodes.PROVIDER_NOT_FOUND,
@@ -4249,7 +4444,7 @@ function registerSkillsInstall(parent) {
4249
4444
  ErrorCategories.NOT_FOUND
4250
4445
  );
4251
4446
  }
4252
- console.error(pc11.red(message));
4447
+ console.error(pc12.red(message));
4253
4448
  process.exit(1);
4254
4449
  }
4255
4450
  if (opts.profile) {
@@ -4266,7 +4461,7 @@ function registerSkillsInstall(parent) {
4266
4461
  if (!source) {
4267
4462
  const message = "Missing required argument: source";
4268
4463
  if (format === "json") {
4269
- emitError2(
4464
+ emitError(
4270
4465
  operation,
4271
4466
  mvi,
4272
4467
  ErrorCodes.INVALID_INPUT,
@@ -4274,14 +4469,14 @@ function registerSkillsInstall(parent) {
4274
4469
  ErrorCategories.VALIDATION
4275
4470
  );
4276
4471
  }
4277
- console.error(pc11.red(message));
4472
+ console.error(pc12.red(message));
4278
4473
  console.log(
4279
- pc11.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>")
4474
+ pc12.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>")
4280
4475
  );
4281
4476
  process.exit(1);
4282
4477
  }
4283
4478
  if (format === "human") {
4284
- console.log(pc11.dim(`Installing to ${providers.length} provider(s)...`));
4479
+ console.log(pc12.dim(`Installing to ${providers.length} provider(s)...`));
4285
4480
  }
4286
4481
  let localPath;
4287
4482
  let cleanup;
@@ -4327,7 +4522,7 @@ function registerSkillsInstall(parent) {
4327
4522
  ErrorCategories.TRANSIENT
4328
4523
  );
4329
4524
  }
4330
- console.error(pc11.red(message));
4525
+ console.error(pc12.red(message));
4331
4526
  process.exit(1);
4332
4527
  }
4333
4528
  } else if (parsed.type === "gitlab" && parsed.owner && parsed.repo) {
@@ -4351,7 +4546,7 @@ function registerSkillsInstall(parent) {
4351
4546
  ErrorCategories.TRANSIENT
4352
4547
  );
4353
4548
  }
4354
- console.error(pc11.red(message));
4549
+ console.error(pc12.red(message));
4355
4550
  process.exit(1);
4356
4551
  }
4357
4552
  } else if (parsed.type === "local") {
@@ -4372,7 +4567,7 @@ function registerSkillsInstall(parent) {
4372
4567
  ErrorCategories.VALIDATION
4373
4568
  );
4374
4569
  }
4375
- console.error(pc11.red(message));
4570
+ console.error(pc12.red(message));
4376
4571
  process.exit(1);
4377
4572
  }
4378
4573
  const catalogSkill = getSkill(parsed.inferredName);
@@ -4383,7 +4578,7 @@ function registerSkillsInstall(parent) {
4383
4578
  sourceType = "library";
4384
4579
  if (format === "human") {
4385
4580
  console.log(
4386
- ` Found in catalog: ${pc11.bold(catalogSkill.name)} v${catalogSkill.version} (${pc11.dim(catalogSkill.category)})`
4581
+ ` Found in catalog: ${pc12.bold(catalogSkill.name)} v${catalogSkill.version} (${pc12.dim(catalogSkill.category)})`
4387
4582
  );
4388
4583
  }
4389
4584
  } else {
@@ -4400,8 +4595,8 @@ function registerSkillsInstall(parent) {
4400
4595
  }
4401
4596
  );
4402
4597
  }
4403
- console.error(pc11.red(message));
4404
- console.log(pc11.dim("Available skills: " + listSkills().join(", ")));
4598
+ console.error(pc12.red(message));
4599
+ console.log(pc12.dim("Available skills: " + listSkills().join(", ")));
4405
4600
  process.exit(1);
4406
4601
  }
4407
4602
  } else {
@@ -4415,7 +4610,7 @@ function registerSkillsInstall(parent) {
4415
4610
  ErrorCategories.VALIDATION
4416
4611
  );
4417
4612
  }
4418
- console.error(pc11.red(message));
4613
+ console.error(pc12.red(message));
4419
4614
  process.exit(1);
4420
4615
  }
4421
4616
  }
@@ -4431,7 +4626,7 @@ function registerSkillsInstall(parent) {
4431
4626
  ErrorCategories.INTERNAL
4432
4627
  );
4433
4628
  }
4434
- console.error(pc11.red(message));
4629
+ console.error(pc12.red(message));
4435
4630
  process.exit(1);
4436
4631
  }
4437
4632
  const result = await dispatchInstallSkillAcrossProviders(
@@ -4469,14 +4664,14 @@ function registerSkillsInstall(parent) {
4469
4664
  if (format === "json") {
4470
4665
  outputSuccess(operation, mvi, summary);
4471
4666
  } else {
4472
- console.log(pc11.green(`
4473
- \u2713 Installed ${pc11.bold(skillName)}`));
4474
- console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
4667
+ console.log(pc12.green(`
4668
+ \u2713 Installed ${pc12.bold(skillName)}`));
4669
+ console.log(` Canonical: ${pc12.dim(result.canonicalPath)}`);
4475
4670
  console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
4476
4671
  if (result.errors.length > 0) {
4477
- console.log(pc11.yellow("\nWarnings:"));
4672
+ console.log(pc12.yellow("\nWarnings:"));
4478
4673
  for (const err of result.errors) {
4479
- console.log(` ${pc11.yellow("!")} ${err}`);
4674
+ console.log(` ${pc12.yellow("!")} ${err}`);
4480
4675
  }
4481
4676
  }
4482
4677
  }
@@ -4506,11 +4701,11 @@ function registerSkillsInstall(parent) {
4506
4701
  });
4507
4702
  console.error(JSON.stringify(envelope, null, 2));
4508
4703
  } else {
4509
- console.log(pc11.yellow(`
4510
- \u2717 Failed to install ${pc11.bold(skillName)}`));
4511
- console.log(pc11.yellow("Errors:"));
4704
+ console.log(pc12.yellow(`
4705
+ \u2717 Failed to install ${pc12.bold(skillName)}`));
4706
+ console.log(pc12.yellow("Errors:"));
4512
4707
  for (const err of result.errors) {
4513
- console.log(` ${pc11.yellow("!")} ${err}`);
4708
+ console.log(` ${pc12.yellow("!")} ${err}`);
4514
4709
  }
4515
4710
  }
4516
4711
  process.exit(1);
@@ -4525,9 +4720,9 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4525
4720
  if (!isCatalogAvailable()) {
4526
4721
  const message = "No skill library registered. Register one with registerSkillLibraryFromPath() or set CAAMP_SKILL_LIBRARY env var.";
4527
4722
  if (format === "json") {
4528
- emitError2(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
4723
+ emitError(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
4529
4724
  }
4530
- console.error(pc11.red(message));
4725
+ console.error(pc12.red(message));
4531
4726
  process.exit(1);
4532
4727
  }
4533
4728
  const profileSkills = resolveProfile(profileName);
@@ -4545,16 +4740,16 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4545
4740
  }
4546
4741
  );
4547
4742
  }
4548
- console.error(pc11.red(message));
4743
+ console.error(pc12.red(message));
4549
4744
  const available = listProfiles();
4550
4745
  if (available.length > 0) {
4551
- console.log(pc11.dim("Available profiles: " + available.join(", ")));
4746
+ console.log(pc12.dim("Available profiles: " + available.join(", ")));
4552
4747
  }
4553
4748
  process.exit(1);
4554
4749
  }
4555
4750
  if (format === "human") {
4556
- console.log(`Installing profile ${pc11.bold(profileName)} (${profileSkills.length} skill(s))...`);
4557
- console.log(pc11.dim(`Target: ${providers.length} provider(s)`));
4751
+ console.log(`Installing profile ${pc12.bold(profileName)} (${profileSkills.length} skill(s))...`);
4752
+ console.log(pc12.dim(`Target: ${providers.length} provider(s)`));
4558
4753
  }
4559
4754
  const installed = [];
4560
4755
  const failed = [];
@@ -4564,7 +4759,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4564
4759
  const result = await dispatchInstallSkillAcrossProviders(skillDir, name, providers, isGlobal);
4565
4760
  if (result.success) {
4566
4761
  if (format === "human") {
4567
- console.log(pc11.green(` + ${name}`));
4762
+ console.log(pc12.green(` + ${name}`));
4568
4763
  }
4569
4764
  await recordSkillInstall(
4570
4765
  name,
@@ -4583,7 +4778,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4583
4778
  });
4584
4779
  } else {
4585
4780
  if (format === "human") {
4586
- console.log(pc11.yellow(` ! ${name}: ${result.errors.join(", ")}`));
4781
+ console.log(pc12.yellow(` ! ${name}: ${result.errors.join(", ")}`));
4587
4782
  }
4588
4783
  failed.push({
4589
4784
  name,
@@ -4593,7 +4788,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4593
4788
  } catch (err) {
4594
4789
  const errorMsg = err instanceof Error ? err.message : String(err);
4595
4790
  if (format === "human") {
4596
- console.log(pc11.red(` x ${name}: ${errorMsg}`));
4791
+ console.log(pc12.red(` x ${name}: ${errorMsg}`));
4597
4792
  }
4598
4793
  failed.push({
4599
4794
  name,
@@ -4628,7 +4823,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4628
4823
  } else {
4629
4824
  console.log(
4630
4825
  `
4631
- ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yellow(`${failed.length} failed`) : "0 failed"}`
4826
+ ${pc12.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc12.yellow(`${failed.length} failed`) : "0 failed"}`
4632
4827
  );
4633
4828
  if (failed.length > 0) {
4634
4829
  process.exit(1);
@@ -4637,7 +4832,7 @@ ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yello
4637
4832
  }
4638
4833
  async function handleMarketplaceSource(source, _providers, _isGlobal, format, operation, mvi) {
4639
4834
  if (format === "human") {
4640
- console.log(pc11.dim(`Searching marketplace for ${source}...`));
4835
+ console.log(pc12.dim(`Searching marketplace for ${source}...`));
4641
4836
  }
4642
4837
  const client = new MarketplaceClient();
4643
4838
  let skill;
@@ -4648,7 +4843,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4648
4843
  if (format === "json") {
4649
4844
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
4650
4845
  }
4651
- console.error(pc11.red(message));
4846
+ console.error(pc12.red(message));
4652
4847
  return { success: false };
4653
4848
  }
4654
4849
  if (!skill) {
@@ -4656,12 +4851,12 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4656
4851
  if (format === "json") {
4657
4852
  emitJsonError(operation, mvi, ErrorCodes.SKILL_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
4658
4853
  }
4659
- console.error(pc11.red(message));
4854
+ console.error(pc12.red(message));
4660
4855
  return { success: false };
4661
4856
  }
4662
4857
  if (format === "human") {
4663
4858
  console.log(
4664
- ` Found: ${pc11.bold(skill.name)} by ${skill.author} (${pc11.dim(skill.repoFullName)})`
4859
+ ` Found: ${pc12.bold(skill.name)} by ${skill.author} (${pc12.dim(skill.repoFullName)})`
4665
4860
  );
4666
4861
  }
4667
4862
  const parsed = parseSource(skill.githubUrl);
@@ -4670,7 +4865,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4670
4865
  if (format === "json") {
4671
4866
  emitJsonError(operation, mvi, ErrorCodes.INVALID_FORMAT, message, ErrorCategories.VALIDATION);
4672
4867
  }
4673
- console.error(pc11.red(message));
4868
+ console.error(pc12.red(message));
4674
4869
  return { success: false };
4675
4870
  }
4676
4871
  try {
@@ -4682,7 +4877,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4682
4877
  for (const subPath of subPathCandidates) {
4683
4878
  try {
4684
4879
  const result = await cloneRepo(parsed.owner, parsed.repo, parsed.ref, subPath);
4685
- if (subPath && !existsSync11(result.localPath)) {
4880
+ if (subPath && !existsSync12(result.localPath)) {
4686
4881
  await result.cleanup();
4687
4882
  continue;
4688
4883
  }
@@ -4710,22 +4905,22 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4710
4905
  if (format === "json") {
4711
4906
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
4712
4907
  }
4713
- console.error(pc11.red(message));
4908
+ console.error(pc12.red(message));
4714
4909
  return { success: false };
4715
4910
  }
4716
4911
  }
4717
4912
 
4718
4913
  // src/commands/skills/list.ts
4719
- import { randomUUID as randomUUID5 } from "crypto";
4720
- import { resolveOutputFormat as resolveOutputFormat4 } from "@cleocode/lafs";
4721
- import pc12 from "picocolors";
4914
+ import { randomUUID as randomUUID4 } from "crypto";
4915
+ import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
4916
+ import pc13 from "picocolors";
4722
4917
  function registerSkillsList(parent) {
4723
4918
  parent.command("list").description("List installed skills").option("-g, --global", "List global skills").option("-a, --agent <name>", "List skills for specific agent").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
4724
4919
  const operation = "skills.list";
4725
4920
  const mvi = "standard";
4726
4921
  let format;
4727
4922
  try {
4728
- format = resolveOutputFormat4({
4923
+ format = resolveOutputFormat3({
4729
4924
  jsonFlag: opts.json ?? false,
4730
4925
  humanFlag: (opts.human ?? false) || isHuman(),
4731
4926
  projectDefault: "json"
@@ -4745,7 +4940,7 @@ function registerSkillsList(parent) {
4745
4940
  agent: opts.agent
4746
4941
  });
4747
4942
  } else {
4748
- console.error(pc12.red(message));
4943
+ console.error(pc13.red(message));
4749
4944
  }
4750
4945
  process.exit(1);
4751
4946
  }
@@ -4773,21 +4968,21 @@ function registerSkillsList(parent) {
4773
4968
  return;
4774
4969
  }
4775
4970
  if (skills.length === 0) {
4776
- console.log(pc12.dim("No skills found."));
4971
+ console.log(pc13.dim("No skills found."));
4777
4972
  return;
4778
4973
  }
4779
- console.log(pc12.bold(`
4974
+ console.log(pc13.bold(`
4780
4975
  ${skills.length} skill(s) found:
4781
4976
  `));
4782
4977
  skills.forEach((skill, index) => {
4783
4978
  const num = (index + 1).toString().padStart(2);
4784
4979
  console.log(
4785
- ` ${pc12.cyan(num)}. ${pc12.bold(skill.name.padEnd(30))} ${pc12.dim(skill.metadata?.description ?? "")}`
4980
+ ` ${pc13.cyan(num)}. ${pc13.bold(skill.name.padEnd(30))} ${pc13.dim(skill.metadata?.description ?? "")}`
4786
4981
  );
4787
4982
  });
4788
- console.log(pc12.dim(`
4983
+ console.log(pc13.dim(`
4789
4984
  Install with: caamp skills install <name>`));
4790
- console.log(pc12.dim(`Remove with: caamp skills remove <name>`));
4985
+ console.log(pc13.dim(`Remove with: caamp skills remove <name>`));
4791
4986
  });
4792
4987
  }
4793
4988
  function buildEnvelope4(operation, mvi, result, error) {
@@ -4798,7 +4993,7 @@ function buildEnvelope4(operation, mvi, result, error) {
4798
4993
  schemaVersion: "1.0.0",
4799
4994
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4800
4995
  operation,
4801
- requestId: randomUUID5(),
4996
+ requestId: randomUUID4(),
4802
4997
  transport: "cli",
4803
4998
  strict: true,
4804
4999
  mvi,
@@ -4823,7 +5018,7 @@ function emitJsonError4(operation, mvi, code, message, category, details = {}) {
4823
5018
  }
4824
5019
 
4825
5020
  // src/commands/skills/remove.ts
4826
- import pc13 from "picocolors";
5021
+ import pc14 from "picocolors";
4827
5022
  function registerSkillsRemove(parent) {
4828
5023
  parent.command("remove").description("Remove installed skill(s)").argument("[name]", "Skill name to remove").option("-g, --global", "Remove from global scope").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
4829
5024
  async (name, opts) => {
@@ -4873,14 +5068,14 @@ function registerSkillsRemove(parent) {
4873
5068
  return;
4874
5069
  }
4875
5070
  if (removed.length > 0) {
4876
- console.log(pc13.green(`\u2713 Removed ${pc13.bold(name)} from: ${removed.join(", ")}`));
5071
+ console.log(pc14.green(`\u2713 Removed ${pc14.bold(name)} from: ${removed.join(", ")}`));
4877
5072
  await removeSkillFromLock(name);
4878
5073
  } else {
4879
- console.log(pc13.yellow(`Skill ${name} not found in any provider.`));
5074
+ console.log(pc14.yellow(`Skill ${name} not found in any provider.`));
4880
5075
  }
4881
5076
  if (result.errors.length > 0) {
4882
5077
  for (const err of result.errors) {
4883
- console.log(pc13.red(` ${err}`));
5078
+ console.log(pc14.red(` ${err}`));
4884
5079
  }
4885
5080
  }
4886
5081
  } else {
@@ -4893,7 +5088,7 @@ function registerSkillsRemove(parent) {
4893
5088
  count: { removed: 0, total: 0 }
4894
5089
  });
4895
5090
  } else {
4896
- console.log(pc13.dim("No skills installed."));
5091
+ console.log(pc14.dim("No skills installed."));
4897
5092
  }
4898
5093
  return;
4899
5094
  }
@@ -4906,18 +5101,18 @@ function registerSkillsRemove(parent) {
4906
5101
  });
4907
5102
  return;
4908
5103
  }
4909
- console.log(pc13.bold("Installed skills:"));
5104
+ console.log(pc14.bold("Installed skills:"));
4910
5105
  for (const s of skills) {
4911
5106
  console.log(` ${s}`);
4912
5107
  }
4913
- console.log(pc13.dim("\nUse: caamp skills remove <name>"));
5108
+ console.log(pc14.dim("\nUse: caamp skills remove <name>"));
4914
5109
  }
4915
5110
  }
4916
5111
  );
4917
5112
  }
4918
5113
 
4919
5114
  // src/commands/skills/update.ts
4920
- import pc14 from "picocolors";
5115
+ import pc15 from "picocolors";
4921
5116
  function registerSkillsUpdate(parent) {
4922
5117
  parent.command("update").description("Update all outdated skills").option("-y, --yes", "Skip confirmation").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (opts) => {
4923
5118
  const operation = "skills.update";
@@ -4951,12 +5146,12 @@ function registerSkillsUpdate(parent) {
4951
5146
  count: { updated: 0, failed: 0, skipped: 0 }
4952
5147
  });
4953
5148
  } else {
4954
- console.log(pc14.dim("No tracked skills to update."));
5149
+ console.log(pc15.dim("No tracked skills to update."));
4955
5150
  }
4956
5151
  return;
4957
5152
  }
4958
5153
  if (format === "human") {
4959
- console.log(pc14.dim(`Checking ${entries.length} skill(s) for updates...`));
5154
+ console.log(pc15.dim(`Checking ${entries.length} skill(s) for updates...`));
4960
5155
  }
4961
5156
  const outdated = [];
4962
5157
  for (const [name] of entries) {
@@ -4978,19 +5173,19 @@ function registerSkillsUpdate(parent) {
4978
5173
  count: { updated: 0, failed: 0, skipped: 0 }
4979
5174
  });
4980
5175
  } else {
4981
- console.log(pc14.green("\nAll skills are up to date."));
5176
+ console.log(pc15.green("\nAll skills are up to date."));
4982
5177
  }
4983
5178
  return;
4984
5179
  }
4985
5180
  if (format === "human") {
4986
- console.log(pc14.yellow(`
5181
+ console.log(pc15.yellow(`
4987
5182
  ${outdated.length} skill(s) have updates available:
4988
5183
  `));
4989
5184
  for (const skill of outdated) {
4990
5185
  const current = skill.currentVersion?.slice(0, 12) ?? "?";
4991
5186
  const latest = skill.latestVersion ?? "?";
4992
5187
  console.log(
4993
- ` ${pc14.bold(skill.name)} ${pc14.dim(current)} ${pc14.dim("->")} ${pc14.cyan(latest)}`
5188
+ ` ${pc15.bold(skill.name)} ${pc15.dim(current)} ${pc15.dim("->")} ${pc15.cyan(latest)}`
4994
5189
  );
4995
5190
  }
4996
5191
  }
@@ -4998,11 +5193,11 @@ ${outdated.length} skill(s) have updates available:
4998
5193
  const readline = await import("readline");
4999
5194
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5000
5195
  const answer = await new Promise((resolve3) => {
5001
- rl.question(pc14.dim("\nProceed with update? [y/N] "), resolve3);
5196
+ rl.question(pc15.dim("\nProceed with update? [y/N] "), resolve3);
5002
5197
  });
5003
5198
  rl.close();
5004
5199
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
5005
- console.log(pc14.dim("Update cancelled."));
5200
+ console.log(pc15.dim("Update cancelled."));
5006
5201
  return;
5007
5202
  }
5008
5203
  }
@@ -5016,7 +5211,7 @@ ${outdated.length} skill(s) have updates available:
5016
5211
  const entry = tracked[skill.name];
5017
5212
  if (!entry) continue;
5018
5213
  if (format === "human") {
5019
- console.log(pc14.dim(`Updating ${pc14.bold(skill.name)}...`));
5214
+ console.log(pc15.dim(`Updating ${pc15.bold(skill.name)}...`));
5020
5215
  }
5021
5216
  try {
5022
5217
  const parsed = parseSource(entry.source);
@@ -5038,7 +5233,7 @@ ${outdated.length} skill(s) have updates available:
5038
5233
  } else {
5039
5234
  if (format === "human") {
5040
5235
  console.log(
5041
- pc14.yellow(
5236
+ pc15.yellow(
5042
5237
  ` Skipped ${skill.name}: source type "${parsed.type}" does not support auto-update`
5043
5238
  )
5044
5239
  );
@@ -5050,7 +5245,7 @@ ${outdated.length} skill(s) have updates available:
5050
5245
  const providers = entry.agents.map((a) => getProvider(a)).filter((p) => p !== void 0);
5051
5246
  if (providers.length === 0) {
5052
5247
  if (format === "human") {
5053
- console.log(pc14.yellow(` Skipped ${skill.name}: no valid providers found`));
5248
+ console.log(pc15.yellow(` Skipped ${skill.name}: no valid providers found`));
5054
5249
  }
5055
5250
  skipped.push(skill.name);
5056
5251
  continue;
@@ -5075,18 +5270,18 @@ ${outdated.length} skill(s) have updates available:
5075
5270
  skill.latestVersion
5076
5271
  );
5077
5272
  if (format === "human") {
5078
- console.log(pc14.green(` Updated ${pc14.bold(skill.name)}`));
5273
+ console.log(pc15.green(` Updated ${pc15.bold(skill.name)}`));
5079
5274
  }
5080
5275
  updated.push(skill.name);
5081
5276
  } else {
5082
5277
  if (format === "human") {
5083
- console.log(pc14.red(` Failed to update ${skill.name}: no agents linked`));
5278
+ console.log(pc15.red(` Failed to update ${skill.name}: no agents linked`));
5084
5279
  }
5085
5280
  failed.push({ name: skill.name, error: "no agents linked" });
5086
5281
  }
5087
5282
  if (installResult.errors.length > 0 && format === "human") {
5088
5283
  for (const err of installResult.errors) {
5089
- console.log(pc14.yellow(` ${err}`));
5284
+ console.log(pc15.yellow(` ${err}`));
5090
5285
  }
5091
5286
  }
5092
5287
  } finally {
@@ -5095,7 +5290,7 @@ ${outdated.length} skill(s) have updates available:
5095
5290
  } catch (err) {
5096
5291
  const msg = err instanceof Error ? err.message : String(err);
5097
5292
  if (format === "human") {
5098
- console.log(pc14.red(` Failed to update ${skill.name}: ${msg}`));
5293
+ console.log(pc15.red(` Failed to update ${skill.name}: ${msg}`));
5099
5294
  }
5100
5295
  failed.push({ name: skill.name, error: msg });
5101
5296
  }
@@ -5115,24 +5310,24 @@ ${outdated.length} skill(s) have updates available:
5115
5310
  }
5116
5311
  console.log();
5117
5312
  if (updated.length > 0) {
5118
- console.log(pc14.green(`Updated ${updated.length} skill(s).`));
5313
+ console.log(pc15.green(`Updated ${updated.length} skill(s).`));
5119
5314
  }
5120
5315
  if (failed.length > 0) {
5121
- console.log(pc14.red(`Failed to update ${failed.length} skill(s).`));
5316
+ console.log(pc15.red(`Failed to update ${failed.length} skill(s).`));
5122
5317
  }
5123
5318
  });
5124
5319
  }
5125
5320
 
5126
5321
  // src/commands/skills/validate.ts
5127
- import { resolveOutputFormat as resolveOutputFormat5 } from "@cleocode/lafs";
5128
- import pc15 from "picocolors";
5322
+ import { resolveOutputFormat as resolveOutputFormat4 } from "@cleocode/lafs";
5323
+ import pc16 from "picocolors";
5129
5324
  function registerSkillsValidate(parent) {
5130
5325
  parent.command("validate").description("Validate SKILL.md format").argument("[path]", "Path to SKILL.md", "SKILL.md").option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(async (path, opts) => {
5131
5326
  const operation = "skills.validate";
5132
5327
  const mvi = "standard";
5133
5328
  let format;
5134
5329
  try {
5135
- format = resolveOutputFormat5({
5330
+ format = resolveOutputFormat4({
5136
5331
  jsonFlag: opts.json ?? false,
5137
5332
  humanFlag: (opts.human ?? false) || isHuman(),
5138
5333
  projectDefault: "json"
@@ -5165,7 +5360,7 @@ function registerSkillsValidate(parent) {
5165
5360
  }
5166
5361
  );
5167
5362
  } else {
5168
- console.error(pc15.red(message));
5363
+ console.error(pc16.red(message));
5169
5364
  }
5170
5365
  process.exit(1);
5171
5366
  }
@@ -5187,12 +5382,12 @@ function registerSkillsValidate(parent) {
5187
5382
  console.log(JSON.stringify(envelope, null, 2));
5188
5383
  } else {
5189
5384
  if (result.valid) {
5190
- console.log(pc15.green(`\u2713 ${path} is valid`));
5385
+ console.log(pc16.green(`\u2713 ${path} is valid`));
5191
5386
  } else {
5192
- console.log(pc15.red(`\u2717 ${path} has validation errors`));
5387
+ console.log(pc16.red(`\u2717 ${path} has validation errors`));
5193
5388
  }
5194
5389
  for (const issue of result.issues) {
5195
- const icon = issue.level === "error" ? pc15.red("\u2717") : pc15.yellow("!");
5390
+ const icon = issue.level === "error" ? pc16.red("\u2717") : pc16.yellow("!");
5196
5391
  console.log(` ${icon} [${issue.field}] ${issue.message}`);
5197
5392
  }
5198
5393
  }
@@ -5214,6 +5409,8 @@ function registerSkillsCommands(program2) {
5214
5409
  registerSkillsInit(skills);
5215
5410
  registerSkillsAudit(skills);
5216
5411
  registerSkillsValidate(skills);
5412
+ registerSkillsDoctorMigrate(skills);
5413
+ registerSkillsDoctor(skills);
5217
5414
  }
5218
5415
 
5219
5416
  // src/cli.ts