Skip to content

unconfigurePack silently discards failed brew/plugin removals #244

@bguidolim

Description

@bguidolim

Context

unconfigurePack() in Configurator.swift unconditionally clears remaining.brewPackages = [] and remaining.plugins = [] after attempting removal, regardless of whether each individual removal succeeded or failed.

Problem

When brew uninstall or claude plugin remove fails during pack removal (mcs pack remove or deselection during mcs sync):

  • No warning is emitted to the user
  • The artifact is dropped from PackArtifactRecord tracking
  • The failed removal will never be retried on subsequent syncs
  • The user is left with an orphaned brew package or plugin with no indication anything went wrong

Contrast with other call sites

Both removeNewlyExcludedComponentArtifacts() and reconcileStaleArtifacts() correctly handle the .failed case by:

  1. Keeping the artifact in the record for retry
  2. Logging a warning to the user

Only unconfigurePack() silently discards failures.

Proposed Solution

Replace the unconditional bulk-clear with per-item tracking:

for package in artifacts.brewPackages {
    let result = removeBrewArtifact(...)
    switch result {
    case .removed, .stillNeeded:
        break
    case .failed:
        remaining.brewPackages.append(package)
        output.warn("  Could not remove brew package '\(package)' — will retry on next sync")
    }
}
// Remove the unconditional `remaining.brewPackages = []`

Same pattern for plugins.

Notes

Discovered during PR review of #243. Pre-existing defect — not introduced by the refactor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions