fix(execution-workspaces): clear closed_at on reopen via PATCH (SHA-2492)#12
Open
Mlaz-code wants to merge 1 commit into
Open
fix(execution-workspaces): clear closed_at on reopen via PATCH (SHA-2492)#12Mlaz-code wants to merge 1 commit into
Mlaz-code wants to merge 1 commit into
Conversation
…492) When a PATCH transitions an execution_workspace row from a closed status (archived/cleanup_failed) back to an open one (active/idle), the route left closed_at and cleanup_reason populated. That produces a row that's "closed-by-timestamp, open-by-status" — isClosedIsolatedExecutionWorkspace ORs both signals, so subsequent issue comments/PATCHes 409 with "linked to closed workspace" even though the workspace is in use. Triggered by SHA-2105 on 2026-05-08: Coordinator PATCHed status=active on an idle/closed_at-stamped row to unblock the issue; the row stayed contradictory and 1037 sibling rows had been quietly accumulating from manual cleanup recipes that paired closed_at with status='idle'. Fix: in the non-archive PATCH branch, if existing.status is closed and the requested status is open, also clear closedAt and (unless explicitly set in the request) cleanupReason. Exports CLOSED_EXECUTION_WORKSPACE_STATUSES and a new isClosedExecutionWorkspaceStatus helper so the same set drives the route + the existing guard. Adds two route tests covering the reopen-clears-closedAt path and the no-op-when-status-not-changed path. Companion changes coming in a follow-up: a CHECK constraint making the contradictory state representationally impossible, plus a backfill of the 1037 existing rows.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the first half of SHA-2492 —
execution_workspacesrows ending up in(status='active', closed_at=stamped)after a status-only PATCH.The PATCH route at
server/src/routes/execution-workspaces.ts:456-468accepts a status patch but never touchesclosed_at. Transitioning a row fromarchived/cleanup_failedback toactive/idlevia the API leavesclosed_atpopulated.isClosedIsolatedExecutionWorkspaceORs both signals, so the row fails-closed and any subsequent comment/PATCH on a linked issue 409s "linked to closed workspace" even though the workspace is in use.Triggered live on 2026-05-08 when Coordinator PATCHed
{status:'active'}on an SHA-2105 workspace to unblock the issue — succeeded, but left the row contradictory. We've found 1037 of these on the prod paperclip DB, all from manual cleanup recipes that pairedclosed_atwithstatus='idle'. Tracked in Paperclip-issue SHA-2492.Changes
packages/shared/src/execution-workspace-guards.ts— exportCLOSED_EXECUTION_WORKSPACE_STATUSES+ newisClosedExecutionWorkspaceStatus(status)helper so the route + the existingisClosedIsolatedExecutionWorkspaceguard share one source of truth.packages/shared/src/index.ts— re-export the two new symbols.server/src/routes/execution-workspaces.ts— in the non-archive PATCH branch, ifexisting.statusis closed and the requested status is open, also clearclosedAtand (unless the request explicitly sets it)cleanupReason.server/src/__tests__/execution-workspaces-routes.test.ts— two new route tests: (a) reopen clearsclosedAt+cleanupReason; (b) status-not-changed leaves both fields untouched.Companion work (separate PRs / steps, not in this branch)
/shared-tmp/worktree-cleanup.sh(dailyworktree-cleanup.timer, originally SHA-1847) was the prime accreting source. Edited 2026-05-12 to writestatus='archived'instead of'idle'; verified live on the 2026-05-13 04:33 EDT fire.CHECK (closed_at IS NULL OR status IN ('archived','cleanup_failed')),NOT VALID+ post-backfillVALIDATE. Separate PR.UPDATE execution_workspaces SET status='archived' WHERE closed_at IS NOT NULL AND status NOT IN ('archived','cleanup_failed')on the prod paperclip DB (1037 rows expected; pre-audit confirmed 0 rows have a non-terminal source issue, so bulk archive is safe). Manual step pending Board approval.Test plan
bash -non the script fix; observedarchivedrows produced on the next timer fireclosed_atis NULL on the response