test(affected): cover outside-root clean-miss and non-out-dir graph layout (#2706)

Adds the two gaps the deep-dive flagged: an absolute seed outside the derived
root must miss cleanly (not resolve to a same-basename in-root node), and a
--graph pointing at a graph.json NOT under graphify-out uses the else gp.parent
fallback root. Also adds the CHANGELOG entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
safishamsi
2026-08-15 17:16:53 +01:00
co-authored by Claude Opus 4.8
parent 243a1801f1
commit 6f1cbe5fda
2 changed files with 53 additions and 0 deletions
+1
View File
@@ -4,6 +4,7 @@ Full release notes with details on each version: [GitHub Releases](https://githu
## 0.9.44 (unreleased)
- Fix: `graphify affected` resolves an absolute-path seed against the repo root derived from the graph's own location instead of the current working directory, so a blast-radius query with an absolute seed run from anywhere (an editor, a script) no longer silently returns nothing; a seed outside the root still misses cleanly (#2706, thanks @ousamabenyounes).
- Fix: a lazy CommonJS `require(...)` inside a function body (the idiom for breaking circular dependencies) now emits the same `imports_from`/`imports` dependency edges as a top-level require, attributed to the enclosing function, instead of being silently dropped; a dynamic `require(variable)` is still skipped (#2700, thanks @rajanpanth).
- Fix: a JS/TS identifier bound by an import whose target resolves outside the scanned corpus (e.g. a `lucide-react` icon) is now shadowed, so using it as a value no longer fabricates an INFERRED `indirect_call` onto an unrelated same-named callable elsewhere in the corpus; a relative/in-corpus import still resolves to its real target (#2757, thanks @phudayyy).
- Fix: an OCaml qualified call `M.f` to an external module (one not defined in the same file, e.g. Hardcaml's `Reg_spec.create`) no longer binds to a same-named local `let f` — which produced a false `calls` edge and, when the caller was that local `f`, a `f -> f` self-loop. External qualified calls are kept as a distinct target labelled by the full path; unqualified calls and calls into a locally-defined module still resolve locally, and cross-file `Geo.area` still collapses onto another file's `area`.
+52
View File
@@ -371,3 +371,55 @@ def test_affected_absolute_seed_resolves_via_graph_root_off_cwd(tmp_path, monkey
assert "Affected nodes for Foo" in out
assert "X()" in out
def test_affected_absolute_seed_outside_root_misses_cleanly(tmp_path, monkeypatch, capsys):
"""An absolute seed that is NOT under the derived repo root must report a clean
no-match, not silently traverse from a wrong/guessed node (#2706)."""
from graphify.paths import GRAPHIFY_OUT_NAME
repo_root = tmp_path / "repo"
out_dir = repo_root / GRAPHIFY_OUT_NAME
out_dir.mkdir(parents=True)
g = nx.DiGraph()
g.add_node("target", label="Foo", source_file="pkg/foo.py", source_location="L1")
g.add_node("caller", label="X()", source_file="app.py", source_location="L4")
g.add_edge("caller", "target", relation="calls")
gp = out_dir / "graph.json"
gp.write_text(json.dumps(json_graph.node_link_data(g, edges="links")), encoding="utf-8")
monkeypatch.chdir(tmp_path)
outside_seed = str(tmp_path / "other-repo" / "pkg" / "foo.py") # same basename, different tree
monkeypatch.setattr(mainmod, "_check_skill_version", lambda _: None)
monkeypatch.setattr(mainmod.sys, "argv",
["graphify", "affected", outside_seed, "--graph", str(gp)])
mainmod.main()
out = capsys.readouterr().out
assert "Affected nodes for Foo" not in out # must NOT resolve to the in-root Foo
def test_affected_absolute_seed_with_graph_not_under_out_dir(tmp_path, monkeypatch, capsys):
"""Fallback layout: when --graph points at a graph.json NOT under the
graphify-out dir, the root is the graph's own parent (`else gp.parent`)."""
repo_root = tmp_path / "repo"
repo_root.mkdir(parents=True)
g = nx.DiGraph()
g.add_node("target", label="Foo", source_file="pkg/foo.py", source_location="L1")
g.add_node("caller", label="X()", source_file="app.py", source_location="L4")
g.add_edge("caller", "target", relation="calls")
gp = repo_root / "graph.json" # directly under repo_root, not graphify-out/
gp.write_text(json.dumps(json_graph.node_link_data(g, edges="links")), encoding="utf-8")
elsewhere = tmp_path / "elsewhere"
elsewhere.mkdir()
monkeypatch.chdir(elsewhere)
abs_seed = str(repo_root / "pkg" / "foo.py")
monkeypatch.setattr(mainmod, "_check_skill_version", lambda _: None)
monkeypatch.setattr(mainmod.sys, "argv",
["graphify", "affected", abs_seed, "--graph", str(gp)])
mainmod.main()
out = capsys.readouterr().out
assert "Affected nodes for Foo" in out
assert "X()" in out