Skip to content

Commit 2039a7a

Browse files
committed
fix: implement unified command naming pattern
Critical bug fix for duplicate Evolution commands Changes: 1. Unified naming: metaspec.{group}.{command}.md for all commands - SDS: metaspec.sds.specify.md - SDD: metaspec.sdd.plan.md - Evolution: metaspec.evolution.apply.md (was: metaspec.apply.md) 2. Generator: Use unified naming from the start (metaspec init) - src/metaspec/generator.py: Evolution output path updated 3. Sync: Migrate v0.5.x projects automatically - src/metaspec/cli/sync.py: Remove old naming during sync - Prevents duplicate files (metaspec.apply.md + metaspec.evolution.apply.md) 4. Documentation: Update file structure examples - src/metaspec/templates/meta/README.md - src/metaspec/templates/README.md Rationale: - Consistent pattern across all command groups - Better extensibility for future command groups - Easier automation and tooling - Clearer logical grouping Breaking Change: - v0.5.x users must run 'metaspec sync' to migrate naming - Old files automatically cleaned up during sync Resolves duplicate Evolution commands bug report
1 parent a36b47b commit 2039a7a

File tree

6 files changed

+25
-7
lines changed

6 files changed

+25
-7
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626

2727
**Root Cause**: Code only checked for `FileSystemLoader`, but Generator uses `PackageLoader` in editable installs
2828

29+
**Unified Command Naming (Breaking Change for v0.5.x users)**
30+
- Unified naming pattern for all command groups: `metaspec.{group}.{command}.md`
31+
- Evolution commands now use: `metaspec.evolution.apply.md` (previously `metaspec.apply.md`)
32+
- Rationale: Consistent naming pattern across all command groups (SDS, SDD, Evolution)
33+
- Benefits: ✅ Unified pattern, ✅ Better extensibility, ✅ Easier automation, ✅ Clearer grouping
34+
- Migration: `metaspec sync` automatically removes old v0.5.x naming and installs new naming
35+
- **Action Required**: If upgrading from v0.5.x, run `metaspec sync` to migrate naming
36+
2937
---
3038

3139
## [0.6.0] - 2025-11-14

src/metaspec/cli/sync.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ def sync_command(
150150

151151
for source_file in source_dir.glob("*.md.j2"):
152152
# Remove .j2 extension for destination
153+
# Unified naming: metaspec.{group}.{command}.md
153154
dest_file = commands_dir / f"metaspec.{command_group}.{source_file.stem}"
154155

155156
# Read and render template (basic rendering, no complex logic)
@@ -160,6 +161,15 @@ def sync_command(
160161
dest_file.write_text(content)
161162
updated_files.append(dest_file.name)
162163

164+
# Step 7.5: Clean up old Evolution naming (v0.5.x → v0.6.x migration)
165+
# Remove old naming pattern from pre-v0.6.0 versions
166+
old_evolution_files = ["metaspec.apply.md", "metaspec.archive.md", "metaspec.proposal.md"]
167+
for old_file_name in old_evolution_files:
168+
old_file = commands_dir / old_file_name
169+
if old_file.exists():
170+
console.print(f" 🧹 Removing old naming (v0.5.x): {old_file_name}")
171+
old_file.unlink()
172+
163173
# Step 8: Update version in pyproject.toml
164174
_update_generated_version(current_version)
165175

src/metaspec/generator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ def _select_templates(self, meta_spec: MetaSpecDefinition) -> dict[str, str]:
329329
template_map[source_path] = output_path
330330

331331
# Evolution commands (3): Shared specification evolution commands
332-
# File naming: metaspec.{command}.md to use /metaspec.{command} prefix
332+
# File naming: metaspec.evolution.{command}.md (unified naming pattern)
333333
# These commands support both SDS and SDD through --type parameter
334334
evolution_commands = [
335335
"proposal", # Propose changes (SDS or SDD)
@@ -339,7 +339,7 @@ def _select_templates(self, meta_spec: MetaSpecDefinition) -> dict[str, str]:
339339

340340
for cmd in evolution_commands:
341341
source_path = f"meta/evolution/commands/{cmd}.md.j2"
342-
output_path = f".metaspec/commands/metaspec.{cmd}.md"
342+
output_path = f".metaspec/commands/metaspec.evolution.{cmd}.md"
343343
template_map[source_path] = output_path
344344

345345
# MetaSpec README.md (Developer guide for speckit developers)

src/metaspec/templates/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ my-speckit/
206206
│ ├── metaspec.sds.plan.md # from meta/sds/commands/
207207
│ ├── metaspec.sdd.constitution.md # from meta/sdd/commands/
208208
│ ├── metaspec.sdd.plan.md # from meta/sdd/commands/
209-
│ ├── metaspec.proposal.md # from meta/evolution/commands/
209+
│ ├── metaspec.evolution.proposal.md # from meta/evolution/commands/
210210
│ └── ... (19 commands total: 8 SDS + 8 SDD + 3 Evolution)
211211
└── templates/
212212
├── constitution-template.md # from meta/templates/

src/metaspec/templates/meta/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,9 @@ generated-speckit/
198198
│ ├── metaspec.sdd.checklist.md
199199
│ ├── metaspec.sdd.analyze.md
200200
│ │
201-
│ ├── metaspec.proposal.md ← Evolution commands
202-
│ ├── metaspec.apply.md
203-
│ └── metaspec.archive.md
201+
│ ├── metaspec.evolution.proposal.md ← Evolution commands
202+
│ ├── metaspec.evolution.apply.md
203+
│ └── metaspec.evolution.archive.md
204204
205205
├── specs/
206206
│ ├── domain/ ← SDS output (domain specifications)

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)