fix graphify update ghost nodes: as_posix() and relativize existing graph before eviction

Three issues in _rebuild_code (watch.py):
1. _relativize_source_files was called on result after eviction list was built,
   so existing nodes with absolute source_file were never normalized before comparison
2. deleted_paths and evict_sources used str() (backslashes on Windows) while
   graph.json stores forward-slash paths via _norm_source_file
3. _relativize_source_files itself used str() instead of as_posix()

Also fix extract.py source_file relativization to use as_posix(). Closes #1007.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Safi
2026-05-26 20:05:31 +01:00
parent eef623a54a
commit 3f8efaebc2
2 changed files with 7 additions and 6 deletions
+1 -1
View File
@@ -8637,7 +8637,7 @@ def extract(
if not sf_path.is_absolute():
continue
try:
item["source_file"] = str(sf_path.relative_to(root))
item["source_file"] = sf_path.relative_to(root).as_posix()
except ValueError:
pass
+6 -5
View File
@@ -138,7 +138,7 @@ def _relativize_source_files(payload: dict, root: Path) -> None:
if not source_path.is_absolute():
continue
try:
item["source_file"] = str(source_path.resolve().relative_to(root))
item["source_file"] = source_path.resolve().relative_to(root).as_posix()
except ValueError:
continue
@@ -376,9 +376,9 @@ def _rebuild_code(
# (e.g. .gitignore, vendored). Either way, evict any
# preserved nodes that still claim this source path.
try:
deleted_paths.add(str(cand.relative_to(project_root)))
deleted_paths.add(cand.relative_to(project_root).as_posix())
except ValueError:
deleted_paths.add(str(cand))
deleted_paths.add(cand.as_posix())
if not wanted and not deleted_paths:
print("[graphify watch] No tracked code files in change set - skipping rebuild.")
return True
@@ -408,13 +408,14 @@ def _rebuild_code(
existing = json.loads(existing_graph.read_text(encoding="utf-8"))
existing_graph_data = existing
new_ast_ids = {n["id"] for n in result["nodes"]}
_relativize_source_files(existing, project_root)
evict_sources: set[str] = set(deleted_paths)
if changed_paths is not None:
for p in extract_targets:
try:
evict_sources.add(str(p.relative_to(project_root)))
evict_sources.add(p.relative_to(project_root).as_posix())
except ValueError:
evict_sources.add(str(p))
evict_sources.add(p.as_posix())
preserved_nodes = [
n for n in existing.get("nodes", [])
if n["id"] not in new_ast_ids