Skip to content

Commit bb67923

Browse files
feat: implement strategy: wrap for _register_skills — substitute {CORE_TEMPLATE} with core command body
1 parent cdbea09 commit bb67923

2 files changed

Lines changed: 82 additions & 1 deletion

File tree

src/specify_cli/presets.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@
2727
from .extensions import ExtensionRegistry, normalize_priority
2828

2929

30+
def _substitute_core_template(
31+
body: str,
32+
short_name: str,
33+
project_root: "Path",
34+
registrar: "CommandRegistrar",
35+
) -> str:
36+
"""Substitute {CORE_TEMPLATE} with the body of the installed core command template.
37+
38+
Args:
39+
body: Preset command body (may contain {CORE_TEMPLATE} placeholder).
40+
short_name: Short command name (e.g. "specify" from "speckit.specify").
41+
project_root: Project root path.
42+
registrar: CommandRegistrar instance for parse_frontmatter.
43+
44+
Returns:
45+
Body with {CORE_TEMPLATE} replaced by core template body, or body unchanged
46+
if the placeholder is absent or the core template file does not exist.
47+
"""
48+
if "{CORE_TEMPLATE}" not in body:
49+
return body
50+
51+
core_file = project_root / ".specify" / "templates" / "commands" / f"{short_name}.md"
52+
if not core_file.exists():
53+
return body
54+
55+
_, core_body = registrar.parse_frontmatter(core_file.read_text(encoding="utf-8"))
56+
return body.replace("{CORE_TEMPLATE}", core_body)
57+
58+
3059
@dataclass
3160
class PresetCatalogEntry:
3261
"""Represents a single entry in the preset catalog stack."""
@@ -759,6 +788,9 @@ def _register_skills(
759788
content = source_file.read_text(encoding="utf-8")
760789
frontmatter, body = registrar.parse_frontmatter(content)
761790

791+
if frontmatter.get("strategy") == "wrap":
792+
body = _substitute_core_template(body, short_name, self.project_root, registrar)
793+
762794
original_desc = frontmatter.get("description", "")
763795
enhanced_desc = SKILL_DESCRIPTIONS.get(
764796
short_name,

tests/test_presets.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3043,4 +3043,53 @@ def test_bundled_preset_missing_locally_cli_error(self, project_dir):
30433043
assert result.exit_code == 1
30443044
output = strip_ansi(result.output).lower()
30453045
assert "bundled" in output, result.output
3046-
assert "reinstall" in output, result.output
3046+
3047+
3048+
class TestWrapStrategy:
3049+
"""Tests for strategy: wrap preset command substitution."""
3050+
3051+
def test_substitute_core_template_replaces_placeholder(self, project_dir):
3052+
"""Core template body replaces {CORE_TEMPLATE} in preset command body."""
3053+
from specify_cli.presets import _substitute_core_template
3054+
from specify_cli.agents import CommandRegistrar
3055+
3056+
# Set up a core command template
3057+
core_dir = project_dir / ".specify" / "templates" / "commands"
3058+
core_dir.mkdir(parents=True, exist_ok=True)
3059+
(core_dir / "specify.md").write_text(
3060+
"---\ndescription: core\n---\n\n# Core Specify\n\nDo the thing.\n"
3061+
)
3062+
3063+
registrar = CommandRegistrar()
3064+
body = "## Pre-Logic\n\nBefore stuff.\n\n{CORE_TEMPLATE}\n\n## Post-Logic\n\nAfter stuff.\n"
3065+
result = _substitute_core_template(body, "specify", project_dir, registrar)
3066+
3067+
assert "{CORE_TEMPLATE}" not in result
3068+
assert "# Core Specify" in result
3069+
assert "## Pre-Logic" in result
3070+
assert "## Post-Logic" in result
3071+
3072+
def test_substitute_core_template_no_op_when_placeholder_absent(self, project_dir):
3073+
"""Returns body unchanged when {CORE_TEMPLATE} is not present."""
3074+
from specify_cli.presets import _substitute_core_template
3075+
from specify_cli.agents import CommandRegistrar
3076+
3077+
core_dir = project_dir / ".specify" / "templates" / "commands"
3078+
core_dir.mkdir(parents=True, exist_ok=True)
3079+
(core_dir / "specify.md").write_text("---\ndescription: core\n---\n\nCore body.\n")
3080+
3081+
registrar = CommandRegistrar()
3082+
body = "## No placeholder here.\n"
3083+
result = _substitute_core_template(body, "specify", project_dir, registrar)
3084+
assert result == body
3085+
3086+
def test_substitute_core_template_no_op_when_core_missing(self, project_dir):
3087+
"""Returns body unchanged when core template file does not exist."""
3088+
from specify_cli.presets import _substitute_core_template
3089+
from specify_cli.agents import CommandRegistrar
3090+
3091+
registrar = CommandRegistrar()
3092+
body = "Pre.\n\n{CORE_TEMPLATE}\n\nPost.\n"
3093+
result = _substitute_core_template(body, "nonexistent", project_dir, registrar)
3094+
assert result == body
3095+
assert "{CORE_TEMPLATE}" in result

0 commit comments

Comments
 (0)