Fix hook rebuild losing community labels; fix gemini platform install (#705, #706)

This commit is contained in:
Safi
2026-05-04 18:20:16 +01:00
parent 682d124618
commit b3c99ec0ed
2 changed files with 31 additions and 6 deletions
+2
View File
@@ -7,6 +7,8 @@ Full release notes with details on each version: [GitHub Releases](https://githu
- Feat: `graphify extract` now runs incrementally - auto-detects prior `manifest.json` and re-extracts only changed/new files; semantic results cached by content hash so unchanged docs cost zero LLM tokens on repeat runs (#698)
- Feat: Entity deduplication pipeline runs on every build - entropy gate + MinHash/LSH blocking + Jaro-Winkler verification + same-community boost collapses near-duplicate entities (typos, spacing, plurals) before clustering
- Feat: `--dedup-llm` flag for `graphify extract` - optional LLM tiebreaker for ambiguous entity pairs (~$0.01 for 10k-node graphs), off by default
- Fix: `graphify hook install` rebuild now preserves human-readable community labels from `.graphify_labels.json` instead of resetting to generic "Community N" names on every commit (#705)
- Fix: `graphify install --platform gemini` now works correctly (#706)
- Deps: `datasketch` and `rapidfuzz` added as base dependencies
## 0.7.4 (2026-05-04)
+29 -6
View File
@@ -9,6 +9,16 @@ from pathlib import Path
_GRAPHIFY_OUT = os.environ.get("GRAPHIFY_OUT", "graphify-out")
def _git_head() -> str | None:
"""Return current git HEAD commit hash, or None outside a repo."""
import subprocess as _sp
try:
r = _sp.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True, timeout=3)
return r.stdout.strip() if r.returncode == 0 else None
except Exception:
return None
from graphify.detect import CODE_EXTENSIONS, DOC_EXTENSIONS, PAPER_EXTENSIONS, IMAGE_EXTENSIONS
_WATCHED_EXTENSIONS = CODE_EXTENSIONS | DOC_EXTENSIONS | PAPER_EXTENSIONS | IMAGE_EXTENSIONS
@@ -64,6 +74,7 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False, force: boo
print("[graphify watch] No code files found - nothing to rebuild.")
return False
commit = _git_head()
result = extract(code_files, cache_root=watch_root)
# Preserve semantic nodes/edges from a previous full run.
@@ -106,13 +117,22 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False, force: boo
cohesion = score_all(G, communities)
gods = god_nodes(G)
surprises = surprising_connections(G, communities)
labels = {cid: "Community " + str(cid) for cid in communities}
labels_file = out / ".graphify_labels.json"
try:
raw = json.loads(labels_file.read_text(encoding="utf-8")) if labels_file.exists() else {}
labels = {int(k): v for k, v in raw.items() if int(k) in communities}
except Exception:
raw = {}
labels = {}
for cid in communities:
if cid not in labels:
labels[cid] = "Community " + str(cid)
questions = suggest_questions(G, communities, labels)
out.mkdir(exist_ok=True)
(out / ".graphify_root").write_text(str(watch_root), encoding="utf-8")
json_written = to_json(G, communities, str(out / "graph.json"), force=force)
json_written = to_json(G, communities, str(out / "graph.json"), force=force, built_at_commit=commit)
if not json_written:
return False
@@ -123,7 +143,8 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False, force: boo
pass
report = generate(G, communities, cohesion, labels, gods, surprises, detection,
{"input": 0, "output": 0}, report_root, suggested_questions=questions)
{"input": 0, "output": 0}, report_root, suggested_questions=questions,
built_at_commit=commit)
(out / "GRAPH_REPORT.md").write_text(report, encoding="utf-8")
# to_html raises ValueError for graphs > MAX_NODES_FOR_VIZ (5000).
@@ -241,10 +262,12 @@ def watch(watch_path: Path, debounce: float = 3.0) -> None:
batch = list(changed)
changed.clear()
print(f"\n[graphify watch] {len(batch)} file(s) changed")
if _has_non_code(batch):
_notify_only(watch_path)
else:
has_non_code = _has_non_code(batch)
has_code = any(p.suffix.lower() in _CODE_EXTENSIONS for p in batch)
if has_code:
_rebuild_code(watch_path)
if has_non_code:
_notify_only(watch_path)
except KeyboardInterrupt:
print("\n[graphify watch] Stopped.")
finally: