Problem
The graphify skill's Step 5 has Claude write semantic community labels to graphify-out/.graphify_labels.json (e.g. "Attention Mechanism", "Training Pipeline" in the Karpathy worked example). Step 6 reads that file to render obsidian/, wiki/, graph.html, and GRAPH_REPORT.md with the human-readable names.
Step 9 (cleanup) then deletes .graphify_labels.json.
This means labels live ONLY inside the rendered output files. Every subsequent operation that re-runs clustering or regenerates outputs from graph.json directly — --update, --cluster-only, the graphify cluster-only CLI subcommand, or any user-side maintenance script that calls cluster() + to_obsidian() / to_wiki() / to_html() — produces output without the labels. They become Community 0, Community 1, …, Community N, even though graph.json still has the same well-clustered partition.
Symptom: wiki/index.md becomes a sorted list of [[Community 0]] — 178 nodes ... [[Community 156]] — 1 nodes, which is unbrowsable.
Repro
- Build a graph:
/graphify <path> → labels written, outputs use them.
- Make any change that triggers a re-cluster, e.g.
/graphify <path> --cluster-only or /graphify <path> --update with new files.
- Open
graphify-out/wiki/index.md — community names are now Community 0..N.
Real-world impact
In a 1900-node business corpus that's been through several --update + dedup cycles, all 157 communities ended up as numeric IDs. Top 15 cover 84% of the graph, but they're listed as [[Community 0]] — 178 nodes etc. The wiki and obsidian outputs become navigation-useless until labels are manually re-applied. (My corpus shipped with 5,234 obsidian notes + 1,381 wiki articles indexed only by community number.)
Proposed fixes (any one of these would help)
- Persist labels inside
graph.json — store community labels as a top-level community_labels key (alongside directed, nodes, links). Then they survive every regeneration that loads the graph.
- Don't delete
.graphify_labels.json in cleanup — drop that one line from the cleanup rm. The file is small and idempotent.
- Persist a separate non-dotfile — write
graphify-out/community_labels.json (no leading dot) alongside the dotfile. Cleanup leaves it. The skill / cluster-only flow reads from it on the next run if .graphify_labels.json is missing.
- Add a label-carry-forward step to
cluster() — after re-partitioning, match new communities to old by node-membership overlap and propagate the old label to the most-overlapping new community. Avoids having to re-run Claude's labelling step every time.
Workaround in the meantime
I built a local helper that does (3) + (4): persistent community_labels.json + best-match carry-forward across reclusters. Linked from my CLAUDE.md gotcha #12 if useful as reference: https://github.com/safishamsi/graphify/issues (this issue).
Related: #595 covers other hygiene primitives but doesn't address label persistence specifically. #590 covers the directedness flip in cluster-only which is a sibling regression in the same code path.
Problem
The
graphifyskill's Step 5 has Claude write semantic community labels tographify-out/.graphify_labels.json(e.g."Attention Mechanism","Training Pipeline"in the Karpathy worked example). Step 6 reads that file to renderobsidian/,wiki/,graph.html, andGRAPH_REPORT.mdwith the human-readable names.Step 9 (cleanup) then deletes
.graphify_labels.json.This means labels live ONLY inside the rendered output files. Every subsequent operation that re-runs clustering or regenerates outputs from
graph.jsondirectly —--update,--cluster-only, thegraphify cluster-onlyCLI subcommand, or any user-side maintenance script that callscluster()+to_obsidian()/to_wiki()/to_html()— produces output without the labels. They becomeCommunity 0,Community 1, …,Community N, even though graph.json still has the same well-clustered partition.Symptom:
wiki/index.mdbecomes a sorted list of[[Community 0]] — 178 nodes...[[Community 156]] — 1 nodes, which is unbrowsable.Repro
/graphify <path>→ labels written, outputs use them./graphify <path> --cluster-onlyor/graphify <path> --updatewith new files.graphify-out/wiki/index.md— community names are nowCommunity 0..N.Real-world impact
In a 1900-node business corpus that's been through several
--update+ dedup cycles, all 157 communities ended up as numeric IDs. Top 15 cover 84% of the graph, but they're listed as[[Community 0]] — 178 nodesetc. The wiki and obsidian outputs become navigation-useless until labels are manually re-applied. (My corpus shipped with 5,234 obsidian notes + 1,381 wiki articles indexed only by community number.)Proposed fixes (any one of these would help)
graph.json— store community labels as a top-levelcommunity_labelskey (alongsidedirected,nodes,links). Then they survive every regeneration that loads the graph..graphify_labels.jsonin cleanup — drop that one line from the cleanuprm. The file is small and idempotent.graphify-out/community_labels.json(no leading dot) alongside the dotfile. Cleanup leaves it. The skill /cluster-onlyflow reads from it on the next run if.graphify_labels.jsonis missing.cluster()— after re-partitioning, match new communities to old by node-membership overlap and propagate the old label to the most-overlapping new community. Avoids having to re-run Claude's labelling step every time.Workaround in the meantime
I built a local helper that does (3) + (4): persistent
community_labels.json+ best-match carry-forward across reclusters. Linked from myCLAUDE.mdgotcha #12 if useful as reference: https://github.com/safishamsi/graphify/issues (this issue).Related: #595 covers other hygiene primitives but doesn't address label persistence specifically. #590 covers the directedness flip in
cluster-onlywhich is a sibling regression in the same code path.