You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Absolute paths still land in node id + source_file on 0.9.15: out-of-root reference targets and degenerate-symbol id fallback (residual of #1789) #1899
Follow-up to #1789 (fixed in 0.9.13 for .sln/.csprojfile node ids, and in 0.9.14 for virtual solution-folder ids — thanks for both). On 0.9.15 two code paths still emit machine-specific absolute paths into graph.json:
Variant B — degenerate symbol nodes from in-root files. Some symbol nodes get a correctly relativized source_file but an absolute-path-derived id. Two triggers observed: a JSON file using the tsconfig "//" comment-key convention (node label //), and a minified vendor bundle (node label $() from moment.min.js). Symbol-id derivation seems to fall back to _make_id(str(absolute_path)) when no usable symbol/module name is available.
Consequences are the same as #1789: the committed graph.json leaks the local username / checkout path, ids differ per machine and per checkout location, so graphify update from another clone re-creates these nodes (diff churn, non-idempotent versioned graphs).
Environment
graphify (graphifyy) 0.9.15 (installed via uv tool), Python 3.12.9
macOS 26.5 (also expected on Linux/Windows — the fallback logic is OS-agnostic)
(Only elided the middles of the long tmp path with ... — everything else is exactly as emitted. Note Core.csproj shows Variant A — both fields absolute — while the // node shows Variant B — relative source_file, absolute id.)
Expected
Node ids derived from scan-root-relative paths in all code paths.
For out-of-root targets, something machine-independent: relativize with .. segments against the scan root, key off the reference text as written (..\Core\Core.csproj), or mark the node external and key it by basename — anything that doesn't embed the checkout location in id/source_file.
Real-world impact
Hit this rolling graphify out on a large private monorepo (9 scan scopes, ~300k nodes, graphs committed to git): 8 of 9 scope graphs contained 88 machine-specific strings — every scope with a cross-project .csproj reference (the norm in .NET monorepos) leaked the absolute checkout path via Variant A, and vendored/minified bundles plus tsconfig-style JSON hit Variant B.
Current workaround (in case it helps others): post-build textual normalization — strip the <abs-checkout>/ prefix from source_file values and the derived slug prefix from ids; a plain find/replace also fixes the edge references, and node/edge counts stay intact.
Summary
Follow-up to #1789 (fixed in 0.9.13 for
.sln/.csprojfile node ids, and in 0.9.14 for virtual solution-folder ids — thanks for both). On 0.9.15 two code paths still emit machine-specific absolute paths intograph.json:<ProjectReference Include="..\Core\Core.csproj" />when onlyWebApi/is scanned) gets an absolutesource_fileAND an absolute-path-derivedid. The relativization added for Node IDs for file / directory / project nodes embed the absolute scan path (leaks local username, makes committed graph.json non-portable / non-idempotent) #1789 appears to rely onrelative_to(root), which can't apply to out-of-root paths, so both fields fall back to absolute.source_filebut an absolute-path-derivedid. Two triggers observed: a JSON file using the tsconfig"//"comment-key convention (node label//), and a minified vendor bundle (node label$()frommoment.min.js). Symbol-id derivation seems to fall back to_make_id(str(absolute_path))when no usable symbol/module name is available.Consequences are the same as #1789: the committed
graph.jsonleaks the local username / checkout path, ids differ per machine and per checkout location, sographify updatefrom another clone re-creates these nodes (diff churn, non-idempotent versioned graphs).Environment
graphifyy) 0.9.15 (installed viauv tool), Python 3.12.9_origin: "ast"on all affected nodes) — no LLM/deep mode involved, so this is distinct from deep mode: nodes with out-of-scope source_file are warned about but still written to graph.json #1895.Minimal repro (4 files, no .NET SDK, no API key)
Observed output (verbatim, 0.9.15)
{ "label": "Core.csproj", "source_file": "/private/var/folders/sv/.../T/tmp.eSYW7WLP1S/Core/Core.csproj", "id": "private_var_folders_sv_..._t_tmp_esyw7wlp1s_core_core_csproj" } { "label": "//", "source_file": "tsconfig.dev.json", "id": "private_var_folders_sv_..._t_tmp_esyw7wlp1s_webapi_tsconfig_dev" }(Only elided the middles of the long tmp path with
...— everything else is exactly as emitted. NoteCore.csprojshows Variant A — both fields absolute — while the//node shows Variant B — relativesource_file, absolute id.)Expected
..segments against the scan root, key off the reference text as written (..\Core\Core.csproj), or mark the node external and key it by basename — anything that doesn't embed the checkout location inid/source_file.Real-world impact
Hit this rolling graphify out on a large private monorepo (9 scan scopes, ~300k nodes, graphs committed to git): 8 of 9 scope graphs contained 88 machine-specific strings — every scope with a cross-project
.csprojreference (the norm in .NET monorepos) leaked the absolute checkout path via Variant A, and vendored/minified bundles plus tsconfig-style JSON hit Variant B.Current workaround (in case it helps others): post-build textual normalization — strip the
<abs-checkout>/prefix fromsource_filevalues and the derived slug prefix fromids; a plain find/replace also fixes the edge references, and node/edge counts stay intact.