From bdf62ce27523d0ce0d84de5cde73111367c964ac Mon Sep 17 00:00:00 2001 From: MalikHaroonKhokhar Date: Thu, 30 Jul 2026 19:29:32 +0500 Subject: [PATCH] fix(install): stop hardcoding the global skill path in the Antigravity workflow (#2319) `_ANTIGRAVITY_WORKFLOW` is shared by the global and project-scoped installs, which write SKILL.md to different locations (~/.gemini/config/skills vs .agents/skills). The template named the global path unconditionally, so `install --project --platform antigravity` (and `antigravity install --project`) emitted a workflow pointing at a file that scope never writes - a dangling reference on any machine without a prior global install. Refer to the skill by name rather than by location, matching what every block in always_on/ already does. Antigravity resolves it from the `name: graphify` frontmatter in either scope, so no path interpolation is needed and neither scope can dangle. The existing tests only asserted the workflow file exists, which is why this shipped; add coverage that the generated workflow names no skill path, in both project and global scope. --- graphify/install.py | 5 ++++- tests/test_antigravity_install.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/graphify/install.py b/graphify/install.py index 8c0cfee6..dd8e6a82 100644 --- a/graphify/install.py +++ b/graphify/install.py @@ -915,6 +915,9 @@ def vscode_uninstall(project_dir: Path | None = None) -> None: print(f" {instructions} -> deleted (was empty after removal)") _ANTIGRAVITY_RULES_PATH = Path(".agents") / "rules" / "graphify.md" _ANTIGRAVITY_WORKFLOW_PATH = Path(".agents") / "workflows" / "graphify.md" +# Names no SKILL.md location on purpose: this constant is shared by the global and +# project-scoped installs, which put the skill in different places, so any hardcoded +# path dangles for the other scope. Antigravity resolves the skill by frontmatter name. _ANTIGRAVITY_WORKFLOW = """\ --- name: graphify @@ -923,7 +926,7 @@ description: Turn any folder of files into a navigable knowledge graph # Workflow: graphify -Follow the graphify skill installed at ~/.gemini/config/skills/graphify/SKILL.md to run the full pipeline. +Follow the graphify skill to run the full pipeline. If no path argument is given, use `.` (current directory). """ diff --git a/tests/test_antigravity_install.py b/tests/test_antigravity_install.py index 78c7e87f..728574f9 100644 --- a/tests/test_antigravity_install.py +++ b/tests/test_antigravity_install.py @@ -20,6 +20,37 @@ def test_antigravity_project_install_writes_rules_and_workflows(tmp_path): assert skill.read_text(encoding="utf-8").startswith("---\n") +def test_antigravity_workflow_names_no_skill_path(tmp_path): + """The workflow must not hardcode a SKILL.md location. + + One constant serves both scopes, which install the skill to different places, + so naming either path dangles for the other: a project-scoped install used to + point at ~/.gemini/config/skills/graphify/SKILL.md, which it never writes. + """ + m._project_install("antigravity", tmp_path) + body = (tmp_path / ".agents" / "workflows" / "graphify.md").read_text(encoding="utf-8") + assert ".gemini" not in body, "workflow must not reference the global skill dir" + assert "SKILL.md" not in body, "workflow must not name a skill path in any scope" + assert "~" not in body, "workflow must not reference a home directory" + assert "graphify skill" in body, "workflow should still point at the skill by name" + + +def test_antigravity_global_install_workflow_names_no_skill_path(tmp_path, monkeypatch): + """Global install shares the constant, so it must stay path-free too.""" + monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path / "home") + monkeypatch.setenv("HOME", str(tmp_path / "home")) + m._antigravity_install(tmp_path) + + # The skill really does land in the global dir the old text named ... + assert ( + tmp_path / "home" / ".gemini" / "config" / "skills" / "graphify" / "SKILL.md" + ).exists() + # ... but the workflow still must not hardcode it. + body = (tmp_path / ".agents" / "workflows" / "graphify.md").read_text(encoding="utf-8") + assert ".gemini" not in body + assert "SKILL.md" not in body + + def test_antigravity_project_uninstall_clears_rules_and_workflows(tmp_path): m._project_install("antigravity", tmp_path) m._project_uninstall("antigravity", tmp_path)