specweave 0.29.0 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -1
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +12 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +18 -0
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts +0 -26
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js +0 -249
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +0 -28
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +0 -156
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +0 -1
- package/dist/src/core/sync/bidirectional-engine.d.ts +0 -119
- package/dist/src/core/sync/bidirectional-engine.d.ts.map +0 -1
- package/dist/src/core/sync/bidirectional-engine.js +0 -359
- package/dist/src/core/sync/bidirectional-engine.js.map +0 -1
- package/dist/src/core/sync/conflict-resolver.d.ts +0 -66
- package/dist/src/core/sync/conflict-resolver.d.ts.map +0 -1
- package/dist/src/core/sync/conflict-resolver.js +0 -108
- package/dist/src/core/sync/conflict-resolver.js.map +0 -1
- package/dist/src/core/sync/enhanced-content-builder.d.ts +0 -55
- package/dist/src/core/sync/enhanced-content-builder.d.ts.map +0 -1
- package/dist/src/core/sync/enhanced-content-builder.js +0 -203
- package/dist/src/core/sync/enhanced-content-builder.js.map +0 -1
- package/dist/src/core/sync/folder-mapper.d.ts +0 -71
- package/dist/src/core/sync/folder-mapper.d.ts.map +0 -1
- package/dist/src/core/sync/folder-mapper.js +0 -203
- package/dist/src/core/sync/folder-mapper.js.map +0 -1
- package/dist/src/core/sync/label-detector.d.ts +0 -66
- package/dist/src/core/sync/label-detector.d.ts.map +0 -1
- package/dist/src/core/sync/label-detector.js +0 -224
- package/dist/src/core/sync/label-detector.js.map +0 -1
- package/dist/src/core/sync/performance-optimizer.d.ts +0 -153
- package/dist/src/core/sync/performance-optimizer.d.ts.map +0 -1
- package/dist/src/core/sync/performance-optimizer.js +0 -220
- package/dist/src/core/sync/performance-optimizer.js.map +0 -1
- package/dist/src/core/sync/profile-selector.d.ts +0 -52
- package/dist/src/core/sync/profile-selector.d.ts.map +0 -1
- package/dist/src/core/sync/profile-selector.js +0 -179
- package/dist/src/core/sync/profile-selector.js.map +0 -1
- package/dist/src/core/sync/profile-validator.d.ts +0 -52
- package/dist/src/core/sync/profile-validator.d.ts.map +0 -1
- package/dist/src/core/sync/profile-validator.js +0 -170
- package/dist/src/core/sync/profile-validator.js.map +0 -1
- package/dist/src/core/sync/rate-limiter.d.ts +0 -116
- package/dist/src/core/sync/rate-limiter.d.ts.map +0 -1
- package/dist/src/core/sync/rate-limiter.js +0 -308
- package/dist/src/core/sync/rate-limiter.js.map +0 -1
- package/dist/src/core/sync/retry-handler.d.ts +0 -98
- package/dist/src/core/sync/retry-handler.d.ts.map +0 -1
- package/dist/src/core/sync/retry-handler.js +0 -196
- package/dist/src/core/sync/retry-handler.js.map +0 -1
- package/dist/src/core/sync/retry-logic.d.ts +0 -64
- package/dist/src/core/sync/retry-logic.d.ts.map +0 -1
- package/dist/src/core/sync/retry-logic.js +0 -165
- package/dist/src/core/sync/retry-logic.js.map +0 -1
- package/dist/src/core/sync/status-cache.d.ts +0 -91
- package/dist/src/core/sync/status-cache.d.ts.map +0 -1
- package/dist/src/core/sync/status-cache.js +0 -140
- package/dist/src/core/sync/status-cache.js.map +0 -1
- package/dist/src/core/sync/status-mapper.d.ts +0 -69
- package/dist/src/core/sync/status-mapper.d.ts.map +0 -1
- package/dist/src/core/sync/status-mapper.js +0 -90
- package/dist/src/core/sync/status-mapper.js.map +0 -1
- package/dist/src/core/sync/status-sync-engine.d.ts +0 -162
- package/dist/src/core/sync/status-sync-engine.d.ts.map +0 -1
- package/dist/src/core/sync/status-sync-engine.js +0 -347
- package/dist/src/core/sync/status-sync-engine.js.map +0 -1
- package/dist/src/core/sync/sync-event-logger.d.ts +0 -113
- package/dist/src/core/sync/sync-event-logger.d.ts.map +0 -1
- package/dist/src/core/sync/sync-event-logger.js +0 -141
- package/dist/src/core/sync/sync-event-logger.js.map +0 -1
- package/dist/src/core/sync/time-range-selector.d.ts +0 -48
- package/dist/src/core/sync/time-range-selector.d.ts.map +0 -1
- package/dist/src/core/sync/time-range-selector.js +0 -224
- package/dist/src/core/sync/time-range-selector.js.map +0 -1
- package/dist/src/core/sync/types.d.ts +0 -52
- package/dist/src/core/sync/types.d.ts.map +0 -1
- package/dist/src/core/sync/types.js +0 -5
- package/dist/src/core/sync/types.js.map +0 -1
- package/dist/src/core/sync/workflow-detector.d.ts +0 -95
- package/dist/src/core/sync/workflow-detector.d.ts.map +0 -1
- package/dist/src/core/sync/workflow-detector.js +0 -175
- package/dist/src/core/sync/workflow-detector.js.map +0 -1
- package/plugins/specweave-github/lib/enhanced-github-sync.js +0 -220
- package/plugins/specweave-github/lib/enhanced-github-sync.ts +0 -322
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +0 -134
- package/plugins/specweave-jira/lib/enhanced-jira-sync.ts +0 -196
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conflict Resolver
|
|
3
|
-
*
|
|
4
|
-
* Detects and resolves status conflicts between SpecWeave increments
|
|
5
|
-
* and external tools (GitHub, JIRA, Azure DevOps).
|
|
6
|
-
*
|
|
7
|
-
* Supports four resolution strategies:
|
|
8
|
-
* - prompt: Requires user interaction (UI)
|
|
9
|
-
* - last-write-wins: Uses most recent timestamp
|
|
10
|
-
* - specweave-wins: Always uses local SpecWeave status
|
|
11
|
-
* - external-wins: Always uses external tool status
|
|
12
|
-
*/
|
|
13
|
-
export class ConflictResolver {
|
|
14
|
-
/**
|
|
15
|
-
* Detect status conflicts between local and remote
|
|
16
|
-
*
|
|
17
|
-
* @param input - Detection input with local/remote statuses and timestamps
|
|
18
|
-
* @returns StatusConflict if conflict exists, null if statuses match
|
|
19
|
-
*/
|
|
20
|
-
async detect(input) {
|
|
21
|
-
// No conflict if statuses match
|
|
22
|
-
if (input.local === input.remote) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
// Conflict detected - return conflict object
|
|
26
|
-
return {
|
|
27
|
-
incrementId: input.incrementId,
|
|
28
|
-
tool: input.tool,
|
|
29
|
-
localStatus: input.local,
|
|
30
|
-
remoteStatus: input.remote,
|
|
31
|
-
localTimestamp: input.localTimestamp,
|
|
32
|
-
remoteTimestamp: input.remoteTimestamp
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Resolve status conflict using specified strategy
|
|
37
|
-
*
|
|
38
|
-
* @param conflict - The status conflict to resolve
|
|
39
|
-
* @param strategy - Resolution strategy to use
|
|
40
|
-
* @returns Resolution with action and resolved status
|
|
41
|
-
* @throws Error if strategy is unknown or requires user interaction
|
|
42
|
-
*/
|
|
43
|
-
async resolve(conflict, strategy) {
|
|
44
|
-
switch (strategy) {
|
|
45
|
-
case 'specweave-wins':
|
|
46
|
-
return {
|
|
47
|
-
action: 'use-local',
|
|
48
|
-
resolvedStatus: conflict.localStatus
|
|
49
|
-
};
|
|
50
|
-
case 'external-wins':
|
|
51
|
-
return {
|
|
52
|
-
action: 'use-remote',
|
|
53
|
-
resolvedStatus: conflict.remoteStatus
|
|
54
|
-
};
|
|
55
|
-
case 'last-write-wins':
|
|
56
|
-
return this.resolveByTimestamp(conflict);
|
|
57
|
-
case 'prompt':
|
|
58
|
-
throw new Error('Prompt strategy requires user interaction');
|
|
59
|
-
default:
|
|
60
|
-
throw new Error(`Unknown conflict resolution strategy: ${strategy}`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Resolve conflict by comparing timestamps (last-write-wins)
|
|
65
|
-
*
|
|
66
|
-
* @param conflict - The status conflict to resolve
|
|
67
|
-
* @returns Resolution based on most recent timestamp
|
|
68
|
-
*/
|
|
69
|
-
resolveByTimestamp(conflict) {
|
|
70
|
-
const localTime = new Date(conflict.localTimestamp).getTime();
|
|
71
|
-
const remoteTime = new Date(conflict.remoteTimestamp).getTime();
|
|
72
|
-
// If timestamps equal, tie-break favors local (SpecWeave is source of truth)
|
|
73
|
-
if (localTime >= remoteTime) {
|
|
74
|
-
return {
|
|
75
|
-
action: 'use-local',
|
|
76
|
-
resolvedStatus: conflict.localStatus
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
action: 'use-remote',
|
|
81
|
-
resolvedStatus: conflict.remoteStatus
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Format conflict details for display to user
|
|
86
|
-
*
|
|
87
|
-
* @param conflict - The status conflict to format
|
|
88
|
-
* @returns Human-readable conflict message
|
|
89
|
-
*/
|
|
90
|
-
formatConflictMessage(conflict) {
|
|
91
|
-
return `
|
|
92
|
-
Status Conflict Detected for Increment ${conflict.incrementId}
|
|
93
|
-
|
|
94
|
-
Tool: ${conflict.tool}
|
|
95
|
-
|
|
96
|
-
Local (SpecWeave):
|
|
97
|
-
Status: ${conflict.localStatus}
|
|
98
|
-
Last Updated: ${conflict.localTimestamp}
|
|
99
|
-
|
|
100
|
-
Remote (${conflict.tool}):
|
|
101
|
-
Status: ${conflict.remoteStatus}
|
|
102
|
-
Last Updated: ${conflict.remoteTimestamp}
|
|
103
|
-
|
|
104
|
-
Conflict: Local and remote statuses differ.
|
|
105
|
-
`.trim();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
//# sourceMappingURL=conflict-resolver.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conflict-resolver.js","sourceRoot":"","sources":["../../../../src/core/sync/conflict-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA+BH,MAAM,OAAO,gBAAgB;IAC3B;;;;;OAKG;IACI,KAAK,CAAC,MAAM,CAAC,KAA6B;QAC/C,gCAAgC;QAChC,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,6CAA6C;QAC7C,OAAO;YACL,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,KAAK;YACxB,YAAY,EAAE,KAAK,CAAC,MAAM;YAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,eAAe,EAAE,KAAK,CAAC,eAAe;SACvC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,OAAO,CAClB,QAAwB,EACxB,QAAoC;QAEpC,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,gBAAgB;gBACnB,OAAO;oBACL,MAAM,EAAE,WAAW;oBACnB,cAAc,EAAE,QAAQ,CAAC,WAAW;iBACrC,CAAC;YAEJ,KAAK,eAAe;gBAClB,OAAO;oBACL,MAAM,EAAE,YAAY;oBACpB,cAAc,EAAE,QAAQ,CAAC,YAAY;iBACtC,CAAC;YAEJ,KAAK,iBAAiB;gBACpB,OAAO,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAE3C,KAAK,QAAQ;gBACX,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAE/D;gBACE,MAAM,IAAI,KAAK,CAAC,yCAAyC,QAAQ,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,kBAAkB,CAAC,QAAwB;QACjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC;QAC9D,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,CAAC;QAEhE,6EAA6E;QAC7E,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;YAC5B,OAAO;gBACL,MAAM,EAAE,WAAW;gBACnB,cAAc,EAAE,QAAQ,CAAC,WAAW;aACrC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,cAAc,EAAE,QAAQ,CAAC,YAAY;SACtC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACI,qBAAqB,CAAC,QAAwB;QACnD,OAAO;yCAC8B,QAAQ,CAAC,WAAW;;QAErD,QAAQ,CAAC,IAAI;;;YAGT,QAAQ,CAAC,WAAW;kBACd,QAAQ,CAAC,cAAc;;UAE/B,QAAQ,CAAC,IAAI;YACX,QAAQ,CAAC,YAAY;kBACf,QAAQ,CAAC,eAAe;;;KAGrC,CAAC,IAAI,EAAE,CAAC;IACX,CAAC;CACF"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { SpecContent, UserStory, TaskLink, EnhancedSpecContent } from './types.js';
|
|
2
|
-
export { EnhancedSpecContent };
|
|
3
|
-
/**
|
|
4
|
-
* Enhanced Content Builder
|
|
5
|
-
*
|
|
6
|
-
* Builds rich external issue descriptions with full spec content
|
|
7
|
-
* for GitHub, JIRA, and Azure DevOps integrations.
|
|
8
|
-
*/
|
|
9
|
-
export declare class EnhancedContentBuilder {
|
|
10
|
-
/**
|
|
11
|
-
* Build complete external description from spec
|
|
12
|
-
*/
|
|
13
|
-
buildExternalDescription(spec: SpecContent): string;
|
|
14
|
-
/**
|
|
15
|
-
* Build summary section
|
|
16
|
-
*/
|
|
17
|
-
buildSummarySection(spec: SpecContent | {
|
|
18
|
-
summary: string;
|
|
19
|
-
}): string;
|
|
20
|
-
/**
|
|
21
|
-
* Build user stories section with collapsible details
|
|
22
|
-
*/
|
|
23
|
-
buildUserStoriesSection(userStories: UserStory[]): string;
|
|
24
|
-
/**
|
|
25
|
-
* Build individual user story with collapsible details
|
|
26
|
-
*/
|
|
27
|
-
private buildUserStoryDetails;
|
|
28
|
-
/**
|
|
29
|
-
* Group acceptance criteria by priority
|
|
30
|
-
*/
|
|
31
|
-
private groupAcceptanceCriteriaByPriority;
|
|
32
|
-
/**
|
|
33
|
-
* Build tasks section with GitHub issue links
|
|
34
|
-
* Supports both simple array and options object for backward compatibility
|
|
35
|
-
*/
|
|
36
|
-
buildTasksSection(tasks: TaskLink[] | any, ownerOrOptions?: string | {
|
|
37
|
-
showCheckboxes?: boolean;
|
|
38
|
-
showProgressBar?: boolean;
|
|
39
|
-
showCompletionStatus?: boolean;
|
|
40
|
-
provider?: string;
|
|
41
|
-
}, repo?: string): string;
|
|
42
|
-
/**
|
|
43
|
-
* Build architecture section
|
|
44
|
-
*/
|
|
45
|
-
buildArchitectureSection(docs: string[]): string;
|
|
46
|
-
/**
|
|
47
|
-
* Build source links section
|
|
48
|
-
*/
|
|
49
|
-
buildSourceLinksSection(sourceLinks: {
|
|
50
|
-
spec: string;
|
|
51
|
-
plan: string;
|
|
52
|
-
tasks: string;
|
|
53
|
-
}): string;
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=enhanced-content-builder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enhanced-content-builder.d.ts","sourceRoot":"","sources":["../../../../src/core/sync/enhanced-content-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAuB,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGxG,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B;;;;;GAKG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACI,wBAAwB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM;IA2B1D;;OAEG;IACI,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAI3E;;OAEG;IACI,uBAAuB,CAAC,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM;IAehE;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0C7B;;OAEG;IACH,OAAO,CAAC,iCAAiC;IAoBzC;;;OAGG;IACI,iBAAiB,CACtB,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,EACvB,cAAc,CAAC,EAAE,MAAM,GAAG;QAAE,cAAc,CAAC,EAAE,OAAO,CAAC;QAAC,eAAe,CAAC,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EACpI,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM;IAyET;;OAEG;IACI,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM;IAcvD;;OAEG;IACI,uBAAuB,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;CASnG"}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhanced Content Builder
|
|
3
|
-
*
|
|
4
|
-
* Builds rich external issue descriptions with full spec content
|
|
5
|
-
* for GitHub, JIRA, and Azure DevOps integrations.
|
|
6
|
-
*/
|
|
7
|
-
export class EnhancedContentBuilder {
|
|
8
|
-
/**
|
|
9
|
-
* Build complete external description from spec
|
|
10
|
-
*/
|
|
11
|
-
buildExternalDescription(spec) {
|
|
12
|
-
const sections = [];
|
|
13
|
-
// 1. Executive Summary
|
|
14
|
-
sections.push(this.buildSummarySection(spec));
|
|
15
|
-
// 2. User Stories (collapsible in GitHub)
|
|
16
|
-
sections.push(this.buildUserStoriesSection(spec.userStories));
|
|
17
|
-
// 3. Linked Tasks (if available)
|
|
18
|
-
if (spec.tasks && spec.tasks.length > 0) {
|
|
19
|
-
sections.push(this.buildTasksSection(spec.tasks));
|
|
20
|
-
}
|
|
21
|
-
// 4. Architecture References (if available)
|
|
22
|
-
if (spec.architectureDocs && spec.architectureDocs.length > 0) {
|
|
23
|
-
sections.push(this.buildArchitectureSection(spec.architectureDocs));
|
|
24
|
-
}
|
|
25
|
-
// 5. Source Links (if available)
|
|
26
|
-
if (spec.sourceLinks) {
|
|
27
|
-
sections.push(this.buildSourceLinksSection(spec.sourceLinks));
|
|
28
|
-
}
|
|
29
|
-
return sections.join('\n\n');
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Build summary section
|
|
33
|
-
*/
|
|
34
|
-
buildSummarySection(spec) {
|
|
35
|
-
return `## Summary\n\n${spec.summary}`;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Build user stories section with collapsible details
|
|
39
|
-
*/
|
|
40
|
-
buildUserStoriesSection(userStories) {
|
|
41
|
-
if (!userStories || userStories.length === 0) {
|
|
42
|
-
return `## User Stories\n\nNo user stories defined.`;
|
|
43
|
-
}
|
|
44
|
-
const sections = ['## User Stories'];
|
|
45
|
-
for (const story of userStories) {
|
|
46
|
-
const storySection = this.buildUserStoryDetails(story);
|
|
47
|
-
sections.push(storySection);
|
|
48
|
-
}
|
|
49
|
-
return sections.join('\n\n');
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Build individual user story with collapsible details
|
|
53
|
-
*/
|
|
54
|
-
buildUserStoryDetails(story) {
|
|
55
|
-
const lines = [];
|
|
56
|
-
// Use GitHub collapsible format
|
|
57
|
-
lines.push(`<details>`);
|
|
58
|
-
lines.push(`<summary><strong>${story.id}: ${story.title}</strong></summary>`);
|
|
59
|
-
lines.push('');
|
|
60
|
-
// Add description if available
|
|
61
|
-
if (story.description) {
|
|
62
|
-
lines.push(`**Description**: ${story.description}`);
|
|
63
|
-
lines.push('');
|
|
64
|
-
}
|
|
65
|
-
// Acceptance Criteria
|
|
66
|
-
if (story.acceptanceCriteria && story.acceptanceCriteria.length > 0) {
|
|
67
|
-
lines.push('**Acceptance Criteria**:');
|
|
68
|
-
lines.push('');
|
|
69
|
-
// Group by priority
|
|
70
|
-
const byPriority = this.groupAcceptanceCriteriaByPriority(story.acceptanceCriteria);
|
|
71
|
-
for (const priority of ['P1', 'P2', 'P3', 'OTHER']) {
|
|
72
|
-
const criteria = byPriority[priority];
|
|
73
|
-
if (criteria && criteria.length > 0) {
|
|
74
|
-
for (const ac of criteria) {
|
|
75
|
-
const priorityLabel = ac.priority ? ` (${ac.priority})` : '';
|
|
76
|
-
const checkbox = ac.completed ? '[x]' : '[ ]';
|
|
77
|
-
lines.push(`- ${checkbox} **${ac.id}**${priorityLabel}: ${ac.description}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
lines.push('**Acceptance Criteria**: No acceptance criteria defined.');
|
|
84
|
-
}
|
|
85
|
-
lines.push('');
|
|
86
|
-
lines.push('</details>');
|
|
87
|
-
return lines.join('\n');
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Group acceptance criteria by priority
|
|
91
|
-
*/
|
|
92
|
-
groupAcceptanceCriteriaByPriority(criteria) {
|
|
93
|
-
const grouped = {
|
|
94
|
-
P1: [],
|
|
95
|
-
P2: [],
|
|
96
|
-
P3: [],
|
|
97
|
-
OTHER: [] // For criteria without priority or with other priorities
|
|
98
|
-
};
|
|
99
|
-
for (const ac of criteria) {
|
|
100
|
-
const priority = ac.priority || 'OTHER';
|
|
101
|
-
if (priority in grouped) {
|
|
102
|
-
grouped[priority].push(ac);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
grouped.OTHER.push(ac);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return grouped;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Build tasks section with GitHub issue links
|
|
112
|
-
* Supports both simple array and options object for backward compatibility
|
|
113
|
-
*/
|
|
114
|
-
buildTasksSection(tasks, ownerOrOptions, repo) {
|
|
115
|
-
// Handle both old and new signatures
|
|
116
|
-
let taskList;
|
|
117
|
-
let owner;
|
|
118
|
-
let options = {};
|
|
119
|
-
if (Array.isArray(tasks)) {
|
|
120
|
-
taskList = tasks;
|
|
121
|
-
if (typeof ownerOrOptions === 'string') {
|
|
122
|
-
owner = ownerOrOptions;
|
|
123
|
-
}
|
|
124
|
-
else if (typeof ownerOrOptions === 'object') {
|
|
125
|
-
options = ownerOrOptions;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
// tasks is actually taskMapping object
|
|
130
|
-
taskList = tasks?.tasks || [];
|
|
131
|
-
if (typeof ownerOrOptions === 'object') {
|
|
132
|
-
options = ownerOrOptions;
|
|
133
|
-
owner = tasks?.owner;
|
|
134
|
-
repo = tasks?.repo;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (!taskList || taskList.length === 0) {
|
|
138
|
-
return `## Tasks\n\nNo tasks defined.`;
|
|
139
|
-
}
|
|
140
|
-
const lines = ['## Tasks'];
|
|
141
|
-
lines.push('');
|
|
142
|
-
// Add progress bar if requested
|
|
143
|
-
if (options.showProgressBar && taskList.length > 0) {
|
|
144
|
-
const completed = taskList.filter(t => t.completed).length;
|
|
145
|
-
const total = taskList.length;
|
|
146
|
-
const percentage = Math.round((completed / total) * 100);
|
|
147
|
-
lines.push(`**Progress**: ${completed}/${total} tasks (${percentage}%)`);
|
|
148
|
-
lines.push('');
|
|
149
|
-
}
|
|
150
|
-
for (const task of taskList) {
|
|
151
|
-
let taskLine = '';
|
|
152
|
-
// Add checkbox if requested
|
|
153
|
-
if (options.showCheckboxes) {
|
|
154
|
-
taskLine += task.completed ? '- [x] ' : '- [ ] ';
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
taskLine += '- ';
|
|
158
|
-
}
|
|
159
|
-
taskLine += `**${task.id}**: ${task.title}`;
|
|
160
|
-
// Add GitHub issue link if available
|
|
161
|
-
if (task.githubIssue && owner && repo) {
|
|
162
|
-
const issueUrl = `https://github.com/${owner}/${repo}/issues/${task.githubIssue}`;
|
|
163
|
-
taskLine += ` ([#${task.githubIssue}](${issueUrl}))`;
|
|
164
|
-
}
|
|
165
|
-
// Add user story references
|
|
166
|
-
if (task.userStoryIds && task.userStoryIds.length > 0) {
|
|
167
|
-
taskLine += ` → Implements: ${task.userStoryIds.join(', ')}`;
|
|
168
|
-
}
|
|
169
|
-
// Add completion status if requested
|
|
170
|
-
if (options.showCompletionStatus && task.completed) {
|
|
171
|
-
taskLine += ' ✅';
|
|
172
|
-
}
|
|
173
|
-
lines.push(taskLine);
|
|
174
|
-
}
|
|
175
|
-
return lines.join('\n');
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Build architecture section
|
|
179
|
-
*/
|
|
180
|
-
buildArchitectureSection(docs) {
|
|
181
|
-
const lines = ['## Architecture'];
|
|
182
|
-
lines.push('');
|
|
183
|
-
lines.push('Related architecture documentation:');
|
|
184
|
-
lines.push('');
|
|
185
|
-
for (const doc of docs) {
|
|
186
|
-
const fileName = doc.split('/').pop() || doc;
|
|
187
|
-
lines.push(`- [${fileName}](${doc})`);
|
|
188
|
-
}
|
|
189
|
-
return lines.join('\n');
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Build source links section
|
|
193
|
-
*/
|
|
194
|
-
buildSourceLinksSection(sourceLinks) {
|
|
195
|
-
const lines = ['## Source Files'];
|
|
196
|
-
lines.push('');
|
|
197
|
-
lines.push(`- **Specification**: [spec.md](${sourceLinks.spec})`);
|
|
198
|
-
lines.push(`- **Technical Plan**: [plan.md](${sourceLinks.plan})`);
|
|
199
|
-
lines.push(`- **Task List**: [tasks.md](${sourceLinks.tasks})`);
|
|
200
|
-
return lines.join('\n');
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
//# sourceMappingURL=enhanced-content-builder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"enhanced-content-builder.js","sourceRoot":"","sources":["../../../../src/core/sync/enhanced-content-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Folder Mapper for Multi-Team Sync
|
|
3
|
-
*
|
|
4
|
-
* Maps sync profiles (ADO teams, Jira projects/components) to SpecWeave folder structure
|
|
5
|
-
*/
|
|
6
|
-
import { SyncProfile } from '../types/sync-profile.js';
|
|
7
|
-
/**
|
|
8
|
-
* Get specs folders for a sync profile
|
|
9
|
-
*
|
|
10
|
-
* Returns array of folders for multi-team profiles:
|
|
11
|
-
* - ADO with teams: Multiple folders (one per team)
|
|
12
|
-
* - Jira project-per-team: Multiple folders (one per project)
|
|
13
|
-
* - Jira shared-project-with-components: Multiple folders (one per component)
|
|
14
|
-
* - GitHub: Single folder (repo name)
|
|
15
|
-
*
|
|
16
|
-
* @param profile - Sync profile
|
|
17
|
-
* @returns Array of folder paths relative to project root
|
|
18
|
-
*/
|
|
19
|
-
export declare function getSpecsFoldersForProfile(profile: SyncProfile): string[];
|
|
20
|
-
/**
|
|
21
|
-
* Get Area Path for ADO team
|
|
22
|
-
*
|
|
23
|
-
* ADO Area Path format: "Project\\Team Name"
|
|
24
|
-
* Special case: If team name matches project name, use just project name
|
|
25
|
-
*
|
|
26
|
-
* Examples:
|
|
27
|
-
* - getAreaPathForTeam("League Scheduler", "League Scheduler Team") → "League Scheduler"
|
|
28
|
-
* - getAreaPathForTeam("League Scheduler", "Platform Engineering Team") → "League Scheduler\\Platform Engineering Team"
|
|
29
|
-
*
|
|
30
|
-
* @param project - ADO project name
|
|
31
|
-
* @param team - Team name
|
|
32
|
-
* @returns Area Path string
|
|
33
|
-
*/
|
|
34
|
-
export declare function getAreaPathForTeam(project: string, team: string): string;
|
|
35
|
-
/**
|
|
36
|
-
* Generate Area Paths map for ADO profile
|
|
37
|
-
*
|
|
38
|
-
* Creates mapping from team folder names to ADO Area Paths
|
|
39
|
-
*
|
|
40
|
-
* Example:
|
|
41
|
-
* Input: project="League Scheduler", teams=["Platform Engineering Team", "QA Team"]
|
|
42
|
-
* Output: {
|
|
43
|
-
* "platform-engineering-team": "League Scheduler\\Platform Engineering Team",
|
|
44
|
-
* "qa-team": "League Scheduler\\QA Team"
|
|
45
|
-
* }
|
|
46
|
-
*
|
|
47
|
-
* @param project - ADO project name
|
|
48
|
-
* @param teams - Array of team names
|
|
49
|
-
* @returns Map of folder names to Area Paths
|
|
50
|
-
*/
|
|
51
|
-
export declare function generateAreaPaths(project: string, teams: string[]): Record<string, string>;
|
|
52
|
-
/**
|
|
53
|
-
* Get team folder name from Area Path
|
|
54
|
-
*
|
|
55
|
-
* Reverse mapping: "League Scheduler\\Platform Engineering Team" → "platform-engineering-team"
|
|
56
|
-
*
|
|
57
|
-
* @param areaPath - ADO Area Path
|
|
58
|
-
* @returns Folder name (kebab-case)
|
|
59
|
-
*/
|
|
60
|
-
export declare function getFolderNameFromAreaPath(areaPath: string): string;
|
|
61
|
-
/**
|
|
62
|
-
* Get team/project identifier from folder name
|
|
63
|
-
*
|
|
64
|
-
* Maps folder name back to original team/project name
|
|
65
|
-
*
|
|
66
|
-
* @param profile - Sync profile
|
|
67
|
-
* @param folderName - Folder name (kebab-case)
|
|
68
|
-
* @returns Original team/project name, or null if not found
|
|
69
|
-
*/
|
|
70
|
-
export declare function getTeamFromFolder(profile: SyncProfile, folderName: string): string | null;
|
|
71
|
-
//# sourceMappingURL=folder-mapper.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"folder-mapper.d.ts","sourceRoot":"","sources":["../../../../src/core/sync/folder-mapper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,WAAW,EAIZ,MAAM,0BAA0B,CAAC;AAGlC;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,CAyDxE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAYxE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAAE,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAoDf"}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Folder Mapper for Multi-Team Sync
|
|
3
|
-
*
|
|
4
|
-
* Maps sync profiles (ADO teams, Jira projects/components) to SpecWeave folder structure
|
|
5
|
-
*/
|
|
6
|
-
import { slugify } from '../../utils/string-utils.js';
|
|
7
|
-
/**
|
|
8
|
-
* Get specs folders for a sync profile
|
|
9
|
-
*
|
|
10
|
-
* Returns array of folders for multi-team profiles:
|
|
11
|
-
* - ADO with teams: Multiple folders (one per team)
|
|
12
|
-
* - Jira project-per-team: Multiple folders (one per project)
|
|
13
|
-
* - Jira shared-project-with-components: Multiple folders (one per component)
|
|
14
|
-
* - GitHub: Single folder (repo name)
|
|
15
|
-
*
|
|
16
|
-
* @param profile - Sync profile
|
|
17
|
-
* @returns Array of folder paths relative to project root
|
|
18
|
-
*/
|
|
19
|
-
export function getSpecsFoldersForProfile(profile) {
|
|
20
|
-
const folders = [];
|
|
21
|
-
if (profile.provider === 'ado') {
|
|
22
|
-
const config = profile.config;
|
|
23
|
-
// v0.13.0+ architecture
|
|
24
|
-
if (config.projects && config.projects.length > 0) {
|
|
25
|
-
// Multiple projects → multiple folders
|
|
26
|
-
for (const project of config.projects) {
|
|
27
|
-
const folderName = slugify(project);
|
|
28
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
else if (config.areaPaths && config.areaPaths.length > 0) {
|
|
32
|
-
// Single project + area paths → multiple folders
|
|
33
|
-
for (const areaPath of config.areaPaths) {
|
|
34
|
-
const folderName = slugify(areaPath);
|
|
35
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
// Single project → default folder
|
|
40
|
-
const folderName = slugify(config.project || 'default');
|
|
41
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
else if (profile.provider === 'jira') {
|
|
45
|
-
const config = profile.config;
|
|
46
|
-
// v0.13.0+ architecture
|
|
47
|
-
if (config.projects && config.projects.length > 0) {
|
|
48
|
-
// Multiple projects → multiple folders
|
|
49
|
-
for (const projectKey of config.projects) {
|
|
50
|
-
const folderName = slugify(projectKey);
|
|
51
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
// Single project → single folder
|
|
56
|
-
const folderName = slugify(config.projectKey || 'default');
|
|
57
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else if (profile.provider === 'github') {
|
|
61
|
-
const config = profile.config;
|
|
62
|
-
// v0.13.0+ architecture
|
|
63
|
-
if (config.repos && config.repos.length > 0) {
|
|
64
|
-
// Multiple repos → multiple folders
|
|
65
|
-
for (const repo of config.repos) {
|
|
66
|
-
const folderName = slugify(repo);
|
|
67
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
// Single repo → single folder
|
|
72
|
-
const folderName = slugify(config.repo || 'default');
|
|
73
|
-
folders.push(`.specweave/docs/internal/specs/${folderName}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return folders;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Get Area Path for ADO team
|
|
80
|
-
*
|
|
81
|
-
* ADO Area Path format: "Project\\Team Name"
|
|
82
|
-
* Special case: If team name matches project name, use just project name
|
|
83
|
-
*
|
|
84
|
-
* Examples:
|
|
85
|
-
* - getAreaPathForTeam("League Scheduler", "League Scheduler Team") → "League Scheduler"
|
|
86
|
-
* - getAreaPathForTeam("League Scheduler", "Platform Engineering Team") → "League Scheduler\\Platform Engineering Team"
|
|
87
|
-
*
|
|
88
|
-
* @param project - ADO project name
|
|
89
|
-
* @param team - Team name
|
|
90
|
-
* @returns Area Path string
|
|
91
|
-
*/
|
|
92
|
-
export function getAreaPathForTeam(project, team) {
|
|
93
|
-
// Special case: If team name contains project name, use just project name
|
|
94
|
-
// "League Scheduler Team" in "League Scheduler" project → "League Scheduler"
|
|
95
|
-
const teamLower = team.toLowerCase();
|
|
96
|
-
const projectLower = project.toLowerCase();
|
|
97
|
-
if (teamLower.includes(projectLower) && teamLower.replace(/\s+team\s*$/i, '') === projectLower) {
|
|
98
|
-
return project;
|
|
99
|
-
}
|
|
100
|
-
// Default: "Project\\Team Name"
|
|
101
|
-
return `${project}\\${team}`;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Generate Area Paths map for ADO profile
|
|
105
|
-
*
|
|
106
|
-
* Creates mapping from team folder names to ADO Area Paths
|
|
107
|
-
*
|
|
108
|
-
* Example:
|
|
109
|
-
* Input: project="League Scheduler", teams=["Platform Engineering Team", "QA Team"]
|
|
110
|
-
* Output: {
|
|
111
|
-
* "platform-engineering-team": "League Scheduler\\Platform Engineering Team",
|
|
112
|
-
* "qa-team": "League Scheduler\\QA Team"
|
|
113
|
-
* }
|
|
114
|
-
*
|
|
115
|
-
* @param project - ADO project name
|
|
116
|
-
* @param teams - Array of team names
|
|
117
|
-
* @returns Map of folder names to Area Paths
|
|
118
|
-
*/
|
|
119
|
-
export function generateAreaPaths(project, teams) {
|
|
120
|
-
const areaPaths = {};
|
|
121
|
-
for (const team of teams) {
|
|
122
|
-
const folderName = slugify(team);
|
|
123
|
-
areaPaths[folderName] = getAreaPathForTeam(project, team);
|
|
124
|
-
}
|
|
125
|
-
return areaPaths;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Get team folder name from Area Path
|
|
129
|
-
*
|
|
130
|
-
* Reverse mapping: "League Scheduler\\Platform Engineering Team" → "platform-engineering-team"
|
|
131
|
-
*
|
|
132
|
-
* @param areaPath - ADO Area Path
|
|
133
|
-
* @returns Folder name (kebab-case)
|
|
134
|
-
*/
|
|
135
|
-
export function getFolderNameFromAreaPath(areaPath) {
|
|
136
|
-
// Extract team name from "Project\\Team Name"
|
|
137
|
-
const parts = areaPath.split('\\');
|
|
138
|
-
const teamName = parts.length > 1 ? parts[parts.length - 1] : parts[0];
|
|
139
|
-
return slugify(teamName);
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Get team/project identifier from folder name
|
|
143
|
-
*
|
|
144
|
-
* Maps folder name back to original team/project name
|
|
145
|
-
*
|
|
146
|
-
* @param profile - Sync profile
|
|
147
|
-
* @param folderName - Folder name (kebab-case)
|
|
148
|
-
* @returns Original team/project name, or null if not found
|
|
149
|
-
*/
|
|
150
|
-
export function getTeamFromFolder(profile, folderName) {
|
|
151
|
-
if (profile.provider === 'ado') {
|
|
152
|
-
const config = profile.config;
|
|
153
|
-
// v0.13.0+: Check projects[]
|
|
154
|
-
const projects = config.projects || [];
|
|
155
|
-
for (const project of projects) {
|
|
156
|
-
if (slugify(project) === folderName) {
|
|
157
|
-
return project;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
// v0.13.0+: Check areaPaths[]
|
|
161
|
-
const areaPaths = config.areaPaths || [];
|
|
162
|
-
for (const areaPath of areaPaths) {
|
|
163
|
-
if (slugify(areaPath) === folderName) {
|
|
164
|
-
return areaPath;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else if (profile.provider === 'jira') {
|
|
169
|
-
const config = profile.config;
|
|
170
|
-
// v0.13.0+: Check projects[]
|
|
171
|
-
const projects = config.projects || [];
|
|
172
|
-
for (const projectKey of projects) {
|
|
173
|
-
if (slugify(projectKey) === folderName) {
|
|
174
|
-
return projectKey;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
// Fallback to projectKey
|
|
178
|
-
if (config.projectKey && slugify(config.projectKey) === folderName) {
|
|
179
|
-
return config.projectKey;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else if (profile.provider === 'github') {
|
|
183
|
-
const config = profile.config;
|
|
184
|
-
// v0.13.0+: Check repos[]
|
|
185
|
-
const repos = config.repos || [];
|
|
186
|
-
for (const repo of repos) {
|
|
187
|
-
if (slugify(repo) === folderName) {
|
|
188
|
-
return repo;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// Fallback to single repo
|
|
192
|
-
if (config.repo && slugify(config.repo) === folderName) {
|
|
193
|
-
return config.repo;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
// NOTE: The following was removed in v0.13.0+ migration:
|
|
199
|
-
// - config.teams (ADO): Use projects[] or areaPaths[] instead
|
|
200
|
-
// - config.strategy (Jira): Removed, use intelligent mapping
|
|
201
|
-
// - config.components (Jira): Use projects[] instead
|
|
202
|
-
// Please update any code that still references these fields.
|
|
203
|
-
//# sourceMappingURL=folder-mapper.js.map
|