From 222d73d0d6712175e240bafd4eef770e8b536182 Mon Sep 17 00:00:00 2001 From: Lukas May Date: Thu, 5 Mar 2026 11:09:11 +0100 Subject: [PATCH] fix: Clean up agent worktrees, branches, and logs on dismiss and auto-cleanup - Track worktree removal success in autoCleanupAfterCompletion() instead of always returning removed:true when removeAgentWorktrees() throws - Add removeAgentBranches() call to auto-cleanup path (agent/* branches were never cleaned after completion) - Add filesystem cleanup (worktrees, branches, logs) to dismiss() to prevent resource leaks until next server restart --- apps/server/agent/cleanup-manager.ts | 12 ++++++++++-- apps/server/agent/manager.ts | 11 +++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/server/agent/cleanup-manager.ts b/apps/server/agent/cleanup-manager.ts index cb8b1ff..f93c5c4 100644 --- a/apps/server/agent/cleanup-manager.ts +++ b/apps/server/agent/cleanup-manager.ts @@ -297,7 +297,7 @@ export class CleanupManager { /** * Auto-cleanup agent workdir after successful completion. - * Removes worktrees and logs but preserves branches and DB record. + * Removes worktrees, branches, and logs. Preserves DB record. */ async autoCleanupAfterCompletion( agentId: string, @@ -320,10 +320,18 @@ export class CleanupManager { await this.archiveForDebug(alias, agentId); } + let worktreeRemoved = true; try { await this.removeAgentWorktrees(alias, initiativeId); } catch (err) { log.warn({ agentId, alias, err: err instanceof Error ? err.message : String(err) }, 'auto-cleanup: failed to remove worktrees'); + worktreeRemoved = false; + } + + try { + await this.removeAgentBranches(alias, initiativeId); + } catch (err) { + log.warn({ agentId, alias, err: err instanceof Error ? err.message : String(err) }, 'auto-cleanup: failed to remove branches'); } try { @@ -333,7 +341,7 @@ export class CleanupManager { } log.info({ agentId, alias }, 'auto-cleanup: workdir and logs removed'); - return { clean: true, removed: true }; + return { clean: true, removed: worktreeRemoved }; } /** diff --git a/apps/server/agent/manager.ts b/apps/server/agent/manager.ts index 6c62c0d..5065e91 100644 --- a/apps/server/agent/manager.ts +++ b/apps/server/agent/manager.ts @@ -855,6 +855,17 @@ export class MultiProviderAgentManager implements AgentManager { log.info({ agentId, name: agent.name }, 'dismissing agent'); this.cleanupAgentState(agentId); + this.commitRetryCount.delete(agentId); + + // Best-effort filesystem cleanup + try { await this.cleanupManager.removeAgentWorktrees(agent.name, agent.initiativeId); } + catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'dismiss: failed to remove worktrees'); } + + try { await this.cleanupManager.removeAgentBranches(agent.name, agent.initiativeId); } + catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'dismiss: failed to remove branches'); } + + try { await this.cleanupManager.removeAgentLogs(agent.name); } + catch (err) { log.warn({ agentId, err: err instanceof Error ? err.message : String(err) }, 'dismiss: failed to remove logs'); } await this.repository.update(agentId, { userDismissedAt: new Date(),