diff --git a/FORK.md b/FORK.md index 228e00133c..f4c0811a2c 100644 --- a/FORK.md +++ b/FORK.md @@ -11,7 +11,7 @@ All files listed below are modified from upstream and will likely conflict on me | Package name | `specify-cli` → `specify-af-cli` | `pyproject.toml` | | Binary name | `specify` → `specify-af` | `pyproject.toml` | | Catalog URL | Points at `appfolio/spec-kit` `af-main` branch | `src/specify_cli/extensions.py`, `extensions/catalog.json` | -| Init flow | Auto-installs bundled AF extensions after scaffold. `--force` now overwrites init-managed files (scripts, templates, extensions, skills) while preserving user content (`memory/`, `feature.json`, `semantic-specs/`). Cleans up stale `.claude/commands/speckit.*.md` files from pre-fork installs | `src/specify_cli/__init__.py`, `src/specify_cli/integrations/claude/__init__.py` | +| Init flow | Auto-installs bundled AF extensions after scaffold. `--force` now overwrites init-managed files (scripts, templates, extensions, skills) while preserving user content (`memory/`, `feature.json`, `semantic-specs/`). Cleans up stale `.claude/commands/speckit.*.md` files from pre-fork installs and known-removed AF skill dirs under `.claude/skills/` (e.g. `speckit-af-check-version`, `speckit-af-after-common`) which Claude Code would otherwise auto-discover and use to hijack lifecycle dispatch | `src/specify_cli/__init__.py`, `src/specify_cli/integrations/claude/__init__.py` | | Removed command | `specify-af upgrade` removed — redundant with reinit flow | `src/specify_cli/__init__.py` | | Version resolution | Uses `packages_distributions()` instead of hardcoded package name | `src/specify_cli/__init__.py` | | Release workflow | release-please with `af-v*` tags on `af-main` | `.github/workflows/release.yml` | diff --git a/src/specify_cli/integrations/claude/__init__.py b/src/specify_cli/integrations/claude/__init__.py index 90859ba8cc..f98008ca38 100644 --- a/src/specify_cli/integrations/claude/__init__.py +++ b/src/specify_cli/integrations/claude/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +import shutil from pathlib import Path from typing import Any @@ -166,6 +167,24 @@ def setup( for stale in commands_dir.glob("speckit.*.md"): stale.unlink() + # Clean up legacy AF skill directories that were shipped in earlier + # versions of the fork but have since been removed or consolidated. + # --force only overwrites current files; directories whose matching + # bundle content no longer exists survive unless explicitly pruned. + # Claude Code auto-discovers these via skill descriptions, which can + # hijack lifecycle dispatch (e.g. a stale speckit-af-check-version + # skill intercepts VERSION_FAIL handling that now lives in common.md). + legacy_af_skills = ( + "speckit-af-check-version", # replaced by inline VERSION_FAIL branch in common.md + "speckit-af-after-common", # never had a SKILL.md; empty dir leftover + ) + skills_root = project_root / ".claude" / "skills" + if skills_root.is_dir(): + for legacy in legacy_af_skills: + legacy_dir = skills_root / legacy + if legacy_dir.is_dir(): + shutil.rmtree(legacy_dir) + # Post-process generated skill files skills_dir = self.skills_dest(project_root).resolve()