Conversation
A checkbox next to the scope picker on both tabs hides every package that another installed package depends on, matching brew leaves semantics. Dependency edges come from the existing inventory snapshot over the full installed inventory, so no new brew invocations run and the Upgrades tab does not misclassify a package whose only dependent is itself up to date. While the filter is on, Upgrade All names the visible rows explicitly because brew upgrade and the kind flags cannot express top-level only, and the Show All Upgrades empty-state action resets it alongside the scope picker and the search query. The toggle label truncates under narrow windows instead of raising the list column's minimum width, which would otherwise break the saved window-size restore covered by WindowFrameUITests.
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The change is well covered by new unit and UI tests and integrates cleanly with existing filtering and selection behaviour, with only minor optional performance tuning suggested.
Review effort: Lite
Findings: 2
Open (2)
What changed in this PR
Adds a client-side "Top-Level Only" filter to the Installed and Upgrades tabs so users can hide dependency packages (brew leaves-style) and focus on packages they manage directly, while preserving existing scope, search and selection behaviour.
Changes:
- Introduces a top-level-only toggle in both Installed and Upgrades filter bars, including new accessibility identifiers.
- Extends Installed and Upgrades view models to compute and apply top-level filtering, including upgraded Upgrade All behaviour when filtering requires explicit package names.
- Adds unit tests, UI tests and a new UI fixture scenario covering dependency hiding and selection behaviour.
| File | Description |
|---|---|
| Tests/BrewFeatureInstalledTests/UpgradesViewModelTopLevelTests.swift | Adds unit coverage for top-level filtering, selection and upgrade command behaviour on the Upgrades view model. |
| Tests/BrewFeatureInstalledTests/InstalledViewModelTopLevelTests.swift | Adds unit coverage for top-level filtering composition with scope and search, plus selection fallback/restore on Installed. |
| Sources/BrewRepositoryInterfaces/Protocols/InstalledInventoryObserving+TopLevel.swift | Adds a repository-derived dependency ID set used to identify non-top-level packages. |
| Sources/BrewFeatureInstalled/Views/UpgradesPackagesView.swift | Replaces the scope-only picker with a filter bar that includes the new checkbox toggle. |
| Sources/BrewFeatureInstalled/Views/InstalledPackagesView.swift | Replaces the scope-only picker with a persistent filter bar including the new checkbox toggle. |
| Sources/BrewFeatureInstalled/ViewModels/UpgradesViewModel.swift | Applies top-level filtering to the outdated list, adjusts selection re-homing and updates Upgrade All semantics and copy. |
| Sources/BrewFeatureInstalled/ViewModels/InstalledViewModel.swift | Applies top-level filtering to the installed inventory and aligns selection re-homing with filter changes. |
| Sources/BrewAccessibilityID/AXID.swift | Adds AX identifiers for the two new top-level filter toggles. |
| BrewUITests/Tests/InstalledUITests.swift | Adds UI tests asserting dependencies are hidden by the top-level filter in both Installed and Upgrades tabs. |
| BrewUITests/Screens/UpgradesScreen.swift | Adds a screen action for toggling the Upgrades top-level filter checkbox. |
| BrewUITests/Screens/InstalledScreen.swift | Adds a screen action for toggling the Installed top-level filter checkbox. |
| BrewUITests/Harness/BrewUITestScenario.swift | Adds a new installedTopLevel scenario for deterministic UI testing. |
| BrewUITests/Fixtures/ScenarioFixtures.swift | Adds fixture data modelling a dependency chain where the dependency is also outdated, ensuring both tabs exercise the filter. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| .loaded( | ||
| Self.filteredContent( | ||
| InstalledPackagesContent(packages: repository.outdatedPackages), | ||
| scope: scope, | ||
| showsTopLevelPackagesOnly: showsTopLevelPackagesOnly, | ||
| dependencyPackageIDs: repository.userManagedDependencyPackageIDs, | ||
| query: searchQuery, | ||
| ), |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
An alternative to this has been merged in #244. It's only on the installed tab but I think that's fine for now as is. |
|
It's better to add the filter to Upgrades lists page. |

What and why
The Installed and Upgrades tabs list every installed package, including libraries that were pulled in as dependencies, so finding what you actually installed means mentally skipping packages like openssl. This adds a "Top-Level Only" checkbox next to the scope picker on both tabs that hides every package another installed package depends on — the same definition as
brew leaves.brew info --installed --json=v2inventory, computed over the full installed inventory rather than the filtered subset, so no new brew invocations run and the Upgrades tab does not misclassify a package whose only dependent is itself up to date.brew upgrade git wget), because neitherbrew upgradenor the kind flags can express top-level only. The Show All Upgrades empty-state action resets the checkbox alongside the scope and the search.WindowFrameUITests.Validation
Environment: macOS 27.0 (26A428), Mac mini (arm64), Xcode 27.0 (27A266a), Swift 6.2.
scripts/test(BrewKit + BrewUILint packages): pass, including 21 new unit tests covering the filter on both view models (composing with scope and search, dependency edges over the full inventory, selection fallback and restore, subtitle switches,upgradeSelectionfalling back to explicit names,bulkUpgradeSummarycopy,resetFilters).scripts/test-ui(Brew-UI plan): full run passed 46 of 49 tests. The two new UI tests (dependency rows hidden on both tabs, via a newinstalledTopLevelfixture scenario) passed in that run. The 3 failures (WindowFrameUITestswindow-size restore,ListFocusUITestsandSelfUpgradeUITestsfocus/foreground waits) each passed when re-run individually; they are focus flakes of running the windowed suite on a busy Mac, not related to this change.mint run swiftformat --lint .: clean.mint run swiftlint lint --strict: 0 violations.Not run:
scripts/test-e2e(not requested; it installs and uninstallshelloagainst real Homebrew), and the manual VoiceOver and light/dark appearance passes — the checkbox uses the standard system checkbox style and carries accessibility identifiers, but a human pass is still outstanding.Screenshots
Visible change: the Installed and Upgrades filter bars now show a "Top-Level Only" checkbox to the right of the All/Formulae/Casks picker.
AI assistance
Implemented end to end by the GLM5.3 from the request to add a top-level package checkbox to the Installed and Upgrades pages: production code, unit tests, UI tests, fixtures, and every validation run listed above, executed locally on the contributor's machine. All listed checks were therefore performed by the agent; human review and the outstanding manual checks remain.