Summary
When cluster-only re-clusters, it maps the new communities onto the previous ones
(remap_communities_to_previous, #822/#1027) using the community attribute of the nodes in
the input graph.json (cli.py, previous_node_community = {n["id"]: n["community"] ...}).
In a multi-source pipeline, that input is the fresh output of merge-graphs, which carries
each source's own community ids (overlapping 0..N per source before 0.9.50, offset per
input since 0.9.50, original kept in local_community). It does not carry the previous
merged clustering, which is what .graphify_labels.json / .graphify_labels.json.sig
were written against. The remap therefore aligns new communities to the wrong groups, the
per-cid signature check fails for most communities, and they are renamed by their hub.
Version
Measured on 0.9.46; code path unchanged in 0.9.69 (label-reuse branch identical by diff,
previous_node_community still read from the input file).
Evidence
Pipeline: per-source graphify update → graphify merge-graphs a.json b.json ... --out merged/graphify-out/graph.json → cd merged && graphify cluster-only . (labels file kept).
~15 000 nodes, ~1 700 communities, 5 sources.
| Rebuild after a small commit (a few nodes changed) |
Communities renamed by hub |
| As above, 0.9.46 |
1 130 / 1 709 |
Same, but the previous merged graph.json is saved before merge-graphs and its community value is copied back onto each node (by node id) before cluster-only — 0.9.69, first build after the upgrade |
128 / 1 660 |
The saved merged graph.json from the day before had 660 distinct community values
after merge-graphs (per-source ids) vs 1 709 in the previous merged clustering.
Offline simulation on the same graph (0.9.69 offsets, no workaround): if one early source
gains a single community, all later offsets shift and only 285 / 1 702 labels survive.
Workaround (10 lines)
cp merged/graphify-out/graph.json merged/graphify-out/graph.previous.json
graphify merge-graphs ... --out merged/graphify-out/graph.json
python3 - <<'PY'
import json
prev = {n["id"]: n["community"] for n in json.load(open("merged/graphify-out/graph.previous.json"))["nodes"]
if n.get("community") is not None}
g = json.load(open("merged/graphify-out/graph.json"))
for n in g["nodes"]:
if n["id"] in prev: n["community"] = prev[n["id"]]
else: n.pop("community", None)
json.dump(g, open("merged/graphify-out/graph.json", "w"))
PY
(cd merged && graphify cluster-only .)
Related
#3014 (merge-graphs namespacing — this is the downstream effect on label reuse), #2452 (seed
cluster() with a previous partition), #2298 (exact-membership signature), #3334.
Suggested fix
Either merge-graphs could accept --previous <merged graph.json> and emit the previous merged
community (keeping per-source ids only in local_community), or cluster-only could prefer
graphify-out/graph.json already on disk (the previous run's output) over the input's
community attribute when a labels sidecar exists.
Summary
When
cluster-onlyre-clusters, it maps the new communities onto the previous ones(
remap_communities_to_previous, #822/#1027) using thecommunityattribute of the nodes inthe input
graph.json(cli.py,previous_node_community = {n["id"]: n["community"] ...}).In a multi-source pipeline, that input is the fresh output of
merge-graphs, which carrieseach source's own community ids (overlapping 0..N per source before 0.9.50, offset per
input since 0.9.50, original kept in
local_community). It does not carry the previousmerged clustering, which is what
.graphify_labels.json/.graphify_labels.json.sigwere written against. The remap therefore aligns new communities to the wrong groups, the
per-cid signature check fails for most communities, and they are renamed by their hub.
Version
Measured on 0.9.46; code path unchanged in 0.9.69 (label-reuse branch identical by diff,
previous_node_communitystill read from the input file).Evidence
Pipeline: per-source
graphify update→graphify merge-graphs a.json b.json ... --out merged/graphify-out/graph.json→cd merged && graphify cluster-only .(labels file kept).~15 000 nodes, ~1 700 communities, 5 sources.
graph.jsonis saved beforemerge-graphsand itscommunityvalue is copied back onto each node (by node id) beforecluster-only— 0.9.69, first build after the upgradeThe saved merged
graph.jsonfrom the day before had 660 distinctcommunityvaluesafter
merge-graphs(per-source ids) vs 1 709 in the previous merged clustering.Offline simulation on the same graph (0.9.69 offsets, no workaround): if one early source
gains a single community, all later offsets shift and only 285 / 1 702 labels survive.
Workaround (10 lines)
Related
#3014 (merge-graphs namespacing — this is the downstream effect on label reuse), #2452 (seed
cluster()with a previous partition), #2298 (exact-membership signature), #3334.Suggested fix
Either
merge-graphscould accept--previous <merged graph.json>and emit the previous mergedcommunity(keeping per-source ids only inlocal_community), orcluster-onlycould prefergraphify-out/graph.jsonalready on disk (the previous run's output) over the input'scommunityattribute when a labels sidecar exists.