Skip to content

fix(bundles): keep user-set priorities when a bundle is refreshed - #5319

Open
kartsan03 wants to merge 4 commits into
github:mainfrom
kartsan03:fix/bundle-refresh-keep-priorities
Open

kartsan03 wants to merge 4 commits into
github:mainfrom
kartsan03:fix/bundle-refresh-keep-priorities

Conversation

@kartsan03

@kartsan03 kartsan03 commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Description

specify bundle install --refresh and specify bundle update put each bundle component back to the priority the bundle declares, so a priority set with preset set-priority or extension set-priority was lost (#5318). docs/bundles/cli.md says a refresh preserves "primitive-level overrides such as preset priority". The refresh is a forced reinstall, and the preset and extension install paths in bundles/primitives.py passed the declared priority (or the default, 10) to it without looking at the registry.

On a refresh, both paths now pass the priority already recorded for the component, through a small _installed_priority() helper, so a refresh keeps it the way extension update keeps the stored priority of an extension it reinstalls. A fresh install still uses the bundle's declaration, and a missing or malformed stored value falls back to the declaration (normalize_priority with the declared priority as its default). The bundle record keeps the declared priority, as before.

One behavior to weigh: a bundle version that changes a component's declared priority no longer changes it on an existing install, because the refresh can't tell a priority the user chose from one an earlier version of the bundle set. bundle info still shows the declared value, and set-priority applies it. Earlier commits on this branch tried to tell the two apart, from the bundle records and then from a mark in the registry, but each way got a case wrong (a failed refresh retried, an extension shared by two bundles, an extension update in between), so this PR keeps the rule the docs state.

Repro with the real CLI, steps in #5318 (bundle team requires extension bug and preset lean, both at priority 10):

Before bundle install ../team --offline --refresh main (c438494) This PR
preset set-priority lean 3, extension set-priority bug 4 lean 10, bug 10 lean 3, bug 4
no set-priority; bundle.yml now declares priority 5 for both lean 5, bug 5 lean 10, bug 10
the same set-priority calls; bundle.yml now declares 5 for both lean 5, bug 5 lean 3, bug 4

Projects whose priority was already reset need one set-priority call to set it again; the old value isn't recorded anywhere the fix could restore it from. After that, refreshes keep it.

Fixes #5318

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

A bundled_component fixture in tests/specify_cli/bundles/conftest.py installs a bundle with one extension or one preset at priority 10, and priority_bundle then sets that priority to 3 through the CLI.

  • test_command_install.py::test_refresh_preserves_primitive_priority: bundle install --refresh keeps priority 3, and the bundle record still lists the declared 10.
  • test_command_update.py::test_update_preserves_primitive_priority: the same through bundle update from a local catalog.
  • test_command_install.py::test_refresh_keeps_a_user_priority_when_the_bundle_priority_changes: with priority 3 set by the user, the same refresh keeps 3.
  • test_command_install.py::test_refresh_keeps_a_user_priority_after_the_bundle_declares_the_same_value: with priority 3 set by the user, a refresh with the bundle declaring 3 and then one declaring 5 both keep 3.
  • test_primitives.py::test_primitive_priority_on_install_and_refresh: both kinds, bundled and catalog sources, install and refresh, with no stored priority, a stored 3, and a malformed stored value.

With primitives.py reverted to main, 12 of the 32 new cases fail: the eight CLI cases and the refresh cases with a stored priority.

Full suite on Linux, Python 3.13: 13985 passed, 449 skipped, 1 failed (pytest -n 2, 7 min). The failure, test_version_execution.py::TestWindowsUvToolEnvironment::test_non_windows_uv_tool_dry_run_still_previews_installer, fails the same way on main here, as noted on #5308: Rich wraps the dry-run output, and my checkout's venv path is long enough to be split mid-path. Ruff 0.15.0 (ruff check src tests) passes. I haven't run it on Windows.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Codex CLI (model: gpt-6.1-sol, reasoning effort xhigh, autonomous, offline sandbox) found the priority reset while comparing bundle commands with the docs, and wrote the first fix and tests. Claude Code (model: claude-opus-5-5, autonomous) moved the fix into a shared helper, made a malformed stored priority fall back to the declared one, tried two ways to let a bundle's new priority through while keeping the user's, then went back to always keeping the stored priority after Copilot found cases both got wrong; it reran the repro with the real CLI on main and the branch, ran the full suite and lint, and drafted this description. The commits carry Assisted-by: trailers.

`bundle install --refresh` and `bundle update` reinstall each component
with the priority the bundle declares, so a priority the user had set
with `preset set-priority` or `extension set-priority` went back to the
bundle's value. docs/bundles/cli.md says a refresh keeps primitive-level
overrides such as preset priority.

On a refresh, read the priority already recorded for the component and
pass that to the reinstall. A fresh install still uses the bundle's
declaration, and a missing or malformed stored value falls back to it.

Assisted-by: Codex CLI (model: gpt-6.1-sol, autonomous)
Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
@kartsan03
kartsan03 requested a review from mnriem as a code owner November 8, 2026 19:59
Copilot AI auto review requested due to automatic review settings November 8, 2026 19:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the change preserving user-set priorities during bundle refreshes and updates.

No open issues 🎉

What changed in this PR

Fixes #5318 by preserving user-set preset and extension priorities when Specify CLI refreshes or updates a bundle, matching the documented behavior.

Changes:

  • Reuses valid installed priorities during refresh; fresh installs and missing or malformed stored values use the bundle-declared priority.
  • Keeps bundle records unchanged, retaining their declared priorities.
  • Adds regression coverage for both component kinds, bundled and catalog sources, and CLI refresh/update commands.

The PR reports before-and-after regression evidence; tests were not independently run during this review.

File Description
tests/​specify_cli/​bundles/​test_primitives.py Tests priority selection across install, refresh, source, and stored-value cases.
tests/​specify_cli/​bundles/​test_command_update.py Verifies bundle updates preserve user-set priorities.
tests/​specify_cli/​bundles/​test_command_install.py Verifies refresh preserves priorities without changing bundle declarations.
tests/​specify_cli/​bundles/​conftest.py Adds a shared fixture that installs components and changes their priorities through the CLI.
src/​specify_cli/​bundles/​primitives.py Adds shared installed-priority lookup for preset and extension refreshes.

Review effort: Balanced (auto)

The refresh kept every stored priority, including the one the bundle
itself set at install. A bundle update that changes its own priority
(say from 10 to 5) then kept 10.

Keep the stored priority only when it differs from every priority the
installed bundle records declared for the component, which means the
user changed it. Otherwise the bundle's new declaration applies.

Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
Copilot AI auto review requested due to automatic review settings November 8, 2026 20:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Explicit user priority overrides can be lost across consecutive bundle refreshes when a declaration temporarily matches the override, affecting both presets and extensions.

1 open issue

Review effort: Balanced (auto)

Comment thread src/specify_cli/bundles/primitives.py Resolved
A refresh treated the stored priority as the user's only while it
differed from every priority the bundle records declared. After a
bundle version declared the user's value, the record held that value,
and the next version's priority replaced the user's.

When a refresh keeps a user priority, mark the registry entry with
"user_priority". The reinstall rewrites the entry, so the refresh writes
the mark again afterwards, and later refreshes keep a marked priority.

Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
Copilot AI auto review requested due to automatic review settings November 8, 2026 20:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Priority tracking still loses explicit user overrides during shared-extension refreshes and extension updates, while failed refresh retries can incorrectly treat bundle-applied priorities as user choices.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity set-priority fails to mark shared-extension overrides

src/​specify_cli/​bundles/​primitives.py:67

Shared extensions can still lose explicit user priorities: install bundle A declaring 10 and bundle B declaring 5 for the same extension/version, then run extension set-priority <id> 5 and refresh A. Because 5 matches B's recorded declaration and set-priority does not write user_priority, this returns None and resets the priority to 10. Mark explicit overrides when set-priority runs, reserve declaration-based inference for legacy entries, and add a shared-extension regression.

AI-generated by GitHub Copilot for the review requester (model: unknown; autonomous review; analysis and comment drafting).

Medium severity Extension update drops the user-priority marker

src/​specify_cli/​bundles/​primitives.py:460

Ordinary extension update drops user_priority: extensions/_command_update_transaction.py:588–604 restores the priority after reinstalling, but not this marker. If a user-set 3 survives a bundle refresh declaring 3, an intervening extension update removes the marker, and the next bundle refresh declaring 5 resets the override. Preserve the marker in the extension update's metadata restoration and add a regression interleaving primitive and bundle updates.

AI-generated by GitHub Copilot for the review requester (model: unknown; autonomous review; analysis and comment drafting).

1 resolved since last review

Review effort: Balanced (auto)

Comment thread src/specify_cli/bundles/primitives.py Resolved
The last two commits guessed whether the user had set a component's
priority, from the bundle records and then from a registry mark. Each
guess had cases it got wrong: a failed refresh retried, an extension
shared by two bundles, an `extension update` in between.

Go back to the rule the docs state: a refresh reapplies components
through their primitive update paths and preserves primitive-level
overrides such as preset priority. A refresh always keeps the stored
priority, as `extension update` does, and the declared priority is used
only when nothing valid is stored. A bundle version that changes its
declared priority therefore doesn't change an existing install.

Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
Copilot AI auto review requested due to automatic review settings November 8, 2026 21:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the change preserving installed preset and extension priorities during bundle refreshes and updates.

No open issues 🎉

1 resolved since last review

Review effort: Balanced (auto)

This branch has not been deployed

No deployments
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.

[Bug]: bundle install --refresh and bundle update reset priorities set with set-priority

2 participants