2026-01-24 23:28:43 -07:00

105 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""
Validate all skills in the repository.
Checks for required frontmatter fields and proper structure.
"""
import os
import re
import sys
def validate_skills(skills_dir):
print(f"validating skills in: {skills_dir}\n")
errors = []
warnings = []
skill_count = 0
for entry in sorted(os.listdir(skills_dir)):
skill_path = os.path.join(skills_dir, entry)
skill_file = os.path.join(skill_path, "SKILL.md")
if not os.path.isdir(skill_path):
continue
if not os.path.exists(skill_file):
errors.append(f"{entry}: missing SKILL.md")
continue
skill_count += 1
with open(skill_file, 'r', encoding='utf-8') as f:
content = f.read()
# Check for frontmatter
if not content.strip().startswith("---"):
errors.append(f"{entry}: missing frontmatter (must start with ---)")
continue
# Extract frontmatter
fm_match = re.search(r'^---\s*\n(.*?)\n---', content, re.DOTALL)
if not fm_match:
errors.append(f"{entry}: malformed frontmatter")
continue
fm_content = fm_match.group(1)
# Check required fields
name_match = re.search(r'^name:\s*(.+)$', fm_content, re.MULTILINE)
desc_match = re.search(r'^description:\s*(.+)$', fm_content, re.MULTILINE)
if not name_match:
errors.append(f"{entry}: frontmatter missing 'name' field")
else:
name = name_match.group(1).strip()
# Validate name format
if not re.match(r'^[a-z0-9]+(-[a-z0-9]+)*$', name):
errors.append(f"{entry}: name must be lowercase alphanumeric with hyphens")
if name != entry:
warnings.append(f"{entry}: name '{name}' doesn't match directory name")
if not desc_match:
errors.append(f"{entry}: frontmatter missing 'description' field")
else:
desc = desc_match.group(1).strip()
if len(desc) < 10:
warnings.append(f"{entry}: description seems too short")
if len(desc) > 1024:
errors.append(f"{entry}: description exceeds 1024 characters")
# Check for content after frontmatter
body = content[fm_match.end():].strip()
if len(body) < 50:
warnings.append(f"{entry}: skill content seems too short")
# Print results
print(f"checked {skill_count} skills\n")
if warnings:
print("warnings:")
for w in warnings:
print(f" {w}")
print()
if errors:
print("errors:")
for e in errors:
print(f" {e}")
print()
print(f"validation failed with {len(errors)} errors")
return False
print("all skills passed validation!")
return True
if __name__ == "__main__":
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
skills_path = os.path.join(base_dir, "skills")
if not os.path.exists(skills_path):
print(f"error: skills directory not found at {skills_path}")
sys.exit(1)
success = validate_skills(skills_path)
sys.exit(0 if success else 1)