#!/usr/bin/env python3 """zio-harness graphify bootstrap. SessionStart hook: ensure graphify (+SQL parser) is installed, then build or update the project knowledge graph so the assistant can answer codebase questions from graphify-out/graph.json immediately. Env switches: ZIO_HARNESS_NO_GRAPHIFY=1 skip everything ZIO_HARNESS_GRAPHIFY_FULL=1 allow first-time extraction even without .git """ import importlib.util import os import shutil import subprocess import sys import sysconfig TIMEOUT_INSTALL = 300 TIMEOUT_GRAPH = 480 def log(msg: str) -> None: print(f"[zio-harness] {msg}") def has_module(name: str) -> bool: try: return importlib.util.find_spec(name) is not None except Exception: return False def find_graphify() -> str | None: exe = shutil.which("graphify") if exe: return exe scripts = sysconfig.get_path("scripts") or "" for candidate in ("graphify.exe", "graphify"): path = os.path.join(scripts, candidate) if os.path.isfile(path): return path return None def ensure_installed() -> str | None: if find_graphify() and has_module("tree_sitter_sql"): return find_graphify() log("installing graphifyy[sql] (one-time)...") try: subprocess.run( [sys.executable, "-m", "pip", "install", "--quiet", "graphifyy[sql]"], timeout=TIMEOUT_INSTALL, check=False, ) except Exception as exc: # network down, pip missing, etc. log(f"install skipped: {exc}") return find_graphify() def run_graphify(exe: str, *args: str) -> int: try: proc = subprocess.run([exe, *args], timeout=TIMEOUT_GRAPH, check=False) return proc.returncode except Exception as exc: log(f"graphify {' '.join(args[:1])} failed: {exc}") return 1 def main() -> int: if os.environ.get("ZIO_HARNESS_NO_GRAPHIFY") == "1": return 0 cwd = os.getcwd() home = os.path.expanduser("~") graph = os.path.join(cwd, "graphify-out", "graph.json") is_project = os.path.isdir(os.path.join(cwd, ".git")) or os.path.isfile(graph) if os.path.normcase(cwd) == os.path.normcase(home): return 0 # never index the home directory if not is_project and os.environ.get("ZIO_HARNESS_GRAPHIFY_FULL") != "1": return 0 # not a project root — stay quiet exe = ensure_installed() if not exe: log("graphify unavailable — skipping knowledge graph") return 0 if os.path.isfile(graph): rc = run_graphify(exe, "update", cwd) if rc == 0: log("knowledge graph updated (graphify-out/graph.json) — " "use `graphify query/explain/path` for codebase questions") else: log("building knowledge graph (first run, local AST only)...") rc = run_graphify(exe, "extract", cwd, "--code-only") if rc == 0: log("knowledge graph built at graphify-out/graph.json — " "use `graphify query/explain/path` for codebase questions") return 0 if __name__ == "__main__": sys.exit(main())