Skip to content

[Bug]: preset wrap composition drops core argument-hint and leaks its value into description #3991

Description

@takaya0

Bug Description

When a preset overrides a core command with strategy: wrap and its command file's frontmatter declares only description (no argument-hint), the composed skill file loses the core command's argument-hint key — and the orphaned value string is concatenated into the description value. The result still parses as YAML, so the corruption is easy to miss, but the skill metadata is wrong (agents relying on description/argument-hint get a mangled description and no argument hint).

Steps to Reproduce

  1. Initialize a fresh project:

    mkdir demo && cd demo && git init -q && git commit -q --allow-empty -m init
    specify init --here --integration claude --script sh --ignore-agent-tools --force
    head -12 .claude/skills/speckit-specify/SKILL.md

    The core frontmatter contains both keys, e.g.:

    description: Create or update the feature specification from a natural language feature description.
    argument-hint: Describe the feature you want to specify
  2. Create a minimal wrap preset whose command frontmatter has only description and strategy (same layout as in the scaffold example):

    presets-src/demo-wrap/commands/speckit.specify.md

    ---
    description: "Wrapped speckit.specify"
    strategy: wrap
    ---
    
    <!-- demo preamble -->
    
    {CORE_TEMPLATE}

    (plus a matching preset.yml with provides.templates: [{type: command, name: speckit.specify, file: commands/speckit.specify.md, strategy: wrap}])

  3. Apply and inspect:

    specify preset add --dev ./presets-src/demo-wrap
    head -12 .claude/skills/speckit-specify/SKILL.md
    python3 -c "import yaml,io; f=open('.claude/skills/speckit-specify/SKILL.md'); t=f.read().split('---')[1]; print(yaml.safe_load(t))"

Expected Behavior

Core frontmatter keys that the preset does not explicitly override (such as argument-hint) should be inherited into the composed skill frontmatter, and description should contain exactly the preset's declared description.

Actual Behavior

Parsing the composed frontmatter shows:

  • the argument-hint key is gone, and
  • its value (Describe the feature you want to specify) appears inside the description string appended to the preset's description.

Because the YAML remains syntactically valid, nothing fails loudly; we only noticed because the agent's skill list started showing a fallback title instead of the intended description.

Workaround: explicitly repeating the core value in the preset command frontmatter (argument-hint: "Describe the feature you want to specify") produces a correct composition (this goes through the apply_argument_hint path added in #2978).

Specify CLI Version

0.15.2

AI Agent

Claude Code

Operating System

macOS 15 (Apple Silicon, Darwin 25.5.0)

Python Version

3.14.6

Additional Context

Related earlier work (all about argument-hint survival, but covering different cases):

Reading src/specify_cli/presets/__init__.py on current main, the wrap-composition layer inheritance appears to carry over only scripts / agent_scripts from the base layer, which would explain why argument-hint is not inherited; the leakage of the value into description suggests the frontmatter re-serialization also mis-attaches the orphaned value.

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