agents-inc 0.167.0 → 0.170.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 (200) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +18 -15
  3. package/dist/{chunk-ZR4YPKXQ.js → chunk-3G7X2WKI.js} +4 -4
  4. package/dist/{chunk-JOEA52NR.js → chunk-44TE3RKH.js} +46 -2
  5. package/dist/chunk-44TE3RKH.js.map +1 -0
  6. package/dist/{chunk-V5WXIM2F.js → chunk-52HDHJ7I.js} +11 -19
  7. package/dist/chunk-52HDHJ7I.js.map +1 -0
  8. package/dist/{chunk-V3I7VQ7N.js → chunk-6HNXYYVF.js} +39 -22
  9. package/dist/chunk-6HNXYYVF.js.map +1 -0
  10. package/dist/{chunk-MAWNVT2C.js → chunk-6ZRH5RHC.js} +10 -11
  11. package/dist/chunk-6ZRH5RHC.js.map +1 -0
  12. package/dist/{chunk-G6UREQ4V.js → chunk-7RDMTR64.js} +14 -34
  13. package/dist/chunk-7RDMTR64.js.map +1 -0
  14. package/dist/{chunk-GE3WKJ6Q.js → chunk-BMRUNMPV.js} +4 -4
  15. package/dist/{chunk-VAPTVR3J.js → chunk-CLPUWOSA.js} +4 -4
  16. package/dist/{chunk-VAPTVR3J.js.map → chunk-CLPUWOSA.js.map} +1 -1
  17. package/dist/{chunk-HWEKHVLE.js → chunk-F2BHT5C4.js} +9 -7
  18. package/dist/chunk-F2BHT5C4.js.map +1 -0
  19. package/dist/{chunk-ZXKBERQU.js → chunk-F5EBEATU.js} +2 -2
  20. package/dist/{chunk-PMJWD27C.js → chunk-HED2DAXZ.js} +3 -3
  21. package/dist/{chunk-SAYZWCH6.js → chunk-KOLDW6SF.js} +3 -3
  22. package/dist/{chunk-SAYZWCH6.js.map → chunk-KOLDW6SF.js.map} +1 -1
  23. package/dist/{chunk-A4KDXNOT.js → chunk-MQ6CGZNJ.js} +171 -522
  24. package/dist/chunk-MQ6CGZNJ.js.map +1 -0
  25. package/dist/{chunk-G4JK7WVO.js → chunk-NCWDK6L7.js} +115 -196
  26. package/dist/chunk-NCWDK6L7.js.map +1 -0
  27. package/dist/{chunk-VRXX4D6K.js → chunk-NEZ4OAOL.js} +1 -1
  28. package/dist/chunk-NEZ4OAOL.js.map +1 -0
  29. package/dist/chunk-NIHUOWE4.js +106 -0
  30. package/dist/chunk-NIHUOWE4.js.map +1 -0
  31. package/dist/{chunk-OI2H6M5I.js → chunk-NQW25DCF.js} +2 -2
  32. package/dist/chunk-NQW25DCF.js.map +1 -0
  33. package/dist/{chunk-25MPBIK3.js → chunk-OYJQUA3D.js} +3 -3
  34. package/dist/{chunk-25MPBIK3.js.map → chunk-OYJQUA3D.js.map} +1 -1
  35. package/dist/{chunk-ENGYJCTF.js → chunk-PJWGTNOX.js} +220 -254
  36. package/dist/chunk-PJWGTNOX.js.map +1 -0
  37. package/dist/{chunk-NBXXFIIW.js → chunk-RIPSGNLU.js} +3 -3
  38. package/dist/chunk-RIPSGNLU.js.map +1 -0
  39. package/dist/{chunk-Y47EV74W.js → chunk-SZYQISA2.js} +10 -13
  40. package/dist/chunk-SZYQISA2.js.map +1 -0
  41. package/dist/{chunk-TODCQFRB.js → chunk-USVBYQSQ.js} +2 -2
  42. package/dist/{chunk-Y3VIRVVE.js → chunk-V3KTSP3Q.js} +50 -42
  43. package/dist/chunk-V3KTSP3Q.js.map +1 -0
  44. package/dist/{chunk-PXWG7KFO.js → chunk-WTWMGH2C.js} +2 -2
  45. package/dist/commands/build/marketplace.js +23 -22
  46. package/dist/commands/build/marketplace.js.map +1 -1
  47. package/dist/commands/build/plugins.js +8 -9
  48. package/dist/commands/build/plugins.js.map +1 -1
  49. package/dist/commands/compile.js +19 -20
  50. package/dist/commands/compile.js.map +1 -1
  51. package/dist/commands/doctor.js +17 -18
  52. package/dist/commands/doctor.js.map +1 -1
  53. package/dist/commands/edit.js +138 -488
  54. package/dist/commands/edit.js.map +1 -1
  55. package/dist/commands/eject.js +21 -33
  56. package/dist/commands/eject.js.map +1 -1
  57. package/dist/commands/init.js +17 -45
  58. package/dist/commands/list.js +19 -17
  59. package/dist/commands/list.js.map +1 -1
  60. package/dist/commands/new/marketplace.js +11 -11
  61. package/dist/commands/new/marketplace.js.map +1 -1
  62. package/dist/commands/search.js +12 -13
  63. package/dist/commands/search.js.map +1 -1
  64. package/dist/commands/share.js +11 -12
  65. package/dist/commands/share.js.map +1 -1
  66. package/dist/commands/uninstall.js +18 -20
  67. package/dist/commands/uninstall.js.map +1 -1
  68. package/dist/commands/update.js +8 -9
  69. package/dist/commands/update.js.map +1 -1
  70. package/dist/components/common/removal-plan-confirm.js +2 -2
  71. package/dist/components/common/scroll-affordance.js +9 -0
  72. package/dist/components/common/select-list.js +2 -3
  73. package/dist/components/common/skill-agent-summary.js +11 -0
  74. package/dist/components/common/spinner.js +1 -1
  75. package/dist/{chunk-2VUYFTUB.js → components/common/summary-panel.js} +57 -31
  76. package/dist/components/common/summary-panel.js.map +1 -0
  77. package/dist/config-exports.js +1 -1
  78. package/dist/hooks/init.js +18 -46
  79. package/dist/hooks/init.js.map +1 -1
  80. package/dist/load-agent-defs-YMDWBFDP.js +14 -0
  81. package/dist/recompile-project-agents-SZ76WNTW.js +18 -0
  82. package/dist/{source-loader-7KZ3MD5O.js → source-loader-C5SQXZXI.js} +5 -5
  83. package/dist/src/agents/meta/codex-keeper/playbook.md +2 -3
  84. package/package.json +6 -4
  85. package/src/agents/meta/codex-keeper/playbook.md +2 -3
  86. package/src/schemas/project-config.schema.json +1 -1
  87. package/assets/demo.tape +0 -266
  88. package/dist/chunk-2VUYFTUB.js.map +0 -1
  89. package/dist/chunk-4NDBUJHK.js +0 -237
  90. package/dist/chunk-4NDBUJHK.js.map +0 -1
  91. package/dist/chunk-6L75SQZU.js +0 -168
  92. package/dist/chunk-6L75SQZU.js.map +0 -1
  93. package/dist/chunk-6LF4CQBY.js +0 -51
  94. package/dist/chunk-6LF4CQBY.js.map +0 -1
  95. package/dist/chunk-7JNJ52CD.js +0 -1179
  96. package/dist/chunk-7JNJ52CD.js.map +0 -1
  97. package/dist/chunk-A4KDXNOT.js.map +0 -1
  98. package/dist/chunk-DAIEQJIF.js +0 -48
  99. package/dist/chunk-DAIEQJIF.js.map +0 -1
  100. package/dist/chunk-ENGYJCTF.js.map +0 -1
  101. package/dist/chunk-G4JK7WVO.js.map +0 -1
  102. package/dist/chunk-G6UREQ4V.js.map +0 -1
  103. package/dist/chunk-HHIYT3PI.js +0 -53
  104. package/dist/chunk-HHIYT3PI.js.map +0 -1
  105. package/dist/chunk-HWEKHVLE.js.map +0 -1
  106. package/dist/chunk-JOEA52NR.js.map +0 -1
  107. package/dist/chunk-JQRJQ4SS.js +0 -118
  108. package/dist/chunk-JQRJQ4SS.js.map +0 -1
  109. package/dist/chunk-LFWLEDUG.js +0 -59
  110. package/dist/chunk-LFWLEDUG.js.map +0 -1
  111. package/dist/chunk-MAWNVT2C.js.map +0 -1
  112. package/dist/chunk-MPTNC32T.js +0 -92
  113. package/dist/chunk-MPTNC32T.js.map +0 -1
  114. package/dist/chunk-NBXXFIIW.js.map +0 -1
  115. package/dist/chunk-OI2H6M5I.js.map +0 -1
  116. package/dist/chunk-PNB3524H.js +0 -197
  117. package/dist/chunk-PNB3524H.js.map +0 -1
  118. package/dist/chunk-QHDPLLK6.js +0 -35
  119. package/dist/chunk-QHDPLLK6.js.map +0 -1
  120. package/dist/chunk-RAHSOJQ2.js +0 -25
  121. package/dist/chunk-RAHSOJQ2.js.map +0 -1
  122. package/dist/chunk-RZDXDMT6.js +0 -23
  123. package/dist/chunk-RZDXDMT6.js.map +0 -1
  124. package/dist/chunk-SCOQ34YM.js +0 -17
  125. package/dist/chunk-SCOQ34YM.js.map +0 -1
  126. package/dist/chunk-SXVHSOTH.js +0 -268
  127. package/dist/chunk-SXVHSOTH.js.map +0 -1
  128. package/dist/chunk-T6UWJAB3.js +0 -28
  129. package/dist/chunk-T6UWJAB3.js.map +0 -1
  130. package/dist/chunk-TSIU7DME.js +0 -43
  131. package/dist/chunk-TSIU7DME.js.map +0 -1
  132. package/dist/chunk-TTY6DPJN.js +0 -27
  133. package/dist/chunk-TTY6DPJN.js.map +0 -1
  134. package/dist/chunk-TZ2YJJKK.js +0 -292
  135. package/dist/chunk-TZ2YJJKK.js.map +0 -1
  136. package/dist/chunk-V3I7VQ7N.js.map +0 -1
  137. package/dist/chunk-V5WXIM2F.js.map +0 -1
  138. package/dist/chunk-VRXX4D6K.js.map +0 -1
  139. package/dist/chunk-WTJ3AY33.js +0 -31
  140. package/dist/chunk-WTJ3AY33.js.map +0 -1
  141. package/dist/chunk-WVUDLKIO.js +0 -121
  142. package/dist/chunk-WVUDLKIO.js.map +0 -1
  143. package/dist/chunk-WWIFNPJG.js +0 -317
  144. package/dist/chunk-WWIFNPJG.js.map +0 -1
  145. package/dist/chunk-XQHZPINL.js +0 -89
  146. package/dist/chunk-XQHZPINL.js.map +0 -1
  147. package/dist/chunk-XZEVWPX6.js +0 -230
  148. package/dist/chunk-XZEVWPX6.js.map +0 -1
  149. package/dist/chunk-Y3VIRVVE.js.map +0 -1
  150. package/dist/chunk-Y47EV74W.js.map +0 -1
  151. package/dist/components/wizard/category-grid.js +0 -13
  152. package/dist/components/wizard/checkbox-grid.js +0 -12
  153. package/dist/components/wizard/domain-selection.js +0 -18
  154. package/dist/components/wizard/run-wizard-session.js +0 -40
  155. package/dist/components/wizard/run-wizard-session.js.map +0 -1
  156. package/dist/components/wizard/scroll-affordance.js +0 -9
  157. package/dist/components/wizard/skill-agent-summary.js +0 -13
  158. package/dist/components/wizard/source-grid.js +0 -16
  159. package/dist/components/wizard/source-grid.js.map +0 -1
  160. package/dist/components/wizard/stack-selection.js +0 -17
  161. package/dist/components/wizard/stack-selection.js.map +0 -1
  162. package/dist/components/wizard/step-agents.js +0 -18
  163. package/dist/components/wizard/step-agents.js.map +0 -1
  164. package/dist/components/wizard/step-build.js +0 -18
  165. package/dist/components/wizard/step-build.js.map +0 -1
  166. package/dist/components/wizard/step-confirm.js +0 -18
  167. package/dist/components/wizard/step-confirm.js.map +0 -1
  168. package/dist/components/wizard/step-sources.js +0 -19
  169. package/dist/components/wizard/step-sources.js.map +0 -1
  170. package/dist/components/wizard/step-stack.js +0 -18
  171. package/dist/components/wizard/step-stack.js.map +0 -1
  172. package/dist/components/wizard/summary-panel.js +0 -17
  173. package/dist/components/wizard/summary-panel.js.map +0 -1
  174. package/dist/components/wizard/toast.js +0 -9
  175. package/dist/components/wizard/toast.js.map +0 -1
  176. package/dist/components/wizard/wizard-layout.js +0 -22
  177. package/dist/components/wizard/wizard-layout.js.map +0 -1
  178. package/dist/components/wizard/wizard-tabs.js +0 -11
  179. package/dist/components/wizard/wizard-tabs.js.map +0 -1
  180. package/dist/components/wizard/wizard.js +0 -39
  181. package/dist/components/wizard/wizard.js.map +0 -1
  182. package/dist/load-agent-defs-3C27ENC7.js +0 -14
  183. package/dist/load-agent-defs-3C27ENC7.js.map +0 -1
  184. package/dist/recompile-project-agents-DGNBCU3N.js +0 -18
  185. package/dist/recompile-project-agents-DGNBCU3N.js.map +0 -1
  186. package/dist/source-loader-7KZ3MD5O.js.map +0 -1
  187. package/dist/stores/wizard-store.js +0 -24
  188. package/dist/stores/wizard-store.js.map +0 -1
  189. /package/assets/{demo.gif → legacy-wizard.gif} +0 -0
  190. /package/dist/{chunk-ZR4YPKXQ.js.map → chunk-3G7X2WKI.js.map} +0 -0
  191. /package/dist/{chunk-GE3WKJ6Q.js.map → chunk-BMRUNMPV.js.map} +0 -0
  192. /package/dist/{chunk-ZXKBERQU.js.map → chunk-F5EBEATU.js.map} +0 -0
  193. /package/dist/{chunk-PMJWD27C.js.map → chunk-HED2DAXZ.js.map} +0 -0
  194. /package/dist/{chunk-TODCQFRB.js.map → chunk-USVBYQSQ.js.map} +0 -0
  195. /package/dist/{chunk-PXWG7KFO.js.map → chunk-WTWMGH2C.js.map} +0 -0
  196. /package/dist/components/{wizard → common}/scroll-affordance.js.map +0 -0
  197. /package/dist/components/{wizard → common}/skill-agent-summary.js.map +0 -0
  198. /package/dist/{components/wizard/category-grid.js.map → load-agent-defs-YMDWBFDP.js.map} +0 -0
  199. /package/dist/{components/wizard/checkbox-grid.js.map → recompile-project-agents-SZ76WNTW.js.map} +0 -0
  200. /package/dist/{components/wizard/domain-selection.js.map → source-loader-C5SQXZXI.js.map} +0 -0
@@ -1,18 +1,22 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ awaitUnderSpinner
4
+ } from "../chunk-NEZ4OAOL.js";
2
5
  import {
3
6
  publishSeedConfig,
4
7
  seedPayloadForInstallation,
5
8
  skillsAuthoredHere
6
- } from "../chunk-Y47EV74W.js";
9
+ } from "../chunk-SZYQISA2.js";
7
10
  import {
8
11
  RemovalPlanConfirm
9
- } from "../chunk-TODCQFRB.js";
12
+ } from "../chunk-USVBYQSQ.js";
10
13
  import {
11
14
  unofferablePlacementsFound
12
- } from "../chunk-PXWG7KFO.js";
15
+ } from "../chunk-WTWMGH2C.js";
13
16
  import {
14
17
  arrivalLines,
15
18
  arrivalsByScope,
19
+ joinedStatement,
16
20
  notInstalledGlobally,
17
21
  openUrl,
18
22
  readInstalledGlobal,
@@ -21,87 +25,54 @@ import {
21
25
  sameAssignments,
22
26
  skillLabel,
23
27
  withUnplaceableAssignees
24
- } from "../chunk-V3I7VQ7N.js";
25
- import {
26
- runWizardSession
27
- } from "../chunk-HHIYT3PI.js";
28
- import "../chunk-WWIFNPJG.js";
29
- import "../chunk-RAHSOJQ2.js";
30
- import "../chunk-DAIEQJIF.js";
31
- import "../chunk-SCOQ34YM.js";
32
- import "../chunk-4NDBUJHK.js";
33
- import "../chunk-2VUYFTUB.js";
34
- import "../chunk-T6UWJAB3.js";
35
- import "../chunk-6L75SQZU.js";
36
- import "../chunk-LFWLEDUG.js";
37
- import "../chunk-TZ2YJJKK.js";
38
- import "../chunk-SAYZWCH6.js";
39
- import "../chunk-PNB3524H.js";
40
- import "../chunk-XZEVWPX6.js";
41
- import "../chunk-QHDPLLK6.js";
42
- import "../chunk-MPTNC32T.js";
43
- import "../chunk-TSIU7DME.js";
44
- import "../chunk-JOEA52NR.js";
45
- import {
46
- awaitUnderSpinner
47
- } from "../chunk-VRXX4D6K.js";
48
- import "../chunk-SXVHSOTH.js";
49
- import "../chunk-XQHZPINL.js";
50
- import "../chunk-JQRJQ4SS.js";
51
- import "../chunk-TTY6DPJN.js";
52
- import "../chunk-WTJ3AY33.js";
53
- import "../chunk-WVUDLKIO.js";
28
+ } from "../chunk-6HNXYYVF.js";
54
29
  import {
55
30
  fetchSeedConfig
56
- } from "../chunk-25MPBIK3.js";
31
+ } from "../chunk-OYJQUA3D.js";
57
32
  import {
58
33
  promptConfirm
59
34
  } from "../chunk-4AAOOAIN.js";
60
35
  import "../chunk-OZXAJNLA.js";
61
36
  import {
62
37
  hostCompileNotices
63
- } from "../chunk-ZXKBERQU.js";
38
+ } from "../chunk-F5EBEATU.js";
64
39
  import {
65
- applyMigratedGlobalSources,
66
40
  compileAgentsAllScopes,
67
41
  compileProjectScope,
68
42
  detectProject,
69
43
  loadSource,
70
44
  movedGlobalAgentInputs,
71
- mutateGlobal,
72
45
  sayCapturedWarnings,
73
46
  writeProjectConfig
74
- } from "../chunk-G6UREQ4V.js";
47
+ } from "../chunk-7RDMTR64.js";
75
48
  import {
76
49
  copyLocalSkills,
77
50
  discoverInstalledSkills,
78
51
  removeCompiledAgents,
79
52
  uninstallPluginSkills
80
- } from "../chunk-HWEKHVLE.js";
53
+ } from "../chunk-F2BHT5C4.js";
81
54
  import {
82
55
  loadAgentDefs
83
- } from "../chunk-PMJWD27C.js";
84
- import "../chunk-ZR4YPKXQ.js";
85
- import "../chunk-GE3WKJ6Q.js";
86
- import "../chunk-MAWNVT2C.js";
87
- import "../chunk-JFLVEFFP.js";
56
+ } from "../chunk-HED2DAXZ.js";
57
+ import "../chunk-3G7X2WKI.js";
58
+ import "../chunk-BMRUNMPV.js";
88
59
  import {
89
60
  formatScopeTag
90
- } from "../chunk-7JNJ52CD.js";
61
+ } from "../chunk-NIHUOWE4.js";
62
+ import "../chunk-JFLVEFFP.js";
91
63
  import {
92
64
  providerFlag,
93
65
  providerNamedBy,
94
66
  refuseAnAmbiguousInstallation
95
- } from "../chunk-NBXXFIIW.js";
67
+ } from "../chunk-RIPSGNLU.js";
96
68
  import {
97
69
  BaseCommand,
98
70
  EXIT_CODES,
99
71
  carriedSkillsThatDiffer,
100
72
  registerExternalSkills,
101
73
  writeExternalSkills
102
- } from "../chunk-Y3VIRVVE.js";
103
- import "../chunk-VAPTVR3J.js";
104
- import "../chunk-RZDXDMT6.js";
74
+ } from "../chunk-V3KTSP3Q.js";
75
+ import "../chunk-CLPUWOSA.js";
105
76
  import {
106
77
  ERROR_MESSAGES,
107
78
  INCOMPLETE_WORK_RECOVERY,
@@ -116,53 +87,45 @@ import {
116
87
  carriedSkillsWritten,
117
88
  deleteLocalSkill,
118
89
  detectMigrations,
119
- discoverAllPluginSkills,
90
+ editorSkillMetadataUnusableError,
120
91
  ejectCopyFailureError,
121
92
  executeMigration,
122
- foldLocalSkillIntoGlobal,
123
93
  getErrorMessage,
124
94
  holdsItsOwnInstallation,
125
95
  hostAt,
126
96
  isHomeDirectory,
127
97
  keptAsInstalledGlobally,
128
98
  keptUnassigned,
99
+ loadProjectConfig,
129
100
  localSkillsCopied,
130
101
  migrateLocalSkillScope,
131
102
  nothingInstalledToApplyTo,
132
- plural,
133
103
  projectCopyRemoved,
134
104
  providerInUse,
135
105
  recompileSummary,
136
106
  resolveInstallPaths,
137
- seedToWizardResult,
107
+ seedToInstallSelection,
138
108
  sharedConfigDestinations,
139
109
  sharedConfigNeedsTerminal,
140
110
  skippedUnknownAgents,
141
111
  skippedUnknownSkills,
142
- unplaceableKept,
143
- unresolvedSkillRemovalReasons,
144
- wizardNeedsTerminal
145
- } from "../chunk-A4KDXNOT.js";
112
+ unplaceableKept
113
+ } from "../chunk-MQ6CGZNJ.js";
146
114
  import {
147
115
  getSkillById,
148
- getSkillDisplayName,
149
- matrix,
150
- typedKeys
151
- } from "../chunk-V5WXIM2F.js";
116
+ getSkillDisplayName
117
+ } from "../chunk-52HDHJ7I.js";
152
118
  import {
153
119
  CLI_COLORS,
154
120
  CLI_INVOKE_COMMAND,
155
- EDIT_PROJECT_SETUP_FLAG,
156
- EDIT_PROJECT_SETUP_MARKETPLACE_FLAG,
157
121
  EJECT_SOURCE,
158
- activeAgentNames,
159
122
  activeAgentScopeMap,
160
123
  editorConfigUrl,
161
124
  formatSourceDisplayName,
162
125
  isActiveAt,
163
126
  isGlobalTombstone
164
- } from "../chunk-ENGYJCTF.js";
165
- import "../chunk-OI2H6M5I.js";
127
+ } from "../chunk-PJWGTNOX.js";
128
+ import "../chunk-NQW25DCF.js";
166
129
 
167
130
  // src/cli/commands/edit.tsx
168
131
  import path from "path";
@@ -200,13 +163,9 @@ function scopeArrow(change) {
200
163
  function formatValueChangeLine(subject, change, kind) {
201
164
  return chalk.hex(CLI_COLORS.WARNING)(` ~ ${subject}`) + chalk.hex(CLI_COLORS.NEUTRAL)(` (${kind}: ${change.from} \u2192 ${change.to})`);
202
165
  }
203
- function loadedSourceLabel(sourceResult) {
204
- return sourceResult.marketplace ?? sourceResult.sourceConfig.source;
205
- }
206
- function resolveEditRoot(installation, cwd, setupRequested) {
207
- const dir = setupRequested ? cwd : installation.projectDir;
208
- const isGlobal = isHomeDirectory(dir);
209
- return { dir, isGlobal, isProjectSetup: setupRequested && !isGlobal };
166
+ function resolveEditRoot(installation) {
167
+ const dir = installation.projectDir;
168
+ return { dir, isGlobal: isHomeDirectory(dir) };
210
169
  }
211
170
  function sharedConfigPlan(changes, kept) {
212
171
  const dropped = droppedProjectHalves(changes);
@@ -228,12 +187,11 @@ function removalSections(skills, agents) {
228
187
  ].filter((section) => section.items.length > 0);
229
188
  }
230
189
  function droppedProjectHalves(changes) {
231
- const droppedSkills = changes.collapsedPairs.filter((pair) => !pair.folded);
232
190
  const droppedAgents = [...changes.agentScopeChanges].filter(
233
191
  ([name, change]) => change.to === "global" && changes.dualScopeAgentTransitions.has(name)
234
192
  );
235
193
  return {
236
- skillIds: droppedSkills.map(({ projectHalf }) => projectHalf.id),
194
+ skillIds: changes.collapsedPairs.map(({ projectHalf }) => projectHalf.id),
237
195
  agentNames: droppedAgents.map(([name]) => name)
238
196
  };
239
197
  }
@@ -241,13 +199,11 @@ function planHeading(sections) {
241
199
  if (sections.length === 0) return SHARED_CONFIG_APPLY.NOTHING_REMOVED;
242
200
  return SHARED_CONFIG_APPLY.PREVIEW_HEADING;
243
201
  }
244
- function compilesGlobalScope(producer, editRoot, written) {
245
- if (editRoot.isGlobal || producer === "wizard") return true;
246
- return movedGlobalAgentInputs(written);
202
+ function compilesGlobalScope(editRoot, written) {
203
+ return editRoot.isGlobal || movedGlobalAgentInputs(written);
247
204
  }
248
205
  function withReassignments(changes, result, installedStack, editRoot) {
249
206
  const { assignedStack } = result;
250
- if (assignedStack === void 0) return { ...changes, reassignedAgents: [] };
251
207
  const ownedHere = (agent) => editRoot.isGlobal || isActiveAt(agent, "project");
252
208
  const countedAsAdded = (agent) => changes.addedAgents.includes(agent.name);
253
209
  const rowsMoved = (agent) => !sameAssignments(assignedStack[agent.name], installedStack?.[agent.name]);
@@ -303,51 +259,34 @@ function applyAuthority(editRoot) {
303
259
  return editRoot.isGlobal ? "all" : "owned";
304
260
  }
305
261
  var Edit = class _Edit extends BaseCommand {
306
- static summary = "Edit skills in the plugin";
307
- static description = "Modify the currently installed skills via interactive wizard";
262
+ static summary = "Open this installation in the editor, or apply a configuration with --from";
263
+ static description = "Open this installation in agentsinc.sh/editor, or apply a configuration built there with --from";
308
264
  static examples = [
309
265
  {
310
- description: "Open the edit wizard",
266
+ description: "Open this installation in the editor",
311
267
  command: "<%= config.bin %> <%= command.id %>"
312
268
  },
313
- {
314
- description: "Open this installation in the editor instead of the wizard",
315
- command: "<%= config.bin %> <%= command.id %> --ui"
316
- },
317
269
  {
318
270
  description: "Apply a configuration built in the editor, by its id",
319
271
  command: "<%= config.bin %> <%= command.id %> --from <id>"
272
+ },
273
+ {
274
+ description: "Look at a shared configuration without applying it",
275
+ command: "<%= config.bin %> <%= command.id %> --ui --from <id>"
320
276
  }
321
277
  ];
322
278
  static flags = {
323
279
  ui: Flags.boolean({
324
- description: "Open agentsinc.sh/editor instead of the wizard \u2014 the id --from names, or this installation",
280
+ description: "Open agentsinc.sh/editor on this installation, or on the id --from names without applying it \u2014 what a bare edit does",
325
281
  default: false
326
282
  }),
327
283
  from: Flags.string({
328
284
  description: "Apply a configuration shared from agentsinc.sh by its id, removing whatever it leaves out \u2014 from a project, only the project's own entries",
329
285
  helpValue: "<id>"
330
286
  }),
331
- [EDIT_PROJECT_SETUP_FLAG]: Flags.boolean({
332
- description: "Internal: this run continues an `init` project setup",
333
- default: false,
334
- hidden: true
335
- }),
336
- [EDIT_PROJECT_SETUP_MARKETPLACE_FLAG]: Flags.string({
337
- description: "Internal: the marketplace `init --marketplace` named for that project setup",
338
- hidden: true,
339
- dependsOn: [EDIT_PROJECT_SETUP_FLAG]
340
- }),
341
287
  provider: providerFlag()
342
288
  };
343
- /**
344
- * The command in two statements: do the work, then answer for it.
345
- *
346
- * `applyEdit` owns every path through the edit and returns however it likes; the exit code is
347
- * decided once, here, after the last of them. Deciding it inside `applyEdit` would mean
348
- * deciding it at each of that method's three endings, and an ending added later would inherit
349
- * the exit-0 default silently — which is the defect this pair exists to close.
350
- */
289
+ /** The exit code is decided once, after every path through `applyEdit`. */
351
290
  async run() {
352
291
  await this.applyEdit();
353
292
  this.exitIfWorkIncomplete();
@@ -364,17 +303,16 @@ var Edit = class _Edit extends BaseCommand {
364
303
  );
365
304
  await this.ensureConfigReadable(cwd);
366
305
  await this.refuseUnofferablePlacements(cwd);
367
- if (flags.ui) return this.openInEditor(cwd);
368
- const payload = flags.from === void 0 ? null : await this.fetchSharedConfigOrFail(flags.from);
369
- const context = await this.loadContextUnderSpinner(flags[EDIT_PROJECT_SETUP_MARKETPLACE_FLAG]);
370
- const editRoot = resolveEditRoot(context.installation, cwd, flags[EDIT_PROJECT_SETUP_FLAG]);
306
+ if (flags.from === void 0) return this.openInEditor(cwd);
307
+ const payload = await this.fetchSharedConfigOrFail(flags.from);
308
+ const context = await this.loadContextUnderSpinner();
309
+ const editRoot = resolveEditRoot(context.installation);
371
310
  await this.ensureSavedSkillsReadable(
372
311
  context.projectConfig?.skills ?? [],
373
312
  context.sourceResult.matrix,
374
- context.projectDir
313
+ editRoot.dir
375
314
  );
376
- const selection = payload ? await this.selectionFromSharedConfig(payload, context, editRoot) : await this.selectionFromWizard(context, editRoot);
377
- if (!selection) this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
315
+ const selection = await this.selectionFromSharedConfig(payload, context, editRoot);
378
316
  const { result } = selection;
379
317
  this.reportValidationErrors(result.validation);
380
318
  const activeNewSkills = result.skills.filter((s) => !s.excluded);
@@ -387,18 +325,21 @@ var Edit = class _Edit extends BaseCommand {
387
325
  agentConfigs: activeNewAgents
388
326
  };
389
327
  const filteredOldConfig = context.projectConfig ? { ...context.projectConfig, skills: activeOldSkills, agents: activeOldAgents } : null;
390
- const planned = withReassignments(
391
- detectConfigChanges(filteredOldConfig, filteredResult, {
392
- newSkills: result.skills,
393
- oldSkills: context.projectConfig?.skills ?? [],
394
- newAgents: result.agentConfigs,
395
- oldAgents: context.projectConfig?.agents ?? []
396
- }),
397
- filteredResult,
398
- context.projectConfig?.stack,
399
- editRoot
400
- );
401
- const rewritten = selection.producer === "shared" ? await this.confirmAndWriteCarried(selection, planned, filteredResult) : [];
328
+ const planned = {
329
+ ...withReassignments(
330
+ detectConfigChanges(filteredOldConfig, filteredResult, {
331
+ newSkills: result.skills,
332
+ oldSkills: context.projectConfig?.skills ?? [],
333
+ newAgents: result.agentConfigs,
334
+ oldAgents: context.projectConfig?.agents ?? []
335
+ }),
336
+ filteredResult,
337
+ context.projectConfig?.stack,
338
+ editRoot
339
+ ),
340
+ joinedGlobalAgents: selection.joinedGlobalAgents
341
+ };
342
+ const rewritten = await this.confirmAndWriteCarried(selection, planned, filteredResult);
402
343
  const changes = {
403
344
  ...planned,
404
345
  rewrittenSkills: difference(rewritten, planned.addedSkills)
@@ -406,24 +347,9 @@ var Edit = class _Edit extends BaseCommand {
406
347
  const authority = applyAuthority(editRoot);
407
348
  if (!hasAnyChanges(changes)) {
408
349
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)("No changes made."));
409
- if (!editRoot.isProjectSetup) return;
410
- await this.writeConfigAndCompile(result, context, editRoot, authority, selection.producer);
411
- await this.reportWhatThisHostCannotCarry(editRoot);
412
- this.logCompletionSummary(changes);
413
350
  return;
414
351
  }
415
- const removalReasons = await unresolvedSkillRemovalReasons(
416
- result.unresolvableSkillIds,
417
- activeOldSkills,
418
- context.projectDir,
419
- loadedSourceLabel(context.sourceResult)
420
- );
421
- this.logChangeSummary(
422
- changes,
423
- filteredResult.skills,
424
- filteredOldConfig?.skills ?? [],
425
- removalReasons
426
- );
352
+ this.logChangeSummary(changes, filteredResult.skills, filteredOldConfig?.skills ?? []);
427
353
  const migratedSkillIds = await this.applyMigrations(
428
354
  changes,
429
355
  filteredResult,
@@ -431,49 +357,22 @@ var Edit = class _Edit extends BaseCommand {
431
357
  context,
432
358
  editRoot
433
359
  );
434
- await this.recordGlobalSourceMigrations(
435
- migratedSkillIds,
436
- filteredResult.skills,
437
- editRoot,
438
- context
439
- );
440
360
  await this.applyScopeChanges(changes, filteredResult, context, editRoot);
441
- await this.applyCollapsedPairs(changes, filteredResult, context, editRoot);
361
+ await this.applyCollapsedPairs(changes, context, editRoot);
442
362
  await this.applySourceChanges(changes, activeOldSkills, editRoot, migratedSkillIds);
443
363
  await this.applyPluginChanges(changes, filteredResult, activeOldSkills, context, editRoot);
444
364
  await this.copyNewLocalSkills(changes, filteredResult, context, editRoot);
445
365
  await this.removeDeletedLocalSkills(changes, activeOldSkills, editRoot);
446
- await this.writeConfigAndCompile(result, context, editRoot, authority, selection.producer);
366
+ await this.writeConfigAndCompile(result, context, editRoot, authority);
447
367
  await this.cleanupStaleAgentFiles(changes, activeOldAgents, editRoot);
448
368
  await this.reportWhatThisHostCannotCarry(editRoot);
449
369
  this.logCompletionSummary(changes);
450
370
  }
451
- /** The interactive producer: open the wizard on what is installed, return what was chosen. */
452
- async selectionFromWizard(context, editRoot) {
453
- if (!process.stdin.isTTY) {
454
- this.error(wizardNeedsTerminal("edit"), { exit: EXIT_CODES.ERROR });
455
- }
456
- const result = await this.runEditWizard(context, editRoot);
457
- if (!result) return null;
458
- return { producer: "wizard", result };
459
- }
460
371
  /**
461
- * The `--from <id>` producer: fetch, seat what the configuration carries, decode, and put back
462
- * what this run has no authority to remove.
463
- *
464
- * Everything a shared configuration says is a statement about the whole roster, so the apply
465
- * that follows is destructive — the project is made to MATCH it. Two exceptions come back into
466
- * the result: a skill written here, which the producer drops on the way out because
467
- * `forkedFrom` says the CLI never wrote it, and an id the configuration NAMES that this
468
- * catalogue cannot place, because a destructive apply removes on intent and never on its own
469
- * inability. Both are disclosed in the confirm rather than silently excused.
470
- *
471
- * From a project the global install comes back too, whole: it is one installation every project
472
- * on the machine reads, so a project run only ADDS to it (owner ruling 2026-10-02). Every global
473
- * entry the configuration leaves out is put back as installed, every one it states otherwise is
474
- * held as installed and named in the confirm, and only the global entries the global install
475
- * lacks arrive — a skill with its rows, on a global sub-agent already there too. At the home
476
- * directory the run IS the global install, so nothing is held there.
372
+ * A shared configuration applies destructively, except for a skill written here (`forkedFrom`)
373
+ * and an id this catalogue cannot place — both disclosed in the confirm. From a project the
374
+ * global install is only added to (owner ruling 2026-10-02): entries the configuration omits or
375
+ * states otherwise are held as installed, and only what it lacks arrives.
477
376
  */
478
377
  async selectionFromSharedConfig(payload, context, editRoot) {
479
378
  const { matrix: sourceMatrix } = context.sourceResult;
@@ -507,25 +406,18 @@ var Edit = class _Edit extends BaseCommand {
507
406
  if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));
508
407
  if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));
509
408
  return {
510
- producer: "shared",
511
409
  result: held.result,
512
410
  kept: [
513
411
  ...keptStatements(reconciled.kept),
514
412
  ...unassignedStatement(reconciled.unassigned),
413
+ ...joinedStatement(held),
515
414
  ...keptAsInstalledStatement(held, revisedGlobally)
516
415
  ],
517
- carried: arrivingCarried
416
+ carried: arrivingCarried,
417
+ joinedGlobalAgents: held.joined.map(({ agentName }) => agentName)
518
418
  };
519
419
  }
520
- /**
521
- * Which installed skills the round trip does not own, asked of the disk exactly as the
522
- * producing half asks it.
523
- *
524
- * Best-effort by nature and never fatal: the question is only ever asked to PROTECT a skill,
525
- * so a directory that cannot be read protects nothing and must not fail an apply. The
526
- * consequence of an unanswered question is that the entry is treated as the CLI's own, which
527
- * is what every other command already assumes about it.
528
- */
420
+ /** Best-effort: an unreadable directory protects nothing and must not fail an apply. */
529
421
  async readAuthoredHere(projectConfig, editRoot) {
530
422
  if (!projectConfig) return /* @__PURE__ */ new Set();
531
423
  try {
@@ -535,16 +427,7 @@ var Edit = class _Edit extends BaseCommand {
535
427
  return /* @__PURE__ */ new Set();
536
428
  }
537
429
  }
538
- /**
539
- * The id, fetched — or the run refused before it is.
540
- *
541
- * Two questions are answered first, because nothing in the payload can change either answer:
542
- * an apply with nothing to apply to, or that cannot be confirmed, is over before the store is
543
- * asked, and a refusal that had already spent a round trip would be describing work it never
544
- * intended to do. Whether anything is installed comes before the terminal: the terminal
545
- * refusal's way on is this same command from a terminal, which in a folder with nothing
546
- * installed would only refuse again.
547
- */
430
+ /** Refuses an empty directory or a missing terminal before spending a round trip. */
548
431
  async fetchSharedConfigOrFail(id) {
549
432
  if (!await detectProject()) {
550
433
  this.error(nothingInstalledToApplyTo(id), { exit: EXIT_CODES.ERROR });
@@ -559,25 +442,13 @@ var Edit = class _Edit extends BaseCommand {
559
442
  }
560
443
  return fetched.payload;
561
444
  }
562
- /**
563
- * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).
564
- * That is a failure of this command, reported with this command's exit code rather than left to
565
- * surface as an unhandled throw.
566
- */
567
445
  decodeSeedOrFail(payload, sourceMatrix) {
568
446
  try {
569
- return seedToWizardResult(payload, sourceMatrix);
447
+ return seedToInstallSelection(payload, sourceMatrix);
570
448
  } catch (error) {
571
449
  this.handleError(error);
572
450
  }
573
451
  }
574
- /**
575
- * Seats the catalogue entries the payload carries with it, or refuses the run. The refusals are
576
- * `registerExternalSkills`' own — a carried skill asked for as a plugin, which no marketplace
577
- * serves, and a carried skill claiming an id the loaded catalogue already owns, whose bytes would
578
- * be written over that catalogue's own copy — reported with this command's exit code for the same
579
- * reason the decode's is.
580
- */
581
452
  registerExternalSkillsOrFail(payload, sourceMatrix, projectDir) {
582
453
  try {
583
454
  return registerExternalSkills(payload, sourceMatrix, projectDir);
@@ -585,15 +456,10 @@ var Edit = class _Edit extends BaseCommand {
585
456
  this.handleError(error);
586
457
  }
587
458
  }
588
- /**
589
- * Confirms a shared configuration, then writes the skills it brought with it — answering with
590
- * those whose files now read differently.
591
- */
592
459
  async confirmAndWriteCarried(selection, planned, result) {
593
460
  await this.confirmSharedConfigOrCancel(planned, selection.kept, applyArrivals(planned, result));
594
461
  return this.writeCarriedSkills(selection.carried);
595
462
  }
596
- /** Writes the skills the configuration brought with it, and says which they were. */
597
463
  async writeCarriedSkills(carried) {
598
464
  if (carried.length === 0) return [];
599
465
  const rewritten = await writeExternalSkills(carried);
@@ -601,17 +467,8 @@ var Edit = class _Edit extends BaseCommand {
601
467
  return rewritten;
602
468
  }
603
469
  /**
604
- * Shows what applying this configuration takes away, and stops the run unless a person says
605
- * yes.
606
- *
607
- * The plan is built from the SAME `ConfigChanges` the apply below acts on, so what is approved
608
- * and what is removed are one value read twice. Its kept half is the other side of the same
609
- * honesty: nothing is refused over an entry this run cannot remove, and nothing is silent
610
- * about one either.
611
- *
612
- * Above it go the two lists every `--from` install prints — what the apply adds or changes in
613
- * this project, and in the global install — so the question is asked about the whole of what a
614
- * yes does, not only about what it takes away.
470
+ * The plan and the apply read the same `ConfigChanges`, so what is approved is what is removed.
471
+ * The arrivals print above it, so the question covers the whole of what a yes does.
615
472
  */
616
473
  async confirmSharedConfigOrCancel(changes, kept, arrivals) {
617
474
  const plan = sharedConfigPlan(changes, kept);
@@ -633,31 +490,17 @@ var Edit = class _Edit extends BaseCommand {
633
490
  this.log("\nEdit cancelled");
634
491
  this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
635
492
  }
636
- /**
637
- * Refuses a configuration whose own host cannot place what it asks for, before the wizard runs.
638
- *
639
- * `compile` asks the same question of the same roster and `update` asks it too. `edit` is the
640
- * command that REWRITES the file, so letting it through would mean a user curating a
641
- * configuration no command will act on — and then saving it back, with the unofferable row
642
- * carried forward because nothing on the edit path had any reason to drop it.
643
- */
493
+ /** `edit` rewrites the file, so it must not let a user curate a roster no command acts on. */
644
494
  async refuseUnofferablePlacements(cwd) {
645
495
  const [finding] = await unofferablePlacementsFound(cwd);
646
496
  if (finding !== void 0) this.error(finding, { exit: EXIT_CODES.ERROR });
647
497
  }
648
498
  /**
649
- * The outbound half of the editor round trip: this installation, minted as a configuration
650
- * the editor opens, and handed to a browser.
651
- *
652
- * It is the same mint `share` performs — same reader, same mapping, same refusals, through
653
- * `seedPayloadForInstallation` — because an id is the whole of what either command produces
654
- * and two spellings of "the installation in this directory" would mint two different ids for
655
- * one project. What differs is only the ending: `share` reports the id, this opens it.
656
- *
657
- * Nothing on disk is touched. A configuration is read, not rewritten, so a run that changed
658
- * anything here would be editing the project on the way to offering to edit it.
499
+ * Mints through `seedPayloadForInstallation`, as `share` does, so one project has one id. Touches
500
+ * nothing on disk.
659
501
  */
660
502
  async openInEditor(projectDir) {
503
+ await this.ensureInstalledSkillsReadable(projectDir);
661
504
  const prepared = await seedPayloadForInstallation(projectDir);
662
505
  if (!prepared.ok) {
663
506
  this.error(prepared.error, { exit: EXIT_CODES.ERROR });
@@ -670,16 +513,20 @@ var Edit = class _Edit extends BaseCommand {
670
513
  await this.handToBrowser(published.id);
671
514
  }
672
515
  /**
673
- * An id somebody shared, opened rather than applied.
674
- *
675
- * The counterpart of `openInEditor` above and deliberately not a variant of it: that one MINTS,
676
- * because an installation is not yet a configuration the store holds. An id already is one, so
677
- * there is nothing to publish, and no way for this to fail except the browser refusing to launch
678
- * — which is a warning beside a link that still works.
679
- *
680
- * `--from` without `--ui` remains the destructive apply. Looking and applying are the two
681
- * things a recipient can do with an id, and this is the one that changes nothing.
516
+ * The payload reads every ejected skill's metadata.yaml for its provenance, and no catalogue is
517
+ * loaded here to resolve a skill around it, so every installed entry is asked about — not only
518
+ * those a catalogue lacks, as `edit --from` asks. The config read is the one the payload reads.
682
519
  */
520
+ async ensureInstalledSkillsReadable(projectDir) {
521
+ const loaded = await loadProjectConfig(projectDir);
522
+ if (!loaded) return;
523
+ await this.refuseUnusableSavedSkillMetadata(
524
+ loaded.config.skills,
525
+ projectDir,
526
+ editorSkillMetadataUnusableError
527
+ );
528
+ }
529
+ /** Opens an id rather than applying it; `--from` without `--ui` is the destructive apply. */
683
530
  async openSharedInEditor(id, cwd) {
684
531
  const url = editorConfigUrl(id);
685
532
  this.log(`Open it at ${url}`);
@@ -688,18 +535,7 @@ var Edit = class _Edit extends BaseCommand {
688
535
  const opened = await openUrl(url);
689
536
  if (!opened.ok) this.warn(opened.error);
690
537
  }
691
- /**
692
- * The link, printed first and opened second.
693
- *
694
- * Printed first because it is the only part of this that works everywhere: over a pipe, in CI
695
- * and on a machine with no desktop session there is no browser to be anybody's, and a link
696
- * nobody can copy is the whole loss. Opening one is the convenience on top, so a failure to
697
- * open is a warning beside a link that still works rather than a failed command.
698
- *
699
- * `process.stdin.isTTY` is the same question `init`'s dashboard asks before it offers a
700
- * prompt — is there a person here — because that is exactly what "whose browser is this"
701
- * means.
702
- */
538
+ /** The link prints first: it works over a pipe, in CI and with no desktop. Opening is extra. */
703
539
  async handToBrowser(id) {
704
540
  this.logSuccess(`Shared as ${id}`);
705
541
  for (const destination of sharedConfigDestinations(id)) {
@@ -709,21 +545,10 @@ var Edit = class _Edit extends BaseCommand {
709
545
  const opened = await openUrl(editorConfigUrl(id));
710
546
  if (!opened.ok) this.warn(opened.error);
711
547
  }
712
- /**
713
- * The load below, behind a spinner that comes down whichever way the await ends — all
714
- * three of `loadContext`'s refusals are raised while it is mounted.
715
- */
716
- async loadContextUnderSpinner(setupMarketplace) {
717
- return awaitUnderSpinner(
718
- STATUS_MESSAGES.LOADING_SKILLS,
719
- () => this.loadContext(setupMarketplace)
720
- );
548
+ async loadContextUnderSpinner() {
549
+ return awaitUnderSpinner(STATUS_MESSAGES.LOADING_SKILLS, () => this.loadContext());
721
550
  }
722
- /**
723
- * @param setupMarketplace - What `init --marketplace` named for the project setup this run
724
- * continues. Absent, the catalogue is the one the installation stored.
725
- */
726
- async loadContext(setupMarketplace) {
551
+ async loadContext() {
727
552
  const detected = await detectProject();
728
553
  if (!detected) {
729
554
  this.error(ERROR_MESSAGES.NO_INSTALLATION, {
@@ -731,147 +556,17 @@ var Edit = class _Edit extends BaseCommand {
731
556
  });
732
557
  }
733
558
  const { installation, config: projectConfig } = detected;
734
- const projectDir = installation.projectDir;
735
- let sourceResult;
736
- let startupMessages = [];
737
559
  try {
738
- const loaded = await loadSource({
739
- projectDir,
740
- ...setupMarketplace !== void 0 && { sourceFlag: setupMarketplace },
560
+ const { sourceResult, startupMessages } = await loadSource({
561
+ projectDir: installation.projectDir,
741
562
  captureStartupMessages: true
742
563
  });
743
- sourceResult = loaded.sourceResult;
744
- startupMessages = loaded.startupMessages;
745
- const sourceInfo = sourceResult.isLocal ? "local" : sourceResult.sourceConfig.sourceOrigin;
746
- startupMessages.push({
747
- level: "info",
748
- text: `Loaded ${plural(Object.keys(matrix.skills).length, "skill")} (${sourceInfo})`
749
- });
750
- } catch (error) {
751
- this.handleError(error);
752
- }
753
- let currentSkillIds;
754
- try {
755
- const discoveredSkills = await discoverAllPluginSkills(projectDir);
756
- const pluginSkillIds = typedKeys(discoveredSkills);
757
- const excludedConfigIds = new Set(
758
- projectConfig?.skills.filter((s) => s.excluded).map((s) => s.id) ?? []
759
- );
760
- const configSkillIds = projectConfig?.skills.filter((s) => !s.excluded).map((s) => s.id) ?? [];
761
- const filteredPluginSkillIds = pluginSkillIds.filter((id) => !excludedConfigIds.has(id));
762
- const mergedIds = /* @__PURE__ */ new Set([...filteredPluginSkillIds, ...configSkillIds]);
763
- currentSkillIds = [...mergedIds];
764
- startupMessages.push({
765
- level: "info",
766
- text: `Found ${plural(currentSkillIds.length, "installed skill")}`
767
- });
564
+ return { installation, projectConfig, sourceResult, startupMessages };
768
565
  } catch (error) {
769
566
  this.handleError(error);
770
567
  }
771
- return {
772
- installation,
773
- projectConfig,
774
- projectDir,
775
- sourceResult,
776
- startupMessages,
777
- currentSkillIds,
778
- ...setupMarketplace !== void 0 && sourceResult.marketplace !== void 0 && { setupMarketplace: sourceResult.marketplace }
779
- };
780
- }
781
- async runEditWizard(context, editRoot) {
782
- const { projectConfig, currentSkillIds } = context;
783
- const selectedAgents = projectConfig?.agents && activeAgentNames(projectConfig.agents);
784
- return runWizardSession({
785
- hydrate: {
786
- initialStep: "build",
787
- ...projectConfig?.selectedDomains !== void 0 && {
788
- initialDomains: projectConfig.selectedDomains
789
- },
790
- ...selectedAgents !== void 0 && { initialAgents: selectedAgents },
791
- installedSkillIds: currentSkillIds,
792
- ...projectConfig?.skills !== void 0 && { installedSkillConfigs: projectConfig.skills },
793
- ...projectConfig?.agents !== void 0 && { installedAgentConfigs: projectConfig.agents },
794
- isEditingFromGlobalScope: editRoot.isGlobal,
795
- ...context.setupMarketplace !== void 0 && {
796
- setupMarketplace: context.setupMarketplace
797
- }
798
- },
799
- props: {
800
- version: this.config.version,
801
- initialAgents: selectedAgents,
802
- installedSkillIds: currentSkillIds,
803
- startupMessages: context.startupMessages
804
- },
805
- onCancel: () => this.log("\nEdit cancelled"),
806
- clearTerminal: () => this.clearTerminal()
807
- });
808
- }
809
- /**
810
- * Records, in the GLOBAL config, the install-mode migrations this run already performed
811
- * under `$HOME`.
812
- *
813
- * A project-context edit otherwise never writes global config (commit 403df46, "never
814
- * modify global config from project-level operations"), and `authoritativeScope: "owned"`
815
- * enforces that for the roster — an inherited global-active entry is read-only, so
816
- * `mergeGlobalConfigs` preserves it verbatim. That protection is correct for selection and
817
- * scope, but `executeMigration` resolves each skill's paths from ITS OWN scope: switching a
818
- * global-scoped skill's source has already copied it under `$HOME` (or deleted it) and
819
- * added/removed its user-scope plugin registration by the time the config is written.
820
- * Leaving the global config alone there protects nothing — it only makes the recorded
821
- * source contradict the filesystem and the plugin registry.
822
- *
823
- * So authority follows the work actually performed, and no further: only ids
824
- * `executeMigration` acted on this run are rewritten, and only their `origin` field. Global
825
- * entries this session merely displayed, re-scoped or deselected are untouched, as are
826
- * `marketplace`, `stack`, `agents` and every other registered project's view of them.
827
- *
828
- * Driving a global-scope migration from a project directory is NOT a supported flow, and this
829
- * method is no longer the thing that permits it. The wizard now refuses it at source: the two
830
- * bulk install-mode keys are withdrawn, and `setInstallMode` ignores a project-context call
831
- * against a global slot the hydration snapshot owns — the same authority the Sources grid
832
- * already enforced by rendering that row inert. What still reaches here is the residue that
833
- * authority leaves legitimate: a mode change committed on the project half of a `[P][G]` pair
834
- * and then carried to global scope by a P->G collapse (`s`) in the same session. The entry is
835
- * the project's own to configure at the moment it is configured, and global at the moment it
836
- * is written — so the migration is real, and the global config must record it.
837
- *
838
- * Runs BEFORE `writeConfigAndCompile`, so the global config written here is the one
839
- * the wizard write reloads, keeps (existing wins in `mergeGlobalConfigs`) and inlines
840
- * into the project config — both files then tell the same story. That second write
841
- * classifies as a no-op against what this one left on disk, so the fan-out below
842
- * happens once.
843
- *
844
- * The migrated `origin` decides the reference form a compiled agent emits, so every
845
- * OTHER registered project's config and agents are stale until this write fans out —
846
- * which is why it goes through the gate rather than straight to the file.
847
- */
848
- async recordGlobalSourceMigrations(migratedSkillIds, newSkills, editRoot, context) {
849
- if (editRoot.isGlobal) return;
850
- const migratedSources = new Map(
851
- newSkills.filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, "global")).map((s) => [s.id, s.origin])
852
- );
853
- if (migratedSources.size === 0) return;
854
- try {
855
- const report = await mutateGlobal(
856
- { kind: "migrate-skill-sources", sources: migratedSources },
857
- {
858
- // The deps contract in config-gate/deps.ts declares
859
- // `() => Promise<MergedSkillsMatrix>`; this caller happens to have its
860
- // matrix in hand already.
861
- // eslint-disable-next-line @typescript-eslint/require-await -- deps contract
862
- loadMatrix: async () => context.sourceResult.matrix,
863
- loadAgents: async () => (await loadAgentDefs()).agents
864
- }
865
- );
866
- this.reportFanOut(report);
867
- } catch (error) {
868
- this.reportIncompleteWork(
869
- `Could not record global origin change: ${getErrorMessage(error)}`,
870
- INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION
871
- );
872
- }
873
568
  }
874
- logChangeSummary(changes, newSkills, oldSkills, removalReasons) {
569
+ logChangeSummary(changes, newSkills, oldSkills) {
875
570
  const {
876
571
  addedSkills,
877
572
  removedSkills,
@@ -884,6 +579,7 @@ var Edit = class _Edit extends BaseCommand {
884
579
  dualScopeAgentTransitions,
885
580
  tuningChanges,
886
581
  reassignedAgents,
582
+ joinedGlobalAgents,
887
583
  rewrittenSkills
888
584
  } = changes;
889
585
  this.log(`
@@ -898,10 +594,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
898
594
  for (const skillId of removedSkills) {
899
595
  const scope = oldSkills.find((s) => s.id === skillId)?.scope;
900
596
  const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : "";
901
- const reason = removalReasons.get(skillId);
902
- this.log(
903
- chalk.hex(CLI_COLORS.ERROR)(` - ${getSkillDisplayName(skillId)}${scopeLabel}`) + (reason ? chalk.hex(CLI_COLORS.NEUTRAL)(` (${reason})`) : "")
904
- );
597
+ this.log(chalk.hex(CLI_COLORS.ERROR)(` - ${getSkillDisplayName(skillId)}${scopeLabel}`));
905
598
  }
906
599
  for (const agentName of addedAgents) {
907
600
  this.log(
@@ -935,6 +628,11 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
935
628
  chalk.hex(CLI_COLORS.WARNING)(` ~ ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(" (agent: skills reassigned)")
936
629
  );
937
630
  }
631
+ for (const agentName of joinedGlobalAgents) {
632
+ this.log(
633
+ chalk.hex(CLI_COLORS.WARNING)(` ~ ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(` ${formatScopeTag("global")} (agent: skills added)`)
634
+ );
635
+ }
938
636
  for (const skillId of rewrittenSkills) {
939
637
  this.log(
940
638
  chalk.hex(CLI_COLORS.WARNING)(` ~ ${getSkillDisplayName(skillId)}`) + chalk.hex(CLI_COLORS.NEUTRAL)(" (skill: files rewritten)")
@@ -981,18 +679,8 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
981
679
  return migratedSkillIds;
982
680
  }
983
681
  /**
984
- * What the plugin→eject half copied, what it could not, and the refusal to continue past
985
- * a failure.
986
- *
987
- * The shape of `BaseCommand.reportPluginInstalls`, deliberately: the two directions of one
988
- * mode switch owe the user the same account, and the eject half having no structured
989
- * failure at all is what let a config record `origin: "eject"` for a skill whose copy was
990
- * refused. It stays private because `edit` is the only command that migrates a mode —
991
- * `init` installs, and has no old state to move.
992
- *
993
- * The count line is the same one `copyNewLocalSkills` prints, and names no destination:
994
- * the migration splits its copies between the project and $HOME by each skill's own scope,
995
- * so one directory would misname the other half.
682
+ * Mirrors `BaseCommand.reportPluginInstalls` for the plugin→eject half. The count line names no
683
+ * destination: copies split between the project and $HOME by each skill's scope.
996
684
  */
997
685
  reportEjectCopies(result) {
998
686
  for (const item of result.failed) {
@@ -1003,14 +691,12 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1003
691
  }
1004
692
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(result.copied.length)));
1005
693
  }
1006
- /** Names what this run is switching, in the words `init` describes an install mode with. */
1007
694
  logModeSwitch(count, modeDescription) {
1008
695
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Switching ${count} skill(s) to ${modeDescription}`));
1009
696
  }
1010
697
  /**
1011
- * The scope moves this edit made, on disk. A collapsed `[P][G]` pair is not one of them: its
1012
- * project half is dropped or folded ({@link applyCollapsedPairs}), and moving every collapse is
1013
- * what wrote a dropped copy over the global install.
698
+ * A collapsed `[P][G]` pair is not a move: its project half is dropped
699
+ * ({@link applyCollapsedPairs}).
1014
700
  */
1015
701
  async applyScopeChanges(changes, filteredResult, context, editRoot) {
1016
702
  const scopeChanges = scopeMovesOf(changes);
@@ -1044,29 +730,14 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1044
730
  }
1045
731
  }
1046
732
  /**
1047
- * The project's own half of each `[P][G]` pair this edit collapsed. A Local copy `s` folded into
1048
- * a Local global install moves there, edits included, replacing the global copy every project
1049
- * reads. Every other half is removed at project scope and nowhere else: its ejected copy deleted,
1050
- * or its project-scope plugin registration uninstalled.
1051
- *
1052
- * The global install's MODE is {@link applyMigrations}' to change, and it changes only when the
1053
- * collapse carried a new install mode with it — a fold into a plugin installs the plugin there.
1054
- *
1055
- * The uninstall is diagnostic, as every plugin uninstall here is: the config no longer names the
1056
- * registration, so one left behind is untidy rather than wrong.
733
+ * Each project half is removed at project scope only. The global install's mode is
734
+ * {@link applyMigrations}' to change. The uninstall is diagnostic, as every one here is.
1057
735
  */
1058
- async applyCollapsedPairs(changes, filteredResult, context, editRoot) {
1059
- const [foldedCopies, removedPairs] = partition(
1060
- changes.collapsedPairs,
1061
- (pair) => foldsItsCopyIntoGlobal(pair, filteredResult.skills)
1062
- );
736
+ async applyCollapsedPairs(changes, context, editRoot) {
1063
737
  const [ejectedHalves, pluginHalves] = partition(
1064
- removedPairs.map(({ projectHalf }) => projectHalf),
738
+ changes.collapsedPairs.map(({ projectHalf }) => projectHalf),
1065
739
  (half) => half.origin === EJECT_SOURCE
1066
740
  );
1067
- for (const { projectHalf } of foldedCopies) {
1068
- await foldLocalSkillIntoGlobal(editRoot.dir, projectHalf.id);
1069
- }
1070
741
  for (const half of ejectedHalves) {
1071
742
  await deleteLocalSkill(editRoot.dir, half.id, half.scope);
1072
743
  }
@@ -1076,7 +747,6 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1076
747
  editRoot
1077
748
  );
1078
749
  }
1079
- /** The project-scope registrations of collapsed pairs' plugin halves, uninstalled and reported. */
1080
750
  async uninstallProjectPluginHalves(pluginHalves, marketplace, editRoot) {
1081
751
  if (pluginHalves.length === 0) return;
1082
752
  if (marketplace === void 0) {
@@ -1173,7 +843,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1173
843
  await deleteLocalSkill(editRoot.dir, skillId, oldSkill.scope);
1174
844
  }
1175
845
  }
1176
- async writeConfigAndCompile(result, context, editRoot, authority, producer) {
846
+ async writeConfigAndCompile(result, context, editRoot, authority) {
1177
847
  let agentDefsResult;
1178
848
  try {
1179
849
  agentDefsResult = await loadAgentDefs();
@@ -1183,14 +853,10 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1183
853
  let configResult;
1184
854
  try {
1185
855
  configResult = await writeProjectConfig({
1186
- wizardResult: result,
856
+ selection: result,
1187
857
  sourceResult: context.sourceResult,
1188
858
  projectDir: editRoot.dir,
1189
859
  agentDefs: agentDefsResult,
1190
- // A full `cc edit` pass is authoritative over the roster it owns, so deselected entries
1191
- // are removed rather than union-preserved. `applyAuthority` decides
1192
- // how much that is from the producer and the directory, and hands the same word to the
1193
- // merger and to the global config the project branch of the gate commits.
1194
860
  authoritativeScope: authority
1195
861
  });
1196
862
  } catch (error) {
@@ -1202,7 +868,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1202
868
  try {
1203
869
  const agentScopeMap = activeAgentScopeMap(result.agentConfigs);
1204
870
  const { allSkills } = await discoverInstalledSkills(editRoot.dir);
1205
- const compile = compilesGlobalScope(producer, editRoot, configResult.propagation) ? compileAgentsAllScopes : compileProjectScope;
871
+ const compile = compilesGlobalScope(editRoot, configResult.propagation) ? compileAgentsAllScopes : compileProjectScope;
1206
872
  const compilationResult = await compile({
1207
873
  projectDir: editRoot.dir,
1208
874
  sourcePath: agentDefsResult.sourcePath,
@@ -1250,16 +916,9 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
1250
916
  }
1251
917
  }
1252
918
  /**
1253
- * What this host could not carry, once per run and after the last write: the lines `init` and
1254
- * `compile` print, from {@link hostCompileNotices}, so `edit` cannot say something different
1255
- * about the tree it just compiled.
1256
- *
1257
- * After {@link cleanupStaleAgentFiles}, because the question is about the tree as it now stands:
1258
- * an edit that removed the project's last gated sub-agent must not count the file it deleted.
1259
- *
1260
- * Not on a run that owes work, which ends on that account instead: such a run may have left
1261
- * nothing here to read, and a notice that threw over it would turn the run's
1262
- * `COMPLETED_WITH_FAILURES` exit into an `ERROR`.
919
+ * The host notices `init` and `compile` print ({@link hostCompileNotices}), after
920
+ * {@link cleanupStaleAgentFiles} so a deleted file is not counted. Skipped on a run that owes
921
+ * work, whose tree may not be readable.
1263
922
  */
1264
923
  async reportWhatThisHostCannotCarry(editRoot) {
1265
924
  if (this.hasIncompleteWork) return;
@@ -1274,21 +933,21 @@ ${chalk.hex(CLI_COLORS.SUCCESS)("\u2713 Done")}
1274
933
  `);
1275
934
  }
1276
935
  };
1277
- function detectConfigChanges(oldConfig, wizardResult, fullEntries) {
936
+ function detectConfigChanges(oldConfig, selection, fullEntries) {
1278
937
  const oldSkillIds = oldConfig?.skills.map((s) => s.id) ?? [];
1279
- const newSkillIds = wizardResult.skills.map((s) => s.id);
938
+ const newSkillIds = selection.skills.map((s) => s.id);
1280
939
  const oldAgentNames = oldConfig?.agents.map((a) => a.name) ?? [];
1281
- const newAgentNames = wizardResult.agentConfigs.map((a) => a.name);
940
+ const newAgentNames = selection.agentConfigs.map((a) => a.name);
1282
941
  const oldSkillsById = indexBy(oldConfig?.skills ?? [], (s) => s.id);
1283
942
  const oldAgentsByName = indexBy(oldConfig?.agents ?? [], (a) => a.name);
1284
943
  const scopeChanges = detectPropertyChanges(
1285
- wizardResult.skills,
944
+ selection.skills,
1286
945
  oldSkillsById,
1287
946
  (s) => s.id,
1288
947
  (s) => s.scope
1289
948
  );
1290
949
  const agentScopeChanges = detectPropertyChanges(
1291
- wizardResult.agentConfigs,
950
+ selection.agentConfigs,
1292
951
  oldAgentsByName,
1293
952
  (a) => a.name,
1294
953
  (a) => a.scope
@@ -1302,8 +961,7 @@ function detectConfigChanges(oldConfig, wizardResult, fullEntries) {
1302
961
  const collapsedPairs = collapsedPairsOf(
1303
962
  scopeChanges,
1304
963
  dualScopeSkillTransitions,
1305
- fullEntries?.oldSkills ?? [],
1306
- wizardResult.foldedSkillIds ?? []
964
+ fullEntries?.oldSkills ?? []
1307
965
  );
1308
966
  return {
1309
967
  addedSkills: difference(newSkillIds, oldSkillIds),
@@ -1311,7 +969,7 @@ function detectConfigChanges(oldConfig, wizardResult, fullEntries) {
1311
969
  addedAgents: difference(newAgentNames, oldAgentNames),
1312
970
  removedAgents: difference(oldAgentNames, newAgentNames),
1313
971
  sourceChanges: detectPropertyChanges(
1314
- wizardResult.skills,
972
+ selection.skills,
1315
973
  indexBy(withMaskedGlobalsRestored(oldConfig?.skills ?? [], collapsedPairs), (s) => s.id),
1316
974
  (s) => s.id,
1317
975
  (s) => s.origin
@@ -1327,7 +985,7 @@ function detectConfigChanges(oldConfig, wizardResult, fullEntries) {
1327
985
  (a) => a.name
1328
986
  ),
1329
987
  tuningChanges: detectPropertyChanges(
1330
- wizardResult.agentConfigs,
988
+ selection.agentConfigs,
1331
989
  oldAgentsByName,
1332
990
  (a) => a.name,
1333
991
  describeTuning
@@ -1338,6 +996,7 @@ var RESTING_TUNING = "defaults";
1338
996
  function describeTuning(agent) {
1339
997
  const settings = [
1340
998
  agent.model === void 0 ? void 0 : `model ${agent.model}`,
999
+ agent.codexModel === void 0 ? void 0 : `codex model ${agent.codexModel}`,
1341
1000
  agent.effort === void 0 ? void 0 : `effort ${agent.effort}`
1342
1001
  ].filter((setting) => setting !== void 0);
1343
1002
  return settings.length === 0 ? RESTING_TUNING : settings.join(", ");
@@ -1365,20 +1024,12 @@ function detectDualScopeTransitions(scopeChanges, fullNew, fullOld, getKey) {
1365
1024
  }
1366
1025
  return result;
1367
1026
  }
1368
- function collapsedPairsOf(scopeChanges, dualScopeSkillTransitions, fullOldSkills, foldedSkillIds) {
1027
+ function collapsedPairsOf(scopeChanges, dualScopeSkillTransitions, fullOldSkills) {
1369
1028
  return [...scopeChanges].filter(([id, change]) => change.to === "global" && dualScopeSkillTransitions.has(id)).map(([id]) => ({
1370
1029
  projectHalf: oldHalfOf(fullOldSkills, id, (skill) => isActiveAt(skill, "project")),
1371
- maskedGlobal: oldHalfOf(fullOldSkills, id, isGlobalTombstone),
1372
- folded: foldedSkillIds.includes(id)
1030
+ maskedGlobal: oldHalfOf(fullOldSkills, id, isGlobalTombstone)
1373
1031
  }));
1374
1032
  }
1375
- function foldsItsCopyIntoGlobal(pair, newSkills) {
1376
- const { projectHalf, folded } = pair;
1377
- const globalEntry = newSkills.find(
1378
- (skill) => skill.id === projectHalf.id && isActiveAt(skill, "global")
1379
- );
1380
- return folded && projectHalf.origin === EJECT_SOURCE && globalEntry?.origin === EJECT_SOURCE;
1381
- }
1382
1033
  function oldHalfOf(fullOldSkills, id, isHalf) {
1383
1034
  const half = fullOldSkills.find((skill) => skill.id === id && isHalf(skill));
1384
1035
  if (half === void 0) {
@@ -1424,7 +1075,7 @@ function planStaleAgentRemovals(changes, oldAgents, editRoot) {
1424
1075
  return STALE_AGENT_SCOPES.map(removalAtScope).filter((removal) => removal.agents.length > 0);
1425
1076
  }
1426
1077
  function hasAnyChanges(changes) {
1427
- return changes.reassignedAgents.length > 0 || changes.rewrittenSkills.length > 0 || changes.addedSkills.length > 0 || changes.removedSkills.length > 0 || changes.addedAgents.length > 0 || changes.removedAgents.length > 0 || changes.sourceChanges.size > 0 || changes.scopeChanges.size > 0 || changes.agentScopeChanges.size > 0 || changes.tuningChanges.size > 0;
1078
+ return changes.reassignedAgents.length > 0 || changes.joinedGlobalAgents.length > 0 || changes.rewrittenSkills.length > 0 || changes.addedSkills.length > 0 || changes.removedSkills.length > 0 || changes.addedAgents.length > 0 || changes.removedAgents.length > 0 || changes.sourceChanges.size > 0 || changes.scopeChanges.size > 0 || changes.agentScopeChanges.size > 0 || changes.tuningChanges.size > 0;
1428
1079
  }
1429
1080
  async function migratePluginSkillScopes(scopeChanges, skills, marketplace, projectDir) {
1430
1081
  const host = hostAt(projectDir);
@@ -1449,7 +1100,6 @@ async function migratePluginSkillScopes(scopeChanges, skills, marketplace, proje
1449
1100
  return { migrated, failed };
1450
1101
  }
1451
1102
  export {
1452
- applyMigratedGlobalSources,
1453
1103
  Edit as default,
1454
1104
  detectConfigChanges,
1455
1105
  migratePluginSkillScopes