diff --git a/graphify/skill-agents.md b/graphify/skill-agents.md index 3f7fade81..126a76ca7 100644 --- a/graphify/skill-agents.md +++ b/graphify/skill-agents.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-amp.md b/graphify/skill-amp.md index 3f7fade81..126a76ca7 100644 --- a/graphify/skill-amp.md +++ b/graphify/skill-amp.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-claw.md b/graphify/skill-claw.md index 2eca2a295..72baabb55 100644 --- a/graphify/skill-claw.md +++ b/graphify/skill-claw.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-codex.md b/graphify/skill-codex.md index a126527fd..48c77384f 100644 --- a/graphify/skill-codex.md +++ b/graphify/skill-codex.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-copilot.md b/graphify/skill-copilot.md index 2eca2a295..72baabb55 100644 --- a/graphify/skill-copilot.md +++ b/graphify/skill-copilot.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-droid.md b/graphify/skill-droid.md index b1eeb4925..639bde513 100644 --- a/graphify/skill-droid.md +++ b/graphify/skill-droid.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-kilo.md b/graphify/skill-kilo.md index 387563de4..1797e2f27 100644 --- a/graphify/skill-kilo.md +++ b/graphify/skill-kilo.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-kiro.md b/graphify/skill-kiro.md index 2eca2a295..72baabb55 100644 --- a/graphify/skill-kiro.md +++ b/graphify/skill-kiro.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-opencode.md b/graphify/skill-opencode.md index 144378e65..98f2d8111 100644 --- a/graphify/skill-opencode.md +++ b/graphify/skill-opencode.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-pi.md b/graphify/skill-pi.md index 2eca2a295..72baabb55 100644 --- a/graphify/skill-pi.md +++ b/graphify/skill-pi.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-trae.md b/graphify/skill-trae.md index 36706e3d7..68ee4ca00 100644 --- a/graphify/skill-trae.md +++ b/graphify/skill-trae.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-vscode.md b/graphify/skill-vscode.md index 6191a4ca6..66d3bea85 100644 --- a/graphify/skill-vscode.md +++ b/graphify/skill-vscode.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/graphify/skill-windows.md b/graphify/skill-windows.md index 456244a24..4ad034ba1 100644 --- a/graphify/skill-windows.md +++ b/graphify/skill-windows.md @@ -218,7 +218,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding="utf-8") print(f'AST: {len(result["nodes"])} nodes, {len(result["edges"])} edges') else: diff --git a/graphify/skill.md b/graphify/skill.md index 2eca2a295..72baabb55 100644 --- a/graphify/skill.md +++ b/graphify/skill.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tests/test_skill_part_a_explicit_root.py b/tests/test_skill_part_a_explicit_root.py new file mode 100644 index 000000000..381d1269d --- /dev/null +++ b/tests/test_skill_part_a_explicit_root.py @@ -0,0 +1,78 @@ +"""Step 3 Part A passes root= to extract(), so the cache location never anchors ids (#3727). + +``extract(paths, cache_root=...)`` uses ``cache_root`` as the fallback anchor for +``source_file`` and node ids when ``root`` is not given (#1941). Part A called it +with ``cache_root`` alone. That is harmless while the cache sits in the scan root, +but the two parameters look alike, and anyone adapting the block to a cache that +lives elsewhere re-anchored every code node: same node count, every id renamed, +and every cached edge into code left dangling. A node-count guard cannot see it. +""" +from __future__ import annotations + +import sys +from pathlib import Path + +import pytest + +# tests/ -> repo root is one parent up; put it on the path so tools.skillgen +# imports regardless of pytest's import mode. +REPO_ROOT = Path(__file__).resolve().parent.parent +if str(REPO_ROOT) not in sys.path: + sys.path.insert(0, str(REPO_ROOT)) + +from graphify.extract import extract # noqa: E402 +from tools.skillgen import gen # noqa: E402 + +_CALL = "extract(code_files, cache_root=" + + +def _split_hosts() -> list[gen.Platform]: + return [p for p in gen.load_platforms().values() if p.bucket != "monolith"] + + +def _part_a_calls(platform: gen.Platform) -> list[str]: + body = gen.render(platform)[0].content + return [line.strip() for line in body.splitlines() if _CALL in line] + + +def test_split_hosts_are_discovered(): + """The parametrized guard below must not pass vacuously on an empty list.""" + assert len(_split_hosts()) >= 10, [p.key for p in _split_hosts()] + + +@pytest.mark.parametrize("platform", _split_hosts(), ids=lambda p: p.key) +def test_part_a_passes_an_explicit_root(platform: gen.Platform): + calls = _part_a_calls(platform) + assert calls, f"[{platform.key}] Part A extract() call not found" + for call in calls: + assert "root=Path('INPUT_PATH')" in call.replace("cache_root=Path('INPUT_PATH')", ""), ( + f"[{platform.key}] Part A calls extract() with cache_root but no root= (#3727): {call!r}" + ) + + +def test_relocating_only_the_cache_does_not_rename_part_a_nodes(tmp_path: Path): + """Run the shipped call twice, moving nothing but the cache: ids must not change.""" + scan_root = tmp_path / "proj" + (scan_root / "pkg").mkdir(parents=True) + module = scan_root / "pkg" / "mod.py" + module.write_text("def hello():\n return 1\n", encoding="utf-8") + elsewhere = tmp_path / "cache-elsewhere" + elsewhere.mkdir() + + (call,) = _part_a_calls(gen.load_platforms()["claude"]) + expression = call.removeprefix("result = ") + in_place = expression.replace("Path('INPUT_PATH')", f"Path({str(scan_root)!r})") + relocated = expression.replace( + "cache_root=Path('INPUT_PATH')", f"cache_root=Path({str(elsewhere)!r})" + ).replace("Path('INPUT_PATH')", f"Path({str(scan_root)!r})") + assert in_place != relocated + + scope = {"extract": extract, "Path": Path, "code_files": [module]} + ids_in_place = sorted(n["id"] for n in eval(in_place, dict(scope))["nodes"]) + ids_relocated = sorted(n["id"] for n in eval(relocated, dict(scope))["nodes"]) + + assert ids_in_place, "expected AST nodes for the module" + assert ids_relocated == ids_in_place, ( + "moving only the cache renamed the code nodes: " + f"{ids_in_place} -> {ids_relocated}" + ) diff --git a/tools/skillgen/expected/graphify__skill-agents.md b/tools/skillgen/expected/graphify__skill-agents.md index 3f7fade81..126a76ca7 100644 --- a/tools/skillgen/expected/graphify__skill-agents.md +++ b/tools/skillgen/expected/graphify__skill-agents.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-amp.md b/tools/skillgen/expected/graphify__skill-amp.md index 3f7fade81..126a76ca7 100644 --- a/tools/skillgen/expected/graphify__skill-amp.md +++ b/tools/skillgen/expected/graphify__skill-amp.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-claw.md b/tools/skillgen/expected/graphify__skill-claw.md index 2eca2a295..72baabb55 100644 --- a/tools/skillgen/expected/graphify__skill-claw.md +++ b/tools/skillgen/expected/graphify__skill-claw.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-codex.md b/tools/skillgen/expected/graphify__skill-codex.md index a126527fd..48c77384f 100644 --- a/tools/skillgen/expected/graphify__skill-codex.md +++ b/tools/skillgen/expected/graphify__skill-codex.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-copilot.md b/tools/skillgen/expected/graphify__skill-copilot.md index 2eca2a295..72baabb55 100644 --- a/tools/skillgen/expected/graphify__skill-copilot.md +++ b/tools/skillgen/expected/graphify__skill-copilot.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-droid.md b/tools/skillgen/expected/graphify__skill-droid.md index b1eeb4925..639bde513 100644 --- a/tools/skillgen/expected/graphify__skill-droid.md +++ b/tools/skillgen/expected/graphify__skill-droid.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-kilo.md b/tools/skillgen/expected/graphify__skill-kilo.md index 387563de4..1797e2f27 100644 --- a/tools/skillgen/expected/graphify__skill-kilo.md +++ b/tools/skillgen/expected/graphify__skill-kilo.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-kiro.md b/tools/skillgen/expected/graphify__skill-kiro.md index 2eca2a295..72baabb55 100644 --- a/tools/skillgen/expected/graphify__skill-kiro.md +++ b/tools/skillgen/expected/graphify__skill-kiro.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-opencode.md b/tools/skillgen/expected/graphify__skill-opencode.md index 144378e65..98f2d8111 100644 --- a/tools/skillgen/expected/graphify__skill-opencode.md +++ b/tools/skillgen/expected/graphify__skill-opencode.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-pi.md b/tools/skillgen/expected/graphify__skill-pi.md index 2eca2a295..72baabb55 100644 --- a/tools/skillgen/expected/graphify__skill-pi.md +++ b/tools/skillgen/expected/graphify__skill-pi.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-trae.md b/tools/skillgen/expected/graphify__skill-trae.md index 36706e3d7..68ee4ca00 100644 --- a/tools/skillgen/expected/graphify__skill-trae.md +++ b/tools/skillgen/expected/graphify__skill-trae.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-vscode.md b/tools/skillgen/expected/graphify__skill-vscode.md index 6191a4ca6..66d3bea85 100644 --- a/tools/skillgen/expected/graphify__skill-vscode.md +++ b/tools/skillgen/expected/graphify__skill-vscode.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill-windows.md b/tools/skillgen/expected/graphify__skill-windows.md index 456244a24..4ad034ba1 100644 --- a/tools/skillgen/expected/graphify__skill-windows.md +++ b/tools/skillgen/expected/graphify__skill-windows.md @@ -218,7 +218,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding="utf-8") print(f'AST: {len(result["nodes"])} nodes, {len(result["edges"])} edges') else: diff --git a/tools/skillgen/expected/graphify__skill.md b/tools/skillgen/expected/graphify__skill.md index 2eca2a295..72baabb55 100644 --- a/tools/skillgen/expected/graphify__skill.md +++ b/tools/skillgen/expected/graphify__skill.md @@ -190,7 +190,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: diff --git a/tools/skillgen/fragments/core/core.md b/tools/skillgen/fragments/core/core.md index c527a1256..4a30d95ed 100644 --- a/tools/skillgen/fragments/core/core.md +++ b/tools/skillgen/fragments/core/core.md @@ -143,7 +143,10 @@ for f in detect.get('files', {}).get('code', []): code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)]) if code_files: - result = extract(code_files, cache_root=Path('INPUT_PATH')) + # root= anchors node ids and source_file on the scan root; cache_root only says + # where graphify-out/cache lives. Pass both: without root= the anchor falls back + # to cache_root, so pointing the cache elsewhere would rename every node (#3727). + result = extract(code_files, cache_root=Path('INPUT_PATH'), root=Path('INPUT_PATH')) Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\") print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges') else: