Skip to content

Commit ca03036

Browse files
committed
Release v0.0.132 - Fix extension refresh on init
1 parent 99ec719 commit ca03036

5 files changed

Lines changed: 59 additions & 25 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ All notable changes to the Specify CLI and templates are documented here.
77
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88
and this project adheres to to [Semantic Versioning](https://semver.org/spec/v2.0.0/).
99

10+
## [0.0.132] - 2026-03-13
11+
12+
### Fixed
13+
14+
- **Extensions always reinstall on init**: Re-running `specify init` now properly reinstalls bundled extensions by removing existing ones first (previously failed because `install_from_directory` rejects existing extensions)
15+
16+
## [0.0.131] - 2026-03-13
17+
18+
### Fixed
19+
20+
- **Extensions always reinstall on init**: Re-running `specify init` now reinstalls all bundled extensions to get latest versions (previously skipped existing extensions, preventing updates)
21+
1022
## [0.0.130] - 2026-03-13
1123

1224
### Added

extensions/levelup/scripts/bash/setup-levelup.sh

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ detect_subsystems() {
156156
fi
157157
fi
158158

159-
# Output as JSON array if JSON mode
159+
# Output as JSON array if JSON mode (without outer braces - will be merged into main output)
160160
if $JSON_MODE; then
161-
printf '{"subsystems":['
161+
printf '"subsystems":['
162162
local first=true
163163
for d in "${dirs[@]}"; do
164164
if [[ "$first" == "true" ]]; then
@@ -168,7 +168,7 @@ detect_subsystems() {
168168
fi
169169
printf '{"id":"%s","name":"%s","detection_method":"directory","evidence":"%s/"}' "$d" "$d" "$d"
170170
done
171-
printf '],"decomposition":%s}' "$DECOMPOSE"
171+
printf '],"decomposition":%s' "$DECOMPOSE"
172172
else
173173
# Human-readable output
174174
if [[ ${#dirs[@]} -eq 0 ]]; then
@@ -185,11 +185,24 @@ detect_subsystems() {
185185
# Resolve team-ai-directives path
186186
# Priority:
187187
# 1. SPECIFY_TEAM_DIRECTIVES environment variable
188-
# 2. .specify/team-ai-directives (submodule - recommended)
189-
# 3. .specify/memory/team-ai-directives (clone - legacy)
188+
# 2. .specify/config.json team_directives.path (from specify init)
189+
# 3. .specify/team-ai-directives (submodule - recommended)
190+
# 4. .specify/memory/team-ai-directives (clone - legacy)
190191

191192
TEAM_DIRECTIVES="${SPECIFY_TEAM_DIRECTIVES:-}"
192193

194+
if [[ -z "$TEAM_DIRECTIVES" ]]; then
195+
# Try reading from config.json (written by specify init)
196+
CONFIG_FILE="$REPO_ROOT/.specify/config.json"
197+
if [[ -f "$CONFIG_FILE" ]]; then
198+
# Extract team_directives.path using grep/sed (no jq dependency)
199+
CONFIG_PATH=$(grep -o '"path"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_FILE" 2>/dev/null | head -1 | sed 's/.*"\([^"]*\)"$/\1/')
200+
if [[ -n "$CONFIG_PATH" && -d "$CONFIG_PATH" ]]; then
201+
TEAM_DIRECTIVES="$CONFIG_PATH"
202+
fi
203+
fi
204+
fi
205+
193206
if [[ -z "$TEAM_DIRECTIVES" ]]; then
194207
if [[ -d "$REPO_ROOT/.specify/team-ai-directives" ]]; then
195208
TEAM_DIRECTIVES="$REPO_ROOT/.specify/team-ai-directives"
@@ -218,7 +231,7 @@ fi
218231
if $JSON_MODE; then
219232
subsystem_data=$(detect_subsystems)
220233
printf '{"REPO_ROOT":"%s","TEAM_DIRECTIVES":"%s","SKILLS_DRAFTS":"%s","CDR_FILE":"%s","BRANCH":"%s",%s}\n' \
221-
"$REPO_ROOT" "$TEAM_DIRECTIVES" "$SKILLS_DRAFTS" "$CDR_FILE" "$CURRENT_BRANCH" "${subsystem_data:1}"
234+
"$REPO_ROOT" "$TEAM_DIRECTIVES" "$SKILLS_DRAFTS" "$CDR_FILE" "$CURRENT_BRANCH" "$subsystem_data"
222235
else
223236
echo "REPO_ROOT: $REPO_ROOT"
224237
if [[ -n "$TEAM_DIRECTIVES" ]]; then

extensions/levelup/scripts/powershell/setup-levelup.ps1

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,30 @@ function Detect-Subsystems {
137137
# Resolve team-ai-directives path
138138
# Priority:
139139
# 1. SPECIFY_TEAM_DIRECTIVES environment variable
140-
# 2. .specify/team-ai-directives (submodule - recommended)
141-
# 3. .specify/memory/team-ai-directives (clone - legacy)
140+
# 2. .specify/config.json team_directives.path (from specify init)
141+
# 3. .specify/team-ai-directives (submodule - recommended)
142+
# 4. .specify/memory/team-ai-directives (clone - legacy)
142143

143144
$teamDirectives = $env:SPECIFY_TEAM_DIRECTIVES
144145

146+
if (-not $teamDirectives) {
147+
# Try reading from config.json (written by specify init)
148+
$configFile = Join-Path $repoRoot ".specify/config.json"
149+
if (Test-Path $configFile) {
150+
try {
151+
$config = Get-Content $configFile -Raw | ConvertFrom-Json
152+
if ($config.team_directives -and $config.team_directives.path) {
153+
$configPath = $config.team_directives.path
154+
if (Test-Path $configPath) {
155+
$teamDirectives = $configPath
156+
}
157+
}
158+
} catch {
159+
# Ignore JSON parsing errors, fall through to other methods
160+
}
161+
}
162+
}
163+
145164
if (-not $teamDirectives) {
146165
$submodulePath = Join-Path $repoRoot ".specify/team-ai-directives"
147166
$clonePath = Join-Path $repoRoot ".specify/memory/team-ai-directives"

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.0.130"
3+
version = "0.0.132"
44
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
55
requires-python = ">=3.11"
66
dependencies = [

src/specify_cli/__init__.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,7 +2582,7 @@ def _ensure_commands_for_agent(
25822582
extensions_dir: Directory containing extension directories
25832583
agent_name: Agent name to register commands for
25842584
"""
2585-
from .extensions import CommandRegistrar, ExtensionManifest, ExtensionRegistry
2585+
from .extensions import CommandRegistrar, ExtensionManifest
25862586

25872587
if agent_name not in CommandRegistrar.AGENT_CONFIGS:
25882588
return
@@ -2591,8 +2591,6 @@ def _ensure_commands_for_agent(
25912591
if not project_extensions_dir.exists():
25922592
return
25932593

2594-
registry = ExtensionRegistry(project_extensions_dir)
2595-
25962594
for ext_dir in project_extensions_dir.iterdir():
25972595
if not ext_dir.is_dir() or ext_dir.name.startswith("."):
25982596
continue
@@ -2602,14 +2600,8 @@ def _ensure_commands_for_agent(
26022600
continue
26032601

26042602
try:
2605-
# Check if commands already registered for this agent
2606-
if registry.is_installed(ext_dir.name):
2607-
reg_data = registry.get(ext_dir.name)
2608-
registered = reg_data.get("registered_commands", {}) if reg_data else {}
2609-
if agent_name in registered:
2610-
continue
2611-
2612-
# Register commands for this agent
2603+
# Always re-register commands on init to ensure they're up-to-date
2604+
# (removed skip logic that prevented updates when re-running init)
26132605
manifest = ExtensionManifest(ext_manifest_file)
26142606
registrar = CommandRegistrar()
26152607
registrar.register_commands_for_agent(
@@ -2751,12 +2743,10 @@ def install_bundled_extensions(
27512743
continue
27522744

27532745
try:
2754-
# Check if already installed
2746+
# Always install to ensure latest version
2747+
# Remove existing extension first to allow reinstall (install_from_directory rejects existing)
27552748
if manager.registry.is_installed(ext_name):
2756-
skipped.append(f"{ext_name} (existing)")
2757-
continue
2758-
2759-
# Install from bundled directory
2749+
manager.remove(ext_name, keep_config=True)
27602750
manager.install_from_directory(ext_dir, speckit_version)
27612751
installed.append(ext_name)
27622752
except ExtensionError as e:

0 commit comments

Comments
 (0)