fix(host-service): don't reuse an archived (tombstoned) workspace on create

Closed
AN
3mo ago
+50-2

Fixes #6383

Problem

Since PR #6296 made workspace deletes archive rows (tombstones) instead of removing them, workspaces.create could "reuse" a deleted workspace. findExistingWorkspaceByBranch matched on (projectId, branch) without excluding archived rows, so a create on a branch whose previous workspace was deleted returned the tombstone: exit code 0, alreadyExists: true, message "Reused existing workspace", no git worktree created — and the requested agent was still dispatched against a worktreePath the delete pipeline already removed.

The archived row is hidden from workspaces list, so from the caller's side the workspace simply doesn't exist while the CLI reports success.

Root cause

packages/host-service/src/trpc/router/workspaces/workspaces.ts — findExistingWorkspaceByBranch (line 156) queried only on (projectId, branch):

where: and(
  eq(workspaces.projectId, projectId),
  eq(workspaces.branch, branch),
),

It never excluded rows with a non-null archivedAt, so tombstones were treated as live workspaces.

Fix

The lookup now excludes archived rows via isNull(workspaces.archivedAt), so a create-after-delete on the same branch creates a fresh workspace and worktree instead of "reusing" the dead row. Because the fix lives in the shared lookup function, both call sites (create for PR-derived branches and for plain branch names) benefit.

Verification

  • New integration test: create → delete (archives row) → create on the exact same branch asserts alreadyExists === false, a new workspace id, an active (non-archived) row, and a distinct worktreePath.
  • Full workspace-create-delete.integration.test.ts passes: 13/13.
  • tsc --noEmit clean on host-service; biome check clean on both edited files.

Summary by cubic

Stop reusing archived (tombstoned) workspaces when creating on a branch that previously had a deleted workspace. Before: create-after-delete matched the tombstone, returned alreadyExists=true, skipped worktree creation, and dispatched agents to a removed worktreePath. Now: archived rows are ignored and a fresh workspace and worktree are created.

  • In shared findExistingWorkspaceByBranch, add isNull(workspaces.archivedAt) to the (projectId, branch) lookup so both PR-derived and plain-branch creates ignore tombstones.
  • Tests: add an integration test for create → delete → create asserting alreadyExists === false, a new workspace id, an active row, and a distinct worktreePath; update deletion test to require archivedAt to be defined (timestamped).

Summary by CodeRabbit

  • Bug Fixes

    • Creating a workspace after deleting a previous one now correctly creates a new active workspace instead of reusing the archived workspace.
  • Tests

    • Added coverage to verify workspace recreation and associated worktree creation after deletion.