What's happening
Running graphify cluster-only . on a directed graph (directed: true in graph.json) silently re-saves it as undirected (directed: false) and canonicalises edge source/target order to NetworkX's internal storage order, scrambling the original directions.
Reproduction (graphify v0.4.23, macOS, Python 3.14)
# Start with a directed graph.json
python3 -c "
import json
data = json.loads(open('graphify-out/graph.json').read())
data['directed'] = True
open('graphify-out/graph.json','w').write(json.dumps(data))
print('directed:', json.loads(open('graphify-out/graph.json').read())['directed'])
"
# → directed: True
graphify cluster-only .
# → Done — N communities. GRAPH_REPORT.md, graph.json and graph.html updated.
python3 -c "
import json
print('directed:', json.loads(open('graphify-out/graph.json').read())['directed'])
"
# → directed: False
The Python --cluster-only flow used in the skill doesn't have this issue — node_link_graph reads the directed flag, returns a DiGraph, and to_json/node_link_data preserves it. It looks like the CLI subcommand is loading or saving without preserving the directedness.
Why it matters
CLAUDE.md / skill.md make --directed a contract: "switching to undirected requires a full rebuild, not --update". Users who run graphify cluster-only . after a directed --update discover the contract was broken silently. Edge directions can't be recovered from the resulting undirected graph because NetworkX canonicalises them on export.
Recovery requires rebuilding from semantic cache with build_from_json(extraction, directed=True) and re-running any post-extraction merges.
Suggested fix
In whatever code path the CLI cluster-only subcommand uses to load/save graph.json, mirror the skill's pattern: read directed from the JSON, build a DiGraph accordingly, and pass through to to_json (which already preserves directedness for DiGraph input).
Workaround
Don't use graphify cluster-only via CLI on directed corpora. Use the Python flow (skill --cluster-only step, or local script invoking cluster() and to_json() directly).
What's happening
Running
graphify cluster-only .on a directed graph (directed: truein graph.json) silently re-saves it as undirected (directed: false) and canonicalises edgesource/targetorder to NetworkX's internal storage order, scrambling the original directions.Reproduction (graphify v0.4.23, macOS, Python 3.14)
The Python
--cluster-onlyflow used in the skill doesn't have this issue —node_link_graphreads thedirectedflag, returns aDiGraph, andto_json/node_link_datapreserves it. It looks like the CLI subcommand is loading or saving without preserving the directedness.Why it matters
CLAUDE.md / skill.md make
--directeda contract: "switching to undirected requires a full rebuild, not --update". Users who rungraphify cluster-only .after a directed--updatediscover the contract was broken silently. Edge directions can't be recovered from the resulting undirected graph because NetworkX canonicalises them on export.Recovery requires rebuilding from semantic cache with
build_from_json(extraction, directed=True)and re-running any post-extraction merges.Suggested fix
In whatever code path the CLI
cluster-onlysubcommand uses to load/save graph.json, mirror the skill's pattern: readdirectedfrom the JSON, build aDiGraphaccordingly, and pass through toto_json(which already preserves directedness forDiGraphinput).Workaround
Don't use
graphify cluster-onlyvia CLI on directed corpora. Use the Python flow (skill--cluster-onlystep, or local script invokingcluster()andto_json()directly).