@cleocode/caamp 2026.5.83 → 2026.5.86

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,31 @@ 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,
47
+ registerSkillsDoctorAdopt,
40
48
  removeMcpServer,
41
49
  removeMcpServerFromAll,
42
50
  removeSkillFromLock,
43
51
  resolveDefaultTargetProviders,
52
+ resolveFormat,
44
53
  resolveProfile,
45
54
  scanDirectory,
46
55
  scanFile,
@@ -52,7 +61,7 @@ import {
52
61
  tokenizeCriteriaValue,
53
62
  updateInstructionsSingleOperation,
54
63
  validateSkill
55
- } from "./chunk-4W35AEYA.js";
64
+ } from "./chunk-WXL7RPS4.js";
56
65
  import {
57
66
  buildSkillsMap,
58
67
  checkAllInjections,
@@ -65,7 +74,7 @@ import {
65
74
  groupByInstructFile,
66
75
  injectAll,
67
76
  providerSupports
68
- } from "./chunk-OPUPNLUJ.js";
77
+ } from "./chunk-PGETUTYZ.js";
69
78
  import {
70
79
  CANONICAL_HOOK_EVENTS,
71
80
  buildHookMatrix,
@@ -74,12 +83,12 @@ import {
74
83
  getHookSupport,
75
84
  getProviderSummary,
76
85
  translateToAll
77
- } from "./chunk-SV33CE5X.js";
86
+ } from "./chunk-QKC2JRSG.js";
78
87
  import {
79
88
  buildSkillSubPathCandidates,
80
89
  resolveProviderConfigPath,
81
90
  resolveProviderSkillsDir
82
- } from "./chunk-OCI4RYI5.js";
91
+ } from "./chunk-H5YXR2DC.js";
83
92
 
84
93
  // src/cli.ts
85
94
  import { Command } from "commander";
@@ -153,7 +162,7 @@ function emitSuccess(operation, result, mvi = "standard") {
153
162
  };
154
163
  console.log(JSON.stringify(envelope, null, 2));
155
164
  }
156
- function emitError(operation, error, mvi = "standard") {
165
+ function emitError2(operation, error, mvi = "standard") {
157
166
  let envelope;
158
167
  if (error instanceof LAFSCommandError) {
159
168
  envelope = {
@@ -204,7 +213,7 @@ async function runLafsCommand(command, mvi, action) {
204
213
  const result = await action();
205
214
  emitSuccess(command, result, mvi);
206
215
  } catch (error) {
207
- emitError(command, error, mvi);
216
+ emitError2(command, error, mvi);
208
217
  process.exit(1);
209
218
  }
210
219
  }
@@ -499,117 +508,6 @@ function registerAdvancedCommands(program2) {
499
508
  // src/commands/config.ts
500
509
  import { existsSync } from "fs";
501
510
  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
511
  function registerConfigCommand(program2) {
614
512
  const config = program2.command("config").description("View provider configuration");
615
513
  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 +2837,8 @@ function registerPiCommands(program2) {
2939
2837
  }
2940
2838
 
2941
2839
  // src/commands/providers.ts
2942
- import { randomUUID as randomUUID3 } from "crypto";
2943
- import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
2840
+ import { randomUUID as randomUUID2 } from "crypto";
2841
+ import { resolveOutputFormat } from "@cleocode/lafs";
2944
2842
  import pc6 from "picocolors";
2945
2843
  function registerProvidersCommand(program2) {
2946
2844
  const providers = program2.command("providers").description("Manage AI agent providers");
@@ -2949,7 +2847,7 @@ function registerProvidersCommand(program2) {
2949
2847
  const mvi = "standard";
2950
2848
  let format;
2951
2849
  try {
2952
- format = resolveOutputFormat2({
2850
+ format = resolveOutputFormat({
2953
2851
  jsonFlag: opts.json ?? false,
2954
2852
  humanFlag: (opts.human ?? false) || isHuman(),
2955
2853
  projectDefault: "json"
@@ -2999,7 +2897,7 @@ CAMP Provider Registry v${getRegistryVersion()}`));
2999
2897
  const mvi = "standard";
3000
2898
  let format;
3001
2899
  try {
3002
- format = resolveOutputFormat2({
2900
+ format = resolveOutputFormat({
3003
2901
  jsonFlag: opts.json ?? false,
3004
2902
  humanFlag: (opts.human ?? false) || isHuman(),
3005
2903
  projectDefault: "json"
@@ -3055,7 +2953,7 @@ Detected ${installed.length} installed providers:
3055
2953
  const mvi = "standard";
3056
2954
  let format;
3057
2955
  try {
3058
- format = resolveOutputFormat2({
2956
+ format = resolveOutputFormat({
3059
2957
  jsonFlag: opts.json ?? false,
3060
2958
  humanFlag: (opts.human ?? false) || isHuman(),
3061
2959
  projectDefault: "json"
@@ -3128,7 +3026,7 @@ ${provider.toolName}`));
3128
3026
  const mvi = "standard";
3129
3027
  let format;
3130
3028
  try {
3131
- format = resolveOutputFormat2({
3029
+ format = resolveOutputFormat({
3132
3030
  jsonFlag: opts.json ?? false,
3133
3031
  humanFlag: (opts.human ?? false) || isHuman(),
3134
3032
  projectDefault: "json"
@@ -3186,7 +3084,7 @@ ${provider.toolName}`));
3186
3084
  const mvi = "standard";
3187
3085
  let format;
3188
3086
  try {
3189
- format = resolveOutputFormat2({
3087
+ format = resolveOutputFormat({
3190
3088
  jsonFlag: opts.json ?? false,
3191
3089
  humanFlag: (opts.human ?? false) || isHuman(),
3192
3090
  projectDefault: "json"
@@ -3254,7 +3152,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3254
3152
  const mvi = "standard";
3255
3153
  let format;
3256
3154
  try {
3257
- format = resolveOutputFormat2({
3155
+ format = resolveOutputFormat({
3258
3156
  jsonFlag: opts.json ?? false,
3259
3157
  humanFlag: (opts.human ?? false) || isHuman(),
3260
3158
  projectDefault: "json"
@@ -3301,7 +3199,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3301
3199
  const mvi = "standard";
3302
3200
  let format;
3303
3201
  try {
3304
- format = resolveOutputFormat2({
3202
+ format = resolveOutputFormat({
3305
3203
  jsonFlag: opts.json ?? false,
3306
3204
  humanFlag: (opts.human ?? false) || isHuman(),
3307
3205
  projectDefault: "json"
@@ -3349,7 +3247,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3349
3247
  return;
3350
3248
  }
3351
3249
  if (opts.from) {
3352
- const { toCanonical } = await import("./hooks-5EXBKPII.js");
3250
+ const { toCanonical } = await import("./hooks-ZN3C4WCK.js");
3353
3251
  const canonical2 = toCanonical(event, opts.from);
3354
3252
  if (format === "json") {
3355
3253
  const envelope = buildEnvelope2(
@@ -3389,7 +3287,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3389
3287
  }
3390
3288
  process.exit(1);
3391
3289
  }
3392
- const { getMappedProviderIds } = await import("./hooks-5EXBKPII.js");
3290
+ const { getMappedProviderIds } = await import("./hooks-ZN3C4WCK.js");
3393
3291
  const allIds = getMappedProviderIds();
3394
3292
  const translations = translateToAll(canonical, allIds);
3395
3293
  if (format === "json") {
@@ -3432,7 +3330,7 @@ CAMP Hook Support (mappings v${getHookMappingsVersion()})
3432
3330
  const mvi = "standard";
3433
3331
  let format;
3434
3332
  try {
3435
- format = resolveOutputFormat2({
3333
+ format = resolveOutputFormat({
3436
3334
  jsonFlag: opts.json ?? false,
3437
3335
  humanFlag: (opts.human ?? false) || isHuman(),
3438
3336
  projectDefault: "json"
@@ -3502,7 +3400,7 @@ function buildEnvelope2(operation, mvi, result, error) {
3502
3400
  schemaVersion: "1.0.0",
3503
3401
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3504
3402
  operation,
3505
- requestId: randomUUID3(),
3403
+ requestId: randomUUID2(),
3506
3404
  transport: "cli",
3507
3405
  strict: true,
3508
3406
  mvi,
@@ -3817,10 +3715,308 @@ function registerSkillsCheck(parent) {
3817
3715
  });
3818
3716
  }
3819
3717
 
3820
- // src/commands/skills/find.ts
3821
- import { randomUUID as randomUUID4 } from "crypto";
3822
- import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
3718
+ // src/commands/skills/doctor.ts
3719
+ function registerSkillsDoctor(parent) {
3720
+ const doctor = parent.command("doctor").description("Diagnose and repair the skill storage topology");
3721
+ registerDoctorBridge(doctor);
3722
+ }
3723
+
3724
+ // src/commands/skills/doctor-migrate.ts
3823
3725
  import pc9 from "picocolors";
3726
+
3727
+ // src/core/skills/migration.ts
3728
+ import { execFile } from "child_process";
3729
+ import {
3730
+ cpSync,
3731
+ existsSync as existsSync10,
3732
+ mkdirSync,
3733
+ readdirSync as readdirSync2,
3734
+ rmSync,
3735
+ statSync as statSync3,
3736
+ writeFileSync
3737
+ } from "fs";
3738
+ import { homedir as homedir2 } from "os";
3739
+ import { join as join8 } from "path";
3740
+ import { promisify } from "util";
3741
+ var execFileAsync = promisify(execFile);
3742
+ var LEGACY_MIGRATED_MARKER = ".MIGRATED-TO-CLEO";
3743
+ function defaultMigrationOptions(manifestNames) {
3744
+ const home = homedir2();
3745
+ return {
3746
+ legacyRoot: join8(home, ".local", "share", "agents", "skills"),
3747
+ canonicalRoot: join8(home, ".cleo", "skills"),
3748
+ backupDir: join8(home, ".cleo", "backups", "skills"),
3749
+ manifestNames,
3750
+ now: () => /* @__PURE__ */ new Date(),
3751
+ tarExec: systemTarExec,
3752
+ recordRow: () => void 0
3753
+ };
3754
+ }
3755
+ var systemTarExec = {
3756
+ async create({ archivePath, sourceRoot }) {
3757
+ const parent = join8(sourceRoot, "..");
3758
+ const base = sourceRoot.slice(parent.length + 1);
3759
+ await execFileAsync("tar", ["-czf", archivePath, "-C", parent, base]);
3760
+ },
3761
+ async extract({ archivePath, destinationRoot }) {
3762
+ mkdirSync(destinationRoot, { recursive: true });
3763
+ const parent = join8(destinationRoot, "..");
3764
+ await execFileAsync("tar", ["-xzf", archivePath, "-C", parent]);
3765
+ }
3766
+ };
3767
+ function isAlreadyMigrated(legacyRoot) {
3768
+ if (!existsSync10(legacyRoot)) return true;
3769
+ return existsSync10(join8(legacyRoot, LEGACY_MIGRATED_MARKER));
3770
+ }
3771
+ function listSkillDirs(root) {
3772
+ if (!existsSync10(root)) return [];
3773
+ const entries = readdirSync2(root, { withFileTypes: true });
3774
+ return entries.filter((d) => d.isDirectory() && d.name !== LEGACY_MIGRATED_MARKER).map((d) => d.name).sort();
3775
+ }
3776
+ function planMigration(options) {
3777
+ const start = Date.now();
3778
+ const migrated = [];
3779
+ const skipped = [];
3780
+ if (isAlreadyMigrated(options.legacyRoot)) {
3781
+ return {
3782
+ action: "no-op",
3783
+ migrated,
3784
+ skipped,
3785
+ backupPath: null,
3786
+ legacyRoot: options.legacyRoot,
3787
+ canonicalRoot: options.canonicalRoot,
3788
+ durationMs: Date.now() - start
3789
+ };
3790
+ }
3791
+ const names = listSkillDirs(options.legacyRoot);
3792
+ for (const name of names) {
3793
+ const legacyPath = join8(options.legacyRoot, name);
3794
+ if (!statSync3(legacyPath).isDirectory()) {
3795
+ skipped.push({ name, reason: "not-a-directory", legacyPath });
3796
+ continue;
3797
+ }
3798
+ const destPath = join8(options.canonicalRoot, name);
3799
+ if (existsSync10(destPath)) {
3800
+ skipped.push({ name, reason: "already-present", legacyPath });
3801
+ continue;
3802
+ }
3803
+ migrated.push({
3804
+ name,
3805
+ installPath: destPath,
3806
+ legacyPath,
3807
+ sourceType: options.manifestNames.includes(name) ? "canonical" : "user"
3808
+ });
3809
+ }
3810
+ return {
3811
+ action: "dry-run",
3812
+ migrated,
3813
+ skipped,
3814
+ backupPath: null,
3815
+ legacyRoot: options.legacyRoot,
3816
+ canonicalRoot: options.canonicalRoot,
3817
+ durationMs: Date.now() - start
3818
+ };
3819
+ }
3820
+ function formatBackupTimestamp(now) {
3821
+ const pad = (n) => n.toString().padStart(2, "0");
3822
+ return `${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}-${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`;
3823
+ }
3824
+ function listBackups(backupDir) {
3825
+ if (!existsSync10(backupDir)) return [];
3826
+ const files = readdirSync2(backupDir).filter(
3827
+ (f) => f.startsWith("skills-pre-migrate-") && f.endsWith(".tgz")
3828
+ );
3829
+ files.sort().reverse();
3830
+ return files.map((f) => join8(backupDir, f));
3831
+ }
3832
+ async function runMigration(options) {
3833
+ const start = Date.now();
3834
+ const now = (options.now ?? (() => /* @__PURE__ */ new Date()))();
3835
+ const tar = options.tarExec ?? systemTarExec;
3836
+ const sink = options.recordRow ?? (() => void 0);
3837
+ if (isAlreadyMigrated(options.legacyRoot)) {
3838
+ return {
3839
+ action: "no-op",
3840
+ migrated: [],
3841
+ skipped: [],
3842
+ backupPath: null,
3843
+ legacyRoot: options.legacyRoot,
3844
+ canonicalRoot: options.canonicalRoot,
3845
+ durationMs: Date.now() - start
3846
+ };
3847
+ }
3848
+ const plan = planMigration(options);
3849
+ mkdirSync(options.canonicalRoot, { recursive: true });
3850
+ mkdirSync(options.backupDir, { recursive: true });
3851
+ const backupName = `skills-pre-migrate-${formatBackupTimestamp(now)}.tgz`;
3852
+ const backupPath = join8(options.backupDir, backupName);
3853
+ await tar.create({ archivePath: backupPath, sourceRoot: options.legacyRoot });
3854
+ for (const entry of plan.migrated) {
3855
+ cpSync(entry.legacyPath, entry.installPath, { recursive: true, dereference: false });
3856
+ await sink(entry);
3857
+ }
3858
+ writeFileSync(
3859
+ join8(options.legacyRoot, LEGACY_MIGRATED_MARKER),
3860
+ JSON.stringify(
3861
+ {
3862
+ migratedAt: now.toISOString(),
3863
+ backupPath,
3864
+ canonicalRoot: options.canonicalRoot,
3865
+ entries: plan.migrated.length
3866
+ },
3867
+ null,
3868
+ 2
3869
+ ),
3870
+ "utf-8"
3871
+ );
3872
+ return {
3873
+ action: "migrate",
3874
+ migrated: plan.migrated,
3875
+ skipped: plan.skipped,
3876
+ backupPath,
3877
+ legacyRoot: options.legacyRoot,
3878
+ canonicalRoot: options.canonicalRoot,
3879
+ durationMs: Date.now() - start
3880
+ };
3881
+ }
3882
+ async function runRollback(options) {
3883
+ const start = Date.now();
3884
+ const tar = options.tarExec ?? systemTarExec;
3885
+ const backups = listBackups(options.backupDir);
3886
+ const newest = backups[0];
3887
+ if (!newest) {
3888
+ throw new Error(
3889
+ `No backup tarballs found under ${options.backupDir}. Run "cleo skills migrate" (without --rollback) first.`
3890
+ );
3891
+ }
3892
+ if (existsSync10(options.legacyRoot)) {
3893
+ rmSync(options.legacyRoot, { recursive: true, force: true });
3894
+ }
3895
+ await tar.extract({ archivePath: newest, destinationRoot: options.legacyRoot });
3896
+ return {
3897
+ action: "rollback",
3898
+ migrated: [],
3899
+ skipped: [],
3900
+ backupPath: newest,
3901
+ legacyRoot: options.legacyRoot,
3902
+ canonicalRoot: options.canonicalRoot,
3903
+ durationMs: Date.now() - start
3904
+ };
3905
+ }
3906
+
3907
+ // src/commands/skills/doctor-migrate.ts
3908
+ function buildOptions(opts) {
3909
+ if (opts.__optionsOverride) return opts.__optionsOverride;
3910
+ const manifestNames = opts.__manifestNamesOverride ?? [];
3911
+ return defaultMigrationOptions(manifestNames);
3912
+ }
3913
+ function renderHuman(outcome) {
3914
+ const lines = [];
3915
+ lines.push(pc9.bold(`
3916
+ skills ${outcome.action}`));
3917
+ lines.push(pc9.dim(` legacy: ${outcome.legacyRoot}`));
3918
+ lines.push(pc9.dim(` canonical: ${outcome.canonicalRoot}`));
3919
+ if (outcome.backupPath) {
3920
+ lines.push(pc9.dim(` backup: ${outcome.backupPath}`));
3921
+ }
3922
+ lines.push(pc9.dim(` duration: ${outcome.durationMs}ms`));
3923
+ if (outcome.migrated.length > 0) {
3924
+ lines.push(pc9.green(`
3925
+ Migrated (${outcome.migrated.length}):`));
3926
+ for (const m of outcome.migrated) {
3927
+ lines.push(` + ${pc9.bold(m.name)} ${pc9.dim(`[${m.sourceType}]`)}`);
3928
+ }
3929
+ }
3930
+ if (outcome.skipped.length > 0) {
3931
+ lines.push(pc9.yellow(`
3932
+ Skipped (${outcome.skipped.length}):`));
3933
+ for (const s of outcome.skipped) {
3934
+ lines.push(` ! ${pc9.bold(s.name)} ${pc9.dim(`(${s.reason})`)}`);
3935
+ }
3936
+ }
3937
+ if (outcome.action === "no-op") {
3938
+ lines.push(pc9.dim("\nLegacy store is already migrated (sentinel present)."));
3939
+ }
3940
+ if (outcome.action === "dry-run") {
3941
+ lines.push(pc9.dim("\n(dry run \u2014 no filesystem changes were made)"));
3942
+ }
3943
+ return lines.join("\n");
3944
+ }
3945
+ function registerSkillsDoctorMigrate(parent) {
3946
+ 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) => {
3947
+ const operation = "skills.migrate";
3948
+ const mvi = "standard";
3949
+ let format;
3950
+ try {
3951
+ format = resolveFormat({
3952
+ jsonFlag: opts.json ?? false,
3953
+ humanFlag: (opts.human ?? false) || isHuman(),
3954
+ projectDefault: "json"
3955
+ });
3956
+ } catch (error) {
3957
+ const message = error instanceof Error ? error.message : String(error);
3958
+ emitJsonError(
3959
+ operation,
3960
+ mvi,
3961
+ ErrorCodes.FORMAT_CONFLICT,
3962
+ message,
3963
+ ErrorCategories.VALIDATION
3964
+ );
3965
+ process.exit(1);
3966
+ }
3967
+ if (opts.dryRun && opts.rollback) {
3968
+ const message = "Cannot combine --dry-run with --rollback";
3969
+ if (format === "json") {
3970
+ emitJsonError(
3971
+ operation,
3972
+ mvi,
3973
+ ErrorCodes.INVALID_INPUT,
3974
+ message,
3975
+ ErrorCategories.VALIDATION
3976
+ );
3977
+ } else {
3978
+ console.error(pc9.red(message));
3979
+ }
3980
+ process.exit(1);
3981
+ }
3982
+ const options = buildOptions(opts);
3983
+ try {
3984
+ let outcome;
3985
+ if (opts.rollback) {
3986
+ outcome = await runRollback(options);
3987
+ } else if (opts.dryRun) {
3988
+ outcome = planMigration(options);
3989
+ } else {
3990
+ outcome = await runMigration(options);
3991
+ }
3992
+ if (format === "json") {
3993
+ outputSuccess(operation, mvi, outcome);
3994
+ } else {
3995
+ console.log(renderHuman(outcome));
3996
+ }
3997
+ } catch (error) {
3998
+ const message = error instanceof Error ? error.message : String(error);
3999
+ if (format === "json") {
4000
+ emitJsonError(
4001
+ operation,
4002
+ mvi,
4003
+ ErrorCodes.INTERNAL_ERROR,
4004
+ message,
4005
+ ErrorCategories.MIGRATION,
4006
+ { legacyRoot: options.legacyRoot, canonicalRoot: options.canonicalRoot }
4007
+ );
4008
+ } else {
4009
+ console.error(pc9.red(`migration failed: ${message}`));
4010
+ }
4011
+ process.exit(1);
4012
+ }
4013
+ });
4014
+ }
4015
+
4016
+ // src/commands/skills/find.ts
4017
+ import { randomUUID as randomUUID3 } from "crypto";
4018
+ import { resolveOutputFormat as resolveOutputFormat2 } from "@cleocode/lafs";
4019
+ import pc10 from "picocolors";
3824
4020
  var SkillsFindValidationError = class extends Error {
3825
4021
  code;
3826
4022
  constructor(code, message) {
@@ -3851,7 +4047,7 @@ function registerSkillsFind(parent) {
3851
4047
  const mvi = details ? "full" : "standard";
3852
4048
  let format;
3853
4049
  try {
3854
- format = resolveOutputFormat3({
4050
+ format = resolveOutputFormat2({
3855
4051
  jsonFlag: opts.json ?? false,
3856
4052
  humanFlag: (opts.human ?? false) || isHuman(),
3857
4053
  projectDefault: "json"
@@ -3861,7 +4057,7 @@ function registerSkillsFind(parent) {
3861
4057
  if (opts.json) {
3862
4058
  emitJsonError3(operation, mvi, "E_FORMAT_CONFLICT", message, "VALIDATION");
3863
4059
  } else {
3864
- console.error(pc9.red(message));
4060
+ console.error(pc10.red(message));
3865
4061
  }
3866
4062
  process.exit(1);
3867
4063
  }
@@ -3928,19 +4124,19 @@ function registerSkillsFind(parent) {
3928
4124
  query: query ?? null
3929
4125
  });
3930
4126
  } else {
3931
- console.error(pc9.red(`Recommendation failed: ${message}`));
4127
+ console.error(pc10.red(`Recommendation failed: ${message}`));
3932
4128
  }
3933
4129
  process.exit(1);
3934
4130
  }
3935
4131
  }
3936
4132
  if (!query) {
3937
- console.log(pc9.dim("Usage: caamp skills find <query>"));
4133
+ console.log(pc10.dim("Usage: caamp skills find <query>"));
3938
4134
  return;
3939
4135
  }
3940
4136
  const limit = parseInt(opts.limit, 10);
3941
4137
  const client = new MarketplaceClient();
3942
4138
  if (format === "human") {
3943
- console.log(pc9.dim(`Searching marketplaces for "${query}"...
4139
+ console.log(pc10.dim(`Searching marketplaces for "${query}"...
3944
4140
  `));
3945
4141
  }
3946
4142
  let results;
@@ -3954,7 +4150,7 @@ function registerSkillsFind(parent) {
3954
4150
  limit
3955
4151
  });
3956
4152
  } else {
3957
- console.error(pc9.red(`Marketplace search failed: ${message}`));
4153
+ console.error(pc10.red(`Marketplace search failed: ${message}`));
3958
4154
  }
3959
4155
  process.exit(1);
3960
4156
  }
@@ -3974,21 +4170,21 @@ function registerSkillsFind(parent) {
3974
4170
  return;
3975
4171
  }
3976
4172
  if (results.length === 0) {
3977
- console.log(pc9.yellow("No results found."));
4173
+ console.log(pc10.yellow("No results found."));
3978
4174
  return;
3979
4175
  }
3980
- console.log(pc9.dim(`Found ${results.length} result(s) for "${query}":
4176
+ console.log(pc10.dim(`Found ${results.length} result(s) for "${query}":
3981
4177
  `));
3982
4178
  results.forEach((skill, index) => {
3983
4179
  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}`)}`);
4180
+ const stars = skill.stars > 0 ? pc10.yellow(`\u2605 ${formatStars(skill.stars)}`) : "";
4181
+ console.log(` ${pc10.cyan(num)}. ${pc10.bold(skill.scopedName)} ${stars}`);
4182
+ console.log(` ${pc10.dim(skill.description?.slice(0, 80) ?? "")}`);
4183
+ console.log(` ${pc10.dim(`from ${skill.source}`)}`);
3988
4184
  console.log();
3989
4185
  });
3990
- console.log(pc9.dim("Install with: caamp skills install <name>"));
3991
- console.log(pc9.dim("Or select by number: caamp skills install <n>"));
4186
+ console.log(pc10.dim("Install with: caamp skills install <name>"));
4187
+ console.log(pc10.dim("Or select by number: caamp skills install <n>"));
3992
4188
  });
3993
4189
  }
3994
4190
  function formatStars(n) {
@@ -4080,7 +4276,7 @@ function buildEnvelope3(operation, mvi, result, error) {
4080
4276
  schemaVersion: "1.0.0",
4081
4277
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4082
4278
  operation,
4083
- requestId: randomUUID4(),
4279
+ requestId: randomUUID3(),
4084
4280
  transport: "cli",
4085
4281
  strict: true,
4086
4282
  mvi,
@@ -4105,10 +4301,10 @@ function emitJsonError3(operation, mvi, code, message, category, details = {}) {
4105
4301
  }
4106
4302
 
4107
4303
  // src/commands/skills/init.ts
4108
- import { existsSync as existsSync10 } from "fs";
4304
+ import { existsSync as existsSync11 } from "fs";
4109
4305
  import { mkdir, writeFile as writeFile3 } from "fs/promises";
4110
- import { join as join8 } from "path";
4111
- import pc10 from "picocolors";
4306
+ import { join as join9 } from "path";
4307
+ import pc11 from "picocolors";
4112
4308
  function registerSkillsInit(parent) {
4113
4309
  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
4310
  async (name, opts) => {
@@ -4133,8 +4329,8 @@ function registerSkillsInit(parent) {
4133
4329
  process.exit(1);
4134
4330
  }
4135
4331
  const skillName = name ?? "my-skill";
4136
- const skillDir = join8(opts.dir, skillName);
4137
- if (existsSync10(skillDir)) {
4332
+ const skillDir = join9(opts.dir, skillName);
4333
+ if (existsSync11(skillDir)) {
4138
4334
  const message = `Directory already exists: ${skillDir}`;
4139
4335
  if (format === "json") {
4140
4336
  emitJsonError(
@@ -4148,7 +4344,7 @@ function registerSkillsInit(parent) {
4148
4344
  }
4149
4345
  );
4150
4346
  } else {
4151
- console.error(pc10.red(message));
4347
+ console.error(pc11.red(message));
4152
4348
  }
4153
4349
  process.exit(1);
4154
4350
  }
@@ -4176,7 +4372,7 @@ Provide detailed instructions for the AI agent here.
4176
4372
 
4177
4373
  Show example inputs and expected outputs.
4178
4374
  `;
4179
- await writeFile3(join8(skillDir, "SKILL.md"), template, "utf-8");
4375
+ await writeFile3(join9(skillDir, "SKILL.md"), template, "utf-8");
4180
4376
  const result = {
4181
4377
  name: skillName,
4182
4378
  directory: skillDir,
@@ -4187,18 +4383,88 @@ Show example inputs and expected outputs.
4187
4383
  outputSuccess(operation, mvi, result);
4188
4384
  return;
4189
4385
  }
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}`));
4386
+ console.log(pc11.green(`\u2713 Created skill template: ${skillDir}/SKILL.md`));
4387
+ console.log(pc11.dim("\nNext steps:"));
4388
+ console.log(pc11.dim(" 1. Edit SKILL.md with your instructions"));
4389
+ console.log(pc11.dim(` 2. Validate: caamp skills validate ${join9(skillDir, "SKILL.md")}`));
4390
+ console.log(pc11.dim(` 3. Install: caamp skills install ${skillDir}`));
4195
4391
  }
4196
4392
  );
4197
4393
  }
4198
4394
 
4199
4395
  // src/commands/skills/install.ts
4200
- import { existsSync as existsSync11 } from "fs";
4201
- import pc11 from "picocolors";
4396
+ import { existsSync as existsSync12 } from "fs";
4397
+ import pc12 from "picocolors";
4398
+
4399
+ // src/core/skills/trust-gate-adapter.ts
4400
+ var cachedCore;
4401
+ async function resolveCore() {
4402
+ if (cachedCore !== void 0) return cachedCore;
4403
+ try {
4404
+ const mod = await import("@cleocode/core");
4405
+ cachedCore = mod;
4406
+ } catch {
4407
+ cachedCore = null;
4408
+ process.stderr.write(
4409
+ "[caamp] WARNING: @cleocode/core unavailable \u2014 skipping trust gate (skill installs not security-checked)\n"
4410
+ );
4411
+ }
4412
+ return cachedCore;
4413
+ }
4414
+ async function evaluateSkillTrustGate(localPath, source, force = false) {
4415
+ const core = await resolveCore();
4416
+ if (!core) {
4417
+ return {
4418
+ decision: "allow",
4419
+ reason: "Trust gate skipped \u2014 @cleocode/core not available",
4420
+ scan: {
4421
+ skillName: localPath.split("/").filter(Boolean).pop() ?? localPath,
4422
+ source,
4423
+ trustLevel: "community",
4424
+ verdict: "safe",
4425
+ findings: [],
4426
+ scannedAt: (/* @__PURE__ */ new Date()).toISOString(),
4427
+ summary: "core-unavailable"
4428
+ }
4429
+ };
4430
+ }
4431
+ const scan = core.scanSkill(localPath, source);
4432
+ const gate = core.shouldAllowInstall(scan, force);
4433
+ return { decision: gate.decision, reason: gate.reason, scan };
4434
+ }
4435
+ async function evaluateFederationGate(source, opts = {}) {
4436
+ const core = await resolveCore();
4437
+ if (!core) {
4438
+ return {
4439
+ decision: "allow",
4440
+ reason: "Federation gate skipped \u2014 @cleocode/core not available",
4441
+ peer: null,
4442
+ isFederationSource: false,
4443
+ computedChecksum: null,
4444
+ expectedChecksum: null
4445
+ };
4446
+ }
4447
+ return core.evaluateFederationInstallGate({
4448
+ source,
4449
+ artefactPath: opts.artefactPath,
4450
+ expectedChecksum: opts.expectedChecksum,
4451
+ approveNewSource: opts.approveNewSource
4452
+ });
4453
+ }
4454
+ async function recordSkillTrustBypass(scan, reason = null) {
4455
+ const core = await resolveCore();
4456
+ if (!core) return;
4457
+ try {
4458
+ core.recordTrustBypass(scan, reason);
4459
+ } catch (err) {
4460
+ process.stderr.write(
4461
+ `[caamp] WARNING: failed to record trust-bypass audit row: ${err instanceof Error ? err.message : String(err)}
4462
+ `
4463
+ );
4464
+ }
4465
+ }
4466
+
4467
+ // src/commands/skills/install.ts
4202
4468
  function registerSkillsInstall(parent) {
4203
4469
  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
4470
  "-a, --agent <name>",
@@ -4208,6 +4474,12 @@ function registerSkillsInstall(parent) {
4208
4474
  ).option("-g, --global", "Install globally").option("-y, --yes", "Skip confirmation").option("--all", "Install to all detected agents").option(
4209
4475
  "--profile <name>",
4210
4476
  "Install a skill library profile (minimal, core, recommended, full)"
4477
+ ).option(
4478
+ "--force",
4479
+ "Override trust-gate block decisions (audited to .cleo/audit/skill-trust-bypass.jsonl)"
4480
+ ).option(
4481
+ "--allow-new-source",
4482
+ "Bypass first-install confirmation prompt for unknown federation sources (non-TTY safe)"
4211
4483
  ).option("--json", "Output as JSON (default)").option("--human", "Output in human-readable format").action(
4212
4484
  async (source, opts) => {
4213
4485
  const operation = "skills.install";
@@ -4241,7 +4513,7 @@ function registerSkillsInstall(parent) {
4241
4513
  if (providers.length === 0) {
4242
4514
  const message = "No target providers found. Use --agent or --all.";
4243
4515
  if (format === "json") {
4244
- emitError2(
4516
+ emitError(
4245
4517
  operation,
4246
4518
  mvi,
4247
4519
  ErrorCodes.PROVIDER_NOT_FOUND,
@@ -4249,7 +4521,7 @@ function registerSkillsInstall(parent) {
4249
4521
  ErrorCategories.NOT_FOUND
4250
4522
  );
4251
4523
  }
4252
- console.error(pc11.red(message));
4524
+ console.error(pc12.red(message));
4253
4525
  process.exit(1);
4254
4526
  }
4255
4527
  if (opts.profile) {
@@ -4266,7 +4538,7 @@ function registerSkillsInstall(parent) {
4266
4538
  if (!source) {
4267
4539
  const message = "Missing required argument: source";
4268
4540
  if (format === "json") {
4269
- emitError2(
4541
+ emitError(
4270
4542
  operation,
4271
4543
  mvi,
4272
4544
  ErrorCodes.INVALID_INPUT,
@@ -4274,14 +4546,14 @@ function registerSkillsInstall(parent) {
4274
4546
  ErrorCategories.VALIDATION
4275
4547
  );
4276
4548
  }
4277
- console.error(pc11.red(message));
4549
+ console.error(pc12.red(message));
4278
4550
  console.log(
4279
- pc11.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>")
4551
+ pc12.dim("Usage: caamp skills install <source> or caamp skills install --profile <name>")
4280
4552
  );
4281
4553
  process.exit(1);
4282
4554
  }
4283
4555
  if (format === "human") {
4284
- console.log(pc11.dim(`Installing to ${providers.length} provider(s)...`));
4556
+ console.log(pc12.dim(`Installing to ${providers.length} provider(s)...`));
4285
4557
  }
4286
4558
  let localPath;
4287
4559
  let cleanup;
@@ -4327,7 +4599,7 @@ function registerSkillsInstall(parent) {
4327
4599
  ErrorCategories.TRANSIENT
4328
4600
  );
4329
4601
  }
4330
- console.error(pc11.red(message));
4602
+ console.error(pc12.red(message));
4331
4603
  process.exit(1);
4332
4604
  }
4333
4605
  } else if (parsed.type === "gitlab" && parsed.owner && parsed.repo) {
@@ -4351,7 +4623,7 @@ function registerSkillsInstall(parent) {
4351
4623
  ErrorCategories.TRANSIENT
4352
4624
  );
4353
4625
  }
4354
- console.error(pc11.red(message));
4626
+ console.error(pc12.red(message));
4355
4627
  process.exit(1);
4356
4628
  }
4357
4629
  } else if (parsed.type === "local") {
@@ -4372,7 +4644,7 @@ function registerSkillsInstall(parent) {
4372
4644
  ErrorCategories.VALIDATION
4373
4645
  );
4374
4646
  }
4375
- console.error(pc11.red(message));
4647
+ console.error(pc12.red(message));
4376
4648
  process.exit(1);
4377
4649
  }
4378
4650
  const catalogSkill = getSkill(parsed.inferredName);
@@ -4383,7 +4655,7 @@ function registerSkillsInstall(parent) {
4383
4655
  sourceType = "library";
4384
4656
  if (format === "human") {
4385
4657
  console.log(
4386
- ` Found in catalog: ${pc11.bold(catalogSkill.name)} v${catalogSkill.version} (${pc11.dim(catalogSkill.category)})`
4658
+ ` Found in catalog: ${pc12.bold(catalogSkill.name)} v${catalogSkill.version} (${pc12.dim(catalogSkill.category)})`
4387
4659
  );
4388
4660
  }
4389
4661
  } else {
@@ -4400,8 +4672,8 @@ function registerSkillsInstall(parent) {
4400
4672
  }
4401
4673
  );
4402
4674
  }
4403
- console.error(pc11.red(message));
4404
- console.log(pc11.dim("Available skills: " + listSkills().join(", ")));
4675
+ console.error(pc12.red(message));
4676
+ console.log(pc12.dim("Available skills: " + listSkills().join(", ")));
4405
4677
  process.exit(1);
4406
4678
  }
4407
4679
  } else {
@@ -4415,7 +4687,7 @@ function registerSkillsInstall(parent) {
4415
4687
  ErrorCategories.VALIDATION
4416
4688
  );
4417
4689
  }
4418
- console.error(pc11.red(message));
4690
+ console.error(pc12.red(message));
4419
4691
  process.exit(1);
4420
4692
  }
4421
4693
  }
@@ -4431,9 +4703,103 @@ function registerSkillsInstall(parent) {
4431
4703
  ErrorCategories.INTERNAL
4432
4704
  );
4433
4705
  }
4434
- console.error(pc11.red(message));
4706
+ console.error(pc12.red(message));
4435
4707
  process.exit(1);
4436
4708
  }
4709
+ if (sourceType !== "library" && sourceType !== "package") {
4710
+ const fedGate = await evaluateFederationGate(sourceValue, {
4711
+ artefactPath: localPath,
4712
+ approveNewSource: opts.allowNewSource === true
4713
+ });
4714
+ if (fedGate.decision === "block-checksum") {
4715
+ const message = `Federation install blocked: ${fedGate.reason}`;
4716
+ if (format === "json") {
4717
+ emitJsonError(
4718
+ operation,
4719
+ mvi,
4720
+ ErrorCodes.FEDERATION_CHECKSUM_MISMATCH,
4721
+ message,
4722
+ ErrorCategories.VALIDATION,
4723
+ {
4724
+ expectedChecksum: fedGate.expectedChecksum,
4725
+ computedChecksum: fedGate.computedChecksum
4726
+ }
4727
+ );
4728
+ }
4729
+ console.error(pc12.red(message));
4730
+ process.exit(1);
4731
+ }
4732
+ if (fedGate.decision === "prompt-first-install") {
4733
+ const message = `${fedGate.reason} Use --allow-new-source to approve in non-interactive contexts.`;
4734
+ if (format === "json") {
4735
+ emitJsonError(
4736
+ operation,
4737
+ mvi,
4738
+ ErrorCodes.FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED,
4739
+ message,
4740
+ ErrorCategories.VALIDATION,
4741
+ { peer: fedGate.peer?.url ?? null }
4742
+ );
4743
+ }
4744
+ console.error(pc12.yellow(message));
4745
+ process.exit(1);
4746
+ }
4747
+ }
4748
+ if (sourceType !== "library" && sourceType !== "package") {
4749
+ const gate = await evaluateSkillTrustGate(localPath, sourceValue, opts.force ?? false);
4750
+ if (gate.decision === "block") {
4751
+ const message = `Trust gate blocked install: ${gate.reason}`;
4752
+ if (format === "json") {
4753
+ const envelope = buildEnvelope(
4754
+ operation,
4755
+ mvi,
4756
+ { scan: gate.scan },
4757
+ {
4758
+ code: ErrorCodes.SKILL_TRUST_GATE_BLOCKED,
4759
+ message,
4760
+ category: ErrorCategories.VALIDATION,
4761
+ retryable: false,
4762
+ retryAfterMs: null,
4763
+ details: {
4764
+ verdict: gate.scan.verdict,
4765
+ trustLevel: gate.scan.trustLevel,
4766
+ findingsCount: gate.scan.findings.length
4767
+ }
4768
+ }
4769
+ );
4770
+ console.error(JSON.stringify(envelope, null, 2));
4771
+ } else {
4772
+ console.error(pc12.red(`
4773
+ ${message}`));
4774
+ for (const f of gate.scan.findings.slice(0, 5)) {
4775
+ console.error(
4776
+ pc12.dim(
4777
+ ` [${f.severity}] ${f.category} ${f.file}:${f.line} \u2014 ${f.description}`
4778
+ )
4779
+ );
4780
+ }
4781
+ console.error(pc12.yellow(" Use --force to override (audited)."));
4782
+ }
4783
+ process.exit(1);
4784
+ }
4785
+ if (gate.decision === "ask") {
4786
+ const message = `Trust gate requires confirmation: ${gate.reason}`;
4787
+ if (format === "json") {
4788
+ emitJsonError(
4789
+ operation,
4790
+ mvi,
4791
+ ErrorCodes.SKILL_TRUST_GATE_BLOCKED,
4792
+ message,
4793
+ ErrorCategories.VALIDATION
4794
+ );
4795
+ }
4796
+ console.error(pc12.red(message));
4797
+ process.exit(1);
4798
+ }
4799
+ if (opts.force === true && gate.scan.verdict !== "safe") {
4800
+ await recordSkillTrustBypass(gate.scan, "operator --force on caamp skills install");
4801
+ }
4802
+ }
4437
4803
  const result = await dispatchInstallSkillAcrossProviders(
4438
4804
  localPath,
4439
4805
  skillName,
@@ -4469,14 +4835,14 @@ function registerSkillsInstall(parent) {
4469
4835
  if (format === "json") {
4470
4836
  outputSuccess(operation, mvi, summary);
4471
4837
  } else {
4472
- console.log(pc11.green(`
4473
- \u2713 Installed ${pc11.bold(skillName)}`));
4474
- console.log(` Canonical: ${pc11.dim(result.canonicalPath)}`);
4838
+ console.log(pc12.green(`
4839
+ \u2713 Installed ${pc12.bold(skillName)}`));
4840
+ console.log(` Canonical: ${pc12.dim(result.canonicalPath)}`);
4475
4841
  console.log(` Linked to: ${result.linkedAgents.join(", ")}`);
4476
4842
  if (result.errors.length > 0) {
4477
- console.log(pc11.yellow("\nWarnings:"));
4843
+ console.log(pc12.yellow("\nWarnings:"));
4478
4844
  for (const err of result.errors) {
4479
- console.log(` ${pc11.yellow("!")} ${err}`);
4845
+ console.log(` ${pc12.yellow("!")} ${err}`);
4480
4846
  }
4481
4847
  }
4482
4848
  }
@@ -4506,11 +4872,11 @@ function registerSkillsInstall(parent) {
4506
4872
  });
4507
4873
  console.error(JSON.stringify(envelope, null, 2));
4508
4874
  } else {
4509
- console.log(pc11.yellow(`
4510
- \u2717 Failed to install ${pc11.bold(skillName)}`));
4511
- console.log(pc11.yellow("Errors:"));
4875
+ console.log(pc12.yellow(`
4876
+ \u2717 Failed to install ${pc12.bold(skillName)}`));
4877
+ console.log(pc12.yellow("Errors:"));
4512
4878
  for (const err of result.errors) {
4513
- console.log(` ${pc11.yellow("!")} ${err}`);
4879
+ console.log(` ${pc12.yellow("!")} ${err}`);
4514
4880
  }
4515
4881
  }
4516
4882
  process.exit(1);
@@ -4525,9 +4891,9 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4525
4891
  if (!isCatalogAvailable()) {
4526
4892
  const message = "No skill library registered. Register one with registerSkillLibraryFromPath() or set CAAMP_SKILL_LIBRARY env var.";
4527
4893
  if (format === "json") {
4528
- emitError2(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
4894
+ emitError(operation, mvi, ErrorCodes.INVALID_INPUT, message, ErrorCategories.VALIDATION);
4529
4895
  }
4530
- console.error(pc11.red(message));
4896
+ console.error(pc12.red(message));
4531
4897
  process.exit(1);
4532
4898
  }
4533
4899
  const profileSkills = resolveProfile(profileName);
@@ -4545,16 +4911,16 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4545
4911
  }
4546
4912
  );
4547
4913
  }
4548
- console.error(pc11.red(message));
4914
+ console.error(pc12.red(message));
4549
4915
  const available = listProfiles();
4550
4916
  if (available.length > 0) {
4551
- console.log(pc11.dim("Available profiles: " + available.join(", ")));
4917
+ console.log(pc12.dim("Available profiles: " + available.join(", ")));
4552
4918
  }
4553
4919
  process.exit(1);
4554
4920
  }
4555
4921
  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)`));
4922
+ console.log(`Installing profile ${pc12.bold(profileName)} (${profileSkills.length} skill(s))...`);
4923
+ console.log(pc12.dim(`Target: ${providers.length} provider(s)`));
4558
4924
  }
4559
4925
  const installed = [];
4560
4926
  const failed = [];
@@ -4564,7 +4930,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4564
4930
  const result = await dispatchInstallSkillAcrossProviders(skillDir, name, providers, isGlobal);
4565
4931
  if (result.success) {
4566
4932
  if (format === "human") {
4567
- console.log(pc11.green(` + ${name}`));
4933
+ console.log(pc12.green(` + ${name}`));
4568
4934
  }
4569
4935
  await recordSkillInstall(
4570
4936
  name,
@@ -4583,7 +4949,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4583
4949
  });
4584
4950
  } else {
4585
4951
  if (format === "human") {
4586
- console.log(pc11.yellow(` ! ${name}: ${result.errors.join(", ")}`));
4952
+ console.log(pc12.yellow(` ! ${name}: ${result.errors.join(", ")}`));
4587
4953
  }
4588
4954
  failed.push({
4589
4955
  name,
@@ -4593,7 +4959,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4593
4959
  } catch (err) {
4594
4960
  const errorMsg = err instanceof Error ? err.message : String(err);
4595
4961
  if (format === "human") {
4596
- console.log(pc11.red(` x ${name}: ${errorMsg}`));
4962
+ console.log(pc12.red(` x ${name}: ${errorMsg}`));
4597
4963
  }
4598
4964
  failed.push({
4599
4965
  name,
@@ -4628,7 +4994,7 @@ async function handleProfileInstall(profileName, providers, isGlobal, format, op
4628
4994
  } else {
4629
4995
  console.log(
4630
4996
  `
4631
- ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yellow(`${failed.length} failed`) : "0 failed"}`
4997
+ ${pc12.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc12.yellow(`${failed.length} failed`) : "0 failed"}`
4632
4998
  );
4633
4999
  if (failed.length > 0) {
4634
5000
  process.exit(1);
@@ -4637,7 +5003,7 @@ ${pc11.green(`${installed.length} installed`)}, ${failed.length > 0 ? pc11.yello
4637
5003
  }
4638
5004
  async function handleMarketplaceSource(source, _providers, _isGlobal, format, operation, mvi) {
4639
5005
  if (format === "human") {
4640
- console.log(pc11.dim(`Searching marketplace for ${source}...`));
5006
+ console.log(pc12.dim(`Searching marketplace for ${source}...`));
4641
5007
  }
4642
5008
  const client = new MarketplaceClient();
4643
5009
  let skill;
@@ -4648,7 +5014,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4648
5014
  if (format === "json") {
4649
5015
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
4650
5016
  }
4651
- console.error(pc11.red(message));
5017
+ console.error(pc12.red(message));
4652
5018
  return { success: false };
4653
5019
  }
4654
5020
  if (!skill) {
@@ -4656,12 +5022,12 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4656
5022
  if (format === "json") {
4657
5023
  emitJsonError(operation, mvi, ErrorCodes.SKILL_NOT_FOUND, message, ErrorCategories.NOT_FOUND);
4658
5024
  }
4659
- console.error(pc11.red(message));
5025
+ console.error(pc12.red(message));
4660
5026
  return { success: false };
4661
5027
  }
4662
5028
  if (format === "human") {
4663
5029
  console.log(
4664
- ` Found: ${pc11.bold(skill.name)} by ${skill.author} (${pc11.dim(skill.repoFullName)})`
5030
+ ` Found: ${pc12.bold(skill.name)} by ${skill.author} (${pc12.dim(skill.repoFullName)})`
4665
5031
  );
4666
5032
  }
4667
5033
  const parsed = parseSource(skill.githubUrl);
@@ -4670,7 +5036,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4670
5036
  if (format === "json") {
4671
5037
  emitJsonError(operation, mvi, ErrorCodes.INVALID_FORMAT, message, ErrorCategories.VALIDATION);
4672
5038
  }
4673
- console.error(pc11.red(message));
5039
+ console.error(pc12.red(message));
4674
5040
  return { success: false };
4675
5041
  }
4676
5042
  try {
@@ -4682,7 +5048,7 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4682
5048
  for (const subPath of subPathCandidates) {
4683
5049
  try {
4684
5050
  const result = await cloneRepo(parsed.owner, parsed.repo, parsed.ref, subPath);
4685
- if (subPath && !existsSync11(result.localPath)) {
5051
+ if (subPath && !existsSync12(result.localPath)) {
4686
5052
  await result.cleanup();
4687
5053
  continue;
4688
5054
  }
@@ -4710,22 +5076,22 @@ async function handleMarketplaceSource(source, _providers, _isGlobal, format, op
4710
5076
  if (format === "json") {
4711
5077
  emitJsonError(operation, mvi, ErrorCodes.NETWORK_ERROR, message, ErrorCategories.TRANSIENT);
4712
5078
  }
4713
- console.error(pc11.red(message));
5079
+ console.error(pc12.red(message));
4714
5080
  return { success: false };
4715
5081
  }
4716
5082
  }
4717
5083
 
4718
5084
  // 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";
5085
+ import { randomUUID as randomUUID4 } from "crypto";
5086
+ import { resolveOutputFormat as resolveOutputFormat3 } from "@cleocode/lafs";
5087
+ import pc13 from "picocolors";
4722
5088
  function registerSkillsList(parent) {
4723
5089
  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
5090
  const operation = "skills.list";
4725
5091
  const mvi = "standard";
4726
5092
  let format;
4727
5093
  try {
4728
- format = resolveOutputFormat4({
5094
+ format = resolveOutputFormat3({
4729
5095
  jsonFlag: opts.json ?? false,
4730
5096
  humanFlag: (opts.human ?? false) || isHuman(),
4731
5097
  projectDefault: "json"
@@ -4745,7 +5111,7 @@ function registerSkillsList(parent) {
4745
5111
  agent: opts.agent
4746
5112
  });
4747
5113
  } else {
4748
- console.error(pc12.red(message));
5114
+ console.error(pc13.red(message));
4749
5115
  }
4750
5116
  process.exit(1);
4751
5117
  }
@@ -4773,21 +5139,21 @@ function registerSkillsList(parent) {
4773
5139
  return;
4774
5140
  }
4775
5141
  if (skills.length === 0) {
4776
- console.log(pc12.dim("No skills found."));
5142
+ console.log(pc13.dim("No skills found."));
4777
5143
  return;
4778
5144
  }
4779
- console.log(pc12.bold(`
5145
+ console.log(pc13.bold(`
4780
5146
  ${skills.length} skill(s) found:
4781
5147
  `));
4782
5148
  skills.forEach((skill, index) => {
4783
5149
  const num = (index + 1).toString().padStart(2);
4784
5150
  console.log(
4785
- ` ${pc12.cyan(num)}. ${pc12.bold(skill.name.padEnd(30))} ${pc12.dim(skill.metadata?.description ?? "")}`
5151
+ ` ${pc13.cyan(num)}. ${pc13.bold(skill.name.padEnd(30))} ${pc13.dim(skill.metadata?.description ?? "")}`
4786
5152
  );
4787
5153
  });
4788
- console.log(pc12.dim(`
5154
+ console.log(pc13.dim(`
4789
5155
  Install with: caamp skills install <name>`));
4790
- console.log(pc12.dim(`Remove with: caamp skills remove <name>`));
5156
+ console.log(pc13.dim(`Remove with: caamp skills remove <name>`));
4791
5157
  });
4792
5158
  }
4793
5159
  function buildEnvelope4(operation, mvi, result, error) {
@@ -4798,7 +5164,7 @@ function buildEnvelope4(operation, mvi, result, error) {
4798
5164
  schemaVersion: "1.0.0",
4799
5165
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4800
5166
  operation,
4801
- requestId: randomUUID5(),
5167
+ requestId: randomUUID4(),
4802
5168
  transport: "cli",
4803
5169
  strict: true,
4804
5170
  mvi,
@@ -4823,7 +5189,7 @@ function emitJsonError4(operation, mvi, code, message, category, details = {}) {
4823
5189
  }
4824
5190
 
4825
5191
  // src/commands/skills/remove.ts
4826
- import pc13 from "picocolors";
5192
+ import pc14 from "picocolors";
4827
5193
  function registerSkillsRemove(parent) {
4828
5194
  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
5195
  async (name, opts) => {
@@ -4873,14 +5239,14 @@ function registerSkillsRemove(parent) {
4873
5239
  return;
4874
5240
  }
4875
5241
  if (removed.length > 0) {
4876
- console.log(pc13.green(`\u2713 Removed ${pc13.bold(name)} from: ${removed.join(", ")}`));
5242
+ console.log(pc14.green(`\u2713 Removed ${pc14.bold(name)} from: ${removed.join(", ")}`));
4877
5243
  await removeSkillFromLock(name);
4878
5244
  } else {
4879
- console.log(pc13.yellow(`Skill ${name} not found in any provider.`));
5245
+ console.log(pc14.yellow(`Skill ${name} not found in any provider.`));
4880
5246
  }
4881
5247
  if (result.errors.length > 0) {
4882
5248
  for (const err of result.errors) {
4883
- console.log(pc13.red(` ${err}`));
5249
+ console.log(pc14.red(` ${err}`));
4884
5250
  }
4885
5251
  }
4886
5252
  } else {
@@ -4893,7 +5259,7 @@ function registerSkillsRemove(parent) {
4893
5259
  count: { removed: 0, total: 0 }
4894
5260
  });
4895
5261
  } else {
4896
- console.log(pc13.dim("No skills installed."));
5262
+ console.log(pc14.dim("No skills installed."));
4897
5263
  }
4898
5264
  return;
4899
5265
  }
@@ -4906,18 +5272,18 @@ function registerSkillsRemove(parent) {
4906
5272
  });
4907
5273
  return;
4908
5274
  }
4909
- console.log(pc13.bold("Installed skills:"));
5275
+ console.log(pc14.bold("Installed skills:"));
4910
5276
  for (const s of skills) {
4911
5277
  console.log(` ${s}`);
4912
5278
  }
4913
- console.log(pc13.dim("\nUse: caamp skills remove <name>"));
5279
+ console.log(pc14.dim("\nUse: caamp skills remove <name>"));
4914
5280
  }
4915
5281
  }
4916
5282
  );
4917
5283
  }
4918
5284
 
4919
5285
  // src/commands/skills/update.ts
4920
- import pc14 from "picocolors";
5286
+ import pc15 from "picocolors";
4921
5287
  function registerSkillsUpdate(parent) {
4922
5288
  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
5289
  const operation = "skills.update";
@@ -4951,12 +5317,12 @@ function registerSkillsUpdate(parent) {
4951
5317
  count: { updated: 0, failed: 0, skipped: 0 }
4952
5318
  });
4953
5319
  } else {
4954
- console.log(pc14.dim("No tracked skills to update."));
5320
+ console.log(pc15.dim("No tracked skills to update."));
4955
5321
  }
4956
5322
  return;
4957
5323
  }
4958
5324
  if (format === "human") {
4959
- console.log(pc14.dim(`Checking ${entries.length} skill(s) for updates...`));
5325
+ console.log(pc15.dim(`Checking ${entries.length} skill(s) for updates...`));
4960
5326
  }
4961
5327
  const outdated = [];
4962
5328
  for (const [name] of entries) {
@@ -4978,19 +5344,19 @@ function registerSkillsUpdate(parent) {
4978
5344
  count: { updated: 0, failed: 0, skipped: 0 }
4979
5345
  });
4980
5346
  } else {
4981
- console.log(pc14.green("\nAll skills are up to date."));
5347
+ console.log(pc15.green("\nAll skills are up to date."));
4982
5348
  }
4983
5349
  return;
4984
5350
  }
4985
5351
  if (format === "human") {
4986
- console.log(pc14.yellow(`
5352
+ console.log(pc15.yellow(`
4987
5353
  ${outdated.length} skill(s) have updates available:
4988
5354
  `));
4989
5355
  for (const skill of outdated) {
4990
5356
  const current = skill.currentVersion?.slice(0, 12) ?? "?";
4991
5357
  const latest = skill.latestVersion ?? "?";
4992
5358
  console.log(
4993
- ` ${pc14.bold(skill.name)} ${pc14.dim(current)} ${pc14.dim("->")} ${pc14.cyan(latest)}`
5359
+ ` ${pc15.bold(skill.name)} ${pc15.dim(current)} ${pc15.dim("->")} ${pc15.cyan(latest)}`
4994
5360
  );
4995
5361
  }
4996
5362
  }
@@ -4998,11 +5364,11 @@ ${outdated.length} skill(s) have updates available:
4998
5364
  const readline = await import("readline");
4999
5365
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5000
5366
  const answer = await new Promise((resolve3) => {
5001
- rl.question(pc14.dim("\nProceed with update? [y/N] "), resolve3);
5367
+ rl.question(pc15.dim("\nProceed with update? [y/N] "), resolve3);
5002
5368
  });
5003
5369
  rl.close();
5004
5370
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
5005
- console.log(pc14.dim("Update cancelled."));
5371
+ console.log(pc15.dim("Update cancelled."));
5006
5372
  return;
5007
5373
  }
5008
5374
  }
@@ -5016,7 +5382,7 @@ ${outdated.length} skill(s) have updates available:
5016
5382
  const entry = tracked[skill.name];
5017
5383
  if (!entry) continue;
5018
5384
  if (format === "human") {
5019
- console.log(pc14.dim(`Updating ${pc14.bold(skill.name)}...`));
5385
+ console.log(pc15.dim(`Updating ${pc15.bold(skill.name)}...`));
5020
5386
  }
5021
5387
  try {
5022
5388
  const parsed = parseSource(entry.source);
@@ -5038,7 +5404,7 @@ ${outdated.length} skill(s) have updates available:
5038
5404
  } else {
5039
5405
  if (format === "human") {
5040
5406
  console.log(
5041
- pc14.yellow(
5407
+ pc15.yellow(
5042
5408
  ` Skipped ${skill.name}: source type "${parsed.type}" does not support auto-update`
5043
5409
  )
5044
5410
  );
@@ -5050,7 +5416,7 @@ ${outdated.length} skill(s) have updates available:
5050
5416
  const providers = entry.agents.map((a) => getProvider(a)).filter((p) => p !== void 0);
5051
5417
  if (providers.length === 0) {
5052
5418
  if (format === "human") {
5053
- console.log(pc14.yellow(` Skipped ${skill.name}: no valid providers found`));
5419
+ console.log(pc15.yellow(` Skipped ${skill.name}: no valid providers found`));
5054
5420
  }
5055
5421
  skipped.push(skill.name);
5056
5422
  continue;
@@ -5075,18 +5441,18 @@ ${outdated.length} skill(s) have updates available:
5075
5441
  skill.latestVersion
5076
5442
  );
5077
5443
  if (format === "human") {
5078
- console.log(pc14.green(` Updated ${pc14.bold(skill.name)}`));
5444
+ console.log(pc15.green(` Updated ${pc15.bold(skill.name)}`));
5079
5445
  }
5080
5446
  updated.push(skill.name);
5081
5447
  } else {
5082
5448
  if (format === "human") {
5083
- console.log(pc14.red(` Failed to update ${skill.name}: no agents linked`));
5449
+ console.log(pc15.red(` Failed to update ${skill.name}: no agents linked`));
5084
5450
  }
5085
5451
  failed.push({ name: skill.name, error: "no agents linked" });
5086
5452
  }
5087
5453
  if (installResult.errors.length > 0 && format === "human") {
5088
5454
  for (const err of installResult.errors) {
5089
- console.log(pc14.yellow(` ${err}`));
5455
+ console.log(pc15.yellow(` ${err}`));
5090
5456
  }
5091
5457
  }
5092
5458
  } finally {
@@ -5095,7 +5461,7 @@ ${outdated.length} skill(s) have updates available:
5095
5461
  } catch (err) {
5096
5462
  const msg = err instanceof Error ? err.message : String(err);
5097
5463
  if (format === "human") {
5098
- console.log(pc14.red(` Failed to update ${skill.name}: ${msg}`));
5464
+ console.log(pc15.red(` Failed to update ${skill.name}: ${msg}`));
5099
5465
  }
5100
5466
  failed.push({ name: skill.name, error: msg });
5101
5467
  }
@@ -5115,24 +5481,24 @@ ${outdated.length} skill(s) have updates available:
5115
5481
  }
5116
5482
  console.log();
5117
5483
  if (updated.length > 0) {
5118
- console.log(pc14.green(`Updated ${updated.length} skill(s).`));
5484
+ console.log(pc15.green(`Updated ${updated.length} skill(s).`));
5119
5485
  }
5120
5486
  if (failed.length > 0) {
5121
- console.log(pc14.red(`Failed to update ${failed.length} skill(s).`));
5487
+ console.log(pc15.red(`Failed to update ${failed.length} skill(s).`));
5122
5488
  }
5123
5489
  });
5124
5490
  }
5125
5491
 
5126
5492
  // src/commands/skills/validate.ts
5127
- import { resolveOutputFormat as resolveOutputFormat5 } from "@cleocode/lafs";
5128
- import pc15 from "picocolors";
5493
+ import { resolveOutputFormat as resolveOutputFormat4 } from "@cleocode/lafs";
5494
+ import pc16 from "picocolors";
5129
5495
  function registerSkillsValidate(parent) {
5130
5496
  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
5497
  const operation = "skills.validate";
5132
5498
  const mvi = "standard";
5133
5499
  let format;
5134
5500
  try {
5135
- format = resolveOutputFormat5({
5501
+ format = resolveOutputFormat4({
5136
5502
  jsonFlag: opts.json ?? false,
5137
5503
  humanFlag: (opts.human ?? false) || isHuman(),
5138
5504
  projectDefault: "json"
@@ -5165,7 +5531,7 @@ function registerSkillsValidate(parent) {
5165
5531
  }
5166
5532
  );
5167
5533
  } else {
5168
- console.error(pc15.red(message));
5534
+ console.error(pc16.red(message));
5169
5535
  }
5170
5536
  process.exit(1);
5171
5537
  }
@@ -5187,12 +5553,12 @@ function registerSkillsValidate(parent) {
5187
5553
  console.log(JSON.stringify(envelope, null, 2));
5188
5554
  } else {
5189
5555
  if (result.valid) {
5190
- console.log(pc15.green(`\u2713 ${path} is valid`));
5556
+ console.log(pc16.green(`\u2713 ${path} is valid`));
5191
5557
  } else {
5192
- console.log(pc15.red(`\u2717 ${path} has validation errors`));
5558
+ console.log(pc16.red(`\u2717 ${path} has validation errors`));
5193
5559
  }
5194
5560
  for (const issue of result.issues) {
5195
- const icon = issue.level === "error" ? pc15.red("\u2717") : pc15.yellow("!");
5561
+ const icon = issue.level === "error" ? pc16.red("\u2717") : pc16.yellow("!");
5196
5562
  console.log(` ${icon} [${issue.field}] ${issue.message}`);
5197
5563
  }
5198
5564
  }
@@ -5214,6 +5580,9 @@ function registerSkillsCommands(program2) {
5214
5580
  registerSkillsInit(skills);
5215
5581
  registerSkillsAudit(skills);
5216
5582
  registerSkillsValidate(skills);
5583
+ registerSkillsDoctorMigrate(skills);
5584
+ registerSkillsDoctor(skills);
5585
+ registerSkillsDoctorAdopt(skills);
5217
5586
  }
5218
5587
 
5219
5588
  // src/cli.ts