Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion extensions/EXTENSION-API-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -631,10 +631,23 @@ Or for mandatory hooks:

```markdown
**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```

Here `{invocation}` is the environment-correct command form: usually `/{command}`, but
skills-mode sessions render it as e.g. `/skill:speckit-*` or `$speckit-*`.

> **Dispatch contract**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI
> orchestrators that watch agent output — emitting it does not execute anything by
> itself. Because the agent cannot reliably tell whether such an orchestrator is
> present, it is instructed to invoke the hook itself and wait for the result. It does
> so using the `EXECUTE_COMMAND_INVOCATION:` line, which carries the environment-correct
> invocation (skills mode renders it as e.g. `/skill:speckit-*` or `$speckit-*` rather
> than `/<command>`). Extension authors should not assume an external dispatcher will
> pick up the directive.
Comment thread
Quratulain-bilal marked this conversation as resolved.

---

## CLI Commands
Expand Down
15 changes: 15 additions & 0 deletions src/specify_cli/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3057,6 +3057,21 @@ def format_hook_message(
lines.append(f"Executing: `{display_invocation}`")
lines.append(f"EXECUTE_COMMAND: {command_text}")
lines.append(f"EXECUTE_COMMAND_INVOCATION: {display_invocation}")
# The directive lines above are only a dispatch signal for
# CLI orchestrators that watch agent output; emitting them
# does not run anything. The agent cannot reliably tell
# whether such an orchestrator is present, so the contract is
# unconditional: invoke the hook yourself. ``display_invocation``
# is the environment-correct form (skills mode renders e.g.
# ``/skill:speckit-*`` rather than ``/<command>``). Without
# this, mandatory hooks are silently skipped (issue #2730).
lines.append(
"\nEmitting the EXECUTE_COMMAND directive above does not "
"run the hook. You MUST now invoke the hook yourself using "
f"`{display_invocation}` (the invocation shown on the "
"EXECUTE_COMMAND_INVOCATION line) and wait for it to "
"complete before continuing."
)

return "\n".join(lines)

Expand Down
10 changes: 8 additions & 2 deletions templates/commands/analyze.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Goal.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Goal
Expand Down Expand Up @@ -225,9 +228,12 @@ After reporting, check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Operating Principles
Expand Down
10 changes: 8 additions & 2 deletions templates/commands/checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Execution Steps.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Execution Steps
Expand Down Expand Up @@ -360,7 +363,10 @@ Check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
12 changes: 9 additions & 3 deletions templates/commands/clarify.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Outline.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Outline
Expand Down Expand Up @@ -248,9 +251,12 @@ Check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- **Optional hook** (`optional: true`):
```
## Extension Hooks
Expand Down Expand Up @@ -278,5 +284,5 @@ Report completion (after questioning loop ends or early termination):

- [ ] Spec ambiguities identified and clarifications integrated into spec file
- [ ] Spec quality checklist re-validated against updated spec (if `FEATURE_DIR/checklists/requirements.md` exists)
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above (mandatory hooks actually invoked and completed — emitting `EXECUTE_COMMAND:` alone does not count as dispatched)
- [ ] Completion reported to user with questions answered, sections touched, checklist status, and coverage summary
10 changes: 8 additions & 2 deletions templates/commands/constitution.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Outline.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Outline
Expand Down Expand Up @@ -144,7 +147,10 @@ Check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
12 changes: 9 additions & 3 deletions templates/commands/implement.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Outline.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Outline
Expand Down Expand Up @@ -189,9 +192,12 @@ Check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- **Optional hook** (`optional: true`):
```
## Extension Hooks
Expand All @@ -212,5 +218,5 @@ Report final status with summary of completed work.

- [ ] All tasks in tasks.md completed and marked `[X]`
- [ ] Implementation validated against specification, plan, and test coverage
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above (mandatory hooks actually invoked and completed — emitting `EXECUTE_COMMAND:` alone does not count as dispatched)
- [ ] Completion reported to user with summary of completed work
12 changes: 9 additions & 3 deletions templates/commands/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Outline.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Outline
Expand Down Expand Up @@ -88,9 +91,12 @@ Check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- **Optional hook** (`optional: true`):
```
## Extension Hooks
Expand Down Expand Up @@ -167,5 +173,5 @@ Command ends after Phase 2 planning. Report branch, IMPL_PLAN path, and generate
## Done When

- [ ] Plan workflow executed and design artifacts generated
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above (mandatory hooks actually invoked and completed — emitting `EXECUTE_COMMAND:` alone does not count as dispatched)
- [ ] Completion reported to user with branch, plan path, and generated artifacts
12 changes: 9 additions & 3 deletions templates/commands/specify.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ You **MUST** consider the user input before proceeding (if not empty).
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}

Wait for the result of the hook command before proceeding to the Outline.
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before proceeding.
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Outline
Expand Down Expand Up @@ -249,9 +252,12 @@ Check if `.specify/extensions.yml` exists in the project root.
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
Executing: `{invocation}`
EXECUTE_COMMAND: {command}
EXECUTE_COMMAND_INVOCATION: {invocation}
```
- Here `{invocation}` is the command form for the current environment: usually `/{command}`, but skills-mode sessions render it differently (e.g. `/skill:speckit-*` or `$speckit-*`). Use the same value for both the `Executing:` and `EXECUTE_COMMAND_INVOCATION:` lines.
- **Dispatch contract for mandatory hooks**: the `EXECUTE_COMMAND:` line is only a dispatch signal for CLI orchestrators that watch agent output — emitting it does not run anything. You MUST then invoke the hook yourself using `{invocation}` (the value on the `EXECUTE_COMMAND_INVOCATION:` line) and wait for its result before reporting completion.
- **Optional hook** (`optional: true`):
```
## Extension Hooks
Expand Down Expand Up @@ -338,5 +344,5 @@ Success criteria must be:
## Done When

- [ ] Specification written to `SPEC_FILE` and validated against quality checklist
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above
- [ ] Extension hooks dispatched or skipped according to the rules in Mandatory Post-Execution Hooks above (mandatory hooks actually invoked and completed — emitting `EXECUTE_COMMAND:` alone does not count as dispatched)
- [ ] Completion reported to user with feature directory, spec file path, and checklist results
Loading