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.
- package/lib/bundle/.claude/commands/sdd-tasks.md +183 -62
- package/lib/bundle/commands/sdd-tasks.ps1 +86 -331
- package/lib/bundle/generate-tasks.ps1 +450 -0
- package/package.json +12 -9
- package/lib/converge-task.ps1 +0 -260
- package/lib/output-dirs.ps1 +0 -461
- package/lib/sdd-check.ps1 +0 -130
- package/lib/shared-converge.ps1 +0 -270
- package/lib/verify-patterns.ps1 +0 -208
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
---
|
|
3
3
|
tool: Bash
|
|
4
4
|
when: always
|
|
5
|
-
description: Phase 3 — Break SPEC.md into independently verifiable tasks (each ≤2 hours). Creates sdd/tasks/task-{timestamp}-{project}/ with MASTER-TASKS.md + T-XXX-*.md files.
|
|
5
|
+
description: Phase 3 — Break SPEC.md into independently verifiable tasks (each ≤2 hours). Creates sdd/tasks/task-{timestamp}-{project}/ with MASTER-TASKS.md + T-XXX-*.md files. Includes test tasks from SPEC Section 9.
|
|
6
|
+
args: optional
|
|
6
7
|
---
|
|
7
8
|
$ErrorActionPreference = "Stop"
|
|
8
9
|
|
|
9
|
-
#
|
|
10
|
+
# Parse arguments
|
|
11
|
+
$args = $argsRaw.Trim()
|
|
12
|
+
|
|
13
|
+
# Output path resolution
|
|
10
14
|
$SDD_OUTPUT_BASE = "sdd"
|
|
11
|
-
$SDD_TASKS_DIR = "
|
|
15
|
+
$SDD_TASKS_DIR = "$SDD_OUTPUT_BASE/tasks"
|
|
12
16
|
|
|
13
17
|
# Check config for custom output directory
|
|
14
18
|
if (Test-Path ".sdd/config.json") {
|
|
@@ -28,7 +32,7 @@ if (-not (Test-Path $SDD_TASKS_DIR)) {
|
|
|
28
32
|
New-Item -ItemType Directory -Path $SDD_TASKS_DIR -Force | Out-Null
|
|
29
33
|
}
|
|
30
34
|
|
|
31
|
-
#
|
|
35
|
+
# Gate 1: SPEC.md must exist
|
|
32
36
|
$specPath = "$SDD_OUTPUT_BASE/SPEC.md"
|
|
33
37
|
$legacySpecPath = "SPEC.md"
|
|
34
38
|
|
|
@@ -42,24 +46,183 @@ if (-not (Test-Path $specPath) -and -not (Test-Path $legacySpecPath)) {
|
|
|
42
46
|
|
|
43
47
|
if (Test-Path $specPath) {
|
|
44
48
|
Write-Host "[OK] Found: $specPath" -ForegroundColor Green
|
|
49
|
+
$activeSpec = $specPath
|
|
45
50
|
} else {
|
|
46
51
|
Write-Host "[OK] Found: $legacySpecPath (legacy location)" -ForegroundColor Green
|
|
52
|
+
Write-Host "[MIGRATE] SPEC.md should be moved to $specPath" -ForegroundColor Yellow
|
|
53
|
+
$activeSpec = $legacySpecPath
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
Write-Host ""
|
|
57
|
+
Write-Host "=== SDD Tasks Generator - Phase 3 ===" -ForegroundColor Cyan
|
|
58
|
+
|
|
59
|
+
# Read and parse SPEC
|
|
60
|
+
$specContent = Get-Content $activeSpec -Raw -Encoding UTF8
|
|
61
|
+
|
|
62
|
+
# Extract project name
|
|
63
|
+
$projectName = "Project"
|
|
64
|
+
if ($specContent -match "^#\s+SPEC\.md\s*[-—]\s*(.+)$") {
|
|
65
|
+
$projectName = $Matches[1].Trim()
|
|
54
66
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
|
|
68
|
+
# Extract features
|
|
69
|
+
$features = @()
|
|
70
|
+
if ($specContent -match "(?s)### 4\.1\s+Core Features(.+?)(?=###|\Z)") {
|
|
71
|
+
$featuresSection = $Matches[1]
|
|
72
|
+
$featureMatches = [regex]::Matches($featuresSection, "(?s)####\s+\[([^\]]+)\](.+?)(?=####|\Z)")
|
|
73
|
+
foreach ($match in $featureMatches) {
|
|
74
|
+
$features += @{
|
|
75
|
+
Name = $match.Groups[1].Value.Trim()
|
|
76
|
+
Content = $match.Groups[2].Value
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Extract test categories
|
|
82
|
+
$testCategories = @()
|
|
83
|
+
if ($specContent -match "(?s)### 9\.1\s+Test Categories(.+?)(?=###|\Z)") {
|
|
84
|
+
$testSection = $Matches[1]
|
|
85
|
+
if ($testSection -match 'Unit\s+Tests') { $testCategories += 'Unit' }
|
|
86
|
+
if ($testSection -match 'Integration\s+Tests') { $testCategories += 'Integration' }
|
|
87
|
+
if ($testSection -match 'E2E\s+Tests') { $testCategories += 'E2E' }
|
|
88
|
+
if ($testSection -match 'Accessibility\s+Tests') { $testCategories += 'Accessibility' }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
Write-Host "[OK] Project: $projectName" -ForegroundColor Green
|
|
92
|
+
Write-Host "[OK] Features: $($features.Count)" -ForegroundColor Green
|
|
93
|
+
Write-Host "[OK] Test categories: $($testCategories -join ', ')" -ForegroundColor Green
|
|
94
|
+
|
|
95
|
+
# Create task directory
|
|
96
|
+
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
|
97
|
+
$safeName = $projectName -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
|
|
98
|
+
$taskDir = "$SDD_TASKS_DIR/task-$timestamp-$safeName"
|
|
99
|
+
New-Item -ItemType Directory -Path $taskDir -Force | Out-Null
|
|
100
|
+
Write-Host "[OK] Created: $taskDir" -ForegroundColor Green
|
|
101
|
+
|
|
102
|
+
# Generate tasks
|
|
103
|
+
$tasks = @()
|
|
104
|
+
$phase = 1
|
|
105
|
+
|
|
106
|
+
# Task 1: Setup
|
|
107
|
+
$tasks += @{
|
|
108
|
+
Id = "T-001"
|
|
109
|
+
Name = "Project Setup"
|
|
110
|
+
Phase = $phase
|
|
111
|
+
DependsOn = @()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
$phase++
|
|
115
|
+
$prevTask = $tasks[-1].Id
|
|
116
|
+
|
|
117
|
+
# Feature tasks
|
|
118
|
+
foreach ($feature in $features) {
|
|
119
|
+
$tasks += @{
|
|
120
|
+
Id = "T-00$phase"
|
|
121
|
+
Name = $feature.Name
|
|
122
|
+
Phase = $phase
|
|
123
|
+
DependsOn = @($prevTask)
|
|
124
|
+
}
|
|
125
|
+
$prevTask = "T-00$phase"
|
|
126
|
+
$phase++
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Test tasks
|
|
130
|
+
foreach ($category in $testCategories) {
|
|
131
|
+
$tasks += @{
|
|
132
|
+
Id = "T-00$phase"
|
|
133
|
+
Name = "$category Tests"
|
|
134
|
+
Phase = $phase
|
|
135
|
+
DependsOn = @($prevTask)
|
|
136
|
+
}
|
|
137
|
+
$prevTask = "T-00$phase"
|
|
138
|
+
$phase++
|
|
59
139
|
}
|
|
60
|
-
Write-Host "[OK] Templates verified" -ForegroundColor Green
|
|
61
140
|
|
|
62
|
-
#
|
|
141
|
+
# Final task
|
|
142
|
+
$tasks += @{
|
|
143
|
+
Id = "T-00$phase"
|
|
144
|
+
Name = "Final Polish"
|
|
145
|
+
Phase = $phase
|
|
146
|
+
DependsOn = @($prevTask)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# Generate MASTER-TASKS.md
|
|
150
|
+
$masterContent = @"
|
|
151
|
+
# MASTER-TASKS — $projectName
|
|
152
|
+
|
|
153
|
+
## Task Index
|
|
154
|
+
|
|
155
|
+
| ID | Name | Estimate | Status |
|
|
156
|
+
|----|------|----------|--------|
|
|
157
|
+
"@
|
|
158
|
+
|
|
159
|
+
foreach ($task in $tasks) {
|
|
160
|
+
$masterContent += "| $($task.Id) | $($task.Name) | 1h | [ ] |`n"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
$total = $tasks.Count
|
|
164
|
+
$masterContent += @"
|
|
165
|
+
|
|
166
|
+
## Progress
|
|
167
|
+
|
|
168
|
+
- Completed: 0 / $total
|
|
169
|
+
- In Progress: 0
|
|
170
|
+
- Pending: $total
|
|
171
|
+
|
|
172
|
+
## Test Categories
|
|
173
|
+
|
|
174
|
+
$($testCategories -join ', ')
|
|
175
|
+
|
|
176
|
+
## Notes
|
|
177
|
+
|
|
178
|
+
Generated from: SPEC.md
|
|
179
|
+
Auto-generated by SDD Pipeline v1.2.2
|
|
180
|
+
"@
|
|
181
|
+
|
|
182
|
+
Set-Content -Path "$taskDir/MASTER-TASKS.md" -Value $masterContent -Encoding UTF8
|
|
183
|
+
Write-Host " [CREATED] MASTER-TASKS.md" -ForegroundColor Gray
|
|
184
|
+
|
|
185
|
+
# Generate individual task files
|
|
186
|
+
$taskNum = 1
|
|
187
|
+
foreach ($task in $tasks) {
|
|
188
|
+
$safeName = $task.Name -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
|
|
189
|
+
$filename = "$($task.Id)-$safeName.md"
|
|
190
|
+
|
|
191
|
+
$taskContent = @"
|
|
192
|
+
---
|
|
193
|
+
name: $filename
|
|
194
|
+
description: "$($task.Name)"
|
|
195
|
+
phase: $($task.Phase)
|
|
196
|
+
estimate: 1h
|
|
197
|
+
spec_sections: ["4.1"]
|
|
198
|
+
depends_on: [$($task.DependsOn -join ', ')]
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
# $($task.Id): $($task.Name)
|
|
202
|
+
|
|
203
|
+
## Files to Modify/Create
|
|
204
|
+
|
|
205
|
+
- [List files]
|
|
206
|
+
|
|
207
|
+
## Implementation Steps
|
|
208
|
+
|
|
209
|
+
1. [Step 1]
|
|
210
|
+
2. [Step 2]
|
|
211
|
+
3. [Step 3]
|
|
212
|
+
|
|
213
|
+
## Verification
|
|
214
|
+
|
|
215
|
+
- [ ] Verification check 1
|
|
216
|
+
- [ ] Verification check 2
|
|
217
|
+
- [ ] Verification check 3
|
|
218
|
+
"@
|
|
219
|
+
|
|
220
|
+
Set-Content -Path "$taskDir/$filename" -Value $taskContent -Encoding UTF8
|
|
221
|
+
Write-Host " [CREATED] $filename" -ForegroundColor Gray
|
|
222
|
+
$taskNum++
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
# Update config
|
|
63
226
|
if (Test-Path ".sdd/config.json") {
|
|
64
227
|
$config = Get-Content ".sdd/config.json" -Raw | ConvertFrom-Json
|
|
65
228
|
$config.phases.current = 3
|
|
@@ -67,55 +230,13 @@ if (Test-Path ".sdd/config.json") {
|
|
|
67
230
|
$config.phases.phase2.completedAt = (Get-Date -Format "yyyy-MM-dd")
|
|
68
231
|
$config.phases.phase3.status = "in-progress"
|
|
69
232
|
$config | ConvertTo-Json -Depth 10 | Set-Content ".sdd/config.json"
|
|
233
|
+
Write-Host "[OK] Config updated" -ForegroundColor Green
|
|
70
234
|
}
|
|
71
235
|
|
|
72
|
-
#
|
|
73
|
-
$timestamp = Get-Date -Format "yyMMdd-HHmmss"
|
|
74
|
-
$projectName = if ($config.project.name -and $config.project.name -ne "TODO") { $config.project.name } else { "project" }
|
|
75
|
-
$taskDirName = "task-${timestamp}-$($projectName.ToLower().Replace(' ', '-'))"
|
|
76
|
-
$taskDirPath = Join-Path $SDD_TASKS_DIR $taskDirName
|
|
77
|
-
|
|
78
|
-
New-Item -ItemType Directory -Path $taskDirPath -Force | Out-Null
|
|
79
|
-
|
|
80
|
-
# --- Copy templates ---
|
|
81
|
-
Copy-Item "templates/task-master.template.md" "$taskDirPath/MASTER-TASKS.md"
|
|
82
|
-
Copy-Item "templates/task-detail.template.md" "$taskDirPath/T-001-[task-name].md"
|
|
83
|
-
|
|
84
|
-
# --- Update MASTER-TASKS.md with project info ---
|
|
85
|
-
$masterContent = Get-Content "$taskDirPath/MASTER-TASKS.md" -Raw
|
|
86
|
-
$masterContent = $masterContent -replace '\[Project Name\]', $projectName
|
|
87
|
-
$masterContent = $masterContent -replace '\[DATE\]', (Get-Date -Format "yyyy-MM-dd")
|
|
88
|
-
$masterContent = $masterContent -replace '\.\./SPEC\.md', "../SPEC.md"
|
|
89
|
-
Set-Content "$taskDirPath/MASTER-TASKS.md" $masterContent -Encoding UTF8
|
|
90
|
-
|
|
91
|
-
# --- Summary ---
|
|
92
|
-
Write-Host ""
|
|
93
|
-
Write-Host "========================================" -ForegroundColor Cyan
|
|
94
|
-
Write-Host " Task Directory Created" -ForegroundColor Cyan
|
|
95
|
-
Write-Host "========================================" -ForegroundColor Cyan
|
|
96
|
-
Write-Host ""
|
|
97
|
-
Write-Host "Location: $taskDirPath/" -ForegroundColor White
|
|
236
|
+
# Summary
|
|
98
237
|
Write-Host ""
|
|
99
|
-
Write-Host "
|
|
100
|
-
Write-Host " sdd/tasks/$taskDirName/" -ForegroundColor Gray
|
|
101
|
-
Write-Host " ├── MASTER-TASKS.md # Task index" -ForegroundColor Gray
|
|
102
|
-
Write-Host " └── T-001-[task-name].md # Task template" -ForegroundColor Gray
|
|
238
|
+
Write-Host "[OK] Tasks generated: $total tasks" -ForegroundColor Green
|
|
103
239
|
Write-Host ""
|
|
104
|
-
Write-Host "
|
|
240
|
+
Write-Host "Directory: $taskDir" -ForegroundColor White
|
|
105
241
|
Write-Host ""
|
|
106
|
-
Write-Host "Next
|
|
107
|
-
Write-Host " 1. Edit $taskDirName/MASTER-TASKS.md with task index" -ForegroundColor Gray
|
|
108
|
-
Write-Host " 2. Create T-XXX-*.md files" -ForegroundColor Gray
|
|
109
|
-
Write-Host " 3. Implement tasks using /sdd-cook --task T-XXX" -ForegroundColor Gray
|
|
110
|
-
Write-Host " 4. Mark done with /sdd-task-status T-XXX done" -ForegroundColor Gray
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
# Generate tasks by analyzing SPEC.md
|
|
115
|
-
# Break SPEC.md into discrete tasks (T-001, T-002, ...)
|
|
116
|
-
# Each task must:
|
|
117
|
-
# - Take <= 2 hours
|
|
118
|
-
# - Be independently verifiable
|
|
119
|
-
# - Have output artifact specified
|
|
120
|
-
# - Have frontmatter fields: depends_on, parallel_group, spec_sections
|
|
121
|
-
# Follow templates/task-master.template.md and task-detail.template.md
|
|
242
|
+
Write-Host "Next: /sdd-cook --all" -ForegroundColor Cyan
|