From 73156bf3751916427e639e857eb142f2319c222c Mon Sep 17 00:00:00 2001 From: Eyejoker Date: Wed, 1 Apr 2026 04:18:15 +0900 Subject: [PATCH] fix: only count final-phase output as visible for handoff decisions Progress messages (phase: 'progress') were setting sawVisibleOutput=true, which blocked failover handoffs when Claude usage was exhausted. Now only final-phase output counts as visible, allowing reviewer handoff to codex even after progress messages were shown. --- src/message-agent-executor.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/message-agent-executor.ts b/src/message-agent-executor.ts index d7ba990..4c66fce 100644 --- a/src/message-agent-executor.ts +++ b/src/message-agent-executor.ts @@ -114,8 +114,8 @@ export async function runAgentForGroup( const inferredRole = resolveActiveRole(pairedTask?.status); const canHonorForcedRole = Boolean( args.forcedRole === 'owner' || - (args.forcedRole === 'reviewer' && currentLease.reviewer_service_id) || - (args.forcedRole === 'arbiter' && currentLease.arbiter_service_id), + (args.forcedRole === 'reviewer' && currentLease.reviewer_service_id) || + (args.forcedRole === 'arbiter' && currentLease.arbiter_service_id), ); const activeRole = canHonorForcedRole ? args.forcedRole! : inferredRole; const effectiveServiceId = @@ -534,7 +534,16 @@ export async function runAgentForGroup( if (!evaluation.shouldForwardOutput) { return; } - if (typeof outputText === 'string' && outputText.length > 0) { + // Only count final-phase output as "visible" for handoff decisions. + // Progress messages (phase: 'progress') should not block failover + // handoffs — they don't represent meaningful completed work. + const isFinalPhase = + output.phase === undefined || output.phase === 'final'; + if ( + isFinalPhase && + typeof outputText === 'string' && + outputText.length > 0 + ) { streamedState = { ...evaluation.state, sawVisibleOutput: true,