fix(sln): skip solution folders, which are not files (one node per .sln) - #3270
fix(sln): skip solution folders, which are not files (one node per .sln)#3270mallyskies wants to merge 1 commit into
Conversation
A solution folder is a virtual grouping declared only inside the .sln --
there is no such directory on disk -- so it is not a file and should not
become a node. Visual Studio marks one with the well-known project type
GUID 2150E333-8FDC-42A3-9474-1A3956D46DE8 and writes the folder name in
the path position:
Project("{2150E333-...}") = "Solution Items", "Solution Items", "{C40B...}"
against a real project's relative path:
Project("{8BC9CEB8-...}") = "jpgfltr", "jpgfltr\jpgfltr.vcproj", "{EA73...}"
_PROJECT_RE discarded the type GUID, so the two were indistinguishable by
the field that states which is which. The folder was emitted as a node
whose source_file is a bare name with no directory component and whose
source_location is null. Downstream that reads as a stray unignored
top-level path, and no ignore pattern can suppress it, because there is
no path to match.
This supersedes the `proj_path == proj_name` heuristic added for Graphify-Labs#1789,
where resolving a folder to an absolute path leaked the scan path -- and
the local username with it -- into a committed graph.json. Skipping the
entry closes that leak more directly, and a real project whose relative
path equals its display name is no longer misread as a folder; there is a
test for that case.
Nothing dangles: solution-folder GUIDs are never edge endpoints, since
only ProjectSection(ProjectDependencies) is parsed and a folder has no
such section. On a 5,372-project depot the change removes exactly one
node and its one contains edge per affected .sln, leaving every real
project and dependency edge intact.
test_sln_solution_folder_ids_are_relative is replaced by
test_sln_solution_folder_is_not_a_node, keeping the Graphify-Labs#1789 assertion.
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Skips solution folders in extract_sln by matching Visual Studio's well-known solution-folder type GUID (captured from the Project(...) type field) instead of the old proj_path == proj_name heuristic, so virtual groupings never become nodes and real projects always resolve to their path. This closes the #1789 username leak more directly — no folder node means no absolute scan path to relativize — and no longer misclassifies a real project whose path equals its name. Updates the tests to assert folders are absent while path-equals-name projects remain nodes.
No blocking issues surfaced. 2 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 69 functions depend on the 65 functions this change touches.
Health — grade A; no new coupling hotspots.
Verification — 69 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 69 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify extract\_sln.
The verifier did not have enough to check extract\_sln, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set
A solution folder exists only inside the
.sln— there's no such directory on disk — so it shouldn't become a node. Visual Studio marks one with the project type GUID2150E333-8FDC-42A3-9474-1A3956D46DE8and repeats the name in the path position:_PROJECT_REdiscarded the type GUID, so the folder became a node with a baresource_file, no directory component, and a nullsource_location— which no ignore rule can suppress, since there's no path to match.Supersedes the
proj_path == proj_nameheuristic from #1789 (absolute-path leak). Skipping the entry closes that leak more directly and keys off the field that states the entry's kind, rather than a coincidence between two others — a real project whose path equals its name would trip the old heuristic, and there's a regression test for that.test_sln_solution_folder_ids_are_relativebecomestest_sln_solution_folder_is_not_a_node, keeping the #1789 assertion.Scope is one node and its
containsedge per affected.sln. Nothing dangles: folder GUIDs are never edge endpoints.tests/test_dotnet.py47 passed.🤖 Generated with Claude Code