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
This commit is contained in:
Manfred Riem
2026-07-17 07:55:41 -05:00
parent 4c8124d22b
commit 6e2d81d18c
3 changed files with 8 additions and 15 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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"