specweave 1.0.464 → 1.0.466
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/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.d.ts +16 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js +139 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.d.ts +111 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.js +304 -0
- package/dist/plugins/specweave/lib/vendor/core/ac-test-validator.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +359 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +121 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +273 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +72 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +237 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +281 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +278 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +925 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.d.ts +113 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.js +317 -0
- package/dist/plugins/specweave/lib/vendor/core/increment/status-auto-transition.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +442 -0
- package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.js +246 -0
- package/dist/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.d.ts +64 -0
- package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.js +228 -0
- package/dist/plugins/specweave/lib/vendor/core/universal-auto-create.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js +300 -0
- package/dist/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/config.d.ts +73 -0
- package/dist/plugins/specweave/lib/vendor/sync/config.js +132 -0
- package/dist/plugins/specweave/lib/vendor/sync/config.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.d.ts +163 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js +898 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/provider-router.d.ts +86 -0
- package/dist/plugins/specweave/lib/vendor/sync/provider-router.js +147 -0
- package/dist/plugins/specweave/lib/vendor/sync/provider-router.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/status-mapper.d.ts +120 -0
- package/dist/plugins/specweave/lib/vendor/sync/status-mapper.js +164 -0
- package/dist/plugins/specweave/lib/vendor/sync/status-mapper.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.d.ts +151 -0
- package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.js +359 -0
- package/dist/plugins/specweave/lib/vendor/utils/auth-helpers.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.d.ts +38 -0
- package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.js +118 -0
- package/dist/plugins/specweave/lib/vendor/utils/chalk-fallback.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/clean-env.d.ts +47 -0
- package/dist/plugins/specweave/lib/vendor/utils/clean-env.js +63 -0
- package/dist/plugins/specweave/lib/vendor/utils/clean-env.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/credential-masker.d.ts +118 -0
- package/dist/plugins/specweave/lib/vendor/utils/credential-masker.js +275 -0
- package/dist/plugins/specweave/lib/vendor/utils/credential-masker.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.d.ts +99 -0
- package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.js +149 -0
- package/dist/plugins/specweave/lib/vendor/utils/execFileNoThrow.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.d.ts +63 -0
- package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.js +85 -0
- package/dist/plugins/specweave/lib/vendor/utils/feature-id-derivation.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.d.ts +219 -0
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.js +397 -0
- package/dist/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/logger.d.ts +56 -0
- package/dist/plugins/specweave/lib/vendor/utils/logger.js +123 -0
- package/dist/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
- package/dist/plugins/specweave/lib/vendor/utils/translation.js +414 -0
- package/dist/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js +2 -2
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +13 -4
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js +1 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js.map +1 -1
- package/dist/src/sync/spec-to-living-docs-sync.js +1 -1
- package/dist/src/sync/spec-to-living-docs-sync.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/lib/vendor/utils/auth-helpers.d.ts +151 -0
- package/plugins/specweave/lib/vendor/utils/auth-helpers.js +359 -0
- package/plugins/specweave/lib/vendor/utils/auth-helpers.js.map +1 -0
- package/plugins/specweave/skills/team-lead/SKILL.md +150 -56
- package/plugins/specweave/skills/team-lead/agents/backend.md +13 -9
- package/plugins/specweave/skills/team-lead/agents/database.md +13 -9
- package/plugins/specweave/skills/team-lead/agents/frontend.md +12 -8
- package/plugins/specweave/skills/team-lead/agents/security.md +13 -9
- package/plugins/specweave/skills/team-lead/agents/testing.md +12 -8
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +1 -1
- package/plugins/specweave-ado/lib/ado-spec-sync.js +1 -1
- package/plugins/specweave-ado/lib/ado-spec-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.ts +2 -2
- package/plugins/specweave-github/lib/github-feature-sync.js +11 -3
- package/plugins/specweave-github/lib/github-feature-sync.ts +13 -4
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +1 -1
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.ts +1 -1
- package/plugins/specweave-jira/lib/jira-spec-sync.js +1 -1
- package/plugins/specweave-jira/lib/jira-spec-sync.ts +1 -1
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Parser with US-Task Linkage Support
|
|
3
|
+
*
|
|
4
|
+
* Parses tasks.md files to extract task metadata including new US linkage fields:
|
|
5
|
+
* - userStory: US-ID this task implements (e.g., "US-001")
|
|
6
|
+
* - satisfiesACs: List of AC-IDs this task satisfies (e.g., ["AC-US1-01", "AC-US1-02"])
|
|
7
|
+
*
|
|
8
|
+
* Supports hierarchical task structure grouped by User Story.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
11
|
+
/**
|
|
12
|
+
* Parse task status from checkbox and status text
|
|
13
|
+
*/
|
|
14
|
+
function parseTaskStatus(checkbox, statusText) {
|
|
15
|
+
if (checkbox === 'x')
|
|
16
|
+
return 'completed';
|
|
17
|
+
if (statusText.includes('progress'))
|
|
18
|
+
return 'in_progress';
|
|
19
|
+
if (statusText.includes('transfer'))
|
|
20
|
+
return 'transferred';
|
|
21
|
+
if (statusText.includes('cancel'))
|
|
22
|
+
return 'canceled';
|
|
23
|
+
return 'pending';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parse tasks.md and extract all tasks with US linkage
|
|
27
|
+
*
|
|
28
|
+
* @param tasksPath - Path to tasks.md file
|
|
29
|
+
* @returns Map of User Story ID → Tasks
|
|
30
|
+
* @throws Error if tasks.md cannot be read or is malformed
|
|
31
|
+
*/
|
|
32
|
+
export function parseTasksWithUSLinks(tasksPath) {
|
|
33
|
+
try {
|
|
34
|
+
const content = readFileSync(tasksPath, 'utf-8');
|
|
35
|
+
const tasks = {};
|
|
36
|
+
// Split content into lines for line number tracking
|
|
37
|
+
const lines = content.split('\n');
|
|
38
|
+
// Regex patterns for task parsing (T-029: Support E suffix for external IDs)
|
|
39
|
+
// Updated: Support 3+ digits for T-XXX and US-XXX (Y2K fix)
|
|
40
|
+
const taskHeaderRegex = /^###\s+(T-\d{3,}E?):\s*(.+)$/;
|
|
41
|
+
const userStoryRegex = /^\*\*User Story\*\*:\s*(US-\d{3,}E?)/;
|
|
42
|
+
const satisfiesACsRegex = /^\*\*Satisfies ACs\*\*:\s*(AC-US\d+E?-\d{2}(?:,\s*AC-US\d+E?-\d{2})*)/;
|
|
43
|
+
const statusRegex = /^\*\*Status\*\*:\s*\[([x ])\]\s*(\w+)/;
|
|
44
|
+
const priorityRegex = /^\*\*Priority\*\*:\s*(.+)/;
|
|
45
|
+
const estimatedEffortRegex = /^\*\*Estimated Effort\*\*:\s*(.+)/;
|
|
46
|
+
const dependenciesRegex = /^\*\*Dependencies\*\*:\s*(.+)/;
|
|
47
|
+
let currentTask = null;
|
|
48
|
+
let currentDescription = [];
|
|
49
|
+
let currentSection = 'none';
|
|
50
|
+
for (let i = 0; i < lines.length; i++) {
|
|
51
|
+
const line = lines[i];
|
|
52
|
+
const lineNumber = i + 1;
|
|
53
|
+
// Check for task header (### T-XXX: Title)
|
|
54
|
+
const taskHeaderMatch = line.match(taskHeaderRegex);
|
|
55
|
+
if (taskHeaderMatch) {
|
|
56
|
+
// Save previous task if exists
|
|
57
|
+
if (currentTask) {
|
|
58
|
+
saveTask(tasks, currentTask, currentDescription);
|
|
59
|
+
}
|
|
60
|
+
// Start new task
|
|
61
|
+
currentTask = {
|
|
62
|
+
id: taskHeaderMatch[1],
|
|
63
|
+
title: taskHeaderMatch[2],
|
|
64
|
+
status: 'pending',
|
|
65
|
+
lineNumber
|
|
66
|
+
};
|
|
67
|
+
currentDescription = [];
|
|
68
|
+
currentSection = 'none';
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// Skip if no current task
|
|
72
|
+
if (!currentTask)
|
|
73
|
+
continue;
|
|
74
|
+
// Parse task fields
|
|
75
|
+
const userStoryMatch = line.match(userStoryRegex);
|
|
76
|
+
if (userStoryMatch) {
|
|
77
|
+
currentTask.userStory = userStoryMatch[1];
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const satisfiesACsMatch = line.match(satisfiesACsRegex);
|
|
81
|
+
if (satisfiesACsMatch) {
|
|
82
|
+
// Split comma-separated AC-IDs and trim whitespace
|
|
83
|
+
currentTask.satisfiesACs = satisfiesACsMatch[1]
|
|
84
|
+
.split(',')
|
|
85
|
+
.map(ac => ac.trim());
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const statusMatch = line.match(statusRegex);
|
|
89
|
+
if (statusMatch) {
|
|
90
|
+
const checkbox = statusMatch[1];
|
|
91
|
+
const statusText = statusMatch[2].toLowerCase();
|
|
92
|
+
currentTask.status = parseTaskStatus(checkbox, statusText);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const priorityMatch = line.match(priorityRegex);
|
|
96
|
+
if (priorityMatch) {
|
|
97
|
+
currentTask.priority = priorityMatch[1];
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const estimatedEffortMatch = line.match(estimatedEffortRegex);
|
|
101
|
+
if (estimatedEffortMatch) {
|
|
102
|
+
currentTask.estimatedEffort = estimatedEffortMatch[1];
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const dependenciesMatch = line.match(dependenciesRegex);
|
|
106
|
+
if (dependenciesMatch) {
|
|
107
|
+
// Parse dependencies (T-001, T-002, T-1000, etc.)
|
|
108
|
+
currentTask.dependencies = dependenciesMatch[1]
|
|
109
|
+
.split(',')
|
|
110
|
+
.map(dep => dep.trim())
|
|
111
|
+
.filter(dep => dep.match(/^T-\d{3,}$/));
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
// Track sections for description parsing
|
|
115
|
+
if (line.startsWith('**Description**:')) {
|
|
116
|
+
currentSection = 'description';
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (line.startsWith('**Implementation Steps**:')) {
|
|
120
|
+
currentSection = 'implementation';
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (line.startsWith('**Test Plan**:')) {
|
|
124
|
+
currentSection = 'test';
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (line.startsWith('**Files Affected**:')) {
|
|
128
|
+
currentSection = 'files';
|
|
129
|
+
currentTask.filesAffected = [];
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// Collect description lines
|
|
133
|
+
if (currentSection === 'description' && line.trim() && !line.startsWith('**')) {
|
|
134
|
+
currentDescription.push(line.trim());
|
|
135
|
+
}
|
|
136
|
+
// Collect files affected
|
|
137
|
+
if (currentSection === 'files' && line.trim().startsWith('- `')) {
|
|
138
|
+
const filePath = line.trim().replace(/^- `(.+)`/, '$1');
|
|
139
|
+
if (currentTask.filesAffected) {
|
|
140
|
+
currentTask.filesAffected.push(filePath);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Save last task
|
|
145
|
+
if (currentTask) {
|
|
146
|
+
saveTask(tasks, currentTask, currentDescription);
|
|
147
|
+
}
|
|
148
|
+
return tasks;
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
throw new Error(`Failed to parse tasks.md at ${tasksPath}: ${error}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Helper: Save task to tasks map, grouped by User Story
|
|
156
|
+
*/
|
|
157
|
+
function saveTask(tasks, task, description) {
|
|
158
|
+
// Set description
|
|
159
|
+
if (description.length > 0) {
|
|
160
|
+
task.description = description.join(' ');
|
|
161
|
+
}
|
|
162
|
+
// Group by User Story (or "unassigned" if no userStory field)
|
|
163
|
+
const usId = task.userStory || 'unassigned';
|
|
164
|
+
if (!tasks[usId]) {
|
|
165
|
+
tasks[usId] = [];
|
|
166
|
+
}
|
|
167
|
+
tasks[usId].push(task);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Validate task US and AC linkage
|
|
171
|
+
*
|
|
172
|
+
* @param task - Task to validate
|
|
173
|
+
* @param validUSIds - List of valid US-IDs from spec.md
|
|
174
|
+
* @param validACIds - List of valid AC-IDs from spec.md
|
|
175
|
+
* @returns Array of validation errors (empty if valid)
|
|
176
|
+
*/
|
|
177
|
+
export function validateTaskLinkage(task, validUSIds, validACIds) {
|
|
178
|
+
const errors = [];
|
|
179
|
+
// Validate userStory field
|
|
180
|
+
if (task.userStory) {
|
|
181
|
+
// Check format (US-XXX, 3+ digits)
|
|
182
|
+
if (!task.userStory.match(/^US-\d{3,}$/)) {
|
|
183
|
+
errors.push({
|
|
184
|
+
taskId: task.id,
|
|
185
|
+
field: 'userStory',
|
|
186
|
+
value: task.userStory,
|
|
187
|
+
message: `Invalid US-ID format: "${task.userStory}" (expected format: US-001 or US-1000)`,
|
|
188
|
+
suggestedFix: 'Use format: US-XXX where XXX is 3 or more digits'
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
// Check if US exists in spec.md
|
|
192
|
+
else if (!validUSIds.includes(task.userStory)) {
|
|
193
|
+
errors.push({
|
|
194
|
+
taskId: task.id,
|
|
195
|
+
field: 'userStory',
|
|
196
|
+
value: task.userStory,
|
|
197
|
+
message: `User Story ${task.userStory} not found in spec.md`,
|
|
198
|
+
suggestedFix: `Valid User Stories: ${validUSIds.join(', ')}`
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Validate satisfiesACs field
|
|
203
|
+
if (task.satisfiesACs && task.satisfiesACs.length > 0) {
|
|
204
|
+
for (const acId of task.satisfiesACs) {
|
|
205
|
+
// Check format (AC-USXX-YY)
|
|
206
|
+
if (!acId.match(/^AC-US\d+-\d{2}$/)) {
|
|
207
|
+
errors.push({
|
|
208
|
+
taskId: task.id,
|
|
209
|
+
field: 'satisfiesACs',
|
|
210
|
+
value: acId,
|
|
211
|
+
message: `Invalid AC-ID format: "${acId}" (expected format: AC-US1-01)`,
|
|
212
|
+
suggestedFix: 'Use format: AC-USXX-YY where XX is US number, YY is AC number'
|
|
213
|
+
});
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
// Check if AC exists in spec.md
|
|
217
|
+
if (!validACIds.includes(acId)) {
|
|
218
|
+
errors.push({
|
|
219
|
+
taskId: task.id,
|
|
220
|
+
field: 'satisfiesACs',
|
|
221
|
+
value: acId,
|
|
222
|
+
message: `Acceptance Criteria ${acId} not found in spec.md`,
|
|
223
|
+
suggestedFix: `Check spec.md for valid AC-IDs in this User Story`
|
|
224
|
+
});
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
// Check if AC belongs to correct User Story
|
|
228
|
+
if (task.userStory) {
|
|
229
|
+
const acUSNumber = extractUSNumberFromACId(acId);
|
|
230
|
+
const taskUSNumber = extractUSNumber(task.userStory);
|
|
231
|
+
if (acUSNumber !== taskUSNumber) {
|
|
232
|
+
errors.push({
|
|
233
|
+
taskId: task.id,
|
|
234
|
+
field: 'satisfiesACs',
|
|
235
|
+
value: acId,
|
|
236
|
+
message: `AC ${acId} belongs to US-${String(acUSNumber).padStart(3, '0')}, but task is linked to ${task.userStory}`,
|
|
237
|
+
suggestedFix: `Either link task to US-${String(acUSNumber).padStart(3, '0')} or use different AC-ID`
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return errors;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Extract US number from AC-ID (AC-US1-01 → 1)
|
|
247
|
+
*/
|
|
248
|
+
function extractUSNumberFromACId(acId) {
|
|
249
|
+
const match = acId.match(/^AC-US(\d+)-\d{2}$/);
|
|
250
|
+
return match ? parseInt(match[1], 10) : -1;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Extract US number from US-ID (US-001 → 1, US-1000 → 1000)
|
|
254
|
+
*/
|
|
255
|
+
function extractUSNumber(usId) {
|
|
256
|
+
const match = usId.match(/^US-(\d{3,})$/);
|
|
257
|
+
return match ? parseInt(match[1], 10) : -1;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get all tasks (flattened, not grouped by US)
|
|
261
|
+
*
|
|
262
|
+
* @param tasksByUS - Tasks grouped by User Story
|
|
263
|
+
* @returns Array of all tasks
|
|
264
|
+
*/
|
|
265
|
+
export function getAllTasks(tasksByUS) {
|
|
266
|
+
return Object.values(tasksByUS).flat();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Count tasks by status
|
|
270
|
+
*
|
|
271
|
+
* @param tasksByUS - Tasks grouped by User Story
|
|
272
|
+
* @returns Map of status → count
|
|
273
|
+
*/
|
|
274
|
+
export function countTasksByStatus(tasksByUS) {
|
|
275
|
+
const counts = {
|
|
276
|
+
pending: 0,
|
|
277
|
+
in_progress: 0,
|
|
278
|
+
completed: 0,
|
|
279
|
+
transferred: 0,
|
|
280
|
+
canceled: 0
|
|
281
|
+
};
|
|
282
|
+
for (const task of getAllTasks(tasksByUS)) {
|
|
283
|
+
counts[task.status]++;
|
|
284
|
+
}
|
|
285
|
+
return counts;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Calculate completion percentage
|
|
289
|
+
*
|
|
290
|
+
* @param tasksByUS - Tasks grouped by User Story
|
|
291
|
+
* @returns Completion percentage (0-100)
|
|
292
|
+
*/
|
|
293
|
+
export function calculateCompletionPercentage(tasksByUS) {
|
|
294
|
+
const allTasks = getAllTasks(tasksByUS);
|
|
295
|
+
if (allTasks.length === 0)
|
|
296
|
+
return 0;
|
|
297
|
+
const completedTasks = allTasks.filter(t => t.status === 'completed').length;
|
|
298
|
+
return Math.round((completedTasks / allTasks.length) * 100);
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=task-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-parser.js","sourceRoot":"","sources":["../../../../src/generators/spec/task-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Config — Permission Presets & Config Validation
|
|
3
|
+
*
|
|
4
|
+
* ADR-0236: Named presets replace 8+ booleans.
|
|
5
|
+
* 4 presets: read-only, push-only, bidirectional, full-control
|
|
6
|
+
* With optional per-flag overrides.
|
|
7
|
+
*/
|
|
8
|
+
export type SyncPreset = 'read-only' | 'push-only' | 'bidirectional' | 'full-control';
|
|
9
|
+
export interface SyncPermissions {
|
|
10
|
+
canRead: boolean;
|
|
11
|
+
canUpdateStatus: boolean;
|
|
12
|
+
canUpsert: boolean;
|
|
13
|
+
canDelete: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** Legacy settings from the old boolean-based system */
|
|
16
|
+
export interface LegacySyncSettings {
|
|
17
|
+
canUpsertInternalItems?: boolean;
|
|
18
|
+
canUpdateExternalItems?: boolean;
|
|
19
|
+
canUpdateStatus?: boolean;
|
|
20
|
+
autoSyncOnCompletion?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const PRESET_DEFAULTS: Record<SyncPreset, SyncPermissions>;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve effective permissions from preset + overrides + legacy settings.
|
|
25
|
+
*
|
|
26
|
+
* Priority: preset → overrides → effective
|
|
27
|
+
* If no preset, falls back to legacy boolean settings.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolvePermissions(preset?: SyncPreset, overrides?: Partial<SyncPermissions>, legacySettings?: LegacySyncSettings): SyncPermissions;
|
|
30
|
+
export interface SyncConfigIssue {
|
|
31
|
+
type: 'contradiction' | 'warning' | 'failure';
|
|
32
|
+
message: string;
|
|
33
|
+
suggestedFix: string;
|
|
34
|
+
}
|
|
35
|
+
interface PartialSyncConfig {
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
settings?: {
|
|
38
|
+
canUpsertInternalItems?: boolean;
|
|
39
|
+
canUpdateExternalItems?: boolean;
|
|
40
|
+
canUpdateStatus?: boolean;
|
|
41
|
+
autoSyncOnCompletion?: boolean;
|
|
42
|
+
};
|
|
43
|
+
github?: {
|
|
44
|
+
enabled?: boolean;
|
|
45
|
+
owner?: string;
|
|
46
|
+
repo?: string;
|
|
47
|
+
};
|
|
48
|
+
jira?: {
|
|
49
|
+
enabled?: boolean;
|
|
50
|
+
domain?: string;
|
|
51
|
+
projectKey?: string;
|
|
52
|
+
};
|
|
53
|
+
ado?: {
|
|
54
|
+
enabled?: boolean;
|
|
55
|
+
organization?: string;
|
|
56
|
+
project?: string;
|
|
57
|
+
};
|
|
58
|
+
preset?: SyncPreset;
|
|
59
|
+
profiles?: Record<string, {
|
|
60
|
+
provider?: string;
|
|
61
|
+
config?: Record<string, unknown>;
|
|
62
|
+
}>;
|
|
63
|
+
}
|
|
64
|
+
interface PlatformSyncMetadata {
|
|
65
|
+
lastSyncResult?: string;
|
|
66
|
+
lastImportCount?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validate sync configuration for consistency and report issues.
|
|
70
|
+
*/
|
|
71
|
+
export declare function validateSyncConfigConsistency(config: PartialSyncConfig, syncMetadata?: Record<string, PlatformSyncMetadata>): SyncConfigIssue[];
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Config — Permission Presets & Config Validation
|
|
3
|
+
*
|
|
4
|
+
* ADR-0236: Named presets replace 8+ booleans.
|
|
5
|
+
* 4 presets: read-only, push-only, bidirectional, full-control
|
|
6
|
+
* With optional per-flag overrides.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Preset defaults
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export const PRESET_DEFAULTS = {
|
|
12
|
+
'read-only': {
|
|
13
|
+
canRead: true,
|
|
14
|
+
canUpdateStatus: false,
|
|
15
|
+
canUpsert: false,
|
|
16
|
+
canDelete: false,
|
|
17
|
+
},
|
|
18
|
+
'push-only': {
|
|
19
|
+
canRead: false,
|
|
20
|
+
canUpdateStatus: true,
|
|
21
|
+
canUpsert: true,
|
|
22
|
+
canDelete: false,
|
|
23
|
+
},
|
|
24
|
+
bidirectional: {
|
|
25
|
+
canRead: true,
|
|
26
|
+
canUpdateStatus: true,
|
|
27
|
+
canUpsert: true,
|
|
28
|
+
canDelete: false,
|
|
29
|
+
},
|
|
30
|
+
'full-control': {
|
|
31
|
+
canRead: true,
|
|
32
|
+
canUpdateStatus: true,
|
|
33
|
+
canUpsert: true,
|
|
34
|
+
canDelete: true,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Permission resolution
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/**
|
|
41
|
+
* Resolve effective permissions from preset + overrides + legacy settings.
|
|
42
|
+
*
|
|
43
|
+
* Priority: preset → overrides → effective
|
|
44
|
+
* If no preset, falls back to legacy boolean settings.
|
|
45
|
+
*/
|
|
46
|
+
export function resolvePermissions(preset, overrides, legacySettings) {
|
|
47
|
+
let base;
|
|
48
|
+
if (preset && PRESET_DEFAULTS[preset]) {
|
|
49
|
+
base = { ...PRESET_DEFAULTS[preset] };
|
|
50
|
+
}
|
|
51
|
+
else if (legacySettings) {
|
|
52
|
+
// Backward compat: map old booleans to new permissions
|
|
53
|
+
base = {
|
|
54
|
+
canRead: legacySettings.canUpdateExternalItems ?? true,
|
|
55
|
+
canUpdateStatus: legacySettings.canUpdateStatus ?? true,
|
|
56
|
+
canUpsert: legacySettings.canUpsertInternalItems ?? true,
|
|
57
|
+
canDelete: false, // legacy system had no delete
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Default to read-only
|
|
62
|
+
base = { ...PRESET_DEFAULTS['read-only'] };
|
|
63
|
+
}
|
|
64
|
+
if (overrides) {
|
|
65
|
+
if (overrides.canRead !== undefined)
|
|
66
|
+
base.canRead = overrides.canRead;
|
|
67
|
+
if (overrides.canUpdateStatus !== undefined)
|
|
68
|
+
base.canUpdateStatus = overrides.canUpdateStatus;
|
|
69
|
+
if (overrides.canUpsert !== undefined)
|
|
70
|
+
base.canUpsert = overrides.canUpsert;
|
|
71
|
+
if (overrides.canDelete !== undefined)
|
|
72
|
+
base.canDelete = overrides.canDelete;
|
|
73
|
+
}
|
|
74
|
+
return base;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validate sync configuration for consistency and report issues.
|
|
78
|
+
*/
|
|
79
|
+
export function validateSyncConfigConsistency(config, syncMetadata) {
|
|
80
|
+
const issues = [];
|
|
81
|
+
// Check: enabled=false with write flags=true
|
|
82
|
+
if (config.enabled === false && config.settings) {
|
|
83
|
+
const { canUpsertInternalItems, canUpdateExternalItems, canUpdateStatus } = config.settings;
|
|
84
|
+
if (canUpsertInternalItems || canUpdateExternalItems || canUpdateStatus) {
|
|
85
|
+
issues.push({
|
|
86
|
+
type: 'contradiction',
|
|
87
|
+
message: 'Sync is disabled but write permissions are enabled. The effective behavior is disabled (sync.enabled=false overrides all).',
|
|
88
|
+
suggestedFix: 'Either set sync.enabled=true to use the permissions, or set all permission flags to false.',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check: provider enabled but incomplete config (legacy format only)
|
|
93
|
+
// Skip these checks when the provider is configured via profiles instead
|
|
94
|
+
if (config.enabled !== false) {
|
|
95
|
+
const profileProviders = new Set(Object.values(config.profiles ?? {}).map((p) => p.provider).filter(Boolean));
|
|
96
|
+
if (config.github?.enabled && !config.github.owner && !config.github.repo && !profileProviders.has('github')) {
|
|
97
|
+
issues.push({
|
|
98
|
+
type: 'warning',
|
|
99
|
+
message: 'GitHub sync enabled but github.owner and github.repo are not configured.',
|
|
100
|
+
suggestedFix: 'Set sync.github.owner and sync.github.repo in config.json, or run /sw:sync-setup.',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (config.jira?.enabled && !config.jira.domain && !profileProviders.has('jira')) {
|
|
104
|
+
issues.push({
|
|
105
|
+
type: 'warning',
|
|
106
|
+
message: 'JIRA sync enabled but jira.domain is not configured.',
|
|
107
|
+
suggestedFix: 'Set sync.jira.domain and sync.jira.projectKey in config.json.',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (config.ado?.enabled && !config.ado.organization && !profileProviders.has('ado')) {
|
|
111
|
+
issues.push({
|
|
112
|
+
type: 'warning',
|
|
113
|
+
message: 'ADO sync enabled but ado.organization is not configured.',
|
|
114
|
+
suggestedFix: 'Set sync.ado.organization and sync.ado.project in config.json.',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Check sync metadata for failures
|
|
119
|
+
if (syncMetadata) {
|
|
120
|
+
for (const [platform, meta] of Object.entries(syncMetadata)) {
|
|
121
|
+
if (meta.lastSyncResult === 'failed') {
|
|
122
|
+
issues.push({
|
|
123
|
+
type: 'failure',
|
|
124
|
+
message: `${platform} sync last result was "failed" with ${meta.lastImportCount ?? 0} imports.`,
|
|
125
|
+
suggestedFix: `Check ${platform} credentials and configuration. Run /sw:sync-setup to reconfigure.`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return issues;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/sync/config.ts"],"names":[],"mappings":"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"}
|