opencode-ralph-rlm 0.1.12 → 0.1.13
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 +2 -0
- package/dist/ralph-rlm.js +31 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -228,6 +228,8 @@ Create `.opencode/ralph.json`. All fields are optional — the plugin runs with
|
|
|
228
228
|
| `statusVerbosity` | `"normal"` | Supervisor status emission level: `minimal` (warnings/errors), `normal`, or `verbose`. |
|
|
229
229
|
| `maxAttempts` | `20` | Hard stop after this many failed verify attempts. |
|
|
230
230
|
| `heartbeatMinutes` | `15` | Warn if active strategist/worker has no progress for this many minutes. |
|
|
231
|
+
| `strategistHandoffMinutes` | `5` | Warn/retry if the strategist does not spawn a worker within this many minutes. |
|
|
232
|
+
| `strategistHandoffMaxRetries` | `2` | Max retries to respawn strategist after a missed handoff. |
|
|
231
233
|
| `verifyTimeoutMinutes` | `0` | Timeout for verify command in minutes. `0` disables timeouts. |
|
|
232
234
|
| `verify.command` | - | Shell command to run as an array, e.g. `["bun", "run", "verify"]`. If omitted, verify always returns `unknown`. |
|
|
233
235
|
| `verify.cwd` | `"."` | Working directory for the verify command, relative to the repo root. |
|
package/dist/ralph-rlm.js
CHANGED
|
@@ -23417,6 +23417,8 @@ var RalphConfigSchema = exports_Schema.Struct({
|
|
|
23417
23417
|
statusVerbosity: exports_Schema.optional(exports_Schema.Union(exports_Schema.Literal("minimal"), exports_Schema.Literal("normal"), exports_Schema.Literal("verbose"))),
|
|
23418
23418
|
maxAttempts: exports_Schema.optional(exports_Schema.Number),
|
|
23419
23419
|
heartbeatMinutes: exports_Schema.optional(exports_Schema.Number),
|
|
23420
|
+
strategistHandoffMinutes: exports_Schema.optional(exports_Schema.Number),
|
|
23421
|
+
strategistHandoffMaxRetries: exports_Schema.optional(exports_Schema.Number),
|
|
23420
23422
|
verifyTimeoutMinutes: exports_Schema.optional(exports_Schema.Number),
|
|
23421
23423
|
verify: exports_Schema.optional(VerifyConfigSchema),
|
|
23422
23424
|
gateDestructiveToolsUntilContextLoaded: exports_Schema.optional(exports_Schema.Boolean),
|
|
@@ -23456,6 +23458,8 @@ var CONFIG_DEFAULTS = {
|
|
|
23456
23458
|
statusVerbosity: "normal",
|
|
23457
23459
|
maxAttempts: 20,
|
|
23458
23460
|
heartbeatMinutes: 15,
|
|
23461
|
+
strategistHandoffMinutes: 5,
|
|
23462
|
+
strategistHandoffMaxRetries: 2,
|
|
23459
23463
|
verifyTimeoutMinutes: 0,
|
|
23460
23464
|
gateDestructiveToolsUntilContextLoaded: true,
|
|
23461
23465
|
maxRlmSliceLines: 200,
|
|
@@ -23482,6 +23486,8 @@ function resolveConfig(raw) {
|
|
|
23482
23486
|
statusVerbosity: raw.statusVerbosity ?? CONFIG_DEFAULTS.statusVerbosity,
|
|
23483
23487
|
maxAttempts: toBoundedInt(raw.maxAttempts, CONFIG_DEFAULTS.maxAttempts, 1, 500),
|
|
23484
23488
|
heartbeatMinutes: toBoundedInt(raw.heartbeatMinutes, CONFIG_DEFAULTS.heartbeatMinutes, 1, 240),
|
|
23489
|
+
strategistHandoffMinutes: toBoundedInt(raw.strategistHandoffMinutes, CONFIG_DEFAULTS.strategistHandoffMinutes, 1, 60),
|
|
23490
|
+
strategistHandoffMaxRetries: toBoundedInt(raw.strategistHandoffMaxRetries, CONFIG_DEFAULTS.strategistHandoffMaxRetries, 0, 10),
|
|
23485
23491
|
verifyTimeoutMinutes: toBoundedInt(raw.verifyTimeoutMinutes, CONFIG_DEFAULTS.verifyTimeoutMinutes, 0, 240),
|
|
23486
23492
|
...verify !== undefined ? { verify } : {},
|
|
23487
23493
|
gateDestructiveToolsUntilContextLoaded: raw.gateDestructiveToolsUntilContextLoaded ?? CONFIG_DEFAULTS.gateDestructiveToolsUntilContextLoaded,
|
|
@@ -23514,6 +23520,7 @@ var DEFAULT_TEMPLATES = {
|
|
|
23514
23520
|
" When you receive one, call ralph_respond(id, answer) to unblock the session.",
|
|
23515
23521
|
"- Use ralph_doctor() to check setup, ralph_bootstrap_plan() to generate PLAN/TODOS,",
|
|
23516
23522
|
" ralph_create_supervisor_session() to bind/start explicitly, ralph_pause_supervision()/ralph_resume_supervision() to control execution, and ralph_end_supervision() to stop.",
|
|
23523
|
+
"- Only call loop-control tools (spawn, pause, resume, end) after the supervisor session is bound via ralph_create_supervisor_session().",
|
|
23517
23524
|
"- End supervision when verification has passed and the user confirms they are done, or when the user explicitly asks to stop the loop.",
|
|
23518
23525
|
"- Optional reviewer flow: worker marks readiness with ralph_request_review(); supervisor runs ralph_run_reviewer().",
|
|
23519
23526
|
"- Monitor progress in SUPERVISOR_LOG.md, CONVERSATION.md, or via toast notifications.",
|
|
@@ -23700,6 +23707,7 @@ var DEFAULT_TEMPLATES = {
|
|
|
23700
23707
|
"- You do NOT write code yourself; you are not the RLM worker.",
|
|
23701
23708
|
"- After reviewing state and optionally updating PLAN.md / RLM_INSTRUCTIONS.md,",
|
|
23702
23709
|
" call ralph_spawn_worker() to hand off to the RLM worker for this attempt.",
|
|
23710
|
+
"- You MUST call ralph_spawn_worker() exactly once per attempt.",
|
|
23703
23711
|
"- Then STOP. The plugin verifies independently and will spawn the next Ralph session if needed.",
|
|
23704
23712
|
"",
|
|
23705
23713
|
"Role boundaries:",
|
|
@@ -23720,7 +23728,7 @@ var DEFAULT_TEMPLATES = {
|
|
|
23720
23728
|
" guidance for the next worker based on patterns in the failures.",
|
|
23721
23729
|
"5. Optionally call ralph_set_status('running', 'strategy finalized').",
|
|
23722
23730
|
"6. Call ralph_report() summarizing strategy changes for this attempt.",
|
|
23723
|
-
"7. Call ralph_spawn_worker() to delegate the coding work to a fresh RLM worker.",
|
|
23731
|
+
"7. Call ralph_spawn_worker() to delegate the coding work to a fresh RLM worker (required).",
|
|
23724
23732
|
"8. STOP \u2014 the plugin handles verification and will spawn attempt {{nextAttempt}} if needed.",
|
|
23725
23733
|
"",
|
|
23726
23734
|
"You do not write code. Your value is strategic context adjustment between attempts.",
|
|
@@ -23728,7 +23736,10 @@ var DEFAULT_TEMPLATES = {
|
|
|
23728
23736
|
"Tool meaning:",
|
|
23729
23737
|
"- ralph_update_plan / ralph_update_rlm_instructions = durable strategy changes",
|
|
23730
23738
|
"- ralph_spawn_worker = handoff to implementation session",
|
|
23731
|
-
"- ralph_report = visible summary for the supervisor"
|
|
23739
|
+
"- ralph_report = visible summary for the supervisor",
|
|
23740
|
+
"",
|
|
23741
|
+
"Example flow:",
|
|
23742
|
+
'- ralph_load_context() \u2192 ralph_report("Strategy: update PLAN.md with constraint X") \u2192 ralph_spawn_worker() \u2192 STOP'
|
|
23732
23743
|
].join(`
|
|
23733
23744
|
`)
|
|
23734
23745
|
};
|
|
@@ -25733,6 +25744,8 @@ ${interpolate(templates.continuePrompt, { attempt: String(attemptN), verdict })}
|
|
|
25733
25744
|
mutateSession(sessionID, (s) => {
|
|
25734
25745
|
s.workerSpawned = true;
|
|
25735
25746
|
});
|
|
25747
|
+
supervisor.ralphHandoffRetries = 0;
|
|
25748
|
+
supervisor.ralphHandoffAttempt = st.attempt;
|
|
25736
25749
|
await notifySupervisor(`ralph/attempt-${st.attempt}`, `Delegated coding to worker session ${workerId}.`, "info", true, sessionID);
|
|
25737
25750
|
return JSON.stringify({ ok: true, workerSessionId: workerId, attempt: st.attempt }, null, 2);
|
|
25738
25751
|
};
|
|
@@ -25741,6 +25754,10 @@ ${interpolate(templates.continuePrompt, { attempt: String(attemptN), verdict })}
|
|
|
25741
25754
|
body: { title: `ralph-strategist-attempt-${attempt}` }
|
|
25742
25755
|
});
|
|
25743
25756
|
const ralphId = result.data?.id ?? `ralph-${Date.now()}`;
|
|
25757
|
+
if (supervisor.ralphHandoffAttempt !== attempt) {
|
|
25758
|
+
supervisor.ralphHandoffAttempt = attempt;
|
|
25759
|
+
supervisor.ralphHandoffRetries = 0;
|
|
25760
|
+
}
|
|
25744
25761
|
supervisor.currentRalphSessionId = ralphId;
|
|
25745
25762
|
sessionMap.set(ralphId, freshSession("ralph", attempt));
|
|
25746
25763
|
mutateSession(ralphId, (s) => {
|
|
@@ -25762,7 +25779,7 @@ ${interpolate(templates.continuePrompt, { attempt: String(attemptN), verdict })}
|
|
|
25762
25779
|
clearTimeout(supervisor.ralphHandoffTimer);
|
|
25763
25780
|
}
|
|
25764
25781
|
const cfg = await run(getConfig());
|
|
25765
|
-
const timeoutMs = Math.max(cfg.
|
|
25782
|
+
const timeoutMs = Math.max(cfg.strategistHandoffMinutes, 1) * 60000;
|
|
25766
25783
|
supervisor.ralphHandoffTimer = setTimeout(async () => {
|
|
25767
25784
|
if (supervisor.done || supervisor.paused)
|
|
25768
25785
|
return;
|
|
@@ -25771,7 +25788,17 @@ ${interpolate(templates.continuePrompt, { attempt: String(attemptN), verdict })}
|
|
|
25771
25788
|
const st = sessionMap.get(ralphId);
|
|
25772
25789
|
if (st?.workerSpawned)
|
|
25773
25790
|
return;
|
|
25774
|
-
|
|
25791
|
+
const retries = supervisor.ralphHandoffRetries ?? 0;
|
|
25792
|
+
if (retries < cfg.strategistHandoffMaxRetries) {
|
|
25793
|
+
supervisor.ralphHandoffRetries = retries + 1;
|
|
25794
|
+
await notifySupervisor(`ralph/attempt-${attempt}`, `Strategist did not hand off; retrying strategist (${retries + 1}/${cfg.strategistHandoffMaxRetries}).`, "warning", true, ralphId);
|
|
25795
|
+
supervisor.currentRalphSessionId = undefined;
|
|
25796
|
+
await client.session.abort({ path: { id: ralphId } }).catch(() => {});
|
|
25797
|
+
await spawnRalphSession(attempt);
|
|
25798
|
+
return;
|
|
25799
|
+
}
|
|
25800
|
+
await notifySupervisor(`ralph/attempt-${attempt}`, "Strategist did not hand off after retries; supervision paused. Use ralph_create_supervisor_session(restart_if_done=true) to retry.", "error", true, ralphId);
|
|
25801
|
+
supervisor.paused = true;
|
|
25775
25802
|
}, timeoutMs);
|
|
25776
25803
|
await notifySupervisor(`supervisor/attempt-${attempt}`, `Spawned Ralph strategist session ${ralphId}.`, "info", true);
|
|
25777
25804
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-ralph-rlm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "OpenCode plugin: Ralph outer loop + RLM inner loop. Iterative AI development with file-first discipline and sub-agent support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/ralph-rlm.js",
|