Skip to content

[Bug]: /speckit-specify copies "the resolved spec-template file", which drops append-strategy preset layers #5177

Closed

Description

@greggy20

Bug Description

What happens. The specify command says:

  • 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
    When a preset provides spec-template with strategy: "append", no single file holds the resolved template. The core .specify/templates/spec-template.md doesn't have the preset section, and the preset's file has only that section. scripts/bash/resolve-template.sh composes the layers correctly, but the command tells the agent to copy a file. In practice the agent copies the core template, and the preset's section silently goes missing from new specs. /speckit-plan (setup-plan.sh → resolve_template_content) and /speckit-tasks (TASKS_TEMPLATE_CONTENT) already use composed content, so only specify is affected.

Steps to Reproduce

mkdir -p .specify/presets/example/templates
cat > .specify/presets/example/preset.yml <<'EOF'
schema_version: "1.0"
preset: {id: "example", name: "Example", version: "0.1.0", description: "append repro"}
provides:
  templates:
    - {type: "template", name: "spec-template", file: "templates/spec-addendum.md", description: "extra section", strategy: "append"}
EOF
printf '## Team Section\n\nTeam-specific fields.\n' > .specify/presets/example/templates/spec-addendum.md
# register "example" in .specify/presets/.registry (or install it with the preset CLI), then:
bash .specify/scripts/bash/resolve-template.sh spec-template --json | jq -r .TEMPLATE_CONTENT | grep -c '## Team Section'   # 1
grep -c '## Team Section' .specify/templates/spec-template.md                                                             # 0
grep -c '## Requirements' .specify/presets/example/templates/spec-addendum.md                                             # 0

Running /speckit-specify then gives a spec.md with no ## Team Section.

Expected Behavior

the new spec.md starts from the composed template: the core sections plus every append/prepend layer.

Actual Behavior

"The new spec.md contains only the core template. The append preset section is missing, and nothing warns about it."

Specify CLI Version

1.2.2 (still present in 1.2.5 and on main)

AI Agent

Claude Code

Operating System

Linux (WSL2)

Python Version

Run python3 --version wherever specify is installed. I couldn't check this, because the specify CLI isn't installed in this environment.

Error Logs

Additional Context

have the command run resolve-template.sh spec-template --json (or the PowerShell equivalent) and write TEMPLATE_CONTENT to spec.md, the way /speckit-tasks uses TASKS_TEMPLATE_CONTENT. Or add a setup script for specify that writes the composed file, like setup-plan.sh.

AI Disclosure

Found during an AI-assisted code review. I drafted and reproduced it with Claude Code, then reviewed and verified it myself.

Activity

  1. github-actions commented on Oct 29, 2026

    @github-actions
    Contributor

    Bug assessment — specify-template-append-layers: Valid · severity medium


    Bug Assessment: /speckit-specify drops append/prepend spec-template layers when it copies a file path

    Report (summarized)

    Issue author @greggy20 reports that /speckit-specify instructs the agent to copy a single resolved spec-template file into spec.md, which omits preset-provided append layers. They provided a concrete reproduction using a preset manifest entry with strategy: "append", where resolve-template.sh spec-template --json includes the appended section in TEMPLATE_CONTENT, but neither the core template file nor the preset addendum file alone contains the full composed template.

    No follow-up issue comments were present at assessment time.

    Symptom

    When a preset composes spec-template via append/prepend, running /speckit-specify can produce spec.md from a single file layer (typically core), so preset-composed sections are silently missing. Expected behavior is for spec.md to start from fully composed template content.

    Reproduction

    1. Configure a preset that provides spec-template with strategy: append and add a distinctive section (e.g., ## Team Section) in the addendum file.
    2. Verify composition output includes that section via scripts/bash/resolve-template.sh spec-template --json and TEMPLATE_CONTENT.
    3. Run /speckit-specify to generate a new spec.
    4. Observe spec.md does not include the appended section when the command follows the current “copy file” instruction.

    [NEEDS CLARIFICATION: exact agent/integration path used in the failing run (Copilot/Claude/Gemini command rendering), though the command template text itself is already sufficient to establish the defect.]

    Suspected Code Paths

    • templates/commands/specify.md:96-97 — instructs to resolve spec-template then “Copy the resolved spec-template file” to spec.md; this is the direct behavior mismatch for composed templates.
    • scripts/bash/common.sh:517 (resolve_template) — resolves to a single file path layer; using this for spec-template loses composed append/prepend/wrap semantics.
    • scripts/bash/common.sh:626 (resolve_template_content) — implements the actual composition stack (append/prepend/wrap/replace) and is the correct primitive for this flow.
    • scripts/bash/resolve-template.sh:38-56 — returns composed content as TEMPLATE_CONTENT; confirms the expected data shape for commands that need full template materialization.
    • scripts/bash/create-new-feature.sh:441-456 and scripts/python/create_new_feature.py:411 — both already create spec.md from composed resolve_template_content(...), showing prior-art behavior aligned with expected outcome.
    • scripts/bash/setup-plan.sh:48 and scripts/bash/setup-tasks.sh:54-55 — these paths already consume composed template content, matching the issue’s claim that the inconsistency is specific to /speckit-specify command instructions.

    Root Cause Hypothesis

    The /speckit-specify command template mixes “resolve through preset stack” language with a file-copy instruction that is only safe for pure replace stacks. In composed-template scenarios, there is no single canonical source file containing final content, so the instruction drives agents toward path-based resolution and drops additive layers. Confidence: high.

    Proposed Remediation

    Preferred: Update templates/commands/specify.md so spec generation uses composed content (TEMPLATE_CONTENT) from template resolution, not file-copy semantics. Concretely: instruct the command to run the existing template resolver (resolve-template script family / specify preset resolve ... --json equivalent), parse TEMPLATE_CONTENT, and write that content to SPECIFY_FEATURE_DIRECTORY/spec.md. Keep terminology consistent with other command templates that already require composed content.

    Also add a regression test that asserts the specify command template explicitly references composed content (and does not instruct copying a resolved file path), similar to existing assertions for constitution/checklist command templates in tests/test_presets.py.

    Alternatives (optional):

    • Route /speckit-specify to reuse create-new-feature script output as mandatory setup, then require the command to edit the created SPEC_FILE only. Trade-off: stronger determinism but tighter coupling between command prose and script contract.
    • Introduce a dedicated setup-specify script that emits SPEC_FILE + composed template content to unify shell/PowerShell/Python behavior. Trade-off: more moving parts than necessary if command-template correction is sufficient.

    Files likely to change:

    • templates/commands/specify.md
    • tests/test_presets.py (or another command-template assertion suite)
    • (if design chooses script-first setup) scripts/bash/create-new-feature.sh, scripts/powershell/create-new-feature.ps1, scripts/python/create_new_feature.py wiring/invocation docs only

    Tests to add or update:

    • A template-content regression test asserting specify command instructions consume composed template content (TEMPLATE_CONTENT) and avoid “copy resolved file” wording.
    • A negative assertion preventing future reintroduction of path-copy guidance in specify command text.

    Risks & Considerations

    • Changing command instructions affects agent behavior across integrations; wording must be synchronized where command variants are generated or overridden.
    • If some preset-specific command overrides bypass core templates/commands/specify.md, they may need equivalent updates to avoid divergent behavior.
    • Silent omission risk is process-quality impacting (requirements completeness), even though runtime/system safety impact is low.

    Open Questions

    • [NEEDS CLARIFICATION: Should /speckit-specify mandate the existing create-new-feature scripts as the only spec bootstrap path, or only update prose to require composed template content regardless of implementation path?]
    • [NEEDS CLARIFICATION: Are any shipped preset command overrides intentionally retaining file-copy semantics for backward compatibility, or should all be normalized to composed-content semantics now?]

    Generated by 🐛 Assess Bug from Labeled Issue for #5177 · copilot · gpt53codex · 30.8 AIC · ⌖ 0.604 AIC · ⊞ 22.4K · ◷

  2. added
    triage-must-haveVerdict: high-value, important work for Spec Kit — do first
    on Oct 29, 2026
  3. added a commit that references this issue on Oct 29, 2026
    a283c9d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions