sdd-pipeline 1.2.1 → 1.2.3
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/bin/sdd.js +1 -1
- package/lib/bmad/problem-first.js +6 -0
- package/lib/bundle/.claude/commands/sdd-tasks.md +183 -62
- package/lib/bundle/commands/sdd-tasks.ps1 +140 -0
- package/lib/bundle/generate-tasks.ps1 +450 -0
- package/lib/bundle/templates/SPEC.template.md +169 -17
- package/lib/generate-tasks.ps1 +450 -0
- package/package.json +1 -1
|
@@ -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
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
<!-- Template: SPEC.md v3.
|
|
1
|
+
<!-- Template: SPEC.md v3.1.0 -->
|
|
2
2
|
<!-- Spec-Driven Development — Agent-Optimized SPEC -->
|
|
3
3
|
<!-- Generated by: SDD Pipeline (2026-08-28) -->
|
|
4
|
+
<!-- Updated: 2026-08-29 — Clause ID tracking added -->
|
|
4
5
|
<!-- Key: MUST=required, SHOULD=recommended, MUST NOT=forbidden -->
|
|
5
6
|
|
|
6
7
|
# SPEC.md — [Project Name]
|
|
@@ -37,26 +38,36 @@
|
|
|
37
38
|
## 3. Exact Content Contracts
|
|
38
39
|
|
|
39
40
|
> **Critical:** These blocks contain EXACT text that MUST appear verbatim in the implementation.
|
|
41
|
+
> **Clause Tracking:** Each contract item has a `[SC-xxx]` ID for automated validation.
|
|
40
42
|
|
|
41
43
|
### 3.1 Required Text (copy verbatim)
|
|
42
44
|
|
|
45
|
+
> **Clause IDs for tracking:** `[SC-001]`, `[SC-002]`, etc.
|
|
46
|
+
|
|
43
47
|
```
|
|
44
|
-
[Copy exact text here — headlines
|
|
48
|
+
[SC-001] [Copy exact text here — headlines]
|
|
49
|
+
[SC-002] [Copy exact text here — button labels]
|
|
50
|
+
[SC-003] [Copy exact text here — error messages]
|
|
45
51
|
```
|
|
46
52
|
|
|
47
53
|
### 3.2 Exact Colors
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
|
52
|
-
|
|
53
|
-
|
|
|
55
|
+
> **Clause IDs for tracking:** `[SC-COLOR-xxx]`
|
|
56
|
+
|
|
57
|
+
| Clause ID | Element | Hex | Usage |
|
|
58
|
+
|-----------|---------|-----|-------|
|
|
59
|
+
| [SC-COLOR-001] | Primary | `#XXXXXX` | [Usage] |
|
|
60
|
+
| [SC-COLOR-002] | Secondary | `#XXXXXX` | [Usage] |
|
|
61
|
+
| [SC-COLOR-003] | Error | `#XXXXXX` | [Usage] |
|
|
54
62
|
|
|
55
63
|
### 3.3 Exact Dimensions
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
|
65
|
+
> **Clause IDs for tracking:** `[SC-DIM-xxx]`
|
|
66
|
+
|
|
67
|
+
| Clause ID | Element | Size | Context |
|
|
68
|
+
|-----------|---------|------|---------|
|
|
69
|
+
| [SC-DIM-001] | [Element] | [W]x[H]px | [Where] |
|
|
70
|
+
| [SC-DIM-002] | [Element] | [W]x[H]px | [Where] |
|
|
60
71
|
|
|
61
72
|
---
|
|
62
73
|
|
|
@@ -64,7 +75,7 @@
|
|
|
64
75
|
|
|
65
76
|
### 4.1 Core Features
|
|
66
77
|
|
|
67
|
-
#### [Feature Name]
|
|
78
|
+
#### [[SC-FEATURE-001] Feature Name]
|
|
68
79
|
|
|
69
80
|
- **Description:** [What it does]
|
|
70
81
|
- **BMAD Source:** Architect MVP (Q4) + UX first impression (Q7)
|
|
@@ -81,8 +92,8 @@
|
|
|
81
92
|
```
|
|
82
93
|
|
|
83
94
|
**Acceptance criteria:**
|
|
84
|
-
- [
|
|
85
|
-
- [
|
|
95
|
+
- [[AC-001]] [Specific, measurable condition]
|
|
96
|
+
- [[AC-002]] [Specific, measurable condition]
|
|
86
97
|
|
|
87
98
|
### 4.2 User Flows
|
|
88
99
|
|
|
@@ -173,7 +184,130 @@ Flow: [Flow Name]
|
|
|
173
184
|
|
|
174
185
|
---
|
|
175
186
|
|
|
176
|
-
## 9.
|
|
187
|
+
## 9. Testing Requirements
|
|
188
|
+
|
|
189
|
+
> **Critical:** This section defines WHAT to test. Task generator uses this to create test tasks.
|
|
190
|
+
|
|
191
|
+
### 9.1 Test Categories
|
|
192
|
+
|
|
193
|
+
| Category | Description | Priority |
|
|
194
|
+
|----------|-------------|----------|
|
|
195
|
+
| Unit Tests | Individual function/method testing | MUST |
|
|
196
|
+
| Integration Tests | Component interaction testing | MUST |
|
|
197
|
+
| E2E Tests | Full user flow testing | SHOULD |
|
|
198
|
+
| Visual Tests | UI rendering verification | SHOULD |
|
|
199
|
+
| Accessibility Tests | WCAG compliance | MUST |
|
|
200
|
+
|
|
201
|
+
### 9.2 Unit Test Specifications
|
|
202
|
+
|
|
203
|
+
> **Format:** `describe([unit]) → it([behavior]) → expect([assertion])`
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
Unit: [function/module name]
|
|
207
|
+
describe('[unit name]')
|
|
208
|
+
it('[should do X when Y]')
|
|
209
|
+
expect([actual]).to[matcher]([expected])
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Examples:**
|
|
213
|
+
```
|
|
214
|
+
Unit: addTask()
|
|
215
|
+
describe('addTask()')
|
|
216
|
+
it('should add task to list when input is valid')
|
|
217
|
+
expect(tasks.length).toBe(1)
|
|
218
|
+
it('should show error when input is empty')
|
|
219
|
+
expect(alert).toHaveBeenCalled()
|
|
220
|
+
it('should clear input after adding task')
|
|
221
|
+
expect(input.value).toBe('')
|
|
222
|
+
|
|
223
|
+
Unit: toggleTask()
|
|
224
|
+
describe('toggleTask(id)')
|
|
225
|
+
it('should toggle completed state')
|
|
226
|
+
expect(task.completed).toBe(true)
|
|
227
|
+
it('should persist state to localStorage')
|
|
228
|
+
expect(localStorage.setItem).toHaveBeenCalled()
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 9.3 Integration Test Specifications
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
Flow: [user flow name]
|
|
235
|
+
Given: [initial state]
|
|
236
|
+
When: [action]
|
|
237
|
+
Then: [expected outcome]
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Examples:**
|
|
241
|
+
```
|
|
242
|
+
Flow: Add Task Flow
|
|
243
|
+
Given: empty task list
|
|
244
|
+
When: user types "Buy milk" and clicks Add
|
|
245
|
+
Then: task appears in list with "Buy milk" text
|
|
246
|
+
|
|
247
|
+
Flow: Complete Task Flow
|
|
248
|
+
Given: task "Buy milk" exists
|
|
249
|
+
When: user clicks on task text
|
|
250
|
+
Then: task shows strikethrough, completed=true
|
|
251
|
+
|
|
252
|
+
Flow: Delete Task Flow
|
|
253
|
+
Given: task "Buy milk" exists
|
|
254
|
+
When: user clicks Delete button
|
|
255
|
+
Then: task removed from list, localStorage updated
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 9.4 E2E Test Specifications
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
Scenario: [user scenario]
|
|
262
|
+
Given: [prerequisites]
|
|
263
|
+
When: [user actions]
|
|
264
|
+
Then: [system response]
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Examples:**
|
|
268
|
+
```
|
|
269
|
+
Scenario: Add and complete a task
|
|
270
|
+
Given: browser at app URL
|
|
271
|
+
When: I type "Test task" and submit form
|
|
272
|
+
And: I click on the task text
|
|
273
|
+
Then: I see task with strikethrough
|
|
274
|
+
And: I refresh the page
|
|
275
|
+
And: task is still marked complete
|
|
276
|
+
|
|
277
|
+
Scenario: Empty input validation
|
|
278
|
+
Given: browser at app URL
|
|
279
|
+
When: I click Add button with empty input
|
|
280
|
+
Then: I see validation error message
|
|
281
|
+
And: no task is added
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 9.5 Test Data
|
|
285
|
+
|
|
286
|
+
> **Known inputs for testing:**
|
|
287
|
+
|
|
288
|
+
| Test Case | Input | Expected Output |
|
|
289
|
+
|-----------|-------|-----------------|
|
|
290
|
+
| Valid task | "Buy groceries" | Task added to list |
|
|
291
|
+
| Empty task | "" | Validation error |
|
|
292
|
+
| Long task | "[200+ chars]" | Task added (truncated display) |
|
|
293
|
+
| Duplicate task | "Same task" (x2) | Both tasks added |
|
|
294
|
+
| Special chars | "Task <script>" | Sanitized, displayed safely |
|
|
295
|
+
|
|
296
|
+
### 9.6 Test Verification Checklist
|
|
297
|
+
|
|
298
|
+
> **sdd-tasks generates test tasks from this checklist.**
|
|
299
|
+
|
|
300
|
+
For each feature in Section 4.1:
|
|
301
|
+
|
|
302
|
+
- [ ] Unit test: Happy path
|
|
303
|
+
- [ ] Unit test: Error path
|
|
304
|
+
- [ ] Unit test: Edge case
|
|
305
|
+
- [ ] Integration test: Component interaction
|
|
306
|
+
- [ ] E2E test: Full user flow
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 10. Success Criteria
|
|
177
311
|
|
|
178
312
|
> **Agent instruction:** These criteria define "done". All MUST pass before marking complete.
|
|
179
313
|
|
|
@@ -184,7 +318,7 @@ Flow: [Flow Name]
|
|
|
184
318
|
|
|
185
319
|
---
|
|
186
320
|
|
|
187
|
-
##
|
|
321
|
+
## 11. Decision Log
|
|
188
322
|
|
|
189
323
|
> **Agent instruction:** This log explains WHY. Read when uncertain about intent.
|
|
190
324
|
|
|
@@ -194,7 +328,7 @@ Flow: [Flow Name]
|
|
|
194
328
|
|
|
195
329
|
---
|
|
196
330
|
|
|
197
|
-
##
|
|
331
|
+
## 12. Anti-Patterns (Do NOT do)
|
|
198
332
|
|
|
199
333
|
> **Agent warning:** These patterns were explicitly rejected. Do not suggest or implement.
|
|
200
334
|
|
|
@@ -205,15 +339,33 @@ Flow: [Flow Name]
|
|
|
205
339
|
|
|
206
340
|
## Agent Verification Checklist
|
|
207
341
|
|
|
342
|
+
> **Updated v3.1:** Use clause IDs `[SC-xxx]` for automated tracking.
|
|
343
|
+
|
|
208
344
|
Before marking implementation complete, verify:
|
|
209
345
|
|
|
346
|
+
- [ ] All clause IDs tracked: `[SC-001]`, `[SC-002]`, etc.
|
|
210
347
|
- [ ] All "Required Text" (Section 3.1) appears verbatim
|
|
211
348
|
- [ ] All colors match hex values in Section 3.2 exactly
|
|
212
349
|
- [ ] All dimensions match Section 3.3 exactly
|
|
213
|
-
- [ ] All acceptance criteria in Section 4.1 checked
|
|
350
|
+
- [ ] All acceptance criteria `[AC-xxx]` in Section 4.1 checked
|
|
214
351
|
- [ ] All user flows implemented as specified
|
|
215
352
|
- [ ] All edge cases handled as specified
|
|
216
353
|
- [ ] All data contracts match schemas exactly
|
|
217
354
|
- [ ] No items from Out of Scope (Section 7) implemented
|
|
218
355
|
- [ ] All Open Questions resolved or escalated
|
|
219
356
|
- [ ] All Success Criteria met
|
|
357
|
+
- [ ] Converge report generated in `converge/task-T-XXX.md`
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## Clause Index
|
|
362
|
+
|
|
363
|
+
> **Auto-generated index of all clause IDs for easy reference.**
|
|
364
|
+
|
|
365
|
+
| Clause ID | Type | Location | Text |
|
|
366
|
+
|-----------|------|----------|------|
|
|
367
|
+
| [SC-001] | Text | §3.1 | [excerpt] |
|
|
368
|
+
| [SC-002] | Text | §3.1 | [excerpt] |
|
|
369
|
+
| [SC-COLOR-001] | Color | §3.2 | [excerpt] |
|
|
370
|
+
| [SC-FEATURE-001] | Feature | §4.1 | [excerpt] |
|
|
371
|
+
| [AC-001] | Criterion | §4.1 | [excerpt] |
|