Normalize relative source_file to POSIX separators - #2764
Conversation
extract()'s canonicalization pass only ran source_file through as_posix() on the absolute-input branch. A relative-input source_file -- from the documented extract(paths) entry point with no root, or python -m graphify.extract <file>... -- was left exactly as the extractor's plain str(path) produced it, which renders with a native backslash separator on Windows. That diverges from the POSIX form the explicit-root and CLI paths already produce, fragmenting the string-equality lookups keyed on source_file (build._norm_source_file, analyze.find_import_cycles, the semantic-cache key) into two spellings of one file. Normalize the relative branch too: replace any backslash in the raw source_file string. No id-remap needed there, since ids are minted independently of this field. Fixes Graphify-Labs#2625.
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
This PR modifies the canonicalization pass in extract() so that relative source_file values containing backslashes are rewritten to use forward slashes. Previously, only the absolute-path branch applied POSIX normalization, so relative-path callers (e.g. extract(paths) with no root) could retain native Windows separators. It also adds a test that monkeypatches an extractor to emit backslash-separated source_file strings on both a node and an edge, then asserts they are normalized to POSIX form after extraction.
No blocking issues surfaced. 1 lower-confidence candidate did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 1655 functions depend on the 546 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 455 callers, 41 callees - new:
_rebuild_code()— 95 callers, 51 callees - new:
extract_xaml()— 19 callers, 17 callees - new:
dispatch_command()— 2 callers, 117 callees - new:
extract_js()— 76 callers, 3 callees - new:
_get_extractor()— 26 callers, 6 callees - new:
run_pipeline()— 8 callers, 13 callees - new:
collect_files()— 17 callers, 6 callees - …and 22 more
Verification — 1655 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: 1515 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify extract.
The verifier did not have enough to check extract, 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 `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set
· 30 more finding(s) on lines outside this diff (see the check run).
extract()'s canonicalization pass only ran source_file through
as_posix() on the absolute-input branch. A relative-input source_file
-- from the documented extract(paths) entry point with no root, or
python -m graphify.extract ... -- was left exactly as the
extractor's plain str(path) produced it, which renders with a native
backslash separator on Windows. That diverges from the POSIX form the
explicit-root and CLI paths already produce, fragmenting the
string-equality lookups keyed on source_file (build._norm_source_file,
analyze.find_import_cycles, the semantic-cache key) into two spellings
of one file.
Normalize the relative branch too: replace any backslash in the raw
source_file string. No id-remap needed there, since ids are minted
independently of this field.
A real WindowsPath can't be constructed on this (POSIX) dev machine, so
the added regression test monkeypatches one extension's dispatch to
return a node/edge with a literal backslash-separated source_file --
exactly the shape str(WindowsPath(...)) produces on Windows -- and
asserts extract()'s post-pass normalizes it. This exercises the actual
fixed code path directly rather than depending on OS-native path
rendering.
Fixes #2625.