fix: /clear resets paired task to prevent reviewer auto-triggering after session clear

This commit is contained in:
Eyejoker
2026-03-29 21:07:34 +09:00
parent d8cb4b691e
commit 9127841359
3 changed files with 24 additions and 2 deletions

View File

@@ -15,6 +15,7 @@ import {
getLastHumanMessageContent, getLastHumanMessageContent,
isPairedRoomJid, isPairedRoomJid,
getLatestOpenPairedTaskForChat, getLatestOpenPairedTaskForChat,
updatePairedTask,
type ServiceHandoff, type ServiceHandoff,
type WorkItem, type WorkItem,
} from './db.js'; } from './db.js';
@@ -673,6 +674,17 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
}); });
return formatRoomReviewReadyMessage(result); return formatRoomReviewReadyMessage(result);
}, },
resetPairedTask: () => {
if (isPairedRoomJid(chatJid)) {
const task = getLatestOpenPairedTaskForChat(chatJid);
if (task) {
updatePairedTask(task.id, {
status: 'completed',
updated_at: new Date().toISOString(),
});
}
}
},
killProcess: () => deps.queue.killProcess(chatJid), killProcess: () => deps.queue.killProcess(chatJid),
}, },
}); });

View File

@@ -32,9 +32,16 @@ import type {
// Reviewer verdict detection // Reviewer verdict detection
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
type ReviewerVerdict = 'done' | 'done_with_concerns' | 'blocked' | 'needs_context' | 'continue'; type ReviewerVerdict =
| 'done'
| 'done_with_concerns'
| 'blocked'
| 'needs_context'
| 'continue';
function classifyReviewerVerdict(summary: string | null | undefined): ReviewerVerdict { function classifyReviewerVerdict(
summary: string | null | undefined,
): ReviewerVerdict {
if (!summary) return 'continue'; if (!summary) return 'continue';
const firstLine = summary.trimStart().split('\n')[0].trim(); const firstLine = summary.trimStart().split('\n')[0].trim();
if (/\bBLOCKED\b/.test(firstLine)) return 'blocked'; if (/\bBLOCKED\b/.test(firstLine)) return 'blocked';

View File

@@ -80,6 +80,8 @@ export interface SessionCommandDeps {
/** Whether the denied sender would normally be allowed to interact (for denial messages). */ /** Whether the denied sender would normally be allowed to interact (for denial messages). */
canSenderInteract: (msg: NewMessage) => boolean; canSenderInteract: (msg: NewMessage) => boolean;
markReviewReady: () => Promise<string | null>; markReviewReady: () => Promise<string | null>;
/** Reset/complete the active paired task so ping-pong stops. */
resetPairedTask?: () => void;
/** Kill the currently running agent process for this group. Returns true if a process was killed. */ /** Kill the currently running agent process for this group. Returns true if a process was killed. */
killProcess: () => boolean; killProcess: () => boolean;
} }
@@ -159,6 +161,7 @@ export async function handleSessionCommand(opts: {
if (command === '/clear') { if (command === '/clear') {
deps.closeStdin(); deps.closeStdin();
deps.clearSession({ allRoles: true }); deps.clearSession({ allRoles: true });
deps.resetPairedTask?.();
deps.advanceCursor(cmdMsg.timestamp); deps.advanceCursor(cmdMsg.timestamp);
await deps.sendMessage( await deps.sendMessage(
'Current session cleared. The next message will start a new conversation.', 'Current session cleared. The next message will start a new conversation.',