Summary
specify extension update decides whether an installed extension needs updating by comparing semver versions (src/specify_cli/extensions/_commands.py, extension_update, ~line 1660):
if catalog_version > installed_version:
...offer update...
else:
console.print(f"✓ {ext_id}: Up to date (v{installed_version})")
Both bundled extensions (agent-context, git) have carried version: "1.0.0" since the day they were created, while their content kept changing — including bug fixes for failures that make an extension unusable on some platforms. Any project that installed them before those fixes is told "Up to date (v1.0.0)" forever and never receives them. Nothing else catches it: the registry's manifest_hash covers the manifest (which didn't change), not the scripts.
Quantified drift (checked 2026-08-26 against main)
extensions/agent-context — version: "1.0.0" set at extraction (#2546, 2026-05-30), never bumped since (the manifest was never touched again). Changes an installed v1.0.0 copy is missing:
- 15 commits, aggregate 7 files changed, +1,120 / −169 lines (the extension is 8 files total — nearly every file rewritten)
- Among them:
extensions/git — version: "1.0.0" set at creation (#1941, 2026-04-07), never bumped; the manifest was edited once more (#3293, 2026-07-06) and the version still stayed 1.0.0. Changes an installed v1.0.0 copy is missing:
- 23 commits, aggregate 21 files changed, +2,191 / −567 lines (the extension is 21 files total — every file touched)
- Among them:
(Methodology: commit counts via git rev-list --count <version-set-commit>..origin/main -- extensions/<id>, aggregate stats via git diff --stat, version history by inspecting extension.yml at each commit that touched it.)
Real-world impact (how we found this)
Our repo runs spec-kit 0.16.5 (2026-08-19) but had installed agent-context on 2026-06-16 — six days before the PS 5.1 fix landed in #2969 (released the same day in v0.11.5). Because the version never moved off 1.0.0, fourteen subsequent CLI releases all considered the extension current, and the after_specify/after_plan hook failed silently (warns + exit 0) on every run for two months; our CLAUDE.md context block was stuck pointing at a plan three features old. The staleness is undetectable from the client side without diffing script contents against this repo.
Workaround
Force reinstallation, which overwrites regardless of version:
specify extension add agent-context --force
specify extension add git --force
(--force = "Overwrite if already installed"; extension add refuses otherwise. Config files are preserved via the backup/restore path.)
Proposed fix
- Bump
version: in extension.yml for both extensions now (content warrants at least a minor bump each: 1.1.0), so every installed copy finally sees an available update.
- Guard it in CI so this can't regress: fail a PR that changes any file under
extensions/<id>/ without also changing the version: field of that extension's extension.yml. This is a small check (git diff of the PR range, per extension) that converts "please remember to bump" into a merge requirement.
- Optionally, belt-and-braces: make
extension_update compare a content hash of the extension directory (the registry already stores a manifest_hash; extend it to cover all shipped files) so even an unbumped content change is detected as "update available".
Happy to send a PR for (1) + (2) if the approach sounds right.
Related (adjacent but distinct): #2716 discusses catalog semantics for update discovery of org-local/third-party catalogs; this issue is about bundled extensions never signalling an update at all because their source version never changes.
Generated by Fable 5 Extra
Summary
specify extension updatedecides whether an installed extension needs updating by comparing semver versions (src/specify_cli/extensions/_commands.py,extension_update, ~line 1660):Both bundled extensions (
agent-context,git) have carriedversion: "1.0.0"since the day they were created, while their content kept changing — including bug fixes for failures that make an extension unusable on some platforms. Any project that installed them before those fixes is told "Up to date (v1.0.0)" forever and never receives them. Nothing else catches it: the registry'smanifest_hashcovers the manifest (which didn't change), not the scripts.Quantified drift (checked 2026-08-26 against
main)extensions/agent-context—version: "1.0.0"set at extraction (#2546, 2026-05-30), never bumped since (the manifest was never touched again). Changes an installed v1.0.0 copy is missing:python -cargument mangling) — fixed incidentally in fix(agent-context): support multiple context files safely #2969context_filesmulti-file support + path-containment validation (fix(agent-context): support multiple context files safely #2969)feature.json(fix: derive plan path from feature.json in update-agent-context #3069)scripts/python/update_agent_context.py, 368 lines) (feat(extensions): port update-agent-context to Python #3387)extensions/git—version: "1.0.0"set at creation (#1941, 2026-04-07), never bumped; the manifest was edited once more (#3293, 2026-07-06) and the version still stayed 1.0.0. Changes an installed v1.0.0 copy is missing:SPECIFY_INIT_DIR(feat(scripts): add SPECIFY_INIT_DIR to target a member project from the repo root #2892)-Number 0/ negative-Numberhandling (fix(git-ext): honor explicit -Number 0 in PowerShell branch creation (parity with bash) #3412, fix(extensions/git): reject negative -Number in create-new-feature-branch.ps1 #3538), commit-message quote/whitespace handling (fix(git-extension): trim trailing whitespace before stripping commit-message quotes #3673, fix: replace xargs trim with sed to handle quotes in descriptions #2351), CRLF-warning stderr failures (fix: suppress CRLF warnings in auto-commit.ps1 #2258), several bash/PowerShell parity fixes(Methodology: commit counts via
git rev-list --count <version-set-commit>..origin/main -- extensions/<id>, aggregate stats viagit diff --stat, version history by inspectingextension.ymlat each commit that touched it.)Real-world impact (how we found this)
Our repo runs spec-kit 0.16.5 (2026-08-19) but had installed
agent-contexton 2026-06-16 — six days before the PS 5.1 fix landed in #2969 (released the same day in v0.11.5). Because the version never moved off 1.0.0, fourteen subsequent CLI releases all considered the extension current, and theafter_specify/after_planhook failed silently (warns +exit 0) on every run for two months; ourCLAUDE.mdcontext block was stuck pointing at a plan three features old. The staleness is undetectable from the client side without diffing script contents against this repo.Workaround
Force reinstallation, which overwrites regardless of version:
(
--force= "Overwrite if already installed";extension addrefuses otherwise. Config files are preserved via the backup/restore path.)Proposed fix
version:inextension.ymlfor both extensions now (content warrants at least a minor bump each:1.1.0), so every installed copy finally sees an available update.extensions/<id>/without also changing theversion:field of that extension'sextension.yml. This is a small check (git diff of the PR range, per extension) that converts "please remember to bump" into a merge requirement.extension_updatecompare a content hash of the extension directory (the registry already stores amanifest_hash; extend it to cover all shipped files) so even an unbumped content change is detected as "update available".Happy to send a PR for (1) + (2) if the approach sounds right.
Related (adjacent but distinct): #2716 discusses catalog semantics for update discovery of org-local/third-party catalogs; this issue is about bundled extensions never signalling an update at all because their source version never changes.
Generated by Fable 5 Extra