specweave 0.22.2 → 0.22.4

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 (93) hide show
  1. package/CLAUDE.md +300 -920
  2. package/dist/src/cli/commands/repair-status-desync.d.ts +69 -0
  3. package/dist/src/cli/commands/repair-status-desync.d.ts.map +1 -0
  4. package/dist/src/cli/commands/repair-status-desync.js +221 -0
  5. package/dist/src/cli/commands/repair-status-desync.js.map +1 -0
  6. package/dist/src/cli/commands/sync-specs.d.ts +4 -1
  7. package/dist/src/cli/commands/sync-specs.d.ts.map +1 -1
  8. package/dist/src/cli/commands/sync-specs.js +99 -49
  9. package/dist/src/cli/commands/sync-specs.js.map +1 -1
  10. package/dist/src/cli/commands/validate-status-sync.d.ts +52 -0
  11. package/dist/src/cli/commands/validate-status-sync.d.ts.map +1 -0
  12. package/dist/src/cli/commands/validate-status-sync.js +176 -0
  13. package/dist/src/cli/commands/validate-status-sync.js.map +1 -0
  14. package/dist/src/cli/update-status-line.d.ts +16 -0
  15. package/dist/src/cli/update-status-line.d.ts.map +1 -0
  16. package/dist/src/cli/update-status-line.js +44 -0
  17. package/dist/src/cli/update-status-line.js.map +1 -0
  18. package/dist/src/core/cicd/workflow-monitor.d.ts +4 -0
  19. package/dist/src/core/cicd/workflow-monitor.d.ts.map +1 -1
  20. package/dist/src/core/cicd/workflow-monitor.js +6 -2
  21. package/dist/src/core/cicd/workflow-monitor.js.map +1 -1
  22. package/dist/src/core/increment/completion-validator.d.ts +56 -0
  23. package/dist/src/core/increment/completion-validator.d.ts.map +1 -0
  24. package/dist/src/core/increment/completion-validator.js +102 -0
  25. package/dist/src/core/increment/completion-validator.js.map +1 -0
  26. package/dist/src/core/increment/increment-archiver.d.ts +4 -1
  27. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  28. package/dist/src/core/increment/increment-archiver.js +21 -9
  29. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  30. package/dist/src/core/increment/metadata-manager.d.ts +22 -0
  31. package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
  32. package/dist/src/core/increment/metadata-manager.js +62 -0
  33. package/dist/src/core/increment/metadata-manager.js.map +1 -1
  34. package/dist/src/core/increment/spec-frontmatter-updater.d.ts +78 -0
  35. package/dist/src/core/increment/spec-frontmatter-updater.d.ts.map +1 -0
  36. package/dist/src/core/increment/spec-frontmatter-updater.js +152 -0
  37. package/dist/src/core/increment/spec-frontmatter-updater.js.map +1 -0
  38. package/dist/src/core/increment/spec-sync-manager.d.ts +5 -1
  39. package/dist/src/core/increment/spec-sync-manager.d.ts.map +1 -1
  40. package/dist/src/core/increment/spec-sync-manager.js +4 -2
  41. package/dist/src/core/increment/spec-sync-manager.js.map +1 -1
  42. package/dist/src/core/increment-utils.d.ts.map +1 -1
  43. package/dist/src/core/increment-utils.js +18 -1
  44. package/dist/src/core/increment-utils.js.map +1 -1
  45. package/dist/src/core/living-docs/living-docs-sync.d.ts +5 -1
  46. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  47. package/dist/src/core/living-docs/living-docs-sync.js +36 -33
  48. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  49. package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -1
  50. package/dist/src/core/living-docs/task-project-specific-generator.js +13 -8
  51. package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -1
  52. package/dist/src/core/status-line/status-line-manager.d.ts +3 -2
  53. package/dist/src/core/status-line/status-line-manager.d.ts.map +1 -1
  54. package/dist/src/core/status-line/status-line-manager.js +42 -17
  55. package/dist/src/core/status-line/status-line-manager.js.map +1 -1
  56. package/dist/src/core/status-line/status-line-updater.d.ts +67 -0
  57. package/dist/src/core/status-line/status-line-updater.d.ts.map +1 -0
  58. package/dist/src/core/status-line/status-line-updater.js +203 -0
  59. package/dist/src/core/status-line/status-line-updater.js.map +1 -0
  60. package/dist/src/core/status-line/types.d.ts +19 -5
  61. package/dist/src/core/status-line/types.d.ts.map +1 -1
  62. package/dist/src/core/status-line/types.js +3 -3
  63. package/dist/src/core/status-line/types.js.map +1 -1
  64. package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
  65. package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -0
  66. package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
  67. package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
  68. package/dist/src/integrations/jira/jira-mapper.js +4 -0
  69. package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
  70. package/dist/src/utils/logger.d.ts +48 -0
  71. package/dist/src/utils/logger.d.ts.map +1 -0
  72. package/dist/src/utils/logger.js +53 -0
  73. package/dist/src/utils/logger.js.map +1 -0
  74. package/package.json +3 -2
  75. package/plugins/specweave/agents/code-standards-detective/AGENT.md +828 -0
  76. package/plugins/specweave/agents/test-aware-planner/templates/task-non-testable.md.template +12 -0
  77. package/plugins/specweave/agents/test-aware-planner/templates/task-testable.md.template +12 -0
  78. package/plugins/specweave/commands/specweave-analyze-standards.sh +315 -0
  79. package/plugins/specweave/commands/specweave-done.md +91 -4
  80. package/plugins/specweave/commands/specweave-reopen.md +29 -2
  81. package/plugins/specweave/commands/specweave-sync-docs.md +137 -22
  82. package/plugins/specweave/commands/specweave-update-status.md +151 -0
  83. package/plugins/specweave/hooks/lib/update-status-line.sh +39 -8
  84. package/plugins/specweave/hooks/user-prompt-submit.sh +21 -0
  85. package/plugins/specweave/hooks/validate-increment-completion.sh +113 -0
  86. package/plugins/specweave/skills/brownfield-analyzer/SKILL.md +40 -3
  87. package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +455 -0
  88. package/plugins/specweave/templates/coding-standards.md.template +447 -0
  89. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
  90. package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +21 -0
  91. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
  92. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
  93. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -3222
@@ -0,0 +1,447 @@
1
+ # Coding Standards
2
+
3
+ **Auto-Generated**: {{timestamp}}
4
+ **Codebase**: {{project_name}}
5
+ **Analysis**: {{file_count}} files, {{line_count}} lines of code
6
+ **Overall Confidence**: {{overall_confidence}}%
7
+
8
+ > 📊 This document combines:
9
+ > - ✅ **Explicit Standards** - Declared in ESLint, Prettier, CLAUDE.md
10
+ > - 📈 **Implicit Standards** - Detected from codebase analysis ({{file_count}} files)
11
+ > - 🚨 **Issues** - Anti-patterns and security concerns
12
+
13
+ ---
14
+
15
+ ## Table of Contents
16
+
17
+ 1. [Summary](#summary)
18
+ 2. [Naming Conventions](#naming-conventions)
19
+ 3. [Import Patterns](#import-patterns)
20
+ 4. [Function Guidelines](#function-guidelines)
21
+ 5. [Type Safety](#type-safety)
22
+ 6. [Error Handling](#error-handling)
23
+ 7. [Security](#security)
24
+ 8. [Performance](#performance)
25
+ 9. [SpecWeave-Specific Rules](#specweave-specific-rules)
26
+ 10. [Anti-Patterns & Issues](#anti-patterns--issues)
27
+ 11. [Next Steps](#next-steps)
28
+ 12. [Appendix](#appendix)
29
+
30
+ ---
31
+
32
+ ## Summary
33
+
34
+ ### Confidence Levels
35
+
36
+ | Level | Criteria | Meaning |
37
+ |-------|----------|---------|
38
+ | **ENFORCED** | 100% | Linter/compiler enforced |
39
+ | **HIGH** | 90%+ | Overwhelming compliance |
40
+ | **MEDIUM** | 70-89% | Majority compliance |
41
+ | **LOW** | 50-69% | Weak pattern |
42
+ | **CONFLICT** | <50% | Inconsistent, needs decision |
43
+
44
+ ### Overall Health
45
+
46
+ {{overall_health_summary}}
47
+
48
+ ---
49
+
50
+ ## 1. Naming Conventions
51
+
52
+ ### Variables
53
+
54
+ **Standard**: {{variable_naming_standard}}
55
+ **Confidence**: {{variable_naming_confidence}}
56
+ **Compliance**: {{variable_naming_compliance}}%
57
+ **Samples**: {{variable_naming_samples}}
58
+
59
+ **Enforced by**: {{variable_naming_enforcement}}
60
+
61
+ **Examples**:
62
+ ```typescript
63
+ // ✅ Good ({{variable_naming_good_percent}}% of codebase)
64
+ {{variable_naming_good_examples}}
65
+
66
+ // ❌ Bad ({{variable_naming_bad_percent}}% of codebase)
67
+ {{variable_naming_bad_examples}}
68
+ ```
69
+
70
+ **Recommendation**: {{variable_naming_recommendation}}
71
+
72
+ ---
73
+
74
+ ### Functions
75
+
76
+ **Standard**: {{function_naming_standard}}
77
+ **Confidence**: {{function_naming_confidence}}
78
+ **Compliance**: {{function_naming_compliance}}%
79
+ **Samples**: {{function_naming_samples}}
80
+
81
+ **Examples**:
82
+ ```typescript
83
+ // ✅ Good
84
+ {{function_naming_good_examples}}
85
+
86
+ // ❌ Bad
87
+ {{function_naming_bad_examples}}
88
+ ```
89
+
90
+ **Recommendation**: {{function_naming_recommendation}}
91
+
92
+ ---
93
+
94
+ ### Classes
95
+
96
+ **Standard**: {{class_naming_standard}}
97
+ **Confidence**: {{class_naming_confidence}}
98
+ **Compliance**: {{class_naming_compliance}}%
99
+ **Samples**: {{class_naming_samples}}
100
+
101
+ **Examples**:
102
+ ```typescript
103
+ // ✅ Good
104
+ {{class_naming_good_examples}}
105
+
106
+ // ❌ Bad (if any)
107
+ {{class_naming_bad_examples}}
108
+ ```
109
+
110
+ **Recommendation**: {{class_naming_recommendation}}
111
+
112
+ ---
113
+
114
+ ### Constants
115
+
116
+ **Standard**: {{constant_naming_standard}}
117
+ **Confidence**: {{constant_naming_confidence}}
118
+ **Compliance**: {{constant_naming_compliance}}%
119
+ **Samples**: {{constant_naming_samples}}
120
+
121
+ **Examples**:
122
+ ```typescript
123
+ // ✅ Good
124
+ {{constant_naming_good_examples}}
125
+
126
+ // ⚠️ Inconsistent ({{constant_naming_bad_percent}}% use different convention)
127
+ {{constant_naming_bad_examples}}
128
+ ```
129
+
130
+ **Recommendation**: {{constant_naming_recommendation}}
131
+
132
+ ---
133
+
134
+ ## 2. Import Patterns
135
+
136
+ ### File Extensions
137
+
138
+ **Standard**: {{import_extension_standard}}
139
+ **Confidence**: {{import_extension_confidence}}
140
+ **Compliance**: {{import_extension_compliance}}%
141
+
142
+ **Enforced by**: {{import_extension_enforcement}}
143
+
144
+ **Examples**:
145
+ ```typescript
146
+ // ✅ Good ({{import_extension_good_percent}}% compliance)
147
+ {{import_extension_good_examples}}
148
+
149
+ // ❌ Bad ({{import_extension_bad_percent}}% if any)
150
+ {{import_extension_bad_examples}}
151
+ ```
152
+
153
+ **Recommendation**: {{import_extension_recommendation}}
154
+
155
+ ---
156
+
157
+ ### Import Ordering
158
+
159
+ **Standard**: {{import_ordering_standard}}
160
+ **Confidence**: {{import_ordering_confidence}}
161
+ **Compliance**: {{import_ordering_compliance}}%
162
+
163
+ **Examples**:
164
+ ```typescript
165
+ // ✅ Good ({{import_ordering_good_percent}}% of files)
166
+ {{import_ordering_good_examples}}
167
+
168
+ // ⚠️ Not followed ({{import_ordering_bad_percent}}% of files)
169
+ {{import_ordering_bad_examples}}
170
+ ```
171
+
172
+ **Recommendation**: {{import_ordering_recommendation}}
173
+
174
+ ---
175
+
176
+ ## 3. Function Guidelines
177
+
178
+ ### Function Length
179
+
180
+ **Detected Pattern**:
181
+ - **Average**: {{function_length_avg}} lines
182
+ - **Median**: {{function_length_median}} lines
183
+ - **90th percentile**: {{function_length_p90}} lines
184
+ - **Max**: {{function_length_max}} lines ({{function_length_max_location}})
185
+
186
+ **Recommended**: <50 lines (ideal), <100 lines (max)
187
+
188
+ **Violations** ({{function_length_violations}} functions >100 lines):
189
+ {{function_length_violations_list}}
190
+
191
+ **Recommendation**: {{function_length_recommendation}}
192
+
193
+ ---
194
+
195
+ ### Function Style
196
+
197
+ **Detected Pattern**:
198
+ - Arrow functions: {{arrow_function_percent}}%
199
+ - Regular functions: {{regular_function_percent}}%
200
+
201
+ **Examples**:
202
+ ```typescript
203
+ // Preferred ({{arrow_function_percent}}% of codebase)
204
+ {{arrow_function_examples}}
205
+
206
+ // Also acceptable ({{regular_function_percent}}% of codebase)
207
+ {{regular_function_examples}}
208
+ ```
209
+
210
+ **Recommendation**: {{function_style_recommendation}}
211
+
212
+ ---
213
+
214
+ ## 4. Type Safety
215
+
216
+ ### Avoid `any` Type
217
+
218
+ **Detected**: {{any_type_count}} instances of `any` type
219
+
220
+ **Enforced by**: {{any_type_enforcement}}
221
+
222
+ **Violations**:
223
+ {{any_type_violations_list}}
224
+
225
+ **Recommendation**: {{any_type_recommendation}}
226
+
227
+ ---
228
+
229
+ ### Interface vs Type
230
+
231
+ **Detected Pattern**:
232
+ - Interfaces: {{interface_percent}}%
233
+ - Types: {{type_percent}}%
234
+
235
+ **Examples**:
236
+ ```typescript
237
+ // Preferred for objects ({{interface_percent}}% of codebase)
238
+ {{interface_examples}}
239
+
240
+ // Preferred for unions/aliases ({{type_percent}}% of codebase)
241
+ {{type_examples}}
242
+ ```
243
+
244
+ **Recommendation**: {{interface_type_recommendation}}
245
+
246
+ ---
247
+
248
+ ## 5. Error Handling
249
+
250
+ ### Custom Error Types
251
+
252
+ **Detected**: {{custom_error_count}} custom error classes
253
+
254
+ **Examples**:
255
+ ```typescript
256
+ {{custom_error_examples}}
257
+ ```
258
+
259
+ **Recommendation**: {{custom_error_recommendation}}
260
+
261
+ ---
262
+
263
+ ### Try/Catch Usage
264
+
265
+ **Detected**: {{try_catch_percent}}% of async functions have try/catch
266
+
267
+ **Examples**:
268
+ ```typescript
269
+ // ✅ Good ({{try_catch_good_count}} functions)
270
+ {{try_catch_good_examples}}
271
+
272
+ // ⚠️ Missing error handling ({{try_catch_missing_count}} functions)
273
+ {{try_catch_missing_list}}
274
+ ```
275
+
276
+ **Recommendation**: {{try_catch_recommendation}}
277
+
278
+ ---
279
+
280
+ ## 6. Security
281
+
282
+ ### No Hardcoded Secrets
283
+
284
+ **Status**: {{hardcoded_secrets_status}}
285
+
286
+ **Violations** ({{hardcoded_secrets_count}} instances):
287
+ {{hardcoded_secrets_list}}
288
+
289
+ **Recommendation**: {{hardcoded_secrets_recommendation}}
290
+
291
+ ---
292
+
293
+ ### No console.* in Production
294
+
295
+ **Status**: {{console_usage_status}}
296
+
297
+ **Violations** ({{console_usage_count}} instances):
298
+ {{console_usage_list}}
299
+
300
+ **Recommendation**: {{console_usage_recommendation}}
301
+
302
+ ---
303
+
304
+ ## 7. Performance
305
+
306
+ ### No N+1 Queries
307
+
308
+ **Status**: {{n_plus_one_status}}
309
+
310
+ {{n_plus_one_details}}
311
+
312
+ **Recommendation**: {{n_plus_one_recommendation}}
313
+
314
+ ---
315
+
316
+ ## 8. SpecWeave-Specific Rules
317
+
318
+ ### 1. Logger Abstraction
319
+
320
+ **Rule**: NEVER use console.* in src/
321
+
322
+ **Compliance**: {{logger_compliance}}%
323
+
324
+ **Violations**: {{logger_violations_count}} instances
325
+
326
+ **Correct usage**:
327
+ ```typescript
328
+ import { logger } from '../utils/logger.js';
329
+ logger.info('Message');
330
+ logger.error('Error', error);
331
+ ```
332
+
333
+ ---
334
+
335
+ ### 2. Test File Naming
336
+
337
+ **Rule**: Use .test.ts suffix (NEVER .spec.ts)
338
+
339
+ **Compliance**: {{test_naming_compliance}}%
340
+
341
+ ---
342
+
343
+ ### 3. Import Extensions
344
+
345
+ **Rule**: ALWAYS use .js extensions for ESM compatibility
346
+
347
+ **Compliance**: {{import_extension_compliance}}%
348
+
349
+ ---
350
+
351
+ ## 9. Anti-Patterns & Issues
352
+
353
+ ### 🔴 CRITICAL ({{critical_issues_count}} issues)
354
+
355
+ {{critical_issues_list}}
356
+
357
+ ---
358
+
359
+ ### 🟠 HIGH ({{high_issues_count}} issues)
360
+
361
+ {{high_issues_list}}
362
+
363
+ ---
364
+
365
+ ### 🟡 MEDIUM ({{medium_issues_count}} issues)
366
+
367
+ {{medium_issues_list}}
368
+
369
+ ---
370
+
371
+ ### 🟢 LOW
372
+
373
+ {{low_issues_summary}}
374
+
375
+ ---
376
+
377
+ ## 10. Next Steps
378
+
379
+ ### Critical (Fix Immediately)
380
+ {{critical_next_steps}}
381
+
382
+ ### High Priority (This Sprint)
383
+ {{high_priority_next_steps}}
384
+
385
+ ### Medium Priority (Next Sprint)
386
+ {{medium_priority_next_steps}}
387
+
388
+ ### Documentation
389
+ {{documentation_next_steps}}
390
+
391
+ ---
392
+
393
+ ## 11. Appendix
394
+
395
+ ### Configuration Files
396
+
397
+ #### .eslintrc.json
398
+ ```json
399
+ {{eslint_config}}
400
+ ```
401
+
402
+ #### .prettierrc
403
+ ```json
404
+ {{prettier_config}}
405
+ ```
406
+
407
+ #### tsconfig.json (relevant sections)
408
+ ```json
409
+ {{tsconfig_config}}
410
+ ```
411
+
412
+ ---
413
+
414
+ ### Statistics
415
+
416
+ | Metric | Value |
417
+ |--------|-------|
418
+ | Total Files | {{file_count}} |
419
+ | Total LOC | {{line_count}} |
420
+ | Variables Analyzed | {{variable_count}} |
421
+ | Functions Analyzed | {{function_count}} |
422
+ | Classes Analyzed | {{class_count}} |
423
+ | Imports Analyzed | {{import_count}} |
424
+ | Analysis Duration | {{analysis_duration}} |
425
+
426
+ ---
427
+
428
+ ### Change Log
429
+
430
+ **Previous Analysis**: {{previous_analysis_date}}
431
+ **This Analysis**: {{current_analysis_date}}
432
+
433
+ **Changes Since Last Analysis**:
434
+ {{change_log}}
435
+
436
+ ---
437
+
438
+ ## Metadata
439
+
440
+ **Generated by**: SpecWeave code-standards-detective agent
441
+ **Version**: {{specweave_version}}
442
+ **Analysis Date**: {{analysis_date}}
443
+ **Next Review**: {{next_review_date}} (recommended: quarterly)
444
+
445
+ ---
446
+
447
+ *This document is auto-generated. For questions or updates, consult the development team.*
@@ -373,7 +373,6 @@ ${userStory.technicalContext}
373
373
  return mapping.task || "Task";
374
374
  case "Subtask":
375
375
  return mapping.task || "Task";
376
- // ADO doesn't have subtasks, use Task
377
376
  default:
378
377
  return "User Story";
379
378
  }
@@ -1,6 +1,27 @@
1
1
  ---
2
2
  name: specweave-github:cleanup-duplicates
3
3
  description: Clean up duplicate GitHub issues for an Epic. Finds issues with duplicate titles and closes all except the first created issue.
4
+ justification: |
5
+ CRITICAL INCIDENT RESPONSE TOOL - DO NOT DELETE!
6
+
7
+ Why This Command Exists:
8
+ - Prevention systems (deduplication, GitHub self-healing) work for single-process execution
9
+ - Multiple parallel Claude Code instances bypass all prevention (file-based cache, no distributed locking)
10
+ - GitHub API race conditions: Time gap between "check exists" and "create issue" allows duplicates
11
+ - Historical duplicates from pre-v0.14.1 users (before prevention was added)
12
+
13
+ Evidence of Need:
14
+ - 2025-11-13: 123 duplicate GitHub issues incident (cleaned to 29 unique)
15
+ - Parallel execution creates race conditions that prevention CANNOT solve
16
+ - Industry standard: Prevention + Detection + Cleanup (defense in depth)
17
+
18
+ When to Delete:
19
+ - ONLY if distributed locking implemented (Redis/file locks)
20
+ - AND parallel execution tested (100+ concurrent syncs with zero duplicates)
21
+ - AND zero duplicates for 6+ months in production
22
+ - AND all users migrated to prevention-enabled versions
23
+
24
+ See: .specweave/increments/0043-spec-md-desync-fix/reports/ULTRATHINK-CLEANUP-DUPLICATES-NECESSITY-2025-11-18.md
4
25
  ---
5
26
 
6
27
  # Clean Up Duplicate GitHub Issues
@@ -1,6 +1,6 @@
1
- import { EnhancedContentBuilder } from "../../../dist/src/core/sync/enhanced-content-builder.js";
2
- import { SpecIncrementMapper } from "../../../dist/src/core/sync/spec-increment-mapper.js";
3
- import { parseSpecContent } from "../../../dist/src/core/spec-content-sync.js";
1
+ import { EnhancedContentBuilder } from "../../../src/core/sync/enhanced-content-builder.js";
2
+ import { SpecIncrementMapper } from "../../../src/core/sync/spec-increment-mapper.js";
3
+ import { parseSpecContent } from "../../../src/core/spec-content-sync.js";
4
4
  import * as path from "path";
5
5
  import * as fs from "fs/promises";
6
6
  async function syncSpecToJiraWithEnhancedContent(options) {
@@ -1,170 +0,0 @@
1
- import { AdoClientV2 } from "./ado-client-v2.js";
2
- import { EnhancedContentBuilder } from "../../../src/core/sync/enhanced-content-builder.js";
3
- import { SpecIncrementMapper } from "../../../src/core/sync/spec-increment-mapper.js";
4
- import { parseSpecContent } from "../../../src/core/spec-content-sync.js";
5
- import path from "path";
6
- import fs from "fs/promises";
7
- async function syncSpecToAdoWithEnhancedContent(options) {
8
- const { specPath, organization, project, dryRun = false, verbose = false } = options;
9
- try {
10
- const baseSpec = await parseSpecContent(specPath);
11
- if (!baseSpec) {
12
- return {
13
- success: false,
14
- action: "error",
15
- error: "Failed to parse spec content"
16
- };
17
- }
18
- if (verbose) {
19
- console.log(`\u{1F4C4} Parsed spec: ${baseSpec.identifier.compact}`);
20
- }
21
- const specId = baseSpec.identifier.full || baseSpec.identifier.compact;
22
- const rootDir = await findSpecWeaveRoot(specPath);
23
- const mapper = new SpecIncrementMapper(rootDir);
24
- const mapping = await mapper.mapSpecToIncrements(specId);
25
- if (verbose) {
26
- console.log(`\u{1F517} Found ${mapping.increments.length} related increments`);
27
- }
28
- const taskMapping = buildTaskMapping(mapping.increments, organization, project);
29
- const architectureDocs = await findArchitectureDocs(rootDir, specId);
30
- const enhancedSpec = {
31
- ...baseSpec,
32
- summary: baseSpec.description,
33
- taskMapping,
34
- architectureDocs
35
- };
36
- const builder = new EnhancedContentBuilder();
37
- const description = builder.buildExternalDescription(enhancedSpec);
38
- if (verbose) {
39
- console.log(`\u{1F4DD} Generated description: ${description.length} characters`);
40
- }
41
- if (dryRun) {
42
- console.log("\u{1F50D} DRY RUN - Would create/update feature with:");
43
- console.log(` Title: ${baseSpec.title}`);
44
- console.log(` Description length: ${description.length}`);
45
- return {
46
- success: true,
47
- action: "no-change",
48
- tasksLinked: taskMapping?.tasks.length || 0
49
- };
50
- }
51
- if (!organization || !project) {
52
- return {
53
- success: false,
54
- action: "error",
55
- error: "Azure DevOps organization/project not specified"
56
- };
57
- }
58
- const profile = {
59
- provider: "ado",
60
- displayName: `${organization}/${project}`,
61
- config: {
62
- organization,
63
- project
64
- },
65
- timeRange: { default: "1M", max: "6M" }
66
- };
67
- const pat = process.env.AZURE_DEVOPS_PAT || "";
68
- const client = new AdoClientV2(profile, pat);
69
- const existingFeature = await findExistingFeature(client, baseSpec.identifier.compact);
70
- let result;
71
- if (existingFeature) {
72
- await client.updateWorkItem(existingFeature.id, {
73
- title: `[${baseSpec.identifier.compact}] ${baseSpec.title}`,
74
- description
75
- });
76
- result = {
77
- success: true,
78
- action: "updated",
79
- featureId: existingFeature.id,
80
- featureUrl: `https://dev.azure.com/${organization}/${project}/_workitems/edit/${existingFeature.id}`,
81
- tasksLinked: taskMapping?.tasks.length || 0
82
- };
83
- } else {
84
- const feature = await client.createEpic({
85
- title: `[${baseSpec.identifier.compact}] ${baseSpec.title}`,
86
- description,
87
- tags: ["spec", "external-tool-sync"]
88
- });
89
- result = {
90
- success: true,
91
- action: "created",
92
- featureId: feature.id,
93
- featureUrl: `https://dev.azure.com/${organization}/${project}/_workitems/edit/${feature.id}`,
94
- tasksLinked: taskMapping?.tasks.length || 0
95
- };
96
- }
97
- if (verbose) {
98
- console.log(`\u2705 ${result.action === "created" ? "Created" : "Updated"} feature #${result.featureId}`);
99
- }
100
- return result;
101
- } catch (error) {
102
- return {
103
- success: false,
104
- action: "error",
105
- error: error.message
106
- };
107
- }
108
- }
109
- async function findSpecWeaveRoot(specPath) {
110
- let currentDir = path.dirname(specPath);
111
- while (true) {
112
- const specweaveDir = path.join(currentDir, ".specweave");
113
- try {
114
- await fs.access(specweaveDir);
115
- return currentDir;
116
- } catch {
117
- const parentDir = path.dirname(currentDir);
118
- if (parentDir === currentDir) {
119
- throw new Error(".specweave directory not found");
120
- }
121
- currentDir = parentDir;
122
- }
123
- }
124
- }
125
- function buildTaskMapping(increments, organization, project) {
126
- if (increments.length === 0) return void 0;
127
- const firstIncrement = increments[0];
128
- const tasks = firstIncrement.tasks.map((task) => ({
129
- id: task.id,
130
- title: task.title,
131
- userStories: task.userStories
132
- }));
133
- return {
134
- incrementId: firstIncrement.id,
135
- tasks,
136
- tasksUrl: `https://dev.azure.com/${organization}/${project}/_git/repo?path=/.specweave/increments/${firstIncrement.id}/tasks.md`
137
- };
138
- }
139
- async function findArchitectureDocs(rootDir, specId) {
140
- const docs = [];
141
- const archDir = path.join(rootDir, ".specweave/docs/internal/architecture");
142
- try {
143
- const adrDir = path.join(archDir, "adr");
144
- try {
145
- const adrs = await fs.readdir(adrDir);
146
- const relatedAdrs = adrs.filter((file) => file.includes(specId.replace("spec-", "")));
147
- for (const adr of relatedAdrs) {
148
- docs.push({
149
- type: "adr",
150
- path: path.join(adrDir, adr),
151
- title: adr.replace(".md", "").replace(/-/g, " ")
152
- });
153
- }
154
- } catch {
155
- }
156
- } catch {
157
- }
158
- return docs;
159
- }
160
- async function findExistingFeature(client, specId) {
161
- try {
162
- const features = await client.queryWorkItems(`[System.Title] Contains '[${specId}]' AND [System.WorkItemType] = 'Feature'`);
163
- return features[0] || null;
164
- } catch {
165
- return null;
166
- }
167
- }
168
- export {
169
- syncSpecToAdoWithEnhancedContent
170
- };