Skip to content

fix(host-service): don't reuse a tombstoned workspace on same-branch create - #6552

Merged
Kitenite merged 3 commits into
ParadevAI:mainfrom
distroinfinity:workspace-not-found
Aug 19, 2026
Merged

Kitenite merged 3 commits into
ParadevAI:mainfrom
distroinfinity:workspace-not-found

Conversation

@distroinfinity

@distroinfinity distroinfinity commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

What & why

Fixes #6383, refs #6380.

Since #6296 turned workspace deletes into tombstones (archivedAt + archiveReason, row kept for the board's Merged/Deleted history), the create flow's branch-idempotency lookup findExistingWorkspaceByBranch still matched on (projectId, branch) with no archived filter — the one consumer #6296's "consumers updated" pass missed. Recreating a deleted workspace's name therefore "reused" the tombstone: exit 0, alreadyExists: true, no worktree created, and the desktop redirected to the dead row's id, which workspace.list filters out — landing users on the "Workspace not found" screen. CLI/SDK/MCP callers got a success response for a workspace that doesn't exist (the automation-fleet failure described in #6383).

This PR adds the isNull(workspaces.archivedAt) guard to the lookup, matching the convention every sibling lookup already follows (adopt-existing-worktree.ts, workspace.list, session folder dedupe). #6296 explicitly planned for re-creating a workspace on a tombstoned branch ("Tombstones aren't phantoms — same-branch history must survive re-creating a workspace on that branch"); this makes that path reachable.

Note: #6384 proposes the same guard — happy to defer to it if it lands first; this PR adds an independent regression test and desktop-flow verification.

How I tested it

  • New integration test (workspace-create-delete.integration.test.ts): create → delete (assert tombstone) → create on the same branch → asserts a fresh live row with a real worktree on disk, alreadyExists: false, and the tombstone's history untouched. Watched it fail on main (alreadyExists came back true) before the fix.
  • End-to-end in the dev desktop app (before/after): reproduced the bug twice on main — each recreate left zero new rows, no worktree, no branch, and the renderer sat on the tombstone's id showing "Workspace not found" (screenshots below). With the fix, repeated create → delete → recreate cycles on the same name each produced a fresh live workspace coexisting with its tombstone, verified in host.db and on disk.
  • bun run lint (clean — no warnings), bun run typecheck, full @superset/host-service suite: 1112 pass / 0 fail.

Known limitation (deliberately out of scope): a create that lands while a destroy of the same branch is still mid-pipeline (archive-first, worktree removed last) can adopt the dying worktree; that window predates this change and is better handled by serializing create/destroy separately.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass (CI fails on lint warnings too)
  • "Allow edits from maintainers" is checked on fork PRs

Summary by cubic

Prevents workspace.create from reusing a tombstoned workspace on the same branch, fixing “Workspace not found” after recreate. Previously the idempotency lookup matched archived rows, returned alreadyExists: true, and created no worktree; now it ignores tombstones and inserts a fresh live workspace with a real worktree.

  • Filters archived rows in findExistingWorkspaceByBranch by adding isNull(workspaces.archivedAt) in @superset/host-service.
  • Adds an integration test for delete → same-branch recreate asserting a new id, alreadyExists: false, live worktree, and preserved tombstone history.
  • No API or schema changes; adopt path already excludes archived rows. Known gap unchanged: a create racing a delete on the same branch can adopt the dying worktree.

Written for commit 9dd093e. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

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

    • Added coverage confirming archived workspaces remain unchanged and newly created workspaces receive a distinct ID and worktree.

…create

Since ParadevAI#6296 turned workspace deletes into tombstones (archivedAt), the
create flow's branch-idempotency lookup still matched archived rows, so
recreating a deleted workspace's name returned the dead row: no worktree
was created, the call reported alreadyExists, and the desktop navigated
to an id the workspace list filters out — landing on "Workspace not
found" (ParadevAI#6383, ParadevAI#6380).

Filter tombstones out of findExistingWorkspaceByBranch, matching the
isNull(archivedAt) convention every sibling lookup already follows, and
add an integration regression test for the delete → same-branch
recreate flow.
@coderabbitai

coderabbitai Bot commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ef01fdca-40f0-4191-847c-dee7d96d7584

📥 Commits

Reviewing files that changed from the base of the PR and between 1f07abf and 9dd093e.

📒 Files selected for processing (2)
  • packages/host-service/src/trpc/router/workspaces/workspaces.ts
  • packages/host-service/test/integration/workspace-create-delete.integration.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/host-service/src/trpc/router/workspaces/workspaces.ts
  • packages/host-service/test/integration/workspace-create-delete.integration.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

Workspace branch idempotency lookup now excludes archived workspace rows. Integration coverage verifies that deleting and recreating a workspace on the same branch creates a new active workspace and worktree while preserving the original archive metadata.

Changes

Workspace branch reuse

Layer / File(s) Summary
Active branch lookup and regression coverage
packages/host-service/src/trpc/router/workspaces/workspaces.ts, packages/host-service/test/integration/workspace-create-delete.integration.test.ts
findExistingWorkspaceByBranch now requires archivedAt to be null. The integration test verifies that recreation returns a new workspace with a worktree and leaves the archived row unchanged.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 9dd09

This change prevents deleted workspace records from being reused during same-branch creation and adds regression coverage; no actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title uses conventional commit format and clearly describes the fix for tombstoned workspace reuse.
Description check ✅ Passed The description covers the problem, solution, testing, checklist, linked issues, and known limitation in sufficient detail.
Linked Issues check ✅ Passed The change adds the required archived-row filter and regression test for fresh workspace creation after deletion [#6383].
Out of Scope Changes check ✅ Passed The code changes are limited to the archived-row filter and its focused integration regression test.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@distroinfinity

Copy link
Copy Markdown
Contributor Author

hey @Kitenite
did you get a chance to check this?

…potency filter

Folds in the clearer rationale from the duplicate PR ParadevAI#6605: matching a
tombstone returns the archived row with alreadyExists: true and silently
skips the create, and the adopt path already filters archived rows.
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@Kitenite
Kitenite merged commit e483672 into ParadevAI:main Aug 19, 2026
18 of 20 checks passed

This branch had an error being deployed

1 failed deployment
preview — 9dd093ee Deployed Aug 19, 2026 by Kitenite via Deploy Database (Neon) #8087
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants