@agents-inc/cli 0.41.1 → 0.42.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 (168) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-ZLHGJSRK.js → chunk-2TWELY5M.js} +3 -3
  4. package/dist/{chunk-4UTPJXUX.js → chunk-33D24DAF.js} +22 -54
  5. package/dist/chunk-33D24DAF.js.map +1 -0
  6. package/dist/{chunk-UKTYDNWJ.js → chunk-44QCEK7E.js} +5 -5
  7. package/dist/chunk-44QCEK7E.js.map +1 -0
  8. package/dist/{chunk-NYP5SB2V.js → chunk-52SI5XJH.js} +2 -2
  9. package/dist/{chunk-GEDWVX6Y.js → chunk-53K3URKF.js} +8 -8
  10. package/dist/chunk-53K3URKF.js.map +1 -0
  11. package/dist/{chunk-2D6LKRHW.js → chunk-ALWLM5MC.js} +2 -2
  12. package/dist/{chunk-AVVYFEMF.js → chunk-AQANPOLS.js} +2 -2
  13. package/dist/{chunk-5TMB53BV.js → chunk-BKW34TKI.js} +7 -4
  14. package/dist/chunk-BKW34TKI.js.map +1 -0
  15. package/dist/{chunk-BFISETQG.js → chunk-EFZN22TO.js} +3 -3
  16. package/dist/{chunk-7FBM7V3E.js → chunk-EPJ2GJNJ.js} +10 -10
  17. package/dist/chunk-EPJ2GJNJ.js.map +1 -0
  18. package/dist/{chunk-SILUTTV7.js → chunk-FDY6SGSA.js} +2 -2
  19. package/dist/{chunk-342YB6TQ.js → chunk-FF4Z7MHY.js} +20 -13
  20. package/dist/chunk-FF4Z7MHY.js.map +1 -0
  21. package/dist/{chunk-ACVJVYMC.js → chunk-GCN7GGWE.js} +15 -27
  22. package/dist/chunk-GCN7GGWE.js.map +1 -0
  23. package/dist/{chunk-FHBICUXB.js → chunk-GIZ6DENW.js} +4 -4
  24. package/dist/{chunk-KC2SIUIA.js → chunk-GVRZY5KI.js} +4 -5
  25. package/dist/chunk-GVRZY5KI.js.map +1 -0
  26. package/dist/{chunk-LJRP4SWY.js → chunk-HMGWGWFT.js} +2 -2
  27. package/dist/{chunk-H6H3COI5.js → chunk-IUYU2TP6.js} +5 -5
  28. package/dist/{chunk-AH7XHAKN.js → chunk-J73KIP6Z.js} +2 -2
  29. package/dist/chunk-J73KIP6Z.js.map +1 -0
  30. package/dist/{chunk-TJAZ7QCF.js → chunk-KA253GGY.js} +4 -4
  31. package/dist/{chunk-4SYXPG7L.js → chunk-MHET2RG2.js} +8 -3
  32. package/dist/chunk-MHET2RG2.js.map +1 -0
  33. package/dist/{chunk-DV4ALU5I.js → chunk-MI4NWOWD.js} +17 -24
  34. package/dist/chunk-MI4NWOWD.js.map +1 -0
  35. package/dist/chunk-MMD26LKJ.js +20 -0
  36. package/dist/chunk-MMD26LKJ.js.map +1 -0
  37. package/dist/{chunk-MNPPGIZQ.js → chunk-ORJPGZVD.js} +5 -5
  38. package/dist/{chunk-R52N7DBG.js → chunk-PEAPABFI.js} +4 -4
  39. package/dist/chunk-PEAPABFI.js.map +1 -0
  40. package/dist/{chunk-BK7TANUV.js → chunk-PP7NDFFE.js} +4 -3
  41. package/dist/{chunk-BK7TANUV.js.map → chunk-PP7NDFFE.js.map} +1 -1
  42. package/dist/{chunk-TTXV55NQ.js → chunk-SYHRJG5G.js} +6 -3
  43. package/dist/chunk-SYHRJG5G.js.map +1 -0
  44. package/dist/{chunk-NZYKDVRL.js → chunk-UVVNWF43.js} +2 -2
  45. package/dist/{chunk-NZYKDVRL.js.map → chunk-UVVNWF43.js.map} +1 -1
  46. package/dist/{chunk-XJXJZ2MJ.js → chunk-UXNHU7Y7.js} +5 -1
  47. package/dist/chunk-UXNHU7Y7.js.map +1 -0
  48. package/dist/{chunk-YLJYAQSG.js → chunk-VHGIQN5O.js} +7 -5
  49. package/dist/chunk-VHGIQN5O.js.map +1 -0
  50. package/dist/{chunk-4LT6RXMY.js → chunk-WMAALRQI.js} +4 -4
  51. package/dist/{chunk-PURJZ72D.js → chunk-X34RGEFX.js} +2 -2
  52. package/dist/{chunk-423MJ6DT.js → chunk-XRA4LHTJ.js} +5 -5
  53. package/dist/chunk-ZHJEZ7AU.js +40 -0
  54. package/dist/chunk-ZHJEZ7AU.js.map +1 -0
  55. package/dist/commands/build/marketplace.js +3 -3
  56. package/dist/commands/build/plugins.js +5 -5
  57. package/dist/commands/build/stack.js +5 -5
  58. package/dist/commands/compile.js +6 -6
  59. package/dist/commands/config/get.js +4 -4
  60. package/dist/commands/config/index.js +5 -5
  61. package/dist/commands/config/path.js +4 -4
  62. package/dist/commands/config/set-project.js +4 -4
  63. package/dist/commands/config/show.js +5 -5
  64. package/dist/commands/config/unset-project.js +4 -4
  65. package/dist/commands/diff.js +4 -4
  66. package/dist/commands/doctor.js +4 -4
  67. package/dist/commands/edit.js +37 -30
  68. package/dist/commands/edit.js.map +1 -1
  69. package/dist/commands/eject.js +33 -13
  70. package/dist/commands/eject.js.map +1 -1
  71. package/dist/commands/import/skill.js +5 -5
  72. package/dist/commands/info.js +5 -5
  73. package/dist/commands/init.js +27 -27
  74. package/dist/commands/list.js +4 -4
  75. package/dist/commands/new/agent.js +5 -5
  76. package/dist/commands/new/skill.js +4 -4
  77. package/dist/commands/outdated.js +4 -4
  78. package/dist/commands/search.js +7 -7
  79. package/dist/commands/uninstall.js +6 -6
  80. package/dist/commands/update.js +6 -6
  81. package/dist/commands/validate.js +5 -5
  82. package/dist/commands/version/bump.js +4 -4
  83. package/dist/commands/version/index.js +4 -4
  84. package/dist/commands/version/set.js +4 -4
  85. package/dist/commands/version/show.js +4 -4
  86. package/dist/components/skill-search/skill-search.js +3 -3
  87. package/dist/components/wizard/category-grid.js +2 -2
  88. package/dist/components/wizard/category-grid.test.js +2 -2
  89. package/dist/components/wizard/checkbox-grid.js +3 -2
  90. package/dist/components/wizard/checkbox-grid.test.js +16 -22
  91. package/dist/components/wizard/checkbox-grid.test.js.map +1 -1
  92. package/dist/components/wizard/domain-selection.js +8 -7
  93. package/dist/components/wizard/help-modal.js +2 -2
  94. package/dist/components/wizard/menu-item.js +25 -4
  95. package/dist/components/wizard/menu-item.js.map +1 -1
  96. package/dist/components/wizard/search-modal.js +2 -2
  97. package/dist/components/wizard/search-modal.test.js +2 -2
  98. package/dist/components/wizard/section-progress.js +2 -2
  99. package/dist/components/wizard/section-progress.test.js +2 -2
  100. package/dist/components/wizard/selection-card.js +10 -0
  101. package/dist/components/wizard/source-grid.js +3 -3
  102. package/dist/components/wizard/source-grid.test.js +3 -3
  103. package/dist/components/wizard/stack-selection.js +8 -8
  104. package/dist/components/wizard/step-agents.js +7 -6
  105. package/dist/components/wizard/step-agents.test.js +8 -8
  106. package/dist/components/wizard/step-agents.test.js.map +1 -1
  107. package/dist/components/wizard/step-build.js +7 -7
  108. package/dist/components/wizard/step-build.test.js +18 -18
  109. package/dist/components/wizard/step-build.test.js.map +1 -1
  110. package/dist/components/wizard/step-confirm.js +3 -2
  111. package/dist/components/wizard/step-confirm.test.js +7 -6
  112. package/dist/components/wizard/step-confirm.test.js.map +1 -1
  113. package/dist/components/wizard/step-refine.js +2 -2
  114. package/dist/components/wizard/step-refine.test.js +2 -2
  115. package/dist/components/wizard/step-settings.js +5 -5
  116. package/dist/components/wizard/step-settings.test.js +8 -8
  117. package/dist/components/wizard/step-sources.js +10 -9
  118. package/dist/components/wizard/step-sources.test.js +14 -12
  119. package/dist/components/wizard/step-sources.test.js.map +1 -1
  120. package/dist/components/wizard/step-stack.js +11 -11
  121. package/dist/components/wizard/step-stack.test.js +15 -16
  122. package/dist/components/wizard/step-stack.test.js.map +1 -1
  123. package/dist/components/wizard/view-title.js +2 -2
  124. package/dist/components/wizard/wizard-layout.js +8 -8
  125. package/dist/components/wizard/wizard-tabs.js +2 -2
  126. package/dist/components/wizard/wizard-tabs.test.js +2 -2
  127. package/dist/components/wizard/wizard.js +24 -24
  128. package/dist/hooks/init.js +3 -3
  129. package/dist/{source-manager-PPABS6BC.js → source-manager-ABK5COKX.js} +4 -4
  130. package/dist/source-manager-ABK5COKX.js.map +1 -0
  131. package/dist/stores/wizard-store.js +5 -5
  132. package/dist/stores/wizard-store.test.js +6 -6
  133. package/package.json +1 -1
  134. package/src/schemas/project-config.schema.json +7 -0
  135. package/dist/chunk-342YB6TQ.js.map +0 -1
  136. package/dist/chunk-4SYXPG7L.js.map +0 -1
  137. package/dist/chunk-4UTPJXUX.js.map +0 -1
  138. package/dist/chunk-5TMB53BV.js.map +0 -1
  139. package/dist/chunk-7FBM7V3E.js.map +0 -1
  140. package/dist/chunk-ACVJVYMC.js.map +0 -1
  141. package/dist/chunk-AH7XHAKN.js.map +0 -1
  142. package/dist/chunk-DV4ALU5I.js.map +0 -1
  143. package/dist/chunk-GEDWVX6Y.js.map +0 -1
  144. package/dist/chunk-KC2SIUIA.js.map +0 -1
  145. package/dist/chunk-KXM7KOPE.js +0 -31
  146. package/dist/chunk-KXM7KOPE.js.map +0 -1
  147. package/dist/chunk-R52N7DBG.js.map +0 -1
  148. package/dist/chunk-TTXV55NQ.js.map +0 -1
  149. package/dist/chunk-UKTYDNWJ.js.map +0 -1
  150. package/dist/chunk-WS6OQIEN.js +0 -32
  151. package/dist/chunk-WS6OQIEN.js.map +0 -1
  152. package/dist/chunk-XJXJZ2MJ.js.map +0 -1
  153. package/dist/chunk-YLJYAQSG.js.map +0 -1
  154. /package/dist/{chunk-ZLHGJSRK.js.map → chunk-2TWELY5M.js.map} +0 -0
  155. /package/dist/{chunk-NYP5SB2V.js.map → chunk-52SI5XJH.js.map} +0 -0
  156. /package/dist/{chunk-2D6LKRHW.js.map → chunk-ALWLM5MC.js.map} +0 -0
  157. /package/dist/{chunk-AVVYFEMF.js.map → chunk-AQANPOLS.js.map} +0 -0
  158. /package/dist/{chunk-BFISETQG.js.map → chunk-EFZN22TO.js.map} +0 -0
  159. /package/dist/{chunk-SILUTTV7.js.map → chunk-FDY6SGSA.js.map} +0 -0
  160. /package/dist/{chunk-FHBICUXB.js.map → chunk-GIZ6DENW.js.map} +0 -0
  161. /package/dist/{chunk-LJRP4SWY.js.map → chunk-HMGWGWFT.js.map} +0 -0
  162. /package/dist/{chunk-H6H3COI5.js.map → chunk-IUYU2TP6.js.map} +0 -0
  163. /package/dist/{chunk-TJAZ7QCF.js.map → chunk-KA253GGY.js.map} +0 -0
  164. /package/dist/{chunk-MNPPGIZQ.js.map → chunk-ORJPGZVD.js.map} +0 -0
  165. /package/dist/{chunk-4LT6RXMY.js.map → chunk-WMAALRQI.js.map} +0 -0
  166. /package/dist/{chunk-PURJZ72D.js.map → chunk-X34RGEFX.js.map} +0 -0
  167. /package/dist/{chunk-423MJ6DT.js.map → chunk-XRA4LHTJ.js.map} +0 -0
  168. /package/dist/{source-manager-PPABS6BC.js.map → components/wizard/selection-card.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/lib/configuration/source-manager.ts","../src/cli/lib/configuration/config.ts","../src/cli/utils/yaml.ts","../src/cli/lib/loading/source-fetcher.ts","../src/cli/lib/configuration/index.ts","../src/cli/lib/configuration/config-generator.ts","../src/cli/lib/loading/index.ts","../src/cli/lib/loading/loader.ts","../src/cli/lib/loading/source-loader.ts","../src/cli/lib/metadata-keys.ts","../src/cli/lib/skills/index.ts","../src/cli/lib/skills/skill-metadata.ts","../src/cli/lib/versioning.ts","../src/cli/lib/skills/skill-copier.ts","../src/cli/lib/skills/skill-plugin-compiler.ts","../src/cli/lib/plugins/index.ts","../src/cli/lib/plugins/plugin-manifest.ts","../src/cli/lib/plugins/plugin-manifest-finder.ts","../src/cli/lib/plugins/plugin-finder.ts","../src/cli/lib/plugins/plugin-info.ts","../src/cli/lib/installation/index.ts","../src/cli/lib/installation/installation.ts","../src/cli/lib/installation/local-installer.ts","../src/cli/lib/stacks/index.ts","../src/cli/lib/stacks/stacks-loader.ts","../src/cli/lib/stacks/stack-plugin-compiler.ts","../src/cli/lib/compiler.ts","../src/cli/lib/resolver.ts","../src/cli/utils/frontmatter.ts","../src/cli/lib/plugins/plugin-discovery.ts","../src/cli/lib/plugins/plugin-settings.ts","../src/cli/lib/plugins/plugin-version.ts","../src/cli/lib/plugins/plugin-validator.ts","../src/cli/lib/skills/local-skill-loader.ts","../src/cli/lib/skills/source-switcher.ts","../src/cli/lib/matrix/index.ts","../src/cli/lib/matrix/matrix-loader.ts","../src/cli/lib/matrix/matrix-resolver.ts","../src/cli/lib/matrix/matrix-health-check.ts","../src/cli/lib/loading/multi-source-loader.ts","../src/cli/lib/loading/defaults-loader.ts","../src/cli/lib/configuration/config-merger.ts","../src/cli/lib/configuration/project-config.ts","../src/cli/lib/configuration/config-saver.ts"],"sourcesContent":["import type { SourceEntry } from \"./config\";\nimport { loadProjectSourceConfig, saveProjectConfig, DEFAULT_SOURCE } from \"./config\";\nimport { fetchMarketplace } from \"../loading/source-fetcher\";\nimport { discoverLocalSkills } from \"../skills/local-skill-loader\";\nimport { discoverAllPluginSkills } from \"../plugins/plugin-discovery\";\nimport { verbose } from \"../../utils/logger\";\n\nconst DEFAULT_SOURCE_NAME = \"public\";\n\nexport type SourceSummary = {\n sources: Array<SourceEntry & { enabled: boolean }>;\n localSkillCount: number;\n pluginSkillCount: number;\n};\n\n/**\n * Add a new source to the project configuration.\n * Validates the URL by fetching the marketplace.\n */\nexport async function addSource(\n projectDir: string,\n url: string,\n): Promise<{ name: string; skillCount: number }> {\n const result = await fetchMarketplace(url, { forceRefresh: true });\n const name = result.marketplace.name;\n const skillCount = result.marketplace.plugins.length;\n\n const config = (await loadProjectSourceConfig(projectDir)) ?? {};\n const sources = config.sources ?? [];\n\n const exists = sources.some((s) => s.name === name);\n if (exists) {\n throw new Error(`Source \"${name}\" already exists`);\n }\n\n sources.push({ name, url });\n config.sources = sources;\n await saveProjectConfig(projectDir, config);\n\n verbose(`Added source \"${name}\" with ${skillCount} skills`);\n return { name, skillCount };\n}\n\n/**\n * Remove a source by name. Cannot remove \"public\" (the default).\n */\nexport async function removeSource(projectDir: string, name: string): Promise<void> {\n if (name === DEFAULT_SOURCE_NAME) {\n throw new Error(`Cannot remove the \"${DEFAULT_SOURCE_NAME}\" source`);\n }\n\n const config = (await loadProjectSourceConfig(projectDir)) ?? {};\n const sources = config.sources ?? [];\n\n const filtered = sources.filter((s) => s.name !== name);\n if (filtered.length === sources.length) {\n throw new Error(`Source \"${name}\" not found`);\n }\n\n config.sources = filtered;\n await saveProjectConfig(projectDir, config);\n\n verbose(`Removed source \"${name}\"`);\n}\n\n/**\n * Get summary of all configured sources and local/plugin counts.\n */\nexport async function getSourceSummary(projectDir: string): Promise<SourceSummary> {\n const config = (await loadProjectSourceConfig(projectDir)) ?? {};\n\n const sources: Array<SourceEntry & { enabled: boolean }> = [\n {\n name: DEFAULT_SOURCE_NAME,\n url: config.source ?? DEFAULT_SOURCE,\n enabled: true,\n },\n ];\n\n if (config.sources) {\n for (const source of config.sources) {\n sources.push({ ...source, enabled: true });\n }\n }\n\n let localSkillCount = 0;\n try {\n const localResult = await discoverLocalSkills(projectDir);\n if (localResult) {\n localSkillCount = localResult.skills.length;\n }\n } catch {\n verbose(\"Failed to discover local skills for source summary\");\n }\n\n let pluginSkillCount = 0;\n try {\n const discoveredSkills = await discoverAllPluginSkills(projectDir);\n pluginSkillCount = Object.keys(discoveredSkills).length;\n } catch {\n verbose(\"Failed to discover plugin skills for source summary\");\n }\n\n return { sources, localSkillCount, pluginSkillCount };\n}\n","import path from \"path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { writeFile, fileExists, ensureDir } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { safeLoadYamlFile } from \"../../utils/yaml\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n DEFAULT_BRANDING,\n GITHUB_SOURCE,\n SCHEMA_PATHS,\n STANDARD_FILES,\n YAML_FORMATTING,\n yamlSchemaComment,\n} from \"../../consts\";\nimport { projectSourceConfigSchema } from \"../schemas\";\nimport type { BoundSkill } from \"../../types\";\n\nexport const DEFAULT_SOURCE = `${GITHUB_SOURCE.GITHUB_PREFIX}agents-inc/skills`;\nexport const SOURCE_ENV_VAR = \"CC_SOURCE\";\nexport const PROJECT_CONFIG_FILE = STANDARD_FILES.CONFIG_YAML;\n\nexport type SourceEntry = {\n name: string;\n url: string;\n description?: string;\n ref?: string;\n};\n\n/** Branding overrides for white-labeling the CLI */\nexport type BrandingConfig = {\n /** Custom CLI name (e.g., \"Acme Dev Tools\") */\n name?: string;\n /** Custom tagline shown in wizard header */\n tagline?: string;\n};\n\nexport type ProjectSourceConfig = {\n source?: string;\n author?: string;\n marketplace?: string;\n agentsSource?: string;\n sources?: SourceEntry[];\n boundSkills?: BoundSkill[];\n /** Branding overrides for white-labeling the CLI */\n branding?: BrandingConfig;\n skillsDir?: string; // default: src/skills (SKILLS_DIR_PATH)\n agentsDir?: string; // default: src/agents (DIRS.agents)\n stacksFile?: string; // default: config/stacks.yaml (STACKS_FILE)\n matrixFile?: string; // default: config/skills-matrix.yaml (SKILLS_MATRIX_PATH)\n};\n\nexport type ResolvedConfig = {\n source: string;\n sourceOrigin: \"flag\" | \"env\" | \"project\" | \"default\";\n marketplace?: string;\n};\n\nexport function getProjectConfigPath(projectDir: string): string {\n return path.join(projectDir, CLAUDE_SRC_DIR, PROJECT_CONFIG_FILE);\n}\n\nexport async function loadProjectSourceConfig(\n projectDir: string,\n): Promise<ProjectSourceConfig | null> {\n const srcConfigPath = getProjectConfigPath(projectDir);\n const legacyConfigPath = path.join(projectDir, CLAUDE_DIR, STANDARD_FILES.CONFIG_YAML);\n\n let configPath = srcConfigPath;\n if (!(await fileExists(srcConfigPath))) {\n if (await fileExists(legacyConfigPath)) {\n configPath = legacyConfigPath;\n verbose(`Using legacy config location: ${legacyConfigPath}`);\n } else {\n verbose(`Project config not found at ${srcConfigPath} or ${legacyConfigPath}`);\n return null;\n }\n }\n\n const data = await safeLoadYamlFile(configPath, projectSourceConfigSchema);\n if (!data) return null;\n\n verbose(`Loaded project config from ${configPath}`);\n return data as ProjectSourceConfig;\n}\n\nexport async function saveProjectConfig(\n projectDir: string,\n config: ProjectSourceConfig,\n): Promise<void> {\n const configPath = getProjectConfigPath(projectDir);\n await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));\n const schemaComment = `${yamlSchemaComment(SCHEMA_PATHS.projectSourceConfig)}\\n`;\n const content = stringifyYaml(config, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });\n await writeFile(configPath, `${schemaComment}${content}`);\n verbose(`Saved project config to ${configPath}`);\n}\n\n// Precedence: flag > env > project > default\nexport async function resolveSource(\n flagValue?: string,\n projectDir?: string,\n): Promise<ResolvedConfig> {\n const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;\n const marketplace = projectConfig?.marketplace;\n\n if (flagValue !== undefined) {\n if (flagValue === \"\" || flagValue.trim() === \"\") {\n throw new Error(\n \"--source flag cannot be empty. Provide a valid source: a local directory path or a git repository URL (e.g., './my-skills' or 'https://github.com/user/repo')\",\n );\n }\n validateSourceFormat(flagValue.trim(), \"--source\");\n verbose(`Source from --source flag: ${flagValue}`);\n return { source: flagValue, sourceOrigin: \"flag\", marketplace };\n }\n\n const envValue = process.env[SOURCE_ENV_VAR];\n if (envValue) {\n const trimmed = envValue.trim();\n if (trimmed === \"\") {\n warn(`${SOURCE_ENV_VAR} is set but empty — ignoring and falling back to next source.`);\n } else {\n try {\n validateSourceFormat(trimmed, SOURCE_ENV_VAR);\n verbose(`Source from ${SOURCE_ENV_VAR} env var: ${trimmed}`);\n return { source: trimmed, sourceOrigin: \"env\", marketplace };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n warn(\n `${SOURCE_ENV_VAR} has an invalid value — ignoring and falling back to next source.\\n${message}`,\n );\n }\n }\n }\n\n if (projectConfig?.source) {\n verbose(`Source from project config: ${projectConfig.source}`);\n return {\n source: projectConfig.source,\n sourceOrigin: \"project\",\n marketplace,\n };\n }\n\n verbose(`Using default source: ${DEFAULT_SOURCE}`);\n return { source: DEFAULT_SOURCE, sourceOrigin: \"default\", marketplace };\n}\n\nexport type AgentsSourceOrigin = \"flag\" | \"project\" | \"default\";\n\nexport type ResolvedAgentsSource = {\n agentsSource?: string;\n agentsSourceOrigin: AgentsSourceOrigin;\n};\n\n// Precedence: flag > project > default (undefined)\nexport async function resolveAgentsSource(\n flagValue?: string,\n projectDir?: string,\n): Promise<ResolvedAgentsSource> {\n if (flagValue !== undefined) {\n if (flagValue === \"\" || flagValue.trim() === \"\") {\n throw new Error(\n \"--agent-source flag cannot be empty. Provide a valid source: a local directory path or a git repository URL (e.g., './my-agents' or 'https://github.com/user/repo')\",\n );\n }\n validateSourceFormat(flagValue.trim(), \"--agent-source\");\n verbose(`Agents source from --agent-source flag: ${flagValue}`);\n return { agentsSource: flagValue, agentsSourceOrigin: \"flag\" };\n }\n\n const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;\n if (projectConfig?.agentsSource) {\n verbose(`Agents source from project config: ${projectConfig.agentsSource}`);\n return {\n agentsSource: projectConfig.agentsSource,\n agentsSourceOrigin: \"project\",\n };\n }\n\n verbose(\"Using default agents source (local CLI)\");\n return { agentsSource: undefined, agentsSourceOrigin: \"default\" };\n}\n\nconst PROJECT_ORIGIN_LABEL = \"project config (.claude-src/config.yaml)\";\n\nexport function formatOrigin(\n type: \"source\" | \"agents\",\n origin: ResolvedConfig[\"sourceOrigin\"] | AgentsSourceOrigin,\n): string {\n if (origin === \"project\") return PROJECT_ORIGIN_LABEL;\n\n if (type === \"source\") {\n switch (origin) {\n case \"flag\":\n return \"--source flag\";\n case \"env\":\n return `${SOURCE_ENV_VAR} environment variable`;\n case \"default\":\n return \"default\";\n default:\n break;\n }\n }\n\n // type === \"agents\"\n switch (origin) {\n case \"flag\":\n return \"--agent-source flag\";\n case \"default\":\n return \"default (local CLI)\";\n default:\n break;\n }\n\n return origin;\n}\n\nexport async function resolveAuthor(projectDir?: string): Promise<string | undefined> {\n const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;\n return projectConfig?.author;\n}\n\n/** Resolved branding with defaults applied for any missing fields */\nexport type ResolvedBranding = {\n name: string;\n tagline: string;\n};\n\n/** Resolves branding from project config, falling back to DEFAULT_BRANDING for missing fields. */\nexport async function resolveBranding(projectDir?: string): Promise<ResolvedBranding> {\n const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;\n return {\n name: projectConfig?.branding?.name ?? DEFAULT_BRANDING.NAME,\n tagline: projectConfig?.branding?.tagline ?? DEFAULT_BRANDING.TAGLINE,\n };\n}\n\nexport async function resolveAllSources(\n projectDir?: string,\n): Promise<{ primary: SourceEntry; extras: SourceEntry[] }> {\n const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;\n\n const resolvedConfig = await resolveSource(undefined, projectDir);\n const primary: SourceEntry = {\n name: \"marketplace\",\n url: resolvedConfig.source,\n description: \"Primary skills marketplace\",\n };\n\n const extras: SourceEntry[] = [];\n const seenNames = new Set<string>();\n\n if (projectConfig?.sources) {\n for (const source of projectConfig.sources) {\n if (!seenNames.has(source.name)) {\n seenNames.add(source.name);\n extras.push(source);\n }\n }\n }\n\n return { primary, extras };\n}\n\nconst REMOTE_PROTOCOLS = [\n GITHUB_SOURCE.GITHUB_PREFIX, // \"github:\"\n GITHUB_SOURCE.GH_PREFIX, // \"gh:\"\n \"gitlab:\",\n \"bitbucket:\",\n \"sourcehut:\",\n \"https://\",\n \"http://\",\n] as const;\n\n// Minimum length after protocol prefix for a valid remote source (e.g., \"org/repo\" = 8 chars min)\nconst MIN_REMOTE_PATH_LENGTH = 3;\nconst MAX_SOURCE_LENGTH = 512;\n\n// Null bytes must never appear in source strings — they can bypass C-level string termination in downstream tools\nconst NULL_BYTE_PATTERN = /\\0/;\n\n// Path traversal sequences in git refs/branches/tags (e.g., \"?branch=../../etc/passwd\")\nconst PATH_TRAVERSAL_PATTERN = /\\.\\./;\n\n// UNC path prefixes (Windows network paths): \\\\server\\share or //server/share\n// These can trigger SMB authentication to attacker-controlled servers\nconst UNC_PATH_PATTERN = /^(?:\\/\\/|\\\\\\\\)/;\n\n// Private/reserved IPv4 ranges that should not appear in source URLs (SSRF prevention)\n// Matches: 127.x.x.x, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 0.0.0.0, 169.254.x.x\nconst PRIVATE_IPV4_PATTERN =\n /^(?:127\\.\\d+\\.\\d+\\.\\d+|10\\.\\d+\\.\\d+\\.\\d+|172\\.(?:1[6-9]|2\\d|3[01])\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+|0\\.0\\.0\\.0|169\\.254\\.\\d+\\.\\d+)$/;\n\n// IPv6 loopback and private addresses in URL hostname brackets\nconst PRIVATE_IPV6_PATTERN =\n /^\\[(?:::1|::ffff:(?:127\\.\\d+\\.\\d+\\.\\d+|10\\.\\d+\\.\\d+\\.\\d+|192\\.168\\.\\d+\\.\\d+)|fd[0-9a-f]{2}:.*|fe80:.*)\\]$/i;\n\n/**\n * Validates a source string format before it reaches giget or filesystem operations.\n * Catches obviously invalid formats early with clear error messages.\n *\n * @param source - The trimmed, non-empty source value to validate\n * @param flagName - The flag name for error messages (\"--source\" or \"--agent-source\")\n */\nexport function validateSourceFormat(source: string, flagName: string): void {\n // Null bytes can bypass C-level string termination in downstream tools (giget, git)\n if (NULL_BYTE_PATTERN.test(source)) {\n throw new Error(\n `${flagName} contains invalid characters.\\n\\n` +\n `Source values must not contain null bytes.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} github:user/repo`,\n );\n }\n\n if (source.length > MAX_SOURCE_LENGTH) {\n throw new Error(\n `${flagName} value is too long (${source.length} characters, max ${MAX_SOURCE_LENGTH}).\\n\\n` +\n `Provide a shorter source path or URL.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} github:user/repo`,\n );\n }\n\n const matchedProtocol = REMOTE_PROTOCOLS.find((prefix) => source.startsWith(prefix));\n\n if (matchedProtocol) {\n validateRemoteSource(source, matchedProtocol, flagName);\n } else {\n validateLocalPath(source, flagName);\n }\n}\n\nfunction validateRemoteSource(source: string, protocol: string, flagName: string): void {\n const pathAfterProtocol = source.slice(protocol.length).trim();\n\n if (pathAfterProtocol.length < MIN_REMOTE_PATH_LENGTH) {\n throw new Error(\n `${flagName} has an incomplete URL: \"${source}\"\\n\\n` +\n `A repository path is required after the protocol prefix.\\n` +\n `Examples:\\n` +\n ` ${flagName} github:user/repo\\n` +\n ` ${flagName} https://github.com/user/repo`,\n );\n }\n\n // Block path traversal in any remote source (refs, branches, query params)\n if (PATH_TRAVERSAL_PATTERN.test(pathAfterProtocol)) {\n throw new Error(\n `${flagName} contains path traversal in URL: \"${source}\"\\n\\n` +\n `Remote source URLs must not contain '..' sequences.\\n` +\n `Examples:\\n` +\n ` ${flagName} github:user/repo\\n` +\n ` ${flagName} https://github.com/user/repo`,\n );\n }\n\n // For https:// and http:// URLs, validate basic URL structure\n if (protocol === \"https://\" || protocol === \"http://\") {\n validateHttpUrl(source, flagName);\n }\n\n // For git shorthand protocols (github:, gh:, gitlab:, etc.), validate org/repo pattern\n if (protocol !== \"https://\" && protocol !== \"http://\") {\n validateGitShorthand(source, pathAfterProtocol, flagName);\n }\n}\n\nfunction validateHttpUrl(source: string, flagName: string): void {\n // Basic URL structure check: must have a hostname with at least one dot or localhost\n const afterProtocol = source.replace(/^https?:\\/\\//, \"\");\n // Strip port number for hostname validation (e.g., \"localhost:8080\" -> \"localhost\")\n const hostnameWithPort = afterProtocol.split(\"/\")[0] ?? \"\";\n const hostname = hostnameWithPort.split(\":\")[0] ?? \"\";\n\n // Allow: dotted hostnames (github.com), localhost, and bracketed IPv6 ([::1])\n const isBracketedIPv6 = hostnameWithPort.startsWith(\"[\") && hostnameWithPort.includes(\"]\");\n if (!hostname || (!hostname.includes(\".\") && hostname !== \"localhost\" && !isBracketedIPv6)) {\n throw new Error(\n `${flagName} has an invalid URL: \"${source}\"\\n\\n` +\n `The URL must include a valid hostname.\\n` +\n `Examples:\\n` +\n ` ${flagName} https://github.com/user/repo\\n` +\n ` ${flagName} https://gitlab.company.com/team/skills`,\n );\n }\n\n // Block private/reserved IP addresses (SSRF prevention via giget)\n if (PRIVATE_IPV4_PATTERN.test(hostname) || PRIVATE_IPV6_PATTERN.test(hostnameWithPort)) {\n throw new Error(\n `${flagName} points to a private or reserved IP address: \"${source}\"\\n\\n` +\n `Source URLs must not target private network addresses.\\n` +\n `Use a public hostname instead.\\n` +\n `Examples:\\n` +\n ` ${flagName} https://github.com/user/repo\\n` +\n ` ${flagName} https://gitlab.company.com/team/skills`,\n );\n }\n}\n\nfunction validateGitShorthand(source: string, repoPath: string, flagName: string): void {\n // Git shorthand format: protocol:owner/repo (must have at least owner/repo)\n if (!repoPath.includes(\"/\")) {\n throw new Error(\n `${flagName} has an invalid repository reference: \"${source}\"\\n\\n` +\n `Git shorthand sources require an owner/repo format.\\n` +\n `Examples:\\n` +\n ` ${flagName} github:user/repo\\n` +\n ` ${flagName} gh:organization/skills`,\n );\n }\n}\n\nfunction validateLocalPath(source: string, flagName: string): void {\n // Check for control characters (except common whitespace)\n // eslint-disable-next-line no-control-regex\n const CONTROL_CHAR_PATTERN = /[\\x00-\\x08\\x0E-\\x1F\\x7F]/u;\n if (CONTROL_CHAR_PATTERN.test(source)) {\n throw new Error(\n `${flagName} contains invalid characters: \"${source}\"\\n\\n` +\n `Source paths must not contain control characters.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} /home/user/skills`,\n );\n }\n\n // Block UNC paths (Windows network paths like \\\\server\\share or //server/share)\n // These can trigger SMB authentication to attacker-controlled servers, leaking credentials\n if (UNC_PATH_PATTERN.test(source)) {\n throw new Error(\n `${flagName} contains a UNC network path: \"${source}\"\\n\\n` +\n `Network paths (\\\\\\\\server\\\\share or //server/share) are not allowed for security reasons.\\n` +\n `Use a local directory path or a remote URL instead.\\n` +\n `Examples:\\n` +\n ` ${flagName} ./my-skills\\n` +\n ` ${flagName} /home/user/skills\\n` +\n ` ${flagName} https://github.com/user/repo`,\n );\n }\n}\n\nexport function isLocalSource(source: string): boolean {\n if (source.startsWith(\"/\") || source.startsWith(\".\")) {\n return true;\n }\n\n const hasRemoteProtocol = REMOTE_PROTOCOLS.some((prefix) => source.startsWith(prefix));\n\n if (!hasRemoteProtocol) {\n if (source.includes(\"..\") || source.includes(\"~\")) {\n throw new Error(\n `Invalid source path: ${source}. Path traversal patterns like '..' and '~' are not allowed for security reasons. Use absolute paths or remote URLs instead (e.g., '/home/user/skills' or 'https://github.com/user/repo').`,\n );\n }\n }\n\n return !hasRemoteProtocol;\n}\n","import { parse as parseYaml } from \"yaml\";\nimport type { z } from \"zod\";\nimport { MAX_CONFIG_FILE_SIZE } from \"../consts\";\nimport { readFileSafe } from \"./fs\";\nimport { warn } from \"./logger\";\n\n/**\n * Reads a YAML file, parses it, and validates against a Zod schema.\n * Returns the validated data or null on any failure (missing file, parse error, validation error).\n * Warnings are emitted for parse and validation failures.\n * Enforces a file size limit (default: MAX_CONFIG_FILE_SIZE) to prevent DoS.\n */\nexport async function safeLoadYamlFile<T>(\n filePath: string,\n schema: z.ZodType<T>,\n maxSizeBytes: number = MAX_CONFIG_FILE_SIZE,\n): Promise<T | null> {\n try {\n const content = await readFileSafe(filePath, maxSizeBytes);\n const parsed = parseYaml(content);\n const result = schema.safeParse(parsed);\n if (!result.success) {\n warn(`Invalid YAML at '${filePath}': ${result.error.message}`);\n return null;\n }\n return result.data;\n } catch (error) {\n warn(`Failed to parse YAML at '${filePath}': ${error}`);\n return null;\n }\n}\n","import { createHash } from \"crypto\";\nimport { downloadTemplate } from \"giget\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport {\n CACHE_DIR,\n CACHE_HASH_LENGTH,\n CACHE_READABLE_PREFIX_LENGTH,\n MAX_MARKETPLACE_FILE_SIZE,\n MAX_JSON_NESTING_DEPTH,\n MAX_MARKETPLACE_PLUGINS,\n PLUGIN_MANIFEST_DIR,\n} from \"../../consts\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { ensureDir, directoryExists, readFileSafe, remove } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { isLocalSource } from \"../configuration\";\nimport {\n formatZodErrors,\n marketplaceSchema,\n validateNestingDepth,\n warnUnknownFields,\n} from \"../schemas\";\nimport type { MarketplaceFetchResult } from \"../../types\";\n\n/** Safe name pattern: alphanumeric, hyphens, underscores, dots, spaces, @, / (no shell metacharacters) */\nconst SAFE_NAME_PATTERN = /^[a-zA-Z0-9@._/ -]+$/;\nconst MAX_NAME_LENGTH = 200;\n\n/** Matches giget's source protocol regex to extract provider name */\nconst SOURCE_PROTO_RE = /^([\\w-.]+):/;\n\n/**\n * Matches giget's input regex for git URI parsing.\n * Groups: repo (org/name), subdir (optional path), ref (optional #branch)\n */\nconst GIT_URI_RE = /^(?<repo>[\\w.-]+\\/[\\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\\w./@-]+)?/;\n\nexport type FetchOptions = {\n forceRefresh?: boolean;\n subdir?: string;\n};\n\nexport type FetchResult = {\n path: string;\n fromCache: boolean;\n source: string;\n};\n\nexport function sanitizeSourceForCache(source: string): string {\n const hash = createHash(\"sha256\").update(source).digest(\"hex\").slice(0, CACHE_HASH_LENGTH);\n\n const readable = source\n .replace(/[^a-zA-Z0-9]/g, \"-\")\n .replace(/--+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n .slice(0, CACHE_READABLE_PREFIX_LENGTH);\n\n return readable ? `${readable}-${hash}` : hash;\n}\n\nfunction getCacheDir(source: string): string {\n const sanitized = sanitizeSourceForCache(source) || \"unknown\";\n return path.join(CACHE_DIR, \"sources\", sanitized);\n}\n\nexport async function fetchFromSource(\n source: string,\n options: FetchOptions = {},\n): Promise<FetchResult> {\n const { forceRefresh = false, subdir } = options;\n\n if (isLocalSource(source)) {\n return fetchFromLocalSource(source, subdir);\n }\n\n return fetchFromRemoteSource(source, { forceRefresh, subdir });\n}\n\nasync function fetchFromLocalSource(source: string, subdir?: string): Promise<FetchResult> {\n const fullPath = subdir ? path.join(source, subdir) : source;\n const absolutePath = path.isAbsolute(fullPath) ? fullPath : path.resolve(process.cwd(), fullPath);\n\n if (!(await directoryExists(absolutePath))) {\n throw new Error(`Local source not found: '${absolutePath}'`);\n }\n\n verbose(`Using local source: ${absolutePath}`);\n\n return {\n path: absolutePath,\n fromCache: false,\n source,\n };\n}\n\n/**\n * Compute the giget tarball cache directory for a source.\n *\n * Replicates giget's internal cache path logic:\n * `{cacheRoot}/{providerName}/{templateName}`\n *\n * where templateName is `repo.replace(\"/\", \"-\")` sanitized to `[a-zA-Z0-9-]`.\n * Returns undefined if the source format doesn't match giget's git URI pattern.\n */\nfunction getGigetCacheDir(source: string): string | undefined {\n let providerName = \"github\";\n let rawSource = source;\n\n const protoMatch = source.match(SOURCE_PROTO_RE);\n if (protoMatch) {\n providerName = protoMatch[1];\n rawSource = source.slice(protoMatch[0].length);\n // http/https providers use the full URL, not parseable as git URI\n if (providerName === \"http\" || providerName === \"https\") {\n return undefined;\n }\n }\n\n const uriMatch = rawSource.match(GIT_URI_RE);\n if (!uriMatch?.groups?.repo) {\n return undefined;\n }\n\n // Replicate giget's template.name sanitization\n const templateName = uriMatch.groups.repo.replace(\"/\", \"-\").replace(/[^\\da-z-]/gi, \"-\");\n\n const gigetCacheRoot = process.env.XDG_CACHE_HOME\n ? path.resolve(process.env.XDG_CACHE_HOME, \"giget\")\n : path.resolve(os.homedir(), \".cache\", \"giget\");\n\n return path.join(gigetCacheRoot, providerName, templateName);\n}\n\n/**\n * Clear giget's tarball/ETag cache for a source so downloadTemplate()\n * performs a fresh fetch instead of short-circuiting with a stale ETag.\n */\nasync function clearGigetCache(source: string): Promise<void> {\n const gigetDir = getGigetCacheDir(source);\n if (!gigetDir) return;\n\n if (await directoryExists(gigetDir)) {\n verbose(`Clearing giget cache: ${gigetDir}`);\n await remove(gigetDir);\n }\n}\n\nasync function fetchFromRemoteSource(source: string, options: FetchOptions): Promise<FetchResult> {\n const { forceRefresh = false, subdir } = options;\n const cacheDir = getCacheDir(source);\n\n const fullSource = subdir ? `${source}/${subdir}` : source;\n\n verbose(`Fetching from remote: ${fullSource}`);\n verbose(`Cache directory: ${cacheDir}`);\n\n if (!forceRefresh && (await directoryExists(cacheDir))) {\n verbose(`Using cached source: ${cacheDir}`);\n return {\n path: cacheDir,\n fromCache: true,\n source: fullSource,\n };\n }\n\n if (forceRefresh) {\n await clearGigetCache(source);\n }\n\n await ensureDir(path.dirname(cacheDir));\n\n try {\n const result = await downloadTemplate(fullSource, {\n dir: cacheDir,\n force: true, // Always force when downloading to avoid \"already exists\" error\n offline: false,\n });\n\n verbose(`Downloaded to: ${result.dir}`);\n\n return {\n path: result.dir,\n fromCache: false,\n source: fullSource,\n };\n } catch (error) {\n throw createDetailedFetchError(error, source);\n }\n}\n\nfunction createDetailedFetchError(error: unknown, source: string): Error {\n const message = getErrorMessage(error);\n\n if (message.includes(\"404\") || message.includes(\"Not Found\")) {\n return new Error(\n `Repository not found: ${source}\\n\\n` +\n `This could mean:\\n` +\n ` - The repository doesn't exist\\n` +\n ` - The repository is private and you need to set authentication\\n` +\n ` - There's a typo in the URL\\n\\n` +\n `For private repositories, set the GIGET_AUTH environment variable:\\n` +\n ` export GIGET_AUTH=ghp_your_github_token`,\n );\n }\n\n if (message.includes(\"401\") || message.includes(\"Unauthorized\")) {\n return new Error(\n `Authentication required for: ${source}\\n\\n` +\n `Set the GIGET_AUTH environment variable with a GitHub token:\\n` +\n ` export GIGET_AUTH=ghp_your_github_token\\n\\n` +\n `Create a token at: https://github.com/settings/tokens\\n` +\n `Required scope: repo (for private repos) or public_repo (for public)`,\n );\n }\n\n if (message.includes(\"403\") || message.includes(\"Forbidden\")) {\n return new Error(\n `Access denied to: ${source}\\n\\n` +\n `Your token may not have sufficient permissions.\\n` +\n `Ensure your GIGET_AUTH token has the 'repo' scope for private repositories.`,\n );\n }\n\n if (\n message.includes(\"ENOTFOUND\") ||\n message.includes(\"ETIMEDOUT\") ||\n message.includes(\"network\")\n ) {\n return new Error(\n `Network error fetching: ${source}\\n\\n` +\n `Please check your internet connection.\\n` +\n `If you're behind a corporate proxy, you may need to set:\\n` +\n ` export HTTPS_PROXY=http://your-proxy:port\\n` +\n ` export FORCE_NODE_FETCH=true # Required for Node 20+`,\n );\n }\n\n return new Error(`Failed to fetch ${source}: ${message}`);\n}\n\nexport async function fetchMarketplace(\n source: string,\n options: FetchOptions = {},\n): Promise<MarketplaceFetchResult> {\n const result = await fetchFromSource(source, {\n forceRefresh: options.forceRefresh,\n subdir: \"\", // Root of repo\n });\n\n const marketplacePath = path.join(result.path, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n\n if (!(await directoryExists(path.dirname(marketplacePath)))) {\n throw new Error(\n `Marketplace not found for source: ${source}\\n\\n` +\n `The .claude-plugin/marketplace.json file is missing from this repository.\\n\\n` +\n `Possible causes:\\n` +\n \" - The source URL may be incorrect\\n\" +\n \" - The repository may not have a marketplace configured\\n\\n\" +\n \"To create a marketplace, add a .claude-plugin/marketplace.json file to your source repository.\",\n );\n }\n\n const content = await readFileSafe(marketplacePath, MAX_MARKETPLACE_FILE_SIZE);\n const parsed = JSON.parse(content);\n\n if (!validateNestingDepth(parsed, MAX_JSON_NESTING_DEPTH)) {\n throw new Error(\n `Invalid marketplace.json at: ${marketplacePath}\\n\\n` +\n `JSON structure exceeds maximum nesting depth of ${MAX_JSON_NESTING_DEPTH}.`,\n );\n }\n\n const validation = marketplaceSchema.safeParse(parsed);\n\n if (!validation.success) {\n throw new Error(\n `Invalid marketplace.json at: ${marketplacePath}\\n\\n` +\n `Validation errors: ${formatZodErrors(validation.error.issues)}`,\n );\n }\n\n const marketplace = validation.data;\n\n const EXPECTED_MARKETPLACE_KEYS = [\n \"$schema\",\n \"name\",\n \"version\",\n \"description\",\n \"owner\",\n \"metadata\",\n \"plugins\",\n ] as const;\n if (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n warnUnknownFields(\n parsed as Record<string, unknown>,\n EXPECTED_MARKETPLACE_KEYS,\n \"marketplace.json\",\n );\n }\n\n if (marketplace.plugins.length > MAX_MARKETPLACE_PLUGINS) {\n throw new Error(\n `Invalid marketplace.json at: ${marketplacePath}\\n\\n` +\n `Too many plugins: ${marketplace.plugins.length} (limit: ${MAX_MARKETPLACE_PLUGINS}).`,\n );\n }\n\n for (const plugin of marketplace.plugins) {\n if (plugin.name.length > MAX_NAME_LENGTH) {\n warn(\n `Marketplace plugin name too long (${plugin.name.length} chars): '${plugin.name.slice(0, 50)}...'`,\n );\n }\n if (!SAFE_NAME_PATTERN.test(plugin.name)) {\n warn(`Marketplace plugin name contains unsafe characters: '${plugin.name.slice(0, 50)}'`);\n }\n }\n\n verbose(`Loaded marketplace: ${marketplace.name} v${marketplace.version}`);\n\n return {\n marketplace,\n sourcePath: result.path,\n fromCache: result.fromCache ?? false,\n };\n}\n","export {\n DEFAULT_SOURCE,\n SOURCE_ENV_VAR,\n PROJECT_CONFIG_FILE,\n type BrandingConfig,\n type SourceEntry,\n type ProjectSourceConfig,\n type ResolvedConfig,\n type ResolvedBranding,\n type AgentsSourceOrigin,\n type ResolvedAgentsSource,\n getProjectConfigPath,\n loadProjectSourceConfig,\n saveProjectConfig,\n resolveSource,\n resolveAgentsSource,\n formatOrigin,\n resolveAuthor,\n resolveBranding,\n resolveAllSources,\n isLocalSource,\n validateSourceFormat,\n} from \"./config\";\n\nexport {\n type ProjectConfigOptions,\n generateProjectConfigFromSkills,\n buildStackProperty,\n compactStackForYaml,\n} from \"./config-generator\";\n\nexport { type MergeContext, type MergeResult, mergeWithExistingConfig } from \"./config-merger\";\n\nexport { saveSourceToProjectConfig } from \"./config-saver\";\n\nexport {\n type LoadedProjectConfig,\n loadProjectConfig,\n validateProjectConfig,\n} from \"./project-config\";\n\nexport { type SourceSummary, addSource, removeSource, getSourceSummary } from \"./source-manager\";\n","import type {\n AgentName,\n CategoryPath,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillAssignment,\n SkillId,\n Stack,\n StackAgentConfig,\n Subcategory,\n} from \"../../types\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { getCachedDefaults } from \"../loading\";\n\n// Boundary cast: literal strings are valid AgentName values\nconst DEFAULT_AGENTS: AgentName[] = [\"agent-summoner\", \"skill-summoner\", \"documentor\"];\n\nfunction getEffectiveSkillToAgents(): Record<string, AgentName[]> {\n const defaults = getCachedDefaults();\n if (defaults?.skillToAgents) {\n // Boundary cast: YAML-loaded mappings contain valid AgentName values\n return defaults.skillToAgents as Record<string, AgentName[]>;\n }\n return {};\n}\n\nfunction getAgentsForSkill(skillPath: string, category: CategoryPath): AgentName[] {\n const normalizedPath = skillPath.replace(/^skills\\//, \"\").replace(/\\/$/, \"\");\n\n const skillToAgents = getEffectiveSkillToAgents();\n\n if (skillToAgents[category]) {\n return skillToAgents[category];\n }\n\n for (const [pattern, agents] of Object.entries(skillToAgents)) {\n if (normalizedPath === pattern || normalizedPath.startsWith(`${pattern}/`)) {\n return agents;\n }\n }\n\n for (const [pattern, agents] of Object.entries(skillToAgents)) {\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -2);\n if (normalizedPath.startsWith(prefix)) {\n return agents;\n }\n }\n }\n\n return DEFAULT_AGENTS;\n}\n\nexport type ProjectConfigOptions = {\n description?: string;\n author?: string;\n};\n\nfunction extractSubcategoryFromPath(categoryPath: CategoryPath): Subcategory | undefined {\n if (categoryPath === \"local\") return undefined;\n return categoryPath as Subcategory;\n}\n\n/**\n * Generates a ProjectConfig from a list of selected skill IDs by resolving which\n * agents are needed and building the stack property (agent -> subcategory -> SkillAssignment[]).\n *\n * For each selected skill, looks up its category and determines which agents\n * should receive it (via `getAgentsForSkill`). The resulting config includes\n * the deduplicated sorted agent list, full skill list, and optional stack\n * mappings for subcategory-based skill resolution during compilation.\n *\n * @param name - Project name for the config\n * @param selectedSkillIds - Skill IDs selected by the user in the wizard\n * @param matrix - Merged skills matrix (used to look up skill metadata)\n * @param options - Optional description and author fields\n * @returns Complete ProjectConfig ready to be saved to config.yaml\n */\nexport function generateProjectConfigFromSkills(\n name: string,\n selectedSkillIds: SkillId[],\n matrix: MergedSkillsMatrix,\n options?: ProjectConfigOptions & { selectedAgents?: AgentName[] },\n): ProjectConfig {\n const neededAgents = new Set<AgentName>();\n const stackProperty: Record<string, StackAgentConfig> = {};\n\n // When user explicitly selected agents, filter stack assignments to only those agents\n const selectedAgentSet = options?.selectedAgents\n ? new Set<AgentName>(options.selectedAgents)\n : null;\n\n verbose(\n `generateProjectConfigFromSkills: ${selectedSkillIds.length} skills, ` +\n `matrix has ${Object.keys(matrix.skills).length} entries, ` +\n `selectedAgentSet=${selectedAgentSet ? `[${[...selectedAgentSet].join(\", \")}]` : \"null\"}`,\n );\n\n let foundCount = 0;\n let skippedCount = 0;\n\n for (const skillId of selectedSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) {\n skippedCount++;\n warn(`Skill '${skillId}' NOT FOUND in matrix`);\n continue;\n }\n foundCount++;\n\n const skillPath = skill.path;\n const category = skill.category;\n const agents = getAgentsForSkill(skillPath, category);\n const subcategory = extractSubcategoryFromPath(category);\n\n // When user selected agents, only assign skills to agents in their selection\n const effectiveAgents = selectedAgentSet\n ? agents.filter((a) => selectedAgentSet.has(a))\n : agents;\n\n verbose(\n ` skill '${skillId}': category='${category}', subcategory=${subcategory ?? \"none\"}, ` +\n `agents=[${agents.join(\", \")}], effectiveAgents=[${effectiveAgents.join(\", \")}]`,\n );\n\n if (effectiveAgents.length === 0) {\n warn(\n `Skill '${skillId}': all agents filtered out by selectedAgentSet — ` +\n `derived=[${agents.join(\", \")}], selected=[${[...(selectedAgentSet ?? [])].join(\", \")}]`,\n );\n }\n\n for (const agentId of effectiveAgents) {\n neededAgents.add(agentId);\n\n if (subcategory) {\n if (!stackProperty[agentId]) {\n stackProperty[agentId] = {};\n }\n // Wizard selections are bare IDs with preloaded: false\n stackProperty[agentId][subcategory] = [{ id: skillId, preloaded: false }];\n }\n }\n }\n\n verbose(\n `generateProjectConfigFromSkills: ${foundCount} found, ${skippedCount} not found, ` +\n `${Object.keys(stackProperty).length} agents in stack`,\n );\n\n if (skippedCount > 0) {\n const matrixSample = Object.keys(matrix.skills).slice(0, 5).join(\", \");\n warn(\n `${skippedCount}/${selectedSkillIds.length} skills not found in matrix. ` +\n `Matrix keys sample: [${matrixSample}]`,\n );\n }\n\n // When the user explicitly selected agents, use their selection instead of the derived set\n const agentList = options?.selectedAgents\n ? [...options.selectedAgents].sort()\n : Array.from(neededAgents).sort();\n\n const config: ProjectConfig = {\n name,\n agents: agentList,\n skills: [...selectedSkillIds],\n };\n\n if (Object.keys(stackProperty).length > 0) {\n config.stack = stackProperty;\n }\n\n if (options?.description) {\n config.description = options.description;\n }\n\n if (options?.author) {\n config.author = options.author;\n }\n\n return config;\n}\n\n/**\n * Extracts the stack property (agent -> subcategory -> SkillAssignment[]) from a Stack definition.\n *\n * Stack values are already normalized to SkillAssignment[] by loadStacks().\n * Preserves all assignments and preloaded flags for round-trip fidelity.\n *\n * @param stack - Loaded Stack definition with normalized agent configs\n * @returns Partial mapping of agent names to subcategory-skill assignment mappings\n */\nexport function buildStackProperty(stack: Stack): Partial<Record<AgentName, StackAgentConfig>> {\n const result: Partial<Record<AgentName, StackAgentConfig>> = {};\n\n for (const [agentId, agentConfig] of typedEntries<AgentName, StackAgentConfig>(stack.agents)) {\n if (!agentConfig || Object.keys(agentConfig).length === 0) {\n continue;\n }\n\n const resolvedMappings: StackAgentConfig = {};\n\n for (const [subcategoryId, assignments] of typedEntries<Subcategory, SkillAssignment[]>(\n agentConfig,\n )) {\n if (!assignments || assignments.length === 0) continue;\n resolvedMappings[subcategoryId] = assignments;\n }\n\n if (Object.keys(resolvedMappings).length > 0) {\n result[agentId] = resolvedMappings;\n }\n }\n\n return result;\n}\n\n/**\n * Compacts a ProjectConfig.stack for YAML serialization.\n * Converts SkillAssignment[] to the most compact form:\n * - Single skill with preloaded=false -> bare string (e.g., \"web-framework-react\")\n * - Single skill with preloaded=true -> object (e.g., { id: \"...\", preloaded: true })\n * - Multiple skills -> array of objects/strings\n * This ensures round-trip fidelity: bare strings stay bare, rich format stays rich.\n */\nexport function compactStackForYaml(\n stack: Record<string, StackAgentConfig>,\n): Record<string, Record<string, unknown>> {\n const result: Record<string, Record<string, unknown>> = {};\n\n for (const [agentId, agentConfig] of Object.entries(stack)) {\n const compacted: Record<string, unknown> = {};\n\n for (const [subcategory, assignments] of typedEntries<Subcategory, SkillAssignment[]>(\n agentConfig,\n )) {\n if (!assignments || assignments.length === 0) continue;\n\n if (assignments.length === 1) {\n const assignment = assignments[0];\n // Single skill, no preloaded -> bare string\n if (!assignment.preloaded) {\n compacted[subcategory] = assignment.id;\n } else {\n compacted[subcategory] = { id: assignment.id, preloaded: true };\n }\n } else {\n // Multiple skills -> array, compact each element\n compacted[subcategory] = assignments.map((a) =>\n !a.preloaded ? a.id : { id: a.id, preloaded: true },\n );\n }\n }\n\n if (Object.keys(compacted).length > 0) {\n result[agentId] = compacted;\n }\n }\n\n return result;\n}\n","export {\n parseFrontmatter,\n loadAllAgents,\n loadProjectAgents,\n loadSkillsByIds,\n loadPluginSkills,\n} from \"./loader\";\n\nexport {\n type SourceLoadOptions,\n type SourceLoadResult,\n loadSkillsMatrixFromSource,\n getMarketplaceLabel,\n} from \"./source-loader\";\n\nexport {\n type FetchOptions,\n type FetchResult,\n sanitizeSourceForCache,\n fetchFromSource,\n fetchMarketplace,\n} from \"./source-fetcher\";\n\nexport {\n type DefaultMappings,\n loadDefaultMappings,\n getCachedDefaults,\n clearDefaultsCache,\n} from \"./defaults-loader\";\n\nexport { loadSkillsFromAllSources } from \"./multi-source-loader\";\n","import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { unique } from \"remeda\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { glob, readFile, directoryExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { CLAUDE_SRC_DIR, DIRS, STANDARD_FILES } from \"../../consts\";\nimport type { AgentDefinition, SkillDefinition, SkillFrontmatter, SkillId } from \"../../types\";\nimport { formatZodErrors, skillFrontmatterLoaderSchema, agentYamlConfigSchema } from \"../schemas\";\n\nconst FRONTMATTER_REGEX = /^---\\n([\\s\\S]*?)\\n---/;\n\nexport function parseFrontmatter(content: string, filePath?: string): SkillFrontmatter | null {\n const match = content.match(FRONTMATTER_REGEX);\n if (!match) return null;\n\n const yamlContent = match[1];\n const parsed = skillFrontmatterLoaderSchema.safeParse(parseYaml(yamlContent));\n\n if (!parsed.success) {\n const location = filePath ?? \"unknown file\";\n warn(`Invalid SKILL.md frontmatter in '${location}': ${formatZodErrors(parsed.error.issues)}`);\n return null;\n }\n // Boundary cast: YAML name field may not match strict SkillId pattern (e.g., local skills)\n return parsed.data as SkillFrontmatter;\n}\n\nexport async function loadAllAgents(projectRoot: string): Promise<Record<string, AgentDefinition>> {\n const agents: Record<string, AgentDefinition> = {};\n const agentSourcesDir = path.join(projectRoot, DIRS.agents);\n\n const files = await glob(\"**/agent.yaml\", agentSourcesDir);\n\n for (const file of files) {\n const fullPath = path.join(agentSourcesDir, file);\n try {\n const content = await readFile(fullPath);\n const config = agentYamlConfigSchema.parse(parseYaml(content));\n const agentPath = path.dirname(file);\n\n agents[config.id] = {\n title: config.title,\n description: config.description,\n model: config.model,\n tools: config.tools,\n path: agentPath,\n sourceRoot: projectRoot,\n };\n\n verbose(`Loaded agent: ${config.id} from ${file}`);\n } catch (error) {\n warn(`Skipping invalid agent.yaml at '${fullPath}': ${getErrorMessage(error)}`);\n }\n }\n\n return agents;\n}\n\nexport async function loadProjectAgents(\n projectRoot: string,\n): Promise<Record<string, AgentDefinition>> {\n const agents: Record<string, AgentDefinition> = {};\n const projectAgentsDir = path.join(projectRoot, CLAUDE_SRC_DIR, \"agents\");\n\n if (!(await directoryExists(projectAgentsDir))) {\n verbose(`No project agents directory at ${projectAgentsDir}`);\n return agents;\n }\n\n const files = await glob(\"**/agent.yaml\", projectAgentsDir);\n\n for (const file of files) {\n const fullPath = path.join(projectAgentsDir, file);\n try {\n const content = await readFile(fullPath);\n const config = agentYamlConfigSchema.parse(parseYaml(content));\n const agentPath = path.dirname(file);\n\n agents[config.id] = {\n title: config.title,\n description: config.description,\n model: config.model,\n tools: config.tools,\n path: agentPath,\n sourceRoot: projectRoot,\n agentBaseDir: `${CLAUDE_SRC_DIR}/agents`, // Project agents are in .claude-src/agents/\n };\n\n verbose(`Loaded project agent: ${config.id} from ${file}`);\n } catch (error) {\n warn(`Skipping invalid agent.yaml at '${fullPath}': ${getErrorMessage(error)}`);\n }\n }\n\n return agents;\n}\n\nasync function buildIdToDirectoryPathMap(skillsDir: string): Promise<Record<string, string>> {\n const map: Record<string, string> = {};\n const files = await glob(\"**/SKILL.md\", skillsDir);\n\n for (const file of files) {\n const fullPath = path.join(skillsDir, file);\n const content = await readFile(fullPath);\n const frontmatter = parseFrontmatter(content, fullPath);\n\n if (frontmatter?.name) {\n const directoryPath = file.replace(\"/SKILL.md\", \"\");\n map[frontmatter.name] = directoryPath;\n map[directoryPath] = directoryPath;\n }\n }\n\n return map;\n}\n\nexport async function loadSkillsByIds(\n skillIds: Array<{ id: SkillId }>,\n projectRoot: string,\n): Promise<Record<string, SkillDefinition>> {\n const skills: Record<string, SkillDefinition> = {};\n const skillsDir = path.join(projectRoot, DIRS.skills);\n\n const idToDirectoryPath = await buildIdToDirectoryPathMap(skillsDir);\n const allSkillIds = Object.keys(idToDirectoryPath);\n const expandedSkillIds: SkillId[] = [];\n\n for (const { id: skillId } of skillIds) {\n if (idToDirectoryPath[skillId]) {\n expandedSkillIds.push(skillId);\n } else {\n const childSkills = allSkillIds.filter((id) => {\n const dirPath = idToDirectoryPath[id];\n return dirPath.startsWith(`${skillId}/`);\n });\n\n if (childSkills.length > 0) {\n // Boundary cast: keys from buildIdToDirectoryPathMap are SkillId values from frontmatter\n expandedSkillIds.push(...(childSkills as SkillId[]));\n verbose(`Expanded directory '${skillId}' to ${childSkills.length} skills`);\n } else {\n warn(`Unknown skill reference '${skillId}'`);\n }\n }\n }\n\n const uniqueSkillIds = unique(expandedSkillIds);\n\n for (const skillId of uniqueSkillIds) {\n const directoryPath = idToDirectoryPath[skillId];\n if (!directoryPath) {\n warn(`Could not find skill '${skillId}': no matching skill found`);\n continue;\n }\n\n const skillPath = path.join(skillsDir, directoryPath);\n const skillMdPath = path.join(skillPath, STANDARD_FILES.SKILL_MD);\n\n try {\n const content = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(content, skillMdPath);\n\n if (!frontmatter) {\n warn(`Skipping '${skillId}': missing or invalid frontmatter`);\n continue;\n }\n\n const canonicalId = frontmatter.name;\n const skillDef: SkillDefinition = {\n id: canonicalId,\n path: `${DIRS.skills}/${directoryPath}/`,\n description: frontmatter.description,\n };\n\n skills[canonicalId] = skillDef;\n\n if (directoryPath !== canonicalId) {\n skills[directoryPath] = skillDef;\n }\n\n verbose(`Loaded skill: ${canonicalId} (from ${directoryPath})`);\n } catch (error) {\n warn(`Could not load skill '${skillId}': ${error}`);\n }\n }\n\n return skills;\n}\n\nexport async function loadPluginSkills(\n pluginDir: string,\n): Promise<Record<string, SkillDefinition>> {\n const skills: Record<string, SkillDefinition> = {};\n const pluginSkillsDir = path.join(pluginDir, \"skills\");\n\n if (!(await directoryExists(pluginSkillsDir))) {\n return skills;\n }\n\n const files = await glob(\"**/SKILL.md\", pluginSkillsDir);\n\n for (const file of files) {\n const fullPath = path.join(pluginSkillsDir, file);\n const content = await readFile(fullPath);\n\n const frontmatter = parseFrontmatter(content, fullPath);\n if (!frontmatter) {\n warn(`Skipping '${file}': missing or invalid frontmatter`);\n continue;\n }\n\n const folderPath = file.replace(\"/SKILL.md\", \"\");\n const skillPath = `skills/${folderPath}/`;\n const skillId = frontmatter.name;\n\n skills[skillId] = {\n id: skillId,\n path: skillPath,\n description: frontmatter.description,\n };\n\n verbose(`Loaded plugin skill: ${skillId} from ${file}`);\n }\n\n return skills;\n}\n","import path from \"path\";\nimport { PROJECT_ROOT, SKILLS_DIR_PATH, SKILLS_MATRIX_PATH } from \"../../consts\";\nimport { LOCAL_DEFAULTS } from \"../metadata-keys\";\nimport type {\n AgentName,\n MergedSkillsMatrix,\n ResolvedSkill,\n ResolvedStack,\n SkillId,\n Stack,\n} from \"../../types\";\nimport { fileExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedKeys } from \"../../utils/typed-object\";\nimport {\n DEFAULT_SOURCE,\n isLocalSource,\n loadProjectSourceConfig,\n resolveSource,\n type ResolvedConfig,\n} from \"../configuration\";\nimport { discoverLocalSkills, type LocalSkillDiscoveryResult } from \"../skills\";\nimport {\n checkMatrixHealth,\n extractAllSkills,\n loadSkillsMatrix,\n mergeMatrixWithSkills,\n} from \"../matrix\";\nimport { fetchFromSource, fetchMarketplace } from \"./source-fetcher\";\nimport { loadSkillsFromAllSources } from \"./multi-source-loader\";\nimport { loadStacks, resolveAgentConfigToSkills } from \"../stacks\";\n\nexport type SourceLoadOptions = {\n sourceFlag?: string;\n projectDir?: string;\n forceRefresh?: boolean;\n devMode?: boolean;\n};\n\nexport type SourceLoadResult = {\n matrix: MergedSkillsMatrix;\n sourceConfig: ResolvedConfig;\n sourcePath: string;\n isLocal: boolean;\n marketplace?: string;\n};\n\nexport async function loadSkillsMatrixFromSource(\n options: SourceLoadOptions = {},\n): Promise<SourceLoadResult> {\n const { sourceFlag, projectDir, forceRefresh = false, devMode = false } = options;\n\n const sourceConfig = await resolveSource(sourceFlag, projectDir);\n const { source } = sourceConfig;\n\n verbose(`Loading skills from source: ${source}`);\n\n const isLocal = isLocalSource(source) || devMode === true;\n\n let result: SourceLoadResult;\n if (isLocal) {\n result = await loadFromLocal(source, sourceConfig);\n } else {\n result = await loadFromRemote(source, sourceConfig, forceRefresh);\n }\n\n const resolvedProjectDir = projectDir || process.cwd();\n const localSkillsResult = await discoverLocalSkills(resolvedProjectDir);\n\n if (localSkillsResult && localSkillsResult.skills.length > 0) {\n verbose(\n `Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`,\n );\n result.matrix = mergeLocalSkillsIntoMatrix(result.matrix, localSkillsResult);\n }\n\n await loadSkillsFromAllSources(\n result.matrix,\n sourceConfig,\n resolvedProjectDir,\n forceRefresh,\n result.marketplace,\n );\n\n checkMatrixHealth(result.matrix);\n\n return result;\n}\n\nasync function loadFromLocal(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<SourceLoadResult> {\n let skillsPath: string;\n\n if (isLocalSource(source)) {\n skillsPath = path.isAbsolute(source) ? source : path.resolve(process.cwd(), source);\n } else {\n skillsPath = PROJECT_ROOT;\n }\n\n verbose(`Loading skills from local path: ${skillsPath}`);\n\n const mergedMatrix = await loadAndMergeFromBasePath(skillsPath);\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: skillsPath,\n isLocal: true,\n marketplace: sourceConfig.marketplace,\n };\n}\n\nasync function loadFromRemote(\n source: string,\n sourceConfig: ResolvedConfig,\n forceRefresh: boolean,\n): Promise<SourceLoadResult> {\n verbose(`Fetching skills from remote source: ${source}`);\n\n const fetchResult = await fetchFromSource(source, { forceRefresh });\n\n verbose(`Fetched to: ${fetchResult.path}`);\n\n const mergedMatrix = await loadAndMergeFromBasePath(fetchResult.path);\n\n // Try to read marketplace name from the source's .claude-plugin/marketplace.json.\n // This handles the case where sourceConfig.marketplace is undefined (e.g. during\n // `agentsinc init --source github:user/repo` before any project config exists).\n let marketplace = sourceConfig.marketplace;\n if (!marketplace) {\n try {\n const marketplaceResult = await fetchMarketplace(source, { forceRefresh });\n marketplace = marketplaceResult.marketplace.name;\n verbose(`Using marketplace name from marketplace.json: ${marketplace}`);\n } catch {\n // No marketplace.json — getMarketplaceLabel() handles the fallback display\n verbose(`Source does not have a marketplace.json — using source name as label`);\n }\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: fetchResult.path,\n isLocal: false,\n marketplace,\n };\n}\n\nasync function loadAndMergeFromBasePath(basePath: string): Promise<MergedSkillsMatrix> {\n const sourceProjectConfig = await loadProjectSourceConfig(basePath);\n\n const matrixRelPath = sourceProjectConfig?.matrixFile ?? SKILLS_MATRIX_PATH;\n const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;\n const stacksRelFile = sourceProjectConfig?.stacksFile;\n\n const sourceMatrixPath = path.join(basePath, matrixRelPath);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(basePath, skillsDirRelPath);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from source first, fall back to CLI's config/stacks.yaml\n const sourceStacks = await loadStacks(basePath, stacksRelFile);\n const stacks = sourceStacks.length > 0 ? sourceStacks : await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n mergedMatrix.suggestedStacks = stacks.map((stack) => convertStackToResolvedStack(stack));\n const stackSource = sourceStacks.length > 0 ? \"source\" : \"CLI\";\n verbose(`Loaded ${stacks.length} stacks from ${stackSource}`);\n }\n\n return mergedMatrix;\n}\n\n// Stack values are already skill IDs — no alias resolution needed\nfunction convertStackToResolvedStack(stack: Stack): ResolvedStack {\n const allSkillIds: SkillId[] = [];\n const seenSkillIds = new Set<SkillId>();\n\n for (const agentId of typedKeys<AgentName>(stack.agents)) {\n const agentConfig = stack.agents[agentId];\n if (!agentConfig) continue;\n\n const skillRefs = resolveAgentConfigToSkills(agentConfig);\n\n for (const ref of skillRefs) {\n if (!seenSkillIds.has(ref.id)) {\n seenSkillIds.add(ref.id);\n allSkillIds.push(ref.id);\n }\n }\n }\n\n const agentCount = typedKeys<AgentName>(stack.agents).length;\n verbose(`Stack '${stack.id}' has ${allSkillIds.length} skills from ${agentCount} agents`);\n\n return {\n id: stack.id,\n name: stack.name,\n description: stack.description,\n audience: [], // Not used in new format\n skills: {} as ResolvedStack[\"skills\"], // Skills come from stack agent configs, resolved at runtime\n allSkillIds,\n philosophy: stack.philosophy || \"\",\n };\n}\n\n/**\n * Extract a human-readable name from a source URL.\n * e.g. \"github:agents-inc/skills\" -> \"agents-inc\"\n * \"github:acme-corp/claude-skills\" -> \"acme-corp\"\n */\nfunction extractSourceName(source: string): string {\n // Strip protocol prefix (github:, gh:, https://, etc.)\n const withoutProtocol = source.replace(/^(?:github|gh|gitlab|bitbucket|sourcehut):/, \"\");\n const withoutUrl = withoutProtocol.replace(/^https?:\\/\\/[^/]+\\//, \"\");\n\n // Take the first path segment (org/owner name)\n const firstSegment = withoutUrl.split(\"/\")[0];\n return firstSegment || source;\n}\n\n/**\n * Compute a display label for the marketplace indicator in the wizard.\n *\n * Returns undefined when the source is local (no marketplace to display).\n *\n * Format examples:\n * \"Photoroom + 1 public\" — private marketplace with public also available\n * \"Photoroom\" — private marketplace only\n * \"agents-inc (public)\" — default public marketplace\n */\nexport function getMarketplaceLabel(sourceResult: SourceLoadResult): string | undefined {\n if (sourceResult.isLocal) return undefined;\n\n const { marketplace } = sourceResult;\n\n if (!marketplace) {\n const name = extractSourceName(sourceResult.sourceConfig.source);\n return `${name} (public)`;\n }\n\n // When using a non-default source, the public marketplace is also available\n const PUBLIC_MARKETPLACE_COUNT = 1;\n const isDefaultSource = sourceResult.sourceConfig.source === DEFAULT_SOURCE;\n if (!isDefaultSource) {\n return `${marketplace} + ${PUBLIC_MARKETPLACE_COUNT} public`;\n }\n\n return marketplace;\n}\n\nfunction mergeLocalSkillsIntoMatrix(\n matrix: MergedSkillsMatrix,\n localResult: LocalSkillDiscoveryResult,\n): MergedSkillsMatrix {\n for (const metadata of localResult.skills) {\n const existingSkill = matrix.skills[metadata.id];\n\n // If overwriting an existing remote skill, inherit its category unconditionally.\n // Otherwise, use whatever the local skill declared in its metadata.yaml.\n const category = existingSkill?.category ?? metadata.category;\n const displayName = existingSkill?.displayName ?? matrix.displayNames[metadata.id];\n\n const resolvedSkill: ResolvedSkill = {\n id: metadata.id,\n displayName,\n description: metadata.description,\n usageGuidance: metadata.usageGuidance,\n\n category,\n categoryExclusive: metadata.categoryExclusive,\n tags: metadata.tags ?? [],\n\n author: LOCAL_DEFAULTS.AUTHOR,\n\n conflictsWith: existingSkill?.conflictsWith ?? [],\n recommends: existingSkill?.recommends ?? [],\n requires: existingSkill?.requires ?? [],\n alternatives: existingSkill?.alternatives ?? [],\n discourages: existingSkill?.discourages ?? [],\n compatibleWith: existingSkill?.compatibleWith ?? [],\n\n requiresSetup: existingSkill?.requiresSetup ?? [],\n providesSetupFor: existingSkill?.providesSetupFor ?? [],\n\n path: metadata.path,\n\n local: true,\n localPath: metadata.localPath,\n };\n\n matrix.skills[metadata.id] = resolvedSkill;\n verbose(`Added local skill: ${metadata.id} (category: ${category})`);\n }\n\n return matrix;\n}\n","import { STANDARD_FILES, STANDARD_DIRS } from \"../consts\";\nimport type { CategoryPath } from \"../types\";\n\n/**\n * YAML field names used in skill metadata.yaml files.\n * Centralized to avoid string duplication across loaders and compilers.\n */\nexport const METADATA_KEYS = {\n CLI_NAME: \"cliName\",\n CLI_DESCRIPTION: \"cliDescription\",\n CATEGORY: \"category\",\n FORKED_FROM: \"forkedFrom\",\n CONTENT_HASH: \"contentHash\",\n USAGE_GUIDANCE: \"usageGuidance\",\n} as const;\n\n/**\n * Default values used when importing third-party skills (no existing metadata).\n */\nexport const IMPORT_DEFAULTS = {\n CATEGORY: \"imported\" as CategoryPath,\n AUTHOR: \"@imported\",\n} as const;\n\n/**\n * Default values used for local skills (created via `agentsinc new skill` or discovered locally).\n */\nexport const LOCAL_DEFAULTS = {\n CATEGORY: \"local\" as CategoryPath,\n AUTHOR: \"@local\",\n} as const;\n\n/**\n * Files included when computing a skill's content hash.\n * Shared by versioning.ts (for metadata version bumps) and\n * skill-plugin-compiler.ts (for plugin compilation).\n */\nexport const SKILL_CONTENT_FILES = [STANDARD_FILES.SKILL_MD, STANDARD_FILES.REFERENCE_MD] as const;\n\n/**\n * Directories included when computing a skill's content hash.\n * Shared by versioning.ts and skill-plugin-compiler.ts.\n */\nexport const SKILL_CONTENT_DIRS = [STANDARD_DIRS.EXAMPLES, STANDARD_DIRS.SCRIPTS] as const;\n","export { type FetchSkillsOptions, fetchSkills } from \"./skill-fetcher\";\n\nexport {\n type ForkedFromMetadata,\n type LocalSkillMetadata,\n type SkillComparisonResult,\n readForkedFromMetadata,\n readLocalSkillMetadata,\n getLocalSkillsWithMetadata,\n computeSourceHash,\n compareLocalSkillsWithSource,\n injectForkedFromMetadata,\n} from \"./skill-metadata\";\n\nexport {\n type CopiedSkill,\n type CopyProgressCallback,\n copySkill,\n copySkillFromSource,\n copySkillsToPluginFromSource,\n copySkillsToLocalFlattened,\n} from \"./skill-copier\";\n\nexport {\n type SkillPluginOptions,\n type CompiledSkillPlugin,\n compileSkillPlugin,\n compileAllSkillPlugins,\n printCompilationSummary,\n} from \"./skill-plugin-compiler\";\n\nexport { type LocalSkillDiscoveryResult, discoverLocalSkills } from \"./local-skill-loader\";\n\nexport { archiveLocalSkill, restoreArchivedSkill, hasArchivedSkill } from \"./source-switcher\";\n","import path from \"path\";\nimport { sortBy } from \"remeda\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\n\nimport { fileExists, readFile, writeFile, listDirectories } from \"../../utils/fs\";\nimport { computeFileHash } from \"../versioning\";\nimport { getCurrentDate } from \"../versioning\";\nimport {\n LOCAL_SKILLS_PATH,\n SCHEMA_PATHS,\n STANDARD_FILES,\n YAML_FORMATTING,\n yamlSchemaComment,\n} from \"../../consts\";\nimport type { SkillId } from \"../../types\";\nimport { formatZodErrors, localSkillMetadataSchema } from \"../schemas\";\nimport { warn } from \"../../utils/logger\";\n\n/**\n * Tracks the original marketplace source of a locally-installed skill.\n *\n * Written into each skill's metadata.yaml under the `forkedFrom` key when a skill\n * is copied from a source repository to the local `.claude/skills/` directory.\n * Used for version comparison, update detection, and provenance tracking.\n */\nexport type ForkedFromMetadata = {\n /** Canonical skill ID from the source repository (e.g., \"cc-ts-react-hook-form\") */\n skillId: SkillId;\n /** SHA-256 hash of the source SKILL.md content at the time of installation */\n contentHash: string;\n /** ISO date string (YYYY-MM-DD) when the skill was installed or last updated */\n date: string;\n /** Source URL the skill was installed from (e.g., \"github:agents-inc/skills\") */\n source?: string;\n};\n\n/**\n * Full metadata.yaml content for a locally-installed skill.\n *\n * Parsed from the `metadata.yaml` file in each skill directory under `.claude/skills/`.\n * Uses an index signature to preserve unknown fields written by other tools.\n */\nexport type LocalSkillMetadata = {\n /** Provenance metadata linking back to the original source skill, if any */\n forkedFrom?: ForkedFromMetadata;\n [key: string]: unknown;\n};\n\n/**\n * Result of comparing a local skill against its source repository version.\n *\n * Produced by {@link compareLocalSkillsWithSource} for each skill in the local\n * `.claude/skills/` directory. Used by `agentsinc outdated` to display update status.\n */\nexport type SkillComparisonResult = {\n /** Canonical skill ID (from forkedFrom metadata, or directory name if no metadata) */\n id: SkillId;\n /** SHA-256 hash of the local SKILL.md content at install time, null if no forkedFrom metadata */\n localHash: string | null;\n /** SHA-256 hash of the current source SKILL.md, null if source skill no longer exists */\n sourceHash: string | null;\n /** \"current\" if hashes match, \"outdated\" if they differ, \"local-only\" if no source link */\n status: \"current\" | \"outdated\" | \"local-only\";\n /** Directory name under `.claude/skills/` (may differ from skill ID for aliased skills) */\n dirName: string;\n /** Relative path within the source repository, present only when the source skill exists */\n sourcePath?: string;\n};\n\n/**\n * Reads forkedFrom metadata from a skill's metadata.yaml file.\n *\n * This metadata tracks the original marketplace source of a locally-installed skill,\n * enabling version comparison and update detection via content hash matching.\n *\n * @param skillDir - Absolute path to the skill directory (e.g., `/project/.claude/skills/react-hook-form`)\n * @returns The `forkedFrom` metadata if present and valid, `null` if the file doesn't exist,\n * has no `forkedFrom` field, or fails Zod validation (warns on invalid metadata)\n *\n * @example\n * ```ts\n * const metadata = await readForkedFromMetadata(\"/project/.claude/skills/react-hook-form\");\n * if (metadata) {\n * console.log(`Installed from ${metadata.skillId} on ${metadata.date}`);\n * }\n * ```\n */\nexport async function readForkedFromMetadata(skillDir: string): Promise<ForkedFromMetadata | null> {\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const result = localSkillMetadataSchema.safeParse(parseYaml(content));\n\n if (!result.success) {\n warn(`Invalid metadata.yaml at ${metadataPath}: ${formatZodErrors(result.error.issues)}`);\n return null;\n }\n\n return (result.data as LocalSkillMetadata).forkedFrom ?? null;\n}\n\n/**\n * Reads the full local skill metadata from a skill's metadata.yaml file.\n *\n * Returns the parsed metadata including `forkedFrom` field.\n * Used by the uninstall command to determine whether a skill was installed by the CLI.\n *\n * @param skillDir - Absolute path to the skill directory\n * @returns The parsed metadata if valid, `null` if the file doesn't exist or is invalid\n */\nexport async function readLocalSkillMetadata(skillDir: string): Promise<LocalSkillMetadata | null> {\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n const content = await readFile(metadataPath);\n const result = localSkillMetadataSchema.safeParse(parseYaml(content));\n\n if (!result.success) {\n warn(`Invalid metadata.yaml at ${metadataPath}: ${formatZodErrors(result.error.issues)}`);\n return null;\n }\n\n return result.data as LocalSkillMetadata;\n}\n\n/**\n * Scans all local skill directories and reads their forked-from metadata.\n *\n * Enumerates every subdirectory under `{projectDir}/.claude/skills/` and reads\n * the `forkedFrom` field from each skill's metadata.yaml. The returned Map is\n * keyed by skill ID (from `forkedFrom.skillId` if available, otherwise the\n * directory name).\n *\n * @param projectDir - Absolute path to the project root containing `.claude/skills/`\n * @returns Map from skill identifier to its directory name and forked-from metadata.\n * Returns an empty Map if the skills directory doesn't exist.\n *\n * @example\n * ```ts\n * const skills = await getLocalSkillsWithMetadata(\"/project\");\n * for (const [id, { dirName, forkedFrom }] of skills) {\n * console.log(`${id} in ${dirName}, forked: ${forkedFrom !== null}`);\n * }\n * ```\n */\nexport async function getLocalSkillsWithMetadata(\n projectDir: string,\n): Promise<Map<string, { dirName: string; forkedFrom: ForkedFromMetadata | null }>> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const result = new Map<string, { dirName: string; forkedFrom: ForkedFromMetadata | null }>();\n\n if (!(await fileExists(localSkillsPath))) {\n return result;\n }\n\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const dirName of skillDirs) {\n const skillDir = path.join(localSkillsPath, dirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n const skillId = forkedFrom?.skillId ?? dirName;\n\n result.set(skillId, { dirName, forkedFrom });\n }\n\n return result;\n}\n\n/**\n * Computes the SHA-256 content hash of a skill's SKILL.md in a source repository.\n *\n * Used to compare the current source version against the locally-installed version's\n * `contentHash` to detect whether updates are available.\n *\n * @param sourcePath - Absolute path to the source repository root\n * @param skillPath - Relative path to the skill within `src/` (e.g., \"web/react/react-hook-form\")\n * @returns SHA-256 hash string of the source SKILL.md, or `null` if the file doesn't exist\n */\nexport async function computeSourceHash(\n sourcePath: string,\n skillPath: string,\n): Promise<string | null> {\n const skillMdPath = path.join(sourcePath, \"src\", skillPath, STANDARD_FILES.SKILL_MD);\n\n if (!(await fileExists(skillMdPath))) {\n return null;\n }\n\n return computeFileHash(skillMdPath);\n}\n\n/**\n * Compares all local skills against their source repository versions.\n *\n * For each skill in `{projectDir}/.claude/skills/`, reads its `forkedFrom` metadata\n * and computes the current source hash. Skills are classified as:\n * - **\"current\"** -- local content hash matches the source (no update available)\n * - **\"outdated\"** -- hashes differ (source has been updated since installation)\n * - **\"local-only\"** -- no `forkedFrom` metadata, or the source skill no longer exists\n *\n * Results are sorted alphabetically by skill ID.\n *\n * @param projectDir - Absolute path to the project root containing `.claude/skills/`\n * @param sourcePath - Absolute path to the source repository root (used to locate SKILL.md files)\n * @param sourceSkills - Map of skill IDs to their relative paths within the source repository.\n * Typically built from the skills matrix. Keys are skill IDs, values have\n * a `path` field (e.g., `{ path: \"web/react/react-hook-form\" }`)\n * @returns Array of comparison results, one per local skill, sorted by skill ID\n *\n * @example\n * ```ts\n * const results = await compareLocalSkillsWithSource(\n * \"/project\",\n * \"/tmp/source-repo\",\n * { \"cc-ts-react-hook-form\": { path: \"web/react/react-hook-form\" } },\n * );\n * const outdated = results.filter((r) => r.status === \"outdated\");\n * ```\n */\nexport async function compareLocalSkillsWithSource(\n projectDir: string,\n sourcePath: string,\n sourceSkills: Record<string, { path: string }>,\n): Promise<SkillComparisonResult[]> {\n const results: SkillComparisonResult[] = [];\n const localSkills = await getLocalSkillsWithMetadata(projectDir);\n\n for (const [skillId, { dirName, forkedFrom }] of localSkills) {\n if (!forkedFrom) {\n // Boundary cast: skillId comes from Map<string, ...> keys (directory names or forkedFrom.skillId)\n results.push({\n id: skillId as SkillId,\n localHash: null,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const localHash = forkedFrom.contentHash;\n const sourceSkill = sourceSkills[forkedFrom.skillId];\n\n if (!sourceSkill) {\n results.push({\n id: forkedFrom.skillId,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const sourceHash = await computeSourceHash(sourcePath, sourceSkill.path);\n\n if (sourceHash === null) {\n results.push({\n id: forkedFrom.skillId,\n localHash,\n sourceHash: null,\n status: \"local-only\",\n dirName,\n });\n continue;\n }\n\n const status = localHash === sourceHash ? \"current\" : \"outdated\";\n\n results.push({\n id: forkedFrom.skillId,\n localHash,\n sourceHash,\n status,\n dirName,\n sourcePath: sourceSkill.path,\n });\n }\n\n return sortBy(results, (r) => r.id);\n}\n\n/**\n * Writes forked-from provenance metadata into a skill's metadata.yaml.\n *\n * Reads the existing metadata.yaml (preserving any extra fields), sets the\n * `forkedFrom` block with the given skill ID, content hash, and current date,\n * then writes the file back with a YAML language server schema comment.\n *\n * Called during skill installation (by the skill copier) to record where a\n * locally-installed skill originated from.\n *\n * @param destPath - Absolute path to the skill directory containing metadata.yaml.\n * The file must already exist (created during skill copy).\n * @param skillId - Canonical skill ID from the source repository (e.g., \"cc-ts-react-hook-form\")\n * @param contentHash - SHA-256 hash of the source SKILL.md content at install time\n * @param source - Source URL the skill was installed from (e.g., \"github:agents-inc/skills\")\n *\n * @remarks\n * **Side effect:** Overwrites `{destPath}/metadata.yaml` on disk. Existing fields\n * are preserved if the file parses successfully; if parsing fails, only `forkedFrom`\n * is written (with a warning logged).\n */\nexport async function injectForkedFromMetadata(\n destPath: string,\n skillId: SkillId,\n contentHash: string,\n source?: string,\n): Promise<void> {\n const metadataPath = path.join(destPath, STANDARD_FILES.METADATA_YAML);\n const rawContent = await readFile(metadataPath);\n\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const parseResult = localSkillMetadataSchema.safeParse(parseYaml(yamlContent));\n if (!parseResult.success) {\n warn(`Malformed metadata.yaml at '${metadataPath}' — existing fields may be lost`);\n }\n const metadata: LocalSkillMetadata = parseResult.success\n ? (parseResult.data as LocalSkillMetadata)\n : { forkedFrom: undefined };\n\n metadata.forkedFrom = {\n skillId: skillId,\n contentHash: contentHash,\n date: getCurrentDate(),\n ...(source ? { source } : {}),\n };\n\n const schemaComment = `${yamlSchemaComment(SCHEMA_PATHS.metadata)}\\n`;\n const newYamlContent = stringifyYaml(metadata, { lineWidth: YAML_FORMATTING.LINE_WIDTH_NONE });\n await writeFile(metadataPath, `${schemaComment}${newYamlContent}`);\n}\n","import { createHash } from \"crypto\";\nimport path from \"path\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { readFile, readFileSafe, writeFile, glob, fileExists } from \"../utils/fs\";\nimport { warn } from \"../utils/logger\";\nimport {\n DEFAULT_VERSION,\n MAX_PLUGIN_FILE_SIZE,\n STANDARD_FILES,\n HASH_PREFIX_LENGTH,\n} from \"../consts\";\nimport { pluginManifestSchema } from \"./schemas\";\nimport { SKILL_CONTENT_FILES, SKILL_CONTENT_DIRS } from \"./metadata-keys\";\n\nexport function getCurrentDate(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\nexport function computeStringHash(content: string): string {\n const hash = createHash(\"sha256\");\n hash.update(content);\n return hash.digest(\"hex\").slice(0, HASH_PREFIX_LENGTH);\n}\n\nexport async function computeFileHash(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return computeStringHash(content);\n}\n\nexport async function computeSkillFolderHash(skillPath: string): Promise<string> {\n const contents: string[] = [];\n\n for (const fileName of SKILL_CONTENT_FILES) {\n const filePath = path.join(skillPath, fileName);\n if (await fileExists(filePath)) {\n const content = await readFile(filePath);\n contents.push(`${fileName}:${content}`);\n }\n }\n\n for (const dirName of SKILL_CONTENT_DIRS) {\n const dirPath = path.join(skillPath, dirName);\n if (await fileExists(dirPath)) {\n const files = await glob(\"**/*\", dirPath);\n for (const file of files.sort()) {\n const filePath = path.join(dirPath, file);\n const content = await readFile(filePath);\n contents.push(`${dirName}/${file}:${content}`);\n }\n }\n }\n\n const combined = contents.join(\"\\n---\\n\");\n return computeStringHash(combined);\n}\n\n/**\n * Plugin versioning utilities shared by skill, agent, and stack plugin compilers.\n * Reads existing plugin.json + .content-hash, bumps semver major on content change.\n */\n\nconst CONTENT_HASH_FILE = \".content-hash\";\n\nfunction parseMajorVersion(version: string): number {\n const match = version.match(/^(\\d+)\\./);\n return match ? parseInt(match[1], 10) : 1;\n}\n\nfunction bumpMajorVersion(version: string): string {\n const major = parseMajorVersion(version);\n return `${major + 1}.0.0`;\n}\n\nasync function readExistingPluginManifest(\n pluginDir: string,\n getManifestPath: (dir: string) => string,\n): Promise<{ version: string; contentHash: string | undefined } | null> {\n const manifestPath = getManifestPath(pluginDir);\n\n if (!(await fileExists(manifestPath))) {\n return null;\n }\n\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const manifest = pluginManifestSchema.parse(JSON.parse(content));\n\n const hashFilePath = manifestPath.replace(STANDARD_FILES.PLUGIN_JSON, CONTENT_HASH_FILE);\n let contentHash: string | undefined;\n if (await fileExists(hashFilePath)) {\n contentHash = (await readFile(hashFilePath)).trim();\n }\n\n return {\n version: manifest.version ?? DEFAULT_VERSION,\n contentHash,\n };\n } catch (error) {\n warn(`Failed to read plugin manifest at '${manifestPath}': ${getErrorMessage(error)}`);\n return null;\n }\n}\n\nexport async function determinePluginVersion(\n newHash: string,\n pluginDir: string,\n getManifestPath: (dir: string) => string,\n): Promise<{ version: string; contentHash: string }> {\n const existing = await readExistingPluginManifest(pluginDir, getManifestPath);\n\n if (!existing) {\n return {\n version: DEFAULT_VERSION,\n contentHash: newHash,\n };\n }\n\n if (existing.contentHash !== newHash) {\n return {\n version: bumpMajorVersion(existing.version),\n contentHash: newHash,\n };\n }\n\n return {\n version: existing.version,\n contentHash: newHash,\n };\n}\n\nexport async function writeContentHash(\n pluginDir: string,\n contentHash: string,\n getManifestPath: (dir: string) => string,\n): Promise<void> {\n const hashFilePath = getManifestPath(pluginDir).replace(\n STANDARD_FILES.PLUGIN_JSON,\n CONTENT_HASH_FILE,\n );\n await writeFile(hashFilePath, contentHash);\n}\n","import path from \"path\";\n\nimport { copy, ensureDir } from \"../../utils/fs\";\nimport { warn } from \"../../utils/logger\";\nimport { computeFileHash } from \"../versioning\";\nimport { STANDARD_FILES } from \"../../consts\";\nimport type { MergedSkillsMatrix, ResolvedSkill, SkillId } from \"../../types\";\nimport type { SourceLoadResult } from \"../loading\";\nimport { injectForkedFromMetadata } from \"./skill-metadata\";\n\nexport type CopiedSkill = {\n skillId: SkillId;\n contentHash: string;\n sourcePath: string;\n destPath: string;\n local?: boolean;\n};\n\nconst NULL_BYTE_PATTERN = /\\0/;\n\n/**\n * Validate that a resolved path stays within the expected parent directory.\n * Prevents path traversal attacks where skill.path contains sequences like \"../../sensitive\".\n */\nexport function validateSkillPath(\n resolvedPath: string,\n expectedParent: string,\n skillPath: string,\n): void {\n if (NULL_BYTE_PATTERN.test(skillPath)) {\n throw new Error(`Invalid skill path: '${skillPath}' contains null bytes`);\n }\n\n const normalizedResolved = path.resolve(resolvedPath);\n const normalizedParent = path.resolve(expectedParent);\n\n if (\n !normalizedResolved.startsWith(normalizedParent + path.sep) &&\n normalizedResolved !== normalizedParent\n ) {\n throw new Error(\n `Invalid skill path: '${skillPath}' escapes expected directory '${normalizedParent}'`,\n );\n }\n}\n\n/**\n * Join basePath + skillPath, validate the result stays within basePath,\n * and return the resolved path. Combines path.join + validateSkillPath\n * to eliminate repeated join-then-validate boilerplate.\n */\nfunction resolveSkillPath(basePath: string, skillPath: string): string {\n const resolved = path.join(basePath, skillPath);\n validateSkillPath(resolved, basePath, skillPath);\n return resolved;\n}\n\nfunction getSkillSourcePath(skill: ResolvedSkill, registryRoot: string): string {\n const srcDir = path.join(registryRoot, \"src\");\n return resolveSkillPath(srcDir, skill.path);\n}\n\nfunction getSkillDestPath(skill: ResolvedSkill, stackDir: string): string {\n const skillRelativePath = skill.path.replace(/^skills\\//, \"\");\n const skillsDir = path.join(stackDir, \"skills\");\n return resolveSkillPath(skillsDir, skillRelativePath);\n}\n\nasync function generateSkillHash(skillSourcePath: string): Promise<string> {\n const skillMdPath = path.join(skillSourcePath, STANDARD_FILES.SKILL_MD);\n return computeFileHash(skillMdPath);\n}\n\nexport async function copySkill(\n skill: ResolvedSkill,\n stackDir: string,\n registryRoot: string,\n source?: string,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePath(skill, registryRoot);\n const destPath = getSkillDestPath(skill, stackDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash, source);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nfunction getSkillSourcePathFromSource(\n skill: ResolvedSkill,\n sourceResult: SourceLoadResult,\n): string {\n const srcDir = path.join(sourceResult.sourcePath, \"src\");\n return resolveSkillPath(srcDir, skill.path);\n}\n\nexport async function copySkillFromSource(\n skill: ResolvedSkill,\n stackDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);\n const destPath = getSkillDestPath(skill, stackDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash, sourceResult.sourceConfig.source);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nexport type CopyProgressCallback = (completed: number, total: number) => void;\n\nexport async function copySkillsToPluginFromSource(\n selectedSkillIds: SkillId[],\n pluginDir: string,\n matrix: MergedSkillsMatrix,\n sourceResult: SourceLoadResult,\n sourceSelections?: Partial<Record<SkillId, string>>,\n onProgress?: CopyProgressCallback,\n): Promise<CopiedSkill[]> {\n const total = selectedSkillIds.length;\n let completed = 0;\n const results = await Promise.all(\n selectedSkillIds.map(async (skillId): Promise<CopiedSkill | null> => {\n const skill = matrix.skills[skillId];\n if (!skill) {\n warn(`Skill not found in matrix: '${skillId}'`);\n completed++;\n onProgress?.(completed, total);\n return null;\n }\n\n const selectedSource = sourceSelections?.[skillId];\n const userSelectedRemote = selectedSource && selectedSource !== \"local\";\n\n let result: CopiedSkill;\n if (skill.local && skill.localPath && !userSelectedRemote) {\n const localSkillPath = path.join(process.cwd(), skill.localPath);\n const contentHash = await generateSkillHash(localSkillPath);\n\n result = {\n skillId: skill.id,\n sourcePath: skill.localPath,\n destPath: skill.localPath,\n contentHash,\n local: true,\n };\n } else {\n result = await copySkillFromSource(skill, pluginDir, sourceResult);\n }\n\n completed++;\n onProgress?.(completed, total);\n return result;\n }),\n );\n\n return results.filter((r): r is CopiedSkill => r !== null);\n}\n\nfunction getFlattenedSkillDestPath(skill: ResolvedSkill, localSkillsDir: string): string {\n return resolveSkillPath(localSkillsDir, skill.id);\n}\n\nasync function copySkillToLocalFlattened(\n skill: ResolvedSkill,\n localSkillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);\n const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash, sourceResult.sourceConfig.source);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nexport async function copySkillsToLocalFlattened(\n selectedSkillIds: SkillId[],\n localSkillsDir: string,\n matrix: MergedSkillsMatrix,\n sourceResult: SourceLoadResult,\n sourceSelections?: Partial<Record<SkillId, string>>,\n): Promise<CopiedSkill[]> {\n const results = await Promise.all(\n selectedSkillIds.map(async (skillId): Promise<CopiedSkill | null> => {\n const skill = matrix.skills[skillId];\n if (!skill) {\n warn(`Skill not found in matrix: '${skillId}'`);\n return null;\n }\n\n const selectedSource = sourceSelections?.[skillId];\n const userSelectedRemote = selectedSource && selectedSource !== \"local\";\n\n if (skill.local && skill.localPath && !userSelectedRemote) {\n const localSkillPath = path.join(process.cwd(), skill.localPath);\n const contentHash = await generateSkillHash(localSkillPath);\n\n return {\n skillId: skill.id,\n sourcePath: skill.localPath,\n destPath: skill.localPath,\n contentHash,\n local: true,\n };\n }\n\n return copySkillToLocalFlattened(skill, localSkillsDir, sourceResult);\n }),\n );\n\n return results.filter((r): r is CopiedSkill => r !== null);\n}\n","import path from \"path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, writeFile, ensureDir, glob, fileExists, copy } from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport {\n generateSkillPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { parseFrontmatter } from \"../loading\";\nimport { computeSkillFolderHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport type { PluginManifest, SkillFrontmatter, SkillMetadataConfig } from \"../../types\";\nimport { formatZodErrors, skillMetadataLoaderSchema } from \"../schemas\";\nimport { DEFAULT_BRANDING, STANDARD_FILES } from \"../../consts\";\nimport { SKILL_CONTENT_FILES, SKILL_CONTENT_DIRS } from \"../metadata-keys\";\n\nexport type SkillPluginOptions = {\n skillPath: string;\n outputDir: string;\n skillName?: string;\n};\n\nexport type CompiledSkillPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n skillName: string;\n};\n\nfunction sanitizeSkillName(name: string): string {\n return name.replace(/\\+/g, \"-\");\n}\n\nasync function readSkillMetadata(skillPath: string): Promise<SkillMetadataConfig | null> {\n const metadataPath = path.join(skillPath, STANDARD_FILES.METADATA_YAML);\n\n if (!(await fileExists(metadataPath))) {\n return null;\n }\n\n try {\n const content = await readFile(metadataPath);\n const lines = content.split(\"\\n\");\n const yamlContent = lines[0]?.startsWith(\"# yaml-language-server:\")\n ? lines.slice(1).join(\"\\n\")\n : content;\n\n const result = skillMetadataLoaderSchema.safeParse(parseYaml(yamlContent));\n if (!result.success) {\n warn(`Invalid metadata.yaml at '${skillPath}': ${formatZodErrors(result.error.issues)}`);\n return null;\n }\n return result.data;\n } catch (error) {\n warn(`Failed to read metadata.yaml at '${skillPath}': ${error}`);\n return null;\n }\n}\n\nfunction generateReadme(\n skillName: string,\n frontmatter: SkillFrontmatter,\n metadata: SkillMetadataConfig | null,\n): string {\n const lines: string[] = [];\n\n lines.push(`# ${skillName}`);\n lines.push(\"\");\n lines.push(frontmatter.description);\n lines.push(\"\");\n\n if (metadata?.tags && metadata.tags.length > 0) {\n lines.push(\"## Tags\");\n lines.push(\"\");\n lines.push(metadata.tags.map((t) => `\\`${t}\\``).join(\" \"));\n lines.push(\"\");\n }\n\n lines.push(\"## Installation\");\n lines.push(\"\");\n lines.push(\"Add this plugin to your Claude Code configuration:\");\n lines.push(\"\");\n lines.push(\"```json\");\n lines.push(\"{\");\n lines.push(` \"plugins\": [\"${skillName}\"]`);\n lines.push(\"}\");\n lines.push(\"```\");\n lines.push(\"\");\n\n lines.push(\"## Usage\");\n lines.push(\"\");\n lines.push(\"This skill is automatically available when installed.\");\n if (metadata?.requires && metadata.requires.length > 0) {\n lines.push(\"\");\n lines.push(`**Requires:** ${metadata.requires.join(\", \")}`);\n }\n lines.push(\"\");\n\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(`*Generated by ${DEFAULT_BRANDING.NAME} skill-plugin-compiler*`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\nexport async function compileSkillPlugin(\n options: SkillPluginOptions,\n): Promise<CompiledSkillPlugin> {\n const { skillPath, outputDir, skillName: overrideName } = options;\n\n const dirBasename = path.basename(skillPath);\n\n const skillMdPath = path.join(skillPath, STANDARD_FILES.SKILL_MD);\n if (!(await fileExists(skillMdPath))) {\n throw new Error(\n `Skill '${dirBasename}' is missing required ${STANDARD_FILES.SKILL_MD} file. Expected at: ${skillMdPath}`,\n );\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);\n\n if (!frontmatter) {\n throw new Error(\n `Skill '${dirBasename}' has invalid or missing YAML frontmatter in ${STANDARD_FILES.SKILL_MD}. ` +\n `Required fields: 'name' and 'description'. File: ${skillMdPath}`,\n );\n }\n\n const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);\n\n verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);\n\n const metadata = await readSkillMetadata(skillPath);\n\n const pluginDir = path.join(outputDir, skillName);\n const skillsDir = path.join(pluginDir, \"skills\", skillName);\n\n await ensureDir(pluginDir);\n await ensureDir(skillsDir);\n\n const newHash = await computeSkillFolderHash(skillPath);\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const manifest = generateSkillPluginManifest({\n skillName,\n description: frontmatter.description,\n author: metadata?.author,\n version,\n keywords: metadata?.tags,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json for ${skillName} (v${version})`);\n\n await writeFile(path.join(skillsDir, STANDARD_FILES.SKILL_MD), skillMdContent);\n verbose(` Copied ${STANDARD_FILES.SKILL_MD}`);\n\n for (const fileName of SKILL_CONTENT_FILES) {\n if (fileName === STANDARD_FILES.SKILL_MD) continue;\n\n const sourcePath = path.join(skillPath, fileName);\n if (await fileExists(sourcePath)) {\n const content = await readFile(sourcePath);\n await writeFile(path.join(skillsDir, fileName), content);\n verbose(` Copied ${fileName}`);\n }\n }\n\n for (const dirName of SKILL_CONTENT_DIRS) {\n const sourceDir = path.join(skillPath, dirName);\n if (await fileExists(sourceDir)) {\n await copy(sourceDir, path.join(skillsDir, dirName));\n verbose(` Copied ${dirName}/`);\n }\n }\n\n const readme = generateReadme(skillName, frontmatter, metadata);\n await writeFile(path.join(pluginDir, \"README.md\"), readme);\n verbose(\" Generated README.md\");\n\n return {\n pluginPath: pluginDir,\n manifest,\n skillName,\n };\n}\n\nexport async function compileAllSkillPlugins(\n skillsDir: string,\n outputDir: string,\n): Promise<CompiledSkillPlugin[]> {\n const results: CompiledSkillPlugin[] = [];\n\n const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);\n\n for (const skillMdFile of skillMdFiles) {\n const skillPath = path.join(skillsDir, path.dirname(skillMdFile));\n\n try {\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n results.push(result);\n log(` [OK] ${result.skillName}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n const dirBasename = path.basename(skillPath);\n warn(`Failed to compile skill from '${dirBasename}': ${errorMessage}`);\n }\n }\n\n return results;\n}\n\nexport function printCompilationSummary(results: CompiledSkillPlugin[]): void {\n log(`\\nCompiled ${results.length} skill plugins:`);\n for (const result of results) {\n log(` - ${result.skillName} (v${result.manifest.version})`);\n }\n}\n","export {\n type SkillManifestOptions,\n type AgentManifestOptions,\n type StackManifestOptions,\n generateSkillPluginManifest,\n generateAgentPluginManifest,\n generateStackPluginManifest,\n writePluginManifest,\n getPluginDir,\n} from \"./plugin-manifest\";\n\nexport { findPluginManifest } from \"./plugin-manifest-finder\";\n\nexport {\n getUserPluginsDir,\n getCollectivePluginDir,\n getProjectPluginsDir,\n getPluginSkillsDir,\n getPluginAgentsDir,\n getPluginManifestPath,\n readPluginManifest,\n getPluginSkillIds,\n} from \"./plugin-finder\";\n\nexport {\n type PluginInfo,\n type InstallationInfo,\n getPluginInfo,\n formatPluginDisplay,\n getInstallationInfo,\n formatInstallationDisplay,\n} from \"./plugin-info\";\n\nexport { type VersionBumpType, bumpPluginVersion, getPluginVersion } from \"./plugin-version\";\n\nexport {\n validatePluginStructure,\n validatePluginManifest,\n validateSkillFrontmatter,\n validateAgentFrontmatter,\n validatePlugin,\n validateAllPlugins,\n printPluginValidationResult,\n} from \"./plugin-validator\";\n\nexport { discoverAllPluginSkills, hasIndividualPlugins, listPluginNames } from \"./plugin-discovery\";\n\nexport {\n type PluginKey,\n type ResolvedPlugin,\n getEnabledPluginKeys,\n resolvePluginInstallPaths,\n getVerifiedPluginInstallPaths,\n} from \"./plugin-settings\";\n","import path from \"path\";\n\nimport { ensureDir, writeFile } from \"../../utils/fs\";\nimport { DEFAULT_VERSION, PLUGIN_MANIFEST_DIR, STANDARD_FILES } from \"../../consts\";\nimport type { PluginAuthor, PluginManifest } from \"../../types\";\n\nconst PLUGIN_DIR_NAME = PLUGIN_MANIFEST_DIR;\nconst PLUGIN_MANIFEST_FILE = STANDARD_FILES.PLUGIN_JSON;\nconst SKILL_PLUGIN_PREFIX = \"\";\nconst AGENT_PLUGIN_PREFIX = \"agent-\";\n\nexport type SkillManifestOptions = {\n skillName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n};\n\nexport type AgentManifestOptions = {\n agentName: string;\n description?: string;\n version?: string;\n};\n\nexport type StackManifestOptions = {\n stackName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n hasSkills?: boolean;\n hasAgents?: boolean;\n hasHooks?: boolean;\n};\n\nfunction buildAuthor(name?: string, email?: string): PluginAuthor | undefined {\n if (!name) {\n return undefined;\n }\n const author: PluginAuthor = { name };\n if (email) {\n author.email = email;\n }\n return author;\n}\n\nexport function generateSkillPluginManifest(options: SkillManifestOptions): PluginManifest {\n const manifest: PluginManifest = {\n name: `${SKILL_PLUGIN_PREFIX}${options.skillName}`,\n version: options.version ?? DEFAULT_VERSION,\n skills: \"./skills/\",\n };\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n return manifest;\n}\n\nexport function generateAgentPluginManifest(options: AgentManifestOptions): PluginManifest {\n const manifest: PluginManifest = {\n name: `${AGENT_PLUGIN_PREFIX}${options.agentName}`,\n version: options.version ?? DEFAULT_VERSION,\n agents: \"./agents/\",\n };\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n return manifest;\n}\n\nexport function generateStackPluginManifest(options: StackManifestOptions): PluginManifest {\n const manifest: PluginManifest = {\n name: options.stackName,\n version: options.version ?? DEFAULT_VERSION,\n };\n\n if (options.hasSkills) {\n manifest.skills = \"./skills/\";\n }\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n // Note: Claude Code plugins don't support agents field in manifest\n // Agents are discovered from ./agents/ directory automatically\n\n if (options.hasHooks) {\n manifest.hooks = \"./hooks/hooks.json\";\n }\n\n return manifest;\n}\n\nexport async function writePluginManifest(\n outputDir: string,\n manifest: PluginManifest,\n): Promise<string> {\n const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);\n\n await ensureDir(pluginDir);\n\n const content = JSON.stringify(manifest, null, 2);\n await writeFile(manifestPath, content);\n\n return manifestPath;\n}\n\nexport function getPluginDir(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME);\n}\n\nexport function getPluginManifestPath(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME, PLUGIN_MANIFEST_FILE);\n}\n","import path from \"path\";\n\nimport { PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE } from \"../../consts\";\nimport { fileExists } from \"../../utils/fs\";\n\n// Walks up from startDir looking for the plugin manifest file.\nexport async function findPluginManifest(startDir: string): Promise<string | null> {\n let currentDir = startDir;\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const manifestPath = path.join(currentDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n if (await fileExists(manifestPath)) {\n return manifestPath;\n }\n currentDir = path.dirname(currentDir);\n }\n\n return null;\n}\n","import os from \"os\";\nimport path from \"path\";\n\nimport { last, zip } from \"remeda\";\n\nimport { fileExists, readFileSafe, readFile, glob } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport {\n CLAUDE_DIR,\n DEFAULT_PLUGIN_NAME,\n MAX_PLUGIN_FILE_SIZE,\n PLUGINS_SUBDIR,\n PLUGIN_MANIFEST_DIR,\n PLUGIN_MANIFEST_FILE,\n} from \"../../consts\";\nimport type { MergedSkillsMatrix, PluginManifest, ResolvedSkill, SkillId } from \"../../types\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { pluginManifestSchema } from \"../schemas\";\n\nconst MAX_SKILL_NAME_LENGTH = 100;\n\nexport function getUserPluginsDir(): string {\n return path.join(os.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR);\n}\n\nexport function getCollectivePluginDir(projectDir?: string): string {\n const dir = projectDir ?? process.cwd();\n return path.join(dir, CLAUDE_DIR, PLUGINS_SUBDIR, DEFAULT_PLUGIN_NAME);\n}\n\nexport function getProjectPluginsDir(projectDir?: string): string {\n const dir = projectDir ?? process.cwd();\n return path.join(dir, CLAUDE_DIR, PLUGINS_SUBDIR);\n}\n\nexport function getPluginSkillsDir(pluginDir: string): string {\n return path.join(pluginDir, \"skills\");\n}\n\nexport function getPluginAgentsDir(pluginDir: string): string {\n return path.join(pluginDir, \"agents\");\n}\n\nexport function getPluginManifestPath(pluginDir: string): string {\n return path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n}\n\nexport async function readPluginManifest(pluginDir: string): Promise<PluginManifest | null> {\n const manifestPath = getPluginManifestPath(pluginDir);\n\n if (!(await fileExists(manifestPath))) {\n verbose(` No manifest at ${manifestPath}`);\n return null;\n }\n\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const manifest = pluginManifestSchema.parse(JSON.parse(content));\n\n if (!manifest.name || typeof manifest.name !== \"string\") {\n verbose(` Invalid manifest at ${manifestPath}: missing name`);\n return null;\n }\n\n return manifest;\n } catch (error) {\n verbose(` Failed to parse manifest at ${manifestPath}: ${error}`);\n return null;\n }\n}\n\nexport async function getPluginSkillIds(\n pluginSkillsDir: string,\n matrix: MergedSkillsMatrix,\n): Promise<SkillId[]> {\n const skillFiles = await glob(\"**/SKILL.md\", pluginSkillsDir);\n const skillIds: SkillId[] = [];\n\n const aliasToId = new Map<string, SkillId>();\n for (const [id, skill] of typedEntries<SkillId, ResolvedSkill>(matrix.skills)) {\n if (!skill) continue;\n if (skill.displayName) {\n aliasToId.set(skill.displayName.toLowerCase(), id);\n }\n }\n\n const dirToId = new Map<string, SkillId>();\n for (const [id] of typedEntries<SkillId, ResolvedSkill>(matrix.skills)) {\n const idParts = id.split(\"/\");\n const lastPart = last(idParts);\n if (lastPart) {\n dirToId.set(lastPart.toLowerCase(), id);\n }\n }\n\n const fileContents = await Promise.all(\n skillFiles.map((skillFile) => readFile(path.join(pluginSkillsDir, skillFile))),\n );\n\n for (const [skillFile, content] of zip(skillFiles, fileContents)) {\n const frontmatterMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (frontmatterMatch) {\n const frontmatter = frontmatterMatch[1];\n const nameMatch = frontmatter.match(/^name:\\s*[\"']?(.+?)[\"']?\\s*$/m);\n if (nameMatch) {\n const skillName = nameMatch[1].trim();\n if (skillName.length === 0) {\n warn(`Skipping plugin skill '${skillFile}': empty name in frontmatter`);\n continue;\n }\n if (skillName.length > MAX_SKILL_NAME_LENGTH) {\n warn(\n `Skipping plugin skill '${skillFile}': name exceeds ${MAX_SKILL_NAME_LENGTH} characters`,\n );\n continue;\n }\n if (matrix.skills[skillName as SkillId]) {\n skillIds.push(skillName as SkillId);\n continue;\n }\n const skillId = aliasToId.get(skillName.toLowerCase());\n if (skillId) {\n skillIds.push(skillId);\n continue;\n }\n }\n }\n\n const dirPath = path.dirname(skillFile);\n const dirName = path.basename(dirPath);\n const skillId = dirToId.get(dirName.toLowerCase());\n if (skillId) {\n skillIds.push(skillId);\n }\n }\n\n return skillIds;\n}\n","import { readdir } from \"fs/promises\";\n\nimport { DEFAULT_DISPLAY_VERSION, DEFAULT_PLUGIN_NAME } from \"../../consts\";\nimport { directoryExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { loadProjectConfig } from \"../configuration\";\nimport { detectInstallation, type InstallMode } from \"../installation\";\nimport { getProjectPluginsDir } from \"./plugin-finder\";\nimport { discoverAllPluginSkills, listPluginNames } from \"./plugin-discovery\";\n\nexport type PluginInfo = {\n name: string;\n version: string;\n skillCount: number;\n agentCount: number;\n path: string;\n};\n\nexport type InstallationInfo = {\n mode: InstallMode;\n name: string;\n version: string;\n skillCount: number;\n agentCount: number;\n configPath: string;\n agentsDir: string;\n skillsDir: string;\n};\n\nexport async function getPluginInfo(projectDir?: string): Promise<PluginInfo | null> {\n const dir = projectDir ?? process.cwd();\n\n try {\n const pluginNames = await listPluginNames(dir);\n if (pluginNames.length > 0) {\n return {\n name: DEFAULT_PLUGIN_NAME,\n version: DEFAULT_DISPLAY_VERSION,\n skillCount: pluginNames.length,\n agentCount: 0,\n path: getProjectPluginsDir(dir),\n };\n }\n } catch {\n verbose(\"Failed to list plugins for plugin info\");\n }\n\n return null;\n}\n\nexport function formatPluginDisplay(info: PluginInfo): string {\n return `Plugin: ${info.name} v${info.version}\n Skills: ${info.skillCount}\n Agents: ${info.agentCount}\n Path: ${info.path}`;\n}\n\nexport async function getInstallationInfo(): Promise<InstallationInfo | null> {\n const installation = await detectInstallation();\n\n if (!installation) {\n return null;\n }\n\n let skillCount = 0;\n let agentCount = 0;\n let name = DEFAULT_PLUGIN_NAME;\n let version = DEFAULT_DISPLAY_VERSION;\n\n if (installation.mode === \"plugin\") {\n // Plugin mode: discover skills via settings.json and global cache\n try {\n const pluginSkills = await discoverAllPluginSkills(installation.projectDir);\n skillCount = Object.keys(pluginSkills).length;\n } catch {\n // Ignore errors\n }\n } else if (await directoryExists(installation.skillsDir)) {\n try {\n const skills = await readdir(installation.skillsDir, {\n withFileTypes: true,\n });\n skillCount = skills.filter((s) => s.isDirectory()).length;\n } catch {\n // Ignore errors\n }\n }\n\n if (await directoryExists(installation.agentsDir)) {\n try {\n const agents = await readdir(installation.agentsDir, {\n withFileTypes: true,\n });\n agentCount = agents.filter((a) => a.isFile() && a.name.endsWith(\".md\")).length;\n } catch {\n // Ignore errors\n }\n }\n\n const loaded = await loadProjectConfig(installation.projectDir);\n if (loaded?.config) {\n name = loaded.config.name || DEFAULT_PLUGIN_NAME;\n version = installation.mode === \"local\" ? \"local\" : \"plugin\";\n }\n\n return {\n mode: installation.mode,\n name,\n version,\n skillCount,\n agentCount,\n configPath: installation.configPath,\n agentsDir: installation.agentsDir,\n skillsDir: installation.skillsDir,\n };\n}\n\nexport function formatInstallationDisplay(info: InstallationInfo): string {\n const modeLabel = info.mode === \"local\" ? \"Local\" : \"Plugin\";\n const versionDisplay = info.mode === \"local\" ? \"(local mode)\" : `v${info.version}`;\n\n return `Installation: ${info.name} ${versionDisplay}\n Mode: ${modeLabel}\n Skills: ${info.skillCount}\n Agents: ${info.agentCount}\n Config: ${info.configPath}\n Agents: ${info.agentsDir}`;\n}\n","export {\n type InstallMode,\n type Installation,\n detectInstallation,\n getInstallationOrThrow,\n} from \"./installation\";\n\nexport {\n type LocalInstallOptions,\n type LocalInstallResult,\n type PluginConfigResult,\n installLocal,\n installPluginConfig,\n} from \"./local-installer\";\n","import path from \"path\";\nimport { fileExists } from \"../../utils/fs\";\nimport { loadProjectConfig } from \"../configuration\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n CLI_BIN_NAME,\n DEFAULT_BRANDING,\n PLUGINS_SUBDIR,\n STANDARD_FILES,\n} from \"../../consts\";\n\nexport type InstallMode = \"local\" | \"plugin\";\n\nexport type Installation = {\n mode: InstallMode;\n configPath: string;\n agentsDir: string;\n skillsDir: string;\n projectDir: string;\n};\n\nexport async function detectInstallation(\n projectDir: string = process.cwd(),\n): Promise<Installation | null> {\n const srcConfigPath = path.join(projectDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_YAML);\n const legacyConfigPath = path.join(projectDir, CLAUDE_DIR, STANDARD_FILES.CONFIG_YAML);\n\n const localConfigPath = (await fileExists(srcConfigPath))\n ? srcConfigPath\n : (await fileExists(legacyConfigPath))\n ? legacyConfigPath\n : null;\n\n if (!localConfigPath) {\n return null;\n }\n\n const loaded = await loadProjectConfig(projectDir);\n\n const mode: InstallMode = loaded?.config?.installMode ?? \"local\";\n\n if (mode === \"local\") {\n return {\n mode: \"local\",\n configPath: localConfigPath,\n agentsDir: path.join(projectDir, CLAUDE_DIR, \"agents\"),\n skillsDir: path.join(projectDir, CLAUDE_DIR, \"skills\"),\n projectDir,\n };\n }\n\n // Skills live in global plugin cache; agents compiled locally\n return {\n mode: \"plugin\",\n configPath: localConfigPath,\n agentsDir: path.join(projectDir, CLAUDE_DIR, \"agents\"),\n skillsDir: path.join(projectDir, CLAUDE_DIR, PLUGINS_SUBDIR),\n projectDir,\n };\n}\n\nexport async function getInstallationOrThrow(\n projectDir: string = process.cwd(),\n): Promise<Installation> {\n const installation = await detectInstallation(projectDir);\n\n if (!installation) {\n throw new Error(\n `No ${DEFAULT_BRANDING.NAME} installation found.\\nRun '${CLI_BIN_NAME} init' to create one.`,\n );\n }\n\n return installation;\n}\n","import path from \"path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport type {\n AgentConfig,\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillDefinition,\n SkillId,\n Stack,\n} from \"../../types\";\nimport type { WizardResultV2 } from \"../../components/wizard/wizard\";\nimport { type CopiedSkill, copySkillsToLocalFlattened, archiveLocalSkill } from \"../skills\";\nimport { type MergeResult, mergeWithExistingConfig, DEFAULT_SOURCE } from \"../configuration\";\nimport { loadAllAgents, loadSkillsByIds, type SourceLoadResult } from \"../loading\";\nimport { loadStackById, compileAgentForPlugin, getStackSkillIds } from \"../stacks\";\nimport { resolveAgents, buildSkillRefsFromConfig } from \"../resolver\";\nimport { createLiquidEngine } from \"../compiler\";\nimport {\n generateProjectConfigFromSkills,\n compactStackForYaml,\n buildStackProperty,\n} from \"../configuration\";\nimport { ensureDir, writeFile } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n DEFAULT_PLUGIN_NAME,\n DIRS,\n LOCAL_SKILLS_PATH,\n PROJECT_ROOT,\n SCHEMA_PATHS,\n SKILLS_DIR_PATH,\n SKILLS_MATRIX_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n YAML_FORMATTING,\n yamlSchemaComment,\n} from \"../../consts\";\n\ntype LocalResolvedSkill = SkillDefinition & {\n content: string;\n};\n\n/**\n * Options for the local skill installation pipeline.\n *\n * Passed to {@link installLocal} to drive the full installation flow:\n * skill copying, config generation, agent compilation, and file writing.\n */\nexport type LocalInstallOptions = {\n /** Wizard output containing selected skills, stack, install mode, and source selections */\n wizardResult: WizardResultV2;\n /** Loaded source data including the skills matrix, source path, and source configuration */\n sourceResult: SourceLoadResult;\n /** Absolute path to the project root where `.claude/` artifacts will be written */\n projectDir: string;\n /** Optional `--source` flag override (e.g., \"github:org/repo\"). Takes precedence over\n * source from config when writing the `source` field in config.yaml */\n sourceFlag?: string;\n};\n\n/**\n * Result of a completed local skill installation.\n *\n * Returned by {@link installLocal} with details about what was written to disk,\n * enabling the caller to display a summary to the user.\n */\nexport type LocalInstallResult = {\n /** Skills that were copied to `.claude/skills/`, with source and destination paths */\n copiedSkills: CopiedSkill[];\n /** Final project configuration (may be merged with existing config.yaml) */\n config: ProjectConfig;\n /** Absolute path to the written config.yaml file */\n configPath: string;\n /** Agent names that were compiled and written to `.claude/agents/` */\n compiledAgents: AgentName[];\n /** Whether the config was merged with an existing config.yaml (true) or freshly created (false) */\n wasMerged: boolean;\n /** Absolute path to the pre-existing config.yaml that was merged, if any */\n mergedConfigPath?: string;\n /** Absolute path to the `.claude/skills/` directory */\n skillsDir: string;\n /** Absolute path to the `.claude/agents/` directory */\n agentsDir: string;\n};\n\ntype InstallPaths = {\n skillsDir: string;\n agentsDir: string;\n configPath: string;\n};\n\nfunction resolveInstallPaths(projectDir: string): InstallPaths {\n return {\n skillsDir: path.join(projectDir, LOCAL_SKILLS_PATH),\n agentsDir: path.join(projectDir, CLAUDE_DIR, \"agents\"),\n configPath: path.join(projectDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_YAML),\n };\n}\n\nasync function prepareDirectories(paths: InstallPaths): Promise<void> {\n await ensureDir(paths.skillsDir);\n await ensureDir(paths.agentsDir);\n await ensureDir(path.dirname(paths.configPath));\n}\n\nasync function archiveAndCopySkills(\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n projectDir: string,\n skillsDir: string,\n): Promise<CopiedSkill[]> {\n for (const skillId of wizardResult.selectedSkills) {\n const selectedSource = wizardResult.sourceSelections?.[skillId];\n if (selectedSource && selectedSource !== \"public\") {\n verbose(`Using alternate source '${selectedSource}' for ${skillId}`);\n await archiveLocalSkill(projectDir, skillId);\n }\n }\n\n return copySkillsToLocalFlattened(\n wizardResult.selectedSkills,\n skillsDir,\n sourceResult.matrix,\n sourceResult,\n );\n}\n\nfunction buildLocalSkillsMap(\n copiedSkills: CopiedSkill[],\n matrix: MergedSkillsMatrix,\n): Partial<Record<SkillId, LocalResolvedSkill>> {\n const localSkillsForResolution: Partial<Record<SkillId, LocalResolvedSkill>> = {};\n for (const copiedSkill of copiedSkills) {\n const skill = matrix.skills[copiedSkill.skillId];\n if (skill) {\n localSkillsForResolution[copiedSkill.skillId] = {\n id: copiedSkill.skillId,\n description: skill.description || \"\",\n path: copiedSkill.destPath,\n content: \"\", // Content not needed for skill references\n };\n }\n }\n return localSkillsForResolution;\n}\n\nasync function loadMergedAgents(sourcePath: string): Promise<Record<AgentName, AgentDefinition>> {\n const cliAgents = await loadAllAgents(PROJECT_ROOT);\n const sourceAgents = await loadAllAgents(sourcePath);\n // Boundary cast: loadAllAgents returns Record<string, AgentDefinition>, agent dirs are AgentName by convention\n return { ...cliAgents, ...sourceAgents } as Record<AgentName, AgentDefinition>;\n}\n\nasync function buildLocalConfig(\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n): Promise<{ config: ProjectConfig; loadedStack: Stack | null }> {\n verbose(\n `buildLocalConfig: selectedStackId='${wizardResult.selectedStackId}', ` +\n `selectedSkills=[${wizardResult.selectedSkills.join(\", \")}], ` +\n `selectedAgents=[${wizardResult.selectedAgents.join(\", \")}], ` +\n `installMode='${wizardResult.installMode}'`,\n );\n\n let loadedStack: Stack | null = null;\n if (wizardResult.selectedStackId) {\n loadedStack = await loadStackById(wizardResult.selectedStackId, sourceResult.sourcePath);\n if (!loadedStack) {\n loadedStack = await loadStackById(wizardResult.selectedStackId, PROJECT_ROOT);\n }\n verbose(\n `buildLocalConfig: loadedStack=${loadedStack ? `found (id='${loadedStack.id}')` : \"NOT FOUND\"}`,\n );\n }\n\n let localConfig: ProjectConfig;\n\n // Pass user's agent selection when they explicitly selected agents in the wizard\n const agentOptions =\n wizardResult.selectedAgents.length > 0\n ? { selectedAgents: wizardResult.selectedAgents }\n : undefined;\n\n if (wizardResult.selectedStackId) {\n if (loadedStack) {\n // Use actual selections (may differ from stack defaults after user customization)\n localConfig = generateProjectConfigFromSkills(\n DEFAULT_PLUGIN_NAME,\n wizardResult.selectedSkills,\n sourceResult.matrix,\n agentOptions,\n );\n\n // Overlay preloaded flags from the stack definition — generateProjectConfigFromSkills\n // defaults all skills to preloaded: false; the stack YAML may define preloaded: true\n if (localConfig.stack) {\n const stackProperty = buildStackProperty(loadedStack);\n for (const [agentId, agentConfig] of typedEntries(stackProperty)) {\n if (!agentConfig) continue;\n for (const [subcategory, assignments] of typedEntries(agentConfig)) {\n if (!assignments) continue;\n const localAgentConfig = localConfig.stack[agentId];\n if (!localAgentConfig?.[subcategory]) continue;\n for (const assignment of localAgentConfig[subcategory]) {\n const stackAssignment = assignments.find((a) => a.id === assignment.id);\n if (stackAssignment?.preloaded) {\n assignment.preloaded = true;\n }\n }\n }\n }\n }\n\n localConfig.description = loadedStack.description;\n // Only add stack agents that the user selected (or all if no explicit selection)\n const stackAgentIds = typedKeys<AgentName>(loadedStack.agents);\n for (const agentId of stackAgentIds) {\n if (\n !localConfig.agents.includes(agentId) &&\n (wizardResult.selectedAgents.length === 0 ||\n wizardResult.selectedAgents.includes(agentId))\n ) {\n localConfig.agents.push(agentId);\n }\n }\n localConfig.agents.sort();\n } else {\n throw new Error(\n `Stack '${wizardResult.selectedStackId}' not found in config/stacks.yaml. ` +\n `Available stacks are defined in the CLI's config/stacks.yaml file.`,\n );\n }\n } else {\n localConfig = generateProjectConfigFromSkills(\n DEFAULT_PLUGIN_NAME,\n wizardResult.selectedSkills,\n sourceResult.matrix,\n agentOptions,\n );\n }\n\n verbose(\n `buildLocalConfig result: stack=${localConfig.stack ? Object.keys(localConfig.stack).length + \" agents\" : \"UNDEFINED\"}, ` +\n `agents=[${localConfig.agents.join(\", \")}], skills=${localConfig.skills.length}`,\n );\n\n return { config: localConfig, loadedStack };\n}\n\nfunction setConfigMetadata(\n config: ProjectConfig,\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n sourceFlag?: string,\n): void {\n config.installMode = wizardResult.installMode;\n\n // Only persist expertMode when true (sparse YAML output)\n if (wizardResult.expertMode) {\n config.expertMode = true;\n }\n\n if (sourceFlag) {\n config.source = sourceFlag;\n } else if (sourceResult.sourceConfig.source) {\n config.source = sourceResult.sourceConfig.source;\n }\n\n if (sourceResult.marketplace) {\n config.marketplace = sourceResult.marketplace;\n }\n}\n\nasync function buildAndMergeConfig(\n wizardResult: WizardResultV2,\n sourceResult: SourceLoadResult,\n projectDir: string,\n sourceFlag?: string,\n): Promise<MergeResult> {\n const { config } = await buildLocalConfig(wizardResult, sourceResult);\n verbose(\n `buildAndMergeConfig: before merge — stack=${config.stack ? Object.keys(config.stack).length + \" agents\" : \"UNDEFINED\"}`,\n );\n setConfigMetadata(config, wizardResult, sourceResult, sourceFlag);\n const result = await mergeWithExistingConfig(config, { projectDir });\n verbose(\n `buildAndMergeConfig: after merge — stack=${result.config.stack ? Object.keys(result.config.stack).length + \" agents\" : \"UNDEFINED\"}, merged=${result.merged}`,\n );\n return result;\n}\n\n/** Commented-out config option hints appended to generated config.yaml for discoverability. */\nconst CONFIG_OPTIONS_COMMENT = [\n \"\",\n \"# Additional config options:\",\n `# source: ${DEFAULT_SOURCE}`,\n \"# marketplace: my-company\",\n \"# agentsSource: github:my-org/agents\",\n \"\",\n].join(\"\\n\");\n\n/** Commented-out path override hints appended to generated config.yaml for discoverability. */\nconst PATH_OVERRIDES_COMMENT = [\n \"\",\n \"# Custom paths (for marketplace repos with non-standard layouts):\",\n `# skillsDir: ${SKILLS_DIR_PATH}`,\n `# agentsDir: ${DIRS.agents}`,\n `# stacksFile: ${STACKS_FILE_PATH}`,\n `# matrixFile: ${SKILLS_MATRIX_PATH}`,\n \"\",\n].join(\"\\n\");\n\nasync function writeConfigFile(config: ProjectConfig, configPath: string): Promise<void> {\n const schemaComment = `${yamlSchemaComment(SCHEMA_PATHS.projectConfig)}\\n`;\n // Compact stack for YAML output: bare strings for simple skills, objects for preloaded\n const serializable = config.stack\n ? { ...config, stack: compactStackForYaml(config.stack) }\n : config;\n const configYaml = stringifyYaml(serializable, {\n indent: YAML_FORMATTING.INDENT,\n lineWidth: YAML_FORMATTING.LINE_WIDTH,\n });\n await writeFile(\n configPath,\n `${schemaComment}${configYaml}${CONFIG_OPTIONS_COMMENT}${PATH_OVERRIDES_COMMENT}`,\n );\n}\n\nfunction buildCompileAgents(\n config: ProjectConfig,\n agents: Record<AgentName, AgentDefinition>,\n): Record<AgentName, CompileAgentConfig> {\n const compileAgents: Record<AgentName, CompileAgentConfig> = {} as Record<\n AgentName,\n CompileAgentConfig\n >;\n for (const agentId of config.agents) {\n if (agents[agentId]) {\n const agentStack = config.stack?.[agentId];\n compileAgents[agentId] = agentStack ? { skills: buildSkillRefsFromConfig(agentStack) } : {};\n }\n }\n return compileAgents;\n}\n\nasync function compileAndWriteAgents(\n compileConfig: CompileConfig,\n agents: Record<AgentName, AgentDefinition>,\n localSkills: Partial<Record<SkillId, LocalResolvedSkill>>,\n sourceResult: SourceLoadResult,\n projectDir: string,\n agentsDir: string,\n installMode?: \"plugin\" | \"local\",\n): Promise<AgentName[]> {\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(\n agents,\n localSkills,\n compileConfig,\n sourceResult.sourcePath,\n );\n\n const compiledAgentNames: AgentName[] = [];\n for (const [name, agent] of typedEntries<AgentName, AgentConfig>(resolvedAgents)) {\n const output = await compileAgentForPlugin(\n name,\n agent,\n sourceResult.sourcePath,\n engine,\n installMode,\n );\n await writeFile(path.join(agentsDir, `${name}.md`), output);\n compiledAgentNames.push(name);\n }\n\n return compiledAgentNames;\n}\n\n/**\n * Result of a plugin config installation (no skill copying).\n *\n * Returned by {@link installPluginConfig} with details about what was written to disk,\n * enabling the caller to display a summary to the user.\n */\nexport type PluginConfigResult = {\n /** Final project configuration (may be merged with existing config.yaml) */\n config: ProjectConfig;\n /** Absolute path to the written config.yaml file */\n configPath: string;\n /** Agent names that were compiled and written to `.claude/agents/` */\n compiledAgents: AgentName[];\n /** Whether the config was merged with an existing config.yaml (true) or freshly created (false) */\n wasMerged: boolean;\n /** Absolute path to the pre-existing config.yaml that was merged, if any */\n mergedConfigPath?: string;\n /** Absolute path to the `.claude/agents/` directory */\n agentsDir: string;\n};\n\n/**\n * Generates config and compiles agents for plugin mode (without copying skills).\n *\n * Used when skills are installed as native plugins and should NOT be copied\n * to `.claude/skills/`. This function performs only:\n * 1. Creates `.claude/agents/` and `.claude-src/` directories\n * 2. Loads agent definitions from both the CLI and source repository\n * 3. Generates project config.yaml from the wizard selections, merging with any\n * existing config\n * 4. Writes config.yaml with YAML schema comment\n * 5. Compiles agent markdown files using Liquid templates and writes them to\n * `.claude/agents/`\n *\n * @param options - Installation options containing wizard result, source data,\n * project directory, and optional source flag override\n * @returns Result containing config and agent artifacts (no skills)\n * @throws {Error} If the selected stack ID is not found in config/stacks.yaml\n */\nexport async function installPluginConfig(\n options: LocalInstallOptions,\n): Promise<PluginConfigResult> {\n const { wizardResult, sourceResult, projectDir, sourceFlag } = options;\n\n const paths = resolveInstallPaths(projectDir);\n await ensureDir(paths.agentsDir);\n await ensureDir(path.dirname(paths.configPath));\n\n const agents = await loadMergedAgents(sourceResult.sourcePath);\n const mergeResult = await buildAndMergeConfig(wizardResult, sourceResult, projectDir, sourceFlag);\n const finalConfig = mergeResult.config;\n\n await writeConfigFile(finalConfig, paths.configPath);\n\n const compileAgentsConfig = buildCompileAgents(finalConfig, agents);\n const compileConfig: CompileConfig = {\n name: DEFAULT_PLUGIN_NAME,\n description:\n finalConfig.description || `Plugin setup with ${wizardResult.selectedSkills.length} skills`,\n agents: compileAgentsConfig,\n };\n // Load skill metadata from source for compilation\n // (actual skill content will be loaded from plugins at runtime)\n const stackSkillIds = finalConfig.stack ? getStackSkillIds(finalConfig.stack) : [];\n const skillsForCompilation = (await loadSkillsByIds(\n stackSkillIds.map((id) => ({ id })),\n sourceResult.sourcePath,\n )) as Partial<Record<SkillId, LocalResolvedSkill>>;\n\n const compiledAgentNames = await compileAndWriteAgents(\n compileConfig,\n agents,\n skillsForCompilation,\n sourceResult,\n projectDir,\n paths.agentsDir,\n wizardResult.installMode,\n );\n\n return {\n config: finalConfig,\n configPath: paths.configPath,\n compiledAgents: compiledAgentNames,\n wasMerged: mergeResult.merged,\n mergedConfigPath: mergeResult.existingConfigPath,\n agentsDir: paths.agentsDir,\n };\n}\n\n/**\n * Executes the full local skill installation pipeline.\n *\n * This is the main entry point for the \"local\" install mode (as opposed to plugin mode).\n * It performs the following steps in order:\n * 1. Creates `.claude/skills/` and `.claude/agents/` directories\n * 2. Archives local skills switching to alternate sources, then copies selected\n * skills from the source repository into `.claude/skills/` (flattened layout)\n * 3. Loads agent definitions from both the CLI and source repository\n * 4. Generates project config.yaml from the wizard selections, merging with any\n * existing config\n * 5. Writes config.yaml with YAML schema comment\n * 6. Compiles agent markdown files using Liquid templates and writes them to\n * `.claude/agents/`\n *\n * @param options - Installation options containing wizard result, source data,\n * project directory, and optional source flag override\n * @returns Result containing all written artifacts (skills, config, agents) and\n * metadata about the installation (merge status, paths)\n * @throws {Error} If the selected stack ID is not found in config/stacks.yaml\n *\n * @remarks\n * **Side effects:** Creates directories and writes files under `{projectDir}/.claude/`.\n * May archive existing local skills to `.claude/.archived-skills/` when source\n * selections differ from the current installation.\n */\nexport async function installLocal(options: LocalInstallOptions): Promise<LocalInstallResult> {\n const { wizardResult, sourceResult, projectDir, sourceFlag } = options;\n\n const paths = resolveInstallPaths(projectDir);\n await prepareDirectories(paths);\n\n const copiedSkills = await archiveAndCopySkills(\n wizardResult,\n sourceResult,\n projectDir,\n paths.skillsDir,\n );\n const localSkillsForResolution = buildLocalSkillsMap(copiedSkills, sourceResult.matrix);\n\n const agents = await loadMergedAgents(sourceResult.sourcePath);\n const mergeResult = await buildAndMergeConfig(wizardResult, sourceResult, projectDir, sourceFlag);\n const finalConfig = mergeResult.config;\n\n await writeConfigFile(finalConfig, paths.configPath);\n\n const compileAgentsConfig = buildCompileAgents(finalConfig, agents);\n const compileConfig: CompileConfig = {\n name: DEFAULT_PLUGIN_NAME,\n description:\n finalConfig.description || `Local setup with ${wizardResult.selectedSkills.length} skills`,\n agents: compileAgentsConfig,\n };\n const compiledAgentNames = await compileAndWriteAgents(\n compileConfig,\n agents,\n localSkillsForResolution,\n sourceResult,\n projectDir,\n paths.agentsDir,\n wizardResult.installMode,\n );\n\n return {\n copiedSkills,\n config: finalConfig,\n configPath: paths.configPath,\n compiledAgents: compiledAgentNames,\n wasMerged: mergeResult.merged,\n mergedConfigPath: mergeResult.existingConfigPath,\n skillsDir: paths.skillsDir,\n agentsDir: paths.agentsDir,\n };\n}\n","export {\n loadStacks,\n loadStackById,\n resolveAgentConfigToSkills,\n getStackSkillIds,\n resolveStackSkills,\n} from \"./stacks-loader\";\n\nexport {\n type StackInstallOptions,\n type StackInstallResult,\n compileStackToTemp,\n installStackAsPlugin,\n} from \"./stack-installer\";\n\nexport {\n type StackPluginOptions,\n type CompiledStackPlugin,\n compileAgentForPlugin,\n compileStackPlugin,\n printStackCompilationSummary,\n} from \"./stack-plugin-compiler\";\n","import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { mapValues, pipe, flatMap, unique } from \"remeda\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport type {\n AgentName,\n SkillAssignment,\n SkillId,\n SkillReference,\n Stack,\n StackAgentConfig,\n Subcategory,\n} from \"../../types\";\nimport { SKILL_ID_PATTERN, formatZodErrors, stacksConfigSchema } from \"../schemas\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { STACKS_FILE_PATH } from \"../../consts\";\n\nconst stacksCache = new Map<string, Stack[]>();\n\n/**\n * Normalizes a raw agent config (from Zod-parsed YAML) to StackAgentConfig.\n * Converts bare strings to `{ id, preloaded: false }` and wraps single values in arrays.\n * Used by both loadStacks() and loadProjectConfig() to handle all 3 YAML formats:\n * 1. bare string: `framework: web-framework-react`\n * 2. single object: `framework: { id: web-framework-react, preloaded: true }`\n * 3. array: `methodology: [{ id: ..., preloaded: true }, { id: ... }]`\n */\nexport function normalizeAgentConfig(agentConfig: Record<string, unknown>): StackAgentConfig {\n return mapValues(agentConfig, (value) => {\n const items = Array.isArray(value) ? value : [value];\n return items.map(\n (item): SkillAssignment =>\n typeof item === \"string\"\n ? { id: item as SkillId, preloaded: false }\n : (item as SkillAssignment),\n );\n }) as StackAgentConfig;\n}\n\n/**\n * Normalizes a raw stack record (agent -> raw subcategory config) to the typed form.\n * Applies normalizeAgentConfig to each agent entry.\n */\nexport function normalizeStackRecord(\n rawStack: Record<string, Record<string, unknown>>,\n): Record<string, StackAgentConfig> {\n return mapValues(rawStack, (agentConfig) => normalizeAgentConfig(agentConfig));\n}\n\nexport async function loadStacks(configDir: string, stacksFile?: string): Promise<Stack[]> {\n const resolvedStacksFile = stacksFile ?? STACKS_FILE_PATH;\n const cacheKey = `${configDir}:${resolvedStacksFile}`;\n const cached = stacksCache.get(cacheKey);\n if (cached) return cached;\n\n const stacksPath = path.join(configDir, resolvedStacksFile);\n\n if (!(await fileExists(stacksPath))) {\n verbose(`No stacks file found at ${stacksPath}`);\n return [];\n }\n\n try {\n const content = await readFile(stacksPath);\n const result = stacksConfigSchema.safeParse(parseYaml(content));\n\n if (!result.success) {\n throw new Error(\n `Invalid stacks.yaml at '${stacksPath}': ${formatZodErrors(result.error.issues)}`,\n );\n }\n\n // Normalize: all values to SkillAssignment[] so StackAgentConfig is always SkillAssignment[]\n const stacks: Stack[] = result.data.stacks.map((stack) => ({\n ...stack,\n agents: mapValues(\n stack.agents as Partial<Record<AgentName, Record<string, unknown>>>,\n (agentConfig) => normalizeAgentConfig(agentConfig as Record<string, unknown>),\n ) as Stack[\"agents\"],\n }));\n\n stacksCache.set(cacheKey, stacks);\n verbose(`Loaded ${stacks.length} stacks from ${stacksPath}`);\n\n return stacks;\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n throw new Error(`Failed to load stacks from '${stacksPath}': ${errorMessage}`);\n }\n}\n\nexport async function loadStackById(stackId: string, configDir: string): Promise<Stack | null> {\n const stacks = await loadStacks(configDir);\n const stack = stacks.find((s) => s.id === stackId);\n\n if (!stack) {\n verbose(`Stack '${stackId}' not found`);\n return null;\n }\n\n verbose(`Found stack: ${stack.name} (${stackId})`);\n return stack;\n}\n\n// Converts a StackAgentConfig (subcategory -> SkillAssignment[]) to an array of SkillReferences.\n// Values are already normalized to SkillAssignment[] by loadStacks().\nexport function resolveAgentConfigToSkills(agentConfig: StackAgentConfig): SkillReference[] {\n const skillRefs: SkillReference[] = [];\n\n for (const [subcategory, assignments] of typedEntries<Subcategory, SkillAssignment[]>(\n agentConfig,\n )) {\n if (!assignments) continue;\n\n for (const assignment of assignments) {\n if (!SKILL_ID_PATTERN.test(assignment.id)) {\n warn(\n `Invalid skill ID '${assignment.id}' for subcategory '${subcategory}' in stack config. Skipping.`,\n );\n continue;\n }\n\n skillRefs.push({\n id: assignment.id,\n usage: `when working with ${subcategory}`,\n preloaded: assignment.preloaded ?? false,\n });\n }\n }\n\n return skillRefs;\n}\n\n/** Extracts all unique skill IDs from a stack config (agent -> subcategory -> SkillAssignment[]). */\nexport function getStackSkillIds(stack: Record<string, StackAgentConfig>): SkillId[] {\n return pipe(\n Object.values(stack),\n flatMap(resolveAgentConfigToSkills),\n (refs) => refs.map((r) => r.id),\n unique(),\n );\n}\n\nexport function resolveStackSkills(stack: Stack): Record<string, SkillReference[]> {\n const result = mapValues(stack.agents, (agentConfig) => resolveAgentConfigToSkills(agentConfig));\n\n verbose(`Resolved skills for ${Object.keys(result).length} agents in stack '${stack.id}'`);\n\n return result;\n}\n","import path from \"path\";\nimport { Liquid } from \"liquidjs\";\nimport {\n readFile,\n readFileOptional,\n writeFile,\n ensureDir,\n copy,\n fileExists,\n directoryExists,\n} from \"../../utils/fs\";\nimport { log, verbose } from \"../../utils/logger\";\nimport { DEFAULT_BRANDING, DIRS, PROJECT_ROOT, STANDARD_FILES } from \"../../consts\";\nimport { createLiquidEngine, sanitizeCompiledAgentData } from \"../compiler\";\nimport {\n generateStackPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { loadSkillsByIds, loadAllAgents } from \"../loading\";\nimport { loadStackById, resolveAgentConfigToSkills, getStackSkillIds } from \"./stacks-loader\";\nimport { resolveAgents, convertStackToCompileConfig } from \"../resolver\";\nimport { buildStackProperty } from \"../configuration\";\nimport type {\n AgentConfig,\n AgentDefinition,\n AgentName,\n CompileConfig,\n CompiledAgentData,\n PluginManifest,\n ProjectConfig,\n SkillDefinition,\n SkillId,\n Stack,\n} from \"../../types\";\nimport { computeStringHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport { unique } from \"remeda\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object\";\n\nfunction hashStackConfig(stack: ProjectConfig): string {\n const stackSkillIds = stack.stack ? getStackSkillIds(stack.stack).sort() : [];\n const parts: string[] = [\n `name:${stack.name}`,\n `description:${stack.description ?? \"\"}`,\n `skills:${stackSkillIds.join(\",\")}`,\n `agents:${(stack.agents || []).sort().join(\",\")}`,\n ];\n return computeStringHash(parts.join(\"\\n\"));\n}\n\nexport type StackPluginOptions = {\n stackId: string;\n outputDir: string;\n projectRoot: string;\n agentSourcePath?: string;\n /** Optional stack configuration - if provided, bypasses loading from config/stacks.yaml */\n stack?: Stack;\n};\n\nexport type CompiledStackPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n stackName: string;\n agents: AgentName[];\n skillPlugins: SkillId[];\n hasHooks: boolean;\n};\n\nexport async function compileAgentForPlugin(\n name: AgentName,\n agent: AgentConfig,\n fallbackRoot: string,\n engine: Liquid,\n installMode?: \"plugin\" | \"local\",\n): Promise<string> {\n verbose(`Compiling agent: ${name}`);\n\n // Use agent's sourceRoot if available (for multi-source loading), otherwise fallback\n const agentSourceRoot = agent.sourceRoot || fallbackRoot;\n // Use agent's agentBaseDir if available (for project agents in .claude-src/agents/)\n const agentBaseDir = agent.agentBaseDir || DIRS.agents;\n const agentDir = path.join(agentSourceRoot, agentBaseDir, agent.path || name);\n\n const intro = await readFile(path.join(agentDir, STANDARD_FILES.INTRO_MD));\n const workflow = await readFile(path.join(agentDir, STANDARD_FILES.WORKFLOW_MD));\n const examples = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.EXAMPLES_MD),\n \"## Examples\\n\\n_No examples defined._\",\n );\n const criticalRequirementsTop = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REQUIREMENTS_MD),\n \"\",\n );\n const criticalReminders = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REMINDERS_MD),\n \"\",\n );\n\n const agentPath = agent.path || name;\n const category = agentPath.split(\"/\")[0];\n const categoryDir = path.join(agentSourceRoot, agentBaseDir, category);\n\n let outputFormat = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.OUTPUT_FORMAT_MD),\n \"\",\n );\n if (!outputFormat) {\n outputFormat = await readFileOptional(\n path.join(categoryDir, STANDARD_FILES.OUTPUT_FORMAT_MD),\n \"\",\n );\n }\n\n // In plugin mode, skills are installed as individual plugins — use pluginRef format.\n // Create new skill objects to avoid mutating the caller's data.\n const skills =\n installMode === \"plugin\"\n ? agent.skills.map((s) => ({ ...s, pluginRef: `${s.id}:${s.id}` as const }))\n : agent.skills;\n\n const preloadedSkills = skills.filter((s) => s.preloaded);\n const dynamicSkills = skills.filter((s) => !s.preloaded);\n const preloadedSkillIds = preloadedSkills.map((s) => s.pluginRef ?? s.id);\n\n verbose(\n `Skills for ${name}: ${preloadedSkills.length} preloaded, ${dynamicSkills.length} dynamic`,\n );\n\n const data: CompiledAgentData = {\n agent,\n intro,\n workflow,\n examples,\n criticalRequirementsTop,\n criticalReminders,\n outputFormat,\n skills,\n preloadedSkills,\n dynamicSkills,\n preloadedSkillIds,\n };\n\n return engine.renderFile(\"agent\", sanitizeCompiledAgentData(data));\n}\n\nfunction generateStackReadme(\n stackId: string,\n stack: ProjectConfig,\n agents: AgentName[],\n skillPlugins: SkillId[],\n): string {\n const lines: string[] = [];\n\n lines.push(`# ${stack.name}`);\n lines.push(\"\");\n lines.push(stack.description || \"A Claude Code stack plugin.\");\n lines.push(\"\");\n\n lines.push(\"## Installation\");\n lines.push(\"\");\n lines.push(\"Add this plugin to your Claude Code configuration:\");\n lines.push(\"\");\n lines.push(\"```json\");\n lines.push(\"{\");\n lines.push(` \"plugins\": [\"${stackId}\"]`);\n lines.push(\"}\");\n lines.push(\"```\");\n lines.push(\"\");\n\n lines.push(\"## Agents\");\n lines.push(\"\");\n lines.push(\"This stack includes the following agents:\");\n lines.push(\"\");\n for (const agent of agents) {\n lines.push(`- \\`${agent}\\``);\n }\n lines.push(\"\");\n\n if (skillPlugins.length > 0) {\n lines.push(\"## Included Skills\");\n lines.push(\"\");\n lines.push(\"This stack includes the following skills:\");\n lines.push(\"\");\n const uniqueSkills = unique(skillPlugins).sort();\n for (const skill of uniqueSkills) {\n lines.push(`- \\`${skill}\\``);\n }\n lines.push(\"\");\n }\n\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(`*Generated by ${DEFAULT_BRANDING.NAME} stack-plugin-compiler*`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n\nexport async function compileStackPlugin(\n options: StackPluginOptions,\n): Promise<CompiledStackPlugin> {\n const { stackId, outputDir, projectRoot, agentSourcePath } = options;\n const localAgentRoot = agentSourcePath || projectRoot;\n\n verbose(`Compiling stack plugin: ${stackId}`);\n verbose(` Stack/skills source: ${projectRoot}`);\n verbose(` Local agent source: ${localAgentRoot}`);\n verbose(` CLI agent source: ${PROJECT_ROOT}`);\n\n const cliAgents = await loadAllAgents(PROJECT_ROOT);\n const localAgents = await loadAllAgents(localAgentRoot);\n // Boundary cast: loadAllAgents returns Record<string, AgentDefinition>, agent dirs are AgentName by convention\n const agents = { ...cliAgents, ...localAgents } as Record<AgentName, AgentDefinition>;\n\n verbose(\n ` Loaded ${Object.keys(localAgents).length} local agents, ${Object.keys(cliAgents).length} CLI agents`,\n );\n\n let newStack = options.stack || (await loadStackById(stackId, projectRoot));\n if (!newStack) {\n newStack = await loadStackById(stackId, PROJECT_ROOT);\n }\n\n let stack: ProjectConfig;\n if (newStack) {\n verbose(` Found stack: ${newStack.name}`);\n\n const agentSkillIds = new Set<SkillId>();\n for (const agentName of typedKeys<AgentName>(newStack.agents)) {\n const agentConfig = newStack.agents[agentName];\n if (!agentConfig) continue;\n const skillRefs = resolveAgentConfigToSkills(agentConfig);\n for (const ref of skillRefs) {\n agentSkillIds.add(ref.id);\n }\n }\n\n stack = {\n name: newStack.name,\n description: newStack.description,\n agents: typedKeys<AgentName>(newStack.agents),\n skills: [...agentSkillIds],\n stack: buildStackProperty(newStack) as ProjectConfig[\"stack\"],\n };\n } else {\n throw new Error(`Stack '${stackId}' not found in config/stacks.yaml`);\n }\n\n const stackSkillIds = stack.stack ? getStackSkillIds(stack.stack) : [];\n // Boundary cast: loadSkillsByIds returns Record<string, SkillDefinition>, keys are SkillId by construction\n const skills = (await loadSkillsByIds(\n stackSkillIds.map((id) => ({ id })),\n projectRoot,\n )) as Record<SkillId, SkillDefinition>;\n\n const compileConfig: CompileConfig = convertStackToCompileConfig(stackId, stack);\n\n const resolvedAgents = await resolveAgents(agents, skills, compileConfig, projectRoot, newStack);\n\n const pluginDir = path.join(outputDir, stackId);\n const agentsDir = path.join(pluginDir, \"agents\");\n\n await ensureDir(pluginDir);\n await ensureDir(agentsDir);\n\n const pluginSkillsDir = path.join(pluginDir, \"skills\");\n await ensureDir(pluginSkillsDir);\n\n const copiedSourcePaths = new Set<string>();\n\n for (const resolvedSkill of Object.values(skills)) {\n const sourceSkillDir = path.join(projectRoot, resolvedSkill.path);\n\n if (copiedSourcePaths.has(resolvedSkill.path)) {\n continue;\n }\n\n const destSkillDir = path.join(pluginSkillsDir, resolvedSkill.id);\n\n if (await directoryExists(sourceSkillDir)) {\n await copy(sourceSkillDir, destSkillDir);\n copiedSourcePaths.add(resolvedSkill.path);\n verbose(` Copied skill: ${resolvedSkill.id}`);\n } else {\n verbose(` Warning: Skill directory not found: ${sourceSkillDir}`);\n }\n }\n\n const engine = await createLiquidEngine();\n\n const compiledAgentNames: AgentName[] = [];\n const allSkillPlugins: SkillId[] = [];\n\n for (const [name, agent] of typedEntries<AgentName, AgentConfig>(resolvedAgents)) {\n const output = await compileAgentForPlugin(name, agent, PROJECT_ROOT, engine);\n await writeFile(path.join(agentsDir, `${name}.md`), output);\n compiledAgentNames.push(name);\n\n for (const skill of agent.skills) {\n allSkillPlugins.push(skill.id);\n }\n\n verbose(` Compiled agent: ${name}`);\n }\n\n const stackDir = path.join(projectRoot, DIRS.stacks, stackId);\n const claudeMdPath = path.join(stackDir, STANDARD_FILES.CLAUDE_MD);\n if (await fileExists(claudeMdPath)) {\n const claudeContent = await readFile(claudeMdPath);\n await writeFile(path.join(pluginDir, STANDARD_FILES.CLAUDE_MD), claudeContent);\n verbose(` Copied ${STANDARD_FILES.CLAUDE_MD}`);\n }\n\n const newHash = hashStackConfig(stack);\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const uniqueSkillPlugins = unique(allSkillPlugins);\n const manifest = generateStackPluginManifest({\n stackName: stackId,\n description: stack.description,\n author: stack.author,\n version,\n keywords: undefined,\n hasAgents: true,\n hasHooks: false,\n hasSkills: true,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json (v${version})`);\n\n const readme = generateStackReadme(stackId, stack, compiledAgentNames, uniqueSkillPlugins);\n await writeFile(path.join(pluginDir, \"README.md\"), readme);\n verbose(\" Generated README.md\");\n\n return {\n pluginPath: pluginDir,\n manifest,\n stackName: stack.name,\n agents: compiledAgentNames,\n skillPlugins: uniqueSkillPlugins,\n hasHooks: false,\n };\n}\n\nexport function printStackCompilationSummary(result: CompiledStackPlugin): void {\n log(`\\nStack plugin compiled: ${result.stackName}`);\n log(` Path: ${result.pluginPath}`);\n log(` Agents: ${result.agents.length}`);\n for (const agent of result.agents) {\n log(` - ${agent}`);\n }\n if (result.skillPlugins.length > 0) {\n log(` Skills included: ${result.skillPlugins.length}`);\n for (const skill of result.skillPlugins) {\n log(` - ${skill}`);\n }\n }\n if (result.hasHooks) {\n log(\" Hooks: enabled\");\n }\n}\n","import { Liquid } from \"liquidjs\";\nimport path from \"path\";\nimport { pipe, flatMap, filter, uniqueBy } from \"remeda\";\nimport {\n readFile,\n readFileOptional,\n writeFile,\n ensureDir,\n remove,\n copy,\n glob,\n fileExists,\n directoryExists,\n} from \"../utils/fs\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { log, verbose, warn } from \"../utils/logger\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n DIRS,\n PROJECT_ROOT,\n STANDARD_FILES,\n STANDARD_DIRS,\n} from \"../consts\";\nimport { resolveClaudeMd } from \"./resolver\";\nimport { validateCompiledAgent, printOutputValidationResult } from \"./output-validator\";\nimport type { AgentConfig, AgentName, CompiledAgentData, CompileContext, Skill } from \"../types\";\nimport { typedEntries } from \"../utils/typed-object\";\n\n/** Pattern matching Liquid template delimiters that could enable template injection */\nconst LIQUID_SYNTAX_PATTERN = /\\{\\{|\\}\\}|\\{%|%\\}/g;\n\n/**\n * Strips Liquid template syntax (`{{`, `}}`, `{%`, `%}`) from a string value.\n * Prevents template injection when user-controlled data is passed to the Liquid engine.\n *\n * @param value - Input string that may contain Liquid syntax\n * @param fieldName - Name of the field (for warning messages)\n * @returns Sanitized string with Liquid delimiters removed\n */\nexport function sanitizeLiquidSyntax(value: string, fieldName: string): string {\n if (!LIQUID_SYNTAX_PATTERN.test(value)) return value;\n LIQUID_SYNTAX_PATTERN.lastIndex = 0;\n const sanitized = value.replace(LIQUID_SYNTAX_PATTERN, \"\");\n warn(`Stripped Liquid template syntax from '${fieldName}' — possible template injection attempt`);\n return sanitized;\n}\n\nfunction sanitizeString(value: string | undefined, fieldName: string): string | undefined {\n if (value === undefined) return undefined;\n return sanitizeLiquidSyntax(value, fieldName);\n}\n\nfunction sanitizeStringArray(\n values: string[] | undefined,\n fieldName: string,\n): string[] | undefined {\n if (!values) return values;\n return values.map((v) => sanitizeLiquidSyntax(v, fieldName));\n}\n\nfunction sanitizeSkills(skills: Skill[]): Skill[] {\n return skills.map((s) => ({\n ...s,\n id: sanitizeLiquidSyntax(s.id, \"skill.id\") as Skill[\"id\"],\n description: sanitizeLiquidSyntax(s.description, \"skill.description\"),\n usage: sanitizeLiquidSyntax(s.usage, \"skill.usage\"),\n pluginRef: sanitizeString(s.pluginRef, \"skill.pluginRef\") as Skill[\"pluginRef\"],\n }));\n}\n\n/**\n * Sanitizes all user-controlled fields in compiled agent data to prevent\n * Liquid template injection. Strips `{{`, `}}`, `{%`, `%}` from agent\n * metadata, skill metadata, and file content before template rendering.\n */\nexport function sanitizeCompiledAgentData(data: CompiledAgentData): CompiledAgentData {\n const sanitizedAgent: AgentConfig = {\n ...data.agent,\n name: sanitizeLiquidSyntax(data.agent.name, \"agent.name\"),\n title: sanitizeLiquidSyntax(data.agent.title, \"agent.title\"),\n description: sanitizeLiquidSyntax(data.agent.description, \"agent.description\"),\n tools: sanitizeStringArray(data.agent.tools, \"agent.tools\") ?? data.agent.tools,\n disallowedTools: sanitizeStringArray(data.agent.disallowedTools, \"agent.disallowedTools\"),\n model: sanitizeString(data.agent.model, \"agent.model\") as AgentConfig[\"model\"],\n permissionMode: sanitizeString(\n data.agent.permissionMode,\n \"agent.permissionMode\",\n ) as AgentConfig[\"permissionMode\"],\n };\n\n const sanitizedSkills = sanitizeSkills(data.skills);\n const sanitizedPreloaded = sanitizeSkills(data.preloadedSkills);\n const sanitizedDynamic = sanitizeSkills(data.dynamicSkills);\n const sanitizedPreloadedIds = data.preloadedSkillIds.map(\n (id) => sanitizeLiquidSyntax(String(id), \"preloadedSkillId\") as typeof id,\n );\n\n return {\n agent: sanitizedAgent,\n intro: sanitizeLiquidSyntax(data.intro, \"intro\"),\n workflow: sanitizeLiquidSyntax(data.workflow, \"workflow\"),\n examples: sanitizeLiquidSyntax(data.examples, \"examples\"),\n criticalRequirementsTop: sanitizeLiquidSyntax(\n data.criticalRequirementsTop,\n \"criticalRequirementsTop\",\n ),\n criticalReminders: sanitizeLiquidSyntax(data.criticalReminders, \"criticalReminders\"),\n outputFormat: sanitizeLiquidSyntax(data.outputFormat, \"outputFormat\"),\n skills: sanitizedSkills,\n preloadedSkills: sanitizedPreloaded,\n dynamicSkills: sanitizedDynamic,\n preloadedSkillIds: sanitizedPreloadedIds,\n };\n}\n\ntype AgentFiles = {\n intro: string;\n workflow: string;\n examples: string;\n criticalRequirementsTop: string;\n criticalReminders: string;\n outputFormat: string;\n};\n\nasync function readAgentFiles(\n name: AgentName,\n agent: AgentConfig,\n projectRoot: string,\n): Promise<AgentFiles> {\n const agentSourceRoot = agent.sourceRoot || projectRoot;\n const agentBaseDir = agent.agentBaseDir || DIRS.agents;\n const agentDir = path.join(agentSourceRoot, agentBaseDir, agent.path || name);\n\n const intro = await readFile(path.join(agentDir, STANDARD_FILES.INTRO_MD));\n const workflow = await readFile(path.join(agentDir, STANDARD_FILES.WORKFLOW_MD));\n const examples = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.EXAMPLES_MD),\n \"## Examples\\n\\n_No examples defined._\",\n );\n const criticalRequirementsTop = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REQUIREMENTS_MD),\n \"\",\n );\n const criticalReminders = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REMINDERS_MD),\n \"\",\n );\n\n const agentPath = agent.path || name;\n const parts = agentPath.split(\"/\");\n const category = parts[0] || name;\n const categoryDir = path.join(agentSourceRoot, agentBaseDir, category);\n\n let outputFormat = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.OUTPUT_FORMAT_MD),\n \"\",\n );\n if (!outputFormat) {\n outputFormat = await readFileOptional(\n path.join(categoryDir, STANDARD_FILES.OUTPUT_FORMAT_MD),\n \"\",\n );\n }\n\n return { intro, workflow, examples, criticalRequirementsTop, criticalReminders, outputFormat };\n}\n\nfunction buildAgentTemplateContext(\n name: AgentName,\n agent: AgentConfig,\n files: AgentFiles,\n): CompiledAgentData {\n const preloadedSkills = agent.skills.filter((s) => s.preloaded);\n const dynamicSkills = agent.skills.filter((s) => !s.preloaded);\n const preloadedSkillIds = preloadedSkills.map((s) => s.id);\n\n verbose(\n `Skills for ${name}: ${preloadedSkills.length} preloaded, ${dynamicSkills.length} dynamic`,\n );\n\n return {\n agent,\n ...files,\n skills: agent.skills,\n preloadedSkills,\n dynamicSkills,\n preloadedSkillIds,\n };\n}\n\n/**\n * Compiles a single agent into a rendered Markdown prompt by reading its\n * constituent files (intro, workflow, examples, critical requirements/reminders,\n * output format) and rendering them through a Liquid template.\n *\n * Skills are split into preloaded (content embedded in the compiled agent) and\n * dynamic (loaded via Skill tool at runtime). Output format resolution falls back\n * from the agent-specific directory to the parent category directory.\n *\n * @param name - Agent identifier used for logging and as a directory name fallback\n * @param agent - Fully resolved agent config including skills, paths, and optional sourceRoot\n * @param projectRoot - Root directory of the project (used as base for agent file resolution)\n * @param engine - Pre-configured Liquid template engine with template roots\n * @returns Rendered Markdown string ready to be written to the output directory\n * @throws When required agent files (intro.md, workflow.md) are missing from disk\n */\nasync function compileAgent(\n name: AgentName,\n agent: AgentConfig,\n projectRoot: string,\n engine: Liquid,\n): Promise<string> {\n verbose(`Reading agent files for ${name}...`);\n const files = await readAgentFiles(name, agent, projectRoot);\n const data = buildAgentTemplateContext(name, agent, files);\n\n verbose(`Rendering template for ${name}...`);\n return engine.renderFile(\"agent\", sanitizeCompiledAgentData(data));\n}\n\n/**\n * Compiles all resolved agents into Markdown files and writes them to the output directory.\n *\n * Each agent is compiled via `compileAgent()`, validated for structural issues\n * (missing sections, placeholder text), and written to `{outputDir}/agents/{name}.md`.\n * Validation warnings are printed but do not prevent compilation.\n *\n * @param resolvedAgents - Map of agent names to fully resolved agent configs with skills\n * @param ctx - Compilation context providing projectRoot and outputDir paths\n * @param engine - Pre-configured Liquid template engine\n * @throws When any agent fails to compile (missing files, template errors)\n */\nexport async function compileAllAgents(\n resolvedAgents: Record<AgentName, AgentConfig>,\n ctx: CompileContext,\n engine: Liquid,\n): Promise<void> {\n const outDir = path.join(ctx.outputDir, \"agents\");\n await ensureDir(outDir);\n\n let hasValidationIssues = false;\n\n for (const [name, agent] of typedEntries<AgentName, AgentConfig>(resolvedAgents)) {\n try {\n const output = await compileAgent(name, agent, ctx.projectRoot, engine);\n await writeFile(path.join(outDir, `${name}.md`), output);\n log(` ✓ ${name}.md`);\n\n const validationResult = validateCompiledAgent(output);\n if (!validationResult.valid || validationResult.warnings.length > 0) {\n hasValidationIssues = true;\n printOutputValidationResult(name, validationResult);\n }\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile '${name}': ${errorMessage}`);\n throw new Error(\n `Failed to compile agent '${name}': ${errorMessage}. Check that all required files exist in src/agents/${agent.path || name}/`,\n );\n }\n }\n\n if (hasValidationIssues) {\n log(\"\");\n }\n}\n\n/**\n * Copies all skill files referenced by resolved agents into the output directory.\n *\n * Deduplicates skills across agents (by skill ID) and copies each skill's\n * content to `{outputDir}/skills/{id}/`. For folder-based skills, copies\n * SKILL.md, optional reference.md, examples/, and scripts/ subdirectories.\n * For single-file skills, copies the file as SKILL.md.\n *\n * @param resolvedAgents - Map of agent names to configs (skills extracted from all agents)\n * @param ctx - Compilation context providing projectRoot and outputDir paths\n * @throws When a skill file or directory is missing from the expected source path\n */\nexport async function compileAllSkills(\n resolvedAgents: Record<AgentName, AgentConfig>,\n ctx: CompileContext,\n): Promise<void> {\n const allSkills = pipe(\n Object.values(resolvedAgents),\n flatMap((a) => a.skills),\n filter((s) => Boolean(s.path)),\n );\n\n const uniqueSkills = uniqueBy(allSkills, (s) => s.id);\n\n for (const skill of uniqueSkills) {\n const id = skill.id.replace(\"/\", \"-\");\n const outDir = path.join(ctx.outputDir, \"skills\", id);\n await ensureDir(outDir);\n\n const sourcePath = path.join(ctx.projectRoot, skill.path);\n const isFolder = skill.path.endsWith(\"/\");\n\n try {\n if (isFolder) {\n const mainContent = await readFile(path.join(sourcePath, STANDARD_FILES.SKILL_MD));\n await writeFile(path.join(outDir, STANDARD_FILES.SKILL_MD), mainContent);\n log(` ✓ skills/${id}/${STANDARD_FILES.SKILL_MD}`);\n\n const referenceContent = await readFileOptional(\n path.join(sourcePath, STANDARD_FILES.REFERENCE_MD),\n );\n if (referenceContent) {\n await writeFile(path.join(outDir, STANDARD_FILES.REFERENCE_MD), referenceContent);\n log(` ✓ skills/${id}/${STANDARD_FILES.REFERENCE_MD}`);\n }\n\n const examplesDir = path.join(sourcePath, STANDARD_DIRS.EXAMPLES);\n if (await fileExists(examplesDir)) {\n await copy(examplesDir, path.join(outDir, STANDARD_DIRS.EXAMPLES));\n log(` ✓ skills/${id}/${STANDARD_DIRS.EXAMPLES}/`);\n }\n\n const scriptsDir = path.join(sourcePath, STANDARD_DIRS.SCRIPTS);\n if (await fileExists(scriptsDir)) {\n await copy(scriptsDir, path.join(outDir, STANDARD_DIRS.SCRIPTS));\n log(` ✓ skills/${id}/${STANDARD_DIRS.SCRIPTS}/`);\n }\n } else {\n const content = await readFile(sourcePath);\n await writeFile(path.join(outDir, STANDARD_FILES.SKILL_MD), content);\n log(` ✓ skills/${id}/${STANDARD_FILES.SKILL_MD}`);\n }\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile skill '${id}': ${errorMessage}`);\n throw new Error(\n `Failed to compile skill '${skill.id}': ${errorMessage}. Expected skill at: ${sourcePath}`,\n );\n }\n }\n}\n\n/**\n * Copies the stack-specific CLAUDE.md file to the compilation output directory.\n *\n * Resolves the CLAUDE.md path from the stack directory, reads its content, and\n * writes it to the parent of the output directory (alongside the agents/ folder).\n *\n * @param ctx - Compilation context with stackId, projectRoot, and outputDir\n * @throws When the stack's CLAUDE.md file is missing\n */\nexport async function copyClaudeMdToOutput(ctx: CompileContext): Promise<void> {\n const claudePath = await resolveClaudeMd(ctx.projectRoot, ctx.stackId);\n\n const content = await readFile(claudePath);\n const outputPath = path.join(ctx.outputDir, \"..\", STANDARD_FILES.CLAUDE_MD);\n await writeFile(outputPath, content);\n log(` ✓ ${STANDARD_FILES.CLAUDE_MD} (from stack)`);\n}\n\n/**\n * Copies all custom command Markdown files from the commands source directory\n * to the compilation output directory.\n *\n * Skips gracefully if no commands directory exists or contains no .md files.\n *\n * @param ctx - Compilation context with projectRoot and outputDir\n * @throws When a command file exists but cannot be read or written\n */\nexport async function compileAllCommands(ctx: CompileContext): Promise<void> {\n const commandsDir = path.join(ctx.projectRoot, DIRS.commands);\n const outDir = path.join(ctx.outputDir, \"commands\");\n\n if (!(await fileExists(commandsDir))) {\n log(\" - No commands directory found, skipping...\");\n return;\n }\n\n const files = await glob(\"*.md\", commandsDir);\n\n if (files.length === 0) {\n log(\" - No commands found, skipping...\");\n return;\n }\n\n await ensureDir(outDir);\n\n for (const file of files) {\n try {\n const content = await readFile(path.join(commandsDir, file));\n await writeFile(path.join(outDir, file), content);\n log(` ✓ ${file}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile command '${file}': ${errorMessage}`);\n throw new Error(\n `Failed to compile command '${file}': ${errorMessage}. Expected at: ${path.join(commandsDir, file)}`,\n );\n }\n }\n}\n\n/**\n * Creates a Liquid template engine with a layered template root hierarchy.\n *\n * Template resolution order (first match wins):\n * 1. Project-local templates: `{projectDir}/.claude-src/agents/_templates/`\n * 2. Legacy templates: `{projectDir}/.claude/templates/`\n * 3. Built-in templates: `{PROJECT_ROOT}/templates/`\n *\n * @param projectDir - Optional project directory for local template overrides\n * @returns Configured Liquid engine with `.liquid` extension and strict filters\n */\nexport async function createLiquidEngine(projectDir?: string): Promise<Liquid> {\n const roots: string[] = [];\n\n if (projectDir) {\n const srcTemplatesDir = path.join(projectDir, CLAUDE_SRC_DIR, \"agents\", \"_templates\");\n if (await directoryExists(srcTemplatesDir)) {\n roots.push(srcTemplatesDir);\n verbose(`Using local templates from: ${srcTemplatesDir}`);\n }\n\n const legacyTemplatesDir = path.join(projectDir, CLAUDE_DIR, \"templates\");\n if (await directoryExists(legacyTemplatesDir)) {\n roots.push(legacyTemplatesDir);\n verbose(`Using legacy templates from: ${legacyTemplatesDir}`);\n }\n }\n\n roots.push(path.join(PROJECT_ROOT, DIRS.templates));\n\n return new Liquid({\n root: roots,\n extname: \".liquid\",\n strictVariables: false,\n strictFilters: true,\n });\n}\n\n/** Removes the agents/, skills/, and commands/ subdirectories from the output directory. */\nexport async function removeCompiledOutputDirs(outputDir: string): Promise<void> {\n await remove(path.join(outputDir, \"agents\"));\n await remove(path.join(outputDir, \"skills\"));\n await remove(path.join(outputDir, \"commands\"));\n}\n","import path from \"path\";\nimport { fileExists } from \"../utils/fs\";\nimport { DIRS, STANDARD_FILES } from \"../consts\";\nimport { verbose } from \"../utils/logger\";\nimport type {\n AgentConfig,\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n ProjectConfig,\n Skill,\n SkillDefinition,\n SkillId,\n SkillReference,\n Stack,\n StackAgentConfig,\n Subcategory,\n} from \"../types\";\nimport { typedKeys } from \"../utils/typed-object\";\nimport { resolveAgentConfigToSkills } from \"./stacks/stacks-loader\";\n\nexport async function resolveClaudeMd(projectRoot: string, stackId: string): Promise<string> {\n const stackClaude = path.join(projectRoot, DIRS.stacks, stackId, STANDARD_FILES.CLAUDE_MD);\n if (await fileExists(stackClaude)) return stackClaude;\n\n throw new Error(\n `Stack '${stackId}' is missing required ${STANDARD_FILES.CLAUDE_MD} file. Expected at: ${stackClaude}`,\n );\n}\n\nexport function resolveSkillReference(\n ref: SkillReference,\n skills: Partial<Record<SkillId, SkillDefinition>>,\n): Skill | null {\n const definition = skills[ref.id];\n if (!definition) {\n verbose(`Skill '${ref.id}' not found in available skills, skipping`);\n return null;\n }\n return {\n ...definition,\n usage: ref.usage,\n preloaded: ref.preloaded ?? false,\n };\n}\n\nexport function resolveSkillReferences(\n skillRefs: SkillReference[],\n skills: Partial<Record<SkillId, SkillDefinition>>,\n): Skill[] {\n return skillRefs\n .map((ref) => resolveSkillReference(ref, skills))\n .filter((skill): skill is Skill => skill !== null);\n}\n\n/**\n * Builds skill references from a ProjectConfig stack mapping (agent -> subcategory -> SkillAssignment[]).\n *\n * Values are normalized to SkillAssignment[] at load time (by normalizeStackRecord in project-config.ts).\n * Preserves preloaded flags from skill assignments.\n *\n * @param agentStack - Subcategory-to-SkillAssignment[] mapping from ProjectConfig.stack for one agent\n * @returns Skill references with usage hints derived from subcategory names\n */\nexport function buildSkillRefsFromConfig(agentStack: StackAgentConfig): SkillReference[] {\n return resolveAgentConfigToSkills(agentStack);\n}\n\n/**\n * Resolves skill references for an agent from a Stack definition.\n *\n * Stack values are already SkillAssignment[] normalized by loadStacks().\n * Returns an empty array if the agent is not present in the stack or has\n * no technology-specific skills configured.\n *\n * @param agentName - Agent to resolve skills for\n * @param stack - Loaded stack definition with normalized skill assignments\n * @returns Skill references with usage and preloaded flags from the stack\n */\nexport function resolveAgentSkillsFromStack(agentName: AgentName, stack: Stack): SkillReference[] {\n const agentConfig = stack.agents[agentName];\n\n if (!agentConfig) {\n verbose(`Agent '${agentName}' not found in stack '${stack.id}'`);\n return [];\n }\n\n // Empty config {} means agent has no technology-specific skills\n if (typedKeys<Subcategory>(agentConfig).length === 0) {\n verbose(`Agent '${agentName}' has no technology config in stack '${stack.id}'`);\n return [];\n }\n\n const skillRefs = resolveAgentConfigToSkills(agentConfig);\n\n verbose(`Resolved ${skillRefs.length} skills for agent '${agentName}' from stack '${stack.id}'`);\n\n return skillRefs;\n}\n\n/**\n * Resolves skill references for an agent using a priority hierarchy.\n *\n * Priority order:\n * 1. Explicit skills defined in the agent's compile config\n * 2. Skills derived from the stack definition\n *\n * @param agentName - Agent to resolve skills for\n * @param agentConfig - Compile-time agent config (may contain explicit skills)\n * @param stack - Optional stack definition for fallback skill resolution\n * @returns Skill references from the highest-priority source, or empty array\n */\nexport async function resolveAgentSkillRefs(\n agentName: AgentName,\n agentConfig: CompileAgentConfig,\n stack?: Stack,\n): Promise<SkillReference[]> {\n // Priority 1: Explicit skills in compile config\n if (agentConfig.skills && agentConfig.skills.length > 0) {\n return agentConfig.skills;\n }\n\n // Priority 2: Stack-based skills — values are already skill IDs\n if (stack) {\n const stackSkills = resolveAgentSkillsFromStack(agentName, stack);\n if (stackSkills.length > 0) {\n verbose(`Resolved ${stackSkills.length} skills from stack for ${agentName}`);\n return stackSkills;\n }\n }\n\n return [];\n}\n\n/**\n * Resolves all agents referenced in a compile config into fully populated AgentConfigs\n * with their skill lists materialized from definitions.\n *\n * For each agent in `compileConfig.agents`, this function:\n * 1. Validates the agent exists in the scanned agent definitions\n * 2. Resolves skill references (from explicit config or stack fallback)\n * 3. Materializes skill references into full Skill objects using the skill definitions map\n * 4. Merges the agent definition with its resolved skills into an AgentConfig\n *\n * @param agents - Available agent definitions keyed by name (from scanning agent directories)\n * @param skills - Available skill definitions keyed by ID (from scanning skill directories)\n * @param compileConfig - Compilation config specifying which agents to compile and their overrides\n * @param _projectRoot - Project root directory (currently unused, reserved for future use)\n * @param stack - Optional stack definition for stack-based skill resolution\n * @returns Map of agent names to fully resolved AgentConfig objects ready for compilation\n * @throws When an agent referenced in compileConfig is not found in scanned agents\n */\nexport async function resolveAgents(\n agents: Record<AgentName, AgentDefinition>,\n skills: Partial<Record<SkillId, SkillDefinition>>,\n compileConfig: CompileConfig,\n _projectRoot: string,\n stack?: Stack,\n): Promise<Record<AgentName, AgentConfig>> {\n // Store initialization: accumulator filled below for each agent in compileConfig\n const resolved: Record<AgentName, AgentConfig> = {} as Record<AgentName, AgentConfig>;\n const agentNames = typedKeys<AgentName>(compileConfig.agents);\n\n for (const agentName of agentNames) {\n const definition = agents[agentName];\n if (!definition) {\n const availableAgents = typedKeys<AgentName>(agents);\n const agentList =\n availableAgents.length > 0\n ? `Available agents: ${availableAgents.slice(0, 5).join(\", \")}${availableAgents.length > 5 ? ` (and ${availableAgents.length - 5} more)` : \"\"}`\n : \"No agents found in scanned directories\";\n throw new Error(\n `Agent '${agentName}' referenced in compile config but not found in scanned agents. ${agentList}. Check that src/agents/${agentName}/agent.yaml exists.`,\n );\n }\n\n const agentConfig = compileConfig.agents[agentName];\n\n const skillRefs = await resolveAgentSkillRefs(agentName, agentConfig, stack);\n\n const resolvedSkills = resolveSkillReferences(skillRefs, skills);\n\n resolved[agentName] = {\n name: agentName,\n title: definition.title,\n description: definition.description,\n model: definition.model,\n tools: definition.tools,\n skills: resolvedSkills,\n path: definition.path,\n sourceRoot: definition.sourceRoot,\n agentBaseDir: definition.agentBaseDir,\n };\n }\n\n return resolved;\n}\n\nexport function convertStackToCompileConfig(stackId: string, stack: ProjectConfig): CompileConfig {\n // Store initialization: accumulator filled below for each agent in stack\n const agents: Record<AgentName, CompileAgentConfig> = {} as Record<AgentName, CompileAgentConfig>;\n\n for (const agentId of stack.agents) {\n agents[agentId] = {};\n }\n\n return {\n name: stack.name,\n description: stack.description || \"\",\n stack: stackId,\n agents,\n };\n}\n","import { parse as parseYaml } from \"yaml\";\n\nexport function extractFrontmatter(content: string): unknown | null {\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/;\n const match = content.match(frontmatterRegex);\n\n if (!match || !match[1]) {\n return null;\n }\n\n try {\n return parseYaml(match[1]);\n } catch {\n return null;\n }\n}\n","import type { SkillDefinition, SkillId } from \"../../types\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport { loadPluginSkills } from \"../loading\";\nimport { getVerifiedPluginInstallPaths } from \"./plugin-settings\";\n\n/**\n * Discovers all plugin-installed skills from enabled plugins.\n *\n * Reads `.claude/settings.json` to find enabled plugins, then looks up their\n * install paths in the global plugin registry (`~/.claude/plugins/installed_plugins.json`).\n * Loads skills from the plugin cache directories.\n *\n * @param projectDir - Absolute path to the project root\n * @returns Merged map of all discovered plugin skills (later plugins override earlier)\n */\nexport async function discoverAllPluginSkills(\n projectDir: string,\n): Promise<Partial<Record<SkillId, SkillDefinition>>> {\n const allSkills: Partial<Record<SkillId, SkillDefinition>> = {};\n\n try {\n const pluginPaths = await getVerifiedPluginInstallPaths(projectDir);\n\n if (pluginPaths.length === 0) {\n verbose(`No enabled plugins found in settings.json`);\n return allSkills;\n }\n\n for (const { pluginKey, installPath } of pluginPaths) {\n verbose(`Discovering skills from plugin: '${pluginKey}'`);\n try {\n const pluginSkills = await loadPluginSkills(installPath);\n // Boundary cast: loadPluginSkills returns Record<string, ...> — keys are skill IDs from parsed frontmatter\n for (const [id, skill] of typedEntries<SkillId, SkillDefinition>(pluginSkills)) {\n if (skill) {\n allSkills[id] = skill;\n }\n }\n } catch (error) {\n verbose(`Failed to load skills from '${pluginKey}': ${getErrorMessage(error)}`);\n }\n }\n } catch (error) {\n verbose(`Plugin discovery failed: ${getErrorMessage(error)}`);\n }\n\n return allSkills;\n}\n\n/**\n * Checks whether any plugins are enabled in settings.json.\n *\n * @param projectDir - Absolute path to the project root\n * @returns true if at least one plugin is enabled in settings.json\n */\nexport async function hasIndividualPlugins(projectDir: string): Promise<boolean> {\n try {\n const pluginPaths = await getVerifiedPluginInstallPaths(projectDir);\n return pluginPaths.length > 0;\n } catch (error) {\n verbose(`Failed to check for individual plugins: ${getErrorMessage(error)}`);\n return false;\n }\n}\n\n/**\n * Lists the keys of all enabled plugins.\n *\n * @param projectDir - Absolute path to the project root\n * @returns Array of plugin keys (e.g., [\"web-framework-react@photoroom-marketplace\"])\n */\nexport async function listPluginNames(projectDir: string): Promise<string[]> {\n try {\n const pluginPaths = await getVerifiedPluginInstallPaths(projectDir);\n return pluginPaths.map(({ pluginKey }) => pluginKey);\n } catch (error) {\n verbose(`Failed to list plugin names: ${getErrorMessage(error)}`);\n return [];\n }\n}\n","import path from \"path\";\nimport os from \"os\";\nimport { z } from \"zod\";\nimport { fileExists, readFileSafe } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { typedEntries } from \"../../utils/typed-object\";\nimport {\n CLAUDE_DIR,\n PLUGINS_SUBDIR,\n MAX_CONFIG_FILE_SIZE,\n PLUGIN_MANIFEST_DIR,\n PLUGIN_MANIFEST_FILE,\n} from \"../../consts\";\n\n/**\n * Plugin key format: \"plugin-name@marketplace\"\n * e.g., \"web-framework-react@photoroom-marketplace\"\n *\n * Kept as string — user-extensible identifiers (plugin names and marketplace names).\n */\nexport type PluginKey = string;\n\n/**\n * Resolved plugin with its install path\n */\nexport type ResolvedPlugin = {\n pluginKey: PluginKey;\n installPath: string;\n};\n\n// Zod schemas for JSON parse boundaries\n\nconst pluginSettingsSchema = z\n .object({\n enabledPlugins: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\nconst pluginInstallationSchema = z.object({\n scope: z.enum([\"user\", \"project\", \"local\"]),\n projectPath: z.string().optional(),\n installPath: z.string(),\n version: z.string(),\n installedAt: z.string(),\n lastUpdated: z.string().optional(),\n gitCommitSha: z.string().optional(),\n});\n\nconst installedPluginsSchema = z\n .object({\n version: z.number(),\n plugins: z.record(z.string(), z.array(pluginInstallationSchema)),\n })\n .passthrough();\n\nconst SETTINGS_FILE = \"settings.json\";\nconst INSTALLED_PLUGINS_FILE = \"installed_plugins.json\";\n\n/**\n * Read enabled plugin keys from project's .claude/settings.json\n */\nexport async function getEnabledPluginKeys(projectDir: string): Promise<PluginKey[]> {\n const settingsPath = path.join(projectDir, CLAUDE_DIR, SETTINGS_FILE);\n\n if (!(await fileExists(settingsPath))) {\n verbose(`No settings.json found at '${settingsPath}'`);\n return [];\n }\n\n try {\n const content = await readFileSafe(settingsPath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = pluginSettingsSchema.safeParse(raw);\n\n if (!result.success) {\n verbose(`Invalid settings.json structure: ${getErrorMessage(result.error)}`);\n return [];\n }\n\n const settings = result.data;\n\n if (!settings.enabledPlugins) {\n verbose(`No enabledPlugins found in '${settingsPath}'`);\n return [];\n }\n\n const enabledKeys = typedEntries(settings.enabledPlugins)\n .filter(([, enabled]) => enabled === true)\n .map(([key]) => key);\n\n verbose(`Found ${enabledKeys.length} enabled plugins in settings.json`);\n return enabledKeys;\n } catch (error) {\n verbose(`Failed to read settings.json: ${getErrorMessage(error)}`);\n return [];\n }\n}\n\n/**\n * Resolve install paths for the given plugin keys from global registry\n */\nexport async function resolvePluginInstallPaths(\n pluginKeys: PluginKey[],\n projectDir: string,\n): Promise<ResolvedPlugin[]> {\n if (pluginKeys.length === 0) {\n return [];\n }\n\n const registryPath = path.join(os.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR, INSTALLED_PLUGINS_FILE);\n\n if (!(await fileExists(registryPath))) {\n verbose(`Plugin registry not found at '${registryPath}'`);\n return [];\n }\n\n try {\n const content = await readFileSafe(registryPath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = installedPluginsSchema.safeParse(raw);\n\n if (!result.success) {\n verbose(`Invalid plugin registry structure: ${getErrorMessage(result.error)}`);\n return [];\n }\n\n const registry = result.data;\n const resolvedPaths: ResolvedPlugin[] = [];\n\n for (const pluginKey of pluginKeys) {\n const installations = registry.plugins[pluginKey];\n\n if (!installations || installations.length === 0) {\n verbose(`Plugin '${pluginKey}' not found in registry`);\n continue;\n }\n\n // Find project-scoped installation matching this project\n const projectInstall = installations.find(\n (install) => install.scope === \"project\" && install.projectPath === projectDir,\n );\n\n if (projectInstall) {\n resolvedPaths.push({\n pluginKey,\n installPath: projectInstall.installPath,\n });\n verbose(`Resolved '${pluginKey}' to '${projectInstall.installPath}'`);\n continue;\n }\n\n // Fallback to user-scoped installation\n const userInstall = installations.find((install) => install.scope === \"user\");\n\n if (userInstall) {\n resolvedPaths.push({\n pluginKey,\n installPath: userInstall.installPath,\n });\n verbose(`Resolved '${pluginKey}' to '${userInstall.installPath}' (user scope)`);\n continue;\n }\n\n verbose(`No matching installation found for '${pluginKey}'`);\n }\n\n return resolvedPaths;\n } catch (error) {\n verbose(`Failed to read plugin registry: ${getErrorMessage(error)}`);\n return [];\n }\n}\n\n/**\n * Get verified plugin install paths for the project\n * Combines settings.json reading, registry lookup, and path verification\n */\nexport async function getVerifiedPluginInstallPaths(projectDir: string): Promise<ResolvedPlugin[]> {\n const enabledKeys = await getEnabledPluginKeys(projectDir);\n const resolvedPaths = await resolvePluginInstallPaths(enabledKeys, projectDir);\n\n // Filter out paths that don't exist on disk\n const verified: ResolvedPlugin[] = [];\n\n for (const { pluginKey, installPath } of resolvedPaths) {\n const pluginJsonPath = path.join(installPath, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n\n if (await fileExists(pluginJsonPath)) {\n verified.push({ pluginKey, installPath });\n } else {\n verbose(`Plugin '${pluginKey}' manifest does not exist at: '${pluginJsonPath}'`);\n }\n }\n\n verbose(`Verified ${verified.length} plugin install paths`);\n return verified;\n}\n","import path from \"path\";\n\nimport { readFileSafe, writeFile } from \"../../utils/fs\";\nimport {\n PLUGIN_MANIFEST_DIR,\n PLUGIN_MANIFEST_FILE,\n DEFAULT_VERSION,\n MAX_PLUGIN_FILE_SIZE,\n} from \"../../consts\";\nimport { pluginManifestSchema } from \"../schemas\";\n\nexport type VersionBumpType = \"major\" | \"minor\" | \"patch\";\n\nfunction parseVersion(version: string): [number, number, number] {\n const parts = version.split(\".\").map(Number);\n return [parts[0] || 1, parts[1] || 0, parts[2] || 0];\n}\n\nexport async function bumpPluginVersion(pluginDir: string, type: VersionBumpType): Promise<string> {\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const manifest = pluginManifestSchema.parse(JSON.parse(content));\n\n const [major, minor, patch] = parseVersion(manifest.version || DEFAULT_VERSION);\n\n let newVersion: string;\n switch (type) {\n case \"major\":\n newVersion = `${major + 1}.0.0`;\n break;\n case \"minor\":\n newVersion = `${major}.${minor + 1}.0`;\n break;\n case \"patch\":\n newVersion = `${major}.${minor}.${patch + 1}`;\n break;\n default: {\n const exhaustiveCheck: never = type;\n throw new Error(`Unknown version bump type: ${exhaustiveCheck}`);\n }\n }\n\n manifest.version = newVersion;\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n\n return newVersion;\n}\n\nexport async function getPluginVersion(pluginDir: string): Promise<string> {\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_DIR, PLUGIN_MANIFEST_FILE);\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n const manifest = pluginManifestSchema.parse(JSON.parse(content));\n return manifest.version || DEFAULT_VERSION;\n}\n","import { z } from \"zod\";\nimport path from \"path\";\nimport fg from \"fast-glob\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport {\n fileExists,\n readFile,\n readFileSafe,\n directoryExists,\n listDirectories,\n} from \"../../utils/fs\";\nimport type { ValidationResult } from \"../../types\";\nimport { countBy } from \"remeda\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport { log } from \"../../utils/logger\";\nimport {\n pluginAuthorSchema,\n hooksRecordSchema,\n skillFrontmatterValidationSchema,\n agentFrontmatterValidationSchema,\n} from \"../schemas\";\nimport { MAX_PLUGIN_FILE_SIZE, PLUGIN_MANIFEST_DIR, STANDARD_FILES } from \"../../consts\";\n\nconst PLUGIN_DIR = PLUGIN_MANIFEST_DIR;\nconst PLUGIN_MANIFEST = STANDARD_FILES.PLUGIN_JSON;\nconst KEBAB_CASE_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;\nconst SEMVER_REGEX =\n /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$/;\n\n// Strict schema that rejects unrecognized keys (loader schema in schemas.ts uses .passthrough())\nconst pluginManifestValidationSchema = z\n .object({\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n author: pluginAuthorSchema.optional(),\n keywords: z.array(z.string()).optional(),\n commands: z.union([z.string(), z.array(z.string())]).optional(),\n agents: z.union([z.string(), z.array(z.string())]).optional(),\n skills: z.union([z.string(), z.array(z.string())]).optional(),\n hooks: z.union([z.string(), hooksRecordSchema]).optional(),\n })\n .strict();\n\nfunction formatZodErrors(error: z.ZodError): string[] {\n return error.issues.map((issue) => {\n const path = issue.path.join(\".\");\n if (issue.code === \"unrecognized_keys\") {\n return `Unrecognized key: \"${issue.keys.join('\", \"')}\"`;\n }\n return path ? `${path}: ${issue.message}` : issue.message;\n });\n}\n\nfunction isKebabCase(str: string): boolean {\n return KEBAB_CASE_REGEX.test(str);\n}\n\nfunction isValidSemver(str: string): boolean {\n return SEMVER_REGEX.test(str);\n}\n\n/**\n * Validates the directory structure of a plugin.\n *\n * Checks for the required `.claude-plugin/` directory and `plugin.json` manifest file.\n * Warns if README.md is missing (recommended but not required).\n *\n * @param pluginPath - Absolute path to the plugin root directory\n * @returns Validation result with errors for missing required structure\n */\nexport async function validatePluginStructure(pluginPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await directoryExists(pluginPath))) {\n return {\n valid: false,\n errors: [`Plugin directory does not exist: ${pluginPath}`],\n warnings: [],\n };\n }\n\n const pluginDir = path.join(pluginPath, PLUGIN_DIR);\n if (!(await directoryExists(pluginDir))) {\n errors.push(`Missing ${PLUGIN_DIR}/ directory`);\n }\n\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST);\n if (!(await fileExists(manifestPath))) {\n errors.push(`Missing ${PLUGIN_DIR}/${PLUGIN_MANIFEST}`);\n }\n\n const readmePath = path.join(pluginPath, \"README.md\");\n if (!(await fileExists(readmePath))) {\n warnings.push(\"Missing README.md (recommended for documentation)\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validates a plugin manifest file (plugin.json) for correctness and completeness.\n *\n * Performs the following validation checks:\n * 1. File existence and readability\n * 2. Valid JSON syntax (with file size limit via readFileSafe)\n * 3. Zod schema validation (strict mode rejects unrecognized keys)\n * 4. Plugin name is kebab-case\n * 5. Version string is valid semver\n * 6. Description field is present (warning if missing)\n * 7. Skills directory path exists on disk (if specified as string)\n * 8. Agents directory path exists on disk (if specified as string)\n *\n * @param manifestPath - Absolute path to the plugin.json file\n * @returns Validation result with errors for invalid/missing data and warnings for recommendations\n */\nexport async function validatePluginManifest(manifestPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(manifestPath))) {\n return {\n valid: false,\n errors: [`Manifest file not found: ${manifestPath}`],\n warnings: [],\n };\n }\n\n let manifest: Record<string, unknown>;\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n manifest = JSON.parse(content);\n } catch (err) {\n return {\n valid: false,\n errors: [`Invalid JSON in ${PLUGIN_MANIFEST}: ${getErrorMessage(err)}`],\n warnings: [],\n };\n }\n\n const result = pluginManifestValidationSchema.safeParse(manifest);\n\n if (!result.success) {\n errors.push(...formatZodErrors(result.error));\n }\n\n if (manifest.name && typeof manifest.name === \"string\") {\n if (!isKebabCase(manifest.name)) {\n errors.push(`name must be kebab-case: \"${manifest.name}\"`);\n }\n }\n\n if (manifest.version && typeof manifest.version === \"string\") {\n if (!isValidSemver(manifest.version)) {\n errors.push(\n `version \"${manifest.version}\" is not valid semver (expected: major.minor.patch)`,\n );\n }\n }\n\n if (!manifest.description) {\n warnings.push(\"Missing description field (recommended for discoverability)\");\n }\n\n const pluginDir = path.dirname(path.dirname(manifestPath));\n\n if (manifest.skills && typeof manifest.skills === \"string\") {\n const skillsPath = path.join(pluginDir, manifest.skills);\n if (!(await directoryExists(skillsPath))) {\n errors.push(`Skills path does not exist: ${manifest.skills}`);\n }\n }\n\n if (manifest.agents && typeof manifest.agents === \"string\") {\n const agentsPath = path.join(pluginDir, manifest.agents);\n if (!(await directoryExists(agentsPath))) {\n errors.push(`Agents path does not exist: ${manifest.agents}`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateSkillFrontmatter(skillPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(skillPath))) {\n return {\n valid: false,\n errors: [`Skill file not found: ${skillPath}`],\n warnings: [],\n };\n }\n\n const content = await readFile(skillPath);\n const frontmatter = extractFrontmatter(content);\n\n if (frontmatter === null) {\n return {\n valid: false,\n errors: [\"Missing or invalid YAML frontmatter\"],\n warnings: [],\n };\n }\n\n const result = skillFrontmatterValidationSchema.safeParse(frontmatter);\n\n if (!result.success) {\n errors.push(...formatZodErrors(result.error));\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nexport async function validateAgentFrontmatter(agentPath: string): Promise<ValidationResult> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(await fileExists(agentPath))) {\n return {\n valid: false,\n errors: [`Agent file not found: ${agentPath}`],\n warnings: [],\n };\n }\n\n const content = await readFile(agentPath);\n const frontmatter = extractFrontmatter(content);\n\n if (frontmatter === null) {\n return {\n valid: false,\n errors: [\"Missing or invalid YAML frontmatter\"],\n warnings: [],\n };\n }\n\n const result = agentFrontmatterValidationSchema.safeParse(frontmatter);\n\n if (!result.success) {\n errors.push(...formatZodErrors(result.error));\n }\n\n // Boundary cast: YAML frontmatter parsed as unknown, narrow to record for field access\n const fm = frontmatter as Record<string, unknown>;\n\n if (fm.name && typeof fm.name === \"string\") {\n if (!isKebabCase(fm.name)) {\n errors.push(`name must be kebab-case: \"${fm.name}\"`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nfunction mergeResults(results: ValidationResult[]): ValidationResult {\n const errors = results.flatMap((r) => r.errors);\n const warnings = results.flatMap((r) => r.warnings);\n return { valid: errors.length === 0, errors, warnings };\n}\n\nconst EMPTY_RESULT: ValidationResult = { valid: true, errors: [], warnings: [] };\n\nfunction prefixResult(result: ValidationResult, prefix: string): ValidationResult {\n return {\n valid: result.valid,\n errors: result.valid ? [] : result.errors.map((e) => `${prefix}: ${e}`),\n warnings: result.warnings.map((w) => `${prefix}: ${w}`),\n };\n}\n\nasync function validatePluginSkillFiles(\n pluginPath: string,\n skillsRelPath: string,\n): Promise<ValidationResult> {\n const skillsDir = path.join(pluginPath, skillsRelPath);\n if (!(await directoryExists(skillsDir))) return EMPTY_RESULT;\n\n const files = await fg(\"**/SKILL.md\", { cwd: skillsDir, absolute: true });\n if (files.length === 0) {\n return {\n valid: true,\n errors: [],\n warnings: [`Skills directory exists but contains no SKILL.md files: ${skillsRelPath}`],\n };\n }\n\n const results = await Promise.all(\n files.map(async (f) =>\n prefixResult(await validateSkillFrontmatter(f), path.relative(pluginPath, f)),\n ),\n );\n return mergeResults(results);\n}\n\nasync function validatePluginAgentFiles(\n pluginPath: string,\n agentsRelPath: string,\n): Promise<ValidationResult> {\n const agentsDir = path.join(pluginPath, agentsRelPath);\n if (!(await directoryExists(agentsDir))) return EMPTY_RESULT;\n\n const files = await fg(\"*.md\", { cwd: agentsDir, absolute: true });\n if (files.length === 0) {\n return {\n valid: true,\n errors: [],\n warnings: [`Agents directory exists but contains no .md files: ${agentsRelPath}`],\n };\n }\n\n const results = await Promise.all(\n files.map(async (f) =>\n prefixResult(await validateAgentFrontmatter(f), path.relative(pluginPath, f)),\n ),\n );\n return mergeResults(results);\n}\n\nasync function loadManifestForValidation(\n manifestPath: string,\n): Promise<Record<string, unknown> | null> {\n try {\n const content = await readFileSafe(manifestPath, MAX_PLUGIN_FILE_SIZE);\n return JSON.parse(content) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/**\n * Runs comprehensive validation on a plugin: structure, manifest, skill files, and agent files.\n *\n * Short-circuits on structure validation failure (no point checking manifest if\n * the directory structure is wrong). For valid structures, validates the manifest\n * and then checks all SKILL.md and agent .md files for valid frontmatter.\n *\n * @param pluginPath - Absolute path to the plugin root directory\n * @returns Merged validation result from all validation passes\n */\nexport async function validatePlugin(pluginPath: string): Promise<ValidationResult> {\n const structureResult = await validatePluginStructure(pluginPath);\n if (!structureResult.valid) return structureResult;\n\n const manifestPath = path.join(pluginPath, PLUGIN_DIR, PLUGIN_MANIFEST);\n const manifestResult = await validatePluginManifest(manifestPath);\n const manifest = await loadManifestForValidation(manifestPath);\n\n const skillsResult =\n manifest?.skills && typeof manifest.skills === \"string\"\n ? await validatePluginSkillFiles(pluginPath, manifest.skills)\n : EMPTY_RESULT;\n\n const agentsResult =\n manifest?.agents && typeof manifest.agents === \"string\"\n ? await validatePluginAgentFiles(pluginPath, manifest.agents)\n : EMPTY_RESULT;\n\n return mergeResults([structureResult, manifestResult, skillsResult, agentsResult]);\n}\n\n/**\n * Validates all plugins found in a directory, returning individual results and an aggregate summary.\n *\n * Scans subdirectories for `.claude-plugin/` markers to identify plugins, then validates\n * each one. Returns early with an error if the directory doesn't exist or contains no plugins.\n *\n * @param pluginsDir - Absolute path to the directory containing plugin subdirectories\n * @returns Object with overall validity, per-plugin results, and counts summary\n */\nexport async function validateAllPlugins(pluginsDir: string): Promise<{\n valid: boolean;\n results: Array<{ name: string; result: ValidationResult }>;\n summary: {\n total: number;\n valid: number;\n invalid: number;\n withWarnings: number;\n };\n}> {\n const results: Array<{ name: string; result: ValidationResult }> = [];\n\n if (!(await directoryExists(pluginsDir))) {\n return {\n valid: false,\n results: [\n {\n name: pluginsDir,\n result: {\n valid: false,\n errors: [`Directory does not exist: ${pluginsDir}`],\n warnings: [],\n },\n },\n ],\n summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 },\n };\n }\n\n const allDirs = await listDirectories(pluginsDir);\n const pluginDirs: string[] = [];\n\n for (const dirName of allDirs) {\n const potentialPluginDir = path.join(pluginsDir, dirName, PLUGIN_DIR);\n if (await directoryExists(potentialPluginDir)) {\n pluginDirs.push(dirName);\n }\n }\n\n if (pluginDirs.length === 0) {\n return {\n valid: false,\n results: [\n {\n name: pluginsDir,\n result: {\n valid: false,\n errors: [\n `No plugins found in directory: ${pluginsDir}. Plugins must contain a ${PLUGIN_DIR}/ directory.`,\n ],\n warnings: [],\n },\n },\n ],\n summary: { total: 0, valid: 0, invalid: 1, withWarnings: 0 },\n };\n }\n\n for (const pluginName of pluginDirs) {\n const pluginPath = path.join(pluginsDir, pluginName);\n const result = await validatePlugin(pluginPath);\n results.push({ name: pluginName, result });\n }\n\n const summary = {\n total: results.length,\n valid: countBy(results, (r) => String(r.result.valid))[\"true\"] ?? 0,\n invalid: countBy(results, (r) => String(r.result.valid))[\"false\"] ?? 0,\n withWarnings: countBy(results, (r) => String(r.result.warnings.length > 0))[\"true\"] ?? 0,\n };\n\n return {\n valid: summary.invalid === 0,\n results,\n summary,\n };\n}\n\nexport function printPluginValidationResult(\n name: string,\n result: ValidationResult,\n verbose = false,\n): void {\n const status = result.valid ? \"\\u2713\" : \"\\u2717\";\n\n if (result.valid && result.warnings.length === 0 && !verbose) {\n return;\n }\n\n log(`\\n ${status} ${name}`);\n\n if (result.errors.length > 0) {\n log(\" Errors:\");\n result.errors.forEach((e) => log(` - ${e}`));\n }\n\n if (result.warnings.length > 0) {\n log(\" Warnings:\");\n result.warnings.forEach((w) => log(` - ${w}`));\n }\n}\n","import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { directoryExists, listDirectories, fileExists, readFile } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { LOCAL_SKILLS_PATH, STANDARD_FILES } from \"../../consts\";\nimport { parseFrontmatter } from \"../loading\";\nimport type { CategoryPath, ExtractedSkillMetadata, SkillId } from \"../../types\";\nimport { formatZodErrors, localRawMetadataSchema } from \"../schemas\";\nimport { LOCAL_DEFAULTS, METADATA_KEYS } from \"../metadata-keys\";\n\ntype LocalRawMetadata = {\n cliName: string;\n cliDescription?: string;\n /** Original skill category from source (e.g., \"web-framework\", \"web-styling\", \"api-api\") */\n category?: CategoryPath;\n categoryExclusive?: boolean;\n usageGuidance?: string;\n tags?: string[];\n compatibleWith?: SkillId[];\n conflictsWith?: SkillId[];\n requires?: SkillId[];\n requiresSetup?: SkillId[];\n providesSetupFor?: SkillId[];\n};\n\nexport type LocalSkillDiscoveryResult = {\n skills: ExtractedSkillMetadata[];\n localSkillsPath: string;\n};\n\nexport async function discoverLocalSkills(\n projectDir: string,\n): Promise<LocalSkillDiscoveryResult | null> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (!(await directoryExists(localSkillsPath))) {\n verbose(`Local skills directory not found: ${localSkillsPath}`);\n return null;\n }\n\n const skills: ExtractedSkillMetadata[] = [];\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const skillDirName of skillDirs) {\n const skill = await extractLocalSkill(localSkillsPath, skillDirName);\n if (skill) {\n skills.push(skill);\n }\n }\n\n verbose(`Discovered ${skills.length} local skills from ${localSkillsPath}`);\n\n return {\n skills,\n localSkillsPath,\n };\n}\n\nasync function extractLocalSkill(\n localSkillsPath: string,\n skillDirName: string,\n): Promise<ExtractedSkillMetadata | null> {\n const skillDir = path.join(localSkillsPath, skillDirName);\n const metadataPath = path.join(skillDir, STANDARD_FILES.METADATA_YAML);\n const skillMdPath = path.join(skillDir, STANDARD_FILES.SKILL_MD);\n\n if (!(await fileExists(metadataPath))) {\n verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);\n return null;\n }\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping local skill '${skillDirName}': No SKILL.md found`);\n return null;\n }\n\n const metadataContent = await readFile(metadataPath);\n const parsed = localRawMetadataSchema.safeParse(parseYaml(metadataContent));\n\n if (!parsed.success) {\n warn(\n `Skipping local skill '${skillDirName}': invalid metadata.yaml — ${formatZodErrors(parsed.error.issues)}`,\n );\n return null;\n }\n\n const metadata = parsed.data as LocalRawMetadata;\n\n if (!metadata.cliName) {\n warn(\n `Skipping local skill '${skillDirName}': missing required '${METADATA_KEYS.CLI_NAME}' in metadata.yaml`,\n );\n return null;\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);\n\n if (!frontmatter) {\n warn(`Skipping local skill '${skillDirName}': invalid SKILL.md frontmatter`);\n return null;\n }\n\n const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;\n const skillId = frontmatter.name;\n\n // Use category from metadata.yaml if available (preserved from source skill),\n // otherwise fall back to generic \"local\" category\n const category = metadata.category || LOCAL_DEFAULTS.CATEGORY;\n\n if (!metadata.category) {\n warn(\n `Local skill '${skillDirName}' has no category in metadata.yaml — defaulting to '${LOCAL_DEFAULTS.CATEGORY}' (will not appear in wizard domain views)`,\n );\n }\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDirName,\n description: metadata.cliDescription || frontmatter.description,\n usageGuidance: metadata.usageGuidance,\n category,\n categoryExclusive: metadata.categoryExclusive ?? false,\n author: LOCAL_DEFAULTS.AUTHOR,\n tags: metadata.tags ?? [],\n compatibleWith: metadata.compatibleWith ?? [],\n conflictsWith: metadata.conflictsWith ?? [],\n requires: metadata.requires ?? [],\n requiresSetup: metadata.requiresSetup ?? [],\n providesSetupFor: metadata.providesSetupFor ?? [],\n path: relativePath,\n local: true,\n localPath: relativePath,\n };\n\n verbose(`Extracted local skill: ${skillId}`);\n return extracted;\n}\n","import path from \"path\";\n\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { copy, directoryExists, ensureDir, remove } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { LOCAL_SKILLS_PATH, ARCHIVED_SKILLS_DIR_NAME } from \"../../consts\";\nimport { SKILL_ID_PATTERN } from \"../schemas\";\nimport type { SkillId } from \"../../types\";\n\n/**\n * Validates a skill ID is safe for use in filesystem paths.\n * Checks format, traversal sequences, and null bytes at runtime\n * since TypeScript template literal types don't prevent malformed data from YAML/JSON.\n */\nfunction validateSkillId(skillId: SkillId): boolean {\n if (!SKILL_ID_PATTERN.test(skillId)) {\n return false;\n }\n // Block null bytes and path traversal sequences\n return !(\n skillId.includes(\"\\0\") ||\n skillId.includes(\"..\") ||\n skillId.includes(\"/\") ||\n skillId.includes(\"\\\\\")\n );\n}\n\n/**\n * Validates a resolved path stays within the expected parent directory.\n * Prevents path traversal attacks where crafted input escapes the skills directory.\n */\nfunction validatePathBoundary(resolvedPath: string, expectedParent: string): boolean {\n const normalizedPath = path.resolve(resolvedPath);\n const normalizedParent = path.resolve(expectedParent);\n return normalizedPath.startsWith(normalizedParent + path.sep);\n}\n\n/**\n * Archive a local skill to .claude/skills/_archived/{skill-id}/\n * Preserves user's work before switching to a different source.\n */\nexport async function archiveLocalSkill(projectDir: string, skillId: SkillId): Promise<void> {\n if (!validateSkillId(skillId)) {\n warn(`Invalid skill ID for archiving: '${skillId}'`);\n return;\n }\n\n const skillsDir = path.resolve(path.join(projectDir, LOCAL_SKILLS_PATH));\n const skillPath = path.resolve(path.join(skillsDir, skillId));\n const archivedDir = path.resolve(path.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));\n const archivedSkillPath = path.resolve(path.join(archivedDir, skillId));\n\n if (\n !validatePathBoundary(skillPath, skillsDir) ||\n !validatePathBoundary(archivedSkillPath, archivedDir)\n ) {\n warn(`Skill ID '${skillId}' resolves outside the skills directory.`);\n return;\n }\n\n try {\n await ensureDir(archivedDir);\n await copy(skillPath, archivedSkillPath);\n await remove(skillPath);\n } catch (error) {\n warn(`Failed to archive skill '${skillId}': ${getErrorMessage(error)}`);\n return;\n }\n\n verbose(`Archived local skill '${skillId}' to ${ARCHIVED_SKILLS_DIR_NAME}/`);\n}\n\n/**\n * Restore a previously archived skill from .claude/skills/_archived/{skill-id}/\n * Returns true if found and restored, false if no archive exists.\n */\nexport async function restoreArchivedSkill(projectDir: string, skillId: SkillId): Promise<boolean> {\n if (!validateSkillId(skillId)) {\n warn(`Invalid skill ID for restoring: '${skillId}'`);\n return false;\n }\n\n const skillsDir = path.resolve(path.join(projectDir, LOCAL_SKILLS_PATH));\n const skillPath = path.resolve(path.join(skillsDir, skillId));\n const archivedDir = path.resolve(path.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));\n const archivedSkillPath = path.resolve(path.join(archivedDir, skillId));\n\n if (\n !validatePathBoundary(skillPath, skillsDir) ||\n !validatePathBoundary(archivedSkillPath, archivedDir)\n ) {\n warn(`Skill ID '${skillId}' resolves outside the skills directory.`);\n return false;\n }\n\n try {\n await copy(archivedSkillPath, skillPath);\n await remove(archivedSkillPath);\n } catch {\n // Archive doesn't exist or can't be read — nothing to restore\n return false;\n }\n\n verbose(`Restored archived skill '${skillId}' from ${ARCHIVED_SKILLS_DIR_NAME}/`);\n return true;\n}\n\n/**\n * Check if an archived version of a skill exists.\n */\nexport async function hasArchivedSkill(projectDir: string, skillId: SkillId): Promise<boolean> {\n if (!validateSkillId(skillId)) {\n warn(`Invalid skill ID for archive check: '${skillId}'`);\n return false;\n }\n\n const skillsDir = path.resolve(path.join(projectDir, LOCAL_SKILLS_PATH));\n const archivedDir = path.resolve(path.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));\n const archivedSkillPath = path.resolve(path.join(archivedDir, skillId));\n\n if (!validatePathBoundary(archivedSkillPath, archivedDir)) {\n warn(`Skill ID '${skillId}' resolves outside the skills directory.`);\n return false;\n }\n\n return directoryExists(archivedSkillPath);\n}\n","export {\n loadSkillsMatrix,\n extractAllSkills,\n mergeMatrixWithSkills,\n loadAndMergeSkillsMatrix,\n} from \"./matrix-loader\";\n\nexport {\n resolveAlias,\n getDependentSkills,\n type SkillCheckOptions,\n isDisabled,\n getDisableReason,\n isDiscouraged,\n getDiscourageReason,\n isRecommended,\n getRecommendReason,\n validateSelection,\n getAvailableSkills,\n getSkillsByCategory,\n isCategoryAllDisabled,\n} from \"./matrix-resolver\";\n\nexport { type MatrixHealthIssue, checkMatrixHealth } from \"./matrix-health-check\";\n","import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport { z } from \"zod\";\nimport { glob, readFile, fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { DIRS, STANDARD_FILES } from \"../../consts\";\nimport { METADATA_KEYS } from \"../metadata-keys\";\nimport { parseFrontmatter } from \"../loading\";\nimport {\n skillsMatrixConfigSchema,\n categoryPathSchema,\n formatZodErrors,\n skillDisplayNameSchema,\n skillIdSchema,\n} from \"../schemas\";\nimport type {\n AlternativeGroup,\n ConflictRule,\n DiscourageRule,\n ExtractedSkillMetadata,\n MergedSkillsMatrix,\n RecommendRule,\n RequireRule,\n ResolvedSkill,\n ResolvedStack,\n SkillAlternative,\n SkillDisplayName,\n SkillId,\n SkillRelation,\n SkillRequirement,\n SkillsMatrixConfig,\n} from \"../../types\";\n\n/** Resolves a raw ID (which may be a display name or alias) to a canonical SkillId */\ntype ResolveId = (id: SkillId, context?: string) => SkillId;\n\nconst rawMetadataSchema = z.object({\n category: categoryPathSchema,\n categoryExclusive: z.boolean().optional(),\n author: z.string(),\n version: z.coerce.string(),\n cliName: z.string().optional(),\n cliDescription: z.string().optional(),\n usageGuidance: z.string().optional(),\n tags: z.array(z.string()).optional(),\n // Lenient: accepts display names and skill IDs from YAML, resolved to canonical IDs during matrix merge\n compatibleWith: z.array(z.string() as z.ZodType<SkillId>).optional(),\n conflictsWith: z.array(z.string() as z.ZodType<SkillId>).optional(),\n requires: z.array(z.string() as z.ZodType<SkillId>).optional(),\n requiresSetup: z.array(z.string() as z.ZodType<SkillId>).optional(),\n providesSetupFor: z.array(z.string() as z.ZodType<SkillId>).optional(),\n});\n\n/**\n * Loads and validates a skills matrix YAML configuration file.\n *\n * @param configPath - Absolute path to the skills-matrix.yaml file\n * @returns Parsed and validated skills matrix config\n * @throws When the file cannot be read or fails Zod schema validation\n */\nexport async function loadSkillsMatrix(configPath: string): Promise<SkillsMatrixConfig> {\n const content = await readFile(configPath);\n const raw = parseYaml(content);\n const result = skillsMatrixConfigSchema.safeParse(raw);\n\n if (!result.success) {\n throw new Error(\n `Invalid skills matrix at '${configPath}': ${formatZodErrors(result.error.issues)}`,\n );\n }\n\n verbose(`Loaded skills matrix: ${configPath}`);\n return result.data;\n}\n\n/**\n * Scans a skills directory and extracts metadata from all valid skills.\n *\n * Discovers skills by globbing for `metadata.yaml` files, then for each:\n * 1. Validates a corresponding SKILL.md exists (skips if missing)\n * 2. Parses and validates metadata.yaml against the raw metadata schema\n * 3. Parses SKILL.md frontmatter for the canonical skill ID\n * 4. Merges metadata fields into an ExtractedSkillMetadata object\n *\n * Skills with invalid metadata are warned and skipped. Skills missing\n * the required `cliName` field in metadata.yaml cause a hard error.\n *\n * @param skillsDir - Absolute path to the skills root directory (e.g., `{root}/src/skills`)\n * @returns Array of extracted skill metadata, one per valid skill found\n * @throws When a skill's metadata.yaml is missing the required `cliName` field\n */\nexport async function extractAllSkills(skillsDir: string): Promise<ExtractedSkillMetadata[]> {\n const skills: ExtractedSkillMetadata[] = [];\n const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);\n\n for (const metadataFile of metadataFiles) {\n const skillDir = path.dirname(metadataFile);\n const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);\n const metadataPath = path.join(skillsDir, metadataFile);\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping ${metadataFile}: No ${STANDARD_FILES.SKILL_MD} found`);\n continue;\n }\n\n const metadataContent = await readFile(metadataPath);\n const rawMetadata = parseYaml(metadataContent);\n const metadataResult = rawMetadataSchema.safeParse(rawMetadata);\n\n if (!metadataResult.success) {\n warn(\n `Skipping '${metadataFile}': invalid metadata.yaml — ${formatZodErrors(metadataResult.error.issues)}`,\n );\n continue;\n }\n\n const metadata = metadataResult.data;\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);\n\n if (!frontmatter) {\n verbose(`Skipping ${metadataFile}: Invalid SKILL.md frontmatter`);\n continue;\n }\n\n if (!metadata.cliName) {\n throw new Error(\n `Skill at ${metadataFile} is missing required '${METADATA_KEYS.CLI_NAME}' field in metadata.yaml`,\n );\n }\n\n const skillId = frontmatter.name;\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDir,\n description: metadata.cliDescription || frontmatter.description,\n usageGuidance: metadata.usageGuidance,\n category: metadata.category,\n categoryExclusive: metadata.categoryExclusive ?? true,\n author: metadata.author,\n tags: metadata.tags ?? [],\n compatibleWith: metadata.compatibleWith ?? [],\n conflictsWith: metadata.conflictsWith ?? [],\n requires: metadata.requires ?? [],\n requiresSetup: metadata.requiresSetup ?? [],\n providesSetupFor: metadata.providesSetupFor ?? [],\n path: `skills/${skillDir}/`,\n };\n\n skills.push(extracted);\n verbose(`Extracted skill: ${skillId}`);\n }\n\n return skills;\n}\n\nfunction buildReverseDisplayNames(\n displayNameToId: Partial<Record<SkillDisplayName, SkillId>>,\n): Partial<Record<SkillId, SkillDisplayName>> {\n const reverse: Partial<Record<SkillId, SkillDisplayName>> = {};\n // Object.entries returns [string, SkillId | undefined][] — validate with Zod at boundary\n for (const [name, fullId] of Object.entries(displayNameToId)) {\n const nameResult = skillDisplayNameSchema.safeParse(name);\n const idResult = skillIdSchema.safeParse(fullId);\n if (nameResult.success && idResult.success) {\n reverse[idResult.data] = nameResult.data;\n } else {\n warn(\n `Invalid skill alias mapping: '${name}' -> '${fullId}'${!nameResult.success ? ` (invalid display name: ${nameResult.error.message})` : \"\"}${!idResult.success ? ` (invalid skill ID: ${idResult.error.message})` : \"\"}`,\n );\n }\n }\n return reverse;\n}\n\n// Maps short names, directory paths, and old alias targets to canonical skill IDs\nfunction buildAliasTargetToSkillIdMap(\n displayNameToId: Partial<Record<SkillDisplayName, SkillId>>,\n skills: ExtractedSkillMetadata[],\n): Record<string, SkillId> {\n const map: Record<string, SkillId> = {};\n\n for (const skill of skills) {\n const parts = skill.id.split(\"/\");\n const shortForm = parts[parts.length - 1];\n\n if (shortForm && shortForm !== skill.id) {\n map[shortForm] = skill.id;\n }\n\n if (skill.directoryPath && skill.directoryPath !== skill.id) {\n map[skill.directoryPath] = skill.id;\n }\n }\n\n // Also include any old-style alias targets that might still be referenced\n // Uses Set for O(1) suffix lookups instead of nested iteration over all aliases\n const aliasTargets = new Set(Object.values(displayNameToId));\n for (const skill of skills) {\n // Check each suffix of skill.id after \"/\" delimiters against the alias set\n let slashIdx = skill.id.indexOf(\"/\");\n while (slashIdx !== -1) {\n const suffix = skill.id.slice(slashIdx + 1);\n if (suffix && aliasTargets.has(suffix as SkillId) && suffix !== skill.id) {\n map[suffix] = skill.id;\n }\n slashIdx = skill.id.indexOf(\"/\", slashIdx + 1);\n }\n // Note: original also checked skill.id === aliasTarget, but that was excluded\n // by the aliasTarget !== skill.id guard, making it a no-op\n }\n\n return map;\n}\n\nfunction buildDirectoryPathToIdMap(skills: ExtractedSkillMetadata[]): Record<string, SkillId> {\n const map: Record<string, SkillId> = {};\n for (const skill of skills) {\n if (skill.directoryPath && skill.directoryPath !== skill.id) {\n map[skill.directoryPath] = skill.id;\n }\n }\n return map;\n}\n\nfunction resolveToCanonicalId(\n nameOrId: SkillId,\n displayNameToId: Partial<Record<SkillDisplayName, SkillId>>,\n directoryPathToId: Record<string, SkillId> = {},\n aliasTargetToSkillId: Record<string, SkillId> = {},\n context?: string,\n): SkillId {\n // Boundary cast: nameOrId may contain a display name from YAML — narrow to SkillDisplayName for lookup\n const displayNameResult = displayNameToId[nameOrId as unknown as SkillDisplayName];\n if (displayNameResult) {\n return displayNameResult;\n }\n if (directoryPathToId[nameOrId]) {\n return directoryPathToId[nameOrId];\n }\n // Handle \"short author\" format like \"react (@vince)\" that maps to full ID\n if (aliasTargetToSkillId[nameOrId]) {\n return aliasTargetToSkillId[nameOrId];\n }\n if (context) {\n verbose(`Unresolved ID '${nameOrId}' in ${context} — passing through as-is`);\n }\n return nameOrId;\n}\n\n/**\n * Merges a skills matrix configuration with extracted skill metadata into a\n * fully resolved MergedSkillsMatrix.\n *\n * This is the core resolution step that combines:\n * - Category definitions and display name aliases from the matrix config\n * - Extracted skill metadata (from scanning skill directories)\n * - Relationship rules (conflicts, requirements, recommendations, alternatives, discourages)\n *\n * Each skill's raw relationship references (which may use display names, directory paths,\n * or short aliases) are resolved to canonical SkillIds. The result is the complete\n * data structure consumed by the wizard UI and validation logic.\n *\n * @param matrix - Parsed skills matrix config (categories, aliases, relationship rules)\n * @param skills - Extracted skill metadata from scanning skill directories\n * @returns Fully resolved matrix with canonical IDs, display names, and relationship data\n */\nexport async function mergeMatrixWithSkills(\n matrix: SkillsMatrixConfig,\n skills: ExtractedSkillMetadata[],\n): Promise<MergedSkillsMatrix> {\n const displayNameToId = matrix.skillAliases;\n const displayNames = buildReverseDisplayNames(displayNameToId);\n const directoryPathToId = buildDirectoryPathToIdMap(skills);\n const aliasTargetToSkillId = buildAliasTargetToSkillIdMap(displayNameToId, skills);\n const resolvedSkills: Partial<Record<SkillId, ResolvedSkill>> = {};\n\n for (const skill of skills) {\n const resolved = buildResolvedSkill(\n skill,\n matrix,\n displayNameToId,\n displayNames,\n directoryPathToId,\n aliasTargetToSkillId,\n );\n resolvedSkills[skill.id] = resolved;\n }\n\n const suggestedStacks = resolveSuggestedStacks();\n\n const merged: MergedSkillsMatrix = {\n version: matrix.version,\n categories: matrix.categories,\n skills: resolvedSkills,\n suggestedStacks,\n displayNameToId,\n displayNames,\n generatedAt: new Date().toISOString(),\n };\n\n return merged;\n}\n\n/** Resolves conflicts from skill metadata and matrix conflict rules */\nfunction resolveConflicts(\n skillId: SkillId,\n metadataConflicts: SkillId[],\n conflictRules: ConflictRule[],\n resolve: ResolveId,\n): SkillRelation[] {\n const conflicts: SkillRelation[] = [];\n\n for (const conflictRef of metadataConflicts) {\n conflicts.push({\n skillId: resolve(conflictRef, \"conflictsWith\"),\n reason: \"Defined in skill metadata\",\n });\n }\n\n for (const rule of conflictRules) {\n const resolved = rule.skills.map((id) => resolve(id, \"conflicts\"));\n if (!resolved.includes(skillId)) continue;\n for (const other of resolved) {\n if (other !== skillId && !conflicts.some((c) => c.skillId === other)) {\n conflicts.push({ skillId: other, reason: rule.reason });\n }\n }\n }\n\n return conflicts;\n}\n\n/** Resolves recommendations from skill compatibleWith and matrix recommend rules */\nfunction resolveRecommends(\n skillId: SkillId,\n compatibleWith: SkillId[],\n recommendRules: RecommendRule[],\n resolve: ResolveId,\n): SkillRelation[] {\n const recommends: SkillRelation[] = [];\n\n for (const compatRef of compatibleWith) {\n recommends.push({\n skillId: resolve(compatRef, \"compatibleWith\"),\n reason: \"Compatible with this skill\",\n });\n }\n\n for (const rule of recommendRules) {\n if (resolve(rule.when, \"recommends.when\") !== skillId) continue;\n for (const suggested of rule.suggest) {\n const canonicalId = resolve(suggested, \"recommends.suggest\");\n if (!recommends.some((r) => r.skillId === canonicalId)) {\n recommends.push({ skillId: canonicalId, reason: rule.reason });\n }\n }\n }\n\n return recommends;\n}\n\n/** Resolves requirements from skill metadata and matrix require rules */\nfunction resolveRequirements(\n skillId: SkillId,\n metadataRequires: SkillId[],\n requireRules: RequireRule[],\n resolve: ResolveId,\n): SkillRequirement[] {\n const requires: SkillRequirement[] = [];\n\n if (metadataRequires.length > 0) {\n requires.push({\n skillIds: metadataRequires.map((id) => resolve(id, \"requires\")),\n needsAny: false,\n reason: \"Defined in skill metadata\",\n });\n }\n\n for (const rule of requireRules) {\n if (resolve(rule.skill, \"requires.skill\") !== skillId) continue;\n requires.push({\n skillIds: rule.needs.map((id) => resolve(id, \"requires.needs\")),\n needsAny: rule.needsAny ?? false,\n reason: rule.reason,\n });\n }\n\n return requires;\n}\n\n/** Resolves alternatives from matrix alternative groups */\nfunction resolveAlternatives(\n skillId: SkillId,\n alternativeGroups: AlternativeGroup[],\n resolve: ResolveId,\n): SkillAlternative[] {\n const alternatives: SkillAlternative[] = [];\n\n for (const group of alternativeGroups) {\n const resolved = group.skills.map((id) => resolve(id, \"alternatives\"));\n if (!resolved.includes(skillId)) continue;\n for (const alt of resolved) {\n if (alt !== skillId) {\n alternatives.push({ skillId: alt, purpose: group.purpose });\n }\n }\n }\n\n return alternatives;\n}\n\n/** Resolves discourages from matrix discourage rules */\nfunction resolveDiscourages(\n skillId: SkillId,\n discourageRules: DiscourageRule[] | undefined,\n resolve: ResolveId,\n): SkillRelation[] {\n if (!discourageRules) return [];\n const discourages: SkillRelation[] = [];\n\n for (const rule of discourageRules) {\n const resolved = rule.skills.map((id) => resolve(id, \"discourages\"));\n if (!resolved.includes(skillId)) continue;\n for (const other of resolved) {\n if (other !== skillId && !discourages.some((d) => d.skillId === other)) {\n discourages.push({ skillId: other, reason: rule.reason });\n }\n }\n }\n\n return discourages;\n}\n\nfunction buildResolvedSkill(\n skill: ExtractedSkillMetadata,\n matrix: SkillsMatrixConfig,\n displayNameToId: Partial<Record<SkillDisplayName, SkillId>>,\n displayNames: Partial<Record<SkillId, SkillDisplayName>>,\n directoryPathToId: Record<string, SkillId>,\n aliasTargetToSkillId: Record<string, SkillId>,\n): ResolvedSkill {\n const resolve: ResolveId = (id, context) =>\n resolveToCanonicalId(\n id,\n displayNameToId,\n directoryPathToId,\n aliasTargetToSkillId,\n context ? `${skill.id} ${context}` : undefined,\n );\n\n const { relationships } = matrix;\n\n return {\n id: skill.id,\n displayName: displayNames[skill.id],\n description: skill.description,\n usageGuidance: skill.usageGuidance,\n category: skill.category,\n categoryExclusive: skill.categoryExclusive,\n tags: skill.tags,\n author: skill.author,\n conflictsWith: resolveConflicts(\n skill.id,\n skill.conflictsWith,\n relationships.conflicts,\n resolve,\n ),\n recommends: resolveRecommends(\n skill.id,\n skill.compatibleWith,\n relationships.recommends,\n resolve,\n ),\n requires: resolveRequirements(skill.id, skill.requires, relationships.requires, resolve),\n alternatives: resolveAlternatives(skill.id, relationships.alternatives, resolve),\n discourages: resolveDiscourages(skill.id, relationships.discourages, resolve),\n compatibleWith: skill.compatibleWith.map((id) => resolve(id, \"compatibleWith\")),\n requiresSetup: skill.requiresSetup.map((id) => resolve(id, \"requiresSetup\")),\n providesSetupFor: skill.providesSetupFor.map((id) => resolve(id, \"providesSetupFor\")),\n path: skill.path,\n };\n}\n\nfunction resolveSuggestedStacks(): ResolvedStack[] {\n return [];\n}\n\n/**\n * Convenience function that loads a skills matrix file, extracts all skills from\n * the project's skills directory, and merges them into a MergedSkillsMatrix.\n *\n * @param matrixPath - Path to the skills-matrix.yaml config file\n * @param projectRoot - Project root directory (skills are scanned from `{root}/src/skills`)\n * @returns Fully resolved and merged skills matrix\n */\nexport async function loadAndMergeSkillsMatrix(\n matrixPath: string,\n projectRoot: string,\n): Promise<MergedSkillsMatrix> {\n const matrix = await loadSkillsMatrix(matrixPath);\n const skillsDir = path.join(projectRoot, DIRS.skills);\n const skills = await extractAllSkills(skillsDir);\n return mergeMatrixWithSkills(matrix, skills);\n}\n","import { groupBy } from \"remeda\";\nimport type {\n CategoryPath,\n MergedSkillsMatrix,\n ResolvedSkill,\n SelectionValidation,\n SkillDisplayName,\n SkillId,\n SkillOption,\n Subcategory,\n ValidationError,\n ValidationWarning,\n} from \"../../types\";\nimport { typedEntries } from \"../../utils/typed-object\";\n\nfunction getLabel(\n skill: { displayName?: string; id: string } | undefined,\n fallback: string,\n): string {\n return skill?.displayName || skill?.id || fallback;\n}\n\n/** Resolves a display name or alias to its canonical SkillId, passing through if no mapping exists. */\nexport function resolveAlias(aliasOrId: SkillId, matrix: MergedSkillsMatrix): SkillId {\n // Boundary cast: aliasOrId may contain a display name from legacy contexts — try display name lookup first, fall back to SkillId\n return matrix.displayNameToId[aliasOrId as unknown as SkillDisplayName] || aliasOrId;\n}\n\ntype SelectionContext = {\n resolvedSelections: SkillId[];\n selectedSet: Set<SkillId>;\n};\n\nfunction initializeSelectionContext(\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): SelectionContext {\n const resolvedSelections = currentSelections.map((s) => resolveAlias(s, matrix));\n const selectedSet = new Set<SkillId>(resolvedSelections);\n return { resolvedSelections, selectedSet };\n}\n\n/**\n * Finds all currently selected skills that depend on the given skill.\n *\n * A skill is considered dependent if it has a requirement that would become\n * unsatisfied by removing `skillId`. For `needsAny` requirements, the skill\n * is only dependent if `skillId` is the sole remaining option satisfying\n * that requirement.\n *\n * @param skillId - The skill to check dependents for (resolved via alias lookup)\n * @param currentSelections - Currently selected skill IDs in the wizard\n * @param matrix - Merged skills matrix with relationship data\n * @returns Skill IDs that would lose a required dependency if `skillId` were removed\n */\nexport function getDependentSkills(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): SkillId[] {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) return [];\n\n const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections, matrix);\n const dependents: SkillId[] = [];\n\n for (const selectedId of resolvedSelections) {\n if (selectedId === fullId) continue;\n\n const selectedSkill = matrix.skills[selectedId];\n if (!selectedSkill) continue;\n\n for (const requirement of selectedSkill.requires) {\n if (requirement.needsAny) {\n const satisfiedReqs = requirement.skillIds.filter((reqId) => selectedSet.has(reqId));\n if (satisfiedReqs.length === 1 && satisfiedReqs[0] === fullId) {\n dependents.push(selectedId);\n }\n } else {\n if (requirement.skillIds.includes(fullId)) {\n dependents.push(selectedId);\n }\n }\n }\n }\n\n return dependents;\n}\n\nexport type SkillCheckOptions = {\n expertMode?: boolean;\n};\n\n/**\n * Determines whether a skill should be disabled (unselectable) in the wizard\n * given the current selection state.\n *\n * A skill is disabled when any of these conditions are true:\n * 1. It conflicts with a currently selected skill (bidirectional check)\n * 2. It has unmet `requires` dependencies -- either all required skills are\n * missing (AND mode) or none of the alternatives are selected (OR/needsAny mode)\n *\n * In expert mode, all constraints are bypassed and the skill is always enabled.\n * This is a pure function with no side effects.\n *\n * @param skillId - The skill to check (resolved via alias lookup)\n * @param currentSelections - Currently selected skill IDs\n * @param matrix - Merged skills matrix with conflict and requirement rules\n * @param options - Optional flags; `expertMode` bypasses all constraint checks\n * @returns true if the skill cannot be selected given current state\n */\nexport function isDisabled(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n options?: SkillCheckOptions,\n): boolean {\n if (options?.expertMode) {\n return false;\n }\n\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return false;\n }\n\n for (const selectedId of currentSelections) {\n const selectedFullId = resolveAlias(selectedId, matrix);\n\n if (skill.conflictsWith.some((c) => c.skillId === selectedFullId)) {\n return true;\n }\n\n const selectedSkill = matrix.skills[selectedFullId];\n if (selectedSkill?.conflictsWith.some((c) => c.skillId === fullId)) {\n return true;\n }\n }\n\n const { selectedSet } = initializeSelectionContext(currentSelections, matrix);\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));\n if (!hasAny) {\n return true;\n }\n } else {\n const hasAll = requirement.skillIds.every((reqId) => selectedSet.has(reqId));\n if (!hasAll) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Returns a human-readable reason why a skill is disabled, or undefined if it is not.\n *\n * Checks conflicts (bidirectional) and unmet requirements in the same order as\n * `isDisabled()`, returning the first matching reason with context about which\n * selected skill caused the constraint.\n *\n * @param skillId - The skill to get the disable reason for\n * @param currentSelections - Currently selected skill IDs\n * @param matrix - Merged skills matrix with relationship data\n * @returns Formatted reason string (e.g., \"Incompatible (conflicts with React)\") or undefined\n */\nexport function getDisableReason(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): string | undefined {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return undefined;\n }\n\n const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections, matrix);\n\n for (const selectedId of resolvedSelections) {\n const conflict = skill.conflictsWith.find((c) => c.skillId === selectedId);\n if (conflict) {\n const selectedSkill = matrix.skills[selectedId];\n return `${conflict.reason} (conflicts with ${getLabel(selectedSkill, selectedId)})`;\n }\n\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill) {\n const reverseConflict = selectedSkill.conflictsWith.find((c) => c.skillId === fullId);\n if (reverseConflict) {\n return `${reverseConflict.reason} (conflicts with ${getLabel(selectedSkill, selectedId)})`;\n }\n }\n }\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));\n if (!hasAny) {\n const requiredNames = requirement.skillIds\n .map((id) => getLabel(matrix.skills[id], id))\n .join(\" or \");\n return `${requirement.reason} (requires ${requiredNames})`;\n }\n } else {\n const missingIds = requirement.skillIds.filter((reqId) => !selectedSet.has(reqId));\n if (missingIds.length > 0) {\n const missingNames = missingIds.map((id) => getLabel(matrix.skills[id], id)).join(\", \");\n return `${requirement.reason} (requires ${missingNames})`;\n }\n }\n }\n\n return undefined;\n}\n\nexport function isDiscouraged(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): boolean {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return false;\n }\n\n const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill?.discourages.some((d) => d.skillId === fullId)) {\n return true;\n }\n\n if (skill.discourages.some((d) => d.skillId === selectedId)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getDiscourageReason(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): string | undefined {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return undefined;\n }\n\n const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill) {\n const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);\n if (discourage) {\n return discourage.reason;\n }\n }\n\n const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);\n if (reverseDiscourage) {\n return reverseDiscourage.reason;\n }\n }\n\n return undefined;\n}\n\nexport function isRecommended(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): boolean {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return false;\n }\n\n const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill?.recommends.some((r) => r.skillId === fullId)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getRecommendReason(\n skillId: SkillId,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): string | undefined {\n const fullId = resolveAlias(skillId, matrix);\n const skill = matrix.skills[fullId];\n\n if (!skill) {\n return undefined;\n }\n\n const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);\n\n for (const selectedId of resolvedSelections) {\n const selectedSkill = matrix.skills[selectedId];\n if (selectedSkill) {\n const recommendation = selectedSkill.recommends.find((r) => r.skillId === fullId);\n if (recommendation) {\n return `${recommendation.reason} (recommended by ${getLabel(selectedSkill, selectedId)})`;\n }\n }\n }\n\n return undefined;\n}\n\ntype ValidationPartial = {\n errors: ValidationError[];\n warnings: ValidationWarning[];\n};\n\nfunction validateConflicts(\n resolvedSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): ValidationPartial {\n const errors: ValidationError[] = [];\n\n for (let i = 0; i < resolvedSelections.length; i++) {\n const skillA = matrix.skills[resolvedSelections[i]];\n if (!skillA) continue;\n\n for (let j = i + 1; j < resolvedSelections.length; j++) {\n const skillBId = resolvedSelections[j];\n const conflict = skillA.conflictsWith.find((c) => c.skillId === skillBId);\n if (conflict) {\n errors.push({\n type: \"conflict\",\n message: `${getLabel(skillA, skillA.id)} conflicts with ${getLabel(matrix.skills[skillBId], skillBId)}: ${conflict.reason}`,\n skills: [skillA.id, skillBId],\n });\n }\n }\n }\n\n return { errors, warnings: [] };\n}\n\nfunction validateRequirements(\n resolvedSelections: SkillId[],\n selectedSet: Set<SkillId>,\n matrix: MergedSkillsMatrix,\n): ValidationPartial {\n const errors: ValidationError[] = [];\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n for (const requirement of skill.requires) {\n if (requirement.needsAny) {\n const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));\n if (!hasAny) {\n errors.push({\n type: \"missingRequirement\",\n message: `${getLabel(skill, skillId)} requires one of: ${requirement.skillIds.map((id) => getLabel(matrix.skills[id], id)).join(\", \")}`,\n skills: [skillId, ...requirement.skillIds],\n });\n }\n } else {\n const missingIds = requirement.skillIds.filter((reqId) => !selectedSet.has(reqId));\n if (missingIds.length > 0) {\n errors.push({\n type: \"missingRequirement\",\n message: `${getLabel(skill, skillId)} requires: ${missingIds.map((id) => getLabel(matrix.skills[id], id)).join(\", \")}`,\n skills: [skillId, ...missingIds],\n });\n }\n }\n }\n }\n\n return { errors, warnings: [] };\n}\n\nfunction validateExclusivity(\n resolvedSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n): ValidationPartial {\n const errors: ValidationError[] = [];\n\n const validSkills = resolvedSelections\n .map((skillId) => ({ skillId, skill: matrix.skills[skillId] }))\n .filter((entry): entry is { skillId: SkillId; skill: ResolvedSkill } => entry.skill != null);\n const categorySelections = groupBy(validSkills, (entry) => entry.skill.category);\n\n for (const [categoryId, entries] of typedEntries(categorySelections)) {\n if (entries.length > 1) {\n const skillIds = entries.map((e) => e.skillId);\n // CategoryPath -> Subcategory: categories lookup uses bare subcategory names\n const category = matrix.categories[categoryId as Subcategory];\n if (category?.exclusive) {\n errors.push({\n type: \"categoryExclusive\",\n message: `Category \"${category.displayName}\" only allows one selection, but multiple selected: ${skillIds.map((id) => getLabel(matrix.skills[id], id)).join(\", \")}`,\n skills: skillIds,\n });\n }\n }\n }\n\n return { errors, warnings: [] };\n}\n\nfunction validateRecommendations(\n resolvedSelections: SkillId[],\n selectedSet: Set<SkillId>,\n matrix: MergedSkillsMatrix,\n): ValidationPartial {\n const warnings: ValidationWarning[] = [];\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n for (const recommendation of skill.recommends) {\n if (!selectedSet.has(recommendation.skillId)) {\n const recommendedSkill = matrix.skills[recommendation.skillId];\n if (recommendedSkill) {\n const hasConflict = recommendedSkill.conflictsWith.some((c) =>\n selectedSet.has(c.skillId),\n );\n if (!hasConflict) {\n warnings.push({\n type: \"missing_recommendation\",\n message: `${getLabel(skill, skillId)} recommends ${getLabel(recommendedSkill, recommendation.skillId)}: ${recommendation.reason}`,\n skills: [skillId, recommendation.skillId],\n });\n }\n }\n }\n }\n }\n\n return { errors: [], warnings };\n}\n\nfunction validateSetupUsage(\n resolvedSelections: SkillId[],\n selectedSet: Set<SkillId>,\n matrix: MergedSkillsMatrix,\n): ValidationPartial {\n const warnings: ValidationWarning[] = [];\n\n for (const skillId of resolvedSelections) {\n const skill = matrix.skills[skillId];\n if (!skill || skill.providesSetupFor.length === 0) continue;\n\n const hasUsageSkill = skill.providesSetupFor.some((usageId) => selectedSet.has(usageId));\n if (!hasUsageSkill) {\n warnings.push({\n type: \"unused_setup\",\n message: `Setup skill \"${getLabel(skill, skillId)}\" selected but no corresponding usage skills: ${skill.providesSetupFor.map((id) => getLabel(matrix.skills[id], id)).join(\", \")}`,\n skills: [skillId, ...skill.providesSetupFor],\n });\n }\n }\n\n return { errors: [], warnings };\n}\n\nfunction mergeValidationResults(results: ValidationPartial[]): ValidationPartial {\n return {\n errors: results.flatMap((r) => r.errors),\n warnings: results.flatMap((r) => r.warnings),\n };\n}\n\n/**\n * Validates a complete set of skill selections against all matrix constraints.\n *\n * Runs five validation passes:\n * 1. **Conflicts** - Checks for mutually exclusive skill pairs (errors)\n * 2. **Requirements** - Checks that all required dependencies are selected (errors)\n * 3. **Exclusivity** - Checks that exclusive categories have at most one selection (errors)\n * 4. **Recommendations** - Checks for missing recommended companion skills (warnings)\n * 5. **Setup usage** - Checks that setup-only skills have corresponding usage skills (warnings)\n *\n * @param selections - Complete list of selected skill IDs to validate\n * @param matrix - Merged skills matrix with all relationship rules\n * @returns Validation result with `valid` flag, error list, and warning list\n */\nexport function validateSelection(\n selections: SkillId[],\n matrix: MergedSkillsMatrix,\n): SelectionValidation {\n const { resolvedSelections, selectedSet } = initializeSelectionContext(selections, matrix);\n\n const { errors, warnings } = mergeValidationResults([\n validateConflicts(resolvedSelections, matrix),\n validateRequirements(resolvedSelections, selectedSet, matrix),\n validateExclusivity(resolvedSelections, matrix),\n validateRecommendations(resolvedSelections, selectedSet, matrix),\n validateSetupUsage(resolvedSelections, selectedSet, matrix),\n ]);\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Builds a list of skill options for a category, annotated with their current\n * state (disabled, discouraged, recommended, selected) relative to the wizard's\n * selection state.\n *\n * Each skill is checked against the current selections to determine its visual\n * and interactive state in the wizard UI. States are mutually prioritized:\n * disabled takes precedence over discouraged, which takes precedence over recommended.\n *\n * @param categoryId - Category path to filter skills by\n * @param currentSelections - Currently selected skill IDs\n * @param matrix - Merged skills matrix\n * @param options - Optional flags (e.g., expertMode bypasses constraint checks)\n * @returns Array of skill options with state annotations and reasons\n */\nexport function getAvailableSkills(\n categoryId: CategoryPath,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n options?: SkillCheckOptions,\n): SkillOption[] {\n const skillOptions: SkillOption[] = [];\n const { selectedSet } = initializeSelectionContext(currentSelections, matrix);\n\n for (const skill of Object.values(matrix.skills)) {\n if (!skill) continue;\n if (skill.category !== categoryId) {\n continue;\n }\n\n const disabled = isDisabled(skill.id, currentSelections, matrix, options);\n const discouraged = !disabled && isDiscouraged(skill.id, currentSelections, matrix);\n const recommended =\n !disabled && !discouraged && isRecommended(skill.id, currentSelections, matrix);\n\n skillOptions.push({\n id: skill.id,\n displayName: skill.displayName,\n description: skill.description,\n disabled,\n disabledReason: disabled ? getDisableReason(skill.id, currentSelections, matrix) : undefined,\n discouraged,\n discouragedReason: discouraged\n ? getDiscourageReason(skill.id, currentSelections, matrix)\n : undefined,\n recommended,\n recommendedReason: recommended\n ? getRecommendReason(skill.id, currentSelections, matrix)\n : undefined,\n selected: selectedSet.has(skill.id),\n alternatives: skill.alternatives.map((a) => a.skillId),\n });\n }\n\n return skillOptions;\n}\n\n/** Returns all resolved skills belonging to the given category. */\nexport function getSkillsByCategory(\n categoryId: CategoryPath,\n matrix: MergedSkillsMatrix,\n): ResolvedSkill[] {\n const skills: ResolvedSkill[] = [];\n\n for (const skill of Object.values(matrix.skills)) {\n if (!skill) continue;\n if (skill.category === categoryId) {\n skills.push(skill);\n }\n }\n\n return skills;\n}\n\n/**\n * Checks whether every skill in a category is disabled given the current selections.\n *\n * Used by the wizard to dim entire category tiles when no selectable skills remain.\n * Returns the first disable reason (truncated to the core message before parenthetical\n * details) when all skills are disabled.\n *\n * @param categoryId - Category path to check\n * @param currentSelections - Currently selected skill IDs\n * @param matrix - Merged skills matrix\n * @param options - Optional flags; expertMode always returns not disabled\n * @returns Object with `disabled` flag and optional short `reason` string\n */\nexport function isCategoryAllDisabled(\n categoryId: CategoryPath,\n currentSelections: SkillId[],\n matrix: MergedSkillsMatrix,\n options?: SkillCheckOptions,\n): { disabled: boolean; reason?: string } {\n if (options?.expertMode) {\n return { disabled: false };\n }\n\n const skills = getSkillsByCategory(categoryId, matrix);\n\n if (skills.length === 0) {\n return { disabled: false };\n }\n\n const disabledSkills: Array<{ skillId: SkillId; reason: string | undefined }> = [];\n\n for (const skill of skills) {\n if (isDisabled(skill.id, currentSelections, matrix, options)) {\n disabledSkills.push({\n skillId: skill.id,\n reason: getDisableReason(skill.id, currentSelections, matrix),\n });\n }\n }\n\n if (disabledSkills.length === skills.length) {\n const firstReason = disabledSkills[0]?.reason;\n const shortReason = firstReason?.split(\" (\")[0] || \"requirements not met\";\n return { disabled: true, reason: shortReason };\n }\n\n return { disabled: false };\n}\n","import { warn } from \"../../utils/logger\";\nimport type {\n CategoryDefinition,\n MergedSkillsMatrix,\n ResolvedSkill,\n SkillId,\n Subcategory,\n} from \"../../types\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object\";\n\nexport type MatrixHealthIssue = {\n severity: \"warning\" | \"error\";\n finding: string;\n details: string;\n};\n\nexport function checkMatrixHealth(matrix: MergedSkillsMatrix): MatrixHealthIssue[] {\n const issues: MatrixHealthIssue[] = [];\n const skillIds = new Set(typedKeys<SkillId>(matrix.skills));\n\n checkRelationshipTargets(matrix, skillIds, issues);\n checkSubcategoryDomains(matrix, issues);\n checkSkillCategories(matrix, issues);\n checkCompatibleWithTargets(matrix, skillIds, issues);\n checkStackSkillIds(matrix, skillIds, issues);\n\n for (const issue of issues) {\n warn(`[matrix] ${issue.details}`);\n }\n\n return issues;\n}\n\nfunction checkRelationshipTargets(\n matrix: MergedSkillsMatrix,\n skillIds: Set<SkillId>,\n issues: MatrixHealthIssue[],\n): void {\n for (const [skillId, skill] of typedEntries<SkillId, ResolvedSkill>(matrix.skills)) {\n if (!skill) continue;\n for (const conflict of skill.conflictsWith) {\n if (!skillIds.has(conflict.skillId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-relationship-target\",\n details: `Skill '${skillId}' conflicts with '${conflict.skillId}' which does not exist in the matrix`,\n });\n }\n }\n\n for (const recommend of skill.recommends) {\n if (!skillIds.has(recommend.skillId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-relationship-target\",\n details: `Skill '${skillId}' recommends '${recommend.skillId}' which does not exist in the matrix`,\n });\n }\n }\n\n for (const requirement of skill.requires) {\n for (const reqId of requirement.skillIds) {\n if (!skillIds.has(reqId)) {\n issues.push({\n severity: \"error\",\n finding: \"ghost-requirement-target\",\n details: `Skill '${skillId}' requires '${reqId}' which does not exist in the matrix`,\n });\n }\n }\n }\n\n for (const alt of skill.alternatives) {\n if (!skillIds.has(alt.skillId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-alternative-target\",\n details: `Skill '${skillId}' lists alternative '${alt.skillId}' which does not exist in the matrix`,\n });\n }\n }\n\n for (const discourage of skill.discourages) {\n if (!skillIds.has(discourage.skillId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-relationship-target\",\n details: `Skill '${skillId}' discourages '${discourage.skillId}' which does not exist in the matrix`,\n });\n }\n }\n\n for (const setupId of skill.requiresSetup) {\n if (!skillIds.has(setupId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-setup-target\",\n details: `Skill '${skillId}' requiresSetup '${setupId}' which does not exist in the matrix`,\n });\n }\n }\n\n for (const providesId of skill.providesSetupFor) {\n if (!skillIds.has(providesId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-setup-target\",\n details: `Skill '${skillId}' providesSetupFor '${providesId}' which does not exist in the matrix`,\n });\n }\n }\n }\n}\n\n// Categories without a domain won't appear in any wizard domain view\nfunction checkSubcategoryDomains(matrix: MergedSkillsMatrix, issues: MatrixHealthIssue[]): void {\n for (const [catId, cat] of typedEntries<Subcategory, CategoryDefinition>(matrix.categories)) {\n if (!cat) continue;\n if (!cat.domain) {\n issues.push({\n severity: \"warning\",\n finding: \"category-missing-domain\",\n details: `Category '${catId}' has no domain — it won't appear in any wizard domain view`,\n });\n }\n }\n}\n\nfunction checkSkillCategories(matrix: MergedSkillsMatrix, issues: MatrixHealthIssue[]): void {\n for (const [skillId, skill] of typedEntries<SkillId, ResolvedSkill>(matrix.skills)) {\n if (!skill) continue;\n // Narrowing cast: skill.category is CategoryPath which includes Subcategory | \"local\" | prefixed forms\n if (!matrix.categories[skill.category as Subcategory]) {\n issues.push({\n severity: \"warning\",\n finding: \"skill-unknown-category\",\n details: `Skill '${skillId}' references category '${skill.category}' which does not exist in the matrix`,\n });\n }\n }\n}\n\nfunction checkCompatibleWithTargets(\n matrix: MergedSkillsMatrix,\n skillIds: Set<SkillId>,\n issues: MatrixHealthIssue[],\n): void {\n for (const [skillId, skill] of typedEntries<SkillId, ResolvedSkill>(matrix.skills)) {\n if (!skill) continue;\n for (const compatId of skill.compatibleWith) {\n if (!skillIds.has(compatId)) {\n issues.push({\n severity: \"warning\",\n finding: \"ghost-compatible-with-target\",\n details: `Skill '${skillId}' has compatibleWith '${compatId}' which does not exist in the matrix`,\n });\n }\n }\n }\n}\n\nfunction checkStackSkillIds(\n matrix: MergedSkillsMatrix,\n skillIds: Set<SkillId>,\n issues: MatrixHealthIssue[],\n): void {\n for (const stack of matrix.suggestedStacks) {\n for (const stackSkillId of stack.allSkillIds) {\n if (!skillIds.has(stackSkillId)) {\n issues.push({\n severity: \"warning\",\n finding: \"stack-ghost-skill\",\n details: `Stack '${stack.id}' references skill '${stackSkillId}' which does not exist in the matrix`,\n });\n }\n }\n }\n}\n","import path from \"path\";\n\nimport { DEFAULT_PUBLIC_SOURCE_NAME, SKILLS_DIR_PATH } from \"../../consts\";\nimport type {\n BoundSkillCandidate,\n MergedSkillsMatrix,\n SkillAlias,\n SkillId,\n SkillSource,\n SkillSourceType,\n} from \"../../types\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { typedEntries, typedKeys } from \"../../utils/typed-object\";\nimport {\n DEFAULT_SOURCE,\n resolveAllSources,\n type ResolvedConfig,\n type SourceEntry,\n} from \"../configuration\";\nimport { extractAllSkills } from \"../matrix\";\nimport { discoverAllPluginSkills } from \"../plugins\";\nimport { fetchFromSource, fetchMarketplace } from \"./source-fetcher\";\n\n/**\n * Annotates every skill in the matrix with multi-source availability metadata.\n *\n * Runs a six-phase tagging pipeline that mutates `primaryMatrix.skills` in place:\n * 1. **Primary** -- tags all skills with the primary source (public or private marketplace)\n * 2. **Local** -- tags skills with `local: true` as installed via local source\n * 3. **Plugin** -- detects plugin-installed skills via `settings.json` and global cache\n * 4. **Public fallback** -- when primary is a private marketplace, fetches the default\n * public source and tags matching skills so users can switch between sources\n * 5. **Extra sources** -- fetches each configured extra source and tags matching skills\n * 6. **Active source** -- sets `activeSource` to the installed variant, or first available\n *\n * After this function completes, each skill in the matrix has `availableSources` (all\n * known sources) and `activeSource` (the one currently in use) populated.\n *\n * @param primaryMatrix - The merged skills matrix to annotate. Mutated in place --\n * `availableSources` and `activeSource` are set on each skill.\n * @param sourceConfig - Resolved source configuration, used to determine whether the\n * primary source is a private marketplace or the default public source\n * @param projectDir - Absolute path to the project root, used to locate plugin directories\n * and resolve extra source configurations\n * @param forceRefresh - Whether to bypass cached source data\n * @param marketplace - Optional marketplace name resolved from the source's marketplace.json.\n * Takes precedence over `sourceConfig.marketplace` when provided.\n *\n * @remarks\n * **Side effects:** Mutates `primaryMatrix` in place. May perform network requests\n * to fetch extra source repositories (via giget). Errors from individual extra sources\n * are warned and skipped -- the function never throws.\n */\nexport async function loadSkillsFromAllSources(\n primaryMatrix: MergedSkillsMatrix,\n sourceConfig: ResolvedConfig,\n projectDir: string,\n forceRefresh = false,\n marketplace?: string,\n): Promise<void> {\n const resolvedMarketplace = marketplace ?? sourceConfig.marketplace;\n const isDefaultPublicSource = sourceConfig.source === DEFAULT_SOURCE;\n\n const primarySourceName = resolvedMarketplace ?? DEFAULT_PUBLIC_SOURCE_NAME;\n const primarySourceType: SkillSourceType = isDefaultPublicSource ? \"public\" : \"private\";\n\n tagPrimarySourceSkills(primaryMatrix, primarySourceName, primarySourceType);\n tagLocalSkills(primaryMatrix);\n await tagPluginSkills(primaryMatrix, projectDir, primarySourceName, primarySourceType);\n\n if (!isDefaultPublicSource) {\n await tagPublicSourceSkills(primaryMatrix, forceRefresh);\n }\n\n await tagExtraSources(primaryMatrix, projectDir, forceRefresh);\n setActiveSources(primaryMatrix);\n}\n\nfunction tagPrimarySourceSkills(\n matrix: MergedSkillsMatrix,\n sourceName: string,\n sourceType: SkillSourceType,\n): void {\n for (const [, skill] of typedEntries(matrix.skills)) {\n if (!skill) continue;\n\n const source: SkillSource = {\n name: sourceName,\n type: sourceType,\n version: skill.version,\n installed: false,\n primary: true,\n };\n\n skill.availableSources = skill.availableSources ?? [];\n skill.availableSources.push(source);\n }\n}\n\nfunction tagLocalSkills(matrix: MergedSkillsMatrix): void {\n let count = 0;\n for (const [, skill] of typedEntries(matrix.skills)) {\n if (!skill) continue;\n if (!skill.local) continue;\n\n const source: SkillSource = {\n name: \"local\",\n type: \"local\",\n installed: true,\n installMode: \"local\",\n };\n\n skill.availableSources = skill.availableSources ?? [];\n skill.availableSources.push(source);\n count++;\n }\n\n verbose(`Tagged ${count} local skills with local source`);\n}\n\nasync function tagPluginSkills(\n matrix: MergedSkillsMatrix,\n projectDir: string,\n primarySourceName: string,\n primarySourceType: SkillSourceType,\n): Promise<void> {\n const allPluginSkillIds = await collectPluginSkillIds(matrix, projectDir);\n\n if (allPluginSkillIds.length === 0) {\n return;\n }\n\n for (const skillId of allPluginSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) continue;\n\n skill.availableSources = skill.availableSources ?? [];\n\n const existingSource = skill.availableSources.find((s) => s.name === primarySourceName);\n if (existingSource && !existingSource.installMode) {\n existingSource.installed = true;\n existingSource.installMode = \"plugin\";\n } else if (!skill.availableSources.some((s) => s.installMode === \"plugin\")) {\n skill.availableSources.push({\n name: primarySourceName,\n type: primarySourceType,\n version: skill.version,\n installed: true,\n installMode: \"plugin\",\n primary: true,\n });\n }\n }\n\n verbose(`Tagged ${allPluginSkillIds.length} plugin-installed skills`);\n}\n\n/**\n * Collects skill IDs from all enabled plugins via settings.json and global cache.\n * Uses {@link discoverAllPluginSkills} to find skills from the plugin registry.\n */\nasync function collectPluginSkillIds(\n _matrix: MergedSkillsMatrix,\n projectDir: string,\n): Promise<SkillId[]> {\n const pluginSkills = await discoverAllPluginSkills(projectDir);\n const skillIds = typedKeys<SkillId>(pluginSkills);\n\n if (skillIds.length === 0) {\n verbose(\"No plugin skills discovered from settings.json\");\n }\n\n return skillIds;\n}\n\n/**\n * When the primary source is a private marketplace, fetch the default public source\n * and tag matching skills so the user can switch between private and public sources\n * in the Sources step.\n */\nasync function tagPublicSourceSkills(\n matrix: MergedSkillsMatrix,\n forceRefresh: boolean,\n): Promise<void> {\n let publicSourceName = DEFAULT_PUBLIC_SOURCE_NAME;\n\n try {\n const marketplaceResult = await fetchMarketplace(DEFAULT_SOURCE, { forceRefresh });\n publicSourceName = marketplaceResult.marketplace.name;\n verbose(`Public marketplace name from marketplace.json: ${publicSourceName}`);\n } catch {\n verbose(\"Public source has no marketplace.json -- using default label\");\n }\n\n try {\n const fetchResult = await fetchFromSource(DEFAULT_SOURCE, { forceRefresh });\n const skillsDir = path.join(fetchResult.path, SKILLS_DIR_PATH);\n const publicSkills = await extractAllSkills(skillsDir);\n\n let matchCount = 0;\n for (const publicSkill of publicSkills) {\n const matrixSkill = matrix.skills[publicSkill.id];\n if (!matrixSkill) continue;\n\n const source: SkillSource = {\n name: publicSourceName,\n type: \"public\",\n installed: false,\n };\n\n matrixSkill.availableSources = matrixSkill.availableSources ?? [];\n matrixSkill.availableSources.push(source);\n matchCount++;\n }\n\n verbose(\n `Public source: ${publicSkills.length} skills found, ${matchCount} matching primary matrix`,\n );\n } catch (error) {\n warn(`Failed to load public source for alternative tagging: ${getErrorMessage(error)}`);\n }\n}\n\nasync function tagExtraSources(\n matrix: MergedSkillsMatrix,\n projectDir: string,\n forceRefresh: boolean,\n): Promise<void> {\n let allSources;\n try {\n allSources = await resolveAllSources(projectDir);\n } catch (error) {\n verbose(`Failed to resolve extra sources: ${getErrorMessage(error)}`);\n return;\n }\n\n if (allSources.extras.length === 0) {\n verbose(\"No extra sources configured\");\n return;\n }\n\n for (const extraSource of allSources.extras) {\n verbose(`Loading extra source: ${extraSource.name} (${extraSource.url})`);\n\n try {\n const fetchResult = await fetchFromSource(extraSource.url, { forceRefresh });\n const skillsDir = path.join(fetchResult.path, SKILLS_DIR_PATH);\n const skills = await extractAllSkills(skillsDir);\n\n let matchCount = 0;\n for (const extractedSkill of skills) {\n const matrixSkill = matrix.skills[extractedSkill.id];\n if (!matrixSkill) continue;\n\n const source: SkillSource = {\n name: extraSource.name,\n type: \"private\",\n url: extraSource.url,\n installed: false,\n };\n\n matrixSkill.availableSources = matrixSkill.availableSources ?? [];\n matrixSkill.availableSources.push(source);\n matchCount++;\n }\n\n verbose(\n `Extra source '${extraSource.name}': ${skills.length} skills found, ${matchCount} matching`,\n );\n } catch (error) {\n warn(\n `Failed to load extra source '${extraSource.name}' ('${extraSource.url}'): ${getErrorMessage(error)}`,\n );\n }\n }\n}\n\n/** Prefers installed source so the wizard shows current state; falls back to first available */\nfunction setActiveSources(matrix: MergedSkillsMatrix): void {\n for (const [, skill] of typedEntries(matrix.skills)) {\n if (!skill) continue;\n if (!skill.availableSources || skill.availableSources.length === 0) continue;\n\n // Prefer installed source, then fall back to first available\n const installedSource = skill.availableSources.find((s) => s.installed);\n skill.activeSource = installedSource ?? skill.availableSources[0];\n }\n}\n\n/**\n * Searches configured extra sources for skills matching a given alias.\n *\n * For each configured source, fetches the repository (using cached data when available),\n * extracts all skill metadata, and matches by the last segment of the skill's directory\n * path against the provided alias (case-insensitive). Used by the wizard's skill search\n * modal to find foreign skills that can be bound to a subcategory.\n *\n * @param alias - Skill alias to search for (e.g., \"react\", \"zustand\"). Matched\n * case-insensitively against the last path segment of each skill's\n * directory path in the source repository.\n * @param configuredSources - Array of extra source entries from project/global config.\n * Each entry has `name` (display name) and `url` (giget-compatible\n * source URL like \"github:org/repo\").\n * @returns Array of matching candidates with skill ID, source URL, source name, alias,\n * and description. Returns an empty array if no sources are configured or no\n * matches are found. Never throws -- errors per-source are warned and skipped.\n *\n * @remarks\n * **Side effects:** May perform network requests to fetch source repositories via giget.\n * Uses cached source data when available (controlled by `forceRefresh: false`).\n */\nexport async function searchExtraSources(\n alias: SkillAlias,\n configuredSources: SourceEntry[],\n): Promise<BoundSkillCandidate[]> {\n const candidates: BoundSkillCandidate[] = [];\n\n if (configuredSources.length === 0) {\n return candidates;\n }\n\n const lowerAlias = alias.toLowerCase();\n\n for (const source of configuredSources) {\n try {\n const fetchResult = await fetchFromSource(source.url, { forceRefresh: false });\n const skillsDir = path.join(fetchResult.path, SKILLS_DIR_PATH);\n const skills = await extractAllSkills(skillsDir);\n\n for (const skill of skills) {\n // Match by last segment of directory path (the alias/display-name convention)\n const segments = skill.directoryPath.split(\"/\");\n const lastSegment = segments[segments.length - 1]?.toLowerCase();\n\n if (lastSegment === lowerAlias) {\n candidates.push({\n id: skill.id,\n sourceUrl: source.url,\n sourceName: source.name,\n alias,\n description: skill.description,\n });\n }\n }\n } catch (error) {\n warn(\n `Failed to search extra source '${source.name}' ('${source.url}'): ${getErrorMessage(error)}`,\n );\n }\n }\n\n return candidates;\n}\n","import path from \"path\";\nimport { fileURLToPath } from \"url\";\n\nimport { fileExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { safeLoadYamlFile } from \"../../utils/yaml\";\nimport { defaultMappingsSchema } from \"../schemas\";\n\nexport type DefaultMappings = {\n skillToAgents: Record<string, string[]>;\n agentSkillPrefixes?: Record<string, string[]>;\n};\n\nlet cachedDefaults: DefaultMappings | null = null;\n\nfunction getDefaultsPath(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n // After tsup build, dist/ is flat (chunks at dist/chunk-*.js) but defaults\n // are copied to dist/cli/defaults/. In dev mode, this file lives at\n // src/cli/lib/loading/ so ../../defaults/ resolves correctly.\n const isInDist = currentDir.includes(\"/dist\");\n return isInDist\n ? path.join(currentDir, \"cli\", \"defaults\", \"agent-mappings.yaml\")\n : path.join(currentDir, \"../..\", \"defaults\", \"agent-mappings.yaml\");\n}\n\nexport async function loadDefaultMappings(): Promise<DefaultMappings | null> {\n if (cachedDefaults !== null) {\n return cachedDefaults;\n }\n\n const defaultsPath = getDefaultsPath();\n\n if (!(await fileExists(defaultsPath))) {\n verbose(`Default mappings file not found at ${defaultsPath}`);\n return null;\n }\n\n const data = await safeLoadYamlFile(defaultsPath, defaultMappingsSchema);\n if (!data) return null;\n\n verbose(`Loaded default mappings from ${defaultsPath}`);\n cachedDefaults = data;\n return cachedDefaults;\n}\n\nexport function getCachedDefaults(): DefaultMappings | null {\n return cachedDefaults;\n}\n\nexport function clearDefaultsCache(): void {\n cachedDefaults = null;\n}\n","import { difference } from \"remeda\";\n\nimport type { ProjectConfig } from \"../../types\";\nimport { loadProjectConfig } from \"./project-config\";\nimport { loadProjectSourceConfig } from \"./config\";\n\nexport type MergeContext = {\n projectDir: string;\n};\n\nexport type MergeResult = {\n config: ProjectConfig;\n merged: boolean;\n existingConfigPath?: string;\n};\n\n// Existing values take precedence for identity fields; arrays are unioned; stack is deep-merged\nexport async function mergeWithExistingConfig(\n newConfig: ProjectConfig,\n context: MergeContext,\n): Promise<MergeResult> {\n const localConfig = { ...newConfig };\n\n const existingFullConfig = await loadProjectConfig(context.projectDir);\n if (existingFullConfig) {\n const existingConfig = existingFullConfig.config;\n\n if (existingConfig.name) {\n localConfig.name = existingConfig.name;\n }\n\n if (existingConfig.description) {\n localConfig.description = existingConfig.description;\n }\n\n if (existingConfig.source) {\n localConfig.source = existingConfig.source;\n }\n\n if (existingConfig.agents && existingConfig.agents.length > 0) {\n const newAgentIds = difference(localConfig.agents, existingConfig.agents);\n localConfig.agents = [...existingConfig.agents, ...newAgentIds];\n }\n\n if (existingConfig.stack) {\n const mergedStack = { ...localConfig.stack };\n for (const [agentId, agentConfig] of Object.entries(existingConfig.stack)) {\n mergedStack[agentId] = { ...mergedStack[agentId], ...agentConfig };\n }\n localConfig.stack = mergedStack;\n }\n\n if (existingConfig.author) {\n localConfig.author = existingConfig.author;\n }\n\n if (existingConfig.agentsSource) {\n localConfig.agentsSource = existingConfig.agentsSource;\n }\n\n if (existingConfig.marketplace) {\n localConfig.marketplace = existingConfig.marketplace;\n }\n\n return {\n config: localConfig,\n merged: true,\n existingConfigPath: existingFullConfig.configPath,\n };\n }\n\n // No existing full config, try simple project source config for author/agentsSource\n const existingProjectConfig = await loadProjectSourceConfig(context.projectDir);\n if (existingProjectConfig?.author) {\n localConfig.author = existingProjectConfig.author;\n }\n if (existingProjectConfig?.agentsSource) {\n localConfig.agentsSource = existingProjectConfig.agentsSource;\n }\n\n return { config: localConfig, merged: false };\n}\n","import path from \"path\";\nimport { fileExists } from \"../../utils/fs\";\nimport { verbose, warn } from \"../../utils/logger\";\nimport { safeLoadYamlFile } from \"../../utils/yaml\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR } from \"../../consts\";\nimport type { ProjectConfig, ValidationResult } from \"../../types\";\nimport { projectConfigLoaderSchema } from \"../schemas\";\nimport { normalizeStackRecord } from \"../stacks/stacks-loader\";\n\nconst CONFIG_PATH = `${CLAUDE_SRC_DIR}/config.yaml`;\nconst LEGACY_CONFIG_PATH = `${CLAUDE_DIR}/config.yaml`;\n\nexport type LoadedProjectConfig = {\n config: ProjectConfig;\n configPath: string;\n};\n\nexport async function loadProjectConfig(projectDir: string): Promise<LoadedProjectConfig | null> {\n // Check .claude-src/config.yaml first (new location)\n const srcConfigPath = path.join(projectDir, CONFIG_PATH);\n // Fall back to .claude/config.yaml (legacy location)\n const legacyConfigPath = path.join(projectDir, LEGACY_CONFIG_PATH);\n\n let configPath = srcConfigPath;\n if (!(await fileExists(srcConfigPath))) {\n if (await fileExists(legacyConfigPath)) {\n configPath = legacyConfigPath;\n verbose(`Using legacy config location: ${legacyConfigPath}`);\n } else {\n verbose(`Project config not found at ${srcConfigPath} or ${legacyConfigPath}`);\n return null;\n }\n }\n\n const data = await safeLoadYamlFile(configPath, projectConfigLoaderSchema);\n if (!data) return null;\n\n // Boundary cast: Zod loader schema validates structure; cast narrows passthrough output\n const config = data as ProjectConfig;\n\n // Normalize stack values to SkillAssignment[] (same as loadStacks does for stacks.yaml)\n if (config.stack) {\n config.stack = normalizeStackRecord(\n config.stack as unknown as Record<string, Record<string, unknown>>,\n );\n }\n\n if (!config.name) {\n warn(\n `Project config at '${configPath}' is missing required 'name' field — defaulting to directory name`,\n );\n config.name = path.basename(projectDir);\n }\n if (!config.skills) {\n warn(`Project config at '${configPath}' is missing 'skills' array — defaulting to empty`);\n config.skills = [];\n }\n\n verbose(`Loaded project config from ${configPath}`);\n return {\n config,\n configPath,\n };\n}\n\nexport function validateProjectConfig(config: unknown): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!config || typeof config !== \"object\") {\n return { valid: false, errors: [\"Config must be an object\"], warnings: [] };\n }\n\n // Boundary cast: config validated as object above, narrow to record for field access\n const c = config as Record<string, unknown>;\n\n if (!c.name || typeof c.name !== \"string\") {\n errors.push(\"name is required and must be a string\");\n }\n\n if (!c.agents || !Array.isArray(c.agents)) {\n errors.push(\"agents is required and must be an array\");\n } else {\n for (const agent of c.agents) {\n if (typeof agent !== \"string\") {\n errors.push(`agents must contain strings, found: ${typeof agent}`);\n }\n }\n }\n\n if (c.version !== undefined && c.version !== \"1\") {\n errors.push('version must be \"1\" (or omitted for default)');\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","import { loadProjectSourceConfig, saveProjectConfig } from \"./config\";\n\nexport async function saveSourceToProjectConfig(projectDir: string, source: string): Promise<void> {\n const existing = (await loadProjectSourceConfig(projectDir)) ?? {};\n await saveProjectConfig(projectDir, { ...existing, source });\n}\n"],"mappings":"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","names":["createHash","os","path","parseYaml","path","parseYaml","path","path","path","parseYaml","stringifyYaml","path","path","path","parseYaml","path","parseYaml","stringifyYaml","path","NULL_BYTE_PATTERN","path","path","path","path","path","parseYaml","path","PLUGIN_MANIFEST_FILE","path","path","path","path","path","path","path","path","path","stringifyYaml","parseYaml","path","unique","path","parseYaml","unique","path","path","pipe","flatMap","parseYaml","path","unique","path","unique","path","stringifyYaml","path","path","path","path","z","path","z","formatZodErrors","path","verbose","path","parseYaml","parseYaml","path","path","parseYaml","path","path","parseYaml","path","z","z","parseYaml","path","selectedSkill","path","path","path","path","path","path","path","createHash","path","os"]}