sdd-pipeline 1.2.2 → 1.2.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.
@@ -0,0 +1,450 @@
1
+ # SDD Task Generation - Shared Logic
2
+ # Used by: .claude/commands/sdd-tasks.md, commands/sdd-tasks.ps1, skills/sdd-tasks/
3
+ # Version: 1.0.0
4
+
5
+ param(
6
+ [string]$SpecPath = "sdd/SPEC.md",
7
+ [string]$OutputDir = "sdd/tasks"
8
+ )
9
+
10
+ $ErrorActionPreference = 'Stop'
11
+
12
+ # ============================================================
13
+ # Utility Functions
14
+ # ============================================================
15
+
16
+ function Write-SddHeader {
17
+ param([string]$Text)
18
+ Write-Host "" -ForegroundColor Cyan
19
+ Write-Host "=== $Text ===" -ForegroundColor Cyan
20
+ Write-Host ""
21
+ }
22
+
23
+ function Write-SddSuccess {
24
+ param([string]$Text)
25
+ Write-Host "[OK] $Text" -ForegroundColor Green
26
+ }
27
+
28
+ function Write-SddError {
29
+ param([string]$Text)
30
+ Write-Host "[ERROR] $Text" -ForegroundColor Red
31
+ }
32
+
33
+ function Write-SddWarn {
34
+ param([string]$Text)
35
+ Write-Host "[WARN] $Text" -ForegroundColor Yellow
36
+ }
37
+
38
+ function Write-SddInfo {
39
+ param([string]$Text)
40
+ Write-Host " $Text" -ForegroundColor Gray
41
+ }
42
+
43
+ # ============================================================
44
+ # Parse SPEC.md
45
+ # ============================================================
46
+
47
+ function Get-SpecInfo {
48
+ param([string]$Path)
49
+
50
+ $content = Get-Content $Path -Raw -Encoding UTF8
51
+ $spec = @{
52
+ Name = "Project"
53
+ Features = @()
54
+ TestCategories = @()
55
+ UserStories = @()
56
+ Sections = @{}
57
+ }
58
+
59
+ # Extract project name
60
+ if ($content -match "^#\s+SPEC\.md\s*[-—]\s*(.+)$", $multiline) {
61
+ $spec.Name = $Matches[1].Trim()
62
+ }
63
+
64
+ # Extract features from Section 4.1
65
+ if ($content -match "(?s)### 4\.1\s+Core Features(.+?)(?=###|\Z)") {
66
+ $featuresSection = $Matches[1]
67
+
68
+ # Match feature blocks
69
+ $featureBlocks = [regex]::Matches($featuresSection, '(?s)####\s+\[([^\]]+)\](.+?)(?=####|\Z)')
70
+ foreach ($block in $featureBlocks) {
71
+ $featureName = $block.Groups[1].Value.Trim()
72
+ $featureContent = $block.Groups[2].Value
73
+
74
+ # Extract acceptance criteria
75
+ $criteria = @()
76
+ $criteriaMatches = [regex]::Matches($featureContent, '\[\[AC-(\w+)\]\]\s*(.+)')
77
+ foreach ($c in $criteriaMatches) {
78
+ $criteria += @{
79
+ Id = $c.Groups[1].Value
80
+ Text = $c.Groups[2].Value.Trim()
81
+ }
82
+ }
83
+
84
+ $spec.Features += @{
85
+ Name = $featureName
86
+ Content = $featureContent
87
+ Criteria = $criteria
88
+ }
89
+ }
90
+ }
91
+
92
+ # Extract test categories from Section 9.1
93
+ if ($content -match "(?s)### 9\.1\s+Test Categories(.+?)(?=###|\Z)") {
94
+ $testSection = $Matches[1]
95
+
96
+ if ($testSection -match 'Unit\s+Tests') { $spec.TestCategories += 'Unit' }
97
+ if ($testSection -match 'Integration\s+Tests') { $spec.TestCategories += 'Integration' }
98
+ if ($testSection -match 'E2E\s+Tests') { $spec.TestCategories += 'E2E' }
99
+ if ($testSection -match 'Accessibility\s+Tests') { $spec.TestCategories += 'Accessibility' }
100
+ }
101
+
102
+ # Extract user stories from Section 2
103
+ if ($content -match "(?s)### 2\.1\s+Must Have(.+?)(?=###|\Z)") {
104
+ $storiesSection = $Matches[1]
105
+ $storyMatches = [regex]::Matches($storiesSection, '\*\*As a\*\*.+?(?=\n-|\n\n|\Z)', [System.Text.RegularExpressions.RegexOptions]::Singleline)
106
+ foreach ($story in $storyMatches) {
107
+ $storyText = $story.Value.Trim()
108
+ if ($storyText) {
109
+ $spec.UserStories += $storyText
110
+ }
111
+ }
112
+ }
113
+
114
+ return $spec
115
+ }
116
+
117
+ # ============================================================
118
+ # Generate Tasks
119
+ # ============================================================
120
+
121
+ function New-TaskFile {
122
+ param(
123
+ [string]$Id,
124
+ [string]$Name,
125
+ [string]$Phase,
126
+ [string]$Estimate,
127
+ [string[]]$DependsOn,
128
+ [string[]]$SpecSections,
129
+ [string]$Description,
130
+ [string]$Content
131
+ )
132
+
133
+ $safeName = $Name -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
134
+ $filename = "$Id-$safeName.md"
135
+
136
+ $frontmatter = @"
137
+ ---
138
+ name: $Id-$safeName
139
+ description: "$Description"
140
+ phase: $Phase
141
+ estimate: $Estimate
142
+ spec_sections: [$($SpecSections -join ', ')]
143
+ depends_on: [$($DependsOn -join ', ')]
144
+ ---
145
+
146
+ "@
147
+
148
+ $fullContent = $frontmatter + "# $Id`: $Name`n`n" + $Content
149
+ return @{
150
+ Filename = $filename
151
+ Content = $fullContent
152
+ }
153
+ }
154
+
155
+ function Get-TaskFiles {
156
+ param(
157
+ [object]$Spec,
158
+ [int]$StartPhase = 2
159
+ )
160
+
161
+ $tasks = @()
162
+ $phase = $StartPhase
163
+ $prevTask = $null
164
+
165
+ # Feature tasks
166
+ foreach ($feature in $Spec.Features) {
167
+ $dependsOn = if ($prevTask) { @($prevTask.Id) } else { @() }
168
+
169
+ $task = New-TaskFile `
170
+ -Id "T-00$phase" `
171
+ -Name $feature.Name `
172
+ -Phase $phase `
173
+ -Estimate "1h" `
174
+ -DependsOn $dependsOn `
175
+ -SpecSections @('"4.1"') `
176
+ -Description "Implement: $($feature.Name)" `
177
+ -Content @"
178
+
179
+ ## Files to Modify/Create
180
+
181
+ - [List files based on feature requirements]
182
+
183
+ ## Implementation Steps
184
+
185
+ 1. [Step 1]
186
+ 2. [Step 2]
187
+ 3. [Step 3]
188
+
189
+ ## Verification
190
+
191
+ $($feature.Criteria | ForEach-Object { "- [ ] [[AC-$($_.Id)]] $($_.Text)" } -join "`n")
192
+
193
+ "@
194
+
195
+ $tasks += $task
196
+ $prevTask = $tasks[-1]
197
+ $phase++
198
+ }
199
+
200
+ # Test tasks
201
+ foreach ($category in $Spec.TestCategories) {
202
+ $dependsOn = if ($prevTask) { @($prevTask.Id) } else { @() }
203
+
204
+ switch ($category) {
205
+ 'Unit' {
206
+ $testContent = @"
207
+
208
+ ## Test Files to Create
209
+
210
+ - `tests/unit/*.test.js`
211
+
212
+ ## Unit Tests
213
+
214
+ - Test happy path
215
+ - Test error path
216
+ - Test edge cases
217
+
218
+ ## Verification
219
+
220
+ - [ ] All unit tests pass
221
+ - [ ] Code coverage > 80%
222
+ "@
223
+ }
224
+ 'Integration' {
225
+ $testContent = @"
226
+
227
+ ## Test Files to Create
228
+
229
+ - `tests/integration/*.test.js`
230
+
231
+ ## Integration Tests
232
+
233
+ $($Spec.UserStories | ForEach-Object { "- $_" } -join "`n")
234
+
235
+ ## Verification
236
+
237
+ - [ ] All integration tests pass
238
+ - [ ] Components interact correctly
239
+ "@
240
+ }
241
+ 'E2E' {
242
+ $testContent = @"
243
+
244
+ ## Test Files to Create
245
+
246
+ - `tests/e2e/*.test.js`
247
+
248
+ ## E2E Scenarios
249
+
250
+ - Complete user journey test
251
+ - Error recovery test
252
+
253
+ ## Verification
254
+
255
+ - [ ] All E2E tests pass
256
+ - [ ] Full flows work end-to-end
257
+ "@
258
+ }
259
+ 'Accessibility' {
260
+ $testContent = @"
261
+
262
+ ## Accessibility Verification
263
+
264
+ - Keyboard navigation
265
+ - Screen reader support
266
+ - Color contrast
267
+
268
+ ## Tools
269
+
270
+ - axe-core
271
+ - Lighthouse
272
+
273
+ ## Verification
274
+
275
+ - [ ] axe-core: 0 violations
276
+ - [ ] Keyboard navigation works
277
+ - [ ] Color contrast meets WCAG AA
278
+ "@
279
+ }
280
+ }
281
+
282
+ $task = New-TaskFile `
283
+ -Id "T-00$phase" `
284
+ -Name "$category Tests" `
285
+ -Phase $phase `
286
+ -Estimate "1h" `
287
+ -DependsOn $dependsOn `
288
+ -SpecSections @('"9.1"') `
289
+ -Description "Write and run $category tests" `
290
+ -Content $testContent
291
+
292
+ $tasks += $task
293
+ $prevTask = $tasks[-1]
294
+ $phase++
295
+ }
296
+
297
+ # Polish task
298
+ $dependsOn = if ($prevTask) { @($prevTask.Id) } else { @() }
299
+ $tasks += New-TaskFile `
300
+ -Id "T-00$phase" `
301
+ -Name "Final Polish" `
302
+ -Phase $phase `
303
+ -Estimate "1h" `
304
+ -DependsOn $dependsOn `
305
+ -SpecSections @('"4.1"') `
306
+ -Description "Final polish, styling, edge cases" `
307
+ -Content @"
308
+
309
+ ## Final Checks
310
+
311
+ - [ ] All features work correctly
312
+ - [ ] No console errors
313
+ - [ ] Responsive design
314
+ - [ ] Edge cases handled
315
+
316
+ ## Verification
317
+
318
+ - [ ] Manual testing complete
319
+ - [ ] Code review passed
320
+ "@
321
+
322
+ $phase++
323
+
324
+ # Converge task
325
+ $dependsOn = @($tasks[-1].Id)
326
+ $tasks += New-TaskFile `
327
+ -Id "T-00$phase" `
328
+ -Name "Converge Validation" `
329
+ -Phase $phase `
330
+ -Estimate "1h" `
331
+ -DependsOn $dependsOn `
332
+ -SpecSections @('"9"') `
333
+ -Description "Run converge validation" `
334
+ -Content @"
335
+
336
+ ## Converge Steps
337
+
338
+ 1. Run: `pwsh run-converge.ps1 -Strict`
339
+ 2. Fix any issues
340
+ 3. Verify all checks pass
341
+
342
+ ## Verification
343
+
344
+ - [ ] Converge passes
345
+ - [ ] Ready for deployment
346
+ "@
347
+
348
+ return $tasks
349
+ }
350
+
351
+ function New-MasterTasks {
352
+ param(
353
+ [string]$ProjectName,
354
+ [object[]]$Tasks,
355
+ [string[]]$TestCategories
356
+ )
357
+
358
+ $content = @"
359
+ # MASTER-TASKS — $ProjectName
360
+
361
+ ## Task Index
362
+
363
+ | ID | Name | Estimate | Status |
364
+ |----|------|----------|--------|
365
+ "@
366
+
367
+ foreach ($task in $Tasks) {
368
+ $content += "| $($task.Id) | $($task.Name) | 1h | [ ] |`n"
369
+ }
370
+
371
+ $total = $Tasks.Count
372
+ $content += @"
373
+
374
+ ## Progress
375
+
376
+ - Completed: 0 / $total
377
+ - In Progress: 0
378
+ - Pending: $total
379
+
380
+ ## Test Categories
381
+
382
+ $($TestCategories -join ', ')
383
+
384
+ ## Notes
385
+
386
+ Generated from: SPEC.md
387
+ "@
388
+
389
+ return $content
390
+ }
391
+
392
+ # ============================================================
393
+ # Main Execution
394
+ # ============================================================
395
+
396
+ Write-SddHeader "SDD Tasks Generator - Phase 3"
397
+
398
+ # Check SPEC exists
399
+ if (-not (Test-Path $SpecPath)) {
400
+ Write-SddError "SPEC.md not found at $SpecPath"
401
+ Write-SddWarn "Run /sdd-spec first to generate SPEC.md"
402
+ exit 1
403
+ }
404
+ Write-SddSuccess "Found: $SpecPath"
405
+
406
+ # Parse SPEC
407
+ Write-Host "Parsing SPEC.md..." -ForegroundColor Gray
408
+ $spec = Get-SpecInfo -Path $SpecPath
409
+ Write-SddSuccess "Project: $($spec.Name)"
410
+ Write-SddSuccess "Features: $($spec.Features.Count)"
411
+ Write-SddSuccess "Test categories: $($spec.TestCategories -join ', ')"
412
+
413
+ # Create output directory
414
+ $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
415
+ $safeName = $spec.Name -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
416
+ $taskDir = "$OutputDir/task-$timestamp-$safeName"
417
+
418
+ if (-not (Test-Path $taskDir)) {
419
+ New-Item -ItemType Directory -Path $taskDir -Force | Out-Null
420
+ }
421
+ Write-SddSuccess "Created: $taskDir"
422
+
423
+ # Generate tasks
424
+ Write-Host ""
425
+ Write-Host "Generating tasks..." -ForegroundColor Gray
426
+ $tasks = Get-TaskFiles -Spec $spec
427
+
428
+ # Write task files
429
+ foreach ($task in $tasks) {
430
+ $filepath = Join-Path $taskDir $task.Filename
431
+ Set-Content -Path $filepath -Value $task.Content -Encoding UTF8
432
+ Write-SddInfo "[CREATED] $($task.Filename)"
433
+ }
434
+
435
+ # Write MASTER-TASKS.md
436
+ $masterContent = New-MasterTasks -ProjectName $spec.Name -Tasks $tasks -TestCategories $spec.TestCategories
437
+ $masterPath = Join-Path $taskDir "MASTER-TASKS.md"
438
+ Set-Content -Path $masterPath -Value $masterContent -Encoding UTF8
439
+ Write-SddInfo "[CREATED] MASTER-TASKS.md"
440
+
441
+ # Summary
442
+ Write-Host ""
443
+ Write-SddSuccess "Tasks generated successfully!"
444
+ Write-Host ""
445
+ Write-Host "Summary:" -ForegroundColor Cyan
446
+ Write-Host " Project: $($spec.Name)"
447
+ Write-Host " Tasks: $($tasks.Count)"
448
+ Write-Host " Directory: $taskDir"
449
+ Write-Host ""
450
+ Write-Host "Next: claude `/sdd-cook --all` or implement tasks manually" -ForegroundColor Cyan
package/package.json CHANGED
@@ -1,27 +1,30 @@
1
1
  {
2
2
  "name": "sdd-pipeline",
3
- "version": "1.2.2",
4
- "description": "Spec-Driven Development pipeline for Claude Code — organized output structure (sdd/brief.md, sdd/SPEC.md, sdd/tasks/, sdd/converge/)",
3
+ "version": "1.2.4",
4
+ "description": "Spec-Driven Development pipeline for Claude Code CLI — transforms raw feature requests into validated, shipped code through a self-correcting converge loop",
5
5
  "bin": {
6
6
  "sdd": "bin/sdd.js"
7
7
  },
8
8
  "files": [
9
- "bin",
10
- "lib",
11
- "lib/bundle"
9
+ "bin/",
10
+ "lib/bmad.js",
11
+ "lib/config.js",
12
+ "lib/init.js",
13
+ "lib/sanitize.js",
14
+ "lib/bmad/",
15
+ "lib/bundle/"
12
16
  ],
13
17
  "engines": {
14
18
  "node": ">=18"
15
19
  },
16
20
  "preferGlobal": true,
17
- "scripts": {
18
- "build": "echo 'No build step needed — pure JS'"
19
- },
20
21
  "keywords": [
21
22
  "sdd",
22
23
  "spec-driven",
23
24
  "claude-code",
24
- "pipeline"
25
+ "pipeline",
26
+ "specification",
27
+ "development"
25
28
  ],
26
29
  "license": "MIT"
27
30
  }