RunningApps maps installed casks to their .app bundles via the
Caskroom copy (no brew process needed) and checks them against
NSWorkspace's running applications. Two settings in a new "Running
apps" section: auto-upgrade skips running casks (on by default —
that flow has no dialog to warn anyone), manual bulk upgrades can opt
in. The auto-upgrade filter runs before the trigger decision so a
permanently running app cannot start an upgrade cycle that would skip
it anyway. The confirmation dialog now names the apps actually
running instead of a blanket warning, and stays silent when none are.
Single-package upgrades from the Outdated menu always proceed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fetchOutdated now uses --json and the typed parser, so cachedOutdated
knows formulae from casks. The auto-upgrade trigger checks each kind
against its own toggle: an outdated cask no longer starts a pointless
"upgrade --formula" run (previously any outdated package triggered
whichever auto-upgrades were enabled). runAutoUpgrade takes explicit
formulae/casks flags instead of re-reading settings.
Bonus from the version info now available: outdated menu items and the
Upgrade All confirmation show "name installed → current" instead of
bare names. The legacy line parser and its tests are removed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
parseOutdatedJSON decodes brew outdated --json into OutdatedPackages,
which separates formulae from casks — the plain-text output is just
names with no type information. Codable structs mirror the JSON shape,
with convertFromSnakeCase mapping installed_versions to Swift naming.
Undecodable input (brew error text, empty output) parses as .none.
The legacy line parser stays until callers switch over next commit.
Covered by 4 new unit tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extract brew output parsing into BrewParser.swift (pure Swift, no AppKit)
and add BrewBarTests target with 7 passing tests covering parseOutdated
and parseVersion edge cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>