feat(presets): pluggable preset system with template/command overrides, catalog, and resolver

- Rename 'template packs' to 'presets' to avoid naming collision with core templates
- PresetManifest, PresetRegistry, PresetManager, PresetCatalog, PresetResolver in presets.py
- Extract CommandRegistrar to agents.py as shared infrastructure
- CLI: specify preset list/add/remove/search/resolve/info
- CLI: specify preset catalog list/add/remove
- --preset option on specify init
- Priority-based preset stacking (--priority, lower = higher precedence)
- Command overrides registered into all detected agent directories (17+ agents)
- Extension command safety: skip registration if target extension not installed
- Multi-catalog support: env var, project config, user config, built-in defaults
- resolve_template() / Resolve-Template in bash/PowerShell scripts
- Self-test preset: overrides all 6 core templates + 1 command
- Scaffold with 4 examples: core/extension template and command overrides
- Preset catalog (catalog.json, catalog.community.json)
- Documentation: README.md, ARCHITECTURE.md, PUBLISHING.md
- 110 preset tests, 253 total tests passing
This commit is contained in:
Manfred Riem
2026-03-10 14:17:44 -05:00
parent 6003a232d8
commit abf4aebdb3
32 changed files with 4671 additions and 2458 deletions

View File

@@ -0,0 +1,46 @@
# My Preset
A custom preset for Spec Kit. Copy this directory and customize it to create your own.
## Templates Included
| Template | Type | Description |
|----------|------|-------------|
| `spec-template` | template | Custom feature specification template (overrides core and extensions) |
| `myext-template` | template | Override of the myext extension's report template |
| `speckit.specify` | command | Custom specification command (overrides core) |
| `speckit.myext.myextcmd` | command | Override of the myext extension's myextcmd command |
## Development
1. Copy this directory: `cp -r presets/scaffold my-preset`
2. Edit `preset.yml` — set your preset's ID, name, description, and templates
3. Add or modify templates in `templates/`
4. Test locally: `specify preset add --dev ./my-preset`
5. Verify resolution: `specify preset resolve spec-template`
6. Remove when done testing: `specify preset remove my-preset`
## Manifest Reference (`preset.yml`)
Required fields:
- `schema_version` — always `"1.0"`
- `preset.id` — lowercase alphanumeric with hyphens
- `preset.name` — human-readable name
- `preset.version` — semantic version (e.g. `1.0.0`)
- `preset.description` — brief description
- `requires.speckit_version` — version constraint (e.g. `>=0.1.0`)
- `provides.templates` — list of templates with `type`, `name`, and `file`
## Template Types
- **template** — Document scaffolds (spec-template.md, plan-template.md, tasks-template.md, etc.)
- **command** — AI agent workflow prompts (e.g. speckit.specify, speckit.plan)
- **script** — Custom scripts (reserved for future use)
## Publishing
See the [Preset Publishing Guide](../PUBLISHING.md) for details on submitting to the catalog.
## License
MIT

View File

@@ -0,0 +1,20 @@
---
description: "Override of the myext extension's myextcmd command"
---
<!-- Preset override for speckit.myext.myextcmd -->
You are following a customized version of the myext extension's myextcmd command.
When executing this command:
1. Read the user's input from $ARGUMENTS
2. Follow the standard myextcmd workflow
3. Additionally, apply the following customizations from this preset:
- Add compliance checks before proceeding
- Include audit trail entries in the output
> CUSTOMIZE: Replace the instructions above with your own.
> This file overrides the command that the "myext" extension provides.
> When this preset is installed, all agents (Claude, Gemini, Copilot, etc.)
> will use this version instead of the extension's original.

View File

@@ -0,0 +1,23 @@
---
description: "Create a feature specification (preset override)"
scripts:
sh: scripts/bash/create-new-feature.sh "{ARGS}"
ps: scripts/powershell/create-new-feature.ps1 "{ARGS}"
---
## User Input
```text
$ARGUMENTS
```
Given the feature description above:
1. **Create the feature branch** by running the script:
- Bash: `{SCRIPT} --json --short-name "<short-name>" "<description>"`
- The JSON output contains BRANCH_NAME and SPEC_FILE paths.
2. **Read the spec-template** to see the sections you need to fill.
3. **Write the specification** to SPEC_FILE, replacing the placeholders in each section
(Overview, Requirements, Acceptance Criteria) with details from the user's description.

View File

@@ -0,0 +1,91 @@
schema_version: "1.0"
preset:
# CUSTOMIZE: Change 'my-preset' to your preset ID (lowercase, hyphen-separated)
id: "my-preset"
# CUSTOMIZE: Human-readable name for your preset
name: "My Preset"
# CUSTOMIZE: Update version when releasing (semantic versioning: X.Y.Z)
version: "1.0.0"
# CUSTOMIZE: Brief description (under 200 characters)
description: "Brief description of what your preset provides"
# CUSTOMIZE: Your name or organization name
author: "Your Name"
# CUSTOMIZE: GitHub repository URL (create before publishing)
repository: "https://github.com/your-org/spec-kit-preset-my-preset"
# REVIEW: License (MIT is recommended for open source)
license: "MIT"
# Requirements for this preset
requires:
# CUSTOMIZE: Minimum spec-kit version required
speckit_version: ">=0.1.0"
# Templates provided by this preset
provides:
templates:
# CUSTOMIZE: Define your template overrides
# Templates are document scaffolds (spec-template.md, plan-template.md, etc.)
- type: "template"
name: "spec-template"
file: "templates/spec-template.md"
description: "Custom feature specification template"
replaces: "spec-template" # Which core template this overrides (optional)
# ADD MORE TEMPLATES: Copy this block for each template
# - type: "template"
# name: "plan-template"
# file: "templates/plan-template.md"
# description: "Custom plan template"
# replaces: "plan-template"
# OVERRIDE EXTENSION TEMPLATES:
# Presets sit above extensions in the resolution stack, so you can
# override templates provided by any installed extension.
# For example, if the "myext" extension provides a spec-template,
# the preset's version above will take priority automatically.
# Override a template provided by the "myext" extension:
- type: "template"
name: "myext-template"
file: "templates/myext-template.md"
description: "Override myext's report template"
replaces: "myext-template"
# Command overrides (AI agent workflow prompts)
# Presets can override both core and extension commands.
# Commands are automatically registered into all detected agent
# directories (.claude/commands/, .gemini/commands/, etc.)
# Override a core command:
- type: "command"
name: "speckit.specify"
file: "commands/speckit.specify.md"
description: "Custom specification command"
replaces: "speckit.specify"
# Override an extension command (e.g. from the "myext" extension):
- type: "command"
name: "speckit.myext.myextcmd"
file: "commands/speckit.myext.myextcmd.md"
description: "Override myext's myextcmd command with custom workflow"
replaces: "speckit.myext.myextcmd"
# Script templates (reserved for future use)
# - type: "script"
# name: "create-new-feature"
# file: "scripts/bash/create-new-feature.sh"
# description: "Custom feature creation script"
# replaces: "create-new-feature"
# CUSTOMIZE: Add relevant tags (2-5 recommended)
# Used for discovery in catalog
tags:
- "example"
- "preset"

View File

@@ -0,0 +1,24 @@
# MyExt Report
> This template overrides the one provided by the "myext" extension.
> Customize it to match your needs.
## Summary
Brief summary of the report.
## Details
- Detail 1
- Detail 2
## Actions
- [ ] Action 1
- [ ] Action 2
<!--
CUSTOMIZE: This template takes priority over the myext extension's
version of myext-template. The extension's original is still available
if you remove this preset.
-->

View File

@@ -0,0 +1,18 @@
# Feature Specification: [FEATURE NAME]
**Created**: [DATE]
**Status**: Draft
## Overview
[Brief description of the feature]
## Requirements
- [ ] Requirement 1
- [ ] Requirement 2
## Acceptance Criteria
- [ ] Criterion 1
- [ ] Criterion 2