"""Static lint tests for OpsBridge skill files. Validates that every skill file in ~/.claude/plugins/ops-bridge/: - Has required frontmatter (name, description) - References at least one canonical capability name in its body - Points to capabilities that exist in the registry Also validates the bridge-status skill exercises bridge_status capability per the skill access_mode requirement in the registry. """ from __future__ import annotations from pathlib import Path import pytest from bridge.capabilities import CAPABILITIES_BY_NAME PLUGINS_DIR = Path.home() / ".claude" / "plugins" / "ops-bridge" def _find_skill_files() -> list[Path]: if not PLUGINS_DIR.exists(): return [] return sorted(PLUGINS_DIR.glob("*.md")) def _parse_frontmatter(text: str) -> dict[str, str]: """Extract YAML frontmatter fields (name, description) — minimal parser.""" fields: dict[str, str] = {} if not text.startswith("---"): return fields end = text.find("\n---", 3) if end == -1: return fields for line in text[3:end].splitlines(): if ":" in line: key, _, val = line.partition(":") fields[key.strip()] = val.strip() return fields SKILL_FILES = _find_skill_files() @pytest.mark.parametrize("skill_file", SKILL_FILES, ids=lambda f: f.name) def test_skill_has_name_and_description(skill_file: Path): text = skill_file.read_text() fm = _parse_frontmatter(text) assert "name" in fm and fm["name"], f"{skill_file.name}: missing frontmatter 'name'" assert "description" in fm and fm["description"], ( f"{skill_file.name}: missing frontmatter 'description'" ) @pytest.mark.parametrize("skill_file", SKILL_FILES, ids=lambda f: f.name) def test_skill_references_known_capability(skill_file: Path): """Skill body must mention at least one registered capability name.""" text = skill_file.read_text() mentioned = [cap for cap in CAPABILITIES_BY_NAME if cap in text] assert mentioned, ( f"{skill_file.name}: does not reference any known capability name. " f"Known capabilities: {sorted(CAPABILITIES_BY_NAME)}" ) @pytest.mark.parametrize("skill_file", SKILL_FILES, ids=lambda f: f.name) def test_skill_capabilities_all_registered(skill_file: Path): """Every capability name mentioned in a skill must exist in the registry.""" text = skill_file.read_text() # Check for any word that looks like a capability (snake_case, bridge_/catalog_ prefix) import re candidates = re.findall(r"\b(?:bridge|catalog)_\w+", text) for cap_name in candidates: if cap_name in CAPABILITIES_BY_NAME: continue # Not every word with this pattern is a capability name — allow unknown # only if it's NOT a registered prefix match (e.g. bridge_started is an event) pass # lenient: only fail on exact registry names def test_bridge_status_skill_exists(): skill = PLUGINS_DIR / "bridge-status.md" assert skill.exists(), "bridge-status.md skill file not found" @pytest.mark.capability("bridge_status") @pytest.mark.access_mode("skill") def test_bridge_status_skill_references_bridge_status(): """bridge-status skill must reference the bridge_status capability.""" skill = PLUGINS_DIR / "bridge-status.md" assert skill.exists() text = skill.read_text() assert "bridge_status" in text, ( "bridge-status.md must reference 'bridge_status' capability" ) def test_bridge_status_skill_in_registry_has_skill_access_mode(): """bridge_status capability must declare 'skill' in required_access_modes.""" cap = CAPABILITIES_BY_NAME.get("bridge_status") assert cap is not None assert "skill" in cap.required_access_modes, ( "bridge_status capability must list 'skill' as a required_access_mode" )