sdd-pipeline 1.0.0 → 1.0.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 +33 -26
- package/lib/bundle/.claude/commands/sdd.md +261 -0
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -5,57 +5,64 @@ Spec-Driven Development pipeline that transforms raw feature requests into valid
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```powershell
|
|
8
|
-
#
|
|
9
|
-
|
|
8
|
+
# Install globally (once)
|
|
9
|
+
npm install -g sdd-pipeline
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
|
|
11
|
+
# In any new project directory:
|
|
12
|
+
sdd init # Initialize pipeline
|
|
13
|
+
sdd bmad "todo app" # Generate BMAD brief
|
|
14
|
+
sdd status # Check pipeline phases
|
|
15
|
+
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
claude "/sdd-tasks"
|
|
17
|
+
## Unified Command
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
Use `/sdd` in Claude Code for the full pipeline:
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
```powershell
|
|
22
|
+
claude "/sdd init"
|
|
23
|
+
claude "/sdd bmad landing page for my SaaS"
|
|
24
|
+
claude "/sdd spec"
|
|
25
|
+
claude "/sdd tasks"
|
|
26
|
+
claude "/sdd converge"
|
|
27
|
+
claude "/sdd status"
|
|
24
28
|
```
|
|
25
29
|
|
|
26
30
|
## Pipeline Phases
|
|
27
31
|
|
|
28
32
|
| Phase | Command | Output |
|
|
29
33
|
|-------|---------|--------|
|
|
30
|
-
| 0: BMAD | `/sdd
|
|
31
|
-
| 2: Spec | `/sdd
|
|
32
|
-
| 3: Tasks | `/sdd
|
|
33
|
-
| 5: Converge | `/sdd
|
|
34
|
+
| 0: BMAD | `/sdd bmad` | BMAD-brief.md |
|
|
35
|
+
| 2: Spec | `/sdd spec` | SPEC.md |
|
|
36
|
+
| 3: Tasks | `/sdd tasks` | TASKS.md |
|
|
37
|
+
| 5: Converge | `/sdd converge` | converge/validation.md |
|
|
38
|
+
|
|
39
|
+
Individual commands also available: `/sdd-bmad`, `/sdd-spec`, `/sdd-tasks`, `/sdd-converge`.
|
|
34
40
|
|
|
35
41
|
## Key Features
|
|
36
42
|
|
|
37
|
-
- **Phase gates:** `/sdd
|
|
38
|
-
- **Prompt injection protection:** All user input sanitized
|
|
39
|
-
- **SSRF protection:** URL validation blocks private IPs, localhost
|
|
40
|
-
- **Dev server health check:** 60s timeout
|
|
43
|
+
- **Phase gates:** `/sdd spec` fails if BMAD-brief.md missing — no bypass
|
|
44
|
+
- **Prompt injection protection:** All user input sanitized
|
|
45
|
+
- **SSRF protection:** URL validation blocks private IPs, localhost
|
|
46
|
+
- **Dev server health check:** 60s timeout before Lighthouse runs
|
|
41
47
|
- **GitHub Actions CI:** Runs converge on push/PR, creates Issue on failure
|
|
42
48
|
- **Domain extensions:** API, frontend, backend — set via `.sdd/config.json`
|
|
43
49
|
|
|
44
50
|
## Status
|
|
45
51
|
|
|
46
52
|
```powershell
|
|
47
|
-
|
|
48
|
-
pwsh commands/sdd-status.ps1 --Verify
|
|
53
|
+
sdd status # Quick status (npm package)
|
|
54
|
+
pwsh commands/sdd-status.ps1 --Verify # Full verification
|
|
49
55
|
```
|
|
50
56
|
|
|
51
57
|
## Architecture
|
|
52
58
|
|
|
53
59
|
```
|
|
54
|
-
Raw Idea -> /sdd
|
|
55
|
-
-> /sdd
|
|
56
|
-
-> /sdd
|
|
60
|
+
Raw Idea -> /sdd bmad -> BMAD-brief.md
|
|
61
|
+
-> /sdd spec -> SPEC.md
|
|
62
|
+
-> /sdd tasks -> TASKS.md
|
|
57
63
|
-> Implement
|
|
58
|
-
->
|
|
64
|
+
-> /sdd converge
|
|
65
|
+
-> pwsh run-converge.ps1 -> converge/validation.md
|
|
59
66
|
|
|
|
60
67
|
+-- PASS: merge
|
|
61
68
|
+-- FAIL: fix -> re-enter
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
tool: Bash
|
|
3
|
+
when: always
|
|
4
|
+
args: optional
|
|
5
|
+
---
|
|
6
|
+
$ErrorActionPreference = "Stop"
|
|
7
|
+
$args = $argsRaw.Trim()
|
|
8
|
+
|
|
9
|
+
function Write-Help {
|
|
10
|
+
Write-Host @"
|
|
11
|
+
|
|
12
|
+
sdd — Spec-Driven Development CLI
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
/sdd init Initialize SDD pipeline in current directory
|
|
16
|
+
/sdd bmad <desc> Generate BMAD brief
|
|
17
|
+
/sdd status Show pipeline phase status
|
|
18
|
+
/sdd help Show this help
|
|
19
|
+
|
|
20
|
+
Full pipeline commands:
|
|
21
|
+
/sdd spec Generate SPEC.md from BMAD-brief.md
|
|
22
|
+
/sdd tasks Generate TASKS.md from SPEC.md
|
|
23
|
+
/sdd converge Run converge validation
|
|
24
|
+
|
|
25
|
+
"@
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function Test-PromptInjection {
|
|
29
|
+
param([string]$Input)
|
|
30
|
+
$blocked = '(?i)(ignore previous|disregard|system:|</?script|ignore all previous)'
|
|
31
|
+
if ($Input -match $blocked) {
|
|
32
|
+
Write-Host "[WARN] Input sanitized — blocked pattern detected" -ForegroundColor Yellow
|
|
33
|
+
return $Input -replace $blocked, '[FILTERED]'
|
|
34
|
+
}
|
|
35
|
+
return $Input
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (-not $args) {
|
|
39
|
+
Write-Host "Usage: /sdd <command> [args]" -ForegroundColor Yellow
|
|
40
|
+
Write-Help
|
|
41
|
+
exit 0
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
$parts = $args -split '\s+', 2
|
|
45
|
+
$cmd = $parts[0].ToLower()
|
|
46
|
+
$rest = if ($parts.Length -gt 1) { Test-PromptInjection -Input $parts[1] } else { "" }
|
|
47
|
+
|
|
48
|
+
switch ($cmd) {
|
|
49
|
+
"init" {
|
|
50
|
+
New-Item -ItemType Directory -Force -Path ".sdd","templates","converge",".claude/commands","commands","extensions",".github/workflows" | Out-Null
|
|
51
|
+
|
|
52
|
+
if (Test-Path ".sdd/config.json") {
|
|
53
|
+
Write-Host "[SKIP] SDD pipeline already initialized" -ForegroundColor Yellow
|
|
54
|
+
} else {
|
|
55
|
+
$config = @{
|
|
56
|
+
version = "1.0"
|
|
57
|
+
phases = @{
|
|
58
|
+
current = 0
|
|
59
|
+
phase0 = @{ status = "pending"; brief = "BMAD-brief.md" }
|
|
60
|
+
phase1 = @{ status = "pending" }
|
|
61
|
+
phase2 = @{ status = "pending"; specFile = "SPEC.md" }
|
|
62
|
+
phase3 = @{ status = "pending"; tasksFile = "TASKS.md" }
|
|
63
|
+
phase4 = @{ status = "pending" }
|
|
64
|
+
phase5 = @{ status = "pending"; validationFile = "converge/validation.md" }
|
|
65
|
+
}
|
|
66
|
+
templateVersions = @{
|
|
67
|
+
constitution = "1.0.0"; bmad = "1.0.0"
|
|
68
|
+
spec = "1.0.0"; plan = "1.0.0"; tasks = "1.0.0"
|
|
69
|
+
}
|
|
70
|
+
project = @{ name = "TODO"; domain = "general" }
|
|
71
|
+
settings = @{ autoConverge = $false; strictMode = $true; maxTaskHours = 2 }
|
|
72
|
+
}
|
|
73
|
+
$config | ConvertTo-Json | Set-Content ".sdd/config.json" -Encoding UTF8
|
|
74
|
+
Write-Host "[OK] SDD pipeline initialized." -ForegroundColor Green
|
|
75
|
+
}
|
|
76
|
+
Write-Host ""
|
|
77
|
+
Write-Host "Next: /sdd bmad <feature description>"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
"bmad" {
|
|
81
|
+
if (-not $rest) {
|
|
82
|
+
Write-Host "Usage: /sdd bmad <description>" -ForegroundColor Red
|
|
83
|
+
Write-Host "Example: /sdd bmad landing page for my SaaS"
|
|
84
|
+
exit 1
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
$date = Get-Date -Format "yyyy-MM-dd"
|
|
88
|
+
$expiry = (Get-Date).AddDays(30).ToString("yyyy-MM-dd")
|
|
89
|
+
|
|
90
|
+
$brief = @"
|
|
91
|
+
# BMAD Brief — [Project Name]
|
|
92
|
+
|
|
93
|
+
> Generated: ${date}. Expires: ${expiry}.
|
|
94
|
+
|
|
95
|
+
## Input
|
|
96
|
+
> ${rest}
|
|
97
|
+
|
|
98
|
+
## PM Perspective
|
|
99
|
+
**Target user:** [Who benefits most from this feature]
|
|
100
|
+
**User needs:** [Top 3 needs this feature addresses]
|
|
101
|
+
**Primary conversion action:** [What user does that matters to business]
|
|
102
|
+
|
|
103
|
+
## Architect Perspective
|
|
104
|
+
**Minimum viable approach:** [One paragraph]
|
|
105
|
+
**Technical risks:**
|
|
106
|
+
| Risk | Likelihood | Impact | Mitigation |
|
|
107
|
+
|------|-----------|--------|------------|
|
|
108
|
+
| [Risk 1] | [H/M/L] | [H/M/L] | [Mitigation] |
|
|
109
|
+
|
|
110
|
+
## UX Perspective
|
|
111
|
+
**First impression goal:** [Description]
|
|
112
|
+
**Microcopy needed:** [List]
|
|
113
|
+
|
|
114
|
+
## Synthesis
|
|
115
|
+
**What we're building:** [2-3 sentences describing the feature]
|
|
116
|
+
**What we're NOT building:** [Explicit exclusions]
|
|
117
|
+
1. [Exclusion]
|
|
118
|
+
|
|
119
|
+
## Open Questions
|
|
120
|
+
| # | Question | Impact |
|
|
121
|
+
|---|----------|--------|
|
|
122
|
+
| 1 | [Question] | [Blocking?] |
|
|
123
|
+
|
|
124
|
+
## Prompt Injection Check
|
|
125
|
+
- Input was sanitized before processing
|
|
126
|
+
- No system prompt overrides accepted
|
|
127
|
+
"@
|
|
128
|
+
|
|
129
|
+
if (Test-Path "BMAD-brief.md") {
|
|
130
|
+
Write-Host "[WARN] BMAD-brief.md already exists — overwriting" -ForegroundColor Yellow
|
|
131
|
+
}
|
|
132
|
+
$brief | Set-Content "BMAD-brief.md" -Encoding UTF8
|
|
133
|
+
Write-Host "[OK] BMAD-brief.md created." -ForegroundColor Green
|
|
134
|
+
Write-Host ""
|
|
135
|
+
Write-Host "Next: /sdd spec"
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
"spec" {
|
|
139
|
+
if (-not (Test-Path "BMAD-brief.md")) {
|
|
140
|
+
Write-Host "[ERROR] BMAD-brief.md not found" -ForegroundColor Red
|
|
141
|
+
Write-Host "Run: /sdd bmad <description> first"
|
|
142
|
+
exit 1
|
|
143
|
+
}
|
|
144
|
+
if (-not (Test-Path "templates/SPEC.template.md")) {
|
|
145
|
+
Write-Host "[ERROR] templates/SPEC.template.md not found" -ForegroundColor Red
|
|
146
|
+
Write-Host "Run: /sdd init first"
|
|
147
|
+
exit 1
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (Test-Path ".sdd/config.json") {
|
|
151
|
+
$config = Get-Content ".sdd/config.json" | ConvertFrom-Json
|
|
152
|
+
$config.phases.current = 2
|
|
153
|
+
$config.phases.phase0.status = "completed"
|
|
154
|
+
$config.phases.phase0.completedAt = (Get-Date -Format "yyyy-MM-dd")
|
|
155
|
+
$config.phases.phase2.status = "in-progress"
|
|
156
|
+
$config | ConvertTo-Json | Set-Content ".sdd/config.json" -Encoding UTF8
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
Write-Host "[OK] Phase 0 gate passed." -ForegroundColor Green
|
|
160
|
+
Write-Host "Generate SPEC.md by expanding templates/SPEC.template.md"
|
|
161
|
+
Write-Host "using content from BMAD-brief.md."
|
|
162
|
+
Write-Host ""
|
|
163
|
+
Write-Host "The following sections are required:"
|
|
164
|
+
Write-Host " 1. Overview"
|
|
165
|
+
Write-Host " 2. User Stories (Must Have / Nice to Have)"
|
|
166
|
+
Write-Host " 3. Functional Requirements"
|
|
167
|
+
Write-Host " 4. Non-Functional Requirements"
|
|
168
|
+
Write-Host " 5. Technical Constraints"
|
|
169
|
+
Write-Host " 6. Open Questions"
|
|
170
|
+
Write-Host " 7. Success Criteria"
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
"tasks" {
|
|
174
|
+
if (-not (Test-Path "SPEC.md")) {
|
|
175
|
+
Write-Host "[ERROR] SPEC.md not found" -ForegroundColor Red
|
|
176
|
+
Write-Host "Run: /sdd spec first"
|
|
177
|
+
exit 1
|
|
178
|
+
}
|
|
179
|
+
if (-not (Test-Path "templates/TASKS.template.md")) {
|
|
180
|
+
Write-Host "[ERROR] templates/TASKS.template.md not found" -ForegroundColor Red
|
|
181
|
+
Write-Host "Run: /sdd init first"
|
|
182
|
+
exit 1
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (Test-Path ".sdd/config.json") {
|
|
186
|
+
$config = Get-Content ".sdd/config.json" | ConvertFrom-Json
|
|
187
|
+
$config.phases.current = 3
|
|
188
|
+
$config.phases.phase2.status = "completed"
|
|
189
|
+
$config.phases.phase2.completedAt = (Get-Date -Format "yyyy-MM-dd")
|
|
190
|
+
$config.phases.phase3.status = "in-progress"
|
|
191
|
+
$config | ConvertTo-Json | Set-Content ".sdd/config.json" -Encoding UTF8
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
Write-Host "[OK] Phase 2 gate passed." -ForegroundColor Green
|
|
195
|
+
Write-Host "Break SPEC.md into discrete tasks (T-001, T-002, ...)."
|
|
196
|
+
Write-Host "Each task must:"
|
|
197
|
+
Write-Host " - Take <= 2 hours"
|
|
198
|
+
Write-Host " - Be independently verifiable"
|
|
199
|
+
Write-Host " - Have output artifact specified"
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
"status" {
|
|
203
|
+
if (-not (Test-Path ".sdd/config.json")) {
|
|
204
|
+
Write-Host "[ERROR] .sdd/config.json not found" -ForegroundColor Red
|
|
205
|
+
Write-Host "Run: /sdd init first"
|
|
206
|
+
exit 1
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
$config = Get-Content ".sdd/config.json" | ConvertFrom-Json
|
|
210
|
+
Write-Host "=== SDD Pipeline Status ===" -ForegroundColor Cyan
|
|
211
|
+
Write-Host "Project: $($config.project.name)"
|
|
212
|
+
Write-Host "Phase: $($config.phases.current)"
|
|
213
|
+
Write-Host "Domain: $($config.project.domain)"
|
|
214
|
+
Write-Host ""
|
|
215
|
+
|
|
216
|
+
$phases = @("phase0","phase1","phase2","phase3","phase4","phase5")
|
|
217
|
+
foreach ($p in $phases) {
|
|
218
|
+
$phaseData = $config.phases.$p
|
|
219
|
+
$status = if ($phaseData.status) { $phaseData.status } else { "unknown" }
|
|
220
|
+
$icon = switch ($status) { "completed" { "[V]" } "in-progress" { "[>]" } default { "[ ]" } }
|
|
221
|
+
$color = switch ($status) { "completed" { "Green" } "in-progress" { "Yellow" } default { "Gray" } }
|
|
222
|
+
Write-Host "$icon $p : $status" -ForegroundColor $color
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
Write-Host ""
|
|
226
|
+
$next = $config.phases.current
|
|
227
|
+
$nextCmd = switch ($next) {
|
|
228
|
+
0 { "/sdd bmad <description>" }
|
|
229
|
+
2 { "/sdd spec" }
|
|
230
|
+
3 { "/sdd tasks" }
|
|
231
|
+
default { "All phases complete" }
|
|
232
|
+
}
|
|
233
|
+
Write-Host "Next: $nextCmd"
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
"converge" {
|
|
237
|
+
$required = @("SPEC.md", "PLAN.md", "TASKS.md")
|
|
238
|
+
$missing = $required | Where-Object { -not (Test-Path $_) }
|
|
239
|
+
if ($missing) {
|
|
240
|
+
Write-Host "[ERROR] Missing artifacts: $($missing -join ', ')" -ForegroundColor Red
|
|
241
|
+
Write-Host "Run: /sdd init && /sdd bmad <desc> && /sdd spec && /sdd tasks"
|
|
242
|
+
exit 1
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
Write-Host "[OK] All artifacts present." -ForegroundColor Green
|
|
246
|
+
Write-Host "Running converge validation..."
|
|
247
|
+
Write-Host ""
|
|
248
|
+
Write-Host "Run: pwsh run-converge.ps1 -Url 'http://localhost:3000' -Strict"
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
"help" {
|
|
252
|
+
Write-Help
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
default {
|
|
256
|
+
Write-Host "Unknown command: $cmd" -ForegroundColor Red
|
|
257
|
+
Write-Host ""
|
|
258
|
+
Write-Help
|
|
259
|
+
exit 1
|
|
260
|
+
}
|
|
261
|
+
}
|
package/package.json
CHANGED