mirror of
https://github.com/safishamsi/graphify.git
synced 2026-09-22 13:35:46 +00:00
Fix semantic node preservation on incremental rebuild and detach git hooks
watch.py: filter preserved nodes by ID membership in new AST output instead of file_type — INFERRED/AMBIGUOUS nodes on code files also carry file_type=code and were being wrongly dropped, triggering the to_json safety check refusal. hooks.py: detach post-commit and post-checkout rebuilds with nohup + disown so git commit returns immediately instead of blocking for the full rebuild duration. Rebuild log written to ~/.cache/graphify-rebuild.log. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
be83a8cc55
commit
c8969edd3c
+15
-5
@@ -61,7 +61,13 @@ fi
|
||||
|
||||
""" + _PYTHON_DETECT + """
|
||||
export GRAPHIFY_CHANGED="$CHANGED"
|
||||
$GRAPHIFY_PYTHON -c "
|
||||
|
||||
# Run rebuild detached so git commit returns immediately.
|
||||
# Full repo rebuilds can take hours; blocking the post-commit hook stalls the shell.
|
||||
_GRAPHIFY_LOG="${HOME}/.cache/graphify-rebuild.log"
|
||||
mkdir -p "$(dirname "$_GRAPHIFY_LOG")"
|
||||
echo "[graphify hook] launching background rebuild (log: $_GRAPHIFY_LOG)"
|
||||
nohup $GRAPHIFY_PYTHON -c "
|
||||
import os, sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -79,7 +85,8 @@ try:
|
||||
except Exception as exc:
|
||||
print(f'[graphify hook] Rebuild failed: {exc}')
|
||||
sys.exit(1)
|
||||
"
|
||||
" > "$_GRAPHIFY_LOG" 2>&1 < /dev/null &
|
||||
disown 2>/dev/null || true
|
||||
# graphify-hook-end
|
||||
"""
|
||||
|
||||
@@ -111,8 +118,10 @@ GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
|
||||
[ -f "$GIT_DIR/CHERRY_PICK_HEAD" ] && exit 0
|
||||
|
||||
""" + _PYTHON_DETECT + """
|
||||
echo "[graphify] Branch switched - rebuilding knowledge graph (code files)..."
|
||||
$GRAPHIFY_PYTHON -c "
|
||||
_GRAPHIFY_LOG="${HOME}/.cache/graphify-rebuild.log"
|
||||
mkdir -p "$(dirname "$_GRAPHIFY_LOG")"
|
||||
echo "[graphify] Branch switched - launching background rebuild (log: $_GRAPHIFY_LOG)"
|
||||
nohup $GRAPHIFY_PYTHON -c "
|
||||
from graphify.watch import _rebuild_code
|
||||
from pathlib import Path
|
||||
import sys
|
||||
@@ -121,7 +130,8 @@ try:
|
||||
except Exception as exc:
|
||||
print(f'[graphify] Rebuild failed: {exc}')
|
||||
sys.exit(1)
|
||||
"
|
||||
" > "$_GRAPHIFY_LOG" 2>&1 < /dev/null &
|
||||
disown 2>/dev/null || true
|
||||
# graphify-checkout-hook-end
|
||||
"""
|
||||
|
||||
|
||||
+13
-8
@@ -60,20 +60,25 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False) -> bool:
|
||||
result = extract(code_files, cache_root=watch_root)
|
||||
|
||||
# Preserve semantic nodes/edges from a previous full run.
|
||||
# AST-only rebuild replaces code nodes; doc/paper/image nodes are kept.
|
||||
# AST-only rebuild replaces nodes for changed files; everything else is kept.
|
||||
# Filter by node ID membership in the new AST output, not by file_type —
|
||||
# INFERRED/AMBIGUOUS nodes extracted from code files also carry file_type="code"
|
||||
# and would be wrongly dropped by a file_type-based filter.
|
||||
out = watch_path / "graphify-out"
|
||||
existing_graph = out / "graph.json"
|
||||
if existing_graph.exists():
|
||||
try:
|
||||
existing = json.loads(existing_graph.read_text(encoding="utf-8"))
|
||||
code_ids = {n["id"] for n in existing.get("nodes", []) if n.get("file_type") == "code"}
|
||||
sem_nodes = [n for n in existing.get("nodes", []) if n.get("file_type") != "code"]
|
||||
sem_edges = [e for e in existing.get("links", existing.get("edges", []))
|
||||
if e.get("confidence") in ("INFERRED", "AMBIGUOUS")
|
||||
or (e.get("source") not in code_ids and e.get("target") not in code_ids)]
|
||||
new_ast_ids = {n["id"] for n in result["nodes"]}
|
||||
preserved_nodes = [n for n in existing.get("nodes", []) if n["id"] not in new_ast_ids]
|
||||
all_ids = new_ast_ids | {n["id"] for n in preserved_nodes}
|
||||
preserved_edges = [
|
||||
e for e in existing.get("links", existing.get("edges", []))
|
||||
if e.get("source") in all_ids and e.get("target") in all_ids
|
||||
]
|
||||
result = {
|
||||
"nodes": result["nodes"] + sem_nodes,
|
||||
"edges": result["edges"] + sem_edges,
|
||||
"nodes": result["nodes"] + preserved_nodes,
|
||||
"edges": result["edges"] + preserved_edges,
|
||||
"hyperedges": existing.get("hyperedges", []),
|
||||
"input_tokens": 0,
|
||||
"output_tokens": 0,
|
||||
|
||||
Reference in New Issue
Block a user