agents-inc 0.170.0 → 0.170.2

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 (163) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
  3. package/dist/chunk-2YA4DDRM.js.map +1 -0
  4. package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
  5. package/dist/chunk-3ED3KHHD.js.map +1 -0
  6. package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
  7. package/dist/chunk-5BNX73OU.js.map +1 -0
  8. package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
  9. package/dist/chunk-66AEVERM.js.map +1 -0
  10. package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
  11. package/dist/chunk-7C3PFRBU.js.map +1 -0
  12. package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
  13. package/dist/chunk-AUNRHWH4.js.map +1 -0
  14. package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
  15. package/dist/chunk-BBDGYJHX.js.map +1 -0
  16. package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
  17. package/dist/chunk-ELV5WDS3.js.map +1 -0
  18. package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
  19. package/dist/chunk-GAKVZNTX.js.map +1 -0
  20. package/dist/chunk-GEMW5RQ2.js +1169 -0
  21. package/dist/chunk-GEMW5RQ2.js.map +1 -0
  22. package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
  23. package/dist/chunk-GHHJYNAN.js.map +1 -0
  24. package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
  25. package/dist/chunk-HACRR422.js.map +1 -0
  26. package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
  27. package/dist/chunk-IWY5IR4F.js.map +1 -0
  28. package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
  29. package/dist/chunk-KIK5EZYD.js.map +1 -0
  30. package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
  31. package/dist/chunk-O4LN3HFI.js.map +1 -0
  32. package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
  33. package/dist/chunk-OCAVW6N5.js.map +1 -0
  34. package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
  35. package/dist/chunk-P6CYS4JK.js.map +1 -0
  36. package/dist/chunk-PLFANHRZ.js +35 -0
  37. package/dist/chunk-PLFANHRZ.js.map +1 -0
  38. package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
  39. package/dist/chunk-PMUZR4XO.js.map +1 -0
  40. package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
  41. package/dist/chunk-PSUTNOQ2.js.map +1 -0
  42. package/dist/chunk-RIK45Q4I.js +103 -0
  43. package/dist/chunk-RIK45Q4I.js.map +1 -0
  44. package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
  45. package/dist/chunk-THO7LO5B.js.map +1 -0
  46. package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
  47. package/dist/chunk-YGDWHDOY.js.map +1 -0
  48. package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
  49. package/dist/chunk-YXKTY5WM.js.map +1 -0
  50. package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
  51. package/dist/chunk-ZEGM3MVR.js.map +1 -0
  52. package/dist/commands/build/marketplace.js +46 -46
  53. package/dist/commands/build/marketplace.js.map +1 -1
  54. package/dist/commands/build/plugins.js +25 -28
  55. package/dist/commands/build/plugins.js.map +1 -1
  56. package/dist/commands/compile.js +87 -178
  57. package/dist/commands/compile.js.map +1 -1
  58. package/dist/commands/doctor.js +510 -360
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/edit.js +451 -357
  61. package/dist/commands/edit.js.map +1 -1
  62. package/dist/commands/eject.js +144 -125
  63. package/dist/commands/eject.js.map +1 -1
  64. package/dist/commands/init.js +20 -27
  65. package/dist/commands/list.js +39 -55
  66. package/dist/commands/list.js.map +1 -1
  67. package/dist/commands/new/marketplace.js +6 -11
  68. package/dist/commands/new/marketplace.js.map +1 -1
  69. package/dist/commands/search.js +35 -32
  70. package/dist/commands/search.js.map +1 -1
  71. package/dist/commands/share.js +17 -77
  72. package/dist/commands/share.js.map +1 -1
  73. package/dist/commands/uninstall.js +159 -222
  74. package/dist/commands/uninstall.js.map +1 -1
  75. package/dist/commands/update.js +9 -32
  76. package/dist/commands/update.js.map +1 -1
  77. package/dist/components/common/prompt-confirm.js +2 -2
  78. package/dist/components/common/removal-plan-confirm.js +2 -2
  79. package/dist/components/common/scroll-affordance.js +2 -2
  80. package/dist/components/common/select-list.js +2 -2
  81. package/dist/components/common/skill-agent-summary.js +4 -4
  82. package/dist/components/common/spinner.js +2 -4
  83. package/dist/components/common/summary-panel.js +5 -5
  84. package/dist/components/common/summary-panel.js.map +1 -1
  85. package/dist/config-exports.js +7 -3
  86. package/dist/config-exports.js.map +1 -1
  87. package/dist/hooks/init.js +18 -19
  88. package/dist/hooks/init.js.map +1 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/load-agent-defs-6QUUMGHK.js +14 -0
  91. package/dist/recompile-project-agents-I33KQJFB.js +65 -0
  92. package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
  93. package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
  94. package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
  95. package/dist/src/agents/developer/api-developer/playbook.md +2 -5
  96. package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
  97. package/dist/src/agents/developer/web-developer/playbook.md +2 -5
  98. package/dist/src/agents/meta/agent-summoner/output.md +2 -2
  99. package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
  100. package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  101. package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  102. package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  103. package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
  104. package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
  105. package/dist/src/agents/tester/api-tester/playbook.md +2 -0
  106. package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  107. package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
  108. package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
  109. package/dist/src/agents/tester/web-tester/playbook.md +2 -0
  110. package/package.json +9 -8
  111. package/src/agents/developer/ai-developer/playbook.md +2 -5
  112. package/src/agents/developer/api-developer/playbook.md +2 -5
  113. package/src/agents/developer/cli-developer/playbook.md +2 -5
  114. package/src/agents/developer/web-developer/playbook.md +2 -5
  115. package/src/agents/meta/agent-summoner/output.md +2 -2
  116. package/src/agents/meta/agent-summoner/playbook.md +1 -13
  117. package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  118. package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  119. package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  120. package/src/agents/tester/ai-tester/playbook.md +2 -0
  121. package/src/agents/tester/api-tester/critical-requirements.md +1 -2
  122. package/src/agents/tester/api-tester/playbook.md +2 -0
  123. package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  124. package/src/agents/tester/cli-tester/playbook.md +2 -0
  125. package/src/agents/tester/web-tester/critical-requirements.md +1 -2
  126. package/src/agents/tester/web-tester/playbook.md +2 -0
  127. package/src/schemas/project-config.schema.json +0 -3
  128. package/src/schemas/project-source-config.schema.json +0 -6
  129. package/dist/chunk-3G7X2WKI.js.map +0 -1
  130. package/dist/chunk-44TE3RKH.js.map +0 -1
  131. package/dist/chunk-4AAOOAIN.js.map +0 -1
  132. package/dist/chunk-52HDHJ7I.js.map +0 -1
  133. package/dist/chunk-6HNXYYVF.js +0 -373
  134. package/dist/chunk-6HNXYYVF.js.map +0 -1
  135. package/dist/chunk-6ZRH5RHC.js.map +0 -1
  136. package/dist/chunk-7RDMTR64.js.map +0 -1
  137. package/dist/chunk-BMRUNMPV.js.map +0 -1
  138. package/dist/chunk-CLPUWOSA.js +0 -46
  139. package/dist/chunk-CLPUWOSA.js.map +0 -1
  140. package/dist/chunk-F2BHT5C4.js.map +0 -1
  141. package/dist/chunk-F5EBEATU.js.map +0 -1
  142. package/dist/chunk-HED2DAXZ.js.map +0 -1
  143. package/dist/chunk-JFLVEFFP.js.map +0 -1
  144. package/dist/chunk-KOLDW6SF.js.map +0 -1
  145. package/dist/chunk-MQ6CGZNJ.js.map +0 -1
  146. package/dist/chunk-NCWDK6L7.js.map +0 -1
  147. package/dist/chunk-NEZ4OAOL.js.map +0 -1
  148. package/dist/chunk-NIHUOWE4.js +0 -106
  149. package/dist/chunk-NIHUOWE4.js.map +0 -1
  150. package/dist/chunk-NQW25DCF.js.map +0 -1
  151. package/dist/chunk-OYJQUA3D.js.map +0 -1
  152. package/dist/chunk-PJWGTNOX.js.map +0 -1
  153. package/dist/chunk-RIPSGNLU.js.map +0 -1
  154. package/dist/chunk-SZYQISA2.js.map +0 -1
  155. package/dist/chunk-USVBYQSQ.js.map +0 -1
  156. package/dist/chunk-V3KTSP3Q.js +0 -940
  157. package/dist/chunk-V3KTSP3Q.js.map +0 -1
  158. package/dist/chunk-WTWMGH2C.js.map +0 -1
  159. package/dist/load-agent-defs-YMDWBFDP.js +0 -14
  160. package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
  161. package/dist/source-loader-C5SQXZXI.js.map +0 -1
  162. /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
  163. /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
@@ -1,78 +1,79 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  awaitUnderSpinner
4
- } from "../chunk-NEZ4OAOL.js";
4
+ } from "../chunk-ZEGM3MVR.js";
5
5
  import {
6
6
  publishSeedConfig,
7
7
  seedPayloadForInstallation,
8
8
  skillsAuthoredHere
9
- } from "../chunk-SZYQISA2.js";
9
+ } from "../chunk-ELV5WDS3.js";
10
10
  import {
11
11
  RemovalPlanConfirm
12
- } from "../chunk-USVBYQSQ.js";
12
+ } from "../chunk-O4LN3HFI.js";
13
13
  import {
14
14
  unofferablePlacementsFound
15
- } from "../chunk-WTWMGH2C.js";
15
+ } from "../chunk-HACRR422.js";
16
16
  import {
17
- arrivalLines,
18
- arrivalsByScope,
19
- joinedStatement,
20
- notInstalledGlobally,
21
- openUrl,
22
- readInstalledGlobal,
23
- reconcileSharedConfig,
24
- restoreInstalledGlobal,
25
- sameAssignments,
26
- skillLabel,
27
- withUnplaceableAssignees
28
- } from "../chunk-6HNXYYVF.js";
17
+ openUrl
18
+ } from "../chunk-PLFANHRZ.js";
29
19
  import {
30
20
  fetchSeedConfig
31
- } from "../chunk-OYJQUA3D.js";
21
+ } from "../chunk-YGDWHDOY.js";
32
22
  import {
33
23
  promptConfirm
34
- } from "../chunk-4AAOOAIN.js";
24
+ } from "../chunk-P6CYS4JK.js";
35
25
  import "../chunk-OZXAJNLA.js";
36
26
  import {
37
27
  hostCompileNotices
38
- } from "../chunk-F5EBEATU.js";
28
+ } from "../chunk-PSUTNOQ2.js";
39
29
  import {
40
30
  compileAgentsAllScopes,
41
31
  compileProjectScope,
42
32
  detectProject,
43
33
  loadSource,
44
34
  movedGlobalAgentInputs,
35
+ projectsAFanOutReaches,
45
36
  sayCapturedWarnings,
46
37
  writeProjectConfig
47
- } from "../chunk-7RDMTR64.js";
38
+ } from "../chunk-66AEVERM.js";
48
39
  import {
49
40
  copyLocalSkills,
50
41
  discoverInstalledSkills,
51
42
  removeCompiledAgents,
52
43
  uninstallPluginSkills
53
- } from "../chunk-F2BHT5C4.js";
44
+ } from "../chunk-IWY5IR4F.js";
54
45
  import {
55
46
  loadAgentDefs
56
- } from "../chunk-HED2DAXZ.js";
57
- import "../chunk-3G7X2WKI.js";
58
- import "../chunk-BMRUNMPV.js";
47
+ } from "../chunk-THO7LO5B.js";
48
+ import "../chunk-5BNX73OU.js";
49
+ import "../chunk-2YA4DDRM.js";
59
50
  import {
60
51
  formatScopeTag
61
- } from "../chunk-NIHUOWE4.js";
62
- import "../chunk-JFLVEFFP.js";
52
+ } from "../chunk-RIK45Q4I.js";
53
+ import "../chunk-KIK5EZYD.js";
63
54
  import {
64
55
  providerFlag,
65
56
  providerNamedBy,
66
57
  refuseAnAmbiguousInstallation
67
- } from "../chunk-RIPSGNLU.js";
58
+ } from "../chunk-OCAVW6N5.js";
68
59
  import {
69
60
  BaseCommand,
70
61
  EXIT_CODES,
62
+ arrivalLines,
63
+ arrivalsByScope,
71
64
  carriedSkillsThatDiffer,
65
+ installsAtHome,
66
+ joinedStatement,
67
+ notInstalledGlobally,
68
+ readInstalledGlobal,
69
+ reconcileSharedConfig,
72
70
  registerExternalSkills,
71
+ restoreInstalledGlobal,
72
+ sameAssignments,
73
+ skillLabel,
74
+ withUnplaceableAssignees,
73
75
  writeExternalSkills
74
- } from "../chunk-V3KTSP3Q.js";
75
- import "../chunk-CLPUWOSA.js";
76
+ } from "../chunk-GEMW5RQ2.js";
76
77
  import {
77
78
  ERROR_MESSAGES,
78
79
  INCOMPLETE_WORK_RECOVERY,
@@ -85,6 +86,7 @@ import {
85
86
  authoredHereKept,
86
87
  buildMarketplacePluginRef,
87
88
  carriedSkillsWritten,
89
+ copyingBesideGlobalPlugins,
88
90
  deleteLocalSkill,
89
91
  detectMigrations,
90
92
  editorSkillMetadataUnusableError,
@@ -93,28 +95,31 @@ import {
93
95
  getErrorMessage,
94
96
  holdsItsOwnInstallation,
95
97
  hostAt,
98
+ installingBesideGlobalCopies,
96
99
  isHomeDirectory,
100
+ keepsGlobalInstall,
97
101
  keptAsInstalledGlobally,
98
102
  keptUnassigned,
99
103
  loadProjectConfig,
100
104
  localSkillsCopied,
101
105
  migrateLocalSkillScope,
102
106
  nothingInstalledToApplyTo,
107
+ projectCopyMovedToGlobal,
103
108
  projectCopyRemoved,
104
109
  providerInUse,
105
110
  recompileSummary,
111
+ registeredProjectsRewritten,
106
112
  resolveInstallPaths,
107
113
  seedToInstallSelection,
108
114
  sharedConfigDestinations,
109
115
  sharedConfigNeedsTerminal,
110
- skippedUnknownAgents,
111
- skippedUnknownSkills,
112
116
  unplaceableKept
113
- } from "../chunk-MQ6CGZNJ.js";
117
+ } from "../chunk-GAKVZNTX.js";
114
118
  import {
115
119
  getSkillById,
116
- getSkillDisplayName
117
- } from "../chunk-52HDHJ7I.js";
120
+ getSkillDisplayName,
121
+ stripTerminalControls
122
+ } from "../chunk-AUNRHWH4.js";
118
123
  import {
119
124
  CLI_COLORS,
120
125
  CLI_INVOKE_COMMAND,
@@ -124,61 +129,110 @@ import {
124
129
  formatSourceDisplayName,
125
130
  isActiveAt,
126
131
  isGlobalTombstone
127
- } from "../chunk-PJWGTNOX.js";
128
- import "../chunk-NQW25DCF.js";
132
+ } from "../chunk-7C3PFRBU.js";
133
+ import "../chunk-GHHJYNAN.js";
129
134
 
130
135
  // src/cli/commands/edit.tsx
131
136
  import path from "path";
132
137
  import chalk from "chalk";
133
138
  import { Flags } from "@oclif/core";
134
- import { difference, indexBy, partition } from "remeda";
139
+ import { difference, indexBy, partition, unique } from "remeda";
135
140
  import { jsx } from "react/jsx-runtime";
136
141
  var RECOMPILE_SUBJECT = "agent";
137
- function formatDualScopeTransition(displayName, to) {
138
- const isAdd = to === "project";
139
- const prefix = isAdd ? "+" : "-";
140
- const color = isAdd ? CLI_COLORS.SUCCESS : CLI_COLORS.ERROR;
141
- return chalk.hex(color)(` ${prefix} ${displayName} [P]`);
142
+ var CHANGE_MARKER_COLORS = {
143
+ "+": CLI_COLORS.SUCCESS,
144
+ "-": CLI_COLORS.ERROR,
145
+ "~": CLI_COLORS.WARNING
146
+ };
147
+ var AGENT_DETAIL = " (agent)";
148
+ function changeLine(marker, subject, detail) {
149
+ const head = chalk.hex(CHANGE_MARKER_COLORS[marker])(` ${marker} ${subject}`);
150
+ return detail === void 0 ? head : head + chalk.hex(CLI_COLORS.NEUTRAL)(detail);
151
+ }
152
+ function dualScopeTransitionLine(subject, to, detail) {
153
+ return changeLine(to === "project" ? "+" : "-", `${subject} [P]`, detail);
142
154
  }
143
155
  function formatSkillScopeChangeLine(skillId, change, dualScopeSkillTransitions) {
144
156
  const displayName = getSkillDisplayName(skillId);
145
157
  if (dualScopeSkillTransitions.has(skillId)) {
146
- return formatDualScopeTransition(displayName, change.to);
158
+ return dualScopeTransitionLine(displayName, change.to);
147
159
  }
148
160
  const isGlobalToProject = change.from === "global" && change.to === "project";
149
- const prefix = isGlobalToProject ? "+" : "~";
150
- const color = isGlobalToProject ? CLI_COLORS.SUCCESS : CLI_COLORS.WARNING;
151
- return chalk.hex(color)(` ${prefix} ${displayName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(scopeArrow(change));
161
+ return changeLine(isGlobalToProject ? "+" : "~", displayName, scopeArrow(change));
152
162
  }
153
163
  function formatAgentScopeChangeLine(agentName, change, dualScopeAgentTransitions) {
154
- const agentSuffix = chalk.hex(CLI_COLORS.NEUTRAL)(" (agent)");
155
164
  if (dualScopeAgentTransitions.has(agentName)) {
156
- return formatDualScopeTransition(agentName, change.to) + agentSuffix;
165
+ return dualScopeTransitionLine(agentName, change.to, AGENT_DETAIL);
157
166
  }
158
- return chalk.hex(CLI_COLORS.WARNING)(` ~ ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(scopeArrow(change));
167
+ return changeLine("~", agentName, scopeArrow(change));
159
168
  }
160
169
  function scopeArrow(change) {
161
170
  return ` (${formatScopeTag(change.from)} \u2192 ${formatScopeTag(change.to)})`;
162
171
  }
163
172
  function formatValueChangeLine(subject, change, kind) {
164
- return chalk.hex(CLI_COLORS.WARNING)(` ~ ${subject}`) + chalk.hex(CLI_COLORS.NEUTRAL)(` (${kind}: ${change.from} \u2192 ${change.to})`);
173
+ return changeLine("~", subject, ` (${kind}: ${change.from} \u2192 ${change.to})`);
174
+ }
175
+ function sourceChangeLine(skillId, change) {
176
+ const from = formatSourceDisplayName(change.from);
177
+ const to = formatSourceDisplayName(change.to);
178
+ return changeLine("~", getSkillDisplayName(skillId), ` (${from} \u2192 ${to})`);
179
+ }
180
+ function scopeLabelOf(skillId, skills) {
181
+ const skill = skills.find((s) => s.id === skillId);
182
+ return skill === void 0 ? "" : ` ${formatScopeTag(skill.scope)}`;
183
+ }
184
+ function changeSummaryLines(changes, newSkills, oldSkills) {
185
+ const addedSkill = (id) => changeLine(
186
+ "+",
187
+ `${stripTerminalControls(getSkillById(id).displayName)}${scopeLabelOf(id, newSkills)}`
188
+ );
189
+ const removedSkill = (id) => changeLine("-", `${getSkillDisplayName(id)}${scopeLabelOf(id, oldSkills)}`);
190
+ const joinedGlobalDetail = ` ${formatScopeTag("global")} (agent: skills added)`;
191
+ return [
192
+ ...changes.addedSkills.map(addedSkill),
193
+ ...changes.removedSkills.map(removedSkill),
194
+ ...changes.addedAgents.map((name) => changeLine("+", name, AGENT_DETAIL)),
195
+ ...changes.removedAgents.map((name) => changeLine("-", name, AGENT_DETAIL)),
196
+ ...[...changes.sourceChanges].map(([id, change]) => sourceChangeLine(id, change)),
197
+ ...[...changes.scopeChanges].map(
198
+ ([id, change]) => formatSkillScopeChangeLine(id, change, changes.dualScopeSkillTransitions)
199
+ ),
200
+ ...[...changes.agentScopeChanges].map(
201
+ ([name, change]) => formatAgentScopeChangeLine(name, change, changes.dualScopeAgentTransitions)
202
+ ),
203
+ ...[...changes.tuningChanges].map(
204
+ ([name, change]) => formatValueChangeLine(name, change, "agent")
205
+ ),
206
+ ...changes.reassignedAgents.map((name) => changeLine("~", name, " (agent: skills reassigned)")),
207
+ ...changes.joinedGlobalAgents.map((name) => changeLine("~", name, joinedGlobalDetail)),
208
+ ...changes.rewrittenSkills.map(
209
+ (id) => changeLine("~", getSkillDisplayName(id), " (skill: files rewritten)")
210
+ )
211
+ ];
165
212
  }
166
213
  function resolveEditRoot(installation) {
167
214
  const dir = installation.projectDir;
168
215
  return { dir, isGlobal: isHomeDirectory(dir) };
169
216
  }
170
- function sharedConfigPlan(changes, kept) {
217
+ function sharedConfigPlan(changes, overwrittenSkillIds2, statements) {
171
218
  const dropped = droppedProjectHalves(changes);
219
+ const moved = movedToGlobal(changes);
172
220
  const skillLines = [
173
221
  ...changes.removedSkills.map(skillLabel),
174
- ...dropped.skillIds.map(droppedSkillLine)
222
+ ...dropped.skillIds.map((id) => projectCopyRemoved(skillLabel(id))),
223
+ ...moved.skillIds.map((id) => projectCopyMovedToGlobal(skillLabel(id)))
224
+ ];
225
+ const agentLines = [
226
+ ...changes.removedAgents,
227
+ ...dropped.agentNames.map(projectCopyRemoved),
228
+ ...moved.agentNames.map(projectCopyMovedToGlobal)
175
229
  ];
176
- const agentLines = [...changes.removedAgents, ...dropped.agentNames.map(projectCopyRemoved)];
177
230
  const sections = removalSections(skillLines, agentLines);
178
- return { heading: planHeading(sections), sections, statements: kept };
179
- }
180
- function droppedSkillLine(skillId) {
181
- return projectCopyRemoved(skillLabel(skillId));
231
+ const overwritten = {
232
+ label: SHARED_CONFIG_APPLY.OVERWRITTEN_HEADING,
233
+ items: overwrittenSkillIds2.map(skillLabel)
234
+ };
235
+ return { ...planHeading(sections, overwritten), sections, overwritten, statements };
182
236
  }
183
237
  function removalSections(skills, agents) {
184
238
  return [
@@ -195,17 +249,54 @@ function droppedProjectHalves(changes) {
195
249
  agentNames: droppedAgents.map(([name]) => name)
196
250
  };
197
251
  }
198
- function planHeading(sections) {
199
- if (sections.length === 0) return SHARED_CONFIG_APPLY.NOTHING_REMOVED;
200
- return SHARED_CONFIG_APPLY.PREVIEW_HEADING;
252
+ function movedToGlobal(changes) {
253
+ const skillMoves = [...scopeMovesOf(changes)].filter(([, change]) => change.to === "global");
254
+ const agentMoves = [...changes.agentScopeChanges].filter(
255
+ ([name, change]) => change.to === "global" && !changes.dualScopeAgentTransitions.has(name)
256
+ );
257
+ return {
258
+ skillIds: skillMoves.map(([id]) => id),
259
+ agentNames: agentMoves.map(([name]) => name)
260
+ };
261
+ }
262
+ function planHeading(sections, overwritten) {
263
+ if (sections.length > 0) return { heading: SHARED_CONFIG_APPLY.PREVIEW_HEADING };
264
+ if (overwritten.items.length > 0) return {};
265
+ return { heading: SHARED_CONFIG_APPLY.NOTHING_REMOVED };
266
+ }
267
+ function overwrittenSkillIds(changes, active) {
268
+ const leaving = new Set(movedToGlobal(changes).skillIds);
269
+ const switched = ejectedCopiesSwitchedToPlugins(migrationPlanOf(changes, active));
270
+ return unique([...changes.rewrittenSkills, ...switched]).filter((id) => !leaving.has(id));
271
+ }
272
+ function ejectedCopiesSwitchedToPlugins(plan) {
273
+ return plan.toPlugin.filter((migration) => !keepsGlobalInstall(migration)).map(({ id }) => id);
274
+ }
275
+ function migrationPlanOf(changes, active) {
276
+ return detectMigrations(
277
+ withMaskedGlobalsRestored(active.oldSkills, changes.collapsedPairs),
278
+ active.selection.skills
279
+ );
280
+ }
281
+ async function carriedThatChange(carried) {
282
+ const changing = new Set(await carriedSkillsThatDiffer(carried));
283
+ return carried.filter((skill) => changing.has(skill.id));
284
+ }
285
+ function withRewrittenCarried(planned, carriedToWrite) {
286
+ const writtenIds = carriedToWrite.map((skill) => skill.id);
287
+ return { ...planned, rewrittenSkills: difference(writtenIds, skillsNewHere(planned)) };
201
288
  }
202
289
  function compilesGlobalScope(editRoot, written) {
203
290
  return editRoot.isGlobal || movedGlobalAgentInputs(written);
204
291
  }
205
292
  function withReassignments(changes, result, installedStack, editRoot) {
206
293
  const { assignedStack } = result;
294
+ const arrivingCopies = arrivingProjectHalves(
295
+ changes.agentScopeChanges,
296
+ changes.dualScopeAgentTransitions
297
+ );
207
298
  const ownedHere = (agent) => editRoot.isGlobal || isActiveAt(agent, "project");
208
- const countedAsAdded = (agent) => changes.addedAgents.includes(agent.name);
299
+ const countedAsAdded = (agent) => changes.addedAgents.includes(agent.name) || arrivingCopies.has(agent.name);
209
300
  const rowsMoved = (agent) => !sameAssignments(assignedStack[agent.name], installedStack?.[agent.name]);
210
301
  const reassigned = result.agentConfigs.filter(
211
302
  (agent) => ownedHere(agent) && !countedAsAdded(agent) && rowsMoved(agent)
@@ -249,15 +340,50 @@ function unassignedStatement(unassigned) {
249
340
  unassigned.map(({ skillId, agentName, category }) => keptUnassigned(skillId, agentName, category)).join("\n")
250
341
  ];
251
342
  }
252
- function keptAsInstalledStatement(held, revisedCarried) {
343
+ function keptOnApply(reconciled, held, revisedCarried, idAppliedAtHome) {
344
+ return [
345
+ ...keptStatements(reconciled.kept),
346
+ ...unassignedStatement(reconciled.unassigned),
347
+ ...joinedStatement(held),
348
+ ...keptAsInstalledStatement(held, revisedCarried, idAppliedAtHome)
349
+ ];
350
+ }
351
+ function keptAsInstalledStatement(held, revisedCarried, idAppliedAtHome) {
253
352
  const skillIds = [...held.keptAsInstalled.skillIds, ...revisedCarried];
254
353
  const { agentNames } = held.keptAsInstalled;
255
354
  if (skillIds.length === 0 && agentNames.length === 0) return [];
256
- return [keptAsInstalledGlobally(skillIds, agentNames)];
355
+ return [keptAsInstalledGlobally(skillIds, agentNames, idAppliedAtHome)];
257
356
  }
258
357
  function applyAuthority(editRoot) {
259
358
  return editRoot.isGlobal ? "all" : "owned";
260
359
  }
360
+ function activeEntriesOf(result, projectConfig) {
361
+ const oldSkills = (projectConfig?.skills ?? []).filter((s) => !s.excluded);
362
+ const oldAgents = (projectConfig?.agents ?? []).filter((a) => !a.excluded);
363
+ return {
364
+ selection: {
365
+ ...result,
366
+ skills: result.skills.filter((s) => !s.excluded),
367
+ agentConfigs: result.agentConfigs.filter((a) => !a.excluded)
368
+ },
369
+ oldConfig: projectConfig ? { ...projectConfig, skills: oldSkills, agents: oldAgents } : null,
370
+ oldSkills,
371
+ oldAgents
372
+ };
373
+ }
374
+ function planChanges(selection, active, projectConfig, editRoot) {
375
+ const keptInstalled = globalHalvesKeptInstalled(selection.installedGlobal);
376
+ const changes = detectConfigChanges(active.oldConfig, active.selection, {
377
+ newSkills: [...selection.result.skills, ...keptInstalled.skills],
378
+ oldSkills: projectConfig?.skills ?? [],
379
+ newAgents: [...selection.result.agentConfigs, ...keptInstalled.agents],
380
+ oldAgents: projectConfig?.agents ?? []
381
+ });
382
+ return {
383
+ ...withReassignments(changes, active.selection, projectConfig?.stack, editRoot),
384
+ joinedGlobalAgents: selection.joinedGlobalAgents
385
+ };
386
+ }
261
387
  var Edit = class _Edit extends BaseCommand {
262
388
  static summary = "Open this installation in the editor, or apply a configuration with --from";
263
389
  static description = "Open this installation in agentsinc.sh/editor, or apply a configuration built there with --from";
@@ -294,17 +420,23 @@ var Edit = class _Edit extends BaseCommand {
294
420
  async applyEdit() {
295
421
  const { flags } = await this.parse(_Edit);
296
422
  const cwd = process.cwd();
297
- if (flags.ui && flags.from !== void 0) return this.openSharedInEditor(flags.from, cwd);
423
+ const namedProvider = providerNamedBy(flags.provider);
424
+ if (flags.ui && flags.from !== void 0) {
425
+ return this.openSharedInEditor(flags.from, cwd, namedProvider);
426
+ }
298
427
  await refuseAnAmbiguousInstallation(
299
428
  cwd,
300
429
  "edit",
301
- providerNamedBy(flags.provider),
430
+ namedProvider,
302
431
  (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS })
303
432
  );
304
433
  await this.ensureConfigReadable(cwd);
305
434
  await this.refuseUnofferablePlacements(cwd);
306
435
  if (flags.from === void 0) return this.openInEditor(cwd);
307
- const payload = await this.fetchSharedConfigOrFail(flags.from);
436
+ return this.applySharedConfig(flags.from, namedProvider);
437
+ }
438
+ async applySharedConfig(id, namedProvider) {
439
+ const payload = await this.fetchSharedConfigOrFail(id, namedProvider);
308
440
  const context = await this.loadContextUnderSpinner();
309
441
  const editRoot = resolveEditRoot(context.installation);
310
442
  await this.ensureSavedSkillsReadable(
@@ -312,87 +444,46 @@ var Edit = class _Edit extends BaseCommand {
312
444
  context.sourceResult.matrix,
313
445
  editRoot.dir
314
446
  );
315
- const selection = await this.selectionFromSharedConfig(payload, context, editRoot);
316
- const { result } = selection;
317
- this.reportValidationErrors(result.validation);
318
- const activeNewSkills = result.skills.filter((s) => !s.excluded);
319
- const activeNewAgents = result.agentConfigs.filter((a) => !a.excluded);
320
- const activeOldSkills = (context.projectConfig?.skills ?? []).filter((s) => !s.excluded);
321
- const activeOldAgents = (context.projectConfig?.agents ?? []).filter((a) => !a.excluded);
322
- const filteredResult = {
323
- ...result,
324
- skills: activeNewSkills,
325
- agentConfigs: activeNewAgents
326
- };
327
- const filteredOldConfig = context.projectConfig ? { ...context.projectConfig, skills: activeOldSkills, agents: activeOldAgents } : null;
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);
343
- const changes = {
344
- ...planned,
345
- rewrittenSkills: difference(rewritten, planned.addedSkills)
346
- };
347
- const authority = applyAuthority(editRoot);
348
- if (!hasAnyChanges(changes)) {
349
- this.log(chalk.hex(CLI_COLORS.NEUTRAL)("No changes made."));
350
- return;
351
- }
352
- this.logChangeSummary(changes, filteredResult.skills, filteredOldConfig?.skills ?? []);
353
- const migratedSkillIds = await this.applyMigrations(
354
- changes,
355
- filteredResult,
356
- activeOldSkills,
357
- context,
358
- editRoot
359
- );
360
- await this.applyScopeChanges(changes, filteredResult, context, editRoot);
447
+ const selection = await this.selectionFromSharedConfig(id, payload, context, editRoot);
448
+ this.reportValidationErrors(selection.result.validation);
449
+ const active = activeEntriesOf(selection.result, context.projectConfig);
450
+ const planned = planChanges(selection, active, context.projectConfig, editRoot);
451
+ const carriedToWrite = await carriedThatChange(selection.carried);
452
+ const changes = withRewrittenCarried(planned, carriedToWrite);
453
+ if (!hasAnyChanges(changes)) return this.sayNothingChanged(selection.kept);
454
+ const plan = await this.planToConfirm(changes, active, selection.kept, context, editRoot);
455
+ await this.confirmSharedConfigOrCancel(plan, applyArrivals(changes, active.selection));
456
+ await this.writeCarriedSkills(carriedToWrite);
457
+ await this.applyApprovedChanges(changes, active, selection.result, context, editRoot);
458
+ }
459
+ async applyApprovedChanges(changes, active, result, context, editRoot) {
460
+ const { selection: activeSelection, oldSkills, oldAgents } = active;
461
+ this.logChangeSummary(changes, activeSelection.skills, oldSkills);
462
+ await this.applyMigrations(changes, active, context, editRoot);
463
+ await this.applyScopeChanges(changes, activeSelection, context, editRoot);
361
464
  await this.applyCollapsedPairs(changes, context, editRoot);
362
- await this.applySourceChanges(changes, activeOldSkills, editRoot, migratedSkillIds);
363
- await this.applyPluginChanges(changes, filteredResult, activeOldSkills, context, editRoot);
364
- await this.copyNewLocalSkills(changes, filteredResult, context, editRoot);
365
- await this.removeDeletedLocalSkills(changes, activeOldSkills, editRoot);
366
- await this.writeConfigAndCompile(result, context, editRoot, authority);
367
- await this.cleanupStaleAgentFiles(changes, activeOldAgents, editRoot);
465
+ await this.applyPluginChanges(changes, activeSelection, oldSkills, context, editRoot);
466
+ await this.copyNewLocalSkills(changes, activeSelection, context, editRoot);
467
+ await this.removeDeletedLocalSkills(changes, oldSkills, editRoot);
468
+ await this.writeConfigAndCompile(result, context, editRoot);
469
+ await this.cleanupStaleAgentFiles(changes, oldAgents, editRoot);
368
470
  await this.reportWhatThisHostCannotCarry(editRoot);
369
- this.logCompletionSummary(changes);
471
+ this.logCompletionSummary();
370
472
  }
371
473
  /**
372
474
  * A shared configuration applies destructively, except for a skill written here (`forkedFrom`)
373
475
  * 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.
476
+ * global install is only added to.
376
477
  */
377
- async selectionFromSharedConfig(payload, context, editRoot) {
478
+ async selectionFromSharedConfig(id, payload, context, editRoot) {
378
479
  const { matrix: sourceMatrix } = context.sourceResult;
379
480
  const carried = this.registerExternalSkillsOrFail(payload, sourceMatrix, editRoot.dir);
380
- const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(
381
- payload,
382
- sourceMatrix
383
- );
481
+ const mapping = this.decodeSeedOrFail(payload, sourceMatrix);
482
+ const { result } = mapping;
384
483
  this.refuseProjectScopedContentAtHome(result, editRoot.dir);
385
- const unplaceable = new Set(skippedSkillIds);
386
- const reconciled = reconcileSharedConfig({
387
- decoded: withUnplaceableAssignees(result, context.projectConfig, payload, unplaceable),
388
- installed: context.projectConfig,
389
- authoredHere: await this.readAuthoredHere(context.projectConfig, editRoot.dir),
390
- unplaceable
391
- });
392
- const held = restoreInstalledGlobal(
393
- reconciled.result,
394
- editRoot.isGlobal ? null : await readInstalledGlobal(editRoot.dir)
395
- );
484
+ const reconciled = await this.reconcileWithInstallation(mapping, payload, context, editRoot);
485
+ const installedGlobal = editRoot.isGlobal ? null : await readInstalledGlobal(editRoot.dir);
486
+ const held = restoreInstalledGlobal(reconciled.result, installedGlobal);
396
487
  const arrivingCarried = notInstalledGlobally(carried, held);
397
488
  await this.refuseSharedConfigBeforeAsking(
398
489
  held.result,
@@ -400,23 +491,30 @@ var Edit = class _Edit extends BaseCommand {
400
491
  editRoot.dir,
401
492
  context.sourceResult
402
493
  );
403
- const heldGlobally = difference(carried, arrivingCarried);
404
- const revisedGlobally = await carriedSkillsThatDiffer(heldGlobally);
494
+ const revisedGlobally = await carriedSkillsThatDiffer(difference(carried, arrivingCarried));
405
495
  sayCapturedWarnings(context.startupMessages);
406
- if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));
407
- if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));
496
+ this.warnOfSkippedEntries(mapping, held.result.selectedAgents);
408
497
  return {
409
498
  result: held.result,
410
- kept: [
411
- ...keptStatements(reconciled.kept),
412
- ...unassignedStatement(reconciled.unassigned),
413
- ...joinedStatement(held),
414
- ...keptAsInstalledStatement(held, revisedGlobally)
415
- ],
499
+ kept: keptOnApply(reconciled, held, revisedGlobally, installsAtHome(result) ? id : void 0),
416
500
  carried: arrivingCarried,
417
- joinedGlobalAgents: held.joined.map(({ agentName }) => agentName)
501
+ joinedGlobalAgents: held.joined.map(({ agentName }) => agentName),
502
+ installedGlobal
418
503
  };
419
504
  }
505
+ /**
506
+ * Ids the decode could not place stay, as does a sub-agent only they carried in: a catalogue
507
+ * limit is not an instruction to delete.
508
+ */
509
+ async reconcileWithInstallation({ result, skippedSkillIds }, payload, { projectConfig }, editRoot) {
510
+ const unplaceable = new Set(skippedSkillIds);
511
+ return reconcileSharedConfig({
512
+ decoded: withUnplaceableAssignees(result, projectConfig, payload, unplaceable),
513
+ installed: projectConfig,
514
+ authoredHere: await this.readAuthoredHere(projectConfig, editRoot.dir),
515
+ unplaceable
516
+ });
517
+ }
420
518
  /** Best-effort: an unreadable directory protects nothing and must not fail an apply. */
421
519
  async readAuthoredHere(projectConfig, editRoot) {
422
520
  if (!projectConfig) return /* @__PURE__ */ new Set();
@@ -427,13 +525,16 @@ var Edit = class _Edit extends BaseCommand {
427
525
  return /* @__PURE__ */ new Set();
428
526
  }
429
527
  }
430
- /** Refuses an empty directory or a missing terminal before spending a round trip. */
431
- async fetchSharedConfigOrFail(id) {
528
+ /**
529
+ * Refuses an empty directory, or a missing terminal, before spending a round trip: a destructive
530
+ * apply nobody can confirm must never become a yes.
531
+ */
532
+ async fetchSharedConfigOrFail(id, namedProvider) {
432
533
  if (!await detectProject()) {
433
- this.error(nothingInstalledToApplyTo(id), { exit: EXIT_CODES.ERROR });
534
+ this.error(nothingInstalledToApplyTo(id, namedProvider), { exit: EXIT_CODES.ERROR });
434
535
  }
435
536
  if (!process.stdin.isTTY) {
436
- this.error(sharedConfigNeedsTerminal(id), { exit: EXIT_CODES.ERROR });
537
+ this.error(sharedConfigNeedsTerminal(id, namedProvider), { exit: EXIT_CODES.ERROR });
437
538
  }
438
539
  this.log(`Fetching configuration ${id}...`);
439
540
  const fetched = await fetchSeedConfig(id);
@@ -456,31 +557,50 @@ var Edit = class _Edit extends BaseCommand {
456
557
  this.handleError(error);
457
558
  }
458
559
  }
459
- async confirmAndWriteCarried(selection, planned, result) {
460
- await this.confirmSharedConfigOrCancel(planned, selection.kept, applyArrivals(planned, result));
461
- return this.writeCarriedSkills(selection.carried);
462
- }
463
560
  async writeCarriedSkills(carried) {
464
- if (carried.length === 0) return [];
465
- const rewritten = await writeExternalSkills(carried);
561
+ if (carried.length === 0) return;
562
+ await writeExternalSkills(carried);
466
563
  this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));
467
- return rewritten;
564
+ }
565
+ /** What the run removes and overwrites, then what it keeps and what else it rewrites. */
566
+ async planToConfirm(changes, active, kept, context, editRoot) {
567
+ const reachedProjects = await this.registeredProjectsStatement(changes, context, editRoot);
568
+ return sharedConfigPlan(changes, overwrittenSkillIds(changes, active), [
569
+ ...kept,
570
+ ...reachedProjects
571
+ ]);
572
+ }
573
+ /** Nothing to confirm; what the run keeps still says why nothing changed. */
574
+ sayNothingChanged(kept) {
575
+ for (const statement of kept) {
576
+ this.log(statement);
577
+ }
578
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(INFO_MESSAGES.NO_CHANGES_MADE));
468
579
  }
469
580
  /**
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.
581
+ * At home every registered project inlines the global config, so a change to it rewrites each
582
+ * one the fan-out reaches. Rewritten carried files alone leave the config as it was.
472
583
  */
473
- async confirmSharedConfigOrCancel(changes, kept, arrivals) {
474
- const plan = sharedConfigPlan(changes, kept);
584
+ async registeredProjectsStatement(changes, context, editRoot) {
585
+ if (!editRoot.isGlobal || !changesTheConfig(changes)) return [];
586
+ const reached = await projectsAFanOutReaches(
587
+ context.projectConfig?.projects ?? [],
588
+ providerInUse(editRoot.dir)
589
+ );
590
+ return reached.length === 0 ? [] : [registeredProjectsRewritten(reached)];
591
+ }
592
+ /**
593
+ * The plan and the apply read the same changes, so what is approved is what is removed. The
594
+ * arrivals print above it, so the question covers the whole of what a yes does.
595
+ */
596
+ async confirmSharedConfigOrCancel(plan, arrivals) {
475
597
  for (const line of arrivalLines(arrivals)) {
476
598
  this.log(line);
477
599
  }
478
600
  const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(
479
601
  RemovalPlanConfirm,
480
602
  {
481
- heading: plan.heading,
482
- sections: plan.sections,
483
- statements: plan.statements,
603
+ ...plan,
484
604
  message: SHARED_CONFIG_APPLY.CONFIRM,
485
605
  onConfirm,
486
606
  onCancel
@@ -527,10 +647,10 @@ var Edit = class _Edit extends BaseCommand {
527
647
  );
528
648
  }
529
649
  /** Opens an id rather than applying it; `--from` without `--ui` is the destructive apply. */
530
- async openSharedInEditor(id, cwd) {
650
+ async openSharedInEditor(id, cwd, namedProvider) {
531
651
  const url = editorConfigUrl(id);
532
652
  this.log(`Open it at ${url}`);
533
- this.log(applySharedConfigHere(id, await holdsItsOwnInstallation(cwd)));
653
+ this.log(applySharedConfigHere(id, await holdsItsOwnInstallation(cwd), namedProvider));
534
654
  if (!process.stdin.isTTY) return;
535
655
  const opened = await openUrl(url);
536
656
  if (!opened.ok) this.warn(opened.error);
@@ -567,94 +687,18 @@ var Edit = class _Edit extends BaseCommand {
567
687
  }
568
688
  }
569
689
  logChangeSummary(changes, newSkills, oldSkills) {
570
- const {
571
- addedSkills,
572
- removedSkills,
573
- addedAgents,
574
- removedAgents,
575
- sourceChanges,
576
- scopeChanges,
577
- agentScopeChanges,
578
- dualScopeSkillTransitions,
579
- dualScopeAgentTransitions,
580
- tuningChanges,
581
- reassignedAgents,
582
- joinedGlobalAgents,
583
- rewrittenSkills
584
- } = changes;
585
690
  this.log(`
586
691
  ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
587
- for (const skillId of addedSkills) {
588
- const scope = newSkills.find((s) => s.id === skillId)?.scope;
589
- const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : "";
590
- this.log(
591
- chalk.hex(CLI_COLORS.SUCCESS)(` + ${getSkillById(skillId).displayName}${scopeLabel}`)
592
- );
593
- }
594
- for (const skillId of removedSkills) {
595
- const scope = oldSkills.find((s) => s.id === skillId)?.scope;
596
- const scopeLabel = scope ? ` ${formatScopeTag(scope)}` : "";
597
- this.log(chalk.hex(CLI_COLORS.ERROR)(` - ${getSkillDisplayName(skillId)}${scopeLabel}`));
598
- }
599
- for (const agentName of addedAgents) {
600
- this.log(
601
- chalk.hex(CLI_COLORS.SUCCESS)(` + ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(" (agent)")
602
- );
603
- }
604
- for (const agentName of removedAgents) {
605
- this.log(
606
- chalk.hex(CLI_COLORS.ERROR)(` - ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(" (agent)")
607
- );
608
- }
609
- for (const [skillId, change] of sourceChanges) {
610
- const displayName = getSkillDisplayName(skillId);
611
- const fromLabel = formatSourceDisplayName(change.from);
612
- const toLabel = formatSourceDisplayName(change.to);
613
- this.log(
614
- chalk.hex(CLI_COLORS.WARNING)(` ~ ${displayName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(` (${fromLabel} \u2192 ${toLabel})`)
615
- );
616
- }
617
- for (const [skillId, change] of scopeChanges) {
618
- this.log(formatSkillScopeChangeLine(skillId, change, dualScopeSkillTransitions));
619
- }
620
- for (const [agentName, change] of agentScopeChanges) {
621
- this.log(formatAgentScopeChangeLine(agentName, change, dualScopeAgentTransitions));
622
- }
623
- for (const [agentName, change] of tuningChanges) {
624
- this.log(formatValueChangeLine(agentName, change, "agent"));
625
- }
626
- for (const agentName of reassignedAgents) {
627
- this.log(
628
- chalk.hex(CLI_COLORS.WARNING)(` ~ ${agentName}`) + chalk.hex(CLI_COLORS.NEUTRAL)(" (agent: skills reassigned)")
629
- );
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
- }
636
- for (const skillId of rewrittenSkills) {
637
- this.log(
638
- chalk.hex(CLI_COLORS.WARNING)(` ~ ${getSkillDisplayName(skillId)}`) + chalk.hex(CLI_COLORS.NEUTRAL)(" (skill: files rewritten)")
639
- );
692
+ for (const line of changeSummaryLines(changes, newSkills, oldSkills)) {
693
+ this.log(line);
640
694
  }
641
695
  this.log("");
642
696
  }
643
- async applyMigrations(changes, filteredResult, activeOldSkills, context, editRoot) {
644
- const migrationPlan = detectMigrations(
645
- withMaskedGlobalsRestored(activeOldSkills, changes.collapsedPairs),
646
- filteredResult.skills
647
- );
648
- const migratedSkillIds = /* @__PURE__ */ new Set([
649
- ...migrationPlan.toEject.map((m) => m.id),
650
- ...migrationPlan.toPlugin.map((m) => m.id)
651
- ]);
652
- if (migratedSkillIds.size === 0) return migratedSkillIds;
653
- if (migrationPlan.toEject.length > 0) {
654
- this.logModeSwitch(migrationPlan.toEject.length, INSTALL_MODE_DESCRIPTIONS.eject);
655
- }
697
+ async applyMigrations(changes, active, context, editRoot) {
698
+ const migrationPlan = migrationPlanOf(changes, active);
699
+ if (migrationPlan.toEject.length === 0 && migrationPlan.toPlugin.length === 0) return;
700
+ this.announceMigrations(migrationPlan);
656
701
  if (migrationPlan.toPlugin.length > 0) {
657
- this.logModeSwitch(migrationPlan.toPlugin.length, INSTALL_MODE_DESCRIPTIONS.plugin);
658
702
  await this.requireMarketplaceOrExit(
659
703
  context.sourceResult,
660
704
  "migrate skills to plugin mode",
@@ -676,7 +720,6 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
676
720
  if (migrationPlan.toPlugin.length > 0) {
677
721
  this.reportPluginInstalls(migrationResult.pluginInstalls);
678
722
  }
679
- return migratedSkillIds;
680
723
  }
681
724
  /**
682
725
  * Mirrors `BaseCommand.reportPluginInstalls` for the plugin→eject half. The count line names no
@@ -691,26 +734,46 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
691
734
  }
692
735
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(result.copied.length)));
693
736
  }
737
+ /**
738
+ * One line per kind, each counting its own: a mode switch, then a skill added in the project
739
+ * beside the global install it keeps (`keepsGlobalInstall` decides both the keep and the line).
740
+ */
741
+ announceMigrations(plan) {
742
+ const [copiesBesideGlobalPlugin, switchesToEject] = partition(plan.toEject, keepsGlobalInstall);
743
+ const [installsBesideGlobalCopy, switchesToPlugin] = partition(
744
+ plan.toPlugin,
745
+ keepsGlobalInstall
746
+ );
747
+ if (switchesToEject.length > 0) {
748
+ this.logModeSwitch(switchesToEject.length, INSTALL_MODE_DESCRIPTIONS.eject);
749
+ }
750
+ if (copiesBesideGlobalPlugin.length > 0) {
751
+ this.logCopiesBesideGlobalPlugins(copiesBesideGlobalPlugin.length);
752
+ }
753
+ if (switchesToPlugin.length > 0) {
754
+ this.logModeSwitch(switchesToPlugin.length, INSTALL_MODE_DESCRIPTIONS.plugin);
755
+ }
756
+ if (installsBesideGlobalCopy.length > 0) {
757
+ this.logInstallsBesideGlobalCopies(installsBesideGlobalCopy.length);
758
+ }
759
+ }
694
760
  logModeSwitch(count, modeDescription) {
695
761
  this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Switching ${count} skill(s) to ${modeDescription}`));
696
762
  }
763
+ logCopiesBesideGlobalPlugins(count) {
764
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(copyingBesideGlobalPlugins(count)));
765
+ }
766
+ logInstallsBesideGlobalCopies(count) {
767
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(installingBesideGlobalCopies(count)));
768
+ }
697
769
  /**
698
770
  * A collapsed `[P][G]` pair is not a move: its project half is dropped
699
771
  * ({@link applyCollapsedPairs}).
700
772
  */
701
773
  async applyScopeChanges(changes, filteredResult, context, editRoot) {
702
774
  const scopeChanges = scopeMovesOf(changes);
703
- for (const [skillId, change] of scopeChanges) {
704
- const skillConfig = filteredResult.skills.find((s) => s.id === skillId);
705
- if (skillConfig?.origin === EJECT_SOURCE) {
706
- await migrateLocalSkillScope(skillId, change.from, editRoot.dir);
707
- }
708
- }
709
- const hasPluginScopeChanges = [...scopeChanges.keys()].some((skillId) => {
710
- const skillConfig = filteredResult.skills.find((s) => s.id === skillId);
711
- return skillConfig && skillConfig.origin !== EJECT_SOURCE;
712
- });
713
- if (!hasPluginScopeChanges) return;
775
+ await moveEjectedSkillCopies(scopeChanges, filteredResult.skills, editRoot.dir);
776
+ if (!movesAPluginSkill(scopeChanges, filteredResult.skills)) return;
714
777
  const marketplace = await this.requireMarketplaceOrExit(
715
778
  context.sourceResult,
716
779
  "migrate plugin skill scopes",
@@ -755,33 +818,27 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
755
818
  }
756
819
  return;
757
820
  }
758
- const uninstallResult = await uninstallPluginSkills(
821
+ await this.uninstallPluginSkillsReported(
759
822
  pluginHalves.map((half) => half.id),
760
823
  pluginHalves,
761
824
  marketplace,
762
825
  editRoot.dir
763
826
  );
764
- if (uninstallResult.uninstalled.length > 0) {
765
- this.log(
766
- chalk.hex(CLI_COLORS.NEUTRAL)(`Removed ${uninstallResult.uninstalled.length} plugin(s)`)
767
- );
827
+ }
828
+ async uninstallPluginSkillsReported(skillIds, oldSkills, marketplace, projectDir) {
829
+ const { uninstalled, failed } = await uninstallPluginSkills(
830
+ skillIds,
831
+ oldSkills,
832
+ marketplace,
833
+ projectDir
834
+ );
835
+ if (uninstalled.length > 0) {
836
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Removed ${uninstalled.length} plugin(s)`));
768
837
  }
769
- for (const item of uninstallResult.failed) {
838
+ for (const item of failed) {
770
839
  this.warn(`Failed to uninstall plugin ${item.id}: ${item.error}`);
771
840
  }
772
841
  }
773
- async applySourceChanges(changes, activeOldSkills, editRoot, migratedSkillIds) {
774
- const { sourceChanges } = changes;
775
- for (const [skillId, change] of sourceChanges) {
776
- if (migratedSkillIds.has(skillId)) {
777
- continue;
778
- }
779
- if (change.from === EJECT_SOURCE) {
780
- const oldSkill = activeOldSkills.find((s) => s.id === skillId);
781
- await deleteLocalSkill(editRoot.dir, skillId, oldSkill?.scope);
782
- }
783
- }
784
- }
785
842
  async applyPluginChanges(changes, filteredResult, activeOldSkills, context, editRoot) {
786
843
  const { addedSkills, removedSkills } = changes;
787
844
  const addedPluginSkills = filteredResult.skills.filter(
@@ -805,20 +862,12 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
805
862
  );
806
863
  }
807
864
  if (removedPluginSkills.length > 0) {
808
- const uninstallResult = await uninstallPluginSkills(
865
+ await this.uninstallPluginSkillsReported(
809
866
  removedPluginSkills,
810
867
  activeOldSkills,
811
868
  marketplace,
812
869
  editRoot.dir
813
870
  );
814
- if (uninstallResult.uninstalled.length > 0) {
815
- this.log(
816
- chalk.hex(CLI_COLORS.NEUTRAL)(`Removed ${uninstallResult.uninstalled.length} plugin(s)`)
817
- );
818
- }
819
- for (const item of uninstallResult.failed) {
820
- this.warn(`Failed to uninstall plugin ${item.id}: ${item.error}`);
821
- }
822
871
  }
823
872
  }
824
873
  async copyNewLocalSkills(changes, filteredResult, context, editRoot) {
@@ -843,57 +892,48 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
843
892
  await deleteLocalSkill(editRoot.dir, skillId, oldSkill.scope);
844
893
  }
845
894
  }
846
- async writeConfigAndCompile(result, context, editRoot, authority) {
847
- let agentDefsResult;
895
+ async writeConfigAndCompile(result, context, editRoot) {
896
+ const agentDefs = await this.loadAgentDefsOrFail();
897
+ const configResult = await this.writeConfigOrFail(result, context, editRoot, agentDefs);
898
+ this.reportUnassignedSkills(configResult.config, result.skills);
899
+ await this.recompileAgents(result, editRoot, configResult.propagation, agentDefs.sourcePath);
900
+ this.reportFanOut(configResult.propagation);
901
+ }
902
+ async loadAgentDefsOrFail() {
848
903
  try {
849
- agentDefsResult = await loadAgentDefs();
904
+ return await loadAgentDefs();
850
905
  } catch (error) {
851
906
  this.handleError(error);
852
907
  }
853
- let configResult;
908
+ }
909
+ /** Fatal: every mutation has landed and config.ts is their only record. */
910
+ async writeConfigOrFail(result, context, editRoot, agentDefs) {
854
911
  try {
855
- configResult = await writeProjectConfig({
912
+ return await writeProjectConfig({
856
913
  selection: result,
857
914
  sourceResult: context.sourceResult,
858
915
  projectDir: editRoot.dir,
859
- agentDefs: agentDefsResult,
860
- authoritativeScope: authority
916
+ agentDefs,
917
+ authoritativeScope: applyAuthority(editRoot)
861
918
  });
862
919
  } catch (error) {
863
920
  this.error(`Could not update config: ${getErrorMessage(error)}`, {
864
921
  exit: EXIT_CODES.ERROR
865
922
  });
866
923
  }
867
- this.reportUnassignedSkills(configResult.config, result.skills);
924
+ }
925
+ async recompileAgents(result, editRoot, propagation, sourcePath) {
868
926
  try {
869
927
  const agentScopeMap = activeAgentScopeMap(result.agentConfigs);
870
928
  const { allSkills } = await discoverInstalledSkills(editRoot.dir);
871
- const compile = compilesGlobalScope(editRoot, configResult.propagation) ? compileAgentsAllScopes : compileProjectScope;
872
- const compilationResult = await compile({
929
+ const compile = compilesGlobalScope(editRoot, propagation) ? compileAgentsAllScopes : compileProjectScope;
930
+ const compilation = await compile({
873
931
  projectDir: editRoot.dir,
874
- sourcePath: agentDefsResult.sourcePath,
932
+ sourcePath,
875
933
  skills: allSkills,
876
934
  agentScopeMap
877
935
  });
878
- const { compiled, rewritten, failed, warnings } = compilationResult;
879
- const summary = recompileSummary(
880
- rewritten.length,
881
- compiled.length - rewritten.length,
882
- RECOMPILE_SUBJECT
883
- );
884
- if (failed.length > 0) {
885
- this.log(
886
- chalk.hex(CLI_COLORS.NEUTRAL)(summary) + chalk.hex(CLI_COLORS.WARNING)(` (${failed.length} failed)`)
887
- );
888
- for (const warning of warnings) {
889
- this.warn(warning);
890
- }
891
- this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);
892
- } else if (compiled.length > 0) {
893
- this.log(chalk.hex(CLI_COLORS.NEUTRAL)(summary));
894
- } else {
895
- this.log(chalk.hex(CLI_COLORS.NEUTRAL)(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE));
896
- }
936
+ this.reportRecompile(compilation);
897
937
  } catch (error) {
898
938
  this.reportIncompleteWork(
899
939
  `Agent recompilation failed: ${getErrorMessage(error)}`,
@@ -901,7 +941,26 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
901
941
  );
902
942
  this.log(`You can manually recompile with '${CLI_INVOKE_COMMAND} compile'.`);
903
943
  }
904
- this.reportFanOut(configResult.propagation);
944
+ }
945
+ reportRecompile({ compiled, rewritten, failed, warnings }) {
946
+ const summary = recompileSummary(
947
+ rewritten.length,
948
+ compiled.length - rewritten.length,
949
+ RECOMPILE_SUBJECT
950
+ );
951
+ if (failed.length > 0) {
952
+ this.log(
953
+ chalk.hex(CLI_COLORS.NEUTRAL)(summary) + chalk.hex(CLI_COLORS.WARNING)(` (${failed.length} failed)`)
954
+ );
955
+ for (const warning of warnings) {
956
+ this.warn(warning);
957
+ }
958
+ this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);
959
+ } else if (compiled.length > 0) {
960
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(summary));
961
+ } else {
962
+ this.log(chalk.hex(CLI_COLORS.NEUTRAL)(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE));
963
+ }
905
964
  }
906
965
  async cleanupStaleAgentFiles(changes, oldAgents, editRoot) {
907
966
  for (const removal of planStaleAgentRemovals(changes, oldAgents, editRoot.dir)) {
@@ -926,7 +985,7 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
926
985
  this.log(notice);
927
986
  }
928
987
  }
929
- logCompletionSummary(_changes) {
988
+ logCompletionSummary() {
930
989
  if (this.hasIncompleteWork) return;
931
990
  this.log(`
932
991
  ${chalk.hex(CLI_COLORS.SUCCESS)("\u2713 Done")}
@@ -954,44 +1013,63 @@ function detectConfigChanges(oldConfig, selection, fullEntries) {
954
1013
  );
955
1014
  const dualScopeSkillTransitions = detectDualScopeTransitions(
956
1015
  scopeChanges,
957
- fullEntries?.newSkills ?? [],
958
- fullEntries?.oldSkills ?? [],
1016
+ fullEntries.newSkills,
1017
+ fullEntries.oldSkills,
959
1018
  (s) => s.id
960
1019
  );
961
1020
  const collapsedPairs = collapsedPairsOf(
962
1021
  scopeChanges,
963
1022
  dualScopeSkillTransitions,
964
- fullEntries?.oldSkills ?? []
1023
+ fullEntries.oldSkills
1024
+ );
1025
+ const dualScopeAgentTransitions = detectDualScopeTransitions(
1026
+ agentScopeChanges,
1027
+ fullEntries.newAgents,
1028
+ fullEntries.oldAgents,
1029
+ (a) => a.name
965
1030
  );
1031
+ const arrivingSkills = arrivingProjectHalves(scopeChanges, dualScopeSkillTransitions);
966
1032
  return {
967
1033
  addedSkills: difference(newSkillIds, oldSkillIds),
968
1034
  removedSkills: difference(oldSkillIds, newSkillIds),
969
1035
  addedAgents: difference(newAgentNames, oldAgentNames),
970
1036
  removedAgents: difference(oldAgentNames, newAgentNames),
971
- sourceChanges: detectPropertyChanges(
972
- selection.skills,
973
- indexBy(withMaskedGlobalsRestored(oldConfig?.skills ?? [], collapsedPairs), (s) => s.id),
974
- (s) => s.id,
975
- (s) => s.origin
1037
+ sourceChanges: withoutKeys(
1038
+ detectPropertyChanges(
1039
+ selection.skills,
1040
+ indexBy(withMaskedGlobalsRestored(oldConfig?.skills ?? [], collapsedPairs), (s) => s.id),
1041
+ (s) => s.id,
1042
+ (s) => s.origin
1043
+ ),
1044
+ arrivingSkills
976
1045
  ),
977
1046
  scopeChanges,
978
1047
  agentScopeChanges,
979
1048
  dualScopeSkillTransitions,
980
1049
  collapsedPairs,
981
- dualScopeAgentTransitions: detectDualScopeTransitions(
982
- agentScopeChanges,
983
- fullEntries?.newAgents ?? [],
984
- fullEntries?.oldAgents ?? [],
985
- (a) => a.name
986
- ),
987
- tuningChanges: detectPropertyChanges(
988
- selection.agentConfigs,
989
- oldAgentsByName,
990
- (a) => a.name,
991
- describeTuning
1050
+ dualScopeAgentTransitions,
1051
+ // Either half of a pair is measured against the other install, which this edit never retunes.
1052
+ tuningChanges: withoutKeys(
1053
+ detectPropertyChanges(selection.agentConfigs, oldAgentsByName, (a) => a.name, describeTuning),
1054
+ dualScopeAgentTransitions
992
1055
  )
993
1056
  };
994
1057
  }
1058
+ function skillsNewHere(changes) {
1059
+ return [
1060
+ ...changes.addedSkills,
1061
+ ...arrivingProjectHalves(changes.scopeChanges, changes.dualScopeSkillTransitions)
1062
+ ];
1063
+ }
1064
+ function arrivingProjectHalves(scopeChanges, dualScopeTransitions) {
1065
+ const arriving = [...scopeChanges].filter(
1066
+ ([key, change]) => change.to === "project" && dualScopeTransitions.has(key)
1067
+ );
1068
+ return new Set(arriving.map(([key]) => key));
1069
+ }
1070
+ function withoutKeys(changes, keys) {
1071
+ return new Map([...changes].filter(([key]) => !keys.has(key)));
1072
+ }
995
1073
  var RESTING_TUNING = "defaults";
996
1074
  function describeTuning(agent) {
997
1075
  const settings = [
@@ -1012,17 +1090,20 @@ function detectPropertyChanges(newItems, oldByKey, getKey, getValue) {
1012
1090
  }
1013
1091
  return changes;
1014
1092
  }
1093
+ function globalHalvesKeptInstalled(installedGlobal) {
1094
+ if (installedGlobal === null) return { skills: [], agents: [] };
1095
+ return {
1096
+ skills: installedGlobal.skills.map(asTombstone),
1097
+ agents: installedGlobal.agents.map(asTombstone)
1098
+ };
1099
+ }
1100
+ function asTombstone(entry) {
1101
+ return { ...entry, excluded: true };
1102
+ }
1015
1103
  function detectDualScopeTransitions(scopeChanges, fullNew, fullOld, getKey) {
1016
- const hasGlobalTombstone = (items, key) => items.some((item) => getKey(item) === key && item.scope === "global" && item.excluded === true);
1017
- const result = /* @__PURE__ */ new Set();
1018
- for (const [key, change] of scopeChanges) {
1019
- if (change.from === "global" && change.to === "project" && hasGlobalTombstone(fullNew, key)) {
1020
- result.add(key);
1021
- } else if (change.from === "project" && change.to === "global" && hasGlobalTombstone(fullOld, key)) {
1022
- result.add(key);
1023
- }
1024
- }
1025
- return result;
1104
+ const hasGlobalTombstone = (items, key) => items.some((item) => getKey(item) === key && isGlobalTombstone(item));
1105
+ const isDualScope = ([key, { from, to }]) => from === "global" && to === "project" && hasGlobalTombstone(fullNew, key) || from === "project" && to === "global" && hasGlobalTombstone(fullOld, key);
1106
+ return new Set([...scopeChanges].filter(isDualScope).map(([key]) => key));
1026
1107
  }
1027
1108
  function collapsedPairsOf(scopeChanges, dualScopeSkillTransitions, fullOldSkills) {
1028
1109
  return [...scopeChanges].filter(([id, change]) => change.to === "global" && dualScopeSkillTransitions.has(id)).map(([id]) => ({
@@ -1056,6 +1137,20 @@ function scopeMovesOf(changes) {
1056
1137
  const collapsed = new Set(changes.collapsedPairs.map(({ projectHalf }) => projectHalf.id));
1057
1138
  return new Map([...changes.scopeChanges].filter(([id]) => !collapsed.has(id)));
1058
1139
  }
1140
+ async function moveEjectedSkillCopies(scopeMoves, skills, projectDir) {
1141
+ for (const [skillId, change] of scopeMoves) {
1142
+ const skillConfig = skills.find((s) => s.id === skillId);
1143
+ if (skillConfig?.origin === EJECT_SOURCE) {
1144
+ await migrateLocalSkillScope(skillId, change.from, projectDir);
1145
+ }
1146
+ }
1147
+ }
1148
+ function movesAPluginSkill(scopeMoves, skills) {
1149
+ return [...scopeMoves.keys()].some((skillId) => {
1150
+ const skill = skills.find((s) => s.id === skillId);
1151
+ return skill !== void 0 && skill.origin !== EJECT_SOURCE;
1152
+ });
1153
+ }
1059
1154
  var STALE_AGENT_SCOPES = ["project", "global"];
1060
1155
  var UNRECORDED_AGENT_SCOPE = "project";
1061
1156
  function installedScope(name, oldAgents) {
@@ -1075,11 +1170,13 @@ function planStaleAgentRemovals(changes, oldAgents, editRoot) {
1075
1170
  return STALE_AGENT_SCOPES.map(removalAtScope).filter((removal) => removal.agents.length > 0);
1076
1171
  }
1077
1172
  function hasAnyChanges(changes) {
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;
1173
+ return changes.rewrittenSkills.length > 0 || changesTheConfig(changes);
1174
+ }
1175
+ function changesTheConfig(changes) {
1176
+ return changes.reassignedAgents.length > 0 || changes.joinedGlobalAgents.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;
1079
1177
  }
1080
1178
  async function migratePluginSkillScopes(scopeChanges, skills, marketplace, projectDir) {
1081
1179
  const host = hostAt(projectDir);
1082
- const migrated = [];
1083
1180
  const failed = [];
1084
1181
  for (const [skillId, change] of scopeChanges) {
1085
1182
  const skillConfig = skills.find((s) => s.id === skillId);
@@ -1092,16 +1189,13 @@ async function migratePluginSkillScopes(scopeChanges, skills, marketplace, proje
1092
1189
  await host.uninstallPlugin(pluginRef, "project", projectDir);
1093
1190
  }
1094
1191
  await host.installPlugin(pluginRef, change.to, projectDir);
1095
- migrated.push(skillId);
1096
1192
  } catch (error) {
1097
1193
  failed.push({ id: skillId, error: getErrorMessage(error) });
1098
1194
  }
1099
1195
  }
1100
- return { migrated, failed };
1196
+ return { failed };
1101
1197
  }
1102
1198
  export {
1103
- Edit as default,
1104
- detectConfigChanges,
1105
- migratePluginSkillScopes
1199
+ Edit as default
1106
1200
  };
1107
1201
  //# sourceMappingURL=edit.js.map