Skip to content

fix: wire after_tasks and after_implement hook events into command templates#1702

Merged
mnriem merged 4 commits intogithub:mainfrom
mnriem:fix/extension-hooks-not-triggered
Mar 4, 2026
Merged

fix: wire after_tasks and after_implement hook events into command templates#1702
mnriem merged 4 commits intogithub:mainfrom
mnriem:fix/extension-hooks-not-triggered

Conversation

@mnriem
Copy link
Collaborator

@mnriem mnriem commented Feb 26, 2026

Summary

Fixes #1701.

The HookExecutor class in extensions.py was fully implemented but check_hooks_for_event() was never invoked - the core command templates had no instructions to check .specify/extensions.yml. Hooks silently did nothing after every command run.

Changes

  • templates/commands/tasks.md: added step 6 - after_tasks hook check
  • templates/commands/implement.md: added step 10 - after_implement hook check
  • pyproject.toml: version bump 0.1.6 to 0.1.7
  • CHANGELOG.md: entry for [0.1.7]

Testing

  1. Create an extension with an after_tasks hook and install it
  2. Confirm hook is registered in .specify/extensions.yml
  3. Run /speckit.tasks - the hook message should now appear at the end of the output

…mplates (github#1701)

The HookExecutor backend in extensions.py was fully implemented but
check_hooks_for_event() was never called by anything — the core command
templates had no instructions to check .specify/extensions.yml.

Add a final step to templates/commands/tasks.md (step 6, after_tasks) and
templates/commands/implement.md (step 10, after_implement) that instructs
the AI agent to:

- Read .specify/extensions.yml if it exists
- Filter hooks.{event} to enabled: true entries
- Evaluate any condition fields and skip non-matching hooks
- Output the RFC-specified hook message format, including
  EXECUTE_COMMAND: markers for mandatory (optional: false) hooks

Bumps version to 0.1.7.
Copilot AI review requested due to automatic review settings February 26, 2026 16:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes issue #1701 by wiring extension hooks into command templates. The HookExecutor class in extensions.py was fully implemented but never invoked - core command templates had no instructions to check .specify/extensions.yml. This meant hooks silently did nothing after command completion. The fix adds step-by-step instructions to tasks.md and implement.md templates to read the extensions config, filter enabled hooks, evaluate conditions, and output the appropriate hook messages (including EXECUTE_COMMAND: markers for mandatory hooks).

Changes:

  • Added hook checking instructions to tasks.md (step 6) and implement.md (step 10) templates
  • Version bump from 0.1.6 to 0.1.7 with corresponding changelog entry
  • Templates now parse .specify/extensions.yml and output formatted hook messages for AI agents to execute

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
templates/commands/tasks.md Added step 6 to check for after_tasks hooks after task generation completes
templates/commands/implement.md Added step 10 to check for after_implement hooks after implementation validation
pyproject.toml Version bump from 0.1.6 to 0.1.7
CHANGELOG.md Added entry for version 0.1.7 documenting the hook wiring fix

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…emplates

- Replace ambiguous "evaluate any condition value" instruction with explicit
  guidance to skip hooks with non-empty conditions, deferring evaluation to
  HookExecutor
- Add instruction to skip hook checking silently if extensions.yml cannot
  be parsed or is invalid
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@dhilipkumars dhilipkumars left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a QQ.

@dhilipkumars
Copy link
Contributor

I have pushed two new commits directly addressing the review comments!

  1. feat(templates): implement before-hooks check as pre-execution phase: Added the new before_implement and before_tasks blocks to the templates. Crucially, to prevent breaking the API continuity of the Outline numbering, this was implemented as a new ## Pre-Execution Checks block immediately prior to the Outline.
  2. test(hooks): create scenario for LLMs/Agents on hooks: Created tests/hooks/ mapping mock extension logic that explicitly tests evaluating both pre-hooks and post-hooks. You can use Copilot on this directory according to the TESTING.md specs to verify.

* feat(templates): implement before-hooks check as pre-execution phase

* test(hooks): create scenario for LLMs/Agents on hooks
Copilot AI review requested due to automatic review settings March 4, 2026 13:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (2)

templates/commands/implement.md:180

  • This section also skips hooks with non-empty condition, which will disable all conditional after_implement hooks unless condition evaluation is implemented somewhere else. Align behavior with HookExecutor’s condition support instead of skipping.
    - For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
      - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
      - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation

templates/commands/tasks.md:35

  • These instructions skip any hook with a non-empty condition, but the templates never invoke HookExecutor.check_hooks_for_event(). That means conditional hooks will never execute. Either implement condition evaluation here (matching HookExecutor’s supported patterns) or include conditional hooks in the output so they can still be executed when conditions are met.
- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
  - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
  - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
- For each executable hook, output the following based on its `optional` flag:

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mnriem mnriem merged commit d0a112c into github:main Mar 4, 2026
12 checks passed
@mnriem
Copy link
Collaborator Author

mnriem commented Mar 4, 2026

@dhilipkumars Thanks for the help! Appreciate it bunches.

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.

Extension hooks (after_tasks, after_implement) are never triggered

3 participants