"""Skills Scanner — Scan skills/ directory and generate SKILLS_SNAPSHOT.md.""" from pathlib import Path from hashlib import sha256 import yaml def discover_skills(base_dir: Path) -> list[dict]: """Read the native Skills catalog without changing its generated snapshot.""" root = (base_dir / "skills").resolve() entries = [] for file in sorted(root.rglob("SKILL.md")): resolved = file.resolve() if not resolved.is_relative_to(root): continue try: content = file.read_text(encoding="utf-8") if not content.startswith("---"): continue parts = content.split("---", 2) meta = yaml.safe_load(parts[1]) if len(parts) == 3 else None if not isinstance(meta, dict): continue legacy_id = file.relative_to(root).as_posix() entries.append({ "id": legacy_id, "component_id": str(meta.get("id", legacy_id)), "legacy_id": legacy_id, "kind": str(meta.get("kind", "skill")), "version": str(meta.get("version", "legacy")), "schema_version": int(meta.get("schema_version", 1)), "status": str(meta.get("status", "published")), "name": str(meta.get("name", file.parent.name)), "description": str(meta.get("description", "")), "content_hash": sha256(content.encode("utf-8")).hexdigest(), "content": content, }) except (OSError, ValueError, TypeError, yaml.YAMLError): continue return entries def scan_skills(base_dir: Path) -> str: """Scan all SKILL.md files and generate SKILLS_SNAPSHOT.md.""" skills_dir = base_dir / "skills" snapshot_path = base_dir / "SKILLS_SNAPSHOT.md" if not skills_dir.exists(): skills_dir.mkdir(parents=True) skills = [{**s, "location":f"./backend/skills/{s['legacy_id']}"} for s in discover_skills(base_dir)] # Build XML-style snapshot lines = [""] for s in skills: lines.append(" ") lines.append(f" {s['name']}") lines.append(f" {s['description']}") lines.append(f" {s['location']}") lines.append(" ") lines.append("") snapshot = "\n".join(lines) snapshot_path.write_text(snapshot, encoding="utf-8") print(f"📋 Skills snapshot: {len(skills)} skills found") return snapshot