Add non-destructive recovery for pushed branches after lost issue locks #440

Closed
opened 2026-07-07 12:28:34 -05:00 by jcwalker3 · 3 comments
Owner

Problem

During issue #420, the author completed and pushed branch feat/issue-420-server-code-parity at commit 934688a, but the MCP server restarted before PR creation and wiped the in-memory issue lock.

After restart:

  • gitea_create_pr refused to create the PR because the live issue lock was missing.
  • gitea_lock_issue refused to reacquire the lock because a remote branch matching issue-420 already existed.
  • The branch was the author’s own pushed work, but the duplicate-work guard treated it as a blocker.
  • The proposed recovery path required deleting the remote branch, then re-running lock → push → create PR.

This is unsafe. Recovery from a stale or missing lock should not require destructive remote branch deletion.

Acceptance Criteria

  1. Issue locks must survive MCP server restarts, or recovery must be explicitly supported.
  2. A pushed branch for the same issue must not automatically deadlock lock reacquisition.
  3. Recovery must be non-destructive by default.
  4. gitea_lock_issue must distinguish:
    • another session’s competing branch
    • the same actor/session recovering its own already-pushed branch
    • an existing open PR
    • a stale branch with no active lock
  5. gitea_create_pr should support a safe recovery/adoption path for an already-pushed branch when ownership and safety checks pass.
  6. Duplicate branch detection must not rely only on broad substring matching like issue-420; it should use structured issue/branch ownership evidence where possible.
  7. Add tests for:
    • lock lost after server restart with branch already pushed
    • same actor recovering the branch and creating the PR
    • competing actor blocked from adopting the branch
    • existing PR detection preventing duplicate PR creation
    • stale branch recovery without branch deletion
  8. Update workflow docs so author sessions do not request destructive branch deletion as the normal recovery path.

Observed Case

## Problem During issue #420, the author completed and pushed branch `feat/issue-420-server-code-parity` at commit `934688a`, but the MCP server restarted before PR creation and wiped the in-memory issue lock. After restart: * `gitea_create_pr` refused to create the PR because the live issue lock was missing. * `gitea_lock_issue` refused to reacquire the lock because a remote branch matching `issue-420` already existed. * The branch was the author’s own pushed work, but the duplicate-work guard treated it as a blocker. * The proposed recovery path required deleting the remote branch, then re-running lock → push → create PR. This is unsafe. Recovery from a stale or missing lock should not require destructive remote branch deletion. ## Acceptance Criteria 1. Issue locks must survive MCP server restarts, or recovery must be explicitly supported. 2. A pushed branch for the same issue must not automatically deadlock lock reacquisition. 3. Recovery must be non-destructive by default. 4. `gitea_lock_issue` must distinguish: * another session’s competing branch * the same actor/session recovering its own already-pushed branch * an existing open PR * a stale branch with no active lock 5. `gitea_create_pr` should support a safe recovery/adoption path for an already-pushed branch when ownership and safety checks pass. 6. Duplicate branch detection must not rely only on broad substring matching like `issue-420`; it should use structured issue/branch ownership evidence where possible. 7. Add tests for: * lock lost after server restart with branch already pushed * same actor recovering the branch and creating the PR * competing actor blocked from adopting the branch * existing PR detection preventing duplicate PR creation * stale branch recovery without branch deletion 8. Update workflow docs so author sessions do not request destructive branch deletion as the normal recovery path. ## Observed Case - **Issue**: #420 - **Branch**: `feat/issue-420-server-code-parity` - **Commit**: `934688a` - **Cause**: server restart wiped in-memory issue lock after branch push - **Result**: lock/PR creation deadlock
jcwalker3 added the status:in-progress label 2026-07-07 15:39:26 -05:00
Author
Owner

Issue claim heartbeat

<!-- gitea-issue-claim-heartbeat:v1 --> **Issue claim heartbeat** - kind: claim - issue: #440 - branch: feat/issue-440-lock-recovery - phase: claimed - profile: prgs-author - pr: none - blocker: none - next_action: create worktree and begin implementation
Author
Owner

Issue claim heartbeat

<!-- gitea-issue-claim-heartbeat:v1 --> **Issue claim heartbeat** - kind: claim - issue: #440 - branch: feat/issue-440-branch-recovery - phase: claimed - profile: prgs-author - pr: none - blocker: none - next_action: create worktree and begin implementation
jcwalker3 removed the status:in-progress label 2026-07-07 15:44:13 -05:00
Author
Owner

Deferred (umbrella). PR #466 marked superseded/blocked; author claim released. Work proceeds via dependency PRs #465/#443, #461/#442, #464/#438. Revisit #440 after those land.

**Deferred (umbrella).** PR #466 marked superseded/blocked; author claim released. Work proceeds via dependency PRs #465/#443, #461/#442, #464/#438. Revisit #440 after those land.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#440