diff --git a/graphify/__main__.py b/graphify/__main__.py index e5ac46c46..3a6fcd2c6 100644 --- a/graphify/__main__.py +++ b/graphify/__main__.py @@ -191,6 +191,7 @@ This project has a graphify knowledge graph at graphify-out/. Rules: - Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure - If graphify-out/wiki/index.md exists, navigate it instead of reading raw files +- For cross-module "how does X relate to Y" questions, prefer `graphify query ""`, `graphify path "" ""`, or `graphify explain ""` over grep — these traverse the graph's EXTRACTED + INFERRED edges instead of scanning files - After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost) """ @@ -206,6 +207,7 @@ This project has a graphify knowledge graph at graphify-out/. Rules: - Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure - If graphify-out/wiki/index.md exists, navigate it instead of reading raw files +- For cross-module "how does X relate to Y" questions, prefer `graphify query ""`, `graphify path "" ""`, or `graphify explain ""` over grep — these traverse the graph's EXTRACTED + INFERRED edges instead of scanning files - After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost) """ @@ -219,6 +221,7 @@ This project has a graphify knowledge graph at graphify-out/. Rules: - Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure - If graphify-out/wiki/index.md exists, navigate it instead of reading raw files +- For cross-module "how does X relate to Y" questions, prefer `graphify query ""`, `graphify path "" ""`, or `graphify explain ""` over grep — these traverse the graph's EXTRACTED + INFERRED edges instead of scanning files - After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost) """ @@ -421,6 +424,7 @@ Rules: - Before answering architecture or codebase questions, read graphify-out/GRAPH_REPORT.md for god nodes and community structure - If graphify-out/wiki/index.md exists, navigate it instead of reading raw files - If the graphify MCP server is active, utilize tools like `query_graph`, `get_node`, and `shortest_path` for precise architecture navigation instead of falling back to `grep` +- If the MCP server is not active, the CLI equivalents are `graphify query ""`, `graphify path "" ""`, and `graphify explain ""` — prefer these over grep for cross-module questions - After modifying code files in this session, run `graphify update .` to keep the graph current (AST-only, no API cost) """ diff --git a/graphify/report.py b/graphify/report.py index 82657e1bb..103765dcf 100644 --- a/graphify/report.py +++ b/graphify/report.py @@ -49,10 +49,14 @@ def generate( "- Verdict: corpus is large enough that graph structure adds value.", ] + from .analyze import _is_file_node as _ifn + non_empty = {cid: nodes for cid, nodes in communities.items() + if any(not _ifn(G, n) for n in nodes)} + lines += [ "", "## Summary", - f"- {G.number_of_nodes()} nodes · {G.number_of_edges()} edges · {len(communities)} communities detected", + f"- {G.number_of_nodes()} nodes · {G.number_of_edges()} edges · {len(non_empty)} communities detected", f"- Extraction: {ext_pct}% EXTRACTED · {inf_pct}% INFERRED · {amb_pct}% AMBIGUOUS" + (f" · INFERRED: {len(inf_edges)} edges (avg confidence: {inf_avg})" if inf_avg is not None else ""), f"- Token cost: {token_cost.get('input', 0):,} input · {token_cost.get('output', 0):,} output", @@ -60,9 +64,9 @@ def generate( # Community hub navigation - links to _COMMUNITY_*.md files in the Obsidian vault. # Without these, GRAPH_REPORT.md is a dead-end and the vault splits into disconnected components. - if communities: + if non_empty: lines += ["", "## Community Hubs (Navigation)"] - for cid in communities: + for cid in non_empty: label = community_labels.get(cid, f"Community {cid}") safe = _safe_community_name(label) lines.append(f"- [[_COMMUNITY_{safe}|{label}]]") @@ -105,7 +109,6 @@ def generate( lines.append(f"- **{h.get('label', h.get('id', ''))}** — {node_labels} [{conf_tag}]") lines += ["", "## Communities"] - from .analyze import _is_file_node as _ifn for cid, nodes in communities.items(): label = community_labels.get(cid, f"Community {cid}") score = cohesion_scores.get(cid, 0.0) @@ -141,7 +144,8 @@ def generate( if G.degree(n) <= 1 and not _is_file_node(G, n) and not _is_concept_node(G, n) ] thin_communities = { - cid: nodes for cid, nodes in communities.items() if len(nodes) < 3 + cid: nodes for cid, nodes in communities.items() + if 0 < sum(1 for n in nodes if not _is_file_node(G, n)) < 3 } gap_count = len(isolated) + len(thin_communities) diff --git a/pyproject.toml b/pyproject.toml index 2eece2a6b..0e6c8b6ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "graphifyy" -version = "0.4.24" +version = "0.4.25" description = "AI coding assistant skill (Claude Code, Codex, OpenCode, Cursor, Gemini CLI, Aider, OpenClaw, Factory Droid, Trae, Hermes, Kiro, Google Antigravity) - turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph" readme = "README.md" license = { file = "LICENSE" }