#!/usr/bin/env python3
"""
anchorcheck.py — is the restore target a heal would use still fresh?

WHY THIS EXISTS
---------------
On 2026-09-12 a self-heal instrument for this site was found to carry a hardcoded
"known-good" deploy id that was twelve deploys old. Had the heal fired, it would have
restored the site to before three weeks of work — by the thing built to protect it.
Its detect step read the site as healthy (it was), so the heal never fired, so the
stale target never got the chance to convict itself. Nobody was checking the checker.

WHAT IT DOES
------------
1. Reads the anchor the site PUBLISHES about itself:  <site>/havens.head -> known_good_deploy
2. Reads the anchor any local heal instrument WOULD use (pass its file, or an id).
3. Asks the host for the newest published deploy in state "ready".
4. Convicts if (2) is missing from the host's recent deploys, or is older than TOLERANCE
   deploys behind (3). Also warns if (1) and (2) disagree.

It never restores anything. It only tells you whether a restore would land where you think.

USAGE
-----
  # compare a skill file's hardcoded id against the host
  NETLIFY_TOKEN=... python3 anchorcheck.py --site <site-id> --skill path/to/SKILL.md
  # or compare a bare id
  NETLIFY_TOKEN=... python3 anchorcheck.py --site <site-id> --anchor 6aa5c4b9b29ebe406a131092
  # read-only against the public head file only (no token; skips the host comparison)
  python3 anchorcheck.py --head https://www.avenlost.pet/havens.head --anchor <id>

Exit 0 fresh · 1 stale or missing · 2 could not determine (and says why).
Public domain. Take it.
"""
import argparse, json, os, re, sys, urllib.request

HEX24 = re.compile(r"\b[0-9a-f]{24}\b")

def get(url, token=None):
    req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"} if token else {})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.loads(r.read().decode("utf-8"))

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--site", help="Netlify site id (needed for the host comparison)")
    ap.add_argument("--head", default="https://www.avenlost.pet/havens.head",
                    help="the published cheap-check file that carries known_good_deploy")
    ap.add_argument("--skill", help="a heal instrument's file; its first 24-hex id is read as the anchor it would use")
    ap.add_argument("--anchor", help="the anchor to check, as a bare deploy id")
    ap.add_argument("--tolerance", type=int, default=2,
                    help="how many published deploys behind the newest is still acceptable")
    a = ap.parse_args()
    token = os.environ.get("NETLIFY_TOKEN")

    # (1) what the site says about itself
    published = None
    try:
        head = get(a.head)
        published = head.get("known_good_deploy")
        print(f"  site publishes known_good_deploy = {published}  (generated {head.get('generated')})")
    except Exception as e:
        print(f"  could not read {a.head}: {e}")

    # (2) what the local instrument would use
    local = a.anchor
    if a.skill:
        text = open(a.skill, encoding="utf-8").read()
        m = HEX24.search(text)
        local = m.group(0) if m else None
        print(f"  {a.skill} would restore to = {local}")
    if not local and not published:
        print("  nothing to check: no --anchor, no --skill, and the head carries no anchor"); sys.exit(2)
    if not local:
        local = published

    if published and local and published != local:
        print(f"  WARNING  the instrument's anchor ({local[:12]}) disagrees with the site's own ({published[:12]})")

    # (3) what the host says is newest
    if not (a.site and token):
        print("  no --site or no NETLIFY_TOKEN: skipping the host comparison; verdict is on agreement only")
        sys.exit(0 if (not published or published == local) else 1)

    deploys = get(f"https://api.netlify.com/api/v1/sites/{a.site}/deploys?per_page=50", token)
    good = [d for d in deploys if d.get("state") == "ready" and d.get("published_at")]
    good.sort(key=lambda d: d["published_at"], reverse=True)
    if not good:
        print("  host lists no published ready deploys"); sys.exit(2)
    ids = [d["id"] for d in good]
    print(f"  host newest published = {ids[0]}  ({good[0]['published_at']})")

    if local not in ids:
        print(f"  STALE  {local} is not among the host's last {len(ids)} published deploys"); sys.exit(1)
    behind = ids.index(local)
    if behind > a.tolerance:
        print(f"  STALE  anchor is {behind} published deploys behind the newest (tolerance {a.tolerance})")
        for i, d in enumerate(good[:behind + 1]):
            print(f"         {i:2d}  {d['id']}  {d['published_at']}")
        sys.exit(1)
    print(f"  FRESH  anchor is {behind} deploy(s) behind the newest — within tolerance")
    sys.exit(0)

if __name__ == "__main__":
    main()
