Skip to content

Fix deleted repo group resurrection bug#184

Merged
PureWeen merged 3 commits intomainfrom
fix/deleted-group-resurrection
Feb 27, 2026
Merged

Fix deleted repo group resurrection bug#184
PureWeen merged 3 commits intomainfrom
fix/deleted-group-resurrection

Conversation

@jfversluis
Copy link
Collaborator

Problem

When a user deletes a sidebar group that is linked to a tracked repository, the group reappears ("resurrects") on the next UI state refresh. This happens because ReconcileOrganization() enforces the invariant "every tracked repo must have a sidebar group" — but this conflicts with the user's explicit deletion.

Root Cause

Three code paths in ReconcileOrganization call GetOrCreateRepoGroup, which recreates the group if the repo is still tracked by RepoManager:

  1. Auto-link sessions (line 214): Session's working directory matches a worktree → creates repo group
  2. Reassign orphaned sessions (line 234): Session has WorktreeId but is in _default group → creates repo group
  3. Ensure repo coverage (line 259): Tracked repo has no group → creates repo group

Fix

  • DeletedRepoGroupRepoIds — new HashSet<string> on OrganizationState (persisted to organization.json) that tracks repo IDs whose groups were explicitly deleted by the user
  • GetOrCreateRepoGroup(repoId, name, explicitly) — new explicitly parameter:
    • Implicit calls (from ReconcileOrganization) return null for deleted repos
    • Explicit calls (from repo-add operations) clear the deleted flag and create the group
  • DeleteGroup — now clears WorktreeId on moved sessions for repo groups, preventing ReconcileOrganization from reassigning them via the worktree path
  • Backward compatibility — null-coalesce guard in LoadOrganization handles old organization.json files without the new field

Tests

13 new tests in DeletedRepoGroupResurrectionTests covering:

  • Delete adds to deleted set / non-repo delete doesn't
  • WorktreeId cleared for repo groups / preserved for non-repo groups
  • Implicit GetOrCreateRepoGroup returns null for deleted repos
  • Explicit GetOrCreateRepoGroup clears deleted flag
  • Existing group returned even if in deleted set
  • ReconcileOrganization doesn't resurrect deleted group
  • Session not reassigned after group deletion
  • Serialization round-trip of DeletedRepoGroupRepoIds
  • Legacy JSON backward compatibility
  • Default group deletion is no-op
  • Re-add repo clears deleted flag

All 1157 existing tests pass (1 pre-existing locale-dependent failure unrelated).

jfversluis and others added 2 commits February 26, 2026 19:21
When a user deletes a sidebar group linked to a tracked repository,
ReconcileOrganization would immediately recreate it because it enforces
'every tracked repo must have a sidebar group'. This caused the deleted
group to reappear in the sidebar.

Root cause: Three code paths in ReconcileOrganization call
GetOrCreateRepoGroup which recreates the group if the repo is still
tracked by RepoManager.

Fix:
- Add DeletedRepoGroupRepoIds to OrganizationState (persisted to JSON)
  to track repos whose groups were explicitly deleted by the user
- GetOrCreateRepoGroup now accepts an 'explicitly' parameter: implicit
  calls (from ReconcileOrganization) return null for deleted repos;
  explicit calls (from repo-add operations) clear the deleted flag
- DeleteGroup clears WorktreeId on moved sessions to prevent
  ReconcileOrganization from reassigning them via the worktree path
- Null-coalesce guard in LoadOrganization for backward compatibility
  with old organization.json files

Includes 13 new tests covering all scenarios.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- CopilotService.cs:1616 — pass explicitly:true and add null guard before
  MoveSession(group.Id) to prevent NRE when user creates a session in a
  worktree whose repo group was previously deleted
- WsBridgeServer.cs:681 — wrap GetOrCreateRepoGroup call in InvokeOnUI()
  to marshal Organization mutations from the Task.Run background thread
  to the UI thread, preventing concurrent list modification

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen force-pushed the fix/deleted-group-resurrection branch from 70bea03 to e486bdc Compare February 27, 2026 01:29
Deleting a multi-agent team that has a RepoId set was poisoning the
tombstone set, causing ReconcileOrganization to suppress auto-creation
of the regular sidebar group for that repo on future reconciliations.

DeletedRepoGroupRepoIds — multi-agent groups share the RepoId key
but are tracked separately via IsMultiAgent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen merged commit d6fd6f3 into main Feb 27, 2026
@PureWeen PureWeen deleted the fix/deleted-group-resurrection branch February 27, 2026 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants