55 lines
1.5 KiB
Python
55 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate or verify SKILLS.lock, a checksum manifest of every skill file.
|
|
|
|
Usage:
|
|
python tools/gen_skills_lock.py # write SKILLS.lock
|
|
python tools/gen_skills_lock.py --check # verify, exit 1 on drift
|
|
"""
|
|
import hashlib
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
SKILLS_DIR = ROOT / "skills"
|
|
LOCK_PATH = ROOT / "SKILLS.lock"
|
|
|
|
|
|
def sha256(path: Path) -> str:
|
|
h = hashlib.sha256()
|
|
h.update(path.read_bytes())
|
|
return h.hexdigest()
|
|
|
|
|
|
def build_manifest() -> dict:
|
|
manifest = {}
|
|
for skill_dir in sorted(p for p in SKILLS_DIR.iterdir() if p.is_dir()):
|
|
files = {}
|
|
for f in sorted(skill_dir.rglob("*")):
|
|
if f.is_file():
|
|
rel = f.relative_to(skill_dir).as_posix()
|
|
files[rel] = sha256(f)
|
|
manifest[skill_dir.name] = files
|
|
return manifest
|
|
|
|
|
|
def main() -> int:
|
|
manifest = build_manifest()
|
|
serialized = json.dumps(manifest, indent=2, sort_keys=True) + "\n"
|
|
if "--check" in sys.argv:
|
|
if not LOCK_PATH.exists():
|
|
print("SKILLS.lock is missing. Run tools/gen_skills_lock.py.")
|
|
return 1
|
|
if LOCK_PATH.read_text() != serialized:
|
|
print("SKILLS.lock is out of date. Regenerate and commit it.")
|
|
return 1
|
|
print("SKILLS.lock is current.")
|
|
return 0
|
|
LOCK_PATH.write_text(serialized)
|
|
print(f"Wrote SKILLS.lock with {len(manifest)} skills.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|