Skip to content

fix(presets): restore core skills instead of deleting them on preset remove - #3929

Open
chelsealong wants to merge 1 commit into
github:mainfrom
chelsealong:fix/3928-preset-remove-deletes-core-skills
Open

fix(presets): restore core skills instead of deleting them on preset remove#3929
chelsealong wants to merge 1 commit into
github:mainfrom
chelsealong:fix/3928-preset-remove-deletes-core-skills

Conversation

@chelsealong

Copy link
Copy Markdown

Fixes #3928

Bug

When a preset that overrides core commands/skills is removed, the corresponding
core skills are deleted instead of being restored — the only way to get them
back is to re-scaffold with specify init.

Root cause

PresetManager._unregister_skills_in_dir looks for the original core command
template at self.project_root / ".specify" / "templates" / "commands". That
directory is never populated by specify init in a real project — the actual
core command templates live in the bundled core_pack/commands/ directory
(wheel install) or the repo-root templates/commands/ tree (source checkout),
exactly like PresetResolver.resolve_core() already falls back to via
_locate_core_pack() / _repo_root().

Because the lookup always missed, every preset-removal restoration fell
through to the "no core template found" branch and deleted the skill outright.

Fix

Restoration now falls back to the bundled core_pack/repo-root templates when
the project-local override directory doesn't have the file. This fallback is
gated behind a new restore_from_bundled_core flag so the pre-existing "retire
a stale skill because its command now renders as a command file elsewhere"
path (triggered by ai_skills mode toggles) keeps its original delete
behavior — it must not resurrect a duplicate skill that a command file has
already superseded.

Repro (before the fix)

specify init --here --integration claude
specify preset add lean --dev presets/lean
ls .claude/skills          # all 10 core skills present
specify preset remove lean
ls .claude/skills          # only 5 remain — specify/plan/tasks/implement/constitution deleted

After the fix, all 10 skills are present again, restored with core content
after specify preset remove lean.

Testing

Added test_skill_restored_on_preset_remove_without_project_core_templates,
which (unlike the existing test_skill_restored_on_preset_remove) does not
pre-seed .specify/templates/commands with a fake core file, matching what a
real specify init project looks like. Confirmed it fails without the fix
(AssertionError: Core skill must be restored, not deleted) via
git checkout HEAD~1 -- src/specify_cli/presets/__init__.py, then passes with
the fix restored.

$ .venv/bin/python -m pytest tests/test_presets.py -q
526 passed in 7.40s

$ .venv/bin/python -m pytest tests -q
6380 passed, 9 skipped in 396.25s

$ .venv/bin/python -m pytest tests/test_agent_config_consistency.py -q
28 passed in 0.24s

$ uvx ruff@0.15.0 check src tests
All checks passed!

AI disclosure

This PR was authored primarily by an AI coding agent (Claude Code): it
diagnosed the root cause, implemented the fix, and wrote/verified the
regression test. I reviewed the diff and test output before submitting.

…remove

Skill restoration looked for core command templates under
.specify/templates/commands, a directory specify init never populates
in real projects. Since that lookup always missed, presets overriding
a core command (e.g. speckit.plan) had their skill deleted outright on
removal instead of restored — the actual core templates live in the
bundled core_pack (wheel install) or the repo-root templates/ tree.

Restoration now falls back to that bundled location, gated behind a
restore_from_bundled_core flag so the existing "retire a stale skill
superseded by a command-mode winner" path keeps deleting rather than
resurrecting a duplicate skill.

Fixes github#3928
@chelsealong
chelsealong requested a review from mnriem as a code owner July 31, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Core skills get deleted when preset is removed

1 participant