fix: resolve command references per integration type (dot vs hyphen) (#2354)

* fix: resolve command references per integration type (dot vs hyphen)

Replace hardcoded /speckit.<cmd> references in templates with
__SPECKIT_COMMAND_<NAME>__ placeholders that are resolved at
setup time based on the integration type:

- Markdown/TOML/YAML agents: separator='.' → /speckit.plan
- Skills agents: separator='-' → /speckit-plan

Changes:
- Add resolve_command_refs() static method to IntegrationBase
- Add invoke_separator class attribute (.  for base, - for skills)
- Wire into process_template() as step 8
- Update _install_shared_infra() to process page templates
- Replace /speckit.* in 5 command templates and 3 page templates
- Add unit tests for resolve_command_refs (positive + negative)
- Add integration tests verifying on-disk content for all agents
- Add end-to-end CLI tests for Claude (skills) and Copilot (markdown)

Fixes #2347

* review: use effective_invoke_separator() for Copilot skills mode

Address PR review feedback: instead of bleeding _skills_mode
knowledge into the CLI layer, add effective_invoke_separator()
method to IntegrationBase that accepts parsed_options.

CopilotIntegration overrides it to return "-" when skills
mode is requested. The CLI layer simply asks the integration
for its separator — no hasattr or _skills_mode coupling.

Also adds tests for the new method on both base and Copilot,
plus an end-to-end test for 'specify init --integration copilot
--integration-options --skills' verifying page templates get
hyphen refs.

* fix: build_command_invocation preserves full suffix for extension commands

Previously rsplit('.', 1)[-1] on 'speckit.git.commit' yielded
just 'commit', producing /speckit.commit instead of
/speckit.git.commit (or /speckit-git-commit for skills).

Fix: strip only the 'speckit.' prefix when present, then join
remaining segments with the appropriate separator.

Updated in IntegrationBase, SkillsIntegration, and
CopilotIntegration. Added tests for extension commands in
build_command_invocation across all three.

* fix: Copilot dispatch_command() preserves full extension command suffix

dispatch_command() had the same rsplit('.', 1)[-1] bug as
build_command_invocation() — speckit.git.commit would dispatch
as /speckit-commit instead of /speckit-git-commit in skills
mode, or --agent speckit.commit instead of speckit.git.commit
in default mode.
This commit is contained in:
Manfred Riem
2026-04-24 10:04:14 -05:00
committed by GitHub
parent 6413414907
commit 52c0a5f88f
21 changed files with 434 additions and 55 deletions

View File

@@ -4,13 +4,13 @@
**Created**: [DATE]
**Feature**: [Link to spec.md or relevant documentation]
**Note**: This checklist is generated by the `/speckit.checklist` command based on feature context and requirements.
**Note**: This checklist is generated by the `__SPECKIT_COMMAND_CHECKLIST__` command based on feature context and requirements.
<!--
============================================================================
IMPORTANT: The checklist items below are SAMPLE ITEMS for illustration only.
The /speckit.checklist command MUST replace these with actual items based on:
The __SPECKIT_COMMAND_CHECKLIST__ command MUST replace these with actual items based on:
- User's specific checklist request
- Feature requirements from spec.md
- Technical context from plan.md

View File

@@ -49,13 +49,13 @@ You **MUST** consider the user input before proceeding (if not empty).
## Goal
Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `/speckit.tasks` has successfully produced a complete `tasks.md`.
Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `__SPECKIT_COMMAND_TASKS__` has successfully produced a complete `tasks.md`.
## Operating Constraints
**STRICTLY READ-ONLY**: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually).
**Constitution Authority**: The project constitution (`/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `/speckit.analyze`.
**Constitution Authority**: The project constitution (`/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `__SPECKIT_COMMAND_ANALYZE__`.
## Execution Steps
@@ -191,9 +191,9 @@ Output a Markdown report (no file writes) with the following structure:
At end of report, output a concise Next Actions block:
- If CRITICAL issues exist: Recommend resolving before `/speckit.implement`
- If CRITICAL issues exist: Recommend resolving before `__SPECKIT_COMMAND_IMPLEMENT__`
- If only LOW/MEDIUM: User may proceed, but provide improvement suggestions
- Provide explicit command suggestions: e.g., "Run /speckit.specify with refinement", "Run /speckit.plan to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'"
- Provide explicit command suggestions: e.g., "Run __SPECKIT_COMMAND_SPECIFY__ with refinement", "Run __SPECKIT_COMMAND_PLAN__ to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'"
### 8. Offer Remediation

View File

@@ -249,7 +249,7 @@ You **MUST** consider the user input before proceeding (if not empty).
- Actor/timing
- Any explicit user-specified must-have items incorporated
**Important**: Each `/speckit.checklist` command invocation uses a short, descriptive checklist filename and either creates a new file or appends to an existing one. This allows:
**Important**: Each `__SPECKIT_COMMAND_CHECKLIST__` command invocation uses a short, descriptive checklist filename and either creates a new file or appends to an existing one. This allows:
- Multiple checklists of different types (e.g., `ux.md`, `test.md`, `security.md`)
- Simple, memorable filenames that indicate checklist purpose

View File

@@ -55,7 +55,7 @@ You **MUST** consider the user input before proceeding (if not empty).
Goal: Detect and reduce ambiguity or missing decision points in the active feature specification and record the clarifications directly in the spec file.
Note: This clarification workflow is expected to run (and be completed) BEFORE invoking `/speckit.plan`. If the user explicitly states they are skipping clarification (e.g., exploratory spike), you may proceed, but must warn that downstream rework risk increases.
Note: This clarification workflow is expected to run (and be completed) BEFORE invoking `__SPECKIT_COMMAND_PLAN__`. If the user explicitly states they are skipping clarification (e.g., exploratory spike), you may proceed, but must warn that downstream rework risk increases.
Execution steps:
@@ -63,7 +63,7 @@ Execution steps:
- `FEATURE_DIR`
- `FEATURE_SPEC`
- (Optionally capture `IMPL_PLAN`, `TASKS` for future chained flows.)
- If JSON parsing fails, abort and instruct user to re-run `/speckit.specify` or verify feature branch environment.
- If JSON parsing fails, abort and instruct user to re-run `__SPECKIT_COMMAND_SPECIFY__` or verify feature branch environment.
- For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
2. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).
@@ -202,13 +202,13 @@ Execution steps:
- Path to updated spec.
- Sections touched (list names).
- Coverage summary table listing each taxonomy category with Status: Resolved (was Partial/Missing and addressed), Deferred (exceeds question quota or better suited for planning), Clear (already sufficient), Outstanding (still Partial/Missing but low impact).
- If any Outstanding or Deferred remain, recommend whether to proceed to `/speckit.plan` or run `/speckit.clarify` again later post-plan.
- If any Outstanding or Deferred remain, recommend whether to proceed to `__SPECKIT_COMMAND_PLAN__` or run `__SPECKIT_COMMAND_CLARIFY__` again later post-plan.
- Suggested next command.
Behavior rules:
- If no meaningful ambiguities found (or all potential questions would be low-impact), respond: "No critical ambiguities detected worth formal clarification." and suggest proceeding.
- If spec file missing, instruct user to run `/speckit.specify` first (do not create a new spec here).
- If spec file missing, instruct user to run `__SPECKIT_COMMAND_SPECIFY__` first (do not create a new spec here).
- Never exceed 5 total asked questions (clarification retries for a single question do not count as new questions).
- Avoid speculative tech stack questions unless the absence blocks functional clarity.
- Respect user early termination signals ("stop", "done", "proceed").

View File

@@ -169,7 +169,7 @@ You **MUST** consider the user input before proceeding (if not empty).
- Confirm the implementation follows the technical plan
- Report final status with summary of completed work
Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `/speckit.tasks` first to regenerate the task list.
Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `__SPECKIT_COMMAND_TASKS__` first to regenerate the task list.
10. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root.
- If it exists, read it and look for entries under the `hooks.after_implement` key

View File

@@ -54,7 +54,7 @@ You **MUST** consider the user input before proceeding (if not empty).
## Outline
The text the user typed after `/speckit.specify` in the triggering message **is** the feature description. Assume you always have it available in this conversation even if `{ARGS}` appears literally below. Do not ask the user to repeat it unless they provided an empty command.
The text the user typed after `__SPECKIT_COMMAND_SPECIFY__` in the triggering message **is** the feature description. Assume you always have it available in this conversation even if `{ARGS}` appears literally below. Do not ask the user to repeat it unless they provided an empty command.
Given that feature description, do this:
@@ -100,10 +100,10 @@ Given that feature description, do this:
}
```
Write the actual resolved directory path value (for example, `specs/003-user-auth`), not the literal string `SPECIFY_FEATURE_DIRECTORY`.
This allows downstream commands (`/speckit.plan`, `/speckit.tasks`, etc.) to locate the feature directory without relying on git branch name conventions.
This allows downstream commands (`__SPECKIT_COMMAND_PLAN__`, `__SPECKIT_COMMAND_TASKS__`, etc.) to locate the feature directory without relying on git branch name conventions.
**IMPORTANT**:
- You must only create one feature per `/speckit.specify` invocation
- You must only create one feature per `__SPECKIT_COMMAND_SPECIFY__` invocation
- The spec directory name and the git branch name are independent — they may be the same but that is the user's choice
- The spec directory and file are always created by this command, never by the hook
@@ -174,7 +174,7 @@ Given that feature description, do this:
## Notes
- Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`
- Items marked incomplete require spec updates before `__SPECKIT_COMMAND_CLARIFY__` or `__SPECKIT_COMMAND_PLAN__`
```
b. **Run Validation Check**: Review the spec against each checklist item:
@@ -232,7 +232,7 @@ Given that feature description, do this:
- `SPECIFY_FEATURE_DIRECTORY` — the feature directory path
- `SPEC_FILE` — the spec file path
- Checklist results summary
- Readiness for the next phase (`/speckit.clarify` or `/speckit.plan`)
- Readiness for the next phase (`__SPECKIT_COMMAND_CLARIFY__` or `__SPECKIT_COMMAND_PLAN__`)
9. **Check for extension hooks**: After reporting completion, check if `.specify/extensions.yml` exists in the project root.
- If it exists, read it and look for entries under the `hooks.after_specify` key

View File

@@ -3,7 +3,7 @@
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow.
**Note**: This template is filled in by the `__SPECKIT_COMMAND_PLAN__` command. See `.specify/templates/plan-template.md` for the execution workflow.
## Summary
@@ -39,12 +39,12 @@
```text
specs/[###-feature]/
├── plan.md # This file (/speckit.plan command output)
├── research.md # Phase 0 output (/speckit.plan command)
├── data-model.md # Phase 1 output (/speckit.plan command)
├── quickstart.md # Phase 1 output (/speckit.plan command)
├── contracts/ # Phase 1 output (/speckit.plan command)
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
├── plan.md # This file (__SPECKIT_COMMAND_PLAN__ command output)
├── research.md # Phase 0 output (__SPECKIT_COMMAND_PLAN__ command)
├── data-model.md # Phase 1 output (__SPECKIT_COMMAND_PLAN__ command)
├── quickstart.md # Phase 1 output (__SPECKIT_COMMAND_PLAN__ command)
├── contracts/ # Phase 1 output (__SPECKIT_COMMAND_PLAN__ command)
└── tasks.md # Phase 2 output (__SPECKIT_COMMAND_TASKS__ command - NOT created by __SPECKIT_COMMAND_PLAN__)
```
### Source Code (repository root)

View File

@@ -29,7 +29,7 @@ description: "Task list template for feature implementation"
============================================================================
IMPORTANT: The tasks below are SAMPLE TASKS for illustration purposes only.
The /speckit.tasks command MUST replace these with actual tasks based on:
The __SPECKIT_COMMAND_TASKS__ command MUST replace these with actual tasks based on:
- User stories from spec.md (with their priorities P1, P2, P3...)
- Feature requirements from plan.md
- Entities from data-model.md