@wavilikhin/ralph-wiggum 0.1.14 → 0.1.15

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 CHANGED
@@ -1,182 +1,69 @@
1
1
  # Ralph Wiggum
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@wavilikhin/ralph-wiggum.svg)](https://www.npmjs.com/package/@wavilikhin/ralph-wiggum)
4
- [![npm publish](https://github.com/wavilikhin/ralph-wiggum/actions/workflows/publish.yml/badge.svg?event=push)](https://github.com/wavilikhin/ralph-wiggum/actions/workflows/publish.yml)
4
+ [![npm publish](https://github.com/wavilikhin/ralph-wiggum/actions/workflows/publish.yml/badge.svg)](https://github.com/wavilikhin/ralph-wiggum/actions/workflows/publish.yml)
5
5
 
6
- ```
7
- ____ _ _ __ ___
8
- | _ \ __ _| |_ __ | |__ \ \ / (_) __ _ _ _ _ _ _ __
9
- | |_) / _` | | '_ \| '_ \ \ \ /\ / /| |/ _` | | | | | | | '_ \
10
- | _ < (_| | | |_) | | | | \ V V / | | (_| | |_| | |_| | | | |
11
- |_| \_\__,_|_| .__/|_| |_| \_/\_/ |_|\__, |\__,_|\__,_|_| |_|
12
- |_| |___/
13
- ```
6
+ Ralph Wiggum is a tiny wrapper around the “autonomous loop” pattern: run an AI coding agent repeatedly, but keep each iteration small and strict.
14
7
 
15
- ## Installation
8
+ Each iteration:
9
+ - starts with fresh context (new process)
10
+ - completes exactly one plan item
11
+ - runs your repo’s validation commands
12
+ - creates exactly one local git commit
16
13
 
17
- ```bash
18
- # npm
19
- npx @wavilikhin/ralph-wiggum init
14
+ This keeps context focused and your history clean.
20
15
 
21
- # bun
22
- bunx @wavilikhin/ralph-wiggum init
23
- ```
16
+ ## Install
24
17
 
25
- Or install globally:
18
+ No global install needed:
26
19
 
27
20
  ```bash
28
- # npm
29
- npm install -g @wavilikhin/ralph-wiggum
30
-
31
- # bun
32
- bun install -g @wavilikhin/ralph-wiggum
21
+ npx @wavilikhin/ralph-wiggum init
33
22
  ```
34
23
 
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
- ---
50
-
51
- ## What is this?
52
-
53
- Ralph Wiggum runs your coding agent in a loop, where each iteration:
54
-
55
- 1. Starts with **fresh context** (new process, no memory of previous iterations)
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
24
+ (Inside an existing git repo.)
60
25
 
61
- This approach keeps context focused and produces clean, atomic commits.
26
+ ## Quick start
62
27
 
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)
28
+ 1) Ensure you have prerequisites:
82
29
  - Node.js 18+
83
- - Git repository
84
- - **AGENTS.md file in your repo root** (see below)
85
-
86
- ```bash
87
- # Verify opencode is working
88
- opencode --version
89
-
90
- # List available models
91
- opencode models
92
- ```
30
+ - `opencode` installed and configured (or another CLI agent)
31
+ - a repo-root `AGENTS.md` that lists your validation commands
93
32
 
94
- ### AGENTS.md Requirement
95
-
96
- Ralph Wiggum expects your repository to have a well-configured `AGENTS.md` file at the root. This file tells the AI agent how to validate changes in your project.
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
108
-
109
- Run these commands to validate changes:
110
-
111
- 1. Format: `npm run format`
112
- 2. Lint: `npm run lint`
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
125
-
126
- ### 1. Initialize in your repo
33
+ 2) Scaffold `.ralph/`:
127
34
 
128
35
  ```bash
129
- cd your-project
130
36
  npx @wavilikhin/ralph-wiggum init
131
37
  ```
132
38
 
133
- This creates a `.ralph/` directory with:
134
- - `PROMPT.md` - Instructions for the AI agent (has mandatory + customizable sections)
135
- - `IMPLEMENTATION_PLAN.md` - Your task list template
136
- - `run.sh` - The loop runner
137
- - `logs/` - Directory for iteration logs
39
+ 3) Fill in tasks:
40
+ - Edit `.ralph/IMPLEMENTATION_PLAN.md`
41
+ - Use checkboxes (`- [ ]`, `- [x]`)
138
42
 
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.
158
-
159
- ### 3. Run the loop
43
+ 4) Run the loop:
160
44
 
161
45
  ```bash
162
46
  .ralph/run.sh --max-iterations 20 --model anthropic/claude-opus-4-20250514
163
47
  ```
164
48
 
165
- The loop runs until:
166
- - All tasks are complete (agent outputs `<promise>COMPLETE</promise>`)
167
- - Max iterations reached
168
- - You press Ctrl+C
49
+ The loop stops when either:
50
+ - all tasks are checked off and the agent outputs `<promise>COMPLETE</promise>`
51
+ - `--max-iterations` is reached
52
+ - you press Ctrl+C
53
+
54
+ ## Flags
169
55
 
170
- ## CLI Options
56
+ `ralph-wiggum init` scaffolds files. The loop itself is controlled via `.ralph/run.sh`:
171
57
 
172
58
  ```bash
173
59
  .ralph/run.sh [options]
174
60
 
175
61
  Options:
176
- --max-iterations N Maximum iterations (default: 50)
62
+ --max-iterations N Maximum iterations before stopping (default: 50)
177
63
  --model MODEL Model to use (default: anthropic/claude-opus-4-20250514)
178
- --variant NAME Optional variant name for opencode
179
- --verbose Enable verbose logging (keeps full opencode output)
64
+ --variant NAME Optional variant name passed to opencode
65
+ --verbose Keep per-iteration logs (.ralph/logs/ralph_iter_N.log)
66
+ --live Stream opencode output (requires --verbose)
180
67
  --help Show help
181
68
 
182
69
  Environment variables:
@@ -184,193 +71,76 @@ Environment variables:
184
71
  RALPH_MODEL Default model
185
72
  ```
186
73
 
187
- ## Logging
74
+ ## What gets created
188
75
 
189
- Ralph Wiggum maintains two types of logs in `.ralph/logs/`:
76
+ `init` creates a `.ralph/` directory:
77
+ - `.ralph/PROMPT.md` – instructions the agent reads every iteration
78
+ - `.ralph/IMPLEMENTATION_PLAN.md` – your checklist of tasks
79
+ - `.ralph/run.sh` – the loop runner
80
+ - `.ralph/logs/` – log directory (ignored via `.gitignore`)
190
81
 
191
- ### Status Log (`.ralph/logs/ralph.log`)
82
+ ## Logs
192
83
 
193
- Always written. Contains iteration status with timestamps:
194
-
195
- ```
196
- [2025-01-19 14:30:15] [ITER] === Iteration 1/20 STARTED ===
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
- ```
84
+ - `.ralph/logs/ralph.log` is always written (timestamps + iteration status).
85
+ - `.ralph/logs/ralph_iter_N.log` is kept only with `--verbose` (or on failures).
200
86
 
201
- Use this to monitor progress:
87
+ Watch progress:
202
88
 
203
89
  ```bash
204
- # Watch progress in real-time
205
90
  tail -f .ralph/logs/ralph.log
206
91
  ```
207
92
 
208
- ### Verbose Logs (`.ralph/logs/ralph_iter_N.log`)
93
+ ## Safety
209
94
 
210
- Full opencode output per iteration. By default, these are deleted after successful iterations. Use `--verbose` to keep them:
95
+ - Never pushes: commits are local only.
96
+ - Enforces one commit per iteration.
97
+ - Requires a clean working tree after each iteration.
211
98
 
212
- ```bash
213
- .ralph/run.sh --verbose --max-iterations 10
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
- ```
99
+ <details>
100
+ <summary><strong>AI agent appendix (full detail)</strong></summary>
225
101
 
226
- ### Run with GPT-5.2
102
+ ### Model requirements
227
103
 
228
- ```bash
229
- .ralph/run.sh --max-iterations 10 --model openai/gpt-5.2
230
- ```
104
+ This loop is strict and works best with high-end models that can follow multistep instructions reliably:
105
+ - `anthropic/claude-opus-4-20250514`
106
+ - `openai/gpt-5.2`
231
107
 
232
- ### Run with environment variables
108
+ ### `AGENTS.md` (repo root) is required
233
109
 
234
- ```bash
235
- export RALPH_MODEL="anthropic/claude-opus-4-20250514"
236
- export RALPH_MAX_ITERATIONS=30
237
- .ralph/run.sh
238
- ```
110
+ Ralph Wiggum expects a repo-root `AGENTS.md` that tells the agent how to validate changes.
239
111
 
240
- ### Dry run (single iteration)
112
+ At minimum, include:
113
+ - formatting command
114
+ - lint command
115
+ - typecheck command (if applicable)
116
+ - test command
241
117
 
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
283
-
284
- ## File Structure
285
-
286
- After initialization, your repo will have:
287
-
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
- ```
300
-
301
- ### .ralph/PROMPT.md
302
-
303
- Contains instructions the agent follows each iteration. Has two types of sections:
304
-
305
- - **[MANDATORY] sections**: Core loop mechanics - don't modify these
306
- - **[CUSTOMIZABLE] sections**: Add project-specific context, quality standards
307
-
308
- ### .ralph/IMPLEMENTATION_PLAN.md
309
-
310
- Your task list. Structure it in phases:
118
+ Example (minimal):
311
119
 
312
120
  ```markdown
313
- ## Phase 1: Foundation
314
- - [ ] Task 1
315
- - [x] Task 2 (completed)
316
-
317
- ## Phase 2: Core
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
121
+ ## Validation Commands
122
+ 1. Format: `npm run format`
123
+ 2. Lint: `npm run lint`
124
+ 3. Typecheck: `npm run typecheck`
125
+ 4. Test: `npm test`
343
126
  ```
344
127
 
345
- ### "AGENTS.md not found"
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"
128
+ OpenCode docs: https://opencode.ai/docs/agents-md
358
129
 
359
- The agent left uncommitted changes. This usually means validation failed. Check the log and fix manually, then restart.
130
+ ### What happens each iteration
360
131
 
361
- ### Loop never completes
132
+ - A fresh `opencode run` process starts (no memory).
133
+ - The agent reads (at least) `.ralph/PROMPT.md`, `.ralph/IMPLEMENTATION_PLAN.md`, and `AGENTS.md`.
134
+ - The agent must pick exactly one unchecked task, implement it, run all validation gates, update the plan, and make exactly one commit.
135
+ - When every task is complete, the agent must output exactly `<promise>COMPLETE</promise>`.
362
136
 
363
- - Check if tasks in `.ralph/IMPLEMENTATION_PLAN.md` are achievable
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
137
+ ### Templates
367
138
 
368
- ### Iterations failing consistently
139
+ Scaffolded from:
140
+ - `templates/PROMPT.md`
141
+ - `templates/IMPLEMENTATION_PLAN.md`
369
142
 
370
- This often indicates the model isn't capable enough for autonomous operation. Try:
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
143
+ </details>
374
144
 
375
145
  ## Credits
376
146
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wavilikhin/ralph-wiggum",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Autonomous coding loop for OpenCode - one task, one commit, fresh context per iteration",
5
5
  "type": "module",
6
6
  "bin": {
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 Enable verbose logging (full opencode output)
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
  `);
@@ -17,6 +17,7 @@ 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
20
21
 
21
22
  # All ralph files are in .ralph/
22
23
  RALPH_DIR="$SCRIPT_DIR"
@@ -83,8 +84,11 @@ log_iteration_end() {
83
84
  local iter="$1"
84
85
  local status="$2"
85
86
  local commit_msg="$3"
86
- local duration="$4"
87
- log_to_file "ITER" "=== Iteration $iter FINISHED: $status (${duration}s) - $commit_msg ==="
87
+ local iter_duration="$4"
88
+ local opencode_duration="$5"
89
+ log_to_file "ITER" "=== Iteration $iter FINISHED: $status (iter=${iter_duration}s, opencode=${opencode_duration}s) - $commit_msg ==="
90
+ echo ""
91
+ echo -e "${DIM}Timing: opencode=${opencode_duration}s, iteration=${iter_duration}s${NC}"
88
92
  }
89
93
 
90
94
  #=============================================================================
@@ -111,7 +115,8 @@ print_usage() {
111
115
  echo " --max-iterations N Maximum iterations (default: $MAX_ITERATIONS)"
112
116
  echo " --model MODEL Model to use (default: $MODEL)"
113
117
  echo " --variant NAME Variant name for opencode"
114
- echo " --verbose Enable verbose logging (full opencode output)"
118
+ echo " --verbose Save per-iteration logs (.ralph/logs/ralph_iter_N.log)"
119
+ echo " --live Stream opencode output to terminal (requires --verbose)"
115
120
  echo " --help Show this help"
116
121
  echo ""
117
122
  echo "Environment variables:"
@@ -119,11 +124,11 @@ print_usage() {
119
124
  echo " RALPH_MODEL Default model"
120
125
  echo ""
121
126
  echo "Logs:"
122
- echo " .ralph/logs/ralph.log Iteration status (always written)"
123
- echo " .ralph/logs/ralph_iter_N.log Full opencode output (verbose mode or on error)"
127
+ echo " .ralph/logs/ralph.log Iteration status + timings (always written)"
128
+ echo " .ralph/logs/ralph_iter_N.log Full opencode output (--verbose only)"
124
129
  echo ""
125
130
  echo "Example:"
126
- echo " $0 --max-iterations 10 --model anthropic/claude-opus-4-20250514"
131
+ echo " $0 --max-iterations 10 --verbose --live"
127
132
  }
128
133
 
129
134
  check_prerequisites() {
@@ -201,6 +206,10 @@ while [[ $# -gt 0 ]]; do
201
206
  VERBOSE=true
202
207
  shift
203
208
  ;;
209
+ --live)
210
+ LIVE=true
211
+ shift
212
+ ;;
204
213
  --help|-h)
205
214
  print_usage
206
215
  exit 0
@@ -223,10 +232,17 @@ log_info "Configuration:"
223
232
  echo -e " ${DIM}Max iterations:${NC} $MAX_ITERATIONS"
224
233
  echo -e " ${DIM}Model:${NC} $MODEL"
225
234
  echo -e " ${DIM}Verbose:${NC} $VERBOSE"
235
+ echo -e " ${DIM}Live output:${NC} $LIVE"
226
236
  echo -e " ${DIM}Repo root:${NC} $REPO_ROOT"
227
237
  [[ -n "$VARIANT" ]] && echo -e " ${DIM}Variant:${NC} $VARIANT"
228
238
  echo ""
229
239
 
240
+ # Validate --live requires --verbose
241
+ if [[ "$LIVE" == true && "$VERBOSE" != true ]]; then
242
+ log_error "--live requires --verbose flag"
243
+ exit 1
244
+ fi
245
+
230
246
  check_prerequisites
231
247
 
232
248
  mkdir -p "$LOGS_DIR"
@@ -270,23 +286,37 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
270
286
 
271
287
  log_info "Running opencode..."
272
288
 
289
+ OPENCODE_START=$(date +%s)
290
+
273
291
  set +e
274
- if [[ "$VERBOSE" == true ]]; then
275
- OUTPUT=$("${OPENCODE_CMD[@]}" 2>&1 | tee "$ITER_LOG_FILE")
292
+ if [[ "$LIVE" == true ]]; then
293
+ # Stream to terminal AND write to log file
294
+ "${OPENCODE_CMD[@]}" 2>&1 | tee "$ITER_LOG_FILE"
295
+ EXIT_CODE=${PIPESTATUS[0]}
296
+ OUTPUT=$(cat "$ITER_LOG_FILE")
297
+ elif [[ "$VERBOSE" == true ]]; then
298
+ # Write to log file only (no terminal stream)
299
+ "${OPENCODE_CMD[@]}" > "$ITER_LOG_FILE" 2>&1
300
+ EXIT_CODE=$?
301
+ OUTPUT=$(cat "$ITER_LOG_FILE")
276
302
  else
303
+ # Capture output, write temp file for error inspection
277
304
  OUTPUT=$("${OPENCODE_CMD[@]}" 2>&1)
305
+ EXIT_CODE=$?
278
306
  echo "$OUTPUT" > "$ITER_LOG_FILE"
279
307
  fi
280
- EXIT_CODE=$?
281
308
  set -e
282
309
 
310
+ OPENCODE_END=$(date +%s)
311
+ OPENCODE_DURATION=$((OPENCODE_END - OPENCODE_START))
312
+
283
313
  ITER_END=$(date +%s)
284
314
  ITER_DURATION=$((ITER_END - ITER_START))
285
315
 
286
316
  if [[ $EXIT_CODE -ne 0 ]]; then
287
317
  log_error "opencode exited with code $EXIT_CODE"
288
318
  log_error "Check log: $ITER_LOG_FILE"
289
- log_iteration_end "$i" "FAILED" "opencode error" "$ITER_DURATION"
319
+ log_iteration_end "$i" "FAILED" "opencode error" "$ITER_DURATION" "$OPENCODE_DURATION"
290
320
  exit 1
291
321
  fi
292
322
 
@@ -295,7 +325,7 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
295
325
  log_success "All tasks complete!"
296
326
  echo ""
297
327
  echo -e "${GREEN}${BOLD}Loop finished successfully after $i iteration(s)${NC}"
298
- log_iteration_end "$i" "COMPLETE" "all tasks done" "$ITER_DURATION"
328
+ log_iteration_end "$i" "COMPLETE" "all tasks done" "$ITER_DURATION" "$OPENCODE_DURATION"
299
329
  log_to_file "INFO" "=== LOOP COMPLETED SUCCESSFULLY ==="
300
330
  exit 0
301
331
  fi
@@ -307,14 +337,14 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
307
337
  log_error "No commit was created in this iteration!"
308
338
  log_error "The agent must create exactly one commit per iteration."
309
339
  log_error "Check log: $ITER_LOG_FILE"
310
- log_iteration_end "$i" "FAILED" "no commit created" "$ITER_DURATION"
340
+ log_iteration_end "$i" "FAILED" "no commit created" "$ITER_DURATION" "$OPENCODE_DURATION"
311
341
  exit 1
312
342
  fi
313
343
 
314
344
  COMMIT_COUNT=$(git rev-list --count "$BEFORE_HEAD".."$AFTER_HEAD")
315
345
  if [[ "$COMMIT_COUNT" -ne 1 ]]; then
316
346
  log_error "Expected 1 commit, but $COMMIT_COUNT were created!"
317
- log_iteration_end "$i" "FAILED" "multiple commits" "$ITER_DURATION"
347
+ log_iteration_end "$i" "FAILED" "multiple commits" "$ITER_DURATION" "$OPENCODE_DURATION"
318
348
  exit 1
319
349
  fi
320
350
 
@@ -322,13 +352,13 @@ for i in $(seq 1 "$MAX_ITERATIONS"); do
322
352
  log_error "Working tree is not clean after iteration!"
323
353
  echo ""
324
354
  git status --short
325
- log_iteration_end "$i" "FAILED" "dirty working tree" "$ITER_DURATION"
355
+ log_iteration_end "$i" "FAILED" "dirty working tree" "$ITER_DURATION" "$OPENCODE_DURATION"
326
356
  exit 1
327
357
  fi
328
358
 
329
359
  COMMIT_MSG=$(git log -1 --format='%s')
330
360
  log_success "Commit created: $COMMIT_MSG"
331
- log_iteration_end "$i" "SUCCESS" "$COMMIT_MSG" "$ITER_DURATION"
361
+ log_iteration_end "$i" "SUCCESS" "$COMMIT_MSG" "$ITER_DURATION" "$OPENCODE_DURATION"
332
362
 
333
363
  if [[ "$VERBOSE" != true ]]; then
334
364
  rm -f "$ITER_LOG_FILE"