specweave 0.14.0 → 0.15.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.
Files changed (34) hide show
  1. package/README.md +58 -9
  2. package/bin/specweave.js +65 -0
  3. package/dist/cli/commands/migrate-to-profiles.d.ts.map +1 -1
  4. package/dist/cli/commands/migrate-to-profiles.js +0 -2
  5. package/dist/cli/commands/migrate-to-profiles.js.map +1 -1
  6. package/dist/core/sync/folder-mapper.d.ts.map +1 -1
  7. package/dist/core/sync/folder-mapper.js +70 -35
  8. package/dist/core/sync/folder-mapper.js.map +1 -1
  9. package/dist/core/sync/profile-validator.d.ts.map +1 -1
  10. package/dist/core/sync/profile-validator.js +35 -90
  11. package/dist/core/sync/profile-validator.js.map +1 -1
  12. package/dist/core/types/sync-profile.d.ts +101 -155
  13. package/dist/core/types/sync-profile.d.ts.map +1 -1
  14. package/dist/core/types/sync-profile.js +46 -22
  15. package/dist/core/types/sync-profile.js.map +1 -1
  16. package/dist/utils/env-multi-project-parser.d.ts.map +1 -1
  17. package/dist/utils/env-multi-project-parser.js +0 -2
  18. package/dist/utils/env-multi-project-parser.js.map +1 -1
  19. package/dist/utils/project-mapper.d.ts +19 -1
  20. package/dist/utils/project-mapper.d.ts.map +1 -1
  21. package/dist/utils/project-mapper.js +7 -4
  22. package/dist/utils/project-mapper.js.map +1 -1
  23. package/dist/utils/spec-splitter.d.ts +7 -0
  24. package/dist/utils/spec-splitter.d.ts.map +1 -1
  25. package/dist/utils/spec-splitter.js +20 -2
  26. package/dist/utils/spec-splitter.js.map +1 -1
  27. package/package.json +1 -1
  28. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +40 -7
  29. package/plugins/specweave-ado/lib/ado-multi-project-sync.ts +49 -7
  30. package/plugins/specweave-github/hooks/hooks.json +0 -11
  31. package/plugins/specweave-github/lib/github-multi-project-sync.js +58 -5
  32. package/plugins/specweave-github/lib/github-multi-project-sync.ts +80 -4
  33. package/plugins/specweave-jira/lib/jira-multi-project-sync.js +30 -5
  34. package/plugins/specweave-jira/lib/jira-multi-project-sync.ts +34 -5
@@ -71,6 +71,28 @@ export class JiraMultiProjectSync {
71
71
  });
72
72
  }
73
73
 
74
+ /**
75
+ * Pre-flight validation: Verify all JIRA projects exist
76
+ *
77
+ * @throws Error if any projects are missing
78
+ */
79
+ async validateProjects(): Promise<void> {
80
+ if (!this.config.projects || this.config.projects.length === 0) {
81
+ throw new Error('No JIRA projects configured for validation');
82
+ }
83
+
84
+ // Validate projects exist
85
+ const missing = await validateJiraProjects(this.client, this.config.projects);
86
+
87
+ if (missing.length > 0) {
88
+ throw new Error(
89
+ `❌ Pre-flight check failed: Missing JIRA projects:\n` +
90
+ missing.map(p => ` - ${p} (${this.config.domain})`).join('\n') +
91
+ `\n\nPlease verify project keys and access permissions.`
92
+ );
93
+ }
94
+ }
95
+
74
96
  /**
75
97
  * Sync spec to JIRA projects with intelligent mapping
76
98
  *
@@ -80,6 +102,9 @@ export class JiraMultiProjectSync {
80
102
  async syncSpec(specPath: string): Promise<JiraSyncResult[]> {
81
103
  const results: JiraSyncResult[] = [];
82
104
 
105
+ // Pre-flight validation: Verify all projects exist
106
+ await this.validateProjects();
107
+
83
108
  // Parse spec
84
109
  const parsedSpec = await parseSpecFile(specPath);
85
110
 
@@ -100,16 +125,20 @@ export class JiraMultiProjectSync {
100
125
  for (const userStory of parsedSpec.userStories) {
101
126
  if (this.config.intelligentMapping !== false) {
102
127
  // Intelligent mapping (default)
103
- const mappings = mapUserStoryToProjects(userStory);
128
+ const mapperConfig = {
129
+ confidenceThreshold: this.config.confidenceThreshold
130
+ };
131
+ const primary = getPrimaryProject(userStory, undefined, mapperConfig);
104
132
 
105
- if (mappings.length > 0 && mappings[0].confidence >= 0.3) {
106
- const primary = mappings[0];
133
+ if (primary) {
107
134
  const existing = projectStories.get(primary.projectId) || [];
108
135
  existing.push({ story: userStory, confidence: primary.confidence });
109
136
  projectStories.set(primary.projectId, existing);
110
137
  } else {
111
138
  // No confident match - assign to first project or skip
112
- console.warn(`⚠️ Low confidence for ${userStory.id} (${(mappings[0]?.confidence || 0) * 100}%) - assigning to ${this.config.projects[0]}`);
139
+ const mappings = mapUserStoryToProjects(userStory);
140
+ const threshold = this.config.confidenceThreshold ?? 0.3;
141
+ console.warn(`⚠️ Low confidence for ${userStory.id} (${(mappings[0]?.confidence || 0) * 100}% < ${threshold * 100}% threshold) - assigning to ${this.config.projects[0]}`);
113
142
  const fallback = this.config.projects[0];
114
143
  const existing = projectStories.get(fallback) || [];
115
144
  existing.push({ story: userStory, confidence: mappings[0]?.confidence || 0 });
@@ -156,7 +185,7 @@ export class JiraMultiProjectSync {
156
185
 
157
186
  *Status*: ${parsedSpec.metadata.status}
158
187
  *Priority*: ${parsedSpec.metadata.priority}
159
- *Estimated Effort*: ${parsedSpec.metadata.estimatedEffort || parsedSpec.metadata.estimated_effort}
188
+ *Estimated Effort*: ${parsedSpec.metadata.estimatedEffort || 'TBD'}
160
189
 
161
190
  h3. Executive Summary
162
191