@@ -2352,6 +2352,55 @@ def test_kimi_skill_updated_even_when_ai_skills_disabled(self, project_dir, temp
23522352 metadata = manager .registry .get ("self-test" )
23532353 assert "speckit-specify" in metadata .get ("registered_skills" , [])
23542354
2355+ def test_kimi_new_skill_created_even_when_ai_skills_disabled (self , project_dir , temp_dir ):
2356+ """Kimi native skills should still receive brand-new preset commands."""
2357+ self ._write_init_options (project_dir , ai = "kimi" , ai_skills = False )
2358+ skills_dir = project_dir / ".kimi" / "skills"
2359+ skills_dir .mkdir (parents = True , exist_ok = True )
2360+
2361+ preset_dir = temp_dir / "kimi-new-skill"
2362+ preset_dir .mkdir ()
2363+ (preset_dir / "commands" ).mkdir ()
2364+ (preset_dir / "commands" / "speckit.research.md" ).write_text (
2365+ "---\n "
2366+ "description: Kimi research workflow\n "
2367+ "---\n \n "
2368+ "preset:kimi-new-skill\n "
2369+ )
2370+ manifest_data = {
2371+ "schema_version" : "1.0" ,
2372+ "preset" : {
2373+ "id" : "kimi-new-skill" ,
2374+ "name" : "Kimi New Skill" ,
2375+ "version" : "1.0.0" ,
2376+ "description" : "Test" ,
2377+ },
2378+ "requires" : {"speckit_version" : ">=0.1.0" },
2379+ "provides" : {
2380+ "templates" : [
2381+ {
2382+ "type" : "command" ,
2383+ "name" : "speckit.research" ,
2384+ "file" : "commands/speckit.research.md" ,
2385+ }
2386+ ]
2387+ },
2388+ }
2389+ with open (preset_dir / "preset.yml" , "w" ) as f :
2390+ yaml .dump (manifest_data , f )
2391+
2392+ manager = PresetManager (project_dir )
2393+ manager .install_from_directory (preset_dir , "0.1.5" )
2394+
2395+ skill_file = skills_dir / "speckit-research" / "SKILL.md"
2396+ assert skill_file .exists ()
2397+ content = skill_file .read_text ()
2398+ assert "preset:kimi-new-skill" in content
2399+ assert "name: speckit-research" in content
2400+
2401+ metadata = manager .registry .get ("kimi-new-skill" )
2402+ assert "speckit-research" in metadata .get ("registered_skills" , [])
2403+
23552404 def test_kimi_preset_skill_override_resolves_script_placeholders (self , project_dir , temp_dir ):
23562405 """Kimi preset skill overrides should resolve placeholders and rewrite project paths."""
23572406 self ._write_init_options (project_dir , ai = "kimi" , ai_skills = False , script = "sh" )
@@ -2404,6 +2453,63 @@ def test_kimi_preset_skill_override_resolves_script_placeholders(self, project_d
24042453 assert ".specify/memory/constitution.md" in content
24052454 assert "for kimi" in content
24062455
2456+ def test_agy_skill_restored_on_preset_remove (self , project_dir , temp_dir ):
2457+ """Agy preset removal should restore native skills instead of deleting them."""
2458+ self ._write_init_options (project_dir , ai = "agy" , ai_skills = True )
2459+ skills_dir = project_dir / ".agent" / "skills"
2460+ self ._create_skill (skills_dir , "speckit-specify" , body = "before override" )
2461+
2462+ core_command = project_dir / ".specify" / "templates" / "commands" / "specify.md"
2463+ core_command .write_text (
2464+ "---\n "
2465+ "description: Restored core specify workflow\n "
2466+ "---\n \n "
2467+ "restored core body\n "
2468+ )
2469+
2470+ preset_dir = temp_dir / "agy-override"
2471+ preset_dir .mkdir ()
2472+ (preset_dir / "commands" ).mkdir ()
2473+ (preset_dir / "commands" / "speckit.specify.md" ).write_text (
2474+ "---\n "
2475+ "description: Agy override\n "
2476+ "---\n \n "
2477+ "preset agy body\n "
2478+ )
2479+ manifest_data = {
2480+ "schema_version" : "1.0" ,
2481+ "preset" : {
2482+ "id" : "agy-override" ,
2483+ "name" : "Agy Override" ,
2484+ "version" : "1.0.0" ,
2485+ "description" : "Test" ,
2486+ },
2487+ "requires" : {"speckit_version" : ">=0.1.0" },
2488+ "provides" : {
2489+ "templates" : [
2490+ {
2491+ "type" : "command" ,
2492+ "name" : "speckit.specify" ,
2493+ "file" : "commands/speckit.specify.md" ,
2494+ }
2495+ ]
2496+ },
2497+ }
2498+ with open (preset_dir / "preset.yml" , "w" ) as f :
2499+ yaml .dump (manifest_data , f )
2500+
2501+ manager = PresetManager (project_dir )
2502+ manager .install_from_directory (preset_dir , "0.1.5" )
2503+
2504+ skill_file = skills_dir / "speckit-specify" / "SKILL.md"
2505+ assert "preset agy body" in skill_file .read_text ()
2506+
2507+ assert manager .remove ("agy-override" ) is True
2508+ assert skill_file .exists ()
2509+ restored = skill_file .read_text ()
2510+ assert "restored core body" in restored
2511+ assert "name: speckit-specify" in restored
2512+
24072513 def test_preset_skill_registration_handles_non_dict_init_options (self , project_dir , temp_dir ):
24082514 """Non-dict init-options payloads should not crash preset install/remove flows."""
24092515 init_options = project_dir / ".specify" / "init-options.json"
0 commit comments