specweave 0.7.1 → 0.8.1

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 (132) hide show
  1. package/CLAUDE.md +307 -11
  2. package/README.md +41 -3
  3. package/dist/cli/commands/import-docs.d.ts +21 -0
  4. package/dist/cli/commands/import-docs.d.ts.map +1 -0
  5. package/dist/cli/commands/import-docs.js +146 -0
  6. package/dist/cli/commands/import-docs.js.map +1 -0
  7. package/dist/cli/commands/init-multiproject.d.ts +11 -0
  8. package/dist/cli/commands/init-multiproject.d.ts.map +1 -0
  9. package/dist/cli/commands/init-multiproject.js +202 -0
  10. package/dist/cli/commands/init-multiproject.js.map +1 -0
  11. package/dist/cli/commands/init.js +3 -3
  12. package/dist/cli/commands/init.js.map +1 -1
  13. package/dist/cli/commands/migrate-to-multiproject.d.ts +37 -0
  14. package/dist/cli/commands/migrate-to-multiproject.d.ts.map +1 -0
  15. package/dist/cli/commands/migrate-to-multiproject.js +189 -0
  16. package/dist/cli/commands/migrate-to-multiproject.js.map +1 -0
  17. package/dist/cli/commands/migrate-to-profiles.d.ts +25 -0
  18. package/dist/cli/commands/migrate-to-profiles.d.ts.map +1 -0
  19. package/dist/cli/commands/migrate-to-profiles.js +350 -0
  20. package/dist/cli/commands/migrate-to-profiles.js.map +1 -0
  21. package/dist/cli/commands/switch-project.d.ts +13 -0
  22. package/dist/cli/commands/switch-project.d.ts.map +1 -0
  23. package/dist/cli/commands/switch-project.js +91 -0
  24. package/dist/cli/commands/switch-project.js.map +1 -0
  25. package/dist/cli/helpers/issue-tracker/index.js +4 -4
  26. package/dist/cli/helpers/issue-tracker/index.js.map +1 -1
  27. package/dist/cli/helpers/issue-tracker/utils.d.ts +6 -3
  28. package/dist/cli/helpers/issue-tracker/utils.d.ts.map +1 -1
  29. package/dist/cli/helpers/issue-tracker/utils.js +9 -7
  30. package/dist/cli/helpers/issue-tracker/utils.js.map +1 -1
  31. package/dist/core/brownfield/analyzer.d.ts +86 -0
  32. package/dist/core/brownfield/analyzer.d.ts.map +1 -0
  33. package/dist/core/brownfield/analyzer.js +365 -0
  34. package/dist/core/brownfield/analyzer.js.map +1 -0
  35. package/dist/core/brownfield/importer.d.ts +76 -0
  36. package/dist/core/brownfield/importer.d.ts.map +1 -0
  37. package/dist/core/brownfield/importer.js +287 -0
  38. package/dist/core/brownfield/importer.js.map +1 -0
  39. package/dist/core/config-manager.d.ts +47 -0
  40. package/dist/core/config-manager.d.ts.map +1 -0
  41. package/dist/core/config-manager.js +136 -0
  42. package/dist/core/config-manager.js.map +1 -0
  43. package/dist/core/project-manager.d.ts +127 -0
  44. package/dist/core/project-manager.d.ts.map +1 -0
  45. package/dist/core/project-manager.js +524 -0
  46. package/dist/core/project-manager.js.map +1 -0
  47. package/dist/core/sync/profile-manager.d.ts +72 -0
  48. package/dist/core/sync/profile-manager.d.ts.map +1 -0
  49. package/dist/core/sync/profile-manager.js +338 -0
  50. package/dist/core/sync/profile-manager.js.map +1 -0
  51. package/dist/core/sync/profile-selector.d.ts +52 -0
  52. package/dist/core/sync/profile-selector.d.ts.map +1 -0
  53. package/dist/core/sync/profile-selector.js +179 -0
  54. package/dist/core/sync/profile-selector.js.map +1 -0
  55. package/dist/core/sync/project-context.d.ts +81 -0
  56. package/dist/core/sync/project-context.d.ts.map +1 -0
  57. package/dist/core/sync/project-context.js +354 -0
  58. package/dist/core/sync/project-context.js.map +1 -0
  59. package/dist/core/sync/rate-limiter.d.ts +116 -0
  60. package/dist/core/sync/rate-limiter.d.ts.map +1 -0
  61. package/dist/core/sync/rate-limiter.js +308 -0
  62. package/dist/core/sync/rate-limiter.js.map +1 -0
  63. package/dist/core/sync/time-range-selector.d.ts +48 -0
  64. package/dist/core/sync/time-range-selector.d.ts.map +1 -0
  65. package/dist/core/sync/time-range-selector.js +224 -0
  66. package/dist/core/sync/time-range-selector.js.map +1 -0
  67. package/dist/core/types/config.d.ts +4 -0
  68. package/dist/core/types/config.d.ts.map +1 -1
  69. package/dist/core/types/config.js.map +1 -1
  70. package/dist/core/types/sync-profile.d.ts +205 -0
  71. package/dist/core/types/sync-profile.d.ts.map +1 -0
  72. package/dist/core/types/sync-profile.js +8 -0
  73. package/dist/core/types/sync-profile.js.map +1 -0
  74. package/dist/utils/project-detection.d.ts +141 -0
  75. package/dist/utils/project-detection.d.ts.map +1 -0
  76. package/dist/utils/project-detection.js +321 -0
  77. package/dist/utils/project-detection.js.map +1 -0
  78. package/package.json +2 -1
  79. package/plugins/specweave/agents/pm/AGENT.md +7 -4
  80. package/plugins/specweave/commands/specweave-abandon.md +17 -17
  81. package/plugins/specweave/commands/specweave-check-tests.md +14 -14
  82. package/plugins/specweave/commands/specweave-costs.md +1 -1
  83. package/plugins/specweave/commands/specweave-do.md +12 -12
  84. package/plugins/specweave/commands/specweave-done.md +28 -15
  85. package/plugins/specweave/commands/specweave-import-docs.md +212 -0
  86. package/plugins/specweave/commands/specweave-increment.md +10 -10
  87. package/plugins/specweave/commands/specweave-init-multiproject.md +146 -0
  88. package/plugins/specweave/commands/specweave-next.md +16 -16
  89. package/plugins/specweave/commands/specweave-pause.md +17 -17
  90. package/plugins/specweave/commands/specweave-progress.md +10 -10
  91. package/plugins/specweave/commands/specweave-qa.md +11 -11
  92. package/plugins/specweave/commands/specweave-resume.md +22 -22
  93. package/plugins/specweave/commands/specweave-status.md +18 -18
  94. package/plugins/specweave/commands/specweave-switch-project.md +168 -0
  95. package/plugins/specweave/commands/specweave-sync-docs.md +1 -1
  96. package/plugins/specweave/commands/specweave-sync-tasks.md +9 -9
  97. package/plugins/specweave/commands/specweave-tdd-cycle.md +7 -0
  98. package/plugins/specweave/commands/specweave-tdd-green.md +7 -0
  99. package/plugins/specweave/commands/specweave-tdd-red.md +7 -0
  100. package/plugins/specweave/commands/specweave-tdd-refactor.md +7 -0
  101. package/plugins/specweave/commands/specweave-translate.md +1 -1
  102. package/plugins/specweave/commands/specweave-update-scope.md +8 -8
  103. package/plugins/specweave/commands/specweave-validate.md +18 -20
  104. package/plugins/specweave/commands/specweave.md +5 -5
  105. package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
  106. package/plugins/specweave/skills/increment-planner/SKILL.md +40 -4
  107. package/plugins/specweave/skills/increment-quality-judge/SKILL.md +5 -5
  108. package/plugins/specweave/skills/increment-quality-judge-v2/SKILL.md +5 -5
  109. package/plugins/specweave/skills/specweave-detector/SKILL.md +3 -3
  110. package/plugins/specweave-ado/commands/{close-workitem.md → specweave-ado-close-workitem.md} +1 -1
  111. package/plugins/specweave-ado/commands/{create-workitem.md → specweave-ado-create-workitem.md} +1 -1
  112. package/plugins/specweave-ado/commands/{status.md → specweave-ado-status.md} +1 -1
  113. package/plugins/specweave-ado/commands/{sync.md → specweave-ado-sync.md} +1 -1
  114. package/plugins/specweave-ado/lib/ado-client-v2.ts +547 -0
  115. package/plugins/specweave-github/commands/{close-issue.md → specweave-github-close-issue.md} +1 -1
  116. package/plugins/specweave-github/commands/{create-issue.md → specweave-github-create-issue.md} +1 -1
  117. package/plugins/specweave-github/commands/{status.md → specweave-github-status.md} +1 -1
  118. package/plugins/specweave-github/commands/{sync-tasks.md → specweave-github-sync-tasks.md} +1 -1
  119. package/plugins/specweave-github/commands/specweave-github-sync.md +568 -0
  120. package/plugins/specweave-github/lib/github-client-v2.ts +555 -0
  121. package/plugins/specweave-infrastructure/commands/{monitor-setup.md → specweave-infrastructure-monitor-setup.md} +1 -1
  122. package/plugins/specweave-infrastructure/commands/{slo-implement.md → specweave-infrastructure-slo-implement.md} +1 -1
  123. package/plugins/specweave-jira/commands/{sync.md → specweave-jira-sync.md} +1 -1
  124. package/plugins/specweave-jira/lib/jira-client-v2.ts +529 -0
  125. package/plugins/specweave-ml/commands/{ml-deploy.md → specweave-ml-deploy.md} +1 -1
  126. package/plugins/specweave-ml/commands/{ml-evaluate.md → specweave-ml-evaluate.md} +1 -1
  127. package/plugins/specweave-ml/commands/{ml-explain.md → specweave-ml-explain.md} +1 -1
  128. package/plugins/specweave-ml/commands/{ml-pipeline.md → specweave-ml-pipeline.md} +1 -1
  129. package/src/templates/AGENTS.md.template +1 -0
  130. package/src/templates/CLAUDE.md.template +1 -0
  131. package/plugins/specweave-github/commands/sync.md +0 -443
  132. /package/plugins/specweave/{commands/README.md → COMMANDS.md} +0 -0
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Profile Manager for Multi-Project Sync
3
+ *
4
+ * Manages sync profiles across multiple external projects (GitHub, JIRA, ADO).
5
+ * Handles CRUD operations, validation, and profile selection.
6
+ */
7
+ import * as fs from 'fs-extra';
8
+ import * as path from 'path';
9
+ export class ProfileManager {
10
+ constructor(projectRoot) {
11
+ this.config = null;
12
+ this.configPath = path.join(projectRoot, '.specweave', 'config.json');
13
+ }
14
+ // ==========================================================================
15
+ // Load/Save Operations
16
+ // ==========================================================================
17
+ /**
18
+ * Load sync configuration from disk
19
+ */
20
+ async load() {
21
+ if (this.config) {
22
+ return this.config;
23
+ }
24
+ try {
25
+ const content = await fs.readFile(this.configPath, 'utf-8');
26
+ const fullConfig = JSON.parse(content);
27
+ this.config = fullConfig.sync || {
28
+ profiles: {},
29
+ settings: {
30
+ autoDetectProject: true,
31
+ defaultTimeRange: '1M',
32
+ rateLimitProtection: true,
33
+ },
34
+ };
35
+ return this.config;
36
+ }
37
+ catch (error) {
38
+ if (error.code === 'ENOENT') {
39
+ // Config doesn't exist yet - return empty
40
+ this.config = {
41
+ profiles: {},
42
+ settings: {
43
+ autoDetectProject: true,
44
+ defaultTimeRange: '1M',
45
+ rateLimitProtection: true,
46
+ },
47
+ };
48
+ return this.config;
49
+ }
50
+ throw error;
51
+ }
52
+ }
53
+ /**
54
+ * Save sync configuration to disk
55
+ */
56
+ async save() {
57
+ if (!this.config) {
58
+ throw new Error('No configuration loaded. Call load() first.');
59
+ }
60
+ // Read full config
61
+ let fullConfig = {};
62
+ try {
63
+ const content = await fs.readFile(this.configPath, 'utf-8');
64
+ fullConfig = JSON.parse(content);
65
+ }
66
+ catch (error) {
67
+ if (error.code !== 'ENOENT') {
68
+ throw error;
69
+ }
70
+ }
71
+ // Merge sync section
72
+ fullConfig.sync = this.config;
73
+ // Write back
74
+ await fs.ensureDir(path.dirname(this.configPath));
75
+ await fs.writeFile(this.configPath, JSON.stringify(fullConfig, null, 2), 'utf-8');
76
+ }
77
+ // ==========================================================================
78
+ // Profile CRUD Operations
79
+ // ==========================================================================
80
+ /**
81
+ * Get all profiles
82
+ */
83
+ async getAllProfiles() {
84
+ const config = await this.load();
85
+ return config.profiles || {};
86
+ }
87
+ /**
88
+ * Get a specific profile by ID
89
+ */
90
+ async getProfile(profileId) {
91
+ const config = await this.load();
92
+ return config.profiles?.[profileId] || null;
93
+ }
94
+ /**
95
+ * Get active profile
96
+ */
97
+ async getActiveProfile() {
98
+ const config = await this.load();
99
+ const activeId = config.activeProfile;
100
+ if (!activeId) {
101
+ return null;
102
+ }
103
+ const profile = config.profiles?.[activeId];
104
+ if (!profile) {
105
+ return null;
106
+ }
107
+ return { id: activeId, profile };
108
+ }
109
+ /**
110
+ * Set active profile
111
+ */
112
+ async setActiveProfile(profileId) {
113
+ const config = await this.load();
114
+ // Validate profile exists
115
+ if (!config.profiles?.[profileId]) {
116
+ throw new Error(`Profile '${profileId}' does not exist`);
117
+ }
118
+ config.activeProfile = profileId;
119
+ await this.save();
120
+ }
121
+ /**
122
+ * Create a new profile
123
+ */
124
+ async createProfile(profileId, profile) {
125
+ const config = await this.load();
126
+ // Validate ID format
127
+ if (!/^[a-z0-9-]+$/.test(profileId)) {
128
+ throw new Error('Profile ID must contain only lowercase letters, numbers, and hyphens');
129
+ }
130
+ // Check if profile already exists
131
+ if (config.profiles?.[profileId]) {
132
+ throw new Error(`Profile '${profileId}' already exists`);
133
+ }
134
+ // Validate profile
135
+ const validation = this.validateProfile(profile);
136
+ if (!validation.valid) {
137
+ throw new Error(`Invalid profile: ${validation.errors.join(', ')}`);
138
+ }
139
+ // Add profile
140
+ if (!config.profiles) {
141
+ config.profiles = {};
142
+ }
143
+ config.profiles[profileId] = profile;
144
+ // Set as active if first profile
145
+ if (Object.keys(config.profiles).length === 1) {
146
+ config.activeProfile = profileId;
147
+ }
148
+ await this.save();
149
+ }
150
+ /**
151
+ * Update an existing profile
152
+ */
153
+ async updateProfile(profileId, updates) {
154
+ const config = await this.load();
155
+ const existing = config.profiles?.[profileId];
156
+ if (!existing) {
157
+ throw new Error(`Profile '${profileId}' does not exist`);
158
+ }
159
+ // Merge updates
160
+ const updated = { ...existing, ...updates };
161
+ // Validate updated profile
162
+ const validation = this.validateProfile(updated);
163
+ if (!validation.valid) {
164
+ throw new Error(`Invalid profile: ${validation.errors.join(', ')}`);
165
+ }
166
+ config.profiles[profileId] = updated;
167
+ await this.save();
168
+ }
169
+ /**
170
+ * Delete a profile
171
+ */
172
+ async deleteProfile(profileId) {
173
+ const config = await this.load();
174
+ if (!config.profiles?.[profileId]) {
175
+ throw new Error(`Profile '${profileId}' does not exist`);
176
+ }
177
+ delete config.profiles[profileId];
178
+ // If this was the active profile, clear it
179
+ if (config.activeProfile === profileId) {
180
+ config.activeProfile = undefined;
181
+ // Set first available profile as active
182
+ const remaining = Object.keys(config.profiles);
183
+ if (remaining.length > 0) {
184
+ config.activeProfile = remaining[0];
185
+ }
186
+ }
187
+ await this.save();
188
+ }
189
+ // ==========================================================================
190
+ // Profile Queries
191
+ // ==========================================================================
192
+ /**
193
+ * Get profiles by provider
194
+ */
195
+ async getProfilesByProvider(provider) {
196
+ const all = await this.getAllProfiles();
197
+ const filtered = {};
198
+ for (const [id, profile] of Object.entries(all)) {
199
+ if (profile.provider === provider) {
200
+ filtered[id] = profile;
201
+ }
202
+ }
203
+ return filtered;
204
+ }
205
+ /**
206
+ * Get profiles for a project
207
+ */
208
+ async getProfilesForProject(projectName) {
209
+ const all = await this.getAllProfiles();
210
+ const filtered = {};
211
+ const lowerName = projectName.toLowerCase();
212
+ for (const [id, profile] of Object.entries(all)) {
213
+ if (!profile.projectContext) {
214
+ continue;
215
+ }
216
+ // Match by name
217
+ if (profile.projectContext.name.toLowerCase() === lowerName) {
218
+ filtered[id] = profile;
219
+ continue;
220
+ }
221
+ // Match by keywords
222
+ if (profile.projectContext.keywords) {
223
+ for (const keyword of profile.projectContext.keywords) {
224
+ if (lowerName.includes(keyword.toLowerCase()) ||
225
+ keyword.toLowerCase().includes(lowerName)) {
226
+ filtered[id] = profile;
227
+ break;
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return filtered;
233
+ }
234
+ // ==========================================================================
235
+ // Validation
236
+ // ==========================================================================
237
+ /**
238
+ * Validate a sync profile
239
+ */
240
+ validateProfile(profile) {
241
+ const errors = [];
242
+ const warnings = [];
243
+ // Required fields
244
+ if (!profile.provider) {
245
+ errors.push('Provider is required');
246
+ }
247
+ else if (!['github', 'jira', 'ado'].includes(profile.provider)) {
248
+ errors.push(`Invalid provider: ${profile.provider}`);
249
+ }
250
+ if (!profile.displayName || profile.displayName.trim().length === 0) {
251
+ errors.push('Display name is required');
252
+ }
253
+ if (!profile.config) {
254
+ errors.push('Configuration is required');
255
+ }
256
+ else {
257
+ // Provider-specific validation
258
+ if (profile.provider === 'github') {
259
+ const config = profile.config;
260
+ if (!config.owner)
261
+ errors.push('GitHub owner is required');
262
+ if (!config.repo)
263
+ errors.push('GitHub repo is required');
264
+ }
265
+ else if (profile.provider === 'jira') {
266
+ const config = profile.config;
267
+ if (!config.domain)
268
+ errors.push('JIRA domain is required');
269
+ if (!config.projectKey)
270
+ errors.push('JIRA project key is required');
271
+ }
272
+ else if (profile.provider === 'ado') {
273
+ const config = profile.config;
274
+ if (!config.organization)
275
+ errors.push('ADO organization is required');
276
+ if (!config.project)
277
+ errors.push('ADO project is required');
278
+ }
279
+ }
280
+ if (!profile.timeRange) {
281
+ errors.push('Time range configuration is required');
282
+ }
283
+ else {
284
+ if (!profile.timeRange.default) {
285
+ errors.push('Default time range is required');
286
+ }
287
+ if (!profile.timeRange.max) {
288
+ errors.push('Maximum time range is required');
289
+ }
290
+ // Warn if max < default
291
+ if (profile.timeRange.max && profile.timeRange.default) {
292
+ const presets = ['1W', '2W', '1M', '3M', '6M', '1Y', 'ALL'];
293
+ const defaultIdx = presets.indexOf(profile.timeRange.default);
294
+ const maxIdx = presets.indexOf(profile.timeRange.max);
295
+ if (defaultIdx > maxIdx) {
296
+ warnings.push('Default time range should not exceed maximum time range');
297
+ }
298
+ }
299
+ }
300
+ // Warnings
301
+ if (!profile.projectContext) {
302
+ warnings.push('Project context is recommended for smart project detection');
303
+ }
304
+ if (profile.rateLimits &&
305
+ profile.rateLimits.maxItemsPerSync < profile.rateLimits.warnThreshold) {
306
+ warnings.push('Warn threshold should be less than max items per sync');
307
+ }
308
+ return {
309
+ valid: errors.length === 0,
310
+ errors,
311
+ warnings,
312
+ };
313
+ }
314
+ // ==========================================================================
315
+ // Statistics
316
+ // ==========================================================================
317
+ /**
318
+ * Get profile statistics
319
+ */
320
+ async getStats() {
321
+ const config = await this.load();
322
+ const all = config.profiles || {};
323
+ const stats = {
324
+ totalProfiles: Object.keys(all).length,
325
+ byProvider: {
326
+ github: 0,
327
+ jira: 0,
328
+ ado: 0,
329
+ },
330
+ activeProfile: config.activeProfile || null,
331
+ };
332
+ for (const profile of Object.values(all)) {
333
+ stats.byProvider[profile.provider]++;
334
+ }
335
+ return stats;
336
+ }
337
+ }
338
+ //# sourceMappingURL=profile-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-manager.js","sourceRoot":"","sources":["../../../src/core/sync/profile-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Interactive Profile Selector
3
+ *
4
+ * Rich CLI interface for selecting sync profiles with:
5
+ * - Profile listing by provider
6
+ * - Profile details and metadata
7
+ * - Smart filtering and search
8
+ * - Create new profile option
9
+ */
10
+ import { SyncProfile, SyncProvider } from '../types/sync-profile';
11
+ export declare class ProfileSelector {
12
+ private profileManager;
13
+ constructor(projectRoot: string);
14
+ /**
15
+ * Display all profiles grouped by provider
16
+ */
17
+ displayAllProfiles(): Promise<{
18
+ profiles: Record<string, SyncProfile>;
19
+ activeProfileId: string | null;
20
+ byProvider: Record<SyncProvider, ProfileOption[]>;
21
+ }>;
22
+ /**
23
+ * Display profiles for a specific provider
24
+ */
25
+ displayProfilesByProvider(provider: SyncProvider): Promise<ProfileOption[]>;
26
+ /**
27
+ * Format profile option for display
28
+ */
29
+ formatOption(option: ProfileOption, index: number): string[];
30
+ /**
31
+ * Format profile list header
32
+ */
33
+ formatHeader(provider?: SyncProvider): string[];
34
+ /**
35
+ * Format "no profiles" message
36
+ */
37
+ formatNoProfiles(provider?: SyncProvider): string[];
38
+ /**
39
+ * Display profile stats
40
+ */
41
+ displayStats(): Promise<string[]>;
42
+ private formatProfileDetails;
43
+ private getProviderIcon;
44
+ private getProviderDisplayName;
45
+ }
46
+ export interface ProfileOption {
47
+ id: string;
48
+ profile: SyncProfile;
49
+ isActive: boolean;
50
+ details: string;
51
+ }
52
+ //# sourceMappingURL=profile-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-selector.d.ts","sourceRoot":"","sources":["../../../src/core/sync/profile-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAMlE,qBAAa,eAAe;IAC1B,OAAO,CAAC,cAAc,CAAiB;gBAE3B,WAAW,EAAE,MAAM;IAQ/B;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC;QAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;KACnD,CAAC;IA4BF;;OAEG;IACG,yBAAyB,CAC7B,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC;IAkB3B;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAgC5D;;OAEG;IACH,YAAY,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,MAAM,EAAE;IAc/C;;OAEG;IACH,gBAAgB,CAAC,QAAQ,CAAC,EAAE,YAAY,GAAG,MAAM,EAAE;IAiBnD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAgCvC,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,sBAAsB;CAQ/B;AAMD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Interactive Profile Selector
3
+ *
4
+ * Rich CLI interface for selecting sync profiles with:
5
+ * - Profile listing by provider
6
+ * - Profile details and metadata
7
+ * - Smart filtering and search
8
+ * - Create new profile option
9
+ */
10
+ import { ProfileManager } from './profile-manager';
11
+ // ============================================================================
12
+ // Profile Selector
13
+ // ============================================================================
14
+ export class ProfileSelector {
15
+ constructor(projectRoot) {
16
+ this.profileManager = new ProfileManager(projectRoot);
17
+ }
18
+ // ==========================================================================
19
+ // Interactive Selection
20
+ // ==========================================================================
21
+ /**
22
+ * Display all profiles grouped by provider
23
+ */
24
+ async displayAllProfiles() {
25
+ const allProfiles = await this.profileManager.getAllProfiles();
26
+ const activeProfile = await this.profileManager.getActiveProfile();
27
+ const byProvider = {
28
+ github: [],
29
+ jira: [],
30
+ ado: [],
31
+ };
32
+ for (const [id, profile] of Object.entries(allProfiles)) {
33
+ const option = {
34
+ id,
35
+ profile,
36
+ isActive: activeProfile?.id === id,
37
+ details: this.formatProfileDetails(profile),
38
+ };
39
+ byProvider[profile.provider].push(option);
40
+ }
41
+ return {
42
+ profiles: allProfiles,
43
+ activeProfileId: activeProfile?.id || null,
44
+ byProvider,
45
+ };
46
+ }
47
+ /**
48
+ * Display profiles for a specific provider
49
+ */
50
+ async displayProfilesByProvider(provider) {
51
+ const profiles = await this.profileManager.getProfilesByProvider(provider);
52
+ const activeProfile = await this.profileManager.getActiveProfile();
53
+ const options = [];
54
+ for (const [id, profile] of Object.entries(profiles)) {
55
+ options.push({
56
+ id,
57
+ profile,
58
+ isActive: activeProfile?.id === id,
59
+ details: this.formatProfileDetails(profile),
60
+ });
61
+ }
62
+ return options;
63
+ }
64
+ /**
65
+ * Format profile option for display
66
+ */
67
+ formatOption(option, index) {
68
+ const lines = [];
69
+ // Profile name
70
+ const activeTag = option.isActive ? ' (active)' : '';
71
+ lines.push(` ${index + 1}. ${option.profile.displayName}${activeTag}`);
72
+ // Configuration details
73
+ lines.push(` └─ ${this.getProviderIcon(option.profile.provider)} ${option.details}`);
74
+ // Description (if present)
75
+ if (option.profile.description) {
76
+ lines.push(` └─ ${option.profile.description}`);
77
+ }
78
+ // Time range defaults
79
+ lines.push(` └─ Default time range: ${option.profile.timeRange.default} (max: ${option.profile.timeRange.max})`);
80
+ // Project context (if present)
81
+ if (option.profile.projectContext) {
82
+ lines.push(` └─ Project: ${option.profile.projectContext.name}`);
83
+ }
84
+ return lines;
85
+ }
86
+ /**
87
+ * Format profile list header
88
+ */
89
+ formatHeader(provider) {
90
+ const lines = [];
91
+ if (provider) {
92
+ lines.push(`🔗 ${this.getProviderDisplayName(provider)} Profiles:`);
93
+ }
94
+ else {
95
+ lines.push('🔗 Available Sync Profiles:');
96
+ }
97
+ lines.push('');
98
+ return lines;
99
+ }
100
+ /**
101
+ * Format "no profiles" message
102
+ */
103
+ formatNoProfiles(provider) {
104
+ const lines = [];
105
+ if (provider) {
106
+ lines.push(`No ${this.getProviderDisplayName(provider)} profiles configured yet.`);
107
+ }
108
+ else {
109
+ lines.push('No sync profiles configured yet.');
110
+ }
111
+ lines.push('');
112
+ lines.push('Create your first profile:');
113
+ lines.push(' /specweave:sync-profile create');
114
+ lines.push('');
115
+ return lines;
116
+ }
117
+ /**
118
+ * Display profile stats
119
+ */
120
+ async displayStats() {
121
+ const stats = await this.profileManager.getStats();
122
+ const lines = [];
123
+ lines.push('📊 Profile Statistics:');
124
+ lines.push('');
125
+ lines.push(` Total profiles: ${stats.totalProfiles}`);
126
+ if (stats.totalProfiles > 0) {
127
+ lines.push('');
128
+ lines.push(' By provider:');
129
+ for (const [provider, count] of Object.entries(stats.byProvider)) {
130
+ if (count > 0) {
131
+ lines.push(` ├─ ${this.getProviderIcon(provider)} ${this.getProviderDisplayName(provider)}: ${count}`);
132
+ }
133
+ }
134
+ }
135
+ if (stats.activeProfile) {
136
+ lines.push('');
137
+ lines.push(` Active profile: ${stats.activeProfile}`);
138
+ }
139
+ return lines;
140
+ }
141
+ // ==========================================================================
142
+ // Profile Details Formatting
143
+ // ==========================================================================
144
+ formatProfileDetails(profile) {
145
+ switch (profile.provider) {
146
+ case 'github': {
147
+ const config = profile.config;
148
+ return `GitHub: ${config.owner}/${config.repo}`;
149
+ }
150
+ case 'jira': {
151
+ const config = profile.config;
152
+ return `JIRA: ${config.domain} (${config.projectKey})`;
153
+ }
154
+ case 'ado': {
155
+ const config = profile.config;
156
+ return `Azure DevOps: ${config.organization}/${config.project}`;
157
+ }
158
+ default:
159
+ return 'Unknown provider';
160
+ }
161
+ }
162
+ getProviderIcon(provider) {
163
+ const icons = {
164
+ github: '🐙',
165
+ jira: '📋',
166
+ ado: '⚡',
167
+ };
168
+ return icons[provider] || '🔗';
169
+ }
170
+ getProviderDisplayName(provider) {
171
+ const names = {
172
+ github: 'GitHub',
173
+ jira: 'JIRA',
174
+ ado: 'Azure DevOps',
175
+ };
176
+ return names[provider] || provider;
177
+ }
178
+ }
179
+ //# sourceMappingURL=profile-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-selector.js","sourceRoot":"","sources":["../../../src/core/sync/profile-selector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Project Context Manager
3
+ *
4
+ * Manages project contexts for multi-project sync.
5
+ * Handles project detection, specs folder organization, and project-increment mapping.
6
+ */
7
+ import { ProjectContext, ProjectDetectionResult, SyncConfiguration } from '../types/sync-profile';
8
+ export declare class ProjectContextManager {
9
+ private configPath;
10
+ private projectRoot;
11
+ private config;
12
+ constructor(projectRoot: string);
13
+ /**
14
+ * Load sync configuration
15
+ */
16
+ load(): Promise<SyncConfiguration>;
17
+ /**
18
+ * Save sync configuration
19
+ */
20
+ save(): Promise<void>;
21
+ /**
22
+ * Get all projects
23
+ */
24
+ getAllProjects(): Promise<Record<string, ProjectContext>>;
25
+ /**
26
+ * Get a specific project by ID
27
+ */
28
+ getProject(projectId: string): Promise<ProjectContext | null>;
29
+ /**
30
+ * Create a new project context
31
+ */
32
+ createProject(projectId: string, project: Omit<ProjectContext, 'id'>): Promise<void>;
33
+ /**
34
+ * Update a project context
35
+ */
36
+ updateProject(projectId: string, updates: Partial<Omit<ProjectContext, 'id'>>): Promise<void>;
37
+ /**
38
+ * Delete a project context
39
+ */
40
+ deleteProject(projectId: string, deleteSpecs?: boolean): Promise<void>;
41
+ /**
42
+ * Detect project from increment description
43
+ *
44
+ * @param description Increment description text
45
+ * @returns Detection result with matched project and confidence score
46
+ */
47
+ detectProject(description: string): Promise<ProjectDetectionResult>;
48
+ /**
49
+ * Link increment to project
50
+ */
51
+ linkIncrementToProject(projectId: string, incrementId: string): Promise<void>;
52
+ /**
53
+ * Unlink increment from project
54
+ */
55
+ unlinkIncrementFromProject(projectId: string, incrementId: string): Promise<void>;
56
+ /**
57
+ * Get specs folder path for a project
58
+ */
59
+ getSpecsFolder(projectId: string): string;
60
+ /**
61
+ * Ensure specs folder exists for a project
62
+ */
63
+ ensureSpecsFolder(projectId: string): Promise<string>;
64
+ /**
65
+ * Get all spec files for a project
66
+ */
67
+ getProjectSpecs(projectId: string): Promise<string[]>;
68
+ /**
69
+ * Generate README for project specs folder
70
+ */
71
+ private generateProjectReadme;
72
+ /**
73
+ * Get statistics about projects
74
+ */
75
+ getStats(): Promise<{
76
+ totalProjects: number;
77
+ totalIncrements: number;
78
+ projectsByTeam: Record<string, number>;
79
+ }>;
80
+ }
81
+ //# sourceMappingURL=project-context.d.ts.map