""" Tests for SKILL.md validation. Task 1: Test SKILL.md file exists. Task 2: Test SKILL.md has valid YAML frontmatter. Task 3: Test SKILL.md has name field. Task 4: Test SKILL.md has description field. Task 5: Test description contains /gsd: pattern for triggering. """ import pytest from pathlib import Path import yaml class TestSkillMd: """Tests for SKILL.md structure and trigger patterns.""" @property def skill_path(self) -> Path: """Get path to SKILL.md.""" return Path(__file__).parent.parent / "skill" / "SKILL.md" def test_skill_md_exists(self): """SKILL.md file exists at skill/SKILL.md.""" assert self.skill_path.exists(), f"SKILL.md not found at {self.skill_path}" def test_skill_md_has_valid_frontmatter(self): """SKILL.md has valid YAML frontmatter between --- delimiters.""" content = self.skill_path.read_text(encoding="utf-8") # Check file starts with --- assert content.startswith("---\n"), "SKILL.md must start with '---' frontmatter delimiter" # Find closing delimiter parts = content.split("---\n", 2) assert len(parts) >= 3, "SKILL.md must have opening and closing '---' delimiters" # Parse frontmatter as YAML frontmatter_text = parts[1].strip() frontmatter = yaml.safe_load(frontmatter_text) assert isinstance(frontmatter, dict), "Frontmatter must be valid YAML" def test_skill_md_has_name_field(self): """SKILL.md frontmatter contains 'name' field.""" frontmatter = self._parse_frontmatter() assert "name" in frontmatter, "Frontmatter must contain 'name' field" assert isinstance(frontmatter["name"], str), "'name' must be a string" assert len(frontmatter["name"]) > 0, "'name' must not be empty" def test_skill_md_has_description_field(self): """SKILL.md frontmatter contains 'description' field.""" frontmatter = self._parse_frontmatter() assert "description" in frontmatter, "Frontmatter must contain 'description' field" assert isinstance(frontmatter["description"], str), "'description' must be a string" assert len(frontmatter["description"]) > 0, "'description' must not be empty" def test_skill_md_description_contains_gsd_pattern(self): """SKILL.md description contains /gsd: pattern for trigger matching.""" frontmatter = self._parse_frontmatter() description = frontmatter.get("description", "") assert "/gsd:" in description, "Description must contain '/gsd:' pattern for OpenClaw trigger matching" def _parse_frontmatter(self) -> dict: """Parse and return frontmatter from SKILL.md.""" content = self.skill_path.read_text(encoding="utf-8") parts = content.split("---\n", 2) frontmatter_text = parts[1].strip() return yaml.safe_load(frontmatter_text)