agents-inc 0.149.2 → 0.151.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 (572) hide show
  1. package/CHANGELOG.md +2287 -0
  2. package/LICENSE +21 -0
  3. package/README.md +136 -19
  4. package/assets/demo.gif +0 -0
  5. package/assets/demo.tape +266 -0
  6. package/assets/logo.svg +75 -0
  7. package/dist/chunk-2RSNKBXC.js +84 -0
  8. package/dist/chunk-2RSNKBXC.js.map +1 -0
  9. package/dist/chunk-3LIU2ZEF.js +1355 -0
  10. package/dist/chunk-3LIU2ZEF.js.map +1 -0
  11. package/dist/chunk-3XFUQ6OL.js +68 -0
  12. package/dist/chunk-3XFUQ6OL.js.map +1 -0
  13. package/dist/chunk-3YGUHWLR.js +258 -0
  14. package/dist/chunk-3YGUHWLR.js.map +1 -0
  15. package/dist/chunk-44LLPS2N.js +1135 -0
  16. package/dist/chunk-44LLPS2N.js.map +1 -0
  17. package/dist/chunk-4R6PGHQQ.js +300 -0
  18. package/dist/chunk-4R6PGHQQ.js.map +1 -0
  19. package/dist/chunk-5V2O6C3T.js +112 -0
  20. package/dist/chunk-5V2O6C3T.js.map +1 -0
  21. package/dist/chunk-6RBQBOBS.js +287 -0
  22. package/dist/chunk-6RBQBOBS.js.map +1 -0
  23. package/dist/chunk-7QIHKQL5.js +181 -0
  24. package/dist/chunk-7QIHKQL5.js.map +1 -0
  25. package/dist/chunk-BNE4HHIH.js +28 -0
  26. package/dist/chunk-BNE4HHIH.js.map +1 -0
  27. package/dist/chunk-C55DN7GE.js +35 -0
  28. package/dist/chunk-C55DN7GE.js.map +1 -0
  29. package/dist/chunk-DAG2ULNF.js +125 -0
  30. package/dist/chunk-DAG2ULNF.js.map +1 -0
  31. package/dist/chunk-DG2NGZ7S.js +10929 -0
  32. package/dist/chunk-DG2NGZ7S.js.map +1 -0
  33. package/dist/chunk-DIBCRIMR.js +36 -0
  34. package/dist/chunk-DIBCRIMR.js.map +1 -0
  35. package/dist/chunk-DUVWGO6E.js +54 -0
  36. package/dist/chunk-DUVWGO6E.js.map +1 -0
  37. package/dist/chunk-EKWAUOQB.js +96 -0
  38. package/dist/chunk-EKWAUOQB.js.map +1 -0
  39. package/dist/chunk-ES3NJZON.js +31 -0
  40. package/dist/chunk-ES3NJZON.js.map +1 -0
  41. package/dist/chunk-EVXG3X6G.js +179 -0
  42. package/dist/chunk-EVXG3X6G.js.map +1 -0
  43. package/dist/chunk-EZ7STXUV.js +349 -0
  44. package/dist/chunk-EZ7STXUV.js.map +1 -0
  45. package/dist/chunk-FYPUUYSG.js +31 -0
  46. package/dist/chunk-FYPUUYSG.js.map +1 -0
  47. package/dist/chunk-GYG5SE2D.js +81 -0
  48. package/dist/chunk-GYG5SE2D.js.map +1 -0
  49. package/dist/chunk-I3XKEGHM.js +16383 -0
  50. package/dist/chunk-I3XKEGHM.js.map +1 -0
  51. package/dist/chunk-IHO75PMZ.js +40 -0
  52. package/dist/chunk-IHO75PMZ.js.map +1 -0
  53. package/dist/chunk-IOJR5TOY.js +47 -0
  54. package/dist/chunk-IOJR5TOY.js.map +1 -0
  55. package/dist/chunk-K3OU6TGX.js +77 -0
  56. package/dist/chunk-K3OU6TGX.js.map +1 -0
  57. package/dist/chunk-KIR7VYQD.js +63 -0
  58. package/dist/chunk-KIR7VYQD.js.map +1 -0
  59. package/dist/chunk-KOPEM3Q7.js +27 -0
  60. package/dist/chunk-KOPEM3Q7.js.map +1 -0
  61. package/dist/chunk-KSZ6PCY4.js +43 -0
  62. package/dist/chunk-KSZ6PCY4.js.map +1 -0
  63. package/dist/chunk-LAXAQ3PZ.js +235 -0
  64. package/dist/chunk-LAXAQ3PZ.js.map +1 -0
  65. package/dist/chunk-LYYXX2W5.js +87 -0
  66. package/dist/chunk-LYYXX2W5.js.map +1 -0
  67. package/dist/chunk-NGLQ5W7U.js +339 -0
  68. package/dist/chunk-NGLQ5W7U.js.map +1 -0
  69. package/dist/chunk-NHCGC6DG.js +111 -0
  70. package/dist/chunk-NHCGC6DG.js.map +1 -0
  71. package/dist/chunk-NIKUMXE7.js +24 -0
  72. package/dist/chunk-NIKUMXE7.js.map +1 -0
  73. package/dist/chunk-NM3EDGB5.js +300 -0
  74. package/dist/chunk-NM3EDGB5.js.map +1 -0
  75. package/dist/chunk-O5ASLZ2K.js +270 -0
  76. package/dist/chunk-O5ASLZ2K.js.map +1 -0
  77. package/dist/chunk-OJIESW5B.js +174 -0
  78. package/dist/chunk-OJIESW5B.js.map +1 -0
  79. package/dist/chunk-OZZGXBCN.js +15 -0
  80. package/dist/chunk-OZZGXBCN.js.map +1 -0
  81. package/dist/chunk-P3PN5SVI.js +27 -0
  82. package/dist/chunk-P3PN5SVI.js.map +1 -0
  83. package/dist/chunk-P56WJ5FA.js +50 -0
  84. package/dist/chunk-P56WJ5FA.js.map +1 -0
  85. package/dist/chunk-PG4G4IIK.js +24 -0
  86. package/dist/chunk-PG4G4IIK.js.map +1 -0
  87. package/dist/chunk-PV2HNW4I.js +382 -0
  88. package/dist/chunk-PV2HNW4I.js.map +1 -0
  89. package/dist/chunk-QQLRX4KI.js +41 -0
  90. package/dist/chunk-QQLRX4KI.js.map +1 -0
  91. package/dist/chunk-QTFQEYDA.js +789 -0
  92. package/dist/chunk-QTFQEYDA.js.map +1 -0
  93. package/dist/chunk-RBHYLCUB.js +31 -0
  94. package/dist/chunk-RBHYLCUB.js.map +1 -0
  95. package/dist/chunk-SHHOMVWC.js +62 -0
  96. package/dist/chunk-SHHOMVWC.js.map +1 -0
  97. package/dist/chunk-SI5FOARI.js +42 -0
  98. package/dist/chunk-SI5FOARI.js.map +1 -0
  99. package/dist/chunk-SYUOXSPU.js +510 -0
  100. package/dist/chunk-SYUOXSPU.js.map +1 -0
  101. package/dist/chunk-THKIOI32.js +939 -0
  102. package/dist/chunk-THKIOI32.js.map +1 -0
  103. package/dist/chunk-TVHRMRD3.js +6014 -0
  104. package/dist/chunk-TVHRMRD3.js.map +1 -0
  105. package/dist/chunk-TYJLR32W.js +128 -0
  106. package/dist/chunk-TYJLR32W.js.map +1 -0
  107. package/dist/chunk-UFURYGD3.js +20 -0
  108. package/dist/chunk-UFURYGD3.js.map +1 -0
  109. package/dist/chunk-UTFN6UJS.js +253 -0
  110. package/dist/chunk-UTFN6UJS.js.map +1 -0
  111. package/dist/chunk-V7QOSGQA.js +298 -0
  112. package/dist/chunk-V7QOSGQA.js.map +1 -0
  113. package/dist/chunk-VEP23B5W.js +27 -0
  114. package/dist/chunk-VEP23B5W.js.map +1 -0
  115. package/dist/chunk-VG2TVBFN.js +52 -0
  116. package/dist/chunk-VG2TVBFN.js.map +1 -0
  117. package/dist/chunk-WFWCZEMS.js +92 -0
  118. package/dist/chunk-WFWCZEMS.js.map +1 -0
  119. package/dist/chunk-WK4J2CHH.js +430 -0
  120. package/dist/chunk-WK4J2CHH.js.map +1 -0
  121. package/dist/chunk-XA57SX4T.js +115 -0
  122. package/dist/chunk-XA57SX4T.js.map +1 -0
  123. package/dist/chunk-Y4CXDA3I.js +181 -0
  124. package/dist/chunk-Y4CXDA3I.js.map +1 -0
  125. package/dist/chunk-YA4QQKKE.js +51 -0
  126. package/dist/chunk-YA4QQKKE.js.map +1 -0
  127. package/dist/chunk-YBVA7GPW.js +27 -0
  128. package/dist/chunk-YBVA7GPW.js.map +1 -0
  129. package/dist/chunk-YU2VGX5R.js +4205 -0
  130. package/dist/chunk-YU2VGX5R.js.map +1 -0
  131. package/dist/commands/build/marketplace.js +250 -0
  132. package/dist/commands/build/marketplace.js.map +1 -0
  133. package/dist/commands/build/plugins.js +176 -0
  134. package/dist/commands/build/plugins.js.map +1 -0
  135. package/dist/commands/compile.js +331 -0
  136. package/dist/commands/compile.js.map +1 -0
  137. package/dist/commands/doctor.js +475 -0
  138. package/dist/commands/doctor.js.map +1 -0
  139. package/dist/commands/edit.js +765 -0
  140. package/dist/commands/edit.js.map +1 -0
  141. package/dist/commands/eject.js +393 -0
  142. package/dist/commands/eject.js.map +1 -0
  143. package/dist/commands/import/skill.js +349 -0
  144. package/dist/commands/import/skill.js.map +1 -0
  145. package/dist/commands/init.js +66 -0
  146. package/dist/commands/init.js.map +1 -0
  147. package/dist/commands/list.js +115 -0
  148. package/dist/commands/list.js.map +1 -0
  149. package/dist/commands/new/agent.js +304 -0
  150. package/dist/commands/new/agent.js.map +1 -0
  151. package/dist/commands/new/marketplace.js +315 -0
  152. package/dist/commands/new/marketplace.js.map +1 -0
  153. package/dist/commands/new/skill.js +28 -0
  154. package/dist/commands/new/skill.js.map +1 -0
  155. package/dist/commands/search.js +176 -0
  156. package/dist/commands/search.js.map +1 -0
  157. package/dist/commands/uninstall.js +570 -0
  158. package/dist/commands/uninstall.js.map +1 -0
  159. package/dist/commands/update.js +368 -0
  160. package/dist/commands/update.js.map +1 -0
  161. package/dist/commands/validate.js +581 -0
  162. package/dist/commands/validate.js.map +1 -0
  163. package/dist/components/common/confirm.js +9 -0
  164. package/dist/components/common/confirm.js.map +1 -0
  165. package/dist/components/common/confirm.test.js +203 -0
  166. package/dist/components/common/confirm.test.js.map +1 -0
  167. package/dist/components/common/prompt-confirm.js +11 -0
  168. package/dist/components/common/prompt-confirm.js.map +1 -0
  169. package/dist/components/common/select-list.js +11 -0
  170. package/dist/components/common/select-list.js.map +1 -0
  171. package/dist/components/common/spinner.js +9 -0
  172. package/dist/components/common/spinner.js.map +1 -0
  173. package/dist/components/wizard/category-grid.js +16 -0
  174. package/dist/components/wizard/category-grid.js.map +1 -0
  175. package/dist/components/wizard/category-grid.test.js +1253 -0
  176. package/dist/components/wizard/category-grid.test.js.map +1 -0
  177. package/dist/components/wizard/checkbox-grid.js +14 -0
  178. package/dist/components/wizard/checkbox-grid.js.map +1 -0
  179. package/dist/components/wizard/checkbox-grid.test.js +264 -0
  180. package/dist/components/wizard/checkbox-grid.test.js.map +1 -0
  181. package/dist/components/wizard/domain-selection.js +22 -0
  182. package/dist/components/wizard/domain-selection.js.map +1 -0
  183. package/dist/components/wizard/run-wizard-session.js +47 -0
  184. package/dist/components/wizard/run-wizard-session.js.map +1 -0
  185. package/dist/components/wizard/scroll-affordance.js +10 -0
  186. package/dist/components/wizard/scroll-affordance.js.map +1 -0
  187. package/dist/components/wizard/search-modal.js +14 -0
  188. package/dist/components/wizard/search-modal.js.map +1 -0
  189. package/dist/components/wizard/search-modal.test.js +212 -0
  190. package/dist/components/wizard/search-modal.test.js.map +1 -0
  191. package/dist/components/wizard/selection-card.js +10 -0
  192. package/dist/components/wizard/selection-card.js.map +1 -0
  193. package/dist/components/wizard/skill-agent-summary.js +16 -0
  194. package/dist/components/wizard/skill-agent-summary.js.map +1 -0
  195. package/dist/components/wizard/source-grid.js +23 -0
  196. package/dist/components/wizard/source-grid.js.map +1 -0
  197. package/dist/components/wizard/source-grid.test.js +1094 -0
  198. package/dist/components/wizard/source-grid.test.js.map +1 -0
  199. package/dist/components/wizard/stack-selection.js +20 -0
  200. package/dist/components/wizard/stack-selection.js.map +1 -0
  201. package/dist/components/wizard/step-agents.js +22 -0
  202. package/dist/components/wizard/step-agents.js.map +1 -0
  203. package/dist/components/wizard/step-agents.test.js +204 -0
  204. package/dist/components/wizard/step-agents.test.js.map +1 -0
  205. package/dist/components/wizard/step-build.js +22 -0
  206. package/dist/components/wizard/step-build.js.map +1 -0
  207. package/dist/components/wizard/step-build.test.js +552 -0
  208. package/dist/components/wizard/step-build.test.js.map +1 -0
  209. package/dist/components/wizard/step-confirm.js +21 -0
  210. package/dist/components/wizard/step-confirm.js.map +1 -0
  211. package/dist/components/wizard/step-confirm.test.js +744 -0
  212. package/dist/components/wizard/step-confirm.test.js.map +1 -0
  213. package/dist/components/wizard/step-settings.js +19 -0
  214. package/dist/components/wizard/step-settings.js.map +1 -0
  215. package/dist/components/wizard/step-settings.test.js +244 -0
  216. package/dist/components/wizard/step-settings.test.js.map +1 -0
  217. package/dist/components/wizard/step-sources.js +28 -0
  218. package/dist/components/wizard/step-sources.js.map +1 -0
  219. package/dist/components/wizard/step-sources.test.js +155 -0
  220. package/dist/components/wizard/step-sources.test.js.map +1 -0
  221. package/dist/components/wizard/step-stack.js +21 -0
  222. package/dist/components/wizard/step-stack.js.map +1 -0
  223. package/dist/components/wizard/step-stack.test.js +262 -0
  224. package/dist/components/wizard/step-stack.test.js.map +1 -0
  225. package/dist/components/wizard/summary-panel.js +20 -0
  226. package/dist/components/wizard/summary-panel.js.map +1 -0
  227. package/dist/components/wizard/summary-panel.test.js +317 -0
  228. package/dist/components/wizard/summary-panel.test.js.map +1 -0
  229. package/dist/components/wizard/toast.js +10 -0
  230. package/dist/components/wizard/toast.js.map +1 -0
  231. package/dist/components/wizard/wizard-layout.js +26 -0
  232. package/dist/components/wizard/wizard-layout.js.map +1 -0
  233. package/dist/components/wizard/wizard-layout.test.js +200 -0
  234. package/dist/components/wizard/wizard-layout.test.js.map +1 -0
  235. package/dist/components/wizard/wizard-tabs.js +20 -0
  236. package/dist/components/wizard/wizard-tabs.js.map +1 -0
  237. package/dist/components/wizard/wizard-tabs.test.js +290 -0
  238. package/dist/components/wizard/wizard-tabs.test.js.map +1 -0
  239. package/dist/components/wizard/wizard.js +48 -0
  240. package/dist/components/wizard/wizard.js.map +1 -0
  241. package/dist/config-exports.js +20 -0
  242. package/dist/config-exports.js.map +1 -0
  243. package/dist/copy-local-skills-UPA2GUZV.js +15 -0
  244. package/dist/copy-local-skills-UPA2GUZV.js.map +1 -0
  245. package/dist/dist-VNJNNJK7.js +550 -0
  246. package/dist/dist-VNJNNJK7.js.map +1 -0
  247. package/dist/hooks/init.js +90 -0
  248. package/dist/hooks/init.js.map +1 -0
  249. package/dist/index.js +10 -0
  250. package/dist/index.js.map +1 -0
  251. package/dist/load-agent-defs-SB4XAOVB.js +16 -0
  252. package/dist/load-agent-defs-SB4XAOVB.js.map +1 -0
  253. package/dist/loader-E2ERJYVA.js +23 -0
  254. package/dist/loader-E2ERJYVA.js.map +1 -0
  255. package/dist/magic-string.es-5TV73NJD.js +1316 -0
  256. package/dist/magic-string.es-5TV73NJD.js.map +1 -0
  257. package/dist/recompile-project-agents-U4ZY2GDX.js +20 -0
  258. package/dist/recompile-project-agents-U4ZY2GDX.js.map +1 -0
  259. package/dist/source-loader-5UNRU7EZ.js +20 -0
  260. package/dist/source-loader-5UNRU7EZ.js.map +1 -0
  261. package/dist/source-manager-3O54SIIB.js +18 -0
  262. package/dist/source-manager-3O54SIIB.js.map +1 -0
  263. package/dist/src/agents/_templates/agent.liquid +161 -0
  264. package/dist/src/agents/_templates/methodologies/anti-over-engineering.liquid +121 -0
  265. package/dist/src/agents/_templates/methodologies/context-management.liquid +162 -0
  266. package/dist/src/agents/_templates/methodologies/improvement-protocol.liquid +150 -0
  267. package/dist/src/agents/_templates/methodologies/investigation-requirements.liquid +49 -0
  268. package/dist/src/agents/_templates/methodologies/success-criteria.liquid +111 -0
  269. package/dist/src/agents/_templates/methodologies/write-verification.liquid +43 -0
  270. package/dist/src/agents/developer/ai-developer/critical-reminders.md +54 -0
  271. package/dist/src/agents/developer/ai-developer/critical-requirements.md +59 -0
  272. package/dist/src/agents/developer/ai-developer/identity.md +51 -0
  273. package/dist/src/agents/developer/ai-developer/metadata.yaml +12 -0
  274. package/dist/src/agents/developer/ai-developer/output.md +366 -0
  275. package/dist/src/agents/developer/ai-developer/playbook.md +335 -0
  276. package/dist/src/agents/developer/api-developer/critical-reminders.md +46 -0
  277. package/dist/src/agents/developer/api-developer/critical-requirements.md +44 -0
  278. package/dist/src/agents/developer/api-developer/identity.md +49 -0
  279. package/dist/src/agents/developer/api-developer/metadata.yaml +12 -0
  280. package/dist/src/agents/developer/api-developer/output.md +432 -0
  281. package/dist/src/agents/developer/api-developer/playbook.md +352 -0
  282. package/dist/src/agents/developer/cli-developer/critical-reminders.md +51 -0
  283. package/dist/src/agents/developer/cli-developer/critical-requirements.md +51 -0
  284. package/dist/src/agents/developer/cli-developer/identity.md +51 -0
  285. package/dist/src/agents/developer/cli-developer/metadata.yaml +12 -0
  286. package/dist/src/agents/developer/cli-developer/output.md +285 -0
  287. package/dist/src/agents/developer/cli-developer/playbook.md +386 -0
  288. package/dist/src/agents/developer/web-architecture/critical-reminders.md +48 -0
  289. package/dist/src/agents/developer/web-architecture/critical-requirements.md +65 -0
  290. package/dist/src/agents/developer/web-architecture/identity.md +64 -0
  291. package/dist/src/agents/developer/web-architecture/metadata.yaml +12 -0
  292. package/dist/src/agents/developer/web-architecture/output.md +449 -0
  293. package/dist/src/agents/developer/web-architecture/playbook.md +481 -0
  294. package/dist/src/agents/developer/web-developer/critical-reminders.md +40 -0
  295. package/dist/src/agents/developer/web-developer/critical-requirements.md +39 -0
  296. package/dist/src/agents/developer/web-developer/identity.md +32 -0
  297. package/dist/src/agents/developer/web-developer/metadata.yaml +12 -0
  298. package/dist/src/agents/developer/web-developer/output.md +323 -0
  299. package/dist/src/agents/developer/web-developer/playbook.md +349 -0
  300. package/dist/src/agents/meta/agent-summoner/critical-reminders.md +45 -0
  301. package/dist/src/agents/meta/agent-summoner/critical-requirements.md +52 -0
  302. package/dist/src/agents/meta/agent-summoner/identity.md +34 -0
  303. package/dist/src/agents/meta/agent-summoner/metadata.yaml +12 -0
  304. package/dist/src/agents/meta/agent-summoner/output.md +296 -0
  305. package/dist/src/agents/meta/agent-summoner/playbook.md +1469 -0
  306. package/dist/src/agents/meta/codex-keeper/critical-reminders.md +39 -0
  307. package/dist/src/agents/meta/codex-keeper/critical-requirements.md +29 -0
  308. package/dist/src/agents/meta/codex-keeper/identity.md +45 -0
  309. package/dist/src/agents/meta/codex-keeper/metadata.yaml +12 -0
  310. package/dist/src/agents/meta/codex-keeper/output.md +384 -0
  311. package/dist/src/agents/meta/codex-keeper/playbook.md +1183 -0
  312. package/dist/src/agents/meta/convention-keeper/critical-reminders.md +32 -0
  313. package/dist/src/agents/meta/convention-keeper/critical-requirements.md +32 -0
  314. package/dist/src/agents/meta/convention-keeper/identity.md +33 -0
  315. package/dist/src/agents/meta/convention-keeper/metadata.yaml +12 -0
  316. package/dist/src/agents/meta/convention-keeper/output.md +206 -0
  317. package/dist/src/agents/meta/convention-keeper/playbook.md +180 -0
  318. package/dist/src/agents/meta/skill-summoner/critical-reminders.md +112 -0
  319. package/dist/src/agents/meta/skill-summoner/critical-requirements.md +62 -0
  320. package/dist/src/agents/meta/skill-summoner/identity.md +31 -0
  321. package/dist/src/agents/meta/skill-summoner/metadata.yaml +13 -0
  322. package/dist/src/agents/meta/skill-summoner/output.md +390 -0
  323. package/dist/src/agents/meta/skill-summoner/playbook.md +1457 -0
  324. package/dist/src/agents/pattern/pattern-scout/critical-reminders.md +71 -0
  325. package/dist/src/agents/pattern/pattern-scout/critical-requirements.md +31 -0
  326. package/dist/src/agents/pattern/pattern-scout/identity.md +25 -0
  327. package/dist/src/agents/pattern/pattern-scout/metadata.yaml +10 -0
  328. package/dist/src/agents/pattern/pattern-scout/output.md +290 -0
  329. package/dist/src/agents/pattern/pattern-scout/playbook.md +1806 -0
  330. package/dist/src/agents/pattern/web-pattern-critique/critical-reminders.md +30 -0
  331. package/dist/src/agents/pattern/web-pattern-critique/critical-requirements.md +28 -0
  332. package/dist/src/agents/pattern/web-pattern-critique/identity.md +41 -0
  333. package/dist/src/agents/pattern/web-pattern-critique/metadata.yaml +12 -0
  334. package/dist/src/agents/pattern/web-pattern-critique/output.md +314 -0
  335. package/dist/src/agents/pattern/web-pattern-critique/playbook.md +572 -0
  336. package/dist/src/agents/planning/api-pm/critical-reminders.md +48 -0
  337. package/dist/src/agents/planning/api-pm/critical-requirements.md +41 -0
  338. package/dist/src/agents/planning/api-pm/identity.md +39 -0
  339. package/dist/src/agents/planning/api-pm/metadata.yaml +12 -0
  340. package/dist/src/agents/planning/api-pm/output.md +475 -0
  341. package/dist/src/agents/planning/api-pm/playbook.md +129 -0
  342. package/dist/src/agents/planning/web-pm/critical-reminders.md +36 -0
  343. package/dist/src/agents/planning/web-pm/critical-requirements.md +32 -0
  344. package/dist/src/agents/planning/web-pm/identity.md +26 -0
  345. package/dist/src/agents/planning/web-pm/metadata.yaml +12 -0
  346. package/dist/src/agents/planning/web-pm/output.md +314 -0
  347. package/dist/src/agents/planning/web-pm/playbook.md +318 -0
  348. package/dist/src/agents/researcher/api-researcher/critical-reminders.md +27 -0
  349. package/dist/src/agents/researcher/api-researcher/critical-requirements.md +28 -0
  350. package/dist/src/agents/researcher/api-researcher/identity.md +71 -0
  351. package/dist/src/agents/researcher/api-researcher/metadata.yaml +10 -0
  352. package/dist/src/agents/researcher/api-researcher/output.md +254 -0
  353. package/dist/src/agents/researcher/api-researcher/playbook.md +201 -0
  354. package/dist/src/agents/researcher/web-researcher/critical-reminders.md +39 -0
  355. package/dist/src/agents/researcher/web-researcher/critical-requirements.md +26 -0
  356. package/dist/src/agents/researcher/web-researcher/identity.md +69 -0
  357. package/dist/src/agents/researcher/web-researcher/metadata.yaml +10 -0
  358. package/dist/src/agents/researcher/web-researcher/output.md +241 -0
  359. package/dist/src/agents/researcher/web-researcher/playbook.md +217 -0
  360. package/dist/src/agents/reviewer/ai-reviewer/critical-reminders.md +40 -0
  361. package/dist/src/agents/reviewer/ai-reviewer/critical-requirements.md +37 -0
  362. package/dist/src/agents/reviewer/ai-reviewer/identity.md +51 -0
  363. package/dist/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
  364. package/dist/src/agents/reviewer/ai-reviewer/output.md +395 -0
  365. package/dist/src/agents/reviewer/ai-reviewer/playbook.md +90 -0
  366. package/dist/src/agents/reviewer/api-reviewer/critical-reminders.md +31 -0
  367. package/dist/src/agents/reviewer/api-reviewer/critical-requirements.md +27 -0
  368. package/dist/src/agents/reviewer/api-reviewer/identity.md +51 -0
  369. package/dist/src/agents/reviewer/api-reviewer/metadata.yaml +12 -0
  370. package/dist/src/agents/reviewer/api-reviewer/output.md +343 -0
  371. package/dist/src/agents/reviewer/api-reviewer/playbook.md +288 -0
  372. package/dist/src/agents/reviewer/cli-reviewer/critical-reminders.md +33 -0
  373. package/dist/src/agents/reviewer/cli-reviewer/critical-requirements.md +30 -0
  374. package/dist/src/agents/reviewer/cli-reviewer/identity.md +44 -0
  375. package/dist/src/agents/reviewer/cli-reviewer/metadata.yaml +12 -0
  376. package/dist/src/agents/reviewer/cli-reviewer/output.md +414 -0
  377. package/dist/src/agents/reviewer/cli-reviewer/playbook.md +218 -0
  378. package/dist/src/agents/reviewer/infra-reviewer/critical-reminders.md +38 -0
  379. package/dist/src/agents/reviewer/infra-reviewer/critical-requirements.md +38 -0
  380. package/dist/src/agents/reviewer/infra-reviewer/identity.md +53 -0
  381. package/dist/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
  382. package/dist/src/agents/reviewer/infra-reviewer/output.md +364 -0
  383. package/dist/src/agents/reviewer/infra-reviewer/playbook.md +161 -0
  384. package/dist/src/agents/reviewer/web-reviewer/critical-reminders.md +31 -0
  385. package/dist/src/agents/reviewer/web-reviewer/critical-requirements.md +26 -0
  386. package/dist/src/agents/reviewer/web-reviewer/identity.md +40 -0
  387. package/dist/src/agents/reviewer/web-reviewer/metadata.yaml +12 -0
  388. package/dist/src/agents/reviewer/web-reviewer/output.md +333 -0
  389. package/dist/src/agents/reviewer/web-reviewer/playbook.md +156 -0
  390. package/dist/src/agents/tester/api-tester/critical-reminders.md +41 -0
  391. package/dist/src/agents/tester/api-tester/critical-requirements.md +41 -0
  392. package/dist/src/agents/tester/api-tester/identity.md +47 -0
  393. package/dist/src/agents/tester/api-tester/metadata.yaml +12 -0
  394. package/dist/src/agents/tester/api-tester/output.md +284 -0
  395. package/dist/src/agents/tester/api-tester/playbook.md +275 -0
  396. package/dist/src/agents/tester/cli-tester/critical-reminders.md +36 -0
  397. package/dist/src/agents/tester/cli-tester/critical-requirements.md +36 -0
  398. package/dist/src/agents/tester/cli-tester/identity.md +43 -0
  399. package/dist/src/agents/tester/cli-tester/metadata.yaml +12 -0
  400. package/dist/src/agents/tester/cli-tester/output.md +313 -0
  401. package/dist/src/agents/tester/cli-tester/playbook.md +221 -0
  402. package/dist/src/agents/tester/web-tester/critical-reminders.md +31 -0
  403. package/dist/src/agents/tester/web-tester/critical-requirements.md +28 -0
  404. package/dist/src/agents/tester/web-tester/identity.md +41 -0
  405. package/dist/src/agents/tester/web-tester/metadata.yaml +12 -0
  406. package/dist/src/agents/tester/web-tester/output.md +321 -0
  407. package/dist/src/agents/tester/web-tester/playbook.md +428 -0
  408. package/dist/stores/d227-same-scope-tombstone-duplicate.test.js +118 -0
  409. package/dist/stores/d227-same-scope-tombstone-duplicate.test.js.map +1 -0
  410. package/dist/stores/wizard-store.js +21 -0
  411. package/dist/stores/wizard-store.js.map +1 -0
  412. package/dist/stores/wizard-store.test.js +3053 -0
  413. package/dist/stores/wizard-store.test.js.map +1 -0
  414. package/package.json +130 -12
  415. package/src/agents/_templates/agent.liquid +161 -0
  416. package/src/agents/_templates/methodologies/anti-over-engineering.liquid +121 -0
  417. package/src/agents/_templates/methodologies/context-management.liquid +162 -0
  418. package/src/agents/_templates/methodologies/improvement-protocol.liquid +150 -0
  419. package/src/agents/_templates/methodologies/investigation-requirements.liquid +49 -0
  420. package/src/agents/_templates/methodologies/success-criteria.liquid +111 -0
  421. package/src/agents/_templates/methodologies/write-verification.liquid +43 -0
  422. package/src/agents/developer/ai-developer/critical-reminders.md +54 -0
  423. package/src/agents/developer/ai-developer/critical-requirements.md +59 -0
  424. package/src/agents/developer/ai-developer/identity.md +51 -0
  425. package/src/agents/developer/ai-developer/metadata.yaml +12 -0
  426. package/src/agents/developer/ai-developer/output.md +366 -0
  427. package/src/agents/developer/ai-developer/playbook.md +335 -0
  428. package/src/agents/developer/api-developer/critical-reminders.md +46 -0
  429. package/src/agents/developer/api-developer/critical-requirements.md +44 -0
  430. package/src/agents/developer/api-developer/identity.md +49 -0
  431. package/src/agents/developer/api-developer/metadata.yaml +12 -0
  432. package/src/agents/developer/api-developer/output.md +432 -0
  433. package/src/agents/developer/api-developer/playbook.md +352 -0
  434. package/src/agents/developer/cli-developer/critical-reminders.md +51 -0
  435. package/src/agents/developer/cli-developer/critical-requirements.md +51 -0
  436. package/src/agents/developer/cli-developer/identity.md +51 -0
  437. package/src/agents/developer/cli-developer/metadata.yaml +12 -0
  438. package/src/agents/developer/cli-developer/output.md +285 -0
  439. package/src/agents/developer/cli-developer/playbook.md +386 -0
  440. package/src/agents/developer/web-architecture/critical-reminders.md +48 -0
  441. package/src/agents/developer/web-architecture/critical-requirements.md +65 -0
  442. package/src/agents/developer/web-architecture/identity.md +64 -0
  443. package/src/agents/developer/web-architecture/metadata.yaml +12 -0
  444. package/src/agents/developer/web-architecture/output.md +449 -0
  445. package/src/agents/developer/web-architecture/playbook.md +481 -0
  446. package/src/agents/developer/web-developer/critical-reminders.md +40 -0
  447. package/src/agents/developer/web-developer/critical-requirements.md +39 -0
  448. package/src/agents/developer/web-developer/identity.md +32 -0
  449. package/src/agents/developer/web-developer/metadata.yaml +12 -0
  450. package/src/agents/developer/web-developer/output.md +323 -0
  451. package/src/agents/developer/web-developer/playbook.md +349 -0
  452. package/src/agents/meta/agent-summoner/critical-reminders.md +45 -0
  453. package/src/agents/meta/agent-summoner/critical-requirements.md +52 -0
  454. package/src/agents/meta/agent-summoner/identity.md +34 -0
  455. package/src/agents/meta/agent-summoner/metadata.yaml +12 -0
  456. package/src/agents/meta/agent-summoner/output.md +296 -0
  457. package/src/agents/meta/agent-summoner/playbook.md +1469 -0
  458. package/src/agents/meta/codex-keeper/critical-reminders.md +39 -0
  459. package/src/agents/meta/codex-keeper/critical-requirements.md +29 -0
  460. package/src/agents/meta/codex-keeper/identity.md +45 -0
  461. package/src/agents/meta/codex-keeper/metadata.yaml +12 -0
  462. package/src/agents/meta/codex-keeper/output.md +384 -0
  463. package/src/agents/meta/codex-keeper/playbook.md +1183 -0
  464. package/src/agents/meta/convention-keeper/critical-reminders.md +32 -0
  465. package/src/agents/meta/convention-keeper/critical-requirements.md +32 -0
  466. package/src/agents/meta/convention-keeper/identity.md +33 -0
  467. package/src/agents/meta/convention-keeper/metadata.yaml +12 -0
  468. package/src/agents/meta/convention-keeper/output.md +206 -0
  469. package/src/agents/meta/convention-keeper/playbook.md +180 -0
  470. package/src/agents/meta/skill-summoner/critical-reminders.md +112 -0
  471. package/src/agents/meta/skill-summoner/critical-requirements.md +62 -0
  472. package/src/agents/meta/skill-summoner/identity.md +31 -0
  473. package/src/agents/meta/skill-summoner/metadata.yaml +13 -0
  474. package/src/agents/meta/skill-summoner/output.md +390 -0
  475. package/src/agents/meta/skill-summoner/playbook.md +1457 -0
  476. package/src/agents/pattern/pattern-scout/critical-reminders.md +71 -0
  477. package/src/agents/pattern/pattern-scout/critical-requirements.md +31 -0
  478. package/src/agents/pattern/pattern-scout/identity.md +25 -0
  479. package/src/agents/pattern/pattern-scout/metadata.yaml +10 -0
  480. package/src/agents/pattern/pattern-scout/output.md +290 -0
  481. package/src/agents/pattern/pattern-scout/playbook.md +1806 -0
  482. package/src/agents/pattern/web-pattern-critique/critical-reminders.md +30 -0
  483. package/src/agents/pattern/web-pattern-critique/critical-requirements.md +28 -0
  484. package/src/agents/pattern/web-pattern-critique/identity.md +41 -0
  485. package/src/agents/pattern/web-pattern-critique/metadata.yaml +12 -0
  486. package/src/agents/pattern/web-pattern-critique/output.md +314 -0
  487. package/src/agents/pattern/web-pattern-critique/playbook.md +572 -0
  488. package/src/agents/planning/api-pm/critical-reminders.md +48 -0
  489. package/src/agents/planning/api-pm/critical-requirements.md +41 -0
  490. package/src/agents/planning/api-pm/identity.md +39 -0
  491. package/src/agents/planning/api-pm/metadata.yaml +12 -0
  492. package/src/agents/planning/api-pm/output.md +475 -0
  493. package/src/agents/planning/api-pm/playbook.md +129 -0
  494. package/src/agents/planning/web-pm/critical-reminders.md +36 -0
  495. package/src/agents/planning/web-pm/critical-requirements.md +32 -0
  496. package/src/agents/planning/web-pm/identity.md +26 -0
  497. package/src/agents/planning/web-pm/metadata.yaml +12 -0
  498. package/src/agents/planning/web-pm/output.md +314 -0
  499. package/src/agents/planning/web-pm/playbook.md +318 -0
  500. package/src/agents/researcher/api-researcher/critical-reminders.md +27 -0
  501. package/src/agents/researcher/api-researcher/critical-requirements.md +28 -0
  502. package/src/agents/researcher/api-researcher/identity.md +71 -0
  503. package/src/agents/researcher/api-researcher/metadata.yaml +10 -0
  504. package/src/agents/researcher/api-researcher/output.md +254 -0
  505. package/src/agents/researcher/api-researcher/playbook.md +201 -0
  506. package/src/agents/researcher/web-researcher/critical-reminders.md +39 -0
  507. package/src/agents/researcher/web-researcher/critical-requirements.md +26 -0
  508. package/src/agents/researcher/web-researcher/identity.md +69 -0
  509. package/src/agents/researcher/web-researcher/metadata.yaml +10 -0
  510. package/src/agents/researcher/web-researcher/output.md +241 -0
  511. package/src/agents/researcher/web-researcher/playbook.md +217 -0
  512. package/src/agents/reviewer/ai-reviewer/critical-reminders.md +40 -0
  513. package/src/agents/reviewer/ai-reviewer/critical-requirements.md +37 -0
  514. package/src/agents/reviewer/ai-reviewer/identity.md +51 -0
  515. package/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
  516. package/src/agents/reviewer/ai-reviewer/output.md +395 -0
  517. package/src/agents/reviewer/ai-reviewer/playbook.md +90 -0
  518. package/src/agents/reviewer/api-reviewer/critical-reminders.md +31 -0
  519. package/src/agents/reviewer/api-reviewer/critical-requirements.md +27 -0
  520. package/src/agents/reviewer/api-reviewer/identity.md +51 -0
  521. package/src/agents/reviewer/api-reviewer/metadata.yaml +12 -0
  522. package/src/agents/reviewer/api-reviewer/output.md +343 -0
  523. package/src/agents/reviewer/api-reviewer/playbook.md +288 -0
  524. package/src/agents/reviewer/cli-reviewer/critical-reminders.md +33 -0
  525. package/src/agents/reviewer/cli-reviewer/critical-requirements.md +30 -0
  526. package/src/agents/reviewer/cli-reviewer/identity.md +44 -0
  527. package/src/agents/reviewer/cli-reviewer/metadata.yaml +12 -0
  528. package/src/agents/reviewer/cli-reviewer/output.md +414 -0
  529. package/src/agents/reviewer/cli-reviewer/playbook.md +218 -0
  530. package/src/agents/reviewer/infra-reviewer/critical-reminders.md +38 -0
  531. package/src/agents/reviewer/infra-reviewer/critical-requirements.md +38 -0
  532. package/src/agents/reviewer/infra-reviewer/identity.md +53 -0
  533. package/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
  534. package/src/agents/reviewer/infra-reviewer/output.md +364 -0
  535. package/src/agents/reviewer/infra-reviewer/playbook.md +161 -0
  536. package/src/agents/reviewer/web-reviewer/critical-reminders.md +31 -0
  537. package/src/agents/reviewer/web-reviewer/critical-requirements.md +26 -0
  538. package/src/agents/reviewer/web-reviewer/identity.md +40 -0
  539. package/src/agents/reviewer/web-reviewer/metadata.yaml +12 -0
  540. package/src/agents/reviewer/web-reviewer/output.md +333 -0
  541. package/src/agents/reviewer/web-reviewer/playbook.md +156 -0
  542. package/src/agents/tester/api-tester/critical-reminders.md +41 -0
  543. package/src/agents/tester/api-tester/critical-requirements.md +41 -0
  544. package/src/agents/tester/api-tester/identity.md +47 -0
  545. package/src/agents/tester/api-tester/metadata.yaml +12 -0
  546. package/src/agents/tester/api-tester/output.md +284 -0
  547. package/src/agents/tester/api-tester/playbook.md +275 -0
  548. package/src/agents/tester/cli-tester/critical-reminders.md +36 -0
  549. package/src/agents/tester/cli-tester/critical-requirements.md +36 -0
  550. package/src/agents/tester/cli-tester/identity.md +43 -0
  551. package/src/agents/tester/cli-tester/metadata.yaml +12 -0
  552. package/src/agents/tester/cli-tester/output.md +313 -0
  553. package/src/agents/tester/cli-tester/playbook.md +221 -0
  554. package/src/agents/tester/web-tester/critical-reminders.md +31 -0
  555. package/src/agents/tester/web-tester/critical-requirements.md +28 -0
  556. package/src/agents/tester/web-tester/identity.md +41 -0
  557. package/src/agents/tester/web-tester/metadata.yaml +12 -0
  558. package/src/agents/tester/web-tester/output.md +321 -0
  559. package/src/agents/tester/web-tester/playbook.md +428 -0
  560. package/src/schemas/agent-frontmatter.schema.json +88 -0
  561. package/src/schemas/agent.schema.json +103 -0
  562. package/src/schemas/custom-metadata.schema.json +74 -0
  563. package/src/schemas/hooks.schema.json +47 -0
  564. package/src/schemas/marketplace.schema.json +119 -0
  565. package/src/schemas/metadata.schema.json +387 -0
  566. package/src/schemas/plugin.schema.json +127 -0
  567. package/src/schemas/project-config.schema.json +189 -0
  568. package/src/schemas/project-source-config.schema.json +96 -0
  569. package/src/schemas/skill-frontmatter.schema.json +42 -0
  570. package/src/schemas/stack.schema.json +191 -0
  571. package/src/schemas/stacks.schema.json +107 -0
  572. package/bin/run.js +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/stores/wizard-store.ts","../src/cli/lib/wizard/index.ts","../src/cli/lib/wizard/build-step-logic.ts","../src/cli/lib/wizard/scope-diff.ts","../src/cli/lib/wizard/domain-order.ts"],"sourcesContent":["import { flatMap } from \"remeda\";\nimport { create } from \"zustand\";\nimport { DEFAULT_PUBLIC_SOURCE_NAME, EJECT_SOURCE, FALLBACK_DOMAIN } from \"../consts.js\";\nimport type { InstallMode } from \"../lib/installation/index.js\";\nimport { deriveInstallMode as sharedDeriveInstallMode } from \"../lib/installation/installation.js\";\nimport type { AgentScopeConfig, SkillConfig, SkillScope } from \"../types/config.js\";\nimport {\n isActiveAt,\n isGlobalTombstone,\n isProjectOwned,\n} from \"../lib/configuration/scope-predicates.js\";\nimport { matrix, getSkillById, getCategoryDomain } from \"../lib/matrix/matrix-provider.js\";\nimport {\n buildCategoriesForDomain,\n isCompatibleWithSelectedFrameworks,\n FRAMEWORK_CATEGORY_ID,\n orderDomains,\n skillSlotKey,\n} from \"../lib/wizard/index.js\";\nimport type {\n AgentName,\n BoundSkill,\n Domain,\n DomainSelections,\n SkillAlias,\n SkillId,\n SkillSource,\n Category,\n CategorySelections,\n ResolvedSkill,\n} from \"../types/index.js\";\nimport type { SourceOption, SourceRow } from \"../components/wizard/source-grid.js\";\nimport { warn } from \"../utils/logger.js\";\nimport { typedEntries, typedFromEntries, typedKeys, typedValues } from \"../utils/typed-object.js\";\n\n/** Toast strings surfaced by scope/selection guards (E2E asserts these verbatim). */\nconst TOAST_MESSAGES = {\n GLOBAL_SKILLS_LOCKED: \"Global skills cannot be changed from project scope\",\n ONLY_SKILL_IN_CATEGORY: \"Cannot deselect the only skill in this category\",\n ALREADY_EJECTED_AT_GLOBAL: \"Already exists as ejected skill at global scope\",\n GLOBAL_AGENTS_LOCKED: \"Global agents cannot be changed from project scope\",\n} as const;\n\n/** First defined source among candidates, else the default public source. */\nfunction resolveEffectiveSource(...candidates: Array<string | undefined>): string {\n return candidates.find((source) => source !== undefined) ?? DEFAULT_PUBLIC_SOURCE_NAME;\n}\n\n/** Name of a skill's primary available source, if any. */\nfunction primarySourceName(skill: ResolvedSkill | undefined): string | undefined {\n return skill?.availableSources?.find((s) => s.primary)?.name;\n}\n\nfunction createDefaultSkillConfig(id: SkillId): SkillConfig {\n const skill = matrix.skills[id];\n const primarySource = primarySourceName(skill);\n return { id, scope: \"global\", source: primarySource ?? DEFAULT_PUBLIC_SOURCE_NAME };\n}\n\n/** Finds framework-incompatible skill IDs in web domain selections, excluding already-excluded skills. */\nfunction findIncompatibleWebSkills(\n webSelections: CategorySelections,\n skillConfigs: SkillConfig[],\n): Set<SkillId> {\n const frameworkSelections = webSelections[FRAMEWORK_CATEGORY_ID] ?? [];\n if (frameworkSelections.length === 0) return new Set();\n\n const excludedIds = new Set(skillConfigs.filter((s) => s.excluded).map((s) => s.id));\n const selectedFrameworkIds = frameworkSelections.map((alias) => getSkillById(alias).id);\n\n return new Set(\n flatMap(typedEntries(webSelections), ([cat, skills]) =>\n cat === FRAMEWORK_CATEGORY_ID || !skills\n ? []\n : skills.filter(\n (id) =>\n !excludedIds.has(id) && !isCompatibleWithSelectedFrameworks(id, selectedFrameworkIds),\n ),\n ),\n );\n}\n\n/** Returns selections with the given skill IDs removed from all categories. */\nfunction removeSkillsFromSelections(\n selections: CategorySelections,\n toRemove: Set<SkillId>,\n): CategorySelections {\n return typedFromEntries(\n typedEntries(selections).map(([cat, skills]): [Category, SkillId[]] => [\n cat,\n skills?.filter((id) => !toRemove.has(id)) ?? [],\n ]),\n );\n}\n\n/** True when configs hold an active (non-excluded) project-scope entry for the id. */\nfunction hasProjectActive(configs: SkillConfig[], id: SkillId): boolean {\n return configs.some((sc) => sc.id === id && isActiveAt(sc, \"project\"));\n}\n\n/** The active (non-excluded) global-scope entry for the id, when configs hold one. */\nfunction findGlobalActive(configs: SkillConfig[], id: SkillId): SkillConfig | undefined {\n return configs.find((sc) => sc.id === id && isActiveAt(sc, \"global\"));\n}\n\n/** True when configs hold an active (non-excluded) global-scope entry for the id. */\nfunction hasGlobalActive(configs: SkillConfig[], id: SkillId): boolean {\n return findGlobalActive(configs, id) !== undefined;\n}\n\n/** True when configs hold an excluded global-scope tombstone for the id. */\nfunction hasGlobalTombstone(configs: SkillConfig[], id: SkillId): boolean {\n return configs.some((sc) => sc.id === id && isGlobalTombstone(sc));\n}\n\n/**\n * D-233 Scenario B: a dual-scope pair — an active project entry plus a global tombstone for\n * the same skill. The shape the `[P][G]` row renders from; removal collapses it to a single\n * inherited-global entry, re-selection rebuilds it.\n */\nfunction isDualScopePair(configs: SkillConfig[], id: SkillId): boolean {\n return hasProjectActive(configs, id) && hasGlobalTombstone(configs, id);\n}\n\n/**\n * True when a SELECTED skill must not be deselected (or radio-swapped away) at project scope.\n * Three arms: an active global entry in the hydration snapshot (genuinely global-only — the\n * long-standing read-only behaviour); a snapshot tombstone paired with a LIVE plain active\n * global entry (the stale state a persisted `[P][G]` reaches after an in-session collapse,\n * whose deselect would silently tombstone the still-real global install); and a live `[P][G]`\n * dual-scope pair, which only `s` may collapse or restore. A skill freshly added this session\n * (absent from the snapshot) matches none of the arms and stays freely deselectable.\n */\nfunction isGloballyLockedSkill(\n installed: SkillConfig[],\n liveConfigs: SkillConfig[],\n id: SkillId,\n): boolean {\n return (\n hasGlobalActive(installed, id) ||\n (hasGlobalTombstone(installed, id) && hasGlobalActive(liveConfigs, id)) ||\n isDualScopePair(liveConfigs, id)\n );\n}\n\n/**\n * True when re-scoping this project-eject entry to global would overwrite an ejected global\n * install that the live config does not already override with a tombstone.\n */\nfunction wouldOverwriteGlobalEject(\n config: SkillConfig,\n liveConfigs: SkillConfig[],\n installedSkillConfigs: SkillConfig[] | null,\n): boolean {\n if (config.scope !== \"project\" || config.source !== EJECT_SOURCE) return false;\n const globalEjectInstalled = installedSkillConfigs?.some(\n (sc) =>\n sc.id === config.id && sc.scope === \"global\" && sc.source === EJECT_SOURCE && !sc.excluded,\n );\n if (!globalEjectInstalled) return false;\n return !liveConfigs.some((sc) => sc.id === config.id && sc.excluded);\n}\n\n/**\n * Rewrites the source of the ACTIVE entry at (id, scope), leaving every other entry untouched —\n * in particular a dual-scope skill's excluded global tombstone, which keeps describing the\n * masked global install (D-262).\n */\nfunction withActiveEntrySource(\n configs: SkillConfig[],\n id: SkillId,\n scope: SkillScope | undefined,\n source: string,\n): SkillConfig[] {\n return configs.map((sc) =>\n sc.id === id && !sc.excluded && sc.scope === scope ? { ...sc, source } : sc,\n );\n}\n\n/**\n * Removes deselected skills, honouring what the project is allowed to remove (D-277).\n *\n * An entry the project OWNS — project-scoped, or the project's own global tombstone — is\n * dropped. An entry the project merely INHERITS (an active global-scope entry the hydration\n * snapshot already carried) is immutable from project scope and survives BYTE-IDENTICAL: a\n * project edit neither uninstalls a global install nor mints a tombstone for it. A skill this\n * session added itself is absent from the snapshot, is nobody's install yet, and is dropped\n * like any other so an accidental add stays undoable.\n *\n * `installedSkillConfigs` is `null` when editing FROM global scope, where the config being\n * edited IS the global one: nothing is inherited, so every removal is a genuine uninstall\n * (D-233 Scenario C).\n *\n * Dual-scope entries (an active project entry paired with a global tombstone) collapse to a\n * single inherited-global entry so the `[G]` badge keeps rendering after the project half is\n * dropped (D-233 Scenario B).\n */\nfunction applySkillRemoval(\n configs: SkillConfig[],\n removedIds: Iterable<SkillId>,\n installedSkillConfigs: SkillConfig[] | null,\n): SkillConfig[] {\n const removed = removedIds instanceof Set ? removedIds : new Set(removedIds);\n const installedIds = new Set((installedSkillConfigs ?? []).map((s) => s.id));\n\n /**\n * A removed entry the project may not drop: a global install that existed before this session\n * and that the project does not own. Dual-scope pairs are excluded — both their halves go, and\n * the surviving global install is re-surfaced as a single inherited entry below.\n */\n const survivesRemoval = (entry: SkillConfig): boolean =>\n !isDualScopePair(configs, entry.id) && !isProjectOwned(entry) && installedIds.has(entry.id);\n\n const retained = configs.filter((sc) => !removed.has(sc.id) || survivesRemoval(sc));\n const resurfacedInheritedGlobals = [...removed]\n .filter((id) => isDualScopePair(configs, id))\n .map((id) => ({\n id,\n scope: \"global\" as const,\n source:\n configs.find((sc) => sc.id === id && sc.scope === \"global\")?.source ??\n DEFAULT_PUBLIC_SOURCE_NAME,\n }));\n\n return [...retained, ...resurfacedInheritedGlobals];\n}\n\n/** All skill IDs across a domain's category selections, in category order. */\nfunction flattenCategorySelections(selections: CategorySelections): SkillId[] {\n return typedValues(selections).flat();\n}\n\n/** Collects all skill IDs from a domain's category selections. */\nfunction collectSkillIdsFromSelections(selections: CategorySelections): Set<SkillId> {\n return new Set(flattenCategorySelections(selections));\n}\n\n/** Reconciles skill configs after selection changes: drops project-owned removals, leaves inherited global installs untouched, restores excluded on re-select, adds new defaults. */\nfunction reconcileSkillConfigs(\n configs: SkillConfig[],\n added: SkillId[],\n removed: SkillId[],\n installedSkillConfigs: SkillConfig[] | null,\n isEditingFromGlobalScope: boolean,\n): SkillConfig[] {\n // Editing from global scope has no project overlay, so a removal is a genuine uninstall.\n // Pass null so applySkillRemoval DROPS the skill rather than retaining it as an inherited\n // global install the project may not touch (D-233 Scenario C).\n const effectiveInstalled = isEditingFromGlobalScope ? null : installedSkillConfigs;\n let result = applySkillRemoval(configs, removed, effectiveInstalled);\n\n for (const id of added) {\n // Dual-scope restore: re-selecting a skill that is globally installed (recorded as a\n // tombstone in the project snapshot) with no current project entry re-creates BOTH a\n // fresh project entry and a global tombstone — mirroring toggleSkillScope's G->P path\n // so the row renders `[P][G]` again (D-233 Scenario B second spacebar).\n if (\n !isEditingFromGlobalScope &&\n hasGlobalTombstone(installedSkillConfigs ?? [], id) &&\n !hasProjectActive(result, id)\n ) {\n const globalEntry =\n (installedSkillConfigs ?? []).find((sc) => sc.id === id && sc.scope === \"global\") ??\n result.find((sc) => sc.id === id && sc.scope === \"global\");\n const source = globalEntry?.source ?? DEFAULT_PUBLIC_SOURCE_NAME;\n result = [\n ...result.filter((sc) => sc.id !== id),\n { id, scope: \"project\", source },\n { id, scope: \"global\", excluded: true, source },\n ];\n continue;\n }\n\n const existingExcluded = result.find((sc) => sc.id === id && sc.excluded);\n if (existingExcluded) {\n result = result.map((sc) =>\n sc.id === id && sc.excluded ? { ...sc, excluded: undefined } : sc,\n );\n } else if (!result.some((sc) => sc.id === id)) {\n // Re-selecting a skill that the hydration snapshot still holds is a RESTORE, not a fresh\n // add: it must come back with its persisted scope and source rather than the wizard\n // defaults (a project-scoped eject skill would otherwise round-trip to global+marketplace\n // and trigger a bogus scope/source migration). buildSkillConfigForId degrades to exactly\n // createDefaultSkillConfig's output when the snapshot has no entry, so genuinely-new\n // selections are unaffected.\n result = [...result, buildSkillConfigForId(id, installedSkillConfigs)];\n }\n }\n\n return result;\n}\n\n/** True when configs hold an active (non-excluded) project-scope entry for the agent. */\nfunction agentHasProjectActive(configs: AgentScopeConfig[], name: AgentName): boolean {\n return configs.some((ac) => ac.name === name && ac.scope === \"project\" && !ac.excluded);\n}\n\n/** True when configs hold an active (non-excluded) global-scope entry for the agent. */\nfunction agentHasGlobalActive(configs: AgentScopeConfig[], name: AgentName): boolean {\n return configs.some((ac) => ac.name === name && ac.scope === \"global\" && !ac.excluded);\n}\n\n/** True when configs hold an excluded global-scope tombstone for the agent. */\nfunction agentHasGlobalTombstone(configs: AgentScopeConfig[], name: AgentName): boolean {\n return configs.some((ac) => ac.name === name && ac.scope === \"global\" && ac.excluded);\n}\n\n/** Agent side of isDualScopePair (D-233): active project entry + global tombstone for the same agent. */\nfunction isDualScopeAgentPair(configs: AgentScopeConfig[], name: AgentName): boolean {\n return agentHasProjectActive(configs, name) && agentHasGlobalTombstone(configs, name);\n}\n\n/**\n * Excluded tombstone entries. Preserved across reconcile/preselect merges so a dual-scope\n * pair's tombstone half survives (D-223/D-227) and the pair can be restored later.\n */\nfunction collectTombstones<T extends { excluded?: boolean }>(configs: T[]): T[] {\n return configs.filter((entry) => entry.excluded);\n}\n\n/**\n * Applies an agent toggle: deselect removes the agent's entries; select restores an excluded\n * entry or adds a new one.\n *\n * A deselect never masks a globally-installed agent (D-277). Every reachable deselect here is\n * one the project owns — an active global install and a live `[P][G]` pair are both refused\n * upstream in `toggleAgent`, and a global-scope edit owns everything it can see — so the only\n * correct outcome is a clean removal.\n */\nfunction applyAgentToggle(\n configs: AgentScopeConfig[],\n agent: AgentName,\n isSelected: boolean,\n): AgentScopeConfig[] {\n if (isSelected) {\n return configs.filter((ac) => ac.name !== agent);\n }\n\n const existingExcluded = configs.find((ac) => ac.name === agent && ac.excluded);\n if (existingExcluded) {\n return configs.map((ac) =>\n ac.name === agent && ac.excluded ? { ...ac, excluded: undefined } : ac,\n );\n }\n return [...configs, { name: agent, scope: \"global\" as const }];\n}\n\n/**\n * True when an existing agent entry must outlive a domain-roster rebuild, which merges rather than\n * replaces. Two kinds survive:\n *\n * - ALL excluded tombstones, so a dual-scope pair (active entry plus a tombstone at the other\n * scope) survives preselection — the agent-side mirror of the D-223 fix in\n * `populateFromSkillIds`. Deliberately NOT filtered by roster membership (D-227).\n * - Every entry the project does not own, so a globally-installed agent outside the selected\n * domains' roster is never silently uninstalled by a project edit (D-277).\n *\n * Entries the roster itself rebuilds are excluded — `buildAgentConfigForName` re-derives those.\n */\nfunction survivesRosterRebuild(\n agentConfig: AgentScopeConfig,\n roster: ReadonlySet<AgentName>,\n): boolean {\n if (agentConfig.excluded) return true;\n return !isProjectOwned(agentConfig) && !roster.has(agentConfig.name);\n}\n\n/**\n * D-233: restores the `[P][G]` pair when re-selecting an inherited-global agent row whose\n * global install is recorded as a tombstone in the project snapshot — mirrors\n * reconcileSkillConfigs' restore branch.\n */\nfunction restoreDualScopeAgent(\n selectedAgents: AgentName[],\n agentConfigs: AgentScopeConfig[],\n agent: AgentName,\n) {\n return {\n selectedAgents: [...selectedAgents, agent],\n agentConfigs: [\n ...agentConfigs.filter((ac) => ac.name !== agent),\n { name: agent, scope: \"project\" as const },\n { name: agent, scope: \"global\" as const, excluded: true },\n ],\n };\n}\n\n/**\n * Next selectedAgents after a toggle. A deselect drops the agent; re-enabling a tombstoned\n * agent is already listed; a fresh add appends.\n */\nfunction nextSelectedAgents(\n selectedAgents: AgentName[],\n agent: AgentName,\n flags: { isSelected: boolean; isInList: boolean },\n): AgentName[] {\n if (flags.isSelected) return selectedAgents.filter((a) => a !== agent);\n if (flags.isInList) return selectedAgents;\n return [...selectedAgents, agent];\n}\n\n/** Builds a SkillConfig for a resolved skill ID, preferring saved config values. */\nfunction buildSkillConfigForId(id: SkillId, savedConfigs?: SkillConfig[] | null): SkillConfig {\n // Prefer project-scoped entry over global when duplicates exist (D-198 defensive fix)\n const saved =\n savedConfigs?.find((sc) => sc.id === id && !sc.excluded && sc.scope === \"project\") ??\n savedConfigs?.find((sc) => sc.id === id && !sc.excluded);\n const skill = matrix.skills[id];\n const primarySource = primarySourceName(skill);\n return {\n id,\n scope: saved?.scope ?? \"global\",\n source: resolveEffectiveSource(saved?.source, primarySource),\n };\n}\n\n/**\n * Builds an active AgentScopeConfig for a name, preferring a saved project-scoped\n * active entry. Mirrors buildSkillConfigForId on the agent path so preselection can\n * separate active-entry construction from tombstone preservation (D-227).\n */\nfunction buildAgentConfigForName(\n name: AgentName,\n savedConfigs?: AgentScopeConfig[],\n): AgentScopeConfig {\n // Prefer project-scoped active entry over global when duplicates exist.\n const saved =\n savedConfigs?.find((ac) => ac.name === name && !ac.excluded && ac.scope === \"project\") ??\n savedConfigs?.find((ac) => ac.name === name && !ac.excluded);\n return {\n name,\n scope: saved?.scope ?? \"global\",\n // Model and effort are the user's deliberate choice, not something the roster re-derives —\n // they survive the rebuild on the same terms as scope.\n ...(saved?.model !== undefined && { model: saved.model }),\n ...(saved?.effort !== undefined && { effort: saved.effort }),\n };\n}\n\n/** Restores skill configs for a domain: clears excluded flags on restored skills, adds new defaults for unknown skills. */\nfunction restoreSkillConfigs(\n existingConfigs: SkillConfig[],\n restoredIds: SkillId[],\n): SkillConfig[] {\n const restoredSet = new Set(restoredIds);\n const existingIds = new Set(existingConfigs.map((sc) => sc.id));\n\n const updated = existingConfigs.map((sc) =>\n restoredSet.has(sc.id) && sc.excluded ? { ...sc, excluded: undefined } : sc,\n );\n\n const newConfigs = restoredIds.filter((id) => !existingIds.has(id)).map(createDefaultSkillConfig);\n\n return [...updated, ...newConfigs];\n}\n\n/** Built-in agent names grouped by domain prefix. Custom domains return no preselected agents. */\nconst DOMAIN_AGENTS: Partial<Record<Domain, AgentName[]>> = {\n web: [\n \"web-developer\",\n \"web-reviewer\",\n \"web-researcher\",\n \"web-tester\",\n \"web-pm\",\n \"web-architecture\",\n ],\n api: [\"api-developer\", \"api-reviewer\", \"api-researcher\"],\n cli: [\"cli-developer\", \"cli-tester\", \"cli-reviewer\"],\n};\n\n/**\n * Fixed source sort tiers (lower = higher priority):\n * 1 = eject/global (installed on disk -- type \"eject\" or installed via plugin)\n * 2 = scoped marketplace (primary source from --source flag)\n * 3 = default public marketplace (Agents Inc)\n * 4 = third-party marketplaces (extra configured sources)\n */\nconst SOURCE_SORT_TIER_LOCAL = 1;\nconst SOURCE_SORT_TIER_SCOPED = 2;\nconst SOURCE_SORT_TIER_PUBLIC = 3;\nconst SOURCE_SORT_TIER_THIRD_PARTY = 4;\n\nfunction getSourceSortTier(source: SkillSource): number {\n if (source.type === \"local\") return SOURCE_SORT_TIER_LOCAL;\n if (source.primary) return SOURCE_SORT_TIER_SCOPED;\n if (source.type === \"public\") return SOURCE_SORT_TIER_PUBLIC;\n return SOURCE_SORT_TIER_THIRD_PARTY;\n}\n\nfunction resolveSkillForPopulation(\n skillId: SkillId,\n): { domain: Domain; subcat: Category; techId: SkillId } | null {\n const { skills } = matrix;\n const skill = skills[skillId];\n if (!skill?.category) {\n warn(\n `Installed skill '${skillId}' is missing from the marketplace — it may have been removed or renamed`,\n );\n return null;\n }\n\n const domain = getCategoryDomain(skill.category);\n if (!domain) {\n warn(`Installed skill '${skillId}' has unknown category '${skill.category}' — skipping`);\n return null;\n }\n\n // Boundary cast: domain lookup confirmed category exists in matrix\n const subcat = skill.category as Category;\n return { domain, subcat, techId: skillId };\n}\n\n/** Adds a skill to selections[domain][category] if absent; true when newly added. */\nfunction addToDomainSelections(\n selections: DomainSelections,\n domain: Domain,\n category: Category,\n skillId: SkillId,\n): boolean {\n const categorySelections = (selections[domain] ??= {});\n const skillList = (categorySelections[category] ??= []);\n if (skillList.includes(skillId)) return false;\n skillList.push(skillId);\n return true;\n}\n\nfunction buildBoundSkillOptions(\n boundSkills: BoundSkill[],\n alias: SkillAlias,\n selectedSource: string,\n): SourceOption[] {\n return boundSkills\n .filter((b) => b.boundTo === alias)\n .map((bound) => ({\n id: bound.sourceName,\n selected: selectedSource === bound.sourceName,\n installed: false,\n }));\n}\n\n/** All source options for one skill: eject first, sorted sources (or the public default), then bound skills. */\nfunction buildSkillSourceOptions(\n skill: ResolvedSkill,\n selectedSource: string,\n boundSkills: BoundSkill[],\n): SourceOption[] {\n const sortedSources = [...(skill.availableSources || [])].sort(\n (a, b) => getSourceSortTier(a) - getSourceSortTier(b),\n );\n const baseOptions: SourceOption[] =\n sortedSources.length > 0\n ? sortedSources.map((source) => ({\n id: source.name,\n selected: selectedSource === source.name,\n installed: source.installed,\n }))\n : [\n {\n id: DEFAULT_PUBLIC_SOURCE_NAME,\n selected: selectedSource === DEFAULT_PUBLIC_SOURCE_NAME,\n installed: false,\n },\n ];\n const withEject = baseOptions.some((o) => o.id === EJECT_SOURCE)\n ? baseOptions\n : [\n { id: EJECT_SOURCE, selected: selectedSource === EJECT_SOURCE, installed: false },\n ...baseOptions,\n ];\n return [...withEject, ...buildBoundSkillOptions(boundSkills, skill.slug, selectedSource)];\n}\n\n/**\n * D-257: the snapshot slots this session has emptied — an `(id, scope)` the hydration snapshot\n * holds ACTIVE that no live config entry occupies any more. The emptying leaves nothing behind to\n * render from: a PROJECT skill is dropped outright (applySkillRemoval leaves no tombstone, unlike\n * the global case), and so is ANY skill deselected while editing from global scope, where\n * `reconcileSkillConfigs` passes `null` so `applySkillRemoval` drops rather than tombstones. In\n * both the snapshot is the only surviving record, so without this set the row would vanish and the\n * user would lose sight of what saving is about to remove. Deliberately ungated on edit context:\n * `computeScopeDiff`, which the confirm step classifies removals with, has no global-scope gate\n * either, so neither surface may have one.\n *\n * Keyed per `(id, scope)` SLOT, mirroring `computeScopeDiff`'s removal match (D-271) — removal is a\n * property of the slot, not of the id. Collapsing a dual-scope `[P][G]` pair to `[G]` empties the\n * PROJECT slot while the global one survives, so the skill renders twice on BOTH surfaces (`-` at\n * Project, `•`/lock at Global) instead of the survivor masking the loss. A tombstone OCCUPIES its\n * slot, so re-activating a masked global install is never a removal. Selection is not consulted:\n * `skillConfigs` is the same input the confirm step diffs, which is what keeps the two agreeing.\n *\n * Snapshot TOMBSTONES are deliberately not removal candidates — narrower than `computeScopeDiff`,\n * whose removal filter counts them. A tombstone is a MASK over a global install, not an install of\n * its own: dropping it deletes nothing (the global copy survives), so a red pending-removal row for\n * one would announce a deletion that never happens. No store transition reaches that shape anyway —\n * every path that drops a tombstone fills the same slot with an active entry (`toggleSkillScope`\n * P→G, `applySkillRemoval`'s dual-scope collapse).\n */\nfunction collectRemovedInstalledEntries(\n installedSkillConfigs: SkillConfig[] | null,\n skillConfigs: SkillConfig[],\n): SkillConfig[] {\n if (!installedSkillConfigs) return [];\n const occupiedSlots = new Set(skillConfigs.map((sc) => skillSlotKey(sc.id, sc.scope)));\n return installedSkillConfigs.filter(\n (sc) =>\n !sc.excluded &&\n !occupiedSlots.has(skillSlotKey(sc.id, sc.scope)) &&\n // A skill the marketplace no longer carries has nothing to render — hydration already\n // skipped it into unresolvableSkillIds, and getSkillById would throw on it downstream.\n !!matrix.skills[sc.id],\n );\n}\n\n/**\n * D-258: every `(id, scope)` slot the hydration snapshot occupies — the baseline a Sources row is\n * \"added\" against, and the direct counterpart of `computeScopeDiff`'s `prevSkillKeySet`. Tombstones\n * count as occupied, exactly as that set does (D-232), so re-reading a stored tombstone never flags\n * a spurious addition.\n *\n * A missing snapshot (a first `init`, nothing installed at either scope) collapses to the EMPTY set\n * rather than to a distinct \"no baseline\" state, because the two are the same answer: an empty\n * baseline occupies no slot, so every row is new — which is what `classifyDiffRow` already tells the\n * confirm step for a null baseline, and what an empty snapshot already told this surface.\n */\nfunction collectInstalledSkillSlots(\n installedSkillConfigs: SkillConfig[] | null,\n): ReadonlySet<string> {\n if (!installedSkillConfigs) return new Set();\n return new Set(installedSkillConfigs.map((sc) => skillSlotKey(sc.id, sc.scope)));\n}\n\n/**\n * D-258: the `{ added: true }` fragment for a row whose SLOT is new this session, `{}` otherwise —\n * spread into the row so the Sources tab flags it with the info panel's added-diff marker (`+`).\n * Keying on the id alone would miss a skill adopted at project scope while it stays installed\n * globally: the id is old, but the project slot is new — which is exactly how `classifyDiffRow`\n * classifies the same change on the confirm step. Never gated on `isEditingFromGlobalScope`: an\n * addition is an addition regardless of edit context.\n */\nfunction addedSlotFlag(\n installedSkillSlots: ReadonlySet<string>,\n id: SkillId,\n scope: SkillScope | undefined,\n): { added?: true } {\n return installedSkillSlots.has(skillSlotKey(id, scope)) ? {} : { added: true };\n}\n\n/** Copy of the options with exactly `sourceId` marked selected — for rows pinned to a persisted source. */\nfunction withSelectedSource(options: SourceOption[], sourceId: string | undefined): SourceOption[] {\n return options.map((option) => ({ ...option, selected: option.id === sourceId }));\n}\n\n/**\n * The per-skill inputs every source row shares: the canonical id, the live config entry driving\n * scope/lock classification, and the source options with the effective source preselected. A\n * pending-removal row re-pins that selection to its persisted source (`withSelectedSource`).\n */\nfunction resolveSkillRowInputs(\n id: SkillId,\n skillConfigs: SkillConfig[],\n boundSkills: BoundSkill[],\n): { skillId: SkillId; configEntry: SkillConfig | undefined; options: SourceOption[] } {\n const skill = getSkillById(id);\n const configEntry = skillConfigs.find((sc) => sc.id === skill.id);\n const selectedSource = resolveEffectiveSource(\n configEntry?.source,\n skill.activeSource?.name,\n primarySourceName(skill),\n );\n return {\n skillId: skill.id,\n configEntry,\n options: buildSkillSourceOptions(skill, selectedSource, boundSkills),\n };\n}\n\ntype SourceRowContext = {\n configEntry: SkillConfig | undefined;\n installedSkillConfigs: SkillConfig[] | null;\n isEditingFromGlobalScope: boolean;\n /** D-258: `(id, scope)` slots the snapshot occupies — the baseline each row's `+` derives from. */\n installedSkillSlots: ReadonlySet<string>;\n};\n\n/**\n * D-257: the inert row for a snapshot slot this session emptied. Carries the PERSISTED scope and\n * source so the row stays visible and shows what saving removes. Deliberately NOT readOnly: that\n * renders a lock, which reads as \"installed globally\" rather than \"about to be removed\". Carries no\n * added flag either — the slot it renders comes FROM the snapshot, so it can never be new this\n * session.\n */\nfunction toPendingRemovalRow(\n skillId: SkillId,\n options: SourceOption[],\n removedInstalledEntry: SkillConfig,\n): SourceRow {\n return {\n skillId,\n options: withSelectedSource(options, removedInstalledEntry.source),\n scope: removedInstalledEntry.scope,\n disabled: true,\n };\n}\n\n/**\n * True when an already-emitted row renders the snapshot entry's `(id, scope)` slot, which makes a\n * pending-removal row for it a duplicate rather than a loss.\n *\n * The one shape that reaches this: a global install adopted at project scope WITHOUT a tombstone\n * (`[G]` snapshot, `[P]` live — the historical no-tombstone dual-scope shape `computeScopeDiff`\n * calls an inherited global). Its global slot is unoccupied in the live config, yet the locked\n * global row already renders it FROM the snapshot, so the install is inherited, not removed.\n */\nfunction isSlotAlreadyRendered(rows: SourceRow[], removedInstalledEntry: SkillConfig): boolean {\n const slot = skillSlotKey(removedInstalledEntry.id, removedInstalledEntry.scope);\n return rows.some((row) => skillSlotKey(row.skillId, row.scope) === slot);\n}\n\n/**\n * The locked row for a global install this project may not change from here — the lock reads\n * \"installed globally, not yours to edit at project scope\". Its source is pinned to the installed\n * one, and its added flag derives from the GLOBAL slot, so an install the project merely inherits\n * stays a plain lock rather than reading as new.\n */\nfunction toLockedGlobalRow(\n skillId: SkillId,\n options: SourceOption[],\n installedSource: string | undefined,\n installedSkillSlots: ReadonlySet<string>,\n): SourceRow {\n return {\n skillId,\n options: withSelectedSource(options, installedSource),\n scope: \"global\" as const,\n readOnly: true,\n ...addedSlotFlag(installedSkillSlots, skillId, \"global\"),\n };\n}\n\n/**\n * Classifies one skill's LIVE config entry into its source-grid rows: a locked global row for\n * excluded-global entries, locked global + editable project rows for skills re-scoped\n * global→project this session, or a single row otherwise. Pending-removal rows are not derived\n * here — they belong to snapshot slots with no live entry left (see `toPendingRemovalRow`).\n */\nfunction classifySkillSourceRows(\n skillId: SkillId,\n options: SourceOption[],\n context: SourceRowContext,\n): SourceRow[] {\n const { configEntry, installedSkillConfigs, isEditingFromGlobalScope, installedSkillSlots } =\n context;\n const installedGlobalConfig = findGlobalActive(installedSkillConfigs ?? [], skillId);\n\n const isExcludedGlobal = configEntry?.excluded && configEntry.scope === \"global\";\n if (isExcludedGlobal && !isEditingFromGlobalScope) {\n return [\n toLockedGlobalRow(\n skillId,\n options,\n installedGlobalConfig?.source ?? configEntry.source,\n installedSkillSlots,\n ),\n ];\n }\n\n if (!isEditingFromGlobalScope && installedGlobalConfig && configEntry?.scope === \"project\") {\n // Skill toggled from global to project — emit locked global copy + editable project copy. Each\n // half derives its own added flag from its own slot, so the `+` lands on the newly occupied\n // PROJECT row while the still-installed global row stays a plain lock.\n return [\n toLockedGlobalRow(skillId, options, installedGlobalConfig.source, installedSkillSlots),\n {\n skillId,\n options,\n scope: \"project\" as const,\n ...addedSlotFlag(installedSkillSlots, skillId, \"project\"),\n },\n ];\n }\n\n const readOnly = !isEditingFromGlobalScope && !!installedGlobalConfig;\n return [\n {\n skillId,\n options,\n scope: configEntry?.scope,\n ...(readOnly ? { readOnly: true as const } : {}),\n ...addedSlotFlag(installedSkillSlots, skillId, configEntry?.scope),\n },\n ];\n}\n\n/**\n * Visual grouping order in source-grid: global readOnly, global editable, then project. A\n * pending-removal (disabled) row is NOT a separate tier — it sorts by its own scope so it renders\n * inline with the other rows of that scope, matching the info panel, which shows removals in place\n * rather than in a dedicated section. Its trailing position within a scope section falls out of the\n * removal rows being appended after every live row, which the stable sort preserves.\n */\nfunction sourceRowSortTier(row: SourceRow): number {\n if (row.scope === \"global\" && row.readOnly) return 0;\n if (row.scope === \"global\") return 1;\n return 2;\n}\n\n/**\n * Wizard step identifiers for the multi-step init/edit flow.\n *\n * Progression: stack -> domains -> build -> sources -> agents -> confirm\n * The \"stack\" step shows all stacks + \"Start from scratch\" in a unified list.\n * The \"domains\" step shows domain selection (web, api, cli, mobile, shared).\n * Navigation is tracked via the `history` stack for goBack() support.\n */\nexport type WizardStep =\n | \"stack\" // Select stack or \"Start from scratch\"\n | \"domains\" // Select domains to configure\n | \"build\" // CategoryGrid for technology selection\n | \"sources\" // Choose skill sources (recommended vs custom)\n | \"agents\" // Select which agents to compile\n | \"confirm\"; // Final confirmation\n\n/** How the user builds their config: from a pre-built stack, or skill-by-skill. */\ntype WizardApproach = \"stack\" | \"scratch\";\n\n/** For the stack approach: use the stack's defaults, or customize its skills. */\ntype StackAction = \"defaults\" | \"customize\";\n\nexport const WIZARD_STEP_ORDER = [\n \"stack\",\n \"domains\",\n \"build\",\n \"sources\",\n \"agents\",\n \"confirm\",\n] as const satisfies readonly WizardStep[];\n\n/**\n * Wizard store state and actions.\n *\n * The store uses a composition pattern: small, focused actions that each mutate\n * one or two state fields. Wizard step components compose these actions to build\n * up the full selection state incrementally (domains -> categories -> skills -> sources).\n *\n * State flow: stack/scratch selection -> domain selection -> per-domain skill\n * selection (build step) -> source customization -> agent selection -> confirmation.\n */\nexport type WizardState = {\n step: WizardStep;\n\n approach: WizardApproach | null;\n selectedStackId: string | null;\n stackAction: StackAction | null;\n\n selectedDomains: Domain[];\n\n currentDomainIndex: number;\n domainSelections: DomainSelections;\n /** Snapshot of stack-provided domain selections for restoration on domain re-toggle */\n _stackDomainSelections: DomainSelections | null;\n\n showLabels: boolean;\n filterIncompatible: boolean;\n\n skillConfigs: SkillConfig[];\n focusedSkillId: SkillId | null;\n\n /**\n * Skill ids from the saved config that could NOT be resolved against the currently-loaded\n * source matrix this session (populateFromSkillIds skipped them). The wizard cannot represent\n * these skills, so their absence from the wizard result is NOT a deselection — the merge layer\n * must preserve any existing config entry whose id is in this set, regardless of\n * authoritativeScope (D-233 Scenario C data-loss guard).\n */\n unresolvableSkillIds: SkillId[];\n\n customizeSources: boolean;\n\n showSettings: boolean;\n showInfo: boolean;\n\n selectedAgents: AgentName[];\n agentConfigs: AgentScopeConfig[];\n focusedAgentId: AgentName | null;\n\n boundSkills: BoundSkill[];\n\n /** Snapshot of configs that were installed before the wizard opened, used for diff rendering */\n installedSkillConfigs: SkillConfig[] | null;\n installedAgentConfigs: AgentScopeConfig[] | null;\n\n /** True when running init (first-time setup), false when editing an existing installation */\n isInitMode: boolean;\n\n /** When true, scope toggling is disabled (editing from ~/.claude/ with no project to move items to) */\n isEditingFromGlobalScope: boolean;\n\n /** Temporary toast message shown in the wizard (auto-cleared after timeout) */\n toastMessage: string | null;\n\n /** Global skill configs to pre-select when a stack or scratch is chosen in init. Set by use-wizard-initialization. */\n globalPreselections: SkillConfig[] | null;\n\n /** Global agent preselections to restore after selectStack wipes selectedAgents/agentConfigs. Set by use-wizard-initialization. */\n globalAgentPreselections: { agents: AgentName[]; configs: AgentScopeConfig[] } | null;\n\n history: WizardStep[];\n\n /**\n * Navigate to a wizard step, pushing the current step onto history.\n * @param step - Target step to navigate to\n *\n * Side effects: sets `step`, appends previous step to `history`\n */\n setStep: (step: WizardStep) => void;\n /**\n * Set the wizard approach (stack-based or build-from-scratch).\n * @param approach - \"stack\" to use a pre-built template, \"scratch\" to select skills manually, null to reset\n *\n * Side effects: sets `approach`\n */\n setApproach: (approach: WizardApproach | null) => void;\n /**\n * Select a stack by ID, or null to deselect.\n * @param stackId - Stack identifier from suggestedStacks, or null to clear\n *\n * Side effects: sets `selectedStackId`\n */\n selectStack: (stackId: string | null) => void;\n /**\n * Set how to apply the selected stack.\n * @param action - \"defaults\" to use stack as-is, \"customize\" to enter the build step\n *\n * Side effects: sets `stackAction`\n */\n setStackAction: (action: StackAction) => void;\n /**\n * Pre-populate domainSelections from a flat list of installed skill IDs.\n *\n * Used by `npx agents-inc edit` to restore wizard state from existing project config.\n * Looks up each skill's category and domain, warns for unresolvable skills.\n *\n * @param skillIds - Flat array of currently installed skill IDs\n * @param skills - Skill lookup providing category and displayName per skill ID\n * @param categories - Category definitions used to resolve category -> domain mapping\n *\n * Side effects: sets `domainSelections`, sets `selectedDomains` to domains found in the provided skill IDs\n */\n populateFromSkillIds: (skillIds: SkillId[], savedConfigs?: SkillConfig[]) => void;\n /**\n * Toggle a domain on or off in the selectedDomains list.\n * @param domain - Domain to toggle\n *\n * Side effects: adds or removes from `selectedDomains`\n */\n toggleDomain: (domain: Domain) => void;\n /**\n * Toggle a skill selection within a domain's category.\n *\n * When exclusive is true (radio behavior), selecting a new skill replaces any\n * existing selection in that category. When false (checkbox behavior),\n * the skill is added to or removed from the selection array.\n *\n * @param domain - Domain containing the category\n * @param category - Category within the domain\n * @param technology - Skill ID to toggle\n * @param exclusive - If true, only one skill can be selected per category (radio)\n *\n * Side effects: updates `domainSelections[domain][category]`\n */\n toggleTechnology: (\n domain: Domain,\n category: Category,\n technology: SkillId,\n exclusive: boolean,\n ) => void;\n /**\n * Advance to the next domain in the build step.\n * @returns true if advanced, false if already at the last domain\n *\n * Side effects: increments `currentDomainIndex`\n */\n nextDomain: () => boolean;\n /**\n * Go back to the previous domain in the build step.\n * @returns true if moved back, false if already at the first domain\n *\n * Side effects: decrements `currentDomainIndex`\n */\n prevDomain: () => boolean;\n /**\n * Set the current domain index directly.\n * @param index - Index to set (0-based, must be within selectedDomains range)\n *\n * Side effects: sets `currentDomainIndex` if index is valid, otherwise no-op\n */\n setCurrentDomainIndex: (index: number) => void;\n /** Toggle compatibility label visibility on skill tags in the build step grid. */\n toggleShowLabels: () => void;\n /** Toggle filtering of incompatible skills in the build step grid. */\n toggleFilterIncompatible: () => void;\n /**\n * Derive the install mode from skillConfigs source values.\n * If all skills use \"eject\" source, returns \"eject\". If all use non-eject, returns \"plugin\".\n * If mixed, returns \"mixed\". Returns \"eject\" when no skills are configured.\n */\n deriveInstallMode: () => InstallMode;\n /**\n * Toggle the scope of a specific skill between \"project\" and \"global\".\n * @param skillId - Skill to toggle scope for\n *\n * Side effects: updates `skillConfigs` entry for the skill\n */\n toggleSkillScope: (skillId: SkillId) => void;\n /**\n * Set the currently focused skill ID in the build step (for S hotkey).\n * @param id - Skill ID to focus, or null to clear\n *\n * Side effects: sets `focusedSkillId`\n */\n setFocusedSkillId: (id: SkillId | null) => void;\n /**\n * Seed `focusedSkillId` to the skill the build-step grid focuses first for the\n * active domain (row 0, col 0 of the filtered category rows). Runs synchronously\n * at build-step entry and on every domain change so the `s` scope hotkey — which\n * reads `focusedSkillId` — always resolves the visually-focused skill, with no\n * dependency on CategoryGrid's post-mount effect.\n *\n * Side effects: sets `focusedSkillId` (null when the active domain has no skills)\n */\n seedFocusedSkillForActiveDomain: () => void;\n /**\n * Set which source provides a specific skill.\n * @param skillId - Skill to configure the source for\n * @param sourceId - Source identifier (e.g., \"public\", \"eject\", marketplace name)\n * @param scope - Acting scope from the Sources row: only the active entry at this scope is\n * updated; a masked global tombstone for the same id keeps its source.\n *\n * Side effects: updates the active `skillConfigs` entry for the skill at `scope`. No-op with warning if either param is empty.\n */\n setSourceSelection: (skillId: SkillId, sourceId: string, scope: SkillScope | undefined) => void;\n /**\n * Enable or disable source customization on the sources step.\n * @param customize - true to show per-skill source pickers\n *\n * Side effects: sets `customizeSources`\n */\n setCustomizeSources: (customize: boolean) => void;\n /** Toggle the settings overlay (source management). */\n toggleSettings: () => void;\n /** Toggle the info overlay (selected skills and agents). */\n toggleInfo: () => void;\n /** Set a temporary toast message, or null to clear it. */\n setToastMessage: (message: string | null) => void;\n /**\n * Add a bound skill from search to the wizard's bound skills list.\n * Duplicates (same id + sourceUrl) are silently skipped with a warning.\n *\n * @param skill - Bound skill to add (foreign skill tied to a category alias)\n *\n * Side effects: appends to `boundSkills`\n */\n bindSkill: (skill: BoundSkill) => void;\n /**\n * Navigate to the previous wizard step using the history stack.\n * No-op when history is empty (e.g., edit flow starting at a mid-wizard step).\n *\n * Side effects: pops from `history`, sets `step` to the popped value\n */\n goBack: () => void;\n /**\n * Toggle an agent on or off in the selectedAgents list.\n * @param agent - Agent name to toggle\n *\n * Side effects: adds or removes from `selectedAgents`, syncs `agentConfigs`\n */\n toggleAgent: (agent: AgentName) => void;\n /**\n * Toggle the scope of a specific agent between \"project\" and \"global\".\n * @param agentName - Agent to toggle scope for\n *\n * Side effects: updates `agentConfigs` entry for the agent\n */\n toggleAgentScope: (agentName: AgentName) => void;\n /**\n * Set the currently focused agent ID in the agents step (for S hotkey).\n * @param id - Agent name to focus, or null to clear\n *\n * Side effects: sets `focusedAgentId`\n */\n setFocusedAgentId: (id: AgentName | null) => void;\n /**\n * Preselect agents based on selected domains from the first wizard step.\n * Matches domains against DOMAIN_AGENTS mapping.\n * Optional agents (meta/pattern) are excluded.\n *\n * Side effects: replaces `selectedAgents` with computed preselection\n */\n preselectAgentsFromDomains: () => void;\n /**\n * Preselect agents for a chosen stack: merges the stack's agent keys with global\n * agent preselections, preserving dual-scope tombstones. Parallels\n * populateFromSkillIds on the skill path.\n *\n * Side effects: replaces `selectedAgents` and `agentConfigs` with the merged result\n */\n preselectAgentsFromStack: (stackAgents: AgentName[]) => void;\n /** Reset all wizard state to initial values. */\n reset: () => void;\n\n /**\n * Collect all selected skill IDs across all domains and categories.\n * @returns Flat array of every selected SkillId (may contain duplicates if shared across domains)\n */\n getAllSelectedTechnologies: () => SkillId[];\n /**\n * Group selected skill IDs by domain.\n * @returns Partial record mapping each domain with selections to its skill ID array\n */\n getSelectedTechnologiesPerDomain: () => Partial<Record<Domain, SkillId[]>>;\n /**\n * Get the domain currently visible in the build step.\n * @returns The domain at currentDomainIndex, or null if no domains are selected\n */\n getCurrentDomain: () => Domain | null;\n /**\n * Count total selected technologies across all domains.\n * @returns Number of selected skill IDs\n */\n getTechnologyCount: () => number;\n /**\n * Compute which wizard steps are completed and which are skipped.\n * Used by WizardTabs to render step progress indicators.\n * @returns Object with completedSteps and skippedSteps string arrays\n */\n getStepProgress: () => { completedSteps: WizardStep[]; skippedSteps: WizardStep[] };\n /** @returns true if there is a next domain after the current one */\n canGoToNextDomain: () => boolean;\n /** @returns true if there is a previous domain before the current one */\n canGoToPreviousDomain: () => boolean;\n /** Set all selected skills to \"eject\" source. */\n setAllSourcesEject: () => void;\n /** Set all selected skills to their first non-local (marketplace) source. */\n setAllSourcesPlugin: () => void;\n\n /**\n * Build the source selection rows for the sources step UI.\n *\n * For each selected technology, resolves the canonical skill ID, looks up available\n * sources from the matrix, merges in any bound skills from search, and determines\n * which source is currently selected. Sources are sorted: local first, then public,\n * then private/other.\n *\n * @returns Array of row objects, one per selected technology, each containing:\n * - `skillId` - Canonical resolved skill ID\n * - `options` - Available sources with selection state and install status\n */\n buildSourceRows: () => SourceRow[];\n};\n\n/** State-only fields from WizardState (excludes actions/getters). Used to type createInitialState(). */\ntype WizardStateData = Pick<\n WizardState,\n | \"step\"\n | \"approach\"\n | \"selectedStackId\"\n | \"stackAction\"\n | \"selectedDomains\"\n | \"currentDomainIndex\"\n | \"domainSelections\"\n | \"_stackDomainSelections\"\n | \"showLabels\"\n | \"filterIncompatible\"\n | \"skillConfigs\"\n | \"focusedSkillId\"\n | \"unresolvableSkillIds\"\n | \"customizeSources\"\n | \"showSettings\"\n | \"showInfo\"\n | \"selectedAgents\"\n | \"agentConfigs\"\n | \"focusedAgentId\"\n | \"boundSkills\"\n | \"installedSkillConfigs\"\n | \"installedAgentConfigs\"\n | \"isInitMode\"\n | \"isEditingFromGlobalScope\"\n | \"toastMessage\"\n | \"globalPreselections\"\n | \"globalAgentPreselections\"\n | \"history\"\n>;\n\nexport const createInitialState = (overrides?: Partial<WizardStateData>): WizardStateData => ({\n step: \"stack\",\n approach: null,\n selectedStackId: null,\n stackAction: null,\n selectedDomains: [],\n currentDomainIndex: 0,\n domainSelections: {},\n /** Snapshot of domainSelections from populateFromSkillIds, used to restore on domain re-toggle */\n _stackDomainSelections: null,\n showLabels: false,\n filterIncompatible: false,\n skillConfigs: [],\n focusedSkillId: null,\n unresolvableSkillIds: [],\n customizeSources: false,\n showSettings: false,\n showInfo: false,\n selectedAgents: [],\n agentConfigs: [],\n focusedAgentId: null,\n boundSkills: [],\n installedSkillConfigs: null,\n installedAgentConfigs: null,\n isInitMode: false,\n isEditingFromGlobalScope: false,\n toastMessage: null,\n globalPreselections: null,\n globalAgentPreselections: null,\n history: [],\n ...overrides,\n});\n\nexport const useWizardStore = create<WizardState>((set, get) => ({\n ...createInitialState(),\n\n setStep: (step) => {\n set((state) => ({\n step,\n history: [...state.history, state.step],\n }));\n if (step === \"build\") get().seedFocusedSkillForActiveDomain();\n },\n\n setApproach: (approach) => set({ approach }),\n\n selectStack: (stackId) =>\n set({\n selectedStackId: stackId,\n domainSelections: {},\n _stackDomainSelections: null,\n selectedDomains: [],\n skillConfigs: [],\n selectedAgents: [],\n agentConfigs: [],\n boundSkills: [],\n currentDomainIndex: 0,\n stackAction: null,\n }),\n\n setStackAction: (action) => set({ stackAction: action }),\n\n populateFromSkillIds: (skillIds, savedConfigs) =>\n set(() => {\n const domainSelections: DomainSelections = {};\n const resolvedSkillIds: SkillId[] = [];\n const unresolvableSkillIds: SkillId[] = [];\n\n for (const skillId of skillIds) {\n const resolved = resolveSkillForPopulation(skillId);\n if (!resolved) {\n unresolvableSkillIds.push(skillId);\n continue;\n }\n\n const { domain, subcat, techId } = resolved;\n if (addToDomainSelections(domainSelections, domain, subcat, techId)) {\n resolvedSkillIds.push(techId);\n }\n }\n\n if (unresolvableSkillIds.length > 0) {\n warn(\n `${unresolvableSkillIds.length} installed skill(s) could not be resolved and were skipped`,\n );\n }\n\n const selectedDomains = orderDomains(typedKeys<Domain>(domainSelections));\n\n const skillConfigs: SkillConfig[] = resolvedSkillIds.map((id) =>\n buildSkillConfigForId(id, savedConfigs),\n );\n\n // Preserve excluded entries so they flow through to wizard result.\n // D-223: allow an excluded tombstone to coexist with an active entry for the\n // same skill id at a different scope (render layer computes secondaryScope\n // from the pair).\n const excludedConfigs = collectTombstones(savedConfigs ?? []);\n\n return {\n domainSelections,\n _stackDomainSelections: structuredClone(domainSelections),\n selectedDomains,\n skillConfigs: [...skillConfigs, ...excludedConfigs],\n unresolvableSkillIds,\n };\n }),\n\n toggleDomain: (domain) =>\n set((state) => {\n const isSelected = state.selectedDomains.includes(domain);\n if (isSelected) {\n const { [domain]: _removed, ...remainingSelections } = state.domainSelections;\n const removedSkillIds = _removed\n ? collectSkillIdsFromSelections(_removed)\n : new Set<SkillId>();\n\n return {\n selectedDomains: state.selectedDomains.filter((d) => d !== domain),\n domainSelections: remainingSelections,\n // Global-scope edit: no overlay, so deselecting a domain uninstalls its skills cleanly\n // rather than tombstoning them in the global config (D-233 Scenario C).\n skillConfigs: applySkillRemoval(\n state.skillConfigs,\n removedSkillIds,\n state.isEditingFromGlobalScope ? null : state.installedSkillConfigs,\n ),\n };\n }\n\n // Restore stack selections for this domain if a stack snapshot exists\n const stackSelections = state._stackDomainSelections?.[domain];\n if (stackSelections) {\n const restoredSkillIds = [...collectSkillIdsFromSelections(stackSelections)];\n\n return {\n selectedDomains: orderDomains([...state.selectedDomains, domain]),\n domainSelections: {\n ...state.domainSelections,\n [domain]: structuredClone(stackSelections),\n },\n skillConfigs: restoreSkillConfigs(state.skillConfigs, restoredSkillIds),\n };\n }\n\n return {\n selectedDomains: orderDomains([...state.selectedDomains, domain]),\n };\n }),\n\n toggleTechnology: (domain, category, technology, exclusive) =>\n set((state) => {\n const installed = state.installedSkillConfigs ?? [];\n const currentSelections = state.domainSelections[domain]?.[category] || [];\n const isSelected = currentSelections.includes(technology);\n\n // Block a globally-installed skill from being changed at project scope. On a SELECT only\n // the active-global arm applies (an inherited-global row is read-only in both directions);\n // the other lock arms are deselect guards, kept behind isSelected so the re-select restore\n // path (reconcileSkillConfigs rebuilds `[P][G]`) still runs.\n const isGlobalLocked = isSelected\n ? isGloballyLockedSkill(installed, state.skillConfigs, technology)\n : hasGlobalActive(installed, technology);\n if (isGlobalLocked && !state.isEditingFromGlobalScope) {\n return { toastMessage: TOAST_MESSAGES.GLOBAL_SKILLS_LOCKED };\n }\n\n if (isSelected) {\n const categoryDef = matrix.categories[category];\n if (categoryDef?.exclusive && categoryDef?.required) {\n const categorySkillCount = typedValues(matrix.skills).filter(\n (s) => s.category === category,\n ).length;\n if (categorySkillCount <= 1) {\n return { toastMessage: TOAST_MESSAGES.ONLY_SKILL_IN_CATEGORY };\n }\n }\n }\n\n // In exclusive mode, selecting a new skill replaces the current one. Block if that would\n // implicitly deselect a globally-locked skill (a radio swap must never tombstone a global\n // install or collapse a live `[P][G]` pair — only `s` may change one).\n if (exclusive && !isSelected) {\n const wouldDropLockedSkill = currentSelections.some((selectedId) =>\n isGloballyLockedSkill(installed, state.skillConfigs, selectedId),\n );\n if (wouldDropLockedSkill && !state.isEditingFromGlobalScope) {\n return { toastMessage: TOAST_MESSAGES.GLOBAL_SKILLS_LOCKED };\n }\n }\n\n let newSelections: SkillId[];\n if (exclusive) {\n newSelections = isSelected ? [] : [technology];\n } else {\n newSelections = isSelected\n ? currentSelections.filter((t) => t !== technology)\n : [...currentSelections, technology];\n }\n\n const removed = currentSelections.filter((id) => !newSelections.includes(id));\n const added = newSelections.filter((id) => !currentSelections.includes(id));\n\n const skillConfigs = reconcileSkillConfigs(\n state.skillConfigs,\n added,\n removed,\n state.installedSkillConfigs,\n state.isEditingFromGlobalScope,\n );\n\n // A dual-scope deselect collapses to a single active inherited-global entry, so the\n // skill is still genuinely active. Keep it in the domain selection (mirroring what a\n // save-and-reopen re-derives via populateFromSkillIds) instead of dropping it purely\n // because it left the pre-removal selection array. A genuine full removal leaves no\n // active entry and still drops normally.\n const stillActiveAfterRemoval =\n isSelected &&\n !newSelections.includes(technology) &&\n (hasProjectActive(skillConfigs, technology) || hasGlobalActive(skillConfigs, technology));\n const resolvedSelections = stillActiveAfterRemoval\n ? [...newSelections, technology]\n : newSelections;\n\n return {\n skillConfigs,\n domainSelections: {\n ...state.domainSelections,\n [domain]: {\n ...state.domainSelections[domain],\n [category]: resolvedSelections,\n },\n },\n };\n }),\n\n nextDomain: () => {\n const state = get();\n if (state.currentDomainIndex < state.selectedDomains.length - 1) {\n set({\n currentDomainIndex: state.currentDomainIndex + 1,\n });\n get().seedFocusedSkillForActiveDomain();\n return true;\n }\n return false;\n },\n\n prevDomain: () => {\n const state = get();\n if (state.currentDomainIndex > 0) {\n set({\n currentDomainIndex: state.currentDomainIndex - 1,\n });\n get().seedFocusedSkillForActiveDomain();\n return true;\n }\n return false;\n },\n\n setCurrentDomainIndex: (index) => {\n const state = get();\n if (index >= 0 && index < state.selectedDomains.length) {\n set({ currentDomainIndex: index });\n get().seedFocusedSkillForActiveDomain();\n }\n },\n\n toggleShowLabels: () => set((state) => ({ showLabels: !state.showLabels })),\n toggleFilterIncompatible: () =>\n set((state) => {\n if (state.filterIncompatible) return { filterIncompatible: false };\n\n const webSelections = state.domainSelections.web;\n if (!webSelections) return { filterIncompatible: true };\n\n const removed = findIncompatibleWebSkills(webSelections, state.skillConfigs);\n if (removed.size === 0) return { filterIncompatible: true };\n\n // F uninstalls every incompatible skill, so it must honour the same global lock the\n // spacebar path applies in toggleTechnology: a project-scope edit may never uninstall a\n // globally installed skill. Every targeted id is a removal here, so the tombstone arm\n // (the stale-snapshot state a persisted `[P][G]` reaches after an in-session collapse)\n // needs no `isSelected` gate. The whole operation is refused — filter included — rather\n // than silently removing only the unlocked subset.\n const installed = state.installedSkillConfigs ?? [];\n const removesLockedGlobal = [...removed].some(\n (id) =>\n hasGlobalActive(installed, id) ||\n (hasGlobalTombstone(installed, id) && hasGlobalActive(state.skillConfigs, id)),\n );\n if (removesLockedGlobal && !state.isEditingFromGlobalScope) {\n return { toastMessage: TOAST_MESSAGES.GLOBAL_SKILLS_LOCKED };\n }\n\n return {\n filterIncompatible: true,\n domainSelections: {\n ...state.domainSelections,\n web: removeSkillsFromSelections(webSelections, removed),\n },\n // Global-scope edit: clean uninstall, no tombstone (D-233 Scenario C).\n skillConfigs: applySkillRemoval(\n state.skillConfigs,\n removed,\n state.isEditingFromGlobalScope ? null : state.installedSkillConfigs,\n ),\n };\n }),\n\n deriveInstallMode: (): InstallMode => {\n const { skillConfigs } = get();\n return sharedDeriveInstallMode(skillConfigs);\n },\n\n toggleSkillScope: (skillId) =>\n set((state) => {\n if (state.isEditingFromGlobalScope) return state;\n\n const config = state.skillConfigs.find((sc) => sc.id === skillId && !sc.excluded);\n if (!config) return state;\n\n // Guard: block project eject → global when global eject already exists (would overwrite)\n if (wouldOverwriteGlobalEject(config, state.skillConfigs, state.installedSkillConfigs)) {\n return { toastMessage: TOAST_MESSAGES.ALREADY_EJECTED_AT_GLOBAL };\n }\n\n // A real global install exists when the snapshot carries EITHER an active global entry\n // or a global tombstone: a tombstone means the skill IS installed globally and this\n // project was overriding it. Both must re-create the tombstone on a G→P toggle, so an\n // in-session collapse→`s` restores a genuine `[P][G]` pair rather than a bare `[P]` that\n // loses the still-real global install. (Matches the agent-path derivation, which already\n // counts tombstones.)\n const wasInstalledGlobally =\n state.installedSkillConfigs?.some((sc) => sc.id === skillId && sc.scope === \"global\") ??\n false;\n const newScope = config.scope === \"project\" ? (\"global\" as const) : (\"project\" as const);\n\n const rescoped = state.skillConfigs.map((sc) =>\n sc.id === skillId && !sc.excluded ? { ...sc, scope: newScope } : sc,\n );\n\n if (newScope === \"project\") {\n // Moving global → project: add the excluded global tombstone if not already there.\n // Gated on wasInstalledGlobally so fresh init toggles don't create spurious tombstones.\n const needsTombstone =\n wasInstalledGlobally && !rescoped.some((sc) => sc.id === skillId && sc.excluded);\n return {\n skillConfigs: needsTombstone\n ? [\n ...rescoped,\n { id: skillId, scope: \"global\" as const, excluded: true, source: config.source },\n ]\n : rescoped,\n };\n }\n\n // Moving project → global: always drop any excluded global tombstone for this id.\n // An active entry at global scope supersedes any tombstone at the same scope — the\n // invariant \"no active + tombstone at the same (id, scope)\" must hold. Unconditional\n // removal (not gated on wasInstalledGlobally) heals the D-224 case where the prior\n // G→P produced a tombstone that installedSkillConfigs-derived wasInstalledGlobally\n // cannot see (because its `!sc.excluded` filter ignores the tombstone itself).\n return { skillConfigs: rescoped.filter((sc) => !(sc.id === skillId && sc.excluded)) };\n }),\n\n setFocusedSkillId: (id) => set({ focusedSkillId: id }),\n\n seedFocusedSkillForActiveDomain: () => {\n const state = get();\n // Mirror the build-step renderer's domain fallback (use-build-step-props.ts):\n // when no domain is selected the grid still renders FALLBACK_DOMAIN and\n // highlights a cell, so the seed must resolve that same domain — never null\n // while a cell is visibly focused — or the cold `s` toggle no-ops on a desync.\n const domain = state.getCurrentDomain() ?? FALLBACK_DOMAIN;\n const categories = buildCategoriesForDomain(\n domain,\n state.getAllSelectedTechnologies(),\n state.domainSelections[domain] ?? {},\n undefined,\n state.skillConfigs,\n state.filterIncompatible,\n );\n set({ focusedSkillId: categories[0]?.options[0]?.id ?? null });\n },\n\n setSourceSelection: (skillId, sourceId, scope) =>\n set((state) => {\n if (!skillId) {\n warn(\"Ignoring setSourceSelection call with empty skillId\");\n return state;\n }\n if (!sourceId) {\n warn(`Ignoring setSourceSelection call with empty sourceId for skill '${skillId}'`);\n return state;\n }\n return {\n skillConfigs: withActiveEntrySource(state.skillConfigs, skillId, scope, sourceId),\n };\n }),\n\n setCustomizeSources: (customize) => set({ customizeSources: customize }),\n\n toggleSettings: () => set((state) => ({ showSettings: !state.showSettings })),\n\n toggleInfo: () => set((state) => ({ showInfo: !state.showInfo })),\n\n setToastMessage: (message) => set({ toastMessage: message }),\n\n bindSkill: (skill) =>\n set((state) => {\n const exists = state.boundSkills.some(\n (b) => b.id === skill.id && b.sourceUrl === skill.sourceUrl,\n );\n if (exists) {\n warn(`Skill '${skill.id}' from '${skill.sourceUrl}' is already bound — skipping duplicate`);\n return state;\n }\n return { boundSkills: [...state.boundSkills, skill] };\n }),\n\n goBack: () =>\n set((state) => {\n if (state.history.length === 0) return state;\n const history = [...state.history];\n const previousStep = history.pop()!;\n return {\n step: previousStep,\n history,\n };\n }),\n\n toggleAgent: (agent) =>\n set((state) => {\n const installed = state.installedAgentConfigs ?? [];\n\n // A live dual-scope `[P][G]` row is locked to `s`: the selection key is inert on it and\n // emits the same global-locked toast an inherited-global row shows. Mirrors the skill-side\n // dual-scope arm in toggleTechnology — `s` alone collapses and restores the pair.\n const isDualScopePairRow =\n !state.isEditingFromGlobalScope && isDualScopeAgentPair(state.agentConfigs, agent);\n if (isDualScopePairRow) {\n return { toastMessage: TOAST_MESSAGES.GLOBAL_AGENTS_LOCKED };\n }\n\n const isInheritedGlobalReselect =\n !state.isEditingFromGlobalScope &&\n agentHasGlobalActive(state.agentConfigs, agent) &&\n !agentHasProjectActive(state.agentConfigs, agent) &&\n !state.selectedAgents.includes(agent) &&\n agentHasGlobalTombstone(installed, agent);\n if (isInheritedGlobalReselect) {\n return restoreDualScopeAgent(state.selectedAgents, state.agentConfigs, agent);\n }\n\n // Block a globally-installed agent from being changed at project scope. Mirrors the\n // skill-path guard in toggleTechnology: fire on an active global entry in the snapshot,\n // or on a snapshot tombstone paired with a LIVE plain active global entry (the stale\n // state a persisted `[P][G]` reaches after an in-session collapse). A freshly-added\n // global agent (absent from the snapshot) stays freely deselectable.\n const isActiveGlobal =\n agentHasGlobalActive(installed, agent) ||\n (agentHasGlobalTombstone(installed, agent) &&\n agentHasGlobalActive(state.agentConfigs, agent));\n if (isActiveGlobal && !state.isEditingFromGlobalScope) {\n return { toastMessage: TOAST_MESSAGES.GLOBAL_AGENTS_LOCKED };\n }\n\n const isInList = state.selectedAgents.includes(agent);\n const hasExcludedTombstone = state.agentConfigs.some(\n (ac) => ac.name === agent && ac.excluded,\n );\n // An agent is effectively selected only if it's in the list WITHOUT an excluded tombstone.\n // When it has an excluded tombstone, it's visually \"off\" and toggling means \"re-enable\".\n const isSelected = isInList && !hasExcludedTombstone;\n\n return {\n selectedAgents: nextSelectedAgents(state.selectedAgents, agent, { isSelected, isInList }),\n agentConfigs: applyAgentToggle(state.agentConfigs, agent, isSelected),\n };\n }),\n\n toggleAgentScope: (agentName) =>\n set((state) => {\n if (state.isEditingFromGlobalScope) return state;\n\n const config = state.agentConfigs.find((ac) => ac.name === agentName && !ac.excluded);\n if (!config) return state;\n\n // Counts a global tombstone as \"installed globally\" (a tombstone means a real global\n // install this project overrides), so an in-session collapse→`s` restores a genuine\n // `[P][G]` pair.\n const wasInstalledGlobally =\n state.installedAgentConfigs?.some((ac) => ac.name === agentName && ac.scope === \"global\") ??\n false;\n const newScope = config.scope === \"project\" ? (\"global\" as const) : (\"project\" as const);\n\n const rescoped = state.agentConfigs.map((ac) =>\n ac.name === agentName && !ac.excluded ? { ...ac, scope: newScope } : ac,\n );\n\n if (newScope === \"project\") {\n // Moving global → project: add the excluded global tombstone if not already there.\n // Gated on wasInstalledGlobally so fresh init toggles don't create spurious tombstones.\n const needsTombstone =\n wasInstalledGlobally && !rescoped.some((ac) => ac.name === agentName && ac.excluded);\n return {\n agentConfigs: needsTombstone\n ? [...rescoped, { name: agentName, scope: \"global\" as const, excluded: true }]\n : rescoped,\n };\n }\n\n // Moving project → global: always drop any excluded global tombstone for this name.\n // Symmetric with toggleSkillScope — see its comment for the invariant.\n return { agentConfigs: rescoped.filter((ac) => !(ac.name === agentName && ac.excluded)) };\n }),\n\n setFocusedAgentId: (id) => set({ focusedAgentId: id }),\n\n preselectAgentsFromDomains: () =>\n set((state) => {\n const sorted = state.selectedDomains.flatMap((domain) => DOMAIN_AGENTS[domain] ?? []).sort();\n const roster = new Set(sorted);\n const merged = sorted.map((name) => buildAgentConfigForName(name, state.agentConfigs));\n const retained = state.agentConfigs.filter((ac) => survivesRosterRebuild(ac, roster));\n return {\n selectedAgents: sorted,\n agentConfigs: [...merged, ...retained],\n };\n }),\n\n preselectAgentsFromStack: (stackAgents) =>\n set((state) => {\n const savedConfigs = state.globalAgentPreselections?.configs ?? [];\n const globalAgents = state.globalAgentPreselections?.agents ?? [];\n const mergedAgents = [...new Set([...stackAgents, ...globalAgents])].sort();\n const merged = mergedAgents.map((name) => buildAgentConfigForName(name, savedConfigs));\n // Preserve dual-scope tombstones, same invariant as preselectAgentsFromDomains (D-227).\n const excludedConfigs = collectTombstones(savedConfigs);\n return {\n selectedAgents: mergedAgents,\n agentConfigs: [...merged, ...excludedConfigs],\n };\n }),\n\n reset: () => set(createInitialState()),\n\n getAllSelectedTechnologies: () => {\n return typedValues(get().domainSelections).flatMap(flattenCategorySelections);\n },\n\n getSelectedTechnologiesPerDomain: () => {\n const entries = typedEntries(get().domainSelections)\n .map(([domain, domainSel]) => [domain, flattenCategorySelections(domainSel)] as const)\n .filter(([, techs]) => techs.length > 0);\n return typedFromEntries(entries);\n },\n\n getCurrentDomain: () => {\n const state = get();\n return state.selectedDomains[state.currentDomainIndex] || null;\n },\n\n getTechnologyCount: () => {\n return get().getAllSelectedTechnologies().length;\n },\n\n getStepProgress: () => {\n const state = get();\n const isStackDefaults =\n state.approach === \"stack\" && !!state.selectedStackId && state.stackAction === \"defaults\";\n const skippedSteps: WizardStep[] = isStackDefaults ? [\"build\", \"sources\", \"agents\"] : [];\n const precedingSteps = WIZARD_STEP_ORDER.slice(0, WIZARD_STEP_ORDER.indexOf(state.step));\n const completedSteps = precedingSteps.filter((step) => !skippedSteps.includes(step));\n return { completedSteps, skippedSteps };\n },\n\n canGoToNextDomain: () => {\n const state = get();\n return state.currentDomainIndex < state.selectedDomains.length - 1;\n },\n\n canGoToPreviousDomain: () => {\n const state = get();\n return state.currentDomainIndex > 0;\n },\n\n setAllSourcesEject: () => {\n set((state) => ({\n // Never touch tombstones — a dual-scope skill's excluded global tombstone keeps describing\n // the masked global install. The bulk set-all applies only to active entries, mirroring the\n // D-262 per-skill setSkillSource/setSourceSelection guard (D-265).\n skillConfigs: state.skillConfigs.map((sc) =>\n sc.excluded ? sc : { ...sc, source: EJECT_SOURCE },\n ),\n }));\n },\n\n setAllSourcesPlugin: () => {\n set((state) => ({\n // Never touch tombstones (see setAllSourcesEject) — the excluded global tombstone keeps its\n // marketplace source describing the masked global install (D-265).\n skillConfigs: state.skillConfigs.map((sc) => {\n if (sc.excluded) return sc;\n const marketplaceSource = getSkillById(sc.id).availableSources?.find(\n (source) => source.type !== \"local\",\n );\n return marketplaceSource ? { ...sc, source: marketplaceSource.name } : sc;\n }),\n }));\n },\n\n buildSourceRows: () => {\n const state = get();\n const selectedTechnologies = get().getAllSelectedTechnologies();\n const { skillConfigs, boundSkills } = state;\n\n // Include inherited global skills (in skillConfigs but not in domainSelections)\n const selectedSet = new Set(selectedTechnologies);\n const inheritedSkillIds = skillConfigs\n .filter((sc) => !sc.excluded && !selectedSet.has(sc.id))\n .map((sc) => sc.id);\n const allActiveIds = new Set([...inheritedSkillIds, ...selectedTechnologies]);\n const excludedGlobalIds = skillConfigs\n .filter((sc) => isGlobalTombstone(sc) && !allActiveIds.has(sc.id))\n .map((sc) => sc.id);\n // Every skill with a LIVE config entry or selection. Internally disjoint by construction, so no\n // skill contributes live rows twice.\n const liveSkillIds = [...inheritedSkillIds, ...selectedTechnologies, ...excludedGlobalIds];\n // D-258: the slot baseline additions are measured against. Each emitted row checks its OWN\n // `(id, scope)` slot, so a skill adopted at a second scope registers as added on the newly\n // occupied row alone — the same classification the confirm step's computeScopeDiff makes.\n const installedSkillSlots = collectInstalledSkillSlots(state.installedSkillConfigs);\n const resolveRowInputs = (id: SkillId) => resolveSkillRowInputs(id, skillConfigs, boundSkills);\n\n const liveRows: SourceRow[] = liveSkillIds.flatMap((id) => {\n const { skillId, configEntry, options } = resolveRowInputs(id);\n return classifySkillSourceRows(skillId, options, {\n configEntry,\n installedSkillConfigs: state.installedSkillConfigs,\n isEditingFromGlobalScope: state.isEditingFromGlobalScope,\n installedSkillSlots,\n });\n });\n\n // D-257/D-271: slots the session emptied. A skill may appear in BOTH lists — a collapsed\n // dual-scope pair keeps its surviving global row and gains a project pending-removal row — so\n // rows are no longer disjoint per SKILL. They stay disjoint per `(id, scope)` SLOT: a snapshot\n // slot a live row already renders never gets a removal row on top of it.\n const pendingRemovalRows: SourceRow[] = collectRemovedInstalledEntries(\n state.installedSkillConfigs,\n skillConfigs,\n )\n .filter((entry) => !isSlotAlreadyRendered(liveRows, entry))\n .map((entry) => {\n const { skillId, options } = resolveRowInputs(entry.id);\n return toPendingRemovalRow(skillId, options, entry);\n });\n\n // Stable sort by scope tier: global readOnly, global editable, then project. Pending-removal\n // rows carry no dedicated tier — they sort by their own scope and, being appended last, trail\n // inline within that scope section. Matches source-grid grouping so navigation indices align\n // with render order.\n const rows = [...liveRows, ...pendingRemovalRows];\n rows.sort((a, b) => sourceRowSortTier(a) - sourceRowSortTier(b));\n\n return rows;\n },\n}));\n\nexport type HydrateOptions = {\n initialStep?: WizardStep;\n initialDomains?: Domain[];\n initialAgents?: AgentName[];\n installedSkillIds?: SkillId[];\n installedSkillConfigs?: SkillConfig[];\n installedAgentConfigs?: AgentScopeConfig[];\n isEditingFromGlobalScope?: boolean;\n};\n\n/**\n * Imperatively hydrates the wizard store before the first render.\n *\n * Must be called BEFORE render(<Wizard ... />) so React captures the correct\n * initial snapshot on the first frame. Running this inside a render-phase hook\n * causes a one-frame flash of the default \"stack\" step before the jump to the\n * intended step is committed to stdout.\n */\nexport function hydrateWizardStore(options: HydrateOptions): void {\n useWizardStore.setState(createInitialState());\n\n const { initialStep } = options;\n const isEditFlow = initialStep !== undefined;\n if (isEditFlow) {\n hydrateForEdit(initialStep, options);\n } else {\n hydrateForInit(options);\n }\n}\n\n/** Edit flow: populate from installed skills, then jump straight to the saved step. */\nfunction hydrateForEdit(initialStep: WizardStep, options: HydrateOptions): void {\n const {\n initialDomains,\n initialAgents,\n installedSkillIds,\n installedSkillConfigs,\n installedAgentConfigs,\n isEditingFromGlobalScope,\n } = options;\n\n if (installedSkillIds?.length) {\n useWizardStore.getState().populateFromSkillIds(installedSkillIds, installedSkillConfigs);\n }\n\n useWizardStore.setState({\n isInitMode: false,\n // Jump directly to initialStep with empty history. The user is starting\n // fresh at this step — no prior steps to navigate back through.\n step: initialStep,\n history: [],\n approach: \"scratch\",\n // Saved domains/agents from config override what populateFromSkillIds derived.\n ...(initialDomains?.length ? { selectedDomains: initialDomains, currentDomainIndex: 0 } : {}),\n ...(initialAgents?.length ? { selectedAgents: initialAgents } : {}),\n ...(initialAgents?.length && installedAgentConfigs?.length\n ? { agentConfigs: installedAgentConfigs }\n : {}),\n // Snapshot installed configs for diff rendering in SkillAgentSummary\n ...(installedSkillConfigs?.length || installedAgentConfigs?.length\n ? {\n installedSkillConfigs: installedSkillConfigs ?? null,\n installedAgentConfigs: installedAgentConfigs ?? null,\n }\n : {}),\n ...(isEditingFromGlobalScope ? { isEditingFromGlobalScope: true } : {}),\n });\n\n useWizardStore.getState().seedFocusedSkillForActiveDomain();\n}\n\n/**\n * Init flow: skills are not populated yet — the stack step runs first, so saved\n * selections are stored as preselections for stack-selection.tsx to merge after\n * the stack/scratch choice (selectStack wipes agents).\n */\nfunction hydrateForInit(options: HydrateOptions): void {\n const {\n initialDomains,\n initialAgents,\n installedSkillConfigs,\n installedAgentConfigs,\n isEditingFromGlobalScope,\n } = options;\n\n useWizardStore.setState({\n isInitMode: true,\n ...(initialDomains?.length ? { selectedDomains: initialDomains, currentDomainIndex: 0 } : {}),\n ...(initialAgents?.length ? { selectedAgents: initialAgents } : {}),\n ...(initialAgents?.length && installedAgentConfigs?.length\n ? { agentConfigs: installedAgentConfigs }\n : {}),\n // Snapshot installed configs for diff rendering in SkillAgentSummary\n ...(installedSkillConfigs?.length || installedAgentConfigs?.length\n ? {\n installedSkillConfigs: installedSkillConfigs ?? null,\n installedAgentConfigs: installedAgentConfigs ?? null,\n }\n : {}),\n ...(isEditingFromGlobalScope ? { isEditingFromGlobalScope: true } : {}),\n ...(installedSkillConfigs?.length ? { globalPreselections: installedSkillConfigs } : {}),\n ...(initialAgents?.length || installedAgentConfigs?.length\n ? {\n globalAgentPreselections: {\n agents: initialAgents ?? [],\n configs: installedAgentConfigs ?? [],\n },\n }\n : {}),\n });\n\n useWizardStore.getState().seedFocusedSkillForActiveDomain();\n}\n","export {\n type BuildStepValidation,\n validateBuildStep,\n buildCategoriesForDomain,\n isCompatibleWithSelectedFrameworks,\n FRAMEWORK_CATEGORY_ID,\n} from \"./build-step-logic\";\nexport {\n type AgentDiffRow,\n type DiffRowStatus,\n type ScopeDiff,\n type ScopeDiffInput,\n type SkillDiffRow,\n type ScopeBadges,\n agentSlotKey,\n computeScopeDiff,\n deriveScopeBadges,\n formatScopeTag,\n skillSlotKey,\n} from \"./scope-diff\";\nexport { orderDomains } from \"./domain-order\";\n","import { sortBy } from \"remeda\";\nimport { typedValues } from \"../../utils/typed-object.js\";\nimport type { Domain, SkillId, CategorySelections } from \"../../types/index.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport {\n getAvailableSkills,\n getUnmetRequiredBy,\n isCompatibleWithSelections,\n} from \"../matrix/index.js\";\nimport { matrix, getSkillById } from \"../matrix/matrix-provider.js\";\nimport { deriveScopeBadges } from \"./scope-diff.js\";\nimport type { CategoryRow, CategoryOption } from \"../../components/wizard/category-grid.js\";\n\nexport const FRAMEWORK_CATEGORY_ID = \"web-framework\";\nconst WEB_DOMAIN_ID = \"web\";\n\nexport type BuildStepValidation = {\n valid: boolean;\n message?: string;\n};\n\nexport function validateBuildStep(\n categories: CategoryRow[],\n selections: CategorySelections,\n): BuildStepValidation {\n const emptyRequired = categories.find(\n (category) => category.required && !selections[category.id]?.length,\n );\n return emptyRequired\n ? {\n valid: true,\n message: `No skills selected in ${emptyRequired.displayName} (required category)`,\n }\n : { valid: true };\n}\n\nfunction getSelectedFrameworks(selections: CategorySelections): SkillId[] {\n return (selections[FRAMEWORK_CATEGORY_ID] ?? []).map((alias) => getSkillById(alias).id);\n}\n\nexport function isCompatibleWithSelectedFrameworks(\n skillId: SkillId,\n selectedFrameworkIds: SkillId[],\n): boolean {\n return isCompatibleWithSelections(getSkillById(skillId), selectedFrameworkIds);\n}\n\n// Build CategoryRow[] from matrix for a domain\nexport function buildCategoriesForDomain(\n domain: Domain,\n allSelections: SkillId[],\n selections: CategorySelections,\n installedSkillIds?: SkillId[],\n skillConfigs?: SkillConfig[],\n filterIncompatible?: boolean,\n): CategoryRow[] {\n const selectedFrameworkIds = getSelectedFrameworks(selections);\n const shouldFilter =\n filterIncompatible && domain === WEB_DOMAIN_ID && selectedFrameworkIds.length > 0;\n\n const categories = sortBy(\n typedValues(matrix.categories).filter((cat) => cat.domain === domain),\n (cat) => cat.order ?? 0,\n );\n\n const categoryRows: CategoryRow[] = categories.map((cat) => {\n const skillOptions = getAvailableSkills(cat.id, allSelections);\n\n const filteredOptions =\n shouldFilter && cat.id !== FRAMEWORK_CATEGORY_ID\n ? skillOptions.filter((skill) =>\n isCompatibleWithSelectedFrameworks(skill.id, selectedFrameworkIds),\n )\n : skillOptions;\n\n const isExclusive = cat.exclusive ?? true;\n\n // Sort options by displayName so the grid order is deterministic across\n // machines and source types (readdir/insertion order is otherwise unstable).\n // Lowercased ordinal comparison keeps the order locale-independent.\n const sortedOptions = sortBy(filteredOptions, (skill) =>\n getSkillById(skill.id).displayName.toLowerCase(),\n );\n\n const options: CategoryOption[] = sortedOptions.map((skill) => {\n const activeConfig = skillConfigs?.find((sc) => sc.id === skill.id && !sc.excluded);\n const excludedConfig = skillConfigs?.find((sc) => sc.id === skill.id && sc.excluded);\n const { secondaryScope } = deriveScopeBadges(activeConfig, excludedConfig);\n return {\n id: skill.id,\n state:\n isExclusive && skill.advisoryState.status === \"incompatible\"\n ? { status: \"normal\" }\n : skill.advisoryState,\n selected: skill.selected,\n local: getSkillById(skill.id).local,\n installed: installedSkillIds?.includes(skill.id) || false,\n scope: activeConfig?.scope,\n secondaryScope,\n source: activeConfig?.source,\n hasUnmetRequirements: skill.hasUnmetRequirements,\n unmetRequirementsReason: skill.unmetRequirementsReason,\n requiredBy: skill.selected ? undefined : getUnmetRequiredBy(skill.id, allSelections),\n };\n });\n\n return {\n id: cat.id,\n displayName: cat.displayName,\n required: cat.required ?? false,\n exclusive: cat.exclusive ?? true,\n options,\n };\n });\n\n return categoryRows.filter((row) => row.options.length > 0);\n}\n","import type { AgentScopeConfig, SkillConfig, SkillScope } from \"../../types/config\";\nimport type { AgentName, SkillId } from \"../../types/index\";\n\nexport type ScopeDiffInput = {\n currentSkills: SkillConfig[];\n currentAgents: AgentScopeConfig[];\n installedSkillConfigs: SkillConfig[] | null;\n installedAgentConfigs: AgentScopeConfig[] | null;\n isInitMode: boolean;\n};\n\nexport type DiffRowStatus = \"added\" | \"source-changed\" | \"removed\" | \"unchanged\";\n\nexport type SkillDiffRow = {\n id: SkillId;\n source: string;\n status: DiffRowStatus;\n};\n\nexport type AgentDiffRow = {\n name: AgentName;\n status: Exclude<DiffRowStatus, \"source-changed\">;\n};\n\nexport type ScopeDiff = {\n projectSkillRows: SkillDiffRow[];\n globalSkillRows: SkillDiffRow[];\n projectAgentRows: AgentDiffRow[];\n globalAgentRows: AgentDiffRow[];\n hasContent: boolean;\n};\n\n/**\n * Computes the per-scope diff rows the confirm-step summary renders.\n *\n * The diff baseline keeps tombstones as first-class entries. A tombstone\n * occupies the (id, scope) slot: it means \"the global install still exists but\n * is silenced at project scope\" (D-223 dual-scope indicator). Treating the slot\n * as occupied — for both the previous-key set (isNew detection) and removal\n * (slot-occupancy match) — prevents a dual-scope G→P toggle from rendering a\n * spurious `-` at Global (D-230) or a spurious `+` at Global on the next edit\n * when the stored tombstone is re-read (D-232). See D-225 investigation 09 for\n * the full derivation; source-change (`~`) tracking filters to active baseline\n * entries because tombstones don't represent a live install source.\n */\nexport function computeScopeDiff(input: ScopeDiffInput): ScopeDiff {\n const { currentSkills, currentAgents, installedSkillConfigs, installedAgentConfigs, isInitMode } =\n input;\n\n const projectSkills = currentSkills.filter((s) => s.scope === \"project\" && !s.excluded);\n const globalSkills = currentSkills.filter((s) => s.scope === \"global\" && !s.excluded);\n const projectAgents = currentAgents.filter((a) => a.scope === \"project\" && !a.excluded);\n const globalAgents = currentAgents.filter((a) => a.scope === \"global\" && !a.excluded);\n const excludedGlobalSkills = currentSkills.filter((s) => s.scope === \"global\" && !!s.excluded);\n const excludedGlobalAgents = currentAgents.filter((a) => a.scope === \"global\" && !!a.excluded);\n\n const prevSkillKeySet = installedSkillConfigs\n ? new Set(installedSkillConfigs.map((s) => skillSlotKey(s.id, s.scope)))\n : null;\n const prevSourceMap = installedSkillConfigs\n ? new Map(\n installedSkillConfigs\n .filter((s) => !s.excluded)\n .map((s) => [skillSlotKey(s.id, s.scope), s.source]),\n )\n : null;\n const prevAgentKeySet = installedAgentConfigs\n ? new Set(installedAgentConfigs.map((a) => agentSlotKey(a.name, a.scope)))\n : null;\n\n // Active baseline globals that are overridden at project scope without a\n // tombstone in current state — a historical no-tombstone dual-scope shape.\n // Current tombstones are handled directly via `uniqueExcludedGlobalSkills`.\n const activeSkillBaseline = installedSkillConfigs\n ? installedSkillConfigs.filter((s) => !s.excluded)\n : [];\n const activeAgentBaseline = installedAgentConfigs\n ? installedAgentConfigs.filter((a) => !a.excluded)\n : [];\n const inheritedGlobalSkills = activeSkillBaseline.filter(\n (s) =>\n s.scope === \"global\" &&\n !globalSkills.some((g) => g.id === s.id) &&\n !excludedGlobalSkills.some((e) => e.id === s.id) &&\n projectSkills.some((p) => p.id === s.id),\n );\n const inheritedGlobalAgents = activeAgentBaseline.filter(\n (a) =>\n a.scope === \"global\" &&\n !globalAgents.some((g) => g.name === a.name) &&\n !excludedGlobalAgents.some((e) => e.name === a.name) &&\n projectAgents.some((p) => p.name === a.name),\n );\n\n // Slot-occupancy match: a baseline entry at (id, scope) is considered\n // removed only if nothing — active OR tombstone — occupies that slot in\n // current. A current tombstone at the same key keeps the slot occupied\n // (dual-scope indicator, not a removal). See D-230 / D-232.\n const removedSkills = installedSkillConfigs\n ? installedSkillConfigs.filter(\n (s) => !currentSkills.some((c) => c.id === s.id && c.scope === s.scope),\n )\n : [];\n const removedAgents = installedAgentConfigs\n ? installedAgentConfigs.filter(\n (a) => !currentAgents.some((c) => c.name === a.name && c.scope === a.scope),\n )\n : [];\n\n // `uniqueExcludedGlobalSkills` dedups the current tombstone row against any\n // inherited-global entry for the same id so the Global section never shows\n // two rows for the same skill. Under the slot-occupancy removal match above,\n // a current tombstone at (id, global) keeps the slot occupied and therefore\n // cannot collide with the removed-global rows — no further dedup needed there.\n const inheritedSkillIdSet = new Set(inheritedGlobalSkills.map((s) => s.id));\n const uniqueExcludedGlobalSkills = excludedGlobalSkills.filter(\n (s) => !inheritedSkillIdSet.has(s.id),\n );\n const allGlobalSkills = [\n ...globalSkills,\n ...inheritedGlobalSkills,\n ...uniqueExcludedGlobalSkills,\n ];\n const inheritedAgentNameSet = new Set(inheritedGlobalAgents.map((a) => a.name));\n const uniqueExcludedGlobalAgents = excludedGlobalAgents.filter(\n (a) => !inheritedAgentNameSet.has(a.name),\n );\n const allGlobalAgents = [\n ...globalAgents,\n ...inheritedGlobalAgents,\n ...uniqueExcludedGlobalAgents,\n ];\n\n const removedGlobalSkills = isInitMode ? [] : removedSkills.filter((s) => s.scope === \"global\");\n const removedProjectSkills = removedSkills.filter((s) => s.scope === \"project\");\n const removedGlobalAgents = isInitMode ? [] : removedAgents.filter((a) => a.scope === \"global\");\n const removedProjectAgents = removedAgents.filter((a) => a.scope === \"project\");\n\n const projectSkillRows = [\n ...projectSkills.map((s) => classifyDiffRow(s, prevSkillKeySet, prevSourceMap)),\n ...removedProjectSkills.map(toRemovedSkillRow),\n ];\n const globalSkillRows = [\n ...allGlobalSkills.map((s) => classifyDiffRow(s, prevSkillKeySet, prevSourceMap)),\n ...removedGlobalSkills.map(toRemovedSkillRow),\n ];\n const projectAgentRows = [\n ...projectAgents.map((a) => classifyAgentDiffRow(a, prevAgentKeySet)),\n ...removedProjectAgents.map(toRemovedAgentRow),\n ];\n const globalAgentRows = [\n ...allGlobalAgents.map((a) => classifyAgentDiffRow(a, prevAgentKeySet)),\n ...removedGlobalAgents.map(toRemovedAgentRow),\n ];\n\n const hasContent =\n projectSkillRows.length > 0 ||\n globalSkillRows.length > 0 ||\n projectAgentRows.length > 0 ||\n globalAgentRows.length > 0;\n\n return { projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows, hasContent };\n}\n\n/**\n * The `(id, scope)` SLOT key this module diffs on. Exported so every surface that computes its own\n * session diff — notably the wizard store's Sources tab — keys on the same slot rather than on the\n * id alone, which is what let one skill read as added on one surface and unchanged on the other\n * (todo/D-271 secondary hardening).\n */\nexport function skillSlotKey(id: SkillId, scope: SkillScope | undefined): string {\n return `${id}:${scope}`;\n}\n\n/**\n * The `(name, scope)` SLOT key for an agent — the agent-side counterpart of {@link skillSlotKey},\n * exported for the same reason. Today only this module diffs agent slots, so there is nothing to\n * disagree with; the helper exists so that a second surface routes through it from the start rather\n * than re-deriving the key on `name` alone, which is precisely how the skill side reached D-278.\n */\nexport function agentSlotKey(name: AgentName, scope: SkillScope | undefined): string {\n return `${name}:${scope}`;\n}\n\nexport type ScopeBadges = {\n scope: SkillScope | undefined;\n secondaryScope: SkillScope | undefined;\n};\n\n/** Bracketed scope badge: `[G]` for global, `[P]` for project. */\nexport function formatScopeTag(scope: SkillScope): \"[G]\" | \"[P]\" {\n return scope === \"global\" ? \"[G]\" : \"[P]\";\n}\n\n/**\n * D-223: derives the primary + secondary scope badges for a row from its active\n * entry and its excluded tombstone. A tombstone at the OTHER scope renders as a\n * secondary badge (`[P][G]`); a same-scope tombstone renders nothing extra.\n */\nexport function deriveScopeBadges(\n activeConfig: { scope: SkillScope } | undefined,\n excludedConfig: { scope: SkillScope } | undefined,\n): ScopeBadges {\n const secondaryScope =\n excludedConfig && activeConfig && excludedConfig.scope !== activeConfig.scope\n ? excludedConfig.scope\n : undefined;\n return { scope: activeConfig?.scope, secondaryScope };\n}\n\n/** Classifies an active skill entry against the baseline: added, source-changed, or unchanged. */\nfunction classifyDiffRow(\n skill: SkillConfig,\n prevKeySet: Set<string> | null,\n prevSourceMap: Map<string, string> | null,\n): SkillDiffRow {\n const key = skillSlotKey(skill.id, skill.scope);\n const isNew = prevKeySet === null || !prevKeySet.has(key);\n const prevSource = prevSourceMap?.get(key);\n const sourceChanged = !isNew && prevSource != null && prevSource !== skill.source;\n if (sourceChanged) {\n return { id: skill.id, source: skill.source, status: \"source-changed\" };\n }\n return { id: skill.id, source: skill.source, status: isNew ? \"added\" : \"unchanged\" };\n}\n\nfunction classifyAgentDiffRow(\n agent: AgentScopeConfig,\n prevKeySet: Set<string> | null,\n): AgentDiffRow {\n const isNew = prevKeySet === null || !prevKeySet.has(agentSlotKey(agent.name, agent.scope));\n return { name: agent.name, status: isNew ? \"added\" : \"unchanged\" };\n}\n\nfunction toRemovedSkillRow(skill: SkillConfig): SkillDiffRow {\n return { id: skill.id, source: skill.source, status: \"removed\" };\n}\n\nfunction toRemovedAgentRow(agent: AgentScopeConfig): AgentDiffRow {\n return { name: agent.name, status: \"removed\" };\n}\n","import { BUILT_IN_DOMAIN_ORDER } from \"../../consts.js\";\nimport type { Domain } from \"../../types/index.js\";\n\n/**\n * Sort domains into canonical display order: custom domains first (alphabetically),\n * then built-in domains in BUILT_IN_DOMAIN_ORDER.\n */\nexport function orderDomains(domains: Domain[]): Domain[] {\n const builtInSet = new Set<Domain>(BUILT_IN_DOMAIN_ORDER);\n return [\n ...domains.filter((d) => !builtInSet.has(d)).sort(),\n ...BUILT_IN_DOMAIN_ORDER.filter((d) => domains.includes(d)),\n ];\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadAgentDefs
4
+ } from "./chunk-YBVA7GPW.js";
5
+ import {
6
+ pruneStaleCompiledAgents,
7
+ recompileAgents
8
+ } from "./chunk-NGLQ5W7U.js";
9
+ import {
10
+ buildAgentScopeMap,
11
+ buildMarketplacePluginRef,
12
+ claudePluginInstall,
13
+ claudePluginUninstall,
14
+ compareLocalSkillsWithSource,
15
+ discoverAllPluginSkills,
16
+ isHomeDirectory,
17
+ loadProjectConfigFromDir,
18
+ resolveInstallPaths,
19
+ toClaudePluginScope
20
+ } from "./chunk-TVHRMRD3.js";
21
+ import {
22
+ fileExists,
23
+ getErrorMessage,
24
+ listDirectories,
25
+ loadSkillsFromDir,
26
+ verbose
27
+ } from "./chunk-3LIU2ZEF.js";
28
+ import {
29
+ typedEntries,
30
+ typedKeys
31
+ } from "./chunk-VEP23B5W.js";
32
+ import {
33
+ EJECT_SOURCE,
34
+ GLOBAL_INSTALL_ROOT,
35
+ LOCAL_SKILLS_PATH
36
+ } from "./chunk-O5ASLZ2K.js";
37
+ import {
38
+ init_esm_shims
39
+ } from "./chunk-P56WJ5FA.js";
40
+
41
+ // src/cli/lib/operations/project/recompile-project-agents.ts
42
+ init_esm_shims();
43
+
44
+ // src/cli/lib/operations/project/compile-agents.ts
45
+ init_esm_shims();
46
+ async function compileAgents(options) {
47
+ let resolvedAgents = options.agents;
48
+ let resolvedAgentScopeMap = options.agentScopeMap;
49
+ if (options.scopeFilter) {
50
+ const loadedConfig = await loadProjectConfigFromDir(options.projectDir);
51
+ if (!resolvedAgentScopeMap && loadedConfig?.config) {
52
+ resolvedAgentScopeMap = buildAgentScopeMap(loadedConfig.config);
53
+ }
54
+ const filteredAgents = loadedConfig?.config?.agents?.filter((a) => !a.excluded && a.scope === options.scopeFilter).map((a) => a.name);
55
+ if (resolvedAgents && filteredAgents) {
56
+ const filterSet = new Set(filteredAgents);
57
+ resolvedAgents = resolvedAgents.filter((a) => filterSet.has(a));
58
+ } else if (filteredAgents) {
59
+ resolvedAgents = filteredAgents;
60
+ }
61
+ }
62
+ const recompileResult = await recompileAgents({
63
+ pluginDir: options.pluginDir ?? options.projectDir,
64
+ sourcePath: options.sourcePath,
65
+ agents: resolvedAgents,
66
+ skills: options.skills,
67
+ projectDir: options.projectDir,
68
+ outputDir: options.outputDir,
69
+ agentScopeMap: resolvedAgentScopeMap
70
+ });
71
+ await pruneStaleAgentsForPass(options, recompileResult);
72
+ return {
73
+ compiled: recompileResult.compiled,
74
+ failed: recompileResult.failed,
75
+ warnings: recompileResult.warnings
76
+ };
77
+ }
78
+ async function pruneStaleAgentsForPass(options, recompileResult) {
79
+ if (options.scopeFilter || !options.outputDir) return;
80
+ const compiledForDir = /* @__PURE__ */ new Set([
81
+ ...recompileResult.compiled,
82
+ ...recompileResult.failed
83
+ ]);
84
+ await pruneStaleCompiledAgents(options.outputDir, compiledForDir);
85
+ }
86
+
87
+ // src/cli/lib/operations/skills/index.ts
88
+ init_esm_shims();
89
+
90
+ // src/cli/lib/operations/skills/discover-skills.ts
91
+ init_esm_shims();
92
+ import os from "os";
93
+ import path from "path";
94
+ async function discoverLocalProjectSkills(rootDir) {
95
+ const localSkillsDir = path.join(rootDir, LOCAL_SKILLS_PATH);
96
+ return loadSkillsFromDir(localSkillsDir, {
97
+ pathPrefix: LOCAL_SKILLS_PATH,
98
+ requireMetadata: true
99
+ });
100
+ }
101
+ function mergeSkills(...skillSources) {
102
+ const merged = {};
103
+ for (const source of skillSources) {
104
+ for (const [id, skill] of typedEntries(source)) {
105
+ if (skill) {
106
+ merged[id] = skill;
107
+ }
108
+ }
109
+ }
110
+ return merged;
111
+ }
112
+ async function discoverInstalledSkills(projectDir) {
113
+ const isGlobalProject = isHomeDirectory(projectDir);
114
+ const globalPluginSkills = isGlobalProject ? {} : await discoverAllPluginSkills(os.homedir());
115
+ const globalPluginSkillCount = typedKeys(globalPluginSkills).length;
116
+ if (globalPluginSkillCount > 0) {
117
+ verbose(` Found ${globalPluginSkillCount} skills from global plugins`);
118
+ }
119
+ const globalLocalSkills = isGlobalProject ? {} : await discoverLocalProjectSkills(GLOBAL_INSTALL_ROOT);
120
+ const globalLocalSkillCount = typedKeys(globalLocalSkills).length;
121
+ if (globalLocalSkillCount > 0) {
122
+ verbose(` Found ${globalLocalSkillCount} global local skills from ~/.claude/skills/`);
123
+ }
124
+ const pluginSkills = await discoverAllPluginSkills(projectDir);
125
+ const pluginSkillCount = typedKeys(pluginSkills).length;
126
+ verbose(` Found ${pluginSkillCount} skills from installed plugins`);
127
+ const localSkills = await discoverLocalProjectSkills(projectDir);
128
+ const localSkillCount = typedKeys(localSkills).length;
129
+ verbose(` Found ${localSkillCount} local skills from .claude/skills/`);
130
+ const allSkills = mergeSkills(globalPluginSkills, globalLocalSkills, pluginSkills, localSkills);
131
+ const totalSkillCount = typedKeys(allSkills).length;
132
+ return {
133
+ allSkills,
134
+ totalSkillCount,
135
+ pluginSkillCount: globalPluginSkillCount + pluginSkillCount,
136
+ localSkillCount: globalLocalSkillCount + localSkillCount,
137
+ globalPluginSkillCount,
138
+ globalLocalSkillCount
139
+ };
140
+ }
141
+
142
+ // src/cli/lib/operations/skills/collect-scoped-skill-dirs.ts
143
+ init_esm_shims();
144
+ import os2 from "os";
145
+ import path2 from "path";
146
+ async function collectScopedSkillDirs(projectDir) {
147
+ const homeDir = os2.homedir();
148
+ const projectLocalPath = path2.join(projectDir, LOCAL_SKILLS_PATH);
149
+ const globalLocalPath = path2.join(homeDir, LOCAL_SKILLS_PATH);
150
+ const hasProject = await fileExists(projectLocalPath);
151
+ const hasGlobal = !isHomeDirectory(projectDir) && await fileExists(globalLocalPath);
152
+ const dirs = [];
153
+ if (hasProject) {
154
+ for (const dirName of await listDirectories(projectLocalPath)) {
155
+ dirs.push({ dirName, localSkillsPath: projectLocalPath, scope: "project" });
156
+ }
157
+ }
158
+ if (hasGlobal) {
159
+ const projectDirNames = new Set(dirs.map((d) => d.dirName));
160
+ for (const dirName of await listDirectories(globalLocalPath)) {
161
+ if (!projectDirNames.has(dirName)) {
162
+ dirs.push({ dirName, localSkillsPath: globalLocalPath, scope: "global" });
163
+ }
164
+ }
165
+ }
166
+ return { dirs, hasProject, hasGlobal, projectLocalPath, globalLocalPath };
167
+ }
168
+
169
+ // src/cli/lib/operations/skills/compare-skills.ts
170
+ init_esm_shims();
171
+ import os3 from "os";
172
+ function buildSourceSkillsMap(matrix) {
173
+ const sourceSkills = {};
174
+ for (const [skillId, skill] of typedEntries(matrix.skills)) {
175
+ if (!skill) continue;
176
+ if (!skill.local) {
177
+ sourceSkills[skillId] = { path: skill.path };
178
+ }
179
+ }
180
+ return sourceSkills;
181
+ }
182
+ async function compareSkillsWithSource(projectDir, sourcePath, matrix) {
183
+ const sourceSkills = buildSourceSkillsMap(matrix);
184
+ const { hasProject, hasGlobal } = await collectScopedSkillDirs(projectDir);
185
+ const homeDir = os3.homedir();
186
+ const projectResults = hasProject ? await compareLocalSkillsWithSource(projectDir, sourcePath, sourceSkills) : [];
187
+ const globalResults = hasGlobal ? await compareLocalSkillsWithSource(homeDir, sourcePath, sourceSkills) : [];
188
+ const seenIds = new Set(projectResults.map((r) => r.id));
189
+ const merged = [...projectResults, ...globalResults.filter((r) => !seenIds.has(r.id))];
190
+ return { projectResults, globalResults, merged };
191
+ }
192
+
193
+ // src/cli/lib/operations/skills/find-skill-match.ts
194
+ init_esm_shims();
195
+ function findSkillMatch(skillName, results) {
196
+ const exact = results.find((r) => r.id === skillName);
197
+ if (exact) return { match: exact, similar: [] };
198
+ const partial = results.find((r) => {
199
+ const nameWithoutAuthor = r.id.replace(/\s*\(@\w+\)$/, "").toLowerCase();
200
+ return nameWithoutAuthor === skillName.toLowerCase();
201
+ });
202
+ if (partial) return { match: partial, similar: [] };
203
+ const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());
204
+ if (byDir) return { match: byDir, similar: [] };
205
+ const lowered = skillName.toLowerCase();
206
+ const similar = results.filter((r) => {
207
+ const name = r.id.toLowerCase();
208
+ const dir = r.dirName.toLowerCase();
209
+ return name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(" ")[0]);
210
+ }).map((r) => r.id).slice(0, 3);
211
+ return { match: null, similar };
212
+ }
213
+
214
+ // src/cli/lib/operations/skills/install-plugin-skills.ts
215
+ init_esm_shims();
216
+ function pluginInstallFailureError(failedCount) {
217
+ return `Failed to install ${failedCount} plugin skill(s). Plugin install intent could not be honored. Verify the skill id matches the marketplace, re-run with --refresh to update the marketplace, or switch affected skills to eject mode.`;
218
+ }
219
+ async function installPluginSkills(skills, marketplace, projectDir) {
220
+ const pluginSkills = skills.filter((s) => s.source !== EJECT_SOURCE);
221
+ const installed = [];
222
+ const failed = [];
223
+ for (const skill of pluginSkills) {
224
+ const pluginRef = buildMarketplacePluginRef(skill.id, marketplace);
225
+ const pluginScope = toClaudePluginScope(skill.scope);
226
+ try {
227
+ await claudePluginInstall(pluginRef, pluginScope, projectDir);
228
+ installed.push({ id: skill.id, ref: pluginRef });
229
+ } catch (error) {
230
+ failed.push({ id: skill.id, error: getErrorMessage(error) });
231
+ }
232
+ }
233
+ return { installed, failed };
234
+ }
235
+
236
+ // src/cli/lib/operations/skills/uninstall-plugin-skills.ts
237
+ init_esm_shims();
238
+ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDir) {
239
+ const uninstalled = [];
240
+ const failed = [];
241
+ for (const skillId of skillIds) {
242
+ const oldSkill = oldSkills.find((s) => s.id === skillId);
243
+ const pluginScope = toClaudePluginScope(oldSkill?.scope);
244
+ const pluginRef = buildMarketplacePluginRef(skillId, marketplace);
245
+ try {
246
+ await claudePluginUninstall(pluginRef, pluginScope, projectDir);
247
+ uninstalled.push(skillId);
248
+ } catch (error) {
249
+ failed.push({ id: skillId, error: getErrorMessage(error) });
250
+ }
251
+ }
252
+ return { uninstalled, failed };
253
+ }
254
+
255
+ // src/cli/lib/operations/project/recompile-project-agents.ts
256
+ async function recompileRegisteredProjectAgents(projectDir) {
257
+ const { allSkills } = await discoverInstalledSkills(projectDir);
258
+ const { sourcePath } = await loadAgentDefs({ projectDir });
259
+ return compileAgents({
260
+ projectDir,
261
+ sourcePath,
262
+ skills: allSkills,
263
+ scopeFilter: "project",
264
+ outputDir: resolveInstallPaths(projectDir, "project").agentsDir
265
+ });
266
+ }
267
+ async function recompilePropagatedProjectAgents(projectDirs) {
268
+ let recompiledCount = 0;
269
+ let failedCount = 0;
270
+ const warnings = [];
271
+ for (const dir of projectDirs) {
272
+ try {
273
+ const result = await recompileRegisteredProjectAgents(dir);
274
+ if (result.failed.length > 0) {
275
+ failedCount++;
276
+ warnings.push(...result.warnings);
277
+ continue;
278
+ }
279
+ recompiledCount++;
280
+ } catch (error) {
281
+ failedCount++;
282
+ warnings.push(`Could not recompile agents in ${dir}: ${getErrorMessage(error)}`);
283
+ }
284
+ }
285
+ return { recompiledCount, failedCount, warnings };
286
+ }
287
+
288
+ export {
289
+ compileAgents,
290
+ discoverInstalledSkills,
291
+ collectScopedSkillDirs,
292
+ compareSkillsWithSource,
293
+ findSkillMatch,
294
+ pluginInstallFailureError,
295
+ installPluginSkills,
296
+ uninstallPluginSkills,
297
+ recompileRegisteredProjectAgents,
298
+ recompilePropagatedProjectAgents
299
+ };
300
+ //# sourceMappingURL=chunk-4R6PGHQQ.js.map