Compare commits

..

21 Commits

Author SHA1 Message Date
github-actions[bot]
9f84b0d0d6 chore: bump version to 0.12.18 2026-07-17 13:06:04 +00:00
dependabot[bot]
0b7c688203 chore(deps): bump actions/setup-dotnet from 5.4.0 to 6.0.0 (#3574)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 5.4.0 to 6.0.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](26b0ec14cb...a98b56852c)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 08:05:03 -05:00
dependabot[bot]
3b63534781 chore(deps): bump actions/stale from 10.3.0 to 10.4.0 (#3572)
Bumps [actions/stale](https://github.com/actions/stale) from 10.3.0 to 10.4.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](eb5cf3af3a...1e223db275)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: 10.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 08:02:14 -05:00
dependabot[bot]
4a00243817 chore(deps): bump actions/setup-node from 6.4.0 to 7.0.0 (#3570)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.4.0 to 7.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](48b55a011b...8207627860)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 07:56:41 -05:00
Manfred Riem
7bdf6c5041 docs: weave harness/SDLC framing into landing page (#3567)
Reframe the docs landing hero and "Make it your own" pillar to inject
the "harness" and "SDLC" framing while keeping SDD front and center:

- Hero: describe Spec Kit as an extensible, intent-driven harness that
  pushes any coding agent beyond code, across the SDLC or any business
  process; tagline now contrasts step-by-step vs automated-workflow runs.
- "Make it your own": explain the process lives in swappable building
  blocks (not locked to SDD or even software) and add a real non-software
  preset (Fiction Book Writing) to back the broadened scope.
- Community blurb: drop "development" so "entirely new processes" matches
  the wider positioning.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)

Copilot-Session: 1cf71797-ac0d-4a5e-8266-784906933b54

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-16 13:33:58 -05:00
Manfred Riem
396fc2c240 docs: reframe SDD positioning, modernize install, and de-duplicate walkthroughs (#3565)
* docs: reframe SDD positioning, modernize install, and de-duplicate walkthroughs

Reframe the landing page so Spec Kit reads as a toolkit for Spec-Driven
Development *or your own process* with any AI coding agent, and correct
stale claims: context files and git are now opt-in extensions, and the
install path uses PyPI (specify-cli). Generalize the landing cards to
cover bundles and catalog hosting across all primitives.

Restructure the Quick Start into a lean, guided Taskify walkthrough with
one command per step (install as a prerequisite, Steps 1-9 aligned with
the Full path), and extract the deep per-command detail into two new
reference pages: reference/agentic-sdd.md (the /speckit.* SDD process)
and reference/agentic-bugfix.md (the bug extension). Retitle the
reference overview to "Reference" and group these agentic processes in
their own section, distinct from CLI-managed primitives.

Remove the duplicated "Detailed Process" walkthrough from README.md
(and its TOC entry), repointing readers to the docs-site Quick Start
while keeping the concise "Get Started" section as the front door.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9d9232f8-ece4-4aa6-a9bd-ff8d74ca1c89

* docs: address review feedback on accuracy and scope

- quickstart: correct the git/feature note — resolution reads
  .specify/feature.json / SPECIFY_FEATURE, not the checked-out branch,
  so switching branches alone does not switch the active feature.
- quickstart + agentic-sdd: add an invocation-style note ($speckit-* for
  Codex/ZCode, /skill:speckit-* for Kimi) so the agent-neutral commands
  are executable everywhere.
- agentic-sdd: fix the tasks phase structure to match the generator
  (Setup, Foundational, one phase per user story, final Polish; tests
  optional within user-story phases).
- index: soften the catalog claim (catalogs curate discovery, not an
  install allow-list) and relabel the "CLI reference" link to "Reference"
  to match the retitled, broader page.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9d9232f8-ece4-4aa6-a9bd-ff8d74ca1c89

* docs: correct feature-resolution override and add bug-command invocation note

- quickstart: the previous fix named the wrong override. The active
  feature *directory* resolves from SPECIFY_FEATURE_DIRECTORY then
  .specify/feature.json; SPECIFY_FEATURE only supplies the identifier
  after a directory is resolved. Rewrite the note to point users at
  .specify/feature.json / SPECIFY_FEATURE_DIRECTORY, and clarify the git
  extension's branches don't by themselves change the active feature.
- agentic-bugfix: add the same invocation-style caveat as the SDD
  reference ($speckit-bug-* for Codex/ZCode, /skill:speckit-bug-* for
  Kimi).

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9d9232f8-ece4-4aa6-a9bd-ff8d74ca1c89

* docs: tighten bug-command contracts and drop numbered-phase examples

- agentic-bugfix: don't overstate overwrite protection — an interactive
  run can overwrite an existing assessment after confirmation; only
  automated mode refuses and picks a new slug. Correct the verify verdict
  to the schema's verified/partial/failed (not-run is a per-check status);
  an unexercised reproduction downgrades the result to partial.
- agentic-sdd: the implement examples labeled scoping "Phase 1/2", but
  the tasks contract reserves Phase 1 for Setup and Phase 2 for
  Foundational (user stories start at Phase 3). Scope by phase name and
  user-story content instead to avoid mis-scoping execution.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9d9232f8-ece4-4aa6-a9bd-ff8d74ca1c89

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-16 11:08:25 -05:00
Ehtasham Yasin
b08d665837 docs: document extensions.yml hook configuration (#3563)
* docs: document extesnion.yml hook confriguration

* docs: address hook confriguration review feedback

* clarify auto execute hooks behavior

* docs: clarify hook priority and condition behavior
2026-07-16 10:43:30 -05:00
Manfred Riem
aaf6bc22e3 docs: refresh landing page ecosystem stats (#3561)
* docs: refresh landing page ecosystem stats

Update stale numbers in docs/index.md to match current catalogs on
upstream/main and live GitHub data: extensions 105->138, presets
22->25, integrations 30+->35, contributors 200+->240+, friends 4->6,
GitHub stars 106K+->121K+, extension authors 60+->70+, and the
last-updated date.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e5f34221-4e6c-42e8-9fa3-5cfbc26104d1

* docs: align community extension stats on overview page

Update docs/community/overview.md from "Over 90 ... 50+ authors" to
"Over 130 ... 70+ authors" so it matches the refreshed landing-page
numbers in docs/index.md (137 community extensions, 77 unique authors).

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 134166d9-e599-44fa-a88d-daf84ab6aca6

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-16 08:35:00 -05:00
github-actions[bot]
c40db8ac10 [extension] Add Dotdog extension to community catalog (#3558)
* Add Dotdog extension to community catalog

Add dotdog extension submitted by @logohere to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #3555

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(catalog): alphabetize dotdog entry and correct tool requirement

Assisted-by: GitHub Copilot (model: claude-opus-4.8, autonomous)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-16 07:55:37 -05:00
github-actions[bot]
29eb6eddf1 Update DocGuard — CDD Enforcement to v0.33.0 (#3559)
Update docguard extension submitted by @raccioly:
- extensions/catalog.community.json (version, download_url, description, updated_at)
- docs/community/extensions.md community extensions table

Closes #3556

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-16 07:42:26 -05:00
Manfred Riem
ff436da2b4 chore: release 0.12.17, begin 0.12.18.dev0 development (#3560)
* chore: bump version to 0.12.17

* chore: begin 0.12.18.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-16 07:29:46 -05:00
WOLIKIMCHENG
4fed84a08d fix(extensions): resolve __SPECKIT_COMMAND tokens in auto-registered skills (#3544)
* fix(extensions): resolve command ref tokens in extension skills

* fix(extensions): render skill command refs by invocation style

Resolve extension skill command-reference tokens with the active skill invocation style so Codex and ZCode use $speckit-* while slash-style agents keep their native forms. Preserve literal command-looking text.

* fix(extensions): resolve slash skill command refs from init options

---------

Co-authored-by: root <kinsonnee@gmail.com>
2026-07-16 07:21:14 -05:00
Noor ul ain
459f483f57 fix(workflows): fail if/switch steps on non-list branch instead of crashing (#3515)
* fix(workflows): fail if/switch steps on non-list branch instead of crashing

`IfThenStep.validate()` and `SwitchStep.validate()` already reject a
non-list branch (`then`/`else`, and `case`/`default`), but the engine's
`execute()` path does not auto-validate (see
`WorkflowEngine.load_workflow`, whose docstring notes the definition is
"not yet validated"). On an unvalidated run, the selected branch is fed
straight into `next_steps`, which `_execute_steps` iterates as step
mappings. A non-list branch — a single mapping or scalar authoring
mistake — was iterated element-wise (a dict yields its string keys, a
str its characters) and raised `AttributeError` on `.get()`, taking down
the whole run; the engine invokes `step_impl.execute()` with no
surrounding try/except.

Guard both `execute` paths to return a FAILED StepResult naming the type
error instead, mirroring the switch non-mapping `cases` and fan-out
non-list `items` handling. The switch guard is factored into a shared
`_non_list_branch_failure` helper covering both `case` and `default`
branches. A missing `else`/`default` still defaults to an empty list
(COMPLETED), unchanged; the guard fires only on an explicit non-list
value. The condition/expression is still evaluated first, so its result
is surfaced in the step output for downstream context.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* test(workflows): cover switch non-list branch execute paths

Copilot flagged the new switch branch guards as untested: coverage
stopped at a non-mapping `cases` container. Add SwitchStep.execute
tests for a matched case with a non-list body and a non-list default
(dict/str/int), asserting FAILED, the branch-specific error, empty
next_steps, and preserved expression_value. Also add explicit
`default: null` / `else: null` normalization tests so the
validator-approved empty-branch contract cannot regress.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-16 07:17:34 -05:00
Nate Chadwick
fd101d531e feat(integrations): add Grok Build skills-based integration (#3535)
* feat(integrations): add Grok Build skills-based integration

Add first-class support for xAI Grok Build via SkillsIntegration, installing
speckit skills under .grok/skills and wiring init/invocation/catalog surfaces.

Assisted-by: Grok Build (model: grok-4, supervised)

* test+docs: address Copilot review on Grok multi-install and next steps

Assert init next-steps guidance for Grok (.grok/skills, /speckit-*) and
clarify that multi-install safety is path/manifest isolation, not
agent-context defaults such as shared AGENTS.md.

* fix(integrations): Grok headless --always-approve and isolation paths

Document Grok multi-install isolation as .grok/skills and .grok/rules.
Override build_exec_args to pass --always-approve so non-interactive
dispatch is not blocked at tool permission gates.

* docs(integrations): list only managed .grok/skills for Grok isolation

Multi-install isolation documents Spec Kit-managed paths; Grok only
writes .grok/skills, so drop the read-only .grok/rules entry.

* fix(integrations): always-slash Grok hooks and refresh catalog date

Move grok to ALWAYS_SLASH_AGENTS so hooks never emit /speckit.plan when
ai_skills is missing/false. Update slash-format tests, persist ai_skills
on init, and bump catalog updated_at for the Grok entry.

---------

Co-authored-by: Nate Chadwick <1232206+natechadwick@users.noreply.github.com>
Co-authored-by: test <test@example.com>
2026-07-15 14:55:25 -05:00
Noor ul ain
a7f6fe8dd4 fix(extensions/git): reject negative -Number in create-new-feature-branch.ps1 (#3538)
The bash and Python twins validate --number against ^[0-9]+$ and reject a
negative value with 'Error: --number must be a non-negative integer'. The
PowerShell twin declares the parameter as [long]$Number, so PowerShell binds
'-5' as -5 instead of rejecting it. That value then formats via '{0:000}' to
'-005' and yields a branch name starting with a dash, which git refuses (refs
cannot begin with '-') — a confusing late failure instead of the twins' clear
early error.

Guard for $Number -lt 0 up front (before the description check, matching the
bash twin's parse-time validation order) and emit the identical error. An
explicit -Number 0 is still honored, preserving the #3412 fix.

Add matching negative-number parity tests to the bash and PowerShell
create-feature suites, mirroring the existing test_explicit_number_zero_is_honored
pair. Same PowerShell-parity bug class as #3412.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 12:48:24 -05:00
github-actions[bot]
f065e27478 test: cover preset constitution seeding through init CLI (#3297)
* Fix preset-constitution-not-installed: use PresetResolver in constitution setup

Apply the remediation from the bug assessment on issue #3272.

Changes:
1. Modify ensure_constitution_from_template (init.py) to resolve the
   constitution-template through the preset priority stack via
   PresetResolver, instead of hardcoding the core template path. This
   ensures a preset's replacement constitution-template is used when
   seeding .specify/memory/constitution.md.

2. Reorder init flow: move ensure_constitution_from_template to after
   the preset installation block so that 'specify init --preset' seeds
   the memory file from the already-resolved template stack, not from
   the generic template that existed before the preset arrived.

3. Add _maybe_reseed_constitution to PresetManager (presets/__init__.py):
   a post-install hook that re-seeds .specify/memory/constitution.md
   from the preset's constitution-template during 'specify preset add'
   on an existing project, but only when the memory file still contains
   generic placeholder tokens ([PROJECT_NAME] or [PRINCIPLE_1_NAME]).
   Legitimately authored constitutions (no placeholder tokens) are never
   overwritten.

4. Add regression tests covering both code paths (TestConstitutionReseedOnPresetInstall
   and TestEnsureConstitutionFromTemplate in tests/test_presets.py).

Refs #3272

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Harden preset constitution resolution

Use manifest-aware composed content, atomic safe writes, and conservative generic-template matching for constitution seeding and re-seeding.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 49891a32-bec4-462c-a7f2-6d6ec4eefcdb

* Limit preset CLI change to regression test

Remove accidental whole-file Ruff formatting introduced during conflict resolution so the PR contains only the intended end-to-end test.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 49891a32-bec4-462c-a7f2-6d6ec4eefcdb

* Make preset init test depend on init ordering

Disable preset-install lifecycle seeding in the regression test so it fails unless init materializes the constitution after registering the preset.

Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 49891a32-bec4-462c-a7f2-6d6ec4eefcdb

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Ben Buttigieg <70525+BenBtg@users.noreply.github.com>
2026-07-15 17:52:14 +01:00
Manfred Riem
2fb18c73cb fix(integration): preserve ai_skills on use for skills-mode Copilot (#3550) (#3551)
`specify integration use copilot` against a Copilot install configured with
`--integration-options "--skills"` dropped `"ai_skills": true` from
init-options.json and regenerated extension commands in the legacy
`.agent.md`/`.prompt.md` layout, contradicting `integration.json`'s stored
`parsed_options.skills: true`.

`_update_init_options_for_integration` only inspected `SkillsIntegration` /
the instance `_skills_mode` flag. On the `use` path no `setup()` runs, so the
freshly-resolved Copilot instance has `_skills_mode == False` and the stored
skills intent in `parsed_options` was ignored. Thread the resolved
`parsed_options` through and treat `parsed_options["skills"]` as skills mode.

Adds a regression test that resets the registry singleton's `_skills_mode` to
simulate a fresh process (in-process singleton reuse otherwise masks the bug).

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)


Copilot-Session: 06fb6ae9-f444-4dfd-ab3f-d0669c5d0604

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-15 11:18:54 -05:00
github-actions[bot]
5409670c13 [extension] Add Figma Starter extension to community catalog (#3547)
* Add Figma Starter extension to community catalog

Add figma-starter extension submitted by @vibhus to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #3545

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: add missing python3 >=3.8 version constraint in figma-starter catalog entry

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix(agent-context): reduce Python subprocess overhead in PS 5.1 YAML fallback

The PowerShell update-agent-context.ps1 script falls back to Python when
PS 5.1 (which lacks ConvertFrom-Yaml and cannot parse YAML as JSON) reads
the extension config.  It previously launched Python twice: once to verify
that Python 3 + PyYAML were available, and once to run a temp script file
that parsed the YAML and printed JSON.

On Windows CI each Python startup—plus potential Windows Defender scanning
of a freshly-created .tmp file—can take several seconds.  With two launches
plus PS 5.1's own startup time the subprocess.run(timeout=30) threshold in
test_powershell_script_discovers_nested_plan was regularly exceeded, causing
the CI job to fail.

Replace the two-phase approach with a single Python -c one-liner that
verifies PyYAML availability, parses the YAML file, and emits JSON in one
process.  This halves the number of Python launches and eliminates the temp
file entirely, keeping total execution time well under 30 s.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* revert(agent-context): restore update-agent-context.ps1 to pre-optimization state

The runtime optimization (one-liner Python fallback, stderr suppression) was
unrelated to the Figma Starter catalog addition (issue #3545) and removed the
actionable PyYAML/parse diagnostic messages. Revert the file so the PR only
contains the catalog-entry and documentation changes.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-15 10:58:49 -05:00
github-actions[bot]
a4aa4f6701 [extension] Add Spec-Kit BDD extension to community catalog (#3548)
* Add Spec-Kit BDD extension to community catalog

Add bdd extension submitted by @RSginer to:
- extensions/catalog.community.json (alphabetical order)
- docs/community/extensions.md community extensions table

Closes #3546

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(catalog): add optional BDD framework tools to bdd extension entry

Add the six optional tool dependencies submitted with the bdd extension
to the requires.tools field so they appear in CLI extension details:
pytest-bdd, behave, @cucumber/cucumber, cucumber, io.cucumber, SpecFlow

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-15 09:44:23 -05:00
github-actions[bot]
7a99c4a230 [extension] Update Quality Gates (Enforcement Layer) extension to v0.3.2 (#3542)
* Update Quality Gates (Enforcement Layer) extension to v0.3.2

Update gates extension submitted by @schwichtgit to:
- extensions/catalog.community.json (version, download_url, description, provides, changelog, updated_at)
- docs/community/extensions.md community extensions table

Closes #3541

Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: limit catalog changes to gates entry only, revert unrelated re-serialization

Reverts the wholesale Unicode-escape and tools-array reformatting that
was unintentionally introduced across catalog.community.json. Only the
gates-specific updates remain:
- description updated to v0.3.2 wording
- version: 0.1.0 → 0.3.2
- download_url updated to gates-0.3.2.zip
- git tool required: true → false
- commands: 5 → 8, hooks: 1 → 2
- updated_at: 2026-07-13 → 2026-07-15
- changelog field added

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix: move changelog field above license in gates entry

Move changelog URL field to sit after documentation and before license,
matching the catalog's standard field ordering. Remove the dangling
changelog at the bottom of the entry so updated_at is the final field
with no trailing comma.

Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)

* fix: shorten gates catalog description

Assisted-by: GitHub Copilot (model: GPT-5, autonomous)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-15 09:29:15 -05:00
Manfred Riem
fbc59d278e chore: release 0.12.16, begin 0.12.17.dev0 development (#3549)
* chore: bump version to 0.12.16

* chore: begin 0.12.17.dev0 development

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-15 09:25:55 -05:00
44 changed files with 1320 additions and 499 deletions

View File

@@ -8,7 +8,7 @@ body:
value: |
Thanks for requesting a new agent! Before submitting, please check if the agent is already supported.
**Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed
**Currently supported agents**: Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Cursor, Devin for Terminal, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Grok Build, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed
- type: input
id: agent-name

View File

@@ -76,6 +76,7 @@ body:
- Gemini CLI
- GitHub Copilot
- Goose
- Grok Build
- Hermes Agent
- IBM Bob
- Junie

View File

@@ -70,6 +70,7 @@ body:
- Gemini CLI
- GitHub Copilot
- Goose
- Grok Build
- Hermes Agent
- IBM Bob
- Junie

View File

@@ -36,7 +36,7 @@
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8
#
@@ -1399,7 +1399,7 @@ jobs:
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
package-manager-cache: false

View File

@@ -36,7 +36,7 @@
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8
#
@@ -1399,7 +1399,7 @@ jobs:
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
package-manager-cache: false

View File

@@ -35,7 +35,7 @@
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8
#
@@ -1344,7 +1344,7 @@ jobs:
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
package-manager-cache: false

4
.github/workflows/bug-fix.lock.yml generated vendored
View File

@@ -36,7 +36,7 @@
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8
#
@@ -1405,7 +1405,7 @@ jobs:
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
package-manager-cache: false

View File

@@ -35,7 +35,7 @@
# - actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
# - actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
# - github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8
#
@@ -1366,7 +1366,7 @@ jobs:
mkdir -p /tmp/gh-aw/threat-detection
touch /tmp/gh-aw/threat-detection/detection.log
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
package-manager-cache: false

View File

@@ -35,7 +35,7 @@ jobs:
fetch-depth: 0 # Fetch all history for git info
- name: Setup .NET
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
dotnet-version: '8.x'

View File

@@ -14,7 +14,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10
- uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10
with:
# Days of inactivity before an issue or PR becomes stale
days-before-stale: 150

3
.gitignore vendored
View File

@@ -53,9 +53,10 @@ docs/dev
# The following directories/file are intentionally ignored so that they are not accidentally
# committed to the repository. They contain the scaffolding `specify init --integration copilot`
# does and they are meant for dogfooding Spec Kit during its own feature development.
# (or other agents) does and they are meant for dogfooding Spec Kit during its own feature development.
.github/agents/
.github/prompts/
.github/copilot-instructions.md
.grok/
.specify/
specs/

View File

@@ -2,6 +2,36 @@
<!-- insert new changelog below this comment -->
## [0.12.18] - 2026-07-17
### Changed
- chore(deps): bump actions/setup-dotnet from 5.4.0 to 6.0.0 (#3574)
- chore(deps): bump actions/stale from 10.3.0 to 10.4.0 (#3572)
- chore(deps): bump actions/setup-node from 6.4.0 to 7.0.0 (#3570)
- docs: weave harness/SDLC framing into landing page (#3567)
- docs: reframe SDD positioning, modernize install, and de-duplicate walkthroughs (#3565)
- docs: document extensions.yml hook configuration (#3563)
- docs: refresh landing page ecosystem stats (#3561)
- [extension] Add Dotdog extension to community catalog (#3558)
- Update DocGuard — CDD Enforcement to v0.33.0 (#3559)
- chore: release 0.12.17, begin 0.12.18.dev0 development (#3560)
## [0.12.17] - 2026-07-16
### Changed
- fix(extensions): resolve __SPECKIT_COMMAND tokens in auto-registered skills (#3544)
- fix(workflows): fail if/switch steps on non-list branch instead of crashing (#3515)
- feat(integrations): add Grok Build skills-based integration (#3535)
- fix(extensions/git): reject negative -Number in create-new-feature-branch.ps1 (#3538)
- test: cover preset constitution seeding through init CLI (#3297)
- fix(integration): preserve ai_skills on `use` for skills-mode Copilot (#3550) (#3551)
- [extension] Add Figma Starter extension to community catalog (#3547)
- [extension] Add Spec-Kit BDD extension to community catalog (#3548)
- [extension] Update Quality Gates (Enforcement Layer) extension to v0.3.2 (#3542)
- chore: release 0.12.16, begin 0.12.17.dev0 development (#3549)
## [0.12.16] - 2026-07-15
### Changed

290
README.md
View File

@@ -32,7 +32,6 @@
- [🎯 Experimental Goals](#-experimental-goals)
- [🔧 Prerequisites](#-prerequisites)
- [📖 Learn More](#-learn-more)
- [📋 Detailed Process](#-detailed-process)
- [💬 Support](#-support)
- [🙏 Acknowledgements](#-acknowledgements)
- [📄 License](#-license)
@@ -361,294 +360,7 @@ If you encounter issues with an agent, please open an issue so we can refine the
## 📖 Learn More
- **[Complete Spec-Driven Development Methodology](./spec-driven.md)** - Deep dive into the full process
- **[Detailed Walkthrough](#-detailed-process)** - Step-by-step implementation guide
---
## 📋 Detailed Process
<details>
<summary>Click to expand the detailed step-by-step walkthrough</summary>
You can use the Specify CLI to bootstrap your project, which will bring in the required artifacts in your environment. Run:
```bash
specify init <project_name>
```
Or initialize in the current directory:
```bash
specify init .
# or use the --here flag
specify init --here
# Skip confirmation when the directory already has files
specify init . --force
# or
specify init --here --force
```
![Specify CLI bootstrapping a new project in the terminal](./media/specify_cli.gif)
In an interactive terminal, you will be prompted to select the coding agent integration you are using. In non-interactive sessions, such as CI or piped runs, `specify init` defaults to GitHub Copilot unless you pass `--integration`. You can also proactively specify the integration directly in the terminal:
```bash
specify init <project_name> --integration copilot
specify init <project_name> --integration gemini
specify init <project_name> --integration codex
# Or in current directory:
specify init . --integration copilot
specify init . --integration codex --integration-options="--skills"
# or use --here flag
specify init --here --integration copilot
specify init --here --integration codex --integration-options="--skills"
# Force merge into a non-empty current directory
specify init . --force --integration copilot
# or
specify init --here --force --integration copilot
```
The CLI checks that the selected integration's required CLI tool is installed on your machine when that integration has `requires_cli: True`. If you do not have the required tool installed, or you prefer to get the templates without checking for the right tools, use `--ignore-agent-tools` with your command:
```bash
specify init <project_name> --integration copilot --ignore-agent-tools
```
### **STEP 1:** Establish project principles
Go to the project folder and run your coding agent. In our example, we're using `claude`.
![Bootstrapping Claude Code environment](./media/bootstrap-claude-code.gif)
You will know that things are configured correctly if you see the `/speckit.constitution`, `/speckit.specify`, `/speckit.plan`, `/speckit.tasks`, and `/speckit.implement` commands available.
The first step should be establishing your project's governing principles using the `/speckit.constitution` command. This helps ensure consistent decision-making throughout all subsequent development phases:
```text
/speckit.constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements. Include governance for how these principles should guide technical decisions and implementation choices.
```
This step creates or updates the `.specify/memory/constitution.md` file with your project's foundational guidelines that the coding agent will reference during specification, planning, and implementation phases.
### **STEP 2:** Create project specifications
With your project principles established, you can now create the functional specifications. Use the `/speckit.specify` command and then provide the concrete requirements for the project you want to develop.
> [!IMPORTANT]
> Be as explicit as possible about *what* you are trying to build and *why*. **Do not focus on the tech stack at this point**.
An example prompt:
```text
Develop Taskify, a team productivity platform. It should allow users to create projects, add team members,
assign tasks, comment and move tasks between boards in Kanban style. In this initial phase for this feature,
let's call it "Create Taskify," let's have multiple users but the users will be declared ahead of time, predefined.
I want five users in two different categories, one product manager and four engineers. Let's create three
different sample projects. Let's have the standard Kanban columns for the status of each task, such as "To Do,"
"In Progress," "In Review," and "Done." There will be no login for this application as this is just the very
first testing thing to ensure that our basic features are set up. For each task in the UI for a task card,
you should be able to change the current status of the task between the different columns in the Kanban work board.
You should be able to leave an unlimited number of comments for a particular card. You should be able to, from that task
card, assign one of the valid users. When you first launch Taskify, it's going to give you a list of the five users to pick
from. There will be no password required. When you click on a user, you go into the main view, which displays the list of
projects. When you click on a project, you open the Kanban board for that project. You're going to see the columns.
You'll be able to drag and drop cards back and forth between different columns. You will see any cards that are
assigned to you, the currently logged in user, in a different color from all the other ones, so you can quickly
see yours. You can edit any comments that you make, but you can't edit comments that other people made. You can
delete any comments that you made, but you can't delete comments anybody else made.
```
After this prompt is entered, you should see Claude Code kick off the planning and spec drafting process. Claude Code will also trigger some of the built-in scripts to set up the repository.
Once this step is completed, you should have a new branch created (e.g., `001-create-taskify`), as well as a new specification in the `specs/001-create-taskify` directory.
The produced specification should contain a set of user stories and functional requirements, as defined in the template.
At this stage, your project folder contents should resemble the following:
```text
.
├── .specify
│ ├── memory
│ │ └── constitution.md
│ ├── scripts
│ │ └── bash
│ │ ├── check-prerequisites.sh
│ │ ├── common.sh
│ │ ├── create-new-feature.sh
│ │ ├── setup-plan.sh
│ │ └── setup-tasks.sh
│ └── templates
│ ├── plan-template.md
│ ├── spec-template.md
│ └── tasks-template.md
└── specs
└── 001-create-taskify
└── spec.md
```
### **STEP 3:** Functional specification clarification (required before planning)
With the baseline specification created, you can go ahead and clarify any of the requirements that were not captured properly within the first shot attempt.
You should run the structured clarification workflow **before** creating a technical plan to reduce rework downstream.
Preferred order:
1. Use `/speckit.clarify` (structured) sequential, coverage-based questioning that records answers in a Clarifications section.
2. Optionally follow up with ad-hoc free-form refinement if something still feels vague.
If you intentionally want to skip clarification (e.g., spike or exploratory prototype), explicitly state that so the agent doesn't block on missing clarifications.
Example free-form refinement prompt (after `/speckit.clarify` if still needed):
```text
For each sample project or project that you create there should be a variable number of tasks between 5 and 15
tasks for each one randomly distributed into different states of completion. Make sure that there's at least
one task in each stage of completion.
```
You should also ask Claude Code to validate the **Review & Acceptance Checklist**, checking off the things that are validated/pass the requirements, and leave the ones that are not unchecked. The following prompt can be used:
```text
Read the review and acceptance checklist, and check off each item in the checklist if the feature spec meets the criteria. Leave it empty if it does not.
```
It's important to use the interaction with Claude Code as an opportunity to clarify and ask questions around the specification - **do not treat its first attempt as final**.
### **STEP 4:** Generate a plan
You can now be specific about the tech stack and other technical requirements. You can use the `/speckit.plan` command that is built into the project template with a prompt like this:
```text
We are going to generate this using .NET Aspire, using Postgres as the database. The frontend should use
Blazor server with drag-and-drop task boards, real-time updates. There should be a REST API created with a projects API,
tasks API, and a notifications API.
```
The output of this step will include a number of implementation detail documents, with your directory tree resembling this:
```text
.
├── CLAUDE.md
├── .specify
│ ├── memory
│ │ └── constitution.md
│ ├── scripts
│ │ └── bash
│ │ ├── check-prerequisites.sh
│ │ ├── common.sh
│ │ ├── create-new-feature.sh
│ │ ├── setup-plan.sh
│ │ └── setup-tasks.sh
│ └── templates
│ ├── CLAUDE-template.md
│ ├── plan-template.md
│ ├── spec-template.md
│ └── tasks-template.md
└── specs
└── 001-create-taskify
├── contracts
│ ├── api-spec.json
│ └── signalr-spec.md
├── data-model.md
├── plan.md
├── quickstart.md
├── research.md
└── spec.md
```
Check the `research.md` document to ensure that the right tech stack is used, based on your instructions. You can ask Claude Code to refine it if any of the components stand out, or even have it check the locally-installed version of the platform/framework you want to use (e.g., .NET).
Additionally, you might want to ask Claude Code to research details about the chosen tech stack if it's something that is rapidly changing (e.g., .NET Aspire, JS frameworks), with a prompt like this:
```text
I want you to go through the implementation plan and implementation details, looking for areas that could
benefit from additional research as .NET Aspire is a rapidly changing library. For those areas that you identify that
require further research, I want you to update the research document with additional details about the specific
versions that we are going to be using in this Taskify application and spawn parallel research tasks to clarify
any details using research from the web.
```
During this process, you might find that Claude Code gets stuck researching the wrong thing - you can help nudge it in the right direction with a prompt like this:
```text
I think we need to break this down into a series of steps. First, identify a list of tasks
that you would need to do during implementation that you're not sure of or would benefit
from further research. Write down a list of those tasks. And then for each one of these tasks,
I want you to spin up a separate research task so that the net results is we are researching
all of those very specific tasks in parallel. What I saw you doing was it looks like you were
researching .NET Aspire in general and I don't think that's gonna do much for us in this case.
That's way too untargeted research. The research needs to help you solve a specific targeted question.
```
> [!NOTE]
> Claude Code might be over-eager and add components that you did not ask for. Ask it to clarify the rationale and the source of the change.
### **STEP 5:** Have Claude Code validate the plan
With the plan in place, you should have Claude Code run through it to make sure that there are no missing pieces. You can use a prompt like this:
```text
Now I want you to go and audit the implementation plan and the implementation detail files.
Read through it with an eye on determining whether or not there is a sequence of tasks that you need
to be doing that are obvious from reading this. Because I don't know if there's enough here. For example,
when I look at the core implementation, it would be useful to reference the appropriate places in the implementation
details where it can find the information as it walks through each step in the core implementation or in the refinement.
```
This helps refine the implementation plan and helps you avoid potential blind spots that Claude Code missed in its planning cycle. Once the initial refinement pass is complete, ask Claude Code to go through the checklist once more before you can get to the implementation.
You can also ask Claude Code (if you have the [GitHub CLI](https://docs.github.com/en/github-cli/github-cli) installed) to go ahead and create a pull request from your current branch to `main` with a detailed description, to make sure that the effort is properly tracked.
> [!NOTE]
> Before you have the agent implement it, it's also worth prompting Claude Code to cross-check the details to see if there are any over-engineered pieces (remember - it can be over-eager). If over-engineered components or decisions exist, you can ask Claude Code to resolve them. Ensure that Claude Code follows the constitution in `.specify/memory/constitution.md` as the foundational piece that it must adhere to when establishing the plan.
### **STEP 6:** Generate task breakdown with /speckit.tasks
With the implementation plan validated, you can now break down the plan into specific, actionable tasks that can be executed in the correct order. Use the `/speckit.tasks` command to automatically generate a detailed task breakdown from your implementation plan:
```text
/speckit.tasks
```
This step creates a `tasks.md` file in your feature specification directory that contains:
- **Task breakdown organized by user story** - Each user story becomes a separate implementation phase with its own set of tasks
- **Dependency management** - Tasks are ordered to respect dependencies between components (e.g., models before services, services before endpoints)
- **Parallel execution markers** - Tasks that can run in parallel are marked with `[P]` to optimize development workflow
- **File path specifications** - Each task includes the exact file paths where implementation should occur
- **Test-driven development structure** - If tests are requested, test tasks are included and ordered to be written before implementation
- **Checkpoint validation** - Each user story phase includes checkpoints to validate independent functionality
The generated tasks.md provides a clear roadmap for the `/speckit.implement` command, ensuring systematic implementation that maintains code quality and allows for incremental delivery of user stories.
### **STEP 7:** Implementation
Once ready, use the `/speckit.implement` command to execute your implementation plan:
```text
/speckit.implement
```
The `/speckit.implement` command will:
- Validate that all prerequisites are in place (constitution, spec, plan, and tasks)
- Parse the task breakdown from `tasks.md`
- Execute tasks in the correct order, respecting dependencies and parallel execution markers
- Follow the TDD approach defined in your task plan
- Provide progress updates and handle errors appropriately
> [!IMPORTANT]
> The coding agent will execute local CLI commands (such as `dotnet`, `npm`, etc.) - make sure you have the required tools installed on your machine.
Once the implementation is complete, test the application and resolve any runtime errors that may not be visible in CLI logs (e.g., browser console errors). You can copy and paste such errors back to your coding agent for resolution.
</details>
- **[Quick Start Guide](https://github.github.io/spec-kit/quickstart.html)** - Step-by-step implementation walkthrough
---

View File

@@ -51,9 +51,11 @@ The following community-contributed extensions are available in [`catalog.commun
| Confluence Extension | Create a doc in Confluence summarizing the specifications and planning files | `integration` | Read+Write | [spec-kit-confluence](https://github.com/aaronrsun/spec-kit-confluence) |
| Cost Tracker | Track real LLM dollar cost across SDD workflows — per-feature budgets, per-integration comparison, and finance-ready exports | `visibility` | Read+Write | [spec-kit-cost](https://github.com/Quratulain-bilal/spec-kit-cost) |
| Data Model Diagram | Generates Mermaid ER diagrams from Spec Kit data models after planning | `docs` | Read+Write | [spec-kit-data-model-diagram](https://github.com/benizzio/spec-kit-data-model-diagram) |
| DocGuard — CDD Enforcement | Doc-integrity engine with MCP server, SARIF output, and zero-LLM core. Validates, scores, and traces documentation against code — 24 validators, stable finding codes, spec-kit hooks. Pure Node.js. | `docs` | Read+Write | [spec-kit-docguard](https://github.com/raccioly/docguard) |
| DocGuard — CDD Enforcement | The only doc-integrity engine with an MCP server, SARIF/JUnit output, and a deterministic zero-LLM core. Validates, scores, and traces documentation against code — 27 validators, stable finding codes, adoption baseline for legacy repos, compliance-evidence reports, GitHub Action with PR annotations, spec-kit hooks. Pure Node.js, one pinned dep. | `docs` | Read+Write | [spec-kit-docguard](https://github.com/raccioly/docguard) |
| Dotdog | Import GitHub Spec Kit artifacts into local knowledge graphs for validation, analysis, search, and MCP queries. | `docs` | Read+Write | [dotdog](https://github.com/specdog/dotdog) |
| EARS Requirements Syntax | Author, lint, and convert requirements using EARS - the five industry-standard sentence patterns for unambiguous, testable requirements | `docs` | Read+Write | [spec-kit-ears](https://github.com/dhruv-15-03/spec-kit-ears) |
| Extensify | Create and validate extensions and extension catalogs | `process` | Read+Write | [extensify](https://github.com/mnriem/spec-kit-extensions/tree/main/extensify) |
| Figma Starter | Turns a Figma section's screens into per-screen spec.md files, an app-level user-stories.md, and a build-order.md, then hands off to /speckit.specify | `integration` | Read+Write | [spec-kit-figma-starter](https://github.com/wavemaker/spec-kit-figma-starter) |
| Fix Findings | Automated analyze-fix-reanalyze loop that resolves spec findings until clean | `code` | Read+Write | [spec-kit-fix-findings](https://github.com/Quratulain-bilal/spec-kit-fix-findings) |
| FixIt Extension | Spec-aware bug fixing — maps bugs to spec artifacts, proposes a plan, applies minimal changes | `code` | Read+Write | [spec-kit-fixit](https://github.com/speckit-community/spec-kit-fixit) |
| Fleet Orchestrator | Orchestrate a full feature lifecycle with human-in-the-loop gates across all SpecKit phases | `process` | Read+Write | [spec-kit-fleet](https://github.com/sharathsatish/spec-kit-fleet) |
@@ -100,7 +102,7 @@ The following community-contributed extensions are available in [`catalog.commun
| Project Health Check | Diagnose a Spec Kit project and report health issues across structure, agents, features, scripts, extensions, and git | `visibility` | Read-only | [spec-kit-doctor](https://github.com/KhawarHabibKhan/spec-kit-doctor) |
| Project Status | Show current SDD workflow progress — active feature, artifact status, task completion, workflow phase, and extensions summary | `visibility` | Read-only | [spec-kit-status](https://github.com/KhawarHabibKhan/spec-kit-status) |
| QA Testing Extension | Systematic QA testing with browser-driven or CLI-based validation of acceptance criteria from spec | `code` | Read-only | [spec-kit-qa](https://github.com/arunt14/spec-kit-qa) |
| Quality Gates (Enforcement Layer) | Deterministic quality enforcement for Spec Kit projects at three boundaries — agent hooks, git pre-commit, CI — with one policy file and provable enforcement (attestations, canaries, verified parity). | `process` | Read+Write | [spec-gates](https://github.com/schwichtgit/spec-gates) |
| Quality Gates (Enforcement Layer) | Deterministic quality enforcement for Spec Kit across agent hooks, git checks, and CI pipelines with one policy file and one verify entrypoint for identical results at every boundary. | `process` | Read+Write | [spec-gates](https://github.com/schwichtgit/spec-gates) |
| RAG Azure Builder | Spec Kit extension for onboarding and operating an Azure RAG stack with guided workflows. | `process` | Read+Write | [spec-kit-extension-rag-azure-builder](https://github.com/Sertxito/spec-kit-extension-rag-azure-builder) |
| Ralph Loop | Autonomous implementation loop using AI agent CLI | `code` | Read+Write | [spec-kit-ralph](https://github.com/Rubiss-Projects/spec-kit-ralph) |
| Reconcile Extension | Reconcile implementation drift by surgically updating feature artifacts. | `docs` | Read+Write | [spec-kit-reconcile](https://github.com/stn1slv/spec-kit-reconcile) |
@@ -134,6 +136,7 @@ The following community-contributed extensions are available in [`catalog.commun
| Spec Sync | Detect and resolve drift between specs and implementation. AI-assisted resolution with human approval | `docs` | Read+Write | [spec-kit-sync](https://github.com/bgervin/spec-kit-sync) |
| Spec Trace | Build a requirement → test traceability matrix from spec.md and the test suite — surface untested requirements and orphan tests | `code` | Read+Write | [spec-kit-trace](https://github.com/Quratulain-bilal/spec-kit-trace) |
| Spec Validate | Comprehension validation, review gating, and approval state for spec-kit artifacts — staged quizzes, peer review SLA, and a hard gate before /speckit.implement | `process` | Read+Write | [spec-kit-spec-validate](https://github.com/aeltayeb/spec-kit-spec-validate) |
| Spec-Kit BDD | ATDD/BDD extension: convert specs to Gherkin scenarios, scaffold step definitions, and verify acceptance test coverage | `process` | Read+Write | [spec-kit-bdd](https://github.com/RSginer/spec-kit-bdd) |
| Spec2Cloud | Spec-driven workflow tuned for shipping to Azure | `process` | Read+Write | [spec2cloud](https://github.com/Azure-Samples/Spec2Cloud) |
| SpecKit Companion | Live spec-driven progress — lifecycle capture, status, resume, and a turbo pipeline profile | `visibility` | Read+Write | [speckit-companion](https://github.com/alfredoperez/speckit-companion) |
| SpecTest | Auto-generate test scaffolds from spec criteria, map coverage, and find untested requirements | `code` | Read+Write | [spec-kit-spectest](https://github.com/Quratulain-bilal/spec-kit-spectest) |

View File

@@ -4,7 +4,7 @@ The Spec Kit community builds extensions, presets, bundles, walkthroughs, and co
## Extensions
Extensions add new capabilities to Spec Kit — domain-specific commands, external tool integrations, quality gates, and more. Over 90 community extensions are available from 50+ authors, covering everything from accessibility governance to multi-agent orchestration.
Extensions add new capabilities to Spec Kit — domain-specific commands, external tool integrations, quality gates, and more. Over 130 community extensions are available from 70+ authors, covering everything from accessibility governance to multi-agent orchestration.
[Browse community extensions →](extensions.md)

View File

@@ -2,9 +2,9 @@
# GitHub Spec Kit
**Define what to build before building it — with any AI coding agent.**
**Spec-Driven Development or your own process — step by step or as an automated workflow.**
Spec Kit is a toolkit for [Spec-Driven Development](concepts/sdd.md) (SDD), a methodology that puts specifications at the center of AI-assisted software development. Instead of jumping straight to code, you describe _what_ to build, refine it through structured phases, and let your AI coding agent implement it.
Spec Kit is an extensible, intent-driven harness that pushes any coding agent beyond code, guiding it across your SDLC or any business process. Use it for [Spec-Driven Development](concepts/sdd.md) (SDD), where you describe _what_ to build and refine it through structured phases. Run it step by step, automate it end to end, or shape a process of your own, keeping intent at the center.
<a href="installation.md" class="btn btn-primary btn-lg">Install Spec Kit</a>&nbsp;
<a href="quickstart.md" class="btn btn-outline-primary btn-lg">Quick Start</a>
@@ -31,9 +31,9 @@ Define what to build before building it. Rich templates, quality checklists, and
### Use any coding agent
<span class="pillar-stat">30+ integrations</span> — Copilot, Gemini, Codex, Kilo Code, Zed, Claude, Forge, Kiro, and more. Switch freely between agents with a single command. No lock-in.
<span class="pillar-stat">35 integrations</span> — Copilot, Gemini, Codex, Kilo Code, Zed, Claude, Forge, Kiro, and more. Switch freely between agents with a single command. No lock-in.
Run `specify init` with your agent of choice and Spec Kit sets up the right command files, context rules, and directory structures automatically. If your agent isn't listed, the `generic` integration is an escape hatch for any tool.
Run `specify init` with your agent of choice and Spec Kit sets up the right command files and directory structures automatically. If your agent isn't listed, the `generic` integration is an escape hatch for any tool.
<a href="reference/integrations.md" class="pillar-link">See all integrations →</a>
@@ -43,17 +43,21 @@ Run `specify init` with your agent of choice and Spec Kit sets up the right comm
### Make it your own
<span class="pillar-stat">105 community extensions</span> (60+ authors), <span class="pillar-stat">22 presets</span>, and growing. Tune the core process with presets, extend it with extensions, orchestrate it with workflows, or replace it entirely. Build and publish your own.
<span class="pillar-stat">138 community extensions</span> (70+ authors), <span class="pillar-stat">25 presets</span>, and growing. Tune the core process with presets, extend it with extensions, orchestrate it with workflows, and package it all up as bundles you can share — or replace the process entirely. The process itself lives in these building blocks, so you're never locked to SDD, or even to software.
Including entirely different SDD processes:
Including entirely different processes:
- **AIDE** — 7-step AI-driven engineering lifecycle
- **Canon** — baseline-driven workflows (spec-first, code-first, spec-drift)
- **Product Forge** — product-management-oriented SDD
- **FX→.NET** — end-to-end .NET Framework migration across 7 phases
- **MAQA** — multi-agent orchestration with quality assurance gates
- **Fiction Book Writing** — novels and long-form fiction, from story bible to submission
<a href="community/presets.md" class="pillar-link">Browse community presets →</a>
<a href="reference/presets.md" class="pillar-link">Presets →</a>&nbsp;&nbsp;
<a href="reference/extensions.md" class="pillar-link">Extensions →</a>&nbsp;&nbsp;
<a href="reference/workflows.md" class="pillar-link">Workflows →</a>&nbsp;&nbsp;
<a href="reference/bundles.md" class="pillar-link">Bundles →</a>
</div>
@@ -61,12 +65,12 @@ Including entirely different SDD processes:
### Integrate into your organization
Works offline, behind firewalls, and on **Windows, macOS, and Linux**. Host your own extension and preset catalogs so your organization controls what gets installed.
Works offline, behind firewalls, and on **Windows, macOS, and Linux**. Host your own catalogs to curate what integrations, extensions, presets, workflows, and bundles your organization discovers and recommends.
Community extensions like CI Guard and Architecture Guard add compliance gates and governance that fit the way your team already works.
<a href="installation.md" class="pillar-link">Installation guide →</a>&nbsp;&nbsp;
<a href="reference/extensions.md" class="pillar-link">Extensions reference →</a>
<a href="install/air-gapped.md" class="pillar-link">Enterprise / Air-Gapped →</a>&nbsp;&nbsp;
<a href="reference/overview.md" class="pillar-link">Reference →</a>
</div>
@@ -78,31 +82,31 @@ Community extensions like CI Guard and Architecture Guard add compliance gates a
## Built by the community
**200+ contributors** power the Spec Kit ecosystem — from core integrations to entirely new development processes. Anyone can create and publish an extension, preset, or workflow.
**240+ contributors** power the Spec Kit ecosystem — from core integrations to entirely new processes. Anyone can create and publish an extension, preset, or workflow.
<div class="stats-grid">
<div class="stat-item">
<span class="stat-number">106K+</span>
<span class="stat-number">121K+</span>
<span class="stat-label">GitHub stars</span>
</div>
<div class="stat-item">
<span class="stat-number">200+</span>
<span class="stat-number">240+</span>
<span class="stat-label">Contributors</span>
</div>
<div class="stat-item">
<span class="stat-number">30+</span>
<span class="stat-number">35</span>
<span class="stat-label">Integrations</span>
</div>
<div class="stat-item">
<span class="stat-number">105</span>
<span class="stat-number">138</span>
<span class="stat-label">Extensions</span>
</div>
<div class="stat-item">
<span class="stat-number">22</span>
<span class="stat-number">25</span>
<span class="stat-label">Presets</span>
</div>
<div class="stat-item">
<span class="stat-number">4</span>
<span class="stat-number">6</span>
<span class="stat-label">Friends projects</span>
</div>
</div>
@@ -143,7 +147,7 @@ Community extensions like CI Guard and Architecture Guard add compliance gates a
<div class="footer-cta">
```bash
uvx --from git+https://github.com/github/spec-kit.git
uv tool install specify-cli
specify init my-project --integration copilot
```
@@ -151,4 +155,4 @@ Ready to start? Follow the [Quick Start Guide](quickstart.md).
</div>
<p class="text-end small text-body-secondary">Last updated: May 27, 2026</p>
<p class="text-end small text-body-secondary">Last updated: July 16, 2026</p>

View File

@@ -1,203 +1,128 @@
# Quick Start Guide
This guide will help you get started with Spec-Driven Development using Spec Kit.
This guide will help you get started with Spec-Driven Development using Spec Kit. Throughout, we illustrate each step with a running example: **Taskify**, a small team productivity platform.
> [!NOTE]
> All automation scripts now provide both Bash (`.sh`) and PowerShell (`.ps1`) variants. The `specify` CLI auto-selects based on OS unless you pass `--script sh|ps`.
> Automation scripts are provided as both Bash (`.sh`) and PowerShell (`.ps1`) variants. The `specify` CLI auto-selects based on your OS unless you pass `--script sh|ps`.
## Recommended Workflow
> [!NOTE]
> Commands are shown here in `/speckit.*` form, but the exact invocation depends on your agent. Some skills-based agents use `$speckit-*` (e.g. Codex, ZCode) or `/skill:speckit-*` (e.g. Kimi). Use whichever form your agent exposes — the steps are otherwise identical.
## Recommended Process
> [!TIP]
> **Context Awareness**: Spec Kit commands automatically detect the active feature based on your current Git branch (e.g., `001-feature-name`). To switch between different specifications, simply switch Git branches.
> **Context Awareness**: Spec Kit tracks the active feature by the feature directory recorded in `.specify/feature.json` (overridable with the `SPECIFY_FEATURE_DIRECTORY` environment variable). Commands resolve the feature from that state, **not** from the checked-out Git branch — no Git required. The opt-in **git** extension adds numbered feature branches (e.g. `001-feature-name`) for organizing work in version control, but the active feature is still whichever directory that state points to; `git checkout` alone does not change it. To point commands at a different feature, update `.specify/feature.json` (or set `SPECIFY_FEATURE_DIRECTORY`).
After installing Spec Kit and defining your project constitution, quick experiments can use the lean feature path: `/speckit.specify` -> `/speckit.plan` -> `/speckit.tasks` -> `/speckit.implement`. For production features or any work with meaningful ambiguity, treat `/speckit.clarify`, `/speckit.checklist`, and `/speckit.analyze` as regular quality gates:
After installing Spec Kit, each command below is a step in the process. Two paths are common:
**Shorter path** — for smaller features:
1. `/speckit.specify`
2. `/speckit.plan`
3. `/speckit.tasks`
4. `/speckit.implement`
5. `/speckit.converge`
**Full path** — for production features, adding `/speckit.clarify`, `/speckit.checklist`, and `/speckit.analyze` as quality gates:
1. `/speckit.constitution`
2. `/speckit.specify`
3. `/speckit.clarify`
4. `/speckit.plan`
5. `/speckit.checklist`
6. `/speckit.tasks`
7. `/speckit.analyze`
8. `/speckit.implement`
9. `/speckit.converge`
### Install Specify
**In your terminal**, install the CLI from PyPI (requires [uv](install/uv.md)), then initialize your project:
```bash
uv tool install specify-cli
specify init taskify # or: specify init . to use the current directory
```
`init` lets you pick your coding agent interactively, or pass it explicitly with `--integration` (e.g. `--integration copilot`).
> [!NOTE]
> Prefer `pipx`, one-time `uvx` runs, a pinned release, or an offline/air-gapped setup? See the [Installation Guide](installation.md) for all supported methods.
### Step 1: `/speckit.constitution` — set the ground rules
Establishes the project's guiding principles, which every later step is evaluated against. Run it once up front, passing your principles as arguments.
```text
/speckit.constitution -> /speckit.specify -> /speckit.clarify -> /speckit.plan -> /speckit.checklist -> /speckit.tasks -> /speckit.analyze -> /speckit.implement -> /speckit.converge
```
Use `/speckit.clarify` to reduce requirement ambiguity before planning, `/speckit.checklist` (after `/speckit.plan`) to generate quality checklists that validate requirements completeness, clarity, and consistency, and `/speckit.analyze` to check spec/plan/task consistency before implementation starts. You can repeat `/speckit.analyze` after implementation as an extra review, but keep the first analysis before `/speckit.implement` so gaps are caught while the plan and tasks can still be adjusted. Finally, run `/speckit.converge` after implementation to verify all planned work is complete and generate tasks for any remaining gaps. If `/speckit.converge` appends new tasks, run `/speckit.implement` again (and converge again) until it reports that the feature has converged.
### Step 1: Install Specify
**In your terminal**, run the `specify` CLI command to initialize your project:
```bash
# Create a new project directory
uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME>
# OR initialize in the current directory
uvx --from git+https://github.com/github/spec-kit.git specify init .
```
> [!NOTE]
> You can also install the CLI persistently with `pipx`:
>
> ```bash
> pipx install git+https://github.com/github/spec-kit.git
> ```
>
> After installing with `pipx`, run `specify` directly instead of `uvx --from ... specify`, for example:
>
> ```bash
> specify init <PROJECT_NAME>
> specify init .
> ```
Pick script type explicitly (optional):
```bash
uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME> --script ps # Force PowerShell
uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME> --script sh # Force POSIX shell
```
### Step 2: Define Your Constitution
**In your coding agent's chat interface**, use the `/speckit.constitution` slash command to establish the core rules and principles for your project. You should provide your project's specific principles as arguments.
```markdown
/speckit.constitution This project follows a "Library-First" approach. All features must be implemented as standalone libraries first. We use TDD strictly. We prefer functional programming patterns.
```
### Step 3: Create the Spec
**In the chat**, use the `/speckit.specify` slash command to describe what you want to build. Focus on the **what** and **why**, not the tech stack.
```markdown
/speckit.specify Build an application that can help me organize my photos in separate photo albums. Albums are grouped by date and can be re-organized by dragging and dropping on the main page. Albums are never in other nested albums. Within each album, photos are previewed in a tile-like interface.
```
### Step 4: Refine and Validate the Spec
**In the chat**, use the `/speckit.clarify` slash command to identify and resolve ambiguities in your specification. You can provide specific focus areas as arguments.
```bash
/speckit.clarify Focus on security and performance requirements.
```
### Step 5: Create a Technical Implementation Plan
**In the chat**, use the `/speckit.plan` slash command to provide your tech stack and architecture choices.
```markdown
/speckit.plan The application uses Vite with minimal number of libraries. Use vanilla HTML, CSS, and JavaScript as much as possible. Images are not uploaded anywhere and metadata is stored in a local SQLite database.
```
Then generate quality checklists with `/speckit.checklist` once the plan exists:
```bash
/speckit.checklist
```
### Step 6: Break Down, Analyze, and Implement
**In the chat**, use the `/speckit.tasks` slash command to create an actionable task list.
```markdown
/speckit.tasks
```
Validate cross-artifact consistency with `/speckit.analyze` before implementation:
```markdown
/speckit.analyze
```
Use the `/speckit.implement` slash command to execute the plan.
```markdown
/speckit.implement
```
> [!TIP]
> **Phased Implementation**: For complex projects, implement in phases to avoid overwhelming the agent's context. Start with core functionality, validate it works, then add features incrementally.
## Detailed Example: Building Taskify
Here's a complete example of building a team productivity platform:
### Step 1: Define Constitution
Initialize the project's constitution to set ground rules:
```markdown
/speckit.constitution Taskify is a "Security-First" application. All user inputs must be validated. We use a microservices architecture. Code must be fully documented.
```
### Step 2: Define Requirements with `/speckit.specify`
### Step 2: `/speckit.specify` — describe what to build
Creates the feature specification from a natural-language description. Focus on the **what** and **why**, not the tech stack.
```text
/speckit.specify Develop Taskify, a team productivity platform. It should allow users to create projects, add team members,
assign tasks, comment and move tasks between boards in Kanban style. In this initial phase for this feature,
let's call it "Create Taskify," let's have multiple users but the users will be declared ahead of time, predefined.
I want five users in two different categories, one product manager and four engineers. Let's create three
different sample projects. Let's have the standard Kanban columns for the status of each task, such as "To Do,"
"In Progress," "In Review," and "Done." There will be no login for this application as this is just the very
first testing thing to ensure that our basic features are set up.
/speckit.specify Develop Taskify, a team productivity platform where predefined users create projects, assign tasks, comment, and move tasks across Kanban columns (To Do, In Progress, In Review, Done). Five users (one product manager, four engineers), three sample projects, no login for this first phase.
```
### Step 3: Refine the Specification
### Step 3: `/speckit.clarify` — resolve ambiguities
Use the `/speckit.clarify` command to interactively resolve any ambiguities in your specification. You can also provide specific details you want to ensure are included.
Asks targeted questions about anything underspecified and folds your answers back into the spec, so you're not planning on top of ambiguity. Run it before planning, optionally with a focus area.
```bash
/speckit.clarify I want to clarify the task card details. For each task in the UI for a task card, you should be able to change the current status of the task between the different columns in the Kanban work board. You should be able to leave an unlimited number of comments for a particular card. You should be able to, from that task card, assign one of the valid users.
```text
/speckit.clarify Focus on task card behavior — status changes, comment permissions, and user assignment.
```
You can continue to refine the spec with more details using `/speckit.clarify`:
### Step 4: `/speckit.plan` — choose the tech stack
```bash
/speckit.clarify When you first launch Taskify, it's going to give you a list of the five users to pick from. There will be no password required. When you click on a user, you go into the main view, which displays the list of projects. When you click on a project, you open the Kanban board for that project. You're going to see the columns. You'll be able to drag and drop cards back and forth between different columns. You will see any cards that are assigned to you, the currently logged in user, in a different color from all the other ones, so you can quickly see yours. You can edit any comments that you make, but you can't edit comments that other people made. You can delete any comments that you made, but you can't delete comments anybody else made.
Generates the design artifacts from the spec. This is where implementation detail belongs — provide your tech stack and architecture.
```text
/speckit.plan Use .NET Aspire with Postgres. The frontend is Blazor Server with drag-and-drop boards and real-time updates. Expose REST APIs for projects, tasks, and notifications.
```
### Step 4: Generate Technical Plan with `/speckit.plan`
### Step 5: `/speckit.checklist` — validate the spec
Be specific about your tech stack and technical requirements:
Generates a quality checklist — "unit tests for your requirements" — to confirm the spec is complete, clear, and consistent before you break the work down.
```bash
/speckit.plan We are going to generate this using .NET Aspire, using Postgres as the database. The frontend should use Blazor server with drag-and-drop task boards, real-time updates. There should be a REST API created with a projects API, tasks API, and a notifications API.
```
### Step 5: Validate the Spec
Generate quality checklists to validate the specification using the `/speckit.checklist` command:
```bash
```text
/speckit.checklist
```
### Step 6: Define Tasks
### Step 6: `/speckit.tasks` — break the work down
Generate an actionable task list using the `/speckit.tasks` command:
Generates an actionable, dependency-ordered `tasks.md` from the design artifacts.
```bash
```text
/speckit.tasks
```
### Step 7: Validate and Implement
### Step 7: `/speckit.analyze` — check consistency
Have your coding agent audit the spec, plan, and tasks with `/speckit.analyze` before implementation:
Reports conflicts, gaps, and ambiguities across `spec.md`, `plan.md`, and `tasks.md`. It's read-only — if it flags issues, fix them at the source and re-run before implementing.
```bash
```text
/speckit.analyze
```
Finally, implement the solution:
### Step 8: `/speckit.implement` — build it
```bash
Executes the tasks in `tasks.md` in dependency order. Run it once to build everything, or scope it to one phase at a time for large features.
```text
/speckit.implement
```
### Step 8: Converge
### Step 9: `/speckit.converge` — verify completeness
Run the `/speckit.converge` command after implementation to assess the current codebase against the feature's artifacts and append any remaining unbuilt work as new tasks to `tasks.md`. If the command appends new tasks, run `/speckit.implement` again to complete them, and repeat the converge step until the feature is fully complete.
Checks the codebase against the spec, plan, and tasks. If it finds gaps, it appends new tasks to `tasks.md`; run `/speckit.implement` and converge again until it reports converged. Otherwise you're done — proceed to review or open a PR.
```bash
```text
/speckit.converge
```
> [!TIP]
> **Phased Implementation**: For large projects like Taskify, consider implementing in phases (e.g., Phase 1: Basic project/task structure, Phase 2: Kanban functionality, Phase 3: Comments and assignments). This prevents context saturation and allows for validation at each stage.
> For a full reference on each command — arguments, output, phased implementation, and how they interact — see [Agentic SDD](reference/agentic-sdd.md).
## Key Principles
@@ -209,6 +134,7 @@ Run the `/speckit.converge` command after implementation to assess the current c
## Next Steps
- See the [Agentic SDD](reference/agentic-sdd.md) reference for full detail on every command
- Read the [complete methodology](https://github.com/github/spec-kit/blob/main/spec-driven.md) for in-depth guidance
- Check out [more examples](https://github.com/github/spec-kit/tree/main/templates) in the repository
- Explore the [source code on GitHub](https://github.com/github/spec-kit)

View File

@@ -0,0 +1,52 @@
# Agentic Bug Fix
The **bug** extension adds a three-step bug triage process — assess, fix, and validate — that your coding agent runs alongside the core [Agentic SDD](agentic-sdd.md) process. Each bug lives in its own directory under `.specify/bugs/<slug>/`, with one Markdown report per stage.
> [!NOTE]
> Commands are written in `/speckit.bug.*` form throughout this page. The exact invocation depends on your agent — some skills-based agents use `$speckit-bug-*` (e.g. Codex, ZCode) or `/skill:speckit-bug-*` (e.g. Kimi). Substitute the form your agent exposes.
The bug extension is a bundled, opt-in extension. Install it before using these commands:
```bash
specify extension add bug
```
The three commands share a single handle — the **slug**, the per-bug directory name under `.specify/bugs/`. Supply it with `slug=<name>`; if omitted, `/speckit.bug.assess` asks for one (or generates a unique one in automated mode). Slugs are normalized to lowercase kebab-case. If an assessment already exists for a slug, an interactive run asks before overwriting it, while an automated run refuses and picks a new unique slug instead.
```text
/speckit.bug.assess -> /speckit.bug.fix -> /speckit.bug.test
```
## `/speckit.bug.assess`
Triages a bug report — pasted text (such as a stack trace) or a URL (such as a GitHub issue) — against the codebase: it judges whether the report is a real bug, locates the suspected code paths, and proposes a remediation. This command is **read-only**: it writes only `assessment.md` and never modifies source code.
```text
/speckit.bug.assess "TypeError: cannot read properties of undefined (reading 'token') at /auth/callback"
```
```text
/speckit.bug.assess https://github.com/example/repo/issues/1234 slug=callback-token
```
Output: `.specify/bugs/<slug>/assessment.md`.
## `/speckit.bug.fix`
Applies the remediation described in the assessment and records exactly what changed. This is the **only** bug command that edits source code, and it stays within the files listed in the assessment unless new evidence requires expanding scope (logged under **Deviations from Assessment**).
```text
/speckit.bug.fix slug=callback-token
```
Output: `.specify/bugs/<slug>/fix.md`.
## `/speckit.bug.test`
Validates the fix by re-running the reproduction and any added tests, then records the verification result — one of `verified`, `partial`, or `failed`. Like `assess`, it is **read-only** with respect to source code. Verdicts are never over-claimed: if the assessment listed a reproduction that wasn't actually exercised, the overall result is downgraded to `partial` rather than reported as `verified`.
```text
/speckit.bug.test slug=callback-token
```
Output: `.specify/bugs/<slug>/test.md`.

View File

@@ -0,0 +1,115 @@
# Agentic SDD
The `/speckit.*` slash commands drive the core Spec-Driven Development (SDD) process — an **agentic process** your coding agent runs step by step. For a guided, end-to-end run see the [Quick Start Guide](../quickstart.md); this page is the detailed reference for each command — including arguments, output, and how they interact. For the philosophy behind the process, see [What is SDD?](../concepts/sdd.md). For bug triage, see [Agentic Bug Fix](agentic-bugfix.md).
The commands are designed to run in order, but only `/speckit.specify` is strictly required before `/speckit.plan`. The clarify, checklist, and analyze commands are quality gates you add for anything with meaningful ambiguity.
> [!NOTE]
> Commands are written in `/speckit.*` form throughout this page. The exact invocation depends on your agent — some skills-based agents use `$speckit-*` (e.g. Codex, ZCode) or `/skill:speckit-*` (e.g. Kimi). Substitute the form your agent exposes.
```text
/speckit.constitution -> /speckit.specify -> /speckit.clarify -> /speckit.plan -> /speckit.checklist -> /speckit.tasks -> /speckit.analyze -> /speckit.implement -> /speckit.converge
```
## `/speckit.constitution`
Creates or updates the project **constitution** — the guiding principles that every later phase is evaluated against — and keeps dependent templates in sync. Run it once up front and update it whenever your principles change. Pass the principles as arguments.
```text
/speckit.constitution This project follows a "Library-First" approach. All features must be implemented as standalone libraries first. We use TDD strictly. We prefer functional programming patterns.
```
## `/speckit.specify`
Creates or updates the feature **specification** from a natural-language description. Focus on the **what** and **why** — the user-facing behavior and goals — not the tech stack, which belongs in `/speckit.plan`.
```text
/speckit.specify Build an application that helps me organize photos into albums grouped by date, re-orderable by drag-and-drop on the main page, with a tile preview inside each album.
```
## `/speckit.clarify`
Asks up to five targeted questions about underspecified areas of the current spec and encodes your answers back into `spec.md`. Run it as many times as needed before planning, each time tackling a different area. Optionally pass a focus area as an argument.
```text
/speckit.clarify Focus on the task card behavior: status changes, comment limits, and who can be assigned.
```
Clarifying before planning keeps you from designing on top of ambiguity. If `/speckit.analyze` later surfaces requirement gaps, come back and run `/speckit.clarify` (or `/speckit.specify`) again.
## `/speckit.plan`
Runs the planning process to generate design artifacts from the spec. This is where implementation detail belongs — provide your tech stack, architecture, and technical constraints as arguments.
```text
/speckit.plan Use .NET Aspire with Postgres. The frontend is Blazor Server with drag-and-drop boards and real-time updates. Expose REST APIs for projects, tasks, and notifications.
```
## `/speckit.checklist`
Generates a quality checklist for the feature — think of it as **"unit tests for your requirements."** Rather than testing code, it checks whether the spec itself is complete, clear, unambiguous, and consistent (for example: "Are the drag-and-drop rules defined for every column?", "Is behavior specified for a deleted assigned user?").
Run it with no arguments for a broad pass, or pass a focus area to target one aspect:
```text
/speckit.checklist
```
```text
/speckit.checklist Focus on the Kanban board interactions and comment permissions.
```
Review the generated checklist. If it surfaces gaps, loop back to `/speckit.clarify` or `/speckit.specify` to tighten the spec before breaking the work down.
## `/speckit.tasks`
Generates an actionable, dependency-ordered `tasks.md` from the design artifacts. Tasks are organized into phases: **Setup**, **Foundational** (blocking prerequisites), then **one phase per user story** in priority order, and a final **Polish** phase for cross-cutting concerns. Tests are generated within a user story's phase when requested rather than as a separate phase, and tasks are marked for parallel execution where possible.
```text
/speckit.tasks
```
## `/speckit.analyze`
Performs a **read-only** cross-artifact consistency and quality analysis across `spec.md`, `plan.md`, and `tasks.md`, reporting conflicts, gaps, and ambiguities (for example a task with no matching requirement, or a plan choice that contradicts the spec). It never edits files — it produces a report and can optionally suggest remediations for you to approve.
```text
/speckit.analyze
```
Run it before implementing, while the artifacts can still be adjusted cheaply. If it surfaces issues, **return to the earlier step that owns them** and fix them at the source — `/speckit.specify` or `/speckit.clarify` for requirement problems, `/speckit.plan` for design problems, `/speckit.tasks` to regenerate the task list — then re-run `/speckit.analyze` until it comes back clean. You can also run `/speckit.analyze` again after implementation as an extra review.
## `/speckit.implement`
Executes the tasks in `tasks.md`, running each phase in dependency order and respecting parallel markers.
For a small feature, run it once to build everything:
```text
/speckit.implement
```
For a large feature, work in stages to avoid overwhelming the agent's context — scope each run with an argument, validate the result, then continue:
```text
/speckit.implement Implement only the Setup and Foundational phases: project scaffolding and the project/task data model with basic CRUD. Stop before the user-story features.
```
```text
/speckit.implement Now implement the Kanban board user story: drag-and-drop between columns.
```
Verify each stage works before moving to the next.
## `/speckit.converge`
Assesses the codebase against the feature's spec, plan, and tasks to confirm nothing was missed. It is **append-only**: it never edits or deletes code, and its only possible write is adding tasks to `tasks.md`. Run it only after `/speckit.implement` has run on the current `tasks.md`.
```text
/speckit.converge
```
It first prints a severity-graded findings summary, then resolves to one of two outcomes:
- **Converged** — no gaps found. `tasks.md` is left byte-for-byte unchanged and you'll see a clean result like `✅ Converged — the implementation satisfies the spec, plan, and tasks.` You're done; proceed to review or open a PR.
- **Tasks appended** — gaps found. Converge appends them as new tasks under a Convergence section in `tasks.md` and tells you how many. Run `/speckit.implement` again to complete them, then `/speckit.converge` once more. Each pass finds fewer items; repeat until it reports converged.

View File

@@ -171,6 +171,63 @@ To set up configuration for a newly installed extension, copy the template:
cp .specify/extensions/<ext>/<ext>-config.template.yml \
.specify/extensions/<ext>/<ext>-config.yml
```
## Project Extension and Hook Configuration
Spec Kit stores project-level extension registration and hook configuration in:
```text
.specify/extensions.yml
```
The file contains installed extensions, global settings, and hooks that are surfaced before or after Spec Kit commands.
```yaml
installed:
- git
- my-extension
settings:
auto_execute_hooks: true
hooks:
before_implement:
- extension: git
command: speckit.git.commit
enabled: true
optional: true
priority: 10
prompt: "Commit outstanding changes before implementation?"
description: "Auto-commit before implementation"
after_implement:
- extension: my-extension
command: speckit.my-extension.verify
enabled: true
optional: false
priority: 5
description: "Run verification after implementation"
```
### Configuration fields
The top-level `installed` list records extensions installed in the project. The `settings` mapping stores project-wide extension settings, and `hooks` groups hook registrations by event.
`auto_execute_hooks` defaults to `true`, but is currently reserved and is not consulted when hooks are surfaced or invoked.
Each hook entry supports the following fields:
| Field | Description |
| --- | --- |
| `extension` | ID of the extension that registered the hook. |
| `command` | Extension command associated with the hook. |
| `enabled` | Whether the hook is active. Hooks with `enabled: false` are skipped. |
| `optional` | Whether the hook is optional. If `true`, the hook is presented with its `prompt` and can be skipped; if `false`, the hook is emitted as an automatic hook (includes `EXECUTE_COMMAND` markers). |
| `priority` | Priority metadata for the hook. Values must be integers >= 1; invalid values fall back to the default priority `10`. Current command templates surface hooks in their configured YAML order and do not sort them by `priority`. |
| `prompt` | Message shown when asking whether to run an optional hook. |
| `description` | Human-readable explanation of what the hook does. |
| `condition` | Optional expression evaluated by `HookExecutor` (using `config.<path>` or `env.<VAR>` with `is set`, `==`, or `!=`). Current command templates do not evaluate conditions and skip hooks with a non-empty condition. |
Hook event names identify when a hook is invoked. They generally use `before_<command>` or `after_<command>`, such as `before_implement`, `after_implement`, `before_tasks`, and `after_tasks`.
`HookExecutor.get_hooks_for_event()` returns hooks ordered by `priority`, with lower values first. However, current command templates read hook lists directly and surface them in their configured YAML order rather than using priority ordering.
## FAQ

View File

@@ -1,6 +1,6 @@
# Supported AI Coding Agent Integrations
The Specify CLI supports a wide range of AI coding agents. When you run `specify init`, the CLI sets up the appropriate command files, context rules, and directory structures for your chosen AI coding agent — so you can start using Spec-Driven Development immediately, regardless of which tool you prefer.
The Specify CLI supports a wide range of AI coding agents. When you run `specify init`, the CLI sets up the appropriate command files and directory structures for your chosen AI coding agent — so you can start using Spec-Driven Development immediately, regardless of which tool you prefer.
## Supported AI Coding Agents
@@ -20,6 +20,7 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | |
| [GitHub Copilot](https://code.visualstudio.com/) | `copilot` | Defaults to legacy markdown mode: `.agent.md` command files under `.github/agents/`, companion `.prompt.md` files under `.github/prompts/`, and a `.vscode/settings.json` merge. Pass `--integration-options="--skills"` to scaffold skills as `speckit-<command>/SKILL.md` under `.github/skills/` instead. Legacy markdown mode is deprecated and will stop being the default in a future release. |
| [Goose](https://goose-docs.ai/) | `goose` | Uses YAML recipe format in `.goose/recipes/` |
| [Grok Build](https://docs.x.ai/build/overview) | `grok` | Skills-based integration; installs skills into `.grok/skills` and invokes them as `/speckit-<command>` |
| [Hermes](https://github.com/NousResearch/hermes-agent) | `hermes` | Skills-based integration; installs skills globally into `~/.hermes/skills/` |
| [IBM Bob](https://www.ibm.com/products/bob) | `bob` | IDE-based agent |
| [Junie](https://junie.jetbrains.com/) | `junie` | |
@@ -249,7 +250,11 @@ Spec Kit tracks one default integration in `.specify/integration.json` with `def
### Which integrations are multi-install safe?
An integration is multi-install safe when it uses isolated agent directories, a dedicated context file that does not collide with another safe integration, stable command invocation settings, and a separate install manifest. Shared Spec Kit templates remain aligned to the single default integration.
An integration is multi-install safe when it uses a static, unique agent root and command directory, stable command invocation settings, and a separate install manifest whose managed files do not overlap another safe integration. Registry tests enforce those path and manifest invariants. Shared Spec Kit templates remain aligned to the single default integration.
The Isolation column below lists paths Spec Kit manages for that integration (skills/commands roots and any integration-owned rule files). It is not a full inventory of every file an agent may read.
**Agent-context defaults are separate.** The optional agent-context extension maps each integration to a default context file in `extensions/agent-context/agent-context-defaults.json`. Those defaults are independent of multi-install safety: several agents may share a root file such as `AGENTS.md` when the extension is enabled. Multi-install safety does not require a unique context file per safe integration.
The currently declared multi-install safe integrations are:
@@ -263,6 +268,7 @@ The currently declared multi-install safe integrations are:
| `cursor-agent` | `.cursor/skills`, `.cursor/rules/specify-rules.mdc` |
| `firebender` | `.firebender/commands`, `.firebender/rules/specify-rules.mdc` |
| `gemini` | `.gemini/commands`, `GEMINI.md` |
| `grok` | `.grok/skills` |
| `junie` | `.junie/commands`, `.junie/AGENTS.md` |
| `kilocode` | `.kilocode/workflows`, `.kilocode/rules/specify-rules.md` |
| `qodercli` | `.qoder/commands`, `QODER.md` |
@@ -272,7 +278,7 @@ The currently declared multi-install safe integrations are:
| `trae` | `.trae/skills`, `.trae/rules/project_rules.md` |
| `zcode` | `.zcode/skills`, `ZCODE.md` |
Integrations that share a context file or command directory with another integration, require dynamic install paths such as `--commands-dir`, or merge shared tool settings are not declared safe by default. They can still be installed alongside another integration with `--force`.
Integrations that share a command directory with another integration, require dynamic install paths such as `--commands-dir`, or merge shared tool settings are not declared safe by default. They can still be installed alongside another integration with `--force`.
### What happens to my changes when I uninstall or switch?

View File

@@ -1,6 +1,6 @@
# CLI Reference
# Reference
The Specify CLI (`specify`) manages the full lifecycle of Spec-Driven Development — from project initialization to workflow automation.
The Specify CLI (`specify`) manages the full lifecycle of Spec-Driven Development — from project initialization to workflow automation. This section is the detailed reference for the CLI's commands and primitives, plus the agentic `/speckit.*` processes your coding agent runs.
## Core Commands
@@ -10,7 +10,7 @@ The foundational commands for creating and managing Spec Kit projects. Initializ
## Integrations
Integrations connect Spec Kit to your AI coding agent. Each integration sets up the appropriate command files, context rules, and directory structures for a specific agent. Only one integration is active per project at a time, and you can switch between them at any point.
Integrations connect Spec Kit to your AI coding agent. Each integration sets up the appropriate command files and directory structures for a specific agent. Only one integration is active per project at a time, and you can switch between them at any point.
[Integrations reference →](integrations.md)
@@ -37,3 +37,19 @@ Workflows automate multi-step Spec-Driven Development processes into repeatable
Bundles compose existing extensions, presets, workflows, and steps into a single, versioned, installable unit. Rather than adding new behavior, a bundle curates a stack of primitives — everything a team or role needs — and installs it in one step through each component's own machinery, with version pinning, conflict checks, and provenance tracking for clean updates and removal.
[Bundles reference →](bundles.md)
## Agentic Commands
The sections above cover primitives managed by the `specify` CLI. The following are the `/speckit.*` slash commands your coding agent runs step by step inside the editor — the agentic processes built on top of that foundation.
### Agentic SDD
The `/speckit.*` slash commands that drive the core Spec-Driven Development process your coding agent runs step by step: constitution, specify, clarify, plan, checklist, tasks, analyze, implement, and converge. Run them in order, adding the clarify/checklist/analyze quality gates for anything with meaningful ambiguity.
[Agentic SDD reference →](agentic-sdd.md)
### Agentic Bug Fix
The bundled **bug** extension adds a three-step bug triage process — assess, fix, and validate — with each bug tracked in its own directory under `.specify/bugs/`. Install it with `specify extension add bug`.
[Agentic Bug Fix reference →](agentic-bugfix.md)

View File

@@ -39,6 +39,10 @@
href: reference/workflows.md
- name: Bundles
href: reference/bundles.md
- name: Agentic SDD
href: reference/agentic-sdd.md
- name: Agentic Bug Fix
href: reference/agentic-bugfix.md
- name: Authentication
href: reference/authentication.md

View File

@@ -17,6 +17,7 @@
"gemini": "GEMINI.md",
"generic": "AGENTS.md",
"goose": "AGENTS.md",
"grok": "AGENTS.md",
"hermes": "AGENTS.md",
"junie": ".junie/AGENTS.md",
"kilocode": ".kilocode/rules/specify-rules.md",

View File

@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
"updated_at": "2026-07-15T00:00:00Z",
"updated_at": "2026-07-16T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
"extensions": {
"aide": {
@@ -395,6 +395,66 @@
"created_at": "2026-03-03T00:00:00Z",
"updated_at": "2026-03-03T00:00:00Z"
},
"bdd": {
"name": "Spec-Kit BDD",
"id": "bdd",
"description": "ATDD/BDD extension: convert specs to Gherkin scenarios, scaffold step definitions, and verify acceptance test coverage.",
"author": "RSginer",
"version": "1.0.2",
"download_url": "https://github.com/RSginer/spec-kit-bdd/archive/refs/tags/v1.0.2.zip",
"repository": "https://github.com/RSginer/spec-kit-bdd",
"homepage": "https://github.com/RSginer/spec-kit-bdd",
"documentation": "https://github.com/RSginer/spec-kit-bdd/blob/main/docs/usage.md",
"changelog": "https://github.com/RSginer/spec-kit-bdd/releases",
"license": "MIT",
"category": "process",
"effect": "read-write",
"requires": {
"speckit_version": ">=0.2.0",
"tools": [
{
"name": "pytest-bdd",
"required": false
},
{
"name": "behave",
"required": false
},
{
"name": "@cucumber/cucumber",
"required": false
},
{
"name": "cucumber",
"required": false
},
{
"name": "io.cucumber",
"required": false
},
{
"name": "SpecFlow",
"required": false
}
]
},
"provides": {
"commands": 3,
"hooks": 2
},
"tags": [
"bdd",
"gherkin",
"atdd",
"acceptance-testing",
"tdd"
],
"verified": false,
"downloads": 0,
"stars": 0,
"created_at": "2026-07-15T00:00:00Z",
"updated_at": "2026-07-15T00:00:00Z"
},
"blueprint": {
"name": "Blueprint",
"id": "blueprint",
@@ -1106,10 +1166,10 @@
"docguard": {
"name": "DocGuard — CDD Enforcement",
"id": "docguard",
"description": "Doc-integrity engine with MCP server, SARIF output, and zero-LLM core. Validates, scores, and traces documentation against code — 24 validators, stable finding codes, spec-kit hooks. Pure Node.js.",
"description": "The only doc-integrity engine with an MCP server, SARIF/JUnit output, and a deterministic zero-LLM core. Validates, scores, and traces documentation against code — 27 validators, stable finding codes, adoption baseline for legacy repos, compliance-evidence reports, GitHub Action with PR annotations, spec-kit hooks. Pure Node.js, one pinned dep.",
"author": "raccioly",
"version": "0.32.0",
"download_url": "https://github.com/raccioly/docguard/releases/download/v0.32.0/spec-kit-docguard-v0.32.0.zip",
"version": "0.33.0",
"download_url": "https://github.com/raccioly/docguard/releases/download/v0.33.0/spec-kit-docguard-v0.33.0.zip",
"repository": "https://github.com/raccioly/docguard",
"homepage": "https://www.npmjs.com/package/docguard-cli",
"documentation": "https://github.com/raccioly/docguard/blob/main/extensions/spec-kit-docguard/README.md",
@@ -1153,7 +1213,7 @@
"downloads": 0,
"stars": 0,
"created_at": "2026-03-13T00:00:00Z",
"updated_at": "2026-07-13T00:00:00Z"
"updated_at": "2026-07-16T00:00:00Z"
},
"doctor": {
"name": "Project Health Check",
@@ -1188,6 +1248,47 @@
"created_at": "2026-03-13T00:00:00Z",
"updated_at": "2026-03-13T00:00:00Z"
},
"dotdog": {
"name": "Dotdog",
"id": "dotdog",
"description": "Import GitHub Spec Kit artifacts into local knowledge graphs for validation, analysis, search, and MCP queries.",
"author": "specdog",
"version": "0.9.0",
"download_url": "https://github.com/specdog/dotdog/releases/download/v0.9.0/dotdog-spec-kit-extension-v0.9.0.zip",
"repository": "https://github.com/specdog/dotdog",
"homepage": "https://specdog.github.io/dotdog",
"documentation": "https://github.com/specdog/dotdog/blob/main/docs/spec-kit-extension.md",
"changelog": "https://github.com/specdog/dotdog/blob/main/CHANGELOG.md",
"license": "MIT",
"category": "docs",
"effect": "read-write",
"requires": {
"speckit_version": ">=0.12.0",
"tools": [
{
"name": "dotdog",
"version": ">=0.9.0",
"required": true
}
]
},
"provides": {
"commands": 3,
"hooks": 0
},
"tags": [
"specification",
"knowledge-graph",
"validation",
"mcp",
"local-first"
],
"verified": false,
"downloads": 0,
"stars": 0,
"created_at": "2026-07-16T00:00:00Z",
"updated_at": "2026-07-16T00:00:00Z"
},
"ears": {
"name": "EARS Requirements Syntax",
"id": "ears",
@@ -1295,6 +1396,43 @@
"created_at": "2026-07-08T00:00:00Z",
"updated_at": "2026-07-08T00:00:00Z"
},
"figma-starter": {
"name": "Figma Starter",
"id": "figma-starter",
"description": "Turns a Figma section's screens into per-screen spec.md files, an app-level user-stories.md, and a build-order.md, then hands off to /speckit.specify.",
"author": "WaveMaker",
"version": "1.0.0",
"download_url": "https://github.com/wavemaker/spec-kit-figma-starter/archive/refs/tags/v1.0.0.zip",
"repository": "https://github.com/wavemaker/spec-kit-figma-starter",
"homepage": "https://github.com/wavemaker/spec-kit-figma-starter",
"documentation": "https://github.com/wavemaker/spec-kit-figma-starter/blob/main/README.md",
"changelog": "https://github.com/wavemaker/spec-kit-figma-starter/blob/main/CHANGELOG.md",
"license": "MIT",
"category": "integration",
"effect": "read-write",
"requires": {
"speckit_version": ">=0.1.0",
"tools": [
{ "name": "python3", "version": ">=3.8", "required": true }
]
},
"provides": {
"commands": 1,
"hooks": 1
},
"tags": [
"figma",
"design",
"design-to-spec",
"ui",
"frontend"
],
"verified": false,
"downloads": 0,
"stars": 0,
"created_at": "2026-07-15T00:00:00Z",
"updated_at": "2026-07-15T00:00:00Z"
},
"fix-findings": {
"name": "Fix Findings",
"id": "fix-findings",
@@ -1438,13 +1576,14 @@
"gates": {
"name": "Quality Gates (Enforcement Layer)",
"id": "gates",
"description": "Deterministic quality enforcement for Spec Kit projects at three boundaries — agent hooks, git pre-commit, CI — with one policy file and provable enforcement (attestations, canaries, verified parity).",
"description": "Deterministic quality enforcement for Spec Kit across agent hooks, git checks, and CI pipelines with one policy file and one verify entrypoint for identical results at every boundary.",
"author": "schwichtgit",
"version": "0.1.0",
"download_url": "https://github.com/schwichtgit/spec-gates/releases/download/v0.1.0/gates-0.1.0.zip",
"version": "0.3.2",
"download_url": "https://github.com/schwichtgit/spec-gates/releases/download/v0.3.2/gates-0.3.2.zip",
"repository": "https://github.com/schwichtgit/spec-gates",
"homepage": "https://github.com/schwichtgit/spec-gates",
"documentation": "https://github.com/schwichtgit/spec-gates/blob/main/docs/how-it-works.md",
"changelog": "https://github.com/schwichtgit/spec-gates/releases",
"license": "MIT",
"category": "process",
"effect": "read-write",
@@ -1457,7 +1596,7 @@
},
{
"name": "git",
"required": true
"required": false
},
{
"name": "node",
@@ -1470,8 +1609,8 @@
]
},
"provides": {
"commands": 5,
"hooks": 1
"commands": 8,
"hooks": 2
},
"tags": [
"quality",
@@ -1484,7 +1623,7 @@
"downloads": 0,
"stars": 0,
"created_at": "2026-07-09T00:00:00Z",
"updated_at": "2026-07-13T00:00:00Z"
"updated_at": "2026-07-15T00:00:00Z"
},
"github-issues": {
"name": "GitHub Issues Integration 1",

View File

@@ -41,6 +41,16 @@ if ($Help) {
exit 0
}
# -Number is [long], so PowerShell binds "-5" as -5 rather than rejecting it
# the way the bash/Python twins do (`^[0-9]+$`). A negative value would format
# via '{0:000}' to e.g. "-005" and produce a branch name starting with "-",
# which git refuses (refs cannot begin with a dash). Reject it here, before the
# description check, matching the bash twin's parse-time validation order.
if ($Number -lt 0) {
Write-Error 'Error: --number must be a non-negative integer'
exit 1
}
if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) {
Write-Error "Usage: ./create-new-feature-branch.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
exit 1

View File

@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
"updated_at": "2026-06-23T00:00:00Z",
"updated_at": "2026-07-15T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json",
"integrations": {
"claude": {
@@ -282,6 +282,15 @@
"repository": "https://github.com/github/spec-kit",
"tags": ["cli"]
},
"grok": {
"id": "grok",
"name": "Grok Build",
"version": "1.0.0",
"description": "xAI Grok Build CLI skills-based integration",
"author": "spec-kit-core",
"repository": "https://github.com/github/spec-kit",
"tags": ["cli", "skills", "xai"]
},
"hermes": {
"id": "hermes",
"name": "Hermes Agent",

View File

@@ -1,6 +1,6 @@
[project]
name = "specify-cli"
version = "0.12.16"
version = "0.12.18"
description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
readme = "README.md"
requires-python = ">=3.11"

View File

@@ -12,7 +12,7 @@ from __future__ import annotations
DOLLAR_SKILLS_AGENTS: frozenset[str] = frozenset({"codex", "zcode"})
# Agents that always render /speckit-<name>, regardless of ai_skills.
ALWAYS_SLASH_AGENTS: frozenset[str] = frozenset({"devin", "trae", "zed"})
ALWAYS_SLASH_AGENTS: frozenset[str] = frozenset({"devin", "grok", "trae", "zed"})
# Agents that render /speckit-<name> only when ai_skills is enabled.
CONDITIONAL_SLASH_AGENTS: frozenset[str] = frozenset(

View File

@@ -701,6 +701,7 @@ def register(app: typer.Typer) -> None:
copilot_skill_mode = selected_ai == "copilot" and _is_skills_integration
devin_skill_mode = selected_ai == "devin"
zed_skill_mode = selected_ai == "zed" and _is_skills_integration
grok_skill_mode = selected_ai == "grok" and _is_skills_integration
cline_skill_mode = selected_ai == "cline"
native_skill_mode = (
codex_skill_mode
@@ -713,6 +714,7 @@ def register(app: typer.Typer) -> None:
or copilot_skill_mode
or devin_skill_mode
or zed_skill_mode
or grok_skill_mode
)
if codex_skill_mode:
@@ -745,6 +747,11 @@ def register(app: typer.Typer) -> None:
f"{step_num}. Start Zed in this project directory; spec-kit skills were installed to [cyan].agents/skills[/cyan]"
)
step_num += 1
if grok_skill_mode:
steps_lines.append(
f"{step_num}. Start Grok Build in this project directory; spec-kit skills were installed to [cyan].grok/skills[/cyan]"
)
step_num += 1
usage_label = "skills" if native_skill_mode else "slash commands"
from .._invocation_style import (

View File

@@ -1004,6 +1004,7 @@ class ExtensionManager:
from .. import load_init_options
from ..agents import CommandRegistrar
from ..integrations import get_integration
from ..integrations.base import IntegrationBase
written: List[str] = []
opts = load_init_options(self.project_root)
@@ -1015,6 +1016,30 @@ class ExtensionManager:
registrar = CommandRegistrar()
agent_config = registrar.AGENT_CONFIGS.get(selected_ai, {})
integration = get_integration(selected_ai)
ai_skills_enabled = is_ai_skills_enabled(opts)
def _resolve_command_ref_tokens(body: str) -> str:
"""Resolve explicit command-ref tokens with the active skill style."""
def _replacement(match: re.Match[str]) -> str:
command_name = "speckit." + match.group(1).lower().replace("_", ".")
if is_dollar_skills_agent(selected_ai, ai_skills_enabled):
return "$" + command_name.replace("speckit.", "speckit-").replace(
".", "-"
)
if is_slash_skills_agent(selected_ai, ai_skills_enabled):
return "/" + command_name.replace("speckit.", "speckit-").replace(
".", "-"
)
if integration is not None:
return integration.build_command_invocation(command_name)
return IntegrationBase.resolve_command_refs(
match.group(0), agent_config.get("invoke_separator", ".")
)
return re.sub(
r"__SPECKIT_COMMAND_([A-Z][A-Z0-9_]*)__", _replacement, body
)
for cmd_info in manifest.commands:
cmd_name = cmd_info["name"]
@@ -1086,6 +1111,7 @@ class ExtensionManager:
body = registrar.resolve_skill_placeholders(
selected_ai, frontmatter, body, self.project_root, extension_id=manifest.id
)
body = _resolve_command_ref_tokens(body)
original_desc = frontmatter.get("description", "")
description = original_desc or f"Extension command: {cmd_name}"

View File

@@ -63,6 +63,7 @@ def _register_builtins() -> None:
from .gemini import GeminiIntegration
from .generic import GenericIntegration
from .goose import GooseIntegration
from .grok import GrokIntegration
from .hermes import HermesIntegration
from .junie import JunieIntegration
from .kilocode import KilocodeIntegration
@@ -99,6 +100,7 @@ def _register_builtins() -> None:
_register(GeminiIntegration())
_register(GenericIntegration())
_register(GooseIntegration())
_register(GrokIntegration())
_register(HermesIntegration())
_register(JunieIntegration())
_register(KilocodeIntegration())

View File

@@ -260,6 +260,7 @@ def _update_init_options_for_integration(
project_root: Path,
integration: Any,
script_type: str | None = None,
parsed_options: dict[str, Any] | None = None,
) -> None:
"""Update init-options.json to reflect *integration* as the active one.
@@ -278,7 +279,17 @@ def _update_init_options_for_integration(
opts["speckit_version"] = _get_speckit_version()
if script_type:
opts["script"] = script_type
if isinstance(integration, SkillsIntegration) or getattr(integration, "_skills_mode", False):
# Skills mode is either intrinsic (SkillsIntegration), set on the instance
# during setup() (_skills_mode), or requested via parsed options (e.g.
# Copilot's --skills, persisted as parsed_options["skills"]). The latter is
# the only signal available on the `use` path, where no setup() runs and a
# fresh integration instance has _skills_mode == False (issue #3550).
skills_mode = (
isinstance(integration, SkillsIntegration)
or getattr(integration, "_skills_mode", False)
or bool((parsed_options or {}).get("skills"))
)
if skills_mode:
opts["ai_skills"] = True
else:
opts.pop("ai_skills", None)
@@ -334,7 +345,9 @@ def _set_default_integration(
) from exc
_write_integration_json(project_root, key, installed_keys, settings)
_update_init_options_for_integration(project_root, integration, script_type=resolved_script)
_update_init_options_for_integration(
project_root, integration, script_type=resolved_script, parsed_options=parsed_options
)
def _set_default_integration_or_exit(*args: Any, **kwargs: Any) -> None:

View File

@@ -0,0 +1,60 @@
"""Grok Build integration — skills-based agent.
Grok Build discovers project skills from ``.grok/skills/speckit-<name>/SKILL.md``
(and also scans ``.agents/skills/``). Spec Kit installs into the native
``.grok/skills`` tree so skills take highest local priority.
"""
from __future__ import annotations
from ..base import SkillsIntegration
class GrokIntegration(SkillsIntegration):
"""Integration for xAI Grok Build CLI."""
key = "grok"
config = {
"name": "Grok Build",
"folder": ".grok/",
"commands_subdir": "skills",
"install_url": "https://docs.x.ai/build/overview",
"requires_cli": True,
}
registrar_config = {
"dir": ".grok/skills",
"format": "markdown",
"args": "$ARGUMENTS",
"extension": "/SKILL.md",
}
multi_install_safe = True
def build_exec_args(
self,
prompt: str,
*,
model: str | None = None,
output_json: bool = True,
) -> list[str] | None:
"""Build CLI arguments for non-interactive ``grok`` execution.
Mandatory headless flag:
* ``--always-approve`` — auto-approve tool executions so workflow
dispatch and ``dispatch_command()`` are not blocked at permission
gates (same role as Cursor's ``--force`` / Copilot's ``--yolo``).
"""
if not self.config or not self.config.get("requires_cli"):
return None
args = [
self._resolve_executable(),
"-p",
prompt,
"--always-approve",
]
self._apply_extra_args_env_var(args)
if model:
args.extend(["--model", model])
if output_json:
args.extend(["--output-format", "json"])
return args

View File

@@ -22,10 +22,33 @@ class IfThenStep(StepBase):
result = evaluate_condition(condition, context)
if result:
branch_name = "then"
branch = config.get("then", [])
else:
branch_name = "else"
branch = config.get("else", [])
# The engine does not auto-validate step config (see
# ``WorkflowEngine.load_workflow``), and it feeds ``next_steps`` straight
# into ``_execute_steps`` which iterates them as step mappings. A
# non-list branch (a single mapping or scalar authoring mistake) would
# otherwise be iterated element-wise — a dict yields its string keys, a
# str its characters — and crash the whole run with AttributeError on
# ``.get()``. ``validate`` already rejects a non-list branch; fail this
# step loudly on an unvalidated run instead, mirroring the switch/fan-out
# steps. A missing ``else`` defaults to ``[]`` and stays valid.
if branch is None and branch_name == "else":
branch = []
elif not isinstance(branch, list):
return StepResult(
status=StepStatus.FAILED,
output={"condition_result": result},
error=(
f"If step {config.get('id', '?')!r}: {branch_name!r} must be "
f"a list of steps, got {type(branch).__name__}."
),
)
return StepResult(
status=StepStatus.COMPLETED,
output={"condition_result": result},

View File

@@ -42,6 +42,10 @@ class SwitchStep(StepBase):
)
for case_key, case_steps in cases.items():
if str(case_key) == str_value:
if not isinstance(case_steps, list):
return self._non_list_branch_failure(
config, f"case {str(case_key)!r}", case_steps, value
)
return StepResult(
status=StepStatus.COMPLETED,
output={"matched_case": str(case_key), "expression_value": value},
@@ -50,12 +54,41 @@ class SwitchStep(StepBase):
# Default fallback
default_steps = config.get("default", [])
if default_steps is None:
default_steps = []
elif not isinstance(default_steps, list):
return self._non_list_branch_failure(
config, "'default'", default_steps, value
)
return StepResult(
status=StepStatus.COMPLETED,
output={"matched_case": "__default__", "expression_value": value},
next_steps=default_steps,
)
@staticmethod
def _non_list_branch_failure(
config: dict[str, Any], branch_label: str, branch: Any, value: Any
) -> StepResult:
"""Fail the step for a non-list branch instead of crashing the run.
``validate`` rejects a non-list case/default branch, but the engine does
not auto-validate and feeds ``next_steps`` straight into
``_execute_steps``, which iterates them as step mappings. A non-list
branch would be iterated element-wise (a dict yields its keys, a str its
characters) and crash the whole run with AttributeError on ``.get()``.
Fail this step loudly on an unvalidated run instead, mirroring the
non-mapping ``cases`` guard above.
"""
return StepResult(
status=StepStatus.FAILED,
output={"matched_case": None, "expression_value": value},
error=(
f"Switch step {config.get('id', '?')!r}: {branch_label} must be "
f"a list of steps, got {type(branch).__name__}."
),
)
def validate(self, config: dict[str, Any]) -> list[str]:
errors = super().validate(config)
if "expression" not in config:

View File

@@ -653,6 +653,19 @@ class TestCreateFeatureBash:
assert data["BRANCH_NAME"] == "000-zero"
assert data["FEATURE_NUM"] == "000"
def test_negative_number_rejected(self, tmp_path: Path):
"""A negative --number is rejected. Pins the canonical behavior the
PowerShell twin must mirror; a negative value would otherwise format to
e.g. '-005' and produce a branch name starting with '-', which git
refuses (refs cannot begin with a dash)."""
project = _setup_project(tmp_path)
result = _run_bash(
"create-new-feature-branch.sh", project,
"--json", "--dry-run", "--number", "-5", "--short-name", "neg", "Negative feature",
)
assert result.returncode != 0
assert "--number must be a non-negative integer" in result.stderr
@pytest.mark.skipif(not HAS_PWSH, reason="pwsh not available")
class TestCreateFeaturePowerShell:
@@ -974,6 +987,21 @@ class TestCreateFeaturePowerShell:
assert data["BRANCH_NAME"] == "000-zero"
assert data["FEATURE_NUM"] == "000"
def test_negative_number_rejected(self, tmp_path: Path):
"""A negative -Number is rejected, matching the bash/Python twins'
'--number must be a non-negative integer'. Regression guard: -Number is
[long], so PowerShell binds '-5' as -5 rather than rejecting it the way
the twins' `^[0-9]+$` check does; the value would then format via
'{0:000}' to '-005' and yield a branch name starting with '-', which
git refuses (refs cannot begin with a dash)."""
project = _setup_project(tmp_path)
result = _run_pwsh(
"create-new-feature-branch.ps1", project,
"-Json", "-DryRun", "-Number", "-5", "-ShortName", "neg", "Negative feature",
)
assert result.returncode != 0
assert "--number must be a non-negative integer" in result.stderr
# ── auto-commit.sh Tests ─────────────────────────────────────────────────────

View File

@@ -224,6 +224,66 @@ class TestInitIntegrationFlag:
assert "Continuing without the optional preset" in normalized
assert "Project ready" in normalized
def test_init_with_local_preset_seeds_manifest_constitution(
self, tmp_path, monkeypatch
):
from typer.testing import CliRunner
from specify_cli import app
from specify_cli.presets import PresetManager
monkeypatch.setattr(
PresetManager,
"_seed_constitution_from_preset",
lambda *_args, **_kwargs: None,
)
preset_dir = tmp_path / "constitution-preset"
(preset_dir / "organization").mkdir(parents=True)
preset_content = "# Ratified Organization Constitution\n"
(preset_dir / "organization" / "ratified.md").write_text(preset_content)
(preset_dir / "preset.yml").write_text(
yaml.safe_dump({
"schema_version": "1.0",
"preset": {
"id": "constitution-preset",
"name": "Constitution Preset",
"version": "1.0.0",
"description": "Provides a ratified constitution",
},
"requires": {"speckit_version": ">=0.1.0"},
"provides": {
"templates": [{
"type": "template",
"name": "constitution-template",
"file": "organization/ratified.md",
"strategy": "replace",
}]
},
})
)
project = tmp_path / "init-with-preset"
result = CliRunner().invoke(
app,
[
"init",
str(project),
"--integration",
"copilot",
"--script",
"sh",
"--ignore-agent-tools",
"--preset",
str(preset_dir),
],
catch_exceptions=False,
)
assert result.exit_code == 0, result.output
assert (
project / ".specify" / "memory" / "constitution.md"
).read_text() == preset_content
def test_integration_claude_here_preserves_preexisting_commands(self, tmp_path):
from typer.testing import CliRunner
from specify_cli import app

View File

@@ -0,0 +1,187 @@
"""Tests for GrokIntegration."""
import json
import pytest
from specify_cli.integrations import get_integration
from specify_cli.integrations.manifest import IntegrationManifest
from .test_integration_base_skills import SkillsIntegrationTests
class TestGrokIntegration(SkillsIntegrationTests):
KEY = "grok"
FOLDER = ".grok/"
COMMANDS_SUBDIR = "skills"
REGISTRAR_DIR = ".grok/skills"
def test_options_include_skills_flag(self):
"""Not applicable — Grok Build is always skills-based."""
pytest.skip("Grok Build is always skills-based and does not expose a --skills option")
def test_options_do_not_include_skills_flag(self):
i = get_integration(self.KEY)
assert i is not None
opts = i.options()
skills_opts = [o for o in opts if o.name == "--skills"]
assert len(skills_opts) == 0
def test_requires_cli_is_true(self):
i = get_integration(self.KEY)
assert i is not None
assert i.config["requires_cli"] is True
assert i.config["name"] == "Grok Build"
assert i.multi_install_safe is True
class TestGrokInitFlow:
"""--integration grok creates expected files."""
def test_integration_grok_creates_skills(self, tmp_path):
"""--integration grok should create skills in .grok/skills."""
from typer.testing import CliRunner
from specify_cli import app
runner = CliRunner()
target = tmp_path / "test-proj"
result = runner.invoke(
app,
[
"init",
str(target),
"--integration",
"grok",
"--ignore-agent-tools",
"--script",
"sh",
],
catch_exceptions=False,
)
assert result.exit_code == 0, f"init --integration grok failed: {result.output}"
assert (target / ".grok" / "skills" / "speckit-plan" / "SKILL.md").exists()
assert (target / ".grok" / "skills" / "speckit-specify" / "SKILL.md").exists()
def test_plan_skill_has_no_context_placeholder(self, tmp_path):
"""Core skills must not carry a context-file placeholder."""
target = tmp_path / "test-proj"
target.mkdir()
integration = get_integration("grok")
manifest = IntegrationManifest("grok", target)
integration.setup(target, manifest, script_type="sh")
plan_skill = target / ".grok" / "skills" / "speckit-plan" / "SKILL.md"
content = plan_skill.read_text(encoding="utf-8")
assert "__CONTEXT_FILE__" not in content
def test_build_exec_args_uses_headless_prompt_flag(self):
integration = get_integration("grok")
args = integration.build_exec_args("hello", model="grok-build", output_json=True)
assert args is not None
assert args[0] == "grok" or args[0].endswith("/grok")
assert "-p" in args
assert "hello" in args
assert "--always-approve" in args
assert "--model" in args
assert "grok-build" in args
assert "--output-format" in args
assert "json" in args
class TestGrokNextSteps:
"""CLI output tests for Grok next-steps display."""
def test_init_next_steps_show_grok_skill_guidance(self, tmp_path):
"""init --integration grok should guide users to .grok/skills and /speckit-*."""
from typer.testing import CliRunner
from specify_cli import app
runner = CliRunner()
target = tmp_path / "grok-next-steps"
result = runner.invoke(
app,
[
"init",
str(target),
"--integration",
"grok",
"--ignore-agent-tools",
"--script",
"sh",
],
catch_exceptions=False,
)
assert result.exit_code == 0, f"init --integration grok failed: {result.output}"
assert "Start Grok Build" in result.output, (
f"Expected Grok start guidance in next steps but got:\n{result.output}"
)
assert ".grok/skills" in result.output, (
f"Expected .grok/skills install path in next steps but got:\n{result.output}"
)
assert "/speckit-plan" in result.output, (
f"Expected /speckit-plan in next steps but got:\n{result.output}"
)
assert "/speckit.plan" not in result.output, (
f"Should not show /speckit.plan for Grok skills mode:\n{result.output}"
)
class TestGrokInitOptions:
"""Init-options persistence for always-skills Grok."""
def test_init_persists_ai_skills_for_grok(self, tmp_path, monkeypatch):
"""specify init --integration grok must persist ai_skills: true,
so HookExecutor renders slash-skill invocations without manual
init-options manipulation.
"""
from typer.testing import CliRunner
from specify_cli import app
from specify_cli.extensions import HookExecutor
project = tmp_path / "grok-init-test"
project.mkdir()
monkeypatch.chdir(project)
runner = CliRunner()
result = runner.invoke(
app,
[
"init",
"--here",
"--integration",
"grok",
"--script",
"sh",
"--ignore-agent-tools",
],
catch_exceptions=False,
)
assert result.exit_code == 0, f"init failed: {result.output}"
opts_path = project / ".specify" / "init-options.json"
assert opts_path.exists()
opts = json.loads(opts_path.read_text(encoding="utf-8"))
assert opts.get("ai") == "grok"
assert opts.get("ai_skills") is True, (
f"init must persist ai_skills=true for Grok, got: {opts.get('ai_skills')}"
)
hook_executor = HookExecutor(project)
message = hook_executor.format_hook_message(
"before_plan",
[
{
"extension": "test-ext",
"command": "speckit.plan",
"optional": False,
}
],
)
assert "Executing: `/speckit-plan`" in message, (
"Hook rendering must produce /speckit-plan for Grok without hint injection"
)
assert "EXECUTE_COMMAND_INVOCATION: /speckit-plan" in message

View File

@@ -1566,6 +1566,43 @@ class TestIntegrationUse:
assert opts["integration"] == "codex"
assert opts["ai"] == "codex"
def test_use_preserves_copilot_skills_mode(self, tmp_path):
"""`use` on a skills-mode Copilot keeps ``ai_skills`` (issue #3550).
Re-selecting the same skills-mode Copilot must not drop ``ai_skills``
from init-options.json nor regenerate extension commands in the legacy
``.agent.md``/``.prompt.md`` layout.
"""
project = _init_project(tmp_path, "copilot", integration_options="--skills")
opts = json.loads((project / ".specify" / "init-options.json").read_text(encoding="utf-8"))
assert opts.get("ai_skills") is True, "precondition: init recorded skills mode"
result = _run_in_project(project, ["extension", "add", "git"])
assert result.exit_code == 0, f"extension add failed: {result.output}"
# Simulate a fresh process: `use` in real life runs in its own process
# where the registry's Copilot instance has _skills_mode == False (it is
# only set during setup()). In-process test invocations otherwise reuse
# the singleton left in skills mode by init, masking the bug (#3550).
from specify_cli.integrations import get_integration
get_integration("copilot")._skills_mode = False
result = _run_in_project(project, ["integration", "use", "copilot"])
assert result.exit_code == 0, result.output
opts = json.loads((project / ".specify" / "init-options.json").read_text(encoding="utf-8"))
assert opts.get("ai_skills") is True, "ai_skills must survive `use copilot`"
# No legacy command-layout files should be regenerated for the
# skills-mode agent.
assert not (project / ".github" / "agents" / "speckit.git.feature.agent.md").exists()
assert not (project / ".github" / "prompts" / "speckit.git.feature.prompt.md").exists()
assert (
project / ".github" / "skills" / "speckit-git-feature" / "SKILL.md"
).exists()
def test_use_requires_installed_integration(self, tmp_path):
project = _init_project(tmp_path, "claude")
old_cwd = os.getcwd()

View File

@@ -141,6 +141,8 @@ class TestSlashSkillsSets:
# ALWAYS_SLASH_AGENTS — unconditional on ai_skills
("devin", True, "/speckit-plan"),
("devin", False, "/speckit-plan"),
("grok", True, "/speckit-plan"),
("grok", False, "/speckit-plan"),
("trae", True, "/speckit-plan"),
("trae", False, "/speckit-plan"),
("zed", True, "/speckit-plan"),

View File

@@ -25,6 +25,7 @@ ISSUE_TEMPLATE_AGENT_KEYS = [
"gemini",
"copilot",
"goose",
"grok",
"hermes",
"bob",
"junie",

View File

@@ -970,6 +970,113 @@ class TestExtensionSkillRegistration:
assert "Read agents/control" not in content
assert "and knowledge-base/" not in content
@pytest.mark.parametrize(
("ai", "expected_invocation"),
[
("claude", "/speckit-plan"),
("copilot", "/speckit-plan"),
("codex", "$speckit-plan"),
("kimi", "/skill:speckit-plan"),
("zcode", "$speckit-plan"),
],
)
def test_skill_registration_resolves_command_ref_tokens(
self, project_dir, temp_dir, ai, expected_invocation
):
"""Auto-registered skills should resolve explicit command ref tokens."""
_create_init_options(project_dir, ai=ai, ai_skills=True)
skills_dir = _create_skills_dir(project_dir, ai=ai)
ext_dir = temp_dir / "command-ref-ext"
ext_dir.mkdir()
manifest_data = {
"schema_version": "1.0",
"extension": {
"id": "command-ref-ext",
"name": "Command Ref Extension",
"version": "1.0.0",
"description": "Test",
},
"requires": {"speckit_version": ">=0.1.0"},
"provides": {
"commands": [
{
"name": "speckit.command-ref-ext.run",
"file": "commands/run.md",
"description": "Run command",
}
]
},
}
with open(ext_dir / "extension.yml", "w") as f:
yaml.safe_dump(manifest_data, f)
(ext_dir / "commands").mkdir()
(ext_dir / "commands" / "run.md").write_text(
"---\n"
"description: Run command\n"
"---\n\n"
"Use __SPECKIT_COMMAND_PLAN__ before proceeding.\n"
)
manager = ExtensionManager(project_dir)
manager.install_from_directory(ext_dir, "0.1.0", register_commands=False)
content = (skills_dir / "speckit-command-ref-ext-run" / "SKILL.md").read_text()
assert "__SPECKIT_COMMAND_PLAN__" not in content
assert expected_invocation in content
def test_skill_registration_does_not_rewrite_literal_speckit_text(
self, project_dir, temp_dir
):
"""Auto-registered skills should leave literal speckit text untouched."""
_create_init_options(project_dir, ai="codex", ai_skills=True)
skills_dir = _create_skills_dir(project_dir, ai="codex")
ext_dir = temp_dir / "literal-ref-ext"
ext_dir.mkdir()
manifest_data = {
"schema_version": "1.0",
"extension": {
"id": "literal-ref-ext",
"name": "Literal Ref Extension",
"version": "1.0.0",
"description": "Test",
},
"requires": {"speckit_version": ">=0.1.0"},
"provides": {
"commands": [
{
"name": "speckit.literal-ref-ext.run",
"file": "commands/run.md",
"description": "Run command",
}
]
},
}
with open(ext_dir / "extension.yml", "w") as f:
yaml.safe_dump(manifest_data, f)
(ext_dir / "commands").mkdir()
(ext_dir / "commands" / "run.md").write_text(
"---\n"
"description: Run command\n"
"---\n\n"
"Literal slash form: /speckit.foo.bar\n"
"Literal skill form: /speckit-plan\n"
"Literal bare form: speckit.foo.bar\n"
)
manager = ExtensionManager(project_dir)
manager.install_from_directory(ext_dir, "0.1.0", register_commands=False)
content = (skills_dir / "speckit-literal-ref-ext-run" / "SKILL.md").read_text()
assert "/speckit.foo.bar" in content
assert "/speckit-plan" in content
assert "speckit.foo.bar" in content
assert "/speckit-foo-bar" not in content
assert "$speckit-plan" not in content
def test_missing_command_file_skipped(self, skills_project, temp_dir):
"""Commands with missing source files should be skipped gracefully."""
project_dir, skills_dir = skills_project

View File

@@ -2112,6 +2112,69 @@ class TestIfThenStep:
errors = step.validate({"id": "test", "then": []})
assert any("missing 'condition'" in e for e in errors)
@pytest.mark.parametrize("bad_branch", [{"id": "x"}, "oops", 5])
def test_execute_non_list_then_fails_loudly(self, bad_branch):
"""A non-list ``then`` must fail the step, not crash the run.
``validate`` rejects a non-list ``then``, but the engine does not
auto-validate (see ``WorkflowEngine.load_workflow``) and feeds
``next_steps`` straight into ``_execute_steps``, which iterates them as
step mappings. Before the guard, a non-list ``then`` (a single mapping
or scalar authoring mistake) was iterated element-wise and raised
AttributeError on ``.get()``, taking down the whole run. Mirrors the
switch/fan-out non-list handling.
"""
from specify_cli.workflows.steps.if_then import IfThenStep
from specify_cli.workflows.base import StepContext, StepStatus
step = IfThenStep()
ctx = StepContext(inputs={})
result = step.execute(
{"id": "branch", "condition": "true", "then": bad_branch}, ctx
)
assert result.status == StepStatus.FAILED
assert "'then' must be a list of steps" in (result.error or "")
assert result.next_steps == []
@pytest.mark.parametrize("bad_branch", [{"id": "x"}, "oops", 5])
def test_execute_non_list_else_fails_loudly(self, bad_branch):
"""A non-list ``else`` selected at runtime must fail the step, not crash.
Same asymmetry as ``then``: the ``else`` branch is only reached when the
condition is false, so a non-list ``else`` reaches ``next_steps`` and
would crash the engine's step iteration on an unvalidated run.
"""
from specify_cli.workflows.steps.if_then import IfThenStep
from specify_cli.workflows.base import StepContext, StepStatus
step = IfThenStep()
ctx = StepContext(inputs={})
result = step.execute(
{"id": "branch", "condition": "false", "then": [], "else": bad_branch},
ctx,
)
assert result.status == StepStatus.FAILED
assert "'else' must be a list of steps" in (result.error or "")
assert result.next_steps == []
def test_execute_none_else_stays_empty(self):
"""An explicit ``else: null`` selected at runtime stays an empty branch.
``validate`` deliberately accepts ``else: None``; the execute guard must
normalize it to an empty branch (COMPLETED) rather than failing a
validator-approved workflow when the condition is false.
"""
from specify_cli.workflows.steps.if_then import IfThenStep
from specify_cli.workflows.base import StepContext, StepStatus
step = IfThenStep()
ctx = StepContext(inputs={})
result = step.execute(
{"id": "branch", "condition": "false", "then": [], "else": None}, ctx
)
assert result.status == StepStatus.COMPLETED
assert result.next_steps == []
@pytest.mark.parametrize("bad_else", [False, 0, "", {}, 42])
def test_validate_rejects_non_list_else(self, bad_else):
"""A non-list 'else' must be rejected even when it is falsy.
@@ -2245,6 +2308,91 @@ class TestSwitchStep:
# expression is still evaluated, so its value is surfaced for context.
assert result.output["expression_value"] == "approve"
@pytest.mark.parametrize("bad_branch", [{"id": "x"}, "oops", 5])
def test_execute_non_list_matched_case_fails_loudly(self, bad_branch):
"""A matched case with a non-list body must fail the step, not crash.
``validate`` rejects a non-list case body, but the engine does not
auto-validate (see ``WorkflowEngine.load_workflow``) and feeds the
selected branch straight into ``_execute_steps``, which iterates it as
step mappings. A non-list body (a single mapping or scalar authoring
mistake) would be iterated element-wise and raise AttributeError on
``.get()``, taking down the whole run. Mirrors the non-mapping
``cases`` guard.
"""
from specify_cli.workflows.steps.switch import SwitchStep
from specify_cli.workflows.base import StepContext, StepStatus
step = SwitchStep()
ctx = StepContext(steps={"review": {"output": {"choice": "approve"}}})
result = step.execute(
{
"id": "route",
"expression": "{{ steps.review.output.choice }}",
"cases": {"approve": bad_branch},
},
ctx,
)
assert result.status == StepStatus.FAILED
assert "case 'approve' must be a list of steps" in (result.error or "")
assert result.next_steps == []
# expression is still evaluated, so its value is surfaced for context.
assert result.output["expression_value"] == "approve"
@pytest.mark.parametrize("bad_branch", [{"id": "x"}, "oops", 5])
def test_execute_non_list_default_fails_loudly(self, bad_branch):
"""A non-list ``default`` reached at runtime must fail, not crash.
Same asymmetry as the case body: ``default`` is only selected when no
case matches, so a non-list ``default`` reaches ``next_steps`` and would
crash the engine's step iteration on an unvalidated run.
"""
from specify_cli.workflows.steps.switch import SwitchStep
from specify_cli.workflows.base import StepContext, StepStatus
step = SwitchStep()
ctx = StepContext(steps={"review": {"output": {"choice": "other"}}})
result = step.execute(
{
"id": "route",
"expression": "{{ steps.review.output.choice }}",
"cases": {"approve": [{"id": "plan", "command": "speckit.plan"}]},
"default": bad_branch,
},
ctx,
)
assert result.status == StepStatus.FAILED
assert "'default' must be a list of steps" in (result.error or "")
assert result.next_steps == []
# expression is still evaluated, so its value is surfaced for context.
assert result.output["expression_value"] == "other"
@pytest.mark.parametrize("ok_default", [None, [], [{"id": "x", "command": "/y"}]])
def test_execute_none_default_stays_empty(self, ok_default):
"""An explicit ``default: null`` or a list default stays valid.
``validate`` deliberately accepts ``default: None``; the execute guard
must normalize it to an empty branch (COMPLETED) rather than failing a
validator-approved workflow.
"""
from specify_cli.workflows.steps.switch import SwitchStep
from specify_cli.workflows.base import StepContext, StepStatus
step = SwitchStep()
ctx = StepContext(steps={"review": {"output": {"choice": "other"}}})
result = step.execute(
{
"id": "route",
"expression": "{{ steps.review.output.choice }}",
"cases": {"approve": [{"id": "plan", "command": "speckit.plan"}]},
"default": ok_default,
},
ctx,
)
assert result.status == StepStatus.COMPLETED
assert result.output["matched_case"] == "__default__"
assert result.next_steps == (ok_default or [])
def test_validate_missing_expression(self):
from specify_cli.workflows.steps.switch import SwitchStep