From d026df5fb282eeb867ffb02fde6c7b80be0dc682 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Tue, 19 May 2026 03:02:03 +0000 Subject: [PATCH 1/2] fix(code): prevent archived tasks from reappearing after archive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit archiveTaskImperative wrote optimistic updates to the archive queries without cancelling in-flight refetches first. A background refetch (triggered by the window-focus manager or the 30s task poll) could land between the optimistic write and the mutation completing, then overwrite the optimistic cache with the still-unarchived server snapshot — making the archived task reappear in the sidebar until the post-mutation invalidate caught up. Match the pattern useDeleteTask already uses: cancelQueries before setQueryData. Also snapshot per-task terminal state and command center cell index before clearing them, and restore both in the error path so a failed archive leaves no orphaned UI state. Generated-By: PostHog Code Task-Id: 3c57db18-63ca-4bc0-9fa5-8fbe8a3795a8 --- .../features/tasks/hooks/useArchiveTask.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts b/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts index 6552a87b2..45f3df161 100644 --- a/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts +++ b/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts @@ -34,10 +34,21 @@ export async function archiveTaskImperative( } } + const terminalStatesSnapshot = Object.fromEntries( + Object.entries(useTerminalStore.getState().terminalStates).filter( + ([key]) => key === taskId || key.startsWith(`${taskId}-`), + ), + ); + const commandCenterIndex = useCommandCenterStore + .getState() + .cells.indexOf(taskId); + pinnedTasksApi.unpin(taskId); useTerminalStore.getState().clearTerminalStatesForTask(taskId); useCommandCenterStore.getState().removeTaskById(taskId); + await queryClient.cancelQueries(trpc.archive.pathFilter()); + queryClient.setQueryData( trpc.archive.archivedTaskIds.queryKey(), (old) => (old ? [...old, taskId] : [taskId]), @@ -87,6 +98,14 @@ export async function archiveTaskImperative( if (wasPinned) { pinnedTasksApi.togglePin(taskId); } + if (Object.keys(terminalStatesSnapshot).length > 0) { + useTerminalStore.setState((s) => ({ + terminalStates: { ...s.terminalStates, ...terminalStatesSnapshot }, + })); + } + if (commandCenterIndex !== -1) { + useCommandCenterStore.getState().assignTask(commandCenterIndex, taskId); + } throw error; } From 3b4beee292d9605abed9f1a074878b89d077c693 Mon Sep 17 00:00:00 2001 From: Richard Solomou Date: Tue, 19 May 2026 03:21:21 +0000 Subject: [PATCH 2/2] fix(code): preserve active task on archive rollback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous rollback used assignTask(cellIndex, taskId) to restore the command-center cell on archive failure. assignTask unconditionally sets activeTaskId to the assigned task, so a failed archive of a non-active cell silently stole focus from whatever the user actually had active. Snapshot wasActiveInCommandCenter alongside the cell index, and restore the cell via setState — only writing activeTaskId back when the archived task was the active one. Mirrors removeTaskById's existing semantics. Generated-By: PostHog Code Task-Id: 3c57db18-63ca-4bc0-9fa5-8fbe8a3795a8 --- .../features/tasks/hooks/useArchiveTask.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts b/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts index 45f3df161..9f70c79f2 100644 --- a/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts +++ b/apps/code/src/renderer/features/tasks/hooks/useArchiveTask.ts @@ -39,9 +39,9 @@ export async function archiveTaskImperative( ([key]) => key === taskId || key.startsWith(`${taskId}-`), ), ); - const commandCenterIndex = useCommandCenterStore - .getState() - .cells.indexOf(taskId); + const commandCenterState = useCommandCenterStore.getState(); + const commandCenterIndex = commandCenterState.cells.indexOf(taskId); + const wasActiveInCommandCenter = commandCenterState.activeTaskId === taskId; pinnedTasksApi.unpin(taskId); useTerminalStore.getState().clearTerminalStatesForTask(taskId); @@ -104,7 +104,13 @@ export async function archiveTaskImperative( })); } if (commandCenterIndex !== -1) { - useCommandCenterStore.getState().assignTask(commandCenterIndex, taskId); + useCommandCenterStore.setState((s) => { + const cells = [...s.cells]; + cells[commandCenterIndex] = taskId; + return wasActiveInCommandCenter + ? { cells, activeTaskId: taskId } + : { cells }; + }); } throw error;