@graypark/ralph-codex 0.4.1 → 0.5.0
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 +10 -0
- package/lib/state.mjs +1 -0
- package/lib/stop-hook-core.mjs +71 -0
- package/package.json +1 -1
- package/skills/ralph-interview/SKILL.md +81 -12
- package/skills/ralph-orchestrator/SKILL.md +0 -19
package/README.md
CHANGED
|
@@ -69,6 +69,16 @@ node bin/install.mjs --global
|
|
|
69
69
|
/ralph-interview Refactor the auth module across 3 services, run immediately
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
**Multi-phase pipeline:** When multiple phases are generated, choose how to run:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Ready to run?
|
|
76
|
+
- y → Pipeline mode: all phases run automatically (1 → 2 → 3)
|
|
77
|
+
- step → Manual mode: run one phase at a time, confirm between each
|
|
78
|
+
- n → Copy-paste commands yourself
|
|
79
|
+
- edit → Modify the generated commands
|
|
80
|
+
```
|
|
81
|
+
|
|
72
82
|
### `/ralph-orchestrator` — Multi-Agent Patterns
|
|
73
83
|
|
|
74
84
|
Analyzes your task and recommends the best orchestration strategy:
|
package/lib/state.mjs
CHANGED
package/lib/stop-hook-core.mjs
CHANGED
|
@@ -75,7 +75,40 @@ export async function processStopHook(hookInput, readStateFn, writeStateFn) {
|
|
|
75
75
|
stderr.push(
|
|
76
76
|
`Ralph loop: max iterations (${state.maxIterations}) reached.\n`,
|
|
77
77
|
);
|
|
78
|
+
|
|
79
|
+
// On max iterations, also check queue for next phase
|
|
80
|
+
const queue = Array.isArray(state.queue) ? state.queue : [];
|
|
81
|
+
if (queue.length > 0) {
|
|
82
|
+
const next = queue.shift();
|
|
83
|
+
state.prompt = next.prompt;
|
|
84
|
+
state.completionPromise = next.completionPromise || "TADA";
|
|
85
|
+
state.maxIterations = next.maxIterations || 20;
|
|
86
|
+
state.currentIteration = 0;
|
|
87
|
+
state.queue = queue;
|
|
88
|
+
await writeStateFn(state);
|
|
89
|
+
|
|
90
|
+
stderr.push(
|
|
91
|
+
`Ralph loop: advancing to next phase (${queue.length} remaining).\n`,
|
|
92
|
+
);
|
|
93
|
+
const reason = [
|
|
94
|
+
state.prompt,
|
|
95
|
+
"",
|
|
96
|
+
"---",
|
|
97
|
+
`Ralph Loop — new phase started (iteration 1/${state.maxIterations}). Previous phase hit max iterations. Work on the task above.`,
|
|
98
|
+
].join("\n");
|
|
99
|
+
const output = { decision: "block", reason };
|
|
100
|
+
if (state.completionPromise) {
|
|
101
|
+
output.systemMessage = `Ralph phase started (${queue.length} more queued) | To complete: output <promise>${state.completionPromise}</promise>`;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
exitCode: 0,
|
|
105
|
+
stdout: JSON.stringify(output),
|
|
106
|
+
stderr: stderr.join(""),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
78
110
|
state.active = false;
|
|
111
|
+
state.queue = [];
|
|
79
112
|
await writeStateFn(state);
|
|
80
113
|
return { exitCode: 0, stdout: "", stderr: stderr.join("") };
|
|
81
114
|
}
|
|
@@ -91,7 +124,45 @@ export async function processStopHook(hookInput, readStateFn, writeStateFn) {
|
|
|
91
124
|
stderr.push(
|
|
92
125
|
`Ralph loop: completion promise "${state.completionPromise}" detected.\n`,
|
|
93
126
|
);
|
|
127
|
+
|
|
128
|
+
// Check queue for next phase
|
|
129
|
+
const queue = Array.isArray(state.queue) ? state.queue : [];
|
|
130
|
+
if (queue.length > 0) {
|
|
131
|
+
const next = queue.shift();
|
|
132
|
+
state.prompt = next.prompt;
|
|
133
|
+
state.completionPromise = next.completionPromise || "TADA";
|
|
134
|
+
state.maxIterations = next.maxIterations || 20;
|
|
135
|
+
state.currentIteration = 0;
|
|
136
|
+
state.queue = queue;
|
|
137
|
+
await writeStateFn(state);
|
|
138
|
+
|
|
139
|
+
const phasesLeft = queue.length;
|
|
140
|
+
stderr.push(
|
|
141
|
+
`Ralph loop: advancing to next phase (${phasesLeft} remaining in queue).\n`,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const nextIterInfo =
|
|
145
|
+
state.maxIterations > 0 ? `1/${state.maxIterations}` : "1";
|
|
146
|
+
const reason = [
|
|
147
|
+
state.prompt,
|
|
148
|
+
"",
|
|
149
|
+
"---",
|
|
150
|
+
`Ralph Loop — new phase started (iteration ${nextIterInfo}). Work on the task above.`,
|
|
151
|
+
].join("\n");
|
|
152
|
+
|
|
153
|
+
const output = { decision: "block", reason };
|
|
154
|
+
if (state.completionPromise) {
|
|
155
|
+
output.systemMessage = `Ralph phase started (${phasesLeft} more queued) | To complete: output <promise>${state.completionPromise}</promise> (ONLY when TRUE)`;
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
exitCode: 0,
|
|
159
|
+
stdout: JSON.stringify(output),
|
|
160
|
+
stderr: stderr.join(""),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
94
164
|
state.active = false;
|
|
165
|
+
state.queue = [];
|
|
95
166
|
await writeStateFn(state);
|
|
96
167
|
return { exitCode: 0, stdout: "", stderr: stderr.join("") };
|
|
97
168
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graypark/ralph-codex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ralph Loop for Codex CLI & Claude Code — iterative dev loops with multi-agent orchestration, interactive interview, and stop hooks",
|
|
6
6
|
"license": "MIT",
|
|
@@ -5,7 +5,7 @@ description: "Interactive interview that generates optimized /ralph-loop command
|
|
|
5
5
|
|
|
6
6
|
# Ralph Interview — Command Generator
|
|
7
7
|
|
|
8
|
-
You are an expert at crafting `/ralph-loop:ralph-loop` commands for
|
|
8
|
+
You are an expert at crafting `/ralph-loop:ralph-loop` commands for the Ralph Loop plugin.
|
|
9
9
|
When the user describes a task, conduct a brief interview to gather missing context, then generate a copy-paste-ready command.
|
|
10
10
|
|
|
11
11
|
## Core Principles
|
|
@@ -68,7 +68,7 @@ Evaluate the task against the ralph-orchestrator decision matrix:
|
|
|
68
68
|
- **Score 0–2** → Sequential loop, optional scout phase
|
|
69
69
|
- **Score < 0** → Single sequential Ralph Loop
|
|
70
70
|
|
|
71
|
-
When subagents are recommended, embed subagent spawn instructions directly in the generated ralph-loop prompt using
|
|
71
|
+
When subagents are recommended, embed subagent spawn instructions directly in the generated ralph-loop prompt using Codex's experimental multi-agent capabilities.
|
|
72
72
|
|
|
73
73
|
### Recommended max-iterations
|
|
74
74
|
|
|
@@ -131,7 +131,7 @@ When the orchestrator score is >= 3, embed subagent instructions in the prompt:
|
|
|
131
131
|
[Task summary]
|
|
132
132
|
|
|
133
133
|
## Phase 1 — Parallel Exploration
|
|
134
|
-
Spawn these subagents simultaneously
|
|
134
|
+
Spawn these subagents simultaneously:
|
|
135
135
|
|
|
136
136
|
1. Agent 'scan-frontend' (subagent_type: Explore, run_in_background: true):
|
|
137
137
|
Search src/frontend/** for [pattern]. Write findings to .ralph/reports/frontend.md
|
|
@@ -154,9 +154,52 @@ Read .ralph/reports/merged.md, then for each item:
|
|
|
154
154
|
Output <promise>[PROMISE]</promise>" --max-iterations [N] --completion-promise "[PROMISE]"
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
### Multi-Phase
|
|
157
|
+
### Multi-Phase (Pipeline Mode — DEFAULT)
|
|
158
|
+
|
|
159
|
+
When a task requires multiple phases, generate a **single** `/ralph-loop:ralph-loop` command with a `queue` in the state file. The stop hook automatically advances to the next phase when a completion promise is detected.
|
|
160
|
+
|
|
161
|
+
**How to set up pipeline mode:**
|
|
162
|
+
|
|
163
|
+
Create the state file at `.codex/ralph-loop.state.json` with a queue:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"active": true,
|
|
168
|
+
"prompt": "Phase 1 prompt here...",
|
|
169
|
+
"completionPromise": "PHASE1_DONE",
|
|
170
|
+
"maxIterations": 10,
|
|
171
|
+
"currentIteration": 0,
|
|
172
|
+
"sessionId": "",
|
|
173
|
+
"queue": [
|
|
174
|
+
{
|
|
175
|
+
"prompt": "Phase 2 prompt here...",
|
|
176
|
+
"completionPromise": "PHASE2_DONE",
|
|
177
|
+
"maxIterations": 20
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"prompt": "Phase 3 prompt here...",
|
|
181
|
+
"completionPromise": "TADA",
|
|
182
|
+
"maxIterations": 15
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Then start with:
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
/ralph-loop:ralph-loop "Phase 1 prompt here..." --max-iterations 10 --completion-promise "PHASE1_DONE"
|
|
192
|
+
```
|
|
158
193
|
|
|
159
|
-
|
|
194
|
+
When Phase 1 completes, the stop hook will automatically:
|
|
195
|
+
|
|
196
|
+
1. Detect the completion promise
|
|
197
|
+
2. Load Phase 2 from the queue
|
|
198
|
+
3. Re-inject Phase 2's prompt as a new loop — no user intervention needed
|
|
199
|
+
|
|
200
|
+
### Multi-Phase (Manual Mode)
|
|
201
|
+
|
|
202
|
+
If the user chooses manual mode, generate each Phase as a separate `/ralph-loop:ralph-loop` command:
|
|
160
203
|
|
|
161
204
|
- State Phase number and dependencies explicitly.
|
|
162
205
|
- Link prior Phase outputs as references in the next Phase.
|
|
@@ -215,9 +258,9 @@ To cancel at any time: `/ralph-loop:cancel-ralph`
|
|
|
215
258
|
[Assistant] → Asks interview questions (1 round, max 5 questions)
|
|
216
259
|
[User] → Answers
|
|
217
260
|
[Assistant] → Generates Phase plan + command blocks
|
|
218
|
-
[Assistant] → Asks: "
|
|
219
|
-
[User] →
|
|
220
|
-
[Assistant] → Executes
|
|
261
|
+
[Assistant] → Asks: "Ready to run?" with options
|
|
262
|
+
[User] → Chooses an option
|
|
263
|
+
[Assistant] → Executes accordingly
|
|
221
264
|
```
|
|
222
265
|
|
|
223
266
|
### Quick-Run Flow
|
|
@@ -226,19 +269,45 @@ If the user includes phrases like "run immediately", "just do it", "바로 실
|
|
|
226
269
|
|
|
227
270
|
1. Conduct the interview as normal (skip if enough context is provided).
|
|
228
271
|
2. Generate the command blocks.
|
|
229
|
-
3. **
|
|
230
|
-
4. Show the command that was
|
|
272
|
+
3. **Set up pipeline state file with queue** and **immediately execute Phase 1** without confirmation.
|
|
273
|
+
4. Show the command and queue that was set up so the user can see what's running.
|
|
231
274
|
|
|
232
275
|
### Post-Generation Action
|
|
233
276
|
|
|
234
277
|
After generating all command blocks, ALWAYS end with this prompt:
|
|
235
278
|
|
|
279
|
+
**For multi-phase tasks:**
|
|
280
|
+
|
|
236
281
|
```
|
|
237
282
|
---
|
|
238
283
|
**Ready to run?**
|
|
239
|
-
- **y** / **yes** / **실행** →
|
|
284
|
+
- **y** / **yes** / **실행** → Pipeline mode: run all phases automatically (Phase 1 → 2 → 3, no stops between phases)
|
|
285
|
+
- **step** / **단계별** → Manual mode: run Phase 1 only, I'll ask before each next phase
|
|
240
286
|
- **n** / **no** / **아니오** → Commands are above, copy-paste when ready
|
|
241
287
|
- **edit** / **수정** → Tell me what to change
|
|
242
288
|
```
|
|
243
289
|
|
|
244
|
-
|
|
290
|
+
**For single-phase tasks:**
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
---
|
|
294
|
+
**Ready to run?**
|
|
295
|
+
- **y** / **yes** / **실행** → Start immediately
|
|
296
|
+
- **n** / **no** / **아니오** → Command is above, copy-paste when ready
|
|
297
|
+
- **edit** / **수정** → Tell me what to change
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Execution Modes
|
|
301
|
+
|
|
302
|
+
**Pipeline mode (default for "y"):**
|
|
303
|
+
|
|
304
|
+
1. Create the state file with the first phase as active and remaining phases in `queue`
|
|
305
|
+
2. Execute Phase 1 via `/ralph-loop:ralph-loop`
|
|
306
|
+
3. When Phase 1 promise is detected, the stop hook automatically loads Phase 2 from queue
|
|
307
|
+
4. Continues until all phases complete — no user intervention between phases
|
|
308
|
+
|
|
309
|
+
**Manual mode ("step"):**
|
|
310
|
+
|
|
311
|
+
1. Execute Phase 1 via `/ralph-loop:ralph-loop`
|
|
312
|
+
2. When Phase 1 completes, prompt the user to confirm before starting Phase 2
|
|
313
|
+
3. Repeat for each phase
|
|
@@ -146,25 +146,6 @@ Execute Phase (Ralph Loop):
|
|
|
146
146
|
|
|
147
147
|
## Subagent Configuration Reference
|
|
148
148
|
|
|
149
|
-
### Claude Code (Agent tool)
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
Agent tool parameters:
|
|
153
|
-
- description: "short task description"
|
|
154
|
-
- prompt: "detailed instructions"
|
|
155
|
-
- subagent_type: "general-purpose" | "Explore" | "Plan" | "coder-fe" | "coder-be" | etc.
|
|
156
|
-
- isolation: "worktree" (optional — gives agent an isolated repo copy)
|
|
157
|
-
- run_in_background: true (for parallel execution)
|
|
158
|
-
- model: "sonnet" | "opus" | "haiku" (optional model override)
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
**Best practices:**
|
|
162
|
-
|
|
163
|
-
- Use `subagent_type: "Explore"` for read-only scanning — faster and safer
|
|
164
|
-
- Use `isolation: "worktree"` when agents write to files — prevents merge conflicts
|
|
165
|
-
- Launch parallel agents in a single message with multiple Agent tool calls
|
|
166
|
-
- Use `run_in_background: true` for truly independent work streams
|
|
167
|
-
|
|
168
149
|
### Codex CLI (experimental)
|
|
169
150
|
|
|
170
151
|
Codex spawns subagents via natural language prompts with keywords: "spawn", "parallel", "delegate", "one agent per".
|