Skip to content
Merged
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
10 changes: 7 additions & 3 deletions templates/commands/specify.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ handoffs:
agent: speckit.clarify
prompt: Clarify specification requirements
send: true
scripts:
sh: scripts/bash/resolve-template.sh spec-template --json
ps: scripts/powershell/resolve-template.ps1 spec-template -Json
py: scripts/python/resolve_template.py spec-template --json
---

## User Input
Expand Down Expand Up @@ -92,9 +96,9 @@ Given that feature description, do this:
- If `branch_numbering` was used (and `feature_numbering` was absent), emit a one-line warning: "⚠️ `branch_numbering` in init-options.json is deprecated. Rename to `feature_numbering`."

**Create the directory and spec file**:
- Run `{SCRIPT}` from the repository root and parse `TEMPLATE_CONTENT` as the active `spec-template`. The shared resolver composes project overrides, preset layers, and extension layers over the core template, including `append`, `prepend`, and `wrap` strategies. If it fails, stop and report the resolution error; do not continue with only one contributing template layer.
- `mkdir -p SPECIFY_FEATURE_DIRECTORY`
- Resolve the active `spec-template` through the Spec Kit preset/template resolution stack (equivalent to `specify preset resolve spec-template`)
- Copy the resolved `spec-template` file to `SPECIFY_FEATURE_DIRECTORY/spec.md` as the starting point
- Write `TEMPLATE_CONTENT` to `SPECIFY_FEATURE_DIRECTORY/spec.md` as the starting point. Do not copy a template file from disk instead: when a preset composes `spec-template`, no single file holds the full template.
- Set `SPEC_FILE` to `SPECIFY_FEATURE_DIRECTORY/spec.md`
- Persist the resolved path to `.specify/feature.json`:
```json
Expand All @@ -110,7 +114,7 @@ Given that feature description, do this:
- 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

4. Load the resolved active `spec-template` file to understand required sections.
4. Use `TEMPLATE_CONTENT` to understand required sections.

5. **IF EXISTS**: Load `/memory/constitution.md` for project principles and governance constraints.

Expand Down
7 changes: 5 additions & 2 deletions tests/integrations/test_integration_copilot.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,11 @@ def test_specify_agent_resolves_active_spec_template(self, tmp_path):
specify_file = tmp_path / ".github" / "agents" / "speckit.specify.agent.md"
content = specify_file.read_text(encoding="utf-8")

assert "specify preset resolve spec-template" in content
assert "resolved active `spec-template`" in content
assert "resolve-template" in content
assert "{SCRIPT}" not in content
assert "parse `TEMPLATE_CONTENT` as the active `spec-template`" in content
assert "Write `TEMPLATE_CONTENT` to `SPECIFY_FEATURE_DIRECTORY/spec.md`" in content
assert "Copy the resolved `spec-template` file" not in content
assert "Copy `.specify/templates/spec-template.md`" not in content
assert "Load `.specify/templates/spec-template.md`" not in content

Expand Down
15 changes: 15 additions & 0 deletions tests/test_presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,21 @@ def test_core_checklist_command_resolves_template_at_runtime():
assert "Use TEMPLATE_CONTENT as the structural template" in content


def test_core_specify_command_writes_composed_spec_template():
"""The specify command must start spec.md from the composed spec-template."""
content = (CORE_CONSTITUTION_COMMAND.parent / "specify.md").read_text(
encoding="utf-8"
)

assert "resolve-template.sh spec-template --json" in content
assert "resolve-template.ps1 spec-template -Json" in content
assert "resolve_template.py spec-template --json" in content
assert "parse `TEMPLATE_CONTENT` as the active `spec-template`" in content
assert "Write `TEMPLATE_CONTENT` to `SPECIFY_FEATURE_DIRECTORY/spec.md`" in content
assert "do not continue with only one contributing template layer" in content
assert "Copy the resolved `spec-template` file" not in content


class TestLeanPreset:
"""Tests for the lean preset that ships with the repo."""

Expand Down
Loading