agents-inc 0.155.0 → 0.157.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 (173) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/{chunk-PMUABBPG.js → chunk-24IGOJ7E.js} +9 -13
  3. package/dist/chunk-24IGOJ7E.js.map +1 -0
  4. package/dist/{chunk-H6UTKTLK.js → chunk-3E52LCYC.js} +98 -34
  5. package/dist/chunk-3E52LCYC.js.map +1 -0
  6. package/dist/{chunk-UMH2YZKG.js → chunk-4CIAZOTD.js} +4 -6
  7. package/dist/{chunk-UMH2YZKG.js.map → chunk-4CIAZOTD.js.map} +1 -1
  8. package/dist/{chunk-D2CAV7MG.js → chunk-4DMFK67G.js} +2 -2
  9. package/dist/{chunk-PNMM5HNX.js → chunk-4EPJWN7C.js} +9 -10
  10. package/dist/chunk-4EPJWN7C.js.map +1 -0
  11. package/dist/{chunk-MHRC3KRX.js → chunk-4KHUHPX4.js} +3 -3
  12. package/dist/chunk-4KHUHPX4.js.map +1 -0
  13. package/dist/{chunk-2H7UWE2G.js → chunk-CEGHC7L5.js} +13 -12
  14. package/dist/chunk-CEGHC7L5.js.map +1 -0
  15. package/dist/{chunk-MO5FGLVS.js → chunk-DCIC35R7.js} +11 -12
  16. package/dist/chunk-DCIC35R7.js.map +1 -0
  17. package/dist/{chunk-ILUVL7WM.js → chunk-DZD25NHW.js} +2 -2
  18. package/dist/{chunk-IO5YBKHV.js → chunk-G6G2FT2G.js} +10 -8
  19. package/dist/chunk-G6G2FT2G.js.map +1 -0
  20. package/dist/{chunk-RWOYPOMR.js → chunk-IGOFZG3S.js} +19 -5
  21. package/dist/chunk-IGOFZG3S.js.map +1 -0
  22. package/dist/{chunk-CLFHC2DK.js → chunk-K2VTGT45.js} +17 -18
  23. package/dist/chunk-K2VTGT45.js.map +1 -0
  24. package/dist/{chunk-YO2LTXB4.js → chunk-KTXVQ7OM.js} +115 -10
  25. package/dist/chunk-KTXVQ7OM.js.map +1 -0
  26. package/dist/{chunk-SY4X2LND.js → chunk-KUZBMEWR.js} +3 -3
  27. package/dist/{chunk-ZUAZHDKP.js → chunk-LDBVIPTP.js} +277 -40
  28. package/dist/chunk-LDBVIPTP.js.map +1 -0
  29. package/dist/{chunk-PCC4LBKB.js → chunk-MU2TQ5KK.js} +2 -2
  30. package/dist/{chunk-4G2YHZIM.js → chunk-O4K42CJB.js} +4 -6
  31. package/dist/{chunk-4G2YHZIM.js.map → chunk-O4K42CJB.js.map} +1 -1
  32. package/dist/{chunk-HXKOIWLU.js → chunk-P6OKOH62.js} +2 -6
  33. package/dist/chunk-P6OKOH62.js.map +1 -0
  34. package/dist/{chunk-IXRZAHZF.js → chunk-PGZSNNDA.js} +4 -4
  35. package/dist/{chunk-LJCNUP6M.js → chunk-PVPNVK3W.js} +2 -2
  36. package/dist/{chunk-4A4L3YIW.js → chunk-PXGDA2SY.js} +6 -7
  37. package/dist/chunk-PXGDA2SY.js.map +1 -0
  38. package/dist/{chunk-G47TDUK3.js → chunk-QNAMXQKF.js} +2 -2
  39. package/dist/{chunk-5OKLCVM4.js → chunk-QO4XD5V5.js} +3 -3
  40. package/dist/{chunk-5F2YR5XV.js → chunk-QXPMQBEI.js} +15 -5
  41. package/dist/chunk-QXPMQBEI.js.map +1 -0
  42. package/dist/{chunk-F5T6TV4Z.js → chunk-RLU2IXD3.js} +40 -14
  43. package/dist/chunk-RLU2IXD3.js.map +1 -0
  44. package/dist/{chunk-WCAUUBHO.js → chunk-RVXI5VQU.js} +14758 -14501
  45. package/dist/chunk-RVXI5VQU.js.map +1 -0
  46. package/dist/{chunk-WFRTHH3A.js → chunk-TZRXWFF5.js} +3 -3
  47. package/dist/{chunk-HG4JPXJT.js → chunk-V7PMQDDU.js} +23 -10
  48. package/dist/chunk-V7PMQDDU.js.map +1 -0
  49. package/dist/{chunk-Y5Y7XHVU.js → chunk-VI6U2PJG.js} +4 -4
  50. package/dist/{chunk-TBOVYLQJ.js → chunk-VTIDLRNA.js} +2 -2
  51. package/dist/{chunk-OKH64JZE.js → chunk-WCZNQECQ.js} +2 -2
  52. package/dist/{chunk-QWVXOCXO.js → chunk-WENBESZO.js} +7 -9
  53. package/dist/{chunk-QWVXOCXO.js.map → chunk-WENBESZO.js.map} +1 -1
  54. package/dist/{chunk-TNGMF4UX.js → chunk-XOZAKFTS.js} +12 -12
  55. package/dist/chunk-XOZAKFTS.js.map +1 -0
  56. package/dist/{chunk-6RLV45HN.js → chunk-YG5YPVTJ.js} +6 -6
  57. package/dist/chunk-YG5YPVTJ.js.map +1 -0
  58. package/dist/{chunk-HTYH7CKN.js → chunk-YKFCUVHG.js} +3 -3
  59. package/dist/{chunk-VPASBA7P.js → chunk-YXI3BTQQ.js} +2 -2
  60. package/dist/chunk-Z3H2K5PK.js +1352 -0
  61. package/dist/chunk-Z3H2K5PK.js.map +1 -0
  62. package/dist/{chunk-5QZAK6J7.js → chunk-ZAQ6WMJV.js} +50 -18
  63. package/dist/chunk-ZAQ6WMJV.js.map +1 -0
  64. package/dist/{chunk-GS2NZ3GD.js → chunk-ZBYVDXZG.js} +5 -5
  65. package/dist/chunk-ZBYVDXZG.js.map +1 -0
  66. package/dist/commands/build/marketplace.js +9 -12
  67. package/dist/commands/build/marketplace.js.map +1 -1
  68. package/dist/commands/build/plugins.js +9 -12
  69. package/dist/commands/build/plugins.js.map +1 -1
  70. package/dist/commands/compile.js +15 -19
  71. package/dist/commands/compile.js.map +1 -1
  72. package/dist/commands/doctor.js +75 -54
  73. package/dist/commands/doctor.js.map +1 -1
  74. package/dist/commands/edit.js +154 -109
  75. package/dist/commands/edit.js.map +1 -1
  76. package/dist/commands/eject.js +68 -38
  77. package/dist/commands/eject.js.map +1 -1
  78. package/dist/commands/init.js +36 -39
  79. package/dist/commands/list.js +8 -10
  80. package/dist/commands/list.js.map +1 -1
  81. package/dist/commands/new/marketplace.js +8 -11
  82. package/dist/commands/new/marketplace.js.map +1 -1
  83. package/dist/commands/search.js +10 -13
  84. package/dist/commands/search.js.map +1 -1
  85. package/dist/commands/share.js +8 -10
  86. package/dist/commands/share.js.map +1 -1
  87. package/dist/commands/uninstall.js +39 -28
  88. package/dist/commands/uninstall.js.map +1 -1
  89. package/dist/commands/update.js +7 -10
  90. package/dist/commands/update.js.map +1 -1
  91. package/dist/components/common/removal-plan-confirm.js +2 -2
  92. package/dist/components/common/select-list.js +2 -2
  93. package/dist/components/wizard/category-grid.js +4 -5
  94. package/dist/components/wizard/checkbox-grid.js +4 -4
  95. package/dist/components/wizard/domain-selection.js +9 -11
  96. package/dist/components/wizard/run-wizard-session.js +26 -28
  97. package/dist/components/wizard/scroll-affordance.js +2 -2
  98. package/dist/components/wizard/skill-agent-summary.js +5 -7
  99. package/dist/components/wizard/source-grid.js +5 -6
  100. package/dist/components/wizard/stack-selection.js +7 -9
  101. package/dist/components/wizard/step-agents.js +8 -10
  102. package/dist/components/wizard/step-build.js +7 -9
  103. package/dist/components/wizard/step-confirm.js +9 -11
  104. package/dist/components/wizard/step-sources.js +8 -10
  105. package/dist/components/wizard/step-stack.js +8 -10
  106. package/dist/components/wizard/summary-panel.js +8 -10
  107. package/dist/components/wizard/toast.js +2 -2
  108. package/dist/components/wizard/wizard-layout.js +12 -14
  109. package/dist/components/wizard/wizard-tabs.js +2 -4
  110. package/dist/components/wizard/wizard.js +25 -27
  111. package/dist/hooks/init.js +36 -39
  112. package/dist/hooks/init.js.map +1 -1
  113. package/dist/load-agent-defs-M6LRVISN.js +13 -0
  114. package/dist/recompile-project-agents-G7ZM25PC.js +17 -0
  115. package/dist/{source-loader-3DL3NYUX.js → source-loader-BIAEDR5R.js} +4 -8
  116. package/dist/src/agents/_templates/agent.liquid +2 -2
  117. package/dist/stores/wizard-store.js +6 -6
  118. package/package.json +1 -1
  119. package/src/agents/_templates/agent.liquid +2 -2
  120. package/src/schemas/custom-metadata.schema.json +1 -1
  121. package/src/schemas/marketplace.schema.json +2 -1
  122. package/dist/chunk-2H7UWE2G.js.map +0 -1
  123. package/dist/chunk-4A4L3YIW.js.map +0 -1
  124. package/dist/chunk-5F2YR5XV.js.map +0 -1
  125. package/dist/chunk-5QZAK6J7.js.map +0 -1
  126. package/dist/chunk-6RLV45HN.js.map +0 -1
  127. package/dist/chunk-CLFHC2DK.js.map +0 -1
  128. package/dist/chunk-F2AMBBIA.js +0 -64
  129. package/dist/chunk-F2AMBBIA.js.map +0 -1
  130. package/dist/chunk-F5T6TV4Z.js.map +0 -1
  131. package/dist/chunk-GS2NZ3GD.js.map +0 -1
  132. package/dist/chunk-H6UTKTLK.js.map +0 -1
  133. package/dist/chunk-HG4JPXJT.js.map +0 -1
  134. package/dist/chunk-HXKOIWLU.js.map +0 -1
  135. package/dist/chunk-IO5YBKHV.js.map +0 -1
  136. package/dist/chunk-MHRC3KRX.js.map +0 -1
  137. package/dist/chunk-MO5FGLVS.js.map +0 -1
  138. package/dist/chunk-PMUABBPG.js.map +0 -1
  139. package/dist/chunk-PNMM5HNX.js.map +0 -1
  140. package/dist/chunk-RWOYPOMR.js.map +0 -1
  141. package/dist/chunk-TNGMF4UX.js.map +0 -1
  142. package/dist/chunk-VASLW636.js +0 -23
  143. package/dist/chunk-VASLW636.js.map +0 -1
  144. package/dist/chunk-WCAUUBHO.js.map +0 -1
  145. package/dist/chunk-WUQ3MTPF.js +0 -173
  146. package/dist/chunk-WUQ3MTPF.js.map +0 -1
  147. package/dist/chunk-XAXJWXI4.js +0 -1667
  148. package/dist/chunk-XAXJWXI4.js.map +0 -1
  149. package/dist/chunk-YO2LTXB4.js.map +0 -1
  150. package/dist/chunk-ZUAZHDKP.js.map +0 -1
  151. package/dist/copy-local-skills-NSUTBVLJ.js +0 -14
  152. package/dist/load-agent-defs-X4E57I2U.js +0 -15
  153. package/dist/loader-G6BFG2VA.js +0 -24
  154. package/dist/recompile-project-agents-JE4MM72I.js +0 -20
  155. package/dist/recompile-project-agents-JE4MM72I.js.map +0 -1
  156. package/dist/source-loader-3DL3NYUX.js.map +0 -1
  157. /package/dist/{chunk-D2CAV7MG.js.map → chunk-4DMFK67G.js.map} +0 -0
  158. /package/dist/{chunk-ILUVL7WM.js.map → chunk-DZD25NHW.js.map} +0 -0
  159. /package/dist/{chunk-SY4X2LND.js.map → chunk-KUZBMEWR.js.map} +0 -0
  160. /package/dist/{chunk-PCC4LBKB.js.map → chunk-MU2TQ5KK.js.map} +0 -0
  161. /package/dist/{chunk-IXRZAHZF.js.map → chunk-PGZSNNDA.js.map} +0 -0
  162. /package/dist/{chunk-LJCNUP6M.js.map → chunk-PVPNVK3W.js.map} +0 -0
  163. /package/dist/{chunk-G47TDUK3.js.map → chunk-QNAMXQKF.js.map} +0 -0
  164. /package/dist/{chunk-5OKLCVM4.js.map → chunk-QO4XD5V5.js.map} +0 -0
  165. /package/dist/{chunk-WFRTHH3A.js.map → chunk-TZRXWFF5.js.map} +0 -0
  166. /package/dist/{chunk-Y5Y7XHVU.js.map → chunk-VI6U2PJG.js.map} +0 -0
  167. /package/dist/{chunk-TBOVYLQJ.js.map → chunk-VTIDLRNA.js.map} +0 -0
  168. /package/dist/{chunk-OKH64JZE.js.map → chunk-WCZNQECQ.js.map} +0 -0
  169. /package/dist/{chunk-HTYH7CKN.js.map → chunk-YKFCUVHG.js.map} +0 -0
  170. /package/dist/{chunk-VPASBA7P.js.map → chunk-YXI3BTQQ.js.map} +0 -0
  171. /package/dist/{copy-local-skills-NSUTBVLJ.js.map → load-agent-defs-M6LRVISN.js.map} +0 -0
  172. /package/dist/{load-agent-defs-X4E57I2U.js.map → recompile-project-agents-G7ZM25PC.js.map} +0 -0
  173. /package/dist/{loader-G6BFG2VA.js.map → source-loader-BIAEDR5R.js.map} +0 -0
@@ -0,0 +1,1352 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ compileAgents
4
+ } from "./chunk-ZAQ6WMJV.js";
5
+ import {
6
+ loadAgentDefs
7
+ } from "./chunk-4KHUHPX4.js";
8
+ import {
9
+ ConfigLoadError,
10
+ GlobalPairWriteViolation,
11
+ STACK_AGENT_CONFIG_LOOSE_LINE,
12
+ activeProjectAgentNames,
13
+ assembleConfigTypesSource,
14
+ assertGateToken,
15
+ buildAndMergeConfig,
16
+ buildConfigTypesBackgroundData,
17
+ deriveCategories,
18
+ deriveDomains,
19
+ detectGlobalInstallation,
20
+ detectInstallation,
21
+ detectProjectInstallation,
22
+ disableBuffering,
23
+ drainBuffer,
24
+ enableBuffering,
25
+ ensureDir,
26
+ fileExists,
27
+ generateConfigTypesSource,
28
+ getErrorMessage,
29
+ getProjectConfigPath,
30
+ isActiveAt,
31
+ isGlobalTombstone,
32
+ isHomeDirectory,
33
+ isSkillAssignment,
34
+ loadProjectConfig,
35
+ loadProjectConfigFromDir,
36
+ loadSkillsMatrixFromSource,
37
+ mergeConfigs,
38
+ normalizeStackRecord,
39
+ readFile,
40
+ regenerateConfigTypes,
41
+ resolveInstallPaths,
42
+ splitConfigByScope,
43
+ verbose,
44
+ withGateToken,
45
+ writeFile
46
+ } from "./chunk-RVXI5VQU.js";
47
+ import {
48
+ byCategoryDeclarationOrder,
49
+ matrix,
50
+ typedEntries,
51
+ typedKeys
52
+ } from "./chunk-IGOFZG3S.js";
53
+ import {
54
+ CLAUDE_SRC_DIR,
55
+ CLI_INVOKE_COMMAND,
56
+ DEFAULT_PLUGIN_NAME,
57
+ GLOBAL_CONFIG_NAME,
58
+ LOCAL_PSEUDO_CATEGORY,
59
+ STANDARD_FILES
60
+ } from "./chunk-G6G2FT2G.js";
61
+
62
+ // src/cli/lib/operations/source/load-source.ts
63
+ async function loadSource(options) {
64
+ const { caller, sourceFlag, projectDir, captureStartupMessages } = options;
65
+ if (captureStartupMessages) {
66
+ enableBuffering();
67
+ }
68
+ let sourceResult;
69
+ try {
70
+ sourceResult = await loadSkillsMatrixFromSource({
71
+ ...caller !== void 0 && { caller },
72
+ ...sourceFlag !== void 0 && { sourceFlag },
73
+ projectDir
74
+ });
75
+ } catch (error) {
76
+ if (captureStartupMessages) {
77
+ disableBuffering();
78
+ }
79
+ throw error;
80
+ }
81
+ let startupMessages = [];
82
+ if (captureStartupMessages) {
83
+ startupMessages = drainBuffer();
84
+ disableBuffering();
85
+ }
86
+ return { sourceResult, startupMessages };
87
+ }
88
+
89
+ // src/cli/lib/operations/project/detect-project.ts
90
+ async function detectProject(projectDir) {
91
+ const resolvedDir = projectDir ?? process.cwd();
92
+ let installation;
93
+ try {
94
+ installation = await detectInstallation(resolvedDir);
95
+ } catch (error) {
96
+ if (error instanceof ConfigLoadError) return null;
97
+ throw error;
98
+ }
99
+ if (!installation) {
100
+ return null;
101
+ }
102
+ const loaded = await loadProjectConfig(installation.projectDir);
103
+ return {
104
+ installation,
105
+ config: loaded?.config ?? null,
106
+ configPath: loaded?.configPath ?? null
107
+ };
108
+ }
109
+
110
+ // src/cli/lib/operations/project/detect-both-installations.ts
111
+ async function detectBothInstallations(projectDir) {
112
+ const global = await detectGlobalInstallation();
113
+ const project = isHomeDirectory(projectDir) ? null : await detectProjectInstallation(projectDir);
114
+ return { global, project, hasBoth: !!global && !!project };
115
+ }
116
+
117
+ // src/cli/lib/config-gate/propagate.ts
118
+ import fs from "fs";
119
+ import { isDeepEqual, unique } from "remeda";
120
+
121
+ // src/cli/lib/configuration/config-writer.ts
122
+ import os from "os";
123
+ import path from "path";
124
+ var EXTRACTED_FIELDS = /* @__PURE__ */ new Set(["skills", "agents", "stack", "selectedDomains"]);
125
+ var CANONICAL_FIELD_ORDER = [
126
+ "name",
127
+ "description",
128
+ "agents",
129
+ "skills",
130
+ "author",
131
+ "selectedDomains",
132
+ "stack",
133
+ "marketplace",
134
+ "marketplaceName",
135
+ "agentsSource",
136
+ "projects"
137
+ ];
138
+ var CANONICAL_FIELDS = new Set(CANONICAL_FIELD_ORDER);
139
+ function canonicalizeFieldOrder(cleaned) {
140
+ const inSchemaOrder = CANONICAL_FIELD_ORDER.filter(
141
+ (key) => key in cleaned
142
+ ).map((key) => [key, cleaned[key]]);
143
+ const passthrough = Object.entries(cleaned).filter(([key]) => !CANONICAL_FIELDS.has(key));
144
+ return Object.fromEntries([...inSchemaOrder, ...passthrough]);
145
+ }
146
+ function withKeysOrderedBy(record, compareKeys) {
147
+ return Object.fromEntries(Object.entries(record).sort(([a], [b]) => compareKeys(a, b)));
148
+ }
149
+ function compareNamesInCodeUnitOrder(a, b) {
150
+ if (a === b) return 0;
151
+ return a < b ? -1 : 1;
152
+ }
153
+ function canonicalizeStackOrder(stack) {
154
+ const byDeclaration = byCategoryDeclarationOrder();
155
+ const withCategoriesInOrder = Object.entries(stack).map(
156
+ ([agent, categories]) => [agent, withKeysOrderedBy(categories, byDeclaration)]
157
+ );
158
+ return withKeysOrderedBy(Object.fromEntries(withCategoriesInOrder), compareNamesInCodeUnitOrder);
159
+ }
160
+ function renderEntryLine(entry) {
161
+ return ` ${JSON.stringify(entry)},`;
162
+ }
163
+ function renderScalarField(key, value) {
164
+ return ` ${JSON.stringify(key)}: ${JSON.stringify(value)},`;
165
+ }
166
+ function extractConfigArrays(cleaned) {
167
+ return {
168
+ skills: cleaned.skills ?? [],
169
+ agents: cleaned.agents ?? [],
170
+ stack: cleaned.stack,
171
+ selectedDomains: cleaned.selectedDomains ?? []
172
+ };
173
+ }
174
+ function cleanForEmission(config, options) {
175
+ const cleaned = JSON.parse(JSON.stringify(config));
176
+ if (options.dropProjects) {
177
+ delete cleaned.projects;
178
+ }
179
+ if (cleaned.stack) {
180
+ const compacted = compactStackAssignments(
181
+ cleaned.stack
182
+ );
183
+ cleaned.stack = canonicalizeStackOrder(compacted);
184
+ }
185
+ return canonicalizeFieldOrder(cleaned);
186
+ }
187
+ function generateConfigSource(config, options) {
188
+ if (options?.isProjectConfig && options.globalConfig) {
189
+ return generateProjectConfigWithInlinedGlobal(
190
+ cleanForEmission(config, { dropProjects: true }),
191
+ cleanForEmission(options.globalConfig, { dropProjects: true })
192
+ );
193
+ }
194
+ if (options?.isProjectConfig) {
195
+ return generateProjectConfigWithGlobalImport(
196
+ cleanForEmission(config, { dropProjects: true }),
197
+ getGlobalConfigImportPath()
198
+ );
199
+ }
200
+ return generateStandaloneConfig(cleanForEmission(config, { dropProjects: false }));
201
+ }
202
+ function generateStandaloneConfig(cleaned) {
203
+ const { skills, agents, stack, selectedDomains } = extractConfigArrays(cleaned);
204
+ const hasSkills = skills.length > 0;
205
+ const hasAgents = agents.length > 0;
206
+ const hasStack = stack != null && Object.keys(stack).length > 0;
207
+ const hasSelectedDomains = selectedDomains.length > 0;
208
+ const typeImports = buildTypeImports({
209
+ hasSkills,
210
+ hasAgents,
211
+ hasStack,
212
+ hasSelectedDomains
213
+ });
214
+ const lines = [`import type { ${typeImports} } from "./config-types";`];
215
+ if (hasSkills) {
216
+ lines.push(``);
217
+ lines.push(`const skills: SkillConfig[] = [`);
218
+ lines.push(skills.map(renderEntryLine).join("\n"));
219
+ lines.push(`];`);
220
+ }
221
+ if (hasAgents) {
222
+ lines.push(``);
223
+ lines.push(`const agents: AgentScopeConfig[] = [`);
224
+ lines.push(agents.map(renderEntryLine).join("\n"));
225
+ lines.push(`];`);
226
+ }
227
+ if (hasStack) {
228
+ lines.push(``);
229
+ const stackBody = JSON.stringify(stack, null, 2);
230
+ lines.push(`const stack: Partial<Record<ProjectAgentName, StackAgentConfig>> = ${stackBody};`);
231
+ }
232
+ if (hasSelectedDomains) {
233
+ lines.push(``);
234
+ const items = selectedDomains.map((d) => JSON.stringify(d)).join(", ");
235
+ lines.push(`const selectedDomains: Domain[] = [${items}];`);
236
+ }
237
+ const renderExportField = (key, value) => {
238
+ if (!EXTRACTED_FIELDS.has(key)) return [renderScalarField(key, value)];
239
+ if (key === "skills") return [` skills${hasSkills ? "" : ": []"},`];
240
+ if (key === "agents") return [` agents${hasAgents ? "" : ": []"},`];
241
+ if (key === "stack") return hasStack ? [` stack,`] : [];
242
+ return [` selectedDomains${hasSelectedDomains ? "" : ": []"},`];
243
+ };
244
+ const exportFields = Object.entries(cleaned).flatMap(
245
+ ([key, value]) => renderExportField(key, value)
246
+ );
247
+ lines.push(``);
248
+ lines.push(`export default {`);
249
+ lines.push(...exportFields);
250
+ lines.push(`} satisfies ProjectConfig;`);
251
+ lines.push(``);
252
+ return lines.join("\n");
253
+ }
254
+ function buildTypeImports(flags) {
255
+ return [
256
+ flags.hasSelectedDomains && "Domain",
257
+ "ProjectConfig",
258
+ flags.hasStack && "ProjectAgentName",
259
+ flags.hasAgents && "AgentScopeConfig",
260
+ flags.hasSkills && "SkillConfig",
261
+ flags.hasStack && "StackAgentConfig"
262
+ ].filter((t) => Boolean(t)).join(", ");
263
+ }
264
+ function generateProjectConfigWithGlobalImport(cleaned, globalImportPath) {
265
+ const importPath = `${globalImportPath}/config`;
266
+ const { skills, agents, stack, selectedDomains } = extractConfigArrays(cleaned);
267
+ const hasProjectDomains = selectedDomains.length > 0;
268
+ const hasStack = stack != null && Object.keys(stack).length > 0;
269
+ const typeImports = buildTypeImports({
270
+ hasSkills: true,
271
+ // Always present (spread from global)
272
+ hasAgents: true,
273
+ // Always present (spread from global)
274
+ hasStack,
275
+ hasSelectedDomains: hasProjectDomains
276
+ });
277
+ const lines = [
278
+ `import globalConfig from "${importPath}";`,
279
+ `import type { ${typeImports} } from "./config-types";`
280
+ ];
281
+ lines.push(``);
282
+ const skillItems = skills.map(renderEntryLine).join("\n");
283
+ lines.push(`const skills: SkillConfig[] = [`);
284
+ lines.push(` ...globalConfig.skills,`);
285
+ if (skillItems) lines.push(skillItems);
286
+ lines.push(`];`);
287
+ lines.push(``);
288
+ const agentItems = agents.map(renderEntryLine).join("\n");
289
+ lines.push(`const agents: AgentScopeConfig[] = [`);
290
+ lines.push(` ...globalConfig.agents,`);
291
+ if (agentItems) lines.push(agentItems);
292
+ lines.push(`];`);
293
+ if (hasStack) {
294
+ lines.push(``);
295
+ const stackBody = JSON.stringify(stack, null, 2);
296
+ lines.push(`const stack: Partial<Record<ProjectAgentName, StackAgentConfig>> = ${stackBody};`);
297
+ }
298
+ if (hasProjectDomains) {
299
+ lines.push(``);
300
+ const domainItems = selectedDomains.map(renderEntryLine).join("\n");
301
+ lines.push(`const selectedDomains: Domain[] = [`);
302
+ lines.push(` ...(globalConfig.selectedDomains ?? []),`);
303
+ if (domainItems) lines.push(domainItems);
304
+ lines.push(`];`);
305
+ }
306
+ const scalarFields = Object.entries(cleaned).filter(([key]) => !EXTRACTED_FIELDS.has(key) && key !== "name").map(([key, value]) => renderScalarField(key, value)).join("\n");
307
+ const exportFields = [
308
+ ` ...globalConfig,`,
309
+ ` name: ${JSON.stringify(resolveProjectName(cleaned))},`,
310
+ ` skills,`,
311
+ ` agents,`,
312
+ ...hasStack ? [` stack,`] : [],
313
+ ...hasProjectDomains ? [` selectedDomains,`] : [],
314
+ ...scalarFields ? [scalarFields] : []
315
+ ];
316
+ lines.push(``);
317
+ lines.push(`export default {`);
318
+ lines.push(...exportFields);
319
+ lines.push(`} satisfies ProjectConfig;`);
320
+ lines.push(``);
321
+ return lines.join("\n");
322
+ }
323
+ function resolveProjectName(cleaned) {
324
+ return cleaned.name && cleaned.name !== GLOBAL_CONFIG_NAME ? cleaned.name : DEFAULT_PLUGIN_NAME;
325
+ }
326
+ function partitionInlinedConfigEntries(cleaned, cleanedGlobal) {
327
+ const project = extractConfigArrays(cleaned);
328
+ const global = extractConfigArrays(cleanedGlobal);
329
+ const isExcluded = (entry) => entry.excluded === true;
330
+ const idOf = (entry) => entry.id;
331
+ const nameOf = (entry) => entry.name;
332
+ const excludedGlobalSkills = project.skills.filter(isExcluded);
333
+ const excludedGlobalAgents = project.agents.filter(isExcluded);
334
+ const projectSkills = project.skills.filter((s) => !isExcluded(s));
335
+ const projectAgents = project.agents.filter((a) => !isExcluded(a));
336
+ const excludedSkillIds = new Set(excludedGlobalSkills.map(idOf));
337
+ const excludedAgentNames = new Set(excludedGlobalAgents.map(nameOf));
338
+ const globalSkills = [
339
+ ...global.skills.filter((s) => !excludedSkillIds.has(idOf(s))),
340
+ ...excludedGlobalSkills
341
+ ];
342
+ const globalAgents = [
343
+ ...global.agents.filter((a) => !excludedAgentNames.has(nameOf(a))),
344
+ ...excludedGlobalAgents
345
+ ];
346
+ const projectAgentNames = new Set(projectAgents.map(nameOf));
347
+ const filteredStack = project.stack ? Object.fromEntries(
348
+ Object.entries(project.stack).filter(([agent]) => projectAgentNames.has(agent))
349
+ ) : void 0;
350
+ return {
351
+ globalSkills,
352
+ globalAgents,
353
+ projectSkills,
354
+ projectAgents,
355
+ filteredStack,
356
+ selectedDomains: [.../* @__PURE__ */ new Set([...global.selectedDomains, ...project.selectedDomains])]
357
+ };
358
+ }
359
+ function mergeInlinedScalarFields(cleaned, cleanedGlobal) {
360
+ return Object.entries(canonicalizeFieldOrder({ ...cleanedGlobal, ...cleaned })).filter(
361
+ ([key]) => !EXTRACTED_FIELDS.has(key) && key !== "name"
362
+ );
363
+ }
364
+ function generateProjectConfigWithInlinedGlobal(cleaned, cleanedGlobal) {
365
+ const partition = partitionInlinedConfigEntries(cleaned, cleanedGlobal);
366
+ const { globalSkills, globalAgents, projectSkills, projectAgents, filteredStack } = partition;
367
+ const hasGlobalSkills = globalSkills.length > 0;
368
+ const hasProjectSkills = projectSkills.length > 0;
369
+ const hasSkills = hasGlobalSkills || hasProjectSkills;
370
+ const hasGlobalAgents = globalAgents.length > 0;
371
+ const hasProjectAgents = projectAgents.length > 0;
372
+ const hasAgents = hasGlobalAgents || hasProjectAgents;
373
+ const hasStack = filteredStack != null && Object.keys(filteredStack).length > 0;
374
+ const hasSelectedDomains = partition.selectedDomains.length > 0;
375
+ const typeImports = buildTypeImports({
376
+ hasSkills,
377
+ hasAgents,
378
+ hasStack,
379
+ hasSelectedDomains
380
+ });
381
+ const lines = [`import type { ${typeImports} } from "./config-types";`];
382
+ if (hasSkills) {
383
+ lines.push(``);
384
+ lines.push(`const skills: SkillConfig[] = [`);
385
+ lines.push(
386
+ ...hasGlobalSkills ? [` // global`, ...globalSkills.map(renderEntryLine)] : [],
387
+ ...hasProjectSkills ? [` // project`, ...projectSkills.map(renderEntryLine)] : []
388
+ );
389
+ lines.push(`];`);
390
+ }
391
+ if (hasAgents) {
392
+ lines.push(``);
393
+ lines.push(`const agents: AgentScopeConfig[] = [`);
394
+ lines.push(
395
+ ...hasGlobalAgents ? [` // global`, ...globalAgents.map(renderEntryLine)] : [],
396
+ ...hasProjectAgents ? [` // project`, ...projectAgents.map(renderEntryLine)] : []
397
+ );
398
+ lines.push(`];`);
399
+ }
400
+ if (hasStack) {
401
+ lines.push(``);
402
+ const stackBody = JSON.stringify(filteredStack, null, 2);
403
+ lines.push(`const stack: Partial<Record<ProjectAgentName, StackAgentConfig>> = ${stackBody};`);
404
+ }
405
+ if (hasSelectedDomains) {
406
+ lines.push(``);
407
+ const items = partition.selectedDomains.map((d) => JSON.stringify(d)).join(", ");
408
+ lines.push(`const selectedDomains: Domain[] = [${items}];`);
409
+ }
410
+ const scalarFields = mergeInlinedScalarFields(cleaned, cleanedGlobal);
411
+ const exportFields = [
412
+ ` name: ${JSON.stringify(resolveProjectName(cleaned))},`,
413
+ ...scalarFields.map(([key, value]) => renderScalarField(key, value)),
414
+ hasSkills ? ` skills,` : ` skills: [],`,
415
+ hasAgents ? ` agents,` : ` agents: [],`,
416
+ ...hasStack ? [` stack,`] : [],
417
+ ...hasSelectedDomains ? [` selectedDomains,`] : []
418
+ ];
419
+ lines.push(``);
420
+ lines.push(`export default {`);
421
+ lines.push(...exportFields);
422
+ lines.push(`} satisfies ProjectConfig;`);
423
+ lines.push(``);
424
+ return lines.join("\n");
425
+ }
426
+ function carriesFlags(assignment) {
427
+ return Boolean(assignment.preloaded || assignment.local || assignment.path);
428
+ }
429
+ function compactAssignment(assignment) {
430
+ if (isSkillAssignment(assignment) && !carriesFlags(assignment)) return assignment.id;
431
+ return assignment;
432
+ }
433
+ function isExclusiveCategory(category) {
434
+ return matrix.categories[category]?.exclusive === true;
435
+ }
436
+ function compactCategoryAssignments(category, assignments) {
437
+ const compacted = assignments.map(compactAssignment);
438
+ if (!isExclusiveCategory(category)) return compacted;
439
+ if (compacted.length > 1) {
440
+ throw new Error(
441
+ `Category '${category}' is exclusive but holds ${compacted.length} skills: ${JSON.stringify(compacted)}`
442
+ );
443
+ }
444
+ return compacted[0];
445
+ }
446
+ function compactCategories(categories) {
447
+ return Object.fromEntries(
448
+ Object.entries(categories).filter(([, assignments]) => Array.isArray(assignments) && assignments.length > 0).map(([category, assignments]) => [
449
+ category,
450
+ compactCategoryAssignments(category, assignments)
451
+ ])
452
+ );
453
+ }
454
+ function compactStackAssignments(stack) {
455
+ return Object.fromEntries(
456
+ Object.entries(stack).map(([agent, categories]) => [agent, compactCategories(categories)]).filter(([, categories]) => Object.keys(categories).length > 0)
457
+ );
458
+ }
459
+ function getGlobalConfigImportPath() {
460
+ return path.join(os.homedir(), CLAUDE_SRC_DIR);
461
+ }
462
+ function generateBlankGlobalConfigSource() {
463
+ return `import type { ProjectConfig } from "./config-types";
464
+
465
+ export default {
466
+ "name": "${GLOBAL_CONFIG_NAME}",
467
+ "skills": [],
468
+ "agents": [],
469
+ "selectedDomains": []
470
+ } satisfies ProjectConfig;
471
+ `;
472
+ }
473
+ function generateBlankGlobalConfigTypesSource() {
474
+ return assembleConfigTypesSource({
475
+ skillId: "never",
476
+ agentName: "never",
477
+ selectedAgentName: "never",
478
+ projectAgentName: "SelectedAgentName",
479
+ domain: "never",
480
+ category: "never",
481
+ stackAgentConfig: STACK_AGENT_CONFIG_LOOSE_LINE
482
+ });
483
+ }
484
+
485
+ // src/cli/lib/config-gate/propagate.ts
486
+ async function writeConfigFile(config, configPath, options) {
487
+ const source = generateConfigSource(config, options);
488
+ await writeFile(configPath, source);
489
+ }
490
+ function additiveMergeStack(existing, incoming) {
491
+ const merged = existing ? structuredClone(existing) : {};
492
+ if (!incoming) return { stack: merged, changed: false };
493
+ let changed = false;
494
+ for (const [agentName, incomingAgentStack] of typedEntries(
495
+ incoming
496
+ )) {
497
+ if (!incomingAgentStack) continue;
498
+ const existingAgentStack = merged[agentName];
499
+ if (!existingAgentStack) {
500
+ merged[agentName] = structuredClone(incomingAgentStack);
501
+ changed = true;
502
+ continue;
503
+ }
504
+ if (mergeAgentCategories(existingAgentStack, incomingAgentStack)) {
505
+ changed = true;
506
+ }
507
+ }
508
+ return { stack: merged, changed };
509
+ }
510
+ function mergeAgentCategories(existingAgentStack, incomingAgentStack) {
511
+ let changed = false;
512
+ for (const [category, incomingAssignments] of typedEntries(
513
+ incomingAgentStack
514
+ )) {
515
+ if (!incomingAssignments) continue;
516
+ const existingAssignments = existingAgentStack[category];
517
+ if (!existingAssignments) {
518
+ existingAgentStack[category] = incomingAssignments.map((a) => ({ ...a }));
519
+ changed = true;
520
+ continue;
521
+ }
522
+ const existingIds = new Set(existingAssignments.map((a) => a.id));
523
+ for (const assignment of incomingAssignments) {
524
+ if (!existingIds.has(assignment.id)) {
525
+ existingAssignments.push({ ...assignment });
526
+ existingIds.add(assignment.id);
527
+ changed = true;
528
+ }
529
+ }
530
+ }
531
+ return changed;
532
+ }
533
+ function mergeGlobalConfigs(existing, incoming) {
534
+ const existingSkillIds = new Set(existing.skills.map((s) => s.id));
535
+ const existingAgentNames = new Set(existing.agents.map((a) => a.name));
536
+ const incomingActiveSkills = incoming.skills.filter((s) => !s.excluded);
537
+ const incomingActiveAgents = incoming.agents.filter((a) => !a.excluded);
538
+ const newSkills = incomingActiveSkills.filter((s) => !existingSkillIds.has(s.id));
539
+ const newAgents = incomingActiveAgents.filter((a) => !existingAgentNames.has(a.name));
540
+ const mergedSkills = [...existing.skills, ...newSkills];
541
+ const mergedAgents = [...existing.agents, ...newAgents];
542
+ const { stack: mergedStack, changed: stackChanged } = additiveMergeStack(
543
+ existing.stack,
544
+ incoming.stack
545
+ );
546
+ const mergedSelectedDomains = [
547
+ .../* @__PURE__ */ new Set([...existing.selectedDomains ?? [], ...incoming.selectedDomains ?? []])
548
+ ];
549
+ const mergedMarketplaceName = existing.marketplaceName ?? incoming.marketplaceName;
550
+ const mergedMarketplace = existing.marketplace ?? incoming.marketplace;
551
+ const changed = newSkills.length > 0 || newAgents.length > 0 || stackChanged || !isDeepEqual(existing.selectedDomains ?? [], mergedSelectedDomains) || mergedMarketplaceName !== existing.marketplaceName || mergedMarketplace !== existing.marketplace;
552
+ return {
553
+ config: {
554
+ ...existing,
555
+ skills: mergedSkills,
556
+ agents: mergedAgents,
557
+ stack: mergedStack,
558
+ selectedDomains: mergedSelectedDomains,
559
+ ...mergedMarketplaceName !== void 0 && { marketplaceName: mergedMarketplaceName },
560
+ ...mergedMarketplace !== void 0 && { marketplace: mergedMarketplace }
561
+ },
562
+ changed
563
+ };
564
+ }
565
+ function normalizeProjectPath(projectDir) {
566
+ return fs.realpathSync(projectDir);
567
+ }
568
+ async function registerProjectPath(globalConfig, projectDir) {
569
+ const normalizedPath = normalizeProjectPath(projectDir);
570
+ const existing = globalConfig.projects ?? [];
571
+ const staleChecks = await Promise.all(
572
+ existing.map(async (p) => ({
573
+ path: p,
574
+ hasConfig: await fileExists(getProjectConfigPath(p))
575
+ }))
576
+ );
577
+ const valid = staleChecks.filter((c) => c.hasConfig).map((c) => c.path);
578
+ if (valid.includes(normalizedPath)) {
579
+ const changed = valid.length !== existing.length;
580
+ return { config: changed ? { ...globalConfig, projects: valid } : globalConfig, changed };
581
+ }
582
+ return { config: { ...globalConfig, projects: [...valid, normalizedPath] }, changed: true };
583
+ }
584
+ function isProjectScopedEntry(entry) {
585
+ return entry.scope === "project";
586
+ }
587
+ function globalHasActiveSkill(globalConfig, id) {
588
+ return globalConfig.skills.some((s) => s.id === id && isActiveAt(s, "global"));
589
+ }
590
+ function globalHasActiveAgent(globalConfig, name) {
591
+ return globalConfig.agents.some((a) => a.name === name && isActiveAt(a, "global"));
592
+ }
593
+ function retainProjectOwnedSkills(skills, globalConfig) {
594
+ return skills.filter(
595
+ (entry) => isProjectScopedEntry(entry) || isGlobalTombstone(entry) && globalHasActiveSkill(globalConfig, entry.id)
596
+ );
597
+ }
598
+ function retainProjectOwnedAgents(agents, globalConfig) {
599
+ return agents.filter(
600
+ (entry) => isProjectScopedEntry(entry) || isGlobalTombstone(entry) && globalHasActiveAgent(globalConfig, entry.name)
601
+ );
602
+ }
603
+ function categoryOfSkill(id, matrix2) {
604
+ const category = matrix2.skills[id]?.category;
605
+ if (category === void 0 || category === LOCAL_PSEUDO_CATEGORY) return void 0;
606
+ return category;
607
+ }
608
+ function isExclusiveCategory2(category, matrix2) {
609
+ return matrix2.categories[category]?.exclusive === true;
610
+ }
611
+ function activeProjectCategories(projectOwnedSkills, matrix2) {
612
+ return new Set(
613
+ projectOwnedSkills.filter((s) => isActiveAt(s, "project")).map((s) => categoryOfSkill(s.id, matrix2)).filter((category) => category !== void 0)
614
+ );
615
+ }
616
+ function buildProjectCollisionTest(projectOwnedSkills, matrix2) {
617
+ const ownedIds = new Set(
618
+ projectOwnedSkills.filter((s) => isActiveAt(s, "project")).map((s) => s.id)
619
+ );
620
+ const occupiedExclusiveCategories = new Set(
621
+ [...activeProjectCategories(projectOwnedSkills, matrix2)].filter(
622
+ (category) => isExclusiveCategory2(category, matrix2)
623
+ )
624
+ );
625
+ return (id) => {
626
+ if (ownedIds.has(id)) return true;
627
+ const category = categoryOfSkill(id, matrix2);
628
+ return category !== void 0 && occupiedExclusiveCategories.has(category);
629
+ };
630
+ }
631
+ function dropOrphanedDerivedMasks(projectOwnedSkills, matrix2) {
632
+ const collidesWithProjectOwnership = buildProjectCollisionTest(projectOwnedSkills, matrix2);
633
+ return projectOwnedSkills.filter(
634
+ (entry) => !isGlobalTombstone(entry) || collidesWithProjectOwnership(entry.id)
635
+ );
636
+ }
637
+ function dropOrphanedDerivedAgentMasks(projectOwnedAgents) {
638
+ const ownedNames = new Set(activeProjectAgentNames(projectOwnedAgents));
639
+ return projectOwnedAgents.filter(
640
+ (entry) => !isGlobalTombstone(entry) || ownedNames.has(entry.name)
641
+ );
642
+ }
643
+ function maskCollidingGlobalSkills(projectOwnedSkills, globalConfig, matrix2) {
644
+ const collidesWithProjectOwnership = buildProjectCollisionTest(projectOwnedSkills, matrix2);
645
+ const alreadyTombstoned = new Set(projectOwnedSkills.filter(isGlobalTombstone).map((s) => s.id));
646
+ return globalConfig.skills.filter(
647
+ (globalEntry) => isActiveAt(globalEntry, "global") && collidesWithProjectOwnership(globalEntry.id) && !alreadyTombstoned.has(globalEntry.id)
648
+ ).map((globalEntry) => ({ ...globalEntry, excluded: true }));
649
+ }
650
+ function maskCollidingGlobalAgents(projectOwnedAgents, globalConfig) {
651
+ const ownedNames = new Set(activeProjectAgentNames(projectOwnedAgents));
652
+ const alreadyTombstoned = new Set(
653
+ projectOwnedAgents.filter(isGlobalTombstone).map((a) => a.name)
654
+ );
655
+ return globalConfig.agents.filter(
656
+ (globalEntry) => isActiveAt(globalEntry, "global") && ownedNames.has(globalEntry.name) && !alreadyTombstoned.has(globalEntry.name)
657
+ ).map((globalEntry) => ({ ...globalEntry, excluded: true }));
658
+ }
659
+ function reconcileProjectSplitAgainstGlobal(projectSplit, globalConfig, matrix2) {
660
+ const healedSkills = dropOrphanedDerivedMasks(projectSplit.skills, matrix2);
661
+ const healedAgents = dropOrphanedDerivedAgentMasks(projectSplit.agents);
662
+ return {
663
+ ...projectSplit,
664
+ skills: [...healedSkills, ...maskCollidingGlobalSkills(healedSkills, globalConfig, matrix2)],
665
+ agents: [...healedAgents, ...maskCollidingGlobalAgents(healedAgents, globalConfig)]
666
+ };
667
+ }
668
+ function computeRemovedGlobalSkillIds(priorProjectSkills, globalConfig) {
669
+ const activeGlobalIds = new Set(
670
+ globalConfig.skills.filter((s) => isActiveAt(s, "global")).map((s) => s.id)
671
+ );
672
+ const projectOwnedIds = new Set(
673
+ priorProjectSkills.filter((s) => isActiveAt(s, "project")).map((s) => s.id)
674
+ );
675
+ return new Set(
676
+ priorProjectSkills.filter(
677
+ (s) => s.scope === "global" && !s.excluded && !activeGlobalIds.has(s.id) && !projectOwnedIds.has(s.id)
678
+ ).map((s) => s.id)
679
+ );
680
+ }
681
+ function retainReconciledStack(stack, removedGlobalSkillIds) {
682
+ if (!stack || removedGlobalSkillIds.size === 0) return stack;
683
+ const reconciled = {};
684
+ for (const [agent, agentStack] of Object.entries(stack)) {
685
+ const reconciledAgentStack = {};
686
+ for (const [category, assignments] of typedEntries(agentStack)) {
687
+ if (!assignments) continue;
688
+ const kept = assignments.filter((assignment) => !removedGlobalSkillIds.has(assignment.id));
689
+ if (kept.length > 0) reconciledAgentStack[category] = kept;
690
+ }
691
+ if (typedKeys(reconciledAgentStack).length > 0) {
692
+ reconciled[agent] = reconciledAgentStack;
693
+ }
694
+ }
695
+ return reconciled;
696
+ }
697
+ async function writeProjectConfigPair(projectDir, reconciledSplit, effectiveGlobal, matrix2, agents, options = {}) {
698
+ await writeConfigFile(reconciledSplit, getProjectConfigPath(projectDir), {
699
+ isProjectConfig: true,
700
+ globalConfig: effectiveGlobal
701
+ });
702
+ if (options.regenerateTypes === false) return;
703
+ await regenerateConfigTypes(
704
+ projectDir,
705
+ Promise.resolve(buildConfigTypesBackgroundData(matrix2, agents)),
706
+ buildProjectTypesExtras(inlinedProjectView(reconciledSplit, effectiveGlobal), matrix2)
707
+ );
708
+ }
709
+ function inlinedProjectView(reconciledSplit, effectiveGlobal) {
710
+ return {
711
+ ...reconciledSplit,
712
+ skills: [...effectiveGlobal.skills, ...reconciledSplit.skills],
713
+ agents: [...effectiveGlobal.agents, ...reconciledSplit.agents],
714
+ selectedDomains: unique([
715
+ ...effectiveGlobal.selectedDomains ?? [],
716
+ ...reconciledSplit.selectedDomains ?? []
717
+ ]),
718
+ stack: { ...effectiveGlobal.stack ?? {}, ...reconciledSplit.stack ?? {} }
719
+ };
720
+ }
721
+ async function propagateGlobalChangesToProjects(globalConfig, matrix2, agents, currentProjectDir, options = {}) {
722
+ const projects = globalConfig.projects ?? [];
723
+ if (projects.length === 0) return { updated: [], skipped: [] };
724
+ const currentNormalized = currentProjectDir ? normalizeProjectPath(currentProjectDir) : null;
725
+ const updated = [];
726
+ const skipped = [];
727
+ for (const projectPath of projects) {
728
+ if (currentNormalized && projectPath === currentNormalized) continue;
729
+ const projectConfigPath = getProjectConfigPath(projectPath);
730
+ if (!await fileExists(projectConfigPath)) {
731
+ skipped.push(projectPath);
732
+ verbose(`Skipped propagation to ${projectPath} (config not found)`);
733
+ continue;
734
+ }
735
+ try {
736
+ const existingProject = await loadProjectConfigFromDir(projectPath);
737
+ if (!existingProject?.config) {
738
+ skipped.push(projectPath);
739
+ continue;
740
+ }
741
+ const projectConfig = existingProject.config;
742
+ const removedGlobalSkillIds = computeRemovedGlobalSkillIds(
743
+ projectConfig.skills,
744
+ globalConfig
745
+ );
746
+ const retained = retainReconciledStack(projectConfig.stack, removedGlobalSkillIds);
747
+ const reconciledStack = retained === void 0 ? {} : { stack: retained };
748
+ const projectSplit = reconcileProjectSplitAgainstGlobal(
749
+ {
750
+ ...projectConfig,
751
+ skills: retainProjectOwnedSkills(projectConfig.skills, globalConfig),
752
+ agents: retainProjectOwnedAgents(projectConfig.agents, globalConfig),
753
+ ...reconciledStack
754
+ },
755
+ globalConfig,
756
+ matrix2
757
+ );
758
+ await writeProjectConfigPair(projectPath, projectSplit, globalConfig, matrix2, agents, {
759
+ regenerateTypes: options.regenerateTypes ?? true
760
+ });
761
+ updated.push(projectPath);
762
+ verbose(`Propagated global changes to ${projectPath}`);
763
+ } catch (error) {
764
+ skipped.push(projectPath);
765
+ verbose(`Failed to propagate to ${projectPath}: ${getErrorMessage(error)}`);
766
+ }
767
+ }
768
+ return { updated, skipped };
769
+ }
770
+ async function pruneGlobalEntriesFromRegisteredProjects(globalConfig, matrix2, agents) {
771
+ const emptiedGlobal = {
772
+ ...globalConfig,
773
+ skills: [],
774
+ agents: []
775
+ };
776
+ return propagateGlobalChangesToProjects(emptiedGlobal, matrix2, agents);
777
+ }
778
+ async function resolveEffectiveGlobalConfig(globalSplit, existingGlobalConfig, projectDir, authority) {
779
+ const merged = authority === "all" ? matchGlobalToSession(globalSplit, existingGlobalConfig) : addSessionToGlobal(globalSplit, existingGlobalConfig);
780
+ const registration = await registerProjectPath(merged.config, projectDir);
781
+ return {
782
+ config: registration.config,
783
+ globalDataChanged: merged.changed,
784
+ changed: merged.changed || registration.changed
785
+ };
786
+ }
787
+ function addSessionToGlobal(globalSplit, existingGlobalConfig) {
788
+ const hasGlobalItems = globalSplit.skills.length > 0 || globalSplit.agents.length > 0;
789
+ if (!hasGlobalItems) {
790
+ return {
791
+ config: existingGlobalConfig ?? { name: GLOBAL_CONFIG_NAME, skills: [], agents: [] },
792
+ changed: false
793
+ };
794
+ }
795
+ if (!existingGlobalConfig) return { config: globalSplit, changed: true };
796
+ return mergeGlobalConfigs(existingGlobalConfig, globalSplit);
797
+ }
798
+ function matchGlobalToSession(globalSplit, existingGlobalConfig) {
799
+ if (!existingGlobalConfig) return { config: globalSplit, changed: true };
800
+ const config = mergeConfigs(globalSplit, existingGlobalConfig, { authoritativeScope: "all" });
801
+ return { config, changed: !isDeepEqual(config, existingGlobalConfig) };
802
+ }
803
+ function stackCategories(stack) {
804
+ return Object.values(stack ?? {}).flatMap((agentStack) => typedKeys(agentStack ?? {}));
805
+ }
806
+ function buildProjectTypesExtras(finalConfig, matrix2) {
807
+ const activeSkills = finalConfig.skills.filter((s) => !s.excluded);
808
+ const activeAgents = finalConfig.agents.filter((a) => !a.excluded);
809
+ const extraSkillIds = unique(activeSkills.map((s) => s.id));
810
+ const extraAgentNames = unique(activeAgents.map((a) => a.name));
811
+ const extraCategories = unique([
812
+ ...deriveCategories(extraSkillIds, matrix2),
813
+ ...stackCategories(finalConfig.stack)
814
+ ]);
815
+ const extraDomains = unique([
816
+ ...deriveDomains(extraCategories, matrix2),
817
+ ...finalConfig.selectedDomains ?? []
818
+ ]);
819
+ return { extraSkillIds, extraAgentNames, extraDomains, extraCategories };
820
+ }
821
+
822
+ // src/cli/lib/config-gate/index.ts
823
+ import os3 from "os";
824
+ import path3 from "path";
825
+
826
+ // src/cli/lib/config-gate/classify.ts
827
+ import { isDeepEqual as isDeepEqual2 } from "remeda";
828
+ var NO_CHANGES = {
829
+ skills: { added: [], removed: [], sourceChanged: [], otherChanged: [] },
830
+ agents: { added: [], removed: [], changed: [] },
831
+ stackChanged: false,
832
+ selectedDomainsChanged: false,
833
+ scalarsChanged: [],
834
+ projectsChanged: false
835
+ };
836
+ var EXTRACTED_FIELDS2 = /* @__PURE__ */ new Set(["skills", "agents", "stack", "selectedDomains"]);
837
+ var REGISTRATION_FIELD = "projects";
838
+ function normalize(config) {
839
+ return JSON.parse(JSON.stringify(config));
840
+ }
841
+ function field(config, key) {
842
+ return config[key];
843
+ }
844
+ function skillsById(config) {
845
+ const skills = config.skills ?? [];
846
+ return new Map(skills.map((skill) => [skill.id, skill]));
847
+ }
848
+ function agentsByName(config) {
849
+ const agents = config.agents ?? [];
850
+ return new Map(agents.map((agent) => [agent.name, agent]));
851
+ }
852
+ function scalarKeys(prev, next) {
853
+ const isScalarKey = (key) => !EXTRACTED_FIELDS2.has(key) && key !== REGISTRATION_FIELD;
854
+ const nextKeys = Object.keys(next).filter(isScalarKey);
855
+ const extraPrevKeys = Object.keys(prev).filter(
856
+ (key) => isScalarKey(key) && !nextKeys.includes(key)
857
+ );
858
+ return [...nextKeys, ...extraPrevKeys];
859
+ }
860
+ function diffSkills(prev, next) {
861
+ const before = skillsById(prev);
862
+ const after = skillsById(next);
863
+ const added = [...after.keys()].filter((id) => !before.has(id));
864
+ const removed = [...before.keys()].filter((id) => !after.has(id));
865
+ const sourceChanged = [];
866
+ const otherChanged = [];
867
+ for (const [id, afterEntry] of after) {
868
+ const beforeEntry = before.get(id);
869
+ if (!beforeEntry || isDeepEqual2(beforeEntry, afterEntry)) continue;
870
+ if (beforeEntry.origin !== afterEntry.origin) sourceChanged.push(id);
871
+ else otherChanged.push(id);
872
+ }
873
+ return { added, removed, sourceChanged, otherChanged };
874
+ }
875
+ function diffAgents(prev, next) {
876
+ const before = agentsByName(prev);
877
+ const after = agentsByName(next);
878
+ return {
879
+ added: [...after.keys()].filter((name) => !before.has(name)),
880
+ removed: [...before.keys()].filter((name) => !after.has(name)),
881
+ changed: [...after.keys()].filter((name) => {
882
+ const beforeEntry = before.get(name);
883
+ return beforeEntry !== void 0 && !isDeepEqual2(beforeEntry, after.get(name));
884
+ })
885
+ };
886
+ }
887
+ function classifyGlobalChange(prev, next) {
888
+ const before = prev ? normalize(prev) : {};
889
+ const after = normalize(next);
890
+ return {
891
+ skills: diffSkills(before, after),
892
+ agents: diffAgents(before, after),
893
+ stackChanged: !isDeepEqual2(field(before, "stack"), field(after, "stack")),
894
+ selectedDomainsChanged: !isDeepEqual2(
895
+ field(before, "selectedDomains"),
896
+ field(after, "selectedDomains")
897
+ ),
898
+ scalarsChanged: scalarKeys(before, after).filter(
899
+ (key) => !isDeepEqual2(field(before, key), field(after, key))
900
+ ),
901
+ projectsChanged: !isDeepEqual2(
902
+ field(before, REGISTRATION_FIELD),
903
+ field(after, REGISTRATION_FIELD)
904
+ )
905
+ };
906
+ }
907
+ function movesTypesOrCompiledAgents(changes) {
908
+ const { skills, agents } = changes;
909
+ return skills.added.length > 0 || skills.removed.length > 0 || skills.sourceChanged.length > 0 || skills.otherChanged.length > 0 || agents.added.length > 0 || agents.removed.length > 0 || agents.changed.length > 0 || changes.stackChanged || changes.selectedDomainsChanged;
910
+ }
911
+ function consequenceTier(changes) {
912
+ if (movesTypesOrCompiledAgents(changes)) return "T1";
913
+ if (changes.scalarsChanged.length > 0) return "T2";
914
+ if (changes.projectsChanged) return "T3";
915
+ return "T4";
916
+ }
917
+ function tierNeedsDeps(tier) {
918
+ return tier === "T1" || tier === "T2";
919
+ }
920
+ function tierRegeneratesTypes(tier) {
921
+ return tier === "T1";
922
+ }
923
+ function tierPropagates(tier) {
924
+ return tier === "T1" || tier === "T2";
925
+ }
926
+
927
+ // src/cli/lib/config-gate/deps.ts
928
+ function isLoaded(deps) {
929
+ return "matrix" in deps;
930
+ }
931
+ async function resolveGateDeps(deps, tier) {
932
+ if (!tierNeedsDeps(tier)) return null;
933
+ if (isLoaded(deps)) return deps;
934
+ const [matrix2, agents] = await Promise.all([
935
+ deps.loadMatrix(),
936
+ tierRegeneratesTypes(tier) ? deps.loadAgents() : NO_AGENTS
937
+ ]);
938
+ return { matrix: matrix2, agents };
939
+ }
940
+ var NO_AGENTS = Promise.resolve({});
941
+
942
+ // src/cli/lib/config-gate/pair-writer.ts
943
+ import os2 from "os";
944
+ import path2 from "path";
945
+ function globalPairPaths() {
946
+ const dir = path2.join(os2.homedir(), CLAUDE_SRC_DIR);
947
+ return {
948
+ configPath: path2.join(dir, STANDARD_FILES.CONFIG_TS),
949
+ typesPath: path2.join(dir, STANDARD_FILES.CONFIG_TYPES_TS)
950
+ };
951
+ }
952
+ function typesPathFor(configPath) {
953
+ return path2.join(path2.dirname(configPath), STANDARD_FILES.CONFIG_TYPES_TS);
954
+ }
955
+ async function writeIfChanged(filePath, source) {
956
+ assertGateToken(filePath);
957
+ if (await fileExists(filePath) && await readFile(filePath) === source) return false;
958
+ await writeFile(filePath, source);
959
+ return true;
960
+ }
961
+ function renderStandaloneTypes(config, matrix2, agents, extras) {
962
+ const data = buildConfigTypesBackgroundData(matrix2, agents);
963
+ return generateConfigTypesSource(
964
+ data.matrix,
965
+ data.agentNames,
966
+ data.customAgentNames,
967
+ extras,
968
+ config
969
+ );
970
+ }
971
+ async function writeGlobalConfigHalf(config, configPath) {
972
+ return writeIfChanged(configPath, generateConfigSource(config));
973
+ }
974
+ async function writeGlobalTypesHalf(config, configPath, matrix2, agents, extras) {
975
+ return writeIfChanged(
976
+ typesPathFor(configPath),
977
+ renderStandaloneTypes(config, matrix2, agents, extras)
978
+ );
979
+ }
980
+ async function writeGlobalPair(config, configPath, matrix2, agents) {
981
+ const configWritten = await writeIfChanged(configPath, generateConfigSource(config));
982
+ const typesWritten = await writeIfChanged(
983
+ typesPathFor(configPath),
984
+ renderStandaloneTypes(config, matrix2, agents)
985
+ );
986
+ return configWritten || typesWritten;
987
+ }
988
+ async function ensureBlankPair() {
989
+ const { configPath, typesPath } = globalPairPaths();
990
+ if (await fileExists(configPath)) {
991
+ verbose("Global config already exists, skipping blank creation");
992
+ return false;
993
+ }
994
+ await ensureDir(path2.dirname(configPath));
995
+ await writeIfChanged(configPath, generateBlankGlobalConfigSource());
996
+ await writeIfChanged(typesPath, generateBlankGlobalConfigTypesSource());
997
+ verbose(`Created blank global config at ${path2.dirname(configPath)}`);
998
+ return true;
999
+ }
1000
+
1001
+ // src/cli/lib/config-gate/recompile.ts
1002
+ var NOTHING_RECOMPILED = {
1003
+ rewrittenCount: 0,
1004
+ unchangedCount: 0,
1005
+ failedCount: 0,
1006
+ warnings: []
1007
+ };
1008
+ async function recompilePropagated(projectDirs) {
1009
+ if (projectDirs.length === 0) return NOTHING_RECOMPILED;
1010
+ const { recompilePropagatedProjectAgents: recompilePropagatedProjectAgents2 } = await import("./recompile-project-agents-G7ZM25PC.js");
1011
+ return recompilePropagatedProjectAgents2(projectDirs);
1012
+ }
1013
+
1014
+ // src/cli/lib/config-gate/index.ts
1015
+ var NOTHING_PROPAGATED = { updated: [], skipped: [] };
1016
+ function report(globalWritten, changes, propagated = NOTHING_PROPAGATED, recompile = NOTHING_RECOMPILED) {
1017
+ return { globalWritten, changes, propagated, recompile };
1018
+ }
1019
+ async function applyConsequences(globalConfig, changes, deps, currentProjectDir) {
1020
+ const tier = consequenceTier(changes);
1021
+ if (!tierPropagates(tier) || !globalConfig.projects?.length) {
1022
+ return { propagated: NOTHING_PROPAGATED, recompile: NOTHING_RECOMPILED };
1023
+ }
1024
+ const propagated = await propagateGlobalChangesToProjects(
1025
+ globalConfig,
1026
+ deps.matrix,
1027
+ deps.agents,
1028
+ currentProjectDir,
1029
+ { regenerateTypes: tierRegeneratesTypes(tier) }
1030
+ );
1031
+ if (propagated.updated.length > 0) {
1032
+ verbose(`Propagated global changes to ${propagated.updated.length} project(s)`);
1033
+ }
1034
+ const recompile = tierRegeneratesTypes(tier) ? await recompilePropagated(propagated.updated) : NOTHING_RECOMPILED;
1035
+ return { propagated, recompile };
1036
+ }
1037
+ function lazyGateDeps(projectDir) {
1038
+ return {
1039
+ loadMatrix: async () => {
1040
+ const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-BIAEDR5R.js");
1041
+ const { matrix: matrix2 } = await loadSkillsMatrixFromSource2({
1042
+ projectDir,
1043
+ skipExtraSources: true,
1044
+ matrixOnly: true
1045
+ });
1046
+ return matrix2;
1047
+ },
1048
+ loadAgents: async () => {
1049
+ const { loadAgentDefs: loadAgentDefs2 } = await import("./load-agent-defs-M6LRVISN.js");
1050
+ return (await loadAgentDefs2()).agents;
1051
+ }
1052
+ };
1053
+ }
1054
+ async function writeScopedFromWizard(args) {
1055
+ return withGateToken(async () => {
1056
+ const { finalConfig, matrix: matrix2, agents, projectDir, projectConfigPath } = args;
1057
+ const homeDir = os3.homedir();
1058
+ const deps = { matrix: matrix2, agents };
1059
+ if (!isHomeDirectory(projectDir)) {
1060
+ return writeFromProjectContext(args, homeDir, deps);
1061
+ }
1062
+ const priorGlobal = await loadProjectConfigFromDir(homeDir);
1063
+ const changes = classifyGlobalChange(priorGlobal?.config, finalConfig);
1064
+ const globalWritten = await writeGlobalPair(finalConfig, projectConfigPath, matrix2, agents);
1065
+ const { propagated, recompile } = await applyConsequences(finalConfig, changes, deps);
1066
+ return report(globalWritten, changes, propagated, recompile);
1067
+ });
1068
+ }
1069
+ async function writeFromProjectContext(args, homeDir, deps) {
1070
+ const { finalConfig, matrix: matrix2, agents, projectDir, projectConfigPath } = args;
1071
+ const { global: globalConfig, project: projectSplitConfig } = splitConfigByScope(finalConfig);
1072
+ const globalConfigPath = getProjectConfigPath(homeDir);
1073
+ const existingGlobal = await loadProjectConfigFromDir(homeDir);
1074
+ const effective = await resolveEffectiveGlobalConfig(
1075
+ globalConfig,
1076
+ existingGlobal?.config,
1077
+ projectDir,
1078
+ args.authoritativeScope
1079
+ );
1080
+ const effectiveGlobalConfig = effective.config;
1081
+ const changes = classifyGlobalChange(existingGlobal?.config, effectiveGlobalConfig);
1082
+ let globalWritten = false;
1083
+ if (effective.changed) {
1084
+ await ensureDir(path3.dirname(globalConfigPath));
1085
+ globalWritten = await writeGlobalPair(effectiveGlobalConfig, globalConfigPath, matrix2, agents);
1086
+ verbose(`Updated global config at ${globalConfigPath}`);
1087
+ } else {
1088
+ verbose("Global config unchanged, skipping write");
1089
+ }
1090
+ const { propagated, recompile } = await applyConsequences(
1091
+ effectiveGlobalConfig,
1092
+ changes,
1093
+ deps,
1094
+ projectDir
1095
+ );
1096
+ const reconciledProjectConfig = reconcileProjectSplitAgainstGlobal(
1097
+ projectSplitConfig,
1098
+ effectiveGlobalConfig,
1099
+ matrix2
1100
+ );
1101
+ const hasProjectItems = reconciledProjectConfig.skills.length > 0 || reconciledProjectConfig.agents.length > 0;
1102
+ if (args.projectInstallationExists || hasProjectItems) {
1103
+ await ensureDir(path3.dirname(projectConfigPath));
1104
+ await writeProjectConfigPair(
1105
+ projectDir,
1106
+ reconciledProjectConfig,
1107
+ effectiveGlobalConfig,
1108
+ matrix2,
1109
+ agents
1110
+ );
1111
+ verbose(`Updated project config at ${projectConfigPath}`);
1112
+ } else {
1113
+ verbose(
1114
+ "Skipped project config \u2014 no existing project installation and no project-scoped items"
1115
+ );
1116
+ }
1117
+ return report(globalWritten, changes, propagated, recompile);
1118
+ }
1119
+ async function writeScopeConfigTypes(projectDir, config, deps, extras) {
1120
+ return withGateToken(async () => {
1121
+ if (isHomeDirectory(projectDir)) {
1122
+ return writeGlobalTypesHalf(
1123
+ config,
1124
+ getProjectConfigPath(projectDir),
1125
+ deps.matrix,
1126
+ deps.agents,
1127
+ extras
1128
+ );
1129
+ }
1130
+ await regenerateConfigTypes(
1131
+ projectDir,
1132
+ Promise.resolve(buildConfigTypesBackgroundData(deps.matrix, deps.agents)),
1133
+ extras ?? buildProjectTypesExtras(config, deps.matrix)
1134
+ );
1135
+ return false;
1136
+ });
1137
+ }
1138
+ async function reconcileTypesFromDisk(projectDir, config, deps, options) {
1139
+ return withGateToken(async () => {
1140
+ const changes = classifyGlobalChange(void 0, config);
1141
+ const globalWritten = await writeScopeConfigTypes(projectDir, config, deps, options?.extras);
1142
+ if (!isHomeDirectory(projectDir)) return report(false, changes);
1143
+ if (!config.projects?.length) return report(globalWritten, changes);
1144
+ const propagated = await propagateGlobalChangesToProjects(
1145
+ config,
1146
+ deps.matrix,
1147
+ deps.agents,
1148
+ options?.currentProjectDir
1149
+ );
1150
+ if (propagated.updated.length > 0) {
1151
+ verbose(`Propagated global changes to ${propagated.updated.length} project(s)`);
1152
+ }
1153
+ const recompile = await recompilePropagated(propagated.updated);
1154
+ return report(globalWritten, changes, propagated, recompile);
1155
+ });
1156
+ }
1157
+ function withMigratedSource(skill, migratedSources) {
1158
+ if (!isActiveAt(skill, "global")) return skill;
1159
+ const origin = migratedSources.get(skill.id);
1160
+ if (origin === void 0 || origin === skill.origin) return skill;
1161
+ return { ...skill, origin };
1162
+ }
1163
+ function applyMigratedGlobalSources(globalSkills, migratedSources) {
1164
+ const skills = globalSkills.map((skill) => withMigratedSource(skill, migratedSources));
1165
+ return { skills, changed: skills.some((skill, index) => skill !== globalSkills[index]) };
1166
+ }
1167
+ function fillRequiredFields(partial, fallbackName) {
1168
+ const name = partial.name ?? fallbackName;
1169
+ if (!name) {
1170
+ throw new Error(
1171
+ `Cannot write config: no project config found. Run \`${CLI_INVOKE_COMMAND} init\` first.`
1172
+ );
1173
+ }
1174
+ return { ...partial, name, skills: partial.skills ?? [], agents: partial.agents ?? [] };
1175
+ }
1176
+ function applyMutation(mutation, current) {
1177
+ switch (mutation.kind) {
1178
+ case "migrate-skill-sources": {
1179
+ const { skills, changed } = applyMigratedGlobalSources(
1180
+ current.skills ?? [],
1181
+ mutation.sources
1182
+ );
1183
+ return changed ? { ...current, skills } : null;
1184
+ }
1185
+ case "deregister-project": {
1186
+ const projects = current.projects ?? [];
1187
+ if (projects.length === 0) return null;
1188
+ const normalized = normalizeProjectPath(mutation.projectDir);
1189
+ const filtered = projects.filter((p) => p !== normalized);
1190
+ return filtered.length === projects.length ? null : { ...current, projects: filtered };
1191
+ }
1192
+ case "set-source":
1193
+ return { ...current, marketplace: mutation.source };
1194
+ default: {
1195
+ const _exhaustive = mutation;
1196
+ return _exhaustive;
1197
+ }
1198
+ }
1199
+ }
1200
+ function fallbackNameFor(mutation) {
1201
+ return mutation.kind === "set-source" ? mutation.fallbackName : void 0;
1202
+ }
1203
+ async function mutateGlobal(mutation, deps) {
1204
+ return withGateToken(async () => {
1205
+ const homeDir = os3.homedir();
1206
+ const loadedGlobal = await loadProjectConfigFromDir(homeDir);
1207
+ if (!loadedGlobal) return report(false, NO_CHANGES);
1208
+ const current = loadedGlobal.config;
1209
+ const mutated = applyMutation(mutation, current);
1210
+ if (!mutated) return report(false, NO_CHANGES);
1211
+ const prior = fillRequiredFields(current, fallbackNameFor(mutation));
1212
+ const next = fillRequiredFields(mutated, fallbackNameFor(mutation));
1213
+ const changes = classifyGlobalChange(prior, next);
1214
+ const globalWritten = await writeGlobalConfigHalf(next, getProjectConfigPath(homeDir));
1215
+ if (!next.projects?.length) return report(globalWritten, changes);
1216
+ const loaded = await resolveGateDeps(deps, consequenceTier(changes));
1217
+ if (!loaded) return report(globalWritten, changes);
1218
+ const { propagated, recompile } = await applyConsequences(next, changes, loaded);
1219
+ return report(globalWritten, changes, propagated, recompile);
1220
+ });
1221
+ }
1222
+ async function propagateGlobalRemoval(preRemovalGlobalConfig, deps) {
1223
+ return withGateToken(async () => {
1224
+ const changes = classifyGlobalChange(preRemovalGlobalConfig, {
1225
+ ...preRemovalGlobalConfig,
1226
+ skills: [],
1227
+ agents: []
1228
+ });
1229
+ const propagated = await pruneGlobalEntriesFromRegisteredProjects(
1230
+ preRemovalGlobalConfig,
1231
+ deps.matrix,
1232
+ deps.agents
1233
+ );
1234
+ const recompile = await recompilePropagated(propagated.updated);
1235
+ return report(false, changes, propagated, recompile);
1236
+ });
1237
+ }
1238
+ async function ensureBlankPair2() {
1239
+ return withGateToken(() => ensureBlankPair());
1240
+ }
1241
+ function withNormalizedStack(partial) {
1242
+ if (!partial.stack) return partial;
1243
+ return { ...partial, stack: normalizeStackRecord(partial.stack) };
1244
+ }
1245
+ async function writeProjectPartial(projectDir, partial, options = {}) {
1246
+ if (isHomeDirectory(projectDir)) {
1247
+ throw new GlobalPairWriteViolation(getProjectConfigPath(projectDir));
1248
+ }
1249
+ const configPath = getProjectConfigPath(projectDir);
1250
+ await ensureDir(path3.join(projectDir, CLAUDE_SRC_DIR));
1251
+ await writeFile(
1252
+ configPath,
1253
+ generateConfigSource(fillRequiredFields(withNormalizedStack(partial), options.fallbackName))
1254
+ );
1255
+ }
1256
+
1257
+ // src/cli/lib/operations/project/write-project-config.ts
1258
+ import path4 from "path";
1259
+ async function writeProjectConfig(options) {
1260
+ const { wizardResult, sourceResult, projectDir, sourceFlag } = options;
1261
+ const projectPaths = resolveInstallPaths(projectDir, "project");
1262
+ await ensureDir(path4.dirname(projectPaths.configPath));
1263
+ const { agents } = options.agentDefs ?? await loadAgentDefs();
1264
+ const mergeResult = await buildAndMergeConfig(
1265
+ wizardResult,
1266
+ sourceResult,
1267
+ projectDir,
1268
+ sourceFlag,
1269
+ options.authoritativeScope
1270
+ );
1271
+ const finalConfig = mergeResult.config;
1272
+ const isProjectContext = !isHomeDirectory(projectDir);
1273
+ if (isProjectContext) {
1274
+ await ensureBlankPair2();
1275
+ }
1276
+ const propagation = await writeScopedFromWizard({
1277
+ finalConfig,
1278
+ matrix: sourceResult.matrix,
1279
+ agents,
1280
+ projectDir,
1281
+ projectConfigPath: projectPaths.configPath,
1282
+ projectInstallationExists: isProjectContext,
1283
+ // The same word the merger above took. It decides the config ROW there and the GLOBAL
1284
+ // config a project write commits here, and the two files disagree the moment it does not
1285
+ // reach both: a row preserved for a skill whose directory the removal diff deleted.
1286
+ ...options.authoritativeScope !== void 0 && {
1287
+ authoritativeScope: options.authoritativeScope
1288
+ }
1289
+ });
1290
+ return {
1291
+ config: finalConfig,
1292
+ configPath: projectPaths.configPath,
1293
+ wasMerged: mergeResult.merged,
1294
+ ...mergeResult.existingConfigPath !== void 0 && {
1295
+ existingConfigPath: mergeResult.existingConfigPath
1296
+ },
1297
+ filesWritten: isProjectContext ? 4 : 2,
1298
+ propagation
1299
+ };
1300
+ }
1301
+
1302
+ // src/cli/lib/operations/project/compile-agents-all-scopes.ts
1303
+ import os4 from "os";
1304
+ async function compileAgentsAllScopes(options) {
1305
+ const { projectDir, sourcePath, skills, agentScopeMap } = options;
1306
+ const base = { sourcePath, skills, agentScopeMap };
1307
+ if (isHomeDirectory(projectDir)) {
1308
+ return compileAgents({
1309
+ ...base,
1310
+ projectDir,
1311
+ outputDir: resolveInstallPaths(projectDir, "project").agentsDir
1312
+ });
1313
+ }
1314
+ const globalResult = await compileAgents({
1315
+ ...base,
1316
+ projectDir: os4.homedir(),
1317
+ outputDir: resolveInstallPaths(os4.homedir(), "global").agentsDir,
1318
+ scopeFilter: "global"
1319
+ });
1320
+ const projectResult = await compileAgents({
1321
+ ...base,
1322
+ projectDir,
1323
+ outputDir: resolveInstallPaths(projectDir, "project").agentsDir,
1324
+ scopeFilter: "project"
1325
+ });
1326
+ return mergeCompilationResults(globalResult, projectResult);
1327
+ }
1328
+ function mergeCompilationResults(...results) {
1329
+ return {
1330
+ compiled: results.flatMap((r) => r.compiled),
1331
+ rewritten: results.flatMap((r) => r.rewritten),
1332
+ failed: results.flatMap((r) => r.failed),
1333
+ warnings: results.flatMap((r) => r.warnings)
1334
+ };
1335
+ }
1336
+
1337
+ export {
1338
+ loadSource,
1339
+ detectProject,
1340
+ detectBothInstallations,
1341
+ normalizeProjectPath,
1342
+ lazyGateDeps,
1343
+ reconcileTypesFromDisk,
1344
+ applyMigratedGlobalSources,
1345
+ mutateGlobal,
1346
+ propagateGlobalRemoval,
1347
+ ensureBlankPair2 as ensureBlankPair,
1348
+ writeProjectPartial,
1349
+ writeProjectConfig,
1350
+ compileAgentsAllScopes
1351
+ };
1352
+ //# sourceMappingURL=chunk-Z3H2K5PK.js.map