@@ -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 ("---\n name: speckit.plan\n ---\n \n legacy\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