Skip to content
Merged
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
85 changes: 85 additions & 0 deletions tests/integrations/test_integration_base_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,91 @@ def test_skill_uses_template_descriptions(self, tmp_path):
assert isinstance(fm["description"], str)
assert len(fm["description"]) > 0, f"{f} has empty description"

def test_skill_frontmatter_preserves_multiline_description(
self, tmp_path, monkeypatch
):
"""A multiline (block-scalar) description must round-trip exactly.

The hand-built SKILL.md frontmatter used to only escape backslash and
quote, so a block-scalar description was emitted with raw newlines inside
a double-quoted scalar and reparsed with those newlines collapsed to
spaces. The description must survive byte-for-byte."""
from pathlib import Path

i = get_integration(self.KEY)
# Hermes writes to ~/.hermes/skills/ — isolate Path.home() to prevent
# overwriting a developer's real global skill directory.
if self.KEY == "hermes":
home = tmp_path / "home"
home.mkdir(exist_ok=True)
monkeypatch.setattr(Path, "home", lambda: home)

template = tmp_path / "sample.md"
template.write_text(
"---\n"
"description: |\n"
" first line\n"
" second line\n"
"scripts:\n"
" sh: scripts/bash/x.sh\n"
"---\n"
"Body\n",
encoding="utf-8",
)
monkeypatch.setattr(i, "list_command_templates", lambda: [template])

m = IntegrationManifest(self.KEY, tmp_path)
created = i.setup(tmp_path, m)
skill_files = [f for f in created if f.name == "SKILL.md"]
assert len(skill_files) == 1

content = skill_files[0].read_text(encoding="utf-8")
fm = yaml.safe_load(content.split("---", 2)[1])
assert "\n" in fm["description"]
assert fm["description"] == "first line\nsecond line\n"

def test_skill_frontmatter_preserves_control_characters(
self, tmp_path, monkeypatch
):
"""A description carrying a C0/DEL control char must round-trip exactly.

A control character can reach ``description`` via a YAML escape in the
source template (``"a\\x08b"`` parses to a real U+0008). The old
hand-built frontmatter only escaped backslash and quote, so the raw
control char landed inside the emitted double-quoted scalar and made the
SKILL.md unparseable / lossy. ``yaml_quote`` must escape it so the
value survives byte-for-byte."""
from pathlib import Path

i = get_integration(self.KEY)
# Hermes writes to ~/.hermes/skills/ — isolate Path.home() to prevent
# overwriting a developer's real global skill directory.
if self.KEY == "hermes":
home = tmp_path / "home"
home.mkdir(exist_ok=True)
monkeypatch.setattr(Path, "home", lambda: home)

template = tmp_path / "sample.md"
template.write_text(
"---\n"
'description: "a\\x08b\\ttab"\n'
"scripts:\n"
" sh: scripts/bash/x.sh\n"
"---\n"
"Body\n",
encoding="utf-8",
)
monkeypatch.setattr(i, "list_command_templates", lambda: [template])

m = IntegrationManifest(self.KEY, tmp_path)
created = i.setup(tmp_path, m)
skill_files = [f for f in created if f.name == "SKILL.md"]
assert len(skill_files) == 1

content = skill_files[0].read_text(encoding="utf-8")
fm = yaml.safe_load(content.split("---", 2)[1])
assert fm["description"] == "a\x08b\ttab"

def test_templates_are_processed(self, tmp_path):
"""Skill body must have placeholders replaced, not raw templates."""
i = get_integration(self.KEY)
Expand Down