* Update preset-fiction-book-writing to community catalog
- Preset ID: fiction-book-writing
- Version: 1.5.0
- Author: Andreas Daumann
- Description: Spec-Driven Development for novel and long-form fiction. Replaces software engineering terminology with storytelling craft: specs become story briefs, plans become story structures, and tasks become scene-by-scene writing tasks. Supports 8 POV modes, all major plot structure frameworks, 5 humanized-AI prose profiles, and exports to DOCX/EPUB/LaTeX via pandoc. V1.5.0: Support interactive, audiobooks, series, workflow corrections
* Add fiction-book-writing preset to community catalog
- Preset ID: fiction-book-writing
- Version: 1.6.0
- Author: Andreas Daumann
- Description: Added support for 12 languages, export with templates, cover builder, bio builder, workflow fixes
* Update presets/catalog.community.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fixed update_at for fiction-book-writing preset
* Update README.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fixed description for fiction-book-writing
* "Add fiction-book-preset to community catalog
- Preset ID: fiction-book-writing
- Version: 1.7.0
- Author: Andreas Daumann
- Description: It adapts the Spec-Driven Development workflow for storytelling to create books or audiobooks (with annotations) in 12 languages: features become story elements, specs become story briefs, plans become story structures, and tasks become scene-by-scene writing tasks. Supports single and multi-POV, all major plot structure frameworks, and two style modes: an author voice sample or humanized AI prose. Supports interactive elements like brainstorming, interview, roleplay and extras like statistics, cover builder and bio command. Export with templates for KDP, D2D etc. V1.7.0: Support for offline semantic search.
* Update presets/catalog.community.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update presets/catalog.community.json
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add fiction-book-writing to community catalog
- Preset ID: fiction-book-writing
- Version: 1.7.0
- Author: Andreas Daumann
- Description: Spec-Driven Development for novel and long-form fiction. RAG support
* Update docs/community/presets.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix(extensions): use explicit UTF-8 encoding when reading manifest YAML
On Windows, Python's open() defaults to the system locale encoding
(e.g., GBK on Chinese Windows), which causes UnicodeDecodeError when
extension.yml or preset.yml contains non-ASCII content such as Chinese
characters in description fields.
Add encoding='utf-8' to ExtensionManifest._load_yaml and
PresetManifest._load_yaml so manifests are read consistently across
platforms.
Fixes#2325
* test(extensions,presets): add UTF-8 manifest regression tests for #2325
Positive: extension.yml/preset.yml with non-ASCII (Chinese + emoji)
descriptions load correctly when written as UTF-8 bytes — fails on
Windows without explicit encoding='utf-8'.
Negative: files containing invalid UTF-8 bytes raise a clean error
(ValidationError or UnicodeDecodeError), not a silent crash.
* fix(extensions,presets): wrap I/O and decode errors as ValidationError
Address remaining Copilot concerns on #2370:
- Catch UnicodeDecodeError and OSError in both manifest loaders and
re-raise as ValidationError / PresetValidationError so callers see a
consistent error type, not a bare decode/IO traceback.
- Validate that PresetManifest YAML root is a mapping (extensions.py
already had this; presets.py was missing it). Treat None as {} for
empty-file compatibility.
- Tighten the negative regression tests to assert the specific message,
and add a non-mapping-root test for PresetManifest matching the
existing one for ExtensionManifest.
Add Microsoft 365 Integration to community catalog and README.
Ingests Teams messages, files, and meeting transcripts as Markdown
for use with speckit specify.
* docs: replace deprecated --ai flag with --integration in all documentation
Replace all user-facing --ai, --ai-skills, and --ai-commands-dir references
with their modern equivalents:
- --ai <agent> → --integration <agent>
- --ai-skills → --integration-options="--skills"
- --ai-commands-dir <dir> → --integration generic --integration-options="--commands-dir <dir>"
Updated files:
- README.md (~17 occurrences)
- docs/installation.md (~8 occurrences)
- docs/upgrade.md (~11 occurrences)
- docs/local-development.md (~5 occurrences)
- CONTRIBUTING.md (1 occurrence)
- extensions/EXTENSION-USER-GUIDE.md (1 occurrence)
- src/specify_cli/__init__.py (docstring examples and error messages)
Left unchanged:
- CHANGELOG.md (historical record)
- Test files (intentionally exercise deprecated flag path)
- CLI flag implementation (backward compatibility)
Closes#2358
* docs: address review feedback on pre-existing issues
- Fix duplicate copilot example in README.md (replace with codex)
- Fix invalid gemini --integration-options="--skills" example (gemini
does not support --skills)
- Update generic integration comment from 'Unsupported agent' to
'Bring your own agent; requires --commands-dir'
- Clarify EXTENSION-USER-GUIDE.md: skills auto-register for
skills-based integrations, not only with --integration-options
* docs: replace bare 'AI agent' / 'AI assistant' with 'coding agent' throughout
Full sweep across all documentation and user-facing CLI messages to
align terminology. Bare references like 'AI agent', 'AI assistant',
and 'AI Agent' are replaced with 'coding agent' or 'coding agent
integration' as appropriate.
Intentionally left unchanged:
- 'AI coding agent' (already correct expanded form)
- Deprecated --ai flag help text and error messages (describes the
deprecated flag itself)
- Community extension descriptions (external project text)
- 'generated by an AI' in CONTRIBUTING.md (general AI, not agent)
* docs: address review — remove deprecated --offline, qualify --skills scope
- Remove --offline from docstring examples (deprecated no-op)
- Remove --offline from CONTRIBUTING.md testing example
- Replace --offline instructions in docs/installation.md with note that
bundled assets are used by default
- Qualify --integration-options="--skills" in README.md to note it only
applies to integrations that support skills mode
* feat(extensions,presets): authenticate GitHub-hosted catalog and download requests with GITHUB_TOKEN/GH_TOKEN
Squashed from #2087 (original author: @anasseth).
Adds GitHub-token authentication to extension and preset catalog fetching
and ZIP downloads so private GitHub repos work when GITHUB_TOKEN/GH_TOKEN
is set, while preventing credential leakage to non-GitHub hosts.
- Introduces shared _github_http module with build_github_request() and
open_github_url() helpers
- Routes ExtensionCatalog and PresetCatalog network calls through
GitHub-auth-aware opener
- Adds comprehensive unit/integration tests for auth header behavior
- Updates user docs for both extensions and presets
Co-authored-by: anasseth <16745089+anasseth@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(auth): address review feedback from #2087
- Fix redirect handler to preserve Authorization on GitHub-to-GitHub
redirects (e.g. github.com → codeload.github.com). The previous
implementation relied on super().redirect_request() which strips
auth on cross-host redirects, breaking private repo archive downloads.
- Add codeload.github.com to documented host lists in both
EXTENSION-USER-GUIDE.md and presets/README.md
- Add redirect auth-preservation and auth-stripping tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(auth): use Bearer scheme instead of token for consistency
Aligns with the rest of the codebase (e.g. __init__.py:1721) and
GitHub's current API guidance. Updates all test assertions accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: address second round of Copilot review feedback
- Fix docstring to say Bearer instead of token (matches implementation)
- Remove unused imports/fixtures from redirect tests (GITHUB_HOSTS,
MagicMock, temp_dir, monkeypatch)
- Replace __import__('io').BytesIO() with normal import io pattern
in test_presets.py
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: anasseth <16745089+anasseth@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(init): deprecate --no-git flag, gate deprecations at v0.10.0
- Add deprecation warning when --no-git is used on specify init
- Update --ai deprecation gate from 1.0.0 to 0.10.0
- Update test expectation for the new version gate
Closes#2167
* fix: address PR review feedback
- Update --no-git deprecation message to reference existing 'specify extension'
commands instead of non-existent --extension flag
- Add test_no_git_emits_deprecation_warning CLI test
* fix: strengthen --no-git deprecation test assertions
Add assertions unique to the --no-git message ('will be removed',
'git extension will no longer be enabled by default') to prevent
false positives from the --ai deprecation panel.
* chore: bump version to 0.8.1
* chore: begin 0.8.2.dev0 development
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(vibe): migrate to SkillsIntegration and inject user-invocable frontmatter
Switches VibeIntegration from the old prompts-based MarkdownIntegration to SkillsIntegration, adopting the .vibe/skills/speckit-<name>/SKILL.md layout required by Mistral Vibe v2.0.0+. Post-processes each generated SKILL.md to inject `user-invocable: true` so skills are directly callable by users, not just by other agents.
* test(vibe): assert user- invocable: true is present in all generated SKILL.md files
* Update tests/integrations/test_integration_vibe.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* docs: move community presets table to docs site, add missing entries
- Move the full community presets table from README.md to the docs site
at docs/community/presets.md, replacing the README section with a
short link (matching the pattern used for Walkthroughs and Friends).
- Add missing Jira Issue Tracking and Screenwriting rows to the docs
table so it reflects all entries in catalog.community.json.
* docs(presets): add docs site table step to publishing guide
Add step to update docs/community/presets.md when submitting a
community preset, and add corresponding PR checklist item. Matches
the pattern used in the extensions publishing guide.
* Clarify alphabetical sort key in presets publishing guide
Specify that the docs table should be sorted by preset name (the first
column), disambiguating from the catalog JSON which sorts by preset ID.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Address review: fix provides count, admonition style, example row
- Add missing scripts count to Fiction Book Writing table row to match catalog
- Switch README disclaimer to GitHub admonition format for consistency
- Include optional scripts count in PUBLISHING.md example row
* Fix Fiction Book Writing link text to match actual repo name
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* docs(presets): add lean preset README and enrich catalog metadata
- Add README.md documenting the lean workflow preset, its commands,
when to use it, and development instructions.
- Add license, requires.speckit_version, and provides.commands fields
to the lean preset catalog entry.
- Add "core" tag to preset.yml for discoverability.
* fix: bump catalog updated_at and add provides.templates for consistency
Address PR review feedback:
- Bump updated_at to reflect catalog modification time
- Add provides.templates (0) to lean preset entry for consistency
with catalog schema used in catalog.community.json
* fix: resolve command references per integration type (dot vs hyphen)
Replace hardcoded /speckit.<cmd> references in templates with
__SPECKIT_COMMAND_<NAME>__ placeholders that are resolved at
setup time based on the integration type:
- Markdown/TOML/YAML agents: separator='.' → /speckit.plan
- Skills agents: separator='-' → /speckit-plan
Changes:
- Add resolve_command_refs() static method to IntegrationBase
- Add invoke_separator class attribute (. for base, - for skills)
- Wire into process_template() as step 8
- Update _install_shared_infra() to process page templates
- Replace /speckit.* in 5 command templates and 3 page templates
- Add unit tests for resolve_command_refs (positive + negative)
- Add integration tests verifying on-disk content for all agents
- Add end-to-end CLI tests for Claude (skills) and Copilot (markdown)
Fixes#2347
* review: use effective_invoke_separator() for Copilot skills mode
Address PR review feedback: instead of bleeding _skills_mode
knowledge into the CLI layer, add effective_invoke_separator()
method to IntegrationBase that accepts parsed_options.
CopilotIntegration overrides it to return "-" when skills
mode is requested. The CLI layer simply asks the integration
for its separator — no hasattr or _skills_mode coupling.
Also adds tests for the new method on both base and Copilot,
plus an end-to-end test for 'specify init --integration copilot
--integration-options --skills' verifying page templates get
hyphen refs.
* fix: build_command_invocation preserves full suffix for extension commands
Previously rsplit('.', 1)[-1] on 'speckit.git.commit' yielded
just 'commit', producing /speckit.commit instead of
/speckit.git.commit (or /speckit-git-commit for skills).
Fix: strip only the 'speckit.' prefix when present, then join
remaining segments with the appropriate separator.
Updated in IntegrationBase, SkillsIntegration, and
CopilotIntegration. Added tests for extension commands in
build_command_invocation across all three.
* fix: Copilot dispatch_command() preserves full extension command suffix
dispatch_command() had the same rsplit('.', 1)[-1] bug as
build_command_invocation() — speckit.git.commit would dispatch
as /speckit-commit instead of /speckit-git-commit in skills
mode, or --agent speckit.commit instead of speckit.git.commit
in default mode.
* Update product-forge to v1.5.0 in community catalog
- Extension ID: product-forge
- Version: 1.1.1 → 1.5.0
- Author: VaiYav
- Description: updated to reflect v1.5 features (portfolio, lite mode,
monorepo, optional V-Model)
- Commands: 10 → 29
- Tags: refreshed to reflect current surface area
- download_url pinned to v1.5.0 release tag
- updated_at bumped to 2026-04-24
Release: https://github.com/VaiYav/speckit-product-forge/releases/tag/v1.5.0
* Bump product-forge to v1.5.1 (docs patch)
Follow-up to v1.5.0 that surfaces the optional V-Model dependency
(leocamello/spec-kit-v-model ≥ 0.5.0) in README Requirements,
config-template.yml, and docs/config.md. Docs-only patch — no
behavioural change.
Release: https://github.com/VaiYav/speckit-product-forge/releases/tag/v1.5.1
xargs re-parses stdin as shell tokens, causing 'unterminated quote'
errors when feature descriptions contain apostrophes, double quotes,
or backslashes. Replace with sed-based whitespace trim that preserves
input verbatim.
Add regression tests for special characters in descriptions (core and
extension scripts), plus a negative test for whitespace-only input.
Fixes#2339
* feat: register jira preset in community catalog
Adds luno/spec-kit-preset-jira — overrides speckit.taskstoissues to
create Jira issues instead of GitHub Issues.
See #2223 for context on why this is a preset rather than an extension.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use immutable tag URL and sort jira preset alphabetically
- Change download_url from heads/main to refs/tags/v1.0.0 for reproducible installs
- Move jira entry to correct alphabetical position in presets object
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Ed Harrod <1381991+echarrod@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* chore: bump version to 0.8.0
* chore: begin 0.8.1.dev0 development
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* fix: rebase onto upstream/main, resolve conflicts with PR #2189
upstream/main merged PR #2189 (wrap-only strategy) which overlaps with
our comprehensive composition strategies (prepend/append/wrap). Resolved
conflicts keeping our implementation as source of truth:
- README: keep our future considerations (composition is now fully
implemented, not a future item)
- presets.py: keep our composition architecture (_reconcile_composed_commands,
collect_all_layers, resolve_content) while preserving #2189's
_substitute_core_template which is used by agents.py for skill
generation
- tests: keep both test sets (our composition tests + #2189's wrap
tests), removed TestReplayWrapsForCommand and
TestInstallRemoveWrapLifecycle which test the superseded
_replay_wraps_for_command API; our composition tests cover equivalent
scenarios
- Restored missing _unregister_commands call in remove() that was lost
during #2189 merge
* fix: re-create skill directory in _reconcile_skills after removal
After _unregister_skills removes a skill directory, _register_skills
skips writing because the dir no longer passes the is_dir() check.
Fix by ensuring the skill subdirectory exists before calling
_register_skills so the next winning preset's content gets registered.
Fixes the Claude E2E failure where removing a top-priority override
preset left skill-based agents without any SKILL.md file.
* fix: address twenty-third round of Copilot PR review feedback
- Protect reconciliation in remove(): wrap _reconcile_composed_commands
and _reconcile_skills in try/except so failures emit a warning instead
of leaving the project in an inconsistent state
- Protect reconciliation in install(): same pattern for post-install
reconciliation so partial installs don't lack cleanup
- Inherit scripts/agent_scripts from base frontmatter: when composing
commands, merge scripts and agent_scripts keys from the base command's
frontmatter into the top layer's frontmatter if missing, preventing
composed commands from losing required script references
- Add tier-5 bundled core fallback to collect_all_layers(): check the
bundled core_pack (wheel) or repo-root templates (source checkout) when
.specify/templates/ doesn't contain the core file, matching resolve()'s
tier-5 fallback so composition can always find a base layer
* fix: address twenty-fourth round of Copilot PR review feedback
- Use yaml.safe_load for frontmatter parsing in resolve_content instead
of CommandRegistrar.parse_frontmatter which uses naive find('---',3);
strip strategy key from final frontmatter to prevent leaking internal
composition directives into rendered agent command files
- Filter _reconcile_skills to specific commands: use _FilteredManifest
wrapper so only the commands being reconciled get their skills updated,
preventing accidental overwrites of other commands' skills that may be
owned by higher-priority presets
* fix: address twenty-fifth round of Copilot PR review feedback
- Support legacy command-frontmatter strategy: when preset.yml doesn't
declare a strategy, check the command file's YAML frontmatter for
strategy: wrap as a fallback so legacy wrap presets participate in
composition and multi-preset chaining
- Guard skill dir creation in _reconcile_skills: only re-create the
skill directory if the skill was previously managed (listed in some
preset's registered_skills), avoiding creation of new skill dirs
that _register_skills would normally skip
* fix: add explanatory comment to empty except in legacy frontmatter parsing
* fix: address twenty-sixth round of Copilot PR review feedback
- Unregister stale commands when composition fails: when resolve_content
returns None during reconciliation (base layer removed), unregister
the command from non-skill agents and emit a warning
- Load extension aliases during reconciliation: _register_command_from_path
now checks extension.yml for aliases when the winning layer is an
extension, so alias files are restored after preset removal
- Use line-based fence detection for legacy frontmatter strategy fallback:
scan for --- on its own line instead of split('---',2) to avoid
mis-parsing YAML values containing ---
* fix: address twenty-seventh round of Copilot PR review feedback
- Handle non-preset winners in _reconcile_skills: when the winning
layer is core/extension/project-override, restore skills via
_unregister_skills so skill-based agents stay consistent with the
priority stack
- Update base_frontmatter_text on replace layers: when a higher-priority
replace layer occurs during composition, update both top and base
frontmatter so scripts/agent_scripts inheritance reflects the
effective base beneath the top composed layer
* fix: address twenty-eighth round of Copilot PR review feedback
- Parse only interior lines in _parse_fm_yaml: use lines[1:-1] instead
of filtering all --- lines, preventing corruption when YAML values
contain a line that is exactly ---
- Omit empty frontmatter: skip re-rendering when top_fm is empty dict
to avoid emitting ---/{}/--- for intentionally empty frontmatter
- Update scaffold wrap comment: mention both {CORE_TEMPLATE} and
$CORE_SCRIPT placeholders for templates/commands vs scripts
- Clarify shell composition scope in ARCHITECTURE.md: note that bash/PS1
resolve_template_content only handles templates; command/script
composition is handled by the Python resolver
* fix: address twenty-ninth round of Copilot PR review feedback
- Fix TestCollectAllLayers docstring: reference collect_all_layers()
- Add default/unknown strategy handling in bash/PS1 composition: error
on unrecognized strategy values instead of silently skipping
- Fix comment: .composed/ is a persistent dir, not temporary
- Fix comment: legacy fallback checks all valid strategies, not just wrap
- Cache PresetRegistry in _reconcile_skills: build presets_by_priority
once instead of constructing registry per-command
* fix: address thirtieth round of Copilot PR review feedback
- Guard legacy frontmatter fallback: only check command file frontmatter
for strategy when the manifest entry doesn't explicitly include the
strategy key, preventing override of manifest-declared strategies
- Document rollback limitation: note that mid-registration failures may
leave orphaned agent command files since partial progress isn't
captured by the local vars
* fix: handle project override skills and extension context in reconciliation
* fix: add comment to empty except in extension registration fallback
* fix: filter extension commands in reconciliation and fix type annotation
* fix: filter extension commands from post-install reconciliation
Apply the same extension-installed check used in _register_commands to
the reconciliation command list, preventing reconciliation from
registering commands for extensions that are not installed.
* fix: skip convention fallback for explicit file paths and add stem fallback to tier-5
When a preset manifest provides an explicit file path that does not
exist, skip the convention-based fallback to avoid masking typos.
Also add speckit.<stem> to <stem>.md fallback in tier-5 bundled/source
core lookup for consistency with tier-4.
* fix: scan past non-replace layers to find base in resolve_content
The base-finding scan now skips non-replace layers below a replace
layer instead of stopping at the first non-replace. This fixes the
case where a low-priority append/prepend layer sits below a replace
that should serve as the base for composition.
* fix: add context_note to non-skill agent registration for extensions
Add context_note parameter to register_commands_for_non_skill_agents
and pass extension name/id during reconciliation so rendered command
files preserve the extension-specific context markers.
* fix: Optional type, rollback safety, and override skill restoration
- Fix context_note type to Optional[str]
- Wrap shutil.rmtree in try/except during install rollback
- Separate override-backed skills from core/extension in _reconcile_skills
* fix: align bash/PS1 base-finding with Python resolver
Rewrite bash and PowerShell composition loops to find the effective
base replace layer first (scanning bottom-up, skipping non-replace
layers below it), then compose only from the base upward. This
prevents evaluation of irrelevant lower layers (e.g. a wrap with
no placeholder below a replace) and matches resolve_content behavior.
* fix: PS1 no-python warning, integration hook for override skills, alias cleanup
- Warn when no Python 3 found in PS1 and presets use composition strategies
- Apply post_process_skill_content integration hook when restoring
override-backed skills so agent-specific flags are preserved
- Unregister command aliases alongside primary name when composition
fails to prevent orphaned alias files
* fix: include aliases in removed_cmd_names during preset removal
Read aliases from preset manifest before deleting pack_dir so alias
command files are included in unregistration and reconciliation.
* fix: add comment to empty except in alias extraction during removal
* fix: scan top-down for effective base in all resolvers
Change base-finding to scan from highest priority downward to find the
nearest replace layer, then compose only layers above it. Prevents
evaluation of irrelevant lower layers (e.g. a wrap without placeholder
below a higher-priority replace) across Python, bash, and PowerShell.
* fix: align CLI composition chain display with top-down base-finding
Show only contributing layers (base and above) in preset resolve
output, matching resolve_content top-down semantics. Layers below
the effective base are omitted since they do not contribute.
* fix: guard corrupted registry entries and make manifest authoritative
- Add isinstance(meta, dict) guard in bash registry parsing so corrupted
entries are skipped instead of breaking priority ordering
- Only use convention-based file lookup when the manifest does not list
the requested template, making preset.yml authoritative and preventing
stray on-disk files from creating unintended layers
* fix: align resolve() with manifest file paths and match extension context_note
- Update resolve() preset tier to consult manifest file paths before
convention-based lookup, matching collect_all_layers behavior
- Use exact extension context_note format matching extensions.CommandRegistrar
- Update test to declare template in manifest (authoritative manifest)
* revert: restore resolve() convention-based behavior for backwards compatibility
resolve() is the existing public API used by shell scripts and other
callers. Changing it to manifest-authoritative breaks backward compat
for presets that rely on convention-based file lookup. Only the new
collect_all_layers/resolve_content path uses manifest-authoritative
logic.
* fix: only pre-compose when this preset is the top composing layer
Skip composition in _register_commands when a higher-priority replace
layer already wins for the command. Register the raw file instead and
let reconciliation write the correct final content.
* fix: deduplicate PyYAML warnings and use self.registry in reconciliation
- Emit PyYAML-missing warning once per function call in bash/PS1 instead
of per-preset to avoid spamming stderr
- Use self.registry.list_by_priority() in reconciliation methods instead
of constructing new PresetRegistry instances to avoid redundant I/O
and potential consistency issues
* fix: document strategy handling consistency between layers and registrar
Composed output already strips strategy from frontmatter (resolve_content
pops it). Raw file registration preserves legacy frontmatter strategy
for backward compat; reconciliation corrects the final state.
* fix: correct stale comments for alias tracking and base-finding algorithm
* security: validate manifest file paths in bash/PowerShell resolvers
Reject absolute paths and parent directory traversal (..) in the
manifest-declared file field before joining with the preset directory.
Matches the Python-side validation in PresetManifest._validate().
---------
Co-authored-by: Manfred Riem <15701806+mnriem@users.noreply.github.com>
* Initial plan
* feat(copilot): add --skills flag for skills-based scaffolding
Add --skills integration option to CopilotIntegration that scaffolds
commands as speckit-<name>/SKILL.md under .github/skills/ instead of
the default .agent.md + .prompt.md layout.
- Add options() with --skills flag (default=False)
- Branch setup() between default and skills modes
- Add post_process_skill_content() for Copilot-specific mode: field
- Adjust build_command_invocation() for skills mode (/speckit-<stem>)
- Update dispatch_command() with skills mode detection
- Parse --integration-options during init command
- Add 22 new skills-mode tests
- All 15 existing default-mode tests continue to pass
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/a4903fab-64ff-46c3-8eb8-a47f495a70c0
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* docs(AGENTS.md): document Copilot --skills option
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/a4903fab-64ff-46c3-8eb8-a47f495a70c0
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* Potential fix for pull request finding 'Unused local variable'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* fix: address PR #2324 review feedback
- Reset _skills_mode at start of setup() to prevent singleton state leak
- Tighten skills auto-detection to require speckit-*/SKILL.md (not any
non-empty .github/skills/ directory)
- Add copilot_skill_mode to init next-steps so skills mode renders
/speckit-plan instead of /speckit.plan
- Fix docstring quoting to match actual unquoted output
- Add 4 tests covering singleton reset, auto-detection false positive,
speckit layout detection, and next-steps skill syntax
- Fix skipped test_invalid_metadata_error_returns_unknown by simulating
InvalidMetadataError on Python versions that lack it
* fix: inline skills prompt in dispatch_command auto-detection path
build_command_invocation() reads self._skills_mode which stays False
when skills mode is only auto-detected from the project layout. Inline
the /speckit-<stem> prompt construction so dispatch_command() sends the
correct prompt regardless of how skills mode was detected.
Also strengthen test_dispatch_detects_speckit_skills_layout to assert
the -p prompt contains /speckit-plan and the user args.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* docs(install): add pipx as alternative installation method
- Add pipx commands to README.md installation section
- Add note about pipx compatibility to docs/installation.md
- Mention pipx persistent installation in docs/quickstart.md
- Add pipx upgrade instructions to docs/upgrade.md
- Clarify that project has no uv-specific dependencies
Refs: https://github.com/github/spec-kit/discussions/2255
* docs(install): address Copilot feedback - update prerequisites and upgrade references for pipx
* Update docs/quickstart.md
markdownlint’s MD012 (enabled in this repo) flags multiple consecutive blank lines
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update docs/upgrade.md
In the Quick Reference table, the label “pipx upgrade” is misleading because the command shown is `pipx install --force ...` (a reinstall). by copilot.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: --force now overwrites shared infra files during init and upgrade
_install_shared_infra() previously skipped all existing files under
.specify/scripts/ and .specify/templates/, regardless of --force.
This meant users could never receive upstream fixes to shared scripts
or templates after initial project setup.
Changes:
- Add force parameter to _install_shared_infra(); when True, existing
files are overwritten with the latest bundled versions
- Wire force=True through specify init --here --force and
specify integration upgrade --force call sites
- Replace hidden logging.warning with visible console output listing
skipped files and suggesting --force
- Fix contradictory upgrade docs that claimed --force updated shared
infra (it didn't) and warned about overwrites (they didn't happen)
- Add 6 tests: unit tests for skip/overwrite/warning behavior, plus
end-to-end CLI tests for both --force and non-force paths
Fixes#2319
* fix: improve skip warning to suggest specific commands
Address review feedback: the generic '--force' suggestion was
misleading when _install_shared_infra is called from integration
install/switch (which don't have a --force for shared infra).
Now points users to the specific commands that can refresh shared
infra: 'specify init --here --force' or 'specify integration
upgrade --force'.
* chore: bump version to 0.7.5
* chore: begin 0.7.6.dev0 development
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat(cli): add specify self check and self upgrade stub (#2282)
Introduce a new `specify self` Typer sub-app with two subcommands.
`specify self check` performs a read-only lookup against the GitHub Releases
API, compares the installed version to the latest tag with PEP 440 semantics,
and prints one of four verdicts (newer-available, up-to-date, indeterminate,
graceful-failure). When a newer stable release is available, the output
includes a copy-pasteable `uv tool install --force --from git+...@<tag>`
reinstall command. `GH_TOKEN` / `GITHUB_TOKEN` is attached as a bearer
credential when set so users behind shared IPs escape the anonymous 60/hour
rate limit.
`specify self upgrade` is a documented non-destructive stub in this release:
three-line guidance output, exit 0, no outbound call, no install-method
detection. The real destructive implementation is planned as follow-up work.
Failure categorization is a fixed three-entry enum (offline or timeout,
rate limited, HTTP <code>). Anything outside those three categories
propagates as a non-zero exit so bugs surface instead of being silently
swallowed. No machine-readable output, no retries, no caching in this
release — see issue #2282 discussion.
Tests mock `urllib.request.urlopen`; the suite performs zero real network
calls. Full regression suite: 1586 passed.
* fix(cli): disable Rich highlight for deterministic output
Rich's default `highlight=True` applies ANSI color to detected patterns
(integers, version strings, paths) whenever stdout is deemed a TTY.
This caused intermittent failures in existing pytest assertions in
tests/test_cli_version.py and tests/test_extensions.py::TestExtensionRemoveCLI
that compare plain-text output without passing through `strip_ansi()`.
Setting `Console(highlight=False)` globally makes all CLI output
deterministic and fixes the flake without modifying the affected tests.
The numeric cyan highlighting was not a documented part of the CLI
visual contract.
* fix: address copilot review feedback
* fix: tighten self-check token handling
* fix: align self-check helpers and script metadata
* fix: harden self-check version handling
* fix: guard self-check failure rendering
Move the community presets table from the main README to a dedicated
docs/community/presets.md page, matching the pattern used for
walkthroughs and friends.
- Add docs/community/presets.md with the full presets table
- Add Claude AskUserQuestion preset (was in catalog but missing from table)
- Add Presets entry to docs/toc.yml under Community
- Replace inline README table with a short link to the docs page
* catalog: add wireframe extension
Adds https://github.com/TortoiseWolfe/spec-kit-extension-wireframe
(v0.1.0) to the community catalog. Provides a visual feedback loop
for spec-driven development: SVG wireframe generation, review, and
sign-off. Approved wireframes become spec constraints honored by
/plan, /tasks, and /implement.
Supersedes #1410 — the old PR predated the extension system
introduced in #2130 and proposed commands in templates/commands/,
which is no longer the right home for third-party commands.
* catalog: address review feedback (position + author)
Two changes per Copilot review:
- Move `wireframe` entry alphabetically between `whatif` and
`worktree` (was appended after `worktrees`).
- Simplify `author` from "TortoiseWolfe (turtlewolfe.com)" to
just "TortoiseWolfe" so the exact-match author filter in
`ExtensionCatalog.search` finds the entry. Portfolio URL
remains accessible via `homepage`/`repository`.
Thanks @Copilot, @mnriem for the review.
* docs(readme): add Wireframe Visual Feedback Loop row
Addresses @mnriem's follow-up: the README extension table also
needs an entry, not just the catalog JSON. Slots in alphabetically
between "What-if Analysis" and "Worktree Isolation" with category
`visibility` and Read+Write effect (since sign-off writes the
approved wireframe paths into spec.md).
* catalog: use speckit-prefixed command names in wireframe description
Address remaining Copilot review comment on PR #2262. The actual
commands are /speckit.plan, /speckit.tasks, /speckit.implement;
the unprefixed names would mislead catalog users.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* catalog: bump wireframe extension to v0.1.1
v0.1.1 of spec-kit-extension-wireframe ships the /speckit.-prefixed
command references in extension.yml and README.md. This updates the
catalog entry to point at the new release tag so `specify extension
add wireframe` installs the corrected version.
* catalog: set wireframe created_at to current timestamp
Per EXTENSION-PUBLISHING-GUIDE.md: newly added entries should use
the current timestamp for both created_at and updated_at. The 04-17
value reflected when I drafted the entry locally, not when the
catalog submission landed.
---------
Co-authored-by: TortoiseWolfe <jonpohlner@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Move community walkthroughs from README to docs/community
Extract the community walkthroughs section from README.md into its own
docs/community/walkthroughs.md file and replace it with a short summary
linking to the GitHub Pages URL.
* Address review: fix double-See phrasing, add walkthroughs to docs nav
Follow-up to #2306 (merged). Per maintainer request
(https://github.com/github/spec-kit/pull/2306#issuecomment-4296655643),
adds the red-team entry to the alphabetically-ordered community-extensions
table in README.md so the extension is discoverable alongside the other
community entries — not only via catalog.community.json.
Slotted alphabetically between "Reconcile Extension" and "Repository
Index". Category: docs. Effect: Read+Write (produces a structured
findings-report file at specs/<feature-id>/red-team-findings-*.md; does
not modify specs — every resolution is maintainer-authorised).
Co-authored-by: Ash Brener <ashley@midletearth.com>
* feat(catalog): add red-team extension
Adds the `red-team` community extension to the catalog:
- Adversarial review of functional specs before /speckit.plan locks in
architecture.
- Complements /speckit.clarify (correctness) and /speckit.analyze
(consistency) with parallel adversarial lens agents.
- One command: speckit.red-team.run
- MIT licensed; requires spec-kit >= 0.7.0.
Origin: this extension was originally proposed as a core command
(github/spec-kit#2303). Per maintainer guidance (mnriem's comment on
that PR), it's been restructured as a community extension hosted at
https://github.com/ashbrener/spec-kit-red-team.
Dogfood-validated on a 500-line functional spec: 5 lens agents
dispatched in parallel returned 25 findings in ~1.5 min wall-clock,
19 of which met the meaningful-finding bar (severity >= HIGH AND
novel adversarial angle that clarify/analyze structurally cannot
catch). Full detail in the extension's CHANGELOG.
* catalog: shorten red-team description to fit <200 char schema limit
Resolves Copilot review comment on #2306. Previous description (259
chars) exceeded the extensions/EXTENSION-PUBLISHING-GUIDE.md Appendix
schema ceiling. Shortened to 188 chars, keeping the distinctive
value proposition (adversarial, complements clarify/analyze) and
moving the per-phase mechanics to the extension's own README.
* catalog: bump red-team to v1.0.1 (lower required spec-kit version)
Follow-up to v1.0.0 catalog entry:
- version: 1.0.0 -> 1.0.1
- download_url: points at v1.0.1 release asset
- requires.speckit_version: >=0.7.0 -> >=0.1.0
The v1.0.0 requirement was too strict and blocked installation on
common 0.6.x field versions (confirmed via local install attempt).
The extension uses no 0.7.x-specific APIs; matches community norm
(reconcile, refine, others use >=0.1.0).
* catalog: bump red-team to v1.0.2 (adds mandatory before_plan gate)
v1.0.2 ships a /speckit.red-team.gate command wired as a mandatory
before_plan hook so /speckit.plan auto-invokes it on every run against
qualifying specs. Non-qualifying specs return PROCEED silently; qualifying
specs without findings on record return HALT with explicit remediation
(run /speckit.red-team.run, or opt out via --skip-red-team-gate: <reason>
which is recorded as an Accepted Risk [red-team-skipped] in the plan).
Catalog metadata delta:
- version: 1.0.1 -> 1.0.2
- download_url: v1.0.2/red-team-v1.0.2.zip
- provides.commands: 1 -> 2 (adds speckit.red-team.gate)
- provides.hooks: 0 -> 1 (adds before_plan hook)
No breaking changes. Projects that do not want the gate simply do not
install the extension.
---------
Co-authored-by: Ash Brener <ashley@midletearth.com>
* Add superpowers-bridge community extension
Adds the superpowers-bridge extension by WangX0111 to the community
catalog and README table. This extension bridges spec-kit with
obra/superpowers (brainstorming, TDD, subagent-driven-development,
code-review) into a unified, resumable workflow with graceful
degradation and session progress tracking.
Extension details:
- ID: superpowers-bridge
- Repository: https://github.com/WangX0111/superspec
- Version: 1.0.0
- Commands: 5, Hooks: 3
- License: MIT
* Address Copilot review feedback
- Update top-level updated_at to 2026-04-22
- Shorten description to under 200 characters
---------
Co-authored-by: 乘浩 <wch453799@alibaba-inc.com>
* feat: implement strategy: wrap
* fix: resolve merge conflict for strategy wrap correctness
* feat: multi-preset composable wrapping with priority ordering
Implements comment #4 from PR review: multiple installed wrap presets
now compose in priority order rather than overwriting each other.
Key changes:
- PresetResolver.resolve() gains skip_presets flag; resolve_core() wraps
it to skip tier 2, preventing accidental nesting during replay
- _replay_wraps_for_command() recomposed all enabled wrap presets for a
command in ascending priority order (innermost-first) after any
install or remove
- _replay_skill_override() keeps SKILL.md in sync with the recomposed
command body for ai-skills-enabled projects
- install_from_directory() detects strategy: wrap commands, stores
wrap_commands in the registry entry, and calls replay after install
- remove() reads wrap_commands before deletion, removes registry entry
before rmtree so replay sees post-removal state, then replays
remaining wraps or unregisters when none remain
Tests: TestResolveCore (5), TestReplayWrapsForCommand (5),
TestInstallRemoveWrapLifecycle (5), plus 2 skill/alias regression tests
* fix: resolve extension commands via manifest file mapping
PresetResolver.resolve_extension_command_via_manifest() consults each
installed extension.yml to find the actual file declared for a command
name, rather than assuming the file is named <cmd_name>.md. This fixes
_substitute_core_template for extensions like selftest where the manifest
maps speckit.selftest.extension → commands/selftest.md.
Resolution order in _substitute_core_template is now:
1. resolve_core(cmd_name) — project overrides win, then name-based lookup
2. resolve_extension_command_via_manifest(cmd_name) — manifest fallback
3. resolve_core(short_name) — core template short-name fallback
Path traversal guard mirrors the containment check already present in
ExtensionManager to reject absolute paths or paths escaping the extension
root.
* fix: add bundled core_pack as Priority 5 in PresetResolver.resolve()
resolve_core() was returning None for built-in commands (implement,
specify, etc.) because PresetResolver only checked .specify/templates/
commands/ (Priority 4), which is never populated for commands in a
normal project. strategy:wrap presets rely on resolve_core() to fetch
the {CORE_TEMPLATE} body, so the wrap was silently skipped and SKILL.md
was never updated.
Priority 5 now checks core_pack/commands/ (wheel install) or
repo_root/templates/commands/ (source checkout), mirroring the pattern
used by _locate_core_pack() elsewhere.
Updated two tests whose assertions assumed resolve_core() always
returned None when .specify/templates/commands/ was absent.
* fix: harden preset wrap replay removal
* fix: stabilize existing directory error output
* fix: track outermost_pack_id from contributing preset; use Path.parts in tests
- outermost_pack_id now updates alongside outermost_frontmatter inside
the wrap loop, so it reflects the actual last contributing preset
rather than always taking wrap_presets[0] (which may have been skipped)
- Replace str(path) substring checks in TestResolveCore with Path.parts
tuple comparisons for correct behaviour on Windows (CI runs windows-latest)
* fix: guard against non-mapping YAML manifests; apply integration post-processing in replay
- ExtensionManifest._load raises ValidationError for non-dict YAML roots instead of TypeError
- PresetManager._replay_wraps_for_command calls integration.post_process_skill_content,
matching _register_skills behaviour
- PresetResolver skips extensions that raise OSError/TypeError/AttributeError on manifest load
- Tests: non-mapping YAML, OSError manifest skip, and replay integration post-processing