sdd-pipeline 1.2.8 → 1.3.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.
- package/README.md +24 -10
- package/bin/sdd.cjs +2 -2
- package/lib/bundle/.claude/commands/sdd-bmad.md +92 -26
- package/lib/bundle/.claude/commands/sdd-converge.md +144 -25
- package/lib/bundle/.claude/commands/sdd-tasks.md +29 -59
- package/lib/bundle/.claude/commands/sdd.md +1 -1
- package/lib/bundle/.github/workflows/converge.yml +1 -1
- package/lib/bundle/bin/sdd.cjs +2 -2
- package/lib/bundle/commands/sdd-status.ps1 +59 -23
- package/lib/bundle/commands/sdd-tasks.ps1 +78 -36
- package/lib/bundle/lib/init.js +1 -1
- package/lib/bundle/skills/sdd-cook/references/subagent-patterns.md +17 -0
- package/lib/bundle/skills/sdd-cook/references/subagent-prompts.md +22 -0
- package/lib/bundle/templates/task-detail.template.md +65 -9
- package/lib/init.js +1 -1
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -276,22 +276,36 @@ Two Interfaces (same logic):
|
|
|
276
276
|
Shell CLI: sdd bmad "feature" → bin/sdd.cjs
|
|
277
277
|
Claude Code: /sdd bmad "feature" → .claude/commands/sdd.md
|
|
278
278
|
|
|
279
|
-
|
|
279
|
+
Project structure:
|
|
280
280
|
├── .sdd/config.json # Phase tracking
|
|
281
|
-
├── templates/ # SDD templates
|
|
282
|
-
├── skills/ # Implementation skills (
|
|
283
|
-
├── .claude/commands/ # Claude Code slash commands
|
|
284
|
-
├── commands/ # Standalone PowerShell scripts
|
|
285
|
-
├──
|
|
281
|
+
├── templates/ # SDD templates (synced from bundle)
|
|
282
|
+
├── skills/ # Implementation skills (synced from bundle)
|
|
283
|
+
├── .claude/commands/ # Claude Code slash commands (synced from bundle)
|
|
284
|
+
├── commands/ # Standalone PowerShell scripts (synced from bundle)
|
|
285
|
+
├── lib/
|
|
286
|
+
│ ├── bmad.js # BMAD CLI wrapper
|
|
287
|
+
│ ├── bmad/ # BMAD modules
|
|
288
|
+
│ └── bundle/ # SOURCE OF TRUTH for npm package
|
|
289
|
+
├── scripts/
|
|
290
|
+
│ └── sync-bundle.ps1 # Sync bundle to working directories
|
|
286
291
|
└── extensions/ # Domain-specific (api/frontend/backend)
|
|
287
292
|
|
|
288
293
|
npm package (sdd-pipeline):
|
|
289
294
|
├── bin/sdd.cjs # CLI entry
|
|
290
|
-
├── lib/
|
|
295
|
+
├── lib/bmad.js # CLI wrapper
|
|
291
296
|
├── lib/bmad/ # BMAD orchestrator
|
|
292
|
-
└── lib/bundle/ #
|
|
297
|
+
└── lib/bundle/ # All pipeline files for distribution
|
|
293
298
|
```
|
|
294
299
|
|
|
300
|
+
### Development Workflow
|
|
301
|
+
|
|
302
|
+
1. Edit files in `lib/bundle/` (source of truth)
|
|
303
|
+
2. Run `npm run sync` to sync to working directories
|
|
304
|
+
3. Test with `npm run pack --dry-run`
|
|
305
|
+
4. Commit and publish
|
|
306
|
+
|
|
307
|
+
**Important:** After modifying `lib/bundle/`, always run `npm run sync` before testing!
|
|
308
|
+
|
|
295
309
|
---
|
|
296
310
|
|
|
297
311
|
## Requirements
|
|
@@ -314,7 +328,7 @@ jobs:
|
|
|
314
328
|
runs-on: windows-latest
|
|
315
329
|
steps:
|
|
316
330
|
- uses: actions/checkout@v4
|
|
317
|
-
- run: pwsh run-converge.ps1 -Url '${{ env.DEV_URL }}' -Strict
|
|
331
|
+
- run: pwsh lib/bundle/run-converge.ps1 -Url '${{ env.DEV_URL }}' -Strict
|
|
318
332
|
```
|
|
319
333
|
|
|
320
334
|
---
|
|
@@ -324,7 +338,7 @@ jobs:
|
|
|
324
338
|
| Field | Value |
|
|
325
339
|
|-------|-------|
|
|
326
340
|
| Name | `sdd-pipeline` |
|
|
327
|
-
| Version | `1.
|
|
341
|
+
| Version | `1.3.0` |
|
|
328
342
|
| Registry | npmjs.com |
|
|
329
343
|
| CLI command | `sdd` |
|
|
330
344
|
| Claude Code command | `/sdd` |
|
package/bin/sdd.cjs
CHANGED
|
@@ -143,10 +143,10 @@ switch (cmd) {
|
|
|
143
143
|
console.log('=== SDD Converge Validation ===')
|
|
144
144
|
console.log('')
|
|
145
145
|
console.log('Full validation (requires dev server):')
|
|
146
|
-
console.log(' pwsh run-converge.ps1 -Url http://localhost:3000 -Strict')
|
|
146
|
+
console.log(' pwsh lib/bundle/run-converge.ps1 -Url http://localhost:3000 -Strict')
|
|
147
147
|
console.log('')
|
|
148
148
|
console.log('Per-task validation:')
|
|
149
|
-
console.log(' pwsh run-converge.ps1 -TaskId T-001')
|
|
149
|
+
console.log(' pwsh lib/bundle/run-converge.ps1 -TaskId T-001')
|
|
150
150
|
console.log('')
|
|
151
151
|
console.log('Claude Code:')
|
|
152
152
|
console.log(' claude "/sdd-converge"')
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
---
|
|
2
|
-
# SDD BMAD — Brainstorm, Multi-Agent, Define (Interactive)
|
|
2
|
+
# SDD BMAD — Brainstorm, Multi-Agent, Define (Interactive + Batch)
|
|
3
3
|
---
|
|
4
4
|
tool: Bash
|
|
5
5
|
when: always
|
|
6
|
-
description: Phase 0 — Interactive brainstorm. Asks 9 discovery questions (Problem/Architect/UX tiers), applies problem-first inversion, generates confidence-scored brief. Outputs to sdd/brief.md. Args: "<feature
|
|
6
|
+
description: Phase 0 — Interactive brainstorm with batch mode. Asks 9 discovery questions (Problem/Architect/UX tiers), applies problem-first inversion, generates confidence-scored brief. Outputs to sdd/brief.md. Args: "<feature>" or "--batch <file.json>" or "--answers '{...}'"
|
|
7
7
|
---
|
|
8
8
|
# ============================================================
|
|
9
|
-
# SDD BMAD Interactive Mode
|
|
9
|
+
# SDD BMAD Interactive + Batch Mode
|
|
10
10
|
# ============================================================
|
|
11
11
|
# Phase 0: Brainstorm, Multi-Agent, Define
|
|
12
12
|
# Asks 9 discovery questions (Tier 1 + 2 + 3)
|
|
13
13
|
# Applies problem-first inversion
|
|
14
|
-
# Spawns 3 parallel agents (PM / Architect / UX)
|
|
15
14
|
# Produces confidence-scored brief
|
|
15
|
+
# Supports batch mode: --batch file.json or --answers '{...}'
|
|
16
16
|
# ============================================================
|
|
17
17
|
|
|
18
18
|
$ErrorActionPreference = 'Stop'
|
|
@@ -27,16 +27,80 @@ function Sanitize-UserInput {
|
|
|
27
27
|
|
|
28
28
|
# --- Parse arguments ---
|
|
29
29
|
$rawInput = $args -join ' '
|
|
30
|
-
|
|
30
|
+
$batchMode = $false
|
|
31
|
+
$batchFile = $null
|
|
32
|
+
$batchAnswers = $null
|
|
33
|
+
$answers = @{}
|
|
34
|
+
|
|
35
|
+
# Check for batch mode
|
|
36
|
+
if ($args -contains "--batch") {
|
|
37
|
+
$batchMode = $true
|
|
38
|
+
$batchIdx = [array]::IndexOf($args, "--batch")
|
|
39
|
+
if ($batchIdx -ge 0 -and $batchIdx + 1 -lt $args.Count) {
|
|
40
|
+
$batchFile = $args[$batchIdx + 1]
|
|
41
|
+
}
|
|
42
|
+
} elseif ($args -contains "--answers") {
|
|
43
|
+
$batchMode = $true
|
|
44
|
+
$batchIdx = [array]::IndexOf($args, "--answers")
|
|
45
|
+
if ($batchIdx -ge 0 -and $batchIdx + 1 -lt $args.Count) {
|
|
46
|
+
$batchAnswers = $args[$batchIdx + 1]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Extract feature description (first positional arg, or --input value)
|
|
51
|
+
$featureDesc = ($args | Where-Object { $_ -notmatch '^--' } | Select-Object -First 1)
|
|
52
|
+
|
|
53
|
+
if (-not $featureDesc) {
|
|
31
54
|
Write-Host "Usage: /sdd-bmad <feature description>"
|
|
32
|
-
Write-Host "
|
|
55
|
+
Write-Host " /sdd-bmad --batch <answers.json>"
|
|
56
|
+
Write-Host " /sdd-bmad --answers '`{`"q1`":`"answer`",...`}`'"
|
|
57
|
+
Write-Host ""
|
|
58
|
+
Write-Host "Example interactive: /sdd-bmad `"landing page for my SaaS product`""
|
|
59
|
+
Write-Host "Example batch: /sdd-bmad --batch answers.json"
|
|
33
60
|
exit 1
|
|
34
61
|
}
|
|
35
62
|
|
|
36
|
-
$sanitizedInput = Sanitize-UserInput -Input $
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Write-Host "
|
|
63
|
+
$sanitizedInput = Sanitize-UserInput -Input $featureDesc
|
|
64
|
+
|
|
65
|
+
if ($batchMode) {
|
|
66
|
+
Write-Host ""
|
|
67
|
+
Write-Host "=== BMAD Batch Mode ===" -ForegroundColor Cyan
|
|
68
|
+
|
|
69
|
+
# Load answers from file or inline JSON
|
|
70
|
+
if ($batchFile) {
|
|
71
|
+
if (Test-Path $batchFile) {
|
|
72
|
+
try {
|
|
73
|
+
$jsonContent = Get-Content $batchFile -Raw
|
|
74
|
+
$batchData = $jsonContent | ConvertFrom-Json
|
|
75
|
+
foreach ($prop in $batchData.PSObject.Properties) {
|
|
76
|
+
$answers[$prop.Name] = Sanitize-UserInput -Input $prop.Value
|
|
77
|
+
}
|
|
78
|
+
Write-Host "Loaded $($answers.Count) answers from: $batchFile" -ForegroundColor Green
|
|
79
|
+
} catch {
|
|
80
|
+
Write-Host "[ERROR] Failed to parse JSON file: $_" -ForegroundColor Red
|
|
81
|
+
exit 1
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
Write-Host "[ERROR] Batch file not found: $batchFile" -ForegroundColor Red
|
|
85
|
+
exit 1
|
|
86
|
+
}
|
|
87
|
+
} elseif ($batchAnswers) {
|
|
88
|
+
try {
|
|
89
|
+
$batchData = $batchAnswers | ConvertFrom-Json
|
|
90
|
+
foreach ($prop in $batchData.PSObject.Properties) {
|
|
91
|
+
$answers[$prop.Name] = Sanitize-UserInput -Input $prop.Value
|
|
92
|
+
}
|
|
93
|
+
Write-Host "Loaded $($answers.Count) answers from inline JSON" -ForegroundColor Green
|
|
94
|
+
} catch {
|
|
95
|
+
Write-Host "[ERROR] Failed to parse inline JSON: $_" -ForegroundColor Red
|
|
96
|
+
exit 1
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
Write-Host ""
|
|
101
|
+
Write-Host "=== BMAD Interactive Session ===" -ForegroundColor Cyan
|
|
102
|
+
Write-Host "Input sanitized. Prompt injection protection active." -ForegroundColor Gray
|
|
103
|
+
}
|
|
40
104
|
|
|
41
105
|
# --- Date helpers ---
|
|
42
106
|
$date = Get-Date -Format 'yyyy-MM-dd'
|
|
@@ -106,26 +170,28 @@ $questions = @(
|
|
|
106
170
|
@{ id="q9"; tier=3; tierName="UX & Polish"; q="What could go wrong that we need to handle gracefully?"; hint="Network failure, empty data, permission denied, slow loading" }
|
|
107
171
|
)
|
|
108
172
|
|
|
109
|
-
#
|
|
110
|
-
$
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if ($q.id -eq "q7") { Write-Host ""; Write-Host "=== Tier 3: UX & Polish ===" -ForegroundColor Cyan }
|
|
173
|
+
# Skip interactive questions in batch mode (answers already loaded)
|
|
174
|
+
if (-not $batchMode) {
|
|
175
|
+
foreach ($q in $questions) {
|
|
176
|
+
# Show tier header on first question of each tier
|
|
177
|
+
if ($q.id -eq "q1") { Write-Host "=== Tier 1: Problem Definition ===" -ForegroundColor Cyan }
|
|
178
|
+
if ($q.id -eq "q4") { Write-Host ""; Write-Host "=== Tier 2: Technical & Feasibility ===" -ForegroundColor Cyan }
|
|
179
|
+
if ($q.id -eq "q7") { Write-Host ""; Write-Host "=== Tier 3: UX & Polish ===" -ForegroundColor Cyan }
|
|
117
180
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
181
|
+
Write-Host ""
|
|
182
|
+
Write-Host "[$($q.id)] $($q.q)" -ForegroundColor White
|
|
183
|
+
Write-Host "Hint: $($q.hint)" -ForegroundColor Gray
|
|
121
184
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
185
|
+
$answer = Read-Host "Your answer"
|
|
186
|
+
$answer = Sanitize-UserInput -Input $answer
|
|
187
|
+
$answers[$q.id] = $answer
|
|
125
188
|
|
|
126
|
-
|
|
127
|
-
|
|
189
|
+
if (-not $answer) {
|
|
190
|
+
Write-Host "(skipped — answer recorded as empty)" -ForegroundColor DarkGray
|
|
191
|
+
}
|
|
128
192
|
}
|
|
193
|
+
} else {
|
|
194
|
+
Write-Host "Using batch mode — skipping interactive questions." -ForegroundColor Gray
|
|
129
195
|
}
|
|
130
196
|
|
|
131
197
|
# ============================================================
|
|
@@ -2,39 +2,158 @@
|
|
|
2
2
|
---
|
|
3
3
|
tool: Bash
|
|
4
4
|
when: always
|
|
5
|
-
|
|
5
|
+
args: --task <task-id>
|
|
6
|
+
description: Phase 5 — Validate implementation matches SPEC.md. Self-correcting converge loop. Args: [--task <task-id>] or full project. Checks clause IDs, exact text, hex colors, ACs, dev server health. Output to sdd/converge/.
|
|
6
7
|
---
|
|
7
|
-
$
|
|
8
|
+
$ErrorActionPreference = 'Continue'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# Parse task argument
|
|
11
|
+
$taskId = $null
|
|
12
|
+
if ($argsRaw -match '-task["\s]+([T-t]-\d+)') {
|
|
13
|
+
$taskId = $Matches[1].ToUpper()
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
#
|
|
15
|
-
$
|
|
16
|
-
if ($
|
|
17
|
-
|
|
18
|
-
if (!(Test-Path "$taskDir/MASTER-TASKS.md")) {
|
|
19
|
-
Write-Host "ERROR: $taskDir/MASTER-TASKS.md not found" -ForegroundColor Red
|
|
20
|
-
$missing += "$taskDir/MASTER-TASKS.md"
|
|
21
|
-
}
|
|
22
|
-
} else {
|
|
23
|
-
Write-Host "ERROR: No task directory found (task-*/)" -ForegroundColor Red
|
|
24
|
-
$missing += "task-*/MASTER-TASKS.md"
|
|
16
|
+
# Ensure converge directory exists
|
|
17
|
+
$convergeDir = "sdd/converge"
|
|
18
|
+
if (-not (Test-Path $convergeDir)) {
|
|
19
|
+
New-Item -ItemType Directory -Path $convergeDir -Force | Out-Null
|
|
25
20
|
}
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
# Run converge validation
|
|
23
|
+
Write-Host "=== SDD Converge Validation ===" -ForegroundColor Cyan
|
|
24
|
+
|
|
25
|
+
if ($taskId) {
|
|
26
|
+
Write-Host "Running per-task converge for: $taskId" -ForegroundColor Cyan
|
|
27
|
+
pwsh run-converge.ps1 -TaskId $taskId
|
|
28
|
+
} else {
|
|
29
|
+
Write-Host "Running full project converge..." -ForegroundColor Cyan
|
|
30
|
+
pwsh run-converge.ps1
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
Write-Host "
|
|
34
|
-
Write-Host "
|
|
35
|
-
|
|
33
|
+
Write-Host ""
|
|
34
|
+
Write-Host "Converge reports saved to: $convergeDir/" -ForegroundColor Green
|
|
35
|
+
|
|
36
|
+
## SDD Converge — Phase 5 Validation
|
|
37
|
+
|
|
38
|
+
**Purpose:** Verify implementation matches SPEC.md. Run per-task or full project.
|
|
39
|
+
|
|
40
|
+
**Output Location:** `sdd/converge/` (v1.1.0+)
|
|
41
|
+
|
|
42
|
+
### Usage
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Full project converge (after all tasks)
|
|
46
|
+
claude "/sdd-converge"
|
|
47
|
+
|
|
48
|
+
# Per-task converge (after each task)
|
|
49
|
+
pwsh run-converge.ps1 -TaskId "T-001"
|
|
50
|
+
|
|
51
|
+
# Per-task with strict mode
|
|
52
|
+
pwsh run-converge.ps1 -TaskId "T-002" -Strict
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Per-Task Converge (Recommended)
|
|
58
|
+
|
|
59
|
+
Run after each task to catch issues early:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
pwsh run-converge.ps1 -TaskId "T-001"
|
|
63
|
+
pwsh run-converge.ps1 -TaskId "T-002" -Strict
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### What it validates:
|
|
67
|
+
- ✅ All spec clause IDs match implementation
|
|
68
|
+
- ✅ Required text appears verbatim
|
|
69
|
+
- ✅ Colors match hex values
|
|
70
|
+
- ✅ Acceptance criteria met
|
|
71
|
+
- ✅ Edge cases handled
|
|
72
|
+
|
|
73
|
+
### Output:
|
|
74
|
+
- `sdd/converge/task-T-XXX/report.md` — Per-task validation report
|
|
36
75
|
|
|
37
76
|
---
|
|
38
77
|
|
|
39
|
-
|
|
40
|
-
|
|
78
|
+
## Full Project Converge
|
|
79
|
+
|
|
80
|
+
Run after all tasks complete:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
pwsh run-converge.ps1 -Url 'http://localhost:3000' -Strict
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### What it validates:
|
|
87
|
+
- ✅ All artifacts exist (sdd/SPEC.md, sdd/tasks/)
|
|
88
|
+
- ✅ SPEC.md structure complete
|
|
89
|
+
- ✅ Dev server health check
|
|
90
|
+
- ✅ All tasks implemented
|
|
91
|
+
- ✅ Lighthouse/axe-core (if URL provided)
|
|
92
|
+
|
|
93
|
+
### Output:
|
|
94
|
+
- `sdd/converge/validation.md` — Full project validation
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Phase Status
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
102
|
+
║ SDD Converge — Phase 5 ║
|
|
103
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
104
|
+
║ Per-Task: Run after each task → sdd/converge/task-T-XXX║
|
|
105
|
+
║ Full: Run after all tasks → sdd/converge/validation ║
|
|
106
|
+
║ ║
|
|
107
|
+
║ Flow: Task → Fix → Re-converge → Next Task ║
|
|
108
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Agent Instructions
|
|
114
|
+
|
|
115
|
+
After implementing a task:
|
|
116
|
+
|
|
117
|
+
1. **Generate converge report:**
|
|
118
|
+
```bash
|
|
119
|
+
pwsh run-converge.ps1 -TaskId "T-XXX"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
2. **Review report** for any failures
|
|
123
|
+
|
|
124
|
+
3. **If PASS:** Update task status in MASTER-TASKS.md → proceed to next task
|
|
125
|
+
|
|
126
|
+
4. **If FAIL:** Fix issues → re-run converge until PASS
|
|
127
|
+
|
|
128
|
+
5. **If SPEC issue:** Update SPEC.md → re-generate affected tasks
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Validation Checks
|
|
133
|
+
|
|
134
|
+
### Per-Task (run-converge.ps1 -TaskId)
|
|
135
|
+
| Check | Description |
|
|
136
|
+
|-------|-------------|
|
|
137
|
+
| Clause IDs | All `[SC-xxx]` from SPEC.md found in implementation |
|
|
138
|
+
| Text Match | Required text appears verbatim |
|
|
139
|
+
| Color Match | Hex values match exactly |
|
|
140
|
+
| AC Check | Acceptance criteria `[AC-xxx]` verified |
|
|
141
|
+
|
|
142
|
+
### Full Project (run-converge.ps1)
|
|
143
|
+
| Check | Description |
|
|
144
|
+
|-------|-------------|
|
|
145
|
+
| Artifacts | SPEC.md, TASKS.md, task files exist |
|
|
146
|
+
| Structure | Required sections in SPEC.md |
|
|
147
|
+
| URL Safety | No SSRF vulnerabilities |
|
|
148
|
+
| Dev Health | Target server reachable |
|
|
149
|
+
| Live Tests | Lighthouse, axe-core (if URL provided) |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Loop-Back Rules
|
|
154
|
+
|
|
155
|
+
| Failure Type | Re-enter Phase | Action |
|
|
156
|
+
|-------------|---------------|--------|
|
|
157
|
+
| Clause mismatch | Phase 4 | Fix implementation |
|
|
158
|
+
| SPEC unclear | Phase 2 | Update SPEC.md |
|
|
159
|
+
| Intent wrong | Phase 1 | Regenerate BMAD brief |
|
|
@@ -10,7 +10,7 @@ $ErrorActionPreference = "Stop"
|
|
|
10
10
|
# Parse arguments
|
|
11
11
|
$args = $argsRaw.Trim()
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# SDD Path Resolution
|
|
14
14
|
$SDD_OUTPUT_BASE = "sdd"
|
|
15
15
|
$SDD_TASKS_DIR = "$SDD_OUTPUT_BASE/tasks"
|
|
16
16
|
|
|
@@ -18,11 +18,9 @@ $SDD_TASKS_DIR = "$SDD_OUTPUT_BASE/tasks"
|
|
|
18
18
|
if (Test-Path ".sdd/config.json") {
|
|
19
19
|
try {
|
|
20
20
|
$config = Get-Content ".sdd/config.json" -Raw | ConvertFrom-Json
|
|
21
|
-
if ($config.output
|
|
22
|
-
$SDD_OUTPUT_BASE = $config.output.baseDir
|
|
23
|
-
|
|
24
|
-
if ($config.output -and $config.output.tasksDir) {
|
|
25
|
-
$SDD_TASKS_DIR = $config.output.tasksDir
|
|
21
|
+
if ($config.output) {
|
|
22
|
+
if ($config.output.baseDir) { $SDD_OUTPUT_BASE = $config.output.baseDir }
|
|
23
|
+
if ($config.output.tasksDir) { $SDD_TASKS_DIR = $config.output.tasksDir }
|
|
26
24
|
}
|
|
27
25
|
} catch {}
|
|
28
26
|
}
|
|
@@ -53,6 +51,16 @@ if (Test-Path $specPath) {
|
|
|
53
51
|
$activeSpec = $legacySpecPath
|
|
54
52
|
}
|
|
55
53
|
|
|
54
|
+
# Gate 2: Template must exist
|
|
55
|
+
$templatePath = "templates/task-detail.template.md"
|
|
56
|
+
if (-not (Test-Path $templatePath)) {
|
|
57
|
+
Write-Host "[ERROR] Template not found: $templatePath" -ForegroundColor Red
|
|
58
|
+
Write-Host "Run /sdd-init first" -ForegroundColor Yellow
|
|
59
|
+
exit 1
|
|
60
|
+
}
|
|
61
|
+
$templateContent = Get-Content $templatePath -Raw -Encoding UTF8
|
|
62
|
+
Write-Host "[OK] Template: $templatePath" -ForegroundColor Green
|
|
63
|
+
|
|
56
64
|
Write-Host ""
|
|
57
65
|
Write-Host "=== SDD Tasks Generator - Phase 3 ===" -ForegroundColor Cyan
|
|
58
66
|
|
|
@@ -187,80 +195,42 @@ $($testCategories -join ', ')
|
|
|
187
195
|
## Notes
|
|
188
196
|
|
|
189
197
|
Generated from: SPEC.md
|
|
190
|
-
Auto-generated by SDD Pipeline v1.
|
|
198
|
+
Auto-generated by SDD Pipeline v1.3.0
|
|
191
199
|
"@
|
|
192
200
|
|
|
193
201
|
Set-Content -Path "$taskDir/MASTER-TASKS.md" -Value $masterContent -Encoding UTF8
|
|
194
202
|
Write-Host " [CREATED] MASTER-TASKS.md" -ForegroundColor Gray
|
|
195
203
|
|
|
196
|
-
# Generate individual task files
|
|
197
|
-
$taskNum = 1
|
|
204
|
+
# Generate individual task files using template
|
|
198
205
|
foreach ($task in $tasks) {
|
|
199
206
|
$safeName = $task.Name -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
|
|
200
207
|
$filename = "$($task.Id)-$safeName.md"
|
|
201
208
|
|
|
202
|
-
#
|
|
203
|
-
$featureContent = ""
|
|
209
|
+
# Determine spec sections based on task type
|
|
204
210
|
$specSection = "4.1"
|
|
205
|
-
$extractedClauses = @()
|
|
206
|
-
|
|
207
211
|
if ($task.Name -eq "Project Setup") {
|
|
208
|
-
# Setup task - extract colors and dimensions from SPEC
|
|
209
|
-
$colors = @()
|
|
210
|
-
if ($specContent -match '(?s)## 3\.2.*?Colors(.+?)(?=##|\Z)') {
|
|
211
|
-
$colorMatches = [regex]::Matches($Matches[1], '`([^`]+)`')
|
|
212
|
-
foreach ($m in $colorMatches) {
|
|
213
|
-
$colors += $m.Groups[1].Value
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
$featureContent = "## Files to Create`n`n"
|
|
217
|
-
$featureContent += "- `index.html` — Main calculator page`n"
|
|
218
|
-
$featureContent += "- `styles.css` — Calculator styling`n"
|
|
219
|
-
$featureContent += "- `app.js` — Calculator logic`n`n"
|
|
220
|
-
$featureContent += "## Implementation Steps`n`n"
|
|
221
|
-
$featureContent += "1. Create `index.html` with calculator structure`n"
|
|
222
|
-
$featureContent += "2. Create `styles.css` with colors from SPEC §3.2`n"
|
|
223
|
-
$featureContent += "3. Create `app.js` with calculator state`n"
|
|
224
212
|
$specSection = "3.1, 3.2, 3.3, 6"
|
|
225
|
-
} else {
|
|
226
|
-
# Feature tasks - extract from feature content
|
|
227
|
-
$featureContent = "## Files to Modify/Create`n`n"
|
|
228
|
-
$featureContent += "- `app.js` — Add calculator logic`n`n"
|
|
229
|
-
$featureContent += "## Implementation Steps`n`n"
|
|
230
|
-
$featureContent += "1. Read SPEC.md §4.1 for feature details`n"
|
|
231
|
-
$featureContent += "2. Implement the feature logic`n"
|
|
232
|
-
$featureContent += "3. Test with manual verification`n"
|
|
233
213
|
}
|
|
234
214
|
|
|
215
|
+
# Format depends_on
|
|
235
216
|
$dependsStr = ""
|
|
236
217
|
if ($task.DependsOn.Count -gt 0 -and $task.DependsOn[0]) {
|
|
237
|
-
$dependsStr =
|
|
218
|
+
$dependsStr = "`"" + ($task.DependsOn -join "`", `"") + "`""
|
|
238
219
|
}
|
|
239
220
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
# $($task.Id): $($task.Name)
|
|
251
|
-
|
|
252
|
-
$featureContent
|
|
253
|
-
|
|
254
|
-
## Verification
|
|
255
|
-
|
|
256
|
-
- [ ] Implementation matches SPEC requirements
|
|
257
|
-
- [ ] No console errors
|
|
258
|
-
- [ ] Manual test passes
|
|
259
|
-
"@
|
|
221
|
+
# Apply template substitutions
|
|
222
|
+
$taskContent = $templateContent
|
|
223
|
+
$taskContent = $taskContent -replace '\{\{TASK_ID\}\}', $task.Id
|
|
224
|
+
$taskContent = $taskContent -replace '\{\{TASK_NAME\}\}', $task.Name
|
|
225
|
+
$taskContent = $taskContent -replace '\{\{FILENAME\}\}', $filename
|
|
226
|
+
$taskContent = $taskContent -replace '\{\{DESCRIPTION\}\}', $task.Name
|
|
227
|
+
$taskContent = $taskContent -replace '\{\{PHASE\}\}', $task.Phase
|
|
228
|
+
$taskContent = $taskContent -replace '\{\{ESTIMATE\}\}', "1h"
|
|
229
|
+
$taskContent = $taskContent -replace '\{\{SPEC_SECTIONS\}\}', $specSection
|
|
230
|
+
$taskContent = $taskContent -replace '\{\{DEPENDS_ON\}\}', $dependsStr
|
|
260
231
|
|
|
261
232
|
Set-Content -Path "$taskDir/$filename" -Value $taskContent -Encoding UTF8
|
|
262
233
|
Write-Host " [CREATED] $filename" -ForegroundColor Gray
|
|
263
|
-
$taskNum++
|
|
264
234
|
}
|
|
265
235
|
|
|
266
236
|
# Update config
|
|
@@ -285,7 +285,7 @@ switch ($cmd) {
|
|
|
285
285
|
Write-Host "[OK] All artifacts present." -ForegroundColor Green
|
|
286
286
|
Write-Host "Running converge validation..."
|
|
287
287
|
Write-Host ""
|
|
288
|
-
Write-Host "Run: pwsh run-converge.ps1 -Url 'http://localhost:3000' -Strict"
|
|
288
|
+
Write-Host "Run: pwsh lib/bundle/run-converge.ps1 -Url 'http://localhost:3000' -Strict"
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
"help" {
|
package/lib/bundle/bin/sdd.cjs
CHANGED
|
@@ -143,10 +143,10 @@ switch (cmd) {
|
|
|
143
143
|
console.log('=== SDD Converge Validation ===')
|
|
144
144
|
console.log('')
|
|
145
145
|
console.log('Full validation (requires dev server):')
|
|
146
|
-
console.log(' pwsh run-converge.ps1 -Url http://localhost:3000 -Strict')
|
|
146
|
+
console.log(' pwsh lib/bundle/run-converge.ps1 -Url http://localhost:3000 -Strict')
|
|
147
147
|
console.log('')
|
|
148
148
|
console.log('Per-task validation:')
|
|
149
|
-
console.log(' pwsh run-converge.ps1 -TaskId T-001')
|
|
149
|
+
console.log(' pwsh lib/bundle/run-converge.ps1 -TaskId T-001')
|
|
150
150
|
console.log('')
|
|
151
151
|
console.log('Claude Code:')
|
|
152
152
|
console.log(' claude "/sdd-converge"')
|
|
@@ -8,6 +8,19 @@ if (!(Test-Path $configPath)) {
|
|
|
8
8
|
|
|
9
9
|
$config = Get-Content $configPath | ConvertFrom-Json
|
|
10
10
|
|
|
11
|
+
# SDD Path Resolution - read from config
|
|
12
|
+
$SDD_OUTPUT_BASE = "sdd"
|
|
13
|
+
$SDD_SPEC_FILE = "sdd/SPEC.md"
|
|
14
|
+
$SDD_BRIEF_FILE = "sdd/brief.md"
|
|
15
|
+
$SDD_TASKS_DIR = "sdd/tasks"
|
|
16
|
+
|
|
17
|
+
if ($config.output) {
|
|
18
|
+
if ($config.output.baseDir) { $SDD_OUTPUT_BASE = $config.output.baseDir }
|
|
19
|
+
if ($config.output.spec) { $SDD_SPEC_FILE = $config.output.spec }
|
|
20
|
+
if ($config.output.brief) { $SDD_BRIEF_FILE = $config.output.brief }
|
|
21
|
+
if ($config.output.tasksDir) { $SDD_TASKS_DIR = $config.output.tasksDir }
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
Write-Host "=== SDD Pipeline Status ===" -ForegroundColor Cyan
|
|
12
25
|
Write-Host "Project: $($config.project.name)"
|
|
13
26
|
Write-Host "Phase: $($config.phases.current)"
|
|
@@ -34,34 +47,58 @@ foreach ($p in $phases) {
|
|
|
34
47
|
if ($Verify) {
|
|
35
48
|
Write-Host ""
|
|
36
49
|
Write-Host "=== Verification ===" -ForegroundColor Cyan
|
|
37
|
-
$artifacts = @(
|
|
38
|
-
@{ File = "SPEC.md"; Phase = "phase2"; Required = $true },
|
|
39
|
-
@{ File = "BMAD-brief.md"; Phase = "phase0"; Required = $false }
|
|
40
|
-
)
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
# Check brief (v1.1.0 location + legacy fallback)
|
|
52
|
+
$briefExists = (Test-Path $SDD_BRIEF_FILE) -or (Test-Path "BMAD-brief.md")
|
|
53
|
+
$briefStatus = $config.phases.phase0.status
|
|
54
|
+
if ($briefExists -and $briefStatus -eq "completed") {
|
|
55
|
+
Write-Host "[V] brief.md (in sync)" -ForegroundColor Green
|
|
56
|
+
} elseif ($briefExists -and $briefStatus -ne "completed") {
|
|
57
|
+
Write-Host "[!] brief.md (exists but config shows $briefStatus)" -ForegroundColor Yellow
|
|
58
|
+
} elseif (-not $briefExists) {
|
|
59
|
+
Write-Host "[ ] brief.md (not created yet)" -ForegroundColor Gray
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# Check SPEC (v1.1.0 location + legacy fallback)
|
|
63
|
+
$specExists = (Test-Path $SDD_SPEC_FILE) -or (Test-Path "SPEC.md")
|
|
64
|
+
$specStatus = $config.phases.phase2.status
|
|
65
|
+
if ($specExists -and $specStatus -eq "completed") {
|
|
66
|
+
Write-Host "[V] SPEC.md (in sync)" -ForegroundColor Green
|
|
67
|
+
} elseif ($specExists -and $specStatus -ne "completed") {
|
|
68
|
+
Write-Host "[!] SPEC.md (exists but config shows $specStatus)" -ForegroundColor Yellow
|
|
69
|
+
} elseif (-not $specExists) {
|
|
70
|
+
Write-Host "[ ] SPEC.md (not created yet)" -ForegroundColor Gray
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Check task directory (v1.1.0 location + legacy fallback)
|
|
74
|
+
$taskDir = $null
|
|
75
|
+
$taskDirSource = ""
|
|
76
|
+
|
|
77
|
+
# Check new location first
|
|
78
|
+
if (Test-Path $SDD_TASKS_DIR) {
|
|
79
|
+
$taskDirs = Get-ChildItem -Path $SDD_TASKS_DIR -Filter "task-*-*" -Directory -ErrorAction SilentlyContinue
|
|
80
|
+
if ($taskDirs) {
|
|
81
|
+
$taskDir = Join-Path $SDD_TASKS_DIR ($taskDirs | Select-Object -First 1).Name
|
|
82
|
+
$taskDirSource = "v1.1.0"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Fallback to legacy location
|
|
87
|
+
if (-not $taskDir) {
|
|
88
|
+
$legacyDirs = Get-ChildItem -Filter "task-*-*" -Directory -ErrorAction SilentlyContinue
|
|
89
|
+
if ($legacyDirs) {
|
|
90
|
+
$taskDir = ($legacyDirs | Select-Object -First 1).FullName
|
|
91
|
+
$taskDirSource = "legacy"
|
|
53
92
|
}
|
|
54
93
|
}
|
|
55
94
|
|
|
56
|
-
|
|
57
|
-
$taskDirs = Get-ChildItem -Filter "task-*-*" -Directory -ErrorAction SilentlyContinue
|
|
58
|
-
if ($taskDirs) {
|
|
59
|
-
$taskDir = ($taskDirs | Select-Object -First 1).Name
|
|
95
|
+
if ($taskDir) {
|
|
60
96
|
$masterPath = Join-Path $taskDir "MASTER-TASKS.md"
|
|
61
97
|
$taskFiles = Get-ChildItem -Path $taskDir -Filter "T-*.md" -ErrorAction SilentlyContinue
|
|
62
98
|
$taskFiles = $taskFiles | Where-Object { $_.Name -ne "MASTER-TASKS.md" }
|
|
63
99
|
if ($masterPath) {
|
|
64
|
-
|
|
100
|
+
$sourceNote = if ($taskDirSource -eq "legacy") { " (legacy)" } else { "" }
|
|
101
|
+
Write-Host "[V] $taskDir/$sourceNote (found)" -ForegroundColor Green
|
|
65
102
|
Write-Host " $($taskFiles.Count) task files" -ForegroundColor Gray
|
|
66
103
|
} else {
|
|
67
104
|
Write-Host "[X] $taskDir/MASTER-TASKS.md (missing)" -ForegroundColor Red
|
|
@@ -71,8 +108,7 @@ if ($Verify) {
|
|
|
71
108
|
}
|
|
72
109
|
|
|
73
110
|
# Check task progress
|
|
74
|
-
if ($
|
|
75
|
-
$taskDir = ($taskDirs | Select-Object -First 1).Name
|
|
111
|
+
if ($taskDir) {
|
|
76
112
|
$allTaskFiles = Get-ChildItem -Path $taskDir -Filter "T-*.md" -ErrorAction SilentlyContinue
|
|
77
113
|
$allTaskFiles = $allTaskFiles | Where-Object { $_.Name -ne "MASTER-TASKS.md" }
|
|
78
114
|
$total = $allTaskFiles.Count
|
|
@@ -90,4 +126,4 @@ if ($Verify) {
|
|
|
90
126
|
|
|
91
127
|
Write-Host ""
|
|
92
128
|
Write-Host "Next: Phase $($config.phases.current + 1)"
|
|
93
|
-
Write-Host "Run
|
|
129
|
+
Write-Host "Run sdd status --verify to check artifact sync."
|
|
@@ -7,18 +7,53 @@ $ErrorActionPreference = 'Stop'
|
|
|
7
7
|
Write-Host ""
|
|
8
8
|
Write-Host "=== SDD Tasks Generator - Phase 3 ===" -ForegroundColor Cyan
|
|
9
9
|
|
|
10
|
+
# SDD Path Resolution
|
|
11
|
+
$SDD_OUTPUT_BASE = "sdd"
|
|
12
|
+
$SDD_TASKS_DIR = "$SDD_OUTPUT_BASE/tasks"
|
|
13
|
+
|
|
14
|
+
# Check config for custom output directory
|
|
15
|
+
if (Test-Path ".sdd/config.json") {
|
|
16
|
+
try {
|
|
17
|
+
$config = Get-Content ".sdd/config.json" -Raw | ConvertFrom-Json
|
|
18
|
+
if ($config.output) {
|
|
19
|
+
if ($config.output.baseDir) { $SDD_OUTPUT_BASE = $config.output.baseDir }
|
|
20
|
+
if ($config.output.tasksDir) { $SDD_TASKS_DIR = $config.output.tasksDir }
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
|
|
10
25
|
# Check SPEC
|
|
11
|
-
$specPath = "
|
|
12
|
-
|
|
26
|
+
$specPath = "$SDD_OUTPUT_BASE/SPEC.md"
|
|
27
|
+
$legacySpecPath = "SPEC.md"
|
|
28
|
+
|
|
29
|
+
if (-not (Test-Path $specPath) -and -not (Test-Path $legacySpecPath)) {
|
|
13
30
|
Write-Host "[ERROR] SPEC.md not found at $specPath" -ForegroundColor Red
|
|
14
31
|
Write-Host "Run: sdd bmad [feature]" -ForegroundColor Yellow
|
|
15
32
|
Write-Host "Then: claude `/sdd-spec`" -ForegroundColor Yellow
|
|
16
33
|
exit 1
|
|
17
34
|
}
|
|
18
|
-
|
|
35
|
+
|
|
36
|
+
# Use new path if exists, else use legacy
|
|
37
|
+
if (Test-Path $specPath) {
|
|
38
|
+
Write-Host "[OK] Found: $specPath" -ForegroundColor Green
|
|
39
|
+
$activeSpec = $specPath
|
|
40
|
+
} else {
|
|
41
|
+
Write-Host "[OK] Found: $legacySpecPath (legacy location)" -ForegroundColor Green
|
|
42
|
+
$activeSpec = $legacySpecPath
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Read template
|
|
46
|
+
$templatePath = "templates/task-detail.template.md"
|
|
47
|
+
if (-not (Test-Path $templatePath)) {
|
|
48
|
+
Write-Host "[ERROR] Template not found: $templatePath" -ForegroundColor Red
|
|
49
|
+
Write-Host "Run: /sdd-init first" -ForegroundColor Yellow
|
|
50
|
+
exit 1
|
|
51
|
+
}
|
|
52
|
+
$templateContent = Get-Content $templatePath -Raw -Encoding UTF8
|
|
53
|
+
Write-Host "[OK] Template: $templatePath" -ForegroundColor Green
|
|
19
54
|
|
|
20
55
|
# Parse SPEC
|
|
21
|
-
$specContent = Get-Content $
|
|
56
|
+
$specContent = Get-Content $activeSpec -Raw -Encoding UTF8
|
|
22
57
|
|
|
23
58
|
# Extract project name
|
|
24
59
|
$projectName = "Project"
|
|
@@ -53,9 +88,20 @@ Write-Host "[OK] Test categories: $($testCategories -join ', ')" -ForegroundColo
|
|
|
53
88
|
# Create task directory
|
|
54
89
|
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
|
|
55
90
|
$safeName = $projectName -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
|
|
56
|
-
$taskDir = "
|
|
57
|
-
|
|
58
|
-
|
|
91
|
+
$taskDir = "$SDD_TASKS_DIR/task-$timestamp-$safeName"
|
|
92
|
+
|
|
93
|
+
# Check for existing task directories for this project
|
|
94
|
+
$existingDirs = Get-ChildItem -Path $SDD_TASKS_DIR -Filter "task-*-${safeName}" -Directory -ErrorAction SilentlyContinue
|
|
95
|
+
if ($existingDirs) {
|
|
96
|
+
$existingDir = $existingDirs[0].FullName
|
|
97
|
+
Write-Host ""
|
|
98
|
+
Write-Host "[WARN] Task directory already exists: $existingDir" -ForegroundColor Yellow
|
|
99
|
+
Write-Host "[INFO] Using existing directory" -ForegroundColor Cyan
|
|
100
|
+
$taskDir = $existingDir
|
|
101
|
+
} else {
|
|
102
|
+
New-Item -ItemType Directory -Path $taskDir -Force | Out-Null
|
|
103
|
+
Write-Host "[OK] Created: $taskDir" -ForegroundColor Green
|
|
104
|
+
}
|
|
59
105
|
|
|
60
106
|
# Build task list
|
|
61
107
|
$tasks = @()
|
|
@@ -89,49 +135,45 @@ $masterContent += "| ID | Name | Estimate | Status |`n|----|------|----------|--
|
|
|
89
135
|
foreach ($t in $tasks) {
|
|
90
136
|
$masterContent += "| $($t.Id) | $($t.Name) | 1h | [ ] |`n"
|
|
91
137
|
}
|
|
92
|
-
$masterContent += "`n## Progress`n`n- Completed: 0 / $($tasks.Count)`n- Pending: $($tasks.Count)`n`n"
|
|
138
|
+
$masterContent += "`n## Progress`n`n- Completed: 0 / $($tasks.Count)`n- In Progress: 0`n- Pending: $($tasks.Count)`n`n"
|
|
93
139
|
$masterContent += "## Test Categories`n`n$($testCategories -join ', ')`n`n"
|
|
94
140
|
$masterContent += "## Notes`n`nGenerated from: SPEC.md`nAuto-generated by SDD Pipeline v1.2.2`n"
|
|
95
141
|
|
|
96
142
|
Set-Content -Path "$taskDir/MASTER-TASKS.md" -Value $masterContent -Encoding UTF8
|
|
97
143
|
Write-Host " [CREATED] MASTER-TASKS.md" -ForegroundColor Gray
|
|
98
144
|
|
|
99
|
-
# Generate task files
|
|
145
|
+
# Generate task files using template
|
|
100
146
|
foreach ($t in $tasks) {
|
|
101
147
|
$safeName = $t.Name -replace '[^a-zA-Z0-9]', '-' -replace '-+', '-'
|
|
102
148
|
$filename = "$($t.Id)-$safeName.md"
|
|
103
|
-
$dependsOn = if ($t.DependsOn) { "
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
# $($t.Id): $($t.Name)
|
|
116
|
-
|
|
117
|
-
## Files to Modify/Create
|
|
118
|
-
- [List files]
|
|
119
|
-
|
|
120
|
-
## Implementation Steps
|
|
121
|
-
1. [Step 1]
|
|
122
|
-
2. [Step 2]
|
|
123
|
-
3. [Step 3]
|
|
124
|
-
|
|
125
|
-
## Verification
|
|
126
|
-
- [ ] Check 1
|
|
127
|
-
- [ ] Check 2
|
|
128
|
-
- [ ] Check 3
|
|
129
|
-
"@
|
|
149
|
+
$dependsOn = if ($t.DependsOn) { "`"$($t.DependsOn)`"" } else { "" }
|
|
150
|
+
|
|
151
|
+
# Apply template substitutions
|
|
152
|
+
$taskContent = $templateContent
|
|
153
|
+
$taskContent = $taskContent -replace '\{\{TASK_ID\}\}', $t.Id
|
|
154
|
+
$taskContent = $taskContent -replace '\{\{TASK_NAME\}\}', $t.Name
|
|
155
|
+
$taskContent = $taskContent -replace '\{\{FILENAME\}\}', $filename
|
|
156
|
+
$taskContent = $taskContent -replace '\{\{DESCRIPTION\}\}', $t.Name
|
|
157
|
+
$taskContent = $taskContent -replace '\{\{PHASE\}\}', $t.Phase
|
|
158
|
+
$taskContent = $taskContent -replace '\{\{ESTIMATE\}\}', "1h"
|
|
159
|
+
$taskContent = $taskContent -replace '\{\{SPEC_SECTIONS\}\}', "4.1"
|
|
160
|
+
$taskContent = $taskContent -replace '\{\{DEPENDS_ON\}\}', $dependsOn
|
|
130
161
|
|
|
131
162
|
Set-Content -Path "$taskDir/$filename" -Value $taskContent -Encoding UTF8
|
|
132
163
|
Write-Host " [CREATED] $filename" -ForegroundColor Gray
|
|
133
164
|
}
|
|
134
165
|
|
|
166
|
+
# Update config
|
|
167
|
+
if (Test-Path ".sdd/config.json") {
|
|
168
|
+
$config = Get-Content ".sdd/config.json" -Raw | ConvertFrom-Json
|
|
169
|
+
$config.phases.current = 3
|
|
170
|
+
$config.phases.phase2.status = "completed"
|
|
171
|
+
$config.phases.phase2.completedAt = (Get-Date -Format "yyyy-MM-dd")
|
|
172
|
+
$config.phases.phase3.status = "in-progress"
|
|
173
|
+
$config | ConvertTo-Json -Depth 10 | Set-Content ".sdd/config.json"
|
|
174
|
+
Write-Host "[OK] Config updated" -ForegroundColor Green
|
|
175
|
+
}
|
|
176
|
+
|
|
135
177
|
Write-Host ""
|
|
136
178
|
Write-Host "[OK] Tasks generated: $($tasks.Count) tasks" -ForegroundColor Green
|
|
137
179
|
Write-Host ""
|
package/lib/bundle/lib/init.js
CHANGED
|
@@ -4,6 +4,23 @@ Standard patterns for spawning subagents during SDD task execution.
|
|
|
4
4
|
|
|
5
5
|
**IMPORTANT:** All subagent names listed here are verified to exist in the Claude Code environment.
|
|
6
6
|
|
|
7
|
+
## IMPORTANT: Claude Code Commands vs CLI Commands
|
|
8
|
+
|
|
9
|
+
**When running SDD pipeline commands in subagents, use Claude Code commands:**
|
|
10
|
+
```bash
|
|
11
|
+
# CORRECT
|
|
12
|
+
claude "/sdd-bmad simple calculator app..."
|
|
13
|
+
claude "/sdd-spec"
|
|
14
|
+
claude "/sdd-tasks"
|
|
15
|
+
claude "/sdd-cook --task T-001"
|
|
16
|
+
|
|
17
|
+
# WRONG
|
|
18
|
+
sdd bmad "simple calculator app..."
|
|
19
|
+
sdd spec
|
|
20
|
+
sdd tasks
|
|
21
|
+
sdd cook --task T-001
|
|
22
|
+
```
|
|
23
|
+
|
|
7
24
|
## Task Tool Pattern
|
|
8
25
|
|
|
9
26
|
```
|
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Standard templates for spawning subagents during SDD task execution.
|
|
4
4
|
|
|
5
|
+
## IMPORTANT: Claude Code Commands vs CLI Commands
|
|
6
|
+
|
|
7
|
+
**When running SDD pipeline commands in subagents, use Claude Code commands:**
|
|
8
|
+
```bash
|
|
9
|
+
# CORRECT - Interactive mode with higher confidence
|
|
10
|
+
claude "/sdd-bmad simple calculator app..."
|
|
11
|
+
claude "/sdd-spec"
|
|
12
|
+
claude "/sdd-tasks"
|
|
13
|
+
claude "/sdd-cook --task T-001"
|
|
14
|
+
|
|
15
|
+
# WRONG - Fast CLI mode with lower confidence
|
|
16
|
+
sdd bmad "simple calculator app..."
|
|
17
|
+
sdd spec
|
|
18
|
+
sdd tasks
|
|
19
|
+
sdd cook --task T-001
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Why:** Claude Code commands run in interactive mode, which:
|
|
23
|
+
- Generates higher confidence briefs (50-100 vs 5-30)
|
|
24
|
+
- Provides better prompts for SPEC generation
|
|
25
|
+
- Enables the full 9-question BMAD interview
|
|
26
|
+
|
|
5
27
|
## Task Tool Pattern
|
|
6
28
|
|
|
7
29
|
```
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
Template: T-XXX-task-name.md v1.
|
|
2
|
+
Template: T-XXX-task-name.md v1.2.0
|
|
3
3
|
Spec-Driven Development — Phase 3 Task
|
|
4
4
|
Generated by: /sdd-tasks
|
|
5
|
+
Updated: 2026-08-31 (Use template for generation)
|
|
5
6
|
-->
|
|
6
7
|
---
|
|
7
|
-
|
|
8
|
+
name: {{FILENAME}}
|
|
9
|
+
description: "{{DESCRIPTION}}"
|
|
10
|
+
phase: {{PHASE}}
|
|
11
|
+
estimate: {{ESTIMATE}}
|
|
12
|
+
status: pending
|
|
13
|
+
spec_sections: [{{SPEC_SECTIONS}}]
|
|
8
14
|
parallel_group: ""
|
|
9
|
-
|
|
15
|
+
depends_on: [{{DEPENDS_ON}}]
|
|
10
16
|
---
|
|
11
17
|
|
|
12
|
-
#
|
|
18
|
+
# {{TASK_ID}}: {{TASK_NAME}}
|
|
13
19
|
|
|
14
|
-
**Phase:**
|
|
15
|
-
**Estimate:**
|
|
20
|
+
**Phase:** {{PHASE}}
|
|
21
|
+
**Estimate:** {{ESTIMATE}}
|
|
16
22
|
**Status:** Pending
|
|
23
|
+
**Converge Status:** ⏳ PENDING
|
|
17
24
|
|
|
18
25
|
## Description
|
|
19
26
|
|
|
@@ -29,12 +36,61 @@ spec_sections: []
|
|
|
29
36
|
2. [Step 2]
|
|
30
37
|
3. [Step 3]
|
|
31
38
|
|
|
32
|
-
##
|
|
39
|
+
## Acceptance Criteria
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
> **Agent:** Verify each criterion against SPEC.md before marking complete.
|
|
42
|
+
|
|
43
|
+
| ID | Criterion | Spec Clause | Verified By | Status |
|
|
44
|
+
|----|-----------|-------------|-------------|--------|
|
|
45
|
+
| AC-001 | [Specific criterion] | [SC-xxx] | [Test/Check] | ⏳ PENDING |
|
|
46
|
+
| AC-002 | [Specific criterion] | [SC-xxx] | [Test/Check] | ⏳ PENDING |
|
|
47
|
+
|
|
48
|
+
## Spec Clauses
|
|
49
|
+
|
|
50
|
+
> **Track exact spec text for automated validation.**
|
|
51
|
+
|
|
52
|
+
| Clause ID | Spec Text | Location | Verified |
|
|
53
|
+
|-----------|-----------|----------|----------|
|
|
54
|
+
| [SC-xxx] | "[exact text from SPEC.md]" | [SPEC.md §X.X] | ⏳ |
|
|
55
|
+
|
|
56
|
+
## Converge Report
|
|
57
|
+
|
|
58
|
+
> **Fill after implementation — see converge/task-{{TASK_ID}}/report.md**
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
## {{TASK_ID}} Converge Report
|
|
62
|
+
|
|
63
|
+
**Task:** {{TASK_NAME}}
|
|
64
|
+
**Date:** [YYYY-MM-DD]
|
|
65
|
+
**Agent:** [Claude/User]
|
|
66
|
+
**Status:** ✅ PASS | ❌ FAIL
|
|
67
|
+
|
|
68
|
+
### Spec Adherence
|
|
69
|
+
|
|
70
|
+
| Clause | Spec Says | Implementation Has | Match |
|
|
71
|
+
|--------|-----------|-------------------|-------|
|
|
72
|
+
| [SC-xxx] | "[text]" | "[found text]" | ✅/❌ |
|
|
73
|
+
|
|
74
|
+
### Acceptance Criteria
|
|
75
|
+
|
|
76
|
+
| Criterion | Status |
|
|
77
|
+
|-----------|--------|
|
|
78
|
+
| AC-001 | ✅/❌ |
|
|
79
|
+
| AC-002 | ✅/❌ |
|
|
80
|
+
|
|
81
|
+
### Issues Found (if any)
|
|
82
|
+
|
|
83
|
+
- [Issue 1]
|
|
84
|
+
- [Issue 2]
|
|
85
|
+
|
|
86
|
+
### Next Steps
|
|
87
|
+
|
|
88
|
+
- [If PASS: Proceed to next task]
|
|
89
|
+
- [If FAIL: Fix issues, re-run converge]
|
|
90
|
+
```
|
|
36
91
|
|
|
37
92
|
## References
|
|
38
93
|
|
|
39
94
|
- SPEC.md Sections: [§X.X, §Y.Y — from spec_sections above]
|
|
40
95
|
- MASTER-TASKS: `../MASTER-TASKS.md`
|
|
96
|
+
- Converge: `../../converge/task-{{TASK_ID}}/report.md`
|
package/lib/init.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sdd-pipeline",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
|
-
"lib/",
|
|
11
|
+
"lib/bmad.js",
|
|
12
|
+
"lib/bmad/",
|
|
13
|
+
"lib/config.js",
|
|
14
|
+
"lib/init.js",
|
|
15
|
+
"lib/sanitize.js",
|
|
12
16
|
"lib/bundle/"
|
|
13
17
|
],
|
|
14
18
|
"engines": {
|
|
@@ -25,6 +29,8 @@
|
|
|
25
29
|
],
|
|
26
30
|
"license": "MIT",
|
|
27
31
|
"scripts": {
|
|
28
|
-
"test": "node test/run.js"
|
|
32
|
+
"test": "node test/run.js",
|
|
33
|
+
"sync": "pwsh scripts/sync-bundle.ps1",
|
|
34
|
+
"pack": "npm pack --dry-run"
|
|
29
35
|
}
|
|
30
36
|
}
|