From 6e2d81d18c22bbda2a258083b67a396dd450312d Mon Sep 17 00:00:00 2001 From: Manfred Riem <15701806+mnriem@users.noreply.github.com> Date: Fri, 17 Jul 2026 07:55:41 -0500 Subject: [PATCH] refactor(extensions): remove before_specify hook from assess Assess is a separate business process from spec-driven development, so it should not inject itself into the /speckit.specify lifecycle. The hook fired on every /speckit.specify invocation (it had no condition), nagging even when an assessment already existed and the user was deliberately proceeding. Unlike git's before_specify (a mechanical prerequisite: create a feature branch) or agent-context's after_* hooks (reacting to spec output), assess is an upstream, optional, human-judgment process. The coupling that belongs here already runs forward and by choice: a `go` verdict from /speckit.assess.decide hands off to /speckit.specify. The backward hook was the redundant, intrusive direction. - extension.yml: drop the hooks block (commands-only manifest) - README.md: replace the Hooks section with a Handoff section - test: replace the hook assertion with test_declares_no_hooks to lock in the standalone-pipeline design Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1f25cf9d-b7eb-4b2b-b811-3e91d8db8f6a --- extensions/assess/README.md | 6 ++---- extensions/assess/extension.yml | 7 ------- tests/extensions/assess/test_assess_extension.py | 10 ++++++---- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/extensions/assess/README.md b/extensions/assess/README.md index e103e8bf9..7aae736ce 100644 --- a/extensions/assess/README.md +++ b/extensions/assess/README.md @@ -85,11 +85,9 @@ specify extension enable assess # → on "go", hand the decision.md handoff summary to /speckit.specify ``` -## Hooks +## Handoff -Registers one **optional** hook: - -- `before_specify` → prompts `speckit.assess.intake` — a nudge to assess an idea before committing it to a specification. It never runs automatically; the user chooses. +`assess` is a **standalone pipeline you enter deliberately** — it registers no lifecycle hooks and never inserts itself into `/speckit.specify`. The only coupling runs forward and by choice: a `go` verdict from `/speckit.assess.decide` hands its `decision.md` summary to `/speckit.specify`. Discovery and specification stay separate processes. ## Guardrails diff --git a/extensions/assess/extension.yml b/extensions/assess/extension.yml index 012b96fb4..897d52998 100644 --- a/extensions/assess/extension.yml +++ b/extensions/assess/extension.yml @@ -32,13 +32,6 @@ provides: file: commands/speckit.assess.decide.md description: "Apply a go / needs-clarification / kill gate and hand survivors off to /speckit.specify" -hooks: - before_specify: - command: speckit.assess.intake - optional: true - prompt: "Assess this idea before specifying?" - description: "Nudge to assess an idea before committing it to a specification" - tags: - "assessment" - "discovery" diff --git a/tests/extensions/assess/test_assess_extension.py b/tests/extensions/assess/test_assess_extension.py index 554a97113..138652b81 100644 --- a/tests/extensions/assess/test_assess_extension.py +++ b/tests/extensions/assess/test_assess_extension.py @@ -48,13 +48,15 @@ class TestExtensionLayout: commands = {c["name"] for c in manifest["provides"]["commands"]} assert commands == EXPECTED_COMMANDS - def test_before_specify_hook_is_optional(self): + def test_declares_no_hooks(self): + """assess is a standalone pipeline: it must not register lifecycle + hooks (e.g. before_specify). Discovery and specification stay + separate processes; the only coupling is the forward decide -> + /speckit.specify handoff described in the commands.""" manifest = yaml.safe_load( (EXT_DIR / "extension.yml").read_text(encoding="utf-8") ) - hook = manifest["hooks"]["before_specify"] - assert hook["optional"] is True - assert hook["command"] == "speckit.assess.intake" + assert "hooks" not in manifest or not manifest["hooks"] def test_readme_exists(self): readme = EXT_DIR / "README.md"