diff --git a/graphify/__main__.py b/graphify/__main__.py index 3472b707..e2b3d9e6 100644 --- a/graphify/__main__.py +++ b/graphify/__main__.py @@ -1294,7 +1294,7 @@ def main() -> None: from graphify.cluster import cluster, score_all from graphify.analyze import god_nodes, surprising_connections, suggest_questions from graphify.report import generate - from graphify.export import to_json + from graphify.export import to_json, to_html print("Loading existing graph...") _raw = json.loads(graph_json.read_text(encoding="utf-8")) G = build_from_json(_raw) @@ -1312,7 +1312,8 @@ def main() -> None: out = watch_path / "graphify-out" (out / "GRAPH_REPORT.md").write_text(report, encoding="utf-8") to_json(G, communities, str(out / "graph.json")) - print(f"Done — {len(communities)} communities. GRAPH_REPORT.md and graph.json updated.") + to_html(G, communities, str(out / "graph.html"), community_labels=labels or None) + print(f"Done — {len(communities)} communities. GRAPH_REPORT.md, graph.json and graph.html updated.") elif cmd == "update": watch_path = Path(sys.argv[2]) if len(sys.argv) > 2 else Path(".") diff --git a/graphify/extract.py b/graphify/extract.py index 717026ab..cac6bf7e 100644 --- a/graphify/extract.py +++ b/graphify/extract.py @@ -147,7 +147,8 @@ def _import_js(node, source: bytes, file_nid: str, stem: str, edges: list, str_p break if raw.startswith("."): # Relative import - resolve to full path so IDs match file node IDs - resolved = Path(str_path).parent / raw + # normpath removes ".." segments so the ID matches the target file's own node ID + resolved = Path(os.path.normpath(Path(str_path).parent / raw)) # TypeScript ESM: imports written as .js but actual file is .ts/.tsx if resolved.suffix == ".js": resolved = resolved.with_suffix(".ts") diff --git a/graphify/watch.py b/graphify/watch.py index 6a354c60..e1d07d1b 100644 --- a/graphify/watch.py +++ b/graphify/watch.py @@ -25,7 +25,7 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False) -> bool: from graphify.cluster import cluster, score_all from graphify.analyze import god_nodes, surprising_connections, suggest_questions from graphify.report import generate - from graphify.export import to_json + from graphify.export import to_json, to_html detected = detect(watch_path, follow_symlinks=follow_symlinks) code_files = [Path(f) for f in detected['files']['code']] @@ -78,6 +78,7 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False) -> bool: {"input": 0, "output": 0}, str(watch_path), suggested_questions=questions) (out / "GRAPH_REPORT.md").write_text(report, encoding="utf-8") to_json(G, communities, str(out / "graph.json")) + to_html(G, communities, str(out / "graph.html"), community_labels=labels or None) # clear stale needs_update flag if present flag = out / "needs_update" @@ -86,7 +87,7 @@ def _rebuild_code(watch_path: Path, *, follow_symlinks: bool = False) -> bool: print(f"[graphify watch] Rebuilt: {G.number_of_nodes()} nodes, " f"{G.number_of_edges()} edges, {len(communities)} communities") - print(f"[graphify watch] graph.json and GRAPH_REPORT.md updated in {out}") + print(f"[graphify watch] graph.json, graph.html and GRAPH_REPORT.md updated in {out}") return True except Exception as exc: