sdd-pipeline 1.0.1 → 1.1.0

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.
Files changed (41) hide show
  1. package/README.md +341 -58
  2. package/bin/sdd.js +14 -6
  3. package/lib/bmad/agents/architect.js +96 -0
  4. package/lib/bmad/agents/pm.js +67 -0
  5. package/lib/bmad/agents/ux.js +103 -0
  6. package/lib/bmad/confidence.js +129 -0
  7. package/lib/bmad/index.js +140 -0
  8. package/lib/bmad/problem-first.js +85 -0
  9. package/lib/bmad/questions.js +110 -0
  10. package/lib/bmad/synthesis.js +109 -0
  11. package/lib/bmad.js +54 -0
  12. package/lib/bundle/.claude/commands/sdd-bmad.md +360 -20
  13. package/lib/bundle/.claude/commands/sdd-converge.md +21 -7
  14. package/lib/bundle/.claude/commands/sdd-cook.md +335 -0
  15. package/lib/bundle/.claude/commands/sdd-init.md +71 -13
  16. package/lib/bundle/.claude/commands/sdd-spec.md +103 -35
  17. package/lib/bundle/.claude/commands/sdd-task-status.md +95 -0
  18. package/lib/bundle/.claude/commands/sdd-tasks.md +100 -17
  19. package/lib/bundle/.claude/commands/sdd.md +48 -8
  20. package/lib/bundle/.sdd/config.json +2 -2
  21. package/lib/bundle/CLAUDE.md +6 -4
  22. package/lib/bundle/commands/sdd-status.ps1 +40 -6
  23. package/lib/bundle/commands/sdd-task-status.ps1 +78 -0
  24. package/lib/bundle/run-converge.ps1 +84 -23
  25. package/lib/bundle/skills/sdd-cook/SKILL.md +236 -0
  26. package/lib/bundle/skills/sdd-cook/references/subagent-prompts.md +346 -0
  27. package/lib/bundle/skills/sdd-cook/references/task-execution.md +238 -0
  28. package/lib/bundle/templates/BMAD-brief.template.md +75 -14
  29. package/lib/bundle/templates/SPEC.template.md +193 -20
  30. package/lib/bundle/templates/TASKS.template.md +32 -13
  31. package/lib/bundle/templates/task-detail.template.md +40 -0
  32. package/lib/bundle/templates/task-master.template.md +41 -0
  33. package/lib/config.js +35 -0
  34. package/lib/converge-task.ps1 +260 -0
  35. package/lib/init.js +128 -0
  36. package/lib/output-dirs.ps1 +461 -0
  37. package/lib/sanitize.js +10 -0
  38. package/lib/sdd-check.ps1 +130 -0
  39. package/lib/shared-converge.ps1 +270 -0
  40. package/lib/verify-patterns.ps1 +208 -0
  41. package/package.json +3 -2
package/README.md CHANGED
@@ -1,95 +1,378 @@
1
- # XDM Method — SDD Pipeline for Claude Code
1
+ # XDM Method — Spec-Driven Development Pipeline
2
2
 
3
- Spec-Driven Development pipeline that transforms raw feature requests into validated, shipped code through a self-correcting converge loop.
3
+ **Spec-Driven Development pipeline for Claude Code CLI.** Transforms raw feature requests into validated, shipped code through a self-correcting converge loop.
4
4
 
5
5
  ## Quick Start
6
6
 
7
7
  ```powershell
8
- # Install globally (once)
8
+ # 1. Install globally (once)
9
9
  npm install -g sdd-pipeline
10
10
 
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
11
+ # 2. Navigate to your project
12
+ cd my-project
13
+
14
+ # 3. Initialize pipeline
15
+ sdd init
16
+
17
+ # 4. Start with a feature
18
+ sdd bmad "landing page for my SaaS"
19
+
20
+ # 5. Use Claude Code for full pipeline
21
+ /sdd spec # Generate SPEC.md
22
+ /sdd tasks # Generate tasks
23
+ /ck:cook # Implement tasks
24
+
25
+ # 6. Validate
26
+ pwsh run-converge.ps1 -Url 'http://localhost:3000' -Strict
15
27
  ```
16
28
 
17
- ## Unified Command
29
+ ---
18
30
 
19
- Use `/sdd` in Claude Code for the full pipeline:
31
+ ## Output Directory Structure
32
+
33
+ All generated artifacts are organized in the `sdd/` directory:
34
+
35
+ ```
36
+ project/
37
+ ├── sdd/ # All generated artifacts
38
+ │ ├── brief.md # Phase 0: BMAD brief
39
+ │ ├── SPEC.md # Phase 2: Specification
40
+ │ ├── tasks/ # Phase 3: Task directories
41
+ │ │ └── task-260829-1700-feature/
42
+ │ │ ├── MASTER-TASKS.md
43
+ │ │ └── T-001-*.md
44
+ │ └── converge/ # Phase 5: Validation reports
45
+ │ ├── validation.md # Full project converge
46
+ │ └── task-T-001/
47
+ │ └── report.md # Per-task converge
48
+ ├── .sdd/config.json # Pipeline state & config
49
+ ├── templates/ # SDD templates
50
+ └── .claude/commands/ # Claude Code commands
51
+ ```
52
+
53
+ **Key features:**
54
+ - All artifacts in one place (`sdd/`)
55
+ - Easy cleanup: delete `sdd/` to reset
56
+ - Legacy files auto-migrated on first use
57
+ - Configurable via `.sdd/config.json`
58
+
59
+ ---
60
+
61
+ ## Pipeline Phases
62
+
63
+ ```
64
+ Raw Idea
65
+
66
+ ├── /sdd bmad → sdd/brief.md (Phase 0)
67
+ ├── /sdd spec → sdd/SPEC.md (Phase 2)
68
+ ├── /sdd tasks → sdd/tasks/ (Phase 3)
69
+ ├── /ck:cook → Implementation (Phase 4)
70
+
71
+ └── /sdd converge → sdd/converge/ (Phase 5)
72
+
73
+ ├── PASS → Merge / Deploy
74
+ └── FAIL → Fix → Re-enter
75
+ ```
76
+
77
+ | Phase | Command | Output | Gate |
78
+ |-------|---------|--------|------|
79
+ | 0 | `/sdd bmad <desc>` | `sdd/brief.md` | None |
80
+ | 2 | `/sdd spec` | `sdd/SPEC.md` | Requires `sdd/brief.md` + confidence ≥20 |
81
+ | 3 | `/sdd tasks` | `sdd/tasks/task-*/` | Requires `sdd/SPEC.md` |
82
+ | 4 | `/ck:cook` | Code | Requires task files |
83
+ | 5 | `pwsh run-converge.ps1` | `sdd/converge/` | All phases |
84
+
85
+ ---
86
+
87
+ ## Commands Reference
88
+
89
+ ### Core Pipeline Commands
90
+
91
+ | Command | Phase | Output | Description |
92
+ |---------|-------|--------|-------------|
93
+ | `/sdd init` | — | `.sdd/`, `templates/`, `sdd/` | Initialize SDD pipeline. Creates directory structure. Run once per project. |
94
+ | `/sdd bmad <desc>` | 0 | `sdd/brief.md` | Interactive brainstorm. Asks 9 discovery questions, generates confidence-scored brief. |
95
+ | `/sdd spec` | 2 | `sdd/SPEC.md` | Generate SPEC.md from brief. Validates confidence ≥20/100 + expiry check. |
96
+ | `/sdd tasks` | 3 | `sdd/tasks/task-*/` | Break SPEC.md into tasks (≤2 hours each). Creates MASTER-TASKS.md + T-XXX-*.md files. |
97
+ | `/sdd cook` | 4 | — | Execute tasks sequentially. Args: `[--all \| --task T-XXX]`. |
98
+ | `/sdd converge` | 5 | `sdd/converge/` | Validate implementation. Self-correcting loop. Args: `[--task <task-id>]`. |
99
+
100
+ ### Utility Commands
101
+
102
+ | Command | Description |
103
+ |---------|-------------|
104
+ | `/sdd status` | Show pipeline phase status. Displays current phase, completed phases, next command. |
105
+ | `/sdd check <file>` | Real-time validation. Check file(s) against SPEC.md clauses ([SC-xxx], [AC-xxx]). |
106
+ | `/sdd task-status T-XXX <status>` | Update task status. Args: `pending \| in-progress \| completed`. |
107
+
108
+ ### Shell CLI (npm global)
20
109
 
21
110
  ```powershell
22
- claude "/sdd init"
23
- claude "/sdd bmad landing page for my SaaS"
111
+ sdd init # Same as /sdd init
112
+ sdd bmad <desc> # Same as /sdd bmad
113
+ sdd status # Same as /sdd status
114
+ sdd help # Show help
115
+
116
+ # Full pipeline requires Claude Code
24
117
  claude "/sdd spec"
25
118
  claude "/sdd tasks"
26
- claude "/sdd converge"
27
- claude "/sdd status"
119
+ pwsh run-converge.ps1 -Strict
28
120
  ```
29
121
 
30
- ## Pipeline Phases
122
+ ---
31
123
 
32
- | Phase | Command | Output |
33
- |-------|---------|--------|
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 |
124
+ ## Usage Examples
38
125
 
39
- Individual commands also available: `/sdd-bmad`, `/sdd-spec`, `/sdd-tasks`, `/sdd-converge`.
126
+ ### Example 1: Landing Page
40
127
 
41
- ## Key Features
128
+ ```powershell
129
+ cd my-saas-project
42
130
 
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
47
- - **GitHub Actions CI:** Runs converge on push/PR, creates Issue on failure
48
- - **Domain extensions:** API, frontend, backend — set via `.sdd/config.json`
131
+ # Initialize
132
+ sdd init
49
133
 
50
- ## Status
134
+ # Start with feature description
135
+ sdd bmad "landing page for my SaaS product"
136
+
137
+ # Claude Code generates spec
138
+ /sdd spec
139
+
140
+ # Break into tasks
141
+ /sdd tasks
142
+
143
+ # Implement each task
144
+ /sdd cook --task T-001
145
+ /sdd cook --task T-002
146
+ /sdd cook --task T-003
147
+
148
+ # Validate (with dev server running)
149
+ /sdd converge
150
+ ```
151
+
152
+ ### Example 2: API Feature
51
153
 
52
154
  ```powershell
53
- sdd status # Quick status (npm package)
54
- pwsh commands/sdd-status.ps1 --Verify # Full verification
155
+ cd my-api-project
156
+ sdd init
157
+
158
+ # Set domain to API
159
+ # Edit .sdd/config.json: set project.domain = "api"
160
+
161
+ sdd bmad "user authentication with JWT tokens"
162
+
163
+ # /sdd spec now includes OpenAPI validation sections
164
+ /sdd spec
165
+ /sdd tasks
166
+ /ck:cook --all
55
167
  ```
56
168
 
57
- ## Architecture
169
+ ### Example 3: Real-Time Validation
170
+
171
+ ```powershell
172
+ # During implementation, check your work
173
+ /sdd check src/components/Button.tsx
174
+
175
+ # Result:
176
+ # ✅ SC-001: "Start Free Trial" found
177
+ # ✅ SC-COLOR-001: #22c55e found
178
+ # ❌ SC-002: "Get Started" NOT FOUND
58
179
 
180
+ # Fix the issue, then continue
181
+ /sdd cook --task T-002
59
182
  ```
60
- Raw Idea -> /sdd bmad -> BMAD-brief.md
61
- -> /sdd spec -> SPEC.md
62
- -> /sdd tasks -> TASKS.md
63
- -> Implement
64
- -> /sdd converge
65
- -> pwsh run-converge.ps1 -> converge/validation.md
66
- |
67
- +-- PASS: merge
68
- +-- FAIL: fix -> re-enter
183
+
184
+ ---
185
+
186
+ ## Phase Gates
187
+
188
+ Phase gates enforce deliberate progress. Commands fail if prerequisites are missing:
189
+
190
+ | Command | Gate | If Missing |
191
+ |---------|------|------------|
192
+ | `/sdd spec` | BMAD-brief.md | ERROR: Phase 0 not complete. Run `/sdd bmad` first. |
193
+ | `/sdd spec` | Confidence ≥20 | WARNING: Confidence is Weak. Spec may be incomplete. |
194
+ | `/sdd tasks` | SPEC.md | ERROR: SPEC.md not found. Run `/sdd spec` first. |
195
+ | `/sdd converge` | All artifacts | ERROR: Missing artifacts. Run full pipeline first. |
196
+
197
+ ---
198
+
199
+ ## BMAD Confidence Score
200
+
201
+ BMAD calculates a 0-100 confidence score before generating SPEC.md:
202
+
203
+ | Score | Level | Action |
204
+ |-------|-------|--------|
205
+ | <20 | None | `/sdd spec` BLOCKED. Re-run BMAD with more detail. |
206
+ | 20-49 | Weak | WARNING. Proceed with caution — spec may need iteration. |
207
+ | 50-69 | Medium | Acceptable. Answer more questions for better spec. |
208
+ | ≥70 | Strong | Full confidence. Proceed to spec. |
209
+
210
+ **Scoring factors:**
211
+ - Input quality (0-30 pts) — more detail = higher score
212
+ - Interview completion (0-30 pts) — more answers = higher score
213
+ - Problem clarity (0-20 pts) — specific, measurable = higher score
214
+ - Technical awareness (0-20 pts) — stack/integration detail = higher score
215
+
216
+ ---
217
+
218
+ ## Task Format
219
+
220
+ Each task in MASTER-TASKS.md:
221
+ - Takes ≤2 hours
222
+ - Independently verifiable
223
+ - Has frontmatter with `depends_on`, `spec_sections`
224
+
225
+ ```
226
+ task-260829-1657-landing-page/
227
+ ├── MASTER-TASKS.md # Task index, phases, status
228
+ ├── T-001-html-structure.md
229
+ ├── T-002-mobile-css.md
230
+ ├── T-003-desktop-css.md
231
+ └── ...
69
232
  ```
70
233
 
71
- ## Files
234
+ ---
235
+
236
+ ## Extension System
237
+
238
+ Domain-specific templates activate via `.sdd/config.json`:
239
+
240
+ ```json
241
+ {
242
+ "project": {
243
+ "domain": "frontend"
244
+ }
245
+ }
246
+ ```
247
+
248
+ | Domain | Adds |
249
+ |--------|------|
250
+ | `general` | Base pipeline only |
251
+ | `api` | OpenAPI spec, endpoint validation, API checklist |
252
+ | `frontend` | Design system prompts, Lighthouse targets, UX checklist |
253
+ | `backend` | Data models, security requirements, backend checklist |
254
+
255
+ Extensions are **additive** — base pipeline always works.
72
256
 
73
- | Path | Purpose |
74
- |------|---------|
75
- | `.sdd/config.json` | Pipeline state, template versions |
76
- | `templates/` | SDD artifact templates |
77
- | `.claude/commands/` | Claude Code slash commands |
78
- | `run-converge.ps1` | Converge validation script |
79
- | `.github/workflows/converge.yml` | CI/CD pipeline |
80
- | `extensions/` | Domain-specific extensions |
257
+ ---
81
258
 
82
- ## Extensions
259
+ ## Security
83
260
 
84
- Enable via `.sdd/config.json` `project.domain`:
85
- - `api` — OpenAPI spec, endpoint validation
86
- - `frontend` design system, Lighthouse targets
87
- - `backend`data models, security requirements
261
+ | Layer | Protection |
262
+ |-------|-----------|
263
+ | Input | Sanitize regex blocks prompt injection patterns |
264
+ | URL | SSRF prevention blocks private IPs, localhost |
265
+ | npm | `--ignore-scripts` on global installs |
266
+ | GitHub Actions | Least-privilege permissions block |
267
+
268
+ ---
269
+
270
+ ## Architecture
271
+
272
+ ```
273
+ Two Interfaces (same logic):
274
+
275
+ Shell CLI: sdd bmad "feature" → bin/sdd.js
276
+ Claude Code: /sdd bmad "feature" → .claude/commands/sdd.md
277
+
278
+ Pipeline files:
279
+ ├── .sdd/config.json # Phase tracking, template versions
280
+ ├── templates/ # SDD artifact templates
281
+ ├── .claude/commands/ # Claude Code slash commands
282
+ ├── commands/ # Standalone CLI scripts
283
+ ├── run-converge.ps1 # Converge automation
284
+ └── extensions/ # Domain-specific (api/frontend/backend)
285
+
286
+ npm package (sdd-pipeline):
287
+ ├── bin/sdd.js # CLI entry
288
+ ├── lib/init.js # Extract pipeline
289
+ ├── lib/bmad/ # BMAD orchestrator (8 modules)
290
+ └── lib/bundle/ # 31 pipeline files for distribution
291
+ ```
292
+
293
+ ---
88
294
 
89
295
  ## Requirements
90
296
 
91
297
  - Windows 11 + PowerShell (primary), Bash (fallback)
92
- - Git, Node.js, npm
93
- - Claude Code CLI
298
+ - Git 2.52+
299
+ - Node.js 18+ + npm 9+
300
+ - Claude Code CLI (`npx @anthropic-ai/claude-code`)
301
+
302
+ ## CI/CD
303
+
304
+ GitHub Actions workflow runs converge on push/PR:
305
+
306
+ ```yaml
307
+ on: [push, pull_request]
308
+ jobs:
309
+ converge:
310
+ runs-on: windows-latest
311
+ steps:
312
+ - uses: actions/checkout@v4
313
+ - run: pwsh run-converge.ps1 -Url '${{ env.DEV_URL }}' -Strict
314
+ ```
315
+
316
+ On failure: artifacts uploaded + GitHub Issue created with fix recommendations.
317
+
318
+ ---
319
+
320
+ ## File Structure
321
+
322
+ ```
323
+ project/
324
+ ├── .sdd/config.json # Pipeline state
325
+ ├── BMAD-brief.md # Phase 0 output
326
+ ├── SPEC.md # Phase 2 output
327
+ ├── task-*/ # Phase 3 output
328
+ │ ├── MASTER-TASKS.md
329
+ │ └── T-XXX-*.md
330
+ ├── converge/ # Phase 5 output
331
+ │ └── validation.md
332
+ └── .claude/commands/ # SDD commands
333
+ ```
334
+
335
+ ## Status
336
+
337
+ ```powershell
338
+ sdd status # Quick status (npm package)
339
+ pwsh commands/sdd-status.ps1 --Verify # Full verification
340
+ ```
341
+
342
+ ---
343
+
344
+ ## npm Package
345
+
346
+ | Field | Value |
347
+ |-------|-------|
348
+ | Name | `sdd-pipeline` |
349
+ | Version | `1.0.2` |
350
+ | Registry | npmjs.com |
351
+ | CLI command | `sdd` |
352
+ | Claude Code command | `/sdd` |
353
+ | Install | `npm install -g sdd-pipeline` |
354
+
355
+ ---
356
+
357
+ ## Key Features
358
+
359
+ - **Phase gates** — `/sdd spec` fails if BMAD-brief.md missing — no bypass
360
+ - **Confidence scoring** — BMAD quantifies spec readiness before implementation
361
+ - **Problem-first** — Solution→problem inversion surfaces actual user needs
362
+ - **Self-correcting converge** — Loop back to appropriate phase on failure
363
+ - **Domain extensions** — API, frontend, backend — set via config
364
+ - **SSRF protection** — URL validation blocks private IPs, localhost
365
+ - **GitHub Actions CI** — Runs converge on push/PR, creates Issue on failure
366
+
367
+ ---
368
+
369
+ ## Documentation
94
370
 
95
- See [docs/spec-pipeline-synthesis.md](docs/spec-pipeline-synthesis.md) for full pipeline specification.
371
+ | Document | Purpose |
372
+ |----------|---------|
373
+ | `docs/project-overview-pdr.md` | Project overview, problem statement, solution |
374
+ | `docs/system-architecture.md` | System architecture, component map, CI/CD flow |
375
+ | `docs/spec-pipeline-synthesis.md` | Full pipeline specification (1,200+ lines) |
376
+ | `docs/codebase-summary.md` | Codebase overview, file inventory, key contracts |
377
+ | `docs/deployment-guide.md` | Deployment instructions |
378
+ | `docs/project-roadmap.md` | Future plans |
package/bin/sdd.js CHANGED
@@ -37,15 +37,23 @@ switch (cmd) {
37
37
  console.log(`
38
38
  sdd — Spec-Driven Development CLI
39
39
 
40
+ Output Structure:
41
+ sdd/ # All generated artifacts
42
+ brief.md # Phase 0: BMAD brief
43
+ SPEC.md # Phase 2: Specification
44
+ tasks/ # Phase 3: Task directories
45
+ converge/ # Phase 5: Validation reports
46
+
40
47
  Usage:
41
- sdd init Initialize SDD pipeline in current directory
42
- sdd bmad <description> Generate BMAD brief
43
- sdd status Show pipeline phase status
48
+ sdd init Initialize SDD pipeline
49
+ sdd bmad <desc> Phase 0: Interactive brainstorm
50
+ sdd status Show pipeline status
44
51
  sdd help Show this help
45
52
 
46
53
  Full pipeline (requires Claude Code):
47
- claude "/sdd-spec" Generate SPEC.md
48
- claude "/sdd-tasks" Generate TASKS.md
49
- pwsh run-converge.ps1 Run converge validation
54
+ claude "/sdd-spec" Phase 2: Generate SPEC.md
55
+ claude "/sdd-tasks" Phase 3: Generate tasks
56
+ claude "/sdd-cook" Phase 4: Execute tasks
57
+ pwsh run-converge.ps1 Phase 5: Validate
50
58
  `)
51
59
  }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * BMAD Architect Agent — Technical Architect perspective
3
+ * Analyzes from a feasibility, risk, and technical constraints lens.
4
+ */
5
+
6
+ /**
7
+ * @param {object} state - BMAD interview state
8
+ * @returns {{ section: string, confidence: string }}
9
+ */
10
+ function analyze(state) {
11
+ const input = state.input || ''
12
+ const answers = state.answers || {}
13
+
14
+ // Architect key questions: q4, q5, q6
15
+ const q4 = answers.q4 || ''
16
+ const q5 = answers.q5 || ''
17
+ const q6 = answers.q6 || ''
18
+
19
+ const mvp = q4 || inferMvp(input)
20
+ const risks = parseRisks(q6)
21
+ const integrations = parseIntegrations(q5)
22
+
23
+ const section = `## Architect Perspective
24
+ **Minimum viable approach:** ${mvp}
25
+
26
+ **Required integrations:** ${integrations}
27
+
28
+ **Technical risks:**
29
+ | Risk | Likelihood | Impact | Mitigation |
30
+ |------|-----------|--------|------------|
31
+ ${risks}
32
+
33
+ **Tech constraints:**
34
+ - ${inferConstraints(input)}
35
+
36
+ **Done criteria (technical):** ${inferDoneCriteria(input, mvp)}
37
+ `
38
+
39
+ const confidence = inferConfidence(q4, q5, q6)
40
+ return { section, confidence }
41
+ }
42
+
43
+ function inferMvp(input) {
44
+ if (!input) return '[one paragraph — what is the simplest thing that works?]'
45
+ return `Deliver: ${input.trim()}. No optional features in v1.`
46
+ }
47
+
48
+ function parseRisks(q6) {
49
+ if (!q6 || q6.trim().length < 10) {
50
+ return '| [Risk 1] | [H/M/L] | [H/M/L] | [Mitigation] |\n| [Risk 2] | [H/M/L] | [H/M/L] | [Mitigation] |'
51
+ }
52
+ // Best-effort parse — user provides structured answer or free text
53
+ const lines = q6.split('\n').filter((l) => l.trim())
54
+ if (lines.length >= 2) {
55
+ return lines
56
+ .slice(0, 3)
57
+ .map((line) => {
58
+ const parts = line.split(/[,;]/).map((p) => p.trim())
59
+ return `| ${parts[0] || 'Risk'} | ${parts[1] || 'M'} | ${parts[2] || 'M'} | ${parts.slice(3).join(', ') || 'TBD'} |`
60
+ })
61
+ .join('\n')
62
+ }
63
+ const risk1 = q6.split(/[.,\n]/)[0].trim() || 'Risk'
64
+ return `| ${risk1} | M | M | [Provide mitigation] |\n| [Risk 2] | [H/M/L] | [H/M/L] | [Mitigation] |`
65
+ }
66
+
67
+ function parseIntegrations(q5) {
68
+ if (!q5 || q5.trim().length < 5) return '[from Q5 — list required integrations or "None for MVP"]'
69
+ return q5.split(/[,;\n]/).filter((i) => i.trim()).slice(0, 5).join(', ')
70
+ }
71
+
72
+ function inferConstraints(input) {
73
+ const lower = (input || '').toLowerCase()
74
+ if (lower.includes('frontend') || lower.includes('website') || lower.includes('landing page'))
75
+ return 'Performance budget: Lighthouse ≥90, mobile-first CSS, no layout shift'
76
+ if (lower.includes('api') || lower.includes('backend') || lower.includes('service'))
77
+ return 'API: REST preferred, versioned endpoints, error responses must be structured'
78
+ if (lower.includes('mobile') || lower.includes('ios') || lower.includes('android'))
79
+ return 'Native build targets: latest OS version, accessibility support required'
80
+ return 'Technology choices constrained by existing project stack — do not introduce new dependencies without approval'
81
+ }
82
+
83
+ function inferDoneCriteria(input, mvp) {
84
+ if (!mvp) return '[define what "done" looks like technically — measurable conditions]'
85
+ return `MVP (${mvp.slice(0, 50)}...) is functional, tested, and meets non-functional requirements`
86
+ }
87
+
88
+ function inferConfidence(q4, q5, q6) {
89
+ const filled = [q4, q5, q6].filter((a) => a.trim().length > 10).length
90
+ if (filled >= 3) return 'High'
91
+ if (filled >= 2) return 'Medium'
92
+ if (filled >= 1) return 'Low'
93
+ return 'None'
94
+ }
95
+
96
+ module.exports = { analyze }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * BMAD PM Agent — Product Manager perspective
3
+ * Analyzes user input and interview answers from a PM lens.
4
+ */
5
+
6
+ /**
7
+ * @param {object} state - BMAD interview state (input, answers, inversion)
8
+ * @returns {{ section: string, confidence: string }}
9
+ */
10
+ function analyze(state) {
11
+ const input = state.input || ''
12
+ const answers = state.answers || {}
13
+ const inversion = state.inversion || {}
14
+
15
+ // PM key questions: q1, q2, q3
16
+ const q1 = answers.q1 || inversion.problem || ''
17
+ const q2 = answers.q2 || ''
18
+ const q3 = answers.q3 || ''
19
+
20
+ // Synthesize PM perspective
21
+ const targetUser = q2.split(/[,.\n]/)[0].trim() || '[from Q2 — who is the user?]'
22
+ const primaryAction = inferPrimaryAction(input, q1)
23
+ const topNeeds = extractNeeds(q1, q3)
24
+
25
+ const section = `## PM Perspective
26
+ **Target user:** ${targetUser}
27
+ **User needs:** ${topNeeds}
28
+ **Primary conversion action:** ${primaryAction}
29
+ **Success metric (90-day):** ${q3 || '[from Q3 — what measurable outcome?]'}
30
+
31
+ **Problem framing:** ${q1 || '[from Q1 — the problem being solved]'}
32
+ `
33
+
34
+ const confidence = inferConfidence(q1, q2, q3)
35
+ return { section, confidence }
36
+ }
37
+
38
+ function inferPrimaryAction(input, q1) {
39
+ const lower = (input + ' ' + q1).toLowerCase()
40
+ if (lower.includes('signup') || lower.includes('register') || lower.includes('sign up'))
41
+ return 'Sign up / create account'
42
+ if (lower.includes('purchase') || lower.includes('buy') || lower.includes('checkout'))
43
+ return 'Complete purchase'
44
+ if (lower.includes('download')) return 'Download content or file'
45
+ if (lower.includes('subscribe')) return 'Subscribe to plan'
46
+ if (lower.includes('contact') || lower.includes('demo')) return 'Request demo or contact'
47
+ if (lower.includes('share') || lower.includes('invite')) return 'Share or invite'
48
+ return '[to be determined — what does the user do that matters to business?]'
49
+ }
50
+
51
+ function extractNeeds(q1, q3) {
52
+ if (!q1) return '[List top 3 needs this feature addresses]'
53
+ // Extract first 3 sentences or items
54
+ const sentences = q1.split(/[.\n]/).filter((s) => s.trim().length > 5).slice(0, 3)
55
+ if (sentences.length === 0) return '[List top 3 needs this feature addresses]'
56
+ return sentences.map((s) => `• ${s.trim()}`).join('\n')
57
+ }
58
+
59
+ function inferConfidence(q1, q2, q3) {
60
+ const filled = [q1, q2, q3].filter((a) => a.trim().length > 10).length
61
+ if (filled >= 3) return 'High'
62
+ if (filled >= 2) return 'Medium'
63
+ if (filled >= 1) return 'Low'
64
+ return 'None'
65
+ }
66
+
67
+ module.exports = { analyze }