← Files AI PsychiatryARCHIVED FILE

scripts/build_all_the_medicine.py

7.05 KB · Oct 2, 2026 · 00:30 UTC

↓ Download file

"""Build the compiled all-the-medicine skill and rule references from the manifests."""

from __future__ import annotations

import argparse
import hashlib
import json
import os
import re
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
OUTPUT_DIR = ROOT / "skills/all-the-medicine/references"
SELF_NAME = "all-the-medicine"
SKILLS_MD = OUTPUT_DIR / "all-skills-compiled.md"
RULES_MD = OUTPUT_DIR / "all-rules-compiled.md"
SKILL_INDEX = OUTPUT_DIR / "skill-index.json"
SOURCE_HASHES = OUTPUT_DIR / "source-hashes.json"

LINK = re.compile(r"(?<!!)\[([^\]]+)\]\(([^)]+)\)")


def _rewrite_links(text: str, source_dir: Path) -> str:
    """Rewrite relative markdown links so they still resolve from OUTPUT_DIR after compilation."""

    def replace(match: re.Match) -> str:
        label, target = match.group(1), match.group(2)
        if "://" in target or target.startswith("mailto:") or target.startswith("#") or not target:
            return match.group(0)
        path_part, _, anchor = target.partition("#")
        if not path_part:
            return match.group(0)
        absolute = (source_dir / path_part).resolve()
        relative = os.path.relpath(absolute, OUTPUT_DIR).replace(os.sep, "/")
        return f"[{label}]({relative}{'#' + anchor if anchor else ''})"

    return LINK.sub(replace, text)

GENERATED_HEADER = (
    "<!-- GENERATED by scripts/build_all_the_medicine.py. DO NOT EDIT MANUALLY. -->\n"
    "<!-- Source of truth: .ai/manifests/skills.json, .ai/manifests/rules.json, and the individual skill/rule files. -->\n"
)


def _sha256(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest().upper()


def assert_no_duplicates(entries: list[dict], field: str, source: str) -> None:
    """Fail generation when a manifest declares the same skill or rule identity twice."""
    values = [item[field] for item in entries]
    if len(values) != len(set(values)):
        raise ValueError(f"duplicate {field!r} in {source}")


def assert_paths_exist(entries: list[dict], root: Path = ROOT) -> None:
    """Fail generation when a manifest-declared skill or rule file is missing from disk."""
    for item in entries:
        path = root / item["path"]
        if not path.exists():
            raise FileNotFoundError(f"declared path missing: {item['path']}")


def load_plugin_skills(root: Path = ROOT) -> list[dict]:
    manifest = json.loads((root / ".ai/manifests/skills.json").read_text(encoding="utf-8"))
    entries = list(manifest["plugin_skills"])
    assert_no_duplicates(entries, "name", ".ai/manifests/skills.json")
    assert_no_duplicates(entries, "id", ".ai/manifests/skills.json")
    entries = [item for item in entries if item["name"] != SELF_NAME]
    entries.sort(key=lambda item: int(item["id"].split("-")[-1]))
    assert_paths_exist(entries, root)
    return entries


def load_rules(root: Path = ROOT) -> list[dict]:
    manifest = json.loads((root / ".ai/manifests/rules.json").read_text(encoding="utf-8"))
    entries = list(manifest["rules"])
    assert_no_duplicates(entries, "id", ".ai/manifests/rules.json")
    entries.sort(key=lambda item: item["id"])
    assert_paths_exist(entries, root)
    return entries


def build_skills_document(skills: list[dict]) -> str:
    parts = [GENERATED_HEADER, "\n# All the medicine — compiled public skills\n"]
    for item in skills:
        name = item["name"]
        source_path = ROOT / item["path"]
        text = _rewrite_links(source_path.read_text(encoding="utf-8"), source_path.parent)
        parts.append(f"\n<!-- BEGIN SKILL: {name} -->\n")
        parts.append(text.rstrip("\n") + "\n")
        parts.append(f"<!-- END SKILL: {name} -->\n")
    return "".join(parts)


def build_rules_document(rules: list[dict]) -> str:
    parts = [GENERATED_HEADER, "\n# All the medicine — compiled canonical rules\n"]
    for item in rules:
        rule_id = item["id"]
        source_path = ROOT / item["path"]
        text = _rewrite_links(source_path.read_text(encoding="utf-8"), source_path.parent)
        parts.append(f"\n<!-- BEGIN RULE: {rule_id} -->\n")
        parts.append(text.rstrip("\n") + "\n")
        parts.append(f"<!-- END RULE: {rule_id} -->\n")
    return "".join(parts)


def build_skill_index(skills: list[dict]) -> dict:
    return {
        "generated_by": "scripts/build_all_the_medicine.py",
        "self_excluded": SELF_NAME,
        "count": len(skills),
        "skills": [
            {"id": item["id"], "name": item["name"], "path": item["path"]}
            for item in skills
        ],
    }


def build_source_hashes(skills: list[dict], rules: list[dict]) -> dict:
    hashes = {item["path"]: _sha256(ROOT / item["path"]) for item in skills}
    hashes.update({item["path"]: _sha256(ROOT / item["path"]) for item in rules})
    return {"generated_by": "scripts/build_all_the_medicine.py", "hashes": dict(sorted(hashes.items()))}


def assert_no_self_recursion(skills_doc: str) -> None:
    marker = f"BEGIN SKILL: {SELF_NAME}"
    if marker in skills_doc:
        raise ValueError("all-the-medicine must not appear in its own compiled inventory")


def build() -> dict[str, str]:
    skills = load_plugin_skills()
    rules = load_rules()
    skills_doc = build_skills_document(skills)
    assert_no_self_recursion(skills_doc)
    rules_doc = build_rules_document(rules)
    index = json.dumps(build_skill_index(skills), indent=2) + "\n"
    hashes = json.dumps(build_source_hashes(skills, rules), indent=2) + "\n"
    return {
        str(SKILLS_MD): skills_doc,
        str(RULES_MD): rules_doc,
        str(SKILL_INDEX): index,
        str(SOURCE_HASHES): hashes,
    }


def write(outputs: dict[str, str]) -> None:
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    for path_str, content in outputs.items():
        Path(path_str).write_text(content, encoding="utf-8", newline="\n")


def check(outputs: dict[str, str]) -> list[str]:
    issues: list[str] = []
    for path_str, content in outputs.items():
        path = Path(path_str)
        if not path.exists():
            issues.append(f"missing: {path.relative_to(ROOT)}")
            continue
        current = path.read_text(encoding="utf-8")
        if current != content:
            issues.append(f"stale: {path.relative_to(ROOT)}")
    return issues


def main() -> int:
    parser = argparse.ArgumentParser(description="Build or check the compiled all-the-medicine references")
    parser.add_argument("--check", action="store_true", help="verify compiled output is current without writing")
    args = parser.parse_args()

    try:
        outputs = build()
    except (FileNotFoundError, ValueError, KeyError) as exc:
        print(f"build failed: {exc}")
        return 1

    if args.check:
        issues = check(outputs)
        if issues:
            for issue in issues:
                print(f"[stale] {issue}")
            print(f"All-the-medicine compiled references are stale: {len(issues)} issue(s)")
            return 1
        print("All-the-medicine compiled references are current")
        return 0

    write(outputs)
    print(f"Built {len(outputs)} all-the-medicine reference files")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

SHA-256: d62d06c45b03f3bef6774476fd4da8cc1d9063ee2adaa3ddc9ad0988e0f3e184