bmalph 2.3.0 → 2.5.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 (61) hide show
  1. package/README.md +105 -38
  2. package/dist/cli.js +19 -0
  3. package/dist/commands/doctor.d.ts +0 -11
  4. package/dist/commands/doctor.js +22 -55
  5. package/dist/commands/implement.d.ts +6 -0
  6. package/dist/commands/implement.js +82 -0
  7. package/dist/commands/init.js +4 -2
  8. package/dist/commands/reset.d.ts +7 -0
  9. package/dist/commands/reset.js +81 -0
  10. package/dist/commands/status.js +100 -11
  11. package/dist/commands/watch.d.ts +6 -0
  12. package/dist/commands/watch.js +19 -0
  13. package/dist/installer.d.ts +0 -6
  14. package/dist/installer.js +0 -10
  15. package/dist/platform/claude-code.js +0 -1
  16. package/dist/reset.d.ts +18 -0
  17. package/dist/reset.js +181 -0
  18. package/dist/transition/artifact-scan.d.ts +27 -0
  19. package/dist/transition/artifact-scan.js +91 -0
  20. package/dist/transition/artifacts.d.ts +0 -1
  21. package/dist/transition/artifacts.js +0 -26
  22. package/dist/transition/context.js +34 -0
  23. package/dist/transition/fix-plan.d.ts +8 -2
  24. package/dist/transition/fix-plan.js +33 -7
  25. package/dist/transition/index.d.ts +1 -1
  26. package/dist/transition/index.js +1 -1
  27. package/dist/transition/orchestration.d.ts +2 -2
  28. package/dist/transition/orchestration.js +120 -41
  29. package/dist/transition/preflight.d.ts +6 -0
  30. package/dist/transition/preflight.js +154 -0
  31. package/dist/transition/specs-index.d.ts +1 -1
  32. package/dist/transition/specs-index.js +24 -1
  33. package/dist/transition/types.d.ts +23 -1
  34. package/dist/utils/dryrun.d.ts +1 -1
  35. package/dist/utils/dryrun.js +22 -0
  36. package/dist/utils/state.d.ts +0 -2
  37. package/dist/utils/validate.js +3 -2
  38. package/dist/watch/dashboard.d.ts +4 -0
  39. package/dist/watch/dashboard.js +60 -0
  40. package/dist/watch/file-watcher.d.ts +9 -0
  41. package/dist/watch/file-watcher.js +27 -0
  42. package/dist/watch/renderer.d.ts +16 -0
  43. package/dist/watch/renderer.js +241 -0
  44. package/dist/watch/state-reader.d.ts +9 -0
  45. package/dist/watch/state-reader.js +190 -0
  46. package/dist/watch/types.d.ts +55 -0
  47. package/dist/watch/types.js +1 -0
  48. package/package.json +9 -4
  49. package/ralph/lib/circuit_breaker.sh +86 -59
  50. package/ralph/lib/enable_core.sh +3 -6
  51. package/ralph/lib/response_analyzer.sh +5 -29
  52. package/ralph/lib/task_sources.sh +45 -11
  53. package/ralph/lib/wizard_utils.sh +9 -0
  54. package/ralph/ralph_import.sh +7 -2
  55. package/ralph/ralph_loop.sh +44 -34
  56. package/ralph/ralph_monitor.sh +4 -0
  57. package/slash-commands/bmalph-doctor.md +16 -0
  58. package/slash-commands/bmalph-implement.md +18 -141
  59. package/slash-commands/bmalph-status.md +15 -0
  60. package/slash-commands/bmalph-upgrade.md +15 -0
  61. package/slash-commands/bmalph-watch.md +20 -0
package/README.md CHANGED
@@ -25,7 +25,11 @@ bmalph provides:
25
25
  - `bmalph init` — Install both systems
26
26
  - `bmalph upgrade` — Update to latest versions
27
27
  - `bmalph doctor` — Check installation health
28
- - `/bmalph-implement` — Transition from BMAD to Ralph
28
+ - `bmalph implement` — Transition from BMAD to Ralph
29
+ - `bmalph check-updates` — Check for upstream updates
30
+ - `bmalph status` — Show project status and phase
31
+ - `bmalph reset` — Remove all bmalph files
32
+ - `bmalph watch` — Live Ralph loop dashboard
29
33
 
30
34
  ## Supported Platforms
31
35
 
@@ -155,7 +159,7 @@ Available in any phase for supporting tasks:
155
159
 
156
160
  > **Note:** Ralph is only available on **full** tier platforms (Claude Code, OpenAI Codex). Instructions-only platforms (Cursor, Windsurf, Copilot, Aider) support Phases 1-3 only.
157
161
 
158
- Use the `/bmalph-implement` slash command in Claude Code, or run the transition from the BMAD agents in Codex.
162
+ Run `bmalph implement` from the terminal, or use the `/bmalph-implement` slash command in Claude Code.
159
163
 
160
164
  This transitions your BMAD artifacts into Ralph's format:
161
165
 
@@ -164,10 +168,14 @@ This transitions your BMAD artifacts into Ralph's format:
164
168
  3. Copies specs to `.ralph/specs/` with changelog tracking
165
169
  4. Instructs you to start the Ralph autonomous loop
166
170
 
167
- Then start Ralph:
171
+ Then start Ralph using the driver for your platform:
168
172
 
169
173
  ```bash
170
- bash .ralph/ralph_loop.sh
174
+ # Claude Code
175
+ bash .ralph/drivers/claude-code.sh
176
+
177
+ # OpenAI Codex
178
+ bash .ralph/drivers/codex.sh
171
179
  ```
172
180
 
173
181
  Ralph picks stories one by one, implements with TDD, and commits. The loop stops when all stories are done or the circuit breaker triggers.
@@ -177,12 +185,12 @@ Ralph picks stories one by one, implements with TDD, and commits. The loop stops
177
185
  bmalph supports iterative development cycles:
178
186
 
179
187
  ```
180
- BMAD (Epic 1) → /bmalph-implement → Ralph works on Epic 1
188
+ BMAD (Epic 1) → bmalph implement → Ralph works on Epic 1
181
189
 
182
- BMAD (add Epic 2) → /bmalph-implement → Ralph sees changes + picks up Epic 2
190
+ BMAD (add Epic 2) → bmalph implement → Ralph sees changes + picks up Epic 2
183
191
  ```
184
192
 
185
- **Smart Merge**: When you run `/bmalph-implement` again after Ralph has made progress:
193
+ **Smart Merge**: When you run `bmalph implement` again after Ralph has made progress:
186
194
 
187
195
  - Completed stories (`[x]`) are preserved in the new fix_plan
188
196
  - New stories from BMAD are added as pending (`[ ]`)
@@ -198,6 +206,9 @@ BMAD (add Epic 2) → /bmalph-implement → Ralph sees changes + picks up Epic 2
198
206
  | `bmalph doctor` | Check installation health |
199
207
  | `bmalph check-updates` | Check if bundled BMAD/Ralph versions are up to date |
200
208
  | `bmalph status` | Show current project status and phase |
209
+ | `bmalph implement` | Transition BMAD planning artifacts to Ralph format |
210
+ | `bmalph reset` | Remove all bmalph files from the project |
211
+ | `bmalph watch` | Live dashboard showing Ralph loop status |
201
212
 
202
213
  ### Global options
203
214
 
@@ -217,6 +228,31 @@ BMAD (add Epic 2) → /bmalph-implement → Ralph sees changes + picks up Epic 2
217
228
  | `-n, --name <name>` | Project name | directory name |
218
229
  | `-d, --description <desc>` | Project description | (prompted) |
219
230
  | `--platform <id>` | Target platform (`claude-code`, `codex`, `cursor`, `windsurf`, `copilot`, `aider`) | auto-detect |
231
+ | `--dry-run` | Preview changes without writing files | |
232
+
233
+ ### implement options
234
+
235
+ | Flag | Description |
236
+ | --------- | ------------------------------------- |
237
+ | `--force` | Override pre-flight validation errors |
238
+
239
+ ### check-updates options
240
+
241
+ | Flag | Description |
242
+ | -------- | -------------- |
243
+ | `--json` | Output as JSON |
244
+
245
+ ### doctor options
246
+
247
+ | Flag | Description |
248
+ | -------- | -------------- |
249
+ | `--json` | Output as JSON |
250
+
251
+ ### status options
252
+
253
+ | Flag | Description |
254
+ | -------- | -------------- |
255
+ | `--json` | Output as JSON |
220
256
 
221
257
  ### upgrade options
222
258
 
@@ -225,9 +261,22 @@ BMAD (add Epic 2) → /bmalph-implement → Ralph sees changes + picks up Epic 2
225
261
  | `--force` | Skip confirmation prompts |
226
262
  | `--dry-run` | Preview changes |
227
263
 
264
+ ### reset options
265
+
266
+ | Flag | Description |
267
+ | ----------- | ------------------------ |
268
+ | `--dry-run` | Preview changes |
269
+ | `--force` | Skip confirmation prompt |
270
+
271
+ ### watch options
272
+
273
+ | Flag | Description |
274
+ | ----------------- | ------------------------------------------------ |
275
+ | `--interval <ms>` | Refresh interval in milliseconds (default: 2000) |
276
+
228
277
  ## Slash Commands
229
278
 
230
- bmalph installs 47 BMAD slash commands. Command delivery varies by platform:
279
+ bmalph installs 51 slash commands (45 BMAD + 6 bmalph). Command delivery varies by platform:
231
280
 
232
281
  - **Claude Code** — installed as files in `.claude/commands/` (invoke with `/command-name`)
233
282
  - **OpenAI Codex** — inlined in `AGENTS.md` (reference agents by name)
@@ -256,7 +305,7 @@ For full list, run `/bmad-help` in Claude Code.
256
305
 
257
306
  ### Transition to Ralph
258
307
 
259
- Use `/bmalph-implement` to transition from BMAD planning to Ralph implementation.
308
+ Use `bmalph implement` (or `/bmalph-implement` in Claude Code) to transition from BMAD planning to Ralph implementation.
260
309
 
261
310
  ## Project Structure (after init)
262
311
 
@@ -264,15 +313,23 @@ Use `/bmalph-implement` to transition from BMAD planning to Ralph implementation
264
313
  project/
265
314
  ├── _bmad/ # BMAD agents, workflows, core
266
315
  │ ├── _config/ # Generated configuration
267
- │ │ └── config.yaml # Platform config
316
+ │ │ ├── config.yaml # Platform config
317
+ │ │ ├── task-manifest.csv # Combined task manifest
318
+ │ │ ├── workflow-manifest.csv # Combined workflow manifest
319
+ │ │ └── bmad-help.csv # Combined help manifest
268
320
  │ ├── core/
269
321
  │ │ ├── agents/ # Master agent
270
322
  │ │ ├── tasks/ # Workflow tasks
271
- │ │ └── workflows/ # Brainstorming, party-mode, etc.
323
+ │ │ ├── workflows/ # Brainstorming, party-mode, etc.
324
+ │ │ ├── module.yaml # Core module metadata
325
+ │ │ └── module-help.csv # Core module help entries
272
326
  │ └── bmm/
273
327
  │ ├── agents/ # Analyst, PM, Architect, Dev, QA, etc.
328
+ │ ├── data/ # Templates (project-context-template.md)
274
329
  │ ├── workflows/ # Phase 1-4 workflows
275
- └── teams/ # Agent team definitions
330
+ ├── teams/ # Agent team definitions
331
+ │ ├── module.yaml # BMM module metadata
332
+ │ └── module-help.csv # BMM module help entries
276
333
  ├── _bmad-output/ # BMAD planning artifacts (generated)
277
334
  │ ├── planning-artifacts/ # PRD, architecture, stories
278
335
  │ ├── implementation-artifacts/ # Sprint plans (optional)
@@ -286,14 +343,16 @@ project/
286
343
  │ ├── drivers/ # Platform driver scripts
287
344
  │ │ ├── claude-code.sh # Claude Code driver (uses `claude`)
288
345
  │ │ └── codex.sh # OpenAI Codex driver (uses `codex exec`)
289
- │ ├── lib/ # Circuit breaker, response analyzer
346
+ │ ├── lib/ # Shell libraries
347
+ │ ├── docs/generated/ # Generated documentation
290
348
  │ ├── specs/ # Copied from _bmad-output during transition
291
349
  │ ├── logs/ # Loop execution logs
292
350
  │ ├── PROMPT.md # Iteration prompt template
293
- │ ├── PROJECT_CONTEXT.md # Extracted project context (after /bmalph-implement)
294
- │ ├── SPECS_CHANGELOG.md # Spec diff since last run (after /bmalph-implement)
351
+ │ ├── PROJECT_CONTEXT.md # Extracted project context (after bmalph implement)
352
+ │ ├── SPECS_CHANGELOG.md # Spec diff since last run (after bmalph implement)
353
+ │ ├── SPECS_INDEX.md # Prioritized spec file index (after bmalph implement)
295
354
  │ ├── @AGENT.md # Agent build instructions
296
- │ └── @fix_plan.md # Generated task list (after /bmalph-implement)
355
+ │ └── @fix_plan.md # Generated task list (after bmalph implement)
297
356
  ├── bmalph/ # State management
298
357
  │ ├── config.json # Project config (name, description, platform)
299
358
  │ └── state/ # Phase tracking data
@@ -352,8 +411,8 @@ wsl --install
352
411
  If you get permission errors:
353
412
 
354
413
  ```bash
355
- # Unix/Mac: Make ralph_loop.sh executable
356
- chmod +x .ralph/ralph_loop.sh
414
+ # Unix/Mac: Make driver scripts executable
415
+ chmod +x .ralph/drivers/*.sh
357
416
 
358
417
  # Check file ownership
359
418
  ls -la .ralph/
@@ -372,25 +431,33 @@ ls -la .ralph/
372
431
 
373
432
  ### Reset Installation
374
433
 
375
- If something goes wrong, you can manually reset:
434
+ The simplest way to remove all bmalph files:
376
435
 
377
436
  ```bash
378
- # Remove bmalph directories (preserves your project code)
379
- rm -rf _bmad .ralph bmalph
380
-
381
- # Also remove platform-specific files:
382
- # Claude Code: rm -rf .claude/commands/ and remove bmalph section from CLAUDE.md
383
- # Codex: remove bmalph sections from AGENTS.md
384
- # Cursor: rm .cursor/rules/bmad.mdc
385
- # Windsurf: rm .windsurf/rules/bmad.md
386
- # Copilot: remove bmalph sections from .github/copilot-instructions.md
387
- # Aider: remove bmalph sections from CONVENTIONS.md
388
- # See the Supported Platforms table for your platform's files.
389
-
390
- # Reinitialize
391
- bmalph init
437
+ bmalph reset
392
438
  ```
393
439
 
440
+ Use `--dry-run` to preview what will be removed, or `--force` to skip confirmation.
441
+
442
+ #### Manual removal
443
+
444
+ If the CLI is unavailable, remove these directories and files manually:
445
+
446
+ ```bash
447
+ rm -rf _bmad/ .ralph/ bmalph/
448
+ ```
449
+
450
+ Then remove the bmalph-managed sections from your instructions file. The file depends on your platform:
451
+
452
+ - **Claude Code** — remove `.claude/commands/` and bmalph section from `CLAUDE.md`
453
+ - **Codex** — remove bmalph sections from `AGENTS.md`
454
+ - **Cursor** — remove `.cursor/rules/bmad.mdc`
455
+ - **Windsurf** — remove `.windsurf/rules/bmad.md`
456
+ - **Copilot** — remove bmalph sections from `.github/copilot-instructions.md`
457
+ - **Aider** — remove bmalph sections from `CONVENTIONS.md`
458
+
459
+ See the [Supported Platforms](#supported-platforms) table for details. After manual removal, run `bmalph init` to reinitialize.
460
+
394
461
  ## Quick Examples
395
462
 
396
463
  ### Initialize a new project
@@ -448,10 +515,10 @@ claude
448
515
  # Phase 3: /architect → create architecture and stories
449
516
 
450
517
  # 4. Transition to Ralph
451
- # Use /bmalph-implement to generate @fix_plan.md
518
+ # Run: bmalph implement
452
519
 
453
520
  # 5. Start autonomous implementation
454
- bash .ralph/ralph_loop.sh
521
+ bash .ralph/drivers/claude-code.sh
455
522
  ```
456
523
 
457
524
  **Other platforms:**
@@ -465,9 +532,9 @@ bash .ralph/ralph_loop.sh
465
532
  # 3. Reference BMAD agents by name (analyst, pm, architect)
466
533
  # Follow phases: Analysis → Planning → Solutioning
467
534
 
468
- # 4. For full tier platforms (Codex), transition via BMAD agents
469
- # then start Ralph:
470
- bash .ralph/ralph_loop.sh
535
+ # 4. For full tier platforms (Codex), transition to Ralph:
536
+ # Run: bmalph implement
537
+ bash .ralph/drivers/codex.sh
471
538
  ```
472
539
 
473
540
  ## Contributing
package/dist/cli.js CHANGED
@@ -6,6 +6,9 @@ import { upgradeCommand } from "./commands/upgrade.js";
6
6
  import { doctorCommand } from "./commands/doctor.js";
7
7
  import { checkUpdatesCommand } from "./commands/check-updates.js";
8
8
  import { statusCommand } from "./commands/status.js";
9
+ import { implementCommand } from "./commands/implement.js";
10
+ import { resetCommand } from "./commands/reset.js";
11
+ import { watchCommand } from "./commands/watch.js";
9
12
  import { setVerbose, setQuiet } from "./utils/logger.js";
10
13
  import { getPackageVersion } from "./installer.js";
11
14
  import { isEnoent } from "./utils/errors.js";
@@ -79,4 +82,20 @@ program
79
82
  .description("Show current project status and phase")
80
83
  .option("--json", "Output as JSON")
81
84
  .action(async (opts) => statusCommand({ ...opts, projectDir: await resolveAndValidateProjectDir() }));
85
+ program
86
+ .command("implement")
87
+ .description("Transition BMAD planning artifacts to Ralph implementation format")
88
+ .option("--force", "Override pre-flight validation errors")
89
+ .action(async (opts) => implementCommand({ ...opts, projectDir: await resolveAndValidateProjectDir() }));
90
+ program
91
+ .command("reset")
92
+ .description("Remove all bmalph files from the project")
93
+ .option("--dry-run", "Preview changes without removing files")
94
+ .option("--force", "Skip confirmation prompt")
95
+ .action(async (opts) => resetCommand({ ...opts, projectDir: await resolveAndValidateProjectDir() }));
96
+ program
97
+ .command("watch")
98
+ .description("Live dashboard showing Ralph loop status, circuit breaker, and activity")
99
+ .option("--interval <ms>", "Refresh interval in milliseconds (default: 2000)")
100
+ .action(async (opts) => watchCommand({ ...opts, projectDir: await resolveAndValidateProjectDir() }));
82
101
  void program.parseAsync();
@@ -37,15 +37,4 @@ export declare function runDoctor(options: DoctorOptions): Promise<DoctorResult>
37
37
  * Core checks + platform doctor checks + trailing checks.
38
38
  */
39
39
  export declare function buildCheckRegistry(platform: Platform): CheckDefinition[];
40
- /**
41
- * Static registry for backward compatibility with existing tests.
42
- * Uses claude-code platform checks (slash-command + claude-md).
43
- *
44
- * Note: The check ids here ("slash-command", "claude-md") intentionally differ
45
- * from the live buildCheckRegistry path which uses platform-provided ids
46
- * ("instructions-file"). This is for test backward compatibility only.
47
- *
48
- * @deprecated Use `buildCheckRegistry(platform)` for platform-aware checks.
49
- */
50
- export declare const CHECK_REGISTRY: CheckDefinition[];
51
40
  export {};
@@ -1,6 +1,5 @@
1
1
  import chalk from "chalk";
2
2
  import { readFile, stat } from "fs/promises";
3
- import { exists } from "../utils/file-system.js";
4
3
  import { join } from "path";
5
4
  import { readJsonFile } from "../utils/json.js";
6
5
  import { readConfig } from "../utils/config.js";
@@ -64,10 +63,10 @@ export async function runDoctor(options) {
64
63
  }
65
64
  return { passed, failed };
66
65
  }
67
- async function checkBashAvailable() {
66
+ async function checkCommandAvailable(command) {
68
67
  const { execSync } = await import("child_process");
69
68
  try {
70
- const cmd = process.platform === "win32" ? "where bash" : "which bash";
69
+ const cmd = process.platform === "win32" ? `where ${command}` : `which ${command}`;
71
70
  execSync(cmd, { stdio: "ignore" });
72
71
  return true;
73
72
  }
@@ -88,18 +87,33 @@ async function checkNodeVersion(_projectDir) {
88
87
  };
89
88
  }
90
89
  async function checkBash(_projectDir) {
91
- const bashAvailable = await checkBashAvailable();
90
+ const available = await checkCommandAvailable("bash");
92
91
  return {
93
92
  label: "bash available",
94
- passed: bashAvailable,
95
- detail: bashAvailable ? undefined : "bash not found in PATH",
96
- hint: bashAvailable
93
+ passed: available,
94
+ detail: available ? undefined : "bash not found in PATH",
95
+ hint: available
97
96
  ? undefined
98
97
  : process.platform === "win32"
99
98
  ? "Install Git Bash or WSL: https://git-scm.com/downloads"
100
99
  : "Install bash via your package manager (apt, brew, etc.)",
101
100
  };
102
101
  }
102
+ async function checkJq(_projectDir) {
103
+ const available = await checkCommandAvailable("jq");
104
+ return {
105
+ label: "jq available",
106
+ passed: available,
107
+ detail: available ? undefined : "jq not found in PATH",
108
+ hint: available
109
+ ? undefined
110
+ : process.platform === "win32"
111
+ ? "Install jq: choco install jq (or: winget install jqlang.jq)"
112
+ : process.platform === "darwin"
113
+ ? "Install jq: brew install jq"
114
+ : "Install jq: sudo apt-get install jq",
115
+ };
116
+ }
103
117
  async function checkBmadDir(projectDir) {
104
118
  return checkDir(join(projectDir, "_bmad"), "_bmad/ directory present", "Run: bmalph init");
105
119
  }
@@ -399,6 +413,7 @@ async function checkUpstreamGitHubStatus(_projectDir) {
399
413
  const CORE_CHECKS = [
400
414
  { id: "node-version", run: checkNodeVersion },
401
415
  { id: "bash-available", run: checkBash },
416
+ { id: "jq-available", run: checkJq },
402
417
  { id: "config-valid", run: checkConfig },
403
418
  { id: "bmad-dir", run: checkBmadDir },
404
419
  { id: "ralph-loop", run: checkRalphLoop },
@@ -435,51 +450,3 @@ export function buildCheckRegistry(platform) {
435
450
  }));
436
451
  return [...CORE_CHECKS, ...platformChecks, ...TRAILING_CHECKS];
437
452
  }
438
- /**
439
- * Static registry for backward compatibility with existing tests.
440
- * Uses claude-code platform checks (slash-command + claude-md).
441
- *
442
- * Note: The check ids here ("slash-command", "claude-md") intentionally differ
443
- * from the live buildCheckRegistry path which uses platform-provided ids
444
- * ("instructions-file"). This is for test backward compatibility only.
445
- *
446
- * @deprecated Use `buildCheckRegistry(platform)` for platform-aware checks.
447
- */
448
- export const CHECK_REGISTRY = (() => {
449
- // Inline claude-code platform checks to avoid async import at module level
450
- const slashCommandCheck = {
451
- id: "slash-command",
452
- run: async (projectDir) => {
453
- if (await exists(join(projectDir, ".claude/commands/bmalph.md"))) {
454
- return { label: ".claude/commands/bmalph.md present", passed: true };
455
- }
456
- return {
457
- label: ".claude/commands/bmalph.md present",
458
- passed: false,
459
- detail: "not found",
460
- hint: "Run: bmalph init",
461
- };
462
- },
463
- };
464
- const claudeMdCheck = {
465
- id: "claude-md",
466
- run: async (projectDir) => {
467
- const label = "CLAUDE.md contains BMAD snippet";
468
- const hint = "Run: bmalph init";
469
- try {
470
- const content = await readFile(join(projectDir, "CLAUDE.md"), "utf-8");
471
- if (content.includes("BMAD-METHOD Integration")) {
472
- return { label, passed: true };
473
- }
474
- return { label, passed: false, detail: "missing BMAD-METHOD Integration section", hint };
475
- }
476
- catch (err) {
477
- if (isEnoent(err)) {
478
- return { label, passed: false, detail: "CLAUDE.md not found", hint };
479
- }
480
- return { label, passed: false, detail: `error: ${formatError(err)}`, hint };
481
- }
482
- },
483
- };
484
- return [...CORE_CHECKS, slashCommandCheck, claudeMdCheck, ...TRAILING_CHECKS];
485
- })();
@@ -0,0 +1,6 @@
1
+ interface ImplementOptions {
2
+ force?: boolean;
3
+ projectDir: string;
4
+ }
5
+ export declare function implementCommand(options: ImplementOptions): Promise<void>;
6
+ export {};
@@ -0,0 +1,82 @@
1
+ import chalk from "chalk";
2
+ import { access } from "fs/promises";
3
+ import { join } from "path";
4
+ import { runTransition } from "../transition/orchestration.js";
5
+ import { withErrorHandling } from "../utils/errors.js";
6
+ import { resolveProjectPlatform } from "../platform/resolve.js";
7
+ export async function implementCommand(options) {
8
+ await withErrorHandling(() => runImplement(options));
9
+ }
10
+ async function runImplement(options) {
11
+ const { projectDir, force } = options;
12
+ // Re-run protection: warn if implement was already run
13
+ try {
14
+ await access(join(projectDir, ".ralph/@fix_plan.md"));
15
+ if (!force) {
16
+ console.log(chalk.yellow("Warning: bmalph implement has already been run."));
17
+ console.log("Re-running will overwrite PROMPT.md, PROJECT_CONTEXT.md, @AGENT.md, and SPECS_INDEX.md.");
18
+ console.log("Fix plan progress will be preserved.\n");
19
+ console.log(`Use ${chalk.bold("--force")} to proceed anyway.`);
20
+ process.exitCode = 1;
21
+ return;
22
+ }
23
+ }
24
+ catch {
25
+ // fix_plan doesn't exist — first run, proceed
26
+ }
27
+ const platform = await resolveProjectPlatform(projectDir);
28
+ const result = await runTransition(projectDir, { force });
29
+ // Print preflight issues with severity icons
30
+ if (result.preflightIssues && result.preflightIssues.length > 0) {
31
+ console.log(chalk.bold("\nPre-flight checks\n"));
32
+ for (const issue of result.preflightIssues) {
33
+ console.log(` ${severityIcon(issue)} ${issue.message}`);
34
+ if (issue.suggestion) {
35
+ console.log(chalk.dim(` ${issue.suggestion}`));
36
+ }
37
+ }
38
+ console.log("");
39
+ }
40
+ // Print warnings
41
+ if (result.warnings.length > 0) {
42
+ for (const warning of result.warnings) {
43
+ console.log(chalk.yellow(` ! ${warning}`));
44
+ }
45
+ console.log("");
46
+ }
47
+ // Generated files summary
48
+ if (result.generatedFiles.length > 0) {
49
+ console.log(chalk.bold("\nGenerated files\n"));
50
+ for (const file of result.generatedFiles) {
51
+ const icon = file.action === "created" ? chalk.green("+") : chalk.cyan("~");
52
+ console.log(` ${icon} ${file.path}`);
53
+ }
54
+ console.log("");
55
+ }
56
+ // Summary
57
+ const preserved = result.fixPlanPreserved ? chalk.dim(" (progress preserved)") : "";
58
+ console.log(chalk.green(`Transition complete: ${result.storiesCount} stories`) + preserved);
59
+ if (result.warnings.length > 0) {
60
+ console.log(chalk.yellow(` ${result.warnings.length} warning(s)`));
61
+ }
62
+ // Driver instructions
63
+ console.log("");
64
+ if (platform.tier === "full") {
65
+ console.log(`Start the Ralph loop:\n`);
66
+ console.log(` bash .ralph/drivers/${platform.id}.sh`);
67
+ }
68
+ else {
69
+ console.log(`Ralph requires a full-tier platform (claude-code or codex). ` +
70
+ `Current platform: ${platform.displayName}`);
71
+ }
72
+ }
73
+ function severityIcon(issue) {
74
+ switch (issue.severity) {
75
+ case "error":
76
+ return chalk.red("\u2717");
77
+ case "warning":
78
+ return chalk.yellow("!");
79
+ case "info":
80
+ return chalk.dim("i");
81
+ }
82
+ }
@@ -1,10 +1,12 @@
1
1
  import chalk from "chalk";
2
2
  import inquirer from "inquirer";
3
3
  import { writeConfig } from "../utils/config.js";
4
- import { installProject, mergeInstructionsFile, isInitialized, hasExistingBmadDir, previewInstall, getBundledVersions, } from "../installer.js";
4
+ import { installProject, mergeInstructionsFile, isInitialized, previewInstall, getBundledVersions, } from "../installer.js";
5
5
  import { formatDryRunSummary } from "../utils/dryrun.js";
6
6
  import { validateProjectName } from "../utils/validate.js";
7
7
  import { withErrorHandling } from "../utils/errors.js";
8
+ import { exists } from "../utils/file-system.js";
9
+ import { join } from "path";
8
10
  import { isPlatformId, getPlatform } from "../platform/registry.js";
9
11
  import { detectPlatform } from "../platform/detect.js";
10
12
  export async function initCommand(options) {
@@ -62,7 +64,7 @@ async function runInit(options) {
62
64
  console.log("Use 'bmalph upgrade' to update bundled assets to the latest version.");
63
65
  return;
64
66
  }
65
- if (await hasExistingBmadDir(projectDir)) {
67
+ if (await exists(join(projectDir, "_bmad"))) {
66
68
  console.log(chalk.cyan("Existing BMAD installation detected."));
67
69
  console.log("Framework files in _bmad/ will be replaced with the managed version.");
68
70
  console.log("Planning artifacts in _bmad-output/ will not be modified.\n");
@@ -0,0 +1,7 @@
1
+ interface ResetOptions {
2
+ dryRun?: boolean;
3
+ force?: boolean;
4
+ projectDir: string;
5
+ }
6
+ export declare function resetCommand(options: ResetOptions): Promise<void>;
7
+ export {};
@@ -0,0 +1,81 @@
1
+ import chalk from "chalk";
2
+ import inquirer from "inquirer";
3
+ import { isInitialized } from "../installer.js";
4
+ import { buildResetPlan, executeResetPlan, planToDryRunActions } from "../reset.js";
5
+ import { formatDryRunSummary } from "../utils/dryrun.js";
6
+ import { withErrorHandling } from "../utils/errors.js";
7
+ import { resolveProjectPlatform } from "../platform/resolve.js";
8
+ export async function resetCommand(options) {
9
+ await withErrorHandling(() => runReset(options));
10
+ }
11
+ async function runReset(options) {
12
+ const projectDir = options.projectDir;
13
+ if (!(await isInitialized(projectDir))) {
14
+ console.log(chalk.red("bmalph is not initialized. Nothing to reset."));
15
+ return;
16
+ }
17
+ const platform = await resolveProjectPlatform(projectDir);
18
+ const plan = await buildResetPlan(projectDir, platform);
19
+ // Preview
20
+ const actions = planToDryRunActions(plan);
21
+ if (actions.length === 0) {
22
+ console.log(chalk.dim("Nothing to reset."));
23
+ return;
24
+ }
25
+ // Dry-run mode
26
+ if (options.dryRun) {
27
+ console.log(formatDryRunSummary(actions));
28
+ return;
29
+ }
30
+ // Show preview before confirmation
31
+ for (const action of actions) {
32
+ if (action.type === "delete") {
33
+ console.log(` ${chalk.red("delete")} ${action.path}`);
34
+ }
35
+ else if (action.type === "modify") {
36
+ console.log(` ${chalk.yellow("modify")} ${action.path}`);
37
+ }
38
+ else if (action.type === "warn") {
39
+ console.log(` ${chalk.yellow("warn")} ${action.path}${action.reason ? ` (${action.reason})` : ""}`);
40
+ }
41
+ }
42
+ // Confirm unless --force or non-interactive
43
+ if (!options.force) {
44
+ if (!process.stdin.isTTY) {
45
+ throw new Error("Non-interactive mode requires --force flag for reset");
46
+ }
47
+ const { confirm } = await inquirer.prompt([
48
+ {
49
+ type: "confirm",
50
+ name: "confirm",
51
+ message: "This will remove all bmalph files from the project. Continue?",
52
+ default: false,
53
+ },
54
+ ]);
55
+ if (!confirm) {
56
+ console.log("Aborted.");
57
+ return;
58
+ }
59
+ }
60
+ // Execute
61
+ console.log("\nResetting...");
62
+ await executeResetPlan(projectDir, plan);
63
+ // Summary
64
+ console.log(chalk.green("\nReset complete."));
65
+ if (plan.directories.length > 0) {
66
+ console.log(chalk.dim("\nRemoved:"));
67
+ for (const dir of plan.directories) {
68
+ console.log(` ${dir}/`);
69
+ }
70
+ }
71
+ if (plan.commandFiles.length > 0) {
72
+ console.log(chalk.dim("\nRemoved commands:"));
73
+ for (const file of plan.commandFiles) {
74
+ console.log(` ${file}`);
75
+ }
76
+ }
77
+ // Show warnings
78
+ for (const warning of plan.warnings) {
79
+ console.log(chalk.yellow(`\nNote: ${warning.path} ${warning.message}`));
80
+ }
81
+ }