From 3a58dde3ad1ed95c5a865ecd7d9163c6e4576501 Mon Sep 17 00:00:00 2001 From: Lauren ten Hoor Date: Wed, 11 Feb 2026 00:28:30 +0800 Subject: [PATCH] fix: clear startTime when deactivating workers to prevent stale timestamps Problem: When workers were deactivated (task completed or fixed by health checks), the startTime field was not being cleared. This caused: - Inactive workers to retain stale timestamps - Misleading duration data in projects.json - Potential confusion in health checks and status displays Example from projects.json: { "qa": { "active": false, "issueId": null, "startTime": "2026-02-10T08:51:50.725Z", // Stale! "tier": "qa" } } Root Cause: The deactivateWorker() function only set active: false and issueId: null, but did not clear startTime. Similarly, health check auto-fixes that deactivated workers also failed to clear startTime. Solution: Always set startTime: null when deactivating a worker to ensure clean state. Changes: 1. lib/projects.ts: - deactivateWorker() now sets startTime: null - Updated function comment to document this behavior 2. lib/services/health.ts: - All three auto-fix paths that deactivate workers now clear startTime: * active_no_session fix (line 77) * zombie_session fix (line 98) * stale_worker fix (line 138) Impact: - Inactive workers now have clean state (startTime: null) - Duration calculations only apply to active workers - Health checks work with accurate data - No stale timestamps persisting across task completions - Complements fix from #108 (which ensures startTime is set on activation) Together with #108: - #108: Always SET startTime when activating worker - #113: Always CLEAR startTime when deactivating worker - Result: startTime accurately reflects current task duration Addresses issue #113 --- lib/projects.ts | 2 ++ lib/services/health.ts | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/projects.ts b/lib/projects.ts index cb9c1ca..4215e40 100644 --- a/lib/projects.ts +++ b/lib/projects.ts @@ -230,6 +230,7 @@ export async function activateWorker( /** * Mark a worker as inactive after task completion. * Preserves sessions map and tier for reuse via updateWorker's spread. + * Clears startTime to prevent stale timestamps on inactive workers. */ export async function deactivateWorker( workspaceDir: string, @@ -239,6 +240,7 @@ export async function deactivateWorker( return updateWorker(workspaceDir, groupId, role, { active: false, issueId: null, + startTime: null, }); } diff --git a/lib/services/health.ts b/lib/services/health.ts index 053bd82..031bbdb 100644 --- a/lib/services/health.ts +++ b/lib/services/health.ts @@ -74,7 +74,7 @@ export async function checkWorkerHealth(opts: { fixed: false, }; if (autoFix) { - await updateWorker(workspaceDir, groupId, role, { active: false, issueId: null }); + await updateWorker(workspaceDir, groupId, role, { active: false, issueId: null, startTime: null }); fix.fixed = true; } fixes.push(fix); @@ -95,7 +95,7 @@ export async function checkWorkerHealth(opts: { await revertIssueLabel(fix); const sessions = { ...worker.sessions }; if (worker.tier) sessions[worker.tier] = null; - await updateWorker(workspaceDir, groupId, role, { active: false, issueId: null, sessions }); + await updateWorker(workspaceDir, groupId, role, { active: false, issueId: null, startTime: null, sessions }); fix.fixed = true; } fixes.push(fix); @@ -135,7 +135,7 @@ export async function checkWorkerHealth(opts: { }; if (autoFix) { await revertIssueLabel(fix); - await updateWorker(workspaceDir, groupId, role, { active: false, issueId: null }); + await updateWorker(workspaceDir, groupId, role, { active: false, issueId: null, startTime: null }); fix.fixed = true; } fixes.push(fix);