"""Pin every first-party skill name to kvb-- and the Agent Skills name rules.""" from __future__ import annotations import re import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] SKILLS = REPO_ROOT / "skills" README = REPO_ROOT / "README.md" CATEGORIES = ("think", "create", "code", "ci", "git", "check", "org", "agent", "skill", "coach") UNCATEGORIZED = frozenset( { "kvb-cleanup", "kvb-coach", "kvb-dream", "kvb-help", "kvb-optimize", "kvb-transcend", } ) SPEC = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$") SCHEMA = re.compile(rf"^kvb-(?:{'|'.join(CATEGORIES)})-[a-z0-9]+(?:-[a-z0-9]+)*$") NAME_LINE = re.compile(r"^name:\s*(\S+)\s*$", re.MULTILINE) ORGANIGRAM_EDGE = re.compile(r"^\s*(\w+) --> \w+\[(kvb-[a-z0-9-]+)\]\s*$", re.MULTILINE) class TestSkillNames(unittest.TestCase): def setUp(self): self.names = sorted(p.name for p in SKILLS.iterdir() if p.is_dir()) def test_name_field_matches_the_directory(self): for name in self.names: with self.subTest(skill=name): text = (SKILLS / name / "SKILL.md").read_text(encoding="utf-8") match = NAME_LINE.search(text) self.assertIsNotNone(match, "SKILL.md has no name: line") self.assertEqual(match.group(1), name) def test_names_follow_the_agent_skills_rules(self): for name in self.names: with self.subTest(skill=name): self.assertRegex(name, SPEC) self.assertLessEqual(len(name), 64) self.assertNotRegex(name, "anthropic|claude") def test_names_use_a_listed_category(self): for name in self.names: if name in UNCATEGORIZED: continue with self.subTest(skill=name): self.assertRegex(name, SCHEMA) def test_skill_md_never_names_its_own_slash_command(self): for name in self.names: own = re.compile(rf"(?