Skip to content

Commit fa2b5da

Browse files
committed
fix init-options speckit version refresh
1 parent 68a031c commit fa2b5da

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

src/specify_cli/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,15 @@ def _write_integration_json(
13321332
)
13331333

13341334

1335+
def _refresh_init_options_speckit_version(project_root: Path) -> None:
1336+
"""Refresh only the Spec Kit version recorded in init-options.json."""
1337+
opts = load_init_options(project_root)
1338+
if not isinstance(opts, dict) or not opts:
1339+
return
1340+
opts["speckit_version"] = get_speckit_version()
1341+
save_init_options(project_root, opts)
1342+
1343+
13351344
def _clear_init_options_for_integration(project_root: Path, integration_key: str) -> None:
13361345
"""Clear active integration keys from init-options.json when they match."""
13371346
opts = load_init_options(project_root)
@@ -1692,6 +1701,8 @@ def integration_install(
16921701
_write_integration_json(project_root, new_default, new_installed, settings)
16931702
if new_default == integration.key:
16941703
_update_init_options_for_integration(project_root, integration, script_type=selected_script)
1704+
else:
1705+
_refresh_init_options_speckit_version(project_root)
16951706

16961707
except Exception as e:
16971708
# Attempt rollback of any files written by setup
@@ -1775,6 +1786,7 @@ def _update_init_options_for_integration(
17751786
opts["integration"] = integration.key
17761787
opts["ai"] = integration.key
17771788
opts["context_file"] = integration.context_file
1789+
opts["speckit_version"] = get_speckit_version()
17781790
if script_type:
17791791
opts["script"] = script_type
17801792
if isinstance(integration, SkillsIntegration) or getattr(integration, "_skills_mode", False):
@@ -2339,6 +2351,8 @@ def integration_upgrade(
23392351
_write_integration_json(project_root, installed_key, installed_keys, settings)
23402352
if installed_key == key:
23412353
_update_init_options_for_integration(project_root, integration, script_type=selected_script)
2354+
else:
2355+
_refresh_init_options_speckit_version(project_root)
23422356
except Exception as exc:
23432357
# Don't teardown — setup overwrites in-place, so teardown would
23442358
# delete files that were working before the upgrade. Just report.

tests/integrations/test_integration_subcommand.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,29 @@ def test_install_multi_safe_integration(self, tmp_path):
230230
assert (project / ".claude" / "skills" / "speckit-plan" / "SKILL.md").exists()
231231
assert (project / ".agents" / "skills" / "speckit-plan" / "SKILL.md").exists()
232232

233+
def test_install_non_default_refreshes_init_options_version_only(self, tmp_path, monkeypatch):
234+
project = _init_project(tmp_path, "claude")
235+
init_options = project / ".specify" / "init-options.json"
236+
opts = json.loads(init_options.read_text(encoding="utf-8"))
237+
opts["speckit_version"] = "0.6.1"
238+
init_options.write_text(json.dumps(opts), encoding="utf-8")
239+
240+
import specify_cli
241+
242+
monkeypatch.setattr(specify_cli, "get_speckit_version", lambda: "0.8.11")
243+
244+
result = _run_in_project(project, [
245+
"integration", "install", "codex",
246+
"--script", "sh",
247+
])
248+
249+
assert result.exit_code == 0, result.output
250+
updated = json.loads(init_options.read_text(encoding="utf-8"))
251+
assert updated["speckit_version"] == "0.8.11"
252+
assert updated["integration"] == "claude"
253+
assert updated["ai"] == "claude"
254+
assert updated["context_file"] == "CLAUDE.md"
255+
233256
def test_install_additional_preserves_shared_manifest(self, tmp_path):
234257
project = _init_project(tmp_path, "claude")
235258
shared_manifest = project / ".specify" / "integrations" / "speckit.manifest.json"
@@ -1144,6 +1167,56 @@ def test_upgrade_invalid_manifest_reports_cli_error(self, tmp_path):
11441167
assert "manifest" in result.output
11451168
assert "unreadable" in result.output
11461169

1170+
def test_upgrade_refreshes_init_options_speckit_version(self, tmp_path, monkeypatch):
1171+
project = _init_project(tmp_path, "claude")
1172+
init_options = project / ".specify" / "init-options.json"
1173+
opts = json.loads(init_options.read_text(encoding="utf-8"))
1174+
opts["speckit_version"] = "0.6.1"
1175+
init_options.write_text(json.dumps(opts), encoding="utf-8")
1176+
1177+
import specify_cli
1178+
1179+
monkeypatch.setattr(specify_cli, "get_speckit_version", lambda: "0.8.11")
1180+
1181+
result = _run_in_project(project, [
1182+
"integration", "upgrade", "claude",
1183+
"--force",
1184+
])
1185+
1186+
assert result.exit_code == 0, result.output
1187+
updated = json.loads(init_options.read_text(encoding="utf-8"))
1188+
assert updated["speckit_version"] == "0.8.11"
1189+
1190+
def test_upgrade_non_default_refreshes_init_options_version_only(self, tmp_path, monkeypatch):
1191+
project = _init_project(tmp_path, "gemini")
1192+
install = _run_in_project(project, [
1193+
"integration", "install", "claude",
1194+
"--script", "sh",
1195+
])
1196+
assert install.exit_code == 0, install.output
1197+
1198+
init_options = project / ".specify" / "init-options.json"
1199+
opts = json.loads(init_options.read_text(encoding="utf-8"))
1200+
opts["speckit_version"] = "0.6.1"
1201+
init_options.write_text(json.dumps(opts), encoding="utf-8")
1202+
1203+
import specify_cli
1204+
1205+
monkeypatch.setattr(specify_cli, "get_speckit_version", lambda: "0.8.11")
1206+
1207+
result = _run_in_project(project, [
1208+
"integration", "upgrade", "claude",
1209+
"--script", "sh",
1210+
"--force",
1211+
])
1212+
1213+
assert result.exit_code == 0, result.output
1214+
updated = json.loads(init_options.read_text(encoding="utf-8"))
1215+
assert updated["speckit_version"] == "0.8.11"
1216+
assert updated["integration"] == "gemini"
1217+
assert updated["ai"] == "gemini"
1218+
assert updated["context_file"] == "GEMINI.md"
1219+
11471220
def test_upgrade_does_not_persist_state_when_template_refresh_fails(self, tmp_path, monkeypatch):
11481221
project = _init_project(tmp_path, "claude")
11491222
int_json = project / ".specify" / "integration.json"

0 commit comments

Comments
 (0)