Bug Description
specify bundle update --all can fail when a bundle owns an already-installed extension, then suggests retrying with --force.
However, specify bundle update does not support --force, so the suggested recovery path is invalid.
This looks like a mismatch between bundle refresh semantics and lower-level extension install semantics.
Steps to Reproduce
-
Have a Spec Kit project with an installed bundle that owns the git extension.
-
Run:
specify bundle update --all
-
Observe that the command fails because git is already installed.
-
Follow the suggested recovery and run:
specify bundle update --all --force
-
Observe that --force is rejected because bundle update has no such option.
Expected Behavior
specify bundle update --all should refresh bundle-owned installed components successfully.
If refresh cannot proceed, the error should provide a valid bundle-level recovery path and should not suggest --force unless bundle update actually supports it.
Actual Behavior
The first command fails with an extension-level duplicate-install error:
Error: Failed to install bundle 'basic-speckit-c8volt-stack': Extension 'git' is already installed. Use 'specify extension remove git' first, or retry with --force to overwrite.. No changes were recorded.
Retrying with the suggested --force flag fails because bundle update does not expose that option:
Usage: specify bundle update [OPTIONS] [BUNDLE_ID]
Try 'specify bundle update --help' for help.
╭─ Error ─────────────────────────────────────────────────────────────────╮
│ No such option: --force │
╰─────────────────────────────────────────────────────────────────────────╯
Specify CLI Version
0.12.8
AI Agent
GitHub Copilot
Operating System
macOS Tahoe 26.5.1
Python Version
3.13.5
Error Logs
❯ specify bundle update --all
Error: Failed to install bundle 'basic-speckit-c8volt-stack': Extension 'git' is already installed. Use 'specify extension remove git' first, or retry
with --force to overwrite.. No changes were recorded.
❯ specify bundle update --all --force
Usage: specify bundle update [OPTIONS] [BUNDLE_ID]
Try 'specify bundle update --help' for help.
╭─ Error ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ No such option: --force │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Additional Context
From local inspection, bundle update calls install_bundle(..., refresh=True). For owned existing components, _refresh_component() prefers a primitive refresh() hook, but DefaultPrimitiveInstaller currently does not implement one, so it falls back to installer.install(...).
For extensions, plain install rejects already-installed extensions unless force=True, producing the leaked extension-level message.
This appears broader than wording: bundle update documents refresh semantics, but the real default primitive adapter can fall back to duplicate install semantics for extensions.
Bug Description
specify bundle update --allcan fail when a bundle owns an already-installed extension, then suggests retrying with--force.However,
specify bundle updatedoes not support--force, so the suggested recovery path is invalid.This looks like a mismatch between bundle refresh semantics and lower-level extension install semantics.
Steps to Reproduce
Have a Spec Kit project with an installed bundle that owns the
gitextension.Run:
Observe that the command fails because
gitis already installed.Follow the suggested recovery and run:
Observe that
--forceis rejected becausebundle updatehas no such option.Expected Behavior
specify bundle update --allshould refresh bundle-owned installed components successfully.If refresh cannot proceed, the error should provide a valid bundle-level recovery path and should not suggest
--forceunlessbundle updateactually supports it.Actual Behavior
The first command fails with an extension-level duplicate-install error:
Retrying with the suggested
--forceflag fails becausebundle updatedoes not expose that option:Specify CLI Version
0.12.8
AI Agent
GitHub Copilot
Operating System
macOS Tahoe 26.5.1
Python Version
3.13.5
Error Logs
Additional Context
From local inspection,
bundle updatecallsinstall_bundle(..., refresh=True). For owned existing components,_refresh_component()prefers a primitiverefresh()hook, butDefaultPrimitiveInstallercurrently does not implement one, so it falls back toinstaller.install(...).For extensions, plain install rejects already-installed extensions unless
force=True, producing the leaked extension-level message.This appears broader than wording: bundle update documents refresh semantics, but the real default primitive adapter can fall back to duplicate install semantics for extensions.