Version: graphifyy 0.9.73 (also seen on 0.9.16)
What happens
graphify label . and graphify cluster-only . reload graph.json with
build_from_json(_raw, directed=_directed) (cli.py, around line 2101), which creates
a simple nx.Graph() (build.py, around line 1031). A simple graph keeps one edge
per node pair, so when graph.json contains two edges between the same pair
(for example an imports edge and a calls edge between the same two nodes, or
edges added by an external tool), all but one are lost when the command writes
graph.json back. Nothing is printed about it.
This looks like the same root cause that #2074 fixed for graphify path (loading
with "multigraph": True so parallel links "survive load instead of being silently
collapsed last-writer-wins"), but the cluster-only / label path still loads a
simple graph and then writes it back to disk, so the loss is persistent.
Minimal reproduction (0.9.73)
mkdir -p repro/graphify-out && cd repro
cat > graphify-out/graph.json <<'JSON'
{"directed": false, "multigraph": false, "graph": {}, "nodes": [
{"id": "a", "label": "a", "file_type": "code", "source_file": "a.py"},
{"id": "b", "label": "b", "file_type": "code", "source_file": "a.py"},
{"id": "c", "label": "c", "file_type": "code", "source_file": "a.py"}],
"links": [
{"source": "a", "target": "b", "relation": "imports", "confidence": "EXTRACTED", "source_file": "a.py"},
{"source": "a", "target": "b", "relation": "calls", "confidence": "EXTRACTED", "source_file": "a.py"},
{"source": "b", "target": "c", "relation": "calls", "confidence": "EXTRACTED", "source_file": "a.py"}]}
JSON
uvx --from graphifyy==0.9.73 graphify cluster-only .
Output says Graph: 3 nodes, 2 edges. Before: 3 links. After: 2 links —
(a, b, calls) is gone from graph.json.
Measured on a real graph (~45,600 nodes, 0.9.16, label): 69,784 edges before,
69,462 after. 322 edges lost, none with a missing endpoint, and every one of them
was a second edge on a node pair that stayed connected by another edge.
Expected
Re-clustering / labeling should not change the edge set. Either keep parallel
edges (load into a MultiGraph as #2074 does, or cluster on a simple projection
and write the original link list back), or at least warn with the number of edges
that will be collapsed.
Workaround we use: re-adding the extra edges after every label run.
Side note (separate, minor): running the command via uvx --from graphifyy==<newer>
also rewrote the user's installed Claude skill (~/.claude/skills/graphify/SKILL.md
and references/) to the newer packaged version. SKILL.md got a .bak, but
references/ did not. It was unexpected for a cluster-only run. Happy to open
that as its own issue if useful.
Version: graphifyy 0.9.73 (also seen on 0.9.16)
What happens
graphify label .andgraphify cluster-only .reloadgraph.jsonwithbuild_from_json(_raw, directed=_directed)(cli.py, around line 2101), which createsa simple
nx.Graph()(build.py, around line 1031). A simple graph keeps one edgeper node pair, so when
graph.jsoncontains two edges between the same pair(for example an
importsedge and acallsedge between the same two nodes, oredges added by an external tool), all but one are lost when the command writes
graph.jsonback. Nothing is printed about it.This looks like the same root cause that #2074 fixed for
graphify path(loadingwith
"multigraph": Trueso parallel links "survive load instead of being silentlycollapsed last-writer-wins"), but the
cluster-only/labelpath still loads asimple graph and then writes it back to disk, so the loss is persistent.
Minimal reproduction (0.9.73)
Output says
Graph: 3 nodes, 2 edges. Before: 3 links. After: 2 links —(a, b, calls)is gone fromgraph.json.Measured on a real graph (~45,600 nodes, 0.9.16,
label): 69,784 edges before,69,462 after. 322 edges lost, none with a missing endpoint, and every one of them
was a second edge on a node pair that stayed connected by another edge.
Expected
Re-clustering / labeling should not change the edge set. Either keep parallel
edges (load into a
MultiGraphas #2074 does, or cluster on a simple projectionand write the original link list back), or at least warn with the number of edges
that will be collapsed.
Workaround we use: re-adding the extra edges after every
labelrun.Side note (separate, minor): running the command via
uvx --from graphifyy==<newer>also rewrote the user's installed Claude skill (
~/.claude/skills/graphify/SKILL.mdand
references/) to the newer packaged version.SKILL.mdgot a.bak, butreferences/did not. It was unexpected for acluster-onlyrun. Happy to openthat as its own issue if useful.