Repository navigation
Description
Bug Description
When specify extension add fails after command rendering (e.g. hook registration or the final registry write fails), the rollback removes the installed package and registry entry, but native skill outputs (<agent skills dir>/speckit-<ext>-<cmd>/SKILL.md) written by the attempt are left behind. They are not recorded anywhere, so later lifecycle operations do not own them.
The generic integration's install rollback (rollback_generic_registration) already removes its outputs; the native route has no equivalent.
Steps to Reproduce
Minimal reproduction (pytest, Claude in skills mode; simulates a hook-write failure):
import yaml, pytest
from specify_cli import save_init_options
from specify_cli.extensions import ExtensionManager, HookExecutor
def test_repro(tmp_path, monkeypatch):
project = tmp_path / "p"; (project / ".specify").mkdir(parents=True)
(project / ".claude/skills").mkdir(parents=True)
save_init_options(project, {"ai": "claude", "ai_skills": True, "script": "sh"})
ext = tmp_path / "ext"; (ext / "commands").mkdir(parents=True)
(ext / "commands/run.md").write_text("---\ndescription: d\n---\nhello\n")
(ext / "extension.yml").write_text(yaml.safe_dump({"schema_version": "1.0",
"extension": {"id": "sample", "name": "S", "version": "1.0.0", "description": "d", "author": "t"},
"requires": {"speckit_version": ">=0.1.0"},
"provides": {"commands": [{"name": "speckit.sample.run", "file": "commands/run.md"}]},
"hooks": {"after_tasks": {"command": "speckit.sample.run", "optional": True}}}))
monkeypatch.setattr(HookExecutor, "register_hooks", lambda *a: (_ for _ in ()).throw(OSError("x")))
with pytest.raises(OSError):
ExtensionManager(project).install_from_directory(ext, "1.0.0")
assert not ExtensionManager(project).registry.is_installed("sample")
assert (project / ".claude/skills/speckit-sample-run/SKILL.md").exists() # leftoverExpected Behavior
A failed install leaves no outputs that the attempt created; pre-existing files are restored unchanged.
Actual Behavior
.claude/skills/speckit-sample-run/SKILL.md remains after the failed install while the extension is not installed.
Specify CLI Version
main @ 7ec720e (1.3.4.dev0)
AI Agent
Claude Code (any native SKILL.md integration)
Operating System
Linux 6.17
Python Version
3.14.4
Error Logs
n/a (simulated failure)
Additional Context
Found while implementing extension skill resources (#5366). That change removes copied resources written by a failed attempt, but intentionally leaves this pre-existing SKILL.md gap unchanged.
AI Disclosure
Drafted with the pi coding agent (orchestrator model: Claude Opus 5.5 via GitHub Copilot; implementation/review subagents: GPT-6.1-terra, GPT-6-astra), human-supervised by the filer. Reproductions were run locally by the agent and reviewed by the filer before filing.
Activity