Skip to content

Commit d74385e

Browse files
committed
fix: migrate kimi legacy dotted skills without ai-skills flag
1 parent 9af180c commit d74385e

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed

src/specify_cli/__init__.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,13 +2129,24 @@ def init(
21292129

21302130
ensure_constitution_from_template(project_path, tracker=tracker)
21312131

2132+
# Determine skills directory and migrate any legacy Kimi dotted skills.
2133+
migrated_legacy_kimi_skills = 0
2134+
removed_legacy_kimi_skills = 0
2135+
skills_dir: Optional[Path] = None
2136+
if selected_ai in NATIVE_SKILLS_AGENTS:
2137+
skills_dir = _get_skills_dir(project_path, selected_ai)
2138+
if selected_ai == "kimi" and skills_dir.is_dir():
2139+
(
2140+
migrated_legacy_kimi_skills,
2141+
removed_legacy_kimi_skills,
2142+
) = _migrate_legacy_kimi_dotted_skills(skills_dir)
2143+
21322144
if ai_skills:
21332145
if selected_ai in NATIVE_SKILLS_AGENTS:
2134-
skills_dir = _get_skills_dir(project_path, selected_ai)
2135-
migrated_legacy_kimi_skills = 0
2136-
removed_legacy_kimi_skills = 0
2137-
if selected_ai == "kimi":
2138-
migrated_legacy_kimi_skills, removed_legacy_kimi_skills = _migrate_legacy_kimi_dotted_skills(skills_dir)
2146+
if skills_dir is None:
2147+
raise RuntimeError(
2148+
f"Could not resolve skills directory for agent: {selected_ai}"
2149+
)
21392150
bundled_found = _has_bundled_skills(project_path, selected_ai)
21402151
if bundled_found:
21412152
detail = f"bundled skills → {skills_dir.relative_to(project_path)}"

tests/test_ai_skills.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,32 @@ def fake_download(project_path, *args, **kwargs):
806806
mock_skills.assert_called_once()
807807
assert mock_skills.call_args.kwargs.get("overwrite_existing") is True
808808

809+
def test_kimi_legacy_migration_runs_without_ai_skills_flag(self, tmp_path):
810+
"""Kimi init should migrate dotted legacy skills even when --ai-skills is not set."""
811+
from typer.testing import CliRunner
812+
813+
runner = CliRunner()
814+
target = tmp_path / "kimi-legacy-no-ai-skills"
815+
816+
def fake_download(project_path, *args, **kwargs):
817+
legacy_dir = project_path / ".kimi" / "skills" / "speckit.plan"
818+
legacy_dir.mkdir(parents=True, exist_ok=True)
819+
(legacy_dir / "SKILL.md").write_text("---\nname: speckit.plan\n---\n\nlegacy\n")
820+
821+
with patch("specify_cli.download_and_extract_template", side_effect=fake_download), \
822+
patch("specify_cli.ensure_executable_scripts"), \
823+
patch("specify_cli.ensure_constitution_from_template"), \
824+
patch("specify_cli.is_git_repo", return_value=False), \
825+
patch("specify_cli.shutil.which", return_value="/usr/bin/kimi"):
826+
result = runner.invoke(
827+
app,
828+
["init", str(target), "--ai", "kimi", "--script", "sh", "--no-git"],
829+
)
830+
831+
assert result.exit_code == 0
832+
assert not (target / ".kimi" / "skills" / "speckit.plan").exists()
833+
assert (target / ".kimi" / "skills" / "speckit-plan" / "SKILL.md").exists()
834+
809835
def test_codex_ai_skills_here_mode_preserves_existing_codex_dir(self, tmp_path, monkeypatch):
810836
"""Codex --here skills init should not delete a pre-existing .codex directory."""
811837
from typer.testing import CliRunner

0 commit comments

Comments
 (0)