fix: connect graphify Obsidian output into a single component#221
Closed
CodeAbra wants to merge 1 commit into
Closed
fix: connect graphify Obsidian output into a single component#221CodeAbra wants to merge 1 commit into
CodeAbra wants to merge 1 commit into
Conversation
Two bugs caused /graphify output to form disconnected components when dropped into an Obsidian vault: 1. `safe_name()` in `export.py` (both `to_obsidian` and `to_canvas`) did not strip trailing `.md`/`.mdx`/`.markdown` from the label before the caller appended the file extension. Nodes labelled after markdown sources (e.g. `CLAUDE.md`, `Guidelines.md`) produced filenames like `CLAUDE.md.md` while their incoming `[[CLAUDE.md]]` wikilinks resolved to the non-existent `CLAUDE.md` file. Every such link broke. 2. `report.py`'s `generate()` emitted community headings as plain prose (`### Community 15 - "Haptics"`) with zero wikilinks. Once the generated `GRAPH_REPORT.md` was copied into a vault as `<proj>-graph-report.md`, the entire community subgraph became unreachable from the report — the whole project cluster split off into a disconnected component. On one real vault (4549 notes across six graphify projects) these two bugs produced 52 connected components with ~21% of nodes stranded in 51 islands. After the fixes, re-running the report generator and regenerating the Obsidian export collapses the graph back to 1 component with 100% of nodes reachable from `master_index.md`. Fixes: - `export.py`: both `safe_name()` helpers now strip trailing Markdown extensions (`.md`, `.mdx`, `.markdown`, case-insensitive) after removing Obsidian-unsafe chars. Idempotent with the existing newline-stripping and sanitization. - `report.py`: added a module-level `_safe_community_name()` that mirrors `export.safe_name` so hub filenames and report links stay in sync. Inserted a `## Community Hubs (Navigation)` bullet list right after `## Summary` that emits `[[_COMMUNITY_<safe>|<label>]]` for every community. Upgraded each `### Community N` heading to embed the same wikilink so either entry point (nav block or community walkthrough) reaches the hub. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
safishamsi
added a commit
that referenced
this pull request
Apr 11, 2026
- build/validate: accept NetworkX <=3.1 "links" key alongside "edges" (#212) - __main__: skip version check during install/uninstall, deduplicate paths (#220) - all file IO: explicit encoding="utf-8" to prevent crashes on Windows CJK locales (#204) - hooks: add newline="\n" on write to prevent CRLF shebang breakage on Windows (#204) - export: strip trailing .md from safe_name so "CLAUDE.md" doesn't become "CLAUDE.md.md" (#221) - report: add Community Hubs navigation block so Obsidian vault stays connected (#221) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Owner
|
Cherry-picked into v0.4.2 (safe_name .md strip + community hub nav block) — thank you! |
joyshmitz
pushed a commit
to joyshmitz/graphify
that referenced
this pull request
Apr 13, 2026
…hamsi#221 into 0.4.2 - build/validate: accept NetworkX <=3.1 "links" key alongside "edges" (safishamsi#212) - __main__: skip version check during install/uninstall, deduplicate paths (safishamsi#220) - all file IO: explicit encoding="utf-8" to prevent crashes on Windows CJK locales (safishamsi#204) - hooks: add newline="\n" on write to prevent CRLF shebang breakage on Windows (safishamsi#204) - export: strip trailing .md from safe_name so "CLAUDE.md" doesn't become "CLAUDE.md.md" (safishamsi#221) - report: add Community Hubs navigation block so Obsidian vault stays connected (safishamsi#221) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
safishamsi
added a commit
that referenced
this pull request
Apr 23, 2026
- build/validate: accept NetworkX <=3.1 "links" key alongside "edges" (#212) - __main__: skip version check during install/uninstall, deduplicate paths (#220) - all file IO: explicit encoding="utf-8" to prevent crashes on Windows CJK locales (#204) - hooks: add newline="\n" on write to prevent CRLF shebang breakage on Windows (#204) - export: strip trailing .md from safe_name so "CLAUDE.md" doesn't become "CLAUDE.md.md" (#221) - report: add Community Hubs navigation block so Obsidian vault stays connected (#221) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
matzls
pushed a commit
to matzls/graphify
that referenced
this pull request
May 10, 2026
…hamsi#221 into 0.4.2 - build/validate: accept NetworkX <=3.1 "links" key alongside "edges" (safishamsi#212) - __main__: skip version check during install/uninstall, deduplicate paths (safishamsi#220) - all file IO: explicit encoding="utf-8" to prevent crashes on Windows CJK locales (safishamsi#204) - hooks: add newline="\n" on write to prevent CRLF shebang breakage on Windows (safishamsi#204) - export: strip trailing .md from safe_name so "CLAUDE.md" doesn't become "CLAUDE.md.md" (safishamsi#221) - report: add Community Hubs navigation block so Obsidian vault stays connected (safishamsi#221) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two long-standing bugs in the Obsidian export cause
/graphifyoutput to form disconnected components when it lands in a vault. On one real-world vault (4549 notes, 6 graphify projects) the bugs produced 52 connected components with ~21% of nodes (945/4549) stranded in 51 islands. After this PR re-runs of the same projects produce 1 component, 100% of nodes reachable from `master_index.md`.Bug 1 — `safe_name()` produces `.md.md` filenames
Both `safe_name()` helpers in `export.py` (inside `to_obsidian` and `to_canvas`) sanitize unsafe chars but do not strip trailing `.md`/`.mdx`/`.markdown`. When a node label happens to be a markdown filename (e.g. `CLAUDE.md`, `Guidelines.md` — which is common when graphify ingests a `CLAUDE.md` project file), the caller then appends `.md` to the result and writes a file named `CLAUDE.md.md`. Meanwhile the wikilinks written inside other notes are `[[CLAUDE.md]]`, which Obsidian resolves to the non-existent `CLAUDE.md` — so every incoming link breaks.
Bug 2 — `GRAPH_REPORT.md` has zero wikilinks to community hubs
`report.py`'s `generate()` emits community headings as plain prose:
```
Community 15 - "Haptics"
Cohesion: 0.25
Nodes (8): PFFTHaptics, ...
```
No wikilinks to the `_COMMUNITY_Haptics.md` hub that `to_obsidian` actually writes. Once `GRAPH_REPORT.md` is copied into a vault as `-graph-report.md`, it becomes a dead-end — the community subgraph it describes is unreachable from it, and the whole project cluster splits off into its own connected component.
Changes
`graphify/export.py`
Both `safe_name()` helpers now strip trailing Markdown extensions after the existing unsafe-char / newline sanitization:
```python
cleaned = re.sub(r"\.(md|mdx|markdown)$", "", cleaned, flags=re.IGNORECASE)
```
Idempotent and safe — normal node labels (`Haptics`, `useFormField()`, `Friends & Badges UI`) pass through unchanged; only labels ending in a markdown extension get their extension stripped.
`graphify/report.py`
Before / after on one real vault
Test plan
Notes
🤖 Generated with Claude Code