### Spec-driven by default
-The core SDD process ships ready to use: **Spec → Plan → Tasks → Implement**.
+The core SDD process ships ready to use: **Specify → Plan → Tasks → Implement → Converge**.
Define what to build before building it. Rich templates, quality checklists, and cross-artifact analysis come out of the box. Each phase produces a Markdown artifact that feeds the next — giving your AI coding agent structured context instead of ad-hoc prompts.
@@ -123,8 +140,20 @@ Community extensions like CI Guard and Architecture Guard add compliance gates a
- Getting Started
- Install, configure, and run your first SDD workflow
+ Spec-Driven Development
+ Define, plan, implement, and converge on a feature
+
+
+ Bug Fixing
+ Assess the cause, apply a scoped fix, and verify the result
+
+
+ Idea Assessment
+ Research an idea and decide whether it deserves investment
+
+
+ Customize Spec Kit
+ Adapt a process, add capabilities, or package a role-based setup
Existing Projects
@@ -165,8 +194,8 @@ uv tool install specify-cli
specify init my-project --integration copilot
```
-Ready to start? Follow the [Quick Start Guide](quickstart.md).
+Ready to start? [Choose your process](#choose-your-process).
-
Last updated: August 21, 2026
+
Last updated: September 14, 2026
diff --git a/docs/installation.md b/docs/installation.md
index 67b69505e6..a8a68fc992 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -95,6 +95,27 @@ specify init
--script ps
specify init --script py
```
+### CI and AI Agent Harnesses
+
+For environments without a keyboard, or a PTY that cannot send arrow keys, pass
+`--non-interactive` so initialization never waits on a picker:
+
+```bash
+specify init my-project --non-interactive --ignore-agent-tools
+```
+
+`--ignore-agent-tools` skips the agent executable check when the agent will run
+elsewhere; omit it when you want that check. Non-interactive initialization
+defaults to Copilot unless you select another integration explicitly.
+
+For a non-empty directory, `--force` acknowledges the merge warning. Review the
+[existing-project guide](guides/existing-projects.md) and commit or back up local
+changes before initializing:
+
+```bash
+specify init --here --force --non-interactive --integration claude
+```
+
### Ignore Agent Tools Check
If you prefer to get the templates without checking for the right tools:
@@ -134,6 +155,15 @@ Scripts are installed into a variant subdirectory matching the chosen script typ
- `.specify/scripts/powershell/` — contains `.ps1` scripts (default on Windows)
- `.specify/scripts/python/` — contains `.py` scripts (chosen with `--script py`; also installs the platform shell fallback)
+## Choose a Process
+
+After initialization, launch your coding agent in the project directory and
+follow the [SDD quickstart](quickstart.md),
+[bug-fixing quickstart](guides/bugfix.md), or
+[idea assessment quickstart](guides/assessment.md). These are independent entry
+points. SDD is available immediately; the other guides show how to install their
+bundled, opt-in extensions.
+
## Troubleshooting
### Enterprise / Air-Gapped Installation
diff --git a/docs/local-development.md b/docs/local-development.md
index 34070451fc..243771614c 100644
--- a/docs/local-development.md
+++ b/docs/local-development.md
@@ -4,6 +4,10 @@ This guide shows how to iterate on the `specify` CLI locally without publishing
> Scripts are available as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. Interactive `specify init` prompts you to choose one; non-interactive runs (no TTY, or `--non-interactive`) default to a shell variant for your OS. Pass `--script sh|ps|py` to select explicitly.
+For how the project uses its own SDD and assessment processes, see
+[Does Spec Kit use Spec Kit?](https://github.com/github/spec-kit/blob/main/CONTRIBUTING.md#does-spec-kit-use-spec-kit)
+in the contributor guide.
+
## 1. Clone and Switch Branches
```bash
diff --git a/docs/quickstart.md b/docs/quickstart.md
index fb2ecc2f74..692d725a55 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -1,38 +1,53 @@
-# Quick Start Guide
+
+
+# Spec-Driven Development Quickstart
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.
+Use SDD to build a feature or application from a specification. For a repair,
+follow the [bug-fixing quickstart](guides/bugfix.md); to decide whether an idea
+deserves investment, follow the [idea assessment quickstart](guides/assessment.md).
+These are independent processes, not prerequisites for this guide.
+
> [!NOTE]
> Automation scripts are provided as Bash (`.sh`), PowerShell (`.ps1`), and Python (`.py`) variants. Interactive `specify init` prompts you to choose one; non-interactive runs (no TTY, or `--non-interactive`) default to a shell variant for your OS. Pass `--script sh|ps|py` to select explicitly.
-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.
+The process steps here use GitHub Copilot's default skills mode (`/speckit-*`).
+For other agents or modes, see
+[Command invocation](reference/integrations.md#command-invocation).
+Invoke each `/speckit-*` skill separately in your agent's chat and review the
+result before moving to the next step. These are agent skills, not terminal
+commands; only CLI installation and project setup use the terminal.
## Recommended Process
> [!TIP]
> **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, each command below is a step in the process. Two paths are common:
+After installing Spec Kit, each skill below is a step in the process. Two paths are common:
+
+Establish a constitution once per project with `/speckit-constitution` before
+starting either path.
**Shorter path** — for smaller features:
-1. `/speckit.specify`
-2. `/speckit.plan`
-3. `/speckit.tasks`
-4. `/speckit.implement`
-5. `/speckit.converge`
+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:
+**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`
+1. `/speckit-constitution` (once per project)
+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
@@ -40,7 +55,8 @@ After installing Spec Kit, each command below is a step in the process. Two path
```bash
uv tool install specify-cli
-specify init taskify # or: specify init . to use the current directory
+specify init taskify --integration copilot
+cd taskify
```
`init` lets you pick your coding agent interactively, or pass it explicitly with `--integration` (e.g. `--integration copilot`). For CI and AI agent harnesses, add `--non-interactive` so unspecified choices use documented defaults instead of hanging on an arrow-key picker.
@@ -51,76 +67,97 @@ specify init taskify # or: specify init . to use the current directory
> [Adopting Spec Kit in an Existing Project](guides/existing-projects.md) before
> starting the workflow below.
-### Step 1: `/speckit.constitution` — set the ground rules
+Launch your coding agent in the project directory. Invoke the following skills
+in its chat, one at a time.
+
+
+
+### 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 Taskify is a "Security-First" application. All user inputs must be validated. We use a microservices architecture. Code must be fully documented.
+/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: `/speckit.specify` — describe what to build
+
+
+### 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 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.
+/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: `/speckit.clarify` — resolve ambiguities
+
+
+### Step 3: `/speckit-clarify` — resolve ambiguities
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.
```text
-/speckit.clarify Focus on task card behavior — status changes, comment permissions, and user assignment.
+/speckit-clarify Focus on task card behavior — status changes, comment permissions, and user assignment.
```
-### Step 4: `/speckit.plan` — choose the tech stack
+
+
+### Step 4: `/speckit-plan` — choose the tech stack
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.
+/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 5: `/speckit.checklist` — validate the spec
+
+
+### Step 5: `/speckit-checklist` — validate the spec
Generates a custom quality checklist — "unit tests for your requirements" — to confirm the spec is complete, clear, and consistent before you break the work down. These custom checklists are reviewer-owned requirements-quality review artifacts: mark an item `[x]` only when the reviewer determines that requirement-quality criterion is satisfied. Checked custom items do not mean implementation work is complete.
```text
-/speckit.checklist
+/speckit-checklist
```
-### Step 6: `/speckit.tasks` — break the work down
+
+
+### Step 6: `/speckit-tasks` — break the work down
Generates an actionable, dependency-ordered `tasks.md` from the design artifacts.
```text
-/speckit.tasks
+/speckit-tasks
```
-### Step 7: `/speckit.analyze` — check consistency
+
+
+### Step 7: `/speckit-analyze` — check consistency
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.
```text
-/speckit.analyze
+/speckit-analyze
```
-### Step 8: `/speckit.implement` — build it
+
+
+### Step 8: `/speckit-implement` — build it
-Executes the tasks in `tasks.md` in dependency order. Before implementation, it reads checklist checkbox state as a gate and asks before proceeding if any checklist items are unchecked; it does not change any checklist files or markers. The built-in `checklists/requirements.md` checklist is maintained by `/speckit.specify` and `/speckit.clarify`, while custom checklists remain reviewer-owned. Run it once to build everything, or scope it to one phase at a time for large features.
+Executes the tasks in `tasks.md` in dependency order. Before implementation, it reads checklist checkbox state as a gate and asks before proceeding if any checklist items are unchecked; it does not change any checklist files or markers. The built-in `checklists/requirements.md` checklist is maintained by `/speckit-specify` and `/speckit-clarify`, while custom checklists remain reviewer-owned. Run it once to build everything, or scope it to one phase at a time for large features.
```text
-/speckit.implement
+/speckit-implement
```
-### Step 9: `/speckit.converge` — verify completeness
+
-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.
+### Step 9: `/speckit-converge` — verify completeness
+
+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.
```text
-/speckit.converge
+/speckit-converge
```
> [!TIP]
@@ -137,7 +174,16 @@ Checks the codebase against the spec, plan, and tasks. If it finds gaps, it appe
## Next Steps
- See the [Agentic SDD](reference/agentic-sdd.md) reference for full detail on every command
+- Learn how to [customize the process](guides/customization.md) with extensions, presets, workflows, and bundles
- Read the [complete methodology](https://github.com/github/spec-kit/blob/main/spec-driven.md) for in-depth guidance
- Compare the [core templates](https://github.com/github/spec-kit/tree/main/templates) with
[community walkthroughs](community/walkthroughs.md) to see how Spec-Driven Development is used in real projects
- Explore the [source code on GitHub](https://github.com/github/spec-kit)
+
+## Video Overview
+
+For a visual introduction, watch the
+[Spec Kit video overview](https://www.youtube.com/watch?v=a9eR1xsfvHg).
+Use the commands in this guide for the current workflow and invocation syntax.
+
+[](https://www.youtube.com/watch?v=a9eR1xsfvHg)
diff --git a/docs/reference/agentic-assessment.md b/docs/reference/agentic-assessment.md
new file mode 100644
index 0000000000..d5d48515c5
--- /dev/null
+++ b/docs/reference/agentic-assessment.md
@@ -0,0 +1,102 @@
+# Agentic Idea Assessment
+
+The bundled, opt-in **assess** extension evaluates an idea through
+**intake → research → define → shape → decide**. It is a standalone process:
+it can run in an initialized project with no source code, produces only
+assessment artifacts, and does not automatically start SDD. For a guided example,
+see the [Idea Assessment Quickstart](../guides/assessment.md).
+
+Install it from an initialized project's root:
+
+```bash
+specify extension add assess
+```
+
+Commands below use `/speckit.assess.*` notation. GitHub Copilot's default skills
+mode uses `/speckit-assess-*`; other integrations may use a different prefix.
+See [Command invocation](integrations.md#command-invocation).
+
+## Commands and artifacts
+
+Every artifact is written under `.specify/assessments//`.
+
+| Command | Purpose | Output |
+| --- | --- | --- |
+| `/speckit.assess.intake` | Capture an idea from text, a URL, a ticket, or a codebase pointer | `intake.md` |
+| `/speckit.assess.research` | Gather evidence for and against the idea, with sources and confidence | `research.md` |
+| `/speckit.assess.define` | Define users, the problem, goals, non-goals, metrics, and cost of inaction | `problem.md` |
+| `/speckit.assess.shape` | Compare concept-level options, appetite, and trade-offs | `concept.md` |
+| `/speckit.assess.decide` | Record a scorecard, verdict, rationale, and optional SDD handoff | `decision.md` |
+
+Pass the initial idea and a slug to intake, then reuse the slug:
+
+```text
+/speckit.assess.intake "Let users work offline and sync when they reconnect." slug=offline-mode
+/speckit.assess.research slug=offline-mode
+/speckit.assess.define slug=offline-mode
+/speckit.assess.shape slug=offline-mode
+/speckit.assess.decide slug=offline-mode
+```
+
+## Prerequisites and scope
+
+The five-stage sequence is the normal path, but not every stage is mandatory:
+
+- `define` can work directly from user input; intake and research are optional
+ for producing a problem definition.
+- `shape` requires `problem.md` and stays at concept level. Architecture,
+ data models, APIs, tasks, and implementation belong to delivery, not assessment.
+- `decide` requires `problem.md` and reads every available assessment artifact.
+ A `go` verdict additionally requires a shaped concept and adequate evidence;
+ skipping research does not waive the evidence requirement.
+
+## Slugs and existing artifacts
+
+The slug identifies one idea's directory. User-provided slugs are normalized to
+lowercase kebab-case and retained without appended timestamps or numbers.
+If no slug is supplied, intake asks for one interactively; automated runs
+generate a unique slug. Later stages can reuse the slug from context when its
+directory exists.
+
+Existing artifacts are not overwritten without confirmation. In automated mode,
+commands refuse to overwrite them. For routine clarification, refine the existing
+artifact rather than rerunning the command.
+
+## Decisions and evidence
+
+The decision scorecard rates criteria as `strong`, `adequate`, `weak`, or
+`unknown`, with justifications drawn from the artifacts.
+
+| Verdict | Requirement or meaning |
+| --- | --- |
+| `go` | Problem validity and evidence strength are at least `adequate`, and a concept option is recommended |
+| `needs-clarification` | Named unknowns block the decision; weak or unknown evidence, or a missing concept, cannot justify `go` |
+| `kill` | The idea is not worth pursuing now; the decisive reason is recorded explicitly |
+
+Research must include evidence against the idea. Unsourced claims remain marked
+as `ASSUMPTION`; do not invent citations or present uncertain evidence as fact.
+A documented decision to stop is a useful result.
+
+## Refining an assessment
+
+Run each stage once in the usual flow. To resolve clarification markers or a
+`needs-clarification` verdict, edit the affected Markdown directly or ask the
+agent in free-form chat to incorporate the missing facts. Preserve sources and
+confidence tags, then review dependent artifacts and revise `decision.md` as
+needed. This is artifact refinement, not repeated command execution.
+
+Rerunning an earlier command is reserved for exceptions such as a wrong slug or
+discarded draft. See the
+[guided clarification example](../guides/assessment.md#resolve-unknowns-by-refining-the-artifacts).
+
+## Handoff and guardrails
+
+A `go` decision includes a handoff summary you can choose to pass to
+`/speckit.specify`. No lifecycle hooks install assessment as a prerequisite of
+SDD, and non-software ideas need not enter SDD at all.
+
+Assessment commands write only within `.specify/assessments//`; they do not
+edit source code. The extension checks slugs and paths, treats fetched content
+as untrusted data, and applies its URL trust policy. Consult the
+[extension documentation](https://github.com/github/spec-kit/blob/main/extensions/assess/README.md)
+for the complete guardrails and relationships to other extensions.
diff --git a/docs/reference/agentic-bugfix.md b/docs/reference/agentic-bugfix.md
index e43ac09491..0fad24388b 100644
--- a/docs/reference/agentic-bugfix.md
+++ b/docs/reference/agentic-bugfix.md
@@ -2,8 +2,13 @@
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//`, with one Markdown report per stage.
+For a guided example, follow the [Bug Fixing Quickstart](../guides/bugfix.md).
+Bug fixing does not require the SDD feature process first. For evaluating an idea
+rather than repairing broken behavior, see
+[Idea Assessment](agentic-assessment.md).
+
> [!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.
+> Commands are written in `/speckit.bug.*` form throughout this page. GitHub Copilot's default skills mode uses `/speckit-bug-*`; some other agents use `$speckit-bug-*` (e.g. Codex, ZCode) or `/skill:speckit-bug-*` (e.g. Kimi). See [Command invocation](integrations.md#command-invocation).
The bug extension is a bundled, opt-in extension. Install it before using these commands:
diff --git a/docs/reference/agentic-sdd.md b/docs/reference/agentic-sdd.md
index dc38e76a5a..7c8de58ff0 100644
--- a/docs/reference/agentic-sdd.md
+++ b/docs/reference/agentic-sdd.md
@@ -4,13 +4,37 @@ The `/speckit.*` slash commands drive the core Spec-Driven Development (SDD) pro
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.
+For evaluating an idea before committing to a specification, see
+[Agentic Idea Assessment](agentic-assessment.md). Assessment is optional and
+independent of the SDD process.
+
> [!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.
+> Commands are written in `/speckit.*` form throughout this page. GitHub Copilot's default skills mode uses `/speckit-*`; some other agents use `$speckit-*` (e.g. Codex, ZCode) or `/skill:speckit-*` (e.g. Kimi). See [Command invocation](integrations.md#command-invocation).
```text
/speckit.constitution -> /speckit.specify -> /speckit.clarify -> /speckit.plan -> /speckit.checklist -> /speckit.tasks -> /speckit.analyze -> /speckit.implement -> /speckit.converge
```
+## Command overview
+
+After `specify init`, these commands are available in the selected integration.
+Integrations that support optional skills mode can select it with
+`--integration-options="--skills"`; some integrations, including Copilot, use
+skills by default.
+
+| Command | Agent skill | Purpose |
+| --- | --- | --- |
+| `/speckit.constitution` | `speckit-constitution` | Establish or update project principles |
+| `/speckit.specify` | `speckit-specify` | Define requirements and user stories |
+| `/speckit.plan` | `speckit-plan` | Create the technical implementation plan |
+| `/speckit.tasks` | `speckit-tasks` | Break the plan into actionable tasks |
+| `/speckit.implement` | `speckit-implement` | Execute the tasks |
+| `/speckit.converge` | `speckit-converge` | Assess implementation against the artifacts and append remaining work |
+| `/speckit.taskstoissues` | `speckit-taskstoissues` | Optionally convert tasks into GitHub issues |
+| `/speckit.clarify` | `speckit-clarify` | Resolve ambiguity before planning (optional quality gate; formerly `/quizme`) |
+| `/speckit.analyze` | `speckit-analyze` | Check artifact consistency after tasks and before implementation (optional quality gate) |
+| `/speckit.checklist` | `speckit-checklist` | Generate requirements-quality checklists (optional quality gate) |
+
## `/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.
@@ -19,6 +43,12 @@ Creates or updates the project **constitution** — the guiding principles that
/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.
```
+For a more general starting point:
+
+```text
+/speckit.constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements.
+```
+
## `/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`.
@@ -26,7 +56,7 @@ Creates or updates the feature **specification** from a natural-language descrip
This workflow may also maintain `checklists/requirements.md`, the built-in spec-quality checklist that `/speckit.specify` creates and `/speckit.clarify` re-evaluates. That lifecycle is separate from custom checklists generated by `/speckit.checklist`.
```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.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.
```
## `/speckit.clarify`
@@ -49,6 +79,12 @@ Runs the planning process to generate design artifacts from the spec. This is wh
/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.
```
+For the photo-album example above:
+
+```text
+/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.
+```
+
## `/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?").
@@ -121,3 +157,17 @@ It first prints a severity-graded findings summary, then resolves to one of two
- **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.
+
+## `/speckit.taskstoissues`
+
+Optionally converts an existing `tasks.md` into actionable GitHub issues. Run it
+after generating tasks when you want to track execution in GitHub:
+
+```text
+/speckit.taskstoissues
+```
+
+This command requires a GitHub `origin` remote and access to the GitHub MCP tools
+for listing and creating issues. It creates issues only in the repository
+identified by that remote and checks existing task IDs to avoid duplicates.
+It is not required to implement tasks or converge on a feature.
diff --git a/docs/reference/bundles.md b/docs/reference/bundles.md
index 6035725c47..bb2a6aa7c7 100644
--- a/docs/reference/bundles.md
+++ b/docs/reference/bundles.md
@@ -4,6 +4,13 @@ Bundles compose existing Spec Kit components — extensions, presets, workflows,
A bundle is described by a `bundle.yml` manifest and is discovered through the same catalog stack as other components. Installing a bundle resolves its declared components against pinned versions, checks for the single cross-bundle conflict point (the active integration), and applies each component idempotently with full provenance tracking so it can be cleanly removed or refreshed later.
+For a concrete starting point, see the
+[example bundle manifests](https://github.com/github/spec-kit/tree/main/examples/bundles)
+for product managers, business analysts, security researchers, and developers.
+These demonstrate packaging a role-based setup, not filled generated feature
+specs; for end-to-end usage examples, see
+[community walkthroughs](../community/walkthroughs.md).
+
## Search Available Bundles
```bash
@@ -141,6 +148,11 @@ If your bundle references components from non-default catalogs, document those c
Bundles are discovered through a priority-ordered stack of catalog sources (project, user, and built-in scopes).
+Each source has an install policy. `install-allowed` sources can be installed
+from; `discovery-only` sources appear in `search` and `info` but refuse
+installation. Inspect the active stack before installing a bundle from a
+non-default source.
+
### List the Catalog Stack
```bash
diff --git a/docs/reference/integrations.md b/docs/reference/integrations.md
index 551f73c97e..35aef8f253 100644
--- a/docs/reference/integrations.md
+++ b/docs/reference/integrations.md
@@ -48,6 +48,26 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify
| [Zed](https://zed.dev/) | `zed` | Skills-based integration; installs skills into `.agents/skills` and invokes them as `/speckit-` |
| Generic | `generic` | Bring your own agent — use `--integration generic --integration-options="--commands-dir "` for AI coding agents not listed above |
+## Command Invocation
+
+Invoke Spec Kit's process steps inside your coding agent, not in the terminal.
+In GitHub Copilot's default mode, these are skills you invoke in the agent's
+chat. CLI installation and setup commands are separate terminal operations.
+The steps are the same across integrations, but their spelling depends on the
+agent and its installed mode:
+
+| Integration or mode | SDD example | Extension example |
+| --- | --- | --- |
+| GitHub Copilot, default skills mode | `/speckit-specify` | `/speckit-bug-assess` |
+| Dotted slash-command notation used in the references | `/speckit.specify` | `/speckit.bug.assess` |
+| Codex, Command Code, ZCode skills | `$speckit-specify` | `$speckit-bug-assess` |
+| Kimi skills | `/skill:speckit-specify` | `/skill:speckit-bug-assess` |
+
+Use the form exposed by your agent. Copilot's default skills are installed under
+`.github/skills/`; its opt-in commands layout is selected with
+`--integration-options="--commands"`. In that layout, Copilot CLI can select an
+agent through `/agents` or address it directly in a prompt.
+
## List Available Integrations
```bash
diff --git a/docs/reference/overview.md b/docs/reference/overview.md
index 077eeb1d31..cbfd1c48a8 100644
--- a/docs/reference/overview.md
+++ b/docs/reference/overview.md
@@ -46,7 +46,12 @@ Bundles compose existing extensions, presets, workflows, and steps into a single
## 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.
+The sections above cover primitives managed by the `specify` CLI. The following
+are independent processes your coding agent runs, not terminal commands. The
+references use `/speckit.*` notation; see
+[Command invocation](integrations.md#command-invocation) for your agent's syntax.
+For guided examples, start with [SDD](../quickstart.md),
+[bug fixing](../guides/bugfix.md), or [idea assessment](../guides/assessment.md).
### Agentic SDD
@@ -59,3 +64,12 @@ The `/speckit.*` slash commands that drive the core Spec-Driven Development proc
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)
+
+### Agentic Idea Assessment
+
+The bundled, opt-in **assess** extension evaluates an idea through intake,
+research, definition, shaping, and a go / needs-clarification / kill decision.
+It works without source code and does not require or automatically start SDD.
+Install it with `specify extension add assess`.
+
+[Agentic Idea Assessment reference →](agentic-assessment.md)
diff --git a/docs/toc.yml b/docs/toc.yml
index c0a4264547..5a4e65ac5e 100644
--- a/docs/toc.yml
+++ b/docs/toc.yml
@@ -11,10 +11,16 @@
items:
- name: Installation
href: installation.md
- - name: Quick Start
+ - name: Spec-Driven Development
href: quickstart.md
+ - name: Bug Fixing
+ href: guides/bugfix.md
+ - name: Idea Assessment
+ href: guides/assessment.md
- name: Existing Projects
href: guides/existing-projects.md
+ - name: Customize or Bring Your Own
+ href: guides/customization.md
- name: Upgrade
href: upgrade.md
- name: Install uv
@@ -51,6 +57,8 @@
href: reference/agentic-sdd.md
- name: Agentic Bug Fix
href: reference/agentic-bugfix.md
+ - name: Agentic Idea Assessment
+ href: reference/agentic-assessment.md
- name: Authentication
href: reference/authentication.md
diff --git a/extensions/catalog.community.json b/extensions/catalog.community.json
index 5bdc9cb967..97e0a3f243 100644
--- a/extensions/catalog.community.json
+++ b/extensions/catalog.community.json
@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
- "updated_at": "2026-09-11T00:00:00Z",
+ "updated_at": "2026-09-15T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
"extensions": {
"adrkit": {
@@ -8,8 +8,8 @@
"id": "adrkit",
"description": "Pulls the decisions governing this work into agent context, checks produced plans against them, and drafts an ADR from a plan artifact.",
"author": "Mark Beacom (@mbeacom)",
- "version": "0.1.2",
- "download_url": "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/mbeacom/adrkit/releases/download/spec-kit-v0.1.2/adrkit.zip",
+ "version": "0.1.4",
+ "download_url": "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/mbeacom/adrkit/releases/download/spec-kit-v0.1.4/adrkit.zip",
"repository": "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/mbeacom/adrkit",
"homepage": "https://adrkit.dev",
"documentation": "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/mbeacom/adrkit/blob/main/packages/adapters/spec-kit/README.md",
@@ -18,7 +18,7 @@
"category": "process",
"effect": "read-write",
"requires": {
- "speckit_version": ">=0.13.0,<0.16.0",
+ "speckit_version": ">=0.13.0,<1.1.0",
"tools": [
{
"name": "adr",
@@ -42,7 +42,7 @@
"downloads": 0,
"stars": 0,
"created_at": "2026-08-03T00:00:00Z",
- "updated_at": "2026-08-03T00:00:00Z"
+ "updated_at": "2026-09-15T00:00:00Z"
},
"aide": {
"name": "AI-Driven Engineering (AIDE)",
@@ -1428,8 +1428,8 @@
"id": "cosmosdb",
"description": "Best-practice Azure Cosmos DB code generation and review for any AI coding agent",
"author": "Theo van Kraay (maintained on behalf of the Azure Cosmos DB team; hosted in the AzureCosmosDB org)",
- "version": "0.1.0",
- "download_url": "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/AzureCosmosDB/spec-kit-cosmosdb/archive/refs/tags/v0.1.0.zip",
+ "version": "0.2.0",
+ "download_url": "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/AzureCosmosDB/spec-kit-cosmosdb/archive/refs/tags/v0.2.0.zip",
"repository": "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/AzureCosmosDB/spec-kit-cosmosdb",
"homepage": "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/AzureCosmosDB/spec-kit-cosmosdb",
"documentation": "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/AzureCosmosDB/spec-kit-cosmosdb/blob/main/README.md",
@@ -1455,7 +1455,7 @@
"downloads": 0,
"stars": 0,
"created_at": "2026-08-21T00:00:00Z",
- "updated_at": "2026-08-21T00:00:00Z"
+ "updated_at": "2026-09-15T00:00:00Z"
},
"cost": {
"name": "Cost Tracker",
@@ -3548,6 +3548,48 @@
"created_at": "2026-03-26T00:00:00Z",
"updated_at": "2026-03-26T00:00:00Z"
},
+ "openup": {
+ "name": "OpenUP Governed Lifecycle",
+ "id": "openup",
+ "description": "Adds the OpenUP lifecycle to Spec Kit: phases, iterations, a seven-level WBS, an executable risk register, bi-directional traceability, and machine-checkable milestone gates.",
+ "author": "Aniket Gore",
+ "version": "0.1.0",
+ "download_url": "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/anvigo12/specup/releases/download/v0.1.0/openup-0.1.0.zip",
+ "sha256": "012e11f5949060d57bef2c5ea15772e4649fc92d723e171a85e6230fb87cb46f",
+ "repository": "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/anvigo12/specup",
+ "homepage": "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/anvigo12/specup",
+ "documentation": "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/anvigo12/specup/blob/main/docs/guide/using-specup.md",
+ "changelog": "",
+ "license": "MIT",
+ "category": "process",
+ "effect": "read-write",
+ "requires": {
+ "speckit_version": ">=1.0.0,<2.0.0",
+ "tools": [
+ {
+ "name": "python3",
+ "version": ">=3.10",
+ "required": true
+ }
+ ]
+ },
+ "provides": {
+ "commands": 9,
+ "hooks": 4
+ },
+ "tags": [
+ "governance",
+ "traceability",
+ "risk",
+ "lifecycle",
+ "openup"
+ ],
+ "verified": false,
+ "downloads": 0,
+ "stars": 0,
+ "created_at": "2026-09-15T00:00:00Z",
+ "updated_at": "2026-09-15T00:00:00Z"
+ },
"optimize": {
"name": "Optimize Extension",
"id": "optimize",
@@ -5215,17 +5257,17 @@
"id": "status-report",
"description": "Project status, feature progress, and next-action recommendations for spec-driven workflows.",
"author": "Open-Agent-Tools",
- "version": "1.2.5",
- "download_url": "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/Open-Agent-Tools/spec-kit-status/archive/refs/tags/v1.2.5.zip",
+ "version": "1.4.2",
+ "download_url": "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/Open-Agent-Tools/spec-kit-status/archive/refs/tags/v1.4.2.zip",
"repository": "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/Open-Agent-Tools/spec-kit-status",
"homepage": "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/Open-Agent-Tools/spec-kit-status",
"documentation": "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/Open-Agent-Tools/spec-kit-status/blob/main/README.md",
"changelog": "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/Open-Agent-Tools/spec-kit-status/blob/main/CHANGELOG.md",
"license": "MIT",
"category": "visibility",
- "effect": "read-only",
+ "effect": "read-write",
"requires": {
- "speckit_version": ">=0.1.0"
+ "speckit_version": ">=1.0.0"
},
"provides": {
"commands": 1,
@@ -5240,7 +5282,7 @@
"downloads": 0,
"stars": 0,
"created_at": "2026-04-08T15:05:14Z",
- "updated_at": "2026-04-08T15:05:14Z"
+ "updated_at": "2026-09-14T00:00:00Z"
},
"superb": {
"name": "Superpowers Bridge",
diff --git a/presets/catalog.community.json b/presets/catalog.community.json
index 054a7e3b33..1fd71dc8c5 100644
--- a/presets/catalog.community.json
+++ b/presets/catalog.community.json
@@ -1,6 +1,6 @@
{
"schema_version": "1.0",
- "updated_at": "2026-09-10T00:00:00Z",
+ "updated_at": "2026-09-15T00:00:00Z",
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.community.json",
"presets": {
"a11y-governance": {
@@ -659,6 +659,37 @@
"created_at": "2026-04-09T00:00:00Z",
"updated_at": "2026-04-09T00:00:00Z"
},
+ "openup-governance": {
+ "name": "OpenUP Governance",
+ "id": "openup-governance",
+ "version": "0.1.0",
+ "description": "Composes OpenUP lifecycle governance into Spec Kit's own constitution, spec, plan and tasks templates, and wraps /tasks and /implement with the governed execution contract.",
+ "author": "Aniket Gore",
+ "repository": "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/anvigo12/specup",
+ "download_url": "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/anvigo12/specup/releases/download/v0.1.0/openup-governance-0.1.0.zip",
+ "sha256": "c9bce34220773f07596e2e02e8b23f86886d4f7c3a0d38e22b1039ad2fe50137",
+ "homepage": "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/anvigo12/specup",
+ "documentation": "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/anvigo12/specup/blob/main/presets/openup-governance/README.md",
+ "license": "MIT",
+ "requires": {
+ "speckit_version": ">=1.0.0,<2.0.0",
+ "extensions": [
+ "openup"
+ ]
+ },
+ "provides": {
+ "templates": 4,
+ "commands": 2
+ },
+ "tags": [
+ "openup",
+ "governance",
+ "traceability",
+ "lifecycle"
+ ],
+ "created_at": "2026-09-15T00:00:00Z",
+ "updated_at": "2026-09-15T00:00:00Z"
+ },
"parallel-autonomous-run-governance": {
"name": "Parallel Autonomous Run Governance",
"id": "parallel-autonomous-run-governance",
diff --git a/pyproject.toml b/pyproject.toml
index ee1dc4ab31..217c42d4e2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "specify-cli"
-version = "1.0.7.dev0"
+version = "1.0.8.dev0"
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"
diff --git a/src/specify_cli/integrations/base.py b/src/specify_cli/integrations/base.py
index 529803922e..c0f4bdea14 100644
--- a/src/specify_cli/integrations/base.py
+++ b/src/specify_cli/integrations/base.py
@@ -369,6 +369,29 @@ def build_command_invocation(self, command_name: str, args: str = "") -> str:
invocation = f"{invocation} {args}"
return invocation
+ def _build_dispatch_prompt(
+ self,
+ command_name: str,
+ args: str,
+ project_root: Path | None,
+ ) -> str:
+ """Return the dispatch prompt, given the target *project_root*.
+
+ Seam for integrations whose invocation depends on the project's
+ on-disk layout. ``build_command_invocation()`` is a two-argument
+ contract implemented by every integration, so widening it to carry a
+ *project_root* would change a broad public surface for the sake of
+ the one caller that needs it. Dispatch is that caller: it alone
+ knows which project the command is being run against, so dual-mode
+ integrations (e.g. Bob) resolve the layout here instead.
+
+ The default ignores *project_root* and preserves the previous
+ behaviour exactly.
+
+ See issue #4491.
+ """
+ return self.build_command_invocation(command_name, args)
+
def dispatch_command(
self,
command_name: str,
@@ -384,11 +407,13 @@ def dispatch_command(
"""Dispatch a Spec Kit command through this integration's CLI.
By default this builds a slash-command invocation with
- ``build_command_invocation()`` and passes that prompt to
+ ``_build_dispatch_prompt()`` -- which defers to
+ ``build_command_invocation()`` unless the integration needs the
+ *project_root* to decide -- and passes that prompt to
``build_exec_args()`` to construct the CLI command line.
Integrations with custom dispatch behavior can override
- ``build_command_invocation()``, ``build_exec_args()``, or
- ``dispatch_command()`` directly.
+ ``build_command_invocation()``, ``_build_dispatch_prompt()``,
+ ``build_exec_args()``, or ``dispatch_command()`` directly.
When *stream* is ``True`` (the default), stdout and stderr are
piped directly to the terminal so the user sees live output.
@@ -401,7 +426,7 @@ def dispatch_command(
import subprocess
self.validate_runtime_config(integration_args, integration_options)
- prompt = self.build_command_invocation(command_name, args)
+ prompt = self._build_dispatch_prompt(command_name, args, project_root)
# When streaming to the terminal, request text output so the
# user sees readable output instead of raw JSONL events.
exec_args = self.build_exec_args(
diff --git a/src/specify_cli/integrations/bob/__init__.py b/src/specify_cli/integrations/bob/__init__.py
index 0d1f26dc29..016ecf7aab 100644
--- a/src/specify_cli/integrations/bob/__init__.py
+++ b/src/specify_cli/integrations/bob/__init__.py
@@ -20,6 +20,7 @@
from __future__ import annotations
import warnings
+from collections.abc import Mapping, Sequence
from pathlib import Path
from typing import Any
@@ -254,6 +255,95 @@ def invoke_separator_for_mode(self, skills_enabled: bool) -> str:
"""
return "-" if skills_enabled else "."
+ def build_command_invocation(
+ self,
+ command_name: str,
+ args: str = "",
+ *,
+ project_root: Path | None = None,
+ ) -> str:
+ """Render ``/speckit-`` for skills mode, ``/speckit.`` legacy.
+
+ ``IntegrationBase`` hardcodes ``.``; Bob's skills live at
+ ``.bob/skills/speckit-/SKILL.md``, so the base rendering names a
+ command that does not exist in a skills-mode project. The two layouts
+ differ in the *separator* and in how a dotted extension command is
+ spelled: skills flatten every dot (``speckit.git.commit`` ->
+ ``/speckit-git-commit``, matching the installed
+ ``.bob/skills/speckit-git-commit/`` directory), while legacy commands
+ keep them (``/speckit.git.commit``).
+
+ *project_root* is keyword-only so this stays a superset of the base
+ signature that every other integration implements. It is resolved
+ through :meth:`is_skills_mode`, so a ``None`` root falls back to the
+ same skills default that :meth:`effective_invoke_separator` and
+ ``is_skills_mode`` rule 4 already apply -- the class answers
+ "unknown project" consistently, whichever hook is asked.
+ """
+ if not self.is_skills_mode(None, project_root):
+ return super().build_command_invocation(command_name, args)
+
+ stem = command_name
+ if stem.startswith("speckit."):
+ stem = stem[len("speckit."):]
+ invocation = "/speckit-" + stem.replace(".", "-")
+ return f"{invocation} {args}" if args else invocation
+
+ def _build_dispatch_prompt(
+ self,
+ command_name: str,
+ args: str,
+ project_root: Path | None,
+ ) -> str:
+ """Resolve the layout from *project_root* at dispatch time.
+
+ Dispatch is the one caller that knows the target project, so it is
+ where a legacy install can be detected and given ``/speckit.``
+ instead of the skills default.
+
+ A ``None`` root resolves to the working directory rather than being
+ passed through: ``dispatch_command`` runs ``bob`` with
+ ``cwd = project_root or ``, so when no root is
+ given the cwd *is* the project being dispatched into. Detecting its
+ layout beats falling back to the layout-unknown default, which would
+ send a legacy install the skills spelling.
+ """
+ root = project_root if project_root is not None else Path.cwd()
+ return self.build_command_invocation(
+ command_name, args, project_root=root
+ )
+
+ def build_exec_args(
+ self,
+ prompt: str,
+ *,
+ model: str | None = None,
+ output_json: bool = True,
+ integration_args: Sequence[str] | None = None,
+ integration_options: Mapping[str, Any] | None = None,
+ ) -> list[str] | None:
+ """Non-interactive dispatch through ``bob run``.
+
+ The prompt is **positional and last** -- Bob Shell 2.x has no ``-p`` on
+ ``run``. ``--trust`` is per-invocation (``run`` never persists it) and
+ ``--accept-license`` is required non-interactively.
+
+ *model* is ignored: ``run`` exposes no model flag; model choice comes
+ from ``session.model`` in Bob's settings.
+ """
+ self.validate_runtime_config(integration_args, integration_options)
+ args = [
+ self._resolve_executable(),
+ "run",
+ "--trust",
+ "--accept-license",
+ "-f",
+ "json" if output_json else "pretty",
+ ]
+ self._apply_extra_args_env_var(args)
+ args.append(prompt)
+ return args
+
def post_process_skill_content(self, content: str) -> str:
"""Bob skills are intent-activated; no slash-command note is injected.
diff --git a/templates/commands/clarify.md b/templates/commands/clarify.md
index 8663b6908b..f48d8bd703 100644
--- a/templates/commands/clarify.md
+++ b/templates/commands/clarify.md
@@ -124,7 +124,7 @@ Execution steps:
For each category with Partial or Missing status, add a candidate question opportunity unless:
- Clarification would not materially change implementation or validation strategy
- - Information is better deferred to planning phase (note internally)
+ - The item is specifically about implementation method, tech-stack comparison, or task breakdown (note internally)
4. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints:
- Maximum of 5 total questions across the whole session.
@@ -279,7 +279,7 @@ Report completion (after questioning loop ends or early termination):
- Path to updated spec.
- Sections touched (list names).
- Spec quality checklist status (if `FEATURE_DIR/checklists/requirements.md` was re-validated): show before/after pass counts (e.g., "Spec Quality Checklist: 12/16 → 15/16 items passing") and list any items that changed state — both newly checked (unchecked → checked) and any regressions (checked → unchecked). If any items remain unchecked, list them as areas needing attention.
-- Coverage summary table listing each taxonomy category with Status: Resolved (was Partial/Missing and addressed), Deferred (exceeds question quota or better suited for planning), Clear (already sufficient), Outstanding (still Partial/Missing but low impact).
+- Coverage summary table listing each taxonomy category with Status: Resolved (was Partial/Missing and addressed), Deferred (exceeds question quota, or remaining item is specifically implementation method, tech-stack comparison, or task breakdown), Clear (already sufficient), Outstanding (still Partial/Missing but low impact).
- If any Outstanding or Deferred remain, recommend whether to proceed to `__SPECKIT_COMMAND_PLAN__` or run `__SPECKIT_COMMAND_CLARIFY__` again later post-plan.
- Suggested next command.
diff --git a/tests/integrations/test_integration_bob.py b/tests/integrations/test_integration_bob.py
index 52a25ae2c6..84a4637672 100644
--- a/tests/integrations/test_integration_bob.py
+++ b/tests/integrations/test_integration_bob.py
@@ -925,3 +925,182 @@ def test_post_process_matches_skills_helper(self):
bob.post_process_skill_content(sample)
== _BobSkillsHelper().post_process_skill_content(sample)
)
+
+
+class TestBobCliDispatch:
+ """Headless dispatch through ``bob run``."""
+
+ @staticmethod
+ def _skills_project(tmp_path):
+ (tmp_path / ".bob" / "skills" / "speckit-specify").mkdir(parents=True)
+ return tmp_path
+
+ @staticmethod
+ def _legacy_project(tmp_path):
+ cmds = tmp_path / ".bob" / "commands"
+ cmds.mkdir(parents=True)
+ (cmds / "speckit.specify.md").write_text("x", encoding="utf-8")
+ return tmp_path
+
+ def test_requires_cli_is_false_for_ide_first_flow(self):
+ """``requires_cli`` must stay False so the IDE-only flow keeps working.
+
+ ``specify init --integration bob`` (without ``--ignore-agent-tools``)
+ treats ``requires_cli=True`` as a hard precheck and fails when the
+ ``bob`` CLI isn't on PATH -- even though the Bob IDE / skills flow can
+ run without it. Workflow dispatch support is signalled by overriding
+ ``build_exec_args()`` instead, mirroring ``CursorAgentIntegration``.
+ """
+ bob = get_integration("bob")
+ assert bob.config.get("requires_cli") is False
+
+ def test_build_exec_args_default_is_bob_run_with_json(self):
+ """Default argv is ``bob run`` with the headless flags, ``-f json``,
+ then the prompt: ``run`` takes the prompt positionally, not via ``-p``.
+ """
+ bob = get_integration("bob")
+ assert bob.build_exec_args("/speckit-specify some-feature") == [
+ "bob", "run", "--trust", "--accept-license", "-f", "json",
+ "/speckit-specify some-feature",
+ ]
+
+ def test_build_exec_args_text_output_uses_pretty(self):
+ bob = get_integration("bob")
+ assert bob.build_exec_args("/speckit-plan", output_json=False) == [
+ "bob", "run", "--trust", "--accept-license", "-f", "pretty",
+ "/speckit-plan",
+ ]
+
+ def test_build_exec_args_ignores_model(self):
+ """Bob exposes no model flag on ``run``, so *model* is a no-op."""
+ bob = get_integration("bob")
+ assert bob.build_exec_args("/speckit-plan", model="some-model") == \
+ bob.build_exec_args("/speckit-plan")
+
+ def test_command_invocation_uses_hyphen_in_skills_mode(self):
+ """Skills-mode projects install ``.bob/skills/speckit-/``, so the
+ invocation must use the same separator.
+ """
+ bob = get_integration("bob")
+ assert bob.build_command_invocation("speckit.specify") == "/speckit-specify"
+ assert bob.build_command_invocation("speckit.plan", "arg") == "/speckit-plan arg"
+
+ def test_command_invocation_accepts_bare_stem(self):
+ bob = get_integration("bob")
+ assert bob.build_command_invocation("specify") == "/speckit-specify"
+
+ def test_command_invocation_flattens_dots_in_skills_mode(self, tmp_path):
+ """Extension commands install as ``.bob/skills/speckit-git-commit/``.
+
+ ``SkillsIntegration`` derives the skill directory with
+ ``stem.replace(".", "-")``, so the invocation must flatten every dot,
+ not just the ``speckit.`` prefix.
+ """
+ bob = get_integration("bob")
+ root = self._skills_project(tmp_path)
+ assert (
+ bob.build_command_invocation("speckit.git.commit", project_root=root)
+ == "/speckit-git-commit"
+ )
+ assert (
+ bob.build_command_invocation("git.commit", project_root=root)
+ == "/speckit-git-commit"
+ )
+ # Three segments: distinguishes "flatten every dot" from "flatten the
+ # first one". A two-segment stem cannot tell those apart.
+ assert (
+ bob.build_command_invocation("speckit.a.b.c", project_root=root)
+ == "/speckit-a-b-c"
+ )
+
+ def test_command_invocation_legacy_project_keeps_dots(self, tmp_path):
+ """A legacy project installs ``.bob/commands/speckit..md``.
+
+ The Bob 1.x invocation is ``/speckit.`` with dots preserved --
+ the skills flattening must not leak into this layout.
+ """
+ bob = get_integration("bob")
+ root = self._legacy_project(tmp_path)
+ assert (
+ bob.build_command_invocation("speckit.specify", project_root=root)
+ == "/speckit.specify"
+ )
+ assert (
+ bob.build_command_invocation("speckit.git.commit", project_root=root)
+ == "/speckit.git.commit"
+ )
+ assert (
+ bob.build_command_invocation("speckit.specify", "arg", project_root=root)
+ == "/speckit.specify arg"
+ )
+
+ def test_command_invocation_without_project_root_uses_skills_default(self):
+ """No *project_root* -> Bob's documented skills default.
+
+ ``is_skills_mode`` rule 4 makes a project with no detectable layout
+ skills-mode, and ``effective_invoke_separator()`` answers ``-`` in
+ that state, so the invocation must agree rather than falling back to
+ the Bob 1.x spelling. No production caller reaches this method
+ without a root today; the assertion locks the documented default so a
+ future caller cannot silently inherit the wrong layout.
+ """
+ bob = get_integration("bob")
+ assert bob.build_command_invocation("speckit.specify") == "/speckit-specify"
+ assert (
+ bob.build_command_invocation("speckit.git.commit")
+ == "/speckit-git-commit"
+ )
+
+ def test_dispatch_without_project_root_uses_cwd_layout(self, tmp_path, monkeypatch):
+ """No explicit root -> resolve the layout from the cwd.
+
+ ``dispatch_command`` runs ``bob`` with ``cwd = project_root or ``, so with no root the cwd is the project being
+ dispatched into. A *legacy* cwd is the discriminating case: skills is
+ the layout-unknown default, so only a legacy project proves the cwd
+ was inspected at all.
+ """
+ import subprocess
+
+ captured = {}
+
+ def fake_run(cmd, **kwargs):
+ captured["cmd"] = cmd
+ return subprocess.CompletedProcess(cmd, 0, "", "")
+
+ monkeypatch.setattr(subprocess, "run", fake_run)
+ monkeypatch.chdir(self._legacy_project(tmp_path))
+
+ get_integration("bob").dispatch_command("speckit.git.commit")
+ assert captured["cmd"][-1] == "/speckit.git.commit"
+
+ def test_dispatch_resolves_layout_from_project_root(self, tmp_path, monkeypatch):
+ """Dispatch knows the project, so it must render for that layout.
+
+ This is the seam that carries *project_root* from ``dispatch_command``
+ into invocation building; without it a legacy install is dispatched
+ with the skills spelling and the command is never found.
+ """
+ import subprocess
+
+ captured = {}
+
+ def fake_run(cmd, **kwargs):
+ captured["cmd"] = cmd
+ return subprocess.CompletedProcess(cmd, 0, "", "")
+
+ monkeypatch.setattr(subprocess, "run", fake_run)
+ bob = get_integration("bob")
+
+ bob.dispatch_command(
+ "speckit.specify",
+ args="my feature",
+ project_root=self._legacy_project(tmp_path),
+ )
+ assert captured["cmd"][-1] == "/speckit.specify my feature"
+
+ skills_root = tmp_path / "skills-proj"
+ bob.dispatch_command(
+ "speckit.git.commit", project_root=self._skills_project(skills_root)
+ )
+ assert captured["cmd"][-1] == "/speckit-git-commit"
diff --git a/tests/test_clarify_stage_gate.py b/tests/test_clarify_stage_gate.py
new file mode 100644
index 0000000000..5ecf3410ec
--- /dev/null
+++ b/tests/test_clarify_stage_gate.py
@@ -0,0 +1,25 @@
+"""The planning deferral in ``templates/commands/clarify.md`` must stay bounded (#1717).
+
+The old catch-all ("Information is better deferred to planning phase") let
+agents skip NFRs, acceptance criteria, and edge cases. Defer only
+implementation method, tech-stack comparison, or task breakdown.
+"""
+
+from pathlib import Path
+
+CLARIFY = Path(__file__).parent.parent / "templates" / "commands" / "clarify.md"
+
+
+def test_clarify_planning_deferral_is_bounded() -> None:
+ text = CLARIFY.read_text(encoding="utf-8")
+ assert "- Information is better deferred to planning phase (note internally)" not in text
+ assert "better suited for planning" not in text
+ assert (
+ "implementation method, tech-stack comparison, or task breakdown"
+ in text
+ )
+ completion = text.split("## Completion Report", 1)[1]
+ assert (
+ "implementation method, tech-stack comparison, or task breakdown"
+ in completion
+ )
diff --git a/tests/test_github_workflows.py b/tests/test_github_workflows.py
index dd5abef34f..727bb08e63 100644
--- a/tests/test_github_workflows.py
+++ b/tests/test_github_workflows.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+import json
import os
import re
import subprocess
@@ -12,7 +13,6 @@
from tests.conftest import requires_bash
-
REPO_ROOT = Path(__file__).resolve().parent.parent
WORKFLOWS_DIR = REPO_ROOT / ".github" / "workflows"
# Match both the dedicated-step form (` uses: x@sha`) and the
@@ -24,6 +24,14 @@
"Verify tag format",
"Verify tag matches package version",
)
+FEATURE_ASSESS_WORKFLOW = WORKFLOWS_DIR / "feature-assess.md"
+FEATURE_ASSESS_COMPILED_WORKFLOW = WORKFLOWS_DIR / "feature-assess.lock.yml"
+FEATURE_ASSESS_LABELS = {
+ "feature-go",
+ "feature-needs-clarification",
+ "feature-kill",
+ "feature-invalid",
+}
COMMUNITY_SUBMISSION_WORKFLOWS = (
(
"bundle",
@@ -97,6 +105,22 @@ def _create_pull_request_allowed_files(source_text: str) -> list[str]:
]
+def _workflow_frontmatter(source_text: str) -> dict[str, object]:
+ _, frontmatter, _ = source_text.split("---", maxsplit=2)
+ return yaml.safe_load(frontmatter)
+
+
+def _gh_aw_metadata(compiled_text: str) -> dict[str, object]:
+ metadata_prefix = "# gh-aw-metadata: "
+ first_line = compiled_text.splitlines()[0]
+ assert first_line.startswith(metadata_prefix)
+ return json.loads(first_line.removeprefix(metadata_prefix))
+
+
+def _workflow_step(steps: list[dict[str, object]], name: str) -> dict[str, object]:
+ return next(step for step in steps if step.get("name") == name)
+
+
def test_github_actions_are_pinned_to_full_commit_shas():
unpinned_refs = []
@@ -170,6 +194,104 @@ def test_pinned_action_ref_accepts_uppercase_hex_sha():
)
+def test_feature_assess_upgrade_preserves_positive_execution_path():
+ source_text = FEATURE_ASSESS_WORKFLOW.read_text(encoding="utf-8")
+ compiled_text = FEATURE_ASSESS_COMPILED_WORKFLOW.read_text(encoding="utf-8")
+ source = _workflow_frontmatter(source_text)
+ compiled = yaml.safe_load(compiled_text)
+
+ metadata = _gh_aw_metadata(compiled_text)
+ assert metadata["compiler_version"] == "v0.88.7"
+ assert metadata["engine_versions"] == {"copilot": "1.0.80"}
+
+ source_steps = source["steps"]
+ compiled_steps = compiled["jobs"]["agent"]["steps"]
+ expected_step_names = [
+ "Setup uv",
+ "Set up Python",
+ "Install Spec Kit CLI",
+ "Initialize Spec Kit and install the assess extension",
+ ]
+ compiled_step_names = [step.get("name") for step in compiled_steps]
+ assert [
+ compiled_step_names.index(step_name) for step_name in expected_step_names
+ ] == sorted(compiled_step_names.index(step_name) for step_name in expected_step_names)
+
+ for source_step in source_steps:
+ compiled_step = _workflow_step(compiled_steps, source_step["name"])
+ for field in ("continue-on-error", "uses", "with", "working-directory", "run"):
+ if field in source_step:
+ assert compiled_step[field] == source_step[field]
+
+ install_step = _workflow_step(compiled_steps, "Install Spec Kit CLI")
+ assert 'PIP_SUBCOMMAND=pip' in install_step["run"]
+ assert '"$UV_BIN" "$PIP_SUBCOMMAND" install --system .' in install_step["run"]
+
+
+def test_feature_assess_upgrade_preserves_negative_guards():
+ source_text = FEATURE_ASSESS_WORKFLOW.read_text(encoding="utf-8")
+ compiled_text = FEATURE_ASSESS_COMPILED_WORKFLOW.read_text(encoding="utf-8")
+ source = _workflow_frontmatter(source_text)
+ compiled = yaml.safe_load(compiled_text)
+
+ assert (source.get("on") or source[True]) == {
+ "issues": {"types": ["labeled"], "names": ["feature-assess"]},
+ "skip-bots": ["github-actions", "copilot", "dependabot"],
+ }
+ assert (compiled.get("on") or compiled[True]) == {
+ "issues": {"types": ["labeled"]},
+ }
+
+ activation_condition = compiled["jobs"]["activation"]["if"]
+ pre_activation = compiled["jobs"]["pre_activation"]
+ expected_guard = (
+ "github.event_name != 'issues' || github.event.action != 'labeled' || "
+ "github.event.label.name == 'feature-assess'"
+ )
+ assert " ".join(pre_activation["if"].split()) == expected_guard
+ assert " ".join(activation_condition.split()) == (
+ f"needs.pre_activation.outputs.activated == 'true' && ({expected_guard})"
+ )
+ assert pre_activation["steps"][-1]["env"]["GH_AW_SKIP_BOTS"] == (
+ "github-actions,copilot-swe-agent,Copilot,copilot,"
+ "@app/copilot-swe-agent,dependabot"
+ )
+
+ agent = compiled["jobs"]["agent"]
+ assert agent["permissions"] == {"contents": "read", "issues": "read"}
+ assert compiled["jobs"]["safe_outputs"]["permissions"] == {
+ "issues": "write",
+ "pull-requests": "write",
+ }
+
+ safe_outputs_step = _workflow_step(
+ compiled["jobs"]["safe_outputs"]["steps"], "Process Safe Outputs"
+ )
+ safe_outputs = json.loads(
+ safe_outputs_step["env"]["GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG"]
+ )
+ assert safe_outputs["add_comment"] == {"max": 5}
+ assert safe_outputs["add_labels"]["max"] == 1
+ assert set(safe_outputs["add_labels"]["allowed"]) == FEATURE_ASSESS_LABELS
+ assert set(safe_outputs["remove_labels"]["allowed"]) == FEATURE_ASSESS_LABELS
+ assert not {
+ "create_issue",
+ "create_pull_request",
+ "push_to_pull_request",
+ } & safe_outputs.keys()
+
+ assert re.search(r"without applying any verdict\s+label", source_text)
+ assert "never stage,\n commit, or push" in source_text
+
+ unpinned_refs = [
+ match.group("ref")
+ for match in USES_RE.finditer(compiled_text)
+ if not match.group("ref").startswith(("./", "../"))
+ and not PINNED_SHA_RE.search(match.group("ref"))
+ ]
+ assert unpinned_refs == []
+
+
def test_community_submission_automation_is_wired_to_allowed_files():
assignment = WORKFLOWS_DIR / "catalog-assign.yml"
assignment_text = assignment.read_text(encoding="utf-8")