specweave 0.17.15 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/CLAUDE.md +405 -2495
  2. package/README.md +92 -2
  3. package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
  4. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +188 -36
  5. package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
  6. package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts +54 -0
  7. package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts.map +1 -0
  8. package/dist/plugins/specweave-ado/lib/ado-status-sync.js +86 -0
  9. package/dist/plugins/specweave-ado/lib/ado-status-sync.js.map +1 -0
  10. package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +139 -0
  11. package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts.map +1 -0
  12. package/dist/plugins/specweave-github/lib/duplicate-detector.js +389 -0
  13. package/dist/plugins/specweave-github/lib/duplicate-detector.js.map +1 -0
  14. package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts +26 -0
  15. package/dist/plugins/specweave-github/lib/enhanced-github-sync.d.ts.map +1 -0
  16. package/dist/plugins/specweave-github/lib/enhanced-github-sync.js +249 -0
  17. package/dist/plugins/specweave-github/lib/enhanced-github-sync.js.map +1 -0
  18. package/dist/plugins/specweave-github/lib/github-client.d.ts +1 -1
  19. package/dist/plugins/specweave-github/lib/github-client.d.ts.map +1 -1
  20. package/dist/plugins/specweave-github/lib/github-client.js +25 -13
  21. package/dist/plugins/specweave-github/lib/github-client.js.map +1 -1
  22. package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +83 -0
  23. package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +1 -0
  24. package/dist/plugins/specweave-github/lib/github-epic-sync.js +451 -0
  25. package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -0
  26. package/dist/plugins/specweave-github/lib/github-status-sync.d.ts +43 -0
  27. package/dist/plugins/specweave-github/lib/github-status-sync.d.ts.map +1 -0
  28. package/dist/plugins/specweave-github/lib/github-status-sync.js +82 -0
  29. package/dist/plugins/specweave-github/lib/github-status-sync.js.map +1 -0
  30. package/dist/plugins/specweave-github/lib/task-sync.d.ts +5 -0
  31. package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +1 -1
  32. package/dist/plugins/specweave-github/lib/task-sync.js +38 -2
  33. package/dist/plugins/specweave-github/lib/task-sync.js.map +1 -1
  34. package/dist/plugins/specweave-jira/lib/jira-epic-sync.d.ts +66 -0
  35. package/dist/plugins/specweave-jira/lib/jira-epic-sync.d.ts.map +1 -0
  36. package/dist/plugins/specweave-jira/lib/jira-epic-sync.js +274 -0
  37. package/dist/plugins/specweave-jira/lib/jira-epic-sync.js.map +1 -0
  38. package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts +56 -0
  39. package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts.map +1 -0
  40. package/dist/plugins/specweave-jira/lib/jira-status-sync.js +93 -0
  41. package/dist/plugins/specweave-jira/lib/jira-status-sync.js.map +1 -0
  42. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  43. package/dist/src/cli/helpers/issue-tracker/index.js +48 -3
  44. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  45. package/dist/src/core/living-docs/hierarchy-mapper.d.ts +142 -0
  46. package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -0
  47. package/dist/src/core/living-docs/hierarchy-mapper.js +453 -0
  48. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -0
  49. package/dist/src/core/living-docs/index.d.ts +10 -84
  50. package/dist/src/core/living-docs/index.d.ts.map +1 -1
  51. package/dist/src/core/living-docs/index.js +10 -164
  52. package/dist/src/core/living-docs/index.js.map +1 -1
  53. package/dist/src/core/living-docs/spec-distributor.d.ts +106 -0
  54. package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -0
  55. package/dist/src/core/living-docs/spec-distributor.js +823 -0
  56. package/dist/src/core/living-docs/spec-distributor.js.map +1 -0
  57. package/dist/src/core/living-docs/types.d.ts +201 -0
  58. package/dist/src/core/living-docs/types.d.ts.map +1 -0
  59. package/dist/src/core/living-docs/types.js +15 -0
  60. package/dist/src/core/living-docs/types.js.map +1 -0
  61. package/dist/src/core/logging/prompt-logger.d.ts +70 -0
  62. package/dist/src/core/logging/prompt-logger.d.ts.map +1 -0
  63. package/dist/src/core/logging/prompt-logger.js +247 -0
  64. package/dist/src/core/logging/prompt-logger.js.map +1 -0
  65. package/dist/src/core/status-line/status-line-manager.d.ts +15 -24
  66. package/dist/src/core/status-line/status-line-manager.d.ts.map +1 -1
  67. package/dist/src/core/status-line/status-line-manager.js +33 -70
  68. package/dist/src/core/status-line/status-line-manager.js.map +1 -1
  69. package/dist/src/core/status-line/types.d.ts +19 -31
  70. package/dist/src/core/status-line/types.d.ts.map +1 -1
  71. package/dist/src/core/status-line/types.js +5 -9
  72. package/dist/src/core/status-line/types.js.map +1 -1
  73. package/dist/src/core/sync/conflict-resolver.d.ts +66 -0
  74. package/dist/src/core/sync/conflict-resolver.d.ts.map +1 -0
  75. package/dist/src/core/sync/conflict-resolver.js +108 -0
  76. package/dist/src/core/sync/conflict-resolver.js.map +1 -0
  77. package/dist/src/core/sync/enhanced-content-builder.d.ts +77 -0
  78. package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -0
  79. package/dist/src/core/sync/enhanced-content-builder.js +199 -0
  80. package/dist/src/core/sync/enhanced-content-builder.js.map +1 -0
  81. package/dist/src/core/sync/label-detector.d.ts +66 -0
  82. package/dist/src/core/sync/label-detector.d.ts.map +1 -0
  83. package/dist/src/core/sync/label-detector.js +211 -0
  84. package/dist/src/core/sync/label-detector.js.map +1 -0
  85. package/dist/src/core/sync/retry-logic.d.ts +64 -0
  86. package/dist/src/core/sync/retry-logic.d.ts.map +1 -0
  87. package/dist/src/core/sync/retry-logic.js +165 -0
  88. package/dist/src/core/sync/retry-logic.js.map +1 -0
  89. package/dist/src/core/sync/spec-increment-mapper.d.ts +100 -0
  90. package/dist/src/core/sync/spec-increment-mapper.d.ts.map +1 -0
  91. package/dist/src/core/sync/spec-increment-mapper.js +424 -0
  92. package/dist/src/core/sync/spec-increment-mapper.js.map +1 -0
  93. package/dist/src/core/sync/status-cache.d.ts +91 -0
  94. package/dist/src/core/sync/status-cache.d.ts.map +1 -0
  95. package/dist/src/core/sync/status-cache.js +140 -0
  96. package/dist/src/core/sync/status-cache.js.map +1 -0
  97. package/dist/src/core/sync/status-mapper.d.ts +69 -0
  98. package/dist/src/core/sync/status-mapper.d.ts.map +1 -0
  99. package/dist/src/core/sync/status-mapper.js +90 -0
  100. package/dist/src/core/sync/status-mapper.js.map +1 -0
  101. package/dist/src/core/sync/status-sync-engine.d.ts +162 -0
  102. package/dist/src/core/sync/status-sync-engine.d.ts.map +1 -0
  103. package/dist/src/core/sync/status-sync-engine.js +347 -0
  104. package/dist/src/core/sync/status-sync-engine.js.map +1 -0
  105. package/dist/src/core/sync/sync-event-logger.d.ts +99 -0
  106. package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -0
  107. package/dist/src/core/sync/sync-event-logger.js +103 -0
  108. package/dist/src/core/sync/sync-event-logger.js.map +1 -0
  109. package/dist/src/core/sync/workflow-detector.d.ts +95 -0
  110. package/dist/src/core/sync/workflow-detector.d.ts.map +1 -0
  111. package/dist/src/core/sync/workflow-detector.js +175 -0
  112. package/dist/src/core/sync/workflow-detector.js.map +1 -0
  113. package/dist/src/core/types/config.d.ts.map +1 -1
  114. package/dist/src/core/types/config.js +31 -0
  115. package/dist/src/core/types/config.js.map +1 -1
  116. package/dist/src/utils/github-url.d.ts +53 -0
  117. package/dist/src/utils/github-url.d.ts.map +1 -0
  118. package/dist/src/utils/github-url.js +90 -0
  119. package/dist/src/utils/github-url.js.map +1 -0
  120. package/dist/src/utils/plugin-validator.d.ts +9 -0
  121. package/dist/src/utils/plugin-validator.d.ts.map +1 -1
  122. package/dist/src/utils/plugin-validator.js +86 -19
  123. package/dist/src/utils/plugin-validator.js.map +1 -1
  124. package/dist/src/utils/spec-parser.d.ts +145 -0
  125. package/dist/src/utils/spec-parser.d.ts.map +1 -0
  126. package/dist/src/utils/spec-parser.js +640 -0
  127. package/dist/src/utils/spec-parser.js.map +1 -0
  128. package/package.json +1 -1
  129. package/plugins/specweave/agents/pm/AGENT.md +1 -1
  130. package/plugins/specweave/agents/pm/templates/increment-spec.md +158 -0
  131. package/plugins/specweave/agents/pm/templates/living-docs-spec.md +113 -0
  132. package/plugins/specweave/commands/specweave-done.md +163 -0
  133. package/plugins/specweave/hooks/lib/update-status-line.sh +79 -111
  134. package/plugins/specweave/hooks/post-increment-planning.sh +107 -35
  135. package/plugins/specweave/lib/hooks/sync-living-docs.js +139 -34
  136. package/plugins/specweave/lib/hooks/sync-living-docs.ts +234 -38
  137. package/plugins/specweave/skills/SKILLS-INDEX.md +4 -24
  138. package/plugins/specweave/skills/increment-planner/SKILL.md +94 -0
  139. package/plugins/specweave/skills/increment-work-router/SKILL.md +466 -0
  140. package/plugins/specweave/skills/plugin-validator/SKILL.md +16 -13
  141. package/plugins/specweave-ado/lib/ado-status-sync.js +80 -0
  142. package/plugins/specweave-ado/lib/ado-status-sync.ts +121 -0
  143. package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +205 -0
  144. package/plugins/specweave-github/commands/specweave-github-sync-epic.md +248 -0
  145. package/plugins/specweave-github/lib/duplicate-detector.js +370 -0
  146. package/plugins/specweave-github/lib/duplicate-detector.ts +525 -0
  147. package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
  148. package/plugins/specweave-github/lib/enhanced-github-sync.ts +322 -0
  149. package/plugins/specweave-github/lib/github-client.js +21 -10
  150. package/plugins/specweave-github/lib/github-client.ts +27 -16
  151. package/plugins/specweave-github/lib/github-epic-sync.js +489 -0
  152. package/plugins/specweave-github/lib/github-epic-sync.ts +690 -0
  153. package/plugins/specweave-github/lib/github-status-sync.js +71 -0
  154. package/plugins/specweave-github/lib/github-status-sync.ts +107 -0
  155. package/plugins/specweave-github/lib/task-sync.js +33 -2
  156. package/plugins/specweave-github/lib/task-sync.ts +44 -2
  157. package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +267 -0
  158. package/plugins/specweave-jira/lib/enhanced-jira-sync.ts.disabled +222 -0
  159. package/plugins/specweave-jira/lib/jira-epic-sync.js +304 -0
  160. package/plugins/specweave-jira/lib/jira-epic-sync.ts +459 -0
  161. package/plugins/specweave-jira/lib/jira-status-sync.js +79 -0
  162. package/plugins/specweave-jira/lib/jira-status-sync.ts +139 -0
  163. package/src/templates/AGENTS.md.template +88 -1
  164. package/src/templates/CLAUDE.md.template +49 -0
  165. package/plugins/specweave/skills/increment-quality-judge/SKILL.md +0 -524
  166. package/plugins/specweave/skills/plugin-installer/SKILL.md +0 -353
@@ -0,0 +1,424 @@
1
+ /**
2
+ * Spec-to-Increment Mapper
3
+ *
4
+ * Maps permanent living docs specs to specific increment tasks.
5
+ * Enables traceability: "Which increment implemented US-001?"
6
+ */
7
+ import fs from 'fs/promises';
8
+ import path from 'path';
9
+ import matter from 'gray-matter';
10
+ export class SpecIncrementMapper {
11
+ constructor(rootDir = process.cwd()) {
12
+ this.rootDir = rootDir;
13
+ }
14
+ /**
15
+ * Map a spec to all increments that implement it
16
+ */
17
+ async mapSpecToIncrements(specId) {
18
+ const increments = await this.findIncrementsForSpec(specId);
19
+ const userStoryMappings = {};
20
+ // Build user story to task mappings
21
+ for (const increment of increments) {
22
+ for (const task of increment.tasks) {
23
+ for (const userStoryId of task.userStories) {
24
+ if (!userStoryMappings[userStoryId]) {
25
+ userStoryMappings[userStoryId] = [];
26
+ }
27
+ userStoryMappings[userStoryId].push(task);
28
+ }
29
+ }
30
+ }
31
+ return {
32
+ specId,
33
+ increments,
34
+ userStoryMappings
35
+ };
36
+ }
37
+ /**
38
+ * Find all increments that implement a specific user story
39
+ */
40
+ async findIncrementsByUserStory(userStoryId) {
41
+ const incrementsDir = path.join(this.rootDir, '.specweave/increments');
42
+ try {
43
+ const entries = await fs.readdir(incrementsDir, { withFileTypes: true });
44
+ const incrementDirs = entries
45
+ .filter(e => e.isDirectory() && /^\d{4}-/.test(e.name))
46
+ .map(e => e.name);
47
+ const results = [];
48
+ for (const incrementId of incrementDirs) {
49
+ const tasks = await this.getTasksFromIncrement(incrementId);
50
+ const relevantTasks = tasks.filter(t => t.userStories.includes(userStoryId));
51
+ if (relevantTasks.length > 0) {
52
+ results.push({
53
+ id: incrementId,
54
+ tasks: relevantTasks
55
+ });
56
+ }
57
+ }
58
+ return results;
59
+ }
60
+ catch (error) {
61
+ return [];
62
+ }
63
+ }
64
+ /**
65
+ * Get all tasks that implement a specific user story
66
+ */
67
+ async getTasksForUserStory(userStoryId) {
68
+ const increments = await this.findIncrementsByUserStory(userStoryId);
69
+ const tasks = [];
70
+ for (const increment of increments) {
71
+ tasks.push(...increment.tasks);
72
+ }
73
+ return tasks;
74
+ }
75
+ /**
76
+ * Update spec with increment links in frontmatter (Forward link)
77
+ */
78
+ async updateSpecWithIncrementLinks(specId, incrementId) {
79
+ const specPath = await this.findSpecPath(specId);
80
+ if (!specPath) {
81
+ return false;
82
+ }
83
+ try {
84
+ const content = await fs.readFile(specPath, 'utf-8');
85
+ const { data: frontmatter, content: markdownContent } = matter(content);
86
+ // Initialize linked_increments if not exists
87
+ if (!frontmatter.linked_increments) {
88
+ frontmatter.linked_increments = [];
89
+ }
90
+ // Check if already linked
91
+ if (frontmatter.linked_increments.includes(incrementId)) {
92
+ return false; // Already linked
93
+ }
94
+ // Add new increment link
95
+ frontmatter.linked_increments.push(incrementId);
96
+ // Write back
97
+ const updated = matter.stringify(markdownContent, frontmatter);
98
+ await fs.writeFile(specPath, updated);
99
+ return true;
100
+ }
101
+ catch (error) {
102
+ return false;
103
+ }
104
+ }
105
+ /**
106
+ * Update increment with spec link in frontmatter (Backward link)
107
+ */
108
+ async updateIncrementWithSpecLink(incrementId, specId) {
109
+ const incrementSpecPath = path.join(this.rootDir, '.specweave/increments', incrementId, 'spec.md');
110
+ try {
111
+ await fs.access(incrementSpecPath);
112
+ }
113
+ catch {
114
+ return false; // Increment spec.md doesn't exist
115
+ }
116
+ try {
117
+ const content = await fs.readFile(incrementSpecPath, 'utf-8');
118
+ const { data: frontmatter, content: markdownContent } = matter(content);
119
+ // Check if already linked
120
+ if (frontmatter.spec_id === specId || frontmatter.source_spec === specId) {
121
+ return false; // Already linked
122
+ }
123
+ // Add spec link
124
+ frontmatter.source_spec = specId;
125
+ // Write back
126
+ const updated = matter.stringify(markdownContent, frontmatter);
127
+ await fs.writeFile(incrementSpecPath, updated);
128
+ return true;
129
+ }
130
+ catch (error) {
131
+ return false;
132
+ }
133
+ }
134
+ /**
135
+ * Create bidirectional link between spec and increment (atomic operation)
136
+ */
137
+ async createBidirectionalLink(specId, incrementId) {
138
+ const forwardLink = await this.updateSpecWithIncrementLinks(specId, incrementId);
139
+ const backwardLink = await this.updateIncrementWithSpecLink(incrementId, specId);
140
+ return {
141
+ success: forwardLink || backwardLink,
142
+ forwardLink,
143
+ backwardLink
144
+ };
145
+ }
146
+ /**
147
+ * Get spec for a given increment (reverse lookup)
148
+ */
149
+ async getSpecForIncrement(incrementId) {
150
+ const incrementSpecPath = path.join(this.rootDir, '.specweave/increments', incrementId, 'spec.md');
151
+ try {
152
+ const content = await fs.readFile(incrementSpecPath, 'utf-8');
153
+ const { data: frontmatter } = matter(content);
154
+ // Check both field names for compatibility
155
+ return frontmatter.source_spec || frontmatter.spec_id || null;
156
+ }
157
+ catch {
158
+ return null;
159
+ }
160
+ }
161
+ /**
162
+ * Validate bidirectional links and detect broken references
163
+ */
164
+ async validateLinks() {
165
+ const brokenForwardLinks = [];
166
+ const brokenBackwardLinks = [];
167
+ const orphanedIncrements = [];
168
+ const incrementsDir = path.join(this.rootDir, '.specweave/increments');
169
+ try {
170
+ const entries = await fs.readdir(incrementsDir, { withFileTypes: true });
171
+ const incrementDirs = entries
172
+ .filter(e => e.isDirectory() && /^\d{4}-/.test(e.name))
173
+ .map(e => e.name);
174
+ for (const incrementId of incrementDirs) {
175
+ // Check backward link
176
+ const specId = await this.getSpecForIncrement(incrementId);
177
+ if (!specId) {
178
+ orphanedIncrements.push(incrementId);
179
+ continue;
180
+ }
181
+ // Validate forward link exists
182
+ const specPath = await this.findSpecPath(specId);
183
+ if (specPath) {
184
+ const content = await fs.readFile(specPath, 'utf-8');
185
+ const { data: frontmatter } = matter(content);
186
+ if (!frontmatter.linked_increments?.includes(incrementId)) {
187
+ brokenBackwardLinks.push({ incrementId, specId });
188
+ }
189
+ }
190
+ else {
191
+ brokenBackwardLinks.push({ incrementId, specId });
192
+ }
193
+ }
194
+ // Check specs for broken forward links
195
+ const specsDir = path.join(this.rootDir, '.specweave/docs/internal/specs');
196
+ const projects = await fs.readdir(specsDir, { withFileTypes: true });
197
+ for (const project of projects.filter(e => e.isDirectory())) {
198
+ const specs = await fs.readdir(path.join(specsDir, project.name));
199
+ for (const specFile of specs.filter(f => f.endsWith('.md'))) {
200
+ const specPath = path.join(specsDir, project.name, specFile);
201
+ const content = await fs.readFile(specPath, 'utf-8');
202
+ const { data: frontmatter } = matter(content);
203
+ if (frontmatter.linked_increments) {
204
+ for (const incrementId of frontmatter.linked_increments) {
205
+ const incrementPath = path.join(incrementsDir, incrementId, 'spec.md');
206
+ try {
207
+ await fs.access(incrementPath);
208
+ }
209
+ catch {
210
+ brokenForwardLinks.push({
211
+ specId: specFile.replace('.md', ''),
212
+ incrementId
213
+ });
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ catch (error) {
221
+ // Directory doesn't exist or other error
222
+ }
223
+ return {
224
+ valid: brokenForwardLinks.length === 0 &&
225
+ brokenBackwardLinks.length === 0 &&
226
+ orphanedIncrements.length === 0,
227
+ brokenForwardLinks,
228
+ brokenBackwardLinks,
229
+ orphanedIncrements
230
+ };
231
+ }
232
+ /**
233
+ * Build complete traceability report for a spec
234
+ */
235
+ async buildTraceabilityReport(specId) {
236
+ const mapping = await this.mapSpecToIncrements(specId);
237
+ const userStories = await this.getUserStoriesFromSpec(specId);
238
+ const totalUserStories = userStories.length;
239
+ const totalIncrements = mapping.increments.length;
240
+ const totalTasks = mapping.increments.reduce((sum, inc) => sum + inc.tasks.length, 0);
241
+ const mappedUserStories = Object.keys(mapping.userStoryMappings).filter(us => userStories.includes(us));
242
+ const unmappedUserStories = userStories.filter(us => !mappedUserStories.includes(us));
243
+ const coverage = totalUserStories > 0
244
+ ? Math.min(100, (mappedUserStories.length / totalUserStories) * 100)
245
+ : 0;
246
+ // Build detailed mapping
247
+ const mappingDetails = {};
248
+ for (const [userStoryId, tasks] of Object.entries(mapping.userStoryMappings)) {
249
+ const incrementGroups = {};
250
+ for (const task of tasks) {
251
+ if (!incrementGroups[task.incrementId]) {
252
+ incrementGroups[task.incrementId] = [];
253
+ }
254
+ incrementGroups[task.incrementId].push(task.id);
255
+ }
256
+ mappingDetails[userStoryId] = Object.entries(incrementGroups).map(([incrementId, taskIds]) => ({
257
+ incrementId,
258
+ taskIds
259
+ }));
260
+ }
261
+ return {
262
+ specId,
263
+ totalUserStories,
264
+ totalIncrements,
265
+ totalTasks,
266
+ coverage,
267
+ unmappedUserStories,
268
+ mappingDetails
269
+ };
270
+ }
271
+ // Private helper methods
272
+ async findIncrementsForSpec(specId) {
273
+ const incrementsDir = path.join(this.rootDir, '.specweave/increments');
274
+ try {
275
+ const entries = await fs.readdir(incrementsDir, { withFileTypes: true });
276
+ const incrementDirs = entries
277
+ .filter(e => e.isDirectory() && /^\d{4}-/.test(e.name))
278
+ .map(e => e.name);
279
+ const results = [];
280
+ for (const incrementId of incrementDirs) {
281
+ const specPath = path.join(incrementsDir, incrementId, 'spec.md');
282
+ try {
283
+ const content = await fs.readFile(specPath, 'utf-8');
284
+ const { data: frontmatter } = matter(content);
285
+ // Check if this increment references our spec
286
+ if (frontmatter.spec_id === specId || content.includes(`spec-${specId}`)) {
287
+ const tasks = await this.getTasksFromIncrement(incrementId);
288
+ results.push({
289
+ id: incrementId,
290
+ tasks,
291
+ specId
292
+ });
293
+ }
294
+ }
295
+ catch {
296
+ // Skip if spec.md doesn't exist
297
+ }
298
+ }
299
+ return results;
300
+ }
301
+ catch (error) {
302
+ return [];
303
+ }
304
+ }
305
+ async getTasksFromIncrement(incrementId) {
306
+ const tasksPath = path.join(this.rootDir, '.specweave/increments', incrementId, 'tasks.md');
307
+ try {
308
+ const content = await fs.readFile(tasksPath, 'utf-8');
309
+ const { data: frontmatter } = matter(content);
310
+ const tasks = [];
311
+ // Parse tasks from markdown (tasks use ### heading level)
312
+ const taskRegex = /^###\s+(T-\d+):\s+(.+)$/gm;
313
+ let match;
314
+ while ((match = taskRegex.exec(content)) !== null) {
315
+ const taskId = match[1];
316
+ const title = match[2];
317
+ // Extract user stories for this task
318
+ const taskSection = this.extractTaskSection(content, taskId);
319
+ const userStories = this.extractUserStoriesFromTask(taskSection);
320
+ const githubIssue = this.extractGithubIssue(taskSection);
321
+ const status = this.extractTaskStatus(taskSection);
322
+ tasks.push({
323
+ id: taskId,
324
+ title,
325
+ incrementId,
326
+ userStories,
327
+ githubIssue,
328
+ status
329
+ });
330
+ }
331
+ return tasks;
332
+ }
333
+ catch (error) {
334
+ return [];
335
+ }
336
+ }
337
+ extractTaskSection(content, taskId) {
338
+ const startRegex = new RegExp(`^###\\s+${taskId}:`, 'm');
339
+ const startMatch = content.match(startRegex);
340
+ if (!startMatch)
341
+ return '';
342
+ const startIndex = startMatch.index;
343
+ const nextTaskMatch = content.slice(startIndex + 1).match(/^###\s+T-\d+:/m);
344
+ const endIndex = nextTaskMatch
345
+ ? startIndex + 1 + nextTaskMatch.index
346
+ : content.length;
347
+ return content.slice(startIndex, endIndex);
348
+ }
349
+ extractUserStoriesFromTask(taskSection) {
350
+ // Look for AC references: AC-US1-01, AC-US2-01, etc.
351
+ const acRegex = /AC-US(\d+)-\d+/g;
352
+ const matches = [...taskSection.matchAll(acRegex)];
353
+ const userStoryNumbers = new Set(matches.map(m => m[1]));
354
+ // Also look for explicit "Implements: US-001, US-002"
355
+ const implementsMatch = taskSection.match(/Implements:\s*([^\n]+)/);
356
+ if (implementsMatch) {
357
+ const usMatches = implementsMatch[1].matchAll(/US-(\d+)/g);
358
+ for (const match of usMatches) {
359
+ userStoryNumbers.add(match[1]);
360
+ }
361
+ }
362
+ return Array.from(userStoryNumbers).map(num => `US-${num}`);
363
+ }
364
+ extractGithubIssue(taskSection) {
365
+ const match = taskSection.match(/github.*#(\d+)/i);
366
+ return match ? parseInt(match[1], 10) : undefined;
367
+ }
368
+ extractTaskStatus(taskSection) {
369
+ if (taskSection.includes('[x] Completed') || taskSection.includes('✅')) {
370
+ return 'completed';
371
+ }
372
+ if (taskSection.includes('[ ] In Progress') || taskSection.includes('🔄')) {
373
+ return 'in-progress';
374
+ }
375
+ return 'pending';
376
+ }
377
+ async findSpecPath(specId) {
378
+ const specsDir = path.join(this.rootDir, '.specweave/docs/internal/specs');
379
+ try {
380
+ // Try default project first
381
+ const defaultPath = path.join(specsDir, 'default', `${specId}.md`);
382
+ try {
383
+ await fs.access(defaultPath);
384
+ return defaultPath;
385
+ }
386
+ catch {
387
+ // Not in default, search all projects
388
+ }
389
+ // Search all project folders
390
+ const entries = await fs.readdir(specsDir, { withFileTypes: true });
391
+ const projectDirs = entries.filter(e => e.isDirectory()).map(e => e.name);
392
+ for (const project of projectDirs) {
393
+ const specPath = path.join(specsDir, project, `${specId}.md`);
394
+ try {
395
+ await fs.access(specPath);
396
+ return specPath;
397
+ }
398
+ catch {
399
+ continue;
400
+ }
401
+ }
402
+ return null;
403
+ }
404
+ catch (error) {
405
+ return null;
406
+ }
407
+ }
408
+ async getUserStoriesFromSpec(specId) {
409
+ const specPath = await this.findSpecPath(specId);
410
+ if (!specPath) {
411
+ return [];
412
+ }
413
+ try {
414
+ const content = await fs.readFile(specPath, 'utf-8');
415
+ const userStoryRegex = /\*\*(US-\d+)\*\*:/g;
416
+ const matches = [...content.matchAll(userStoryRegex)];
417
+ return matches.map(m => m[1]);
418
+ }
419
+ catch (error) {
420
+ return [];
421
+ }
422
+ }
423
+ }
424
+ //# sourceMappingURL=spec-increment-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-increment-mapper.js","sourceRoot":"","sources":["../../../../src/core/sync/spec-increment-mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Status Cache
3
+ *
4
+ * Caches external tool statuses to reduce API calls.
5
+ * Uses in-memory cache with TTL (default: 5 minutes).
6
+ *
7
+ * Performance Optimization:
8
+ * - Reduces redundant API calls
9
+ * - Improves sync speed
10
+ * - Respects rate limits
11
+ *
12
+ * @module status-cache
13
+ */
14
+ export interface CacheEntry<T> {
15
+ value: T;
16
+ timestamp: number;
17
+ ttl: number;
18
+ }
19
+ export interface CacheOptions {
20
+ ttl?: number;
21
+ }
22
+ /**
23
+ * Status Cache
24
+ *
25
+ * Generic cache for external tool statuses.
26
+ */
27
+ export declare class StatusCache<T = any> {
28
+ private cache;
29
+ private defaultTtl;
30
+ constructor(options?: CacheOptions);
31
+ /**
32
+ * Get value from cache
33
+ *
34
+ * @param key - Cache key
35
+ * @returns Cached value or undefined if not found/expired
36
+ */
37
+ get(key: string): T | undefined;
38
+ /**
39
+ * Set value in cache
40
+ *
41
+ * @param key - Cache key
42
+ * @param value - Value to cache
43
+ * @param ttl - Optional TTL override (ms)
44
+ */
45
+ set(key: string, value: T, ttl?: number): void;
46
+ /**
47
+ * Check if key exists and is not expired
48
+ *
49
+ * @param key - Cache key
50
+ * @returns True if key exists and is not expired
51
+ */
52
+ has(key: string): boolean;
53
+ /**
54
+ * Delete key from cache
55
+ *
56
+ * @param key - Cache key
57
+ */
58
+ delete(key: string): void;
59
+ /**
60
+ * Clear all cache entries
61
+ */
62
+ clear(): void;
63
+ /**
64
+ * Get cache size
65
+ *
66
+ * @returns Number of entries in cache
67
+ */
68
+ size(): number;
69
+ /**
70
+ * Clean up expired entries
71
+ *
72
+ * Removes all expired entries from cache.
73
+ */
74
+ cleanup(): void;
75
+ /**
76
+ * Get cache statistics
77
+ *
78
+ * @returns Cache statistics (size, oldest entry age)
79
+ */
80
+ getStats(): {
81
+ size: number;
82
+ oldestEntryAge: number | null;
83
+ };
84
+ }
85
+ /**
86
+ * Global status cache instance
87
+ *
88
+ * Used across all sync operations for maximum efficiency.
89
+ */
90
+ export declare const globalStatusCache: StatusCache<any>;
91
+ //# sourceMappingURL=status-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-cache.d.ts","sourceRoot":"","sources":["../../../../src/core/sync/status-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,qBAAa,WAAW,CAAC,CAAC,GAAG,GAAG;IAC9B,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,CAAC,EAAE,YAAY;IAKlC;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAoB/B;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAU9C;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACH,IAAI,IAAI,MAAM;IAMd;;;;OAIG;IACH,OAAO,IAAI,IAAI;IAgBf;;;;OAIG;IACH,QAAQ,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAqB5D;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,kBAAoB,CAAC"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Status Cache
3
+ *
4
+ * Caches external tool statuses to reduce API calls.
5
+ * Uses in-memory cache with TTL (default: 5 minutes).
6
+ *
7
+ * Performance Optimization:
8
+ * - Reduces redundant API calls
9
+ * - Improves sync speed
10
+ * - Respects rate limits
11
+ *
12
+ * @module status-cache
13
+ */
14
+ /**
15
+ * Status Cache
16
+ *
17
+ * Generic cache for external tool statuses.
18
+ */
19
+ export class StatusCache {
20
+ constructor(options) {
21
+ this.cache = new Map();
22
+ this.defaultTtl = options?.ttl || 5 * 60 * 1000; // 5 minutes default
23
+ }
24
+ /**
25
+ * Get value from cache
26
+ *
27
+ * @param key - Cache key
28
+ * @returns Cached value or undefined if not found/expired
29
+ */
30
+ get(key) {
31
+ const entry = this.cache.get(key);
32
+ if (!entry) {
33
+ return undefined;
34
+ }
35
+ // Check if expired
36
+ const now = Date.now();
37
+ const age = now - entry.timestamp;
38
+ if (age > entry.ttl) {
39
+ // Expired - remove and return undefined
40
+ this.cache.delete(key);
41
+ return undefined;
42
+ }
43
+ return entry.value;
44
+ }
45
+ /**
46
+ * Set value in cache
47
+ *
48
+ * @param key - Cache key
49
+ * @param value - Value to cache
50
+ * @param ttl - Optional TTL override (ms)
51
+ */
52
+ set(key, value, ttl) {
53
+ const entry = {
54
+ value,
55
+ timestamp: Date.now(),
56
+ ttl: ttl || this.defaultTtl
57
+ };
58
+ this.cache.set(key, entry);
59
+ }
60
+ /**
61
+ * Check if key exists and is not expired
62
+ *
63
+ * @param key - Cache key
64
+ * @returns True if key exists and is not expired
65
+ */
66
+ has(key) {
67
+ return this.get(key) !== undefined;
68
+ }
69
+ /**
70
+ * Delete key from cache
71
+ *
72
+ * @param key - Cache key
73
+ */
74
+ delete(key) {
75
+ this.cache.delete(key);
76
+ }
77
+ /**
78
+ * Clear all cache entries
79
+ */
80
+ clear() {
81
+ this.cache.clear();
82
+ }
83
+ /**
84
+ * Get cache size
85
+ *
86
+ * @returns Number of entries in cache
87
+ */
88
+ size() {
89
+ // Clean up expired entries first
90
+ this.cleanup();
91
+ return this.cache.size;
92
+ }
93
+ /**
94
+ * Clean up expired entries
95
+ *
96
+ * Removes all expired entries from cache.
97
+ */
98
+ cleanup() {
99
+ const now = Date.now();
100
+ const keysToDelete = [];
101
+ for (const [key, entry] of this.cache.entries()) {
102
+ const age = now - entry.timestamp;
103
+ if (age > entry.ttl) {
104
+ keysToDelete.push(key);
105
+ }
106
+ }
107
+ for (const key of keysToDelete) {
108
+ this.cache.delete(key);
109
+ }
110
+ }
111
+ /**
112
+ * Get cache statistics
113
+ *
114
+ * @returns Cache statistics (size, oldest entry age)
115
+ */
116
+ getStats() {
117
+ this.cleanup();
118
+ if (this.cache.size === 0) {
119
+ return { size: 0, oldestEntryAge: null };
120
+ }
121
+ const now = Date.now();
122
+ let oldestTimestamp = now;
123
+ for (const entry of this.cache.values()) {
124
+ if (entry.timestamp < oldestTimestamp) {
125
+ oldestTimestamp = entry.timestamp;
126
+ }
127
+ }
128
+ return {
129
+ size: this.cache.size,
130
+ oldestEntryAge: now - oldestTimestamp
131
+ };
132
+ }
133
+ }
134
+ /**
135
+ * Global status cache instance
136
+ *
137
+ * Used across all sync operations for maximum efficiency.
138
+ */
139
+ export const globalStatusCache = new StatusCache();
140
+ //# sourceMappingURL=status-cache.js.map