Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ Additional commands for enhanced quality and validation:
| Command | Agent Skill | Description |
| -------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `/speckit.clarify` | `speckit-clarify` | Clarify underspecified areas (recommended before `/speckit.plan`; formerly `/quizme`) |
| `/speckit.status` | `speckit-status` | Summarize workflow status across specs, including artifacts, task progress, checklists, and next actions |
| `/speckit.analyze` | `speckit-analyze` | Cross-artifact consistency & coverage analysis (run after `/speckit.tasks`, before `/speckit.implement`) |
| `/speckit.checklist` | `speckit-checklist` | Generate custom quality checklists that validate requirements completeness, clarity, and consistency (like "unit tests for English") |

Expand Down
2 changes: 2 additions & 0 deletions src/specify_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,7 @@ def _get_skills_dir(project_path: Path, selected_ai: str) -> Path:
"tasks": "Break down implementation plans into actionable task lists.",
"implement": "Execute all tasks from the task breakdown to build the feature.",
"analyze": "Perform cross-artifact consistency analysis across spec.md, plan.md, and tasks.md.",
"status": "Summarize workflow status across all specs.",
"clarify": "Structured clarification workflow for underspecified requirements.",
"constitution": "Create or update project governing principles and development guidelines.",
"checklist": "Generate custom quality checklists for validating requirements completeness and clarity.",
Expand Down Expand Up @@ -1436,6 +1437,7 @@ def _display_cmd(name: str) -> str:
enhancement_intro,
"",
f"○ [cyan]{_display_cmd('clarify')}[/] [bright_black](optional)[/bright_black] - Ask structured questions to de-risk ambiguous areas before planning (run before [cyan]{_display_cmd('plan')}[/] if used)",
f"○ [cyan]{_display_cmd('status')}[/] [bright_black](optional)[/bright_black] - Summarize workflow status across specs, including artifacts, tasks, checklists, and next actions",
f"○ [cyan]{_display_cmd('analyze')}[/] [bright_black](optional)[/bright_black] - Cross-artifact consistency & alignment report (after [cyan]{_display_cmd('tasks')}[/], before [cyan]{_display_cmd('implement')}[/])",
f"○ [cyan]{_display_cmd('checklist')}[/] [bright_black](optional)[/bright_black] - Generate quality checklists to validate requirements completeness, clarity, and consistency (after [cyan]{_display_cmd('plan')}[/])"
]
Expand Down
1 change: 1 addition & 0 deletions src/specify_cli/integrations/claude/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"tasks": "Optional task generation constraints",
"implement": "Optional implementation guidance or task filter",
"analyze": "Optional focus areas for analysis",
"status": "Optional feature filter or status scope",
"clarify": "Optional areas to clarify in the spec",
"constitution": "Principles or values for the project constitution",
"checklist": "Domain or focus area for the checklist",
Expand Down
201 changes: 201 additions & 0 deletions templates/commands/status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
description: Summarize Spec Kit workflow status across all specs without modifying files.
---

## User Input

```text
$ARGUMENTS
```

You **MUST** consider the user input before proceeding (if not empty).

## Pre-Execution Checks

**Check for extension hooks (before status reporting)**:
- Check if `.specify/extensions.yml` exists in the project root.
- If it exists, read it and look for entries under the `hooks.before_status` key
- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
- If the hook has no `condition` field, or it is null/empty, treat the hook as executable
- If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
- For each executable hook, output the following based on its `optional` flag:
- **Optional hook** (`optional: true`):
```
## Extension Hooks

**Optional Pre-Hook**: {extension}
Command: `/{command}`
Description: {description}

Prompt: {prompt}
To execute: `/{command}`
```
- **Mandatory hook** (`optional: false`):
```
## Extension Hooks

**Automatic Pre-Hook**: {extension}
Executing: `/{command}`
EXECUTE_COMMAND: {command}

Wait for the result of the hook command before proceeding to the Goal.
```
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Goal

Produce a read-only status report for every Spec Kit feature under `specs/`, including artifact availability, task progress, checklist progress, inferred workflow phase, and the next suggested command.

## Operating Constraints

**STRICTLY READ-ONLY**: Do **not** modify any files. Do not create, update, or delete specs, plans, tasks, checklists, branches, or configuration.

**Repository Scope**: Work from the repository root. Prefer the current working directory if it contains `.specify/` or `specs/`; otherwise, walk upward until a directory with `.specify/` or `specs/` is found. If neither is found, report that this does not appear to be a Spec Kit project.

**Input Handling**: If the user input is empty, report all specs. If the user input names a feature id, feature directory, branch, or substring, filter the report to matching spec directories and state the filter used.

## Execution Steps

### 1. Discover Project and Specs

- Locate the project root.
- Locate `specs/` under the project root.
- Enumerate direct child directories under `specs/`.
- Treat each child directory as one feature spec. Prefer directories whose names look like `NNN-feature-name`, but do not hide other directories if they contain Spec Kit artifacts.
- Sort features by numeric prefix when present, then by directory name.
- If `specs/` does not exist or no feature directories are found, output a concise empty-state report and stop.

### 2. Identify the Active Feature

- Try to detect the current git branch with `git branch --show-current`.
- If git is unavailable, the command fails, or the project is not a git repository, continue without an active feature marker.
- Mark a feature as active when its directory name exactly matches the current branch, or when the branch name ends with the feature directory name.

### 3. Inspect Artifacts

For each feature directory, inspect only file existence and compact metadata:

- Required workflow artifacts:
- `spec.md`
- `plan.md`
- `tasks.md`
- Optional design artifacts:
- `research.md`
- `data-model.md`
- `contracts/` with at least one file
- `quickstart.md`
- `checklists/` with at least one `.md` file

Do not load full artifact contents. For `tasks.md` and checklist files, read only enough to count checklist item states.

### 4. Calculate Progress

For each `tasks.md`, count task items matching:

- Complete: lines that begin with `- [x]` or `- [X]`
- Incomplete: lines that begin with `- [ ]`

For each checklist file under `checklists/`, count checklist items with the same checkbox pattern.

Derive task progress:

- `n/a` when `tasks.md` is missing
- `0/0` when `tasks.md` exists but has no checkbox items
- `{completed}/{total}` otherwise

Derive checklist status:

- `n/a` when no checklist files exist
- `PASS {completed}/{total}` when all checklist items are complete and total is greater than zero
- `FAIL {completed}/{total}` when at least one checklist item is incomplete
- `0/0` when checklist files exist but contain no checkbox items

### 5. Infer Workflow Phase

Use the following precedence:

- `Missing spec` when `spec.md` is absent
- `Specified` when `spec.md` exists and `plan.md` is absent
- `Planned` when `plan.md` exists and `tasks.md` is absent
- `Ready` when `tasks.md` exists and has task checkboxes but none are complete
- `In progress` when some, but not all, task checkboxes are complete
- `Complete` when all task checkboxes are complete and total is greater than zero
- `Tasked` when `tasks.md` exists but has no task checkboxes

### 6. Suggest Next Action

Use this default mapping, adjusting only when the inspected artifacts clearly indicate a better next action:

- `Missing spec` -> `/speckit.specify`
- `Specified` -> `/speckit.plan`
- `Planned` -> `/speckit.tasks`
- `Ready` -> `/speckit.implement`
- `In progress` -> `/speckit.implement`
- `Tasked` -> Review `tasks.md` formatting
- `Complete` -> Review or ship

If checklist status is `FAIL`, add `complete checklist items` to the next action.

### 7. Produce the Status Report

Output a Markdown report with this structure:

```markdown
## Spec Kit Status

| Active | Feature | Phase | Artifacts | Tasks | Checklists | Next |
|--------|---------|-------|-----------|-------|------------|------|
| * | 001-example | In progress | spec, plan, research, tasks | 12/20 | PASS 8/8 | /speckit.implement |

**Summary**

- Total specs: N
- Active feature: FEATURE_NAME or n/a
- Complete: N
- In progress: N
- Ready for implementation: N
- Missing next artifact: N
```

Artifact display rules:

- List present artifacts by short names: `spec`, `plan`, `research`, `data-model`, `contracts`, `quickstart`, `tasks`, `checklists`
- If an expected workflow artifact is missing, include `missing: spec`, `missing: plan`, or `missing: tasks`
- Keep each row compact; do not include raw artifact content

### 8. Check for Extension Hooks

After reporting, check if `.specify/extensions.yml` exists in the project root.
- If it exists, read it and look for entries under the `hooks.after_status` key
- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
- If the hook has no `condition` field, or it is null/empty, treat the hook as executable
- If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
- For each executable hook, output the following based on its `optional` flag:
- **Optional hook** (`optional: true`):
```
## Extension Hooks

**Optional Hook**: {extension}
Command: `/{command}`
Description: {description}

Prompt: {prompt}
To execute: `/{command}`
```
- **Mandatory hook** (`optional: false`):
```
## Extension Hooks

**Automatic Hook**: {extension}
Executing: `/{command}`
EXECUTE_COMMAND: {command}
```
- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

## Context

{ARGS}
2 changes: 1 addition & 1 deletion tests/integrations/test_integration_base_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def test_integration_flag_creates_files(self, tmp_path):

COMMAND_STEMS = [
"analyze", "checklist", "clarify", "constitution",
"implement", "plan", "specify", "tasks", "taskstoissues",
"implement", "plan", "specify", "status", "tasks", "taskstoissues",
]

def _expected_files(self, script_variant: str) -> list[str]:
Expand Down
4 changes: 2 additions & 2 deletions tests/integrations/test_integration_base_skills.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test_skill_directory_structure(self, tmp_path):

expected_commands = {
"analyze", "checklist", "clarify", "constitution",
"implement", "plan", "specify", "tasks", "taskstoissues",
"implement", "plan", "specify", "status", "tasks", "taskstoissues",
}

# Derive command names from the skill directory names
Expand Down Expand Up @@ -299,7 +299,7 @@ def test_options_include_skills_flag(self):

_SKILL_COMMANDS = [
"analyze", "checklist", "clarify", "constitution",
"implement", "plan", "specify", "tasks", "taskstoissues",
"implement", "plan", "specify", "status", "tasks", "taskstoissues",
]

def _expected_files(self, script_variant: str) -> list[str]:
Expand Down
1 change: 1 addition & 0 deletions tests/integrations/test_integration_base_toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ def test_integration_flag_creates_files(self, tmp_path):
"implement",
"plan",
"specify",
"status",
"tasks",
"taskstoissues",
]
Expand Down
1 change: 1 addition & 0 deletions tests/integrations/test_integration_base_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ def test_integration_flag_creates_files(self, tmp_path):
"implement",
"plan",
"specify",
"status",
"tasks",
"taskstoissues",
]
Expand Down
8 changes: 6 additions & 2 deletions tests/integrations/test_integration_copilot.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ def test_directory_structure(self, tmp_path):
agents_dir = tmp_path / ".github" / "agents"
assert agents_dir.is_dir()
agent_files = sorted(agents_dir.glob("speckit.*.agent.md"))
assert len(agent_files) == 9
assert len(agent_files) == 10
expected_commands = {
"analyze", "checklist", "clarify", "constitution",
"implement", "plan", "specify", "tasks", "taskstoissues",
"implement", "plan", "specify", "status", "tasks", "taskstoissues",
}
actual_commands = {f.name.removeprefix("speckit.").removesuffix(".agent.md") for f in agent_files}
assert actual_commands == expected_commands
Expand Down Expand Up @@ -169,6 +169,7 @@ def test_complete_file_inventory_sh(self, tmp_path):
".github/agents/speckit.implement.agent.md",
".github/agents/speckit.plan.agent.md",
".github/agents/speckit.specify.agent.md",
".github/agents/speckit.status.agent.md",
".github/agents/speckit.tasks.agent.md",
".github/agents/speckit.taskstoissues.agent.md",
".github/prompts/speckit.analyze.prompt.md",
Expand All @@ -178,6 +179,7 @@ def test_complete_file_inventory_sh(self, tmp_path):
".github/prompts/speckit.implement.prompt.md",
".github/prompts/speckit.plan.prompt.md",
".github/prompts/speckit.specify.prompt.md",
".github/prompts/speckit.status.prompt.md",
".github/prompts/speckit.tasks.prompt.md",
".github/prompts/speckit.taskstoissues.prompt.md",
".vscode/settings.json",
Expand Down Expand Up @@ -229,6 +231,7 @@ def test_complete_file_inventory_ps(self, tmp_path):
".github/agents/speckit.implement.agent.md",
".github/agents/speckit.plan.agent.md",
".github/agents/speckit.specify.agent.md",
".github/agents/speckit.status.agent.md",
".github/agents/speckit.tasks.agent.md",
".github/agents/speckit.taskstoissues.agent.md",
".github/prompts/speckit.analyze.prompt.md",
Expand All @@ -238,6 +241,7 @@ def test_complete_file_inventory_ps(self, tmp_path):
".github/prompts/speckit.implement.prompt.md",
".github/prompts/speckit.plan.prompt.md",
".github/prompts/speckit.specify.prompt.md",
".github/prompts/speckit.status.prompt.md",
".github/prompts/speckit.tasks.prompt.md",
".github/prompts/speckit.taskstoissues.prompt.md",
".vscode/settings.json",
Expand Down
2 changes: 2 additions & 0 deletions tests/integrations/test_integration_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ def test_complete_file_inventory_sh(self, tmp_path):
".myagent/commands/speckit.implement.md",
".myagent/commands/speckit.plan.md",
".myagent/commands/speckit.specify.md",
".myagent/commands/speckit.status.md",
".myagent/commands/speckit.tasks.md",
".myagent/commands/speckit.taskstoissues.md",
".specify/init-options.json",
Expand Down Expand Up @@ -284,6 +285,7 @@ def test_complete_file_inventory_ps(self, tmp_path):
".myagent/commands/speckit.implement.md",
".myagent/commands/speckit.plan.md",
".myagent/commands/speckit.specify.md",
".myagent/commands/speckit.status.md",
".myagent/commands/speckit.tasks.md",
".myagent/commands/speckit.taskstoissues.md",
".specify/init-options.json",
Expand Down