Files
aiturk-hermes-ide/tests/skills/test_meeting_action_items_skill.py

97 lines
3.2 KiB
Python

"""Tests for the meeting-action-items bundled skill."""
import re
from pathlib import Path
import yaml
SKILL_PATH = (
Path(__file__).resolve().parents[2]
/ "skills"
/ "productivity"
/ "meeting-action-items"
/ "SKILL.md"
)
def _frontmatter_and_body():
content = SKILL_PATH.read_text(encoding="utf-8")
assert content.startswith("---")
m = re.search(r"\n---\s*\n", content[3:])
assert m, "frontmatter must close with ---"
fm = yaml.safe_load(content[3 : m.start() + 3])
body = content[m.end() + 3 :]
return fm, body
def test_skill_file_exists():
assert SKILL_PATH.is_file()
def test_frontmatter_required_fields():
fm, _ = _frontmatter_and_body()
for field in ("name", "description", "version", "author", "license", "platforms"):
assert field in fm, f"missing frontmatter field: {field}"
assert fm["name"] == "meeting-action-items"
hermes = fm["metadata"]["hermes"]
assert hermes["tags"]
assert "related_skills" in hermes
def test_description_hardline():
fm, _ = _frontmatter_and_body()
desc = fm["description"]
assert len(desc) <= 60, f"description is {len(desc)} chars; hardline is 60"
assert desc.endswith(".")
def test_author_credits_human_first():
fm, _ = _frontmatter_and_body()
assert not fm["author"].startswith("Hermes Agent"), "human contributor must be credited first"
assert "benbarclay" in fm["author"]
def test_related_skills_resolve_in_repo():
fm, _ = _frontmatter_and_body()
repo_root = SKILL_PATH.parents[3]
for name in fm["metadata"]["hermes"]["related_skills"]:
hits = (
list(repo_root.glob(f"skills/*/{name}/SKILL.md"))
+ list(repo_root.glob(f"optional-skills/*/{name}/SKILL.md"))
+ list(repo_root.glob(f"skills/*/*/{name}/SKILL.md"))
)
assert hits, f"related_skills entry does not resolve in-repo: {name}"
def test_no_phantom_connectors_in_prose():
"""Prose must not name tracker connectors that don't exist as skills."""
_, body = _frontmatter_and_body()
assert not re.search(r"\bLinear\b", body), "no phantom 'Linear' connector references"
def test_body_structure_and_size():
_, body = _frontmatter_and_body()
for section in ("## When to Use", "## Procedure", "## Pitfalls", "## Verification"):
assert section in body, f"missing section: {section}"
assert len(SKILL_PATH.read_text(encoding="utf-8")) <= 100_000
def test_no_machine_local_paths():
content = SKILL_PATH.read_text(encoding="utf-8")
assert "/home/" not in content
assert not re.search(r"[A-Z]:\\\\Users", content)
def test_steps_have_completion_criteria():
_, body = _frontmatter_and_body()
steps = re.findall(r"^### \d+\..*?(?=^### \d+\.|^## )", body, re.MULTILINE | re.DOTALL)
assert len(steps) >= 5
for step in steps:
assert "Done when" in step, f"step missing completion criterion: {step[:60]!r}"
def test_core_disciplines_present():
_, body = _frontmatter_and_body()
assert "never invent" in body, "due-date invention ban must be present"
assert "before creating anything" in body, "reconcile-before-create must be present"
assert "`unresolved`" in body, "missing owners/dates stay visibly unresolved"