Skip to content

Commit 9af180c

Browse files
committed
fix: preserve legacy kimi dotted preset skill overrides
1 parent 2cc7aa2 commit 9af180c

File tree

2 files changed

+56
-28
lines changed

2 files changed

+56
-28
lines changed

src/specify_cli/presets.py

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -640,15 +640,21 @@ def _register_skills(
640640
continue
641641

642642
# Derive the short command name (e.g. "specify" from "speckit.specify")
643-
short_name = cmd_name
644-
if short_name.startswith("speckit."):
645-
short_name = short_name[len("speckit."):]
646-
short_name = short_name.replace(".", "-")
643+
raw_short_name = cmd_name
644+
if raw_short_name.startswith("speckit."):
645+
raw_short_name = raw_short_name[len("speckit."):]
646+
short_name = raw_short_name.replace(".", "-")
647647
skill_name = f"speckit-{short_name}"
648-
649-
# Only overwrite if the skill already exists (i.e. --ai-skills was used)
650-
skill_subdir = skills_dir / skill_name
651-
if not skill_subdir.exists():
648+
legacy_skill_name = f"speckit.{raw_short_name}"
649+
650+
# Only overwrite existing skills (i.e. --ai-skills was used).
651+
# If both modern and legacy directories exist, update both.
652+
target_skill_names: List[str] = []
653+
if (skills_dir / skill_name).exists():
654+
target_skill_names.append(skill_name)
655+
if legacy_skill_name != skill_name and (skills_dir / legacy_skill_name).exists():
656+
target_skill_names.append(legacy_skill_name)
657+
if not target_skill_names:
652658
continue
653659

654660
# Parse the command file
@@ -673,27 +679,28 @@ def _register_skills(
673679
original_desc or f"Spec-kit workflow command: {short_name}",
674680
)
675681

676-
frontmatter_data = {
677-
"name": skill_name,
678-
"description": enhanced_desc,
679-
"compatibility": "Requires spec-kit project structure with .specify/ directory",
680-
"metadata": {
681-
"author": "github-spec-kit",
682-
"source": f"preset:{manifest.id}",
683-
},
684-
}
685-
frontmatter_text = yaml.safe_dump(frontmatter_data, sort_keys=False).strip()
686-
skill_content = (
687-
f"---\n"
688-
f"{frontmatter_text}\n"
689-
f"---\n\n"
690-
f"# Speckit {short_name.title()} Skill\n\n"
691-
f"{body}\n"
692-
)
682+
for target_skill_name in target_skill_names:
683+
frontmatter_data = {
684+
"name": target_skill_name,
685+
"description": enhanced_desc,
686+
"compatibility": "Requires spec-kit project structure with .specify/ directory",
687+
"metadata": {
688+
"author": "github-spec-kit",
689+
"source": f"preset:{manifest.id}",
690+
},
691+
}
692+
frontmatter_text = yaml.safe_dump(frontmatter_data, sort_keys=False).strip()
693+
skill_content = (
694+
f"---\n"
695+
f"{frontmatter_text}\n"
696+
f"---\n\n"
697+
f"# Speckit {short_name.title()} Skill\n\n"
698+
f"{body}\n"
699+
)
693700

694-
skill_file = skill_subdir / "SKILL.md"
695-
skill_file.write_text(skill_content, encoding="utf-8")
696-
written.append(skill_name)
701+
skill_file = skills_dir / target_skill_name / "SKILL.md"
702+
skill_file.write_text(skill_content, encoding="utf-8")
703+
written.append(target_skill_name)
697704

698705
return written
699706

tests/test_presets.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,6 +2099,27 @@ def test_extension_skill_override_matches_hyphenated_multisegment_name(self, pro
20992099
metadata = manager.registry.get("ext-skill-override")
21002100
assert "speckit-fakeext-cmd" in metadata.get("registered_skills", [])
21012101

2102+
def test_kimi_legacy_dotted_skill_override_still_applies(self, project_dir, temp_dir):
2103+
"""Preset overrides should still target legacy dotted Kimi skill directories."""
2104+
self._write_init_options(project_dir, ai="kimi")
2105+
skills_dir = project_dir / ".kimi" / "skills"
2106+
self._create_skill(skills_dir, "speckit.specify", body="untouched")
2107+
2108+
(project_dir / ".kimi" / "commands").mkdir(parents=True, exist_ok=True)
2109+
2110+
manager = PresetManager(project_dir)
2111+
self_test_dir = Path(__file__).parent.parent / "presets" / "self-test"
2112+
manager.install_from_directory(self_test_dir, "0.1.5")
2113+
2114+
skill_file = skills_dir / "speckit.specify" / "SKILL.md"
2115+
assert skill_file.exists()
2116+
content = skill_file.read_text()
2117+
assert "preset:self-test" in content
2118+
assert "name: speckit.specify" in content
2119+
2120+
metadata = manager.registry.get("self-test")
2121+
assert "speckit.specify" in metadata.get("registered_skills", [])
2122+
21022123

21032124
class TestPresetSetPriority:
21042125
"""Test preset set-priority CLI command."""

0 commit comments

Comments
 (0)