bmalph 2.7.5 → 2.7.6

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 (53) hide show
  1. package/README.md +20 -5
  2. package/dist/commands/doctor-runtime-checks.js +104 -86
  3. package/dist/commands/doctor-runtime-checks.js.map +1 -1
  4. package/dist/installer/bmad-assets.js +182 -0
  5. package/dist/installer/bmad-assets.js.map +1 -0
  6. package/dist/installer/commands.js +324 -0
  7. package/dist/installer/commands.js.map +1 -0
  8. package/dist/installer/install.js +42 -0
  9. package/dist/installer/install.js.map +1 -0
  10. package/dist/installer/metadata.js +56 -0
  11. package/dist/installer/metadata.js.map +1 -0
  12. package/dist/installer/project-files.js +169 -0
  13. package/dist/installer/project-files.js.map +1 -0
  14. package/dist/installer/ralph-assets.js +91 -0
  15. package/dist/installer/ralph-assets.js.map +1 -0
  16. package/dist/installer/template-files.js +168 -0
  17. package/dist/installer/template-files.js.map +1 -0
  18. package/dist/installer/types.js +2 -0
  19. package/dist/installer/types.js.map +1 -0
  20. package/dist/installer.js +5 -843
  21. package/dist/installer.js.map +1 -1
  22. package/dist/transition/artifact-loading.js +91 -0
  23. package/dist/transition/artifact-loading.js.map +1 -0
  24. package/dist/transition/context-output.js +85 -0
  25. package/dist/transition/context-output.js.map +1 -0
  26. package/dist/transition/fix-plan-sync.js +119 -0
  27. package/dist/transition/fix-plan-sync.js.map +1 -0
  28. package/dist/transition/orchestration.js +25 -362
  29. package/dist/transition/orchestration.js.map +1 -1
  30. package/dist/transition/specs-sync.js +78 -2
  31. package/dist/transition/specs-sync.js.map +1 -1
  32. package/dist/utils/ralph-runtime-state.js +222 -0
  33. package/dist/utils/ralph-runtime-state.js.map +1 -0
  34. package/dist/utils/state.js +17 -16
  35. package/dist/utils/state.js.map +1 -1
  36. package/dist/utils/validate.js +16 -0
  37. package/dist/utils/validate.js.map +1 -1
  38. package/dist/watch/renderer.js +48 -6
  39. package/dist/watch/renderer.js.map +1 -1
  40. package/dist/watch/state-reader.js +79 -44
  41. package/dist/watch/state-reader.js.map +1 -1
  42. package/package.json +1 -1
  43. package/ralph/RALPH-REFERENCE.md +33 -13
  44. package/ralph/drivers/claude-code.sh +25 -0
  45. package/ralph/drivers/codex.sh +11 -0
  46. package/ralph/drivers/copilot.sh +11 -0
  47. package/ralph/drivers/cursor.sh +11 -0
  48. package/ralph/lib/circuit_breaker.sh +3 -3
  49. package/ralph/lib/date_utils.sh +28 -9
  50. package/ralph/lib/response_analyzer.sh +127 -7
  51. package/ralph/ralph_loop.sh +464 -121
  52. package/ralph/templates/PROMPT.md +5 -0
  53. package/ralph/templates/ralphrc.template +14 -4
@@ -0,0 +1,91 @@
1
+ import { chmod, cp, mkdir, readFile, readdir, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { debug } from "../utils/logger.js";
4
+ import { atomicWriteFile, exists } from "../utils/file-system.js";
5
+ import { formatError } from "../utils/errors.js";
6
+ import { isTemplateCustomized, renderRalphrcTemplate } from "./template-files.js";
7
+ export async function installRalphAssets(projectDir, ralphDir, platform, packageVersion) {
8
+ await mkdir(join(projectDir, ".ralph"), { recursive: true });
9
+ const promptPath = join(projectDir, ".ralph/PROMPT.md");
10
+ const agentPath = join(projectDir, ".ralph/@AGENT.md");
11
+ const promptCustomized = await isTemplateCustomized(promptPath, "PROMPT.md");
12
+ const agentCustomized = await isTemplateCustomized(agentPath, "AGENT.md");
13
+ if (!promptCustomized) {
14
+ await cp(join(ralphDir, "templates/PROMPT.md"), promptPath, {
15
+ dereference: false,
16
+ });
17
+ }
18
+ if (!agentCustomized) {
19
+ await cp(join(ralphDir, "templates/AGENT.md"), agentPath, {
20
+ dereference: false,
21
+ });
22
+ }
23
+ await cp(join(ralphDir, "RALPH-REFERENCE.md"), join(projectDir, ".ralph/RALPH-REFERENCE.md"), {
24
+ dereference: false,
25
+ });
26
+ const ralphrcDest = join(projectDir, ".ralph/.ralphrc");
27
+ const ralphrcCustomized = await isTemplateCustomized(ralphrcDest, "RALPHRC", {
28
+ platformId: platform.id,
29
+ });
30
+ const renderedRalphrc = await renderRalphrcTemplate(platform.id);
31
+ let currentRalphrc = "";
32
+ if (await exists(ralphrcDest)) {
33
+ currentRalphrc = await readFile(ralphrcDest, "utf-8");
34
+ }
35
+ if (!ralphrcCustomized && currentRalphrc !== renderedRalphrc) {
36
+ await atomicWriteFile(ralphrcDest, renderedRalphrc);
37
+ }
38
+ // Copy Ralph loop and lib → .ralph/
39
+ const loopContent = await readFile(join(ralphDir, "ralph_loop.sh"), "utf-8");
40
+ const markerLine = `# bmalph-version: ${packageVersion}`;
41
+ const markedContent = loopContent.includes("# bmalph-version:")
42
+ ? loopContent.replace(/# bmalph-version:.*/, markerLine)
43
+ : loopContent.replace(/^(#!.+\r?\n)/, `$1${markerLine}\n`);
44
+ await atomicWriteFile(join(projectDir, ".ralph/ralph_loop.sh"), markedContent);
45
+ await chmod(join(projectDir, ".ralph/ralph_loop.sh"), 0o755);
46
+ await rm(join(projectDir, ".ralph/lib"), { recursive: true, force: true });
47
+ await cp(join(ralphDir, "lib"), join(projectDir, ".ralph/lib"), {
48
+ recursive: true,
49
+ dereference: false,
50
+ });
51
+ // Copy Ralph utilities → .ralph/
52
+ await cp(join(ralphDir, "ralph_import.sh"), join(projectDir, ".ralph/ralph_import.sh"), {
53
+ dereference: false,
54
+ });
55
+ await chmod(join(projectDir, ".ralph/ralph_import.sh"), 0o755);
56
+ await cp(join(ralphDir, "ralph_monitor.sh"), join(projectDir, ".ralph/ralph_monitor.sh"), {
57
+ dereference: false,
58
+ });
59
+ await chmod(join(projectDir, ".ralph/ralph_monitor.sh"), 0o755);
60
+ // Copy Ralph drivers → .ralph/drivers/
61
+ const driversDir = join(ralphDir, "drivers");
62
+ if (await exists(driversDir)) {
63
+ const destDriversDir = join(projectDir, ".ralph/drivers");
64
+ await rm(destDriversDir, { recursive: true, force: true });
65
+ await cp(driversDir, destDriversDir, { recursive: true, dereference: false });
66
+ try {
67
+ const driverFiles = await readdir(destDriversDir);
68
+ for (const file of driverFiles) {
69
+ if (file.endsWith(".sh")) {
70
+ await chmod(join(destDriversDir, file), 0o755);
71
+ }
72
+ }
73
+ }
74
+ catch (err) {
75
+ debug(`chmod on driver scripts failed (non-fatal): ${formatError(err)}`);
76
+ }
77
+ }
78
+ return {
79
+ updatedPaths: [
80
+ ".ralph/ralph_loop.sh",
81
+ ".ralph/ralph_import.sh",
82
+ ".ralph/ralph_monitor.sh",
83
+ ".ralph/lib/",
84
+ ...(!promptCustomized ? [".ralph/PROMPT.md"] : []),
85
+ ...(!agentCustomized ? [".ralph/@AGENT.md"] : []),
86
+ ...(!ralphrcCustomized && currentRalphrc !== renderedRalphrc ? [".ralph/.ralphrc"] : []),
87
+ ".ralph/RALPH-REFERENCE.md",
88
+ ],
89
+ };
90
+ }
91
+ //# sourceMappingURL=ralph-assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ralph-assets.js","sourceRoot":"","sources":["../../src/installer/ralph-assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { isEnoent } from "../utils/errors.js";
4
+ import { getBundledRalphDir } from "./metadata.js";
5
+ const TEMPLATE_PLACEHOLDERS = {
6
+ "PROMPT.md": "[YOUR PROJECT NAME]",
7
+ "AGENT.md": "pip install -r requirements.txt",
8
+ };
9
+ const RALPHRC_TEMPLATE_NAME = "RALPHRC";
10
+ const CLAUDE_PERMISSION_MODE_TEMPLATE_BLOCK = `# Permission mode for Claude Code CLI (default: auto)
11
+ # Options: auto, acceptEdits, bypassPermissions, default, dontAsk, plan
12
+ CLAUDE_PERMISSION_MODE="auto"
13
+
14
+ `;
15
+ const LEGACY_RALPHRC_TEMPLATE = `# .ralphrc - Ralph project configuration
16
+ # Generated by: ralph enable
17
+ # Documentation: https://github.com/frankbria/ralph-claude-code
18
+ #
19
+ # This file configures Ralph's behavior for this specific project.
20
+ # Values here override global Ralph defaults.
21
+ # Environment variables override values in this file.
22
+
23
+ # =============================================================================
24
+ # PLATFORM DRIVER
25
+ # =============================================================================
26
+
27
+ # Platform driver for Ralph loop (claude-code, codex, copilot, or cursor)
28
+ PLATFORM_DRIVER="\${PLATFORM_DRIVER:-__PLATFORM_DRIVER__}"
29
+
30
+ # =============================================================================
31
+ # PROJECT IDENTIFICATION
32
+ # =============================================================================
33
+
34
+ # Project name (used in prompts and logging)
35
+ PROJECT_NAME="\${PROJECT_NAME:-my-project}"
36
+
37
+ # Project type: javascript, typescript, python, rust, go, unknown
38
+ PROJECT_TYPE="\${PROJECT_TYPE:-unknown}"
39
+
40
+ # =============================================================================
41
+ # LOOP SETTINGS
42
+ # =============================================================================
43
+
44
+ # Maximum API calls per hour (rate limiting)
45
+ MAX_CALLS_PER_HOUR=100
46
+
47
+ # Timeout for each Claude Code invocation (in minutes)
48
+ CLAUDE_TIMEOUT_MINUTES=15
49
+
50
+ # Output format: json (structured) or text (legacy)
51
+ CLAUDE_OUTPUT_FORMAT="json"
52
+
53
+ # =============================================================================
54
+ # TOOL PERMISSIONS
55
+ # =============================================================================
56
+
57
+ # Comma-separated list of allowed tools for Claude
58
+ # Common tools: Write, Read, Edit, Grep, Glob
59
+ # Bash patterns: Bash(git *), Bash(npm *), Bash(pytest)
60
+ ALLOWED_TOOLS="Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)"
61
+
62
+ # =============================================================================
63
+ # SESSION MANAGEMENT
64
+ # =============================================================================
65
+
66
+ # Enable session continuity (maintain context across loops)
67
+ SESSION_CONTINUITY=true
68
+
69
+ # Session expiration time in hours (start fresh after this time)
70
+ SESSION_EXPIRY_HOURS=24
71
+
72
+ # =============================================================================
73
+ # TASK SOURCES
74
+ # =============================================================================
75
+
76
+ # Where to import tasks from (comma-separated)
77
+ # Options: local, beads, github
78
+ TASK_SOURCES="local"
79
+
80
+ # GitHub label for task filtering (when github is in TASK_SOURCES)
81
+ GITHUB_TASK_LABEL="ralph-task"
82
+
83
+ # Beads filter for task import (when beads is in TASK_SOURCES)
84
+ BEADS_FILTER="status:open"
85
+
86
+ # =============================================================================
87
+ # CIRCUIT BREAKER THRESHOLDS
88
+ # =============================================================================
89
+
90
+ # Open circuit after N loops with no file changes
91
+ CB_NO_PROGRESS_THRESHOLD=3
92
+
93
+ # Open circuit after N loops with the same error
94
+ CB_SAME_ERROR_THRESHOLD=5
95
+
96
+ # Open circuit if output declines by more than N percent
97
+ CB_OUTPUT_DECLINE_THRESHOLD=70
98
+
99
+ # Auto-recovery: cooldown before retry (minutes, 0 = immediate)
100
+ CB_COOLDOWN_MINUTES=30
101
+
102
+ # Auto-reset circuit breaker on startup (bypasses cooldown)
103
+ # WARNING: Reduces circuit breaker safety for unattended operation
104
+ CB_AUTO_RESET=false
105
+
106
+ # =============================================================================
107
+ # ADVANCED SETTINGS
108
+ # =============================================================================
109
+
110
+ # Minimum Claude CLI version required
111
+ CLAUDE_MIN_VERSION="2.0.76"
112
+
113
+ # Enable verbose logging
114
+ RALPH_VERBOSE=false
115
+
116
+ # Custom prompt file (relative to .ralph/)
117
+ # PROMPT_FILE="PROMPT.md"
118
+
119
+ # Custom fix plan file (relative to .ralph/)
120
+ # FIX_PLAN_FILE="@fix_plan.md"
121
+
122
+ # Custom agent file (relative to .ralph/)
123
+ # AGENT_FILE="@AGENT.md"
124
+ `;
125
+ function renderLegacyRalphrcTemplate(platformId) {
126
+ return LEGACY_RALPHRC_TEMPLATE.replace("__PLATFORM_DRIVER__", platformId);
127
+ }
128
+ function renderCurrentRalphrcTemplate(templateContent, platformId) {
129
+ return templateContent.replace(/PLATFORM_DRIVER="\$\{PLATFORM_DRIVER:-[^"]*\}"/, `PLATFORM_DRIVER="\${PLATFORM_DRIVER:-${platformId}}"`);
130
+ }
131
+ export async function renderRalphrcTemplate(platformId) {
132
+ const ralphDir = getBundledRalphDir();
133
+ const templateContent = await readFile(join(ralphDir, "templates/ralphrc.template"), "utf-8");
134
+ return renderCurrentRalphrcTemplate(templateContent, platformId);
135
+ }
136
+ async function isRalphrcCustomized(filePath, platformId) {
137
+ const content = await readFile(filePath, "utf-8");
138
+ const currentTemplate = await renderRalphrcTemplate(platformId);
139
+ if (content === currentTemplate) {
140
+ return false;
141
+ }
142
+ const previousManagedTemplate = currentTemplate.replace(CLAUDE_PERMISSION_MODE_TEMPLATE_BLOCK, "");
143
+ if (content === previousManagedTemplate) {
144
+ return false;
145
+ }
146
+ const legacyTemplate = renderLegacyRalphrcTemplate(platformId);
147
+ return content !== legacyTemplate;
148
+ }
149
+ export async function isTemplateCustomized(filePath, templateName, options) {
150
+ try {
151
+ if (templateName === RALPHRC_TEMPLATE_NAME) {
152
+ return await isRalphrcCustomized(filePath, options?.platformId ?? "claude-code");
153
+ }
154
+ const placeholder = TEMPLATE_PLACEHOLDERS[templateName];
155
+ if (!placeholder) {
156
+ return false;
157
+ }
158
+ const content = await readFile(filePath, "utf-8");
159
+ return !content.includes(placeholder);
160
+ }
161
+ catch (err) {
162
+ if (isEnoent(err)) {
163
+ return false;
164
+ }
165
+ throw err;
166
+ }
167
+ }
168
+ //# sourceMappingURL=template-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-files.js","sourceRoot":"","sources":["../../src/installer/template-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,qBAAqB,GAA2B;IACpD,WAAW,EAAE,qBAAqB;IAClC,UAAU,EAAE,iCAAiC;CAC9C,CAAC;AAEF,MAAM,qBAAqB,GAAG,SAAS,CAAC;AACxC,MAAM,qCAAqC,GAAG;;;;CAI7C,CAAC;AAEF,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6G/B,CAAC;AAEF,SAAS,2BAA2B,CAAC,UAAkB;IACrD,OAAO,uBAAuB,CAAC,OAAO,CAAC,qBAAqB,EAAE,UAAU,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,4BAA4B,CAAC,eAAuB,EAAE,UAAkB;IAC/E,OAAO,eAAe,CAAC,OAAO,CAC5B,gDAAgD,EAChD,wCAAwC,UAAU,IAAI,CACvD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAAkB;IAC5D,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,4BAA4B,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9F,OAAO,4BAA4B,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,QAAgB,EAAE,UAAkB;IACrE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAChE,IAAI,OAAO,KAAK,eAAe,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,uBAAuB,GAAG,eAAe,CAAC,OAAO,CACrD,qCAAqC,EACrC,EAAE,CACH,CAAC;IACF,IAAI,OAAO,KAAK,uBAAuB,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,cAAc,GAAG,2BAA2B,CAAC,UAAU,CAAC,CAAC;IAC/D,OAAO,OAAO,KAAK,cAAc,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAgB,EAChB,YAAoB,EACpB,OAAiC;IAEjC,IAAI,CAAC;QACH,IAAI,YAAY,KAAK,qBAAqB,EAAE,CAAC;YAC3C,OAAO,MAAM,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,IAAI,aAAa,CAAC,CAAC;QACnF,CAAC;QAED,MAAM,WAAW,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;QACxD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/installer/types.ts"],"names":[],"mappings":""}