Fix 6 bugs: hook exit code, token budget, file node detection, duplicate function, atomic cache writes, deleted file tracking

This commit is contained in:
Safi
2026-04-06 22:23:55 +01:00
parent 9eda1558c2
commit 148e247662
6 changed files with 27 additions and 13 deletions
+8 -4
View File
@@ -16,12 +16,16 @@ def _is_file_node(G: nx.Graph, node_id: str) -> bool:
These are synthetic nodes created by the AST extractor and should be excluded
from god nodes, surprising connections, and knowledge gap reporting.
"""
label = G.nodes[node_id].get("label", "")
attrs = G.nodes[node_id]
label = attrs.get("label", "")
if not label:
return False
# File-level hub: label is a filename with a code extension
if label.split(".")[-1] in ("py", "ts", "js", "go", "rs", "java", "rb", "cpp", "c", "h"):
return True
# File-level hub: label matches the actual source filename (not just any label ending in .py)
source_file = attrs.get("source_file", "")
if source_file:
from pathlib import Path as _Path
if label == _Path(source_file).name:
return True
# Method stub: AST extractor labels methods as '.method_name()'
if label.startswith(".") and label.endswith("()"):
return True
+8 -1
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
import hashlib
import json
import os
from pathlib import Path
@@ -46,7 +47,13 @@ def save_cached(path: Path, result: dict, root: Path = Path(".")) -> None:
"""
h = file_hash(path)
entry = cache_dir(root) / f"{h}.json"
entry.write_text(json.dumps(result))
tmp = entry.with_suffix(".tmp")
try:
tmp.write_text(json.dumps(result))
os.replace(tmp, entry)
except Exception:
tmp.unlink(missing_ok=True)
raise
def cached_files(root: Path = Path(".")) -> set[str]:
+5
View File
@@ -266,9 +266,14 @@ def detect_incremental(root: Path, manifest_path: str = _MANIFEST_PATH) -> dict:
else:
unchanged_files[ftype].append(f)
# Files in manifest that no longer exist - their cached nodes are now ghost nodes
current_files = {f for flist in full["files"].values() for f in flist}
deleted_files = [f for f in manifest if f not in current_files]
new_total = sum(len(v) for v in new_files.values())
full["incremental"] = True
full["new_files"] = new_files
full["unchanged_files"] = unchanged_files
full["new_total"] = new_total
full["deleted_files"] = deleted_files
return full
+1 -5
View File
@@ -8,6 +8,7 @@ from pathlib import Path
import networkx as nx
from networkx.readwrite import json_graph
from graphify.security import sanitize_label
from graphify.analyze import _node_community_map
COMMUNITY_COLORS = [
"#4E79A7", "#F28E2B", "#E15759", "#76B7B2", "#59A14F",
@@ -17,11 +18,6 @@ COMMUNITY_COLORS = [
MAX_NODES_FOR_VIZ = 5_000
def _node_community_map(communities: dict[int, list[str]]) -> dict[str, int]:
"""Invert communities dict: node_id -> community_id."""
return {n: cid for cid, nodes in communities.items() for n in nodes}
def _html_styles() -> str:
return """<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
+3 -1
View File
@@ -40,7 +40,7 @@ try:
_rebuild_code(Path('.'))
except Exception as exc:
print(f'[graphify hook] Rebuild failed: {exc}')
sys.exit(0)
sys.exit(1)
"
"""
@@ -69,10 +69,12 @@ echo "[graphify] Branch switched - rebuilding knowledge graph (code files)..."
python3 -c "
from graphify.watch import _rebuild_code
from pathlib import Path
import sys
try:
_rebuild_code(Path('.'))
except Exception as exc:
print(f'[graphify] Rebuild failed: {exc}')
sys.exit(1)
"
"""
+2 -2
View File
@@ -75,8 +75,8 @@ def _dfs(G: nx.Graph, start_nodes: list[str], depth: int) -> tuple[set[str], lis
def _subgraph_to_text(G: nx.Graph, nodes: set[str], edges: list[tuple], token_budget: int = 2000) -> str:
"""Render subgraph as text, cutting at token_budget (approx 4 chars/token)."""
char_budget = token_budget * 4
"""Render subgraph as text, cutting at token_budget (approx 3 chars/token)."""
char_budget = token_budget * 3
lines = []
for nid in sorted(nodes, key=lambda n: G.degree(n), reverse=True):
d = G.nodes[nid]