agents-inc 0.153.0 → 0.154.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/{chunk-EFU6P3B7.js → chunk-2IMYK4WN.js} +3 -3
  3. package/dist/{chunk-U2YSGBHA.js → chunk-4VCWL2IG.js} +33 -16
  4. package/dist/chunk-4VCWL2IG.js.map +1 -0
  5. package/dist/{chunk-ORJ5Y222.js → chunk-5MFJ24VM.js} +90 -24
  6. package/dist/chunk-5MFJ24VM.js.map +1 -0
  7. package/dist/{chunk-TY6CAOL7.js → chunk-7VZV4O6B.js} +3 -3
  8. package/dist/{chunk-4VYALFQZ.js → chunk-AKQ5QISO.js} +6 -6
  9. package/dist/{chunk-U2DNAHFE.js → chunk-AURY6RT6.js} +3 -3
  10. package/dist/{chunk-ACKC577F.js → chunk-B66SC72V.js} +3 -3
  11. package/dist/{chunk-WDAO3RUY.js → chunk-BZ4CZBOM.js} +3 -3
  12. package/dist/{chunk-NXQAY5U7.js → chunk-CBF4ZYV3.js} +4556 -4457
  13. package/dist/chunk-CBF4ZYV3.js.map +1 -0
  14. package/dist/{chunk-JFAUQDZM.js → chunk-CHNA5RVS.js} +3 -3
  15. package/dist/{chunk-2HC2SNRP.js → chunk-DRKSYJZ2.js} +1 -5
  16. package/dist/chunk-DRKSYJZ2.js.map +1 -0
  17. package/dist/{chunk-X5XJ6WKO.js → chunk-FMYHWKGG.js} +45 -4
  18. package/dist/chunk-FMYHWKGG.js.map +1 -0
  19. package/dist/{chunk-K7PJDWER.js → chunk-GUDGCFSF.js} +6 -6
  20. package/dist/{chunk-35VOK7XE.js → chunk-IPJOMAWC.js} +4355 -4355
  21. package/dist/{chunk-35VOK7XE.js.map → chunk-IPJOMAWC.js.map} +1 -1
  22. package/dist/{chunk-VGEBYCQZ.js → chunk-IXEDSKMH.js} +4 -15
  23. package/dist/chunk-IXEDSKMH.js.map +1 -0
  24. package/dist/{chunk-ZNDLUWWD.js → chunk-LA3JPESW.js} +3 -3
  25. package/dist/{chunk-M5HSTNYU.js → chunk-MJFIO5SX.js} +5 -23
  26. package/dist/chunk-MJFIO5SX.js.map +1 -0
  27. package/dist/{chunk-VECFAKM5.js → chunk-NFH6SA62.js} +4 -4
  28. package/dist/{chunk-R4SEU3DF.js → chunk-NKCY2ULI.js} +2 -2
  29. package/dist/{chunk-IO4VEW5U.js → chunk-ONWEOS77.js} +2 -2
  30. package/dist/{chunk-FRWKCE6R.js → chunk-PRJD5MMQ.js} +3 -3
  31. package/dist/{chunk-HEBPKK5L.js → chunk-QQTYMW7N.js} +11 -23
  32. package/dist/chunk-QQTYMW7N.js.map +1 -0
  33. package/dist/{chunk-KET3EVGX.js → chunk-QUDQTO3O.js} +3 -3
  34. package/dist/{chunk-BMGBA6HJ.js → chunk-R7JV22QK.js} +12 -12
  35. package/dist/{chunk-FIHTAFST.js → chunk-TUQF577Z.js} +30 -30
  36. package/dist/{chunk-FIHTAFST.js.map → chunk-TUQF577Z.js.map} +1 -1
  37. package/dist/{chunk-NXGMM5YN.js → chunk-UW44KSYL.js} +3 -3
  38. package/dist/{chunk-WG6V6VJV.js → chunk-WRRP47PY.js} +2 -2
  39. package/dist/{chunk-F7Z5I6GU.js → chunk-XMEIVWAS.js} +4 -4
  40. package/dist/{chunk-REKOWTIB.js → chunk-ZU6DAR4S.js} +42 -8
  41. package/dist/chunk-ZU6DAR4S.js.map +1 -0
  42. package/dist/commands/build/marketplace.js +6 -5
  43. package/dist/commands/build/marketplace.js.map +1 -1
  44. package/dist/commands/build/plugins.js +6 -6
  45. package/dist/commands/compile.js +48 -10
  46. package/dist/commands/compile.js.map +1 -1
  47. package/dist/commands/doctor.js +10 -10
  48. package/dist/commands/edit.js +93 -59
  49. package/dist/commands/edit.js.map +1 -1
  50. package/dist/commands/eject.js +10 -10
  51. package/dist/commands/init.js +29 -29
  52. package/dist/commands/list.js +7 -7
  53. package/dist/commands/search.js +29 -21
  54. package/dist/commands/search.js.map +1 -1
  55. package/dist/commands/uninstall.js +198 -147
  56. package/dist/commands/uninstall.js.map +1 -1
  57. package/dist/commands/update.js +5 -5
  58. package/dist/components/wizard/category-grid.js +3 -3
  59. package/dist/components/wizard/checkbox-grid.js +2 -2
  60. package/dist/components/wizard/domain-selection.js +8 -8
  61. package/dist/components/wizard/run-wizard-session.js +21 -21
  62. package/dist/components/wizard/skill-agent-summary.js +5 -5
  63. package/dist/components/wizard/source-grid.js +3 -3
  64. package/dist/components/wizard/stack-selection.js +5 -5
  65. package/dist/components/wizard/step-agents.js +8 -8
  66. package/dist/components/wizard/step-build.js +7 -7
  67. package/dist/components/wizard/step-confirm.js +8 -8
  68. package/dist/components/wizard/step-sources.js +7 -7
  69. package/dist/components/wizard/step-stack.js +6 -6
  70. package/dist/components/wizard/summary-panel.js +7 -7
  71. package/dist/components/wizard/wizard-layout.js +9 -9
  72. package/dist/components/wizard/wizard.js +20 -20
  73. package/dist/copy-local-skills-WVHJFRPK.js +14 -0
  74. package/dist/hooks/init.js +29 -29
  75. package/dist/load-agent-defs-5OT54J5M.js +15 -0
  76. package/dist/{loader-4U7UCE2Y.js → loader-JIZDTR4G.js} +2 -2
  77. package/dist/recompile-project-agents-VREEPBDV.js +20 -0
  78. package/dist/{source-loader-ZNSYJJCI.js → source-loader-OE6EJFPU.js} +4 -4
  79. package/dist/stores/wizard-store.js +4 -4
  80. package/package.json +1 -1
  81. package/src/schemas/plugin.schema.json +3 -0
  82. package/dist/chunk-2HC2SNRP.js.map +0 -1
  83. package/dist/chunk-HEBPKK5L.js.map +0 -1
  84. package/dist/chunk-M5HSTNYU.js.map +0 -1
  85. package/dist/chunk-NXQAY5U7.js.map +0 -1
  86. package/dist/chunk-ORJ5Y222.js.map +0 -1
  87. package/dist/chunk-REKOWTIB.js.map +0 -1
  88. package/dist/chunk-U2YSGBHA.js.map +0 -1
  89. package/dist/chunk-VGEBYCQZ.js.map +0 -1
  90. package/dist/chunk-X5XJ6WKO.js.map +0 -1
  91. package/dist/copy-local-skills-KF2RAVD3.js +0 -14
  92. package/dist/load-agent-defs-DGXGBU3Q.js +0 -15
  93. package/dist/recompile-project-agents-CJVBAWDJ.js +0 -20
  94. /package/dist/{chunk-EFU6P3B7.js.map → chunk-2IMYK4WN.js.map} +0 -0
  95. /package/dist/{chunk-TY6CAOL7.js.map → chunk-7VZV4O6B.js.map} +0 -0
  96. /package/dist/{chunk-4VYALFQZ.js.map → chunk-AKQ5QISO.js.map} +0 -0
  97. /package/dist/{chunk-U2DNAHFE.js.map → chunk-AURY6RT6.js.map} +0 -0
  98. /package/dist/{chunk-ACKC577F.js.map → chunk-B66SC72V.js.map} +0 -0
  99. /package/dist/{chunk-WDAO3RUY.js.map → chunk-BZ4CZBOM.js.map} +0 -0
  100. /package/dist/{chunk-JFAUQDZM.js.map → chunk-CHNA5RVS.js.map} +0 -0
  101. /package/dist/{chunk-K7PJDWER.js.map → chunk-GUDGCFSF.js.map} +0 -0
  102. /package/dist/{chunk-ZNDLUWWD.js.map → chunk-LA3JPESW.js.map} +0 -0
  103. /package/dist/{chunk-VECFAKM5.js.map → chunk-NFH6SA62.js.map} +0 -0
  104. /package/dist/{chunk-R4SEU3DF.js.map → chunk-NKCY2ULI.js.map} +0 -0
  105. /package/dist/{chunk-IO4VEW5U.js.map → chunk-ONWEOS77.js.map} +0 -0
  106. /package/dist/{chunk-FRWKCE6R.js.map → chunk-PRJD5MMQ.js.map} +0 -0
  107. /package/dist/{chunk-KET3EVGX.js.map → chunk-QUDQTO3O.js.map} +0 -0
  108. /package/dist/{chunk-BMGBA6HJ.js.map → chunk-R7JV22QK.js.map} +0 -0
  109. /package/dist/{chunk-NXGMM5YN.js.map → chunk-UW44KSYL.js.map} +0 -0
  110. /package/dist/{chunk-WG6V6VJV.js.map → chunk-WRRP47PY.js.map} +0 -0
  111. /package/dist/{chunk-F7Z5I6GU.js.map → chunk-XMEIVWAS.js.map} +0 -0
  112. /package/dist/{copy-local-skills-KF2RAVD3.js.map → copy-local-skills-WVHJFRPK.js.map} +0 -0
  113. /package/dist/{load-agent-defs-DGXGBU3Q.js.map → load-agent-defs-5OT54J5M.js.map} +0 -0
  114. /package/dist/{loader-4U7UCE2Y.js.map → loader-JIZDTR4G.js.map} +0 -0
  115. /package/dist/{recompile-project-agents-CJVBAWDJ.js.map → recompile-project-agents-VREEPBDV.js.map} +0 -0
  116. /package/dist/{source-loader-ZNSYJJCI.js.map → source-loader-OE6EJFPU.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/compile.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport os from \"os\";\nimport { BaseCommand } from \"../base-command\";\nimport { setVerbose, verbose } from \"../utils/logger\";\nimport {\n detectBothInstallations,\n type BothInstallations,\n loadAgentDefs,\n type AgentDefs,\n compileAgents,\n discoverInstalledSkills,\n type DiscoveredSkills,\n} from \"../lib/operations\";\nimport {\n ConfigLoadError,\n effectivelyExcludedSkillIds,\n loadProjectConfig,\n loadProjectConfigFromDir,\n resolveSource,\n} from \"../lib/configuration\";\nimport { getStackSkillIds } from \"../lib/stacks\";\nimport { loadSkillsMatrixFromSource, type UnusableSkillMetadata } from \"../lib/loading\";\nimport { CLI_INVOKE_COMMAND, STANDARD_FILES } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport {\n ERROR_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n configTypesRefreshFailed,\n globalScopedAgentsHint,\n recompileSummary,\n registeredProjectUpdateSkipped,\n skillMetadataUnusableDetail,\n skillMetadataUnusableError,\n} from \"../utils/messages\";\nimport { reconcileTypesFromDisk, type GateReport } from \"../lib/config-gate/index.js\";\nimport type { Installation } from \"../lib/installation\";\nimport type { SkillScope } from \"../types/config\";\nimport type { AgentDefinition, AgentName, SkillDefinitionMap } from \"../types\";\n\nexport default class Compile extends BaseCommand {\n static summary = \"Compile agents using local skills and agent definitions\";\n\n static description =\n \"Compile agents with resolved skill references. Compiles to the Claude plugin directory.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --verbose\",\n ];\n\n static flags = {\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Compile);\n setVerbose(flags.verbose);\n const cwd = process.cwd();\n\n const installations = await this.detectInstallations(cwd);\n await this.resolveAndLogSource(cwd);\n const agentDefs = await this.loadAgentDefsOrFail(cwd);\n await this.runCompilePasses(installations, agentDefs, cwd);\n }\n\n private async detectInstallations(cwd: string): Promise<BothInstallations> {\n let installations: BothInstallations;\n try {\n installations = await detectBothInstallations(cwd);\n } catch (error) {\n // A corrupt config (file present but unparseable) must not let compile run\n // config-less — that resurrects every deselected agent. Hard-error naming\n // the offending file before any compilation happens.\n if (error instanceof ConfigLoadError) {\n this.error(error.message, { exit: EXIT_CODES.ERROR });\n }\n throw error;\n }\n\n if (!installations.global && !installations.project) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n return installations;\n }\n\n /**\n * Names where the source came from — the project's own config first, then the global\n * one, then the default. `compile` takes no `--source`: it recompiles an installation\n * that already recorded which marketplace its skill references answer to, and reading\n * a different one would write agents against a catalogue config.ts does not name.\n */\n private async resolveAndLogSource(projectDir: string): Promise<void> {\n this.log(STATUS_MESSAGES.RESOLVING_SOURCE);\n try {\n const sourceConfig = await resolveSource({ caller: \"stored\", projectDir });\n this.log(`Source: ${sourceConfig.sourceOrigin}`);\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_RESOLVE_SOURCE);\n this.handleError(error);\n }\n }\n\n private async loadAgentDefsOrFail(cwd: string): Promise<AgentDefs> {\n this.log(STATUS_MESSAGES.LOADING_AGENT_PARTIALS);\n try {\n const defs = await loadAgentDefs({ projectDir: cwd });\n this.log(\"Agent partials loaded\");\n verbose(` Agents: ${defs.agentSourcePaths.agentsDir}`);\n verbose(` Templates: ${defs.agentSourcePaths.templatesDir}`);\n return defs;\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_LOAD_AGENT_PARTIALS);\n this.handleError(error);\n }\n }\n\n private async runCompilePasses(\n installations: BothInstallations,\n agentDefs: AgentDefs,\n cwd: string,\n ): Promise<void> {\n const passes = buildCompilePasses(installations, cwd, agentDefs);\n\n let totalPassesWithSkills = 0;\n for (const pass of passes) {\n const hadSkills = await this.runCompilePass(pass, cwd);\n if (hadSkills) totalPassesWithSkills++;\n }\n\n if (totalPassesWithSkills === 0) {\n this.error(\n `No skills found. Add skills with '${CLI_INVOKE_COMMAND} add <skill>' or create in .claude/skills/.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n }\n\n /**\n * Discovers what this pass compiles from, and refuses the run when any installed\n * skill's metadata.yaml exists but describes no skill — before a count is printed,\n * an agent is written or the type unions are regenerated. Skipping such a skill is\n * what the config-types pass already does; loading it anyway is what this pass\n * used to do, so a single run both loaded and skipped the same file.\n */\n private async discoverAllSkills(projectDir: string): Promise<DiscoveredSkills> {\n this.log(STATUS_MESSAGES.DISCOVERING_SKILLS);\n const result = await discoverInstalledSkills(projectDir);\n if (result.unusableMetadata.length > 0) {\n this.refuseUnusableSkillMetadata(result.unusableMetadata);\n }\n if (result.totalSkillCount === 0) return result;\n this.log(formatDiscoveryMessage(result));\n return result;\n }\n\n /**\n * Names each offending file and its reason, then exits. The detail is LOGGED and\n * only the refusal is raised: oclif hard-wraps error text at the terminal width,\n * and a path broken across two lines is one nobody can copy.\n */\n private refuseUnusableSkillMetadata(entries: UnusableSkillMetadata[]): never {\n for (const entry of entries) {\n this.log(skillMetadataUnusableDetail(entry));\n }\n this.error(skillMetadataUnusableError(entries), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * A stack skill that is not among the discovered skills is dropped from every\n * agent that references it. The resolver only records that at verbose level, so\n * the default output would claim a successful recompile of an agent that no\n * longer matches config.ts. Name each dropped skill instead.\n */\n private async warnUnresolvedStackSkills(\n projectDir: string,\n allSkills: SkillDefinitionMap,\n ): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n const excludedIds = effectivelyExcludedSkillIds(loaded.config.skills);\n const unresolved = getStackSkillIds(loaded.config.stack).filter(\n (id) => !excludedIds.has(id) && !(id in allSkills),\n );\n\n for (const id of unresolved) {\n this.warn(\n `Skill '${id}' is configured but was not found — agents will be compiled without it.`,\n );\n }\n }\n\n /**\n * The project pass compiled no agents, but the project config may still declare\n * global-scope agents whose stack lives in the global config. Without a pointer\n * the \"No agents to recompile\" line reads as a silent no-op after a global stack\n * change, so name the global context and the count.\n */\n private async hintGlobalScopedAgents(projectDir: string): Promise<void> {\n const loaded = await loadProjectConfigFromDir(projectDir);\n if (!loaded) return;\n\n const globalAgentCount = loaded.config.agents.filter(\n (agent) => !agent.excluded && agent.scope === \"global\",\n ).length;\n if (globalAgentCount === 0) return;\n\n this.log(globalScopedAgentsHint(globalAgentCount));\n }\n\n /**\n * The documented hand-edit workflow is \"edit config.ts, then run compile\", and\n * the type unions in config-types.ts are derived from config.ts — so a compile\n * pass that leaves them untouched strands stale unions after a hand-edit.\n * Regenerates them from the scope's persisted config exactly as the wizard\n * write path would: standalone narrowed unions at global scope, import-and-\n * extend at project scope. `matrixOnly` keeps the default-source path offline.\n * A failed refresh downgrades to a warning — the compiled agents are already\n * written and remain valid; only the type unions may still be stale.\n *\n * `skipExtraSources: true` is NOT a divergence from the wizard's full\n * multi-source load: extra-source loading only annotates each skill's\n * `availableSources`/`activeSource` for wizard UI tagging — it never adds\n * skills or categories to the matrix, and the config-types writer never reads\n * those annotations, so the emitted types are byte-identical either way\n * (pinned by the skipExtraSources parity test in local-installer.test.ts).\n * Skipping avoids fetching every registered extra source (network on a cold\n * cache, plus unreachable-remote warnings) on this offline compile path.\n */\n private async refreshConfigTypes(pass: CompilePass, cwd: string): Promise<void> {\n let report: GateReport;\n try {\n const loaded = await loadProjectConfigFromDir(pass.projectDir);\n if (!loaded) {\n verbose(\n `No config found at ${pass.projectDir} — skipping ${STANDARD_FILES.CONFIG_TYPES_TS} refresh`,\n );\n return;\n }\n\n const { matrix } = await loadSkillsMatrixFromSource({\n projectDir: pass.projectDir,\n skipExtraSources: true,\n matrixOnly: true,\n });\n // `cwd` is excluded from the fan-out, which only a global pass can perform:\n // whatever this invocation was run from is this command's own subject, so a\n // fan-out must never reach back into it.\n report = await reconcileTypesFromDisk(\n pass.projectDir,\n loaded.config,\n { matrix, agents: pass.agents },\n { currentProjectDir: cwd },\n );\n this.log(INFO_MESSAGES.CONFIG_TYPES_REFRESHED);\n } catch (error) {\n this.warn(configTypesRefreshFailed(getErrorMessage(error)));\n return;\n }\n\n this.reportPropagation(report);\n }\n\n /**\n * Renders the fan-out the refresh above performed. Kept out of the refresh's\n * catch on purpose: a project the fan-out could not reach is reported as that,\n * not as a failure to refresh the type unions — which did succeed.\n */\n private reportPropagation(report: GateReport): void {\n for (const skippedPath of report.propagated.skipped) {\n this.warn(registeredProjectUpdateSkipped(skippedPath));\n }\n this.reportPropagatedRecompile(report);\n }\n\n private async runCompilePass(params: CompilePass, cwd: string): Promise<boolean> {\n const { label, projectDir, installation, sourcePath, scopeFilter } = params;\n\n this.log(\"\");\n this.log(`Compiling ${label.toLowerCase()} agents...`);\n this.log(\"\");\n\n verbose(` Project: ${projectDir}`);\n verbose(` Agents: ${installation.agentsDir}`);\n\n const { allSkills, totalSkillCount } = await this.discoverAllSkills(projectDir);\n\n if (totalSkillCount === 0) {\n this.log(`No skills found for ${label.toLowerCase()} pass, skipping`);\n // The config loads independently of discovered skills: a hand-edited\n // config.ts can list skills while nothing is installed for this scope,\n // and its type unions must follow the config rather than stay stale.\n await this.refreshConfigTypes(params, cwd);\n return false;\n }\n\n await this.warnUnresolvedStackSkills(projectDir, allSkills);\n\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n try {\n const recompileResult = await compileAgents({\n projectDir,\n sourcePath,\n skills: allSkills,\n pluginDir: projectDir,\n outputDir: installation.agentsDir,\n ...(scopeFilter !== undefined && { scopeFilter }),\n });\n\n const { compiled, rewritten, failed, warnings } = recompileResult;\n const summary = recompileSummary(\n rewritten.length,\n compiled.length - rewritten.length,\n `${label.toLowerCase()} agents`,\n );\n\n if (failed.length > 0) {\n this.log(`${summary} (${failed.length} failed)`);\n for (const warning of warnings) {\n this.warn(warning);\n }\n } else if (compiled.length > 0) {\n this.log(summary);\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n if (label === \"Project\") {\n await this.hintGlobalScopedAgents(projectDir);\n }\n }\n\n if (compiled.length > 0) {\n verbose(` Compiled: ${compiled.join(\", \")}`);\n }\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_COMPILE_AGENTS);\n this.handleError(error);\n }\n\n await this.refreshConfigTypes(params, cwd);\n\n this.log(\"\");\n this.logSuccess(`${label} compile complete!`);\n this.log(\"\");\n\n return true;\n }\n}\n\ntype CompilePass = {\n label: \"Global\" | \"Project\";\n projectDir: string;\n installation: Installation;\n sourcePath: string;\n agents: Partial<Record<AgentName, AgentDefinition>>;\n scopeFilter?: SkillScope;\n};\n\n/**\n * The single pass this invocation owns.\n *\n * A compile run inside a project is a PROJECT-scope operation and writes nothing\n * outside that project: it compiles the project's own agents and refreshes the\n * project's own type unions, and never the global install's or another\n * registered project's. Propagation is a global operation's consequence — the\n * global config is what every project's config inlines — and a project compile\n * is not one.\n *\n * The global pass is therefore reached only where no project installation is in\n * play: at the home directory (where `detectBothInstallations` returns no\n * project by construction), or in a directory that has no config of its own, so\n * the global install is the only thing there is to compile.\n *\n * `scopeFilter` still narrows the project pass whenever both installations\n * exist: the project's config inlines the global entries, so an unfiltered pass\n * would compile global-scoped agents into the project's own agents directory.\n */\nfunction buildCompilePasses(\n installations: BothInstallations,\n cwd: string,\n agentDefs: AgentDefs,\n): CompilePass[] {\n const { sourcePath, agents } = agentDefs;\n\n if (installations.project) {\n return [\n {\n label: \"Project\",\n projectDir: cwd,\n installation: installations.project,\n sourcePath,\n agents,\n ...(installations.hasBoth && { scopeFilter: \"project\" as const }),\n },\n ];\n }\n\n if (installations.global) {\n return [\n {\n label: \"Global\",\n projectDir: os.homedir(),\n installation: installations.global,\n sourcePath,\n agents,\n },\n ];\n }\n\n return [];\n}\n\nfunction formatDiscoveryMessage(result: DiscoveredSkills): string {\n const { totalSkillCount, pluginSkillCount } = result;\n const localCount = totalSkillCount - pluginSkillCount;\n\n if (pluginSkillCount > 0 && localCount > 0) {\n return `Discovered ${totalSkillCount} skills (${pluginSkillCount} from plugins, ${localCount} local)`;\n }\n\n return pluginSkillCount > 0\n ? `Discovered ${pluginSkillCount} skills from plugins`\n : `Discovered ${totalSkillCount} local skills`;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/compile.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport os from \"os\";\nimport { unique } from \"remeda\";\nimport { BaseCommand } from \"../base-command\";\nimport { setVerbose, verbose } from \"../utils/logger\";\nimport {\n detectBothInstallations,\n type BothInstallations,\n loadAgentDefs,\n type AgentDefs,\n compileAgents,\n discoverInstalledSkills,\n type DiscoveredSkills,\n} from \"../lib/operations\";\nimport {\n ConfigLoadError,\n effectivelyExcludedSkillIds,\n isActiveAt,\n loadProjectConfig,\n loadProjectConfigFromDir,\n resolveSource,\n} from \"../lib/configuration\";\nimport { getStackSkillIds, resolveAgentConfigToSkills } from \"../lib/stacks\";\nimport { loadSkillsMatrixFromSource, type UnusableSkillMetadata } from \"../lib/loading\";\nimport { CLI_INVOKE_COMMAND, STANDARD_FILES } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport {\n ERROR_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n configTypesRefreshFailed,\n globalScopedAgentsHint,\n recompileSummary,\n registeredProjectUpdateSkipped,\n scopeBlockedStackAssignment,\n skillMetadataUnusableDetail,\n skillMetadataUnusableError,\n} from \"../utils/messages\";\nimport { reconcileTypesFromDisk, type GateReport } from \"../lib/config-gate/index.js\";\nimport type { Installation } from \"../lib/installation\";\nimport type { SkillScope } from \"../types/config\";\nimport type {\n AgentDefinition,\n AgentName,\n ProjectConfig,\n SkillDefinitionMap,\n SkillId,\n StackAgentConfig,\n} from \"../types\";\n\nexport default class Compile extends BaseCommand {\n static summary = \"Compile agents using local skills and agent definitions\";\n\n static description =\n \"Compile agents with resolved skill references. Compiles to the Claude plugin directory.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --verbose\",\n ];\n\n static flags = {\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Compile);\n setVerbose(flags.verbose);\n const cwd = process.cwd();\n\n const installations = await this.detectInstallations(cwd);\n await this.resolveAndLogSource(cwd);\n const agentDefs = await this.loadAgentDefsOrFail(cwd);\n await this.runCompilePasses(installations, agentDefs, cwd);\n }\n\n private async detectInstallations(cwd: string): Promise<BothInstallations> {\n let installations: BothInstallations;\n try {\n installations = await detectBothInstallations(cwd);\n } catch (error) {\n // A corrupt config (file present but unparseable) must not let compile run\n // config-less — that resurrects every deselected agent. Hard-error naming\n // the offending file before any compilation happens.\n if (error instanceof ConfigLoadError) {\n this.error(error.message, { exit: EXIT_CODES.ERROR });\n }\n throw error;\n }\n\n if (!installations.global && !installations.project) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n return installations;\n }\n\n /**\n * Names where the source came from — the project's own config first, then the global\n * one, then the default. `compile` takes no `--source`: it recompiles an installation\n * that already recorded which marketplace its skill references answer to, and reading\n * a different one would write agents against a catalogue config.ts does not name.\n */\n private async resolveAndLogSource(projectDir: string): Promise<void> {\n this.log(STATUS_MESSAGES.RESOLVING_SOURCE);\n try {\n const sourceConfig = await resolveSource({ caller: \"stored\", projectDir });\n this.log(`Source: ${sourceConfig.sourceOrigin}`);\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_RESOLVE_SOURCE);\n this.handleError(error);\n }\n }\n\n private async loadAgentDefsOrFail(cwd: string): Promise<AgentDefs> {\n this.log(STATUS_MESSAGES.LOADING_AGENT_PARTIALS);\n try {\n const defs = await loadAgentDefs({ projectDir: cwd });\n this.log(\"Agent partials loaded\");\n verbose(` Agents: ${defs.agentSourcePaths.agentsDir}`);\n verbose(` Templates: ${defs.agentSourcePaths.templatesDir}`);\n return defs;\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_LOAD_AGENT_PARTIALS);\n this.handleError(error);\n }\n }\n\n private async runCompilePasses(\n installations: BothInstallations,\n agentDefs: AgentDefs,\n cwd: string,\n ): Promise<void> {\n const passes = buildCompilePasses(installations, cwd, agentDefs);\n\n let totalPassesWithSkills = 0;\n for (const pass of passes) {\n const hadSkills = await this.runCompilePass(pass, cwd);\n if (hadSkills) totalPassesWithSkills++;\n }\n\n if (totalPassesWithSkills === 0) {\n this.error(\n `No skills found. Add skills with '${CLI_INVOKE_COMMAND} add <skill>' or create in .claude/skills/.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n }\n\n /**\n * Discovers what this pass compiles from, and refuses the run when any installed\n * skill's metadata.yaml exists but describes no skill — before a count is printed,\n * an agent is written or the type unions are regenerated. Skipping such a skill is\n * what the config-types pass already does; loading it anyway is what this pass\n * used to do, so a single run both loaded and skipped the same file.\n */\n private async discoverAllSkills(projectDir: string): Promise<DiscoveredSkills> {\n this.log(STATUS_MESSAGES.DISCOVERING_SKILLS);\n const result = await discoverInstalledSkills(projectDir);\n if (result.unusableMetadata.length > 0) {\n this.refuseUnusableSkillMetadata(result.unusableMetadata);\n }\n if (result.totalSkillCount === 0) return result;\n this.log(formatDiscoveryMessage(result));\n return result;\n }\n\n /**\n * Names each offending file and its reason, then exits. The detail is LOGGED and\n * only the refusal is raised: oclif hard-wraps error text at the terminal width,\n * and a path broken across two lines is one nobody can copy.\n */\n private refuseUnusableSkillMetadata(entries: UnusableSkillMetadata[]): never {\n for (const entry of entries) {\n this.log(skillMetadataUnusableDetail(entry));\n }\n this.error(skillMetadataUnusableError(entries), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * A stack skill that is not among the discovered skills is dropped from every\n * agent that references it. The resolver only records that at verbose level, so\n * the default output would claim a successful recompile of an agent that no\n * longer matches config.ts. Name each dropped skill instead.\n */\n private async warnUnresolvedStackSkills(\n projectDir: string,\n allSkills: SkillDefinitionMap,\n ): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n const excludedIds = effectivelyExcludedSkillIds(loaded.config.skills);\n const unresolved = getStackSkillIds(loaded.config.stack).filter(\n (id) => !excludedIds.has(id) && !(id in allSkills),\n );\n\n for (const id of unresolved) {\n this.warn(\n `Skill '${id}' is configured but was not found — agents will be compiled without it.`,\n );\n }\n }\n\n /**\n * `config.ts` is the hand-editable half of the pair, so it can declare a pair the scope\n * rule forbids: a GLOBAL sub-agent whose stack carries a PROJECT-scoped skill. The\n * compile-time filter in `buildCompileAgents` drops that reference on the way to the\n * resolver and `compile` rewrites nothing in `config.ts`, so the row survives and is\n * dropped again on every future run — while the recompile summary reports a clean pass\n * over an agent that no longer carries what its own config says it does.\n *\n * The sibling of {@link warnUnresolvedStackSkills} one layer over: there the skill is\n * missing from disk, here it is present and unreachable from that sub-agent.\n */\n private async warnScopeDroppedStackPairs(projectDir: string): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n for (const [skillId, agentNames] of findScopeDroppedStackPairs(loaded.config)) {\n this.warn(scopeBlockedStackAssignment(agentNames, skillId));\n }\n }\n\n /**\n * The project pass compiled no agents, but the project config may still declare\n * global-scope agents whose stack lives in the global config. Without a pointer\n * the \"No agents to recompile\" line reads as a silent no-op after a global stack\n * change, so name the global context and the count.\n */\n private async hintGlobalScopedAgents(projectDir: string): Promise<void> {\n const loaded = await loadProjectConfigFromDir(projectDir);\n if (!loaded) return;\n\n const globalAgentCount = loaded.config.agents.filter(\n (agent) => !agent.excluded && agent.scope === \"global\",\n ).length;\n if (globalAgentCount === 0) return;\n\n this.log(globalScopedAgentsHint(globalAgentCount));\n }\n\n /**\n * The documented hand-edit workflow is \"edit config.ts, then run compile\", and\n * the type unions in config-types.ts are derived from config.ts — so a compile\n * pass that leaves them untouched strands stale unions after a hand-edit.\n * Regenerates them from the scope's persisted config exactly as the wizard\n * write path would: standalone narrowed unions at global scope, import-and-\n * extend at project scope. `matrixOnly` keeps the default-source path offline.\n * A failed refresh downgrades to a warning — the compiled agents are already\n * written and remain valid; only the type unions may still be stale.\n *\n * `skipExtraSources: true` is NOT a divergence from the wizard's full\n * multi-source load: extra-source loading only annotates each skill's\n * `availableSources`/`activeSource` for wizard UI tagging — it never adds\n * skills or categories to the matrix, and the config-types writer never reads\n * those annotations, so the emitted types are byte-identical either way\n * (pinned by the skipExtraSources parity test in local-installer.test.ts).\n * Skipping avoids fetching every registered extra source (network on a cold\n * cache, plus unreachable-remote warnings) on this offline compile path.\n */\n private async refreshConfigTypes(pass: CompilePass, cwd: string): Promise<void> {\n let report: GateReport;\n try {\n const loaded = await loadProjectConfigFromDir(pass.projectDir);\n if (!loaded) {\n verbose(\n `No config found at ${pass.projectDir} — skipping ${STANDARD_FILES.CONFIG_TYPES_TS} refresh`,\n );\n return;\n }\n\n const { matrix } = await loadSkillsMatrixFromSource({\n projectDir: pass.projectDir,\n skipExtraSources: true,\n matrixOnly: true,\n });\n // `cwd` is excluded from the fan-out, which only a global pass can perform:\n // whatever this invocation was run from is this command's own subject, so a\n // fan-out must never reach back into it.\n report = await reconcileTypesFromDisk(\n pass.projectDir,\n loaded.config,\n { matrix, agents: pass.agents },\n { currentProjectDir: cwd },\n );\n this.log(INFO_MESSAGES.CONFIG_TYPES_REFRESHED);\n } catch (error) {\n this.warn(configTypesRefreshFailed(getErrorMessage(error)));\n return;\n }\n\n this.reportPropagation(report);\n }\n\n /**\n * Renders the fan-out the refresh above performed. Kept out of the refresh's\n * catch on purpose: a project the fan-out could not reach is reported as that,\n * not as a failure to refresh the type unions — which did succeed.\n */\n private reportPropagation(report: GateReport): void {\n for (const skippedPath of report.propagated.skipped) {\n this.warn(registeredProjectUpdateSkipped(skippedPath));\n }\n this.reportPropagatedRecompile(report);\n }\n\n private async runCompilePass(params: CompilePass, cwd: string): Promise<boolean> {\n const { label, projectDir, installation, sourcePath, scopeFilter } = params;\n\n this.log(\"\");\n this.log(`Compiling ${label.toLowerCase()} agents...`);\n this.log(\"\");\n\n verbose(` Project: ${projectDir}`);\n verbose(` Agents: ${installation.agentsDir}`);\n\n const { allSkills, totalSkillCount } = await this.discoverAllSkills(projectDir);\n\n if (totalSkillCount === 0) {\n this.log(`No skills found for ${label.toLowerCase()} pass, skipping`);\n // The config loads independently of discovered skills: a hand-edited\n // config.ts can list skills while nothing is installed for this scope,\n // and its type unions must follow the config rather than stay stale.\n await this.refreshConfigTypes(params, cwd);\n return false;\n }\n\n await this.warnUnresolvedStackSkills(projectDir, allSkills);\n await this.warnScopeDroppedStackPairs(projectDir);\n\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n try {\n const recompileResult = await compileAgents({\n projectDir,\n sourcePath,\n skills: allSkills,\n pluginDir: projectDir,\n outputDir: installation.agentsDir,\n ...(scopeFilter !== undefined && { scopeFilter }),\n });\n\n const { compiled, rewritten, failed, warnings } = recompileResult;\n const summary = recompileSummary(\n rewritten.length,\n compiled.length - rewritten.length,\n `${label.toLowerCase()} agents`,\n );\n\n if (failed.length > 0) {\n this.log(`${summary} (${failed.length} failed)`);\n for (const warning of warnings) {\n this.warn(warning);\n }\n } else if (compiled.length > 0) {\n this.log(summary);\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n if (label === \"Project\") {\n await this.hintGlobalScopedAgents(projectDir);\n }\n }\n\n if (compiled.length > 0) {\n verbose(` Compiled: ${compiled.join(\", \")}`);\n }\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_COMPILE_AGENTS);\n this.handleError(error);\n }\n\n await this.refreshConfigTypes(params, cwd);\n\n this.log(\"\");\n this.logSuccess(`${label} compile complete!`);\n this.log(\"\");\n\n return true;\n }\n}\n\ntype CompilePass = {\n label: \"Global\" | \"Project\";\n projectDir: string;\n installation: Installation;\n sourcePath: string;\n agents: Partial<Record<AgentName, AgentDefinition>>;\n scopeFilter?: SkillScope;\n};\n\n/**\n * The single pass this invocation owns.\n *\n * A compile run inside a project is a PROJECT-scope operation and writes nothing\n * outside that project: it compiles the project's own agents and refreshes the\n * project's own type unions, and never the global install's or another\n * registered project's. Propagation is a global operation's consequence — the\n * global config is what every project's config inlines — and a project compile\n * is not one.\n *\n * The global pass is therefore reached only where no project installation is in\n * play: at the home directory (where `detectBothInstallations` returns no\n * project by construction), or in a directory that has no config of its own, so\n * the global install is the only thing there is to compile.\n *\n * `scopeFilter` still narrows the project pass whenever both installations\n * exist: the project's config inlines the global entries, so an unfiltered pass\n * would compile global-scoped agents into the project's own agents directory.\n */\nfunction buildCompilePasses(\n installations: BothInstallations,\n cwd: string,\n agentDefs: AgentDefs,\n): CompilePass[] {\n const { sourcePath, agents } = agentDefs;\n\n if (installations.project) {\n return [\n {\n label: \"Project\",\n projectDir: cwd,\n installation: installations.project,\n sourcePath,\n agents,\n ...(installations.hasBoth && { scopeFilter: \"project\" as const }),\n },\n ];\n }\n\n if (installations.global) {\n return [\n {\n label: \"Global\",\n projectDir: os.homedir(),\n installation: installations.global,\n sourcePath,\n agents,\n },\n ];\n }\n\n return [];\n}\n\n/**\n * Every project-scoped skill that a GLOBAL sub-agent's stack assigns to itself, with the\n * sub-agents that assign it — exactly the pairs `buildCompileAgents`' scope filter drops on\n * the way to the resolver.\n *\n * Grouped by skill rather than emitted per pair, so one sentence accounts for every\n * sub-agent one skill was kept away from.\n */\nfunction findScopeDroppedStackPairs(config: ProjectConfig): [SkillId, AgentName[]][] {\n const stack = config.stack ?? {};\n const globalAgentNames = config.agents\n .filter((agent) => isActiveAt(agent, \"global\"))\n .map((agent) => agent.name);\n const projectScopedIds = unique(\n config.skills.filter((skill) => isActiveAt(skill, \"project\")).map((skill) => skill.id),\n );\n\n return projectScopedIds\n .map((skillId): [SkillId, AgentName[]] => [\n skillId,\n globalAgentNames.filter((agentName) => stackAssignsSkill(stack[agentName], skillId)),\n ])\n .filter(([, agentNames]) => agentNames.length > 0);\n}\n\n/** True when this sub-agent's stack names the skill, in any of its categories. */\nfunction stackAssignsSkill(agentStack: StackAgentConfig | undefined, skillId: SkillId): boolean {\n if (!agentStack) return false;\n return resolveAgentConfigToSkills(agentStack).some((ref) => ref.id === skillId);\n}\n\nfunction formatDiscoveryMessage(result: DiscoveredSkills): string {\n const { totalSkillCount, pluginSkillCount } = result;\n const localCount = totalSkillCount - pluginSkillCount;\n\n if (pluginSkillCount > 0 && localCount > 0) {\n return `Discovered ${totalSkillCount} skills (${pluginSkillCount} from plugins, ${localCount} local)`;\n }\n\n return pluginSkillCount > 0\n ? `Discovered ${pluginSkillCount} skills from plugins`\n : `Discovered ${totalSkillCount} local skills`;\n}\n"],"mappings":"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","names":[]}
@@ -2,19 +2,19 @@
2
2
  import {
3
3
  detectProject,
4
4
  loadSource
5
- } from "../chunk-F7Z5I6GU.js";
6
- import "../chunk-REKOWTIB.js";
7
- import "../chunk-NXGMM5YN.js";
8
- import "../chunk-FRWKCE6R.js";
5
+ } from "../chunk-XMEIVWAS.js";
6
+ import "../chunk-ZU6DAR4S.js";
7
+ import "../chunk-UW44KSYL.js";
8
+ import "../chunk-PRJD5MMQ.js";
9
9
  import {
10
10
  filterExcludedEntries,
11
11
  listAgentMdFiles
12
- } from "../chunk-FIHTAFST.js";
12
+ } from "../chunk-TUQF577Z.js";
13
13
  import {
14
14
  BaseCommand,
15
15
  EXIT_CODES
16
- } from "../chunk-X5XJ6WKO.js";
17
- import "../chunk-TY6CAOL7.js";
16
+ } from "../chunk-FMYHWKGG.js";
17
+ import "../chunk-7VZV4O6B.js";
18
18
  import "../chunk-K3O3YQYG.js";
19
19
  import {
20
20
  checkMatrixHealth,
@@ -46,7 +46,7 @@ import {
46
46
  validatePlugin,
47
47
  validateProjectConfig,
48
48
  validateSkillFrontmatter
49
- } from "../chunk-NXQAY5U7.js";
49
+ } from "../chunk-CBF4ZYV3.js";
50
50
  import {
51
51
  agentYamlGenerationSchema,
52
52
  directoryExists,
@@ -66,10 +66,10 @@ import {
66
66
  stackConfigValidationSchema,
67
67
  stacksConfigSchema,
68
68
  validateSkillMetadata
69
- } from "../chunk-U2YSGBHA.js";
69
+ } from "../chunk-4VCWL2IG.js";
70
70
  import {
71
71
  matrix
72
- } from "../chunk-35VOK7XE.js";
72
+ } from "../chunk-IPJOMAWC.js";
73
73
  import "../chunk-VASLW636.js";
74
74
  import {
75
75
  CLAUDE_SRC_DIR,
@@ -4,28 +4,28 @@ import {
4
4
  } from "../chunk-ZBPEFQ4G.js";
5
5
  import {
6
6
  runWizardSession
7
- } from "../chunk-KET3EVGX.js";
8
- import "../chunk-BMGBA6HJ.js";
9
- import "../chunk-M5HSTNYU.js";
7
+ } from "../chunk-QUDQTO3O.js";
8
+ import "../chunk-R7JV22QK.js";
9
+ import "../chunk-MJFIO5SX.js";
10
10
  import "../chunk-NSJ2S7R5.js";
11
11
  import "../chunk-JC7DBPRD.js";
12
- import "../chunk-K7PJDWER.js";
13
- import "../chunk-WDAO3RUY.js";
14
- import "../chunk-R4SEU3DF.js";
15
- import "../chunk-VECFAKM5.js";
16
- import "../chunk-VGEBYCQZ.js";
17
- import "../chunk-U2DNAHFE.js";
18
- import "../chunk-WG6V6VJV.js";
19
- import "../chunk-EFU6P3B7.js";
12
+ import "../chunk-GUDGCFSF.js";
13
+ import "../chunk-BZ4CZBOM.js";
14
+ import "../chunk-NKCY2ULI.js";
15
+ import "../chunk-NFH6SA62.js";
16
+ import "../chunk-IXEDSKMH.js";
17
+ import "../chunk-AURY6RT6.js";
18
+ import "../chunk-WRRP47PY.js";
19
+ import "../chunk-2IMYK4WN.js";
20
20
  import "../chunk-TSIU7DME.js";
21
21
  import "../chunk-XVAQG2CV.js";
22
- import "../chunk-ZNDLUWWD.js";
22
+ import "../chunk-LA3JPESW.js";
23
23
  import "../chunk-J27W6TXS.js";
24
- import "../chunk-4VYALFQZ.js";
25
- import "../chunk-JFAUQDZM.js";
26
- import "../chunk-IO4VEW5U.js";
24
+ import "../chunk-AKQ5QISO.js";
25
+ import "../chunk-CHNA5RVS.js";
26
+ import "../chunk-ONWEOS77.js";
27
27
  import "../chunk-V3ENMW7G.js";
28
- import "../chunk-2HC2SNRP.js";
28
+ import "../chunk-DRKSYJZ2.js";
29
29
  import "../chunk-Q5FLW4JG.js";
30
30
  import "../chunk-6CNRMCFM.js";
31
31
  import {
@@ -33,30 +33,31 @@ import {
33
33
  detectProject,
34
34
  loadSource,
35
35
  writeProjectConfig
36
- } from "../chunk-F7Z5I6GU.js";
36
+ } from "../chunk-XMEIVWAS.js";
37
37
  import {
38
38
  discoverInstalledSkills,
39
+ removeCompiledAgents,
39
40
  uninstallPluginSkills
40
- } from "../chunk-REKOWTIB.js";
41
+ } from "../chunk-ZU6DAR4S.js";
41
42
  import {
42
43
  copyLocalSkills
43
- } from "../chunk-NXGMM5YN.js";
44
+ } from "../chunk-UW44KSYL.js";
44
45
  import {
45
46
  loadAgentDefs
46
- } from "../chunk-FRWKCE6R.js";
47
- import "../chunk-FIHTAFST.js";
48
- import "../chunk-ACKC577F.js";
47
+ } from "../chunk-PRJD5MMQ.js";
48
+ import "../chunk-TUQF577Z.js";
49
+ import "../chunk-B66SC72V.js";
49
50
  import {
50
51
  render
51
52
  } from "../chunk-JFLVEFFP.js";
52
53
  import {
53
54
  formatScopeTag
54
- } from "../chunk-HEBPKK5L.js";
55
+ } from "../chunk-QQTYMW7N.js";
55
56
  import {
56
57
  BaseCommand,
57
58
  EXIT_CODES
58
- } from "../chunk-X5XJ6WKO.js";
59
- import "../chunk-TY6CAOL7.js";
59
+ } from "../chunk-FMYHWKGG.js";
60
+ import "../chunk-7VZV4O6B.js";
60
61
  import "../chunk-K3O3YQYG.js";
61
62
  import {
62
63
  ERROR_MESSAGES,
@@ -76,22 +77,22 @@ import {
76
77
  installBaseDir,
77
78
  isActiveAt,
78
79
  isHomeDirectory,
80
+ localSkillsCopied,
79
81
  migrateLocalSkillScope,
80
82
  mutateGlobal,
81
83
  recompileSummary,
82
84
  resolveInstallPaths,
83
85
  toClaudePluginScope,
84
86
  unresolvedSkillRemovalReasons
85
- } from "../chunk-NXQAY5U7.js";
87
+ } from "../chunk-CBF4ZYV3.js";
86
88
  import {
87
- getErrorMessage,
88
- remove
89
- } from "../chunk-U2YSGBHA.js";
89
+ getErrorMessage
90
+ } from "../chunk-4VCWL2IG.js";
90
91
  import {
91
92
  getSkillById,
92
93
  getSkillDisplayName,
93
94
  matrix
94
- } from "../chunk-35VOK7XE.js";
95
+ } from "../chunk-IPJOMAWC.js";
95
96
  import {
96
97
  typedKeys
97
98
  } from "../chunk-VASLW636.js";
@@ -160,12 +161,7 @@ var Edit = class _Edit extends BaseCommand {
160
161
  const { flags } = await this.parse(_Edit);
161
162
  const cwd = process.cwd();
162
163
  await this.ensureConfigReadable(cwd);
163
- const { unmount, clear: clearSpinner } = render(
164
- /* @__PURE__ */ jsx(Spinner, { label: STATUS_MESSAGES.LOADING_SKILLS })
165
- );
166
- const context = await this.loadContext();
167
- clearSpinner();
168
- unmount();
164
+ const context = await this.loadContextUnderSpinner();
169
165
  await this.ensureSavedSkillsReadable(
170
166
  context.projectConfig?.skills ?? [],
171
167
  context.sourceResult.matrix,
@@ -227,6 +223,25 @@ var Edit = class _Edit extends BaseCommand {
227
223
  await this.cleanupStaleAgentFiles(changes, activeOldAgents, cwd);
228
224
  this.logCompletionSummary(changes);
229
225
  }
226
+ /**
227
+ * The load below, behind a spinner that comes down whichever way the await ends.
228
+ *
229
+ * The cleanup is a `finally` because all three of `loadContext`'s refusals are raised
230
+ * while this spinner is mounted, and oclif would otherwise paint its error under an Ink
231
+ * tree still repainting over it. Never a `catch`: the throw reaches oclif untouched, or
232
+ * both the error rendering and the pinned exit codes change with it.
233
+ */
234
+ async loadContextUnderSpinner() {
235
+ const { unmount, clear: clearSpinner } = render(
236
+ /* @__PURE__ */ jsx(Spinner, { label: STATUS_MESSAGES.LOADING_SKILLS })
237
+ );
238
+ try {
239
+ return await this.loadContext();
240
+ } finally {
241
+ clearSpinner();
242
+ unmount();
243
+ }
244
+ }
230
245
  async loadContext() {
231
246
  const detected = await detectProject();
232
247
  if (!detected) {
@@ -320,8 +335,16 @@ var Edit = class _Edit extends BaseCommand {
320
335
  * `executeMigration` acted on this run are rewritten, and only their `source` field. Global
321
336
  * entries this session merely displayed, re-scoped or deselected are untouched, as are
322
337
  * `marketplace`, `stack`, `agents` and every other registered project's view of them.
323
- * Refusing the switch instead is not an option — driving a global-scope migration from a
324
- * project directory is a supported flow (`scope-aware-local-copy` lifecycle tests).
338
+ *
339
+ * Driving a global-scope migration from a project directory is NOT a supported flow, and this
340
+ * method is no longer the thing that permits it. The wizard now refuses it at source: the two
341
+ * bulk install-mode keys are withdrawn, and `setInstallMode` ignores a project-context call
342
+ * against a global slot the hydration snapshot owns — the same authority the Sources grid
343
+ * already enforced by rendering that row inert. What still reaches here is the residue that
344
+ * authority leaves legitimate: a mode change committed on the project half of a `[P][G]` pair
345
+ * and then carried to global scope by a P->G collapse (`s`) in the same session. The entry is
346
+ * the project's own to configure at the moment it is configured, and global at the moment it
347
+ * is written — so the migration is real, and the global config must record it.
325
348
  *
326
349
  * Runs BEFORE `writeConfigAndCompile`, so the global config written here is the one
327
350
  * the wizard write reloads, keeps (existing wins in `mergeGlobalConfigs`) and inlines
@@ -430,6 +453,11 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
430
453
  for (const warning of migrationResult.warnings) {
431
454
  this.warn(warning);
432
455
  }
456
+ if (migrationPlan.toEject.length > 0) {
457
+ this.log(
458
+ chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(migrationResult.ejectedSkills.length))
459
+ );
460
+ }
433
461
  if (migrationPlan.toPlugin.length > 0) {
434
462
  this.reportPluginInstalls(migrationResult.pluginInstalls);
435
463
  }
@@ -519,7 +547,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
519
547
  );
520
548
  if (addedLocalSkills.length > 0) {
521
549
  const copyResult = await copyLocalSkills(addedLocalSkills, cwd, context.sourceResult);
522
- this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Copied ${copyResult.totalCopied} local skill(s)`));
550
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(copyResult.totalCopied)));
523
551
  }
524
552
  }
525
553
  async removeDeletedLocalSkills(changes, activeOldSkills, cwd) {
@@ -554,6 +582,9 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
554
582
  } catch (error) {
555
583
  this.warn(`Could not update config: ${getErrorMessage(error)}`);
556
584
  }
585
+ if (configResult) {
586
+ this.reportUnassignedSkills(configResult.config);
587
+ }
557
588
  try {
558
589
  const agentScopeMap = activeAgentScopeMap(result.agentConfigs);
559
590
  const { allSkills } = await discoverInstalledSkills(cwd);
@@ -590,26 +621,11 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
590
621
  }
591
622
  }
592
623
  async cleanupStaleAgentFiles(changes, oldAgents, cwd) {
593
- const { agentScopeChanges, removedAgents } = changes;
594
- for (const [agentName, change] of agentScopeChanges) {
595
- if (change.from === "global") continue;
596
- const oldAgentPath = path.join(
597
- resolveInstallPaths(cwd, "project").agentsDir,
598
- `${agentName}.md`
599
- );
600
- try {
601
- await remove(oldAgentPath);
602
- } catch (error) {
603
- this.warn(`Could not remove old agent file ${oldAgentPath}: ${getErrorMessage(error)}`);
604
- }
605
- }
606
- for (const agentName of removedAgents) {
607
- const oldScope = oldAgents.find((a) => a.name === agentName)?.scope ?? "project";
608
- const agentPath = path.join(resolveInstallPaths(cwd, oldScope).agentsDir, `${agentName}.md`);
609
- try {
610
- await remove(agentPath);
611
- } catch (error) {
612
- this.warn(`Could not remove agent file ${agentPath}: ${getErrorMessage(error)}`);
624
+ for (const removal of planStaleAgentRemovals(changes, oldAgents, cwd)) {
625
+ const { failed } = await removeCompiledAgents(removal);
626
+ for (const { name, error } of failed) {
627
+ const agentPath = path.join(removal.agentsDir, `${name}.md`);
628
+ this.warn(`Could not remove agent file ${agentPath}: ${error}`);
613
629
  }
614
630
  }
615
631
  }
@@ -688,6 +704,24 @@ function detectDualScopeTransitions(scopeChanges, fullNew, fullOld, getKey) {
688
704
  }
689
705
  return result;
690
706
  }
707
+ var STALE_AGENT_SCOPES = ["project", "global"];
708
+ var UNRECORDED_AGENT_SCOPE = "project";
709
+ function installedScope(name, oldAgents) {
710
+ return oldAgents.find((agent) => agent.name === name)?.scope ?? UNRECORDED_AGENT_SCOPE;
711
+ }
712
+ function planStaleAgentRemovals(changes, oldAgents, cwd) {
713
+ const supersededByGlobal = [...changes.agentScopeChanges].filter(([, change]) => change.from !== "global").map(([name]) => ({ name, scope: "project" }));
714
+ const deselected = changes.removedAgents.map((name) => ({
715
+ name,
716
+ scope: installedScope(name, oldAgents)
717
+ }));
718
+ const stale = [...supersededByGlobal, ...deselected];
719
+ const removalAtScope = (scope) => ({
720
+ agentsDir: resolveInstallPaths(cwd, scope).agentsDir,
721
+ agents: stale.filter((agent) => agent.scope === scope).map((agent) => agent.name)
722
+ });
723
+ return STALE_AGENT_SCOPES.map(removalAtScope).filter((removal) => removal.agents.length > 0);
724
+ }
691
725
  function hasAnyChanges(changes) {
692
726
  return changes.addedSkills.length > 0 || changes.removedSkills.length > 0 || changes.addedAgents.length > 0 || changes.removedAgents.length > 0 || changes.sourceChanges.size > 0 || changes.scopeChanges.size > 0 || changes.agentScopeChanges.size > 0;
693
727
  }