// src/lib/crossSpawn.ts
import crossSpawn from "cross-spawn";
function spawn(command, args, options) {
  return crossSpawn(command, args, options);
}

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "node:fs";
import PATH from "node:path";
import { globSync } from "glob";
function readJsonFile(path) {
  if (!existsSync(path)) return void 0;
  try {
    return JSON.parse(readFileSync(path, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH.resolve(cwd, "package.json"));
}
function readWorkspacePatternsFromPackageJson(cwd = process.cwd()) {
  const pkg = readRootPackageJson(cwd);
  if (!pkg?.workspaces) return [];
  if (Array.isArray(pkg.workspaces)) return [...pkg.workspaces];
  return pkg.workspaces.packages ? [...pkg.workspaces.packages] : [];
}
function readPnpmWorkspacePatterns(cwd = process.cwd()) {
  const wsPath = PATH.resolve(cwd, "pnpm-workspace.yaml");
  if (!existsSync(wsPath)) return [];
  const content = readFileSync(wsPath, "utf8");
  const patterns = [];
  let isInPackages = false;
  for (const line of content.split("\n")) {
    if (/^packages\s*:/.test(line.trim())) {
      isInPackages = true;
      continue;
    }
    if (isInPackages) {
      const match = /^\s+-\s+['"]?([^'"]+)['"]?\s*$/.exec(line);
      if (match) {
        patterns.push(match[1]);
      } else if (line.trim() !== "" && !/^\s/.test(line)) {
        break;
      }
    }
  }
  return patterns;
}
function readWorkspacePatterns(cwd = process.cwd()) {
  const fromPackageJson = readWorkspacePatternsFromPackageJson(cwd);
  return fromPackageJson.length > 0 ? fromPackageJson : readPnpmWorkspacePatterns(cwd);
}
function workspaceFromPackageJsonMatch(match, cwd, seen) {
  const pkg = readJsonFile(match);
  const name = pkg?.name;
  if (name === void 0 || name.length === 0) return void 0;
  const location = PATH.relative(cwd, PATH.dirname(match)) || ".";
  if (seen.has(location)) return void 0;
  seen.add(location);
  return { location, name };
}
function listDeclaredWorkspaces(cwd = process.cwd()) {
  const patterns = readWorkspacePatterns(cwd);
  const seen = /* @__PURE__ */ new Set();
  const workspaces = [];
  for (const pattern of patterns) {
    const matches = globSync(PATH.posix.join(pattern.replaceAll(PATH.sep, "/"), "package.json"), {
      absolute: true,
      cwd,
      ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"]
    });
    for (const match of matches) {
      const workspace = workspaceFromPackageJsonMatch(match, cwd, seen);
      if (workspace) workspaces.push(workspace);
    }
  }
  return workspaces.toSorted((a, b) => a.location.localeCompare(b.location));
}

// src/lib/initCwd.ts
function INIT_CWD() {
  return process.env.INIT_CWD ?? process.cwd();
}

// src/lib/reporting/runWithEnvelope.ts
import { performance as performance2 } from "node:perf_hooks";

// src/lib/reporting/xyReporter.ts
import { performance } from "node:perf_hooks";
var reporterState = {
  currentCommand: "unknown",
  isEnvelopeEmitted: false,
  isJsonModeEnabled: false,
  isStrictModeEnabled: false,
  originalStdoutWrite: void 0,
  startTime: 0
};
function isJsonMode() {
  return reporterState.isJsonModeEnabled;
}
function setCurrentCommand(name) {
  reporterState.currentCommand = name;
  reporterState.startTime = performance.now();
  reporterState.isEnvelopeEmitted = false;
}
function emitJson(envelope) {
  if (reporterState.isEnvelopeEmitted) return;
  reporterState.isEnvelopeEmitted = true;
  const json = JSON.stringify(envelope) + "\n";
  if (reporterState.originalStdoutWrite) {
    reporterState.originalStdoutWrite(json);
  } else {
    process.stdout.write(json);
  }
}

// src/lib/reporting/runWithEnvelope.ts
async function runWithEnvelope(command, action) {
  setCurrentCommand(command);
  const start = performance2.now();
  let exitCode;
  let envelope;
  try {
    const ret = await action();
    if (typeof ret === "number") {
      exitCode = ret;
    } else {
      exitCode = ret.exitCode;
      envelope = ret.envelope;
    }
  } catch (ex) {
    exitCode = 1;
    const message = ex instanceof Error ? ex.message : String(ex);
    envelope = {
      errorCount: 1,
      errors: [{ message }]
    };
    if (!isJsonMode()) {
      console.error(message);
    }
  }
  if (isJsonMode()) {
    emitJson({
      command,
      data: envelope?.data,
      durationMs: Math.round(performance2.now() - start),
      errorCount: envelope?.errorCount ?? (exitCode === 0 ? 0 : 1),
      errors: envelope?.errors,
      exitCode,
      schemaVersion: 1,
      success: exitCode === 0,
      warningCount: envelope?.warningCount ?? 0,
      warnings: envelope?.warnings
    });
  }
  return exitCode;
}
async function withEnvelope(command, action) {
  process.exitCode = await runWithEnvelope(command, action);
}

// src/lib/updo/collectWorkspaceDeps.ts
import { readFileSync as readFileSync2 } from "node:fs";
import PATH2 from "node:path";
var DEP_FIELDS = ["dependencies", "devDependencies", "peerDependencies"];
function collectExternalWorkspaceDeps(deps, depField, ws, workspaceNames, declaredDeps) {
  if (!deps) return;
  for (const [name, range] of Object.entries(deps)) {
    if (workspaceNames.has(name)) continue;
    if (range.startsWith("workspace:")) continue;
    declaredDeps.push({
      depType: depField,
      name,
      range,
      workspaceLocation: ws.location,
      workspaceName: ws.name
    });
  }
}
function collectWorkspaceDeps(cwd, workspaces, workspaceNames) {
  const declaredDeps = [];
  for (const ws of workspaces) {
    const pkgPath = PATH2.resolve(cwd, ws.location, "package.json");
    let pkg;
    try {
      pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
    } catch {
      continue;
    }
    for (const depField of DEP_FIELDS) {
      collectExternalWorkspaceDeps(
        pkg[depField],
        depField,
        ws,
        workspaceNames,
        declaredDeps
      );
    }
  }
  return declaredDeps;
}

// src/lib/updo/runUpdo.ts
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
import PATH3 from "node:path";
import chalk from "chalk";
function listWorkspacesFromFs(cwd) {
  const workspaces = listDeclaredWorkspaces(cwd);
  const rootPath = PATH3.resolve(cwd, "package.json");
  if (existsSync2(rootPath)) {
    try {
      const root = JSON.parse(readFileSync3(rootPath, "utf8"));
      if (root.name != null && root.name.length > 0 && workspaces.every((ws) => ws.location !== ".")) {
        workspaces.unshift({ location: ".", name: root.name });
      }
    } catch {
    }
  }
  return workspaces;
}

// src/actions/skills/passthrough.ts
import { createRequire } from "node:module";
import chalk2 from "chalk";
var ANSI_PREFIX = String.raw`\x1B\[[\d;]*m`;
var COMMAND_PREFIX = String.raw`(^|[\s$()\x60>]|${ANSI_PREFIX})`;
var SKILLS_COMMANDS = [
  "<command>",
  "add",
  "a",
  "use",
  "remove",
  "rm",
  "list",
  "ls",
  "find",
  "update",
  "upgrade",
  "experimental_install",
  "init",
  "experimental_sync",
  "defaults",
  "lint",
  "updo"
].join("|");
var NPX_SKILLS_PATTERN = new RegExp(String.raw`${COMMAND_PREFIX}npx(?:\s+-y)?\s+skills(?:@latest)?(?=\W|$)`, "g");
var BARE_USAGE_SKILLS_PATTERN = new RegExp(
  String.raw`^(\s*(?:${ANSI_PREFIX})*Usage:(?:${ANSI_PREFIX})*\s*)skills(?=\s+<command>)`,
  "gm"
);
var BARE_PROMPT_SKILLS_PATTERN = new RegExp(
  String.raw`^(\s*(?:${ANSI_PREFIX})*\$(?:${ANSI_PREFIX})*\s*)skills(?=\s+(?:${SKILLS_COMMANDS})(?:\W|$))`,
  "gm"
);
var require2 = createRequire(import.meta.url);
var rewriteSkillsRefs = (text) => {
  const withNpx = text.replaceAll(NPX_SKILLS_PATTERN, (_match, prefix) => `${prefix}xy skills`);
  return withNpx.replaceAll(BARE_USAGE_SKILLS_PATTERN, "$1xy skills").replaceAll(BARE_PROMPT_SKILLS_PATTERN, "$1xy skills");
};
var resolveBundledSkillsCli = () => {
  return require2.resolve("skills/bin/cli.mjs");
};
var resolveSkillsInvocation = async (args, options = {}) => {
  const resolveCli = options.resolveBundledCli ?? resolveBundledSkillsCli;
  const writeNotice = options.writeNotice ?? ((message) => console.error(message));
  try {
    const cliPath = resolveCli();
    return {
      args: [cliPath, ...args],
      command: process.execPath,
      fallback: false
    };
  } catch {
    writeNotice(chalk2.red("skills package not found. Reinstall @xylabs/toolchain dependencies."));
    return void 0;
  }
};
var runSkills = async (args, options = {}) => {
  const invocation = await resolveSkillsInvocation(args, options);
  if (invocation === void 0) return 1;
  const isInteractive = options.interactive ?? false;
  const stdio = isInteractive ? "inherit" : ["inherit", "pipe", "pipe"];
  return new Promise((resolve) => {
    const child = spawn(invocation.command, invocation.args, {
      env: { FORCE_COLOR: "3", ...process.env },
      stdio
    });
    if (!isInteractive) {
      child.stdout?.setEncoding("utf8");
      child.stderr?.setEncoding("utf8");
      child.stdout?.on("data", (chunk) => {
        process.stdout.write(rewriteSkillsRefs(chunk));
      });
      child.stderr?.on("data", (chunk) => {
        process.stderr.write(rewriteSkillsRefs(chunk));
      });
    }
    child.on("error", () => resolve(1));
    child.on("close", (code) => resolve(code ?? 1));
  });
};
var argvAfterCommand = (command) => {
  const argv = process.argv;
  const commandIdx = argv.indexOf(command);
  if (commandIdx === -1) return [];
  return argv.slice(commandIdx + 1);
};

// src/actions/skills/defaults.ts
var XYO_SKILLS_SOURCE = "XYOracleNetwork/xyo-skills";
var XYO_DEFAULT_SKILLS = [
  "xl1-build",
  "xl1-knowledge",
  "xl1-patterns",
  "xl1-scaffold",
  "xy-development",
  "xy-toolchain",
  "xyo-knowledge"
];
var AGENT_FLAGS = /* @__PURE__ */ new Set(["-a", "--agent"]);
var hasSkillsAgentFlag = (args) => {
  return args.some((arg) => AGENT_FLAGS.has(arg) || arg.startsWith("--agent="));
};
var skillsDefaultsArgs = (args) => {
  const installSelector = hasSkillsAgentFlag(args) ? ["--skill", "*"] : ["--all"];
  return ["add", XYO_SKILLS_SOURCE, ...installSelector, ...args];
};
var skillsDefaults = (args) => {
  return runSkills(skillsDefaultsArgs(args));
};

// src/actions/skills/detectProfile.ts
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
import PATH4 from "node:path";
var XYLABS_SCOPE = "@xylabs/";
var ARIESTOOLS_SCOPE = "@ariestools/";
var XYO_NETWORK_SCOPE = "@xyo-network/";
var XL1_PACKAGE_PREFIX = "@xyo-network/xl1";
var LEGACY_TOOLCHAIN_PACKAGES = /* @__PURE__ */ new Set([
  "@xylabs/ts-scripts-yarn3",
  "@xylabs/ts-scripts-pnpm",
  "@xylabs/ts-scripts-react-yarn3",
  "@xylabs/ts-scripts-common"
]);
var XY_ECOSYSTEM_SCOPES = [XYLABS_SCOPE, ARIESTOOLS_SCOPE, XYO_NETWORK_SCOPE];
var pushUnique = (list, value) => {
  if (!list.includes(value)) list.push(value);
};
var packageScope = (name) => {
  if (!name.startsWith("@")) return void 0;
  const slash = name.indexOf("/");
  if (slash === -1) return void 0;
  return name.slice(0, slash + 1);
};
var isXyoNetworkPackage = (name) => name.startsWith(XYO_NETWORK_SCOPE);
var isXl1Package = (name) => name.startsWith(XL1_PACKAGE_PREFIX);
var isXyEcosystemPackage = (name) => {
  return name.startsWith(XYLABS_SCOPE) || name.startsWith(ARIESTOOLS_SCOPE) || isXyoNetworkPackage(name);
};
var isTrackedImportScope = (scope) => {
  return XY_ECOSYSTEM_SCOPES.includes(scope);
};
var hasToolchainDependency = (depName) => {
  return depName === "@xylabs/toolchain" || LEGACY_TOOLCHAIN_PACKAGES.has(depName);
};
var isUsingXyScripts = (scripts) => {
  if (!scripts) return false;
  return Object.values(scripts).some((script) => /\bxy\b/.test(script));
};
var hasXyConfig = (cwd, workspaces) => {
  const locations = [".", ...workspaces.map((ws) => ws.location)];
  return locations.some((location) => {
    const configPath = PATH4.resolve(cwd, location, "xy.config.ts");
    return existsSync3(configPath);
  });
};
var resolveTier = (produces, imports, isUsingToolchain) => {
  const allPackages = [...produces, ...imports];
  if (allPackages.some(isXl1Package)) return "xl1";
  if (allPackages.some(isXyoNetworkPackage)) return "xyo";
  const hasXyEcosystem = allPackages.some(isXyEcosystemPackage);
  if (hasXyEcosystem || isUsingToolchain) return "xy";
  return "none";
};
var collectProduces = (cwd, workspaces) => {
  const produces = [];
  const signals = [];
  for (const ws of workspaces) {
    const pkgPath = PATH4.resolve(cwd, ws.location, "package.json");
    if (!existsSync3(pkgPath)) continue;
    try {
      const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
      if (pkg.name != null && pkg.name.length > 0 && isXyEcosystemPackage(pkg.name)) {
        pushUnique(produces, pkg.name);
        pushUnique(signals, `produces ${pkg.name}`);
      }
    } catch {
    }
  }
  return { produces, signals };
};
var collectImports = (declaredDeps) => {
  const imports = [];
  const signals = [];
  for (const dep of declaredDeps) {
    pushUnique(imports, dep.name);
    const scope = packageScope(dep.name);
    if (scope != null && isTrackedImportScope(scope)) {
      pushUnique(signals, `imports ${dep.name}`);
    }
  }
  return { imports, signals };
};
var detectToolchainUsage = (cwd, workspaces, declaredDeps) => {
  const signals = [];
  let isUsesToolchain = hasXyConfig(cwd, workspaces);
  const rootPkgPath = PATH4.resolve(cwd, "package.json");
  if (existsSync3(rootPkgPath)) {
    try {
      const rootPkg = JSON.parse(readFileSync4(rootPkgPath, "utf8"));
      if (isUsingXyScripts(rootPkg.scripts)) {
        isUsesToolchain = true;
        pushUnique(signals, "root scripts invoke xy");
      }
    } catch {
    }
  }
  for (const dep of declaredDeps) {
    if (hasToolchainDependency(dep.name)) {
      isUsesToolchain = true;
      pushUnique(signals, `imports ${dep.name}`);
    }
  }
  if (isUsesToolchain && hasXyConfig(cwd, workspaces)) {
    pushUnique(signals, "xy.config.ts present");
  }
  return { signals, isUsingToolchain: isUsesToolchain };
};
var detectRepoProfile = (cwd) => {
  const workspaces = listWorkspacesFromFs(cwd);
  const workspaceNames = new Set(workspaces.map((ws) => ws.name));
  const declaredDeps = collectWorkspaceDeps(cwd, workspaces, workspaceNames);
  const produced = collectProduces(cwd, workspaces);
  const imported = collectImports(declaredDeps);
  const toolchain = detectToolchainUsage(cwd, workspaces, declaredDeps);
  const signals = [...produced.signals, ...imported.signals, ...toolchain.signals].toSorted((a, b) => a.localeCompare(b));
  return {
    imports: imported.imports.toSorted((a, b) => a.localeCompare(b)),
    produces: produced.produces.toSorted((a, b) => a.localeCompare(b)),
    signals,
    tier: resolveTier(produced.produces, imported.imports, toolchain.isUsingToolchain),
    isUsingToolchain: toolchain.isUsingToolchain
  };
};

// src/actions/skills/installed.ts
import {
  existsSync as existsSync4,
  readdirSync,
  readFileSync as readFileSync5,
  statSync
} from "node:fs";
import PATH5 from "node:path";
var PROJECT_SKILL_DIRS = [".claude/skills", ".agents/skills"];
var VERSION_PATTERN = /metadata:\s*\n(?:[ \t]+[^\n]+\n)*?[ \t]+version:\s*([^\s#]+)/;
var listSkillDirs = (root) => {
  if (!existsSync4(root)) return [];
  return readdirSync(root).filter(
    (f) => statSync(PATH5.resolve(root, f)).isDirectory()
  );
};
var recordInstalledSkill = (installed, relativeDir, name, version) => {
  const existing = installed.get(name);
  if (existing == null) {
    installed.set(name, {
      locations: [relativeDir],
      name,
      version
    });
    return;
  }
  existing.locations.push(relativeDir);
  if (existing.version == null && version != null) {
    existing.version = version;
  }
};
var readSkillVersion = (skillDir) => {
  const skillMdPath = PATH5.resolve(skillDir, "SKILL.md");
  if (!existsSync4(skillMdPath)) return void 0;
  try {
    const content = readFileSync5(skillMdPath, "utf8");
    const match = VERSION_PATTERN.exec(content);
    return match?.[1]?.trim();
  } catch {
    return void 0;
  }
};
var scanInstalledSkills = (cwd, projectDirs = PROJECT_SKILL_DIRS) => {
  const installed = /* @__PURE__ */ new Map();
  for (const relativeDir of projectDirs) {
    const root = PATH5.resolve(cwd, relativeDir);
    for (const name of listSkillDirs(root)) {
      const version = readSkillVersion(PATH5.resolve(root, name));
      recordInstalledSkill(installed, relativeDir, name, version);
    }
  }
  return installed;
};
var listSkillDirsAt = (root) => {
  return listSkillDirs(root);
};

// src/actions/skills/lint.ts
import OS from "node:os";
import PATH6 from "node:path";
import chalk3 from "chalk";

// src/actions/skills/skillRules.ts
var XYO_SKILL_NAMES = [...XYO_DEFAULT_SKILLS];
var XY_SKILLS = ["xy-development", "xy-toolchain"];
var XYO_SKILLS = ["xyo-knowledge"];
var XL1_SKILLS = ["xl1-knowledge", "xl1-patterns"];
var XL1_OPTIONAL_SKILLS = ["xl1-scaffold", "xl1-build"];
var TIER_REQUIRED_SKILLS = {
  xy: XY_SKILLS,
  xyo: [...XY_SKILLS, ...XYO_SKILLS],
  xl1: [...XY_SKILLS, ...XYO_SKILLS, ...XL1_SKILLS]
};
var requiredSkillsForTier = (tier) => {
  if (tier === "none") return [];
  return TIER_REQUIRED_SKILLS[tier];
};
var optionalSkillsForTier = (tier) => {
  if (tier !== "xl1") return [];
  return XL1_OPTIONAL_SKILLS;
};
var isXyoSkillName = (name) => {
  return XYO_SKILL_NAMES.includes(name);
};
var unnecessarySkillsForTier = (tier, installed) => {
  const required = new Set(requiredSkillsForTier(tier));
  const optional = new Set(optionalSkillsForTier(tier));
  return installed.filter(isXyoSkillName).filter((name) => !required.has(name) && !optional.has(name)).toSorted((a, b) => a.localeCompare(b));
};

// src/actions/skills/versions.ts
import semver from "semver";
var VERSION_PATTERN2 = /metadata:\s*\n(?:[ \t]+[^\n]+\n)*?[ \t]+version:\s*([^\s#]+)/;
var upstreamSkillUrl = (skillName) => {
  return `https://raw.githubusercontent.com/${XYO_SKILLS_SOURCE}/main/skills/${skillName}/SKILL.md`;
};
var parseSkillVersion = (content) => {
  const match = VERSION_PATTERN2.exec(content);
  return match?.[1]?.trim();
};
var createGitHubSkillVersionFetcher = () => {
  const cache = /* @__PURE__ */ new Map();
  return {
    fetchSkillContent: async (skillName) => {
      if (cache.has(skillName)) return cache.get(skillName);
      try {
        const res = await fetch(upstreamSkillUrl(skillName));
        if (!res.ok) {
          cache.set(skillName, void 0);
          return;
        }
        const content = await res.text();
        cache.set(skillName, content);
        return content;
      } catch {
        cache.set(skillName, void 0);
        return;
      }
    }
  };
};
var fetchLatestSkillVersions = async (skillNames, fetcher = createGitHubSkillVersionFetcher()) => {
  const latest = /* @__PURE__ */ new Map();
  await Promise.all(skillNames.map(async (skillName) => {
    const content = await fetcher.fetchSkillContent(skillName);
    latest.set(skillName, content == null ? void 0 : parseSkillVersion(content));
  }));
  return latest;
};
var isSkillVersionOutdated = (installedVersion, latestVersion) => {
  if (latestVersion == null) return false;
  if (installedVersion == null) return true;
  const installedCoerced = semver.coerce(installedVersion);
  const latestCoerced = semver.coerce(latestVersion);
  if (installedCoerced == null || latestCoerced == null) {
    return installedVersion !== latestVersion;
  }
  return semver.lt(installedCoerced, latestCoerced);
};

// src/actions/skills/lint.ts
var DEFAULT_GLOBAL_DIR = PATH6.resolve(OS.homedir(), ".claude", "skills");
var logOk = (message) => {
  console.log(chalk3.green(`  \u2714 ${message}`));
};
var logError = (message) => {
  console.log(chalk3.red(`  \u2718 ${message}`));
};
var logWarning = (message) => {
  console.log(chalk3.yellow(`  \u26A0 ${message}`));
};
var logInfo = (message) => {
  console.log(chalk3.gray(`  \u2139 ${message}`));
};
var installMissingSkill = async (skillName) => {
  return runSkills(["add", XYO_SKILLS_SOURCE, "--skill", skillName, "-y"]);
};
var missingSkillReason = (profile, skillName) => {
  if (profile.isUsingToolchain && skillName === "xy-toolchain") {
    return "repo uses @xylabs/toolchain";
  }
  return "required for repo profile";
};
var checkRequiredSkills = (required, installed, latestVersions, profile, isOffline) => {
  const missing = [];
  const outdated = [];
  let errors = 0;
  for (const skillName of required) {
    const installedSkill = installed.get(skillName);
    if (installedSkill == null) {
      missing.push(skillName);
      errors += 1;
      logError(`${skillName} \u2014 missing (${missingSkillReason(profile, skillName)})`);
      continue;
    }
    const installedVersion = installedSkill.version;
    const latestVersion = latestVersions.get(skillName);
    const isVersionIsOutdated = isOffline === false && isSkillVersionOutdated(installedVersion, latestVersion);
    if (isVersionIsOutdated) {
      outdated.push({
        latest: latestVersion,
        name: skillName,
        version: installedVersion
      });
      errors += 1;
      logError(`${skillName} v${installedVersion ?? "unknown"} \u2014 outdated (latest ${latestVersion ?? "unknown"})`);
      continue;
    }
    const versionSuffix = installedVersion == null ? "" : ` v${installedVersion}`;
    logOk(`${skillName}${versionSuffix}`);
  }
  return {
    errors,
    missing,
    outdated
  };
};
var findDuplicateSkills = (cwd, globalDir) => {
  const projectClaudeDir = PATH6.resolve(cwd, ".claude", "skills");
  const projectSkills = listSkillDirsAt(projectClaudeDir);
  const globalSkills = new Set(listSkillDirsAt(globalDir));
  return projectSkills.filter((name) => globalSkills.has(name)).toSorted((a, b) => a.localeCompare(b));
};
var logOptionalSkills = (tier, optional, installed) => {
  if (tier !== "xl1") return;
  for (const skillName of optional) {
    if (!installed.has(skillName)) {
      logInfo(`${skillName} \u2014 optional for greenfield XL1 work`);
    }
  }
};
var logProfileHeader = (profile) => {
  console.log(chalk3.bold(`Skills lint (profile: ${profile.tier})`));
  if (profile.signals.length > 0) {
    console.log(chalk3.gray(`  signals: ${profile.signals.join(", ")}`));
  }
  console.log();
};
var collectSkillNamesToCheck = (required, installed) => {
  const names = new Set(required);
  for (const name of installed.keys()) {
    if (isXyoSkillName(name)) names.add(name);
  }
  return [...names];
};
var logLintWarnings = (profile, installed, cwd, globalDir) => {
  let warnings = 0;
  const installedNames = installed.keys().toArray();
  for (const skillName of unnecessarySkillsForTier(profile.tier, installedNames)) {
    warnings += 1;
    logWarning(`${skillName} \u2014 installed but not required for this repo profile`);
  }
  for (const name of findDuplicateSkills(cwd, globalDir)) {
    warnings += 1;
    logWarning(`${name} \u2014 also installed globally (duplicate)`);
  }
  return warnings;
};
var installMissingSkills = async (missing) => {
  console.log();
  console.log(chalk3.gray("Installing missing required skills..."));
  for (const skillName of missing) {
    const code = await installMissingSkill(skillName);
    if (code !== 0) return code;
  }
  console.log(chalk3.green("Missing skills installed. Re-run `xy skills lint` to verify versions."));
  return 0;
};
var resolveLintExitCode = (requiredCheck, warnings, isStrict) => {
  if (requiredCheck.errors > 0) return 1;
  if (isStrict && warnings > 0) return 1;
  return 0;
};
var skillsLint = async (options = {}) => {
  const cwd = options.cwd ?? INIT_CWD();
  const projectDirs = options.projectDirs ?? [...PROJECT_SKILL_DIRS];
  const globalDir = options.globalDir ?? DEFAULT_GLOBAL_DIR;
  const isOffline = options.isOffline === true;
  const isStrict = options.isStrict === true;
  const profile = detectRepoProfile(cwd);
  const required = requiredSkillsForTier(profile.tier);
  const optional = optionalSkillsForTier(profile.tier);
  const installed = scanInstalledSkills(cwd, projectDirs);
  logProfileHeader(profile);
  const latestVersions = isOffline ? /* @__PURE__ */ new Map() : await fetchLatestSkillVersions(collectSkillNamesToCheck(required, installed));
  const requiredCheck = checkRequiredSkills(required, installed, latestVersions, profile, isOffline);
  const warnings = logLintWarnings(profile, installed, cwd, globalDir);
  logOptionalSkills(profile.tier, optional, installed);
  console.log();
  if (requiredCheck.errors === 0 && warnings === 0) {
    console.log(chalk3.green("All required skills are installed and up to date."));
    return 0;
  }
  if (requiredCheck.missing.length > 0 || requiredCheck.outdated.length > 0) {
    const hints = [];
    if (requiredCheck.missing.length > 0) {
      hints.push("run `xy skills lint --fix` to install missing required skills");
    }
    if (requiredCheck.outdated.length > 0) {
      hints.push("run `xy skills updo` to update outdated skills");
    }
    console.log(chalk3.yellow(`${hints.join(", or ")}.`));
  }
  if (options.fix === true && requiredCheck.missing.length > 0) {
    return installMissingSkills(requiredCheck.missing);
  }
  return resolveLintExitCode(requiredCheck, warnings, isStrict);
};

// src/actions/skills/updo.ts
var SCOPE_FLAGS = /* @__PURE__ */ new Set(["-g", "--global", "-p", "--project"]);
var hasSkillsScopeFlag = (args) => args.some((a) => SCOPE_FLAGS.has(a));
var skillsUpdoArgs = (args) => {
  const finalArgs = hasSkillsScopeFlag(args) ? args : ["-p", ...args];
  return ["update", ...finalArgs];
};
var skillsUpdo = (args) => {
  return runSkills(skillsUpdoArgs(args));
};

// src/xy/common/skills/index.ts
var CUSTOM_SKILLS_COMMANDS = /* @__PURE__ */ new Set(["defaults", "lint", "updo"]);
var HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
var hasHelpFlag = (args) => args.some((arg) => HELP_FLAGS.has(arg));
var printDefaultsHelp = () => {
  console.log(`xy skills defaults

Install the XY/XYO/XL1 default skill stack from XYOracleNetwork/xyo-skills.

Usage:
  xy skills defaults [options]

Options:
  -g, --global          Install globally instead of project-locally
  -a, --agent <agent>   Install all default skills to specific agents
  --copy                Copy files instead of symlinking
  -h, --help            Show this help
`);
};
var LINT_FLAGS = /* @__PURE__ */ new Set(["--fix", "--offline", "--strict"]);
var parseLintArgs = (args) => {
  return {
    fix: args.includes("--fix"),
    offline: args.includes("--offline"),
    strict: args.includes("--strict")
  };
};
var printLintHelp = () => {
  console.log(`xy skills lint

Verify project-local xyo-skills match the repo profile, are up to date, and
are not duplicated in global scope.

Usage:
  xy skills lint [options]

Checks:
  - Detect repo tier (xy, xyo, xl1) from package.json and toolchain signals
  - Required skills installed in .claude/skills and/or .agents/skills
  - Installed skill versions vs XYOracleNetwork/xyo-skills main
  - Project/global duplicate installs

Options:
  --fix                 Install missing required skills (project scope)
  --offline             Skip upstream version checks
  --strict              Fail on warnings (duplicates, unnecessary skills)
  -h, --help            Show this help
`);
};
var printUpdoHelp = () => {
  console.log(`xy skills updo

Update installed Skills.sh skills. Defaults to project scope.

Usage:
  xy skills updo [skills..] [options]

Options:
  -g, --global          Update global skills instead of project skills
  -p, --project         Update project skills (default)
  -y, --yes             Skip confirmation prompts
  -h, --help            Show this help
`);
};
var runSkillsTail = (tail) => {
  const [subcommand, ...args] = tail;
  if (subcommand === "defaults" && hasHelpFlag(args)) {
    printDefaultsHelp();
    return 0;
  }
  if (subcommand === "lint" && hasHelpFlag(args)) {
    printLintHelp();
    return 0;
  }
  if (subcommand === "updo" && hasHelpFlag(args)) {
    printUpdoHelp();
    return 0;
  }
  if (subcommand === "defaults") return skillsDefaults(args);
  if (subcommand === "lint") {
    const lintArgs = args.filter((arg) => !LINT_FLAGS.has(arg) && !HELP_FLAGS.has(arg));
    if (lintArgs.length > 0) {
      console.error(`Unknown arguments for skills lint: ${lintArgs.join(", ")}`);
      return 1;
    }
    return skillsLint(parseLintArgs(args));
  }
  if (subcommand === "updo") return skillsUpdo(args);
  return runSkills(tail);
};
var skillsCommand = {
  builder: (yargs) => {
    return yargs.parserConfiguration({ "unknown-options-as-args": true }).positional("args", {
      array: true,
      describe: "Arguments forwarded to Skills.sh",
      type: "string"
    }).help(false).strict(false).version(false);
  },
  command: "skills [args..]",
  describe: "Manage agent skills via the bundled Skills.sh CLI; forwards unknown commands and adds XY conveniences: defaults, lint, updo",
  handler: async () => {
    const tail = argvAfterCommand("skills");
    const commandName = CUSTOM_SKILLS_COMMANDS.has(tail[0] ?? "") ? `skills ${tail[0]}` : "skills";
    await withEnvelope(commandName, () => runSkillsTail(tail));
  }
};
export {
  skillsCommand
};
//# sourceMappingURL=index.mjs.map
