From 61c9b8c2e972691332d7892a532a684fa0a4b1ac Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Tue, 31 Mar 2026 03:55:45 +0900 Subject: [PATCH] fix: reviewer auto-trigger now receives owner turn outputs instead of static prompt --- src/db.ts | 12 +++++++---- src/message-runtime.test.ts | 1 + src/message-runtime.ts | 43 +++++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/db.ts b/src/db.ts index 02c77e7..4ec0589 100644 --- a/src/db.ts +++ b/src/db.ts @@ -2469,7 +2469,13 @@ export function insertPairedTurnOutput( ): void { if (outputText.length > MAX_TURN_OUTPUT_CHARS) { logger.warn( - { taskId, turnNumber, role, originalLen: outputText.length, maxLen: MAX_TURN_OUTPUT_CHARS }, + { + taskId, + turnNumber, + role, + originalLen: outputText.length, + maxLen: MAX_TURN_OUTPUT_CHARS, + }, 'Paired turn output truncated — agent output exceeds storage limit', ); } @@ -2486,9 +2492,7 @@ export function insertPairedTurnOutput( ); } -export function getPairedTurnOutputs( - taskId: string, -): PairedTurnOutput[] { +export function getPairedTurnOutputs(taskId: string): PairedTurnOutput[] { return db .prepare( `SELECT * FROM paired_turn_outputs diff --git a/src/message-runtime.test.ts b/src/message-runtime.test.ts index 3c1ab53..e1ca1f9 100644 --- a/src/message-runtime.test.ts +++ b/src/message-runtime.test.ts @@ -116,6 +116,7 @@ vi.mock('./db.js', () => { getOpenWorkItem: vi.fn(() => undefined), getPendingServiceHandoffs: vi.fn(() => []), getLatestOpenPairedTaskForChat: vi.fn(() => undefined), + getPairedTurnOutputs: vi.fn(() => []), createProducedWorkItem: vi.fn((input) => ({ id: 1, group_folder: input.group_folder, diff --git a/src/message-runtime.ts b/src/message-runtime.ts index 059cd60..1e6008e 100644 --- a/src/message-runtime.ts +++ b/src/message-runtime.ts @@ -201,8 +201,8 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): { const agentMessages = turnOutputsToMessages(turnOutputs, chatJid); // Merge human + agent messages chronologically - const allMessages = [...humanMessages, ...agentMessages].sort( - (a, b) => a.timestamp.localeCompare(b.timestamp), + const allMessages = [...humanMessages, ...agentMessages].sort((a, b) => + a.timestamp.localeCompare(b.timestamp), ); return formatMessages(allMessages, timezone); @@ -651,18 +651,31 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): { : null; const pendingRole = resolveActiveRole(pendingReviewTask?.status); if (pendingReviewTask && pendingRole === 'reviewer') { - // No processable messages remain. Review workspace state using the - // user's request as context, but don't re-inject filtered raw bot - // output from older turns into the next review prompt. - const userMessage = getLastHumanMessageContent(chatJid); - const parts: string[] = []; - if (userMessage) { - parts.push(`User request:\n---\n${userMessage}\n---`); + // Build reviewer prompt from turn outputs (Discord-independent). + // Includes full owner/reviewer conversation history + human messages. + const turnOutputs = getPairedTurnOutputs(pendingReviewTask.id); + let reviewPrompt: string; + if (turnOutputs.length > 0) { + const humanMsgs = getRecentChatMessages(chatJid, 20).filter( + (m) => !m.is_bot_message, + ); + const allMsgs = [ + ...humanMsgs, + ...turnOutputsToMessages(turnOutputs, chatJid), + ].sort((a, b) => a.timestamp.localeCompare(b.timestamp)); + reviewPrompt = formatMessages(allMsgs, deps.timezone); + } else { + // Fallback: no turn outputs yet (pre-migration task) + const userMessage = getLastHumanMessageContent(chatJid); + const parts: string[] = []; + if (userMessage) { + parts.push(`User request:\n---\n${userMessage}\n---`); + } + reviewPrompt = + parts.length > 0 + ? `${parts.join('\n\n')}\n\nReview the latest owner changes in the workspace.` + : 'Review the latest owner changes in the workspace.'; } - const reviewPrompt = - parts.length > 0 - ? `${parts.join('\n\n')}\n\nReview the latest owner changes in the workspace.` - : 'Review the latest owner changes in the workspace.'; // Advance reviewer cursor (not owner cursor) so the reviewer // still sees the owner's messages on subsequent turns. @@ -703,9 +716,7 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): { ); } - const arbiterTurnOutputs = getPairedTurnOutputs( - pendingReviewTask.id, - ); + const arbiterTurnOutputs = getPairedTurnOutputs(pendingReviewTask.id); const recentMsgs = getRecentChatMessages(chatJid, 20); const arbiterMessages = arbiterTurnOutputs.length > 0