specify init does not copy templates/commands/ to .specify/templates/commands/ — wrap composition strategy fails
- 主要言語
- 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