@cleocode/caamp 2026.5.84 → 2026.5.87

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.
@@ -3182,13 +3182,13 @@ async function scanFile(filePath, rules) {
3182
3182
  }
3183
3183
  async function scanDirectory(dirPath) {
3184
3184
  const { readdir: readdir4 } = await import("fs/promises");
3185
- const { join: join10 } = await import("path");
3185
+ const { join: join11 } = await import("path");
3186
3186
  if (!existsSync10(dirPath)) return [];
3187
3187
  const entries = await readdir4(dirPath, { withFileTypes: true });
3188
3188
  const results = [];
3189
3189
  for (const entry of entries) {
3190
3190
  if (entry.isDirectory() || entry.isSymbolicLink()) {
3191
- const skillFile = join10(dirPath, entry.name, "SKILL.md");
3191
+ const skillFile = join11(dirPath, entry.name, "SKILL.md");
3192
3192
  if (existsSync10(skillFile)) {
3193
3193
  results.push(await scanFile(skillFile));
3194
3194
  }
@@ -3554,6 +3554,10 @@ var ErrorCodes = {
3554
3554
  INVALID_FORMAT: "E_INVALID_FORMAT",
3555
3555
  // Operation errors
3556
3556
  INSTALL_FAILED: "E_INSTALL_FAILED",
3557
+ // Skills federation gates (T9564 — Sphere B)
3558
+ SKILL_TRUST_GATE_BLOCKED: "E_SKILL_TRUST_GATE_BLOCKED",
3559
+ FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED: "E_FEDERATION_UNKNOWN_SOURCE_INTERACTIVE_REQUIRED",
3560
+ FEDERATION_CHECKSUM_MISMATCH: "E_FEDERATION_CHECKSUM_MISMATCH",
3557
3561
  REMOVE_FAILED: "E_REMOVE_FAILED",
3558
3562
  UPDATE_FAILED: "E_UPDATE_FAILED",
3559
3563
  VALIDATION_FAILED: "E_VALIDATION_FAILED",
@@ -3820,6 +3824,384 @@ function registerDoctorBridge(parent) {
3820
3824
  );
3821
3825
  }
3822
3826
 
3827
+ // src/commands/skills/doctor-adopt.ts
3828
+ import { randomUUID as randomUUID2 } from "crypto";
3829
+ import {
3830
+ cpSync,
3831
+ existsSync as existsSync13,
3832
+ lstatSync as lstatSync4,
3833
+ mkdirSync,
3834
+ readdirSync as readdirSync2,
3835
+ realpathSync as realpathSync2,
3836
+ renameSync,
3837
+ rmSync,
3838
+ statSync,
3839
+ writeFileSync
3840
+ } from "fs";
3841
+ import { homedir as homedir4 } from "os";
3842
+ import { join as join7 } from "path";
3843
+ import { createInterface } from "readline/promises";
3844
+ import pc2 from "picocolors";
3845
+ function cleoSkillsRoot() {
3846
+ return join7(homedir4(), ".cleo", "skills");
3847
+ }
3848
+ function legacyAgentsSkillsRoot() {
3849
+ return join7(homedir4(), ".local", "share", "agents", "skills");
3850
+ }
3851
+ function homeAgentsSkillsRoot() {
3852
+ return join7(homedir4(), ".agents", "skills");
3853
+ }
3854
+ function archiveRoot() {
3855
+ return join7(cleoSkillsRoot(), ".archive");
3856
+ }
3857
+ function auditLogRoot() {
3858
+ return join7(cleoSkillsRoot(), ".audit-log");
3859
+ }
3860
+ function listCandidates(root) {
3861
+ if (!existsSync13(root)) return [];
3862
+ let entries;
3863
+ try {
3864
+ entries = readdirSync2(root);
3865
+ } catch {
3866
+ return [];
3867
+ }
3868
+ const out = [];
3869
+ for (const name of entries) {
3870
+ if (name.startsWith(".")) continue;
3871
+ const full = join7(root, name);
3872
+ let isDirLike = false;
3873
+ try {
3874
+ const stat4 = lstatSync4(full);
3875
+ if (stat4.isDirectory()) {
3876
+ isDirLike = true;
3877
+ } else if (stat4.isSymbolicLink()) {
3878
+ try {
3879
+ const real = statSync(full);
3880
+ isDirLike = real.isDirectory();
3881
+ } catch {
3882
+ isDirLike = false;
3883
+ }
3884
+ }
3885
+ } catch {
3886
+ isDirLike = false;
3887
+ }
3888
+ if (isDirLike) {
3889
+ out.push({ name, path: full });
3890
+ }
3891
+ }
3892
+ return out;
3893
+ }
3894
+ function approxDirSize(dir) {
3895
+ let total = 0;
3896
+ try {
3897
+ const entries = readdirSync2(dir);
3898
+ for (const entry of entries) {
3899
+ try {
3900
+ const stat4 = statSync(join7(dir, entry));
3901
+ if (stat4.isFile()) total += stat4.size;
3902
+ } catch {
3903
+ }
3904
+ }
3905
+ } catch {
3906
+ return 0;
3907
+ }
3908
+ return total;
3909
+ }
3910
+ function discoverOrphans(registeredNames) {
3911
+ const cleoRoot = cleoSkillsRoot();
3912
+ const legacyRoot = legacyAgentsSkillsRoot();
3913
+ const homeRoot = homeAgentsSkillsRoot();
3914
+ const seen = /* @__PURE__ */ new Map();
3915
+ const visit = (root, via, filter) => {
3916
+ for (const candidate of listCandidates(root)) {
3917
+ if (seen.has(candidate.name)) continue;
3918
+ if (registeredNames.has(candidate.name)) continue;
3919
+ if (filter && !filter(candidate.path)) continue;
3920
+ seen.set(candidate.name, {
3921
+ name: candidate.name,
3922
+ path: candidate.path,
3923
+ discoveredVia: via,
3924
+ hasSkillMd: existsSync13(join7(candidate.path, "SKILL.md")),
3925
+ sizeBytes: approxDirSize(candidate.path)
3926
+ });
3927
+ }
3928
+ };
3929
+ visit(cleoRoot, "cleo");
3930
+ visit(legacyRoot, "legacy-agents");
3931
+ visit(homeRoot, "home-agents", (path2) => {
3932
+ try {
3933
+ const real = realpathSync2(path2);
3934
+ return !real.startsWith(`${cleoRoot}/`);
3935
+ } catch {
3936
+ return true;
3937
+ }
3938
+ });
3939
+ return Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name));
3940
+ }
3941
+ function canonicalAdoptRefusal() {
3942
+ return {
3943
+ code: "E_CANONICAL_ADOPT_REFUSED",
3944
+ message: "Canonical adoption is refused on user machines. Canonical skills are owned by the CLEO core team and ONLY the owner-CI workflow may write them (architecture-v3 \xA76 invariant).",
3945
+ remediation: "To contribute this skill to canonical: clone https://github.com/kryptobaseddev/cleo, place the skill under packages/skills/skills/<name>/, and open a PR. Local user-machine canonical writes are blocked by design."
3946
+ };
3947
+ }
3948
+ function buildAdoptedRow(orphan, now) {
3949
+ return {
3950
+ name: orphan.name,
3951
+ installPath: orphan.path,
3952
+ installedAt: now,
3953
+ sourceType: "user",
3954
+ lifecycleState: "active"
3955
+ };
3956
+ }
3957
+ function archiveAndDelete(orphan, now) {
3958
+ const tsToken = now.replace(/[:.]/g, "-");
3959
+ const archiveDir = join7(archiveRoot(), `${orphan.name}-${tsToken}`);
3960
+ mkdirSync(archiveRoot(), { recursive: true });
3961
+ cpSync(orphan.path, archiveDir, { recursive: true, dereference: false });
3962
+ rmSync(orphan.path, { recursive: true, force: true });
3963
+ return archiveDir;
3964
+ }
3965
+ async function applyDecision(orphan, decision, now, recordRow) {
3966
+ const base = {
3967
+ orphan,
3968
+ decidedAt: now
3969
+ };
3970
+ if (decision === "canonical-adopt") {
3971
+ return {
3972
+ ...base,
3973
+ decision,
3974
+ applied: false,
3975
+ refusal: canonicalAdoptRefusal(),
3976
+ archivedTo: null
3977
+ };
3978
+ }
3979
+ if (decision === "skip") {
3980
+ return { ...base, decision, applied: true, refusal: null, archivedTo: null };
3981
+ }
3982
+ if (decision === "user-adopt") {
3983
+ try {
3984
+ await recordRow(buildAdoptedRow(orphan, now));
3985
+ return { ...base, decision, applied: true, refusal: null, archivedTo: null };
3986
+ } catch (err) {
3987
+ const message = err instanceof Error ? err.message : String(err);
3988
+ return {
3989
+ ...base,
3990
+ decision,
3991
+ applied: false,
3992
+ refusal: {
3993
+ code: "E_CANONICAL_ADOPT_REFUSED",
3994
+ message: `user-adopt failed: ${message}`,
3995
+ remediation: "Initialise the registry with `cleo skills list` then re-run."
3996
+ },
3997
+ archivedTo: null
3998
+ };
3999
+ }
4000
+ }
4001
+ try {
4002
+ const archived = archiveAndDelete(orphan, now);
4003
+ return { ...base, decision, applied: true, refusal: null, archivedTo: archived };
4004
+ } catch (err) {
4005
+ const message = err instanceof Error ? err.message : String(err);
4006
+ return {
4007
+ ...base,
4008
+ decision,
4009
+ applied: false,
4010
+ refusal: {
4011
+ code: "E_CANONICAL_ADOPT_REFUSED",
4012
+ message: `delete failed: ${message}`,
4013
+ remediation: "Inspect filesystem permissions and rerun with --non-interactive to verify."
4014
+ },
4015
+ archivedTo: null
4016
+ };
4017
+ }
4018
+ }
4019
+ function writeAuditLog(result) {
4020
+ const dir = auditLogRoot();
4021
+ mkdirSync(dir, { recursive: true });
4022
+ const tsToken = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4023
+ const path2 = join7(dir, `adopt-${tsToken}.json`);
4024
+ const tmp = `${path2}.tmp`;
4025
+ const payload = {
4026
+ runId: randomUUID2(),
4027
+ writtenAt: (/* @__PURE__ */ new Date()).toISOString(),
4028
+ ...result
4029
+ };
4030
+ writeFileSync(tmp, `${JSON.stringify(payload, null, 2)}
4031
+ `, "utf8");
4032
+ renameSync(tmp, path2);
4033
+ return path2;
4034
+ }
4035
+ async function promptDecision(rl, orphan) {
4036
+ const kb = Math.round(orphan.sizeBytes / 1024);
4037
+ process.stderr.write(
4038
+ `
4039
+ ${pc2.bold(orphan.name)}
4040
+ path: ${orphan.path}
4041
+ via: ${orphan.discoveredVia}
4042
+ size: ~${kb} KiB
4043
+ SKILL.md: ${orphan.hasSkillMd ? "yes" : "no"}
4044
+ `
4045
+ );
4046
+ for (let attempt = 0; attempt < 3; attempt++) {
4047
+ const answer = (await rl.question(" [c]anonical-adopt | [u]ser-adopt | [d]elete | [s]kip: ")).trim().toLowerCase();
4048
+ if (answer === "c" || answer === "canonical" || answer === "canonical-adopt") {
4049
+ return "canonical-adopt";
4050
+ }
4051
+ if (answer === "u" || answer === "user" || answer === "user-adopt") {
4052
+ return "user-adopt";
4053
+ }
4054
+ if (answer === "d" || answer === "delete") return "delete";
4055
+ if (answer === "s" || answer === "skip" || answer === "") return "skip";
4056
+ process.stderr.write(` ${pc2.yellow("unrecognised input \u2014 try one of c/u/d/s")}
4057
+ `);
4058
+ }
4059
+ return "skip";
4060
+ }
4061
+ async function runDoctorAdopt(options) {
4062
+ const discover = options.discoverFn ?? discoverOrphans;
4063
+ const registeredNames = await options.loadRegisteredNames();
4064
+ const orphans = discover(registeredNames);
4065
+ const results = [];
4066
+ const mode = options.nonInteractive ? "non-interactive" : options.autoUserAdopt ? "auto-user-adopt" : "interactive";
4067
+ if (orphans.length === 0) {
4068
+ const empty = {
4069
+ totalOrphans: 0,
4070
+ results: [],
4071
+ auditLogPath: "",
4072
+ mode
4073
+ };
4074
+ if (!options.skipAuditLog) empty.auditLogPath = writeAuditLog(empty);
4075
+ return empty;
4076
+ }
4077
+ if (mode === "non-interactive") {
4078
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4079
+ for (const orphan of orphans) {
4080
+ results.push({
4081
+ orphan,
4082
+ decision: "skip",
4083
+ applied: true,
4084
+ refusal: null,
4085
+ archivedTo: null,
4086
+ decidedAt: now
4087
+ });
4088
+ }
4089
+ } else if (mode === "auto-user-adopt") {
4090
+ for (const orphan of orphans) {
4091
+ results.push(
4092
+ await applyDecision(orphan, "user-adopt", (/* @__PURE__ */ new Date()).toISOString(), options.recordRow)
4093
+ );
4094
+ }
4095
+ } else {
4096
+ const promptFn = options.prompt ?? (async (orphan) => {
4097
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
4098
+ try {
4099
+ return await promptDecision(rl, orphan);
4100
+ } finally {
4101
+ rl.close();
4102
+ }
4103
+ });
4104
+ for (const orphan of orphans) {
4105
+ const decision = await promptFn(orphan);
4106
+ results.push(
4107
+ await applyDecision(orphan, decision, (/* @__PURE__ */ new Date()).toISOString(), options.recordRow)
4108
+ );
4109
+ }
4110
+ }
4111
+ const result = {
4112
+ totalOrphans: orphans.length,
4113
+ results,
4114
+ auditLogPath: "",
4115
+ mode
4116
+ };
4117
+ if (!options.skipAuditLog) result.auditLogPath = writeAuditLog(result);
4118
+ return result;
4119
+ }
4120
+ var caampStandaloneAdapters = {
4121
+ loadRegisteredNames: () => /* @__PURE__ */ new Set(),
4122
+ recordRow: () => {
4123
+ throw new Error(
4124
+ "caamp standalone CLI cannot write to skills.db. Use `cleo skills doctor adopt-orphans` instead."
4125
+ );
4126
+ }
4127
+ };
4128
+ function registerSkillsDoctorAdopt(parent, adapters = caampStandaloneAdapters) {
4129
+ const existing = parent.commands.find((c) => c.name() === "doctor");
4130
+ const doctor = existing ?? parent.command("doctor").description("Diagnostics + repair for the skill system");
4131
+ doctor.command("adopt-orphans").description(
4132
+ "Interactive audit of on-disk skill dirs not tracked in skills.db (canonical/user/delete/skip)"
4133
+ ).option("--json", "Output as LAFS JSON envelope (default)").option("--human", "Output a colorised human-readable summary").option("--non-interactive", "List orphans + exit without action").option("--auto-user-adopt", "Bulk-mark all orphans as source_type=user without prompting").action(
4134
+ async (opts) => {
4135
+ const operation = "skills.doctor.adopt-orphans";
4136
+ const mvi = "standard";
4137
+ let format;
4138
+ try {
4139
+ format = resolveFormat({
4140
+ jsonFlag: opts.json ?? false,
4141
+ humanFlag: opts.human ?? false,
4142
+ projectDefault: "json"
4143
+ });
4144
+ } catch (error) {
4145
+ handleFormatError(error, operation, mvi, opts.json);
4146
+ }
4147
+ try {
4148
+ const result = await runDoctorAdopt({
4149
+ nonInteractive: opts.nonInteractive ?? false,
4150
+ autoUserAdopt: opts.autoUserAdopt ?? false,
4151
+ loadRegisteredNames: adapters.loadRegisteredNames,
4152
+ recordRow: adapters.recordRow
4153
+ });
4154
+ if (format === "json") {
4155
+ outputSuccess(operation, mvi, result);
4156
+ return;
4157
+ }
4158
+ const ok = result.results.filter((r) => r.applied);
4159
+ const blocked = result.results.filter((r) => !r.applied);
4160
+ console.log(pc2.bold(`
4161
+ skills doctor adopt-orphans (${result.mode})
4162
+ `));
4163
+ console.log(
4164
+ ` ${pc2.bold("Discovered")}: ${result.totalOrphans} orphan${result.totalOrphans === 1 ? "" : "s"}`
4165
+ );
4166
+ for (const r of result.results) {
4167
+ const icon = r.decision === "skip" ? pc2.dim("\xB7") : r.applied ? pc2.green("\u2713") : pc2.red("\u2717");
4168
+ const verb = r.applied ? r.decision : `${r.decision} (refused)`;
4169
+ console.log(` ${icon} ${r.orphan.name.padEnd(32)} ${pc2.dim(verb)}`);
4170
+ if (r.refusal) {
4171
+ console.log(` ${pc2.yellow(r.refusal.message)}`);
4172
+ console.log(` ${pc2.dim(r.refusal.remediation)}`);
4173
+ }
4174
+ if (r.archivedTo) {
4175
+ console.log(` ${pc2.dim(`archived \u2192 ${r.archivedTo}`)}`);
4176
+ }
4177
+ }
4178
+ console.log(
4179
+ `
4180
+ ${pc2.bold("Summary")}: ${pc2.green(`${ok.length} applied`)}, ${pc2.red(`${blocked.length} blocked`)}`
4181
+ );
4182
+ if (result.auditLogPath) {
4183
+ console.log(` ${pc2.dim(`audit log \u2192 ${result.auditLogPath}`)}`);
4184
+ }
4185
+ console.log();
4186
+ } catch (error) {
4187
+ const message = error instanceof Error ? error.message : String(error);
4188
+ if (format === "json") {
4189
+ emitJsonError(
4190
+ operation,
4191
+ mvi,
4192
+ ErrorCodes.INTERNAL_ERROR,
4193
+ message,
4194
+ ErrorCategories.INTERNAL
4195
+ );
4196
+ } else {
4197
+ console.error(pc2.red(`Error: ${message}`));
4198
+ }
4199
+ process.exit(1);
4200
+ }
4201
+ }
4202
+ );
4203
+ }
4204
+
3823
4205
  // src/core/network/fetch.ts
3824
4206
  var DEFAULT_FETCH_TIMEOUT_MS = 1e4;
3825
4207
  var NetworkError = class extends Error {
@@ -4396,9 +4778,9 @@ async function recommendSkills2(query, criteria, options = {}) {
4396
4778
  }
4397
4779
 
4398
4780
  // src/core/skills/library-loader.ts
4399
- import { existsSync as existsSync13, readdirSync as readdirSync2, readFileSync } from "fs";
4781
+ import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync } from "fs";
4400
4782
  import { createRequire } from "module";
4401
- import { basename as basename3, dirname as dirname4, join as join7 } from "path";
4783
+ import { basename as basename3, dirname as dirname4, join as join8 } from "path";
4402
4784
  var require2 = createRequire(import.meta.url);
4403
4785
  function loadLibraryFromModule(root) {
4404
4786
  let mod;
@@ -4444,16 +4826,16 @@ function loadLibraryFromModule(root) {
4444
4826
  return mod;
4445
4827
  }
4446
4828
  function buildLibraryFromFiles(root) {
4447
- const catalogPath = join7(root, "skills.json");
4448
- if (!existsSync13(catalogPath)) {
4829
+ const catalogPath = join8(root, "skills.json");
4830
+ if (!existsSync14(catalogPath)) {
4449
4831
  throw new Error(`No skills.json found at ${root}`);
4450
4832
  }
4451
4833
  const catalogData = JSON.parse(readFileSync(catalogPath, "utf-8"));
4452
4834
  const entries = catalogData.skills ?? [];
4453
4835
  const version = catalogData.version ?? "0.0.0";
4454
- const manifestPath = join7(root, "skills", "manifest.json");
4836
+ const manifestPath = join8(root, "skills", "manifest.json");
4455
4837
  let manifest;
4456
- if (existsSync13(manifestPath)) {
4838
+ if (existsSync14(manifestPath)) {
4457
4839
  manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
4458
4840
  } else {
4459
4841
  manifest = {
@@ -4463,14 +4845,14 @@ function buildLibraryFromFiles(root) {
4463
4845
  skills: []
4464
4846
  };
4465
4847
  }
4466
- const profilesDir = join7(root, "profiles");
4848
+ const profilesDir = join8(root, "profiles");
4467
4849
  const profiles = /* @__PURE__ */ new Map();
4468
- if (existsSync13(profilesDir)) {
4469
- for (const file of readdirSync2(profilesDir)) {
4850
+ if (existsSync14(profilesDir)) {
4851
+ for (const file of readdirSync3(profilesDir)) {
4470
4852
  if (!file.endsWith(".json")) continue;
4471
4853
  try {
4472
4854
  const profile = JSON.parse(
4473
- readFileSync(join7(profilesDir, file), "utf-8")
4855
+ readFileSync(join8(profilesDir, file), "utf-8")
4474
4856
  );
4475
4857
  profiles.set(profile.name, profile);
4476
4858
  } catch {
@@ -4484,9 +4866,9 @@ function buildLibraryFromFiles(root) {
4484
4866
  function getSkillDir2(name) {
4485
4867
  const entry = skillMap.get(name);
4486
4868
  if (entry) {
4487
- return dirname4(join7(root, entry.path));
4869
+ return dirname4(join8(root, entry.path));
4488
4870
  }
4489
- return join7(root, "skills", name);
4871
+ return join8(root, "skills", name);
4490
4872
  }
4491
4873
  function resolveDeps(names, visited = /* @__PURE__ */ new Set()) {
4492
4874
  const result = [];
@@ -4514,8 +4896,8 @@ function buildLibraryFromFiles(root) {
4514
4896
  return resolveDeps([...new Set(skills)]);
4515
4897
  }
4516
4898
  function discoverFiles(dir, ext) {
4517
- if (!existsSync13(dir)) return [];
4518
- return readdirSync2(dir).filter((f) => f.endsWith(ext)).map((f) => basename3(f, ext));
4899
+ if (!existsSync14(dir)) return [];
4900
+ return readdirSync3(dir).filter((f) => f.endsWith(ext)).map((f) => basename3(f, ext));
4519
4901
  }
4520
4902
  const library = {
4521
4903
  version,
@@ -4531,14 +4913,14 @@ function buildLibraryFromFiles(root) {
4531
4913
  getSkillPath(name) {
4532
4914
  const entry = skillMap.get(name);
4533
4915
  if (entry) {
4534
- return join7(root, entry.path);
4916
+ return join8(root, entry.path);
4535
4917
  }
4536
- return join7(root, "skills", name, "SKILL.md");
4918
+ return join8(root, "skills", name, "SKILL.md");
4537
4919
  },
4538
4920
  getSkillDir: getSkillDir2,
4539
4921
  readSkillContent(name) {
4540
4922
  const skillPath = library.getSkillPath(name);
4541
- if (!existsSync13(skillPath)) {
4923
+ if (!existsSync14(skillPath)) {
4542
4924
  throw new Error(`Skill content not found: ${skillPath}`);
4543
4925
  }
4544
4926
  return readFileSync(skillPath, "utf-8");
@@ -4565,11 +4947,11 @@ function buildLibraryFromFiles(root) {
4565
4947
  return resolveProfileByName(name);
4566
4948
  },
4567
4949
  listSharedResources() {
4568
- return discoverFiles(join7(root, "skills", "_shared"), ".md");
4950
+ return discoverFiles(join8(root, "skills", "_shared"), ".md");
4569
4951
  },
4570
4952
  getSharedResourcePath(name) {
4571
- const resourcePath = join7(root, "skills", "_shared", `${name}.md`);
4572
- return existsSync13(resourcePath) ? resourcePath : void 0;
4953
+ const resourcePath = join8(root, "skills", "_shared", `${name}.md`);
4954
+ return existsSync14(resourcePath) ? resourcePath : void 0;
4573
4955
  },
4574
4956
  readSharedResource(name) {
4575
4957
  const resourcePath = library.getSharedResourcePath(name);
@@ -4577,15 +4959,15 @@ function buildLibraryFromFiles(root) {
4577
4959
  return readFileSync(resourcePath, "utf-8");
4578
4960
  },
4579
4961
  listProtocols() {
4580
- const rootProtocols = discoverFiles(join7(root, "protocols"), ".md");
4962
+ const rootProtocols = discoverFiles(join8(root, "protocols"), ".md");
4581
4963
  if (rootProtocols.length > 0) return rootProtocols;
4582
- return discoverFiles(join7(root, "skills", "protocols"), ".md");
4964
+ return discoverFiles(join8(root, "skills", "protocols"), ".md");
4583
4965
  },
4584
4966
  getProtocolPath(name) {
4585
- const rootPath = join7(root, "protocols", `${name}.md`);
4586
- if (existsSync13(rootPath)) return rootPath;
4587
- const skillsPath = join7(root, "skills", "protocols", `${name}.md`);
4588
- return existsSync13(skillsPath) ? skillsPath : void 0;
4967
+ const rootPath = join8(root, "protocols", `${name}.md`);
4968
+ if (existsSync14(rootPath)) return rootPath;
4969
+ const skillsPath = join8(root, "skills", "protocols", `${name}.md`);
4970
+ return existsSync14(skillsPath) ? skillsPath : void 0;
4589
4971
  },
4590
4972
  readProtocol(name) {
4591
4973
  const protocolPath = library.getProtocolPath(name);
@@ -4610,8 +4992,8 @@ function buildLibraryFromFiles(root) {
4610
4992
  if (!entry.version) {
4611
4993
  issues.push({ level: "warn", field: "version", message: "Missing version" });
4612
4994
  }
4613
- const skillPath = join7(root, entry.path);
4614
- if (!existsSync13(skillPath)) {
4995
+ const skillPath = join8(root, entry.path);
4996
+ if (!existsSync14(skillPath)) {
4615
4997
  issues.push({
4616
4998
  level: "error",
4617
4999
  field: "path",
@@ -4670,15 +5052,15 @@ __export(catalog_exports, {
4670
5052
  validateAll: () => validateAll,
4671
5053
  validateSkillFrontmatter: () => validateSkillFrontmatter
4672
5054
  });
4673
- import { existsSync as existsSync14 } from "fs";
4674
- import { join as join8 } from "path";
5055
+ import { existsSync as existsSync15 } from "fs";
5056
+ import { join as join9 } from "path";
4675
5057
  var _library = null;
4676
5058
  function registerSkillLibrary(library) {
4677
5059
  _library = library;
4678
5060
  }
4679
5061
  function registerSkillLibraryFromPath(root) {
4680
- const indexPath = join8(root, "index.js");
4681
- if (existsSync14(indexPath)) {
5062
+ const indexPath = join9(root, "index.js");
5063
+ if (existsSync15(indexPath)) {
4682
5064
  _library = loadLibraryFromModule(root);
4683
5065
  return;
4684
5066
  }
@@ -4689,13 +5071,13 @@ function clearRegisteredLibrary() {
4689
5071
  }
4690
5072
  function discoverLibrary() {
4691
5073
  const envPath = process.env["CAAMP_SKILL_LIBRARY"];
4692
- if (envPath && existsSync14(envPath)) {
5074
+ if (envPath && existsSync15(envPath)) {
4693
5075
  try {
4694
- const indexPath = join8(envPath, "index.js");
4695
- if (existsSync14(indexPath)) {
5076
+ const indexPath = join9(envPath, "index.js");
5077
+ if (existsSync15(indexPath)) {
4696
5078
  return loadLibraryFromModule(envPath);
4697
5079
  }
4698
- if (existsSync14(join8(envPath, "skills.json"))) {
5080
+ if (existsSync15(join9(envPath, "skills.json"))) {
4699
5081
  return buildLibraryFromFiles(envPath);
4700
5082
  }
4701
5083
  } catch {
@@ -4802,9 +5184,9 @@ function getLibraryRoot() {
4802
5184
  }
4803
5185
 
4804
5186
  // src/core/skills/discovery.ts
4805
- import { existsSync as existsSync15 } from "fs";
5187
+ import { existsSync as existsSync16 } from "fs";
4806
5188
  import { readdir as readdir3, readFile as readFile7 } from "fs/promises";
4807
- import { join as join9 } from "path";
5189
+ import { join as join10 } from "path";
4808
5190
  import matter from "gray-matter";
4809
5191
  async function parseSkillFile(filePath) {
4810
5192
  try {
@@ -4828,8 +5210,8 @@ async function parseSkillFile(filePath) {
4828
5210
  }
4829
5211
  }
4830
5212
  async function discoverSkill(skillDir) {
4831
- const skillFile = join9(skillDir, "SKILL.md");
4832
- if (!existsSync15(skillFile)) return null;
5213
+ const skillFile = join10(skillDir, "SKILL.md");
5214
+ if (!existsSync16(skillFile)) return null;
4833
5215
  const metadata = await parseSkillFile(skillFile);
4834
5216
  if (!metadata) return null;
4835
5217
  return {
@@ -4840,12 +5222,12 @@ async function discoverSkill(skillDir) {
4840
5222
  };
4841
5223
  }
4842
5224
  async function discoverSkills(rootDir) {
4843
- if (!existsSync15(rootDir)) return [];
5225
+ if (!existsSync16(rootDir)) return [];
4844
5226
  const entries = await readdir3(rootDir, { withFileTypes: true });
4845
5227
  const skills = [];
4846
5228
  for (const entry of entries) {
4847
5229
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
4848
- const skillDir = join9(rootDir, entry.name);
5230
+ const skillDir = join10(rootDir, entry.name);
4849
5231
  const skill = await discoverSkill(skillDir);
4850
5232
  if (skill) {
4851
5233
  skills.push(skill);
@@ -4869,7 +5251,7 @@ async function discoverSkillsMulti(dirs) {
4869
5251
  }
4870
5252
 
4871
5253
  // src/core/skills/validator.ts
4872
- import { existsSync as existsSync16 } from "fs";
5254
+ import { existsSync as existsSync17 } from "fs";
4873
5255
  import { readFile as readFile8 } from "fs/promises";
4874
5256
  import matter2 from "gray-matter";
4875
5257
  var RESERVED_NAMES = [
@@ -4891,7 +5273,7 @@ var WARN_BODY_LINES = 500;
4891
5273
  var WARN_DESCRIPTION_LENGTH = 50;
4892
5274
  async function validateSkill(filePath) {
4893
5275
  const issues = [];
4894
- if (!existsSync16(filePath)) {
5276
+ if (!existsSync17(filePath)) {
4895
5277
  return {
4896
5278
  valid: false,
4897
5279
  issues: [{ level: "error", field: "file", message: "File does not exist" }],
@@ -5079,6 +5461,12 @@ export {
5079
5461
  buildBackupTimestamp,
5080
5462
  runDoctorBridge,
5081
5463
  registerDoctorBridge,
5464
+ discoverOrphans,
5465
+ applyDecision,
5466
+ writeAuditLog,
5467
+ runDoctorAdopt,
5468
+ caampStandaloneAdapters,
5469
+ registerSkillsDoctorAdopt,
5082
5470
  MarketplaceClient,
5083
5471
  RECOMMENDATION_ERROR_CODES,
5084
5472
  tokenizeCriteriaValue,
@@ -5107,4 +5495,4 @@ export {
5107
5495
  discoverSkillsMulti,
5108
5496
  validateSkill
5109
5497
  };
5110
- //# sourceMappingURL=chunk-QSJSM57K.js.map
5498
+ //# sourceMappingURL=chunk-WXL7RPS4.js.map