Skip to content

Commit fdb996d

Browse files
committed
feat: add version-aware preset auto-upgrade
1 parent 7543ba1 commit fdb996d

4 files changed

Lines changed: 54 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ All notable changes to the Specify CLI and templates are documented here.
44

55
# [Unreleased]
66

7-
# [0.8.4+adlc3] - 2026-04-30
7+
# [0.8.4+adlc4] - 2026-04-30
8+
9+
### Added
10+
11+
- **Preset auto-upgrade**: Presets now auto-upgrade when CLI version bumps.
12+
- Add version comparison at two gates: file scaffolding + registry re-registration
13+
- Bundled version > installed version triggers re-scaffold/re-register
14+
- Bundled version <= installed version skips (preserves manual edits)
815

916
### Changed
1017

presets/agentic-sdlc/preset.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ schema_version: "1.0"
33
preset:
44
id: "agentic-sdlc"
55
name: "Agentic SDLC Governance"
6-
version: "1.0.0"
6+
version: "1.0.1"
77
description: "Enhanced templates with governance, team-ai-directives integration, extension hooks, and architectural rigor for the Agentic SDLC workflow"
88
author: "Tikal"
99
repository: "https://github.com/tikalk/agentic-sdlc-spec-kit"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "agentic-sdlc-specify-cli"
3-
version = "0.8.4+adlc3"
3+
version = "0.8.4+adlc4"
44
description = "Specify CLI (tikalk fork). Agentic SDLC toolkit for Spec-Driven Development with pre-installed extensions and AI integrations."
55
requires-python = ">=3.11"
66
dependencies = [

src/specify_cli/cli_customization.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import os
2323
import shutil
2424
import typer
25+
from packaging import version
2526
from pathlib import Path
2627
from typing import Any, Optional
2728

@@ -275,6 +276,26 @@ def _scaffold_extensions_to_project(
275276
return scaffolded
276277

277278

279+
# ============================================================================
280+
# PRESET VERSIONING
281+
# ============================================================================
282+
283+
284+
def _read_preset_version(preset_dir: Path) -> str | None:
285+
"""Read version from preset.yml if it exists."""
286+
preset_yml = preset_dir / "preset.yml"
287+
if not preset_yml.exists():
288+
return None
289+
290+
from .presets import PresetManifest
291+
292+
try:
293+
manifest = PresetManifest(preset_yml)
294+
return manifest.version
295+
except Exception:
296+
return None
297+
298+
278299
def _scaffold_presets_to_project(
279300
source_dir: Path,
280301
project_dir: Path,
@@ -294,6 +315,14 @@ def _scaffold_presets_to_project(
294315
proj_preset = project_dir / preset_dir.name
295316

296317
if (proj_preset / "preset.yml").exists():
318+
bundled_version = _read_preset_version(preset_dir)
319+
installed_version = _read_preset_version(proj_preset)
320+
if bundled_version and installed_version:
321+
try:
322+
if version.parse(bundled_version) <= version.parse(installed_version):
323+
continue
324+
except Exception:
325+
pass
297326
continue
298327

299328
if proj_preset.exists():
@@ -683,9 +712,22 @@ def _install_bundled_presets(
683712
continue
684713

685714
try:
715+
bundled_version = _read_preset_version(preset_dir)
716+
686717
if registry.is_installed(preset_name):
687-
skipped.append(f"{preset_name} (existing)")
688-
continue
718+
reg_entry = registry.get(preset_name)
719+
installed_version = reg_entry.get("version") if reg_entry else None
720+
721+
if bundled_version and installed_version:
722+
try:
723+
if version.parse(bundled_version) <= version.parse(installed_version):
724+
skipped.append(f"{preset_name} (existing v{installed_version})")
725+
continue
726+
except Exception:
727+
pass
728+
else:
729+
skipped.append(f"{preset_name} (existing)")
730+
continue
689731

690732
from .presets import PresetManifest
691733

0 commit comments

Comments
 (0)