Skip to content

Add hierarchical clustering: L0 topics → L1 communities → L2 nodes#297

Open
rongmiao926-hub wants to merge 61 commits into
Graphify-Labs:v4from
rongmiao926-hub:v4
Open

Add hierarchical clustering: L0 topics → L1 communities → L2 nodes#297
rongmiao926-hub wants to merge 61 commits into
Graphify-Labs:v4from
rongmiao926-hub:v4

Conversation

@rongmiao926-hub

Copy link
Copy Markdown

Summary

  • Adds two-pass Leiden hierarchical clustering to organize flat communities into a topic → community → node hierarchy
  • First pass (unchanged): standard Leiden → L1 communities
  • Second pass (new): contracts communities into super-nodes, runs Leiden on contracted graph → L0 topics
  • Fully backward compatible: existing cluster() unchanged, hierarchical_cluster() is additive

Changes

  • cluster.py: HierarchicalCommunities dataclass + hierarchical_cluster() function + _build_contracted_graph()
  • export.py: to_json persists hierarchy; to_html adds two-level collapsible legend with topic filtering; to_obsidian generates _TOPIC_*.md overview notes
  • serve.py: New get_topics and drill_down MCP tools; graph_stats shows topic count; node info includes topic
  • report.py: "Topic Overview" section with ASCII tree view; community headers show parent topic
  • analyze.py: cross_topic question type for edges spanning topic boundaries
  • skill.md: Pipeline updated to use hierarchical_cluster(G) with L0 topic labeling step
  • README.md: Updated clustering description

Backward compatibility

  • All 7 existing MCP tools behave identically
  • cluster() function signature and return value unchanged
  • New get_topics and drill_down tools are pure additions
  • If < 4 L1 communities exist, all are grouped into a single topic (graceful degradation)

Test plan

  • Tested on synthetic 24-node graph: 2 topics, 4 communities correctly produced
  • Full pipeline test: report, JSON, HTML, cross-topic questions all verified
  • Existing behavior preserved when hierarchy has only 1 topic

🤖 Generated with Claude Code

Minidoracat and others added 30 commits April 8, 2026 19:39
* fix: git hooks fail when graphify is installed via pipx

When installed via pipx, the graphify module is only available in
pipx's isolated venv, not the system python3. The git hooks
(post-commit, post-checkout) hardcoded `python3` which cannot import
graphify in this case.

Detect the correct Python interpreter from the graphify binary's
shebang line, matching the approach already used in skill.md Step 1.
Falls back to python3 for system installs.

* fix: handle env-style shebangs and improve interpreter detection

- Use POSIX `command -v` instead of non-standard `which`
- Parse `#!/usr/bin/env python3` shebangs correctly (previous
  `tr -d ' '` would produce `/usr/bin/envpython3`)
- Add import validation fallback to python3 if resolved interpreter
  cannot import graphify
… buffer

* fix: suppress graspologic ANSI output that breaks PowerShell scrolling

graspologic's leiden() emits ANSI escape sequences (progress bars,
colored warnings) that corrupt PowerShell 5.1's scroll buffer on
Windows, disabling vertical scrolling. Redirect stdout/stderr to
StringIO during leiden() calls to prevent any escape codes from
reaching the terminal.

Add 2 tests verifying cluster() produces no stdout/stderr output.

Fixes Graphify-Labs#19

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add PowerShell troubleshooting section to Windows skill

Document the PowerShell 5.1 scrolling issue and provide 4
workarounds: upgrade graphify, use Windows Terminal, reset
terminal, or uninstall graspologic to use Louvain fallback.

Fixes Graphify-Labs#19

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Register 'trae' and 'trae-cn' in _PLATFORM_CONFIG (skill-trae.md,
  ~/.trae/skills/ and ~/.trae-cn/skills/, claude_md=False)
- Add CLI subcommands: graphify trae install/uninstall,
  graphify trae-cn install/uninstall (routes to _agents_install/uninstall)
- Update help text with new platform entries
- Create skill-trae.md (Agent-tool based extraction, AGENTS.md integration,
  no PreToolUse hook support per Trae limitations)
- Update README.md and README.zh-CN.md with Trae platform docs

Co-authored-by: lijinshuan <lijinshuan@bytedance.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…utput

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y-Labs#109: extension drift, click detection, skill coverage, .graphify_python persistence

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ify-Labs#126)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e relations in innerHTML (#sec)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y-Labs#127)

Tree-sitter resolves call targets directly from source — marking them
INFERRED was incorrect. Cross-file class-level uses edges remain INFERRED.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…AST calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Windows git hooks (Graphify-Labs#140)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hify-Labs#105)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
safishamsi and others added 28 commits April 9, 2026 22:45
…he, graphifyignore parent discovery, MCP fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cription

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…port

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nstall

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…attribute

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r prompt itself

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ort.py, bound collision loop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…aceholder

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
 Graphify-Labs#195: skill.md requires general-purpose subagent type for extraction dispatch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…phify-Labs#222 and bump to 0.4.2

- extract.py: use str(path) for node IDs to prevent same-basename collision (Graphify-Labs#211)
- build.py: normalize from/to edge keys before KeyError (Graphify-Labs#216)
- export.py: guard ZeroDivisionError when graph has no edges (Graphify-Labs#217)
- hooks.py: remove stale CODE_EXTS filter, rebuild on any changed file (Graphify-Labs#222)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, Graphify-Labs#221 into 0.4.2

- build/validate: accept NetworkX <=3.1 "links" key alongside "edges" (Graphify-Labs#212)
- __main__: skip version check during install/uninstall, deduplicate paths (Graphify-Labs#220)
- all file IO: explicit encoding="utf-8" to prevent crashes on Windows CJK locales (Graphify-Labs#204)
- hooks: add newline="\n" on write to prevent CRLF shebang breakage on Windows (Graphify-Labs#204)
- export: strip trailing .md from safe_name so "CLAUDE.md" doesn't become "CLAUDE.md.md" (Graphify-Labs#221)
- report: add Community Hubs navigation block so Obsidian vault stays connected (Graphify-Labs#221)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…phify-Labs#226, Graphify-Labs#254 and bump to 0.4.3

- extract.py: resolve relative JS/TS imports to full-path IDs (fixes 0 import edges on TS codebases) (Graphify-Labs#256)
- extract.py: resolve relative Python imports to full-path IDs (Graphify-Labs#256)
- watch.py: merge fresh AST with existing semantic nodes instead of overwriting (Graphify-Labs#253)
- hooks.py: add python fallback after python3 for Windows; exit 0 if neither found (Graphify-Labs#244)
- analyze.py: guard stale _src/_tgt hints with node membership check (Graphify-Labs#226)
- detect.py + extract.py: add .vue and .svelte to CODE_EXTENSIONS and _DISPATCH (Graphify-Labs#254)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two-pass Leiden: first pass produces L1 communities (unchanged from
existing behavior), second pass contracts communities into super-nodes
and runs Leiden again to produce L0 topics that group related
communities into broader themes.

Changes:
- cluster.py: HierarchicalCommunities dataclass + hierarchical_cluster()
- export.py: hierarchy in graph.json, two-level HTML legend, _TOPIC_*.md in Obsidian
- serve.py: get_topics and drill_down MCP tools, topic info in node/stats output
- report.py: Topic Overview section with tree view, topic labels on communities
- analyze.py: cross_topic question type in suggest_questions
- skill.md: Steps 4/5/6 updated for hierarchical pipeline
- README.md: updated clustering description

Fully backward compatible: cluster() signature unchanged, all existing
MCP tools work as before, hierarchy is purely additive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ljinshuan

Copy link
Copy Markdown
Contributor

the same as #264

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants