SIGN IN SIGN UP

fix(parser): normalize node identity paths to POSIX separators (#774)

Qualified names and file_path values are graph identity, but they were
built from str(path), which yields backslashes on Windows. A graph built
on Windows therefore disagreed with one built anywhere else, with the
modules that already normalize separators (communities, incremental
ignore matching, tools/_common), and with the test suite's forward-slash
expectations (15 of the 18 Windows failures in #774).

Normalize at the identity boundary via a single shared helper,
parser.normalize_file_path():

- parser: every str(path) entry point, _qualify()'s path component,
  NodeInfo/EdgeInfo __post_init__ (file_path only), module-to-file
  resolution results, python star-export origins, and exclude_files().
  Symbol names are never touched - PHP namespace identifiers
  legitimately contain backslashes.
- graph: file-keyed GraphStore methods (remove_file_data,
  remove_files_permanently, iter_nodes_by_file, get_files_matching,
  get_node_ids_by_files) normalize their arguments so native-separator
  spellings keep finding the stored POSIX identities.
- incremental: stale-file reconciliation, dependent lookup, missing-path
  bookkeeping, and the watcher's stored-descendants prefix all join
  repo_root through the helper (otherwise every file would be treated
  as stale on Windows).
- changes/flows/search/jedi_resolver/tools: diff-range keys, churn keys,
  flow retracing, search context boosts, jedi targets, and MCP tool
  path joins route through the same helper.

Regression tests simulate Windows on POSIX hosts by feeding
pathlib.PureWindowsPath into parse_bytes, GraphStore, and
_reconcile_stale_files, and assert forward-slash identities plus PHP
namespace preservation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FmPUotoqsNWWt3b41FMjwv
T
Tirth Kanani committed
5ee2a12e45e4fd3f3cb4a7c8f1e75b655d8b6a1b
Parent: f88f26e