Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .claude/spec-loop.local.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
spec_path: spec/20260222-engine-improvements
max_iterations: 50
current_iteration: 2
started_at: 2026-02-22T00:00:00Z
# Ralph pattern: Circuit breaker tracking
no_progress_count: 2
error_count: 0
last_completed_step: 5
circuit_breaker: open
# Learning: Trace tracking
current_trace_path: null
traces_emitted: 0
---

# Spec Loop Active

Implementing: spec/20260222-engine-improvements

## Exit Conditions (Dual-Gate)
1. All steps in PLAN.md marked ✅
2. Completion promise output: `<promise>ALL_STEPS_COMPLETE</promise>`

**Both conditions required for clean exit.**

## Circuit Breaker Triggers
- 3 iterations with no step completion → OPEN
- 5 iterations with repeated errors → OPEN

When circuit breaker opens, analyze and fix before continuing.
last_completed_step: 5
0
last_completed_step: 5
0
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ ralph-tui run --sandbox

# Use a bundled color theme by name
ralph-tui run --theme dracula

# Model escalation: start cheap, escalate on failure
ralph-tui run --start-model sonnet --escalate-model opus

# Auto-commit control (auto-commit is on by default)
ralph-tui run --no-auto-commit # disable auto-commit
ralph-tui run --auto-commit # explicitly enable (default)
```

### Create PRD Options
Expand Down Expand Up @@ -169,6 +176,74 @@ ralph-tui create-prd --output ./docs

See the [full CLI reference](https://ralph-tui.com/docs/cli/overview) for all options.

## Advanced Configuration

Configure these options in `.ralph-tui/config.toml` or `~/.config/ralph-tui/config.toml`.

### Post-Completion Verification

Run shell commands after the agent signals completion. If a command fails, Ralph injects the error into the next retry prompt.

```toml
[verification]
enabled = true
commands = ["bun run typecheck", "bun test"]
timeoutMs = 60000 # per command (default: 60s)
maxRetries = 2 # before skipping task (default: 2)
```

### Model Escalation

Start with a cheaper model and automatically escalate to a more capable one after failures.

```toml
[modelEscalation]
enabled = true
startModel = "sonnet" # initial model
escalateModel = "opus" # used after escalateAfter failures
escalateAfter = 1 # failed attempts before escalating (default: 1)
```

Or via CLI: `ralph-tui run --start-model sonnet --escalate-model opus`

### Completion Detection Strategies

Control how Ralph detects when an agent has finished a task.

```toml
[completion]
# Ordered list: first strategy that matches wins
# Options: "promise-tag" | "relaxed-tag" | "heuristic"
strategies = ["promise-tag", "relaxed-tag"]
```

### Cost Tracking

Track token usage per session. Optionally configure model pricing (in USD per 1M tokens) to enable dollar-cost estimates. **No pricing is built in** — you supply values so they stay current.

```toml
[cost]
enabled = true
alertThreshold = 5.0 # pause if session cost exceeds $5 (default: 0 = no limit)

[cost.pricing]
"claude-opus-4-6" = { inputPer1M = 5.0, outputPer1M = 25.0 }
"claude-sonnet-4-6" = { inputPer1M = 3.0, outputPer1M = 15.0 }
"claude-haiku-4-5" = { inputPer1M = 0.80, outputPer1M = 4.0 }
```
Comment on lines +229 to +233
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Haiku pricing example is stale — same issue as in src/config/types.ts.

Line 232 lists "claude-haiku-4-5" = { inputPer1M = 0.80, outputPer1M = 4.0 } but current Haiku 4.5 pricing is $1 / $5. Since users are likely to copy these examples verbatim, the values should be accurate.

📝 Suggested fix
-"claude-haiku-4-5"   = { inputPer1M = 0.80, outputPer1M = 4.0  }
+"claude-haiku-4-5"   = { inputPer1M = 1.0, outputPer1M = 5.0  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[cost.pricing]
"claude-opus-4-6" = { inputPer1M = 5.0, outputPer1M = 25.0 }
"claude-sonnet-4-6" = { inputPer1M = 3.0, outputPer1M = 15.0 }
"claude-haiku-4-5" = { inputPer1M = 0.80, outputPer1M = 4.0 }
```
[cost.pricing]
"claude-opus-4-6" = { inputPer1M = 5.0, outputPer1M = 25.0 }
"claude-sonnet-4-6" = { inputPer1M = 3.0, outputPer1M = 15.0 }
"claude-haiku-4-5" = { inputPer1M = 1.0, outputPer1M = 5.0 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 229 - 233, Update the stale Haiku pricing entry:
change the "claude-haiku-4-5" cost.pricing values from inputPer1M = 0.80 and
outputPer1M = 4.0 to the current values inputPer1M = 1.0 and outputPer1M = 5.0
in the README example; also make the identical update for the matching entry in
src/config/types.ts (look for the "claude-haiku-4-5" key and the
inputPer1M/outputPer1M fields) so examples and typed config stay consistent.


Token counts are always tracked regardless of whether pricing is configured.

### Auto-Commit

Auto-commit changed files after each successful task (enabled by default as of this version).

```toml
autoCommit = true # default; set to false to disable
```

> **Migration note:** `autoCommit` defaults to `true` starting from this version (previously `false`). If your workflow depends on committing manually, add `autoCommit = false` to your config, or use `--no-auto-commit` on the CLI.

### Custom Themes

Ralph TUI supports custom color themes via the `--theme` option:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* ABOUTME: Completion summary for Step 1: Verification Gates.
*/

# Step 1: Verification Gates — COMPLETED

## Summary

Implemented configurable post-completion verification commands that run after an agent signals `<promise>COMPLETE</promise>` but before the task is marked done in the tracker. If verification fails, the task is NOT marked complete and the engine retries with the verification error output injected into the next prompt.

## Files Created

### `src/engine/verification.ts` (NEW)
Verification gate runner with:
- `runVerification(cwd, config)` — runs all commands via `sh -c`, stops on first failure, returns `VerificationResult`
- `formatVerificationErrors(result)` — formats failures into readable multi-line string for prompt injection

### `tests/engine/verification.test.ts` (NEW)
11 tests covering:
- All commands pass → `result.passed === true`
- First command fails → stops, `result.passed === false`
- Timeout → `result.passed === false`
- Empty commands → `result.passed === true` (vacuously true)
- Format errors → readable multi-line string with command, exit code, stdout, stderr
- Only failed commands appear in formatted output

## Files Modified

### `src/config/types.ts`
- Added `VerificationConfig` interface with `enabled`, `commands`, `timeoutMs`, `maxRetries`
- Added `DEFAULT_VERIFICATION_CONFIG` constant
- Added `verification?: VerificationConfig` to both `StoredConfig` and `RalphConfig`

### `src/engine/types.ts`
- Added `'verification:started' | 'verification:passed' | 'verification:failed'` to `EngineEventType` union
- Added `VerificationStartedEvent`, `VerificationPassedEvent`, `VerificationFailedEvent` interfaces
- Added new events to `EngineEvent` union type

### `src/engine/index.ts`
- Imported `runVerification`, `formatVerificationErrors`, `DEFAULT_VERIFICATION_CONFIG`
- Added `lastVerificationErrors: string` and `verificationRetryMap: Map<string, number>` private fields
- Modified `buildPrompt()` to accept and pass `verificationErrors` into template context
- Modified `runIteration()` to clear `lastVerificationErrors` when no pending verification retries
- Inserted verification gate between completion detection and task completion marking:
- Emits `verification:started` event
- Runs all configured commands
- On pass: emits `verification:passed`, clears state
- On fail: emits `verification:failed`, stores errors for next prompt, suppresses completion
- On exhausted retries (`verificationRetries >= maxRetries`): skips gate and marks done

### `src/templates/types.ts`
- Added `verificationErrors: string` to `TemplateVariables`

### `src/templates/engine.ts`
- Added `verificationErrors?: string` to `ExtendedTemplateContext`
- Wires `verificationErrors` through `buildTemplateVariables()`

### `src/templates/builtin.ts`
- Added `{{#if verificationErrors}}` block to `JSON_TEMPLATE` after `recentProgress`

### `src/plugins/trackers/builtin/json/template.hbs`
- Added same `{{#if verificationErrors}}` block (reference copy)

## Verification Results

```
bun run typecheck ✓ (no errors)
bun run build ✓ (bundled successfully)
bun test ✓ 3278 pass, 0 fail
```

## Behavior When Disabled

When `verification.enabled` is `false` (default) or `verification` is not configured, the engine skips the gate entirely — existing behavior is unchanged.
Loading