mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 20:36:23 +08:00
* feat(extensions): per-event hook lists with priority ordering The manifest validator restricted each hook event to a single mapping, even though HookExecutor stores entries as a list per event. This blocked an extension from running multiple commands on one event (e.g. a verification step plus a doc-generation step after speckit.plan), and get_hooks_for_event returned entries in raw insertion order with no way to influence execution order across or within extensions. This change: 1. Validator: accept hooks.<event> as either a single mapping or a list of mappings. Each entry is validated individually and may carry an optional integer `priority` (>= 1, default 10; bool rejected). 2. Command-ref normalization: apply rename / alias->canonical rewriting to every entry in the list, not just the head. 3. register_hooks: expand list entries, persist `priority`, and purge-and-replace all entries owned by the extension on each event so a reinstall whose shape changed (single<->list, or a shorter list) leaves no orphaned entries behind. 4. get_hooks_for_event: sort enabled entries by `priority` ascending with a stable sort (ties keep insertion order). The existing normalize_priority helper is reused as the sort key so corrupted on-disk values fall back to the default instead of raising. Backward compatible: existing single-mapping manifests parse and register unchanged with priority defaulting to 10. The extension-level `priority` used by preset/template resolution is independent of the new hook-entry `priority`. Implements #2378 * fix(extensions): harden register_hooks per PR review - Skip non-dict hook entries before .get() so a manifest that bypasses validation can't crash register_hooks with AttributeError. - Normalize `priority` on save via normalize_priority so the on-disk config stays clean, mirroring the read-side defense in get_hooks_for_event. - Tests: cover the non-dict-entry skip and add encoding="utf-8" to the new tests' manifest writes. * fix(extensions): purge dropped-event hook orphans on reinstall register_hooks only purged events the new manifest still declared, so an extension that dropped an event on reinstall left stale entries for it in the project config. Purge this extension's entries from undeclared events (and prune emptied events) before registering; scoped to this extension, and a no-op for the install/update flow where unregister_hooks runs first. * fix(extensions): reject boolean priority and complete orphan purge - normalize_priority falls back to default for bool values - dedup deletes duplicate commands before re-insert for last-wins ties - register_hooks purges orphans even when all hooks are dropped * docs(extensions): document per-event hook lists and priority - EXTENSION-API-REFERENCE: hook event accepts a mapping or list; add priority field reference and last-wins dedup note - EXTENSION-DEVELOPMENT-GUIDE: add list-form example with priority * docs(extensions): show both single and list hook forms in schema snippet * docs(extensions): reference DEFAULT_HOOK_PRIORITY in normalize_priority normalize_priority hard-coded the default as the literal 10 in both its signature and docstring, duplicating DEFAULT_HOOK_PRIORITY. Reference the constant in the signature and drop the literal from the docstring so the default has a single source of truth.
Extension Template
Starter template for creating a Spec Kit extension.
Quick Start
-
Copy this template:
cp -r extensions/template my-extension cd my-extension -
Customize
extension.yml:- Change extension ID, name, description
- Update author and repository
- Define your commands
-
Create commands:
- Add command files in
commands/directory - Use Markdown format with YAML frontmatter
- Add command files in
-
Create config template:
- Define configuration options
- Document all settings
-
Write documentation:
- Update README.md with usage instructions
- Add examples
-
Test locally:
cd /path/to/spec-kit-project specify extension add --dev /path/to/my-extension -
Publish (optional):
- Create GitHub repository
- Create release
- Submit to catalog (see EXTENSION-PUBLISHING-GUIDE.md)
Files in This Template
extension.yml- Extension manifest (CUSTOMIZE THIS)config-template.yml- Configuration template (CUSTOMIZE THIS)commands/example.md- Example command (REPLACE THIS)README.md- Extension documentation (REPLACE THIS)LICENSE- MIT License (REVIEW THIS)CHANGELOG.md- Version history (UPDATE THIS).gitignore- Git ignore rules
Customization Checklist
- Update
extension.ymlwith your extension details - Change extension ID to your extension name
- Update author information
- Define your commands
- Create command files in
commands/ - Update config template
- Write README with usage instructions
- Add examples
- Update LICENSE if needed
- Test extension locally
- Create git repository
- Create first release
Need Help?
- Development Guide: See EXTENSION-DEVELOPMENT-GUIDE.md
- API Reference: See EXTENSION-API-REFERENCE.md
- Publishing Guide: See EXTENSION-PUBLISHING-GUIDE.md
- User Guide: See EXTENSION-USER-GUIDE.md
Template Version
- Version: 1.0.0
- Last Updated: 2026-01-28
- Compatible with Spec Kit: >=0.1.0