From 04904ce032f6ba1bc7fc10c833e67d72affa537a Mon Sep 17 00:00:00 2001 From: jedarden Date: Sun, 7 Jun 2026 10:42:31 -0400 Subject: [PATCH] fix(bf-27e4): unify stuck detection metric with beadsCompleted The stuck detection's detectLongRunning function was using text-based message matching ('completed'/'complete' in msg) to count completions, while beadsCompleted counts actual bead.completed and bead.released events with release_success. This caused confusion: a worker with 285 beadsCompleted (all timed out) would be flagged as stuck with 'only 1 completion(s)' because the message filter found few matches. Changed detectLongRunning to use worker.beadsCompleted directly for consistency. Updated reason text to clarify 'successful completion(s)' Fixes #bf-27e4 --- src/tui/utils/stuckDetection.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/tui/utils/stuckDetection.ts b/src/tui/utils/stuckDetection.ts index a886e3a..5adf943 100644 --- a/src/tui/utils/stuckDetection.ts +++ b/src/tui/utils/stuckDetection.ts @@ -284,17 +284,19 @@ function detectLongRunning( if (runningTime > opts.longRunningThresholdMs) { const minutes = Math.floor(runningTime / 60000); - // Check if making progress - const completions = events.filter( - (e) => e.msg?.includes('completed') || e.msg?.includes('complete') - ).length; + // Use worker.beadsCompleted (counts bead.completed and bead.released with release_success) + // instead of text-based message matching + const completions = worker.beadsCompleted; if (completions < 2) { return { type: 'long_running', - reason: `Running for ${minutes}m with only ${completions} completion(s)`, + reason: `Running for ${minutes}m with only ${completions} successful completion(s)`, severity: minutes >= 20 ? 'critical' : 'warning', - evidence: [`Beads completed: ${worker.beadsCompleted}`], + evidence: [ + `Beads completed: ${worker.beadsCompleted}`, + `Total events in window: ${events.length}`, + ], suggestion: 'Consider breaking task into smaller pieces', }; }