diff --git a/graphify/__main__.py b/graphify/__main__.py index ba3ceb6..5d91cec 100644 --- a/graphify/__main__.py +++ b/graphify/__main__.py @@ -901,12 +901,11 @@ def _kiro_install(project_dir: Path) -> None: """Write graphify skill + steering file for Kiro IDE/CLI.""" project_dir = project_dir or Path(".") - # Skill file → .kiro/skills/graphify/SKILL.md - skill_src = Path(__file__).parent / "skill-kiro.md" - skill_dst = project_dir / ".kiro" / "skills" / "graphify" / "SKILL.md" - skill_dst.parent.mkdir(parents=True, exist_ok=True) - skill_dst.write_text(skill_src.read_text(encoding="utf-8"), encoding="utf-8") - print(f" {skill_dst.relative_to(project_dir)} -> /graphify skill") + # Skill file + references/ sidecar + .graphify_version stamp via the shared + # progressive-disclosure helper. Previously this used a bare write_text that + # bypassed _copy_skill_file, so the references/ dir and version stamp were + # never written even though kiro declares skill_refs: "kiro" (#1142). + _copy_skill_file("kiro", project=True, project_dir=project_dir) # Steering file → .kiro/steering/graphify.md (always-on) steering_dir = project_dir / ".kiro" / "steering" @@ -931,15 +930,10 @@ def _kiro_uninstall(project_dir: Path) -> None: project_dir = project_dir or Path(".") removed = [] - skill_dst = project_dir / ".kiro" / "skills" / "graphify" / "SKILL.md" - if skill_dst.exists(): - skill_dst.unlink() + # Skill + .graphify_version + references/ sidecar + empty-dir walk. + skill_dst = _platform_skill_destination("kiro", project=True, project_dir=project_dir) + if _remove_skill_file("kiro", project=True, project_dir=project_dir): removed.append(str(skill_dst.relative_to(project_dir))) - # Remove parent dir if empty - try: - skill_dst.parent.rmdir() - except OSError: - pass steering_dst = project_dir / ".kiro" / "steering" / "graphify.md" if steering_dst.exists(): diff --git a/tests/test_install_upgrade.py b/tests/test_install_upgrade.py index 09ee3d8..13e7c55 100644 --- a/tests/test_install_upgrade.py +++ b/tests/test_install_upgrade.py @@ -231,3 +231,42 @@ def test_kiro_install_upgrades_stale_steering(tmp_path, monkeypatch): assert "read it before answering architecture questions" not in after _assert_query_first(after, ".kiro/steering/graphify.md") assert "inclusion: always" in after # frontmatter preserved + + +def test_kiro_install_ships_references_sidecar_and_version_stamp(tmp_path, monkeypatch): + """_kiro_install routes through _copy_skill_file so the references/ sidecar + and .graphify_version stamp are written alongside SKILL.md (#1142). + Previously it used a bare write_text that bypassed the shared helper.""" + monkeypatch.setattr(mainmod, "_check_skill_version", lambda _: None) + + refs_dir = Path(mainmod.__file__).parent / "skills" / "kiro" / "references" + if not refs_dir.exists(): + pytest.skip("kiro references bundle not present in this checkout") + + mainmod._kiro_install(tmp_path) + + skill_dir = tmp_path / ".kiro" / "skills" / "graphify" + + # SKILL.md present + assert (skill_dir / "SKILL.md").exists() + + # references/ sidecar installed with at least one fragment + refs_dst = skill_dir / "references" + assert refs_dst.is_dir(), "references/ sidecar must be installed (#1142)" + assert any(refs_dst.iterdir()), "references/ must not be empty" + + # .graphify_version stamp written + version_file = skill_dir / ".graphify_version" + assert version_file.exists(), ".graphify_version stamp must be written (#1142)" + assert version_file.read_text(encoding="utf-8") == mainmod.__version__ + + # no references.tmp leftover + assert not (skill_dir / "references.tmp").exists() + + # steering file still written + assert (tmp_path / ".kiro" / "steering" / "graphify.md").exists() + + # uninstall removes skill dir, version stamp, references/, and steering file + mainmod._kiro_uninstall(tmp_path) + assert not skill_dir.exists(), "uninstall must remove skill dir including references/ (#1142)" + assert not (tmp_path / ".kiro" / "steering" / "graphify.md").exists()