agents-inc 0.152.1 → 0.153.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 (440) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +31 -35
  3. package/dist/{chunk-LDP5ASDM.js → chunk-2HC2SNRP.js} +2 -15
  4. package/dist/chunk-2HC2SNRP.js.map +1 -0
  5. package/dist/{chunk-WKTHWQKM.js → chunk-35VOK7XE.js} +1338 -2573
  6. package/dist/chunk-35VOK7XE.js.map +1 -0
  7. package/dist/{chunk-SX5H6TSC.js → chunk-4VYALFQZ.js} +11 -8
  8. package/dist/chunk-4VYALFQZ.js.map +1 -0
  9. package/dist/{chunk-KXYVJGJP.js → chunk-6CNRMCFM.js} +3 -2
  10. package/dist/{chunk-KXYVJGJP.js.map → chunk-6CNRMCFM.js.map} +1 -1
  11. package/dist/{chunk-LZ52XEPR.js → chunk-ACKC577F.js} +7 -6
  12. package/dist/chunk-ACKC577F.js.map +1 -0
  13. package/dist/{chunk-XHUODHZ4.js → chunk-BMGBA6HJ.js} +22 -49
  14. package/dist/chunk-BMGBA6HJ.js.map +1 -0
  15. package/dist/{chunk-FVDKAVOL.js → chunk-EFU6P3B7.js} +18 -51
  16. package/dist/chunk-EFU6P3B7.js.map +1 -0
  17. package/dist/{chunk-STMHDOZD.js → chunk-F7Z5I6GU.js} +12 -9
  18. package/dist/chunk-F7Z5I6GU.js.map +1 -0
  19. package/dist/{chunk-E5X6RJ4E.js → chunk-FIHTAFST.js} +29 -26
  20. package/dist/chunk-FIHTAFST.js.map +1 -0
  21. package/dist/{chunk-QZZJFYUQ.js → chunk-FRWKCE6R.js} +3 -3
  22. package/dist/chunk-FRWKCE6R.js.map +1 -0
  23. package/dist/{chunk-5UWKOOIS.js → chunk-HEBPKK5L.js} +129 -195
  24. package/dist/chunk-HEBPKK5L.js.map +1 -0
  25. package/dist/{chunk-MJ2KHG24.js → chunk-IO4VEW5U.js} +6 -6
  26. package/dist/{chunk-MJ2KHG24.js.map → chunk-IO4VEW5U.js.map} +1 -1
  27. package/dist/{chunk-TUPYW2IQ.js → chunk-JC7DBPRD.js} +9 -12
  28. package/dist/chunk-JC7DBPRD.js.map +1 -0
  29. package/dist/{chunk-5GUOIJSG.js → chunk-JFAUQDZM.js} +3 -15
  30. package/dist/chunk-JFAUQDZM.js.map +1 -0
  31. package/dist/{chunk-ZL7PFNHN.js → chunk-K3O3YQYG.js} +2 -2
  32. package/dist/{chunk-SKQWRUPX.js → chunk-K7PJDWER.js} +59 -33
  33. package/dist/chunk-K7PJDWER.js.map +1 -0
  34. package/dist/{chunk-MVR3SYMN.js → chunk-KET3EVGX.js} +4 -3
  35. package/dist/{chunk-MVR3SYMN.js.map → chunk-KET3EVGX.js.map} +1 -1
  36. package/dist/{chunk-MWG4VU64.js → chunk-M5HSTNYU.js} +50 -56
  37. package/dist/chunk-M5HSTNYU.js.map +1 -0
  38. package/dist/{chunk-TJJPWUMA.js → chunk-NSJ2S7R5.js} +3 -2
  39. package/dist/{chunk-TJJPWUMA.js.map → chunk-NSJ2S7R5.js.map} +1 -1
  40. package/dist/{chunk-IHUY4M22.js → chunk-NXGMM5YN.js} +4 -4
  41. package/dist/chunk-NXQAY5U7.js +18441 -0
  42. package/dist/chunk-NXQAY5U7.js.map +1 -0
  43. package/dist/{chunk-Q2KG7UV3.js → chunk-OJJLYHM3.js} +2 -1
  44. package/dist/{chunk-Q2KG7UV3.js.map → chunk-OJJLYHM3.js.map} +1 -1
  45. package/dist/{chunk-PZIZNMHK.js → chunk-ORJ5Y222.js} +159 -138
  46. package/dist/chunk-ORJ5Y222.js.map +1 -0
  47. package/dist/{chunk-NR3OZGL4.js → chunk-OZXAJNLA.js} +2 -1
  48. package/dist/{chunk-NR3OZGL4.js.map → chunk-OZXAJNLA.js.map} +1 -1
  49. package/dist/{chunk-MM7CTTAV.js → chunk-Q5FLW4JG.js} +2 -2
  50. package/dist/{chunk-MM7CTTAV.js.map → chunk-Q5FLW4JG.js.map} +1 -1
  51. package/dist/{chunk-GRVKW3CC.js → chunk-R4SEU3DF.js} +3 -2
  52. package/dist/{chunk-GRVKW3CC.js.map → chunk-R4SEU3DF.js.map} +1 -1
  53. package/dist/{chunk-76ADG7LQ.js → chunk-R54KIGN2.js} +8 -22
  54. package/dist/chunk-R54KIGN2.js.map +1 -0
  55. package/dist/{chunk-SBHBBZKF.js → chunk-REKOWTIB.js} +25 -120
  56. package/dist/chunk-REKOWTIB.js.map +1 -0
  57. package/dist/chunk-TY6CAOL7.js +40 -0
  58. package/dist/chunk-TY6CAOL7.js.map +1 -0
  59. package/dist/{chunk-BNSRA6HL.js → chunk-U2DNAHFE.js} +39 -176
  60. package/dist/chunk-U2DNAHFE.js.map +1 -0
  61. package/dist/{chunk-PMM2MYMA.js → chunk-U2YSGBHA.js} +624 -349
  62. package/dist/chunk-U2YSGBHA.js.map +1 -0
  63. package/dist/{chunk-DTSG5XZB.js → chunk-V3ENMW7G.js} +3 -3
  64. package/dist/{chunk-L7SZXUBJ.js → chunk-VECFAKM5.js} +7 -6
  65. package/dist/{chunk-L7SZXUBJ.js.map → chunk-VECFAKM5.js.map} +1 -1
  66. package/dist/chunk-VGEBYCQZ.js +59 -0
  67. package/dist/chunk-VGEBYCQZ.js.map +1 -0
  68. package/dist/chunk-VZRO7RYT.js +3694 -0
  69. package/dist/chunk-VZRO7RYT.js.map +1 -0
  70. package/dist/{chunk-LASI35KT.js → chunk-WDAO3RUY.js} +14 -28
  71. package/dist/chunk-WDAO3RUY.js.map +1 -0
  72. package/dist/{chunk-MQ7FLIYS.js → chunk-WG6V6VJV.js} +3 -2
  73. package/dist/{chunk-MQ7FLIYS.js.map → chunk-WG6V6VJV.js.map} +1 -1
  74. package/dist/chunk-X5XJ6WKO.js +284 -0
  75. package/dist/chunk-X5XJ6WKO.js.map +1 -0
  76. package/dist/{chunk-RNJWAKMO.js → chunk-XGMOXMS4.js} +9 -8
  77. package/dist/chunk-XGMOXMS4.js.map +1 -0
  78. package/dist/{chunk-IUQBOCSU.js → chunk-ZBPEFQ4G.js} +2 -1
  79. package/dist/{chunk-IUQBOCSU.js.map → chunk-ZBPEFQ4G.js.map} +1 -1
  80. package/dist/{chunk-QRDTLVXG.js → chunk-ZNDLUWWD.js} +9 -22
  81. package/dist/chunk-ZNDLUWWD.js.map +1 -0
  82. package/dist/commands/build/marketplace.js +114 -35
  83. package/dist/commands/build/marketplace.js.map +1 -1
  84. package/dist/commands/build/plugins.js +9 -10
  85. package/dist/commands/build/plugins.js.map +1 -1
  86. package/dist/commands/compile.js +97 -70
  87. package/dist/commands/compile.js.map +1 -1
  88. package/dist/commands/doctor.js +793 -64
  89. package/dist/commands/doctor.js.map +1 -1
  90. package/dist/commands/edit.js +169 -208
  91. package/dist/commands/edit.js.map +1 -1
  92. package/dist/commands/eject.js +24 -39
  93. package/dist/commands/eject.js.map +1 -1
  94. package/dist/commands/init.js +41 -46
  95. package/dist/commands/list.js +10 -12
  96. package/dist/commands/list.js.map +1 -1
  97. package/dist/commands/search.js +20 -81
  98. package/dist/commands/search.js.map +1 -1
  99. package/dist/commands/uninstall.js +25 -31
  100. package/dist/commands/uninstall.js.map +1 -1
  101. package/dist/commands/update.js +82 -332
  102. package/dist/commands/update.js.map +1 -1
  103. package/dist/components/common/confirm.js +1 -1
  104. package/dist/components/common/prompt-confirm.js +1 -1
  105. package/dist/components/common/select-list.js +2 -2
  106. package/dist/components/common/spinner.js +1 -1
  107. package/dist/components/wizard/category-grid.js +5 -6
  108. package/dist/components/wizard/checkbox-grid.js +5 -6
  109. package/dist/components/wizard/domain-selection.js +12 -13
  110. package/dist/components/wizard/run-wizard-session.js +30 -36
  111. package/dist/components/wizard/scroll-affordance.js +2 -2
  112. package/dist/components/wizard/skill-agent-summary.js +7 -7
  113. package/dist/components/wizard/source-grid.js +6 -11
  114. package/dist/components/wizard/stack-selection.js +9 -9
  115. package/dist/components/wizard/step-agents.js +12 -12
  116. package/dist/components/wizard/step-build.js +10 -11
  117. package/dist/components/wizard/step-confirm.js +11 -11
  118. package/dist/components/wizard/step-sources.js +11 -17
  119. package/dist/components/wizard/step-stack.js +10 -10
  120. package/dist/components/wizard/summary-panel.js +10 -10
  121. package/dist/components/wizard/toast.js +2 -2
  122. package/dist/components/wizard/wizard-layout.js +15 -16
  123. package/dist/components/wizard/wizard-tabs.js +6 -12
  124. package/dist/components/wizard/wizard.js +29 -35
  125. package/dist/config-exports.js +1 -1
  126. package/dist/copy-local-skills-KF2RAVD3.js +14 -0
  127. package/dist/hooks/init.js +49 -48
  128. package/dist/hooks/init.js.map +1 -1
  129. package/dist/index.js +3 -1
  130. package/dist/index.js.map +1 -1
  131. package/dist/load-agent-defs-DGXGBU3Q.js +15 -0
  132. package/dist/{loader-5JP4S7CJ.js → loader-4U7UCE2Y.js} +7 -5
  133. package/dist/recompile-project-agents-CJVBAWDJ.js +20 -0
  134. package/dist/{source-loader-MZYCPL2S.js → source-loader-ZNSYJJCI.js} +6 -6
  135. package/dist/src/agents/developer/ai-developer/identity.md +4 -4
  136. package/dist/src/agents/developer/ai-developer/playbook.md +1 -1
  137. package/dist/src/agents/developer/api-developer/identity.md +4 -4
  138. package/dist/src/agents/developer/api-developer/metadata.yaml +1 -1
  139. package/dist/src/agents/developer/cli-developer/identity.md +4 -4
  140. package/dist/src/agents/developer/web-developer/identity.md +2 -2
  141. package/dist/src/agents/developer/web-developer/metadata.yaml +1 -1
  142. package/dist/src/agents/meta/agent-summoner/identity.md +4 -5
  143. package/dist/src/agents/meta/agent-summoner/output.md +2 -2
  144. package/dist/src/agents/meta/agent-summoner/playbook.md +15 -16
  145. package/dist/src/agents/meta/codex-keeper/identity.md +4 -4
  146. package/dist/src/agents/meta/codex-keeper/playbook.md +1 -1
  147. package/dist/src/agents/meta/convention-keeper/identity.md +1 -1
  148. package/dist/src/agents/meta/skill-summoner/critical-reminders.md +0 -34
  149. package/dist/src/agents/meta/skill-summoner/critical-requirements.md +27 -3
  150. package/dist/src/agents/meta/skill-summoner/identity.md +2 -2
  151. package/{src/agents/planning/web-pm → dist/src/agents/planning/pm}/critical-reminders.md +10 -7
  152. package/dist/src/agents/planning/{web-pm → pm}/critical-requirements.md +8 -4
  153. package/dist/src/agents/planning/pm/identity.md +47 -0
  154. package/dist/src/agents/planning/pm/metadata.yaml +12 -0
  155. package/dist/src/agents/planning/{web-pm → pm}/output.md +7 -90
  156. package/dist/src/agents/planning/pm/playbook.md +185 -0
  157. package/dist/src/agents/researcher/ai-researcher/critical-reminders.md +58 -0
  158. package/dist/src/agents/researcher/ai-researcher/critical-requirements.md +40 -0
  159. package/dist/src/agents/researcher/ai-researcher/identity.md +86 -0
  160. package/dist/src/agents/researcher/ai-researcher/metadata.yaml +10 -0
  161. package/dist/src/agents/researcher/ai-researcher/output.md +363 -0
  162. package/dist/src/agents/researcher/ai-researcher/playbook.md +545 -0
  163. package/dist/src/agents/researcher/api-researcher/critical-reminders.md +16 -0
  164. package/dist/src/agents/researcher/api-researcher/identity.md +7 -7
  165. package/dist/src/agents/researcher/cli-researcher/critical-reminders.md +50 -0
  166. package/dist/src/agents/researcher/cli-researcher/critical-requirements.md +36 -0
  167. package/dist/src/agents/researcher/cli-researcher/identity.md +87 -0
  168. package/dist/src/agents/researcher/cli-researcher/metadata.yaml +10 -0
  169. package/dist/src/agents/researcher/cli-researcher/output.md +343 -0
  170. package/dist/src/agents/researcher/cli-researcher/playbook.md +370 -0
  171. package/dist/src/agents/researcher/web-researcher/identity.md +5 -6
  172. package/dist/src/agents/reviewer/reviewer/critical-reminders.md +29 -0
  173. package/dist/src/agents/reviewer/reviewer/critical-requirements.md +31 -0
  174. package/dist/src/agents/reviewer/reviewer/identity.md +41 -0
  175. package/dist/src/agents/reviewer/reviewer/metadata.yaml +12 -0
  176. package/dist/src/agents/reviewer/reviewer/output.md +202 -0
  177. package/dist/src/agents/reviewer/reviewer/playbook.md +141 -0
  178. package/dist/src/agents/tester/ai-tester/critical-reminders.md +48 -0
  179. package/dist/src/agents/tester/ai-tester/critical-requirements.md +49 -0
  180. package/dist/src/agents/tester/ai-tester/identity.md +62 -0
  181. package/dist/src/agents/tester/ai-tester/metadata.yaml +12 -0
  182. package/dist/src/agents/tester/ai-tester/output.md +375 -0
  183. package/dist/src/agents/tester/ai-tester/playbook.md +789 -0
  184. package/dist/src/agents/tester/api-tester/identity.md +3 -3
  185. package/dist/src/agents/tester/cli-tester/critical-reminders.md +3 -3
  186. package/dist/src/agents/tester/cli-tester/critical-requirements.md +2 -2
  187. package/dist/src/agents/tester/cli-tester/identity.md +3 -3
  188. package/dist/src/agents/tester/cli-tester/output.md +4 -4
  189. package/dist/src/agents/tester/cli-tester/playbook.md +3 -3
  190. package/dist/src/agents/tester/web-tester/identity.md +3 -3
  191. package/dist/stores/wizard-store.js +8 -6
  192. package/package.json +13 -2
  193. package/src/agents/developer/ai-developer/identity.md +4 -4
  194. package/src/agents/developer/ai-developer/playbook.md +1 -1
  195. package/src/agents/developer/api-developer/identity.md +4 -4
  196. package/src/agents/developer/api-developer/metadata.yaml +1 -1
  197. package/src/agents/developer/cli-developer/identity.md +4 -4
  198. package/src/agents/developer/web-developer/identity.md +2 -2
  199. package/src/agents/developer/web-developer/metadata.yaml +1 -1
  200. package/src/agents/meta/agent-summoner/identity.md +4 -5
  201. package/src/agents/meta/agent-summoner/output.md +2 -2
  202. package/src/agents/meta/agent-summoner/playbook.md +15 -16
  203. package/src/agents/meta/codex-keeper/identity.md +4 -4
  204. package/src/agents/meta/codex-keeper/playbook.md +1 -1
  205. package/src/agents/meta/convention-keeper/identity.md +1 -1
  206. package/src/agents/meta/skill-summoner/critical-reminders.md +0 -34
  207. package/src/agents/meta/skill-summoner/critical-requirements.md +27 -3
  208. package/src/agents/meta/skill-summoner/identity.md +2 -2
  209. package/{dist/src/agents/planning/web-pm → src/agents/planning/pm}/critical-reminders.md +10 -7
  210. package/src/agents/planning/{web-pm → pm}/critical-requirements.md +8 -4
  211. package/src/agents/planning/pm/identity.md +47 -0
  212. package/src/agents/planning/pm/metadata.yaml +12 -0
  213. package/src/agents/planning/{web-pm → pm}/output.md +7 -90
  214. package/src/agents/planning/pm/playbook.md +185 -0
  215. package/src/agents/researcher/ai-researcher/critical-reminders.md +58 -0
  216. package/src/agents/researcher/ai-researcher/critical-requirements.md +40 -0
  217. package/src/agents/researcher/ai-researcher/identity.md +86 -0
  218. package/src/agents/researcher/ai-researcher/metadata.yaml +10 -0
  219. package/src/agents/researcher/ai-researcher/output.md +363 -0
  220. package/src/agents/researcher/ai-researcher/playbook.md +545 -0
  221. package/src/agents/researcher/api-researcher/critical-reminders.md +16 -0
  222. package/src/agents/researcher/api-researcher/identity.md +7 -7
  223. package/src/agents/researcher/cli-researcher/critical-reminders.md +50 -0
  224. package/src/agents/researcher/cli-researcher/critical-requirements.md +36 -0
  225. package/src/agents/researcher/cli-researcher/identity.md +87 -0
  226. package/src/agents/researcher/cli-researcher/metadata.yaml +10 -0
  227. package/src/agents/researcher/cli-researcher/output.md +343 -0
  228. package/src/agents/researcher/cli-researcher/playbook.md +370 -0
  229. package/src/agents/researcher/web-researcher/identity.md +5 -6
  230. package/src/agents/reviewer/reviewer/critical-reminders.md +29 -0
  231. package/src/agents/reviewer/reviewer/critical-requirements.md +31 -0
  232. package/src/agents/reviewer/reviewer/identity.md +41 -0
  233. package/src/agents/reviewer/reviewer/metadata.yaml +12 -0
  234. package/src/agents/reviewer/reviewer/output.md +202 -0
  235. package/src/agents/reviewer/reviewer/playbook.md +141 -0
  236. package/src/agents/tester/ai-tester/critical-reminders.md +48 -0
  237. package/src/agents/tester/ai-tester/critical-requirements.md +49 -0
  238. package/src/agents/tester/ai-tester/identity.md +62 -0
  239. package/src/agents/tester/ai-tester/metadata.yaml +12 -0
  240. package/src/agents/tester/ai-tester/output.md +375 -0
  241. package/src/agents/tester/ai-tester/playbook.md +789 -0
  242. package/src/agents/tester/api-tester/identity.md +3 -3
  243. package/src/agents/tester/cli-tester/critical-reminders.md +3 -3
  244. package/src/agents/tester/cli-tester/critical-requirements.md +2 -2
  245. package/src/agents/tester/cli-tester/identity.md +3 -3
  246. package/src/agents/tester/cli-tester/output.md +4 -4
  247. package/src/agents/tester/cli-tester/playbook.md +3 -3
  248. package/src/agents/tester/web-tester/identity.md +3 -3
  249. package/src/schemas/metadata.schema.json +31 -2
  250. package/src/schemas/project-config.schema.json +61 -15
  251. package/src/schemas/project-source-config.schema.json +0 -47
  252. package/dist/chunk-5GUOIJSG.js.map +0 -1
  253. package/dist/chunk-5UWKOOIS.js.map +0 -1
  254. package/dist/chunk-76ADG7LQ.js.map +0 -1
  255. package/dist/chunk-BNSRA6HL.js.map +0 -1
  256. package/dist/chunk-E5X6RJ4E.js.map +0 -1
  257. package/dist/chunk-EEPELKOM.js +0 -5938
  258. package/dist/chunk-EEPELKOM.js.map +0 -1
  259. package/dist/chunk-F7T5AFFN.js +0 -20
  260. package/dist/chunk-F7T5AFFN.js.map +0 -1
  261. package/dist/chunk-FVDKAVOL.js.map +0 -1
  262. package/dist/chunk-KFB5CRXZ.js +0 -377
  263. package/dist/chunk-KFB5CRXZ.js.map +0 -1
  264. package/dist/chunk-KR65TPKC.js +0 -664
  265. package/dist/chunk-KR65TPKC.js.map +0 -1
  266. package/dist/chunk-LASI35KT.js.map +0 -1
  267. package/dist/chunk-LDP5ASDM.js.map +0 -1
  268. package/dist/chunk-LZ52XEPR.js.map +0 -1
  269. package/dist/chunk-M7HO7NBK.js +0 -88
  270. package/dist/chunk-M7HO7NBK.js.map +0 -1
  271. package/dist/chunk-MWG4VU64.js.map +0 -1
  272. package/dist/chunk-ODNDXQH2.js +0 -77
  273. package/dist/chunk-ODNDXQH2.js.map +0 -1
  274. package/dist/chunk-P44SXVH3.js +0 -80
  275. package/dist/chunk-P44SXVH3.js.map +0 -1
  276. package/dist/chunk-PMM2MYMA.js.map +0 -1
  277. package/dist/chunk-PZIZNMHK.js.map +0 -1
  278. package/dist/chunk-Q45ZU6HD.js +0 -37
  279. package/dist/chunk-Q45ZU6HD.js.map +0 -1
  280. package/dist/chunk-QRDTLVXG.js.map +0 -1
  281. package/dist/chunk-QZZJFYUQ.js.map +0 -1
  282. package/dist/chunk-R5NOI2LP.js +0 -170
  283. package/dist/chunk-R5NOI2LP.js.map +0 -1
  284. package/dist/chunk-RNJWAKMO.js.map +0 -1
  285. package/dist/chunk-SBHBBZKF.js.map +0 -1
  286. package/dist/chunk-SKQWRUPX.js.map +0 -1
  287. package/dist/chunk-STMHDOZD.js.map +0 -1
  288. package/dist/chunk-SX5H6TSC.js.map +0 -1
  289. package/dist/chunk-TUPYW2IQ.js.map +0 -1
  290. package/dist/chunk-UBEDZ4FD.js +0 -4198
  291. package/dist/chunk-UBEDZ4FD.js.map +0 -1
  292. package/dist/chunk-VY6MNOXL.js +0 -20
  293. package/dist/chunk-VY6MNOXL.js.map +0 -1
  294. package/dist/chunk-WBCPLH66.js +0 -42
  295. package/dist/chunk-WBCPLH66.js.map +0 -1
  296. package/dist/chunk-WKTHWQKM.js.map +0 -1
  297. package/dist/chunk-XHUODHZ4.js.map +0 -1
  298. package/dist/chunk-ZPPHXXAP.js +0 -252
  299. package/dist/chunk-ZPPHXXAP.js.map +0 -1
  300. package/dist/commands/import/skill.js +0 -344
  301. package/dist/commands/import/skill.js.map +0 -1
  302. package/dist/commands/new/agent.js +0 -300
  303. package/dist/commands/new/agent.js.map +0 -1
  304. package/dist/commands/new/marketplace.js +0 -310
  305. package/dist/commands/new/marketplace.js.map +0 -1
  306. package/dist/commands/new/skill.js +0 -26
  307. package/dist/commands/validate.js +0 -575
  308. package/dist/commands/validate.js.map +0 -1
  309. package/dist/components/wizard/search-modal.js +0 -13
  310. package/dist/components/wizard/selection-card.js +0 -9
  311. package/dist/components/wizard/step-settings.js +0 -18
  312. package/dist/copy-local-skills-6EMVN7RB.js +0 -14
  313. package/dist/load-agent-defs-BWOUVEAR.js +0 -15
  314. package/dist/load-agent-defs-BWOUVEAR.js.map +0 -1
  315. package/dist/loader-5JP4S7CJ.js.map +0 -1
  316. package/dist/recompile-project-agents-6DL45TDI.js +0 -19
  317. package/dist/recompile-project-agents-6DL45TDI.js.map +0 -1
  318. package/dist/source-loader-MZYCPL2S.js.map +0 -1
  319. package/dist/src/agents/developer/web-architecture/critical-reminders.md +0 -48
  320. package/dist/src/agents/developer/web-architecture/critical-requirements.md +0 -65
  321. package/dist/src/agents/developer/web-architecture/identity.md +0 -64
  322. package/dist/src/agents/developer/web-architecture/metadata.yaml +0 -12
  323. package/dist/src/agents/developer/web-architecture/output.md +0 -449
  324. package/dist/src/agents/developer/web-architecture/playbook.md +0 -481
  325. package/dist/src/agents/pattern/pattern-scout/critical-reminders.md +0 -71
  326. package/dist/src/agents/pattern/pattern-scout/critical-requirements.md +0 -31
  327. package/dist/src/agents/pattern/pattern-scout/identity.md +0 -25
  328. package/dist/src/agents/pattern/pattern-scout/metadata.yaml +0 -10
  329. package/dist/src/agents/pattern/pattern-scout/output.md +0 -290
  330. package/dist/src/agents/pattern/pattern-scout/playbook.md +0 -1806
  331. package/dist/src/agents/pattern/web-pattern-critique/critical-reminders.md +0 -30
  332. package/dist/src/agents/pattern/web-pattern-critique/critical-requirements.md +0 -28
  333. package/dist/src/agents/pattern/web-pattern-critique/identity.md +0 -41
  334. package/dist/src/agents/pattern/web-pattern-critique/metadata.yaml +0 -12
  335. package/dist/src/agents/pattern/web-pattern-critique/output.md +0 -314
  336. package/dist/src/agents/pattern/web-pattern-critique/playbook.md +0 -572
  337. package/dist/src/agents/planning/api-pm/critical-reminders.md +0 -48
  338. package/dist/src/agents/planning/api-pm/critical-requirements.md +0 -41
  339. package/dist/src/agents/planning/api-pm/identity.md +0 -39
  340. package/dist/src/agents/planning/api-pm/metadata.yaml +0 -12
  341. package/dist/src/agents/planning/api-pm/output.md +0 -475
  342. package/dist/src/agents/planning/api-pm/playbook.md +0 -129
  343. package/dist/src/agents/planning/web-pm/identity.md +0 -26
  344. package/dist/src/agents/planning/web-pm/metadata.yaml +0 -12
  345. package/dist/src/agents/planning/web-pm/playbook.md +0 -318
  346. package/dist/src/agents/reviewer/ai-reviewer/critical-reminders.md +0 -40
  347. package/dist/src/agents/reviewer/ai-reviewer/critical-requirements.md +0 -37
  348. package/dist/src/agents/reviewer/ai-reviewer/identity.md +0 -51
  349. package/dist/src/agents/reviewer/ai-reviewer/metadata.yaml +0 -10
  350. package/dist/src/agents/reviewer/ai-reviewer/output.md +0 -395
  351. package/dist/src/agents/reviewer/ai-reviewer/playbook.md +0 -90
  352. package/dist/src/agents/reviewer/api-reviewer/critical-reminders.md +0 -31
  353. package/dist/src/agents/reviewer/api-reviewer/critical-requirements.md +0 -27
  354. package/dist/src/agents/reviewer/api-reviewer/identity.md +0 -51
  355. package/dist/src/agents/reviewer/api-reviewer/metadata.yaml +0 -12
  356. package/dist/src/agents/reviewer/api-reviewer/output.md +0 -343
  357. package/dist/src/agents/reviewer/api-reviewer/playbook.md +0 -288
  358. package/dist/src/agents/reviewer/cli-reviewer/critical-reminders.md +0 -33
  359. package/dist/src/agents/reviewer/cli-reviewer/critical-requirements.md +0 -30
  360. package/dist/src/agents/reviewer/cli-reviewer/identity.md +0 -44
  361. package/dist/src/agents/reviewer/cli-reviewer/metadata.yaml +0 -12
  362. package/dist/src/agents/reviewer/cli-reviewer/output.md +0 -414
  363. package/dist/src/agents/reviewer/cli-reviewer/playbook.md +0 -218
  364. package/dist/src/agents/reviewer/infra-reviewer/critical-reminders.md +0 -38
  365. package/dist/src/agents/reviewer/infra-reviewer/critical-requirements.md +0 -38
  366. package/dist/src/agents/reviewer/infra-reviewer/identity.md +0 -53
  367. package/dist/src/agents/reviewer/infra-reviewer/metadata.yaml +0 -10
  368. package/dist/src/agents/reviewer/infra-reviewer/output.md +0 -364
  369. package/dist/src/agents/reviewer/infra-reviewer/playbook.md +0 -161
  370. package/dist/src/agents/reviewer/web-reviewer/critical-reminders.md +0 -31
  371. package/dist/src/agents/reviewer/web-reviewer/critical-requirements.md +0 -26
  372. package/dist/src/agents/reviewer/web-reviewer/identity.md +0 -40
  373. package/dist/src/agents/reviewer/web-reviewer/metadata.yaml +0 -12
  374. package/dist/src/agents/reviewer/web-reviewer/output.md +0 -333
  375. package/dist/src/agents/reviewer/web-reviewer/playbook.md +0 -156
  376. package/src/agents/developer/web-architecture/critical-reminders.md +0 -48
  377. package/src/agents/developer/web-architecture/critical-requirements.md +0 -65
  378. package/src/agents/developer/web-architecture/identity.md +0 -64
  379. package/src/agents/developer/web-architecture/metadata.yaml +0 -12
  380. package/src/agents/developer/web-architecture/output.md +0 -449
  381. package/src/agents/developer/web-architecture/playbook.md +0 -481
  382. package/src/agents/pattern/pattern-scout/critical-reminders.md +0 -71
  383. package/src/agents/pattern/pattern-scout/critical-requirements.md +0 -31
  384. package/src/agents/pattern/pattern-scout/identity.md +0 -25
  385. package/src/agents/pattern/pattern-scout/metadata.yaml +0 -10
  386. package/src/agents/pattern/pattern-scout/output.md +0 -290
  387. package/src/agents/pattern/pattern-scout/playbook.md +0 -1806
  388. package/src/agents/pattern/web-pattern-critique/critical-reminders.md +0 -30
  389. package/src/agents/pattern/web-pattern-critique/critical-requirements.md +0 -28
  390. package/src/agents/pattern/web-pattern-critique/identity.md +0 -41
  391. package/src/agents/pattern/web-pattern-critique/metadata.yaml +0 -12
  392. package/src/agents/pattern/web-pattern-critique/output.md +0 -314
  393. package/src/agents/pattern/web-pattern-critique/playbook.md +0 -572
  394. package/src/agents/planning/api-pm/critical-reminders.md +0 -48
  395. package/src/agents/planning/api-pm/critical-requirements.md +0 -41
  396. package/src/agents/planning/api-pm/identity.md +0 -39
  397. package/src/agents/planning/api-pm/metadata.yaml +0 -12
  398. package/src/agents/planning/api-pm/output.md +0 -475
  399. package/src/agents/planning/api-pm/playbook.md +0 -129
  400. package/src/agents/planning/web-pm/identity.md +0 -26
  401. package/src/agents/planning/web-pm/metadata.yaml +0 -12
  402. package/src/agents/planning/web-pm/playbook.md +0 -318
  403. package/src/agents/reviewer/ai-reviewer/critical-reminders.md +0 -40
  404. package/src/agents/reviewer/ai-reviewer/critical-requirements.md +0 -37
  405. package/src/agents/reviewer/ai-reviewer/identity.md +0 -51
  406. package/src/agents/reviewer/ai-reviewer/metadata.yaml +0 -10
  407. package/src/agents/reviewer/ai-reviewer/output.md +0 -395
  408. package/src/agents/reviewer/ai-reviewer/playbook.md +0 -90
  409. package/src/agents/reviewer/api-reviewer/critical-reminders.md +0 -31
  410. package/src/agents/reviewer/api-reviewer/critical-requirements.md +0 -27
  411. package/src/agents/reviewer/api-reviewer/identity.md +0 -51
  412. package/src/agents/reviewer/api-reviewer/metadata.yaml +0 -12
  413. package/src/agents/reviewer/api-reviewer/output.md +0 -343
  414. package/src/agents/reviewer/api-reviewer/playbook.md +0 -288
  415. package/src/agents/reviewer/cli-reviewer/critical-reminders.md +0 -33
  416. package/src/agents/reviewer/cli-reviewer/critical-requirements.md +0 -30
  417. package/src/agents/reviewer/cli-reviewer/identity.md +0 -44
  418. package/src/agents/reviewer/cli-reviewer/metadata.yaml +0 -12
  419. package/src/agents/reviewer/cli-reviewer/output.md +0 -414
  420. package/src/agents/reviewer/cli-reviewer/playbook.md +0 -218
  421. package/src/agents/reviewer/infra-reviewer/critical-reminders.md +0 -38
  422. package/src/agents/reviewer/infra-reviewer/critical-requirements.md +0 -38
  423. package/src/agents/reviewer/infra-reviewer/identity.md +0 -53
  424. package/src/agents/reviewer/infra-reviewer/metadata.yaml +0 -10
  425. package/src/agents/reviewer/infra-reviewer/output.md +0 -364
  426. package/src/agents/reviewer/infra-reviewer/playbook.md +0 -161
  427. package/src/agents/reviewer/web-reviewer/critical-reminders.md +0 -31
  428. package/src/agents/reviewer/web-reviewer/critical-requirements.md +0 -26
  429. package/src/agents/reviewer/web-reviewer/identity.md +0 -40
  430. package/src/agents/reviewer/web-reviewer/metadata.yaml +0 -12
  431. package/src/agents/reviewer/web-reviewer/output.md +0 -333
  432. package/src/agents/reviewer/web-reviewer/playbook.md +0 -156
  433. /package/dist/{chunk-ZL7PFNHN.js.map → chunk-K3O3YQYG.js.map} +0 -0
  434. /package/dist/{chunk-IHUY4M22.js.map → chunk-NXGMM5YN.js.map} +0 -0
  435. /package/dist/{chunk-DTSG5XZB.js.map → chunk-V3ENMW7G.js.map} +0 -0
  436. /package/dist/{commands/new/skill.js.map → copy-local-skills-KF2RAVD3.js.map} +0 -0
  437. /package/dist/{components/wizard/search-modal.js.map → load-agent-defs-DGXGBU3Q.js.map} +0 -0
  438. /package/dist/{components/wizard/selection-card.js.map → loader-4U7UCE2Y.js.map} +0 -0
  439. /package/dist/{components/wizard/step-settings.js.map → recompile-project-agents-CJVBAWDJ.js.map} +0 -0
  440. /package/dist/{copy-local-skills-6EMVN7RB.js.map → source-loader-ZNSYJJCI.js.map} +0 -0
@@ -2,58 +2,591 @@
2
2
  import {
3
3
  detectProject,
4
4
  loadSource
5
- } from "../chunk-STMHDOZD.js";
6
- import "../chunk-SBHBBZKF.js";
7
- import "../chunk-IHUY4M22.js";
8
- import "../chunk-QZZJFYUQ.js";
5
+ } from "../chunk-F7Z5I6GU.js";
6
+ import "../chunk-REKOWTIB.js";
7
+ import "../chunk-NXGMM5YN.js";
8
+ import "../chunk-FRWKCE6R.js";
9
9
  import {
10
10
  filterExcludedEntries,
11
11
  listAgentMdFiles
12
- } from "../chunk-E5X6RJ4E.js";
12
+ } from "../chunk-FIHTAFST.js";
13
13
  import {
14
14
  BaseCommand,
15
15
  EXIT_CODES
16
- } from "../chunk-KR65TPKC.js";
17
- import "../chunk-ZL7PFNHN.js";
16
+ } from "../chunk-X5XJ6WKO.js";
17
+ import "../chunk-TY6CAOL7.js";
18
+ import "../chunk-K3O3YQYG.js";
18
19
  import {
20
+ checkMatrixHealth,
21
+ configDirsInPlay,
22
+ declaresNoContent,
19
23
  discoverLocalSkills,
20
24
  effectivelyExcludedSkillIds,
25
+ findConfigLoadFailures,
26
+ getInstalledPluginsRegistryPath,
27
+ getProjectConfigPath,
28
+ getProjectPluginsDir,
21
29
  getStackSkillIds,
30
+ getUserPluginsDir,
22
31
  getVerifiedPluginInstallPaths,
23
32
  installBaseDir,
24
33
  isHomeDirectory,
34
+ isLocalSource,
35
+ isRecord,
36
+ listRegisteredPluginInstalls,
37
+ loadConfig,
38
+ loadProjectConfigFromDir,
39
+ loadProjectSourceConfig,
40
+ loadSkillsMatrixFromSource,
25
41
  parseMarketplacePluginRef,
26
42
  resolveInstallPaths,
27
- validateProjectConfig
28
- } from "../chunk-EEPELKOM.js";
43
+ resolvePrimarySourceEntry,
44
+ validateAgentFrontmatter,
45
+ validateAllPlugins,
46
+ validatePlugin,
47
+ validateProjectConfig,
48
+ validateSkillFrontmatter
49
+ } from "../chunk-NXQAY5U7.js";
29
50
  import {
51
+ agentYamlGenerationSchema,
30
52
  directoryExists,
31
53
  fileExists,
54
+ formatZodErrors,
32
55
  getErrorMessage,
33
- setVerbose
34
- } from "../chunk-PMM2MYMA.js";
56
+ glob,
57
+ listDirectories,
58
+ metadataValidationSchema,
59
+ parseFrontmatter,
60
+ readFile,
61
+ readSkillMetadata,
62
+ setVerbose,
63
+ skillCategoriesFileSchema,
64
+ skillRulesFileSchema,
65
+ splitMetadataValidationIssues,
66
+ stackConfigValidationSchema,
67
+ stacksConfigSchema,
68
+ validateSkillMetadata
69
+ } from "../chunk-U2YSGBHA.js";
35
70
  import {
36
71
  matrix
37
- } from "../chunk-WKTHWQKM.js";
72
+ } from "../chunk-35VOK7XE.js";
38
73
  import "../chunk-VASLW636.js";
39
74
  import {
40
75
  CLAUDE_SRC_DIR,
41
76
  CLI_INVOKE_COMMAND,
42
77
  DEFAULT_BRANDING,
78
+ DIRS,
43
79
  EJECT_SOURCE,
44
80
  LOCAL_SKILLS_PATH,
81
+ PLUGIN_MANIFEST_DIR,
82
+ SKILLS_DIR_PATH,
83
+ SKILL_CATEGORIES_PATH,
84
+ SKILL_RULES_PATH,
85
+ STACKS_FILE_PATH,
45
86
  STANDARD_FILES,
46
87
  UI_SYMBOLS
47
- } from "../chunk-76ADG7LQ.js";
48
- import "../chunk-UBEDZ4FD.js";
88
+ } from "../chunk-R54KIGN2.js";
89
+ import "../chunk-VZRO7RYT.js";
49
90
 
50
91
  // src/cli/commands/doctor.ts
51
- import os from "os";
92
+ import os2 from "os";
93
+ import path3 from "path";
94
+
95
+ // src/cli/lib/source-validator.ts
52
96
  import path from "path";
97
+ import { parse as parseYaml } from "yaml";
98
+ import "zod";
99
+ async function isSourceRepo(dir) {
100
+ const sourceConfig = await loadProjectSourceConfig(dir);
101
+ return directoryExists(path.join(dir, sourceConfig?.skillsDir ?? SKILLS_DIR_PATH));
102
+ }
103
+ function isSnakeCase(key) {
104
+ return /[a-z]_[a-z]/.test(key);
105
+ }
106
+ function checkSnakeCaseKeys(rawMetadata, relPath) {
107
+ if (!isRecord(rawMetadata)) return [];
108
+ return Object.keys(rawMetadata).filter(isSnakeCase).map((key) => ({
109
+ severity: "error",
110
+ file: relPath,
111
+ message: `Key '${key}' uses snake_case \u2014 use camelCase instead`
112
+ }));
113
+ }
114
+ function checkDirNameMatchesSkillId(skillId, relPath, dirName) {
115
+ if (skillId === dirName) return [];
116
+ return [
117
+ {
118
+ severity: "warning",
119
+ file: relPath,
120
+ message: `Directory name '${dirName}' does not match skill id '${skillId}'`
121
+ }
122
+ ];
123
+ }
124
+ async function checkSkillDirName(skillsDir, skillsDirRelPath, skillDir) {
125
+ const dirName = path.basename(skillDir);
126
+ const skillMdRelPath = path.join(skillsDirRelPath, skillDir, STANDARD_FILES.SKILL_MD);
127
+ try {
128
+ const content = await readFile(path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD));
129
+ const frontmatter = parseFrontmatter(content, skillMdRelPath);
130
+ if (frontmatter === null) {
131
+ return [
132
+ {
133
+ severity: "warning",
134
+ file: skillMdRelPath,
135
+ message: `Cannot verify directory name '${dirName}': missing or invalid ${STANDARD_FILES.SKILL_MD} frontmatter`
136
+ }
137
+ ];
138
+ }
139
+ return checkDirNameMatchesSkillId(frontmatter.name, skillMdRelPath, dirName);
140
+ } catch (error) {
141
+ return [
142
+ {
143
+ severity: "warning",
144
+ file: skillMdRelPath,
145
+ message: `Cannot verify directory name '${dirName}': ${getErrorMessage(error)}`
146
+ }
147
+ ];
148
+ }
149
+ }
150
+ function validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir) {
151
+ const missingMetadata = [...skillMdDirs].filter((dir) => !metadataDirs.has(dir)).map((dir) => ({
152
+ severity: "error",
153
+ file: path.join(skillsDir, dir),
154
+ message: `Missing ${STANDARD_FILES.METADATA_YAML} \u2014 skill directory has ${STANDARD_FILES.SKILL_MD} but no metadata`
155
+ }));
156
+ const missingSkillMd = [...metadataDirs].filter((dir) => !skillMdDirs.has(dir)).map((dir) => ({
157
+ severity: "error",
158
+ file: path.join(skillsDir, dir),
159
+ message: `Missing ${STANDARD_FILES.SKILL_MD} \u2014 skill directory has ${STANDARD_FILES.METADATA_YAML} but no SKILL.md`
160
+ }));
161
+ return [...missingMetadata, ...missingSkillMd];
162
+ }
163
+ async function validateSource(sourcePath) {
164
+ const issues = [];
165
+ const resolvedPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(sourcePath);
166
+ if (!await directoryExists(resolvedPath)) {
167
+ issues.push({
168
+ severity: "error",
169
+ file: resolvedPath,
170
+ message: "Source directory does not exist"
171
+ });
172
+ return buildResult(issues, 0);
173
+ }
174
+ const sourceProjectConfig = await loadProjectSourceConfig(resolvedPath);
175
+ const skillsDirRelPath = sourceProjectConfig?.skillsDir ?? SKILLS_DIR_PATH;
176
+ const skillsDir = path.join(resolvedPath, skillsDirRelPath);
177
+ if (!await directoryExists(skillsDir)) {
178
+ issues.push({
179
+ severity: "error",
180
+ file: skillsDir,
181
+ message: "Skills directory does not exist"
182
+ });
183
+ return buildResult(issues, 0);
184
+ }
185
+ const skillMdFiles = await glob(`**/${STANDARD_FILES.SKILL_MD}`, skillsDir);
186
+ const metadataFiles = await glob(`**/${STANDARD_FILES.METADATA_YAML}`, skillsDir);
187
+ const skillMdDirs = new Set(skillMdFiles.map((f) => path.dirname(f)));
188
+ const metadataDirs = new Set(metadataFiles.map((f) => path.dirname(f)));
189
+ issues.push(...validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir));
190
+ const validMetadataFiles = metadataFiles.filter((f) => skillMdDirs.has(path.dirname(f)));
191
+ for (const metadataFile of validMetadataFiles) {
192
+ issues.push(...await validateOneSkill(skillsDir, skillsDirRelPath, metadataFile));
193
+ }
194
+ issues.push(...await checkCrossReferences(resolvedPath));
195
+ const extraIssues = await Promise.all([
196
+ validateStacks(resolvedPath),
197
+ validateAgents(resolvedPath),
198
+ validateConfigFiles(resolvedPath)
199
+ ]);
200
+ issues.push(...extraIssues.flat());
201
+ return buildResult(issues, validMetadataFiles.length);
202
+ }
203
+ async function validateOneSkill(skillsDir, skillsDirRelPath, metadataFile) {
204
+ const relPath = path.join(skillsDirRelPath, metadataFile);
205
+ let rawMetadata;
206
+ try {
207
+ rawMetadata = parseYaml(await readFile(path.join(skillsDir, metadataFile)));
208
+ } catch (error) {
209
+ return [
210
+ {
211
+ severity: "error",
212
+ file: relPath,
213
+ message: `Failed to parse YAML: ${getErrorMessage(error)}`
214
+ }
215
+ ];
216
+ }
217
+ return [
218
+ ...checkSnakeCaseKeys(rawMetadata, relPath),
219
+ ...checkMetadataSchema(rawMetadata, relPath),
220
+ // Independent of metadata validity — the id lives in SKILL.md frontmatter
221
+ ...await checkSkillDirName(skillsDir, skillsDirRelPath, path.dirname(metadataFile))
222
+ ];
223
+ }
224
+ function checkMetadataSchema(rawMetadata, relPath) {
225
+ const result = validateSkillMetadata(rawMetadata);
226
+ if (result.success) return [];
227
+ const { errors, warnings } = splitMetadataValidationIssues(result.error, rawMetadata);
228
+ return [
229
+ ...errors.map((message) => ({ severity: "error", file: relPath, message })),
230
+ ...warnings.map((message) => ({ severity: "warning", file: relPath, message }))
231
+ ];
232
+ }
233
+ async function checkCrossReferences(resolvedPath) {
234
+ try {
235
+ await loadSkillsMatrixFromSource({ sourceFlag: resolvedPath, skipExtraSources: true });
236
+ return checkMatrixHealth(matrix).map((healthIssue) => ({
237
+ severity: healthIssue.severity,
238
+ file: SKILL_CATEGORIES_PATH,
239
+ message: healthIssue.details
240
+ }));
241
+ } catch (error) {
242
+ return [
243
+ {
244
+ severity: "warning",
245
+ file: SKILL_CATEGORIES_PATH,
246
+ message: `Cross-reference validation skipped: failed to load categories/rules: ${getErrorMessage(error)}`
247
+ }
248
+ ];
249
+ }
250
+ }
251
+ async function validateStacks(resolvedPath) {
252
+ const stacksDir = path.join(resolvedPath, DIRS.stacks);
253
+ if (!await directoryExists(stacksDir)) return [];
254
+ const [skillMetaIssues, configIssues] = await Promise.all([
255
+ validateYamlFiles({
256
+ baseDir: stacksDir,
257
+ relBaseDir: DIRS.stacks,
258
+ pattern: `**/skills/**/${STANDARD_FILES.METADATA_YAML}`,
259
+ schema: metadataValidationSchema
260
+ }),
261
+ validateYamlFiles({
262
+ baseDir: stacksDir,
263
+ relBaseDir: DIRS.stacks,
264
+ pattern: `*/${STANDARD_FILES.CONFIG_YAML}`,
265
+ schema: stackConfigValidationSchema
266
+ })
267
+ ]);
268
+ return [...skillMetaIssues, ...configIssues];
269
+ }
270
+ async function validateAgents(resolvedPath) {
271
+ const agentsDir = path.join(resolvedPath, DIRS.agents);
272
+ if (!await directoryExists(agentsDir)) return [];
273
+ return validateYamlFiles({
274
+ baseDir: agentsDir,
275
+ relBaseDir: DIRS.agents,
276
+ pattern: `**/${STANDARD_FILES.AGENT_METADATA_YAML}`,
277
+ schema: agentYamlGenerationSchema
278
+ });
279
+ }
280
+ async function validateConfigFiles(resolvedPath) {
281
+ const results = await Promise.all([
282
+ validateTsConfig(resolvedPath, SKILL_CATEGORIES_PATH, skillCategoriesFileSchema),
283
+ validateTsConfig(resolvedPath, SKILL_RULES_PATH, skillRulesFileSchema),
284
+ validateTsConfig(resolvedPath, STACKS_FILE_PATH, stacksConfigSchema)
285
+ ]);
286
+ return results.flat();
287
+ }
288
+ async function validateYamlFiles(opts) {
289
+ const issues = [];
290
+ const files = await glob(opts.pattern, opts.baseDir);
291
+ for (const relFile of files) {
292
+ const absPath = path.join(opts.baseDir, relFile);
293
+ const displayPath = path.join(opts.relBaseDir, relFile);
294
+ let parsed;
295
+ try {
296
+ parsed = parseYaml(await readFile(absPath));
297
+ } catch {
298
+ issues.push({ severity: "error", file: displayPath, message: "Failed to parse YAML" });
299
+ continue;
300
+ }
301
+ const result = opts.schema.safeParse(parsed);
302
+ if (result.success) continue;
303
+ issues.push(
304
+ ...formatZodErrors(result.error).map((message) => ({
305
+ severity: "error",
306
+ file: displayPath,
307
+ message
308
+ }))
309
+ );
310
+ }
311
+ return issues;
312
+ }
313
+ async function validateTsConfig(resolvedPath, relConfigPath, schema) {
314
+ const absPath = path.join(resolvedPath, relConfigPath);
315
+ if (!await fileExists(absPath)) return [];
316
+ try {
317
+ const loaded = await loadConfig(absPath, schema);
318
+ if (loaded === null) {
319
+ return [{ severity: "error", file: relConfigPath, message: "Config has no default export" }];
320
+ }
321
+ return [];
322
+ } catch (error) {
323
+ return [
324
+ { severity: "error", file: relConfigPath, message: formatLoadError(relConfigPath, error) }
325
+ ];
326
+ }
327
+ }
328
+ function formatLoadError(relConfigPath, error) {
329
+ const raw = getErrorMessage(error);
330
+ const stripped = raw.replace(/Failed to load config from '[^']+':\s*/, "");
331
+ return `Failed to load ${relConfigPath}: ${stripped}`;
332
+ }
333
+ function buildResult(issues, skillCount) {
334
+ const errorCount = issues.filter((i) => i.severity === "error").length;
335
+ const warningCount = issues.filter((i) => i.severity === "warning").length;
336
+ return { issues, skillCount, errorCount, warningCount };
337
+ }
338
+
339
+ // src/cli/lib/content-validator.ts
340
+ import os from "os";
341
+ import path2 from "path";
342
+ var CWD_SOURCE_NAME = "current directory";
343
+ var NOTHING_VALIDATED = { count: 0, issues: [], notes: [] };
344
+ function mergeValidations(parts) {
345
+ return parts.reduce(
346
+ (acc, part) => ({
347
+ count: acc.count + part.count,
348
+ issues: [...acc.issues, ...part.issues],
349
+ notes: [...acc.notes, ...part.notes]
350
+ }),
351
+ NOTHING_VALIDATED
352
+ );
353
+ }
354
+ function displayDir(absolutePath) {
355
+ const home = os.homedir();
356
+ if (absolutePath === home) return "~";
357
+ if (absolutePath.startsWith(home + path2.sep)) {
358
+ return `~${path2.sep}${path2.relative(home, absolutePath)}`;
359
+ }
360
+ return absolutePath;
361
+ }
362
+ function toIssues(file, result) {
363
+ return [
364
+ ...result.errors.map((message) => ({ severity: "error", file, message })),
365
+ ...result.warnings.map((message) => ({ severity: "warning", file, message }))
366
+ ];
367
+ }
368
+ var CONFIG_UNREADABLE = "exists but could not be loaded";
369
+ async function validateProjectConfigFile(projectDir) {
370
+ const [present, failures] = await Promise.all([
371
+ countExistingConfigs(projectDir),
372
+ findConfigLoadFailures(projectDir)
373
+ ]);
374
+ return { count: present, issues: failures.map(toUnreadableConfigIssue), notes: [] };
375
+ }
376
+ function toUnreadableConfigIssue(failure) {
377
+ return {
378
+ severity: "error",
379
+ file: displayDir(failure.configPath),
380
+ message: `${CONFIG_UNREADABLE}: ${failure.reason}`
381
+ };
382
+ }
383
+ async function countExistingConfigs(projectDir) {
384
+ const present = await Promise.all(
385
+ configDirsInPlay(projectDir).map((dir) => fileExists(getProjectConfigPath(dir)))
386
+ );
387
+ return present.filter(Boolean).length;
388
+ }
389
+ async function validateRegisteredSources(projectDir) {
390
+ const primary = await resolvePrimarySourceEntry(projectDir);
391
+ const registered = [primary];
392
+ const remote = registered.filter((source) => !isLocalSource(source.url));
393
+ const local = await localSourcesToValidate(projectDir, registered);
394
+ const outcomes = await Promise.all(local.map(validateOneSource));
395
+ return {
396
+ count: local.length,
397
+ issues: outcomes.flatMap((outcome) => outcome.issues),
398
+ notes: [
399
+ ...outcomes.map((outcome) => outcome.note),
400
+ ...remote.map((source) => `${source.name} (${source.url}) \u2014 skipped (remote source)`)
401
+ ]
402
+ };
403
+ }
404
+ async function localSourcesToValidate(projectDir, registered) {
405
+ const local = registered.filter((source) => isLocalSource(source.url));
406
+ const alreadyCovered = local.some(
407
+ (source) => path2.resolve(projectDir, source.url) === projectDir
408
+ );
409
+ if (alreadyCovered || !await isSourceRepo(projectDir)) return local;
410
+ return [...local, { name: CWD_SOURCE_NAME, url: projectDir }];
411
+ }
412
+ async function validateOneSource(source) {
413
+ const label = `${source.name} (${source.url})`;
414
+ try {
415
+ const result = await validateSource(source.url);
416
+ return { note: `${label} \u2014 ${result.skillCount} skills`, issues: result.issues };
417
+ } catch (error) {
418
+ return {
419
+ note: `${label} \u2014 failed`,
420
+ issues: [{ severity: "error", file: source.url, message: getErrorMessage(error) }]
421
+ };
422
+ }
423
+ }
424
+ async function validateInstalledPlugins(projectDir) {
425
+ const dirs = [
426
+ getUserPluginsDir(),
427
+ ...isHomeDirectory(projectDir) ? [] : [getProjectPluginsDir(projectDir)]
428
+ ];
429
+ return mergeValidations(await Promise.all(dirs.map(validatePluginsDirectory)));
430
+ }
431
+ async function validatePluginsDirectory(pluginsDir) {
432
+ if (!await directoryExists(pluginsDir)) return NOTHING_VALIDATED;
433
+ if (await fileExists(getInstalledPluginsRegistryPath(pluginsDir))) {
434
+ const registryValidation = await validateRegistryPlugins(pluginsDir);
435
+ if (registryValidation !== void 0) return registryValidation;
436
+ }
437
+ const pluginDirs = await findPluginDirectories(pluginsDir);
438
+ if (pluginDirs.length === 0) return NOTHING_VALIDATED;
439
+ const { results } = await validateAllPlugins(pluginsDir);
440
+ return {
441
+ count: results.length,
442
+ issues: results.flatMap(({ name, result }) => toIssues(name, result)),
443
+ notes: []
444
+ };
445
+ }
446
+ async function validateRegistryPlugins(pluginsDir) {
447
+ let installs;
448
+ try {
449
+ installs = await listRegisteredPluginInstalls(pluginsDir);
450
+ } catch (error) {
451
+ return {
452
+ count: 0,
453
+ issues: [
454
+ {
455
+ severity: "error",
456
+ file: displayDir(getInstalledPluginsRegistryPath(pluginsDir)),
457
+ message: getErrorMessage(error)
458
+ }
459
+ ],
460
+ notes: []
461
+ };
462
+ }
463
+ if (installs.length === 0) return void 0;
464
+ const results = await Promise.all(
465
+ installs.map(
466
+ async ({ pluginKey, installPath }) => toIssues(pluginKey, await validatePlugin(installPath))
467
+ )
468
+ );
469
+ return { count: installs.length, issues: results.flat(), notes: [] };
470
+ }
471
+ async function findPluginDirectories(pluginsDir) {
472
+ const entries = await listDirectories(pluginsDir);
473
+ const checks = await Promise.all(
474
+ entries.map(async (name) => ({
475
+ name,
476
+ isPlugin: await directoryExists(path2.join(pluginsDir, name, PLUGIN_MANIFEST_DIR))
477
+ }))
478
+ );
479
+ return checks.filter((check) => check.isPlugin).map((check) => check.name);
480
+ }
481
+ async function validateInstalledSkills(projectDir) {
482
+ return mergeValidations(
483
+ await Promise.all(installedDirs(projectDir, "skillsDir").map(validateSkillsDirectory))
484
+ );
485
+ }
486
+ async function validateInstalledAgents(projectDir) {
487
+ return mergeValidations(
488
+ await Promise.all(installedDirs(projectDir, "agentsDir").map(validateAgentsDirectory))
489
+ );
490
+ }
491
+ function installedDirs(projectDir, key) {
492
+ const global = resolveInstallPaths(projectDir, "global")[key];
493
+ if (isHomeDirectory(projectDir)) return [global];
494
+ return [global, resolveInstallPaths(projectDir, "project")[key]];
495
+ }
496
+ async function listInstalledArtifacts(projectDir) {
497
+ const [skills, agents] = await Promise.all([
498
+ listAcrossScopes(installedDirs(projectDir, "skillsDir"), listDirectories),
499
+ listAcrossScopes(installedDirs(projectDir, "agentsDir"), listAgentMdFiles)
500
+ ]);
501
+ return { skills, agents };
502
+ }
503
+ async function listAcrossScopes(dirs, listEntries) {
504
+ const perDir = await Promise.all(dirs.map((dir) => listDisplayPaths(dir, listEntries)));
505
+ return perDir.flat();
506
+ }
507
+ async function listDisplayPaths(dir, listEntries) {
508
+ if (!await directoryExists(dir)) return [];
509
+ const entries = await listEntries(dir);
510
+ return entries.map((entry) => displayDir(path2.join(dir, entry)));
511
+ }
512
+ async function validateSkillsDirectory(skillsDir) {
513
+ if (!await directoryExists(skillsDir)) return NOTHING_VALIDATED;
514
+ const skillDirs = await listDirectories(skillsDir);
515
+ if (skillDirs.length === 0) return NOTHING_VALIDATED;
516
+ const results = await Promise.all(
517
+ skillDirs.map(async (name) => {
518
+ const skillDir = path2.join(skillsDir, name);
519
+ return toIssues(displayDir(skillDir), await validateInstalledSkill(skillDir));
520
+ })
521
+ );
522
+ return { count: skillDirs.length, issues: results.flat(), notes: [] };
523
+ }
524
+ async function validateAgentsDirectory(agentsDir) {
525
+ if (!await directoryExists(agentsDir)) return NOTHING_VALIDATED;
526
+ const agentFiles = await listAgentMdFiles(agentsDir);
527
+ if (agentFiles.length === 0) return NOTHING_VALIDATED;
528
+ const results = await Promise.all(
529
+ agentFiles.map(async (fileName) => {
530
+ const agentPath = path2.join(agentsDir, fileName);
531
+ return toIssues(displayDir(agentPath), await validateAgentFrontmatter(agentPath));
532
+ })
533
+ );
534
+ return { count: agentFiles.length, issues: results.flat(), notes: [] };
535
+ }
536
+ async function validateInstalledSkill(skillDir) {
537
+ const skillMdPath = path2.join(skillDir, STANDARD_FILES.SKILL_MD);
538
+ const metadataPath = path2.join(skillDir, STANDARD_FILES.METADATA_YAML);
539
+ const errors = [];
540
+ const warnings = [];
541
+ if (!await fileExists(skillMdPath)) {
542
+ errors.push(`Missing ${STANDARD_FILES.SKILL_MD}`);
543
+ } else {
544
+ const frontmatterResult = await validateSkillFrontmatter(skillMdPath);
545
+ errors.push(...frontmatterResult.errors);
546
+ warnings.push(...frontmatterResult.warnings);
547
+ }
548
+ if (!await fileExists(metadataPath)) {
549
+ errors.push(`Missing ${STANDARD_FILES.METADATA_YAML}`);
550
+ } else {
551
+ const metadataResult = await validateInstalledSkillMetadata(metadataPath);
552
+ errors.push(...metadataResult.errors);
553
+ warnings.push(...metadataResult.warnings);
554
+ }
555
+ return { valid: errors.length === 0, errors, warnings };
556
+ }
557
+ async function validateInstalledSkillMetadata(metadataPath) {
558
+ const read = await readSkillMetadata(metadataPath);
559
+ if (!read.usable) {
560
+ return {
561
+ valid: false,
562
+ errors: [`${STANDARD_FILES.METADATA_YAML}: ${read.reason}`],
563
+ warnings: []
564
+ };
565
+ }
566
+ const metadata = read.metadata;
567
+ const result = validateSkillMetadata(metadata);
568
+ if (result.success) {
569
+ return { valid: true, errors: [], warnings: [] };
570
+ }
571
+ const { errors, warnings } = splitMetadataValidationIssues(result.error, metadata);
572
+ return {
573
+ valid: errors.length === 0,
574
+ errors: errors.map((e) => `${STANDARD_FILES.METADATA_YAML}: ${e}`),
575
+ warnings: warnings.map((w) => `${STANDARD_FILES.METADATA_YAML}: ${w}`)
576
+ };
577
+ }
578
+
579
+ // src/cli/commands/doctor.ts
53
580
  import { countBy, unique } from "remeda";
54
581
  var CONFIG_TS_REL = `${CLAUDE_SRC_DIR}/${STANDARD_FILES.CONFIG_TS}`;
55
- function checkConfigValid(config) {
56
- if (!config) {
582
+ async function resolveConfigState(detected, projectDir) {
583
+ if (detected?.config) return { kind: "loaded", config: detected.config };
584
+ const loaded = await loadProjectConfigFromDir(projectDir);
585
+ if (!loaded) return { kind: "absent" };
586
+ return declaresNoContent(loaded.config) ? { kind: "declares-nothing", config: loaded.config } : { kind: "loaded", config: loaded.config };
587
+ }
588
+ function checkConfigValid(state) {
589
+ if (state.kind === "absent") {
57
590
  return {
58
591
  result: {
59
592
  kind: "config",
@@ -64,6 +597,17 @@ function checkConfigValid(config) {
64
597
  config: null
65
598
  };
66
599
  }
600
+ if (state.kind === "declares-nothing") {
601
+ return {
602
+ result: {
603
+ kind: "config-empty",
604
+ status: "warn",
605
+ message: `${CONFIG_TS_REL} is valid but declares no skills and no agents`
606
+ },
607
+ config: state.config
608
+ };
609
+ }
610
+ const { config } = state;
67
611
  const validation = validateProjectConfig(config);
68
612
  if (!validation.valid) {
69
613
  return {
@@ -111,20 +655,15 @@ async function checkSkillsResolved(config, matrix2, projectDir) {
111
655
  }
112
656
  const [localResult, globalResult] = await Promise.all([
113
657
  discoverLocalSkills(projectDir),
114
- !isHomeDirectory(projectDir) ? discoverLocalSkills(os.homedir()) : null
658
+ !isHomeDirectory(projectDir) ? discoverLocalSkills(os2.homedir()) : null
115
659
  ]);
116
660
  const localSkillIds = /* @__PURE__ */ new Set([
117
661
  ...localResult?.skills.map((s) => s.id) ?? [],
118
662
  ...globalResult?.skills.map((s) => s.id) ?? []
119
663
  ]);
120
- const missingSkills = [];
121
- for (const skillId of uniqueSkills) {
122
- const inMatrix = skillId in matrix2.skills;
123
- const inLocal = localSkillIds.has(skillId);
124
- if (!inMatrix && !inLocal) {
125
- missingSkills.push(skillId);
126
- }
127
- }
664
+ const missingSkills = uniqueSkills.filter(
665
+ (skillId) => !(skillId in matrix2.skills) && !localSkillIds.has(skillId)
666
+ );
128
667
  if (missingSkills.length > 0) {
129
668
  return {
130
669
  kind: "skills",
@@ -140,7 +679,7 @@ async function checkSkillsResolved(config, matrix2, projectDir) {
140
679
  };
141
680
  }
142
681
  async function checkAgentsCompiled(config, projectDir) {
143
- const agents = config.agents ?? [];
682
+ const agents = config.agents;
144
683
  if (agents.length === 0) {
145
684
  return {
146
685
  kind: "agents",
@@ -153,7 +692,7 @@ async function checkAgentsCompiled(config, projectDir) {
153
692
  const agentChecks = await Promise.all(
154
693
  agents.map(async (agent) => {
155
694
  const agentsDir = agent.scope === "global" ? globalAgentsDir : projectAgentsDir;
156
- const agentPath = path.join(agentsDir, `${agent.name}.md`);
695
+ const agentPath = path3.join(agentsDir, `${agent.name}.md`);
157
696
  return { name: agent.name, compiled: await fileExists(agentPath) };
158
697
  })
159
698
  );
@@ -190,30 +729,21 @@ async function checkNoOrphans(config, projectDir) {
190
729
  const projectMdFiles = projectExists ? await listAgentMdFiles(projectAgentsDir) : [];
191
730
  const globalMdFiles = globalExists ? await listAgentMdFiles(globalAgentsDir) : [];
192
731
  const activeProjectAgents = new Set(
193
- (config.agents ?? []).filter((a) => a.scope === "project" && !a.excluded).map((a) => a.name)
732
+ config.agents.filter((a) => a.scope === "project" && !a.excluded).map((a) => a.name)
194
733
  );
195
734
  const knownGlobalAgents = new Set(
196
- (config.agents ?? []).filter((a) => a.scope === "global").map((a) => a.name)
735
+ config.agents.filter((a) => a.scope === "global").map((a) => a.name)
197
736
  );
198
737
  const knownProjectDirAgents = scopesShareAgentsDir ? /* @__PURE__ */ new Set([...activeProjectAgents, ...knownGlobalAgents]) : activeProjectAgents;
199
- const orphanedFiles = [];
200
- for (const file of projectMdFiles) {
201
- const agentName = file.replace(/\.md$/, "");
202
- if (!knownProjectDirAgents.has(agentName)) {
203
- orphanedFiles.push(agentName);
204
- }
205
- }
206
- for (const file of globalMdFiles) {
207
- const agentName = file.replace(/\.md$/, "");
208
- if (!knownGlobalAgents.has(agentName)) {
209
- orphanedFiles.push(agentName);
210
- }
211
- }
738
+ const orphanedFiles = [
739
+ ...orphanedAgentNames(projectMdFiles, knownProjectDirAgents),
740
+ ...orphanedAgentNames(globalMdFiles, knownGlobalAgents)
741
+ ];
212
742
  if (orphanedFiles.length > 0) {
213
743
  return {
214
744
  kind: "orphans",
215
745
  status: "warn",
216
- message: `${orphanedFiles.length} orphaned agent file${orphanedFiles.length === 1 ? "" : "s"}`,
746
+ message: plural(orphanedFiles.length, "orphaned agent file"),
217
747
  details: orphanedFiles.map((f) => `- ${f}.md (not in config)`)
218
748
  };
219
749
  }
@@ -223,8 +753,29 @@ async function checkNoOrphans(config, projectDir) {
223
753
  message: "No orphaned agent files"
224
754
  };
225
755
  }
756
+ function orphanedAgentNames(mdFiles, knownAgents) {
757
+ return mdFiles.map((fileName) => fileName.replace(/\.md$/, "")).filter((agentName) => !knownAgents.has(agentName));
758
+ }
759
+ async function checkUnownedInstallation(projectDir) {
760
+ const { skills, agents } = await listInstalledArtifacts(projectDir);
761
+ if (skills.length === 0 && agents.length === 0) return skippedResult("orphans");
762
+ return {
763
+ kind: "orphans-unowned",
764
+ status: "fail",
765
+ // The per-line "(not in config)" the other verdict repeats is said once here instead:
766
+ // with no configuration it is true of every line, and there are as many lines as files.
767
+ message: `${countedArtifacts(skills, agents)} installed here, and no configuration declares them`,
768
+ details: [...skills, ...agents].map((artifact) => `- ${artifact}`)
769
+ };
770
+ }
771
+ function countedArtifacts(skills, agents) {
772
+ return [
773
+ ...skills.length > 0 ? [plural(skills.length, "skill")] : [],
774
+ ...agents.length > 0 ? [plural(agents.length, "agent")] : []
775
+ ].join(" and ");
776
+ }
226
777
  async function checkSkillsInstalled(config, projectDir) {
227
- const skills = config.skills ?? [];
778
+ const skills = config.skills;
228
779
  const ejectSkills = skills.filter((s) => s.source === EJECT_SOURCE);
229
780
  if (ejectSkills.length === 0) {
230
781
  return {
@@ -236,7 +787,7 @@ async function checkSkillsInstalled(config, projectDir) {
236
787
  const skillChecks = await Promise.all(
237
788
  ejectSkills.map(async (skill) => {
238
789
  const baseDir = installBaseDir(projectDir, skill.scope);
239
- const skillMdPath = path.join(baseDir, LOCAL_SKILLS_PATH, skill.id, STANDARD_FILES.SKILL_MD);
790
+ const skillMdPath = path3.join(baseDir, LOCAL_SKILLS_PATH, skill.id, STANDARD_FILES.SKILL_MD);
240
791
  return { id: skill.id, installed: await fileExists(skillMdPath) };
241
792
  })
242
793
  );
@@ -245,7 +796,7 @@ async function checkSkillsInstalled(config, projectDir) {
245
796
  return {
246
797
  kind: "installed",
247
798
  status: "warn",
248
- message: `${missingSkills.length} skill${missingSkills.length === 1 ? "" : "s"} missing from disk`,
799
+ message: `${plural(missingSkills.length, "skill")} missing from disk`,
249
800
  details: missingSkills.map((s) => `- ${s} (not found in ${LOCAL_SKILLS_PATH}/)`)
250
801
  };
251
802
  }
@@ -280,7 +831,7 @@ async function checkPluginSkillsInstalled(config, projectDir) {
280
831
  return {
281
832
  kind: "plugins",
282
833
  status: "warn",
283
- message: `${missingSkills.length} skill${missingSkills.length === 1 ? "" : "s"} not installed as plugins`,
834
+ message: `${plural(missingSkills.length, "skill")} not installed as plugins`,
284
835
  details: missingSkills.map((s) => `- ${s} (no enabled plugin found)`)
285
836
  };
286
837
  }
@@ -313,7 +864,82 @@ async function checkSourceReachable(projectDir) {
313
864
  };
314
865
  }
315
866
  }
867
+ var CONFIG_CHECK = {
868
+ kind: "content-config",
869
+ name: "Config",
870
+ noun: "config",
871
+ run: validateProjectConfigFile
872
+ };
873
+ var CONTENT_CHECKS = [
874
+ {
875
+ kind: "content-sources",
876
+ name: "Sources",
877
+ noun: "source",
878
+ // The registered sources are the ones config.ts names.
879
+ readsConfig: true,
880
+ run: validateRegisteredSources
881
+ },
882
+ {
883
+ kind: "content-plugins",
884
+ name: "Plugins",
885
+ noun: "plugin",
886
+ readsConfig: false,
887
+ run: validateInstalledPlugins
888
+ },
889
+ {
890
+ kind: "content-skills",
891
+ name: "Skills",
892
+ noun: "skill",
893
+ readsConfig: false,
894
+ run: validateInstalledSkills
895
+ },
896
+ {
897
+ kind: "content-agents",
898
+ name: "Agents",
899
+ noun: "agent",
900
+ readsConfig: false,
901
+ run: validateInstalledAgents
902
+ }
903
+ ];
904
+ function contentStatus(errors, warnings) {
905
+ if (errors > 0) return "fail";
906
+ if (warnings > 0) return "warn";
907
+ return "pass";
908
+ }
909
+ function contentMessage(noun, count, errors, warnings) {
910
+ if (errors === 0 && warnings === 0) {
911
+ return count === 0 ? `No ${noun}s to validate` : `${plural(count, noun)} validated`;
912
+ }
913
+ return `${plural(count, noun)}: ${plural(errors, "error")}, ${plural(warnings, "warning")}`;
914
+ }
915
+ function formatContentIssue(issue) {
916
+ const marker = issue.severity === "error" ? "ERROR" : "WARN";
917
+ return `- [${marker}] ${issue.file}: ${issue.message}`;
918
+ }
919
+ function toContentResult(check, validation) {
920
+ const errors = validation.issues.filter((issue) => issue.severity === "error").length;
921
+ const warnings = validation.issues.length - errors;
922
+ return {
923
+ kind: check.kind,
924
+ status: contentStatus(errors, warnings),
925
+ message: contentMessage(check.noun, validation.count, errors, warnings),
926
+ details: [
927
+ ...validation.notes.map((note) => `- ${note}`),
928
+ ...validation.issues.map(formatContentIssue)
929
+ ]
930
+ };
931
+ }
316
932
  var CHECK_WIDTH = 20;
933
+ var SECTION_INDENT = " ";
934
+ var ROW_INDENT = " ";
935
+ var SECTION_CONTENT = "Content checks";
936
+ var SECTION_OPERATIONAL = "Operational checks";
937
+ var SKIP_AFTER_CONTENT_ERRORS = "Skipped \u2014 fix the content errors above first";
938
+ var SKIP_NO_INSTALLATION = "Skipped \u2014 no installation here (skills source repository)";
939
+ var SKIP_CONFIG_UNREADABLE = "Skipped \u2014 the configuration that names them cannot be read";
940
+ function plural(count, word) {
941
+ return `${count} ${word}${count === 1 ? "" : "s"}`;
942
+ }
317
943
  function formatCheckName(name) {
318
944
  return name.padEnd(CHECK_WIDTH);
319
945
  }
@@ -334,21 +960,20 @@ function formatStatus(status) {
334
960
  }
335
961
  }
336
962
  function formatCheckLine(name, result) {
337
- const headerLine = ` ${formatCheckName(name)}${formatStatus(result.status)} ${result.message}`;
963
+ const headerLine = `${ROW_INDENT}${formatCheckName(name)}${formatStatus(result.status)} ${result.message}`;
338
964
  const detailLines = (result.details ?? []).map(
339
- (detail) => ` ${" ".repeat(CHECK_WIDTH)} ${detail}`
965
+ (detail) => `${ROW_INDENT}${" ".repeat(CHECK_WIDTH)} ${detail}`
340
966
  );
341
967
  return [headerLine, ...detailLines];
342
968
  }
343
969
  function formatSummary(results) {
344
970
  const counts = countBy(results, (r) => r.status);
345
- const plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
346
971
  const parts = [
347
972
  `${counts.pass ?? 0} passed`,
348
973
  plural(counts.warn ?? 0, "warning"),
349
974
  plural(counts.fail ?? 0, "error")
350
975
  ];
351
- return ` Summary: ${parts.join(", ")}`;
976
+ return `${SECTION_INDENT}Summary: ${parts.join(", ")}`;
352
977
  }
353
978
  var TIPS = [
354
979
  {
@@ -361,6 +986,31 @@ var TIPS = [
361
986
  status: "fail",
362
987
  tip: ` Tip: Run '${CLI_INVOKE_COMMAND} init' to create or fix configuration`
363
988
  },
989
+ {
990
+ // The remedy for a valid config with nothing in it. Not the tip above: there is nothing to
991
+ // create and nothing to fix. `init` on this config opens the wizard rather than the dashboard
992
+ // — that is what the detection returning null is FOR — so it is the way to fill it in.
993
+ kind: "config-empty",
994
+ status: "warn",
995
+ tip: ` Tip: Nothing is configured yet \u2014 run '${CLI_INVOKE_COMMAND} init' to choose skills and sub-agents`
996
+ },
997
+ {
998
+ // The one remedy that applies to a config that cannot be read. `init` does not clear such a
999
+ // file — it refuses it — so the tip above would send the reader in a circle; this is the same
1000
+ // way out `edit` and `init` themselves name, worded the same way.
1001
+ kind: "content-config",
1002
+ status: "fail",
1003
+ tip: ` Tip: There is no automatic repair \u2014 recreate the configuration: '${CLI_INVOKE_COMMAND} uninstall' still works on a config it cannot read, then '${CLI_INVOKE_COMMAND} init'`
1004
+ },
1005
+ {
1006
+ // Printed beside the config tip above, which says how to get a configuration back and
1007
+ // nothing about the files that outlived the old one. Both halves are named with what they
1008
+ // actually do: `uninstall` matches skill directories by their own `forked-from` metadata,
1009
+ // so it clears them without a config — and identifies compiled agents only through one.
1010
+ kind: "orphans-unowned",
1011
+ status: "fail",
1012
+ tip: ` Tip: Nothing declares the files above \u2014 '${CLI_INVOKE_COMMAND} init' writes a configuration that can own them again, or '${CLI_INVOKE_COMMAND} uninstall' removes the installed skills (the compiled agents outlive it: identifying them needs the configuration that is gone)`
1013
+ },
364
1014
  {
365
1015
  kind: "skills",
366
1016
  status: "fail",
@@ -383,6 +1033,15 @@ function formatTips(results) {
383
1033
  function skippedResult(kind) {
384
1034
  return { kind, status: "skip", message: "Skipped (config invalid)" };
385
1035
  }
1036
+ function sourceUnreachableSkillsResult() {
1037
+ return { kind: "skills", status: "skip", message: "Skipped (source unreachable)" };
1038
+ }
1039
+ function skippedContentResult(kind) {
1040
+ return { kind, status: "skip", message: SKIP_CONFIG_UNREADABLE };
1041
+ }
1042
+ function runContentCheck(check, projectDir) {
1043
+ return safeCheck(check.kind, async () => toContentResult(check, await check.run(projectDir)));
1044
+ }
386
1045
  async function safeCheck(kind, fn) {
387
1046
  try {
388
1047
  return await fn();
@@ -394,15 +1053,15 @@ var Doctor = class _Doctor extends BaseCommand {
394
1053
  static summary = "Diagnose common configuration issues";
395
1054
  static description = `Run diagnostic checks on your ${DEFAULT_BRANDING.NAME} configuration to identify issues with config validity, skill resolution, agent compilation, and source connectivity.`;
396
1055
  static examples = ["<%= config.bin %> <%= command.id %>"];
397
- // Override parent baseFlags to drop --source (not relevant for diagnostics)
398
- static baseFlags = {};
399
1056
  static flags = {};
400
1057
  async run() {
401
1058
  await this.parse(_Doctor);
402
1059
  setVerbose(true);
403
1060
  const projectDir = process.cwd();
404
1061
  this.printHeader();
405
- const results = await this.runAllChecks(projectDir);
1062
+ const contentResults = await this.runContentChecks(projectDir);
1063
+ const operationalResults = await this.runOperationalChecks(projectDir, contentResults);
1064
+ const results = [...contentResults, ...operationalResults];
406
1065
  this.printResults(results);
407
1066
  if (results.some((r) => r.status === "fail")) {
408
1067
  this.exit(EXIT_CODES.ERROR);
@@ -412,24 +1071,70 @@ var Doctor = class _Doctor extends BaseCommand {
412
1071
  this.log("");
413
1072
  this.log(`${DEFAULT_BRANDING.NAME} Doctor`);
414
1073
  this.log("");
415
- this.log(" Checking configuration health...");
1074
+ this.log(`${SECTION_INDENT}Checking configuration health...`);
416
1075
  this.log("");
417
1076
  }
418
- async runAllChecks(projectDir) {
1077
+ /**
1078
+ * The config is checked first and alone. A check that reads it to know what to validate would
1079
+ * otherwise ask a file already reported as unreadable — and asking is what emitted the loader's
1080
+ * own failure line once per read, spliced between these rows. Everything that walks installed
1081
+ * content on disk still runs: it says something true whatever the config is in.
1082
+ */
1083
+ async runContentChecks(projectDir) {
1084
+ this.log(`${SECTION_INDENT}${SECTION_CONTENT}`);
1085
+ const configResult = await runContentCheck(CONFIG_CHECK, projectDir);
1086
+ const configUnreadable = configResult.status === "fail";
1087
+ const rows = await Promise.all(
1088
+ CONTENT_CHECKS.map(async (check) => ({
1089
+ name: check.name,
1090
+ result: check.readsConfig && configUnreadable ? skippedContentResult(check.kind) : await runContentCheck(check, projectDir)
1091
+ }))
1092
+ );
1093
+ const allRows = [{ name: CONFIG_CHECK.name, result: configResult }, ...rows];
1094
+ for (const row of allRows) {
1095
+ this.logCheck(row.name, row.result);
1096
+ }
1097
+ return allRows.map((row) => row.result);
1098
+ }
1099
+ /**
1100
+ * The operational layer runs only when it can say something the reader can act on:
1101
+ * not after content errors (its findings would be their cascades), and not in a
1102
+ * source repository with nothing installed (a marketplace author has no install
1103
+ * for it to describe).
1104
+ */
1105
+ async runOperationalChecks(projectDir, contentResults) {
1106
+ this.log("");
1107
+ this.log(`${SECTION_INDENT}${SECTION_OPERATIONAL}`);
1108
+ if (contentResults.some((r) => r.status === "fail")) {
1109
+ this.log(`${ROW_INDENT}${SKIP_AFTER_CONTENT_ERRORS}`);
1110
+ return [];
1111
+ }
419
1112
  const detected = await detectProject(projectDir);
420
- const { result: configResult, config } = checkConfigValid(detected?.config ?? null);
1113
+ if (!detected && await this.isUninstalledSourceRepo(projectDir)) {
1114
+ this.log(`${ROW_INDENT}${SKIP_NO_INSTALLATION}`);
1115
+ return [];
1116
+ }
1117
+ return this.runAllChecks(projectDir, await resolveConfigState(detected, projectDir));
1118
+ }
1119
+ /**
1120
+ * A config file that exists but failed to load also detects as "no project", and
1121
+ * that is a finding rather than an absence — so the skip requires no config file
1122
+ * at all, not merely no usable one.
1123
+ */
1124
+ async isUninstalledSourceRepo(projectDir) {
1125
+ if (await fileExists(getProjectConfigPath(projectDir))) return false;
1126
+ return isSourceRepo(projectDir);
1127
+ }
1128
+ async runAllChecks(projectDir, configState) {
1129
+ const { result: configResult, config } = checkConfigValid(configState);
421
1130
  this.logCheck("Config Valid", configResult);
422
1131
  const sourceResult = await safeCheck("source", () => checkSourceReachable(projectDir));
423
1132
  const filteredConfig = config ? filterExcludedEntries(config) : null;
424
- const skillsResult = !config ? skippedResult("skills") : sourceResult.status === "fail" ? {
425
- kind: "skills",
426
- status: "skip",
427
- message: "Skipped (source unreachable)"
428
- } : await safeCheck("skills", () => checkSkillsResolved(config, matrix, projectDir));
1133
+ const skillsResult = await this.resolveSkillsCheck(config, sourceResult, projectDir);
429
1134
  this.logCheck("Skills Resolved", skillsResult);
430
1135
  const agentsResult = filteredConfig ? await safeCheck("agents", () => checkAgentsCompiled(filteredConfig, projectDir)) : skippedResult("agents");
431
1136
  this.logCheck("Agents Compiled", agentsResult);
432
- const orphansResult = config ? await safeCheck("orphans", () => checkNoOrphans(config, projectDir)) : skippedResult("orphans");
1137
+ const orphansResult = await this.resolveOrphansCheck(config, configState, projectDir);
433
1138
  this.logCheck("No Orphans", orphansResult);
434
1139
  const installedResult = filteredConfig ? await safeCheck("installed", () => checkSkillsInstalled(filteredConfig, projectDir)) : skippedResult("installed");
435
1140
  this.logCheck("Skills Installed", installedResult);
@@ -446,6 +1151,30 @@ var Doctor = class _Doctor extends BaseCommand {
446
1151
  sourceResult
447
1152
  ];
448
1153
  }
1154
+ /**
1155
+ * The orphan row, and which question it can answer. With a config it names the compiled
1156
+ * agents that config does not; with no config at all every installed file is unowned and it
1157
+ * names all of them. It skips for the one state left — a config that loads and fails
1158
+ * validation — because there the file that says who owns what has already been rejected, and
1159
+ * an installation must not be called stranded on the strength of one nobody can trust.
1160
+ */
1161
+ async resolveOrphansCheck(config, configState, projectDir) {
1162
+ if (config) return safeCheck("orphans", () => checkNoOrphans(config, projectDir));
1163
+ if (configState.kind === "absent") {
1164
+ return safeCheck("orphans", () => checkUnownedInstallation(projectDir));
1165
+ }
1166
+ return skippedResult("orphans");
1167
+ }
1168
+ /**
1169
+ * The skills row, and the two states in which it cannot be computed: no config to read the
1170
+ * skills out of, and a source that never loaded — so there is no populated matrix to resolve
1171
+ * them against, and every configured skill would be reported "not found".
1172
+ */
1173
+ async resolveSkillsCheck(config, sourceResult, projectDir) {
1174
+ if (!config) return skippedResult("skills");
1175
+ if (sourceResult.status === "fail") return sourceUnreachableSkillsResult();
1176
+ return safeCheck("skills", () => checkSkillsResolved(config, matrix, projectDir));
1177
+ }
449
1178
  logCheck(name, result) {
450
1179
  for (const line of formatCheckLine(name, result)) {
451
1180
  this.log(line);