Skip to content

fix(cli): apply remap_communities_to_previous in cluster-only path - #1028

Merged
safishamsi merged 1 commit into
Graphify-Labs:v8from
bgmbgm94:fix/cluster-only-label-remap
May 26, 2026
Merged

fix(cli): apply remap_communities_to_previous in cluster-only path#1028
safishamsi merged 1 commit into
Graphify-Labs:v8from
bgmbgm94:fix/cluster-only-label-remap

Conversation

@bgmbgm94

@bgmbgm94 bgmbgm94 commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

cluster-only re-runs Leiden clustering and then re-applies the existing
.graphify_labels.json by raw cid index, without invoking the
remap_communities_to_previous safety net that #822 added to the
watch / update paths. As a result, labels become misaligned with the
actual community contents whenever the graph has changed between the
labeling pass and the cluster-only invocation — including the official
update --no-cluster + cluster-only workflow introduced by #822.

Closes #1027.

What changed

Mirror the existing pattern in graphify/watch.py:_rebuild_code:

  • Build previous_node_community from _raw (already loaded a few lines
    above) using each node's community attribute.
  • Call remap_communities_to_previous(communities, previous_node_community)
    immediately after cluster(...) so the existing labels file keeps
    tracking the same conceptual communities by node-overlap, not by raw
    cid index.

Diff is contained to the elif cmd == "cluster-only": branch in
graphify/__main__.py (one import addition, one block right after the
cluster(...) call).

Test

Added tests/test_cli_export.py::test_cluster_only_remaps_labels_to_previous_cids.

The test tags every node with out-of-band sentinel community ids
(4242 / 9999), writes a labels file keyed on those ids, then runs
graphify cluster-only. With the fix, at least one sentinel cid still
appears in the final graph.json community attributes (= remap matched
by node overlap). Without the fix, Leiden renumbers to 0, 1, ... and
the prior labels become orphaned.

Verified locally:

=== WITH fix ===
1 passed in 17.56s

=== WITHOUT fix (stashed source change) ===
FAILED tests/test_cli_export.py::test_cluster_only_remaps_labels_to_previous_cids
1 failed in 17.14s

Full suite passes:

pytest tests/ -q --ignore=tests/bench_extract.py
1317 passed in 58.20s

Open question

The remap_communities_to_previous helper already exists in
graphify.cluster and is used correctly in watch.py:_rebuild_code.
#822's description explicitly mentions:

"stabilize clustering output with deterministic partition input
ordering, seeded Leiden when supported, and overlap-based remapping
of new communities to prior IDs"

— but cluster-only was not updated alongside the watch/update path. The
neighbouring code paths re-applying labels (watch.py:_rebuild_code,
update) all go through remap; cluster-only is the only
re-clustering CLI entry point that omitted it.

Was there a design reason to deliberately keep cluster-only without
the remap (e.g. a use case where label inheritance is undesirable)?
If so, happy to revise this PR — for example, gate the remap behind an
opt-out flag, or expose a --reset-labels switch instead. Otherwise it
looks like a simple miss when #822 was applied and this PR just mirrors
the existing pattern.

Refs

@bgmbgm94

bgmbgm94 commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

After re-reading skill.md more carefully, I want to flag that this PR may not be the right shape — and would love your guidance before you spend review time.

The cluster-only section in skill.md says:

Skip Steps 1–3. Re-run clustering on the existing graph: graphify cluster-only .
Then run Steps 5–9 as normal (label communities, generate viz, benchmark, clean up, report).

And Step 5 itself reads:

Step 5 - Label communities

Read graphify-out/.graphify_analysis.json. For each community key, look at its node labels and write a 2-5 word plain-language name…

That language reads to me as "label from scratch using the new community contents", not "reuse the prior labels file". If that's correct, then the existing behavior of cluster-only reading back the old .graphify_labels.json at all (by raw cid index) is itself the divergence from intent — and the right fix might actually be to drop / ignore the prior labels file on cluster-only rather than to teach it to remap them.

If that interpretation matches what you had in mind, two alternatives look more consistent with skill.md's intent than this PR:

  • B — drop labels on cluster-only: clear or skip .graphify_labels.json in the cluster-only branch, leaving Step 5 to re-label. Smallest fix, matches the doc.
  • C — opt-in remap: default to dropping labels (option B), but expose --keep-labels for users who explicitly want the watch-style overlap remap.

Apologies for not raising this in the original PR description — I was anchoring too hard on "watch already does this, mirror it." Could you let me know which direction you'd prefer?

  1. Land A as-is (mirror watch — overlap remap by default on cluster-only)
  2. Replace A with B (drop labels — closest to skill.md Step 5 intent)
  3. Replace A with C (default-drop + --keep-labels opt-in)
  4. Something else entirely

I'm happy to amend this PR in whichever direction you point at — or to close it and open a fresh one if you'd rather start from a clean slate.

cluster-only re-runs Leiden clustering and then re-applies the existing
.graphify_labels.json by raw cid index, which causes labels to attach to
clusters whose members are unrelated to the label's original meaning
whenever the graph has changed between labeling and re-clustering.

Mirror the safety net already present in watch.py:_rebuild_code added in
Graphify-Labs#822 for the watch/update paths.

Adds a regression test that fails without the fix (label cids become
orphaned from graph.json community attributes after re-clustering).

Refs: Graphify-Labs#1027
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bgmbgm94
bgmbgm94 force-pushed the fix/cluster-only-label-remap branch from 8762a33 to bf43efb Compare May 26, 2026 13:10
@safishamsi
safishamsi merged commit 9abaa77 into Graphify-Labs:v8 May 26, 2026
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.

cluster-only skips overlap-based community remapping, so labels become misaligned after re-clustering

2 participants