#!/usr/bin/env python3
"""
PostToolUse hook that pushes agent heartbeats on a throttled interval.

Fires on every tool call but only invokes `crosslink heartbeat` if at least
2 minutes have elapsed since the last push. This gives accurate liveness
detection: heartbeats flow when Claude is actively working, and stop when
it hangs — which is exactly the staleness signal lock detection needs.
"""

import json
import os
import subprocess
import sys
import time

HEARTBEAT_INTERVAL_SECONDS = 120  # 2 minutes


def main():
    # Find the INITIALIZED .crosslink directory (GH#625-safe): candidates
    # without hook-config.json are strays seeded by cwd drift and are skipped,
    # never bound — binding one would throttle/cache heartbeats in the wrong
    # place.
    cwd = os.getcwd()
    crosslink_dir = None
    current = cwd
    for _ in range(10):
        candidate = os.path.join(current, ".crosslink")
        if os.path.isdir(candidate) and os.path.isfile(
            os.path.join(candidate, "hook-config.json")
        ):
            crosslink_dir = candidate
            break
        parent = os.path.dirname(current)
        if parent == current:
            break
        current = parent

    if not crosslink_dir:
        sys.exit(0)

    # Only push heartbeats if we're in an agent context (agent.json exists)
    if not os.path.exists(os.path.join(crosslink_dir, "agent.json")):
        sys.exit(0)

    # Throttle: check timestamp file
    cache_dir = os.path.join(crosslink_dir, ".cache")
    stamp_file = os.path.join(cache_dir, "last-heartbeat")

    now = time.time()
    try:
        if os.path.exists(stamp_file):
            last = os.path.getmtime(stamp_file)
            if now - last < HEARTBEAT_INTERVAL_SECONDS:
                sys.exit(0)
    except OSError:
        pass

    # Update timestamp before pushing (avoid thundering herd on slow push)
    try:
        os.makedirs(cache_dir, exist_ok=True)
        with open(stamp_file, "w") as f:
            f.write(str(now))
    except OSError:
        pass

    # Push heartbeat in background (don't block the tool call)
    try:
        subprocess.Popen(
            ["crosslink", "heartbeat"],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
        )
    except OSError:
        pass

    sys.exit(0)


if __name__ == "__main__":
    main()
