Package: graphifyy v0.7.13
Skill version installed: 0.7.8 (warning printed by CLI)
Environment: macOS 24.6.0, Python 3.11 (uv tool install of graphifyy)
Related (closed): #760
Summary
Issue #760 fixed the build_merge() direction-inversion bug in build.py. The fix is correctly used by the CLI graphify update <path> command (__main__.py:2608 calls _build_merge).
However, the bundled skill.md template still ships a hand-rolled merge block in its --update section that never calls build_merge(). It uses the exact node_link_graph() round-trip pattern that #760 identified as the root cause. As a result, any AI coding assistant that follows the skill instructions (Claude Code, Codex, Cursor, etc.) re-introduces the very bug #760 closed.
Evidence
graphify-0.7.13/skill.md line 788 (the --update flow):
existing_data = json.loads(Path('graphify-out/graph.json').read_text())
G_existing = json_graph.node_link_graph(existing_data, edges='links') # round-trip — direction lost
...
G_existing.update(G_new)
to_json(G_existing, communities, 'graphify-out/graph.json') # write back inverted
Compare with the fix in build.py:235:
def build_merge(...):
...
# Read JSON directly instead of going through node_link_graph().
The skill never imports build_merge.
Reproduction
- Build a TypeScript project graph with a small helper imported by many call sites — e.g. an
axios wrapper called requestGet imported in 100+ API files.
- Run
/graphify --update (Claude Code skill path), which executes the inline merge code from skill.md.
- Inspect
graph.json for edges where source = requestGet. They will all be of the form requestGet --calls--> getXxx() despite requestGet being a callee, not a caller, in every actual source file.
In one real codebase:
requestGet (5-line axios wrapper) — graph reports 105 outgoing INFERRED 0.8 calls edges.
grep ground truth: 171 files import requestGet, 178 actual call sites.
- All 105 edges point the wrong way; another 73 actual call sites are missing entirely.
- Same pattern on every other god helper:
requestPost (32), getEncryptUrl (18), usePageMove (17), getApiEncryptKey (17), getDeviceInfo (12), buildUrl (10).
(Bug 2 from #760 — INFERRED 0.8 for deterministic cross-file calls — is also visible because these edges were inserted by an older version, then preserved across every --update because the skill's inline path never re-extracts edges that aren't in the changed-file set.)
Why this matters
- The Claude Code skill is the default invocation path for most users (
/graphify and /graphify --update). Fixing build_merge() while leaving the skill template broken means almost no end-user gets the fix.
- The skill template duplicates merge logic instead of calling
build_merge(), so future build.py improvements will silently fail to reach skill users — exactly what happened here.
- Skill is overwritten on every
graphify install. There is no user-side workaround that survives upgrades.
Suggested fix
Replace the inline merge block in skill.md's --update section with a call to the fixed function:
from graphify.build import build_merge
merged = build_merge(
existing_path='graphify-out/graph.json',
new_extraction=new_extract,
deleted_files=incremental.get('deleted_files', []),
changed_files=incremental['new_files'].get('code', []),
)
Path('graphify-out/.graphify_extract.json').write_text(json.dumps(merged))
(Adjust signature to whatever build_merge already exposes.)
This eliminates ~40 lines of duplicated logic, keeps skill flow in sync with CLI flow, and prevents future build.py fixes from being orphaned.
Optional follow-ups
- Same drift risk exists for the
--cluster-only, query, path, explain, and add subcommand instructions — any block that re-implements logic inline rather than calling a graphify Python entry point is a future drift hazard.
- Consider gating the skill on a minimum graphify version (skill 0.7.8 + package 0.7.13 was the warning seen here). If the inline blocks were replaced with library calls, version mismatch would surface as an
ImportError instead of a silent semantic regression.
Severity
Medium-high. The bug is invisible (graph.json still loads, all stats render), but the most prominent output of the skill — the "God Nodes" section of GRAPH_REPORT.md — gives users a categorically wrong reading of their codebase's call structure.
Package:
graphifyyv0.7.13Skill version installed: 0.7.8 (warning printed by CLI)
Environment: macOS 24.6.0, Python 3.11 (uv tool install of
graphifyy)Related (closed): #760
Summary
Issue #760 fixed the
build_merge()direction-inversion bug inbuild.py. The fix is correctly used by the CLIgraphify update <path>command (__main__.py:2608calls_build_merge).However, the bundled
skill.mdtemplate still ships a hand-rolled merge block in its--updatesection that never callsbuild_merge(). It uses the exactnode_link_graph()round-trip pattern that #760 identified as the root cause. As a result, any AI coding assistant that follows the skill instructions (Claude Code, Codex, Cursor, etc.) re-introduces the very bug #760 closed.Evidence
graphify-0.7.13/skill.mdline 788 (the--updateflow):Compare with the fix in
build.py:235:The skill never imports
build_merge.Reproduction
axioswrapper calledrequestGetimported in 100+ API files./graphify --update(Claude Code skill path), which executes the inline merge code fromskill.md.graph.jsonfor edges wheresource = requestGet. They will all be of the formrequestGet --calls--> getXxx()despiterequestGetbeing a callee, not a caller, in every actual source file.In one real codebase:
requestGet(5-line axios wrapper) — graph reports 105 outgoingINFERRED 0.8callsedges.grepground truth: 171 files importrequestGet, 178 actual call sites.requestPost (32),getEncryptUrl (18),usePageMove (17),getApiEncryptKey (17),getDeviceInfo (12),buildUrl (10).(Bug 2 from #760 —
INFERRED 0.8for deterministic cross-file calls — is also visible because these edges were inserted by an older version, then preserved across every--updatebecause the skill's inline path never re-extracts edges that aren't in the changed-file set.)Why this matters
/graphifyand/graphify --update). Fixingbuild_merge()while leaving the skill template broken means almost no end-user gets the fix.build_merge(), so futurebuild.pyimprovements will silently fail to reach skill users — exactly what happened here.graphify install. There is no user-side workaround that survives upgrades.Suggested fix
Replace the inline merge block in
skill.md's--updatesection with a call to the fixed function:(Adjust signature to whatever
build_mergealready exposes.)This eliminates ~40 lines of duplicated logic, keeps skill flow in sync with CLI flow, and prevents future
build.pyfixes from being orphaned.Optional follow-ups
--cluster-only,query,path,explain, andaddsubcommand instructions — any block that re-implements logic inline rather than calling a graphify Python entry point is a future drift hazard.ImportErrorinstead of a silent semantic regression.Severity
Medium-high. The bug is invisible (graph.json still loads, all stats render), but the most prominent output of the skill — the "God Nodes" section of
GRAPH_REPORT.md— gives users a categorically wrong reading of their codebase's call structure.