specweave 0.28.20 → 0.28.24

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 (47) hide show
  1. package/dist/src/cli/commands/init.d.ts.map +1 -1
  2. package/dist/src/cli/commands/init.js +7 -3
  3. package/dist/src/cli/commands/init.js.map +1 -1
  4. package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
  5. package/dist/src/cli/helpers/init/external-import.js +8 -5
  6. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  7. package/dist/src/cli/helpers/init/initial-increment-generator.d.ts.map +1 -1
  8. package/dist/src/cli/helpers/init/initial-increment-generator.js +123 -35
  9. package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
  10. package/dist/src/cli/helpers/init/language-selection.js +1 -1
  11. package/dist/src/cli/helpers/init/language-selection.js.map +1 -1
  12. package/dist/src/cli/helpers/init/next-steps.d.ts.map +1 -1
  13. package/dist/src/cli/helpers/init/next-steps.js +16 -47
  14. package/dist/src/cli/helpers/init/next-steps.js.map +1 -1
  15. package/dist/src/cli/helpers/init/repository-setup.js +1 -1
  16. package/dist/src/cli/helpers/init/repository-setup.js.map +1 -1
  17. package/dist/src/core/repo-structure/prompt-consolidator.d.ts.map +1 -1
  18. package/dist/src/core/repo-structure/prompt-consolidator.js +6 -36
  19. package/dist/src/core/repo-structure/prompt-consolidator.js.map +1 -1
  20. package/dist/src/core/repo-structure/repo-initializer.d.ts.map +1 -1
  21. package/dist/src/core/repo-structure/repo-initializer.js +8 -0
  22. package/dist/src/core/repo-structure/repo-initializer.js.map +1 -1
  23. package/dist/src/core/sync/bidirectional-engine.d.ts.map +1 -1
  24. package/dist/src/core/sync/bidirectional-engine.js +3 -1
  25. package/dist/src/core/sync/bidirectional-engine.js.map +1 -1
  26. package/dist/src/importers/import-coordinator.d.ts.map +1 -1
  27. package/dist/src/importers/import-coordinator.js +17 -0
  28. package/dist/src/importers/import-coordinator.js.map +1 -1
  29. package/dist/src/init/repo/types.d.ts +1 -1
  30. package/dist/src/utils/multi-project-detector.d.ts +92 -0
  31. package/dist/src/utils/multi-project-detector.d.ts.map +1 -0
  32. package/dist/src/utils/multi-project-detector.js +369 -0
  33. package/dist/src/utils/multi-project-detector.js.map +1 -0
  34. package/package.json +1 -1
  35. package/plugins/specweave/agents/pm/AGENT.md +33 -12
  36. package/plugins/specweave/commands/specweave-import-external.md +1 -1
  37. package/plugins/specweave/commands/specweave.md +1 -1
  38. package/plugins/specweave/skills/increment-planner/SKILL.md +6 -13
  39. package/plugins/specweave/skills/spec-generator/SKILL.md +6 -11
  40. package/plugins/specweave-ado/commands/specweave-ado-sync.md +12 -12
  41. package/plugins/specweave-github/agents/github-manager/AGENT.md +5 -5
  42. package/plugins/specweave-github/commands/specweave-github-sync.md +12 -12
  43. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
  44. package/plugins/specweave-github/skills/github-sync/SKILL.md +4 -4
  45. package/plugins/specweave-jira/commands/specweave-jira-sync.md +11 -11
  46. package/plugins/specweave-jira/skills/specweave-jira-mapper/SKILL.md +2 -2
  47. package/plugins/specweave-release/commands/specweave-release-npm.md +187 -8
@@ -0,0 +1,369 @@
1
+ /**
2
+ * Multi-Project Detector
3
+ *
4
+ * Detects multi-project/umbrella configuration from:
5
+ * 1. config.json (umbrella.enabled, multiProject.enabled)
6
+ * 2. childRepos configuration
7
+ * 3. Project folders in specs/
8
+ * 4. Sync profile projects
9
+ *
10
+ * Used by PM Agent, spec generators, and initial-increment-generator
11
+ * to determine whether to generate project-scoped user stories.
12
+ *
13
+ * @module utils/multi-project-detector
14
+ */
15
+ import * as fs from './fs-native.js';
16
+ import path from 'path';
17
+ /**
18
+ * Default project prefixes for common architectures
19
+ */
20
+ const DEFAULT_PROJECT_PREFIXES = {
21
+ 'fe': 'FE',
22
+ 'frontend': 'FE',
23
+ 'web': 'FE',
24
+ 'ui': 'FE',
25
+ 'client': 'FE',
26
+ 'be': 'BE',
27
+ 'backend': 'BE',
28
+ 'api': 'BE',
29
+ 'server': 'BE',
30
+ 'service': 'BE',
31
+ 'shared': 'SHARED',
32
+ 'common': 'SHARED',
33
+ 'lib': 'SHARED',
34
+ 'types': 'SHARED',
35
+ 'mobile': 'MOBILE',
36
+ 'ios': 'MOBILE',
37
+ 'android': 'MOBILE',
38
+ 'app': 'MOBILE',
39
+ 'infra': 'INFRA',
40
+ 'infrastructure': 'INFRA',
41
+ 'devops': 'INFRA',
42
+ 'deploy': 'INFRA',
43
+ };
44
+ /**
45
+ * Infer project prefix from project ID/name
46
+ */
47
+ export function inferProjectPrefix(projectId) {
48
+ const normalizedId = projectId.toLowerCase();
49
+ // Check for exact matches first
50
+ if (DEFAULT_PROJECT_PREFIXES[normalizedId]) {
51
+ return DEFAULT_PROJECT_PREFIXES[normalizedId];
52
+ }
53
+ // Check for suffix matches (e.g., 'my-app-fe' → 'FE')
54
+ for (const [key, prefix] of Object.entries(DEFAULT_PROJECT_PREFIXES)) {
55
+ if (normalizedId.endsWith(`-${key}`) || normalizedId.endsWith(`_${key}`)) {
56
+ return prefix;
57
+ }
58
+ }
59
+ // Check for contains (e.g., 'frontend-service' → 'FE')
60
+ for (const [key, prefix] of Object.entries(DEFAULT_PROJECT_PREFIXES)) {
61
+ if (normalizedId.includes(key)) {
62
+ return prefix;
63
+ }
64
+ }
65
+ // Default: uppercase first part of ID
66
+ const parts = projectId.split(/[-_]/);
67
+ return parts[0].toUpperCase().slice(0, 6);
68
+ }
69
+ /**
70
+ * Parse project configuration from childRepos
71
+ */
72
+ function parseChildRepos(childRepos) {
73
+ const projects = [];
74
+ for (const repo of childRepos) {
75
+ if (!repo.id)
76
+ continue;
77
+ projects.push({
78
+ id: repo.id,
79
+ prefix: repo.prefix || inferProjectPrefix(repo.id),
80
+ name: repo.displayName || repo.id,
81
+ path: repo.path
82
+ });
83
+ }
84
+ return projects;
85
+ }
86
+ /**
87
+ * Parse project configuration from multiProject.projects
88
+ */
89
+ function parseMultiProjectConfig(projectsConfig) {
90
+ const projects = [];
91
+ for (const [id, config] of Object.entries(projectsConfig)) {
92
+ if (typeof config !== 'object')
93
+ continue;
94
+ projects.push({
95
+ id: id,
96
+ prefix: config.prefix || inferProjectPrefix(id),
97
+ name: config.name || config.displayName || id,
98
+ path: config.path
99
+ });
100
+ }
101
+ return projects;
102
+ }
103
+ /**
104
+ * Detect projects from specs folder structure
105
+ */
106
+ function detectProjectsFromFolders(specsPath) {
107
+ const projects = [];
108
+ if (!fs.existsSync(specsPath)) {
109
+ return projects;
110
+ }
111
+ try {
112
+ const entries = fs.readdirSync(specsPath, { withFileTypes: true });
113
+ for (const entry of entries) {
114
+ // Skip non-directories and special folders
115
+ if (!entry.isDirectory())
116
+ continue;
117
+ if (entry.name.startsWith('.') || entry.name.startsWith('_'))
118
+ continue;
119
+ if (entry.name === 'default')
120
+ continue;
121
+ projects.push({
122
+ id: entry.name,
123
+ prefix: inferProjectPrefix(entry.name),
124
+ name: entry.name,
125
+ path: path.join(specsPath, entry.name)
126
+ });
127
+ }
128
+ }
129
+ catch {
130
+ // Ignore read errors
131
+ }
132
+ return projects;
133
+ }
134
+ /**
135
+ * Parse projects from sync profile configuration
136
+ */
137
+ function parseProjectsFromSyncProfiles(syncConfig) {
138
+ const projects = [];
139
+ const seenIds = new Set();
140
+ if (!syncConfig?.profiles)
141
+ return projects;
142
+ for (const [, profile] of Object.entries(syncConfig.profiles)) {
143
+ const profileConfig = profile?.config;
144
+ if (!profileConfig)
145
+ continue;
146
+ // Check for boardMapping (JIRA)
147
+ if (profileConfig.boardMapping) {
148
+ for (const [boardName, projectId] of Object.entries(profileConfig.boardMapping)) {
149
+ const id = String(projectId);
150
+ if (seenIds.has(id))
151
+ continue;
152
+ seenIds.add(id);
153
+ projects.push({
154
+ id: id,
155
+ prefix: inferProjectPrefix(id),
156
+ name: boardName || id
157
+ });
158
+ }
159
+ }
160
+ // Check for areaPathMapping (ADO)
161
+ if (profileConfig.areaPathMapping) {
162
+ for (const [areaPath, projectId] of Object.entries(profileConfig.areaPathMapping)) {
163
+ const id = String(projectId);
164
+ if (seenIds.has(id))
165
+ continue;
166
+ seenIds.add(id);
167
+ projects.push({
168
+ id: id,
169
+ prefix: inferProjectPrefix(id),
170
+ name: areaPath.split('\\').pop() || id
171
+ });
172
+ }
173
+ }
174
+ // Check for projects array
175
+ if (profileConfig.projects && Array.isArray(profileConfig.projects)) {
176
+ for (const projectId of profileConfig.projects) {
177
+ const id = String(projectId);
178
+ if (seenIds.has(id))
179
+ continue;
180
+ seenIds.add(id);
181
+ projects.push({
182
+ id: id,
183
+ prefix: inferProjectPrefix(id),
184
+ name: id
185
+ });
186
+ }
187
+ }
188
+ }
189
+ return projects;
190
+ }
191
+ /**
192
+ * Detect multi-project configuration
193
+ *
194
+ * @param projectRoot - Path to project root (default: process.cwd())
195
+ * @returns Detection result with project information
196
+ */
197
+ export function detectMultiProjectMode(projectRoot = process.cwd()) {
198
+ const configPath = path.join(projectRoot, '.specweave', 'config.json');
199
+ const specsPath = path.join(projectRoot, '.specweave', 'docs', 'internal', 'specs');
200
+ let config = {};
201
+ // Read config.json if exists
202
+ if (fs.existsSync(configPath)) {
203
+ try {
204
+ config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
205
+ }
206
+ catch {
207
+ // Ignore parse errors
208
+ }
209
+ }
210
+ // Check 1: umbrella.enabled with 2+ child repos
211
+ if (config.umbrella?.enabled === true) {
212
+ const projects = config.umbrella?.childRepos
213
+ ? parseChildRepos(config.umbrella.childRepos)
214
+ : [];
215
+ // Multi-project requires 2+ projects (1 project = single-project mode)
216
+ if (projects.length > 1) {
217
+ return {
218
+ isMultiProject: true,
219
+ detectionReason: 'umbrella.enabled with childRepos',
220
+ projects,
221
+ umbrellaEnabled: true,
222
+ hasBoardMapping: false
223
+ };
224
+ }
225
+ }
226
+ // Check 2: multiProject.enabled with 2+ projects
227
+ if (config.multiProject?.enabled === true) {
228
+ const projects = config.multiProject?.projects
229
+ ? parseMultiProjectConfig(config.multiProject.projects)
230
+ : [];
231
+ // Multi-project requires 2+ projects (1 project = single-project mode)
232
+ if (projects.length > 1) {
233
+ return {
234
+ isMultiProject: true,
235
+ detectionReason: 'multiProject.enabled with projects config',
236
+ projects,
237
+ umbrellaEnabled: false,
238
+ hasBoardMapping: false
239
+ };
240
+ }
241
+ }
242
+ // Check 3: Sync profile with board/area path mapping
243
+ if (config.sync?.profiles) {
244
+ const syncProjects = parseProjectsFromSyncProfiles(config.sync);
245
+ const hasBoardMapping = Object.values(config.sync.profiles).some((p) => p?.config?.boardMapping || p?.config?.areaPathMapping);
246
+ if (syncProjects.length > 1) {
247
+ return {
248
+ isMultiProject: true,
249
+ detectionReason: 'sync profiles with multiple projects',
250
+ projects: syncProjects,
251
+ umbrellaEnabled: false,
252
+ hasBoardMapping
253
+ };
254
+ }
255
+ }
256
+ // Check 4: Multiple project folders in specs/
257
+ const folderProjects = detectProjectsFromFolders(specsPath);
258
+ if (folderProjects.length > 1) {
259
+ return {
260
+ isMultiProject: true,
261
+ detectionReason: 'multiple project folders in specs/',
262
+ projects: folderProjects,
263
+ umbrellaEnabled: false,
264
+ hasBoardMapping: false
265
+ };
266
+ }
267
+ // Single project mode
268
+ return {
269
+ isMultiProject: false,
270
+ detectionReason: 'no multi-project configuration detected',
271
+ projects: [],
272
+ umbrellaEnabled: false,
273
+ hasBoardMapping: false
274
+ };
275
+ }
276
+ /**
277
+ * Get project prefixes for user story generation
278
+ *
279
+ * @param projectRoot - Path to project root
280
+ * @returns Array of project prefixes (e.g., ['FE', 'BE', 'SHARED'])
281
+ */
282
+ export function getProjectPrefixes(projectRoot = process.cwd()) {
283
+ const detection = detectMultiProjectMode(projectRoot);
284
+ if (!detection.isMultiProject || detection.projects.length === 0) {
285
+ return [];
286
+ }
287
+ return detection.projects.map(p => p.prefix);
288
+ }
289
+ /**
290
+ * Get project by prefix
291
+ *
292
+ * @param prefix - Project prefix (e.g., 'FE')
293
+ * @param projectRoot - Path to project root
294
+ * @returns Project or undefined
295
+ */
296
+ export function getProjectByPrefix(prefix, projectRoot = process.cwd()) {
297
+ const detection = detectMultiProjectMode(projectRoot);
298
+ return detection.projects.find(p => p.prefix.toUpperCase() === prefix.toUpperCase());
299
+ }
300
+ /**
301
+ * Format user story ID with project prefix (if multi-project)
302
+ *
303
+ * @param storyNumber - Story number (1, 2, 3...)
304
+ * @param projectPrefix - Optional project prefix (e.g., 'FE')
305
+ * @param projectRoot - Path to project root
306
+ * @returns Formatted ID (e.g., 'US-FE-001' or 'US-001')
307
+ */
308
+ export function formatUserStoryId(storyNumber, projectPrefix, projectRoot = process.cwd()) {
309
+ const paddedNumber = String(storyNumber).padStart(3, '0');
310
+ if (projectPrefix) {
311
+ return `US-${projectPrefix.toUpperCase()}-${paddedNumber}`;
312
+ }
313
+ // Auto-detect if multi-project
314
+ const detection = detectMultiProjectMode(projectRoot);
315
+ if (detection.isMultiProject) {
316
+ // If multi-project but no prefix provided, use generic format
317
+ // (caller should provide prefix for proper scoping)
318
+ return `US-${paddedNumber}`;
319
+ }
320
+ return `US-${paddedNumber}`;
321
+ }
322
+ /**
323
+ * Format acceptance criteria ID with project prefix (if multi-project)
324
+ *
325
+ * @param userStoryNumber - User story number (1, 2, 3...)
326
+ * @param acNumber - Acceptance criteria number within story (1, 2, 3...)
327
+ * @param projectPrefix - Optional project prefix (e.g., 'FE')
328
+ * @returns Formatted ID (e.g., 'AC-FE-US1-01' or 'AC-US1-01')
329
+ */
330
+ export function formatAcceptanceCriteriaId(userStoryNumber, acNumber, projectPrefix) {
331
+ const paddedAcNumber = String(acNumber).padStart(2, '0');
332
+ if (projectPrefix) {
333
+ return `AC-${projectPrefix.toUpperCase()}-US${userStoryNumber}-${paddedAcNumber}`;
334
+ }
335
+ return `AC-US${userStoryNumber}-${paddedAcNumber}`;
336
+ }
337
+ /**
338
+ * Generate template variables for multi-project spec
339
+ *
340
+ * @param detection - Multi-project detection result
341
+ * @returns Template variable map
342
+ */
343
+ export function generateMultiProjectTemplateVars(detection) {
344
+ const vars = {
345
+ MULTI_PROJECT: detection.isMultiProject ? 'true' : 'false'
346
+ };
347
+ if (!detection.isMultiProject) {
348
+ return vars;
349
+ }
350
+ // Add project-specific variables
351
+ for (const project of detection.projects) {
352
+ const prefixUpper = project.prefix.toUpperCase();
353
+ vars[`PROJECT_${prefixUpper}_ID`] = project.id;
354
+ vars[`PROJECT_${prefixUpper}_PREFIX`] = project.prefix;
355
+ vars[`PROJECT_${prefixUpper}_NAME`] = project.name;
356
+ }
357
+ // Add common project IDs for templates
358
+ const feProject = detection.projects.find(p => p.prefix.toUpperCase() === 'FE');
359
+ const beProject = detection.projects.find(p => p.prefix.toUpperCase() === 'BE');
360
+ const sharedProject = detection.projects.find(p => p.prefix.toUpperCase() === 'SHARED' || p.prefix.toUpperCase() === 'COMMON');
361
+ if (feProject)
362
+ vars.PROJECT_FE_ID = feProject.id;
363
+ if (beProject)
364
+ vars.PROJECT_BE_ID = beProject.id;
365
+ if (sharedProject)
366
+ vars.PROJECT_SHARED_ID = sharedProject.id;
367
+ return vars;
368
+ }
369
+ //# sourceMappingURL=multi-project-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-project-detector.js","sourceRoot":"","sources":["../../../src/utils/multi-project-detector.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "0.28.20",
3
+ "version": "0.28.24",
4
4
  "description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -445,24 +445,44 @@ graph TD
445
445
 
446
446
  **YOU MUST CHECK THIS BEFORE WRITING ANY USER STORIES:**
447
447
 
448
- ```bash
449
- # 1. Check config.json for umbrella mode
450
- cat .specweave/config.json | jq '.umbrella.enabled'
448
+ **Detection Utility** (`src/utils/multi-project-detector.ts`): SpecWeave has automated multi-project detection. When generating specs programmatically, use `detectMultiProjectMode(projectRoot)`. For manual checks, run these commands:
451
449
 
452
- # 2. Check for childRepos
453
- cat .specweave/config.json | jq '.umbrella.childRepos[]'
450
+ ```bash
451
+ # Quick check: Is multi-project mode enabled?
452
+ Read .specweave/config.json and check for:
453
+ # - umbrella.enabled: true
454
+ # - multiProject.enabled: true
455
+ # - umbrella.childRepos[] (array of repos)
456
+ # - sync.profiles[].config.boardMapping or areaPathMapping
454
457
 
455
- # 3. Check for project folders
456
- ls -la .specweave/docs/internal/specs/
458
+ # Alternative: Check for multiple project folders
459
+ Glob ".specweave/docs/internal/specs/*/" and count directories
460
+ # If > 1 directory (excluding 'default') → multi-project mode
457
461
  ```
458
462
 
459
463
  **Decision Flow:**
460
464
  ```
461
- Is umbrella.enabled: true?
462
- YES MUST use project-scoped user stories (US-FE-001, US-BE-001)
463
- NO Check for multiple project folders in specs/
464
- → YES → MUST use project-scoped user stories
465
- NO Use standard user stories (US-001, US-002)
465
+ Step 1: Read .specweave/config.json
466
+ Step 2: Check THESE conditions (ANY = multi-project):
467
+ ├─ umbrella.enabled === true AND childRepos.length > 0?
468
+ → YES → Use project prefixes from childRepos[].prefix
469
+ ├─ multiProject.enabled === true AND projects object has keys?
470
+ │ → YES → Use project prefixes from projects object
471
+ ├─ sync.profiles[].config.boardMapping exists?
472
+ │ → YES → Use project IDs from boardMapping values
473
+ ├─ Multiple folders in .specweave/docs/internal/specs/?
474
+ │ → YES → Use folder names as project IDs
475
+ └─ User prompt mentions "frontend", "backend", "3 repos"?
476
+ → YES → Ask user to confirm project prefixes
477
+
478
+ Step 3: If multi-project detected:
479
+ → MUST use project-scoped user stories (US-FE-001, US-BE-001)
480
+ → MUST use project-scoped ACs (AC-FE-US1-01, AC-BE-US1-01)
481
+ → Include 'projects:' array in spec.md frontmatter
482
+
483
+ Step 4: If NO multi-project config:
484
+ → Use standard user stories (US-001, US-002)
485
+ → Use standard ACs (AC-US1-01, AC-US2-01)
466
486
  ```
467
487
 
468
488
  **If multi-project detected, NEVER generate:**
@@ -472,6 +492,7 @@ Is umbrella.enabled: true?
472
492
  **ALWAYS generate:**
473
493
  - ✅ `US-FE-001`, `US-BE-001`, `US-SHARED-001` (project-scoped)
474
494
  - ✅ `AC-FE-US1-01`, `AC-BE-US1-01` (project-scoped ACs)
495
+ - ✅ Frontmatter with `multi_project: true` and `projects:` array
475
496
 
476
497
  ---
477
498
 
@@ -347,7 +347,7 @@ No tasks defined.
347
347
  - **NO automatic increment creation**: Imported items live in living docs ONLY
348
348
  - User must manually create increment when ready to work on external item
349
349
  - **Read-only snapshot**: External items are imported as static snapshots
350
- - No bidirectional sync (external tool → SpecWeave only)
350
+ - No two-way sync (external tool → SpecWeave only)
351
351
  - **Pagination**: Large imports (500+ items) may take several minutes
352
352
  - **API quota**: Uses GitHub/JIRA/ADO API quota
353
353
  - GitHub: 5000 requests/hour (authenticated)
@@ -43,7 +43,7 @@ Claude Code does not support command routing. Each command must be invoked direc
43
43
  | Command | Description | Example |
44
44
  |---------|-------------|---------|
45
45
  | `/specweave-github:create-issue` | Create GitHub issue | `/specweave-github:create-issue 0031` |
46
- | `/specweave-github:sync` | Bidirectional sync | `/specweave-github:sync 0031` |
46
+ | `/specweave-github:sync` | Two-way sync | `/specweave-github:sync 0031` |
47
47
  | `/specweave-github:sync-tasks` | Sync tasks as sub-issues | `/specweave-github:sync-tasks 0031` |
48
48
  | `/specweave-github:close-issue` | Close GitHub issue | `/specweave-github:close-issue 0031` |
49
49
  | `/specweave-github:status` | Show sync status | `/specweave-github:status` |
@@ -134,20 +134,13 @@ Every increment MUST have `metadata.json` or:
134
134
 
135
135
  **⚠️ CRITICAL: Before creating ANY user stories, detect if this is a multi-project (umbrella) setup!**
136
136
 
137
- ```bash
138
- # 1. Check config.json for umbrella mode
139
- UMBRELLA_ENABLED=$(cat .specweave/config.json 2>/dev/null | jq -r '.umbrella.enabled // false')
140
-
141
- # 2. Check for childRepos
142
- CHILD_REPOS=$(cat .specweave/config.json 2>/dev/null | jq -r '.umbrella.childRepos[]?.id // empty' | tr '\n' ',')
137
+ **Automated Detection**: `src/utils/multi-project-detector.ts` provides `detectMultiProjectMode(projectRoot)` which checks ALL config formats and returns `{ isMultiProject, projects, detectionReason }`.
143
138
 
144
- # 3. Check for project folders in specs/
145
- PROJECT_FOLDERS=$(ls -1 .specweave/docs/internal/specs/ 2>/dev/null | grep -v "^_" | head -5)
146
-
147
- echo "Multi-project mode: $UMBRELLA_ENABLED"
148
- echo "Child repos: $CHILD_REPOS"
149
- echo "Project folders: $PROJECT_FOLDERS"
150
- ```
139
+ **Manual check (for agents)**: Read `.specweave/config.json` and check:
140
+ - `umbrella.enabled: true` with `childRepos[]`
141
+ - `multiProject.enabled: true` with `projects{}`
142
+ - `sync.profiles[].config.boardMapping` exists
143
+ - Multiple folders in `.specweave/docs/internal/specs/`
151
144
 
152
145
  **If multi-project detected (`umbrella.enabled: true` OR multiple project folders exist):**
153
146
  - ✅ **MUST** generate project-scoped user stories: `US-FE-001`, `US-BE-001`, `US-SHARED-001`
@@ -360,18 +360,13 @@ spec_generator:
360
360
 
361
361
  ### Detection (MANDATORY FIRST STEP)
362
362
 
363
- **Before generating spec.md, ALWAYS check for multi-project mode:**
363
+ **Automated Detection**: Use `detectMultiProjectMode(projectRoot)` from `src/utils/multi-project-detector.ts`. This utility checks ALL config formats automatically.
364
364
 
365
- ```bash
366
- # 1. Check config.json for umbrella mode
367
- cat .specweave/config.json | jq '.umbrella.enabled'
368
-
369
- # 2. Check for childRepos configuration
370
- cat .specweave/config.json | jq '.umbrella.childRepos[]'
371
-
372
- # 3. Check for project folders in specs/
373
- ls -la .specweave/docs/internal/specs/
374
- ```
365
+ **Manual check (for agents)**: Read `.specweave/config.json` and check:
366
+ - `umbrella.enabled` + `childRepos[]`
367
+ - `multiProject.enabled` + `projects{}`
368
+ - `sync.profiles[].config.boardMapping`
369
+ - Multiple folders in `.specweave/docs/internal/specs/`
375
370
 
376
371
  **If ANY of these conditions are TRUE → Multi-project mode ACTIVE:**
377
372
  - `umbrella.enabled: true` in config.json
@@ -1,29 +1,29 @@
1
1
  ---
2
2
  name: specweave-ado:sync
3
- description: Bidirectional sync between SpecWeave increment and Azure DevOps work item (two-way sync by default)
3
+ description: Two-way sync between SpecWeave increment and Azure DevOps work item (push & pull by default)
4
4
  ---
5
5
 
6
6
  # Sync ADO Work Item Command
7
7
 
8
8
  **Usage**: `/specweave-ado:sync <increment-id> [options]`
9
9
 
10
- **Purpose**: Bidirectional synchronization between SpecWeave increment and Azure DevOps work item
10
+ **Purpose**: Two-way synchronization between SpecWeave increment and Azure DevOps work item
11
11
 
12
- **Default**: Two-way sync (bidirectional)
12
+ **Default**: Two-way sync (push & pull)
13
13
 
14
14
  ---
15
15
 
16
16
  ## Options
17
17
 
18
- - `--direction <mode>`: Sync direction (default: `bidirectional`)
19
- - `bidirectional`: SpecWeave ↔ ADO (default - recommended)
18
+ - `--direction <mode>`: Sync direction (default: `two-way`)
19
+ - `two-way`: SpecWeave ↔ ADO (default - recommended)
20
20
  - `to-ado`: SpecWeave → ADO only (push progress)
21
21
  - `from-ado`: ADO → SpecWeave only (pull updates)
22
22
 
23
23
  ## Examples
24
24
 
25
25
  ```bash
26
- # Bidirectional sync (default - two-way)
26
+ # Two-way sync (default - both directions)
27
27
  /specweave-ado:sync 0005
28
28
 
29
29
  # Push only (one-way to ADO)
@@ -37,7 +37,7 @@ description: Bidirectional sync between SpecWeave increment and Azure DevOps wor
37
37
 
38
38
  ## Command Behavior
39
39
 
40
- When user runs this command, invoke `ado-manager` agent to perform bidirectional sync:
40
+ When user runs this command, invoke `ado-manager` agent to perform two-way sync:
41
41
 
42
42
  ### Phase 1: Pull FROM ADO (default behavior)
43
43
  1. Fetch work item state from ADO API
@@ -66,7 +66,7 @@ When user runs this command, invoke `ado-manager` agent to perform bidirectional
66
66
  ```
67
67
  Use Task tool with subagent_type: "specweave-ado:ado-manager:ado-manager"
68
68
 
69
- Prompt: "Bidirectional sync for increment 0005-payment-integration with ADO.
69
+ Prompt: "Two-way sync for increment 0005-payment-integration with ADO.
70
70
 
71
71
  Phase 1 - Pull FROM ADO:
72
72
  1. Fetch work item #12345 from ADO API
@@ -83,20 +83,20 @@ Phase 2 - Push TO ADO:
83
83
  6. POST comment to ADO API
84
84
  7. Update work item state/fields
85
85
 
86
- Display: Bidirectional sync summary"
86
+ Display: Two-way sync summary"
87
87
  ```
88
88
 
89
89
  ---
90
90
 
91
91
  ## Example Output
92
92
 
93
- ### Bidirectional Sync (Default)
93
+ ### Two-way Sync (Default)
94
94
 
95
95
  ```
96
- 🔄 Bidirectional sync for increment 0005...
96
+ 🔄 Two-way sync for increment 0005...
97
97
 
98
98
  ✓ Azure DevOps work item: #12345
99
- ✓ Sync direction: bidirectional (two-way)
99
+ ✓ Sync direction: Two-way (push & pull)
100
100
 
101
101
  Detecting changes (both directions)...
102
102
 
@@ -38,7 +38,7 @@ GitHub issues MUST use living docs format:
38
38
 
39
39
  **Tools**: Read, Write, Edit, Bash (GitHub CLI)
40
40
 
41
- **Default Behavior**: **Bidirectional sync** (two-way) - Synchronizes changes in both directions automatically
41
+ **Default Behavior**: **Two-way sync** (push & pull) - Synchronizes changes in both directions automatically
42
42
 
43
43
  ---
44
44
 
@@ -69,8 +69,8 @@ Task({
69
69
 
70
70
  As the GitHub Manager agent, I specialize in:
71
71
 
72
- ### 1. Bidirectional Synchronization (Default)
73
- - **Two-Way Sync**: Keep SpecWeave and GitHub synchronized automatically
72
+ ### 1. Two-way Synchronization (Default)
73
+ - **Two-way Sync**: Keep SpecWeave and GitHub synchronized automatically
74
74
  - **FROM GitHub**: Pull status changes, labels, comments, state updates
75
75
  - **TO GitHub**: Push task completion, progress updates, metadata
76
76
  - **Conflict Resolution**: Detect and resolve conflicts between systems
@@ -79,7 +79,7 @@ As the GitHub Manager agent, I specialize in:
79
79
 
80
80
  ### 2. Issue Management
81
81
  - **Create Issues**: Generate well-formatted GitHub issues from increment specs
82
- - **Update Issues**: Sync progress, add comments, update labels (bidirectional)
82
+ - **Update Issues**: Sync progress, add comments, update labels (two-way)
83
83
  - **Close Issues**: Close issues with completion summaries
84
84
  - **Link Issues**: Connect related issues, PRs, and increments
85
85
  - **Bulk Operations**: Batch create/update/close issues
@@ -87,7 +87,7 @@ As the GitHub Manager agent, I specialize in:
87
87
  ### 3. Progress Tracking
88
88
  - **Task Checklists**: Generate and update task checklists in issues
89
89
  - **Progress Comments**: Post detailed task completion comments
90
- - **Status Updates**: Bidirectional sync of increment status ↔ GitHub issue state
90
+ - **Status Updates**: Two-way sync of increment status ↔ GitHub issue state
91
91
  - **Time Tracking**: Track estimated vs actual time per task
92
92
  - **Milestone Progress**: Update milestone completion percentages
93
93