agents-inc 0.154.0 → 0.155.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 (213) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/chunk-2H7UWE2G.js +246 -0
  3. package/dist/chunk-2H7UWE2G.js.map +1 -0
  4. package/dist/{chunk-LA3JPESW.js → chunk-4A4L3YIW.js} +5 -5
  5. package/dist/chunk-4G2YHZIM.js +132 -0
  6. package/dist/chunk-4G2YHZIM.js.map +1 -0
  7. package/dist/{chunk-BZ4CZBOM.js → chunk-5F2YR5XV.js} +3 -3
  8. package/dist/{chunk-CHNA5RVS.js → chunk-5OKLCVM4.js} +3 -3
  9. package/dist/{chunk-ZU6DAR4S.js → chunk-5QZAK6J7.js} +7 -7
  10. package/dist/{chunk-ZU6DAR4S.js.map → chunk-5QZAK6J7.js.map} +1 -1
  11. package/dist/{chunk-NFH6SA62.js → chunk-6RLV45HN.js} +10 -10
  12. package/dist/{chunk-NFH6SA62.js.map → chunk-6RLV45HN.js.map} +1 -1
  13. package/dist/{chunk-GUDGCFSF.js → chunk-CLFHC2DK.js} +15 -106
  14. package/dist/chunk-CLFHC2DK.js.map +1 -0
  15. package/dist/chunk-D2CAV7MG.js +61 -0
  16. package/dist/chunk-D2CAV7MG.js.map +1 -0
  17. package/dist/{chunk-UW44KSYL.js → chunk-F2AMBBIA.js} +6 -6
  18. package/dist/{chunk-UW44KSYL.js.map → chunk-F2AMBBIA.js.map} +1 -1
  19. package/dist/{chunk-QQTYMW7N.js → chunk-F5T6TV4Z.js} +206 -73
  20. package/dist/chunk-F5T6TV4Z.js.map +1 -0
  21. package/dist/{chunk-K3O3YQYG.js → chunk-G47TDUK3.js} +2 -2
  22. package/dist/{chunk-AURY6RT6.js → chunk-GS2NZ3GD.js} +8 -8
  23. package/dist/chunk-GS2NZ3GD.js.map +1 -0
  24. package/dist/{chunk-5MFJ24VM.js → chunk-H6UTKTLK.js} +104 -250
  25. package/dist/chunk-H6UTKTLK.js.map +1 -0
  26. package/dist/{chunk-MJFIO5SX.js → chunk-HG4JPXJT.js} +11 -11
  27. package/dist/chunk-HG4JPXJT.js.map +1 -0
  28. package/dist/{chunk-IXEDSKMH.js → chunk-HTYH7CKN.js} +3 -3
  29. package/dist/{chunk-JC7DBPRD.js → chunk-HXKOIWLU.js} +2 -2
  30. package/dist/chunk-HXKOIWLU.js.map +1 -0
  31. package/dist/{chunk-NSJ2S7R5.js → chunk-ILUVL7WM.js} +2 -2
  32. package/dist/{chunk-R54KIGN2.js → chunk-IO5YBKHV.js} +13 -2
  33. package/dist/chunk-IO5YBKHV.js.map +1 -0
  34. package/dist/chunk-IXRZAHZF.js +53 -0
  35. package/dist/chunk-IXRZAHZF.js.map +1 -0
  36. package/dist/chunk-JCPANDNR.js +35 -0
  37. package/dist/chunk-JCPANDNR.js.map +1 -0
  38. package/dist/{chunk-NKCY2ULI.js → chunk-LJCNUP6M.js} +2 -2
  39. package/dist/{chunk-PRJD5MMQ.js → chunk-MHRC3KRX.js} +5 -5
  40. package/dist/chunk-MHRC3KRX.js.map +1 -0
  41. package/dist/chunk-MO5FGLVS.js +142 -0
  42. package/dist/chunk-MO5FGLVS.js.map +1 -0
  43. package/dist/{chunk-Q5FLW4JG.js → chunk-OKH64JZE.js} +2 -2
  44. package/dist/{chunk-WRRP47PY.js → chunk-PCC4LBKB.js} +2 -2
  45. package/dist/chunk-PMUABBPG.js +258 -0
  46. package/dist/chunk-PMUABBPG.js.map +1 -0
  47. package/dist/{chunk-2IMYK4WN.js → chunk-PNMM5HNX.js} +5 -5
  48. package/dist/{chunk-AKQ5QISO.js → chunk-QWVXOCXO.js} +6 -6
  49. package/dist/{chunk-IPJOMAWC.js → chunk-RWOYPOMR.js} +12 -2
  50. package/dist/{chunk-IPJOMAWC.js.map → chunk-RWOYPOMR.js.map} +1 -1
  51. package/dist/{chunk-ONWEOS77.js → chunk-SY4X2LND.js} +4 -4
  52. package/dist/{chunk-XGMOXMS4.js → chunk-TBOVYLQJ.js} +2 -2
  53. package/dist/{chunk-R7JV22QK.js → chunk-TNGMF4UX.js} +20 -20
  54. package/dist/{chunk-R7JV22QK.js.map → chunk-TNGMF4UX.js.map} +1 -1
  55. package/dist/{chunk-7VZV4O6B.js → chunk-UMH2YZKG.js} +14 -5
  56. package/dist/chunk-UMH2YZKG.js.map +1 -0
  57. package/dist/{chunk-6CNRMCFM.js → chunk-VPASBA7P.js} +2 -2
  58. package/dist/{chunk-CBF4ZYV3.js → chunk-WCAUUBHO.js} +1376 -741
  59. package/dist/chunk-WCAUUBHO.js.map +1 -0
  60. package/dist/{chunk-V3ENMW7G.js → chunk-WFRTHH3A.js} +3 -3
  61. package/dist/{chunk-DRKSYJZ2.js → chunk-WTJ3AY33.js} +1 -1
  62. package/dist/{chunk-DRKSYJZ2.js.map → chunk-WTJ3AY33.js.map} +1 -1
  63. package/dist/{chunk-XMEIVWAS.js → chunk-WUQ3MTPF.js} +11 -5
  64. package/dist/{chunk-XMEIVWAS.js.map → chunk-WUQ3MTPF.js.map} +1 -1
  65. package/dist/{chunk-4VCWL2IG.js → chunk-XAXJWXI4.js} +92 -59
  66. package/dist/chunk-XAXJWXI4.js.map +1 -0
  67. package/dist/{chunk-B66SC72V.js → chunk-Y5Y7XHVU.js} +4 -4
  68. package/dist/{chunk-FMYHWKGG.js → chunk-YO2LTXB4.js} +66 -16
  69. package/dist/chunk-YO2LTXB4.js.map +1 -0
  70. package/dist/{chunk-TUQF577Z.js → chunk-ZUAZHDKP.js} +40 -41
  71. package/dist/chunk-ZUAZHDKP.js.map +1 -0
  72. package/dist/commands/build/marketplace.js +98 -121
  73. package/dist/commands/build/marketplace.js.map +1 -1
  74. package/dist/commands/build/plugins.js +8 -8
  75. package/dist/commands/compile.js +19 -24
  76. package/dist/commands/compile.js.map +1 -1
  77. package/dist/commands/doctor.js +220 -79
  78. package/dist/commands/doctor.js.map +1 -1
  79. package/dist/commands/edit.js +549 -75
  80. package/dist/commands/edit.js.map +1 -1
  81. package/dist/commands/eject.js +26 -21
  82. package/dist/commands/eject.js.map +1 -1
  83. package/dist/commands/init.js +41 -39
  84. package/dist/commands/list.js +11 -11
  85. package/dist/commands/list.js.map +1 -1
  86. package/dist/commands/new/marketplace.js +243 -0
  87. package/dist/commands/new/marketplace.js.map +1 -0
  88. package/dist/commands/search.js +16 -14
  89. package/dist/commands/search.js.map +1 -1
  90. package/dist/commands/share.js +67 -0
  91. package/dist/commands/share.js.map +1 -0
  92. package/dist/commands/uninstall.js +61 -74
  93. package/dist/commands/uninstall.js.map +1 -1
  94. package/dist/commands/update.js +9 -9
  95. package/dist/commands/update.js.map +1 -1
  96. package/dist/components/common/prompt-confirm.js +1 -1
  97. package/dist/components/common/removal-plan-confirm.js +10 -0
  98. package/dist/components/common/select-list.js +2 -2
  99. package/dist/components/wizard/category-grid.js +5 -5
  100. package/dist/components/wizard/checkbox-grid.js +5 -5
  101. package/dist/components/wizard/domain-selection.js +11 -11
  102. package/dist/components/wizard/run-wizard-session.js +29 -28
  103. package/dist/components/wizard/scroll-affordance.js +2 -2
  104. package/dist/components/wizard/skill-agent-summary.js +6 -6
  105. package/dist/components/wizard/source-grid.js +6 -6
  106. package/dist/components/wizard/stack-selection.js +8 -8
  107. package/dist/components/wizard/step-agents.js +10 -11
  108. package/dist/components/wizard/step-build.js +9 -9
  109. package/dist/components/wizard/step-confirm.js +10 -10
  110. package/dist/components/wizard/step-sources.js +10 -10
  111. package/dist/components/wizard/step-stack.js +9 -9
  112. package/dist/components/wizard/summary-panel.js +9 -9
  113. package/dist/components/wizard/toast.js +2 -2
  114. package/dist/components/wizard/wizard-layout.js +14 -14
  115. package/dist/components/wizard/wizard-tabs.js +2 -2
  116. package/dist/components/wizard/wizard.js +27 -27
  117. package/dist/copy-local-skills-NSUTBVLJ.js +14 -0
  118. package/dist/hooks/init.js +42 -62
  119. package/dist/hooks/init.js.map +1 -1
  120. package/dist/load-agent-defs-X4E57I2U.js +15 -0
  121. package/dist/{loader-JIZDTR4G.js → loader-G6BFG2VA.js} +3 -3
  122. package/dist/recompile-project-agents-JE4MM72I.js +20 -0
  123. package/dist/{source-loader-OE6EJFPU.js → source-loader-3DL3NYUX.js} +7 -5
  124. package/dist/source-loader-3DL3NYUX.js.map +1 -0
  125. package/dist/src/agents/developer/ai-developer/critical-reminders.md +1 -1
  126. package/dist/src/agents/developer/ai-developer/critical-requirements.md +1 -1
  127. package/dist/src/agents/developer/ai-developer/identity.md +1 -1
  128. package/dist/src/agents/developer/ai-developer/playbook.md +1 -1
  129. package/dist/src/agents/developer/api-developer/identity.md +1 -1
  130. package/dist/src/agents/developer/cli-developer/identity.md +1 -1
  131. package/dist/src/agents/developer/web-developer/identity.md +1 -1
  132. package/dist/src/agents/meta/codex-keeper/identity.md +1 -1
  133. package/dist/src/agents/meta/convention-keeper/identity.md +1 -1
  134. package/dist/src/agents/meta/skill-summoner/identity.md +1 -1
  135. package/dist/src/agents/researcher/ai-researcher/identity.md +1 -1
  136. package/dist/src/agents/researcher/api-researcher/identity.md +1 -1
  137. package/dist/src/agents/researcher/cli-researcher/identity.md +1 -1
  138. package/dist/src/agents/researcher/web-researcher/identity.md +1 -1
  139. package/dist/src/agents/reviewer/reviewer/playbook.md +1 -1
  140. package/dist/src/agents/tester/ai-tester/identity.md +1 -1
  141. package/dist/src/agents/tester/api-tester/critical-reminders.md +1 -1
  142. package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -1
  143. package/dist/src/agents/tester/api-tester/identity.md +2 -2
  144. package/dist/src/agents/tester/cli-tester/identity.md +1 -1
  145. package/dist/src/agents/tester/web-tester/identity.md +3 -3
  146. package/dist/stores/wizard-store.js +7 -5
  147. package/package.json +10 -7
  148. package/src/agents/developer/ai-developer/critical-reminders.md +1 -1
  149. package/src/agents/developer/ai-developer/critical-requirements.md +1 -1
  150. package/src/agents/developer/ai-developer/identity.md +1 -1
  151. package/src/agents/developer/ai-developer/playbook.md +1 -1
  152. package/src/agents/developer/api-developer/identity.md +1 -1
  153. package/src/agents/developer/cli-developer/identity.md +1 -1
  154. package/src/agents/developer/web-developer/identity.md +1 -1
  155. package/src/agents/meta/codex-keeper/identity.md +1 -1
  156. package/src/agents/meta/convention-keeper/identity.md +1 -1
  157. package/src/agents/meta/skill-summoner/identity.md +1 -1
  158. package/src/agents/researcher/ai-researcher/identity.md +1 -1
  159. package/src/agents/researcher/api-researcher/identity.md +1 -1
  160. package/src/agents/researcher/cli-researcher/identity.md +1 -1
  161. package/src/agents/researcher/web-researcher/identity.md +1 -1
  162. package/src/agents/reviewer/reviewer/playbook.md +1 -1
  163. package/src/agents/tester/ai-tester/identity.md +1 -1
  164. package/src/agents/tester/api-tester/critical-reminders.md +1 -1
  165. package/src/agents/tester/api-tester/critical-requirements.md +1 -1
  166. package/src/agents/tester/api-tester/identity.md +2 -2
  167. package/src/agents/tester/cli-tester/identity.md +1 -1
  168. package/src/agents/tester/web-tester/identity.md +3 -3
  169. package/src/schemas/custom-metadata.schema.json +3 -0
  170. package/src/schemas/metadata.schema.json +3 -0
  171. package/src/schemas/project-config.schema.json +4 -8
  172. package/src/schemas/project-source-config.schema.json +2 -2
  173. package/dist/chunk-4VCWL2IG.js.map +0 -1
  174. package/dist/chunk-5MFJ24VM.js.map +0 -1
  175. package/dist/chunk-7VZV4O6B.js.map +0 -1
  176. package/dist/chunk-AURY6RT6.js.map +0 -1
  177. package/dist/chunk-CBF4ZYV3.js.map +0 -1
  178. package/dist/chunk-FMYHWKGG.js.map +0 -1
  179. package/dist/chunk-GUDGCFSF.js.map +0 -1
  180. package/dist/chunk-JC7DBPRD.js.map +0 -1
  181. package/dist/chunk-MJFIO5SX.js.map +0 -1
  182. package/dist/chunk-OJJLYHM3.js +0 -34
  183. package/dist/chunk-OJJLYHM3.js.map +0 -1
  184. package/dist/chunk-PRJD5MMQ.js.map +0 -1
  185. package/dist/chunk-QQTYMW7N.js.map +0 -1
  186. package/dist/chunk-QUDQTO3O.js +0 -41
  187. package/dist/chunk-QUDQTO3O.js.map +0 -1
  188. package/dist/chunk-R54KIGN2.js.map +0 -1
  189. package/dist/chunk-TUQF577Z.js.map +0 -1
  190. package/dist/copy-local-skills-WVHJFRPK.js +0 -14
  191. package/dist/load-agent-defs-5OT54J5M.js +0 -15
  192. package/dist/recompile-project-agents-VREEPBDV.js +0 -20
  193. /package/dist/{chunk-LA3JPESW.js.map → chunk-4A4L3YIW.js.map} +0 -0
  194. /package/dist/{chunk-BZ4CZBOM.js.map → chunk-5F2YR5XV.js.map} +0 -0
  195. /package/dist/{chunk-CHNA5RVS.js.map → chunk-5OKLCVM4.js.map} +0 -0
  196. /package/dist/{chunk-K3O3YQYG.js.map → chunk-G47TDUK3.js.map} +0 -0
  197. /package/dist/{chunk-IXEDSKMH.js.map → chunk-HTYH7CKN.js.map} +0 -0
  198. /package/dist/{chunk-NSJ2S7R5.js.map → chunk-ILUVL7WM.js.map} +0 -0
  199. /package/dist/{chunk-NKCY2ULI.js.map → chunk-LJCNUP6M.js.map} +0 -0
  200. /package/dist/{chunk-Q5FLW4JG.js.map → chunk-OKH64JZE.js.map} +0 -0
  201. /package/dist/{chunk-WRRP47PY.js.map → chunk-PCC4LBKB.js.map} +0 -0
  202. /package/dist/{chunk-2IMYK4WN.js.map → chunk-PNMM5HNX.js.map} +0 -0
  203. /package/dist/{chunk-AKQ5QISO.js.map → chunk-QWVXOCXO.js.map} +0 -0
  204. /package/dist/{chunk-ONWEOS77.js.map → chunk-SY4X2LND.js.map} +0 -0
  205. /package/dist/{chunk-XGMOXMS4.js.map → chunk-TBOVYLQJ.js.map} +0 -0
  206. /package/dist/{chunk-6CNRMCFM.js.map → chunk-VPASBA7P.js.map} +0 -0
  207. /package/dist/{chunk-V3ENMW7G.js.map → chunk-WFRTHH3A.js.map} +0 -0
  208. /package/dist/{chunk-B66SC72V.js.map → chunk-Y5Y7XHVU.js.map} +0 -0
  209. /package/dist/{copy-local-skills-WVHJFRPK.js.map → components/common/removal-plan-confirm.js.map} +0 -0
  210. /package/dist/{load-agent-defs-5OT54J5M.js.map → copy-local-skills-NSUTBVLJ.js.map} +0 -0
  211. /package/dist/{loader-JIZDTR4G.js.map → load-agent-defs-X4E57I2U.js.map} +0 -0
  212. /package/dist/{recompile-project-agents-VREEPBDV.js.map → loader-G6BFG2VA.js.map} +0 -0
  213. /package/dist/{source-loader-OE6EJFPU.js.map → recompile-project-agents-JE4MM72I.js.map} +0 -0
@@ -1,99 +1,136 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- Spinner
4
- } from "../chunk-ZBPEFQ4G.js";
3
+ publishSeedConfig,
4
+ seedPayloadForInstallation,
5
+ skillsAuthoredHere
6
+ } from "../chunk-2H7UWE2G.js";
7
+ import {
8
+ RemovalPlanConfirm
9
+ } from "../chunk-D2CAV7MG.js";
10
+ import "../chunk-OZXAJNLA.js";
11
+ import {
12
+ seedToWizardResult
13
+ } from "../chunk-MO5FGLVS.js";
5
14
  import {
6
15
  runWizardSession
7
- } from "../chunk-QUDQTO3O.js";
8
- import "../chunk-R7JV22QK.js";
9
- import "../chunk-MJFIO5SX.js";
10
- import "../chunk-NSJ2S7R5.js";
11
- import "../chunk-JC7DBPRD.js";
12
- import "../chunk-GUDGCFSF.js";
13
- import "../chunk-BZ4CZBOM.js";
14
- import "../chunk-NKCY2ULI.js";
15
- import "../chunk-NFH6SA62.js";
16
- import "../chunk-IXEDSKMH.js";
17
- import "../chunk-AURY6RT6.js";
18
- import "../chunk-WRRP47PY.js";
19
- import "../chunk-2IMYK4WN.js";
16
+ } from "../chunk-IXRZAHZF.js";
17
+ import "../chunk-TNGMF4UX.js";
18
+ import "../chunk-LJCNUP6M.js";
19
+ import "../chunk-HTYH7CKN.js";
20
+ import "../chunk-PCC4LBKB.js";
21
+ import "../chunk-HG4JPXJT.js";
22
+ import "../chunk-6RLV45HN.js";
23
+ import "../chunk-ILUVL7WM.js";
24
+ import "../chunk-HXKOIWLU.js";
25
+ import "../chunk-QWVXOCXO.js";
26
+ import "../chunk-GS2NZ3GD.js";
27
+ import "../chunk-VPASBA7P.js";
28
+ import "../chunk-PNMM5HNX.js";
29
+ import "../chunk-CLFHC2DK.js";
30
+ import "../chunk-5OKLCVM4.js";
31
+ import "../chunk-5F2YR5XV.js";
20
32
  import "../chunk-TSIU7DME.js";
21
33
  import "../chunk-XVAQG2CV.js";
22
- import "../chunk-LA3JPESW.js";
34
+ import {
35
+ Spinner
36
+ } from "../chunk-ZBPEFQ4G.js";
37
+ import "../chunk-4A4L3YIW.js";
23
38
  import "../chunk-J27W6TXS.js";
24
- import "../chunk-AKQ5QISO.js";
25
- import "../chunk-CHNA5RVS.js";
26
- import "../chunk-ONWEOS77.js";
27
- import "../chunk-V3ENMW7G.js";
28
- import "../chunk-DRKSYJZ2.js";
29
- import "../chunk-Q5FLW4JG.js";
30
- import "../chunk-6CNRMCFM.js";
39
+ import "../chunk-SY4X2LND.js";
40
+ import "../chunk-WFRTHH3A.js";
41
+ import "../chunk-WTJ3AY33.js";
42
+ import "../chunk-OKH64JZE.js";
43
+ import {
44
+ fetchSeedConfig,
45
+ registerExternalSkills,
46
+ writeExternalSkills
47
+ } from "../chunk-PMUABBPG.js";
48
+ import {
49
+ promptConfirm
50
+ } from "../chunk-JCPANDNR.js";
31
51
  import {
32
52
  compileAgentsAllScopes,
33
53
  detectProject,
34
54
  loadSource,
35
55
  writeProjectConfig
36
- } from "../chunk-XMEIVWAS.js";
56
+ } from "../chunk-WUQ3MTPF.js";
37
57
  import {
38
58
  discoverInstalledSkills,
39
59
  removeCompiledAgents,
40
60
  uninstallPluginSkills
41
- } from "../chunk-ZU6DAR4S.js";
42
- import {
43
- copyLocalSkills
44
- } from "../chunk-UW44KSYL.js";
61
+ } from "../chunk-5QZAK6J7.js";
45
62
  import {
46
63
  loadAgentDefs
47
- } from "../chunk-PRJD5MMQ.js";
48
- import "../chunk-TUQF577Z.js";
49
- import "../chunk-B66SC72V.js";
64
+ } from "../chunk-MHRC3KRX.js";
65
+ import {
66
+ copyLocalSkills
67
+ } from "../chunk-F2AMBBIA.js";
68
+ import "../chunk-ZUAZHDKP.js";
69
+ import "../chunk-Y5Y7XHVU.js";
50
70
  import {
51
71
  render
52
72
  } from "../chunk-JFLVEFFP.js";
53
73
  import {
54
- formatScopeTag
55
- } from "../chunk-QQTYMW7N.js";
74
+ formatScopeTag,
75
+ orderDomains
76
+ } from "../chunk-F5T6TV4Z.js";
56
77
  import {
57
78
  BaseCommand,
58
79
  EXIT_CODES
59
- } from "../chunk-FMYHWKGG.js";
60
- import "../chunk-7VZV4O6B.js";
61
- import "../chunk-K3O3YQYG.js";
80
+ } from "../chunk-YO2LTXB4.js";
81
+ import "../chunk-UMH2YZKG.js";
82
+ import "../chunk-G47TDUK3.js";
62
83
  import {
63
84
  ERROR_MESSAGES,
64
85
  INFO_MESSAGES,
65
86
  INSTALL_MODE_DESCRIPTIONS,
87
+ SHARED_CONFIG_APPLY,
88
+ SHARED_CONFIG_ONE_DIRECTION,
66
89
  STATUS_MESSAGES,
67
90
  activeAgentNames,
68
91
  activeAgentScopeMap,
69
92
  applyMigratedGlobalSources,
93
+ authoredHereKept,
70
94
  buildMarketplacePluginRef,
95
+ carriedSkillsWritten,
71
96
  claudePluginInstall,
72
97
  claudePluginUninstall,
73
98
  deleteLocalSkill,
74
99
  detectMigrations,
75
100
  discoverAllPluginSkills,
101
+ ejectCopyFailureError,
102
+ execCommand,
76
103
  executeMigration,
104
+ globallyInstalledRemoved,
77
105
  installBaseDir,
78
106
  isActiveAt,
79
107
  isHomeDirectory,
108
+ loadProjectConfigFromDir,
80
109
  localSkillsCopied,
81
110
  migrateLocalSkillScope,
82
111
  mutateGlobal,
112
+ normalizeProjectPath,
83
113
  recompileSummary,
84
114
  resolveInstallPaths,
115
+ sharedConfigDestinations,
116
+ sharedConfigNeedsTerminal,
117
+ skippedUnknownAgents,
118
+ skippedUnknownSkills,
85
119
  toClaudePluginScope,
120
+ unplaceableKept,
86
121
  unresolvedSkillRemovalReasons
87
- } from "../chunk-CBF4ZYV3.js";
122
+ } from "../chunk-WCAUUBHO.js";
88
123
  import {
89
124
  getErrorMessage
90
- } from "../chunk-4VCWL2IG.js";
125
+ } from "../chunk-XAXJWXI4.js";
91
126
  import {
127
+ getCategoryDomain,
92
128
  getSkillById,
93
129
  getSkillDisplayName,
94
130
  matrix
95
- } from "../chunk-IPJOMAWC.js";
131
+ } from "../chunk-RWOYPOMR.js";
96
132
  import {
133
+ typedEntries,
97
134
  typedKeys
98
135
  } from "../chunk-VASLW636.js";
99
136
  import {
@@ -101,15 +138,121 @@ import {
101
138
  CLI_INVOKE_COMMAND,
102
139
  EDIT_PROJECT_SETUP_FLAG,
103
140
  EJECT_SOURCE,
141
+ editorConfigUrl,
104
142
  formatSourceDisplayName
105
- } from "../chunk-R54KIGN2.js";
143
+ } from "../chunk-IO5YBKHV.js";
106
144
  import "../chunk-VZRO7RYT.js";
107
145
 
108
146
  // src/cli/commands/edit.tsx
147
+ import os from "os";
109
148
  import path from "path";
110
149
  import chalk from "chalk";
111
150
  import { Flags } from "@oclif/core";
112
- import { difference, indexBy } from "remeda";
151
+ import { difference, indexBy, partition } from "remeda";
152
+
153
+ // src/cli/lib/seed/seed-apply.ts
154
+ var NOTHING_KEPT = {
155
+ authoredSkillIds: [],
156
+ unplaceableSkillIds: []
157
+ };
158
+ function reconcileSharedConfig(options) {
159
+ const { decoded, installed } = options;
160
+ if (!installed) return { result: decoded, kept: NOTHING_KEPT };
161
+ const keptSkills = skillsToKeep(options, installed);
162
+ if (keptSkills.length === 0) return { result: decoded, kept: NOTHING_KEPT };
163
+ return {
164
+ result: withKeptEntries(decoded, installed, keptSkills),
165
+ kept: describeKept(options, keptSkills)
166
+ };
167
+ }
168
+ function skillsToKeep(options, installed) {
169
+ const named = new Set(options.decoded.skills.map((skill) => skill.id));
170
+ return installed.skills.filter(
171
+ (skill) => !skill.excluded && !named.has(skill.id) && mayNotRemove(skill, options)
172
+ );
173
+ }
174
+ function mayNotRemove(skill, options) {
175
+ return options.authoredHere.has(skill.id) || options.unplaceable.has(skill.id);
176
+ }
177
+ function describeKept(options, keptSkills) {
178
+ const idsKeptFor = (reason) => keptSkills.filter((skill) => reasonKept(skill, options) === reason).map((skill) => skill.id);
179
+ return {
180
+ authoredSkillIds: idsKeptFor("authored"),
181
+ unplaceableSkillIds: idsKeptFor("unplaceable")
182
+ };
183
+ }
184
+ function reasonKept(skill, options) {
185
+ return options.authoredHere.has(skill.id) ? "authored" : "unplaceable";
186
+ }
187
+ function withKeptEntries(decoded, installed, keptSkills) {
188
+ return {
189
+ ...decoded,
190
+ skills: [...decoded.skills, ...keptSkills],
191
+ selectedDomains: withKeptDomains(decoded.selectedDomains, keptSkills),
192
+ ...decoded.assignedStack !== void 0 && {
193
+ assignedStack: withKeptStackRows(decoded.assignedStack, installed.stack, {
194
+ keptSkillIds: new Set(keptSkills.map((skill) => skill.id)),
195
+ survivingAgents: new Set(decoded.selectedAgents)
196
+ })
197
+ }
198
+ };
199
+ }
200
+ function withKeptDomains(selected, keptSkills) {
201
+ const keptDomains = keptSkills.flatMap((skill) => domainOfSkill(skill.id) ?? []);
202
+ const missing = keptDomains.filter((domain) => !selected.includes(domain));
203
+ if (missing.length === 0) return selected;
204
+ return orderDomains([...selected, ...new Set(missing)]);
205
+ }
206
+ function domainOfSkill(skillId) {
207
+ const category = matrix.skills[skillId]?.category;
208
+ return category === void 0 ? void 0 : getCategoryDomain(category);
209
+ }
210
+ function withKeptStackRows(assigned, installedStack, filter) {
211
+ if (!installedStack) return assigned;
212
+ const carried = { ...assigned };
213
+ for (const [agent, agentStack] of typedEntries(installedStack)) {
214
+ if (!filter.survivingAgents.has(agent)) continue;
215
+ const rows = keptRowsFor(agentStack, filter.keptSkillIds);
216
+ if (typedKeys(rows).length === 0) continue;
217
+ carried[agent] = { ...carried[agent], ...rows };
218
+ }
219
+ return carried;
220
+ }
221
+ function keptRowsFor(agentStack, keptSkillIds) {
222
+ const rows = {};
223
+ for (const [category, assignments] of typedEntries(agentStack)) {
224
+ const carried = assignments.filter((assignment) => keptSkillIds.has(assignment.id));
225
+ if (carried.length > 0) rows[category] = carried;
226
+ }
227
+ return rows;
228
+ }
229
+
230
+ // src/cli/utils/open-url.ts
231
+ function browserOpenerCommand(platform, url) {
232
+ if (platform === "darwin") return { command: "open", args: [url] };
233
+ if (platform === "win32") return { command: "cmd", args: ["/c", "start", "", url] };
234
+ return { command: "xdg-open", args: [url] };
235
+ }
236
+ function openerRefusedMessage(command, exitCode) {
237
+ return `Could not open your browser \u2014 '${command}' exited ${exitCode}.`;
238
+ }
239
+ function openerUnavailableMessage(command, reason) {
240
+ return `Could not open your browser \u2014 '${command}' could not be run: ${reason}`;
241
+ }
242
+ async function openUrl(url) {
243
+ const { command, args } = browserOpenerCommand(process.platform, url);
244
+ try {
245
+ const result = await execCommand(command, args);
246
+ if (result.exitCode !== 0) {
247
+ return { ok: false, error: openerRefusedMessage(command, result.exitCode) };
248
+ }
249
+ return { ok: true };
250
+ } catch (error) {
251
+ return { ok: false, error: openerUnavailableMessage(command, getErrorMessage(error)) };
252
+ }
253
+ }
254
+
255
+ // src/cli/commands/edit.tsx
113
256
  import { jsx } from "react/jsx-runtime";
114
257
  var RECOMPILE_SUBJECT = "agents";
115
258
  function formatDualScopeTransition(displayName, to) {
@@ -141,6 +284,71 @@ function scopeArrow(change) {
141
284
  function loadedSourceLabel(sourceResult) {
142
285
  return sourceResult.marketplace ?? sourceResult.sourceConfig.source;
143
286
  }
287
+ function globalScopePlan(changes, kept) {
288
+ const sections = removalSections(changes.removedSkills, changes.removedAgents);
289
+ return { heading: planHeading(sections), sections, statements: kept };
290
+ }
291
+ function projectScopePlan(changes, kept, installed, otherProjects) {
292
+ const { here, global } = splitRemovalsByScope(changes, installed);
293
+ const sections = [
294
+ ...removalSections(here.skills, here.agents),
295
+ ...globalRemovalSections(global.skills, global.agents)
296
+ ];
297
+ return {
298
+ heading: planHeading(sections),
299
+ sections,
300
+ statements: [...globalReachStatement(global, otherProjects), ...kept]
301
+ };
302
+ }
303
+ function splitRemovalsByScope(changes, installed) {
304
+ const isGlobalSkill = (id) => installed.skills.some((skill) => skill.id === id && isActiveAt(skill, "global"));
305
+ const isGlobalAgent = (name) => installed.agents.some((agent) => agent.name === name && isActiveAt(agent, "global"));
306
+ const [globalSkills, projectSkills] = partition(changes.removedSkills, isGlobalSkill);
307
+ const [globalAgents, projectAgents] = partition(changes.removedAgents, isGlobalAgent);
308
+ return {
309
+ here: { skills: projectSkills, agents: projectAgents },
310
+ global: { skills: globalSkills, agents: globalAgents }
311
+ };
312
+ }
313
+ function removalSections(skills, agents) {
314
+ return [
315
+ { label: SHARED_CONFIG_APPLY.SKILLS_HEADING, items: skills.map(skillLabel) },
316
+ { label: SHARED_CONFIG_APPLY.AGENTS_HEADING, items: [...agents] }
317
+ ].filter((section) => section.items.length > 0);
318
+ }
319
+ function globalRemovalSections(skills, agents) {
320
+ return [
321
+ { label: SHARED_CONFIG_APPLY.GLOBAL_SKILLS_HEADING, items: skills.map(skillLabel) },
322
+ { label: SHARED_CONFIG_APPLY.GLOBAL_AGENTS_HEADING, items: [...agents] }
323
+ ].filter((section) => section.items.length > 0);
324
+ }
325
+ function globalReachStatement(global, otherProjects) {
326
+ if (global.skills.length === 0 && global.agents.length === 0) return [];
327
+ return [globallyInstalledRemoved(otherProjects)];
328
+ }
329
+ function planHeading(sections) {
330
+ if (sections.length === 0) return SHARED_CONFIG_APPLY.NOTHING_REMOVED;
331
+ return SHARED_CONFIG_APPLY.PREVIEW_HEADING;
332
+ }
333
+ function skillLabel(skillId) {
334
+ const displayName = getSkillDisplayName(skillId);
335
+ return displayName === skillId ? skillId : `${displayName} (${skillId})`;
336
+ }
337
+ function keptStatements(kept) {
338
+ return [...authorshipStatement(kept), ...catalogueStatement(kept)];
339
+ }
340
+ function authorshipStatement(kept) {
341
+ if (kept.authoredSkillIds.length === 0) return [];
342
+ return [authoredHereKept(kept.authoredSkillIds)];
343
+ }
344
+ function catalogueStatement(kept) {
345
+ if (kept.unplaceableSkillIds.length === 0) return [];
346
+ return [unplaceableKept(kept.unplaceableSkillIds)];
347
+ }
348
+ function applyAuthority(producer, cwd) {
349
+ if (isHomeDirectory(cwd)) return "all";
350
+ return producer === "shared" ? "all" : "owned";
351
+ }
144
352
  var Edit = class _Edit extends BaseCommand {
145
353
  static summary = "Edit skills in the plugin";
146
354
  static description = "Modify the currently installed skills via interactive wizard";
@@ -148,9 +356,25 @@ var Edit = class _Edit extends BaseCommand {
148
356
  {
149
357
  description: "Open the edit wizard",
150
358
  command: "<%= config.bin %> <%= command.id %>"
359
+ },
360
+ {
361
+ description: "Open this installation in the editor instead of the wizard",
362
+ command: "<%= config.bin %> <%= command.id %> --ui"
363
+ },
364
+ {
365
+ description: "Apply a configuration built in the editor, by its id",
366
+ command: "<%= config.bin %> <%= command.id %> --from <id>"
151
367
  }
152
368
  ];
153
369
  static flags = {
370
+ ui: Flags.boolean({
371
+ description: "Edit this installation in the browser at agentsinc.sh instead of the wizard",
372
+ default: false
373
+ }),
374
+ from: Flags.string({
375
+ description: "Apply a configuration shared from agentsinc.sh by its id, removing whatever it leaves out",
376
+ helpValue: "<id>"
377
+ }),
154
378
  [EDIT_PROJECT_SETUP_FLAG]: Flags.boolean({
155
379
  description: "Internal: this run continues an `init` project setup",
156
380
  default: false,
@@ -161,14 +385,20 @@ var Edit = class _Edit extends BaseCommand {
161
385
  const { flags } = await this.parse(_Edit);
162
386
  const cwd = process.cwd();
163
387
  await this.ensureConfigReadable(cwd);
388
+ if (flags.ui && flags.from !== void 0) {
389
+ this.error(SHARED_CONFIG_ONE_DIRECTION, { exit: EXIT_CODES.ERROR });
390
+ }
391
+ if (flags.ui) return this.openInEditor(cwd);
392
+ const payload = flags.from === void 0 ? null : await this.fetchSharedConfigOrFail(flags.from);
164
393
  const context = await this.loadContextUnderSpinner();
165
394
  await this.ensureSavedSkillsReadable(
166
395
  context.projectConfig?.skills ?? [],
167
396
  context.sourceResult.matrix,
168
397
  context.projectDir
169
398
  );
170
- const result = await this.runEditWizard(context, cwd);
171
- if (!result) this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
399
+ const selection = payload ? await this.selectionFromSharedConfig(payload, context, cwd) : await this.selectionFromWizard(context, cwd);
400
+ if (!selection) this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
401
+ const { result } = selection;
172
402
  this.reportValidationErrors(result.validation);
173
403
  const activeNewSkills = result.skills.filter((s) => !s.excluded);
174
404
  const activeNewAgents = result.agentConfigs.filter((a) => !a.excluded);
@@ -187,10 +417,20 @@ var Edit = class _Edit extends BaseCommand {
187
417
  oldAgents: context.projectConfig?.agents ?? []
188
418
  });
189
419
  const isProjectSetup = flags[EDIT_PROJECT_SETUP_FLAG] && !isHomeDirectory(cwd);
420
+ if (selection.producer === "shared") {
421
+ await this.confirmSharedConfigOrCancel(
422
+ changes,
423
+ selection.kept,
424
+ { skills: activeOldSkills, agents: activeOldAgents },
425
+ cwd
426
+ );
427
+ await this.writeCarriedSkills(selection.carried);
428
+ }
429
+ const authority = applyAuthority(selection.producer, cwd);
190
430
  if (!hasAnyChanges(changes)) {
191
431
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)("No changes made."));
192
432
  if (!isProjectSetup) return;
193
- await this.writeConfigAndCompile(result, context, cwd);
433
+ await this.writeConfigAndCompile(result, context, cwd, authority);
194
434
  this.logCompletionSummary(changes);
195
435
  return;
196
436
  }
@@ -219,10 +459,220 @@ var Edit = class _Edit extends BaseCommand {
219
459
  await this.applyPluginChanges(changes, filteredResult, activeOldSkills, context, cwd);
220
460
  await this.copyNewLocalSkills(changes, filteredResult, context, cwd);
221
461
  await this.removeDeletedLocalSkills(changes, activeOldSkills, cwd);
222
- await this.writeConfigAndCompile(result, context, cwd);
462
+ await this.writeConfigAndCompile(result, context, cwd, authority);
223
463
  await this.cleanupStaleAgentFiles(changes, activeOldAgents, cwd);
224
464
  this.logCompletionSummary(changes);
225
465
  }
466
+ /** The interactive producer: open the wizard on what is installed, return what was chosen. */
467
+ async selectionFromWizard(context, cwd) {
468
+ const result = await this.runEditWizard(context, cwd);
469
+ if (!result) return null;
470
+ return { producer: "wizard", result };
471
+ }
472
+ /**
473
+ * The `--from <id>` producer: fetch, seat what the configuration carries, decode, and put back
474
+ * what this run has no authority to remove.
475
+ *
476
+ * Everything a shared configuration says is a statement about the whole roster, so the apply
477
+ * that follows is destructive — the project is made to MATCH it. Two exceptions come back into
478
+ * the result: a skill written here, which the producer drops on the way out because
479
+ * `forkedFrom` says the CLI never wrote it, and an id the configuration NAMES that this
480
+ * catalogue cannot place, because a destructive apply removes on intent and never on its own
481
+ * inability. Both are disclosed in the confirm rather than silently excused.
482
+ *
483
+ * A globally installed entry is NOT one of them. It is removable from here, and what its scope
484
+ * changes is who the removal reaches — which the confirm names, rather than this putting the
485
+ * entry back and calling the reach impossible.
486
+ */
487
+ async selectionFromSharedConfig(payload, context, cwd) {
488
+ const { matrix: sourceMatrix } = context.sourceResult;
489
+ const carried = this.registerExternalSkillsOrFail(payload, sourceMatrix, cwd);
490
+ const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(
491
+ payload,
492
+ sourceMatrix
493
+ );
494
+ this.refuseProjectScopedContentAtHome(result, cwd);
495
+ if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));
496
+ if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));
497
+ const reconciled = reconcileSharedConfig({
498
+ decoded: result,
499
+ installed: context.projectConfig,
500
+ authoredHere: await this.readAuthoredHere(context.projectConfig, cwd),
501
+ // The ids the decode above could not place. They are the skips just reported, read as
502
+ // what STAYS rather than as what did not arrive: the payload named them, so their absence
503
+ // from the decode is this catalogue's limit and not an instruction to delete anything.
504
+ unplaceable: new Set(skippedSkillIds)
505
+ });
506
+ return {
507
+ producer: "shared",
508
+ result: reconciled.result,
509
+ kept: keptStatements(reconciled.kept),
510
+ carried
511
+ };
512
+ }
513
+ /**
514
+ * Which installed skills the round trip does not own, asked of the disk exactly as the
515
+ * producing half asks it.
516
+ *
517
+ * Best-effort by nature and never fatal: the question is only ever asked to PROTECT a skill,
518
+ * so a directory that cannot be read protects nothing and must not fail an apply. The
519
+ * consequence of an unanswered question is that the entry is treated as the CLI's own, which
520
+ * is what every other command already assumes about it.
521
+ */
522
+ async readAuthoredHere(projectConfig, cwd) {
523
+ if (!projectConfig) return /* @__PURE__ */ new Set();
524
+ try {
525
+ return await skillsAuthoredHere(projectConfig, cwd);
526
+ } catch (error) {
527
+ this.warn(`Could not tell which skills were written here: ${getErrorMessage(error)}`);
528
+ return /* @__PURE__ */ new Set();
529
+ }
530
+ }
531
+ /**
532
+ * The id, fetched — or the run refused before it is.
533
+ *
534
+ * The terminal question is answered first because nothing in the payload can change its
535
+ * answer: an apply that cannot be confirmed is over before the store is asked, and a refusal
536
+ * that had already spent a round trip would be describing work it never intended to do.
537
+ */
538
+ async fetchSharedConfigOrFail(id) {
539
+ if (!process.stdin.isTTY) {
540
+ this.error(sharedConfigNeedsTerminal(id), { exit: EXIT_CODES.ERROR });
541
+ }
542
+ this.log(`Fetching configuration ${id}...`);
543
+ const fetched = await fetchSeedConfig(id);
544
+ if (!fetched.ok) {
545
+ this.error(fetched.error, { exit: EXIT_CODES.ERROR });
546
+ }
547
+ return fetched.payload;
548
+ }
549
+ /**
550
+ * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).
551
+ * That is a failure of this command, reported with this command's exit code rather than left to
552
+ * surface as an unhandled throw.
553
+ */
554
+ decodeSeedOrFail(payload, sourceMatrix) {
555
+ try {
556
+ return seedToWizardResult(payload, sourceMatrix);
557
+ } catch (error) {
558
+ this.handleError(error);
559
+ }
560
+ }
561
+ /**
562
+ * Seats the catalogue entries the payload carries with it, or refuses the run. The refusal is
563
+ * `registerExternalSkills`' own — a carried skill asked for as a plugin, which no marketplace
564
+ * serves — reported with this command's exit code for the same reason the decode's is.
565
+ */
566
+ registerExternalSkillsOrFail(payload, sourceMatrix, projectDir) {
567
+ try {
568
+ return registerExternalSkills(payload, sourceMatrix, projectDir);
569
+ } catch (error) {
570
+ this.handleError(error);
571
+ }
572
+ }
573
+ /** Writes the skills the configuration brought with it, and says which they were. */
574
+ async writeCarriedSkills(carried) {
575
+ if (carried.length === 0) return;
576
+ await writeExternalSkills(carried);
577
+ this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));
578
+ }
579
+ /**
580
+ * Shows what applying this configuration takes away, and stops the run unless a person says
581
+ * yes.
582
+ *
583
+ * The plan is built from the SAME `ConfigChanges` the apply below acts on, so what is approved
584
+ * and what is removed are one value read twice. Its kept half is the other side of the same
585
+ * honesty: nothing is refused over an entry this run cannot remove, and nothing is silent
586
+ * about one either.
587
+ *
588
+ * WHICH plan is built is decided here and only here, on the directory the run was started in.
589
+ * Inside the global installation the scope was chosen and is obvious, so the ordinary confirm
590
+ * is the whole of the gate; inside a project a global removal reaches projects nobody here is
591
+ * looking at, so it is shown apart and the reach is named.
592
+ */
593
+ async confirmSharedConfigOrCancel(changes, kept, installed, cwd) {
594
+ const plan = isHomeDirectory(cwd) ? globalScopePlan(changes, kept) : projectScopePlan(changes, kept, installed, await this.otherRegisteredProjects(cwd));
595
+ const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(
596
+ RemovalPlanConfirm,
597
+ {
598
+ heading: plan.heading,
599
+ sections: plan.sections,
600
+ statements: plan.statements,
601
+ message: SHARED_CONFIG_APPLY.CONFIRM,
602
+ onConfirm,
603
+ onCancel
604
+ }
605
+ ));
606
+ if (outcome === "confirmed") return;
607
+ this.log("\nEdit cancelled");
608
+ this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
609
+ }
610
+ /**
611
+ * Every registered project but this one — the blast radius a global removal actually has.
612
+ *
613
+ * Read from the GLOBAL config rather than from `context.projectConfig`: `projects[]` is the
614
+ * registry the fan-out itself walks, and a project's own config never carries it, so taking
615
+ * the list from anywhere else would let the confirm name a set the propagation does not.
616
+ *
617
+ * Best-effort by nature. The list exists to be DISCLOSED, so a home directory that cannot be
618
+ * read leaves the disclosure counting nobody rather than failing an apply — and the statement
619
+ * it produces then is the one that says no other project is registered.
620
+ */
621
+ async otherRegisteredProjects(cwd) {
622
+ try {
623
+ const global = await loadProjectConfigFromDir(os.homedir());
624
+ const here = normalizeProjectPath(cwd);
625
+ return (global?.config.projects ?? []).filter((projectDir) => projectDir !== here);
626
+ } catch (error) {
627
+ this.warn(`Could not tell which projects share this install: ${getErrorMessage(error)}`);
628
+ return [];
629
+ }
630
+ }
631
+ /**
632
+ * The outbound half of the editor round trip: this installation, minted as a configuration
633
+ * the editor opens, and handed to a browser.
634
+ *
635
+ * It is the same mint `share` performs — same reader, same mapping, same refusals, through
636
+ * `seedPayloadForInstallation` — because an id is the whole of what either command produces
637
+ * and two spellings of "the installation in this directory" would mint two different ids for
638
+ * one project. What differs is only the ending: `share` reports the id, this opens it.
639
+ *
640
+ * Nothing on disk is touched. A configuration is read, not rewritten, so a run that changed
641
+ * anything here would be editing the project on the way to offering to edit it.
642
+ */
643
+ async openInEditor(projectDir) {
644
+ const prepared = await seedPayloadForInstallation(projectDir);
645
+ if (!prepared.ok) {
646
+ this.error(prepared.error, { exit: EXIT_CODES.ERROR });
647
+ }
648
+ this.log(`Opening ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);
649
+ const published = await publishSeedConfig(prepared.payload);
650
+ if (!published.ok) {
651
+ this.error(published.error, { exit: EXIT_CODES.ERROR });
652
+ }
653
+ await this.handToBrowser(published.id);
654
+ }
655
+ /**
656
+ * The link, printed first and opened second.
657
+ *
658
+ * Printed first because it is the only part of this that works everywhere: over a pipe, in CI
659
+ * and on a machine with no desktop session there is no browser to be anybody's, and a link
660
+ * nobody can copy is the whole loss. Opening one is the convenience on top, so a failure to
661
+ * open is a warning beside a link that still works rather than a failed command.
662
+ *
663
+ * `process.stdin.isTTY` is the same question `init`'s dashboard asks before it offers a
664
+ * prompt — is there a person here — because that is exactly what "whose browser is this"
665
+ * means.
666
+ */
667
+ async handToBrowser(id) {
668
+ this.logSuccess(`Shared as ${id}`);
669
+ for (const destination of sharedConfigDestinations(id)) {
670
+ this.log(destination);
671
+ }
672
+ if (!process.stdin.isTTY) return;
673
+ const opened = await openUrl(editorConfigUrl(id));
674
+ if (!opened.ok) this.warn(opened.error);
675
+ }
226
676
  /**
227
677
  * The load below, behind a spinner that comes down whichever way the await ends.
228
678
  *
@@ -332,7 +782,7 @@ var Edit = class _Edit extends BaseCommand {
332
782
  * source contradict the filesystem and the plugin registry.
333
783
  *
334
784
  * So authority follows the work actually performed, and no further: only ids
335
- * `executeMigration` acted on this run are rewritten, and only their `source` field. Global
785
+ * `executeMigration` acted on this run are rewritten, and only their `origin` field. Global
336
786
  * entries this session merely displayed, re-scoped or deselected are untouched, as are
337
787
  * `marketplace`, `stack`, `agents` and every other registered project's view of them.
338
788
  *
@@ -352,14 +802,14 @@ var Edit = class _Edit extends BaseCommand {
352
802
  * classifies as a no-op against what this one left on disk, so the fan-out below
353
803
  * happens once.
354
804
  *
355
- * The migrated `source` decides the reference form a compiled agent emits, so every
805
+ * The migrated `origin` decides the reference form a compiled agent emits, so every
356
806
  * OTHER registered project's config and agents are stale until this write fans out —
357
807
  * which is why it goes through the gate rather than straight to the file.
358
808
  */
359
809
  async recordGlobalSourceMigrations(migratedSkillIds, newSkills, cwd, context) {
360
810
  if (isHomeDirectory(cwd)) return;
361
811
  const migratedSources = new Map(
362
- newSkills.filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, "global")).map((s) => [s.id, s.source])
812
+ newSkills.filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, "global")).map((s) => [s.id, s.origin])
363
813
  );
364
814
  if (migratedSources.size === 0) return;
365
815
  try {
@@ -371,12 +821,12 @@ var Edit = class _Edit extends BaseCommand {
371
821
  // matrix in hand already.
372
822
  // eslint-disable-next-line @typescript-eslint/require-await -- deps contract
373
823
  loadMatrix: async () => context.sourceResult.matrix,
374
- loadAgents: async () => (await loadAgentDefs({ projectDir: cwd })).agents
824
+ loadAgents: async () => (await loadAgentDefs()).agents
375
825
  }
376
826
  );
377
827
  this.reportPropagatedRecompile(report);
378
828
  } catch (error) {
379
- this.warn(`Could not record global source change: ${getErrorMessage(error)}`);
829
+ this.warn(`Could not record global origin change: ${getErrorMessage(error)}`);
380
830
  }
381
831
  }
382
832
  logChangeSummary(changes, newSkills, oldSkills, removalReasons) {
@@ -454,15 +904,36 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
454
904
  this.warn(warning);
455
905
  }
456
906
  if (migrationPlan.toEject.length > 0) {
457
- this.log(
458
- chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(migrationResult.ejectedSkills.length))
459
- );
907
+ this.reportEjectCopies(migrationResult.ejectCopies);
460
908
  }
461
909
  if (migrationPlan.toPlugin.length > 0) {
462
910
  this.reportPluginInstalls(migrationResult.pluginInstalls);
463
911
  }
464
912
  return migratedSkillIds;
465
913
  }
914
+ /**
915
+ * What the plugin→eject half copied, what it could not, and the refusal to continue past
916
+ * a failure.
917
+ *
918
+ * The shape of `BaseCommand.reportPluginInstalls`, deliberately: the two directions of one
919
+ * mode switch owe the user the same account, and the eject half having no structured
920
+ * failure at all is what let a config record `origin: "eject"` for a skill whose copy was
921
+ * refused. It stays private because `edit` is the only command that migrates a mode —
922
+ * `init` installs, and has no old state to move.
923
+ *
924
+ * The count line is the same one `copyNewLocalSkills` prints, and names no destination:
925
+ * the migration splits its copies between the project and $HOME by each skill's own scope,
926
+ * so one directory would misname the other half.
927
+ */
928
+ reportEjectCopies(result) {
929
+ for (const item of result.failed) {
930
+ this.warn(`Failed to copy ${item.id} for eject: ${item.error}`);
931
+ }
932
+ if (result.failed.length > 0) {
933
+ this.error(ejectCopyFailureError(result.failed.length), { exit: EXIT_CODES.ERROR });
934
+ }
935
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(result.copied.length)));
936
+ }
466
937
  /** Names what this run is switching, in the words `init` describes an install mode with. */
467
938
  logModeSwitch(count, modeDescription) {
468
939
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Switching ${count} skill(s) to ${modeDescription}`));
@@ -471,13 +942,13 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
471
942
  const { scopeChanges } = changes;
472
943
  for (const [skillId, change] of scopeChanges) {
473
944
  const skillConfig = filteredResult.skills.find((s) => s.id === skillId);
474
- if (skillConfig?.source === EJECT_SOURCE) {
945
+ if (skillConfig?.origin === EJECT_SOURCE) {
475
946
  await migrateLocalSkillScope(skillId, change.from, cwd);
476
947
  }
477
948
  }
478
949
  const hasPluginScopeChanges = [...scopeChanges.keys()].some((skillId) => {
479
950
  const skillConfig = filteredResult.skills.find((s) => s.id === skillId);
480
- return skillConfig && skillConfig.source !== EJECT_SOURCE;
951
+ return skillConfig && skillConfig.origin !== EJECT_SOURCE;
481
952
  });
482
953
  if (!hasPluginScopeChanges) return;
483
954
  const marketplace = await this.requireMarketplaceOrExit(
@@ -510,10 +981,10 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
510
981
  async applyPluginChanges(changes, filteredResult, activeOldSkills, context, cwd) {
511
982
  const { addedSkills, removedSkills } = changes;
512
983
  const addedPluginSkills = filteredResult.skills.filter(
513
- (s) => addedSkills.includes(s.id) && s.source !== EJECT_SOURCE
984
+ (s) => addedSkills.includes(s.id) && s.origin !== EJECT_SOURCE
514
985
  );
515
986
  const removedPluginSkills = removedSkills.filter(
516
- (id) => activeOldSkills.find((s) => s.id === id)?.source !== EJECT_SOURCE
987
+ (id) => activeOldSkills.find((s) => s.id === id)?.origin !== EJECT_SOURCE
517
988
  );
518
989
  if (addedPluginSkills.length === 0 && removedPluginSkills.length === 0) return;
519
990
  const marketplace = await this.requireMarketplaceOrExit(
@@ -521,7 +992,12 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
521
992
  "install or uninstall plugin skills"
522
993
  );
523
994
  if (addedPluginSkills.length > 0) {
524
- await this.installPluginSkillsReported(addedPluginSkills, marketplace, cwd);
995
+ await this.installPluginSkillsReported(
996
+ addedPluginSkills,
997
+ marketplace,
998
+ cwd,
999
+ context.sourceResult.matrix
1000
+ );
525
1001
  }
526
1002
  if (removedPluginSkills.length > 0) {
527
1003
  const uninstallResult = await uninstallPluginSkills(
@@ -543,7 +1019,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
543
1019
  async copyNewLocalSkills(changes, filteredResult, context, cwd) {
544
1020
  const { addedSkills } = changes;
545
1021
  const addedLocalSkills = filteredResult.skills.filter(
546
- (s) => addedSkills.includes(s.id) && s.source === EJECT_SOURCE
1022
+ (s) => addedSkills.includes(s.id) && s.origin === EJECT_SOURCE
547
1023
  );
548
1024
  if (addedLocalSkills.length > 0) {
549
1025
  const copyResult = await copyLocalSkills(addedLocalSkills, cwd, context.sourceResult);
@@ -554,15 +1030,15 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
554
1030
  const { removedSkills } = changes;
555
1031
  for (const skillId of removedSkills) {
556
1032
  const oldSkill = activeOldSkills.find((s) => s.id === skillId);
557
- if (oldSkill?.source !== EJECT_SOURCE) continue;
1033
+ if (oldSkill?.origin !== EJECT_SOURCE) continue;
558
1034
  const deleteDir = installBaseDir(cwd, oldSkill.scope);
559
1035
  await deleteLocalSkill(deleteDir, skillId);
560
1036
  }
561
1037
  }
562
- async writeConfigAndCompile(result, context, cwd) {
1038
+ async writeConfigAndCompile(result, context, cwd, authority) {
563
1039
  let agentDefsResult;
564
1040
  try {
565
- agentDefsResult = await loadAgentDefs({});
1041
+ agentDefsResult = await loadAgentDefs();
566
1042
  } catch (error) {
567
1043
  this.handleError(error);
568
1044
  }
@@ -574,17 +1050,17 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
574
1050
  projectDir: cwd,
575
1051
  agents: agentDefsResult.agents,
576
1052
  // A full `cc edit` pass is authoritative over the roster it owns, so deselected entries
577
- // are removed rather than union-preserved (D-233 Scenario C). Global-context edit owns
578
- // the entire config ("all"); a project edit owns only project-scoped entries and its own
579
- // tombstones ("owned"), never inherited global-active entries.
580
- authoritativeScope: isHomeDirectory(cwd) ? "all" : "owned"
1053
+ // are removed rather than union-preserved (D-233 Scenario C). `applyAuthority` decides
1054
+ // how much that is from the producer and the directory, and hands the same word to the
1055
+ // merger and to the global config the project branch of the gate commits.
1056
+ authoritativeScope: authority
581
1057
  });
582
1058
  } catch (error) {
583
- this.warn(`Could not update config: ${getErrorMessage(error)}`);
584
- }
585
- if (configResult) {
586
- this.reportUnassignedSkills(configResult.config);
1059
+ this.error(`Could not update config: ${getErrorMessage(error)}`, {
1060
+ exit: EXIT_CODES.ERROR
1061
+ });
587
1062
  }
1063
+ this.reportUnassignedSkills(configResult.config);
588
1064
  try {
589
1065
  const agentScopeMap = activeAgentScopeMap(result.agentConfigs);
590
1066
  const { allSkills } = await discoverInstalledSkills(cwd);
@@ -616,9 +1092,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
616
1092
  this.warn(`Agent recompilation failed: ${getErrorMessage(error)}`);
617
1093
  this.log(`You can manually recompile with '${CLI_INVOKE_COMMAND} compile'.`);
618
1094
  }
619
- if (configResult) {
620
- this.reportPropagatedRecompile(configResult.propagation);
621
- }
1095
+ this.reportPropagatedRecompile(configResult.propagation);
622
1096
  }
623
1097
  async cleanupStaleAgentFiles(changes, oldAgents, cwd) {
624
1098
  for (const removal of planStaleAgentRemovals(changes, oldAgents, cwd)) {
@@ -663,7 +1137,7 @@ function detectConfigChanges(oldConfig, wizardResult, fullEntries) {
663
1137
  wizardResult.skills,
664
1138
  oldSkillsById,
665
1139
  (s) => s.id,
666
- (s) => s.source
1140
+ (s) => s.origin
667
1141
  ),
668
1142
  scopeChanges,
669
1143
  agentScopeChanges,
@@ -730,7 +1204,7 @@ async function migratePluginSkillScopes(scopeChanges, skills, marketplace, proje
730
1204
  const failed = [];
731
1205
  for (const [skillId, change] of scopeChanges) {
732
1206
  const skillConfig = skills.find((s) => s.id === skillId);
733
- if (!skillConfig || skillConfig.source === EJECT_SOURCE) {
1207
+ if (!skillConfig || skillConfig.origin === EJECT_SOURCE) {
734
1208
  continue;
735
1209
  }
736
1210
  const newPluginScope = toClaudePluginScope(change.to);