github / github/spec-kit

specify init does not copy templates/commands/ to .specify/templates/commands/ — wrap composition strategy fails

オープン
#3,086 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る
bug-assess severity-medium stale
主要言語
Python
スター
137k
フォーク
12.3k
平均マージ
2日 12時間
マージ済み PR(30日)
159

説明

## `specify init` does not copy `templates/commands/` to `.specify/templates/commands/`

### Problem

During `specify init`, the `install_shared_infra` function in `shared_infra.py` copies template files from the bundled `templates/` directory to `.specify/templates/`. However, it only processes **files** at the top level (`src.is_file()` check), skipping subdirectories — specifically `templates/commands/`.

This means the core command templates (e.g., `implement.md`, `specify.md`, `plan.md`, etc.) are installed directly to the agent directory (e.g., `.opencode/commands/speckit.implement.md`) via the integration system, but they are **not** kept in `.specify/templates/commands/` for the preset resolver to find.

### Impact

Preset authors who use the `wrap` composition strategy for command overrides (e.g., wrapping `speckit.implement` with a preamble) cannot resolve the core command as a base layer. The `PresetResolver.collect_all_layers()` method looks for core commands at:

```python
c = self.templates_dir / "commands" / f"{template_name}.md" # or stem fallback
```

Since `.specify/templates/commands/` doesn't exist after `specify init`, the resolver finds no base layer, composition fails, and the command is silently not registered (`registered_commands` stays empty `{}`).

### Reproduction

```bash
specify init --here --integration opencode --script sh --ignore-agent-tools
# .specify/templates/commands/ does NOT exist
# .opencode/commands/speckit.implement.md exists (installed by integration)

# Create a preset with a wrap strategy for speckit.implement
specify preset add --dev /path/to/my-preset
# registered_commands is {} — the wrap composition failed silently
```

### Workaround

Manually copy command templates after init:

```bash
mkdir -p .specify/templates/commands
cp /templates/commands/*.md .specify/templates/commands/
```

### Suggested fix

In `shared_infra.py`, the `install_shared_infra` function should also copy the `templates/commands/` subdirectory (with the same overwrite/manifest logic). Something like:

```python
# After the top-level template files loop:
commands_src = templates_src / "commands"
if commands_src.is_dir():
dest_commands = dest_templates / "commands"
if _ensure_or_bucket_dir(dest_commands):
for src_path in commands_src.iterdir():
if not src_path.is_file() or src_path.name.startswith("."):
continue
dst = dest_commands / src_path.name
rel = dst.relative_to(project_path).as_posix()
# ... same overwrite/manifest logic as above ...
```

Alternatively, the `PresetResolver` could fall back to reading core commands from the agent directory (e.g., `.opencode/commands/speckit.implement.md`) when `.specify/templates/commands/` doesn't have them.

### Environment

- Spec Kit v0.11.3
- macOS Darwin arm64
- Integration: opencode

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

shared_infra.py の install_shared_infra から始め、トップレベルのテンプレートがどのようにコピーされるかを確認してから、PresetResolver.collect_all_layers() とその templates/commands の検索処理を比較します。提供されている specify init コマンドと preset コマンドで再現します。.specify/templates/commands/ 配下でコマンドテンプレートが利用でき、wrap プリセットが合成されたコマンドを登録すれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
cli, tooling
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
活発
明瞭さ
明確に書かれている
初心者へのやさしさ
74/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。