@ralph-orchestrator/ralph-cli 2.2.1 → 2.2.3
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 +275 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
[](https://github.com/mikeyobrien/ralph-orchestrator/actions)
|
|
6
6
|
[](coverage/index.html)
|
|
7
7
|
[](https://github.com/hesreallyhim/awesome-claude-code)
|
|
8
|
+
[](https://mikeyobrien.github.io/ralph-orchestrator/)
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
A hat-based orchestration framework that keeps Ralph in a loop until the task is done.
|
|
@@ -28,6 +29,7 @@ v1.0.0 was ralphed into existence with little oversight and guidance. v2.0.0 is
|
|
|
28
29
|
- [Presets](#presets)
|
|
29
30
|
- [Key Concepts](#key-concepts)
|
|
30
31
|
- [Orchestration and Coordination Patterns](#orchestration-and-coordination-patterns)
|
|
32
|
+
- [Multi-Loop Concurrency](#multi-loop-concurrency)
|
|
31
33
|
- [CLI Reference](#cli-reference)
|
|
32
34
|
- [Architecture](#architecture)
|
|
33
35
|
- [Building & Testing](#building--testing)
|
|
@@ -75,6 +77,7 @@ See [AGENTS.md](AGENTS.md) for the full philosophy.
|
|
|
75
77
|
- **Interactive TUI** — Real-time terminal UI for monitoring Ralph's activity (enabled by default)
|
|
76
78
|
- **Memories** — Persistent learning across sessions stored in `.agent/memories.md`
|
|
77
79
|
- **Tasks** — Runtime work tracking stored in `.agent/tasks.jsonl`
|
|
80
|
+
- **Multi-Loop Concurrency** — Run parallel loops in git worktrees with automatic merge workflow
|
|
78
81
|
- **Session Recording** — Record and replay sessions for debugging and testing (experimental)
|
|
79
82
|
|
|
80
83
|
## Installation
|
|
@@ -923,6 +926,259 @@ Ralph enforces quality gates through backpressure. When a builder publishes `bui
|
|
|
923
926
|
tests: pass, lint: pass, typecheck: pass
|
|
924
927
|
```
|
|
925
928
|
|
|
929
|
+
## Multi-Loop Concurrency
|
|
930
|
+
|
|
931
|
+
Ralph supports running multiple orchestration loops in parallel using git worktrees for filesystem isolation. This enables working on multiple tasks simultaneously without conflicts.
|
|
932
|
+
|
|
933
|
+
### How It Works
|
|
934
|
+
|
|
935
|
+
When you start a Ralph loop:
|
|
936
|
+
|
|
937
|
+
1. **First loop** acquires `.ralph/loop.lock` and runs in-place (the primary loop)
|
|
938
|
+
2. **Additional loops** automatically spawn into `.worktrees/<loop-id>/`
|
|
939
|
+
3. **Each loop** has isolated events, tasks, and scratchpad
|
|
940
|
+
4. **Memories are shared** — symlinked back to the main repo's `.agent/memories.md`
|
|
941
|
+
5. **On completion**, worktree loops automatically spawn a merge-ralph to integrate changes
|
|
942
|
+
|
|
943
|
+
```
|
|
944
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
945
|
+
│ Terminal 1 │ Terminal 2 │
|
|
946
|
+
│ ralph run -p "Add auth" │ ralph run -p "Add logging" │
|
|
947
|
+
│ [acquires lock, runs in-place]│ [spawns to worktree] │
|
|
948
|
+
│ ↓ │ ↓ │
|
|
949
|
+
│ Primary loop │ .worktrees/ralph-20250124-a3f2/ │
|
|
950
|
+
│ ↓ │ ↓ │
|
|
951
|
+
│ LOOP_COMPLETE │ LOOP_COMPLETE → auto-merge │
|
|
952
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
### Usage
|
|
956
|
+
|
|
957
|
+
```bash
|
|
958
|
+
# First loop acquires lock, runs in-place
|
|
959
|
+
ralph run -p "Add authentication"
|
|
960
|
+
|
|
961
|
+
# In another terminal — automatically spawns to worktree
|
|
962
|
+
ralph run -p "Add logging"
|
|
963
|
+
|
|
964
|
+
# Check running loops
|
|
965
|
+
ralph loops
|
|
966
|
+
|
|
967
|
+
# View logs from a specific loop
|
|
968
|
+
ralph loops logs <loop-id>
|
|
969
|
+
ralph loops logs <loop-id> --follow # Real-time streaming
|
|
970
|
+
|
|
971
|
+
# Force sequential execution (wait for lock)
|
|
972
|
+
ralph run --exclusive -p "Task that needs main workspace"
|
|
973
|
+
|
|
974
|
+
# Skip auto-merge (keep worktree for manual handling)
|
|
975
|
+
ralph run --no-auto-merge -p "Experimental feature"
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
### Loop States
|
|
979
|
+
|
|
980
|
+
| State | Description |
|
|
981
|
+
|-------|-------------|
|
|
982
|
+
| `running` | Loop is actively executing |
|
|
983
|
+
| `queued` | Completed, waiting for merge |
|
|
984
|
+
| `merging` | Merge operation in progress |
|
|
985
|
+
| `merged` | Successfully merged to main |
|
|
986
|
+
| `needs-review` | Merge failed, requires manual resolution |
|
|
987
|
+
| `crashed` | Process died unexpectedly |
|
|
988
|
+
| `orphan` | Worktree exists but not tracked |
|
|
989
|
+
| `discarded` | Explicitly abandoned by user |
|
|
990
|
+
|
|
991
|
+
### File Structure
|
|
992
|
+
|
|
993
|
+
```
|
|
994
|
+
project/
|
|
995
|
+
├── .ralph/
|
|
996
|
+
│ ├── loop.lock # Primary loop indicator
|
|
997
|
+
│ ├── loops.json # Loop registry
|
|
998
|
+
│ ├── merge-queue.jsonl # Merge event log
|
|
999
|
+
│ └── events.jsonl # Primary loop events
|
|
1000
|
+
├── .agent/
|
|
1001
|
+
│ └── memories.md # Shared across all loops
|
|
1002
|
+
└── .worktrees/
|
|
1003
|
+
└── ralph-20250124-a3f2/
|
|
1004
|
+
├── .ralph/events.jsonl # Loop-isolated
|
|
1005
|
+
├── .agent/
|
|
1006
|
+
│ ├── memories.md → ../../.agent/memories.md # Symlink
|
|
1007
|
+
│ └── scratchpad.md # Loop-isolated
|
|
1008
|
+
└── [project files]
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
### Managing Loops
|
|
1012
|
+
|
|
1013
|
+
```bash
|
|
1014
|
+
# List all loops with status
|
|
1015
|
+
ralph loops list
|
|
1016
|
+
|
|
1017
|
+
# View loop output
|
|
1018
|
+
ralph loops logs <id> # Full output
|
|
1019
|
+
ralph loops logs <id> --follow # Stream real-time
|
|
1020
|
+
|
|
1021
|
+
# View event history
|
|
1022
|
+
ralph loops history <id> # Formatted table
|
|
1023
|
+
ralph loops history <id> --json # Raw JSONL
|
|
1024
|
+
|
|
1025
|
+
# Show changes from merge-base
|
|
1026
|
+
ralph loops diff <id> # Full diff
|
|
1027
|
+
ralph loops diff <id> --stat # Summary only
|
|
1028
|
+
|
|
1029
|
+
# Open shell in worktree
|
|
1030
|
+
ralph loops attach <id>
|
|
1031
|
+
|
|
1032
|
+
# Re-run merge for failed loop
|
|
1033
|
+
ralph loops retry <id>
|
|
1034
|
+
|
|
1035
|
+
# Stop a running loop
|
|
1036
|
+
ralph loops stop <id> # SIGTERM
|
|
1037
|
+
ralph loops stop <id> --force # SIGKILL
|
|
1038
|
+
|
|
1039
|
+
# Abandon loop and cleanup
|
|
1040
|
+
ralph loops discard <id> # With confirmation
|
|
1041
|
+
ralph loops discard <id> -y # Skip confirmation
|
|
1042
|
+
|
|
1043
|
+
# Clean up stale loops (crashed processes)
|
|
1044
|
+
ralph loops prune
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
### Auto-Merge Workflow
|
|
1048
|
+
|
|
1049
|
+
When a worktree loop completes, it queues itself for merge. The primary loop processes this queue when it finishes:
|
|
1050
|
+
|
|
1051
|
+
```
|
|
1052
|
+
┌──────────────────────────────────────────────────────────────────────┐
|
|
1053
|
+
│ Worktree Loop Primary Loop │
|
|
1054
|
+
│ ───────────── ───────────── │
|
|
1055
|
+
│ LOOP_COMPLETE │
|
|
1056
|
+
│ ↓ │
|
|
1057
|
+
│ Queue for merge ─────────────────────→ [continues working] │
|
|
1058
|
+
│ ↓ ↓ │
|
|
1059
|
+
│ Exit cleanly LOOP_COMPLETE │
|
|
1060
|
+
│ ↓ │
|
|
1061
|
+
│ Process merge queue │
|
|
1062
|
+
│ ↓ │
|
|
1063
|
+
│ Spawn merge-ralph │
|
|
1064
|
+
└──────────────────────────────────────────────────────────────────────┘
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
The merge-ralph process uses a **hat collection** with specialized roles:
|
|
1068
|
+
|
|
1069
|
+
| Hat | Trigger | Purpose |
|
|
1070
|
+
|-----|---------|---------|
|
|
1071
|
+
| `merger` | `merge.start` | Performs `git merge`, runs tests |
|
|
1072
|
+
| `resolver` | `conflict.detected` | Resolves merge conflicts by understanding intent |
|
|
1073
|
+
| `tester` | `conflict.resolved` | Verifies tests pass after conflict resolution |
|
|
1074
|
+
| `cleaner` | `merge.done` | Removes worktree and branch |
|
|
1075
|
+
| `failure_handler` | `*failed`, `unresolvable` | Marks loop for manual review |
|
|
1076
|
+
|
|
1077
|
+
The workflow handles conflicts intelligently:
|
|
1078
|
+
1. **No conflicts**: Merge → Run tests → Clean up → Done
|
|
1079
|
+
2. **With conflicts**: Detect → AI resolves → Run tests → Clean up → Done
|
|
1080
|
+
3. **Unresolvable**: Abort → Mark for review → Keep worktree for manual fix
|
|
1081
|
+
|
|
1082
|
+
### Conflict Resolution
|
|
1083
|
+
|
|
1084
|
+
When merge conflicts occur, the AI resolver:
|
|
1085
|
+
|
|
1086
|
+
1. Examines conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`)
|
|
1087
|
+
2. Understands the **intent** of both sides (not just the code)
|
|
1088
|
+
3. Resolves by preserving both intents when possible
|
|
1089
|
+
4. Prefers the loop's changes when directly contradictory (newer work)
|
|
1090
|
+
|
|
1091
|
+
**Conflicts marked `needs-review`:**
|
|
1092
|
+
- Major architectural changes on both sides
|
|
1093
|
+
- Complex refactoring that can't be automatically reconciled
|
|
1094
|
+
- Business logic contradictions requiring human judgment
|
|
1095
|
+
|
|
1096
|
+
To manually resolve:
|
|
1097
|
+
```bash
|
|
1098
|
+
# Enter the worktree
|
|
1099
|
+
ralph loops attach <loop-id>
|
|
1100
|
+
|
|
1101
|
+
# Fix the issue, commit
|
|
1102
|
+
git add . && git commit -m "Manual conflict resolution"
|
|
1103
|
+
|
|
1104
|
+
# Retry the merge
|
|
1105
|
+
ralph loops retry <loop-id>
|
|
1106
|
+
|
|
1107
|
+
# Or discard if unneeded
|
|
1108
|
+
ralph loops discard <loop-id>
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
### Best Practices
|
|
1112
|
+
|
|
1113
|
+
**When to use parallel loops:**
|
|
1114
|
+
- ✅ Independent features with minimal file overlap
|
|
1115
|
+
- ✅ Bug fixes while feature work continues
|
|
1116
|
+
- ✅ Documentation updates parallel to code changes
|
|
1117
|
+
- ✅ Test additions that don't conflict with active development
|
|
1118
|
+
|
|
1119
|
+
**When to use `--exclusive` (sequential):**
|
|
1120
|
+
- ⚠️ Large refactoring touching many files
|
|
1121
|
+
- ⚠️ Database migrations or schema changes
|
|
1122
|
+
- ⚠️ Tasks that modify shared configuration files
|
|
1123
|
+
- ⚠️ Work that depends on changes from another in-progress loop
|
|
1124
|
+
|
|
1125
|
+
**Tips for reducing conflicts:**
|
|
1126
|
+
- Keep loops focused on distinct areas of the codebase
|
|
1127
|
+
- Use separate files when adding new features
|
|
1128
|
+
- Avoid modifying the same functions in parallel loops
|
|
1129
|
+
- Let one loop complete before starting conflicting work
|
|
1130
|
+
|
|
1131
|
+
### Troubleshooting
|
|
1132
|
+
|
|
1133
|
+
**Loop stuck in `queued` state:**
|
|
1134
|
+
```bash
|
|
1135
|
+
# Check if primary loop is still running
|
|
1136
|
+
ralph loops
|
|
1137
|
+
|
|
1138
|
+
# If primary finished but merge didn't start, manually trigger
|
|
1139
|
+
ralph loops retry <loop-id>
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
**Merge keeps failing:**
|
|
1143
|
+
```bash
|
|
1144
|
+
# View merge-ralph logs
|
|
1145
|
+
ralph loops logs <loop-id>
|
|
1146
|
+
|
|
1147
|
+
# Check what changes conflict
|
|
1148
|
+
ralph loops diff <loop-id>
|
|
1149
|
+
|
|
1150
|
+
# Manually resolve in worktree
|
|
1151
|
+
ralph loops attach <loop-id>
|
|
1152
|
+
```
|
|
1153
|
+
|
|
1154
|
+
**Orphaned worktrees:**
|
|
1155
|
+
```bash
|
|
1156
|
+
# List and clean up orphans
|
|
1157
|
+
ralph loops prune
|
|
1158
|
+
|
|
1159
|
+
# Force cleanup of specific worktree
|
|
1160
|
+
git worktree remove .worktrees/<loop-id> --force
|
|
1161
|
+
git branch -D ralph/<loop-id>
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
**Lock file issues:**
|
|
1165
|
+
```bash
|
|
1166
|
+
# Check who holds the lock
|
|
1167
|
+
cat .ralph/loop.lock
|
|
1168
|
+
|
|
1169
|
+
# If process is dead, remove stale lock
|
|
1170
|
+
rm .ralph/loop.lock
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
### Environment Variables
|
|
1174
|
+
|
|
1175
|
+
| Variable | Description |
|
|
1176
|
+
|----------|-------------|
|
|
1177
|
+
| `RALPH_MERGE_LOOP_ID` | Set by auto-merge to identify which loop to merge |
|
|
1178
|
+
| `RALPH_DIAGNOSTICS=1` | Enable detailed diagnostic logging |
|
|
1179
|
+
| `RALPH_VERBOSE=1` | Verbose output mode |
|
|
1180
|
+
| `RALPH_DEBUG_LOG=1` | Write debug logs to `.agent/ralph.log` |
|
|
1181
|
+
|
|
926
1182
|
## CLI Reference
|
|
927
1183
|
|
|
928
1184
|
### Commands
|
|
@@ -938,6 +1194,7 @@ tests: pass, lint: pass, typecheck: pass
|
|
|
938
1194
|
| `ralph clean` | Clean up `.agent/` directory |
|
|
939
1195
|
| `ralph emit` | Emit an event to the event log |
|
|
940
1196
|
| `ralph tools` | Runtime tools for memories and tasks (agent-facing) |
|
|
1197
|
+
| `ralph loops` | Manage parallel loops (list, logs, stop, merge) |
|
|
941
1198
|
|
|
942
1199
|
### Global Options
|
|
943
1200
|
|
|
@@ -962,6 +1219,8 @@ tests: pass, lint: pass, typecheck: pass
|
|
|
962
1219
|
| `--record-session <FILE>` | Record session to JSONL |
|
|
963
1220
|
| `-q, --quiet` | Suppress output (for CI) |
|
|
964
1221
|
| `--continue` | Resume from existing scratchpad |
|
|
1222
|
+
| `--exclusive` | Wait for primary loop slot instead of spawning worktree |
|
|
1223
|
+
| `--no-auto-merge` | Skip automatic merge after worktree loop completes |
|
|
965
1224
|
|
|
966
1225
|
### `ralph init` Options
|
|
967
1226
|
|
|
@@ -1006,6 +1265,22 @@ ralph tools task ready # Unblocked tasks only
|
|
|
1006
1265
|
ralph tools task close <id> # Mark complete
|
|
1007
1266
|
```
|
|
1008
1267
|
|
|
1268
|
+
### `ralph loops` Subcommands
|
|
1269
|
+
|
|
1270
|
+
Manage parallel loops running in git worktrees:
|
|
1271
|
+
|
|
1272
|
+
| Subcommand | Description |
|
|
1273
|
+
|------------|-------------|
|
|
1274
|
+
| `list` | Show all loops with status (default) |
|
|
1275
|
+
| `logs <ID>` | View loop output (`--follow` for real-time) |
|
|
1276
|
+
| `history <ID>` | Show event history (`--json` for raw JSONL) |
|
|
1277
|
+
| `retry <ID>` | Re-run merge for `needs-review` loop |
|
|
1278
|
+
| `discard <ID>` | Abandon loop and cleanup worktree (`-y` to skip confirm) |
|
|
1279
|
+
| `stop <ID>` | Terminate running loop (`--force` for SIGKILL) |
|
|
1280
|
+
| `prune` | Clean up stale loops (crashed processes) |
|
|
1281
|
+
| `attach <ID>` | Open shell in loop's worktree |
|
|
1282
|
+
| `diff <ID>` | Show changes from merge-base (`--stat` for summary) |
|
|
1283
|
+
|
|
1009
1284
|
## Architecture
|
|
1010
1285
|
|
|
1011
1286
|
Ralph is organized as a Cargo workspace with seven crates:
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"hasInstallScript": true,
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"name": "@ralph-orchestrator/ralph-cli",
|
|
26
|
-
"version": "2.2.
|
|
26
|
+
"version": "2.2.3"
|
|
27
27
|
},
|
|
28
28
|
"node_modules/@isaacs/balanced-match": {
|
|
29
29
|
"engines": {
|
|
@@ -515,5 +515,5 @@
|
|
|
515
515
|
}
|
|
516
516
|
},
|
|
517
517
|
"requires": true,
|
|
518
|
-
"version": "2.2.
|
|
518
|
+
"version": "2.2.3"
|
|
519
519
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"artifactDownloadUrl": "https://github.com/mikeyobrien/ralph-orchestrator/releases/download/v2.2.
|
|
2
|
+
"artifactDownloadUrl": "https://github.com/mikeyobrien/ralph-orchestrator/releases/download/v2.2.3",
|
|
3
3
|
"bin": {
|
|
4
4
|
"ralph": "run-ralph.js"
|
|
5
5
|
},
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"zipExt": ".tar.xz"
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
-
"version": "2.2.
|
|
65
|
+
"version": "2.2.3",
|
|
66
66
|
"volta": {
|
|
67
67
|
"node": "18.14.1",
|
|
68
68
|
"npm": "9.5.0"
|