98 lines
3.4 KiB
Python
98 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Verify the hermes-agent skill is present and readable on this host.
|
|
|
|
This is a HOST probe, not a repo test: its subject -- the live Hermes skill
|
|
catalog -- lives outside this tree, so it binds no module from it. The skills
|
|
root is taken from HERMES_SKILLS_DIR, else HERMES_HOME, else ~/.hermes/skills;
|
|
it is never a pinned /root path, so a copy of this file grades the host it is
|
|
run on.
|
|
|
|
Exit codes, because "not run" must never read as "verified":
|
|
0 the skill's SKILL.md was found and its YAML frontmatter parsed with
|
|
name: hermes-agent and a non-empty description
|
|
77 SKIP -- this host carries no Hermes skills root, so nothing was measured
|
|
1 FAIL -- the root exists but the skill is missing, or its frontmatter is
|
|
unusable
|
|
"""
|
|
import os
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
SKIP = 77
|
|
|
|
|
|
def skills_root():
|
|
"""The catalog this host actually carries, resolved per run."""
|
|
explicit = os.environ.get("HERMES_SKILLS_DIR")
|
|
if explicit:
|
|
return Path(explicit).expanduser()
|
|
home = os.environ.get("HERMES_HOME")
|
|
return (Path(home).expanduser() if home else Path.home() / ".hermes") / "skills"
|
|
|
|
|
|
def find_skill_md(root, name):
|
|
"""Every SKILL.md under a directory called `name`, nearest the root first."""
|
|
direct = root / name / "SKILL.md"
|
|
hits = [direct] if direct.is_file() else []
|
|
hits.extend(sorted(root.glob("**/%s/SKILL.md" % name)))
|
|
return [h for h in hits if h.is_file()]
|
|
|
|
|
|
def frontmatter(text):
|
|
"""The fenced `---` block's `key: value` pairs, or None when there is none."""
|
|
m = re.match(r"---\r?\n(.*?)\r?\n---\r?\n", text, re.S)
|
|
if not m:
|
|
return None
|
|
out = {}
|
|
for line in m.group(1).splitlines():
|
|
if ":" not in line or line.lstrip().startswith("#"):
|
|
continue
|
|
key, val = line.split(":", 1)
|
|
out[key.strip()] = val.strip().strip('"').strip("'")
|
|
return out
|
|
|
|
|
|
def main():
|
|
root = skills_root()
|
|
print("skills root: %s" % root)
|
|
if not root.is_dir():
|
|
print("SKIP: no Hermes skills root at %s -- nothing was measured" % root)
|
|
return SKIP
|
|
|
|
hits = find_skill_md(root, "hermes-agent")
|
|
if not hits:
|
|
print("FAIL: the root exists but carries no hermes-agent/SKILL.md")
|
|
many = sorted(p.name for p in root.iterdir() if p.is_dir())
|
|
print("directories under the root: %s" % (many[:10] or "none"))
|
|
return 1
|
|
|
|
for path in hits:
|
|
try:
|
|
text = path.read_text(encoding="utf-8")
|
|
except (OSError, UnicodeDecodeError) as exc:
|
|
print("FAIL: cannot read %s: %s" % (path, exc))
|
|
return 1
|
|
fm = frontmatter(text)
|
|
if fm is None:
|
|
print("FAIL: %s has no fenced frontmatter block" % path)
|
|
return 1
|
|
if fm.get("name") != "hermes-agent":
|
|
print("FAIL: %s declares name %r, want 'hermes-agent'"
|
|
% (path, fm.get("name")))
|
|
return 1
|
|
if not fm.get("description"):
|
|
print("FAIL: %s declares no description" % path)
|
|
return 1
|
|
print("PASS: %s" % path)
|
|
print(" name=%s version=%s" % (fm.get("name"), fm.get("version", "?")))
|
|
print(" description=%s" % fm["description"][:70])
|
|
|
|
print("\nAll checks passed - hermes-agent skill is present and readable (%d file(s))"
|
|
% len(hits))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|