Files
othmanadi--planning-with-files/tests/test_skill_frontmatter_valid.py
2026-07-13 12:40:00 +08:00

102 lines
3.5 KiB
Python

"""Guard: every SKILL.md frontmatter must be valid, loadable YAML.
Regression test for the v3.1.2 -> v3.1.3 break: an unquoted description that
contained ': ' (colon followed by space) turned the frontmatter into an invalid
YAML mapping ("mapping values are not allowed here"), which breaks skill loading
and the model-triggering description field. The version-parity check is a regex
and did not catch it, so this validates the frontmatter as actual YAML.
clawhub-upload/SKILL.md is gitignored and may be absent on a fresh clone; glob
simply does not find it then, which is fine.
"""
import glob
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
def _skill_md_files():
out = []
for p in glob.glob(str(REPO_ROOT / "**" / "SKILL.md"), recursive=True):
parts = Path(p).parts
if ".git" in parts or "node_modules" in parts:
continue
out.append(Path(p))
return out
def _frontmatter(text):
if not text.startswith("---"):
return None
segments = text.split("---", 2)
if len(segments) < 3:
return None
return segments[1]
def _description_line(frontmatter):
for line in frontmatter.splitlines():
if line.startswith("description:"):
return line
return None
class SkillFrontmatterTests(unittest.TestCase):
def test_files_found(self):
self.assertTrue(_skill_md_files(), "no SKILL.md files discovered")
def test_every_skill_has_frontmatter_and_description(self):
for f in _skill_md_files():
fm = _frontmatter(f.read_text(encoding="utf-8"))
self.assertIsNotNone(fm, f"{f} has no '---' frontmatter block")
self.assertIsNotNone(
_description_line(fm), f"{f} frontmatter has no description:"
)
def test_unquoted_description_has_no_colon_space(self):
# Dependency-free guard for the exact v3.1.2 break.
for f in _skill_md_files():
fm = _frontmatter(f.read_text(encoding="utf-8"))
if fm is None:
continue
line = _description_line(fm)
if line is None:
continue
value = line[len("description:"):].strip()
if value[:1] in ('"', "'"):
continue # quoted scalars may safely contain colons
self.assertNotIn(
": ",
value,
f"{f}: unquoted description contains ': ', which YAML parses as a "
f"mapping and breaks frontmatter loading. Quote the value.",
)
def test_frontmatter_parses_as_yaml(self):
try:
import yaml
except ImportError:
self.skipTest("PyYAML not installed")
for f in _skill_md_files():
fm = _frontmatter(f.read_text(encoding="utf-8"))
if fm is None:
continue
try:
data = yaml.safe_load(fm)
except Exception as exc: # noqa: BLE001
self.fail(f"{f}: frontmatter is not valid YAML: {exc}")
self.assertIsInstance(data, dict, f"{f}: frontmatter is not a mapping")
self.assertIsInstance(
data.get("description"),
str,
f"{f}: description missing or not a string after YAML parse",
)
self.assertTrue(
data["description"].strip(), f"{f}: description is empty"
)
if __name__ == "__main__":
unittest.main()