bmalph 2.6.0 → 2.7.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 -31
- package/bmad/lite/create-prd.md +145 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/check-updates.js +1 -1
- package/dist/commands/check-updates.js.map +1 -1
- package/dist/commands/doctor-checks.js +103 -0
- package/dist/commands/doctor-checks.js.map +1 -0
- package/dist/commands/doctor-health-checks.js +101 -0
- package/dist/commands/doctor-health-checks.js.map +1 -0
- package/dist/commands/doctor-runtime-checks.js +143 -0
- package/dist/commands/doctor-runtime-checks.js.map +1 -0
- package/dist/commands/doctor.js +6 -370
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/implement.js +9 -14
- package/dist/commands/implement.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/run.js +11 -2
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/status.js +4 -44
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade.js +1 -1
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/installer.js +321 -50
- package/dist/installer.js.map +1 -1
- package/dist/platform/aider.js +1 -1
- package/dist/platform/aider.js.map +1 -1
- package/dist/platform/claude-code.js +1 -1
- package/dist/platform/codex.js +3 -3
- package/dist/platform/codex.js.map +1 -1
- package/dist/platform/copilot.js +1 -1
- package/dist/platform/copilot.js.map +1 -1
- package/dist/platform/cursor.js +5 -4
- package/dist/platform/cursor.js.map +1 -1
- package/dist/platform/doctor-checks.js +16 -7
- package/dist/platform/doctor-checks.js.map +1 -1
- package/dist/platform/instructions-snippet.js +37 -38
- package/dist/platform/instructions-snippet.js.map +1 -1
- package/dist/platform/types.js +9 -1
- package/dist/platform/types.js.map +1 -1
- package/dist/platform/windsurf.js +1 -1
- package/dist/platform/windsurf.js.map +1 -1
- package/dist/reset.js +18 -7
- package/dist/reset.js.map +1 -1
- package/dist/run/ralph-process.js +16 -10
- package/dist/run/ralph-process.js.map +1 -1
- package/dist/transition/artifact-scan.js +3 -13
- package/dist/transition/artifact-scan.js.map +1 -1
- package/dist/transition/orchestration.js +16 -26
- package/dist/transition/orchestration.js.map +1 -1
- package/dist/transition/specs-index.js +4 -4
- package/dist/transition/specs-index.js.map +1 -1
- package/dist/transition/tech-stack.js +1 -1
- package/dist/transition/tech-stack.js.map +1 -1
- package/dist/utils/artifact-definitions.js +19 -0
- package/dist/utils/artifact-definitions.js.map +1 -0
- package/dist/utils/constants.js +4 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/file-system.js +1 -1
- package/dist/utils/file-system.js.map +1 -1
- package/dist/utils/format-status.js +31 -0
- package/dist/utils/format-status.js.map +1 -0
- package/dist/utils/json.js +3 -0
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/validate.js +12 -15
- package/dist/utils/validate.js.map +1 -1
- package/dist/watch/dashboard.js +22 -11
- package/dist/watch/dashboard.js.map +1 -1
- package/dist/watch/renderer.js +1 -15
- package/dist/watch/renderer.js.map +1 -1
- package/package.json +2 -2
- package/ralph/drivers/cursor.sh +90 -0
- package/ralph/ralph_loop.sh +20 -13
- package/ralph/templates/ralphrc.template +1 -1
- package/dist/platform/index.js +0 -4
- package/dist/platform/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -36,14 +36,14 @@ bmalph provides:
|
|
|
36
36
|
|
|
37
37
|
bmalph works with multiple AI coding assistants. Each platform gets BMAD planning (Phases 1-3). The Ralph autonomous loop (Phase 4) requires a CLI-based platform.
|
|
38
38
|
|
|
39
|
-
| Platform | ID | Tier | Instructions File | Commands
|
|
40
|
-
| -------------- | ------------- | ------------------- | --------------------------------- |
|
|
41
|
-
| Claude Code | `claude-code` | full | `CLAUDE.md` | `.claude/commands/` directory
|
|
42
|
-
| OpenAI Codex | `codex` | full | `AGENTS.md` |
|
|
43
|
-
| Cursor | `cursor` |
|
|
44
|
-
| Windsurf | `windsurf` | instructions-only | `.windsurf/rules/bmad.md` |
|
|
45
|
-
| GitHub Copilot | `copilot` | full (experimental) | `.github/copilot-instructions.md` |
|
|
46
|
-
| Aider | `aider` | instructions-only | `CONVENTIONS.md` |
|
|
39
|
+
| Platform | ID | Tier | Instructions File | Commands |
|
|
40
|
+
| -------------- | ------------- | ------------------- | --------------------------------- | -------------------------------- |
|
|
41
|
+
| Claude Code | `claude-code` | full | `CLAUDE.md` | `.claude/commands/` directory |
|
|
42
|
+
| OpenAI Codex | `codex` | full | `AGENTS.md` | Codex Skills (`.agents/skills/`) |
|
|
43
|
+
| Cursor | `cursor` | full (experimental) | `.cursor/rules/bmad.mdc` | `_bmad/COMMANDS.md` |
|
|
44
|
+
| Windsurf | `windsurf` | instructions-only | `.windsurf/rules/bmad.md` | `_bmad/COMMANDS.md` |
|
|
45
|
+
| GitHub Copilot | `copilot` | full (experimental) | `.github/copilot-instructions.md` | `_bmad/COMMANDS.md` |
|
|
46
|
+
| Aider | `aider` | instructions-only | `CONVENTIONS.md` | `_bmad/COMMANDS.md` |
|
|
47
47
|
|
|
48
48
|
**Tiers:**
|
|
49
49
|
|
|
@@ -55,7 +55,7 @@ bmalph works with multiple AI coding assistants. Each platform gets BMAD plannin
|
|
|
55
55
|
- Node.js 20+
|
|
56
56
|
- Bash (WSL or Git Bash on Windows)
|
|
57
57
|
- A supported AI coding platform (see table above)
|
|
58
|
-
- For Ralph loop (Phase 4): Claude Code (`claude`), Codex CLI (`codex`),
|
|
58
|
+
- For Ralph loop (Phase 4): Claude Code (`claude`), Codex CLI (`codex`), Copilot CLI (`copilot`), or Cursor CLI (`agent`) in PATH
|
|
59
59
|
|
|
60
60
|
## Installation
|
|
61
61
|
|
|
@@ -87,10 +87,10 @@ bmalph init
|
|
|
87
87
|
This installs:
|
|
88
88
|
|
|
89
89
|
- `_bmad/` — BMAD agents and workflows
|
|
90
|
-
- `.ralph/` — Ralph loop, libs, templates (drivers for claude-code, codex, and
|
|
90
|
+
- `.ralph/` — Ralph loop, libs, templates (drivers for claude-code, codex, copilot, and cursor)
|
|
91
91
|
- `bmalph/` — State management (config.json, stores selected platform)
|
|
92
92
|
- Updates the platform's instructions file with BMAD workflow instructions (e.g. `CLAUDE.md`, `AGENTS.md`, `.cursor/rules/bmad.mdc`)
|
|
93
|
-
- Installs slash commands for supported platforms (Claude Code: `.claude/commands/` directory; Codex:
|
|
93
|
+
- Installs slash commands for supported platforms (Claude Code: `.claude/commands/` directory; Codex: `.agents/skills/`; other platforms: `_bmad/COMMANDS.md` reference index)
|
|
94
94
|
|
|
95
95
|
### Migrating from standalone BMAD
|
|
96
96
|
|
|
@@ -158,7 +158,7 @@ Available in any phase for supporting tasks:
|
|
|
158
158
|
|
|
159
159
|
### Step 3: Implement with Ralph (Phase 4)
|
|
160
160
|
|
|
161
|
-
> **Note:** Ralph is only available on **full** tier platforms (Claude Code, OpenAI Codex, GitHub Copilot). Instructions-only platforms (
|
|
161
|
+
> **Note:** Ralph is only available on **full** tier platforms (Claude Code, OpenAI Codex, GitHub Copilot, Cursor). Instructions-only platforms (Windsurf, Aider) support Phases 1-3 only. GitHub Copilot and Cursor support is experimental.
|
|
162
162
|
|
|
163
163
|
Run `bmalph implement` from the terminal, or use the `/bmalph-implement` slash command in Claude Code.
|
|
164
164
|
|
|
@@ -175,7 +175,7 @@ Then start Ralph:
|
|
|
175
175
|
bmalph run
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
-
> **Advanced:** You can also run drivers directly with `bash .ralph/drivers/claude-code.sh`, `bash .ralph/drivers/codex.sh`, or `bash .ralph/drivers/
|
|
178
|
+
> **Advanced:** You can also run drivers directly with `bash .ralph/drivers/claude-code.sh`, `bash .ralph/drivers/codex.sh`, `bash .ralph/drivers/copilot.sh`, or `bash .ralph/drivers/cursor.sh`.
|
|
179
179
|
|
|
180
180
|
Ralph picks stories one by one, implements with TDD, and commits. The loop stops when all stories are done or the circuit breaker triggers.
|
|
181
181
|
|
|
@@ -270,11 +270,11 @@ BMAD (add Epic 2) → bmalph implement → Ralph sees changes + picks up Epic 2
|
|
|
270
270
|
|
|
271
271
|
### run options
|
|
272
272
|
|
|
273
|
-
| Flag | Description
|
|
274
|
-
| --------------------- |
|
|
275
|
-
| `--driver <platform>` | Override platform driver (claude-code, codex, copilot)
|
|
276
|
-
| `--interval <ms>` | Dashboard refresh interval in milliseconds (default: 2000)
|
|
277
|
-
| `--no-dashboard` | Run Ralph without the dashboard overlay
|
|
273
|
+
| Flag | Description |
|
|
274
|
+
| --------------------- | -------------------------------------------------------------- |
|
|
275
|
+
| `--driver <platform>` | Override platform driver (claude-code, codex, copilot, cursor) |
|
|
276
|
+
| `--interval <ms>` | Dashboard refresh interval in milliseconds (default: 2000) |
|
|
277
|
+
| `--no-dashboard` | Run Ralph without the dashboard overlay |
|
|
278
278
|
|
|
279
279
|
### watch options
|
|
280
280
|
|
|
@@ -289,8 +289,8 @@ BMAD (add Epic 2) → bmalph implement → Ralph sees changes + picks up Epic 2
|
|
|
289
289
|
bmalph installs 51 slash commands (45 BMAD + 6 bmalph). Command delivery varies by platform:
|
|
290
290
|
|
|
291
291
|
- **Claude Code** — installed as files in `.claude/commands/` (invoke with `/command-name`)
|
|
292
|
-
- **OpenAI Codex** —
|
|
293
|
-
- **Cursor, Windsurf, Copilot, Aider** —
|
|
292
|
+
- **OpenAI Codex** — delivered as Codex Skills in `.agents/skills/` (invoke with `$command-name`)
|
|
293
|
+
- **Cursor, Windsurf, Copilot, Aider** — discoverable via `_bmad/COMMANDS.md` reference index
|
|
294
294
|
|
|
295
295
|
Key commands (Claude Code syntax):
|
|
296
296
|
|
|
@@ -344,7 +344,7 @@ project/
|
|
|
344
344
|
│ ├── planning-artifacts/ # PRD, architecture, stories
|
|
345
345
|
│ ├── implementation-artifacts/ # Sprint plans (optional)
|
|
346
346
|
│ └── brainstorming/ # Brainstorm sessions (optional)
|
|
347
|
-
├── .ralph/ # Ralph autonomous loop (drivers for claude-code, codex, and
|
|
347
|
+
├── .ralph/ # Ralph autonomous loop (drivers for claude-code, codex, copilot, and cursor)
|
|
348
348
|
│ ├── ralph_loop.sh # Main loop script
|
|
349
349
|
│ ├── ralph_import.sh # Import requirements into Ralph
|
|
350
350
|
│ ├── ralph_monitor.sh # Monitor loop progress
|
|
@@ -353,7 +353,8 @@ project/
|
|
|
353
353
|
│ ├── drivers/ # Platform driver scripts
|
|
354
354
|
│ │ ├── claude-code.sh # Claude Code driver (uses `claude`)
|
|
355
355
|
│ │ ├── codex.sh # OpenAI Codex driver (uses `codex exec`)
|
|
356
|
-
│ │
|
|
356
|
+
│ │ ├── copilot.sh # GitHub Copilot driver (uses `copilot`, experimental)
|
|
357
|
+
│ │ └── cursor.sh # Cursor driver (uses `agent`, experimental)
|
|
357
358
|
│ ├── lib/ # Shell libraries
|
|
358
359
|
│ ├── docs/generated/ # Generated documentation
|
|
359
360
|
│ ├── specs/ # Copied from _bmad-output during transition
|
|
@@ -381,6 +382,7 @@ Ralph is a bash loop that spawns fresh AI coding sessions using a **platform dri
|
|
|
381
382
|
- **Claude Code driver** — invokes `claude` with `--allowedTools` and session resume
|
|
382
383
|
- **Codex driver** — invokes `codex exec` with `--sandbox workspace-write`
|
|
383
384
|
- **Copilot driver** _(experimental)_ — invokes `copilot --autopilot --yolo` with plain-text output
|
|
385
|
+
- **Cursor driver** _(experimental)_ — invokes `agent --print --force` with NDJSON streaming
|
|
384
386
|
|
|
385
387
|
Each iteration:
|
|
386
388
|
|
|
@@ -432,14 +434,14 @@ ls -la .ralph/
|
|
|
432
434
|
|
|
433
435
|
### Common Issues
|
|
434
436
|
|
|
435
|
-
| Scenario | Solution
|
|
436
|
-
| ----------------------------- |
|
|
437
|
-
| Commands fail before init | Run `bmalph init` first
|
|
438
|
-
| Transition finds no stories | Create stories in Phase 3 with `/create-epics-stories`
|
|
439
|
-
| Ralph stops mid-loop | Circuit breaker detected stagnation. Check `.ralph/logs/`
|
|
440
|
-
| Doctor reports version drift | Run `bmalph upgrade` to update bundled assets
|
|
441
|
-
| Wrong platform detected | Re-run `bmalph init --platform <id>` with the correct platform
|
|
442
|
-
| Ralph unavailable on platform | Ralph requires a full tier platform (claude-code, codex, or
|
|
437
|
+
| Scenario | Solution |
|
|
438
|
+
| ----------------------------- | ---------------------------------------------------------------------------- |
|
|
439
|
+
| Commands fail before init | Run `bmalph init` first |
|
|
440
|
+
| Transition finds no stories | Create stories in Phase 3 with `/create-epics-stories` |
|
|
441
|
+
| Ralph stops mid-loop | Circuit breaker detected stagnation. Check `.ralph/logs/` |
|
|
442
|
+
| Doctor reports version drift | Run `bmalph upgrade` to update bundled assets |
|
|
443
|
+
| Wrong platform detected | Re-run `bmalph init --platform <id>` with the correct platform |
|
|
444
|
+
| Ralph unavailable on platform | Ralph requires a full tier platform (claude-code, codex, copilot, or cursor) |
|
|
443
445
|
|
|
444
446
|
### Reset Installation
|
|
445
447
|
|
|
@@ -544,7 +546,7 @@ bmalph run
|
|
|
544
546
|
# 3. Reference BMAD agents by name (analyst, pm, architect)
|
|
545
547
|
# Follow phases: Analysis → Planning → Solutioning
|
|
546
548
|
|
|
547
|
-
# 4. For full tier platforms (Codex, Copilot), transition to Ralph:
|
|
549
|
+
# 4. For full tier platforms (Codex, Copilot, Cursor), transition to Ralph:
|
|
548
550
|
# Run: bmalph implement
|
|
549
551
|
# Then: bmalph run
|
|
550
552
|
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Condensed PRD Generator
|
|
2
|
+
|
|
3
|
+
> Single-prompt PRD generation for any AI platform. Combines BMAD-METHOD quality rules, project-type guidance, and domain requirements into one actionable reference.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
|
|
7
|
+
1. Read the user's product brief (or ask them to describe their product)
|
|
8
|
+
2. Detect the **project type** and **domain** from the brief using the tables below
|
|
9
|
+
3. Apply the quality rules and generate a complete PRD
|
|
10
|
+
4. The PRD should be information-dense, measurable, and traceable
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## PRD Structure (9 Required Sections)
|
|
15
|
+
|
|
16
|
+
### 1. Executive Summary
|
|
17
|
+
Vision, differentiator, target users. One paragraph max.
|
|
18
|
+
|
|
19
|
+
### 2. Success Criteria
|
|
20
|
+
Measurable outcomes using SMART criteria:
|
|
21
|
+
- **S**pecific: precisely defined
|
|
22
|
+
- **M**easurable: quantifiable with test criteria
|
|
23
|
+
- **A**ttainable: realistic within constraints
|
|
24
|
+
- **R**elevant: aligns with business objectives
|
|
25
|
+
- **T**raceable: links to source requirement
|
|
26
|
+
|
|
27
|
+
### 3. Product Scope
|
|
28
|
+
Define MVP, Growth, and Vision phases. What's in scope for each phase, what's explicitly out of scope.
|
|
29
|
+
|
|
30
|
+
### 4. User Journeys
|
|
31
|
+
Comprehensive coverage of how users interact with the product. Each journey should map to functional requirements.
|
|
32
|
+
|
|
33
|
+
### 5. Domain Requirements
|
|
34
|
+
Industry-specific compliance and regulatory requirements (if applicable). See Domain Guidance below.
|
|
35
|
+
|
|
36
|
+
### 6. Innovation Analysis
|
|
37
|
+
Competitive differentiation and novel approaches (if applicable).
|
|
38
|
+
|
|
39
|
+
### 7. Project-Type Requirements
|
|
40
|
+
Platform-specific and architecture-specific needs. See Project Type Guidance below.
|
|
41
|
+
|
|
42
|
+
### 8. Functional Requirements (FRs)
|
|
43
|
+
Capability contract. Each FR must be:
|
|
44
|
+
- A **capability**, not implementation ("Users can reset password via email" not "System sends JWT")
|
|
45
|
+
- **Measurable** with test criteria ("loads in under 2 seconds" not "fast")
|
|
46
|
+
- **Specific** with concrete quantities ("up to 100 concurrent users" not "multiple users")
|
|
47
|
+
- **Traceable** to a user journey or success criterion
|
|
48
|
+
|
|
49
|
+
**FR Anti-Patterns to Avoid:**
|
|
50
|
+
- Subjective adjectives: "easy to use", "intuitive", "user-friendly", "fast", "responsive"
|
|
51
|
+
- Implementation leakage: technology names, specific libraries, implementation details
|
|
52
|
+
- Vague quantifiers: "multiple", "several", "various"
|
|
53
|
+
- Missing test criteria: "The system shall provide notifications" (when? how fast? to whom?)
|
|
54
|
+
|
|
55
|
+
### 9. Non-Functional Requirements (NFRs)
|
|
56
|
+
Quality attributes. Each NFR must follow this template:
|
|
57
|
+
> "The system shall [metric] [condition] [measurement method]"
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
- "API response time under 200ms for 95th percentile as measured by APM monitoring"
|
|
61
|
+
- "99.9% uptime during business hours as measured by cloud provider SLA"
|
|
62
|
+
- "Support 10,000 concurrent users as measured by load testing"
|
|
63
|
+
|
|
64
|
+
**NFR Anti-Patterns to Avoid:**
|
|
65
|
+
- Unmeasurable claims: "The system shall be scalable" → specify scale target
|
|
66
|
+
- Missing context: "Response time under 1 second" → specify percentile, load conditions
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Quality Rules
|
|
71
|
+
|
|
72
|
+
### Information Density
|
|
73
|
+
Every sentence must carry information weight. Zero fluff.
|
|
74
|
+
|
|
75
|
+
**Replace:**
|
|
76
|
+
- "The system will allow users to..." → "Users can..."
|
|
77
|
+
- "It is important to note that..." → State the fact directly
|
|
78
|
+
- "In order to..." → "To..."
|
|
79
|
+
|
|
80
|
+
### Traceability Chain
|
|
81
|
+
```
|
|
82
|
+
Vision → Success Criteria → User Journeys → Functional Requirements
|
|
83
|
+
```
|
|
84
|
+
Every FR must trace back to a user need. Every success criterion must connect to the vision.
|
|
85
|
+
|
|
86
|
+
### Dual Audience
|
|
87
|
+
The PRD serves both humans (stakeholders review) and AI agents (downstream consumption for UX design, architecture, epics, and implementation). Use:
|
|
88
|
+
- Level 2 headings (`##`) for all main sections
|
|
89
|
+
- Consistent structure and patterns
|
|
90
|
+
- Precise, testable language
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Project Type Guidance
|
|
95
|
+
|
|
96
|
+
Detect the project type from the brief and apply the relevant guidance.
|
|
97
|
+
|
|
98
|
+
| Type | Detection Signals | Key Questions | Focus Sections | Skip Sections |
|
|
99
|
+
|------|------------------|---------------|----------------|---------------|
|
|
100
|
+
| API/Backend | API, REST, GraphQL, backend, service, endpoints | Endpoints needed? Auth method? Rate limits? Versioning? | Endpoint specs, auth model, data schemas, error codes, rate limits | UX/UI, visual design, user journeys |
|
|
101
|
+
| Mobile App | iOS, Android, app, mobile | Native or cross-platform? Offline needed? Push notifications? Store compliance? | Platform reqs, device permissions, offline mode, push strategy, store compliance | Desktop features, CLI commands |
|
|
102
|
+
| SaaS B2B | SaaS, B2B, platform, dashboard, teams, enterprise | Multi-tenant? Permission model? Subscription tiers? Integrations? | Tenant model, RBAC matrix, subscription tiers, integration list, compliance | CLI interface, mobile-first |
|
|
103
|
+
| Developer Tool | SDK, library, package, npm, pip, framework | Language support? Package managers? IDE integration? Documentation? | Language matrix, installation methods, API surface, code examples, migration guide | Visual design, store compliance |
|
|
104
|
+
| CLI Tool | CLI, command, terminal, bash, script | Interactive or scriptable? Output formats? Config method? | Command structure, output formats, config schema, scripting support | Visual design, UX principles |
|
|
105
|
+
| Web App | website, webapp, browser, SPA, PWA | SPA or MPA? Browser support? SEO needed? Real-time? Accessibility? | Browser matrix, responsive design, performance targets, SEO, accessibility | Native features, CLI commands |
|
|
106
|
+
| Desktop App | desktop, Windows, Mac, Linux, native | Cross-platform? Auto-update? System integration? Offline? | Platform support, system integration, update strategy, offline capabilities | Web SEO, mobile features |
|
|
107
|
+
| IoT/Embedded | IoT, embedded, device, sensor, hardware | Hardware specs? Connectivity? Power constraints? Security? OTA updates? | Hardware reqs, connectivity protocol, power profile, security model, update mechanism | Visual UI, browser support |
|
|
108
|
+
| Blockchain/Web3 | blockchain, crypto, DeFi, NFT, smart contract | Chain selection? Wallet integration? Gas optimization? Security audit? | Chain specs, wallet support, smart contracts, security audit, gas optimization | Traditional auth, centralized DB |
|
|
109
|
+
| Game | game, player, gameplay, level, character | Use the BMAD Game Module agent and workflows instead | Game brief, GDD | Most sections |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Domain Guidance
|
|
114
|
+
|
|
115
|
+
Detect the domain from the brief and ensure mandatory requirements are included.
|
|
116
|
+
|
|
117
|
+
| Domain | Signals | Complexity | Key Concerns |
|
|
118
|
+
|--------|---------|------------|--------------|
|
|
119
|
+
| Healthcare | medical, clinical, FDA, patient, HIPAA, therapy | High | FDA approval, clinical validation, HIPAA compliance, patient safety, MFA, audit logging, PHI encryption |
|
|
120
|
+
| Fintech | payment, banking, trading, KYC, AML, transaction | High | PCI-DSS Level 1, AML/KYC compliance, SOX controls, financial audit trails, fraud prevention |
|
|
121
|
+
| GovTech | government, federal, civic, public sector, citizen | High | NIST framework, Section 508 accessibility (WCAG 2.1 AA), FedRAMP, data residency, procurement rules |
|
|
122
|
+
| EdTech | education, learning, student, teacher, LMS | Medium | COPPA/FERPA student privacy, accessibility, content moderation, age verification, curriculum standards |
|
|
123
|
+
| Aerospace | aircraft, spacecraft, aviation, drone, satellite | High | DO-178C compliance, safety certification, simulation accuracy, export controls (ITAR) |
|
|
124
|
+
| Automotive | vehicle, autonomous, ADAS, automotive, EV | High | ISO 26262 functional safety, V2X communication, real-time requirements, certification |
|
|
125
|
+
| Scientific | research, algorithm, simulation, ML, AI, data science | Medium | Reproducibility, validation methodology, statistical validity, computational resources |
|
|
126
|
+
| LegalTech | legal, law, contract, compliance, litigation | High | Legal ethics, bar regulations, data retention, attorney-client privilege, court integration |
|
|
127
|
+
| InsureTech | insurance, claims, underwriting, actuarial, policy | High | Insurance regulations by state, actuarial standards, fraud detection, regulatory reporting |
|
|
128
|
+
| Energy | energy, utility, grid, solar, wind, power | High | NERC grid compliance, environmental regulations, safety requirements, SCADA systems |
|
|
129
|
+
| Process Control | industrial automation, PLC, SCADA, DCS, OT | High | IEC 62443 OT cybersecurity, functional safety, real-time control, legacy integration |
|
|
130
|
+
| Building Automation | BAS, BMS, HVAC, smart building, life safety | High | Life safety codes, building energy standards, multi-trade interoperability, commissioning |
|
|
131
|
+
| General | (no specific signals) | Low | Standard security, user experience, performance |
|
|
132
|
+
|
|
133
|
+
**Critical:** Missing domain-specific requirements in the PRD means they'll be missed in architecture and implementation. Always check the domain table and include applicable requirements.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Output Format
|
|
138
|
+
|
|
139
|
+
Generate the PRD as a markdown document with:
|
|
140
|
+
- `##` headings for each of the 9 required sections
|
|
141
|
+
- Tables where appropriate (user journeys, requirements)
|
|
142
|
+
- Specific, measurable language throughout
|
|
143
|
+
- No filler words or conversational padding
|
|
144
|
+
- Domain requirements section populated based on detected domain
|
|
145
|
+
- Project-type specific sections included/skipped per guidance
|
package/dist/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ const program = new Command();
|
|
|
17
17
|
program
|
|
18
18
|
.name("bmalph")
|
|
19
19
|
.description("BMAD-METHOD + Ralph integration — structured planning to autonomous implementation")
|
|
20
|
-
.version(getPackageVersion())
|
|
20
|
+
.version(await getPackageVersion())
|
|
21
21
|
.option("--verbose", "Enable debug logging")
|
|
22
22
|
.option("--no-color", "Disable colored output")
|
|
23
23
|
.option("--quiet", "Suppress non-essential output")
|
|
@@ -102,7 +102,7 @@ program
|
|
|
102
102
|
program
|
|
103
103
|
.command("run")
|
|
104
104
|
.description("Start Ralph loop with live dashboard")
|
|
105
|
-
.option("--driver <platform>", "Override platform driver (claude-code, codex, copilot)")
|
|
105
|
+
.option("--driver <platform>", "Override platform driver (claude-code, codex, copilot, cursor)")
|
|
106
106
|
.option("--interval <ms>", "Dashboard refresh interval in milliseconds (default: 2000)")
|
|
107
107
|
.option("--no-dashboard", "Run Ralph without the dashboard overlay")
|
|
108
108
|
.action(async (opts) => runCommand({ ...opts, projectDir: await resolveAndValidateProjectDir() }));
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,oFAAoF,CAAC;KACjG,OAAO,CAAC,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ export async function checkUpdatesCommand(options = {}) {
|
|
|
6
6
|
await withErrorHandling(() => runCheckUpdates(options));
|
|
7
7
|
}
|
|
8
8
|
async function runCheckUpdates(options) {
|
|
9
|
-
const bundled = getBundledVersions();
|
|
9
|
+
const bundled = await getBundledVersions();
|
|
10
10
|
if (!options.json) {
|
|
11
11
|
console.log(chalk.dim("Checking upstream versions...\n"));
|
|
12
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-updates.js","sourceRoot":"","sources":["../../src/commands/check-updates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EACL,aAAa,EACb,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAYvD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAA+B,EAAE;IACzE,MAAM,iBAAiB,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,OAA4B;IACzD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"check-updates.js","sourceRoot":"","sources":["../../src/commands/check-updates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EACL,aAAa,EACb,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAYvD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAA+B,EAAE;IACzE,MAAM,iBAAiB,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,OAA4B;IACzD,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAE3C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;IAE5C,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;QAEnE,MAAM,MAAM,GAAe;YACzB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU;SACX,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,wBAAwB;IACxB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACtF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,uCAAuC,MAAM,CAAC,IAAI,CAAC,UAAU,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,CAC5F,CACF,CAAC;YACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,qCAAqC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,UAAU;IACV,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1C,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAClD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readJsonFile } from "../utils/json.js";
|
|
4
|
+
import { isEnoent, formatError } from "../utils/errors.js";
|
|
5
|
+
import { CONFIG_FILE } from "../utils/constants.js";
|
|
6
|
+
export async function checkCommandAvailable(command) {
|
|
7
|
+
const { execFileSync } = await import("node:child_process");
|
|
8
|
+
try {
|
|
9
|
+
const bin = process.platform === "win32" ? "where" : "which";
|
|
10
|
+
execFileSync(bin, [command], { stdio: "ignore" });
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export async function checkNodeVersion(_projectDir) {
|
|
18
|
+
const major = parseInt(process.versions.node.split(".")[0]);
|
|
19
|
+
return {
|
|
20
|
+
label: "Node version >= 20",
|
|
21
|
+
passed: major >= 20,
|
|
22
|
+
detail: major >= 20 ? `v${process.versions.node}` : `got v${process.versions.node}`,
|
|
23
|
+
hint: major >= 20 ? undefined : "Install Node.js 20+ from nodejs.org or run: nvm install 20",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export async function checkBash(_projectDir) {
|
|
27
|
+
const available = await checkCommandAvailable("bash");
|
|
28
|
+
return {
|
|
29
|
+
label: "bash available",
|
|
30
|
+
passed: available,
|
|
31
|
+
detail: available ? undefined : "bash not found in PATH",
|
|
32
|
+
hint: available
|
|
33
|
+
? undefined
|
|
34
|
+
: process.platform === "win32"
|
|
35
|
+
? "Install Git Bash or WSL: https://git-scm.com/downloads"
|
|
36
|
+
: "Install bash via your package manager (apt, brew, etc.)",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function checkJq(_projectDir) {
|
|
40
|
+
const available = await checkCommandAvailable("jq");
|
|
41
|
+
return {
|
|
42
|
+
label: "jq available",
|
|
43
|
+
passed: available,
|
|
44
|
+
detail: available ? undefined : "jq not found in PATH",
|
|
45
|
+
hint: available
|
|
46
|
+
? undefined
|
|
47
|
+
: process.platform === "win32"
|
|
48
|
+
? "Install jq: choco install jq (or: winget install jqlang.jq)"
|
|
49
|
+
: process.platform === "darwin"
|
|
50
|
+
? "Install jq: brew install jq"
|
|
51
|
+
: "Install jq: sudo apt-get install jq",
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export async function checkBmadDir(projectDir) {
|
|
55
|
+
return checkDir(join(projectDir, "_bmad"), "_bmad/ directory present", "Run: bmalph init");
|
|
56
|
+
}
|
|
57
|
+
export async function checkRalphLoop(projectDir) {
|
|
58
|
+
return checkFileHasContent(join(projectDir, ".ralph/ralph_loop.sh"), "ralph_loop.sh present and has content", "Run: bmalph upgrade");
|
|
59
|
+
}
|
|
60
|
+
export async function checkRalphLib(projectDir) {
|
|
61
|
+
return checkDir(join(projectDir, ".ralph/lib"), ".ralph/lib/ directory present", "Run: bmalph upgrade");
|
|
62
|
+
}
|
|
63
|
+
export async function checkConfig(projectDir) {
|
|
64
|
+
const label = "bmalph/config.json exists and valid";
|
|
65
|
+
const hint = "Run: bmalph init";
|
|
66
|
+
const path = join(projectDir, CONFIG_FILE);
|
|
67
|
+
try {
|
|
68
|
+
const data = await readJsonFile(path);
|
|
69
|
+
if (data === null) {
|
|
70
|
+
return { label, passed: false, detail: "file not found", hint };
|
|
71
|
+
}
|
|
72
|
+
return { label, passed: true };
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const msg = err instanceof Error ? err.message : "invalid";
|
|
76
|
+
return { label, passed: false, detail: msg, hint };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export async function checkDir(dirPath, label, hint) {
|
|
80
|
+
try {
|
|
81
|
+
const s = await stat(dirPath);
|
|
82
|
+
return { label, passed: s.isDirectory() };
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
if (isEnoent(err)) {
|
|
86
|
+
return { label, passed: false, detail: "not found", hint };
|
|
87
|
+
}
|
|
88
|
+
return { label, passed: false, detail: `error: ${formatError(err)}`, hint };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export async function checkFileHasContent(filePath, label, hint) {
|
|
92
|
+
try {
|
|
93
|
+
const content = await readFile(filePath, "utf-8");
|
|
94
|
+
return { label, passed: content.trim().length > 0 };
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (isEnoent(err)) {
|
|
98
|
+
return { label, passed: false, detail: "not found", hint };
|
|
99
|
+
}
|
|
100
|
+
return { label, passed: false, detail: `error: ${formatError(err)}`, hint };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=doctor-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-checks.js","sourceRoot":"","sources":["../../src/commands/doctor-checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readConfig } from "../utils/config.js";
|
|
4
|
+
import { parseGitignoreLines } from "../utils/file-system.js";
|
|
5
|
+
import { getBundledVersions } from "../installer.js";
|
|
6
|
+
import { isEnoent, formatError } from "../utils/errors.js";
|
|
7
|
+
export async function checkGitignore(projectDir) {
|
|
8
|
+
const label = ".gitignore has required entries";
|
|
9
|
+
const required = [".ralph/logs/", "_bmad-output/"];
|
|
10
|
+
try {
|
|
11
|
+
const content = await readFile(join(projectDir, ".gitignore"), "utf-8");
|
|
12
|
+
const existingLines = parseGitignoreLines(content);
|
|
13
|
+
const missing = required.filter((e) => !existingLines.has(e));
|
|
14
|
+
if (missing.length === 0) {
|
|
15
|
+
return { label, passed: true };
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
label,
|
|
19
|
+
passed: false,
|
|
20
|
+
detail: `missing: ${missing.join(", ")}`,
|
|
21
|
+
hint: `Add to .gitignore: ${missing.join(" ")}`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (isEnoent(err)) {
|
|
26
|
+
return {
|
|
27
|
+
label,
|
|
28
|
+
passed: false,
|
|
29
|
+
detail: ".gitignore not found",
|
|
30
|
+
hint: "Create .gitignore with: .ralph/logs/ _bmad-output/",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
label,
|
|
35
|
+
passed: false,
|
|
36
|
+
detail: `error: ${formatError(err)}`,
|
|
37
|
+
hint: "Check file permissions on .gitignore",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function checkVersionMarker(projectDir) {
|
|
42
|
+
const label = "version marker matches";
|
|
43
|
+
const hint = "Run: bmalph upgrade";
|
|
44
|
+
try {
|
|
45
|
+
const content = await readFile(join(projectDir, ".ralph/ralph_loop.sh"), "utf-8");
|
|
46
|
+
const match = content.match(/# bmalph-version: (.+)/);
|
|
47
|
+
if (!match) {
|
|
48
|
+
return { label, passed: true, detail: "no marker (pre-0.8.0 install)" };
|
|
49
|
+
}
|
|
50
|
+
const { getPackageVersion } = await import("../installer.js");
|
|
51
|
+
const current = await getPackageVersion();
|
|
52
|
+
if (match[1].trim() === current) {
|
|
53
|
+
return { label, passed: true, detail: `v${current}` };
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
label,
|
|
57
|
+
passed: false,
|
|
58
|
+
detail: `installed: ${match[1].trim()}, current: ${current}`,
|
|
59
|
+
hint,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
if (isEnoent(err)) {
|
|
64
|
+
return { label, passed: true, detail: "no marker found" };
|
|
65
|
+
}
|
|
66
|
+
return { label, passed: false, detail: `error: ${formatError(err)}`, hint };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export async function checkUpstreamVersions(projectDir) {
|
|
70
|
+
const label = "upstream versions tracked";
|
|
71
|
+
const hint = "Run: bmalph upgrade";
|
|
72
|
+
try {
|
|
73
|
+
const config = await readConfig(projectDir);
|
|
74
|
+
if (!config) {
|
|
75
|
+
return { label, passed: false, detail: "config not found", hint: "Run: bmalph init" };
|
|
76
|
+
}
|
|
77
|
+
if (!config.upstreamVersions) {
|
|
78
|
+
return { label, passed: true, detail: "not tracked (pre-1.2.0 install)" };
|
|
79
|
+
}
|
|
80
|
+
const bundled = await getBundledVersions();
|
|
81
|
+
const { bmadCommit } = config.upstreamVersions;
|
|
82
|
+
const bmadMatch = bmadCommit === bundled.bmadCommit;
|
|
83
|
+
if (bmadMatch) {
|
|
84
|
+
return {
|
|
85
|
+
label,
|
|
86
|
+
passed: true,
|
|
87
|
+
detail: `BMAD:${bmadCommit.slice(0, 8)}`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
label,
|
|
92
|
+
passed: false,
|
|
93
|
+
detail: `outdated: BMAD:${bmadCommit.slice(0, 8)}→${bundled.bmadCommit.slice(0, 8)}`,
|
|
94
|
+
hint,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
return { label, passed: false, detail: `error: ${formatError(err)}`, hint };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=doctor-health-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-health-checks.js","sourceRoot":"","sources":["../../src/commands/doctor-health-checks.ts"],"names":[],"mappings":"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"}
|