sdd-pipeline 1.2.4 → 1.2.7
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.cjs +201 -0
- package/lib/bmad/index.js +20 -3
- package/lib/bundle/.claude/commands/sdd-check.md +153 -0
- package/lib/bundle/.claude/commands/sdd-cook.md +149 -167
- package/lib/bundle/.claude/commands/sdd-task-status.md +97 -27
- package/lib/bundle/bin/sdd.cjs +201 -0
- package/lib/bundle/bin/sdd.js +159 -0
- package/lib/bundle/commands/sdd-task-status.ps1 +82 -22
- package/lib/bundle/lib/bmad/confidence.js +129 -0
- package/lib/bundle/lib/bmad/index.js +157 -0
- package/lib/bundle/lib/bmad/problem-first.js +91 -0
- package/lib/bundle/lib/bmad/questions.js +110 -0
- package/lib/bundle/lib/bmad/synthesis.js +109 -0
- package/lib/bundle/lib/config.js +35 -0
- package/lib/bundle/lib/init.js +204 -0
- package/lib/bundle/lib/sanitize.js +10 -0
- package/lib/bundle/run-converge.ps1 +288 -42
- package/lib/bundle/skills/sdd-tasks/SKILL.md +259 -0
- package/lib/init.js +108 -32
- package/package.json +8 -8
- package/bin/sdd.js +0 -70
- package/lib/bmad.js +0 -54
package/bin/sdd.cjs
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// sdd — Spec-Driven Development CLI
|
|
3
|
+
// Unified entry point for both npm package and local development
|
|
4
|
+
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const fs = require('fs')
|
|
7
|
+
|
|
8
|
+
// Determine if we're in npm package or local development
|
|
9
|
+
const isNpmPackage = fs.existsSync(path.join(__dirname, 'lib/bmad.js'))
|
|
10
|
+
const libDir = isNpmPackage ? path.join(__dirname, 'lib') : path.join(__dirname, '..', 'lib')
|
|
11
|
+
|
|
12
|
+
// Dynamic requires
|
|
13
|
+
const init = require(path.join(libDir, 'init'))
|
|
14
|
+
const bmad = require(path.join(libDir, 'bmad/index'))
|
|
15
|
+
const config = require(path.join(libDir, 'config'))
|
|
16
|
+
|
|
17
|
+
const args = process.argv.slice(2)
|
|
18
|
+
const cmd = args[0]
|
|
19
|
+
|
|
20
|
+
// PowerShell detection - use correct command for platform
|
|
21
|
+
function getPowerShellCommand() {
|
|
22
|
+
if (process.platform === 'win32') {
|
|
23
|
+
// Windows: try powershell.exe first (always available), then pwsh
|
|
24
|
+
const system32 = 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
|
25
|
+
if (fs.existsSync(system32)) {
|
|
26
|
+
return 'powershell'
|
|
27
|
+
}
|
|
28
|
+
return 'powershell' // Fallback to whatever is in PATH
|
|
29
|
+
}
|
|
30
|
+
return 'pwsh' // macOS/Linux: PowerShell Core
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function runPowerShellScript(scriptPath, scriptArgs, callback) {
|
|
34
|
+
const psCmd = getPowerShellCommand()
|
|
35
|
+
const psArgs = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath, ...scriptArgs]
|
|
36
|
+
|
|
37
|
+
const { spawn } = require('child_process')
|
|
38
|
+
const ps = spawn(psCmd, psArgs, {
|
|
39
|
+
stdio: 'inherit',
|
|
40
|
+
shell: false,
|
|
41
|
+
windowsHide: true
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
ps.on('error', (err) => {
|
|
45
|
+
callback(err, null)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
ps.on('close', (code) => {
|
|
49
|
+
callback(null, code)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
switch (cmd) {
|
|
54
|
+
case 'init':
|
|
55
|
+
init.run()
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
case 'bmad': {
|
|
59
|
+
const input = args.slice(1).join(' ')
|
|
60
|
+
if (!input) {
|
|
61
|
+
console.error('Usage: sdd bmad <feature description>')
|
|
62
|
+
console.error('Example: sdd bmad "landing page for my SaaS product"')
|
|
63
|
+
console.error('')
|
|
64
|
+
console.error('For interactive mode (9-question interview), use Claude Code:')
|
|
65
|
+
console.error(' claude "/sdd-bmad landing page for my SaaS"')
|
|
66
|
+
process.exit(1)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Try to run PowerShell script if available
|
|
70
|
+
const commandsDir = isNpmPackage
|
|
71
|
+
? path.join(libDir, 'bundle', '.claude', 'commands')
|
|
72
|
+
: path.join(__dirname, '..', '.claude', 'commands')
|
|
73
|
+
const bmadScript = path.join(commandsDir, 'sdd-bmad.md')
|
|
74
|
+
|
|
75
|
+
// Note: Claude Code commands are .md files designed for Claude Code CLI
|
|
76
|
+
// PowerShell cannot run .md files directly
|
|
77
|
+
// So we always use the Node.js module for fast mode
|
|
78
|
+
|
|
79
|
+
// Generate brief using Node.js module
|
|
80
|
+
const session = bmad.init(input)
|
|
81
|
+
const result = bmad.generateBrief()
|
|
82
|
+
|
|
83
|
+
console.log('[OK] sdd/brief.md created.')
|
|
84
|
+
console.log(`Confidence: ${result.confidence.score}/100 — ${result.confidence.level}`)
|
|
85
|
+
console.log('')
|
|
86
|
+
console.log('Output: sdd/brief.md')
|
|
87
|
+
console.log('')
|
|
88
|
+
if (result.confidence.score < 70) {
|
|
89
|
+
console.log('Tip: For higher confidence, use Claude Code with interactive mode:')
|
|
90
|
+
console.log(' claude "/sdd-bmad ' + input.substring(0, 30) + '..."')
|
|
91
|
+
}
|
|
92
|
+
console.log('')
|
|
93
|
+
console.log('Next: claude "/sdd-spec" to generate SPEC.md')
|
|
94
|
+
console.log(' (or use Claude Code for full interactive experience)')
|
|
95
|
+
break
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
case 'spec':
|
|
99
|
+
console.log('=== SDD SPEC Generation ===')
|
|
100
|
+
console.log('')
|
|
101
|
+
console.log('This command requires Claude Code for best results.')
|
|
102
|
+
console.log('')
|
|
103
|
+
console.log('Run: claude "/sdd-spec"')
|
|
104
|
+
console.log('')
|
|
105
|
+
console.log('Claude Code will:')
|
|
106
|
+
console.log(' 1. Read sdd/brief.md')
|
|
107
|
+
console.log(' 2. Validate confidence score (requires >= 20)')
|
|
108
|
+
console.log(' 3. Generate sdd/SPEC.md from template')
|
|
109
|
+
break
|
|
110
|
+
|
|
111
|
+
case 'tasks':
|
|
112
|
+
console.log('=== SDD Task Generation ===')
|
|
113
|
+
console.log('')
|
|
114
|
+
console.log('This command requires Claude Code.')
|
|
115
|
+
console.log('')
|
|
116
|
+
console.log('Run: claude "/sdd-tasks"')
|
|
117
|
+
console.log('')
|
|
118
|
+
console.log('Claude Code will:')
|
|
119
|
+
console.log(' 1. Read sdd/SPEC.md')
|
|
120
|
+
console.log(' 2. Extract features from Section 4.1')
|
|
121
|
+
console.log(' 3. Generate sdd/tasks/task-*/ directory')
|
|
122
|
+
console.log(' 4. Create MASTER-TASKS.md and T-XXX-*.md files')
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
case 'cook':
|
|
126
|
+
console.log('=== SDD Implementation ===')
|
|
127
|
+
console.log('')
|
|
128
|
+
console.log('This command requires Claude Code.')
|
|
129
|
+
console.log('')
|
|
130
|
+
console.log('Run: claude "/sdd-cook"')
|
|
131
|
+
console.log('')
|
|
132
|
+
console.log('Claude Code will:')
|
|
133
|
+
console.log(' 1. Read sdd/tasks/task-*/MASTER-TASKS.md')
|
|
134
|
+
console.log(' 2. Execute tasks sequentially')
|
|
135
|
+
console.log(' 3. Scout, implement, test, review each task')
|
|
136
|
+
console.log('')
|
|
137
|
+
console.log('Flags:')
|
|
138
|
+
console.log(' --all Execute all pending tasks')
|
|
139
|
+
console.log(' --task T-001 Execute specific task')
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
case 'converge':
|
|
143
|
+
console.log('=== SDD Converge Validation ===')
|
|
144
|
+
console.log('')
|
|
145
|
+
console.log('Full validation (requires dev server):')
|
|
146
|
+
console.log(' pwsh run-converge.ps1 -Url http://localhost:3000 -Strict')
|
|
147
|
+
console.log('')
|
|
148
|
+
console.log('Per-task validation:')
|
|
149
|
+
console.log(' pwsh run-converge.ps1 -TaskId T-001')
|
|
150
|
+
console.log('')
|
|
151
|
+
console.log('Claude Code:')
|
|
152
|
+
console.log(' claude "/sdd-converge"')
|
|
153
|
+
break
|
|
154
|
+
|
|
155
|
+
case 'status': {
|
|
156
|
+
config.printStatus()
|
|
157
|
+
break
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
case 'help':
|
|
161
|
+
default:
|
|
162
|
+
if (cmd && cmd !== 'help') {
|
|
163
|
+
console.error(`Unknown command: ${cmd}\n`)
|
|
164
|
+
}
|
|
165
|
+
console.log(`
|
|
166
|
+
sdd — Spec-Driven Development CLI
|
|
167
|
+
|
|
168
|
+
Output Structure (v1.1.0+):
|
|
169
|
+
sdd/ All generated artifacts
|
|
170
|
+
brief.md Phase 0: BMAD brief
|
|
171
|
+
SPEC.md Phase 2: Specification
|
|
172
|
+
tasks/ Phase 3: Task directories
|
|
173
|
+
converge/ Phase 5: Validation reports
|
|
174
|
+
|
|
175
|
+
Usage:
|
|
176
|
+
sdd init Initialize SDD pipeline
|
|
177
|
+
sdd bmad <desc> Phase 0: Generate brief (fast mode)
|
|
178
|
+
sdd status Show pipeline status
|
|
179
|
+
sdd help Show this help
|
|
180
|
+
|
|
181
|
+
Full Pipeline (requires Claude Code):
|
|
182
|
+
claude "/sdd-bmad" Interactive 9-question interview (high confidence)
|
|
183
|
+
claude "/sdd-spec" Generate SPEC.md
|
|
184
|
+
claude "/sdd-tasks" Generate task directory
|
|
185
|
+
claude "/sdd-cook" Execute implementation
|
|
186
|
+
claude "/sdd-converge" Validate implementation
|
|
187
|
+
|
|
188
|
+
Quick Start:
|
|
189
|
+
1. sdd init
|
|
190
|
+
2. sdd bmad "my feature idea"
|
|
191
|
+
3. claude "/sdd-spec"
|
|
192
|
+
4. claude "/sdd-tasks"
|
|
193
|
+
5. claude "/sdd-cook"
|
|
194
|
+
6. claude "/sdd-converge"
|
|
195
|
+
|
|
196
|
+
Notes:
|
|
197
|
+
- Claude Code CLI provides the best experience with interactive commands
|
|
198
|
+
- Install Claude Code: npm install -g @anthropic-ai/claude-code
|
|
199
|
+
- Without Claude Code, use "sdd bmad" for fast mode (lower confidence)
|
|
200
|
+
`)
|
|
201
|
+
}
|
package/lib/bmad/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - 9-question interview framework
|
|
8
8
|
* - 3-agent synthesis (single-pass LLM mode)
|
|
9
9
|
* - Confidence scoring
|
|
10
|
-
* -
|
|
10
|
+
* - Brief output to sdd/ directory
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
const fs = require('fs')
|
|
@@ -18,7 +18,9 @@ const problemFirst = require('./problem-first')
|
|
|
18
18
|
const synthesis = require('./synthesis')
|
|
19
19
|
const confidenceCalc = require('./confidence')
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
// Output directory - can be overridden via environment
|
|
22
|
+
const OUTPUT_BASE = process.env.SDD_OUTPUT_BASE || 'sdd'
|
|
23
|
+
const OUTPUT_FILE = path.join(OUTPUT_BASE, 'brief.md')
|
|
22
24
|
const TEMPLATE_DATE = new Date().toISOString().split('T')[0]
|
|
23
25
|
const TEMPLATE_EXPIRY = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000)
|
|
24
26
|
.toISOString()
|
|
@@ -33,6 +35,15 @@ let state = {
|
|
|
33
35
|
currentTier: 0,
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Ensure output directory exists
|
|
40
|
+
*/
|
|
41
|
+
function ensureOutputDir() {
|
|
42
|
+
if (!fs.existsSync(OUTPUT_BASE)) {
|
|
43
|
+
fs.mkdirSync(OUTPUT_BASE, { recursive: true })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
36
47
|
/**
|
|
37
48
|
* Initialize a new BMAD interview session.
|
|
38
49
|
* @param {string} rawInput - Raw user feature description
|
|
@@ -85,7 +96,7 @@ function canProceed() {
|
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
/**
|
|
88
|
-
* Generate the
|
|
99
|
+
* Generate the sdd/brief.md file.
|
|
89
100
|
* @returns {{ filePath: string, confidence: object }}
|
|
90
101
|
*/
|
|
91
102
|
function generateBrief() {
|
|
@@ -102,11 +113,16 @@ function generateBrief() {
|
|
|
102
113
|
|
|
103
114
|
const fullContent = header + brief
|
|
104
115
|
|
|
116
|
+
// Ensure output directory exists
|
|
117
|
+
ensureOutputDir()
|
|
118
|
+
|
|
119
|
+
// Write to sdd/brief.md
|
|
105
120
|
fs.writeFileSync(OUTPUT_FILE, fullContent, 'utf8')
|
|
106
121
|
|
|
107
122
|
return {
|
|
108
123
|
filePath: path.resolve(OUTPUT_FILE),
|
|
109
124
|
confidence,
|
|
125
|
+
outputDir: OUTPUT_BASE,
|
|
110
126
|
}
|
|
111
127
|
}
|
|
112
128
|
|
|
@@ -137,4 +153,5 @@ module.exports = {
|
|
|
137
153
|
getState,
|
|
138
154
|
getQuestionsWithStatus,
|
|
139
155
|
OUTPUT_FILE,
|
|
156
|
+
OUTPUT_BASE,
|
|
140
157
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# SDD Inline Check — Real-time Spec Validation
|
|
2
|
+
---
|
|
3
|
+
tool: Bash
|
|
4
|
+
when: always
|
|
5
|
+
args: <file-path> --section <spec-section>
|
|
6
|
+
description: Real-time inline validation. Check file(s) against SPEC.md clauses ([SC-xxx], [AC-xxx]). Catches missing text/colors/dimensions during implementation, not at end. Args: <file-path> [--section <spec-section>]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## SDD Check — Real-Time Inline Validation
|
|
10
|
+
|
|
11
|
+
**Purpose:** Validate current file against SPEC.md during implementation. Get instant feedback.
|
|
12
|
+
|
|
13
|
+
### Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Check specific file against SPEC.md
|
|
17
|
+
sdd check src/components/Button.tsx
|
|
18
|
+
|
|
19
|
+
# Check with specific spec section
|
|
20
|
+
sdd check src/components/Button.tsx --section 4.1.1
|
|
21
|
+
|
|
22
|
+
# Check multiple files
|
|
23
|
+
sdd check src/components/ src/utils/
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## What It Does
|
|
29
|
+
|
|
30
|
+
### 1. Extract Spec Clauses
|
|
31
|
+
Reads SPEC.md and extracts all `[SC-xxx]` clause IDs with their text.
|
|
32
|
+
|
|
33
|
+
### 2. Search Implementation
|
|
34
|
+
Searches the target file(s) for:
|
|
35
|
+
- ✅ Exact text matches
|
|
36
|
+
- ✅ Color hex values
|
|
37
|
+
- ✅ Dimension values
|
|
38
|
+
- ✅ Component patterns
|
|
39
|
+
|
|
40
|
+
### 3. Inline Report
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
╔══════════════════════════════════════════════════════════╗
|
|
44
|
+
║ SDD Check: src/components/Button.tsx ║
|
|
45
|
+
╠══════════════════════════════════════════════════════════╣
|
|
46
|
+
║ ✅ SC-001: "Start Free Trial" found at line 42 ║
|
|
47
|
+
║ ✅ SC-COLOR-001: #22c55e found ║
|
|
48
|
+
║ ❌ SC-002: "Get Started" NOT FOUND ║
|
|
49
|
+
║ → Expected at: line 45 ║
|
|
50
|
+
║ ✅ AC-001: Loading state implemented ║
|
|
51
|
+
╚══════════════════════════════════════════════════════════╝
|
|
52
|
+
|
|
53
|
+
Result: 2/3 clauses verified | 1 ISSUE
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Implementation
|
|
59
|
+
|
|
60
|
+
```powershell
|
|
61
|
+
# sdd-check.ps1
|
|
62
|
+
param(
|
|
63
|
+
[Parameter(Mandatory=$true)]
|
|
64
|
+
[string]$FilePath,
|
|
65
|
+
|
|
66
|
+
[string]$Section = "",
|
|
67
|
+
|
|
68
|
+
[string]$SpecFile = "SPEC.md"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
$ErrorActionPreference = "Continue"
|
|
72
|
+
|
|
73
|
+
# Extract clauses from SPEC.md
|
|
74
|
+
$specContent = Get-Content $SpecFile -Raw
|
|
75
|
+
$clausePattern = '\[(SC-[A-Z0-9]+-[0-9]+|SC-[0-9]+)\]'
|
|
76
|
+
$clauses = [regex]::Matches($specContent, $clausePattern) | ForEach-Object {
|
|
77
|
+
@{
|
|
78
|
+
Id = $_.Groups[1].Value
|
|
79
|
+
Text = (Get-ClauseContext -SpecFile $SpecFile -ClauseId $_.Groups[1].Value)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Read implementation file
|
|
84
|
+
$implContent = Get-Content $FilePath -Raw
|
|
85
|
+
|
|
86
|
+
# Check each clause
|
|
87
|
+
$passCount = 0
|
|
88
|
+
$failCount = 0
|
|
89
|
+
|
|
90
|
+
foreach ($clause in $clauses) {
|
|
91
|
+
$searchText = $clause.Text -replace '\[.*?\]', '' -replace '\(.*?\)', ''
|
|
92
|
+
|
|
93
|
+
if ($implContent -match [regex]::Escape($searchText)) {
|
|
94
|
+
Write-Host "✅ $($clause.Id): FOUND" -ForegroundColor Green
|
|
95
|
+
$passCount++
|
|
96
|
+
} else {
|
|
97
|
+
Write-Host "❌ $($clause.Id): NOT FOUND" -ForegroundColor Red
|
|
98
|
+
Write-Host " Expected: $searchText" -ForegroundColor Yellow
|
|
99
|
+
$failCount++
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
Write-Host ""
|
|
104
|
+
Write-Host "Result: $passCount/$($clauses.Count) clauses verified" -ForegroundColor $(if ($failCount -eq 0) { "Green" } else { "Yellow" })
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Example Workflow
|
|
110
|
+
|
|
111
|
+
### Before Implementation
|
|
112
|
+
```bash
|
|
113
|
+
sdd check src/components/Button.tsx --section 4.1.1
|
|
114
|
+
```
|
|
115
|
+
→ Shows what clauses should be in the file
|
|
116
|
+
|
|
117
|
+
### During Implementation
|
|
118
|
+
```bash
|
|
119
|
+
sdd check src/components/Button.tsx
|
|
120
|
+
```
|
|
121
|
+
→ Real-time feedback on what's missing
|
|
122
|
+
|
|
123
|
+
### After Implementation
|
|
124
|
+
```bash
|
|
125
|
+
sdd converge --task T-001
|
|
126
|
+
```
|
|
127
|
+
→ Full converge report
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## For Claude Code Agents
|
|
132
|
+
|
|
133
|
+
Add to your implementation loop:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
1. Read SPEC.md → identify relevant clauses
|
|
137
|
+
2. Implement feature
|
|
138
|
+
3. Run: sdd check [file]
|
|
139
|
+
4. Fix any ❌ issues
|
|
140
|
+
5. Run: sdd converge --task T-XXX
|
|
141
|
+
6. Proceed to next task
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Benefits
|
|
147
|
+
|
|
148
|
+
| Benefit | Description |
|
|
149
|
+
|---------|-------------|
|
|
150
|
+
| Early Detection | Catch missing clauses before converge |
|
|
151
|
+
| Faster Iterations | Don't wait until end to find issues |
|
|
152
|
+
| Clear Direction | Know exactly what's missing |
|
|
153
|
+
| Less Rework | Fix as you go, not all at once |
|