fix: /stop leaves stale paired task, sawOutput guard, progress text overwrite

- /stop now resets the active paired task to completed so the next
  user message routes to the owner instead of the stuck reviewer
- Owner completion with sawOutput=false (e.g. interrupted by /stop)
  no longer auto-triggers the reviewer — treated as interrupted
- Clear pendingProgressText when intermediate updates arrive on an
  existing progress message, preventing flushPendingProgress from
  overwriting latestProgressText with stale buffered content
This commit is contained in:
Eyejoker
2026-03-31 02:54:04 +09:00
parent 33575c84f1
commit dddf18428e
6 changed files with 38 additions and 11 deletions

View File

@@ -227,6 +227,7 @@ export async function runAgentForGroup(
let pairedExecutionStatus: 'succeeded' | 'failed' = 'failed';
let pairedExecutionSummary: string | null = null;
let pairedExecutionCompleted = false;
let pairedSawOutput = false;
const shouldHandoffToCodex = (
reason: AgentTriggerReason,
@@ -708,6 +709,7 @@ export async function runAgentForGroup(
switch (outcome.type) {
case 'success':
pairedSawOutput = outcome.sawOutput;
return 'success';
case 'error':
return 'error';
@@ -998,21 +1000,35 @@ export async function runAgentForGroup(
}
pairedExecutionStatus = 'succeeded';
pairedSawOutput = primaryAttempt.sawOutput;
return 'success';
} finally {
if (pairedExecutionContext && !pairedExecutionCompleted) {
const completedRole = roomRoleContext?.role ?? 'owner';
// Owner was interrupted without producing output (e.g. /stop) —
// treat as failed so reviewer is not auto-triggered.
const effectiveStatus =
completedRole === 'owner' &&
pairedExecutionStatus === 'succeeded' &&
!pairedSawOutput
? 'failed'
: pairedExecutionStatus;
completePairedExecutionContext({
taskId: pairedExecutionContext.task.id,
role: completedRole,
status: pairedExecutionStatus,
status: effectiveStatus,
summary: pairedExecutionSummary,
});
}
// After owner/reviewer completes, enqueue the next turn so
// the message loop picks it up without waiting for a new message.
if (pairedExecutionContext && pairedExecutionStatus === 'succeeded') {
// Skip if owner produced no output — likely interrupted by /stop.
if (
pairedExecutionContext &&
pairedExecutionStatus === 'succeeded' &&
pairedSawOutput
) {
deps.queue.enqueueMessageCheck(chatJid);
}
}