fix(host-service): don't reuse an archived (tombstoned) workspace on create
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 distinctworktreePath. - Full
workspace-create-delete.integration.test.tspasses: 13/13. tsc --noEmitclean onhost-service;biome checkclean 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, addisNull(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 distinctworktreePath; update deletion test to requirearchivedAtto 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.