1414import json
1515import tempfile
1616import shutil
17+ import warnings
1718import zipfile
1819from pathlib import Path
1920from datetime import datetime , timezone
@@ -1889,6 +1890,10 @@ def test_url_cache_expired(self, project_dir):
18891890
18901891
18911892SELF_TEST_PRESET_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
1893+ SELF_TEST_WRAP_WARNING = (
1894+ r"Cannot compose command 'speckit\.wrap-test': no base layer\. "
1895+ r"Stale command files may remain\."
1896+ )
18921897
18931898CORE_TEMPLATE_NAMES = [
18941899 "spec-template" ,
@@ -1899,6 +1904,18 @@ def test_url_cache_expired(self, project_dir):
18991904]
19001905
19011906
1907+ def install_self_test_preset (manager : PresetManager , speckit_version : str = "0.1.5" ) -> PresetManifest :
1908+ """Install self-test while filtering its intentionally missing wrap base."""
1909+ with warnings .catch_warnings ():
1910+ warnings .filterwarnings (
1911+ "ignore" ,
1912+ message = SELF_TEST_WRAP_WARNING ,
1913+ category = UserWarning ,
1914+ module = r"specify_cli\.presets" ,
1915+ )
1916+ return manager .install_from_directory (SELF_TEST_PRESET_DIR , speckit_version )
1917+
1918+
19021919class TestSelfTestPreset :
19031920 """Tests using the self-test preset that ships with the repo."""
19041921
@@ -1939,7 +1956,7 @@ def test_self_test_templates_have_marker(self):
19391956 def test_install_self_test_preset (self , project_dir ):
19401957 """Test installing the self-test preset from its directory."""
19411958 manager = PresetManager (project_dir )
1942- manifest = manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
1959+ manifest = install_self_test_preset ( manager )
19431960 assert manifest .id == "self-test"
19441961 assert manager .registry .is_installed ("self-test" )
19451962
@@ -1952,7 +1969,7 @@ def test_self_test_overrides_all_core_templates(self, project_dir):
19521969
19531970 # Install self-test preset
19541971 manager = PresetManager (project_dir )
1955- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
1972+ install_self_test_preset ( manager )
19561973
19571974 # Every core template should now resolve from the preset
19581975 resolver = PresetResolver (project_dir )
@@ -1971,7 +1988,7 @@ def test_self_test_resolve_with_source(self, project_dir):
19711988 (templates_dir / f"{ name } .md" ).write_text (f"# Core { name } \n " )
19721989
19731990 manager = PresetManager (project_dir )
1974- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
1991+ install_self_test_preset ( manager )
19751992
19761993 resolver = PresetResolver (project_dir )
19771994 for name in CORE_TEMPLATE_NAMES :
@@ -1988,7 +2005,7 @@ def test_self_test_removal_restores_core(self, project_dir):
19882005 (templates_dir / f"{ name } .md" ).write_text (f"# Core { name } \n " )
19892006
19902007 manager = PresetManager (project_dir )
1991- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
2008+ install_self_test_preset ( manager )
19922009 manager .remove ("self-test" )
19932010
19942011 resolver = PresetResolver (project_dir )
@@ -2024,7 +2041,7 @@ def test_self_test_registers_commands_for_claude(self, project_dir):
20242041 claude_dir .mkdir (parents = True )
20252042
20262043 manager = PresetManager (project_dir )
2027- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
2044+ install_self_test_preset ( manager )
20282045
20292046 # Check the skill was registered
20302047 cmd_file = claude_dir / "speckit-specify" / "SKILL.md"
@@ -2040,7 +2057,7 @@ def test_self_test_registers_commands_for_gemini(self, project_dir):
20402057 gemini_dir .mkdir (parents = True )
20412058
20422059 manager = PresetManager (project_dir )
2043- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
2060+ install_self_test_preset ( manager )
20442061
20452062 # Check the command was registered in TOML format
20462063 cmd_file = gemini_dir / "speckit.specify.toml"
@@ -2055,7 +2072,7 @@ def test_self_test_unregisters_commands_on_remove(self, project_dir):
20552072 claude_dir .mkdir (parents = True )
20562073
20572074 manager = PresetManager (project_dir )
2058- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
2075+ install_self_test_preset ( manager )
20592076
20602077 cmd_file = claude_dir / "speckit-specify" / "SKILL.md"
20612078 assert cmd_file .exists ()
@@ -2066,7 +2083,7 @@ def test_self_test_unregisters_commands_on_remove(self, project_dir):
20662083 def test_self_test_no_commands_without_agent_dirs (self , project_dir ):
20672084 """Test that no commands are registered when no agent dirs exist."""
20682085 manager = PresetManager (project_dir )
2069- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
2086+ install_self_test_preset ( manager )
20702087
20712088 metadata = manager .registry .get ("self-test" )
20722089 assert metadata ["registered_commands" ] == {}
@@ -2215,8 +2232,7 @@ def test_skill_overridden_on_preset_install(self, project_dir, temp_dir):
22152232
22162233 # Install self-test preset (has a command override for speckit.specify)
22172234 manager = PresetManager (project_dir )
2218- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2219- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2235+ install_self_test_preset (manager )
22202236
22212237 skill_file = skills_dir / "speckit-specify" / "SKILL.md"
22222238 assert skill_file .exists ()
@@ -2235,8 +2251,7 @@ def test_skill_not_updated_when_ai_skills_disabled(self, project_dir, temp_dir):
22352251 self ._create_skill (skills_dir , "speckit-specify" , body = "untouched" )
22362252
22372253 manager = PresetManager (project_dir )
2238- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2239- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2254+ install_self_test_preset (manager )
22402255
22412256 skill_file = skills_dir / "speckit-specify" / "SKILL.md"
22422257 content = skill_file .read_text ()
@@ -2268,8 +2283,7 @@ def test_skill_not_updated_without_init_options(self, project_dir, temp_dir):
22682283 self ._create_skill (skills_dir , "speckit-specify" , body = "untouched" )
22692284
22702285 manager = PresetManager (project_dir )
2271- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2272- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2286+ install_self_test_preset (manager )
22732287
22742288 skill_file = skills_dir / "speckit-specify" / "SKILL.md"
22752289 file_content = skill_file .read_text ()
@@ -2289,8 +2303,7 @@ def test_skill_restored_on_preset_remove(self, project_dir, temp_dir):
22892303 (core_cmds / "specify.md" ).write_text ("---\n description: Core specify command\n ---\n \n Core specify body\n " )
22902304
22912305 manager = PresetManager (project_dir )
2292- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2293- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2306+ install_self_test_preset (manager )
22942307
22952308 # Verify preset content is in the skill
22962309 skill_file = skills_dir / "speckit-specify" / "SKILL.md"
@@ -2326,8 +2339,7 @@ def test_skill_restored_on_remove_resolves_script_placeholders(self, project_dir
23262339 )
23272340
23282341 manager = PresetManager (project_dir )
2329- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2330- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2342+ install_self_test_preset (manager )
23312343 manager .remove ("self-test" )
23322344
23332345 content = (skills_dir / "speckit-specify" / "SKILL.md" ).read_text ()
@@ -2343,8 +2355,7 @@ def test_skill_not_overridden_when_skill_path_is_file(self, project_dir):
23432355 (skills_dir / "speckit-specify" ).write_text ("not-a-directory" )
23442356
23452357 manager = PresetManager (project_dir )
2346- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2347- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2358+ install_self_test_preset (manager )
23482359
23492360 assert (skills_dir / "speckit-specify" ).is_file ()
23502361 metadata = manager .registry .get ("self-test" )
@@ -2356,8 +2367,7 @@ def test_no_skills_registered_when_no_skill_dir_exists(self, project_dir, temp_d
23562367 # Don't create skills dir — simulate --ai-skills never created them
23572368
23582369 manager = PresetManager (project_dir )
2359- SELF_TEST_DIR = Path (__file__ ).parent .parent / "presets" / "self-test"
2360- manager .install_from_directory (SELF_TEST_DIR , "0.1.5" )
2370+ install_self_test_preset (manager )
23612371
23622372 metadata = manager .registry .get ("self-test" )
23632373 assert metadata .get ("registered_skills" , []) == []
@@ -2558,8 +2568,7 @@ def test_kimi_legacy_dotted_skill_override_still_applies(self, project_dir, temp
25582568 (project_dir / ".kimi" / "commands" ).mkdir (parents = True , exist_ok = True )
25592569
25602570 manager = PresetManager (project_dir )
2561- self_test_dir = Path (__file__ ).parent .parent / "presets" / "self-test"
2562- manager .install_from_directory (self_test_dir , "0.1.5" )
2571+ install_self_test_preset (manager )
25632572
25642573 skill_file = skills_dir / "speckit.specify" / "SKILL.md"
25652574 assert skill_file .exists ()
@@ -2579,8 +2588,7 @@ def test_kimi_skill_updated_even_when_ai_skills_disabled(self, project_dir, temp
25792588 (project_dir / ".kimi" / "commands" ).mkdir (parents = True , exist_ok = True )
25802589
25812590 manager = PresetManager (project_dir )
2582- self_test_dir = Path (__file__ ).parent .parent / "presets" / "self-test"
2583- manager .install_from_directory (self_test_dir , "0.1.5" )
2591+ install_self_test_preset (manager )
25842592
25852593 skill_file = skills_dir / "speckit-specify" / "SKILL.md"
25862594 assert skill_file .exists ()
@@ -2759,8 +2767,7 @@ def test_preset_skill_registration_handles_non_dict_init_options(self, project_d
27592767 self ._create_skill (skills_dir , "speckit-specify" , body = "untouched" )
27602768
27612769 manager = PresetManager (project_dir )
2762- self_test_dir = Path (__file__ ).parent .parent / "presets" / "self-test"
2763- manager .install_from_directory (self_test_dir , "0.1.5" )
2770+ install_self_test_preset (manager )
27642771
27652772 skill_content = (skills_dir / "speckit-specify" / "SKILL.md" ).read_text ()
27662773 assert "untouched" in skill_content
@@ -3419,7 +3426,7 @@ def test_end_to_end_wrap_via_self_test_preset(self, project_dir):
34193426 )
34203427
34213428 manager = PresetManager (project_dir )
3422- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
3429+ install_self_test_preset ( manager )
34233430
34243431 written = (skill_subdir / "SKILL.md" ).read_text ()
34253432 assert "{CORE_TEMPLATE}" not in written
@@ -3471,7 +3478,7 @@ def test_register_skills_inherits_scripts_from_core_when_preset_omits_them(self,
34713478 )
34723479
34733480 manager = PresetManager (project_dir )
3474- manager . install_from_directory ( SELF_TEST_PRESET_DIR , "0.1.5" )
3481+ install_self_test_preset ( manager )
34753482
34763483 written = (skill_subdir / "SKILL.md" ).read_text ()
34773484 # {SCRIPT} should have been resolved (not left as a literal placeholder)
0 commit comments