Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/specify_cli/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,13 @@ def _register_extension_skills(
body = registrar.resolve_skill_placeholders(
selected_ai, frontmatter, body, self.project_root, extension_id=manifest.id
)
# Rewrite in-body command references (`speckit.foo.bar`) to the
# hyphenated skill spelling. Skills-based integrations dispatch
# commands as `speckit-foo-bar` skills, not `/speckit.foo.bar`
# slash commands, so a verbatim dotted reference is not runnable
# (see #3451). The skill dir name and frontmatter hook refs are
# already hyphenated elsewhere; the body was the missing piece.
body = registrar._hyphenate_body_refs(body)

original_desc = frontmatter.get("description", "")
description = original_desc or f"Extension command: {cmd_name}"
Expand Down
23 changes: 23 additions & 0 deletions tests/test_extension_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def _create_extension_dir(temp_dir: Path, ext_id: str = "test-ext") -> Path:
"# Hello Command\n"
"\n"
"Run this to say hello.\n"
f"First run /speckit.{ext_id}.world to set up.\n"
"$ARGUMENTS\n"
)

Expand Down Expand Up @@ -327,6 +328,28 @@ def test_skill_md_content_correct(self, skills_project, extension_dir):
assert "compatibility:" in content
assert "Run this to say hello." in content

def test_skill_body_command_refs_are_hyphenated(self, skills_project, extension_dir):
"""In-body `speckit.x.y` references must be rewritten to the hyphenated
skill spelling for skills-based integrations (#3451).

Skills agents dispatch `speckit-x-y` skills, not `/speckit.x.y` slash
commands, so a verbatim dotted reference copied into the skill body is
not runnable. The skill dir name and frontmatter hook refs are already
hyphenated; the body was the missing piece."""
project_dir, skills_dir = skills_project
manager = ExtensionManager(project_dir)
manager.install_from_directory(
extension_dir, "0.1.0", register_commands=False
)

skill_file = skills_dir / "speckit-test-ext-hello" / "SKILL.md"
content = skill_file.read_text()

# The dotted cross-command reference must be gone from the body...
assert "speckit.test-ext.world" not in content
# ...rewritten to the hyphenated skill name.
assert "speckit-test-ext-world" in content

def test_skill_md_has_parseable_yaml(self, skills_project, extension_dir):
"""Generated SKILL.md should contain valid, parseable YAML frontmatter."""
project_dir, skills_dir = skills_project
Expand Down