- harness·zio-harness·proposal-builder·zioinfo → plugins/zioinfo (git mv 히스토리 보존) - 스킬 4·커맨드 3(/zioinfo:pmo·proposal·wiki)·에이전트 15·graphify 훅·knowledge 통합 - 신규: /zioinfo:wiki (graphify LLM wiki — graphify-out/wiki/ 커뮤니티별 아티클) - 신규: ZIO WISE 테마 (themes/zioinfo.json, experimental) - manifest 최신화: $schema·displayName(ZIO INFOTECH Suite)·experimental.themes - marketplace.json 단일 엔트리, 루트 plugin.json 제거 - CLAUDE.md·PROJECT_MAP·docs/plugins.md·README 3종·CHANGELOG·설치가이드 pptx 재구성 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
104 lines
3.1 KiB
Python
104 lines
3.1 KiB
Python
#!/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())
|