specweave 0.33.2 → 0.33.4
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.
- package/CLAUDE.md +133 -19
- package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts +120 -0
- package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/per-us-sync.js +276 -0
- package/dist/plugins/specweave-ado/lib/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +4 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +13 -3
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/per-us-sync.d.ts +97 -0
- package/dist/plugins/specweave-github/lib/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/per-us-sync.js +274 -0
- package/dist/plugins/specweave-github/lib/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts +113 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.js +254 -0
- package/dist/plugins/specweave-jira/lib/per-us-sync.js.map +1 -0
- package/dist/src/cli/cleanup-zombies.js +8 -5
- package/dist/src/cli/cleanup-zombies.js.map +1 -1
- package/dist/src/config/types.d.ts +203 -1208
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/config/config-manager.d.ts.map +1 -1
- package/dist/src/core/config/config-manager.js +58 -0
- package/dist/src/core/config/config-manager.js.map +1 -1
- package/dist/src/core/config/types.d.ts +80 -0
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/living-docs/cross-project-sync.d.ts +87 -15
- package/dist/src/core/living-docs/cross-project-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/cross-project-sync.js +147 -28
- package/dist/src/core/living-docs/cross-project-sync.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +26 -22
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/living-docs/types.d.ts +24 -3
- package/dist/src/core/living-docs/types.d.ts.map +1 -1
- package/dist/src/core/types/config.d.ts +79 -0
- package/dist/src/core/types/config.d.ts.map +1 -1
- package/dist/src/core/types/config.js.map +1 -1
- package/dist/src/importers/jira-importer.d.ts +10 -0
- package/dist/src/importers/jira-importer.d.ts.map +1 -1
- package/dist/src/importers/jira-importer.js +55 -5
- package/dist/src/importers/jira-importer.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +33 -140
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +30 -27
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +11 -34
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +15 -82
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +38 -93
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +4 -42
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/sync/closure-metrics.d.ts +102 -0
- package/dist/src/sync/closure-metrics.d.ts.map +1 -0
- package/dist/src/sync/closure-metrics.js +267 -0
- package/dist/src/sync/closure-metrics.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +49 -0
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +399 -37
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/utils/notification-constants.d.ts +85 -0
- package/dist/src/utils/notification-constants.d.ts.map +1 -0
- package/dist/src/utils/notification-constants.js +129 -0
- package/dist/src/utils/notification-constants.js.map +1 -0
- package/dist/src/utils/platform-utils.d.ts +13 -3
- package/dist/src/utils/platform-utils.d.ts.map +1 -1
- package/dist/src/utils/platform-utils.js +17 -6
- package/dist/src/utils/platform-utils.js.map +1 -1
- package/dist/src/utils/project-resolver.d.ts +156 -0
- package/dist/src/utils/project-resolver.d.ts.map +1 -0
- package/dist/src/utils/project-resolver.js +587 -0
- package/dist/src/utils/project-resolver.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/commands/specweave-increment.md +46 -0
- package/plugins/specweave/commands/specweave-jobs.md +153 -8
- package/plugins/specweave/hooks/hooks.json +10 -0
- package/plugins/specweave/hooks/spec-project-validator.sh +24 -2
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +26 -26
- package/plugins/specweave/hooks/universal/session-start.cmd +16 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +16 -16
- package/plugins/specweave/hooks/user-prompt-submit.sh +105 -3
- package/plugins/specweave/hooks/v2/guards/per-us-project-validator.sh +281 -0
- package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +29 -0
- package/plugins/specweave/scripts/session-watchdog.sh +278 -130
- package/plugins/specweave/skills/increment-planner/SKILL.md +48 -18
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +27 -14
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +16 -5
- package/plugins/specweave/skills/spec-generator/SKILL.md +74 -15
- package/plugins/specweave-ado/lib/per-us-sync.js +247 -0
- package/plugins/specweave-ado/lib/per-us-sync.ts +410 -0
- package/plugins/specweave-github/lib/github-client-v2.js +10 -3
- package/plugins/specweave-github/lib/github-client-v2.ts +15 -3
- package/plugins/specweave-github/lib/per-us-sync.js +241 -0
- package/plugins/specweave-github/lib/per-us-sync.ts +375 -0
- package/plugins/specweave-jira/lib/per-us-sync.js +224 -0
- package/plugins/specweave-jira/lib/per-us-sync.ts +366 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +0 -738
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -1107
package/CLAUDE.md
CHANGED
|
@@ -77,42 +77,118 @@ MetadataManager.updateStatus(incrementId, IncrementStatus.COMPLETED);
|
|
|
77
77
|
// Only succeeds if current status is "ready_for_review"
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
### 2c. spec.md MUST Have project: (and board: for 2-level) (v0.
|
|
80
|
+
### 2c. spec.md MUST Have project: (and board: for 2-level) - RESOLVED VALUES ONLY! (v0.34.0+)
|
|
81
81
|
|
|
82
|
-
**Increment creation WITHOUT project context = SYNC FAILURE**
|
|
82
|
+
**Increment creation WITHOUT resolved project context = SYNC FAILURE**
|
|
83
|
+
|
|
84
|
+
**⛔ YOU MUST RUN `specweave context projects` BEFORE GENERATING spec.md!**
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# MANDATORY FIRST STEP - run this BEFORE generating any spec.md:
|
|
88
|
+
specweave context projects
|
|
89
|
+
|
|
90
|
+
# Parse the JSON output:
|
|
91
|
+
# 1-level: {"level": 1, "projects": [{"id": "frontend-app"}, {"id": "backend-api"}]}
|
|
92
|
+
# 2-level: {"level": 2, "projects": [...], "boardsByProject": {"project-id": [{"id": "board-1"}]}}
|
|
93
|
+
|
|
94
|
+
# USE the actual IDs from the output - NEVER use placeholders!
|
|
95
|
+
```
|
|
83
96
|
|
|
84
97
|
```yaml
|
|
85
|
-
# 1-level structure (
|
|
98
|
+
# 1-level structure (RESOLVED values only):
|
|
86
99
|
---
|
|
87
100
|
increment: 0001-feature-name
|
|
88
|
-
project:
|
|
101
|
+
project: frontend-app # ← RESOLVED from context API (NOT {{PROJECT_ID}})
|
|
89
102
|
---
|
|
90
103
|
|
|
91
|
-
# 2-level structure (
|
|
104
|
+
# 2-level structure (BOTH RESOLVED):
|
|
92
105
|
---
|
|
93
106
|
increment: 0001-feature-name
|
|
94
|
-
project: acme-corp # ←
|
|
95
|
-
board: digital-operations # ←
|
|
107
|
+
project: acme-corp # ← RESOLVED from projects[].id
|
|
108
|
+
board: digital-operations # ← RESOLVED from boardsByProject[project][].id
|
|
96
109
|
---
|
|
97
110
|
```
|
|
98
111
|
|
|
99
|
-
**
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// config.level === 2 → project AND board required
|
|
112
|
+
**Per-US Project/Board (v0.34.0+ MANDATORY):**
|
|
113
|
+
```markdown
|
|
114
|
+
### US-001: Login Form
|
|
115
|
+
**Project**: frontend-app # ← RESOLVED value, not placeholder!
|
|
116
|
+
**Board**: ui-team # ← RESOLVED value (2-level only)
|
|
105
117
|
```
|
|
106
118
|
|
|
107
|
-
**VALIDATION RULES:**
|
|
119
|
+
**VALIDATION RULES (ENFORCED BY HOOK):**
|
|
108
120
|
```
|
|
109
|
-
❌ FORBIDDEN:
|
|
110
|
-
❌ FORBIDDEN:
|
|
111
|
-
❌ FORBIDDEN:
|
|
112
|
-
|
|
121
|
+
❌ FORBIDDEN: Generating spec.md WITHOUT running "specweave context projects" first
|
|
122
|
+
❌ FORBIDDEN: Using {{PROJECT_ID}}, {{BOARD_ID}}, {{RESOLVED_PROJECT}} placeholders
|
|
123
|
+
❌ FORBIDDEN: Inventing project/board names not in the API response
|
|
124
|
+
❌ FORBIDDEN: User stories without **Project**: field
|
|
125
|
+
❌ FORBIDDEN: User stories in 2-level without **Board**: field
|
|
126
|
+
✅ REQUIRED: Run "specweave context projects" and parse output BEFORE generating
|
|
127
|
+
✅ REQUIRED: Each US has **Project**: with RESOLVED value from API
|
|
128
|
+
✅ REQUIRED: Each US (2-level) has **Board**: with RESOLVED value from API
|
|
113
129
|
```
|
|
114
130
|
|
|
115
|
-
**Pre-tool-use hook `spec-project-validator.sh` BLOCKS
|
|
131
|
+
**Pre-tool-use hook `spec-project-validator.sh` BLOCKS:**
|
|
132
|
+
- spec.md with `{{...}}` placeholders
|
|
133
|
+
- spec.md without `project:` field
|
|
134
|
+
- spec.md (2-level) without `board:` field
|
|
135
|
+
- User stories with unresolved `**Project**:` or `**Board**:` placeholders
|
|
136
|
+
|
|
137
|
+
### 2c-bis. Each User Story MUST Have **Project**: (and **Board**: for 2-level) (v0.34.0+)
|
|
138
|
+
|
|
139
|
+
**CRITICAL 1:1 MAPPING RULE: Each User Story maps to EXACTLY ONE project and ONE board!**
|
|
140
|
+
|
|
141
|
+
```markdown
|
|
142
|
+
### US-001: Login Form UI
|
|
143
|
+
**Project**: frontend-app ← MANDATORY (exactly ONE project)
|
|
144
|
+
**Board**: ui-team ← MANDATORY for 2-level (exactly ONE board)
|
|
145
|
+
**As a** user, I want a login form...
|
|
146
|
+
|
|
147
|
+
### US-002: Auth API Endpoints
|
|
148
|
+
**Project**: backend-api ← DIFFERENT project = OK
|
|
149
|
+
**Board**: api-team ← DIFFERENT board = OK
|
|
150
|
+
**As a** developer, I want JWT auth API...
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**1:1 MAPPING ENFORCEMENT:**
|
|
154
|
+
```
|
|
155
|
+
❌ FORBIDDEN: **Project**: frontend-app, backend-api (MULTIPLE projects)
|
|
156
|
+
❌ FORBIDDEN: **Board**: ui-team, api-team (MULTIPLE boards)
|
|
157
|
+
❌ FORBIDDEN: User Story without **Project**: field
|
|
158
|
+
|
|
159
|
+
✅ REQUIRED: Each US has exactly ONE **Project**: value
|
|
160
|
+
✅ REQUIRED: Each US has exactly ONE **Board**: value (2-level)
|
|
161
|
+
✅ CROSS-PROJECT: Split into separate USs per project
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Cross-project features → Create SEPARATE User Stories:**
|
|
165
|
+
```markdown
|
|
166
|
+
## OAuth Feature (Cross-Project)
|
|
167
|
+
|
|
168
|
+
### US-001: OAuth Login Form
|
|
169
|
+
**Project**: frontend-app ← One project per US
|
|
170
|
+
...
|
|
171
|
+
|
|
172
|
+
### US-002: OAuth API Endpoints
|
|
173
|
+
**Project**: backend-api ← Different project = separate US
|
|
174
|
+
...
|
|
175
|
+
|
|
176
|
+
### US-003: OAuth Mobile Screen
|
|
177
|
+
**Project**: mobile-app ← Different project = separate US
|
|
178
|
+
...
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Pre-tool-use hook `per-us-project-validator.sh` BLOCKS spec.md with:**
|
|
182
|
+
- Missing `**Project**:` field per US
|
|
183
|
+
- Missing `**Board**:` field per US (2-level)
|
|
184
|
+
- Multiple comma-separated projects
|
|
185
|
+
- Multiple comma-separated boards
|
|
186
|
+
|
|
187
|
+
**Bypass (EMERGENCY ONLY):**
|
|
188
|
+
```bash
|
|
189
|
+
SPECWEAVE_FORCE_PROJECT=1 # Skip all validation
|
|
190
|
+
SPECWEAVE_LEGACY_SPEC=1 # Allow legacy specs without per-US fields
|
|
191
|
+
```
|
|
116
192
|
|
|
117
193
|
### 2d. NEVER Create Files in _features/ Folder (OBSOLETE v5.0.0+)
|
|
118
194
|
|
|
@@ -388,6 +464,44 @@ rm -f .specweave/state/.dedup-cache/*.lock
|
|
|
388
464
|
|
|
389
465
|
**Mental model**: Bash = "run a program". Write/Edit/Read = "modify files".
|
|
390
466
|
|
|
467
|
+
### 11. macOS Notifications - MUST Be Explicit (v0.33.3+)
|
|
468
|
+
|
|
469
|
+
**Vague notifications = user confusion!** Every notification MUST clearly state:
|
|
470
|
+
1. **WHO** sent it (always start with "SpecWeave:")
|
|
471
|
+
2. **WHAT** happened (specific action, not vague alert)
|
|
472
|
+
3. **ACTION** needed (or "No action needed" if informational)
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
❌ FORBIDDEN (vague, alarming):
|
|
476
|
+
Title: "🚨 Zombie Cleanup" ← What does this mean?!
|
|
477
|
+
Sound: "Basso" (error sound) ← Red alert icon, scary!
|
|
478
|
+
Message: "Cleaned up 5 processes" ← So what?
|
|
479
|
+
|
|
480
|
+
✅ CORRECT (explicit, calm):
|
|
481
|
+
Title: "SpecWeave: Cleanup Done" ← Clear source
|
|
482
|
+
Sound: "Pop" (neutral) ← Not alarming
|
|
483
|
+
Message: "Cleaned up 5 zombie processes. No action needed."
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**Sound selection rules:**
|
|
487
|
+
| Sound | When to use |
|
|
488
|
+
|-------|-------------|
|
|
489
|
+
| `Pop` | Success, completion (neutral) |
|
|
490
|
+
| `Glass` | Informational (gentle) |
|
|
491
|
+
| `Submarine` | Warning (not critical) |
|
|
492
|
+
| `Basso` | ONLY critical errors requiring immediate action |
|
|
493
|
+
|
|
494
|
+
**Use notification constants from `src/utils/notification-constants.ts`:**
|
|
495
|
+
```typescript
|
|
496
|
+
import { getTitleForType, buildNotificationMessage, getSoundForType } from './notification-constants.js';
|
|
497
|
+
|
|
498
|
+
const title = getTitleForType('cleanup'); // "SpecWeave: Cleanup Done"
|
|
499
|
+
const msg = buildNotificationMessage('cleanup', { count: 5 }); // "Cleaned up 5 zombie..."
|
|
500
|
+
const sound = getSoundForType('cleanup'); // "Pop"
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
**Pre-commit hook validates notification messages in new code (v0.33.3+).**
|
|
504
|
+
|
|
391
505
|
---
|
|
392
506
|
|
|
393
507
|
## Development Setup
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-US Azure DevOps Sync (v0.34.0+)
|
|
3
|
+
*
|
|
4
|
+
* Syncs each User Story to its explicitly declared project's ADO project/area.
|
|
5
|
+
* Uses the **Project**: and **Board**: fields in spec.md (NOT keyword-based classification).
|
|
6
|
+
*
|
|
7
|
+
* Key difference from multi-project-sync:
|
|
8
|
+
* - Multi-project sync uses keyword/heuristic classification
|
|
9
|
+
* - Per-US sync uses EXPLICIT **Project**: and **Board**: fields from spec.md
|
|
10
|
+
*
|
|
11
|
+
* @module per-us-sync
|
|
12
|
+
* @since v0.34.0
|
|
13
|
+
*/
|
|
14
|
+
import type { UserStoryData } from '../../../src/core/living-docs/types.js';
|
|
15
|
+
import type { ProjectMappings } from '../../../src/core/types/config.js';
|
|
16
|
+
import type { USExternalRefsMap } from '../../../src/core/types/increment-metadata.js';
|
|
17
|
+
import { Logger } from '../../../src/utils/logger.js';
|
|
18
|
+
/**
|
|
19
|
+
* Result of syncing a single US to ADO
|
|
20
|
+
*/
|
|
21
|
+
export interface USSyncResult {
|
|
22
|
+
usId: string;
|
|
23
|
+
projectId: string;
|
|
24
|
+
adoProject: string;
|
|
25
|
+
areaPath: string;
|
|
26
|
+
workItemId: number;
|
|
27
|
+
url: string;
|
|
28
|
+
action: 'created' | 'updated' | 'skipped';
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Result of syncing all USs in an increment
|
|
33
|
+
*/
|
|
34
|
+
export interface PerUSSyncResult {
|
|
35
|
+
success: boolean;
|
|
36
|
+
synced: USSyncResult[];
|
|
37
|
+
failed: USSyncResult[];
|
|
38
|
+
externalRefs: USExternalRefsMap;
|
|
39
|
+
summary: {
|
|
40
|
+
total: number;
|
|
41
|
+
created: number;
|
|
42
|
+
updated: number;
|
|
43
|
+
skipped: number;
|
|
44
|
+
failed: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Options for per-US sync
|
|
49
|
+
*/
|
|
50
|
+
export interface PerUSSyncOptions {
|
|
51
|
+
dryRun?: boolean;
|
|
52
|
+
force?: boolean;
|
|
53
|
+
defaultProject?: string;
|
|
54
|
+
defaultBoard?: string;
|
|
55
|
+
logger?: Logger;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* ADO client interface (to be injected)
|
|
59
|
+
*/
|
|
60
|
+
export interface AdoClient {
|
|
61
|
+
createWorkItem(project: string, workItemType: string, title: string, description: string, areaPath?: string): Promise<{
|
|
62
|
+
id: number;
|
|
63
|
+
url: string;
|
|
64
|
+
}>;
|
|
65
|
+
updateWorkItem(project: string, workItemId: number, title: string, description: string, areaPath?: string): Promise<void>;
|
|
66
|
+
searchWorkItems(project: string, query: string): Promise<Array<{
|
|
67
|
+
id: number;
|
|
68
|
+
fields: {
|
|
69
|
+
'System.Title': string;
|
|
70
|
+
};
|
|
71
|
+
}>>;
|
|
72
|
+
getWorkItemUrl(project: string, workItemId: number): string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Per-US ADO Sync
|
|
76
|
+
*
|
|
77
|
+
* Syncs each US to its declared project's ADO project/area path.
|
|
78
|
+
* For 2-level structures, uses **Board**: to determine area path.
|
|
79
|
+
*/
|
|
80
|
+
export declare class PerUSAdoSync {
|
|
81
|
+
private projectMappings;
|
|
82
|
+
private adoClient;
|
|
83
|
+
private logger;
|
|
84
|
+
constructor(adoClient: AdoClient, projectMappings: ProjectMappings, options?: {
|
|
85
|
+
logger?: Logger;
|
|
86
|
+
});
|
|
87
|
+
/**
|
|
88
|
+
* Sync all user stories to their respective ADO projects
|
|
89
|
+
*
|
|
90
|
+
* @param userStories - User stories with explicit project/board fields
|
|
91
|
+
* @param featureId - Feature ID (e.g., "FS-137")
|
|
92
|
+
* @param options - Sync options
|
|
93
|
+
*/
|
|
94
|
+
syncUserStories(userStories: UserStoryData[], featureId: string, options?: PerUSSyncOptions): Promise<PerUSSyncResult>;
|
|
95
|
+
/**
|
|
96
|
+
* Sync a single user story to ADO
|
|
97
|
+
*
|
|
98
|
+
* For 2-level structures:
|
|
99
|
+
* - **Project**: maps to ADO project
|
|
100
|
+
* - **Board**: maps to area path under the project
|
|
101
|
+
*/
|
|
102
|
+
private syncUserStory;
|
|
103
|
+
/**
|
|
104
|
+
* Find existing work item by US ID in title
|
|
105
|
+
*/
|
|
106
|
+
private findExistingWorkItem;
|
|
107
|
+
/**
|
|
108
|
+
* Build work item description from user story
|
|
109
|
+
*/
|
|
110
|
+
private buildWorkItemDescription;
|
|
111
|
+
/**
|
|
112
|
+
* Group user stories by their explicit project field
|
|
113
|
+
*/
|
|
114
|
+
private groupByProject;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Format per-US sync results for display
|
|
118
|
+
*/
|
|
119
|
+
export declare function formatPerUSSyncResults(result: PerUSSyncResult): string;
|
|
120
|
+
//# sourceMappingURL=per-us-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"per-us-sync.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-ado/lib/per-us-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-US Azure DevOps Sync (v0.34.0+)
|
|
3
|
+
*
|
|
4
|
+
* Syncs each User Story to its explicitly declared project's ADO project/area.
|
|
5
|
+
* Uses the **Project**: and **Board**: fields in spec.md (NOT keyword-based classification).
|
|
6
|
+
*
|
|
7
|
+
* Key difference from multi-project-sync:
|
|
8
|
+
* - Multi-project sync uses keyword/heuristic classification
|
|
9
|
+
* - Per-US sync uses EXPLICIT **Project**: and **Board**: fields from spec.md
|
|
10
|
+
*
|
|
11
|
+
* @module per-us-sync
|
|
12
|
+
* @since v0.34.0
|
|
13
|
+
*/
|
|
14
|
+
import { consoleLogger } from '../../../src/utils/logger.js';
|
|
15
|
+
/**
|
|
16
|
+
* Per-US ADO Sync
|
|
17
|
+
*
|
|
18
|
+
* Syncs each US to its declared project's ADO project/area path.
|
|
19
|
+
* For 2-level structures, uses **Board**: to determine area path.
|
|
20
|
+
*/
|
|
21
|
+
export class PerUSAdoSync {
|
|
22
|
+
constructor(adoClient, projectMappings, options = {}) {
|
|
23
|
+
this.adoClient = adoClient;
|
|
24
|
+
this.projectMappings = projectMappings;
|
|
25
|
+
this.logger = options.logger ?? consoleLogger;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sync all user stories to their respective ADO projects
|
|
29
|
+
*
|
|
30
|
+
* @param userStories - User stories with explicit project/board fields
|
|
31
|
+
* @param featureId - Feature ID (e.g., "FS-137")
|
|
32
|
+
* @param options - Sync options
|
|
33
|
+
*/
|
|
34
|
+
async syncUserStories(userStories, featureId, options = {}) {
|
|
35
|
+
const synced = [];
|
|
36
|
+
const failed = [];
|
|
37
|
+
const externalRefs = {};
|
|
38
|
+
// Group USs by their declared project
|
|
39
|
+
const groups = this.groupByProject(userStories, options.defaultProject);
|
|
40
|
+
this.logger.log(`📡 Per-US ADO Sync: ${userStories.length} USs across ${groups.size} projects`);
|
|
41
|
+
for (const [projectId, stories] of groups) {
|
|
42
|
+
// Get ADO mapping for this project
|
|
43
|
+
const mapping = this.projectMappings[projectId]?.ado;
|
|
44
|
+
if (!mapping) {
|
|
45
|
+
// No ADO mapping for this project
|
|
46
|
+
this.logger.warn(` ⚠️ No ADO mapping for project "${projectId}" - skipping ${stories.length} USs`);
|
|
47
|
+
for (const story of stories) {
|
|
48
|
+
failed.push({
|
|
49
|
+
usId: story.id,
|
|
50
|
+
projectId,
|
|
51
|
+
adoProject: 'N/A',
|
|
52
|
+
areaPath: '',
|
|
53
|
+
workItemId: 0,
|
|
54
|
+
url: '',
|
|
55
|
+
action: 'skipped',
|
|
56
|
+
error: `No ADO mapping for project "${projectId}"`
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Sync each US to this project's ADO project
|
|
62
|
+
for (const story of stories) {
|
|
63
|
+
try {
|
|
64
|
+
const result = await this.syncUserStory(story, mapping, featureId, options);
|
|
65
|
+
synced.push({
|
|
66
|
+
...result,
|
|
67
|
+
projectId
|
|
68
|
+
});
|
|
69
|
+
// Build external ref
|
|
70
|
+
if (!options.dryRun && result.action !== 'skipped') {
|
|
71
|
+
externalRefs[story.id] = {
|
|
72
|
+
ado: {
|
|
73
|
+
provider: 'ado',
|
|
74
|
+
issueNumber: result.workItemId,
|
|
75
|
+
url: result.url,
|
|
76
|
+
targetProject: projectId,
|
|
77
|
+
lastSynced: new Date().toISOString()
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
failed.push({
|
|
84
|
+
usId: story.id,
|
|
85
|
+
projectId,
|
|
86
|
+
adoProject: mapping.project,
|
|
87
|
+
areaPath: mapping.areaPath || '',
|
|
88
|
+
workItemId: 0,
|
|
89
|
+
url: '',
|
|
90
|
+
action: 'skipped',
|
|
91
|
+
error: error instanceof Error ? error.message : String(error)
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Calculate summary
|
|
97
|
+
const created = synced.filter(r => r.action === 'created').length;
|
|
98
|
+
const updated = synced.filter(r => r.action === 'updated').length;
|
|
99
|
+
const skipped = synced.filter(r => r.action === 'skipped').length;
|
|
100
|
+
return {
|
|
101
|
+
success: failed.length === 0,
|
|
102
|
+
synced,
|
|
103
|
+
failed,
|
|
104
|
+
externalRefs,
|
|
105
|
+
summary: {
|
|
106
|
+
total: userStories.length,
|
|
107
|
+
created,
|
|
108
|
+
updated,
|
|
109
|
+
skipped,
|
|
110
|
+
failed: failed.length
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Sync a single user story to ADO
|
|
116
|
+
*
|
|
117
|
+
* For 2-level structures:
|
|
118
|
+
* - **Project**: maps to ADO project
|
|
119
|
+
* - **Board**: maps to area path under the project
|
|
120
|
+
*/
|
|
121
|
+
async syncUserStory(story, mapping, featureId, options) {
|
|
122
|
+
const title = `[${featureId}][${story.id}] ${story.title}`;
|
|
123
|
+
const description = this.buildWorkItemDescription(story, featureId);
|
|
124
|
+
// Determine area path:
|
|
125
|
+
// - Use story.board if available (2-level structure)
|
|
126
|
+
// - Fall back to mapping.areaPath
|
|
127
|
+
// - Fall back to project root
|
|
128
|
+
let areaPath = mapping.areaPath || mapping.project;
|
|
129
|
+
if (story.board) {
|
|
130
|
+
// 2-level structure: append board as area path segment
|
|
131
|
+
areaPath = `${mapping.project}\\${story.board}`;
|
|
132
|
+
}
|
|
133
|
+
if (options.dryRun) {
|
|
134
|
+
this.logger.log(` 🔍 [DRY-RUN] Would sync ${story.id} to ${mapping.project} (area: ${areaPath})`);
|
|
135
|
+
return {
|
|
136
|
+
usId: story.id,
|
|
137
|
+
projectId: story.project || 'unknown',
|
|
138
|
+
adoProject: mapping.project,
|
|
139
|
+
areaPath,
|
|
140
|
+
workItemId: 0,
|
|
141
|
+
url: '',
|
|
142
|
+
action: 'skipped'
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// Check for existing work item
|
|
146
|
+
const existingItem = await this.findExistingWorkItem(mapping.project, story.id);
|
|
147
|
+
if (existingItem) {
|
|
148
|
+
// Update existing work item
|
|
149
|
+
await this.adoClient.updateWorkItem(mapping.project, existingItem.id, title, description, areaPath);
|
|
150
|
+
this.logger.log(` 🔄 Updated ${story.id} → ${mapping.project}/${existingItem.id}`);
|
|
151
|
+
return {
|
|
152
|
+
usId: story.id,
|
|
153
|
+
projectId: story.project || 'unknown',
|
|
154
|
+
adoProject: mapping.project,
|
|
155
|
+
areaPath,
|
|
156
|
+
workItemId: existingItem.id,
|
|
157
|
+
url: this.adoClient.getWorkItemUrl(mapping.project, existingItem.id),
|
|
158
|
+
action: 'updated'
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// Create new work item
|
|
163
|
+
const newItem = await this.adoClient.createWorkItem(mapping.project, 'User Story', title, description, areaPath);
|
|
164
|
+
this.logger.log(` ✅ Created ${story.id} → ${mapping.project}/${newItem.id}`);
|
|
165
|
+
return {
|
|
166
|
+
usId: story.id,
|
|
167
|
+
projectId: story.project || 'unknown',
|
|
168
|
+
adoProject: mapping.project,
|
|
169
|
+
areaPath,
|
|
170
|
+
workItemId: newItem.id,
|
|
171
|
+
url: newItem.url,
|
|
172
|
+
action: 'created'
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Find existing work item by US ID in title
|
|
178
|
+
*/
|
|
179
|
+
async findExistingWorkItem(project, usId) {
|
|
180
|
+
try {
|
|
181
|
+
const query = `[System.Title] Contains '[${usId}]'`;
|
|
182
|
+
const results = await this.adoClient.searchWorkItems(project, query);
|
|
183
|
+
return results.length > 0 ? { id: results[0].id } : null;
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Build work item description from user story
|
|
191
|
+
*/
|
|
192
|
+
buildWorkItemDescription(story, featureId) {
|
|
193
|
+
const lines = [];
|
|
194
|
+
lines.push(`<h1>${story.title}</h1>`);
|
|
195
|
+
lines.push('');
|
|
196
|
+
if (story.description) {
|
|
197
|
+
lines.push(`<p>${story.description}</p>`);
|
|
198
|
+
lines.push('');
|
|
199
|
+
}
|
|
200
|
+
if (story.acceptanceCriteria && story.acceptanceCriteria.length > 0) {
|
|
201
|
+
lines.push('<h2>Acceptance Criteria</h2>');
|
|
202
|
+
lines.push('<ul>');
|
|
203
|
+
for (const ac of story.acceptanceCriteria) {
|
|
204
|
+
lines.push(` <li>${ac}</li>`);
|
|
205
|
+
}
|
|
206
|
+
lines.push('</ul>');
|
|
207
|
+
lines.push('');
|
|
208
|
+
}
|
|
209
|
+
lines.push('<hr/>');
|
|
210
|
+
lines.push('');
|
|
211
|
+
lines.push(`<p><strong>Feature</strong>: ${featureId}</p>`);
|
|
212
|
+
lines.push(`<p><strong>User Story</strong>: ${story.id}</p>`);
|
|
213
|
+
if (story.project) {
|
|
214
|
+
lines.push(`<p><strong>Project</strong>: ${story.project}</p>`);
|
|
215
|
+
}
|
|
216
|
+
if (story.board) {
|
|
217
|
+
lines.push(`<p><strong>Board</strong>: ${story.board}</p>`);
|
|
218
|
+
}
|
|
219
|
+
lines.push('');
|
|
220
|
+
lines.push('<p><em>Auto-generated by SpecWeave</em></p>');
|
|
221
|
+
return lines.join('\n');
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Group user stories by their explicit project field
|
|
225
|
+
*/
|
|
226
|
+
groupByProject(userStories, defaultProject) {
|
|
227
|
+
const groups = new Map();
|
|
228
|
+
for (const story of userStories) {
|
|
229
|
+
const project = story.project || defaultProject || 'default';
|
|
230
|
+
if (!groups.has(project)) {
|
|
231
|
+
groups.set(project, []);
|
|
232
|
+
}
|
|
233
|
+
groups.get(project).push(story);
|
|
234
|
+
}
|
|
235
|
+
return groups;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Format per-US sync results for display
|
|
240
|
+
*/
|
|
241
|
+
export function formatPerUSSyncResults(result) {
|
|
242
|
+
const lines = [];
|
|
243
|
+
lines.push('');
|
|
244
|
+
lines.push('📊 Per-US ADO Sync Results');
|
|
245
|
+
lines.push('');
|
|
246
|
+
// Group by project
|
|
247
|
+
const byProject = new Map();
|
|
248
|
+
for (const r of [...result.synced, ...result.failed]) {
|
|
249
|
+
const existing = byProject.get(r.projectId) || [];
|
|
250
|
+
existing.push(r);
|
|
251
|
+
byProject.set(r.projectId, existing);
|
|
252
|
+
}
|
|
253
|
+
for (const [projectId, results] of byProject) {
|
|
254
|
+
const adoProject = results[0]?.adoProject || 'N/A';
|
|
255
|
+
const areaPath = results[0]?.areaPath || '';
|
|
256
|
+
lines.push(`**${projectId}** (→ ${adoProject}${areaPath ? ` [${areaPath}]` : ''}):`);
|
|
257
|
+
for (const r of results) {
|
|
258
|
+
const icon = r.action === 'created' ? '✅' :
|
|
259
|
+
r.action === 'updated' ? '🔄' :
|
|
260
|
+
r.error ? '❌' : '⏭️';
|
|
261
|
+
if (r.workItemId > 0) {
|
|
262
|
+
lines.push(` ${icon} ${r.usId} → ${r.adoProject}/${r.workItemId}`);
|
|
263
|
+
}
|
|
264
|
+
else if (r.error) {
|
|
265
|
+
lines.push(` ${icon} ${r.usId}: ${r.error}`);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
lines.push(` ${icon} ${r.usId} (${r.action})`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
lines.push('');
|
|
272
|
+
}
|
|
273
|
+
lines.push(`📈 Summary: ${result.summary.created} created, ${result.summary.updated} updated, ${result.summary.failed} failed`);
|
|
274
|
+
return lines.join('\n');
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=per-us-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"per-us-sync.js","sourceRoot":"","sources":["../../../../plugins/specweave-ado/lib/per-us-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -101,8 +101,11 @@ export declare class GitHubClientV2 {
|
|
|
101
101
|
* Search for issue by exact title match
|
|
102
102
|
*
|
|
103
103
|
* IDEMPOTENCY: Use this before creating issues to prevent duplicates
|
|
104
|
+
*
|
|
105
|
+
* @param title - Title pattern to search for (e.g., "[FS-136][US-001]")
|
|
106
|
+
* @param includeClosedIssues - If true, searches all issues (open+closed). Default: false (open only)
|
|
104
107
|
*/
|
|
105
|
-
searchIssueByTitle(title: string): Promise<GitHubIssue | null>;
|
|
108
|
+
searchIssueByTitle(title: string, includeClosedIssues?: boolean): Promise<GitHubIssue | null>;
|
|
106
109
|
/**
|
|
107
110
|
* Update issue body
|
|
108
111
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-client-v2.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-client-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAgB,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAElG,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IAEzB;;OAEG;gBACS,OAAO,EAAE,WAAW;IAWhC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc;IAU5D;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIlB;;OAEG;IACH,OAAO,IAAI,MAAM;IAQjB;;OAEG;WACU,QAAQ,IAAI,OAAO,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;QACnB,aAAa,EAAE,OAAO,CAAC;QACvB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAwBF;;OAEG;WACU,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI,CAAC;IA4BpF;;OAEG;IACG,oBAAoB,CACxB,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,WAAW,GAAE,MAAU,GACtB,OAAO,CAAC,eAAe,CAAC;IAqC3B;;OAEG;YACW,mBAAmB;IAqBjC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,kBAAkB;IAqC1B;;;;;;;;;;OAUG;IACG,oBAAoB,CAAC,MAAM,EAAE;QACjC,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBxB;;OAEG;IACG,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAC3B,MAAM,GAAE,MAAM,EAAO,GACpB,OAAO,CAAC,WAAW,CAAC;IA4DvB;;OAEG;IACG,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAC3B,MAAM,GAAE,MAAM,EAAO,GACpB,OAAO,CAAC,WAAW,CAAC;IAOvB;;OAEG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBzD
|
|
1
|
+
{"version":3,"file":"github-client-v2.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-client-v2.ts"],"names":[],"mappings":"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"}
|
|
@@ -299,11 +299,14 @@ export class GitHubClientV2 {
|
|
|
299
299
|
* Search for issue by exact title match
|
|
300
300
|
*
|
|
301
301
|
* IDEMPOTENCY: Use this before creating issues to prevent duplicates
|
|
302
|
+
*
|
|
303
|
+
* @param title - Title pattern to search for (e.g., "[FS-136][US-001]")
|
|
304
|
+
* @param includeClosedIssues - If true, searches all issues (open+closed). Default: false (open only)
|
|
302
305
|
*/
|
|
303
|
-
async searchIssueByTitle(title) {
|
|
306
|
+
async searchIssueByTitle(title, includeClosedIssues = false) {
|
|
304
307
|
// Escape double quotes in title for gh search
|
|
305
308
|
const escapedTitle = title.replace(/"/g, '\\"');
|
|
306
|
-
const
|
|
309
|
+
const args = [
|
|
307
310
|
'issue',
|
|
308
311
|
'list',
|
|
309
312
|
'--repo',
|
|
@@ -314,7 +317,14 @@ export class GitHubClientV2 {
|
|
|
314
317
|
'number,title,state,url,labels',
|
|
315
318
|
'--limit',
|
|
316
319
|
'50', // ✅ FIX: Increased from 1 to 50 to catch duplicates (Issue #0047)
|
|
317
|
-
]
|
|
320
|
+
];
|
|
321
|
+
// v0.34.0: Add --state all to search closed issues too (for closure flow)
|
|
322
|
+
// Without this, closeGitHubIssuesForUserStories() can't find already-closed issues
|
|
323
|
+
// and reports "No GitHub issue found" instead of "already closed"
|
|
324
|
+
if (includeClosedIssues) {
|
|
325
|
+
args.push('--state', 'all');
|
|
326
|
+
}
|
|
327
|
+
const result = await execFileNoThrow('gh', args);
|
|
318
328
|
if (result.exitCode !== 0) {
|
|
319
329
|
// Search failed, return null (treat as not found)
|
|
320
330
|
return null;
|