Two related gaps in loop lifecycle after a loop finishes.
B1: No post-completion action
When a loop passes, finishLoop("pass") (project-loop.js ~line 621) fires a push notification but has no mechanism to run a follow-up action (a slash command, a git operation, or any user-defined callback).
Suggested implementation
Add an onPass field to the loop registry schema. In lib/scheduler.js update() (~line 347), add:
if (data.onPass !== undefined) rec.onPass = data.onPass;
In lib/project-loop.js finishLoop() (~line 638, after the registry recordRun call), add:
if (reason === "pass" && loopState.loopId) {
var source = loopRegistry.getById(loopState.loopId);
if (source && source.onPass) {
var followUp = sm.createSession();
followUp.title = (source.name || "Task") + " — post-completion";
sm.saveSessionFile(followUp);
sm.broadcastSessionList();
var userMsg = { type: "user_message", text: source.onPass };
followUp.history.push(userMsg);
sm.appendToSessionFile(followUp, userMsg);
followUp.isProcessing = true;
onProcessingChanged();
followUp.sentToolResults = {};
sdk.startQuery(followUp, source.onPass, undefined, getLinuxUserForSession(followUp));
}
}
The scheduler detail Meta tab would need a field to set onPass (e.g., a text input labeled "Run on success").
B2: Completed loop sessions are not interactive
All loop sessions (coder + judge) are created with singleTurn = true (project-loop.js lines 479, 595), which calls messageQueue.end() in the SDK worker (sdk-worker.js:314). After completion, sessions are read-only transcripts.
Re-opening a closed message queue is not safe. A cleaner path is a "Continue" action that creates a new session seeded with the loop context.
Suggested implementation
lib/project-loop.js — add a new message handler:
if (msg.type === "loop_continue_session") {
var sourceSession = sm.sessions.get(msg.sessionId);
if (!sourceSession || !sourceSession.loop) {
sendTo(ws, { type: "error", text: "Session not found or not a loop session" });
return true;
}
var contSession = sm.createSession();
contSession.title = (sourceSession.title || "Loop") + " (continued)";
contSession.parentLoopSession = msg.sessionId;
sm.saveSessionFile(contSession);
sm.broadcastSessionList();
sendTo(ws, { type: "loop_continue_ready", sessionId: contSession.localId });
return true;
}
The frontend would add a "Continue" button on completed loop sessions (in the session header or sidebar context menu) that sends this message and switches to the new session.
Two related gaps in loop lifecycle after a loop finishes.
B1: No post-completion action
When a loop passes,
finishLoop("pass")(project-loop.js ~line 621) fires a push notification but has no mechanism to run a follow-up action (a slash command, a git operation, or any user-defined callback).Suggested implementation
Add an
onPassfield to the loop registry schema. Inlib/scheduler.jsupdate()(~line 347), add:In
lib/project-loop.jsfinishLoop()(~line 638, after the registryrecordRuncall), add:The scheduler detail Meta tab would need a field to set
onPass(e.g., a text input labeled "Run on success").B2: Completed loop sessions are not interactive
All loop sessions (coder + judge) are created with
singleTurn = true(project-loop.js lines 479, 595), which callsmessageQueue.end()in the SDK worker (sdk-worker.js:314). After completion, sessions are read-only transcripts.Re-opening a closed message queue is not safe. A cleaner path is a "Continue" action that creates a new session seeded with the loop context.
Suggested implementation
lib/project-loop.js— add a new message handler:The frontend would add a "Continue" button on completed loop sessions (in the session header or sidebar context menu) that sends this message and switches to the new session.