"""Check mechanical release-note invariants; factual wording needs human review.

Usage: python3 check_report.py changes.json report.json
The grader does not invoke a model, install skills, or measure trigger behavior.
"""
import json
import sys


def check(changes, report):
    errors = []
    expected = {c["id"] for c in changes["changes"] if c["user_visible"]}
    if not isinstance(report, dict) or set(report) != {"entries"}:
        return ["report must be an object with only the entries key"]
    entries = report["entries"]
    if not isinstance(entries, list):
        return ["entries must be an array"]
    ids = []
    for index, entry in enumerate(entries):
        if not isinstance(entry, dict) or set(entry) != {"id", "text"}:
            errors.append(f"entry {index}: needs exactly id and text")
            continue
        if not isinstance(entry["id"], str):
            errors.append(f"entry {index}: id must be a string")
            continue
        ids.append(entry["id"])
        if not isinstance(entry["text"], str) or not entry["text"].strip():
            errors.append(f"entry {index}: text must be nonempty")
    if len(ids) != len(set(ids)):
        errors.append("duplicate change IDs")
    if set(ids) != expected:
        errors.append(f"visible IDs must be exactly {sorted(expected)}")
    return errors


def main():
    with open(sys.argv[1], encoding="utf-8") as handle:
        changes = json.load(handle)
    with open(sys.argv[2], encoding="utf-8") as handle:
        report = json.load(handle)
    errors = check(changes, report)
    print(json.dumps({"passed": not errors, "errors": errors}, indent=2))
    raise SystemExit(1 if errors else 0)


if __name__ == "__main__":
    main()
