@agents-inc/cli 0.48.0 → 0.50.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 (250) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -2
  3. package/config/stacks.yaml +0 -1
  4. package/dist/{chunk-YDASDMTH.js → chunk-26MXZUHU.js} +2 -2
  5. package/dist/{chunk-WSGKCBY5.js → chunk-2BWCR762.js} +2 -3
  6. package/dist/chunk-2BWCR762.js.map +1 -0
  7. package/dist/chunk-3VOL4WEG.js +31 -0
  8. package/dist/chunk-3VOL4WEG.js.map +1 -0
  9. package/dist/chunk-4QWDB2MD.js +571 -0
  10. package/dist/chunk-4QWDB2MD.js.map +1 -0
  11. package/dist/{chunk-ZML3OCYA.js → chunk-4R52TQ3K.js} +2 -2
  12. package/dist/{chunk-KPJJOLAQ.js → chunk-5FCHJLM7.js} +34 -16
  13. package/dist/chunk-5FCHJLM7.js.map +1 -0
  14. package/dist/chunk-5FPIKTSA.js +40 -0
  15. package/dist/chunk-5FPIKTSA.js.map +1 -0
  16. package/dist/{chunk-SPVSWDFM.js → chunk-5L724R4C.js} +5 -6
  17. package/dist/{chunk-SPVSWDFM.js.map → chunk-5L724R4C.js.map} +1 -1
  18. package/dist/{chunk-AXV7NFFJ.js → chunk-7LV4V6A4.js} +4 -4
  19. package/dist/{chunk-LESHL6SM.js → chunk-AWP5A6IM.js} +9 -3
  20. package/dist/chunk-AWP5A6IM.js.map +1 -0
  21. package/dist/chunk-C3Q43WLC.js +118 -0
  22. package/dist/chunk-C3Q43WLC.js.map +1 -0
  23. package/dist/{chunk-U2AEK4ZL.js → chunk-CMNKHDOX.js} +2 -2
  24. package/dist/{chunk-X3SZIBVW.js → chunk-D72AFYQR.js} +2 -2
  25. package/dist/chunk-D72AFYQR.js.map +1 -0
  26. package/dist/{chunk-FPTUCWBY.js → chunk-DCE423KO.js} +46 -30
  27. package/dist/chunk-DCE423KO.js.map +1 -0
  28. package/dist/chunk-GBOW6FUW.js +74 -0
  29. package/dist/chunk-GBOW6FUW.js.map +1 -0
  30. package/dist/{chunk-P2SFRDWI.js → chunk-HMSHB5EQ.js} +437 -185
  31. package/dist/chunk-HMSHB5EQ.js.map +1 -0
  32. package/dist/{chunk-GSPPOXMG.js → chunk-HYEUETIC.js} +2 -2
  33. package/dist/{chunk-IS7GP6XC.js → chunk-I6IOGZSZ.js} +61 -52
  34. package/dist/chunk-I6IOGZSZ.js.map +1 -0
  35. package/dist/{chunk-OTTITQ7C.js → chunk-JFF7P4LC.js} +30 -93
  36. package/dist/chunk-JFF7P4LC.js.map +1 -0
  37. package/dist/{chunk-FHKNG3UA.js → chunk-JWYRXE6C.js} +2 -2
  38. package/dist/{chunk-W62XVWXB.js → chunk-KAO3LKB5.js} +3 -3
  39. package/dist/{chunk-AMNCCZSG.js → chunk-KQOU4POU.js} +26 -28
  40. package/dist/chunk-KQOU4POU.js.map +1 -0
  41. package/dist/{chunk-VBAAATPU.js → chunk-M3GQ2R3E.js} +29 -28
  42. package/dist/chunk-M3GQ2R3E.js.map +1 -0
  43. package/dist/{chunk-2BVZOYJP.js → chunk-PGY5XROM.js} +2 -2
  44. package/dist/chunk-PGY5XROM.js.map +1 -0
  45. package/dist/{chunk-5MN5S3DV.js → chunk-QB5HHTAA.js} +8 -19
  46. package/dist/chunk-QB5HHTAA.js.map +1 -0
  47. package/dist/{chunk-34BP5BC4.js → chunk-QYLCINGC.js} +2 -2
  48. package/dist/{chunk-I52THVF6.js → chunk-RA2IPRO2.js} +2 -2
  49. package/dist/{chunk-G5OZQ376.js → chunk-RDWGYKDY.js} +4 -4
  50. package/dist/{chunk-7IAKVZL5.js → chunk-RFKDGJAJ.js} +26 -57
  51. package/dist/chunk-RFKDGJAJ.js.map +1 -0
  52. package/dist/{chunk-5O6GKXAN.js → chunk-SPFHPHYL.js} +7 -7
  53. package/dist/{chunk-NJVJ7VO5.js → chunk-U2W5SENM.js} +3 -3
  54. package/dist/{chunk-37QYD33C.js → chunk-U7X4V4HE.js} +2 -2
  55. package/dist/{chunk-C7DLY64D.js → chunk-UAD3SC27.js} +4 -12
  56. package/dist/chunk-UAD3SC27.js.map +1 -0
  57. package/dist/{chunk-YMUWTPOM.js → chunk-WBHPCBVN.js} +31 -11
  58. package/dist/chunk-WBHPCBVN.js.map +1 -0
  59. package/dist/chunk-WFFV254H.js +314 -0
  60. package/dist/chunk-WFFV254H.js.map +1 -0
  61. package/dist/{chunk-F7KTUFGU.js → chunk-WJHFV6RI.js} +3 -2
  62. package/dist/chunk-WJHFV6RI.js.map +1 -0
  63. package/dist/{chunk-DG2U2WY3.js → chunk-WLZHCM7O.js} +2 -2
  64. package/dist/{chunk-OHDEJEYB.js → chunk-XDSVV5GZ.js} +4 -4
  65. package/dist/{chunk-2DNDAXF6.js → chunk-YDYRAXSY.js} +57 -27
  66. package/dist/chunk-YDYRAXSY.js.map +1 -0
  67. package/dist/commands/build/marketplace.js +4 -4
  68. package/dist/commands/build/plugins.js +5 -5
  69. package/dist/commands/build/stack.js +5 -5
  70. package/dist/commands/compile.js +11 -9
  71. package/dist/commands/compile.js.map +1 -1
  72. package/dist/commands/config/get.js +4 -4
  73. package/dist/commands/config/index.js +5 -5
  74. package/dist/commands/config/path.js +4 -4
  75. package/dist/commands/config/set-project.js +4 -4
  76. package/dist/commands/config/show.js +5 -5
  77. package/dist/commands/config/unset-project.js +4 -4
  78. package/dist/commands/diff.js +4 -4
  79. package/dist/commands/doctor.js +4 -4
  80. package/dist/commands/edit.js +58 -52
  81. package/dist/commands/edit.js.map +1 -1
  82. package/dist/commands/eject.js +4 -4
  83. package/dist/commands/import/skill.js +5 -5
  84. package/dist/commands/info.js +5 -5
  85. package/dist/commands/init.js +40 -435
  86. package/dist/commands/init.js.map +1 -1
  87. package/dist/commands/list.js +4 -4
  88. package/dist/commands/new/agent.js +11 -10
  89. package/dist/commands/new/agent.js.map +1 -1
  90. package/dist/commands/new/marketplace.js +24 -5
  91. package/dist/commands/new/marketplace.js.map +1 -1
  92. package/dist/commands/new/skill.js +15 -208
  93. package/dist/commands/new/skill.js.map +1 -1
  94. package/dist/commands/outdated.js +11 -7
  95. package/dist/commands/outdated.js.map +1 -1
  96. package/dist/commands/search.js +7 -7
  97. package/dist/commands/uninstall.js +6 -6
  98. package/dist/commands/update.js +6 -6
  99. package/dist/commands/validate.js +26 -247
  100. package/dist/commands/validate.js.map +1 -1
  101. package/dist/components/skill-search/skill-search.js +3 -3
  102. package/dist/components/wizard/category-grid.js +3 -2
  103. package/dist/components/wizard/category-grid.test.js +112 -58
  104. package/dist/components/wizard/category-grid.test.js.map +1 -1
  105. package/dist/components/wizard/checkbox-grid.js +5 -3
  106. package/dist/components/wizard/checkbox-grid.test.js +5 -4
  107. package/dist/components/wizard/checkbox-grid.test.js.map +1 -1
  108. package/dist/components/wizard/domain-selection.js +11 -9
  109. package/dist/components/wizard/help-modal.js +2 -2
  110. package/dist/components/wizard/menu-item.js +1 -1
  111. package/dist/components/wizard/search-modal.js +2 -2
  112. package/dist/components/wizard/search-modal.test.js +2 -2
  113. package/dist/components/wizard/section-progress.js +2 -2
  114. package/dist/components/wizard/section-progress.test.js +2 -2
  115. package/dist/components/wizard/selection-card.js +2 -2
  116. package/dist/components/wizard/source-grid.js +4 -3
  117. package/dist/components/wizard/source-grid.test.js +4 -3
  118. package/dist/components/wizard/source-grid.test.js.map +1 -1
  119. package/dist/components/wizard/stack-selection.js +8 -8
  120. package/dist/components/wizard/step-agents.js +10 -8
  121. package/dist/components/wizard/step-agents.test.js +18 -17
  122. package/dist/components/wizard/step-agents.test.js.map +1 -1
  123. package/dist/components/wizard/step-build.js +9 -8
  124. package/dist/components/wizard/step-build.test.js +11 -25
  125. package/dist/components/wizard/step-build.test.js.map +1 -1
  126. package/dist/components/wizard/step-confirm.js +4 -4
  127. package/dist/components/wizard/step-confirm.test.js +8 -8
  128. package/dist/components/wizard/step-refine.js +2 -2
  129. package/dist/components/wizard/step-refine.test.js +2 -2
  130. package/dist/components/wizard/step-settings.js +7 -5
  131. package/dist/components/wizard/step-settings.test.js +10 -8
  132. package/dist/components/wizard/step-settings.test.js.map +1 -1
  133. package/dist/components/wizard/step-sources.js +11 -10
  134. package/dist/components/wizard/step-sources.test.js +12 -11
  135. package/dist/components/wizard/step-sources.test.js.map +1 -1
  136. package/dist/components/wizard/step-stack.js +15 -12
  137. package/dist/components/wizard/step-stack.test.js +16 -13
  138. package/dist/components/wizard/step-stack.test.js.map +1 -1
  139. package/dist/components/wizard/view-title.js +2 -2
  140. package/dist/components/wizard/wizard-layout.js +8 -8
  141. package/dist/components/wizard/wizard-tabs.js +2 -2
  142. package/dist/components/wizard/wizard-tabs.test.js +2 -2
  143. package/dist/components/wizard/wizard.js +27 -25
  144. package/dist/config/stacks.yaml +0 -1
  145. package/dist/hooks/init.js +55 -3
  146. package/dist/hooks/init.js.map +1 -1
  147. package/dist/{source-manager-Y7R6WPOW.js → source-manager-BVB2SG73.js} +4 -4
  148. package/dist/src/agents/meta/agent-summoner/critical-reminders.md +1 -1
  149. package/dist/src/agents/meta/agent-summoner/critical-requirements.md +1 -1
  150. package/dist/src/agents/meta/agent-summoner/examples.md +2 -2
  151. package/dist/src/agents/meta/agent-summoner/output-format.md +1 -1
  152. package/dist/src/agents/meta/agent-summoner/workflow.md +5 -7
  153. package/{src/agents/meta/documentor/agent.yaml → dist/src/agents/meta/documentor/metadata.yaml} +1 -0
  154. package/dist/stores/wizard-store.js +5 -5
  155. package/dist/stores/wizard-store.test.js +79 -27
  156. package/dist/stores/wizard-store.test.js.map +1 -1
  157. package/package.json +1 -1
  158. package/src/agents/meta/agent-summoner/critical-reminders.md +1 -1
  159. package/src/agents/meta/agent-summoner/critical-requirements.md +1 -1
  160. package/src/agents/meta/agent-summoner/examples.md +2 -2
  161. package/src/agents/meta/agent-summoner/output-format.md +1 -1
  162. package/src/agents/meta/agent-summoner/workflow.md +5 -7
  163. package/{dist/src/agents/meta/documentor/agent.yaml → src/agents/meta/documentor/metadata.yaml} +1 -0
  164. package/src/schemas/agent.schema.json +1 -1
  165. package/src/schemas/project-config.schema.json +0 -3
  166. package/dist/chunk-2BVZOYJP.js.map +0 -1
  167. package/dist/chunk-2DNDAXF6.js.map +0 -1
  168. package/dist/chunk-5MN5S3DV.js.map +0 -1
  169. package/dist/chunk-7IAKVZL5.js.map +0 -1
  170. package/dist/chunk-AMNCCZSG.js.map +0 -1
  171. package/dist/chunk-AXZNJ5PN.js +0 -99
  172. package/dist/chunk-AXZNJ5PN.js.map +0 -1
  173. package/dist/chunk-C7DLY64D.js.map +0 -1
  174. package/dist/chunk-F7KTUFGU.js.map +0 -1
  175. package/dist/chunk-FPTUCWBY.js.map +0 -1
  176. package/dist/chunk-IS7GP6XC.js.map +0 -1
  177. package/dist/chunk-KPJJOLAQ.js.map +0 -1
  178. package/dist/chunk-LESHL6SM.js.map +0 -1
  179. package/dist/chunk-OTTITQ7C.js.map +0 -1
  180. package/dist/chunk-P2SFRDWI.js.map +0 -1
  181. package/dist/chunk-PY2XZUBF.js +0 -29
  182. package/dist/chunk-PY2XZUBF.js.map +0 -1
  183. package/dist/chunk-VBAAATPU.js.map +0 -1
  184. package/dist/chunk-WSGKCBY5.js.map +0 -1
  185. package/dist/chunk-X3SZIBVW.js.map +0 -1
  186. package/dist/chunk-YMUWTPOM.js.map +0 -1
  187. package/dist/src/agents/migration/cli-migrator/agent.yaml +0 -12
  188. package/dist/src/agents/migration/cli-migrator/anti-patterns.md +0 -158
  189. package/dist/src/agents/migration/cli-migrator/conversion-mappings.md +0 -63
  190. package/dist/src/agents/migration/cli-migrator/critical-reminders.md +0 -17
  191. package/dist/src/agents/migration/cli-migrator/critical-requirements.md +0 -13
  192. package/dist/src/agents/migration/cli-migrator/intro.md +0 -15
  193. package/dist/src/agents/migration/cli-migrator/output-format.md +0 -164
  194. package/dist/src/agents/migration/cli-migrator/workflow.md +0 -230
  195. package/src/agents/migration/cli-migrator/agent.yaml +0 -12
  196. package/src/agents/migration/cli-migrator/anti-patterns.md +0 -158
  197. package/src/agents/migration/cli-migrator/conversion-mappings.md +0 -63
  198. package/src/agents/migration/cli-migrator/critical-reminders.md +0 -17
  199. package/src/agents/migration/cli-migrator/critical-requirements.md +0 -13
  200. package/src/agents/migration/cli-migrator/intro.md +0 -15
  201. package/src/agents/migration/cli-migrator/output-format.md +0 -164
  202. package/src/agents/migration/cli-migrator/workflow.md +0 -230
  203. /package/dist/{chunk-YDASDMTH.js.map → chunk-26MXZUHU.js.map} +0 -0
  204. /package/dist/{chunk-ZML3OCYA.js.map → chunk-4R52TQ3K.js.map} +0 -0
  205. /package/dist/{chunk-AXV7NFFJ.js.map → chunk-7LV4V6A4.js.map} +0 -0
  206. /package/dist/{chunk-U2AEK4ZL.js.map → chunk-CMNKHDOX.js.map} +0 -0
  207. /package/dist/{chunk-GSPPOXMG.js.map → chunk-HYEUETIC.js.map} +0 -0
  208. /package/dist/{chunk-FHKNG3UA.js.map → chunk-JWYRXE6C.js.map} +0 -0
  209. /package/dist/{chunk-W62XVWXB.js.map → chunk-KAO3LKB5.js.map} +0 -0
  210. /package/dist/{chunk-34BP5BC4.js.map → chunk-QYLCINGC.js.map} +0 -0
  211. /package/dist/{chunk-I52THVF6.js.map → chunk-RA2IPRO2.js.map} +0 -0
  212. /package/dist/{chunk-G5OZQ376.js.map → chunk-RDWGYKDY.js.map} +0 -0
  213. /package/dist/{chunk-5O6GKXAN.js.map → chunk-SPFHPHYL.js.map} +0 -0
  214. /package/dist/{chunk-NJVJ7VO5.js.map → chunk-U2W5SENM.js.map} +0 -0
  215. /package/dist/{chunk-37QYD33C.js.map → chunk-U7X4V4HE.js.map} +0 -0
  216. /package/dist/{chunk-DG2U2WY3.js.map → chunk-WLZHCM7O.js.map} +0 -0
  217. /package/dist/{chunk-OHDEJEYB.js.map → chunk-XDSVV5GZ.js.map} +0 -0
  218. /package/dist/{source-manager-Y7R6WPOW.js.map → source-manager-BVB2SG73.js.map} +0 -0
  219. /package/dist/src/agents/developer/api-developer/{agent.yaml → metadata.yaml} +0 -0
  220. /package/dist/src/agents/developer/cli-developer/{agent.yaml → metadata.yaml} +0 -0
  221. /package/dist/src/agents/developer/web-architecture/{agent.yaml → metadata.yaml} +0 -0
  222. /package/dist/src/agents/developer/web-developer/{agent.yaml → metadata.yaml} +0 -0
  223. /package/dist/src/agents/meta/agent-summoner/{agent.yaml → metadata.yaml} +0 -0
  224. /package/dist/src/agents/meta/skill-summoner/{agent.yaml → metadata.yaml} +0 -0
  225. /package/dist/src/agents/pattern/pattern-scout/{agent.yaml → metadata.yaml} +0 -0
  226. /package/dist/src/agents/pattern/web-pattern-critique/{agent.yaml → metadata.yaml} +0 -0
  227. /package/dist/src/agents/planning/web-pm/{agent.yaml → metadata.yaml} +0 -0
  228. /package/dist/src/agents/researcher/api-researcher/{agent.yaml → metadata.yaml} +0 -0
  229. /package/dist/src/agents/researcher/web-researcher/{agent.yaml → metadata.yaml} +0 -0
  230. /package/dist/src/agents/reviewer/api-reviewer/{agent.yaml → metadata.yaml} +0 -0
  231. /package/dist/src/agents/reviewer/cli-reviewer/{agent.yaml → metadata.yaml} +0 -0
  232. /package/dist/src/agents/reviewer/web-reviewer/{agent.yaml → metadata.yaml} +0 -0
  233. /package/dist/src/agents/tester/cli-tester/{agent.yaml → metadata.yaml} +0 -0
  234. /package/dist/src/agents/tester/web-tester/{agent.yaml → metadata.yaml} +0 -0
  235. /package/src/agents/developer/api-developer/{agent.yaml → metadata.yaml} +0 -0
  236. /package/src/agents/developer/cli-developer/{agent.yaml → metadata.yaml} +0 -0
  237. /package/src/agents/developer/web-architecture/{agent.yaml → metadata.yaml} +0 -0
  238. /package/src/agents/developer/web-developer/{agent.yaml → metadata.yaml} +0 -0
  239. /package/src/agents/meta/agent-summoner/{agent.yaml → metadata.yaml} +0 -0
  240. /package/src/agents/meta/skill-summoner/{agent.yaml → metadata.yaml} +0 -0
  241. /package/src/agents/pattern/pattern-scout/{agent.yaml → metadata.yaml} +0 -0
  242. /package/src/agents/pattern/web-pattern-critique/{agent.yaml → metadata.yaml} +0 -0
  243. /package/src/agents/planning/web-pm/{agent.yaml → metadata.yaml} +0 -0
  244. /package/src/agents/researcher/api-researcher/{agent.yaml → metadata.yaml} +0 -0
  245. /package/src/agents/researcher/web-researcher/{agent.yaml → metadata.yaml} +0 -0
  246. /package/src/agents/reviewer/api-reviewer/{agent.yaml → metadata.yaml} +0 -0
  247. /package/src/agents/reviewer/cli-reviewer/{agent.yaml → metadata.yaml} +0 -0
  248. /package/src/agents/reviewer/web-reviewer/{agent.yaml → metadata.yaml} +0 -0
  249. /package/src/agents/tester/cli-tester/{agent.yaml → metadata.yaml} +0 -0
  250. /package/src/agents/tester/web-tester/{agent.yaml → metadata.yaml} +0 -0
@@ -9,6 +9,7 @@ import {
9
9
  agentFrontmatterValidationSchema,
10
10
  agentNameSchema,
11
11
  agentYamlConfigSchema,
12
+ agentYamlGenerationSchema,
12
13
  categoryPathSchema,
13
14
  copy,
14
15
  directoryExists,
@@ -26,6 +27,7 @@ import {
26
27
  localSkillMetadataSchema,
27
28
  log,
28
29
  marketplaceSchema,
30
+ metadataValidationSchema,
29
31
  pluginAuthorSchema,
30
32
  pluginManifestSchema,
31
33
  projectConfigLoaderSchema,
@@ -41,13 +43,14 @@ import {
41
43
  skillIdSchema,
42
44
  skillMetadataLoaderSchema,
43
45
  skillRulesFileSchema,
46
+ stackConfigValidationSchema,
44
47
  stacksConfigSchema,
45
48
  validateNestingDepth,
46
49
  verbose,
47
50
  warn,
48
51
  warnUnknownFields,
49
52
  writeFile
50
- } from "./chunk-YMUWTPOM.js";
53
+ } from "./chunk-WBHPCBVN.js";
51
54
  import {
52
55
  ARCHIVED_SKILLS_DIR_NAME,
53
56
  CACHE_DIR,
@@ -82,7 +85,7 @@ import {
82
85
  STANDARD_FILES,
83
86
  YAML_FORMATTING,
84
87
  yamlSchemaComment
85
- } from "./chunk-LESHL6SM.js";
88
+ } from "./chunk-AWP5A6IM.js";
86
89
  import {
87
90
  init_esm_shims
88
91
  } from "./chunk-DHET7RCE.js";
@@ -92,6 +95,7 @@ init_esm_shims();
92
95
 
93
96
  // src/cli/lib/configuration/config.ts
94
97
  init_esm_shims();
98
+ import os from "os";
95
99
  import path from "path";
96
100
  import { stringify as stringifyYaml } from "yaml";
97
101
 
@@ -139,6 +143,18 @@ async function loadProjectSourceConfig(projectDir) {
139
143
  verbose(`Loaded project config from ${configPath}`);
140
144
  return data;
141
145
  }
146
+ async function loadGlobalSourceConfig() {
147
+ const homeDir = os.homedir();
148
+ const globalConfigPath = path.join(homeDir, CLAUDE_SRC_DIR, PROJECT_CONFIG_FILE);
149
+ if (!await fileExists(globalConfigPath)) {
150
+ verbose(`Global config not found at ${globalConfigPath}`);
151
+ return null;
152
+ }
153
+ const data = await safeLoadYamlFile(globalConfigPath, projectSourceConfigSchema);
154
+ if (!data) return null;
155
+ verbose(`Loaded global config from ${globalConfigPath}`);
156
+ return data;
157
+ }
142
158
  async function saveProjectConfig(projectDir, config) {
143
159
  const configPath = getProjectConfigPath(projectDir);
144
160
  await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));
@@ -148,9 +164,13 @@ async function saveProjectConfig(projectDir, config) {
148
164
  await writeFile(configPath, `${schemaComment}${content}`);
149
165
  verbose(`Saved project config to ${configPath}`);
150
166
  }
151
- async function resolveSource(flagValue, projectDir) {
167
+ async function loadEffectiveSourceConfig(projectDir) {
152
168
  const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;
153
- const marketplace = projectConfig?.marketplace;
169
+ return projectConfig ?? await loadGlobalSourceConfig();
170
+ }
171
+ async function resolveSource(flagValue, projectDir) {
172
+ const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
173
+ const marketplace = effectiveConfig?.marketplace;
154
174
  if (flagValue !== void 0) {
155
175
  if (flagValue === "" || flagValue.trim() === "") {
156
176
  throw new Error(
@@ -180,10 +200,10 @@ ${message}`
180
200
  }
181
201
  }
182
202
  }
183
- if (projectConfig?.source) {
184
- verbose(`Source from project config: ${projectConfig.source}`);
203
+ if (effectiveConfig?.source) {
204
+ verbose(`Source from project config: ${effectiveConfig.source}`);
185
205
  return {
186
- source: projectConfig.source,
206
+ source: effectiveConfig.source,
187
207
  sourceOrigin: "project",
188
208
  marketplace
189
209
  };
@@ -202,11 +222,11 @@ async function resolveAgentsSource(flagValue, projectDir) {
202
222
  verbose(`Agents source from --agent-source flag: ${flagValue}`);
203
223
  return { agentsSource: flagValue, agentsSourceOrigin: "flag" };
204
224
  }
205
- const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;
206
- if (projectConfig?.agentsSource) {
207
- verbose(`Agents source from project config: ${projectConfig.agentsSource}`);
225
+ const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
226
+ if (effectiveConfig?.agentsSource) {
227
+ verbose(`Agents source from project config: ${effectiveConfig.agentsSource}`);
208
228
  return {
209
- agentsSource: projectConfig.agentsSource,
229
+ agentsSource: effectiveConfig.agentsSource,
210
230
  agentsSourceOrigin: "project"
211
231
  };
212
232
  }
@@ -239,11 +259,11 @@ function formatOrigin(type, origin) {
239
259
  return origin;
240
260
  }
241
261
  async function resolveAuthor(projectDir) {
242
- const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;
243
- return projectConfig?.author;
262
+ const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
263
+ return effectiveConfig?.author;
244
264
  }
245
265
  async function resolveAllSources(projectDir) {
246
- const projectConfig = projectDir ? await loadProjectSourceConfig(projectDir) : null;
266
+ const effectiveConfig = await loadEffectiveSourceConfig(projectDir);
247
267
  const resolvedConfig = await resolveSource(void 0, projectDir);
248
268
  const primary = {
249
269
  name: "marketplace",
@@ -252,8 +272,8 @@ async function resolveAllSources(projectDir) {
252
272
  };
253
273
  const extras = [];
254
274
  const seenNames = /* @__PURE__ */ new Set();
255
- if (projectConfig?.sources) {
256
- for (const source of projectConfig.sources) {
275
+ if (effectiveConfig?.sources) {
276
+ for (const source of effectiveConfig.sources) {
257
277
  if (!seenNames.has(source.name)) {
258
278
  seenNames.add(source.name);
259
279
  extras.push(source);
@@ -420,7 +440,7 @@ function isLocalSource(source) {
420
440
  init_esm_shims();
421
441
  import { createHash } from "crypto";
422
442
  import { downloadTemplate } from "giget";
423
- import os from "os";
443
+ import os3 from "os";
424
444
  import path4 from "path";
425
445
 
426
446
  // src/cli/lib/configuration/index.ts
@@ -535,6 +555,7 @@ import { difference } from "remeda";
535
555
 
536
556
  // src/cli/lib/configuration/project-config.ts
537
557
  init_esm_shims();
558
+ import os2 from "os";
538
559
  import path3 from "path";
539
560
 
540
561
  // src/cli/lib/stacks/stacks-loader.ts
@@ -631,7 +652,7 @@ function getStackSkillIds(stack) {
631
652
  // src/cli/lib/configuration/project-config.ts
632
653
  var CONFIG_PATH = `${CLAUDE_SRC_DIR}/config.yaml`;
633
654
  var LEGACY_CONFIG_PATH = `${CLAUDE_DIR}/config.yaml`;
634
- async function loadProjectConfig(projectDir) {
655
+ async function loadProjectConfigFromDir(projectDir) {
635
656
  const srcConfigPath = path3.join(projectDir, CONFIG_PATH);
636
657
  const legacyConfigPath = path3.join(projectDir, LEGACY_CONFIG_PATH);
637
658
  let configPath = srcConfigPath;
@@ -668,6 +689,15 @@ async function loadProjectConfig(projectDir) {
668
689
  configPath
669
690
  };
670
691
  }
692
+ async function loadProjectConfig(projectDir) {
693
+ const projectResult = await loadProjectConfigFromDir(projectDir);
694
+ if (projectResult) return projectResult;
695
+ const homeDir = os2.homedir();
696
+ if (projectDir !== homeDir) {
697
+ return loadProjectConfigFromDir(homeDir);
698
+ }
699
+ return null;
700
+ }
671
701
  function validateProjectConfig(config) {
672
702
  const errors = [];
673
703
  const warnings = [];
@@ -805,7 +835,7 @@ function getGigetCacheDir(source) {
805
835
  return void 0;
806
836
  }
807
837
  const templateName = uriMatch.groups.repo.replace("/", "-").replace(/[^\da-z-]/gi, "-");
808
- const gigetCacheRoot = process.env.XDG_CACHE_HOME ? path4.resolve(process.env.XDG_CACHE_HOME, "giget") : path4.resolve(os.homedir(), ".cache", "giget");
838
+ const gigetCacheRoot = process.env.XDG_CACHE_HOME ? path4.resolve(process.env.XDG_CACHE_HOME, "giget") : path4.resolve(os3.homedir(), ".cache", "giget");
809
839
  return path4.join(gigetCacheRoot, providerName, templateName);
810
840
  }
811
841
  async function clearGigetCache(source) {
@@ -979,8 +1009,8 @@ Too many plugins: ${marketplace.plugins.length} (limit: ${MAX_MARKETPLACE_PLUGIN
979
1009
 
980
1010
  // src/cli/lib/skills/local-skill-loader.ts
981
1011
  init_esm_shims();
982
- import { parse as parseYaml8 } from "yaml";
983
- import path22 from "path";
1012
+ import { parse as parseYaml9 } from "yaml";
1013
+ import path23 from "path";
984
1014
 
985
1015
  // src/cli/lib/loading/index.ts
986
1016
  init_esm_shims();
@@ -1006,7 +1036,7 @@ function parseFrontmatter(content, filePath) {
1006
1036
  async function loadAllAgents(projectRoot) {
1007
1037
  const agents = {};
1008
1038
  const agentSourcesDir = path5.join(projectRoot, DIRS.agents);
1009
- const files = await glob("**/agent.yaml", agentSourcesDir);
1039
+ const files = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, agentSourcesDir);
1010
1040
  for (const file of files) {
1011
1041
  const fullPath = path5.join(agentSourcesDir, file);
1012
1042
  try {
@@ -1024,7 +1054,7 @@ async function loadAllAgents(projectRoot) {
1024
1054
  };
1025
1055
  verbose(`Loaded agent: ${config.id} from ${file}`);
1026
1056
  } catch (error) {
1027
- warn(`Skipping invalid agent.yaml at '${fullPath}': ${getErrorMessage(error)}`);
1057
+ warn(`Skipping invalid metadata.yaml at '${fullPath}': ${getErrorMessage(error)}`);
1028
1058
  }
1029
1059
  }
1030
1060
  return agents;
@@ -1036,7 +1066,7 @@ async function loadProjectAgents(projectRoot) {
1036
1066
  verbose(`No project agents directory at ${projectAgentsDir}`);
1037
1067
  return agents;
1038
1068
  }
1039
- const files = await glob("**/agent.yaml", projectAgentsDir);
1069
+ const files = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, projectAgentsDir);
1040
1070
  for (const file of files) {
1041
1071
  const fullPath = path5.join(projectAgentsDir, file);
1042
1072
  try {
@@ -1056,7 +1086,7 @@ async function loadProjectAgents(projectRoot) {
1056
1086
  };
1057
1087
  verbose(`Loaded project agent: ${config.id} from ${file}`);
1058
1088
  } catch (error) {
1059
- warn(`Skipping invalid agent.yaml at '${fullPath}': ${getErrorMessage(error)}`);
1089
+ warn(`Skipping invalid metadata.yaml at '${fullPath}': ${getErrorMessage(error)}`);
1060
1090
  }
1061
1091
  }
1062
1092
  return agents;
@@ -1161,7 +1191,8 @@ async function loadPluginSkills(pluginDir) {
1161
1191
 
1162
1192
  // src/cli/lib/loading/source-loader.ts
1163
1193
  init_esm_shims();
1164
- import path21 from "path";
1194
+ import os6 from "os";
1195
+ import path22 from "path";
1165
1196
  import { unique as unique4 } from "remeda";
1166
1197
 
1167
1198
  // src/cli/lib/metadata-keys.ts
@@ -1293,6 +1324,10 @@ async function writeContentHash(pluginDir, contentHash, getManifestPath) {
1293
1324
 
1294
1325
  // src/cli/lib/skills/skill-metadata.ts
1295
1326
  async function readForkedFromMetadata(skillDir) {
1327
+ const metadata = await readLocalSkillMetadata(skillDir);
1328
+ return metadata?.forkedFrom ?? null;
1329
+ }
1330
+ async function readLocalSkillMetadata(skillDir) {
1296
1331
  const metadataPath = path7.join(skillDir, STANDARD_FILES.METADATA_YAML);
1297
1332
  if (!await fileExists(metadataPath)) {
1298
1333
  return null;
@@ -1303,7 +1338,7 @@ async function readForkedFromMetadata(skillDir) {
1303
1338
  warn(`Invalid metadata.yaml at ${metadataPath}: ${formatZodErrors(result.error.issues)}`);
1304
1339
  return null;
1305
1340
  }
1306
- return result.data.forkedFrom ?? null;
1341
+ return result.data;
1307
1342
  }
1308
1343
  async function getLocalSkillsWithMetadata(projectDir) {
1309
1344
  const localSkillsPath = path7.join(projectDir, LOCAL_SKILLS_PATH);
@@ -1476,8 +1511,8 @@ async function copySkillsToLocalFlattened(selectedSkillIds, localSkillsDir, matr
1476
1511
 
1477
1512
  // src/cli/lib/skills/skill-plugin-compiler.ts
1478
1513
  init_esm_shims();
1479
- import path17 from "path";
1480
- import { parse as parseYaml6 } from "yaml";
1514
+ import path18 from "path";
1515
+ import { parse as parseYaml7 } from "yaml";
1481
1516
 
1482
1517
  // src/cli/lib/plugins/index.ts
1483
1518
  init_esm_shims();
@@ -1584,19 +1619,21 @@ init_esm_shims();
1584
1619
 
1585
1620
  // src/cli/lib/installation/installation.ts
1586
1621
  init_esm_shims();
1622
+ import os4 from "os";
1587
1623
  import path11 from "path";
1588
- async function detectInstallation(projectDir = process.cwd()) {
1624
+ async function detectProjectInstallation(projectDir) {
1589
1625
  const srcConfigPath = path11.join(projectDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_YAML);
1590
1626
  const legacyConfigPath = path11.join(projectDir, CLAUDE_DIR, STANDARD_FILES.CONFIG_YAML);
1591
1627
  const localConfigPath = await fileExists(srcConfigPath) ? srcConfigPath : await fileExists(legacyConfigPath) ? legacyConfigPath : null;
1592
1628
  if (!localConfigPath) {
1593
1629
  return null;
1594
1630
  }
1595
- const loaded = await loadProjectConfig(projectDir);
1631
+ const loaded = await loadProjectConfigFromDir(projectDir);
1596
1632
  const mode = loaded?.config?.installMode ?? "local";
1597
1633
  if (mode === "local") {
1598
1634
  return {
1599
1635
  mode: "local",
1636
+ scope: "project",
1600
1637
  configPath: localConfigPath,
1601
1638
  agentsDir: path11.join(projectDir, CLAUDE_DIR, "agents"),
1602
1639
  skillsDir: path11.join(projectDir, CLAUDE_DIR, "skills"),
@@ -1605,12 +1642,45 @@ async function detectInstallation(projectDir = process.cwd()) {
1605
1642
  }
1606
1643
  return {
1607
1644
  mode: "plugin",
1645
+ scope: "project",
1608
1646
  configPath: localConfigPath,
1609
1647
  agentsDir: path11.join(projectDir, CLAUDE_DIR, "agents"),
1610
1648
  skillsDir: path11.join(projectDir, CLAUDE_DIR, PLUGINS_SUBDIR),
1611
1649
  projectDir
1612
1650
  };
1613
1651
  }
1652
+ async function detectGlobalInstallation() {
1653
+ const homeDir = os4.homedir();
1654
+ const srcConfigPath = path11.join(homeDir, CLAUDE_SRC_DIR, STANDARD_FILES.CONFIG_YAML);
1655
+ if (!await fileExists(srcConfigPath)) {
1656
+ return null;
1657
+ }
1658
+ const loaded = await loadProjectConfigFromDir(homeDir);
1659
+ const mode = loaded?.config?.installMode ?? "local";
1660
+ if (mode === "local") {
1661
+ return {
1662
+ mode: "local",
1663
+ scope: "global",
1664
+ configPath: srcConfigPath,
1665
+ agentsDir: path11.join(homeDir, CLAUDE_DIR, "agents"),
1666
+ skillsDir: path11.join(homeDir, CLAUDE_DIR, "skills"),
1667
+ projectDir: homeDir
1668
+ };
1669
+ }
1670
+ return {
1671
+ mode: "plugin",
1672
+ scope: "global",
1673
+ configPath: srcConfigPath,
1674
+ agentsDir: path11.join(homeDir, CLAUDE_DIR, "agents"),
1675
+ skillsDir: path11.join(homeDir, CLAUDE_DIR, PLUGINS_SUBDIR),
1676
+ projectDir: homeDir
1677
+ };
1678
+ }
1679
+ async function detectInstallation(projectDir = process.cwd()) {
1680
+ const projectInstallation = await detectProjectInstallation(projectDir);
1681
+ if (projectInstallation) return projectInstallation;
1682
+ return detectGlobalInstallation();
1683
+ }
1614
1684
 
1615
1685
  // src/cli/lib/installation/local-installer.ts
1616
1686
  init_esm_shims();
@@ -1686,7 +1756,7 @@ async function resolveAgents(agents, skills, compileConfig, _projectRoot, stack)
1686
1756
  const availableAgents = typedKeys(agents);
1687
1757
  const agentList = availableAgents.length > 0 ? `Available agents: ${availableAgents.slice(0, 5).join(", ")}${availableAgents.length > 5 ? ` (and ${availableAgents.length - 5} more)` : ""}` : "No agents found in scanned directories";
1688
1758
  throw new Error(
1689
- `Agent '${agentName}' referenced in compile config but not found in scanned agents. ${agentList}. Check that src/agents/${agentName}/agent.yaml exists.`
1759
+ `Agent '${agentName}' referenced in compile config but not found in scanned agents. ${agentList}. Check that src/agents/${agentName}/metadata.yaml exists.`
1690
1760
  );
1691
1761
  }
1692
1762
  const agentConfig = compileConfig.agents[agentName];
@@ -2183,9 +2253,6 @@ async function buildLocalConfig(wizardResult, sourceResult) {
2183
2253
  }
2184
2254
  function setConfigMetadata(config, wizardResult, sourceResult, sourceFlag) {
2185
2255
  config.installMode = wizardResult.installMode;
2186
- if (wizardResult.expertMode) {
2187
- config.expertMode = true;
2188
- }
2189
2256
  if (wizardResult.selectedDomains && wizardResult.selectedDomains.length > 0) {
2190
2257
  config.domains = wizardResult.selectedDomains;
2191
2258
  }
@@ -2362,7 +2429,7 @@ init_esm_shims();
2362
2429
  // src/cli/lib/plugins/plugin-settings.ts
2363
2430
  init_esm_shims();
2364
2431
  import path15 from "path";
2365
- import os2 from "os";
2432
+ import os5 from "os";
2366
2433
  import { z } from "zod";
2367
2434
  var pluginSettingsSchema = z.object({
2368
2435
  enabledPlugins: z.record(z.string(), z.unknown()).optional()
@@ -2413,7 +2480,7 @@ async function resolvePluginInstallPaths(pluginKeys, projectDir) {
2413
2480
  if (pluginKeys.length === 0) {
2414
2481
  return [];
2415
2482
  }
2416
- const registryPath = path15.join(os2.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR, INSTALLED_PLUGINS_FILE);
2483
+ const registryPath = path15.join(os5.homedir(), CLAUDE_DIR, PLUGINS_SUBDIR, INSTALLED_PLUGINS_FILE);
2417
2484
  if (!await fileExists(registryPath)) {
2418
2485
  verbose(`Plugin registry not found at '${registryPath}'`);
2419
2486
  return [];
@@ -2588,9 +2655,221 @@ function formatInstallationDisplay(info) {
2588
2655
  // src/cli/lib/plugins/plugin-validator.ts
2589
2656
  init_esm_shims();
2590
2657
  import { z as z2 } from "zod";
2658
+ import path17 from "path";
2659
+ import fg2 from "fast-glob";
2660
+ import { countBy } from "remeda";
2661
+
2662
+ // src/cli/lib/schema-validator.ts
2663
+ init_esm_shims();
2664
+ import { sumBy } from "remeda";
2591
2665
  import path16 from "path";
2666
+ import { parse as parseYaml6 } from "yaml";
2592
2667
  import fg from "fast-glob";
2593
- import { countBy } from "remeda";
2668
+ var VALIDATION_TARGETS = [
2669
+ {
2670
+ name: "Skill Categories",
2671
+ schema: skillCategoriesFileSchema,
2672
+ pattern: STANDARD_FILES.SKILL_CATEGORIES_YAML,
2673
+ baseDir: "config"
2674
+ },
2675
+ {
2676
+ name: "Skill Rules",
2677
+ schema: skillRulesFileSchema,
2678
+ pattern: STANDARD_FILES.SKILL_RULES_YAML,
2679
+ baseDir: "config"
2680
+ },
2681
+ {
2682
+ name: "Skill Metadata",
2683
+ schema: metadataValidationSchema,
2684
+ pattern: `**/${STANDARD_FILES.METADATA_YAML}`,
2685
+ baseDir: "src/skills"
2686
+ },
2687
+ {
2688
+ name: "Stack Skill Metadata",
2689
+ schema: metadataValidationSchema,
2690
+ pattern: `**/skills/**/${STANDARD_FILES.METADATA_YAML}`,
2691
+ baseDir: "src/stacks"
2692
+ },
2693
+ {
2694
+ name: "Stack Config",
2695
+ schema: stackConfigValidationSchema,
2696
+ pattern: `*/${STANDARD_FILES.CONFIG_YAML}`,
2697
+ baseDir: "src/stacks"
2698
+ },
2699
+ {
2700
+ name: "Agent Definition",
2701
+ schema: agentYamlGenerationSchema,
2702
+ pattern: `**/${STANDARD_FILES.AGENT_METADATA_YAML}`,
2703
+ baseDir: "src/agents"
2704
+ },
2705
+ {
2706
+ name: "Skill Frontmatter",
2707
+ schema: skillFrontmatterValidationSchema,
2708
+ pattern: `**/${STANDARD_FILES.SKILL_MD}`,
2709
+ baseDir: "src/skills",
2710
+ extractor: extractFrontmatter
2711
+ },
2712
+ {
2713
+ name: "Stack Skill Frontmatter",
2714
+ schema: skillFrontmatterValidationSchema,
2715
+ pattern: `**/skills/**/${STANDARD_FILES.SKILL_MD}`,
2716
+ baseDir: "src/stacks",
2717
+ extractor: extractFrontmatter
2718
+ },
2719
+ {
2720
+ name: "Stacks Config",
2721
+ schema: stacksConfigSchema,
2722
+ pattern: "stacks.yaml",
2723
+ baseDir: "config"
2724
+ },
2725
+ {
2726
+ name: "Project Source Config",
2727
+ schema: projectSourceConfigSchema,
2728
+ pattern: STANDARD_FILES.CONFIG_YAML,
2729
+ baseDir: CLAUDE_SRC_DIR
2730
+ },
2731
+ {
2732
+ name: "Project Skill Metadata",
2733
+ schema: metadataValidationSchema,
2734
+ pattern: `*/${STANDARD_FILES.METADATA_YAML}`,
2735
+ baseDir: `${CLAUDE_DIR}/skills`
2736
+ },
2737
+ {
2738
+ name: "Project Skill Frontmatter",
2739
+ schema: skillFrontmatterValidationSchema,
2740
+ pattern: `*/${STANDARD_FILES.SKILL_MD}`,
2741
+ baseDir: `${CLAUDE_DIR}/skills`,
2742
+ extractor: extractFrontmatter
2743
+ },
2744
+ {
2745
+ name: "Project Agent Frontmatter",
2746
+ schema: agentFrontmatterValidationSchema,
2747
+ pattern: "*.md",
2748
+ baseDir: `${CLAUDE_DIR}/agents`,
2749
+ extractor: extractFrontmatter
2750
+ },
2751
+ {
2752
+ name: "Plugin Manifest",
2753
+ schema: pluginManifestSchema,
2754
+ pattern: `*/${STANDARD_FILES.PLUGIN_JSON}`,
2755
+ baseDir: `${CLAUDE_DIR}/plugins`,
2756
+ extractor: (content) => JSON.parse(content)
2757
+ }
2758
+ ];
2759
+ function formatZodErrors2(error) {
2760
+ return error.issues.map((issue) => {
2761
+ const path24 = issue.path.join(".");
2762
+ if (issue.code === "unrecognized_keys") {
2763
+ return `Unrecognized key: "${issue.keys.join('", "')}"`;
2764
+ }
2765
+ return path24 ? `${path24}: ${issue.message}` : issue.message;
2766
+ });
2767
+ }
2768
+ async function validateFile(filePath, schema, extractor) {
2769
+ try {
2770
+ if (!await fileExists(filePath)) {
2771
+ return { valid: false, errors: [`File not found: ${filePath}`] };
2772
+ }
2773
+ const content = await readFile(filePath);
2774
+ let parsed;
2775
+ if (extractor) {
2776
+ parsed = extractor(content);
2777
+ if (parsed === null) {
2778
+ return {
2779
+ valid: false,
2780
+ errors: ["Failed to extract content (no valid frontmatter found)"]
2781
+ };
2782
+ }
2783
+ } else {
2784
+ parsed = parseYaml6(content);
2785
+ }
2786
+ const result = schema.safeParse(parsed);
2787
+ if (result.success) {
2788
+ return { valid: true, errors: [] };
2789
+ }
2790
+ return { valid: false, errors: formatZodErrors2(result.error) };
2791
+ } catch (error) {
2792
+ const message = getErrorMessage(error);
2793
+ return { valid: false, errors: [`Failed to parse content: ${message}`] };
2794
+ }
2795
+ }
2796
+ async function validateTarget(target, rootDir = process.cwd()) {
2797
+ const baseDir = path16.join(rootDir, target.baseDir);
2798
+ const pattern = path16.join(baseDir, target.pattern);
2799
+ const files = await fg(pattern, { absolute: true });
2800
+ const result = {
2801
+ schemaName: target.name,
2802
+ valid: true,
2803
+ totalFiles: files.length,
2804
+ validFiles: 0,
2805
+ invalidFiles: []
2806
+ };
2807
+ if (files.length === 0) {
2808
+ return result;
2809
+ }
2810
+ for (const file of files) {
2811
+ const validation = await validateFile(file, target.schema, target.extractor);
2812
+ const relativePath = path16.relative(rootDir, file);
2813
+ if (validation.valid) {
2814
+ result.validFiles++;
2815
+ } else {
2816
+ result.valid = false;
2817
+ result.invalidFiles.push({
2818
+ file: relativePath,
2819
+ errors: validation.errors
2820
+ });
2821
+ }
2822
+ }
2823
+ return result;
2824
+ }
2825
+ async function validateAllSchemas(rootDir = process.cwd()) {
2826
+ const results = [];
2827
+ for (const target of VALIDATION_TARGETS) {
2828
+ const result = await validateTarget(target, rootDir);
2829
+ results.push(result);
2830
+ }
2831
+ const summary = {
2832
+ totalSchemas: results.length,
2833
+ totalFiles: sumBy(results, (r) => r.totalFiles),
2834
+ validFiles: sumBy(results, (r) => r.validFiles),
2835
+ invalidFiles: sumBy(results, (r) => r.invalidFiles.length)
2836
+ };
2837
+ return {
2838
+ valid: results.every((r) => r.valid),
2839
+ results,
2840
+ summary
2841
+ };
2842
+ }
2843
+ function printValidationResults(result) {
2844
+ log("\n Schema Validation Summary:");
2845
+ log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
2846
+ log(` Total schemas checked: ${result.summary.totalSchemas}`);
2847
+ log(` Total files: ${result.summary.totalFiles}`);
2848
+ log(` Valid: ${result.summary.validFiles}`);
2849
+ log(` Invalid: ${result.summary.invalidFiles}`);
2850
+ for (const schemaResult of result.results) {
2851
+ if (schemaResult.totalFiles === 0) continue;
2852
+ const status = schemaResult.valid ? "\u2713" : "\u2717";
2853
+ log(
2854
+ `
2855
+ ${status} ${schemaResult.schemaName}: ${schemaResult.validFiles}/${schemaResult.totalFiles} valid`
2856
+ );
2857
+ if (schemaResult.invalidFiles.length > 0) {
2858
+ for (const file of schemaResult.invalidFiles) {
2859
+ log(`
2860
+ ${file.file}:`);
2861
+ file.errors.forEach((e) => log(` - ${e}`));
2862
+ }
2863
+ }
2864
+ }
2865
+ if (result.valid) {
2866
+ log("\n \u2713 All schemas validated successfully\n");
2867
+ } else {
2868
+ log("\n \u2717 Validation failed\n");
2869
+ }
2870
+ }
2871
+
2872
+ // src/cli/lib/plugins/plugin-validator.ts
2594
2873
  var PLUGIN_DIR = PLUGIN_MANIFEST_DIR;
2595
2874
  var PLUGIN_MANIFEST = STANDARD_FILES.PLUGIN_JSON;
2596
2875
  var KEBAB_CASE_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
@@ -2606,15 +2885,6 @@ var pluginManifestValidationSchema = z2.object({
2606
2885
  skills: z2.union([z2.string(), z2.array(z2.string())]).optional(),
2607
2886
  hooks: z2.union([z2.string(), hooksRecordSchema]).optional()
2608
2887
  }).strict();
2609
- function formatZodErrors2(error) {
2610
- return error.issues.map((issue) => {
2611
- const path23 = issue.path.join(".");
2612
- if (issue.code === "unrecognized_keys") {
2613
- return `Unrecognized key: "${issue.keys.join('", "')}"`;
2614
- }
2615
- return path23 ? `${path23}: ${issue.message}` : issue.message;
2616
- });
2617
- }
2618
2888
  function isKebabCase(str) {
2619
2889
  return KEBAB_CASE_REGEX.test(str);
2620
2890
  }
@@ -2631,15 +2901,15 @@ async function validatePluginStructure(pluginPath) {
2631
2901
  warnings: []
2632
2902
  };
2633
2903
  }
2634
- const pluginDir = path16.join(pluginPath, PLUGIN_DIR);
2904
+ const pluginDir = path17.join(pluginPath, PLUGIN_DIR);
2635
2905
  if (!await directoryExists(pluginDir)) {
2636
2906
  errors.push(`Missing ${PLUGIN_DIR}/ directory`);
2637
2907
  }
2638
- const manifestPath = path16.join(pluginDir, PLUGIN_MANIFEST);
2908
+ const manifestPath = path17.join(pluginDir, PLUGIN_MANIFEST);
2639
2909
  if (!await fileExists(manifestPath)) {
2640
2910
  errors.push(`Missing ${PLUGIN_DIR}/${PLUGIN_MANIFEST}`);
2641
2911
  }
2642
- const readmePath = path16.join(pluginPath, "README.md");
2912
+ const readmePath = path17.join(pluginPath, "README.md");
2643
2913
  if (!await fileExists(readmePath)) {
2644
2914
  warnings.push("Missing README.md (recommended for documentation)");
2645
2915
  }
@@ -2689,15 +2959,15 @@ async function validatePluginManifest(manifestPath) {
2689
2959
  if (!manifest.description) {
2690
2960
  warnings.push("Missing description field (recommended for discoverability)");
2691
2961
  }
2692
- const pluginDir = path16.dirname(path16.dirname(manifestPath));
2962
+ const pluginDir = path17.dirname(path17.dirname(manifestPath));
2693
2963
  if (manifest.skills && typeof manifest.skills === "string") {
2694
- const skillsPath = path16.join(pluginDir, manifest.skills);
2964
+ const skillsPath = path17.join(pluginDir, manifest.skills);
2695
2965
  if (!await directoryExists(skillsPath)) {
2696
2966
  errors.push(`Skills path does not exist: ${manifest.skills}`);
2697
2967
  }
2698
2968
  }
2699
2969
  if (manifest.agents && typeof manifest.agents === "string") {
2700
- const agentsPath = path16.join(pluginDir, manifest.agents);
2970
+ const agentsPath = path17.join(pluginDir, manifest.agents);
2701
2971
  if (!await directoryExists(agentsPath)) {
2702
2972
  errors.push(`Agents path does not exist: ${manifest.agents}`);
2703
2973
  }
@@ -2786,9 +3056,9 @@ function prefixResult(result, prefix) {
2786
3056
  };
2787
3057
  }
2788
3058
  async function validatePluginSkillFiles(pluginPath, skillsRelPath) {
2789
- const skillsDir = path16.join(pluginPath, skillsRelPath);
3059
+ const skillsDir = path17.join(pluginPath, skillsRelPath);
2790
3060
  if (!await directoryExists(skillsDir)) return EMPTY_RESULT;
2791
- const files = await fg("**/SKILL.md", { cwd: skillsDir, absolute: true });
3061
+ const files = await fg2("**/SKILL.md", { cwd: skillsDir, absolute: true });
2792
3062
  if (files.length === 0) {
2793
3063
  return {
2794
3064
  valid: true,
@@ -2798,15 +3068,15 @@ async function validatePluginSkillFiles(pluginPath, skillsRelPath) {
2798
3068
  }
2799
3069
  const results = await Promise.all(
2800
3070
  files.map(
2801
- async (f) => prefixResult(await validateSkillFrontmatter(f), path16.relative(pluginPath, f))
3071
+ async (f) => prefixResult(await validateSkillFrontmatter(f), path17.relative(pluginPath, f))
2802
3072
  )
2803
3073
  );
2804
3074
  return mergeResults(results);
2805
3075
  }
2806
3076
  async function validatePluginAgentFiles(pluginPath, agentsRelPath) {
2807
- const agentsDir = path16.join(pluginPath, agentsRelPath);
3077
+ const agentsDir = path17.join(pluginPath, agentsRelPath);
2808
3078
  if (!await directoryExists(agentsDir)) return EMPTY_RESULT;
2809
- const files = await fg("*.md", { cwd: agentsDir, absolute: true });
3079
+ const files = await fg2("*.md", { cwd: agentsDir, absolute: true });
2810
3080
  if (files.length === 0) {
2811
3081
  return {
2812
3082
  valid: true,
@@ -2816,7 +3086,7 @@ async function validatePluginAgentFiles(pluginPath, agentsRelPath) {
2816
3086
  }
2817
3087
  const results = await Promise.all(
2818
3088
  files.map(
2819
- async (f) => prefixResult(await validateAgentFrontmatter(f), path16.relative(pluginPath, f))
3089
+ async (f) => prefixResult(await validateAgentFrontmatter(f), path17.relative(pluginPath, f))
2820
3090
  )
2821
3091
  );
2822
3092
  return mergeResults(results);
@@ -2832,7 +3102,7 @@ async function loadManifestForValidation(manifestPath) {
2832
3102
  async function validatePlugin(pluginPath) {
2833
3103
  const structureResult = await validatePluginStructure(pluginPath);
2834
3104
  if (!structureResult.valid) return structureResult;
2835
- const manifestPath = path16.join(pluginPath, PLUGIN_DIR, PLUGIN_MANIFEST);
3105
+ const manifestPath = path17.join(pluginPath, PLUGIN_DIR, PLUGIN_MANIFEST);
2836
3106
  const manifestResult = await validatePluginManifest(manifestPath);
2837
3107
  const manifest = await loadManifestForValidation(manifestPath);
2838
3108
  const skillsResult = manifest?.skills && typeof manifest.skills === "string" ? await validatePluginSkillFiles(pluginPath, manifest.skills) : EMPTY_RESULT;
@@ -2860,7 +3130,7 @@ async function validateAllPlugins(pluginsDir) {
2860
3130
  const allDirs = await listDirectories(pluginsDir);
2861
3131
  const pluginDirs = [];
2862
3132
  for (const dirName of allDirs) {
2863
- const potentialPluginDir = path16.join(pluginsDir, dirName, PLUGIN_DIR);
3133
+ const potentialPluginDir = path17.join(pluginsDir, dirName, PLUGIN_DIR);
2864
3134
  if (await directoryExists(potentialPluginDir)) {
2865
3135
  pluginDirs.push(dirName);
2866
3136
  }
@@ -2884,7 +3154,7 @@ async function validateAllPlugins(pluginsDir) {
2884
3154
  };
2885
3155
  }
2886
3156
  for (const pluginName of pluginDirs) {
2887
- const pluginPath = path16.join(pluginsDir, pluginName);
3157
+ const pluginPath = path17.join(pluginsDir, pluginName);
2888
3158
  const result = await validatePlugin(pluginPath);
2889
3159
  results.push({ name: pluginName, result });
2890
3160
  }
@@ -2922,7 +3192,7 @@ function sanitizeSkillName(name) {
2922
3192
  return name.replace(/\+/g, "-");
2923
3193
  }
2924
3194
  async function readSkillMetadata(skillPath) {
2925
- const metadataPath = path17.join(skillPath, STANDARD_FILES.METADATA_YAML);
3195
+ const metadataPath = path18.join(skillPath, STANDARD_FILES.METADATA_YAML);
2926
3196
  if (!await fileExists(metadataPath)) {
2927
3197
  return null;
2928
3198
  }
@@ -2930,7 +3200,7 @@ async function readSkillMetadata(skillPath) {
2930
3200
  const content = await readFile(metadataPath);
2931
3201
  const lines = content.split("\n");
2932
3202
  const yamlContent = lines[0]?.startsWith("# yaml-language-server:") ? lines.slice(1).join("\n") : content;
2933
- const result = skillMetadataLoaderSchema.safeParse(parseYaml6(yamlContent));
3203
+ const result = skillMetadataLoaderSchema.safeParse(parseYaml7(yamlContent));
2934
3204
  if (!result.success) {
2935
3205
  warn(`Invalid metadata.yaml at '${skillPath}': ${formatZodErrors(result.error.issues)}`);
2936
3206
  return null;
@@ -2979,8 +3249,8 @@ function generateReadme(skillName, frontmatter, metadata) {
2979
3249
  }
2980
3250
  async function compileSkillPlugin(options) {
2981
3251
  const { skillPath, outputDir, skillName: overrideName } = options;
2982
- const dirBasename = path17.basename(skillPath);
2983
- const skillMdPath = path17.join(skillPath, STANDARD_FILES.SKILL_MD);
3252
+ const dirBasename = path18.basename(skillPath);
3253
+ const skillMdPath = path18.join(skillPath, STANDARD_FILES.SKILL_MD);
2984
3254
  if (!await fileExists(skillMdPath)) {
2985
3255
  throw new Error(
2986
3256
  `Skill '${dirBasename}' is missing required ${STANDARD_FILES.SKILL_MD} file. Expected at: ${skillMdPath}`
@@ -2996,8 +3266,8 @@ async function compileSkillPlugin(options) {
2996
3266
  const skillName = overrideName ?? sanitizeSkillName(frontmatter.name);
2997
3267
  verbose(`Compiling skill plugin: ${skillName} from ${skillPath}`);
2998
3268
  const metadata = await readSkillMetadata(skillPath);
2999
- const pluginDir = path17.join(outputDir, skillName);
3000
- const skillsDir = path17.join(pluginDir, "skills", skillName);
3269
+ const pluginDir = path18.join(outputDir, skillName);
3270
+ const skillsDir = path18.join(pluginDir, "skills", skillName);
3001
3271
  await ensureDir(pluginDir);
3002
3272
  await ensureDir(skillsDir);
3003
3273
  const newHash = await computeSkillFolderHash(skillPath);
@@ -3016,26 +3286,26 @@ async function compileSkillPlugin(options) {
3016
3286
  await writePluginManifest(pluginDir, manifest);
3017
3287
  await writeContentHash(pluginDir, contentHash, getPluginManifestPath);
3018
3288
  verbose(` Wrote plugin.json for ${skillName} (v${version})`);
3019
- await writeFile(path17.join(skillsDir, STANDARD_FILES.SKILL_MD), skillMdContent);
3289
+ await writeFile(path18.join(skillsDir, STANDARD_FILES.SKILL_MD), skillMdContent);
3020
3290
  verbose(` Copied ${STANDARD_FILES.SKILL_MD}`);
3021
3291
  for (const fileName of SKILL_CONTENT_FILES) {
3022
3292
  if (fileName === STANDARD_FILES.SKILL_MD) continue;
3023
- const sourcePath = path17.join(skillPath, fileName);
3293
+ const sourcePath = path18.join(skillPath, fileName);
3024
3294
  if (await fileExists(sourcePath)) {
3025
3295
  const content = await readFile(sourcePath);
3026
- await writeFile(path17.join(skillsDir, fileName), content);
3296
+ await writeFile(path18.join(skillsDir, fileName), content);
3027
3297
  verbose(` Copied ${fileName}`);
3028
3298
  }
3029
3299
  }
3030
3300
  for (const dirName of SKILL_CONTENT_DIRS) {
3031
- const sourceDir = path17.join(skillPath, dirName);
3301
+ const sourceDir = path18.join(skillPath, dirName);
3032
3302
  if (await fileExists(sourceDir)) {
3033
- await copy(sourceDir, path17.join(skillsDir, dirName));
3303
+ await copy(sourceDir, path18.join(skillsDir, dirName));
3034
3304
  verbose(` Copied ${dirName}/`);
3035
3305
  }
3036
3306
  }
3037
3307
  const readme = generateReadme(skillName, frontmatter, metadata);
3038
- await writeFile(path17.join(pluginDir, "README.md"), readme);
3308
+ await writeFile(path18.join(pluginDir, "README.md"), readme);
3039
3309
  verbose(" Generated README.md");
3040
3310
  return {
3041
3311
  pluginPath: pluginDir,
@@ -3047,7 +3317,7 @@ async function compileAllSkillPlugins(skillsDir, outputDir) {
3047
3317
  const results = [];
3048
3318
  const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);
3049
3319
  for (const skillMdFile of skillMdFiles) {
3050
- const skillPath = path17.join(skillsDir, path17.dirname(skillMdFile));
3320
+ const skillPath = path18.join(skillsDir, path18.dirname(skillMdFile));
3051
3321
  try {
3052
3322
  const result = await compileSkillPlugin({
3053
3323
  skillPath,
@@ -3057,7 +3327,7 @@ async function compileAllSkillPlugins(skillsDir, outputDir) {
3057
3327
  log(` [OK] ${result.skillName}`);
3058
3328
  } catch (error) {
3059
3329
  const errorMessage = getErrorMessage(error);
3060
- const dirBasename = path17.basename(skillPath);
3330
+ const dirBasename = path18.basename(skillPath);
3061
3331
  warn(`Failed to compile skill from '${dirBasename}': ${errorMessage}`);
3062
3332
  }
3063
3333
  }
@@ -3073,7 +3343,7 @@ Compiled ${results.length} skill plugins:`);
3073
3343
 
3074
3344
  // src/cli/lib/skills/source-switcher.ts
3075
3345
  init_esm_shims();
3076
- import path18 from "path";
3346
+ import path19 from "path";
3077
3347
  function validateSkillId(skillId) {
3078
3348
  if (!isValidSkillId(skillId)) {
3079
3349
  return false;
@@ -3081,19 +3351,19 @@ function validateSkillId(skillId) {
3081
3351
  return !(skillId.includes("\0") || skillId.includes("..") || skillId.includes("/") || skillId.includes("\\"));
3082
3352
  }
3083
3353
  function validatePathBoundary(resolvedPath, expectedParent) {
3084
- const normalizedPath = path18.resolve(resolvedPath);
3085
- const normalizedParent = path18.resolve(expectedParent);
3086
- return normalizedPath.startsWith(normalizedParent + path18.sep);
3354
+ const normalizedPath = path19.resolve(resolvedPath);
3355
+ const normalizedParent = path19.resolve(expectedParent);
3356
+ return normalizedPath.startsWith(normalizedParent + path19.sep);
3087
3357
  }
3088
3358
  async function archiveLocalSkill(projectDir, skillId) {
3089
3359
  if (!validateSkillId(skillId)) {
3090
3360
  warn(`Invalid skill ID for archiving: '${skillId}'`);
3091
3361
  return;
3092
3362
  }
3093
- const skillsDir = path18.resolve(path18.join(projectDir, LOCAL_SKILLS_PATH));
3094
- const skillPath = path18.resolve(path18.join(skillsDir, skillId));
3095
- const archivedDir = path18.resolve(path18.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));
3096
- const archivedSkillPath = path18.resolve(path18.join(archivedDir, skillId));
3363
+ const skillsDir = path19.resolve(path19.join(projectDir, LOCAL_SKILLS_PATH));
3364
+ const skillPath = path19.resolve(path19.join(skillsDir, skillId));
3365
+ const archivedDir = path19.resolve(path19.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));
3366
+ const archivedSkillPath = path19.resolve(path19.join(archivedDir, skillId));
3097
3367
  if (!validatePathBoundary(skillPath, skillsDir) || !validatePathBoundary(archivedSkillPath, archivedDir)) {
3098
3368
  warn(`Skill ID '${skillId}' resolves outside the skills directory.`);
3099
3369
  return;
@@ -3113,10 +3383,10 @@ async function restoreArchivedSkill(projectDir, skillId) {
3113
3383
  warn(`Invalid skill ID for restoring: '${skillId}'`);
3114
3384
  return false;
3115
3385
  }
3116
- const skillsDir = path18.resolve(path18.join(projectDir, LOCAL_SKILLS_PATH));
3117
- const skillPath = path18.resolve(path18.join(skillsDir, skillId));
3118
- const archivedDir = path18.resolve(path18.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));
3119
- const archivedSkillPath = path18.resolve(path18.join(archivedDir, skillId));
3386
+ const skillsDir = path19.resolve(path19.join(projectDir, LOCAL_SKILLS_PATH));
3387
+ const skillPath = path19.resolve(path19.join(skillsDir, skillId));
3388
+ const archivedDir = path19.resolve(path19.join(skillsDir, ARCHIVED_SKILLS_DIR_NAME));
3389
+ const archivedSkillPath = path19.resolve(path19.join(archivedDir, skillId));
3120
3390
  if (!validatePathBoundary(skillPath, skillsDir) || !validatePathBoundary(archivedSkillPath, archivedDir)) {
3121
3391
  warn(`Skill ID '${skillId}' resolves outside the skills directory.`);
3122
3392
  return false;
@@ -3136,8 +3406,8 @@ init_esm_shims();
3136
3406
 
3137
3407
  // src/cli/lib/matrix/matrix-loader.ts
3138
3408
  init_esm_shims();
3139
- import { parse as parseYaml7 } from "yaml";
3140
- import path19 from "path";
3409
+ import { parse as parseYaml8 } from "yaml";
3410
+ import path20 from "path";
3141
3411
  import { z as z3 } from "zod";
3142
3412
  var rawMetadataSchema = z3.object({
3143
3413
  category: categoryPathSchema,
@@ -3168,7 +3438,7 @@ function synthesizeCategory(categoryPath, skillDomain) {
3168
3438
  }
3169
3439
  async function loadSkillCategories(configPath) {
3170
3440
  const content = await readFile(configPath);
3171
- const raw = parseYaml7(content);
3441
+ const raw = parseYaml8(content);
3172
3442
  const result = skillCategoriesFileSchema.safeParse(raw);
3173
3443
  if (!result.success) {
3174
3444
  throw new Error(
@@ -3180,7 +3450,7 @@ async function loadSkillCategories(configPath) {
3180
3450
  }
3181
3451
  async function loadSkillRules(configPath) {
3182
3452
  const content = await readFile(configPath);
3183
- const raw = parseYaml7(content);
3453
+ const raw = parseYaml8(content);
3184
3454
  const result = skillRulesFileSchema.safeParse(raw);
3185
3455
  if (!result.success) {
3186
3456
  throw new Error(
@@ -3207,15 +3477,15 @@ async function extractAllSkills(skillsDir) {
3207
3477
  const skills = [];
3208
3478
  const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);
3209
3479
  for (const metadataFile of metadataFiles) {
3210
- const skillDir = path19.dirname(metadataFile);
3211
- const skillMdPath = path19.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
3212
- const metadataPath = path19.join(skillsDir, metadataFile);
3480
+ const skillDir = path20.dirname(metadataFile);
3481
+ const skillMdPath = path20.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
3482
+ const metadataPath = path20.join(skillsDir, metadataFile);
3213
3483
  if (!await fileExists(skillMdPath)) {
3214
3484
  verbose(`Skipping ${metadataFile}: No ${STANDARD_FILES.SKILL_MD} found`);
3215
3485
  continue;
3216
3486
  }
3217
3487
  const metadataContent = await readFile(metadataPath);
3218
- const rawMetadata = parseYaml7(metadataContent);
3488
+ const rawMetadata = parseYaml8(metadataContent);
3219
3489
  const metadataResult = rawMetadataSchema.safeParse(rawMetadata);
3220
3490
  if (!metadataResult.success) {
3221
3491
  warn(
@@ -3475,26 +3745,31 @@ function initializeSelectionContext(currentSelections, matrix) {
3475
3745
  const selectedSet = new Set(resolvedSelections);
3476
3746
  return { resolvedSelections, selectedSet };
3477
3747
  }
3478
- function isDisabled(skillId, currentSelections, matrix, options) {
3479
- if (options?.expertMode) {
3480
- return false;
3481
- }
3748
+ function isDiscouraged(skillId, currentSelections, matrix) {
3482
3749
  const fullId = resolveAlias(skillId, matrix);
3483
3750
  const skill = matrix.skills[fullId];
3484
3751
  if (!skill) {
3485
3752
  return false;
3486
3753
  }
3487
- for (const selectedId of currentSelections) {
3488
- const selectedFullId = resolveAlias(selectedId, matrix);
3489
- if (skill.conflictsWith.some((c) => c.skillId === selectedFullId)) {
3754
+ const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections, matrix);
3755
+ for (const selectedId of resolvedSelections) {
3756
+ const selectedSkill = matrix.skills[selectedId];
3757
+ if (selectedSkill?.discourages.some((d) => d.skillId === fullId)) {
3490
3758
  return true;
3491
3759
  }
3492
- const selectedSkill = matrix.skills[selectedFullId];
3760
+ if (skill.discourages.some((d) => d.skillId === selectedId)) {
3761
+ return true;
3762
+ }
3763
+ }
3764
+ for (const selectedId of resolvedSelections) {
3765
+ if (skill.conflictsWith.some((c) => c.skillId === selectedId)) {
3766
+ return true;
3767
+ }
3768
+ const selectedSkill = matrix.skills[selectedId];
3493
3769
  if (selectedSkill?.conflictsWith.some((c) => c.skillId === fullId)) {
3494
3770
  return true;
3495
3771
  }
3496
3772
  }
3497
- const { selectedSet } = initializeSelectionContext(currentSelections, matrix);
3498
3773
  for (const requirement of skill.requires) {
3499
3774
  if (requirement.needsAny) {
3500
3775
  const hasAny = requirement.skillIds.some((reqId) => selectedSet.has(reqId));
@@ -3510,13 +3785,26 @@ function isDisabled(skillId, currentSelections, matrix, options) {
3510
3785
  }
3511
3786
  return false;
3512
3787
  }
3513
- function getDisableReason(skillId, currentSelections, matrix) {
3788
+ function getDiscourageReason(skillId, currentSelections, matrix) {
3514
3789
  const fullId = resolveAlias(skillId, matrix);
3515
3790
  const skill = matrix.skills[fullId];
3516
3791
  if (!skill) {
3517
3792
  return void 0;
3518
3793
  }
3519
3794
  const { resolvedSelections, selectedSet } = initializeSelectionContext(currentSelections, matrix);
3795
+ for (const selectedId of resolvedSelections) {
3796
+ const selectedSkill = matrix.skills[selectedId];
3797
+ if (selectedSkill) {
3798
+ const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);
3799
+ if (discourage) {
3800
+ return discourage.reason;
3801
+ }
3802
+ }
3803
+ const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);
3804
+ if (reverseDiscourage) {
3805
+ return reverseDiscourage.reason;
3806
+ }
3807
+ }
3520
3808
  for (const selectedId of resolvedSelections) {
3521
3809
  const conflict = skill.conflictsWith.find((c) => c.skillId === selectedId);
3522
3810
  if (conflict) {
@@ -3548,46 +3836,6 @@ function getDisableReason(skillId, currentSelections, matrix) {
3548
3836
  }
3549
3837
  return void 0;
3550
3838
  }
3551
- function isDiscouraged(skillId, currentSelections, matrix) {
3552
- const fullId = resolveAlias(skillId, matrix);
3553
- const skill = matrix.skills[fullId];
3554
- if (!skill) {
3555
- return false;
3556
- }
3557
- const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);
3558
- for (const selectedId of resolvedSelections) {
3559
- const selectedSkill = matrix.skills[selectedId];
3560
- if (selectedSkill?.discourages.some((d) => d.skillId === fullId)) {
3561
- return true;
3562
- }
3563
- if (skill.discourages.some((d) => d.skillId === selectedId)) {
3564
- return true;
3565
- }
3566
- }
3567
- return false;
3568
- }
3569
- function getDiscourageReason(skillId, currentSelections, matrix) {
3570
- const fullId = resolveAlias(skillId, matrix);
3571
- const skill = matrix.skills[fullId];
3572
- if (!skill) {
3573
- return void 0;
3574
- }
3575
- const { resolvedSelections } = initializeSelectionContext(currentSelections, matrix);
3576
- for (const selectedId of resolvedSelections) {
3577
- const selectedSkill = matrix.skills[selectedId];
3578
- if (selectedSkill) {
3579
- const discourage = selectedSkill.discourages.find((d) => d.skillId === fullId);
3580
- if (discourage) {
3581
- return discourage.reason;
3582
- }
3583
- }
3584
- const reverseDiscourage = skill.discourages.find((d) => d.skillId === selectedId);
3585
- if (reverseDiscourage) {
3586
- return reverseDiscourage.reason;
3587
- }
3588
- }
3589
- return void 0;
3590
- }
3591
3839
  function isRecommended(skillId, currentSelections, matrix) {
3592
3840
  const fullId = resolveAlias(skillId, matrix);
3593
3841
  const skill = matrix.skills[fullId];
@@ -3750,7 +3998,7 @@ function validateSelection(selections, matrix) {
3750
3998
  warnings
3751
3999
  };
3752
4000
  }
3753
- function getAvailableSkills(categoryId, currentSelections, matrix, options) {
4001
+ function getAvailableSkills(categoryId, currentSelections, matrix) {
3754
4002
  const skillOptions = [];
3755
4003
  const { selectedSet } = initializeSelectionContext(currentSelections, matrix);
3756
4004
  for (const skill of Object.values(matrix.skills)) {
@@ -3758,15 +4006,12 @@ function getAvailableSkills(categoryId, currentSelections, matrix, options) {
3758
4006
  if (skill.category !== categoryId) {
3759
4007
  continue;
3760
4008
  }
3761
- const disabled = isDisabled(skill.id, currentSelections, matrix, options);
3762
- const discouraged = !disabled && isDiscouraged(skill.id, currentSelections, matrix);
3763
- const recommended = !disabled && !discouraged && isRecommended(skill.id, currentSelections, matrix);
4009
+ const discouraged = isDiscouraged(skill.id, currentSelections, matrix);
4010
+ const recommended = !discouraged && isRecommended(skill.id, currentSelections, matrix);
3764
4011
  skillOptions.push({
3765
4012
  id: skill.id,
3766
4013
  displayName: skill.displayName,
3767
4014
  description: skill.description,
3768
- disabled,
3769
- disabledReason: disabled ? getDisableReason(skill.id, currentSelections, matrix) : void 0,
3770
4015
  discouraged,
3771
4016
  discouragedReason: discouraged ? getDiscourageReason(skill.id, currentSelections, matrix) : void 0,
3772
4017
  recommended,
@@ -3861,7 +4106,7 @@ function checkSkillRelationRefs(matrix, issues) {
3861
4106
 
3862
4107
  // src/cli/lib/loading/multi-source-loader.ts
3863
4108
  init_esm_shims();
3864
- import path20 from "path";
4109
+ import path21 from "path";
3865
4110
  async function loadSkillsFromAllSources(primaryMatrix, sourceConfig, projectDir, forceRefresh = false, marketplace) {
3866
4111
  const resolvedMarketplace = marketplace ?? sourceConfig.marketplace;
3867
4112
  const isDefaultPublicSource = sourceConfig.source === DEFAULT_SOURCE;
@@ -3950,7 +4195,7 @@ async function tagPublicSourceSkills(matrix, forceRefresh) {
3950
4195
  }
3951
4196
  try {
3952
4197
  const fetchResult = await fetchFromSource(DEFAULT_SOURCE, { forceRefresh });
3953
- const skillsDir = path20.join(fetchResult.path, SKILLS_DIR_PATH);
4198
+ const skillsDir = path21.join(fetchResult.path, SKILLS_DIR_PATH);
3954
4199
  const publicSkills = await extractAllSkills(skillsDir);
3955
4200
  let matchCount = 0;
3956
4201
  for (const publicSkill of publicSkills) {
@@ -3988,7 +4233,7 @@ async function tagExtraSources(matrix, projectDir, forceRefresh) {
3988
4233
  verbose(`Loading extra source: ${extraSource.name} (${extraSource.url})`);
3989
4234
  try {
3990
4235
  const fetchResult = await fetchFromSource(extraSource.url, { forceRefresh });
3991
- const skillsDir = path20.join(fetchResult.path, SKILLS_DIR_PATH);
4236
+ const skillsDir = path21.join(fetchResult.path, SKILLS_DIR_PATH);
3992
4237
  const skills = await extractAllSkills(skillsDir);
3993
4238
  let matchCount = 0;
3994
4239
  for (const extractedSkill of skills) {
@@ -4031,7 +4276,7 @@ async function searchExtraSources(alias, configuredSources) {
4031
4276
  for (const source of configuredSources) {
4032
4277
  try {
4033
4278
  const fetchResult = await fetchFromSource(source.url, { forceRefresh: false });
4034
- const skillsDir = path20.join(fetchResult.path, SKILLS_DIR_PATH);
4279
+ const skillsDir = path21.join(fetchResult.path, SKILLS_DIR_PATH);
4035
4280
  const skills = await extractAllSkills(skillsDir);
4036
4281
  for (const skill of skills) {
4037
4282
  const segments = skill.directoryPath.split("/");
@@ -4069,7 +4314,11 @@ async function loadSkillsMatrixFromSource(options = {}) {
4069
4314
  result = await loadFromRemote(source, sourceConfig, forceRefresh);
4070
4315
  }
4071
4316
  const resolvedProjectDir = projectDir || process.cwd();
4072
- const localSkillsResult = await discoverLocalSkills(resolvedProjectDir);
4317
+ let localSkillsResult = await discoverLocalSkills(resolvedProjectDir);
4318
+ const homeDir = os6.homedir();
4319
+ if ((!localSkillsResult || localSkillsResult.skills.length === 0) && resolvedProjectDir !== homeDir) {
4320
+ localSkillsResult = await discoverLocalSkills(homeDir);
4321
+ }
4073
4322
  if (localSkillsResult && localSkillsResult.skills.length > 0) {
4074
4323
  verbose(
4075
4324
  `Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`
@@ -4089,7 +4338,7 @@ async function loadSkillsMatrixFromSource(options = {}) {
4089
4338
  async function loadFromLocal(source, sourceConfig) {
4090
4339
  let skillsPath;
4091
4340
  if (isLocalSource(source)) {
4092
- skillsPath = path21.isAbsolute(source) ? source : path21.resolve(process.cwd(), source);
4341
+ skillsPath = path22.isAbsolute(source) ? source : path22.resolve(process.cwd(), source);
4093
4342
  } else {
4094
4343
  skillsPath = PROJECT_ROOT;
4095
4344
  }
@@ -4130,8 +4379,8 @@ async function loadAndMergeFromBasePath(basePath) {
4130
4379
  const sourceProjectConfig = await loadProjectSourceConfig(basePath);
4131
4380
  const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;
4132
4381
  const stacksRelFile = sourceProjectConfig?.stacksFile;
4133
- const cliCategoriesPath = path21.join(PROJECT_ROOT, SKILL_CATEGORIES_YAML_PATH);
4134
- const cliRulesPath = path21.join(PROJECT_ROOT, SKILL_RULES_YAML_PATH);
4382
+ const cliCategoriesPath = path22.join(PROJECT_ROOT, SKILL_CATEGORIES_YAML_PATH);
4383
+ const cliRulesPath = path22.join(PROJECT_ROOT, SKILL_RULES_YAML_PATH);
4135
4384
  const cliCategories = await loadSkillCategories(cliCategoriesPath);
4136
4385
  const cliRules = await loadSkillRules(cliRulesPath);
4137
4386
  let categories = cliCategories;
@@ -4139,8 +4388,8 @@ async function loadAndMergeFromBasePath(basePath) {
4139
4388
  let aliases = cliRules.aliases;
4140
4389
  let perSkillRules = cliRules.perSkill;
4141
4390
  await discoverAndExtendFromSource(basePath);
4142
- const sourceCategoriesPath = path21.join(basePath, SKILL_CATEGORIES_YAML_PATH);
4143
- const sourceRulesPath = path21.join(basePath, SKILL_RULES_YAML_PATH);
4391
+ const sourceCategoriesPath = path22.join(basePath, SKILL_CATEGORIES_YAML_PATH);
4392
+ const sourceRulesPath = path22.join(basePath, SKILL_RULES_YAML_PATH);
4144
4393
  const hasSourceCategories = await fileExists(sourceCategoriesPath);
4145
4394
  const hasSourceRules = await fileExists(sourceRulesPath);
4146
4395
  if (hasSourceCategories || hasSourceRules) {
@@ -4174,7 +4423,7 @@ async function loadAndMergeFromBasePath(basePath) {
4174
4423
  } else {
4175
4424
  verbose(`Matrix from CLI only (source has no categories/rules files)`);
4176
4425
  }
4177
- const skillsDir = path21.join(basePath, skillsDirRelPath);
4426
+ const skillsDir = path22.join(basePath, skillsDirRelPath);
4178
4427
  verbose(`Skills from source: ${skillsDir}`);
4179
4428
  const skills = await extractAllSkills(skillsDir);
4180
4429
  const mergedMatrix = await mergeMatrixWithSkills(
@@ -4261,9 +4510,9 @@ function getMarketplaceLabel(sourceResult) {
4261
4510
  }
4262
4511
  return marketplace;
4263
4512
  }
4264
- async function discoverCustomAgentValues(agentsDir, file, parseYaml9, builtinDomains) {
4265
- const content = await readFile(path21.join(agentsDir, file));
4266
- const raw = parseYaml9(content);
4513
+ async function discoverCustomAgentValues(agentsDir, file, parseYaml10, builtinDomains) {
4514
+ const content = await readFile(path22.join(agentsDir, file));
4515
+ const raw = parseYaml10(content);
4267
4516
  if (raw?.custom !== true) return {};
4268
4517
  const result = {};
4269
4518
  if (typeof raw?.id === "string" && !agentNameSchema.safeParse(raw.id).success) {
@@ -4274,16 +4523,16 @@ async function discoverCustomAgentValues(agentsDir, file, parseYaml9, builtinDom
4274
4523
  }
4275
4524
  return result;
4276
4525
  }
4277
- async function discoverCustomSkillValues(skillsDir, file, parseYaml9, builtinSubcategories, builtinDomains) {
4278
- const content = await readFile(path21.join(skillsDir, file));
4526
+ async function discoverCustomSkillValues(skillsDir, file, parseYaml10, builtinSubcategories, builtinDomains) {
4527
+ const content = await readFile(path22.join(skillsDir, file));
4279
4528
  const frontmatter = parseFrontmatter(content);
4280
4529
  if (!frontmatter) return {};
4281
4530
  const skillId = frontmatter.name;
4282
- const skillDir = path21.dirname(path21.join(skillsDir, file));
4283
- const metadataPath = path21.join(skillDir, STANDARD_FILES.METADATA_YAML);
4531
+ const skillDir = path22.dirname(path22.join(skillsDir, file));
4532
+ const metadataPath = path22.join(skillDir, STANDARD_FILES.METADATA_YAML);
4284
4533
  if (!await fileExists(metadataPath)) return {};
4285
4534
  const metadataContent = await readFile(metadataPath);
4286
- const metadataRaw = parseYaml9(metadataContent);
4535
+ const metadataRaw = parseYaml10(metadataContent);
4287
4536
  if (metadataRaw?.custom !== true) return {};
4288
4537
  const result = {};
4289
4538
  result.skillId = skillId;
@@ -4298,26 +4547,26 @@ async function discoverCustomSkillValues(skillsDir, file, parseYaml9, builtinSub
4298
4547
  return result;
4299
4548
  }
4300
4549
  async function discoverAndExtendFromSource(basePath) {
4301
- const { parse: parseYaml9 } = await import("yaml");
4550
+ const { parse: parseYaml10 } = await import("yaml");
4302
4551
  const builtinSubcategories = new Set(SUBCATEGORY_VALUES);
4303
4552
  const builtinDomains = new Set(DOMAIN_VALUES);
4304
4553
  const customCategories = [];
4305
4554
  const customDomains = [];
4306
4555
  const customAgentNames = [];
4307
4556
  const customSkillIds = [];
4308
- const agentsDir = path21.join(basePath, DIRS.agents);
4557
+ const agentsDir = path22.join(basePath, DIRS.agents);
4309
4558
  if (await directoryExists(agentsDir)) {
4310
- const agentFiles = await glob(`**/${STANDARD_FILES.AGENT_YAML}`, agentsDir);
4559
+ const agentFiles = await glob(`**/${STANDARD_FILES.AGENT_METADATA_YAML}`, agentsDir);
4311
4560
  for (const file of agentFiles) {
4312
4561
  try {
4313
- const result = await discoverCustomAgentValues(agentsDir, file, parseYaml9, builtinDomains);
4562
+ const result = await discoverCustomAgentValues(agentsDir, file, parseYaml10, builtinDomains);
4314
4563
  if (result.agentName) customAgentNames.push(result.agentName);
4315
4564
  if (result.domain) customDomains.push(result.domain);
4316
4565
  } catch {
4317
4566
  }
4318
4567
  }
4319
4568
  }
4320
- const skillsDir = path21.join(basePath, DIRS.skills);
4569
+ const skillsDir = path22.join(basePath, DIRS.skills);
4321
4570
  if (await directoryExists(skillsDir)) {
4322
4571
  const skillFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);
4323
4572
  for (const file of skillFiles) {
@@ -4325,7 +4574,7 @@ async function discoverAndExtendFromSource(basePath) {
4325
4574
  const result = await discoverCustomSkillValues(
4326
4575
  skillsDir,
4327
4576
  file,
4328
- parseYaml9,
4577
+ parseYaml10,
4329
4578
  builtinSubcategories,
4330
4579
  builtinDomains
4331
4580
  );
@@ -4382,7 +4631,7 @@ function mergeLocalSkillsIntoMatrix(matrix, localResult) {
4382
4631
 
4383
4632
  // src/cli/lib/skills/local-skill-loader.ts
4384
4633
  async function discoverLocalSkills(projectDir) {
4385
- const localSkillsPath = path22.join(projectDir, LOCAL_SKILLS_PATH);
4634
+ const localSkillsPath = path23.join(projectDir, LOCAL_SKILLS_PATH);
4386
4635
  if (!await directoryExists(localSkillsPath)) {
4387
4636
  verbose(`Local skills directory not found: ${localSkillsPath}`);
4388
4637
  return null;
@@ -4402,9 +4651,9 @@ async function discoverLocalSkills(projectDir) {
4402
4651
  };
4403
4652
  }
4404
4653
  async function extractLocalSkill(localSkillsPath, skillDirName) {
4405
- const skillDir = path22.join(localSkillsPath, skillDirName);
4406
- const metadataPath = path22.join(skillDir, STANDARD_FILES.METADATA_YAML);
4407
- const skillMdPath = path22.join(skillDir, STANDARD_FILES.SKILL_MD);
4654
+ const skillDir = path23.join(localSkillsPath, skillDirName);
4655
+ const metadataPath = path23.join(skillDir, STANDARD_FILES.METADATA_YAML);
4656
+ const skillMdPath = path23.join(skillDir, STANDARD_FILES.SKILL_MD);
4408
4657
  if (!await fileExists(metadataPath)) {
4409
4658
  verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);
4410
4659
  return null;
@@ -4414,9 +4663,9 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
4414
4663
  return null;
4415
4664
  }
4416
4665
  const metadataContent = await readFile(metadataPath);
4417
- const parsed = localRawMetadataSchema.safeParse(parseYaml8(metadataContent));
4666
+ const parsed = localRawMetadataSchema.safeParse(parseYaml9(metadataContent));
4418
4667
  if (!parsed.success) {
4419
- warn(
4668
+ verbose(
4420
4669
  `Skipping local skill '${skillDirName}': invalid metadata.yaml \u2014 ${formatZodErrors(parsed.error.issues)}`
4421
4670
  );
4422
4671
  return null;
@@ -4430,7 +4679,7 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
4430
4679
  const skillMdContent = await readFile(skillMdPath);
4431
4680
  const frontmatter = parseFrontmatter(skillMdContent, skillMdPath);
4432
4681
  if (!frontmatter) {
4433
- warn(`Skipping local skill '${skillDirName}': invalid SKILL.md frontmatter`);
4682
+ verbose(`Skipping local skill '${skillDirName}': invalid SKILL.md frontmatter`);
4434
4683
  return null;
4435
4684
  }
4436
4685
  const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;
@@ -4590,13 +4839,16 @@ export {
4590
4839
  addSource,
4591
4840
  removeSource,
4592
4841
  getSourceSummary,
4842
+ detectProjectInstallation,
4593
4843
  detectInstallation,
4594
4844
  installPluginConfig,
4595
4845
  installLocal,
4596
4846
  getInstallationInfo,
4597
4847
  formatInstallationDisplay,
4848
+ validateAllSchemas,
4849
+ printValidationResults,
4598
4850
  validatePlugin,
4599
4851
  validateAllPlugins,
4600
4852
  printPluginValidationResult
4601
4853
  };
4602
- //# sourceMappingURL=chunk-P2SFRDWI.js.map
4854
+ //# sourceMappingURL=chunk-HMSHB5EQ.js.map