specweave 0.30.9 → 0.30.11

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 (36) hide show
  1. package/dist/plugins/specweave-ado/lib/ado-client-v2.d.ts.map +1 -1
  2. package/dist/plugins/specweave-ado/lib/ado-client-v2.js +46 -12
  3. package/dist/plugins/specweave-ado/lib/ado-client-v2.js.map +1 -1
  4. package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
  5. package/dist/plugins/specweave-github/lib/github-feature-sync.js +14 -4
  6. package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
  7. package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +1 -1
  8. package/dist/plugins/specweave-github/lib/user-story-content-builder.js +5 -1
  9. package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +1 -1
  10. package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -1
  11. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +9 -2
  12. package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -1
  13. package/dist/src/cli/helpers/init/repository-setup.d.ts.map +1 -1
  14. package/dist/src/cli/helpers/init/repository-setup.js +64 -2
  15. package/dist/src/cli/helpers/init/repository-setup.js.map +1 -1
  16. package/dist/src/cli/helpers/project-count-fetcher.js +33 -2
  17. package/dist/src/cli/helpers/project-count-fetcher.js.map +1 -1
  18. package/dist/src/core/living-docs/living-docs-sync.d.ts +9 -0
  19. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  20. package/dist/src/core/living-docs/living-docs-sync.js +170 -6
  21. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  22. package/dist/src/integrations/ado/ado-client.d.ts +22 -0
  23. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  24. package/dist/src/integrations/ado/ado-client.js +89 -37
  25. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  26. package/package.json +1 -1
  27. package/plugins/specweave/commands/specweave-sync-specs.md +46 -37
  28. package/plugins/specweave-ado/lib/ado-client-v2.js +43 -8
  29. package/plugins/specweave-ado/lib/ado-client-v2.ts +52 -12
  30. package/plugins/specweave-github/lib/github-feature-sync.js +11 -3
  31. package/plugins/specweave-github/lib/github-feature-sync.ts +16 -4
  32. package/plugins/specweave-github/lib/user-story-content-builder.js +3 -1
  33. package/plugins/specweave-github/lib/user-story-content-builder.ts +5 -1
  34. package/plugins/specweave-github/lib/user-story-issue-builder.js +6 -2
  35. package/plugins/specweave-github/lib/user-story-issue-builder.ts +10 -2
  36. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +10 -8
@@ -277,10 +277,22 @@ export class GitHubFeatureSync {
277
277
  * Find Feature folder in specs directory
278
278
  */
279
279
  private async findFeatureFolder(featureId: string): Promise<string | null> {
280
- // Check _features folder first
281
- const featuresFolder = path.join(this.specsDir, '_features', featureId);
282
- if (existsSync(featuresFolder)) {
283
- return featuresFolder;
280
+ // v5.0.0+: NO _features folder - features live in project folders
281
+ // Search all project folders for the feature
282
+ const projectFolders = await this.findProjectFolders();
283
+
284
+ for (const projectFolder of projectFolders) {
285
+ const featureFolder = path.join(projectFolder, featureId);
286
+ if (existsSync(featureFolder) && existsSync(path.join(featureFolder, 'FEATURE.md'))) {
287
+ return featureFolder;
288
+ }
289
+ }
290
+
291
+ // Legacy fallback: Check _features folder (for brownfield migration)
292
+ const legacyFolder = path.join(this.specsDir, '_features', featureId);
293
+ if (existsSync(legacyFolder)) {
294
+ console.log(` ⚠️ Found feature in legacy _features folder - consider migrating to project folder`);
295
+ return legacyFolder;
284
296
  }
285
297
 
286
298
  return null;
@@ -43,7 +43,9 @@ class UserStoryContentBuilder {
43
43
  const priority = this.extractPriorityFromACs(content.acceptanceCriteria);
44
44
  const repo = githubRepo || await this.detectGitHubRepo();
45
45
  if (repo) {
46
- body += `**Feature**: [${content.featureId}](https://github.com/${repo}/tree/develop/.specweave/docs/internal/specs/_features/${content.featureId})
46
+ const pathMatch = this.userStoryPath.match(/specs\/([^/]+)\/FS-\d+\//);
47
+ const projectFolder = pathMatch ? pathMatch[1] : "default";
48
+ body += `**Feature**: [${content.featureId}](https://github.com/${repo}/tree/develop/.specweave/docs/internal/specs/${projectFolder}/${content.featureId})
47
49
  `;
48
50
  } else {
49
51
  body += `**Feature**: ${content.featureId}
@@ -123,8 +123,12 @@ export class UserStoryContentBuilder {
123
123
  const repo = githubRepo || await this.detectGitHubRepo();
124
124
 
125
125
  // Header with metadata
126
+ // v5.0.0+: Features live in project folders, NOT _features
127
+ // Extract project from path: specs/{project}/FS-XXX/us-*.md
126
128
  if (repo) {
127
- body += `**Feature**: [${content.featureId}](https://github.com/${repo}/tree/develop/.specweave/docs/internal/specs/_features/${content.featureId})\n`;
129
+ const pathMatch = this.userStoryPath.match(/specs\/([^/]+)\/FS-\d+\//);
130
+ const projectFolder = pathMatch ? pathMatch[1] : 'default';
131
+ body += `**Feature**: [${content.featureId}](https://github.com/${repo}/tree/develop/.specweave/docs/internal/specs/${projectFolder}/${content.featureId})\n`;
128
132
  } else {
129
133
  body += `**Feature**: ${content.featureId}\n`;
130
134
  }
@@ -329,7 +329,9 @@ User Story ID: ${frontmatter.id}`
329
329
  sections.push("");
330
330
  if (this.repoOwner && this.repoName) {
331
331
  const baseUrl = `https://github.com/${this.repoOwner}/${this.repoName}/blob/${this.branch}`;
332
- sections.push(`- **Feature Spec**: [${this.featureId}](${baseUrl}/.specweave/docs/internal/specs/_features/${this.featureId}/FEATURE.md)`);
332
+ const pathMatch = this.userStoryPath.match(/specs\/([^/]+)\/FS-\d+\//);
333
+ const projectFolder = pathMatch ? pathMatch[1] : "default";
334
+ sections.push(`- **Feature Spec**: [${this.featureId}](${baseUrl}/.specweave/docs/internal/specs/${projectFolder}/${this.featureId}/FEATURE.md)`);
333
335
  const relativeUSPath = path.relative(this.projectRoot, this.userStoryPath);
334
336
  sections.push(`- **User Story File**: [${path.basename(this.userStoryPath)}](${baseUrl}/${relativeUSPath})`);
335
337
  const incrementMatch = implMatch?.[1]?.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
@@ -338,7 +340,9 @@ User Story ID: ${frontmatter.id}`
338
340
  sections.push(`- **Increment**: [${incrementId}](${baseUrl}/.specweave/increments/${incrementId})`);
339
341
  }
340
342
  } else {
341
- sections.push(`- **Feature Spec**: [${this.featureId}](../.specweave/docs/internal/specs/_features/${this.featureId}/FEATURE.md)`);
343
+ const pathMatch = this.userStoryPath.match(/specs\/([^/]+)\/FS-\d+\//);
344
+ const projectFolder = pathMatch ? pathMatch[1] : "default";
345
+ sections.push(`- **Feature Spec**: [${this.featureId}](../.specweave/docs/internal/specs/${projectFolder}/${this.featureId}/FEATURE.md)`);
342
346
  sections.push(`- **User Story File**: [${path.basename(this.userStoryPath)}](${this.userStoryPath})`);
343
347
  }
344
348
  sections.push("");
@@ -525,11 +525,16 @@ export class UserStoryIssueBuilder {
525
525
  sections.push('');
526
526
 
527
527
  // Generate proper GitHub blob URLs
528
+ // v5.0.0+: Features live in project folders, NOT _features
528
529
  if (this.repoOwner && this.repoName) {
529
530
  const baseUrl = `https://github.com/${this.repoOwner}/${this.repoName}/blob/${this.branch}`;
530
531
 
532
+ // Extract project from user story path: specs/{project}/FS-XXX/us-*.md
533
+ const pathMatch = this.userStoryPath.match(/specs\/([^/]+)\/FS-\d+\//);
534
+ const projectFolder = pathMatch ? pathMatch[1] : 'default';
535
+
531
536
  // Feature Spec link
532
- sections.push(`- **Feature Spec**: [${this.featureId}](${baseUrl}/.specweave/docs/internal/specs/_features/${this.featureId}/FEATURE.md)`);
537
+ sections.push(`- **Feature Spec**: [${this.featureId}](${baseUrl}/.specweave/docs/internal/specs/${projectFolder}/${this.featureId}/FEATURE.md)`);
533
538
 
534
539
  // User Story File link (relative to project root)
535
540
  const relativeUSPath = path.relative(this.projectRoot, this.userStoryPath);
@@ -543,7 +548,10 @@ export class UserStoryIssueBuilder {
543
548
  }
544
549
  } else {
545
550
  // Fallback to relative links if repo info not provided
546
- sections.push(`- **Feature Spec**: [${this.featureId}](../.specweave/docs/internal/specs/_features/${this.featureId}/FEATURE.md)`);
551
+ // v5.0.0+: Features live in project folders, NOT _features
552
+ const pathMatch = this.userStoryPath.match(/specs\/([^/]+)\/FS-\d+\//);
553
+ const projectFolder = pathMatch ? pathMatch[1] : 'default';
554
+ sections.push(`- **Feature Spec**: [${this.featureId}](../.specweave/docs/internal/specs/${projectFolder}/${this.featureId}/FEATURE.md)`);
547
555
  sections.push(`- **User Story File**: [${path.basename(this.userStoryPath)}](${this.userStoryPath})`);
548
556
  }
549
557
 
@@ -70,12 +70,14 @@ Every GitHub issue MUST include:
70
70
  - Use GitHub task checkbox format
71
71
  - Example: `- [x] [T-008: Title](https://github.com/owner/repo/tree/develop/.specweave/increments/0031/tasks.md#t-008-title)`
72
72
 
73
- 3. **Working GitHub URLs**
74
- - Feature links: `https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/_features/FS-031`
75
- - User story links: `https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/default/FS-031/us-004-*.md`
73
+ 3. **Working GitHub URLs** (v5.0.0+ - NO _features folder)
74
+ - Feature links: `https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/{project}/FS-031`
75
+ - User story links: `https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/{project}/FS-031/us-004-*.md`
76
76
  - Task links: `https://github.com/owner/repo/tree/develop/.specweave/increments/0031/tasks.md#task-anchor`
77
77
  - Increment links: `https://github.com/owner/repo/tree/develop/.specweave/increments/0031`
78
78
 
79
+ **Note**: Feature ID is DERIVED from increment (0031 → FS-031)
80
+
79
81
  4. **Extracted Priority**
80
82
  - Extract from ACs (highest priority wins: P1 > P2 > P3)
81
83
  - Show ONLY if priority exists (don't show "undefined")
@@ -87,7 +89,7 @@ Every GitHub issue MUST include:
87
89
 
88
90
  ### ❌ Never Use
89
91
 
90
- - ❌ Relative paths (`../../_features/FS-031`)
92
+ - ❌ Relative paths (`../../{project}/FS-031`)
91
93
  - ❌ Undefined values (`**Priority**: undefined`)
92
94
  - ❌ Project field in metadata
93
95
  - ❌ Plain bullet points for ACs (must be checkboxes)
@@ -112,8 +114,8 @@ private async detectGitHubRepo(): Promise<string | null>
112
114
  // 3. Extract priority from ACs
113
115
  private extractPriorityFromACs(criteria: AcceptanceCriterion[]): string | null
114
116
 
115
- // 4. Generate GitHub URLs (not relative)
116
- const featureUrl = `https://github.com/${repo}/tree/develop/.specweave/docs/internal/specs/_features/${featureId}`;
117
+ // 4. Generate GitHub URLs (not relative) - v5.0.0+: No _features folder
118
+ const featureUrl = `https://github.com/${repo}/tree/develop/.specweave/docs/internal/specs/${project}/${featureId}`;
117
119
 
118
120
  // 5. Convert task links to GitHub URLs
119
121
  if (repo && taskLink.startsWith('../../')) {
@@ -125,7 +127,7 @@ if (repo && taskLink.startsWith('../../')) {
125
127
  ### Template
126
128
 
127
129
  ```markdown
128
- **Feature**: [FS-031](https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/_features/FS-031)
130
+ **Feature**: [FS-031](https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/{project}/FS-031)
129
131
  **Status**: complete
130
132
  **Priority**: P1
131
133
 
@@ -137,7 +139,7 @@ if (repo && taskLink.startsWith('../../')) {
137
139
  **I want** feature
138
140
  **So that** benefit
139
141
 
140
- 📄 View full story: [`us-004-name.md`](https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/default/_archive/FS-031/us-004-name.md)
142
+ 📄 View full story: [`us-004-name.md`](https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/{project}/FS-031/us-004-name.md)
141
143
 
142
144
  ---
143
145