bmalph 2.7.2 → 2.7.4
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 +14 -4
- package/dist/commands/doctor-checks.js +17 -10
- package/dist/commands/doctor-checks.js.map +1 -1
- package/dist/run/ralph-process.js +101 -7
- package/dist/run/ralph-process.js.map +1 -1
- package/dist/transition/artifact-collection.js +74 -0
- package/dist/transition/artifact-collection.js.map +1 -0
- package/dist/transition/artifacts.js +12 -1
- package/dist/transition/artifacts.js.map +1 -1
- package/dist/transition/context.js +17 -25
- package/dist/transition/context.js.map +1 -1
- package/dist/transition/fix-plan.js +12 -7
- package/dist/transition/fix-plan.js.map +1 -1
- package/dist/transition/orchestration.js +213 -116
- package/dist/transition/orchestration.js.map +1 -1
- package/dist/transition/preflight.js +30 -17
- package/dist/transition/preflight.js.map +1 -1
- package/dist/transition/section-patterns.js +56 -4
- package/dist/transition/section-patterns.js.map +1 -1
- package/dist/transition/specs-index.js +5 -2
- package/dist/transition/specs-index.js.map +1 -1
- package/dist/transition/specs-sync.js +23 -0
- package/dist/transition/specs-sync.js.map +1 -0
- package/dist/transition/sprint-status.js +91 -0
- package/dist/transition/sprint-status.js.map +1 -0
- package/dist/transition/story-id.js +46 -0
- package/dist/transition/story-id.js.map +1 -0
- package/dist/transition/story-parsing.js +7 -7
- package/dist/transition/story-parsing.js.map +1 -1
- package/dist/transition/tech-stack.js +1 -7
- package/dist/transition/tech-stack.js.map +1 -1
- package/package.json +1 -1
- package/ralph/RALPH-REFERENCE.md +50 -46
- package/ralph/drivers/claude-code.sh +44 -2
- package/ralph/drivers/codex.sh +10 -1
- package/ralph/drivers/copilot.sh +5 -0
- package/ralph/drivers/cursor-agent-wrapper.sh +13 -0
- package/ralph/drivers/cursor.sh +178 -14
- package/ralph/lib/circuit_breaker.sh +5 -5
- package/ralph/lib/enable_core.sh +10 -10
- package/ralph/lib/response_analyzer.sh +357 -111
- package/ralph/ralph_import.sh +14 -10
- package/ralph/ralph_loop.sh +168 -119
- package/ralph/ralph_monitor.sh +4 -4
- package/ralph/templates/AGENT.md +7 -7
- package/ralph/templates/PROMPT.md +13 -13
package/ralph/RALPH-REFERENCE.md
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
This reference guide provides essential information for troubleshooting and understanding Ralph's autonomous development loop.
|
|
4
4
|
|
|
5
|
+
In bmalph-managed projects, start Ralph with `bmalph run`. When you need direct loop flags such as `--reset-circuit` or `--live`, invoke `bash .ralph/ralph_loop.sh ...` from the project root.
|
|
6
|
+
|
|
5
7
|
## Table of Contents
|
|
6
8
|
|
|
7
9
|
1. [Configuration Files](#configuration-files)
|
|
8
|
-
2. [Project Configuration (.ralphrc)](#project-configuration-
|
|
10
|
+
2. [Project Configuration (.ralph/.ralphrc)](#project-configuration-ralphralphrc)
|
|
9
11
|
3. [Session Management](#session-management)
|
|
10
12
|
4. [Circuit Breaker](#circuit-breaker)
|
|
11
13
|
5. [Exit Detection](#exit-detection)
|
|
@@ -16,12 +18,12 @@ This reference guide provides essential information for troubleshooting and unde
|
|
|
16
18
|
|
|
17
19
|
## Configuration Files
|
|
18
20
|
|
|
19
|
-
Ralph uses several files within the `.ralph/` directory:
|
|
21
|
+
Ralph uses several files within the `.ralph/` directory, plus an optional legacy fallback config at the project root:
|
|
20
22
|
|
|
21
23
|
| File | Purpose |
|
|
22
24
|
|------|---------|
|
|
23
25
|
| `.ralph/PROMPT.md` | Main prompt that drives each loop iteration |
|
|
24
|
-
| `.ralph
|
|
26
|
+
| `.ralph/@fix_plan.md` | Prioritized task list that Ralph follows |
|
|
25
27
|
| `.ralph/@AGENT.md` | Build and run instructions maintained by Ralph |
|
|
26
28
|
| `.ralph/status.json` | Real-time status tracking (JSON format) |
|
|
27
29
|
| `.ralph/logs/` | Execution logs for each loop iteration |
|
|
@@ -29,23 +31,25 @@ Ralph uses several files within the `.ralph/` directory:
|
|
|
29
31
|
| `.ralph/.circuit_breaker_state` | Circuit breaker state |
|
|
30
32
|
| `.ralph/live.log` | Live streaming output file for monitoring |
|
|
31
33
|
| `.ralph/.loop_start_sha` | Git HEAD SHA captured at loop start for progress detection |
|
|
32
|
-
| `.ralphrc`
|
|
34
|
+
| `.ralph/.ralphrc` | Project-specific configuration installed by bmalph |
|
|
35
|
+
| `.ralphrc` (project root, legacy fallback) | Optional legacy configuration for older standalone Ralph layouts |
|
|
33
36
|
|
|
34
37
|
### Rate Limiting
|
|
35
38
|
|
|
36
|
-
- Default: 100 API calls per hour (configurable via `--calls` flag or `.ralphrc`)
|
|
39
|
+
- Default: 100 API calls per hour (configurable via `--calls` flag or `.ralph/.ralphrc`)
|
|
37
40
|
- Automatic hourly reset with countdown display
|
|
38
41
|
- Call tracking persists across script restarts
|
|
39
42
|
|
|
40
43
|
---
|
|
41
44
|
|
|
42
|
-
## Project Configuration (.ralphrc)
|
|
45
|
+
## Project Configuration (.ralph/.ralphrc)
|
|
43
46
|
|
|
44
|
-
Ralph
|
|
47
|
+
In bmalph-managed projects, Ralph reads `.ralph/.ralphrc` for per-project settings.
|
|
48
|
+
For backward compatibility with older standalone Ralph layouts, it also falls back to a project-root `.ralphrc` when the bundled config file is missing.
|
|
45
49
|
|
|
46
50
|
### Precedence
|
|
47
51
|
|
|
48
|
-
Environment variables >
|
|
52
|
+
Environment variables > Ralph config file > script defaults
|
|
49
53
|
|
|
50
54
|
### Available Settings
|
|
51
55
|
|
|
@@ -54,7 +58,7 @@ Environment variables > `.ralphrc` > script defaults
|
|
|
54
58
|
| `PROJECT_NAME` | `my-project` | Project name for prompts and logging |
|
|
55
59
|
| `PROJECT_TYPE` | `unknown` | Project type (javascript, typescript, python, rust, go) |
|
|
56
60
|
| `MAX_CALLS_PER_HOUR` | `100` | Rate limit for API calls |
|
|
57
|
-
| `CLAUDE_TIMEOUT_MINUTES` | `15` | Timeout per
|
|
61
|
+
| `CLAUDE_TIMEOUT_MINUTES` | `15` | Timeout per loop driver invocation |
|
|
58
62
|
| `CLAUDE_OUTPUT_FORMAT` | `json` | Output format (json or text) |
|
|
59
63
|
| `ALLOWED_TOOLS` | `Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)` | Comma-separated allowed tools |
|
|
60
64
|
| `SESSION_CONTINUITY` | `true` | Maintain context across loops |
|
|
@@ -69,7 +73,7 @@ Environment variables > `.ralphrc` > script defaults
|
|
|
69
73
|
|
|
70
74
|
### Generation
|
|
71
75
|
|
|
72
|
-
bmalph copies `ralphrc.template` to `.ralph/.ralphrc` during `bmalph init`. Existing `.ralphrc` files are preserved during upgrades.
|
|
76
|
+
bmalph copies `ralphrc.template` to `.ralph/.ralphrc` during `bmalph init`. Existing `.ralph/.ralphrc` files are preserved during upgrades.
|
|
73
77
|
|
|
74
78
|
---
|
|
75
79
|
|
|
@@ -79,7 +83,7 @@ Ralph maintains session continuity across loop iterations using `--resume` with
|
|
|
79
83
|
|
|
80
84
|
### Session Continuity
|
|
81
85
|
|
|
82
|
-
Ralph uses `--resume <session_id>` instead of `--continue` to resume sessions. This ensures Ralph only resumes its own sessions and avoids hijacking active
|
|
86
|
+
Ralph uses `--resume <session_id>` instead of `--continue` to resume sessions. This ensures Ralph only resumes its own saved sessions and avoids hijacking unrelated active sessions.
|
|
83
87
|
|
|
84
88
|
### Session Files
|
|
85
89
|
|
|
@@ -87,7 +91,7 @@ Ralph uses `--resume <session_id>` instead of `--continue` to resume sessions. T
|
|
|
87
91
|
|------|---------|
|
|
88
92
|
| `.ralph/.ralph_session` | Current session ID and timestamps |
|
|
89
93
|
| `.ralph/.ralph_session_history` | History of last 50 session transitions |
|
|
90
|
-
| `.ralph/.claude_session_id` |
|
|
94
|
+
| `.ralph/.claude_session_id` | Persisted driver session ID (shared filename for historical reasons) |
|
|
91
95
|
|
|
92
96
|
### Session Lifecycle
|
|
93
97
|
|
|
@@ -95,12 +99,12 @@ Sessions are automatically reset when:
|
|
|
95
99
|
- Circuit breaker opens (stagnation detected)
|
|
96
100
|
- Manual interrupt (Ctrl+C / SIGINT)
|
|
97
101
|
- Project completion (graceful exit)
|
|
98
|
-
- Manual circuit breaker reset (`ralph --reset-circuit`)
|
|
99
|
-
- Manual session reset (`ralph --reset-session`)
|
|
102
|
+
- Manual circuit breaker reset (`bash .ralph/ralph_loop.sh --reset-circuit`)
|
|
103
|
+
- Manual session reset (`bash .ralph/ralph_loop.sh --reset-session`)
|
|
100
104
|
|
|
101
105
|
### Session Expiration
|
|
102
106
|
|
|
103
|
-
Sessions expire after 24 hours (configurable via `SESSION_EXPIRY_HOURS` in `.ralphrc`). When expired:
|
|
107
|
+
Sessions expire after 24 hours (configurable via `SESSION_EXPIRY_HOURS` in `.ralph/.ralphrc`). When expired:
|
|
104
108
|
- A new session is created automatically
|
|
105
109
|
- Previous context is not preserved
|
|
106
110
|
- Session history records the transition
|
|
@@ -144,16 +148,16 @@ The circuit breaker prevents runaway loops by detecting stagnation.
|
|
|
144
148
|
|
|
145
149
|
### Permission Denial Detection
|
|
146
150
|
|
|
147
|
-
When
|
|
151
|
+
When the active driver is denied permission to execute commands, Ralph:
|
|
148
152
|
1. Detects permission denials from the JSON output
|
|
149
153
|
2. Halts the loop with reason `permission_denied`
|
|
150
|
-
3. Displays guidance to update `ALLOWED_TOOLS` in `.ralphrc`
|
|
154
|
+
3. Displays guidance to update `ALLOWED_TOOLS` in `.ralph/.ralphrc`
|
|
151
155
|
|
|
152
156
|
### Auto-Recovery Cooldown
|
|
153
157
|
|
|
154
158
|
After `CB_COOLDOWN_MINUTES` (default: 30) in OPEN state, the circuit auto-transitions to HALF_OPEN. From HALF_OPEN, if progress is detected, circuit goes to CLOSED; otherwise back to OPEN.
|
|
155
159
|
|
|
156
|
-
Set `CB_AUTO_RESET=true` in `.ralphrc` to bypass cooldown entirely and reset to CLOSED on startup.
|
|
160
|
+
Set `CB_AUTO_RESET=true` in `.ralph/.ralphrc` to bypass cooldown entirely and reset to CLOSED on startup.
|
|
157
161
|
|
|
158
162
|
### Circuit Breaker State Structure
|
|
159
163
|
|
|
@@ -175,7 +179,7 @@ Set `CB_AUTO_RESET=true` in `.ralphrc` to bypass cooldown entirely and reset to
|
|
|
175
179
|
|
|
176
180
|
To reset the circuit breaker:
|
|
177
181
|
```bash
|
|
178
|
-
ralph --reset-circuit
|
|
182
|
+
bash .ralph/ralph_loop.sh --reset-circuit
|
|
179
183
|
```
|
|
180
184
|
|
|
181
185
|
---
|
|
@@ -200,17 +204,17 @@ The `completion_indicators` exit condition requires dual verification:
|
|
|
200
204
|
| completion_indicators | EXIT_SIGNAL | Result |
|
|
201
205
|
|-----------------------|-------------|--------|
|
|
202
206
|
| >= 2 | `true` | **Exit** ("project_complete") |
|
|
203
|
-
| >= 2 | `false` | **Continue** (
|
|
207
|
+
| >= 2 | `false` | **Continue** (agent still working) |
|
|
204
208
|
| >= 2 | missing | **Continue** (defaults to false) |
|
|
205
209
|
| < 2 | `true` | **Continue** (threshold not met) |
|
|
206
210
|
|
|
207
|
-
**Rationale:** Natural language patterns like "done" or "complete" can trigger false positives during productive work. By requiring
|
|
211
|
+
**Rationale:** Natural language patterns like "done" or "complete" can trigger false positives during productive work. By requiring an explicit `EXIT_SIGNAL` confirmation, Ralph avoids exiting mid-iteration.
|
|
208
212
|
|
|
209
|
-
When
|
|
213
|
+
When the agent outputs `STATUS: COMPLETE` with `EXIT_SIGNAL: false`, the explicit `false` takes precedence. This allows marking a phase complete while indicating more phases remain.
|
|
210
214
|
|
|
211
215
|
### RALPH_STATUS Block
|
|
212
216
|
|
|
213
|
-
|
|
217
|
+
The coding agent should include this status block at the end of each response:
|
|
214
218
|
|
|
215
219
|
```
|
|
216
220
|
---RALPH_STATUS---
|
|
@@ -227,7 +231,7 @@ RECOMMENDATION: <one line summary of what to do next>
|
|
|
227
231
|
### When to Set EXIT_SIGNAL: true
|
|
228
232
|
|
|
229
233
|
Set EXIT_SIGNAL to **true** when ALL conditions are met:
|
|
230
|
-
1. All items in fix_plan.md are marked [x]
|
|
234
|
+
1. All items in `@fix_plan.md` are marked `[x]`
|
|
231
235
|
2. All tests are passing (or no tests exist for valid reasons)
|
|
232
236
|
3. No errors or warnings in the last execution
|
|
233
237
|
4. All requirements from specs/ are implemented
|
|
@@ -246,8 +250,8 @@ Ralph supports real-time streaming output with the `--live` flag.
|
|
|
246
250
|
### Usage
|
|
247
251
|
|
|
248
252
|
```bash
|
|
249
|
-
ralph --live # Live streaming output
|
|
250
|
-
ralph --monitor --live # Live streaming with tmux monitoring
|
|
253
|
+
bash .ralph/ralph_loop.sh --live # Live streaming output
|
|
254
|
+
bash .ralph/ralph_loop.sh --monitor --live # Live streaming with tmux monitoring
|
|
251
255
|
```
|
|
252
256
|
|
|
253
257
|
### How It Works
|
|
@@ -260,8 +264,8 @@ ralph --monitor --live # Live streaming with tmux monitoring
|
|
|
260
264
|
|
|
261
265
|
When using `--monitor` with `--live`, tmux creates a 3-pane layout:
|
|
262
266
|
- **Left pane:** Ralph loop with live streaming
|
|
263
|
-
- **Right-top pane:** `tail -f .ralph/live.log` (
|
|
264
|
-
- **Right-bottom pane:** `
|
|
267
|
+
- **Right-top pane:** `tail -f .ralph/live.log` (live driver output)
|
|
268
|
+
- **Right-bottom pane:** status dashboard (`bmalph watch` when available)
|
|
265
269
|
|
|
266
270
|
---
|
|
267
271
|
|
|
@@ -276,11 +280,11 @@ When using `--monitor` with `--live`, tmux creates a 3-pane layout:
|
|
|
276
280
|
**Causes:**
|
|
277
281
|
- EXIT_SIGNAL set to true prematurely
|
|
278
282
|
- completion_indicators triggered by natural language
|
|
279
|
-
- All fix_plan.md items marked complete
|
|
283
|
+
- All `@fix_plan.md` items marked complete
|
|
280
284
|
|
|
281
285
|
**Solutions:**
|
|
282
286
|
1. Ensure EXIT_SIGNAL is only true when genuinely complete
|
|
283
|
-
2. Add remaining tasks to fix_plan.md
|
|
287
|
+
2. Add remaining tasks to `@fix_plan.md`
|
|
284
288
|
3. Check `.ralph/.response_analysis` for exit reasons
|
|
285
289
|
|
|
286
290
|
#### Ralph doesn't exit when complete
|
|
@@ -289,13 +293,13 @@ When using `--monitor` with `--live`, tmux creates a 3-pane layout:
|
|
|
289
293
|
|
|
290
294
|
**Causes:**
|
|
291
295
|
- EXIT_SIGNAL not being set to true
|
|
292
|
-
- fix_plan.md has unmarked items
|
|
296
|
+
- `@fix_plan.md` has unmarked items
|
|
293
297
|
- completion_indicators threshold not met
|
|
294
298
|
|
|
295
299
|
**Solutions:**
|
|
296
300
|
1. Ensure RALPH_STATUS block is included in responses
|
|
297
301
|
2. Set EXIT_SIGNAL: true when all work is done
|
|
298
|
-
3. Mark all completed items in fix_plan.md
|
|
302
|
+
3. Mark all completed items in `@fix_plan.md`
|
|
299
303
|
|
|
300
304
|
#### Circuit breaker opens unexpectedly
|
|
301
305
|
|
|
@@ -309,19 +313,19 @@ When using `--monitor` with `--live`, tmux creates a 3-pane layout:
|
|
|
309
313
|
**Solutions:**
|
|
310
314
|
1. Check `.ralph/logs/` for the recurring error
|
|
311
315
|
2. Fix the underlying issue causing the error
|
|
312
|
-
3. Reset circuit breaker: `ralph --reset-circuit`
|
|
316
|
+
3. Reset circuit breaker: `bash .ralph/ralph_loop.sh --reset-circuit`
|
|
313
317
|
|
|
314
318
|
#### Permission denied halts loop
|
|
315
319
|
|
|
316
320
|
**Symptoms:** "OPEN - permission_denied" message
|
|
317
321
|
|
|
318
322
|
**Causes:**
|
|
319
|
-
-
|
|
320
|
-
- `ALLOWED_TOOLS` in `.ralphrc` too restrictive
|
|
323
|
+
- The active driver denied permission to run commands
|
|
324
|
+
- `ALLOWED_TOOLS` in `.ralph/.ralphrc` too restrictive
|
|
321
325
|
|
|
322
326
|
**Solutions:**
|
|
323
|
-
1. Update `ALLOWED_TOOLS` in `.ralphrc` to include needed tools
|
|
324
|
-
2. Reset circuit breaker: `ralph --reset-circuit`
|
|
327
|
+
1. Update `ALLOWED_TOOLS` in `.ralph/.ralphrc` to include needed tools
|
|
328
|
+
2. Reset circuit breaker: `bash .ralph/ralph_loop.sh --reset-circuit`
|
|
325
329
|
3. Common tools: `Write,Read,Edit,Bash(git *),Bash(npm *),Bash(pytest)`
|
|
326
330
|
|
|
327
331
|
#### Session expires mid-project
|
|
@@ -334,32 +338,32 @@ When using `--monitor` with `--live`, tmux creates a 3-pane layout:
|
|
|
334
338
|
|
|
335
339
|
**Solutions:**
|
|
336
340
|
1. Sessions are designed to expire after 24h (configurable via `SESSION_EXPIRY_HOURS`)
|
|
337
|
-
2. Start a new session with `ralph --reset-session`
|
|
338
|
-
3. Context will be rebuilt from fix_plan.md and specs
|
|
341
|
+
2. Start a new session with `bash .ralph/ralph_loop.sh --reset-session`
|
|
342
|
+
3. Context will be rebuilt from `@fix_plan.md` and `specs/`
|
|
339
343
|
|
|
340
344
|
### Diagnostic Commands
|
|
341
345
|
|
|
342
346
|
```bash
|
|
343
347
|
# Check Ralph status
|
|
344
|
-
ralph --status
|
|
348
|
+
bash .ralph/ralph_loop.sh --status
|
|
345
349
|
|
|
346
350
|
# Check circuit breaker state
|
|
347
|
-
ralph --circuit-status
|
|
351
|
+
bash .ralph/ralph_loop.sh --circuit-status
|
|
348
352
|
|
|
349
353
|
# Reset circuit breaker
|
|
350
|
-
ralph --reset-circuit
|
|
354
|
+
bash .ralph/ralph_loop.sh --reset-circuit
|
|
351
355
|
|
|
352
356
|
# Auto-reset circuit breaker (bypasses cooldown)
|
|
353
|
-
ralph --auto-reset-circuit
|
|
357
|
+
bash .ralph/ralph_loop.sh --auto-reset-circuit
|
|
354
358
|
|
|
355
359
|
# Reset session
|
|
356
|
-
ralph --reset-session
|
|
360
|
+
bash .ralph/ralph_loop.sh --reset-session
|
|
357
361
|
|
|
358
362
|
# Enable live streaming
|
|
359
|
-
ralph --live
|
|
363
|
+
bash .ralph/ralph_loop.sh --live
|
|
360
364
|
|
|
361
365
|
# Live streaming with monitoring
|
|
362
|
-
ralph --monitor --live
|
|
366
|
+
bash .ralph/ralph_loop.sh --monitor --live
|
|
363
367
|
```
|
|
364
368
|
|
|
365
369
|
### Log Files
|
|
@@ -112,7 +112,49 @@ driver_supports_sessions() {
|
|
|
112
112
|
return 0 # true
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
#
|
|
115
|
+
# Claude Code supports stream-json live output.
|
|
116
|
+
driver_supports_live_output() {
|
|
117
|
+
return 0 # true
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Prepare command arguments for live stream-json output.
|
|
121
|
+
driver_prepare_live_command() {
|
|
122
|
+
LIVE_CMD_ARGS=()
|
|
123
|
+
local skip_next=false
|
|
124
|
+
|
|
125
|
+
for arg in "${CLAUDE_CMD_ARGS[@]}"; do
|
|
126
|
+
if [[ "$skip_next" == "true" ]]; then
|
|
127
|
+
LIVE_CMD_ARGS+=("stream-json")
|
|
128
|
+
skip_next=false
|
|
129
|
+
elif [[ "$arg" == "--output-format" ]]; then
|
|
130
|
+
LIVE_CMD_ARGS+=("$arg")
|
|
131
|
+
skip_next=true
|
|
132
|
+
else
|
|
133
|
+
LIVE_CMD_ARGS+=("$arg")
|
|
134
|
+
fi
|
|
135
|
+
done
|
|
136
|
+
|
|
137
|
+
if [[ "$skip_next" == "true" ]]; then
|
|
138
|
+
return 1
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
LIVE_CMD_ARGS+=("--verbose" "--include-partial-messages")
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Stream filter for raw Claude stream-json events.
|
|
116
145
|
driver_stream_filter() {
|
|
117
|
-
echo '
|
|
146
|
+
echo '
|
|
147
|
+
if .type == "stream_event" then
|
|
148
|
+
if .event.type == "content_block_delta" and .event.delta.type == "text_delta" then
|
|
149
|
+
.event.delta.text
|
|
150
|
+
elif .event.type == "content_block_start" and .event.content_block.type == "tool_use" then
|
|
151
|
+
"\n\n⚡ [" + .event.content_block.name + "]\n"
|
|
152
|
+
elif .event.type == "content_block_stop" then
|
|
153
|
+
"\n"
|
|
154
|
+
else
|
|
155
|
+
empty
|
|
156
|
+
end
|
|
157
|
+
else
|
|
158
|
+
empty
|
|
159
|
+
end'
|
|
118
160
|
}
|
package/ralph/drivers/codex.sh
CHANGED
|
@@ -75,7 +75,16 @@ driver_supports_sessions() {
|
|
|
75
75
|
return 0 # true - Codex supports session resume
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
# Codex JSONL output is already suitable for live display.
|
|
79
|
+
driver_supports_live_output() {
|
|
80
|
+
return 0 # true
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
driver_prepare_live_command() {
|
|
84
|
+
LIVE_CMD_ARGS=("${CLAUDE_CMD_ARGS[@]}")
|
|
85
|
+
}
|
|
86
|
+
|
|
78
87
|
# Codex outputs JSONL events
|
|
79
88
|
driver_stream_filter() {
|
|
80
|
-
echo 'select(.type == "
|
|
89
|
+
echo 'select(.type == "item.completed" and .item.type == "agent_message") | (.item.text // ([.item.content[]? | select(.type == "output_text") | .text] | join("\n")) // empty)'
|
|
81
90
|
}
|
package/ralph/drivers/copilot.sh
CHANGED
|
@@ -82,6 +82,11 @@ driver_supports_sessions() {
|
|
|
82
82
|
return 1 # false — session IDs not capturable from -p output
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
# Copilot CLI does not expose structured live output for jq streaming.
|
|
86
|
+
driver_supports_live_output() {
|
|
87
|
+
return 1 # false
|
|
88
|
+
}
|
|
89
|
+
|
|
85
90
|
# Copilot CLI outputs plain text only (no JSON streaming).
|
|
86
91
|
# Passthrough filter — no transformation needed.
|
|
87
92
|
driver_stream_filter() {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Wrap Windows .cmd execution so GNU timeout launches a bash script instead of the .cmd directly.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
cli_path=${1:-}
|
|
7
|
+
if [[ -z "$cli_path" ]]; then
|
|
8
|
+
echo "ERROR: Missing Cursor CLI path" >&2
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
shift
|
|
13
|
+
exec "$cli_path" "$@"
|
package/ralph/drivers/cursor.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Known limitations:
|
|
6
6
|
# - CLI is in beta — binary name and flags may change
|
|
7
7
|
# - NDJSON stream format assumes {type: "text", content: "..."} events
|
|
8
|
-
# - Session
|
|
8
|
+
# - Session continuity is disabled until Cursor exposes a stable capturable session ID
|
|
9
9
|
|
|
10
10
|
driver_name() {
|
|
11
11
|
echo "cursor"
|
|
@@ -16,7 +16,15 @@ driver_display_name() {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
driver_cli_binary() {
|
|
19
|
-
|
|
19
|
+
local binary
|
|
20
|
+
binary=$(driver_resolve_cli_binary)
|
|
21
|
+
|
|
22
|
+
if [[ -n "$binary" ]]; then
|
|
23
|
+
echo "$binary"
|
|
24
|
+
return 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
echo "cursor-agent"
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
driver_min_version() {
|
|
@@ -24,7 +32,14 @@ driver_min_version() {
|
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
driver_check_available() {
|
|
27
|
-
|
|
35
|
+
local cli_binary
|
|
36
|
+
cli_binary=$(driver_cli_binary)
|
|
37
|
+
|
|
38
|
+
if [[ -f "$cli_binary" ]]; then
|
|
39
|
+
return 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
command -v "$cli_binary" &>/dev/null
|
|
28
43
|
}
|
|
29
44
|
|
|
30
45
|
# Cursor CLI tool names
|
|
@@ -46,14 +61,21 @@ driver_build_command() {
|
|
|
46
61
|
local prompt_file=$1
|
|
47
62
|
local loop_context=$2
|
|
48
63
|
local session_id=$3
|
|
49
|
-
|
|
50
|
-
|
|
64
|
+
local cli_binary
|
|
65
|
+
cli_binary=$(driver_cli_binary)
|
|
51
66
|
|
|
52
67
|
if [[ ! -f "$prompt_file" ]]; then
|
|
53
68
|
echo "ERROR: Prompt file not found: $prompt_file" >&2
|
|
54
69
|
return 1
|
|
55
70
|
fi
|
|
56
71
|
|
|
72
|
+
CLAUDE_CMD_ARGS=()
|
|
73
|
+
if [[ "$cli_binary" == *.cmd ]]; then
|
|
74
|
+
CLAUDE_CMD_ARGS+=("$(driver_wrapper_path)" "$cli_binary")
|
|
75
|
+
else
|
|
76
|
+
CLAUDE_CMD_ARGS+=("$cli_binary")
|
|
77
|
+
fi
|
|
78
|
+
|
|
57
79
|
# Headless mode
|
|
58
80
|
CLAUDE_CMD_ARGS+=("--print")
|
|
59
81
|
|
|
@@ -63,28 +85,170 @@ driver_build_command() {
|
|
|
63
85
|
# NDJSON streaming output
|
|
64
86
|
CLAUDE_CMD_ARGS+=("--output-format" "stream-json")
|
|
65
87
|
|
|
66
|
-
# Session resume — gated on CLAUDE_USE_CONTINUE to respect --no-continue flag
|
|
67
|
-
if [[ "$CLAUDE_USE_CONTINUE" == "true" && -n "$session_id" ]]; then
|
|
68
|
-
CLAUDE_CMD_ARGS+=("--resume" "$session_id")
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
88
|
# Build prompt with context prepended
|
|
72
89
|
local prompt_content
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
if driver_running_on_windows; then
|
|
91
|
+
prompt_content=$(driver_build_windows_bootstrap_prompt "$loop_context" "$prompt_file")
|
|
92
|
+
else
|
|
93
|
+
prompt_content=$(cat "$prompt_file")
|
|
94
|
+
if [[ -n "$loop_context" ]]; then
|
|
95
|
+
prompt_content="$loop_context
|
|
76
96
|
|
|
77
97
|
$prompt_content"
|
|
98
|
+
fi
|
|
78
99
|
fi
|
|
79
100
|
|
|
80
101
|
CLAUDE_CMD_ARGS+=("$prompt_content")
|
|
81
102
|
}
|
|
82
103
|
|
|
83
104
|
driver_supports_sessions() {
|
|
84
|
-
return
|
|
105
|
+
return 1 # false — session IDs are not capturable from current NDJSON output
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
driver_supports_live_output() {
|
|
109
|
+
return 0 # true
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
driver_prepare_live_command() {
|
|
113
|
+
LIVE_CMD_ARGS=("${CLAUDE_CMD_ARGS[@]}")
|
|
85
114
|
}
|
|
86
115
|
|
|
87
116
|
# Cursor CLI outputs NDJSON events
|
|
88
117
|
driver_stream_filter() {
|
|
89
118
|
echo 'select(.type == "text") | .content // empty'
|
|
90
119
|
}
|
|
120
|
+
|
|
121
|
+
driver_running_on_windows() {
|
|
122
|
+
[[ "${OS:-}" == "Windows_NT" || "${OSTYPE:-}" == msys* || "${OSTYPE:-}" == cygwin* || "${OSTYPE:-}" == win32* ]]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
driver_resolve_cli_binary() {
|
|
126
|
+
local candidate
|
|
127
|
+
local resolved
|
|
128
|
+
local fallback
|
|
129
|
+
local candidates=(
|
|
130
|
+
"cursor-agent"
|
|
131
|
+
"cursor-agent.cmd"
|
|
132
|
+
"agent"
|
|
133
|
+
"agent.cmd"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
for candidate in "${candidates[@]}"; do
|
|
137
|
+
resolved=$(driver_lookup_cli_candidate "$candidate")
|
|
138
|
+
if [[ -n "$resolved" ]]; then
|
|
139
|
+
echo "$resolved"
|
|
140
|
+
return 0
|
|
141
|
+
fi
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
fallback=$(driver_localappdata_cli_binary)
|
|
145
|
+
if [[ -n "$fallback" ]]; then
|
|
146
|
+
echo "$fallback"
|
|
147
|
+
return 0
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
echo ""
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
driver_lookup_cli_candidate() {
|
|
154
|
+
local candidate=$1
|
|
155
|
+
local resolved
|
|
156
|
+
|
|
157
|
+
resolved=$(command -v "$candidate" 2>/dev/null || true)
|
|
158
|
+
if [[ -n "$resolved" ]]; then
|
|
159
|
+
echo "$resolved"
|
|
160
|
+
return 0
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
if ! driver_running_on_windows; then
|
|
164
|
+
return 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
driver_find_windows_path_candidate "$candidate"
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
driver_find_windows_path_candidate() {
|
|
171
|
+
local candidate=$1
|
|
172
|
+
local path_entry
|
|
173
|
+
local normalized_entry
|
|
174
|
+
local resolved_candidate
|
|
175
|
+
local path_entries="${PATH:-}"
|
|
176
|
+
local -a path_parts=()
|
|
177
|
+
|
|
178
|
+
if [[ "$path_entries" == *";"* ]]; then
|
|
179
|
+
IFS=';' read -r -a path_parts <<< "$path_entries"
|
|
180
|
+
else
|
|
181
|
+
IFS=':' read -r -a path_parts <<< "$path_entries"
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
for path_entry in "${path_parts[@]}"; do
|
|
185
|
+
[[ -z "$path_entry" ]] && continue
|
|
186
|
+
|
|
187
|
+
normalized_entry=$path_entry
|
|
188
|
+
if command -v cygpath &>/dev/null && [[ "$normalized_entry" =~ ^[A-Za-z]:\\ ]]; then
|
|
189
|
+
normalized_entry=$(cygpath -u "$normalized_entry")
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
resolved_candidate="$normalized_entry/$candidate"
|
|
193
|
+
if [[ -f "$resolved_candidate" ]]; then
|
|
194
|
+
echo "$resolved_candidate"
|
|
195
|
+
return 0
|
|
196
|
+
fi
|
|
197
|
+
done
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
driver_localappdata_cli_binary() {
|
|
201
|
+
local local_app_data="${LOCALAPPDATA:-}"
|
|
202
|
+
|
|
203
|
+
if [[ -z "$local_app_data" ]] || ! driver_running_on_windows; then
|
|
204
|
+
return 0
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
if command -v cygpath &>/dev/null && [[ "$local_app_data" =~ ^[A-Za-z]:\\ ]]; then
|
|
208
|
+
local_app_data=$(cygpath -u "$local_app_data")
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
local candidate="$local_app_data/cursor-agent/agent.cmd"
|
|
212
|
+
if [[ -f "$candidate" ]]; then
|
|
213
|
+
echo "$candidate"
|
|
214
|
+
fi
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
driver_wrapper_path() {
|
|
218
|
+
local driver_dir
|
|
219
|
+
driver_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
220
|
+
echo "$driver_dir/cursor-agent-wrapper.sh"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
driver_build_windows_bootstrap_prompt() {
|
|
224
|
+
local loop_context=$1
|
|
225
|
+
local prompt_file=$2
|
|
226
|
+
|
|
227
|
+
cat <<EOF
|
|
228
|
+
Read these Ralph workspace files before taking action:
|
|
229
|
+
- .ralph/PROMPT.md
|
|
230
|
+
- .ralph/PROJECT_CONTEXT.md
|
|
231
|
+
- .ralph/SPECS_INDEX.md
|
|
232
|
+
- .ralph/@fix_plan.md
|
|
233
|
+
- .ralph/@AGENT.md
|
|
234
|
+
- relevant files under .ralph/specs/
|
|
235
|
+
|
|
236
|
+
Then follow the Ralph instructions from those files and continue the next task.
|
|
237
|
+
EOF
|
|
238
|
+
|
|
239
|
+
if [[ -n "$loop_context" ]]; then
|
|
240
|
+
cat <<EOF
|
|
241
|
+
|
|
242
|
+
Current loop context:
|
|
243
|
+
$loop_context
|
|
244
|
+
EOF
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
if [[ "$prompt_file" != ".ralph/PROMPT.md" ]]; then
|
|
248
|
+
cat <<EOF
|
|
249
|
+
|
|
250
|
+
Also read the active prompt file if it differs:
|
|
251
|
+
- $prompt_file
|
|
252
|
+
EOF
|
|
253
|
+
fi
|
|
254
|
+
}
|
|
@@ -463,16 +463,16 @@ should_halt_execution() {
|
|
|
463
463
|
echo -e "${YELLOW}Ralph has detected that no progress is being made.${NC}"
|
|
464
464
|
echo ""
|
|
465
465
|
echo -e "${YELLOW}Possible reasons:${NC}"
|
|
466
|
-
echo " • Project may be complete (check .ralph
|
|
467
|
-
echo " •
|
|
466
|
+
echo " • Project may be complete (check .ralph/@fix_plan.md)"
|
|
467
|
+
echo " • The active driver may be stuck on an error"
|
|
468
468
|
echo " • .ralph/PROMPT.md may need clarification"
|
|
469
469
|
echo " • Manual intervention may be required"
|
|
470
470
|
echo ""
|
|
471
471
|
echo -e "${YELLOW}To continue:${NC}"
|
|
472
472
|
echo " 1. Review recent logs: tail -20 .ralph/logs/ralph.log"
|
|
473
|
-
echo " 2. Check
|
|
474
|
-
echo " 3. Update .ralph
|
|
475
|
-
echo " 4. Reset circuit breaker: ralph --reset-circuit"
|
|
473
|
+
echo " 2. Check recent driver output: ls -lt .ralph/logs/claude_output_*.log | head -1"
|
|
474
|
+
echo " 3. Update .ralph/@fix_plan.md if needed"
|
|
475
|
+
echo " 4. Reset circuit breaker: bash .ralph/ralph_loop.sh --reset-circuit"
|
|
476
476
|
echo ""
|
|
477
477
|
return 0 # Signal to halt
|
|
478
478
|
else
|