@wavilikhin/ralph-wiggum 0.1.14 → 0.1.16
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 +80 -297
- package/package.json +1 -1
- package/src/cli.js +4 -3
- package/templates/ralph-loop.sh +64 -18
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ralph Wiggum
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@wavilikhin/ralph-wiggum)
|
|
4
|
-
[](https://github.com/wavilikhin/ralph-wiggum/actions/workflows/publish.yml)
|
|
5
5
|
|
|
6
6
|
```
|
|
7
7
|
____ _ _ __ ___
|
|
@@ -12,171 +12,71 @@
|
|
|
12
12
|
|_| |___/
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Ralph Wiggum is a tiny wrapper around the “autonomous loop” pattern: run an AI coding agent repeatedly, but keep each iteration small and strict.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
# npm
|
|
19
|
-
npx @wavilikhin/ralph-wiggum init
|
|
20
|
-
|
|
21
|
-
# bun
|
|
22
|
-
bunx @wavilikhin/ralph-wiggum init
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Or install globally:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
# npm
|
|
29
|
-
npm install -g @wavilikhin/ralph-wiggum
|
|
30
|
-
|
|
31
|
-
# bun
|
|
32
|
-
bun install -g @wavilikhin/ralph-wiggum
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
This is a near-vanilla implementation of the [Ralph Wiggum autonomous loop](https://ghuntley.com/ralph/) pattern by Geoffrey Huntley. The core idea: run an AI coding agent in a loop where each iteration gets fresh context, picks exactly one task, implements it, validates it passes all checks, commits, and repeats until done. This produces clean atomic commits and avoids context window bloat.
|
|
38
|
-
|
|
39
|
-
Built for [OpenCode](https://opencode.ai), but should work with any CLI-based coding agent that can read files and run commands.
|
|
40
|
-
|
|
41
|
-
**Additions to the original pattern:**
|
|
42
|
-
- `npx` initialization that scaffolds everything into a `.ralph/` directory
|
|
43
|
-
- Structured logging with timestamps (`.ralph/logs/ralph.log`)
|
|
44
|
-
- `--verbose` flag to preserve full agent output per iteration
|
|
45
|
-
- Enforces exactly one commit per iteration (fails if zero or multiple)
|
|
46
|
-
- Verifies clean working tree after each iteration
|
|
47
|
-
- Phases-based `IMPLEMENTATION_PLAN.md` template
|
|
48
|
-
|
|
49
|
-
---
|
|
17
|
+
Origin: the [Ralph Wiggum autonomous loop](https://ghuntley.com/ralph/) pattern by Geoffrey Huntley.
|
|
50
18
|
|
|
51
|
-
|
|
19
|
+
Each iteration:
|
|
20
|
+
- starts with fresh context (new process)
|
|
21
|
+
- completes exactly one plan item
|
|
22
|
+
- runs your repo’s validation commands
|
|
23
|
+
- creates exactly one local git commit
|
|
52
24
|
|
|
53
|
-
|
|
25
|
+
This keeps context focused and your history clean.
|
|
54
26
|
|
|
55
|
-
|
|
56
|
-
2. Picks **exactly one task** from your implementation plan
|
|
57
|
-
3. Implements it and runs **validation gates** (lint, test, build)
|
|
58
|
-
4. Creates **exactly one commit** (local only, no push)
|
|
59
|
-
5. Repeats until all tasks are complete
|
|
27
|
+
## Install
|
|
60
28
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## Model Requirements
|
|
64
|
-
|
|
65
|
-
> **Warning**: Ralph Wiggum requires the latest generation of AI models to work reliably.
|
|
66
|
-
>
|
|
67
|
-
> The autonomous loop requires models capable of:
|
|
68
|
-
> - Following complex multi-step instructions precisely
|
|
69
|
-
> - Making exactly one commit per iteration
|
|
70
|
-
> - Running validation commands and fixing failures
|
|
71
|
-
> - Updating state files accurately
|
|
72
|
-
>
|
|
73
|
-
> **Recommended models:**
|
|
74
|
-
> - `anthropic/claude-opus-4-20250514`
|
|
75
|
-
> - `openai/gpt-5.2`
|
|
76
|
-
>
|
|
77
|
-
> Using older or less capable models will likely result in failed iterations.
|
|
78
|
-
|
|
79
|
-
## Prerequisites
|
|
80
|
-
|
|
81
|
-
- [OpenCode CLI](https://opencode.ai) installed and configured (or another CLI agent)
|
|
82
|
-
- Node.js 18+
|
|
83
|
-
- Git repository
|
|
84
|
-
- **AGENTS.md file in your repo root** (see below)
|
|
29
|
+
No global install needed:
|
|
85
30
|
|
|
86
31
|
```bash
|
|
87
|
-
|
|
88
|
-
opencode --version
|
|
89
|
-
|
|
90
|
-
# List available models
|
|
91
|
-
opencode models
|
|
32
|
+
npx @wavilikhin/ralph-wiggum init
|
|
92
33
|
```
|
|
93
34
|
|
|
94
|
-
|
|
35
|
+
(Inside an existing git repo.)
|
|
95
36
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
Your `AGENTS.md` must include:
|
|
99
|
-
|
|
100
|
-
1. **Validation commands** - How to run formatting, linting, type checking, and tests
|
|
101
|
-
2. **Project structure** - Overview of your codebase layout
|
|
102
|
-
3. **Coding standards** - Any conventions the agent should follow
|
|
103
|
-
|
|
104
|
-
Example minimal `AGENTS.md`:
|
|
105
|
-
|
|
106
|
-
```markdown
|
|
107
|
-
## Validation Commands
|
|
37
|
+
## Quick start
|
|
108
38
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
3. Typecheck: `npm run typecheck`
|
|
114
|
-
4. Test: `npm test`
|
|
115
|
-
|
|
116
|
-
## Project Structure
|
|
117
|
-
|
|
118
|
-
- `src/` - Source code
|
|
119
|
-
- `tests/` - Test files
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
See [OpenCode AGENTS.md documentation](https://opencode.ai/docs/agents-md) for best practices.
|
|
123
|
-
|
|
124
|
-
## Quick Start
|
|
39
|
+
1) Ensure you have prerequisites:
|
|
40
|
+
- Node.js 18+
|
|
41
|
+
- `opencode` installed and configured (or another CLI agent)
|
|
42
|
+
- a repo-root `AGENTS.md` that lists your validation commands
|
|
125
43
|
|
|
126
|
-
|
|
44
|
+
2) Scaffold `.ralph/`:
|
|
127
45
|
|
|
128
46
|
```bash
|
|
129
|
-
cd your-project
|
|
130
47
|
npx @wavilikhin/ralph-wiggum init
|
|
131
48
|
```
|
|
132
49
|
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- `run.sh` - The loop runner
|
|
137
|
-
- `logs/` - Directory for iteration logs
|
|
138
|
-
|
|
139
|
-
### 2. Fill in your implementation plan
|
|
140
|
-
|
|
141
|
-
Edit `.ralph/IMPLEMENTATION_PLAN.md` with your tasks:
|
|
142
|
-
|
|
143
|
-
```markdown
|
|
144
|
-
## Phase 1: Foundation
|
|
145
|
-
|
|
146
|
-
- [ ] Set up project structure with src/ and tests/ directories
|
|
147
|
-
- [ ] Add TypeScript configuration
|
|
148
|
-
- [ ] Create initial CI pipeline
|
|
149
|
-
|
|
150
|
-
## Phase 2: Core Implementation
|
|
151
|
-
|
|
152
|
-
- [ ] Implement user authentication module
|
|
153
|
-
- [ ] Add database connection layer
|
|
154
|
-
- [ ] Create REST API endpoints
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Use the checkbox format (`- [ ]` / `- [x]`) - the agent marks tasks complete as it works.
|
|
50
|
+
3) Fill in tasks:
|
|
51
|
+
- Edit `.ralph/IMPLEMENTATION_PLAN.md`
|
|
52
|
+
- Use checkboxes (`- [ ]`, `- [x]`)
|
|
158
53
|
|
|
159
|
-
|
|
54
|
+
4) Run the loop:
|
|
160
55
|
|
|
161
56
|
```bash
|
|
162
57
|
.ralph/run.sh --max-iterations 20 --model anthropic/claude-opus-4-20250514
|
|
163
58
|
```
|
|
164
59
|
|
|
165
|
-
The loop
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
60
|
+
The loop stops when either:
|
|
61
|
+
- all tasks are checked off and the agent outputs `<promise>COMPLETE</promise>`
|
|
62
|
+
- `--max-iterations` is reached
|
|
63
|
+
- you press Ctrl+C
|
|
169
64
|
|
|
170
|
-
##
|
|
65
|
+
## Flags
|
|
66
|
+
|
|
67
|
+
`ralph-wiggum init` scaffolds files. The loop itself is controlled via `.ralph/run.sh`.
|
|
68
|
+
|
|
69
|
+
Any additional flags are forwarded to `opencode run`.
|
|
171
70
|
|
|
172
71
|
```bash
|
|
173
72
|
.ralph/run.sh [options]
|
|
174
73
|
|
|
175
74
|
Options:
|
|
176
|
-
--max-iterations N Maximum iterations (default: 50)
|
|
75
|
+
--max-iterations N Maximum iterations before stopping (default: 50)
|
|
177
76
|
--model MODEL Model to use (default: anthropic/claude-opus-4-20250514)
|
|
178
|
-
--variant NAME Optional variant name
|
|
179
|
-
--verbose
|
|
77
|
+
--variant NAME Optional variant name passed to opencode
|
|
78
|
+
--verbose Keep per-iteration logs (.ralph/logs/ralph_iter_N.log)
|
|
79
|
+
--live Stream opencode output (requires --verbose)
|
|
180
80
|
--help Show help
|
|
181
81
|
|
|
182
82
|
Environment variables:
|
|
@@ -184,193 +84,76 @@ Environment variables:
|
|
|
184
84
|
RALPH_MODEL Default model
|
|
185
85
|
```
|
|
186
86
|
|
|
187
|
-
##
|
|
188
|
-
|
|
189
|
-
Ralph Wiggum maintains two types of logs in `.ralph/logs/`:
|
|
87
|
+
## What gets created
|
|
190
88
|
|
|
191
|
-
|
|
89
|
+
`init` creates a `.ralph/` directory:
|
|
90
|
+
- `.ralph/PROMPT.md` – instructions the agent reads every iteration
|
|
91
|
+
- `.ralph/IMPLEMENTATION_PLAN.md` – your checklist of tasks
|
|
92
|
+
- `.ralph/run.sh` – the loop runner
|
|
93
|
+
- `.ralph/logs/` – log directory (ignored via `.gitignore`)
|
|
192
94
|
|
|
193
|
-
|
|
95
|
+
## Logs
|
|
194
96
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
[2025-01-19 14:32:47] [ITER] === Iteration 1 FINISHED: SUCCESS (152s) - feat: add user auth module ===
|
|
198
|
-
[2025-01-19 14:32:48] [ITER] === Iteration 2/20 STARTED ===
|
|
199
|
-
```
|
|
97
|
+
- `.ralph/logs/ralph.log` is always written (timestamps + iteration status).
|
|
98
|
+
- `.ralph/logs/ralph_iter_N.log` is kept only with `--verbose` (or on failures).
|
|
200
99
|
|
|
201
|
-
|
|
100
|
+
Watch progress:
|
|
202
101
|
|
|
203
102
|
```bash
|
|
204
|
-
# Watch progress in real-time
|
|
205
103
|
tail -f .ralph/logs/ralph.log
|
|
206
104
|
```
|
|
207
105
|
|
|
208
|
-
|
|
106
|
+
## Safety
|
|
209
107
|
|
|
210
|
-
|
|
108
|
+
- Never pushes: commits are local only.
|
|
109
|
+
- Enforces one commit per iteration.
|
|
110
|
+
- Requires a clean working tree after each iteration.
|
|
211
111
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
On failure, the iteration log is always preserved for debugging.
|
|
217
|
-
|
|
218
|
-
## Examples
|
|
219
|
-
|
|
220
|
-
### Run with Claude Opus 4
|
|
221
|
-
|
|
222
|
-
```bash
|
|
223
|
-
.ralph/run.sh --max-iterations 10 --model anthropic/claude-opus-4-20250514
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
### Run with GPT-5.2
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
.ralph/run.sh --max-iterations 10 --model openai/gpt-5.2
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Run with environment variables
|
|
233
|
-
|
|
234
|
-
```bash
|
|
235
|
-
export RALPH_MODEL="anthropic/claude-opus-4-20250514"
|
|
236
|
-
export RALPH_MAX_ITERATIONS=30
|
|
237
|
-
.ralph/run.sh
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Dry run (single iteration)
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
.ralph/run.sh --max-iterations 1
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Debug mode (verbose + single iteration)
|
|
247
|
-
|
|
248
|
-
```bash
|
|
249
|
-
.ralph/run.sh --verbose --max-iterations 1
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
## How It Works
|
|
253
|
-
|
|
254
|
-
```
|
|
255
|
-
.ralph/run.sh
|
|
256
|
-
|
|
|
257
|
-
v
|
|
258
|
-
+---------------------------------------+
|
|
259
|
-
| Iteration N |
|
|
260
|
-
| +----------------------------------+ |
|
|
261
|
-
| | 1. Record git HEAD | |
|
|
262
|
-
| | 2. Run: opencode run ... | |
|
|
263
|
-
| | 3. Agent reads PROMPT.md | |
|
|
264
|
-
| | 4. Agent picks ONE task | |
|
|
265
|
-
| | 5. Agent implements + validates | |
|
|
266
|
-
| | 6. Agent commits (local only) | |
|
|
267
|
-
| | 7. Check: exactly 1 commit? | |
|
|
268
|
-
| | 8. Check: working tree clean? | |
|
|
269
|
-
| | 9. Check: COMPLETE marker? | |
|
|
270
|
-
| +----------------------------------+ |
|
|
271
|
-
+---------------------------------------+
|
|
272
|
-
|
|
|
273
|
-
+------------+------------+
|
|
274
|
-
v v
|
|
275
|
-
[COMPLETE] [Continue]
|
|
276
|
-
Exit 0 Iteration N+1
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
Each iteration is a fresh `opencode run` process, so the agent:
|
|
280
|
-
- Has no memory of previous iterations
|
|
281
|
-
- Must re-read PROMPT.md, AGENTS.md, IMPLEMENTATION_PLAN.md
|
|
282
|
-
- Stays focused on one task at a time
|
|
112
|
+
<details>
|
|
113
|
+
<summary><strong>AI agent appendix (full detail)</strong></summary>
|
|
283
114
|
|
|
284
|
-
|
|
115
|
+
### Model requirements
|
|
285
116
|
|
|
286
|
-
|
|
117
|
+
This loop is strict and works best with high-end models that can follow multistep instructions reliably:
|
|
118
|
+
- `anthropic/claude-opus-4-20250514`
|
|
119
|
+
- `openai/gpt-5.2`
|
|
287
120
|
|
|
288
|
-
|
|
289
|
-
your-project/
|
|
290
|
-
├── .ralph/
|
|
291
|
-
│ ├── PROMPT.md # Agent instructions (edit [CUSTOMIZABLE] sections)
|
|
292
|
-
│ ├── IMPLEMENTATION_PLAN.md # Your task list (fill this in)
|
|
293
|
-
│ ├── run.sh # Loop runner script
|
|
294
|
-
│ └── logs/
|
|
295
|
-
│ ├── ralph.log # Iteration status log
|
|
296
|
-
│ └── ralph_iter_N.log # Per-iteration logs (verbose/error only)
|
|
297
|
-
├── AGENTS.md # Your validation commands (required, you create this)
|
|
298
|
-
└── .gitignore # Updated to ignore .ralph/logs/
|
|
299
|
-
```
|
|
121
|
+
### `AGENTS.md` (repo root) is required
|
|
300
122
|
|
|
301
|
-
|
|
123
|
+
Ralph Wiggum expects a repo-root `AGENTS.md` that tells the agent how to validate changes.
|
|
302
124
|
|
|
303
|
-
|
|
125
|
+
At minimum, include:
|
|
126
|
+
- formatting command
|
|
127
|
+
- lint command
|
|
128
|
+
- typecheck command (if applicable)
|
|
129
|
+
- test command
|
|
304
130
|
|
|
305
|
-
|
|
306
|
-
- **[CUSTOMIZABLE] sections**: Add project-specific context, quality standards
|
|
307
|
-
|
|
308
|
-
### .ralph/IMPLEMENTATION_PLAN.md
|
|
309
|
-
|
|
310
|
-
Your task list. Structure it in phases:
|
|
131
|
+
Example (minimal):
|
|
311
132
|
|
|
312
133
|
```markdown
|
|
313
|
-
##
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
- [ ] Task 3
|
|
319
|
-
|
|
320
|
-
## Discovered Tasks
|
|
321
|
-
<!-- Agent adds tasks here as it finds them -->
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### AGENTS.md (your file, repo root)
|
|
325
|
-
|
|
326
|
-
Your project's agent configuration. Must exist in repo root before running.
|
|
327
|
-
|
|
328
|
-
## Safety Features
|
|
329
|
-
|
|
330
|
-
- **Local only**: Never pushes to remote
|
|
331
|
-
- **One commit per iteration**: Enforced by the loop
|
|
332
|
-
- **Clean working tree**: Verified after each iteration
|
|
333
|
-
- **Max iterations**: Hard stop to prevent runaway loops
|
|
334
|
-
- **Validation gates**: All must pass before commit
|
|
335
|
-
|
|
336
|
-
## Troubleshooting
|
|
337
|
-
|
|
338
|
-
### "opencode CLI not found"
|
|
339
|
-
|
|
340
|
-
Install OpenCode:
|
|
341
|
-
```bash
|
|
342
|
-
npm install -g opencode
|
|
134
|
+
## Validation Commands
|
|
135
|
+
1. Format: `npm run format`
|
|
136
|
+
2. Lint: `npm run lint`
|
|
137
|
+
3. Typecheck: `npm run typecheck`
|
|
138
|
+
4. Test: `npm test`
|
|
343
139
|
```
|
|
344
140
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
Create an `AGENTS.md` file in your repo root with validation commands. See the [AGENTS.md Requirement](#agentsmd-requirement) section.
|
|
348
|
-
|
|
349
|
-
### "No commit was created"
|
|
350
|
-
|
|
351
|
-
The agent must create exactly one commit per iteration. Check `.ralph/logs/ralph_iter_N.log` to see what happened. Common causes:
|
|
352
|
-
- Validation gates failed
|
|
353
|
-
- Agent got stuck on a complex task
|
|
354
|
-
- Task was already complete
|
|
355
|
-
- Model not capable enough (try a more advanced model)
|
|
356
|
-
|
|
357
|
-
### "Working tree is not clean"
|
|
141
|
+
OpenCode docs: https://opencode.ai/docs/agents-md
|
|
358
142
|
|
|
359
|
-
|
|
143
|
+
### What happens each iteration
|
|
360
144
|
|
|
361
|
-
|
|
145
|
+
- A fresh `opencode run` process starts (no memory).
|
|
146
|
+
- The agent reads (at least) `.ralph/PROMPT.md`, `.ralph/IMPLEMENTATION_PLAN.md`, and `AGENTS.md`.
|
|
147
|
+
- The agent must pick exactly one unchecked task, implement it, run all validation gates, update the plan, and make exactly one commit.
|
|
148
|
+
- When every task is complete, the agent must output exactly `<promise>COMPLETE</promise>`.
|
|
362
149
|
|
|
363
|
-
|
|
364
|
-
- Ensure validation commands in AGENTS.md are correct
|
|
365
|
-
- Try running with `--verbose --max-iterations 1` to debug a single iteration
|
|
366
|
-
- Consider using a more capable model
|
|
150
|
+
### Templates
|
|
367
151
|
|
|
368
|
-
|
|
152
|
+
Scaffolded from:
|
|
153
|
+
- `templates/PROMPT.md`
|
|
154
|
+
- `templates/IMPLEMENTATION_PLAN.md`
|
|
369
155
|
|
|
370
|
-
|
|
371
|
-
- Using `anthropic/claude-opus-4-20250514` or `openai/gpt-5.2`
|
|
372
|
-
- Simplifying tasks in IMPLEMENTATION_PLAN.md
|
|
373
|
-
- Adding more context to AGENTS.md
|
|
156
|
+
</details>
|
|
374
157
|
|
|
375
158
|
## Credits
|
|
376
159
|
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -74,10 +74,11 @@ ${YELLOW}Available loop options:${RESET}
|
|
|
74
74
|
--max-iterations N Maximum iterations before stopping (default: 50)
|
|
75
75
|
--model provider/m Model to use (default: anthropic/claude-opus-4-20250514)
|
|
76
76
|
--variant name Optional variant name passed to opencode
|
|
77
|
-
--verbose
|
|
77
|
+
--verbose Save per-iteration logs (.ralph/logs/ralph_iter_N.log)
|
|
78
|
+
--live Stream opencode output to terminal (requires --verbose)
|
|
78
79
|
|
|
79
|
-
${DIM}Logs are written to ${CYAN}.ralph/logs/ralph.log${RESET}${DIM} (iteration status)${RESET}
|
|
80
|
-
${DIM}Verbose logs: ${CYAN}.ralph/logs/ralph_iter_N.log${RESET}${DIM} (full output per iteration)${RESET}
|
|
80
|
+
${DIM}Logs are written to ${CYAN}.ralph/logs/ralph.log${RESET}${DIM} (iteration status + timings)${RESET}
|
|
81
|
+
${DIM}Verbose logs: ${CYAN}.ralph/logs/ralph_iter_N.log${RESET}${DIM} (full output per iteration, --verbose only)${RESET}
|
|
81
82
|
|
|
82
83
|
${DIM}The loop stops automatically when all tasks are complete (<promise>COMPLETE</promise>)${RESET}
|
|
83
84
|
`);
|
package/templates/ralph-loop.sh
CHANGED
|
@@ -17,6 +17,8 @@ MAX_ITERATIONS="${RALPH_MAX_ITERATIONS:-50}"
|
|
|
17
17
|
MODEL="${RALPH_MODEL:-anthropic/claude-opus-4-20250514}"
|
|
18
18
|
VARIANT=""
|
|
19
19
|
VERBOSE=false
|
|
20
|
+
LIVE=false
|
|
21
|
+
OPENCODE_ARGS=()
|
|
20
22
|
|
|
21
23
|
# All ralph files are in .ralph/
|
|
22
24
|
RALPH_DIR="$SCRIPT_DIR"
|
|
@@ -83,8 +85,11 @@ log_iteration_end() {
|
|
|
83
85
|
local iter="$1"
|
|
84
86
|
local status="$2"
|
|
85
87
|
local commit_msg="$3"
|
|
86
|
-
local
|
|
87
|
-
|
|
88
|
+
local iter_duration="$4"
|
|
89
|
+
local opencode_duration="$5"
|
|
90
|
+
log_to_file "ITER" "=== Iteration $iter FINISHED: $status (iter=${iter_duration}s, opencode=${opencode_duration}s) - $commit_msg ==="
|
|
91
|
+
echo ""
|
|
92
|
+
echo -e "${DIM}Timing: opencode=${opencode_duration}s, iteration=${iter_duration}s${NC}"
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
#=============================================================================
|
|
@@ -111,7 +116,8 @@ print_usage() {
|
|
|
111
116
|
echo " --max-iterations N Maximum iterations (default: $MAX_ITERATIONS)"
|
|
112
117
|
echo " --model MODEL Model to use (default: $MODEL)"
|
|
113
118
|
echo " --variant NAME Variant name for opencode"
|
|
114
|
-
echo " --verbose
|
|
119
|
+
echo " --verbose Save per-iteration logs (.ralph/logs/ralph_iter_N.log)"
|
|
120
|
+
echo " --live Stream opencode output to terminal (requires --verbose)"
|
|
115
121
|
echo " --help Show this help"
|
|
116
122
|
echo ""
|
|
117
123
|
echo "Environment variables:"
|
|
@@ -119,11 +125,11 @@ print_usage() {
|
|
|
119
125
|
echo " RALPH_MODEL Default model"
|
|
120
126
|
echo ""
|
|
121
127
|
echo "Logs:"
|
|
122
|
-
echo " .ralph/logs/ralph.log Iteration status (always written)"
|
|
123
|
-
echo " .ralph/logs/ralph_iter_N.log Full opencode output (verbose
|
|
128
|
+
echo " .ralph/logs/ralph.log Iteration status + timings (always written)"
|
|
129
|
+
echo " .ralph/logs/ralph_iter_N.log Full opencode output (--verbose only)"
|
|
124
130
|
echo ""
|
|
125
131
|
echo "Example:"
|
|
126
|
-
echo " $0 --max-iterations 10 --
|
|
132
|
+
echo " $0 --max-iterations 10 --verbose --live"
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
check_prerequisites() {
|
|
@@ -201,14 +207,27 @@ while [[ $# -gt 0 ]]; do
|
|
|
201
207
|
VERBOSE=true
|
|
202
208
|
shift
|
|
203
209
|
;;
|
|
210
|
+
--live)
|
|
211
|
+
LIVE=true
|
|
212
|
+
shift
|
|
213
|
+
;;
|
|
204
214
|
--help|-h)
|
|
205
215
|
print_usage
|
|
206
216
|
exit 0
|
|
207
217
|
;;
|
|
218
|
+
--)
|
|
219
|
+
shift
|
|
220
|
+
OPENCODE_ARGS+=("$@")
|
|
221
|
+
break
|
|
222
|
+
;;
|
|
208
223
|
*)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
224
|
+
if [[ $# -ge 2 && "$2" != -* ]]; then
|
|
225
|
+
OPENCODE_ARGS+=("$1" "$2")
|
|
226
|
+
shift 2
|
|
227
|
+
else
|
|
228
|
+
OPENCODE_ARGS+=("$1")
|
|
229
|
+
shift
|
|
230
|
+
fi
|
|
212
231
|
;;
|
|
213
232
|
esac
|
|
214
233
|
done
|
|
@@ -223,10 +242,17 @@ log_info "Configuration:"
|
|
|
223
242
|
echo -e " ${DIM}Max iterations:${NC} $MAX_ITERATIONS"
|
|
224
243
|
echo -e " ${DIM}Model:${NC} $MODEL"
|
|
225
244
|
echo -e " ${DIM}Verbose:${NC} $VERBOSE"
|
|
245
|
+
echo -e " ${DIM}Live output:${NC} $LIVE"
|
|
226
246
|
echo -e " ${DIM}Repo root:${NC} $REPO_ROOT"
|
|
227
247
|
[[ -n "$VARIANT" ]] && echo -e " ${DIM}Variant:${NC} $VARIANT"
|
|
228
248
|
echo ""
|
|
229
249
|
|
|
250
|
+
# Validate --live requires --verbose
|
|
251
|
+
if [[ "$LIVE" == true && "$VERBOSE" != true ]]; then
|
|
252
|
+
log_error "--live requires --verbose flag"
|
|
253
|
+
exit 1
|
|
254
|
+
fi
|
|
255
|
+
|
|
230
256
|
check_prerequisites
|
|
231
257
|
|
|
232
258
|
mkdir -p "$LOGS_DIR"
|
|
@@ -249,6 +275,7 @@ cd "$REPO_ROOT"
|
|
|
249
275
|
for i in $(seq 1 "$MAX_ITERATIONS"); do
|
|
250
276
|
ITER_START=$(date +%s)
|
|
251
277
|
ITER_LOG_FILE="$LOGS_DIR/ralph_iter_${i}.log"
|
|
278
|
+
LIVE_PREFIX=" ${DIM}[LIVE ${i}/${MAX_ITERATIONS}]${NC} "
|
|
252
279
|
|
|
253
280
|
log_iteration_start "$i" "$MAX_ITERATIONS"
|
|
254
281
|
|
|
@@ -265,28 +292,47 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
|
|
|
265
292
|
if [[ -n "$VARIANT" ]]; then
|
|
266
293
|
OPENCODE_CMD+=(--variant "$VARIANT")
|
|
267
294
|
fi
|
|
295
|
+
|
|
296
|
+
if [[ ${#OPENCODE_ARGS[@]} -gt 0 ]]; then
|
|
297
|
+
OPENCODE_CMD+=("${OPENCODE_ARGS[@]}")
|
|
298
|
+
fi
|
|
268
299
|
|
|
269
300
|
OPENCODE_CMD+=("Follow the attached PROMPT.md. Use AGENTS.md for validation commands and IMPLEMENTATION_PLAN.md for task selection. Do exactly one task and one commit.")
|
|
270
301
|
|
|
271
302
|
log_info "Running opencode..."
|
|
272
303
|
|
|
304
|
+
OPENCODE_START=$(date +%s)
|
|
305
|
+
|
|
273
306
|
set +e
|
|
274
|
-
if [[ "$
|
|
275
|
-
|
|
307
|
+
if [[ "$LIVE" == true ]]; then
|
|
308
|
+
# Stream to terminal AND write to log file
|
|
309
|
+
# Prefix each opencode line so it doesn't visually clash with ralph logs.
|
|
310
|
+
"${OPENCODE_CMD[@]}" 2>&1 | while IFS= read -r line; do printf '%b%s\n' "$LIVE_PREFIX" "$line"; done | tee "$ITER_LOG_FILE"
|
|
311
|
+
EXIT_CODE=${PIPESTATUS[0]}
|
|
312
|
+
OUTPUT=$(cat "$ITER_LOG_FILE")
|
|
313
|
+
elif [[ "$VERBOSE" == true ]]; then
|
|
314
|
+
# Write to log file only (no terminal stream)
|
|
315
|
+
"${OPENCODE_CMD[@]}" > "$ITER_LOG_FILE" 2>&1
|
|
316
|
+
EXIT_CODE=$?
|
|
317
|
+
OUTPUT=$(cat "$ITER_LOG_FILE")
|
|
276
318
|
else
|
|
319
|
+
# Capture output, write temp file for error inspection
|
|
277
320
|
OUTPUT=$("${OPENCODE_CMD[@]}" 2>&1)
|
|
321
|
+
EXIT_CODE=$?
|
|
278
322
|
echo "$OUTPUT" > "$ITER_LOG_FILE"
|
|
279
323
|
fi
|
|
280
|
-
EXIT_CODE=$?
|
|
281
324
|
set -e
|
|
282
325
|
|
|
326
|
+
OPENCODE_END=$(date +%s)
|
|
327
|
+
OPENCODE_DURATION=$((OPENCODE_END - OPENCODE_START))
|
|
328
|
+
|
|
283
329
|
ITER_END=$(date +%s)
|
|
284
330
|
ITER_DURATION=$((ITER_END - ITER_START))
|
|
285
331
|
|
|
286
332
|
if [[ $EXIT_CODE -ne 0 ]]; then
|
|
287
333
|
log_error "opencode exited with code $EXIT_CODE"
|
|
288
334
|
log_error "Check log: $ITER_LOG_FILE"
|
|
289
|
-
log_iteration_end "$i" "FAILED" "opencode error" "$ITER_DURATION"
|
|
335
|
+
log_iteration_end "$i" "FAILED" "opencode error" "$ITER_DURATION" "$OPENCODE_DURATION"
|
|
290
336
|
exit 1
|
|
291
337
|
fi
|
|
292
338
|
|
|
@@ -295,7 +341,7 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
|
|
|
295
341
|
log_success "All tasks complete!"
|
|
296
342
|
echo ""
|
|
297
343
|
echo -e "${GREEN}${BOLD}Loop finished successfully after $i iteration(s)${NC}"
|
|
298
|
-
log_iteration_end "$i" "COMPLETE" "all tasks done" "$ITER_DURATION"
|
|
344
|
+
log_iteration_end "$i" "COMPLETE" "all tasks done" "$ITER_DURATION" "$OPENCODE_DURATION"
|
|
299
345
|
log_to_file "INFO" "=== LOOP COMPLETED SUCCESSFULLY ==="
|
|
300
346
|
exit 0
|
|
301
347
|
fi
|
|
@@ -307,14 +353,14 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
|
|
|
307
353
|
log_error "No commit was created in this iteration!"
|
|
308
354
|
log_error "The agent must create exactly one commit per iteration."
|
|
309
355
|
log_error "Check log: $ITER_LOG_FILE"
|
|
310
|
-
log_iteration_end "$i" "FAILED" "no commit created" "$ITER_DURATION"
|
|
356
|
+
log_iteration_end "$i" "FAILED" "no commit created" "$ITER_DURATION" "$OPENCODE_DURATION"
|
|
311
357
|
exit 1
|
|
312
358
|
fi
|
|
313
359
|
|
|
314
360
|
COMMIT_COUNT=$(git rev-list --count "$BEFORE_HEAD".."$AFTER_HEAD")
|
|
315
361
|
if [[ "$COMMIT_COUNT" -ne 1 ]]; then
|
|
316
362
|
log_error "Expected 1 commit, but $COMMIT_COUNT were created!"
|
|
317
|
-
log_iteration_end "$i" "FAILED" "multiple commits" "$ITER_DURATION"
|
|
363
|
+
log_iteration_end "$i" "FAILED" "multiple commits" "$ITER_DURATION" "$OPENCODE_DURATION"
|
|
318
364
|
exit 1
|
|
319
365
|
fi
|
|
320
366
|
|
|
@@ -322,13 +368,13 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
|
|
|
322
368
|
log_error "Working tree is not clean after iteration!"
|
|
323
369
|
echo ""
|
|
324
370
|
git status --short
|
|
325
|
-
log_iteration_end "$i" "FAILED" "dirty working tree" "$ITER_DURATION"
|
|
371
|
+
log_iteration_end "$i" "FAILED" "dirty working tree" "$ITER_DURATION" "$OPENCODE_DURATION"
|
|
326
372
|
exit 1
|
|
327
373
|
fi
|
|
328
374
|
|
|
329
375
|
COMMIT_MSG=$(git log -1 --format='%s')
|
|
330
376
|
log_success "Commit created: $COMMIT_MSG"
|
|
331
|
-
log_iteration_end "$i" "SUCCESS" "$COMMIT_MSG" "$ITER_DURATION"
|
|
377
|
+
log_iteration_end "$i" "SUCCESS" "$COMMIT_MSG" "$ITER_DURATION" "$OPENCODE_DURATION"
|
|
332
378
|
|
|
333
379
|
if [[ "$VERBOSE" != true ]]; then
|
|
334
380
|
rm -f "$ITER_LOG_FILE"
|