Skip to content

[Bug]: after_specify / after_clarify / before_implement hook dispatch silently skipped in interactive slash-command path #2688

@thlandgraf

Description

@thlandgraf

Problem Statement

The after_specify, after_clarify, and before_implement hook directives wired into the core command SKILL.md bodies (per PR #1886, following the PR #1702 pattern) are silently skipped by the agent in practice when invoked via the interactive slash-command path. The wiring is correct at the manifest level, but the dispatch instruction sits near the end of a 300+ line SKILL.md and the LLM does not reach it consistently.

This is a different problem from #2104 (which asked for auto-run and was correctly closed in favour of the workflow engine). I am not asking for auto-run. I am asking for the existing best-effort dispatch step in the SKILL.md to be made more reliable — specifically by moving it earlier and giving it a structure the model can't overlook.

Reproduction

  1. Start with a specify init . --integration claude project on spec-kit 0.8.13.
  2. Install an extension that registers a mandatory after_specify hook (e.g. speckit-speclan; the registered hook is speckit.speclan.intake, optional: false, auto_execute_hooks: true in .specify/extensions.yml).
  3. In Claude Code (tested on the current release of Claude Opus 4.7), invoke /speckit-specify "<some natural-language brief>" — i.e. the interactive slash-command path.
  4. Observe: spec-kit's /specify creates specs/NNN-feature/spec.md and specs/NNN-feature/checklists/requirements.md correctly. No EXECUTE_COMMAND: directive is emitted and the hook command is never dispatched.

Empirical scan of the agent's debug log (Claude Code --debug-file):

grep -E 'EXECUTE_COMMAND|Extension Hooks|after_specify|extensions\.yml' debug.log
# → zero matches

The agent reached step 8 ("Report completion to the user") but never reached step 9 ("Check for extension hooks"). The result is a silently-broken integration from the user's perspective: they ran /speckit-specify, expected the bound extension to run as documented, and got nothing.

Why this happens

In commands/speckit-specify.md (and the parallel clarify, implement SKILL.md bodies), the hook-dispatch instruction is the last numbered step in a section that follows the heavy Execution → Validation → Completion flow. By the time the agent reaches it, attention has been spent on the spec authoring, the validation iterations, and the completion report. The hook step:

  • Is positioned where the agent's "work is done" pattern fires
  • Is prefixed by "After reporting completion" — natural language that signals optional follow-up
  • Lives in a block conditional on .specify/extensions.yml existing — extra decision the agent has to make

The current structure is correct as documentation but fragile as a dispatch mechanism. The miss rate is high enough that downstream extensions documenting after_specify as a usable hook are forced to add "if the hook didn't fire, run X manually" disclaimers to their READMEs.

Proposed Solution

Restructure the SKILL.md hook-dispatch instruction so it is structurally unmissable. Three changes, each independently helpful:

  1. Promote the hook block out of the numbered Execution list and into a top-level ## Mandatory Post-Execution Hooks H2, placed immediately after the spec-writing step and before the "Report completion" step. An H2 boundary is salient in a way that a numbered sub-step is not.

  2. For mandatory hooks (optional: false), use directive language at the top of the section: **You MUST emit EXECUTE_COMMAND: before reporting completion to the user.** followed by the conditional read of extensions.yml. The current "based on its optional flag" framing buries the mandatory cases.

  3. Cap the agent's task list with an explicit "Done When" checklist at the end of the SKILL.md that includes a Hooks dispatched (if .specify/extensions.yml present) item. A terminal checklist gives the model a structured opportunity to verify completion before exiting.

These changes preserve the interactive-vs-workflow distinction the project has already settled on. They do not introduce auto-run. They raise the reliability of the existing best-effort mechanism.

Alternatives Considered

  • Auto-run (already rejected in [Feature]: Automatically run extensions #2104). Not asking for this — workflow engine is the right answer for deterministic dispatch.
  • Move dispatch to a per-extension Step 0 in every core command. Too invasive; cascades to every spec-kit release.
  • Document "manual fallback" in every extension's README. Already the de-facto state; works, but degrades the value proposition of hooks for new extension authors.

Component

Specify CLI (initialization, commands) / Extensions

AI Agent (if applicable)

Claude Code (Claude Opus 4.7) — pattern is likely identical for Cursor / Codex / Gemini CLI because the SKILL.md is agent-agnostic; the failure mode is structural.

Use Cases

Any extension that registers an after_specify, after_clarify, or before_implement hook in the manifest and expects it to fire during the agent-driven slash-command flow. Current examples: SPECLAN spec-format conversion (intake), enterprise linting / AC-format validation (mentioned in #1788), pre-implementation policy gates.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions