mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-14 05:19:53 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68fc049955 | ||
|
|
4874a16495 | ||
|
|
3caabf86cf | ||
|
|
d4593e4a54 | ||
|
|
0144ec2b1b | ||
|
|
8eb7ebd7cd |
@@ -87,6 +87,7 @@ After deployment, create separate PR to:
|
||||
openspec list # List active changes
|
||||
openspec list --specs # List specifications
|
||||
openspec show [item] # Display change or spec
|
||||
openspec diff [change] # Show spec differences
|
||||
openspec validate [item] # Validate changes or specs
|
||||
openspec archive [change] # Archive after deployment
|
||||
|
||||
@@ -255,6 +256,19 @@ Every requirement MUST have at least one scenario.
|
||||
|
||||
Headers matched with `trim(header)` - whitespace ignored.
|
||||
|
||||
#### When to use ADDED vs MODIFIED
|
||||
- ADDED: Introduces a new capability or sub-capability that can stand alone as a requirement. Prefer ADDED when the change is orthogonal (e.g., adding "Slash Command Configuration") rather than altering the semantics of an existing requirement.
|
||||
- MODIFIED: Changes the behavior, scope, or acceptance criteria of an existing requirement. Always paste the full, updated requirement content (header + all scenarios). The archiver will replace the entire requirement with what you provide here; partial deltas will drop previous details.
|
||||
- RENAMED: Use when only the name changes. If you also change behavior, use RENAMED (name) plus MODIFIED (content) referencing the new name.
|
||||
|
||||
Common pitfall: Using MODIFIED to add a new concern without including the previous text. This causes loss of detail at archive time. If you aren’t explicitly changing the existing requirement, add a new requirement under ADDED instead.
|
||||
|
||||
Authoring a MODIFIED requirement correctly:
|
||||
1) Locate the existing requirement in `openspec/specs/<capability>/spec.md`.
|
||||
2) Copy the entire requirement block (from `### Requirement: ...` through its scenarios).
|
||||
3) Paste it under `## MODIFIED Requirements` and edit to reflect the new behavior.
|
||||
4) Ensure the header text matches exactly (whitespace-insensitive) and keep at least one `#### Scenario:`.
|
||||
|
||||
Example for RENAMED:
|
||||
```markdown
|
||||
## RENAMED Requirements
|
||||
@@ -425,6 +439,7 @@ Only add complexity with:
|
||||
```bash
|
||||
openspec list # What's in progress?
|
||||
openspec show [item] # View details
|
||||
openspec diff [change] # What's changing?
|
||||
openspec validate --strict # Is it correct?
|
||||
openspec archive [change] # Mark complete
|
||||
```
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# Add Slash Command Support for Coding Agents
|
||||
|
||||
## Summary
|
||||
- Enable OpenSpec to generate and update custom slash commands for supported coding agents (Claude Code and Cursor).
|
||||
- Provide three slash commands aligned with OpenSpec's workflow: proposal (start a change proposal), apply (implement), and archive.
|
||||
- Share slash command templating between agents to make future extensions simple.
|
||||
|
||||
## Motivation
|
||||
Developers use different coding agents and editors. Having consistent slash commands across tools for the OpenSpec workflow reduces friction and ensures a standard way to trigger the workflow. Supporting both Claude Code and Cursor now lays a foundation for future agents that introduce slash command features.
|
||||
|
||||
## Proposal
|
||||
1. During `openspec init`, when a user selects a supported tool, generate slash command configuration for three OpenSpec workflow stages:
|
||||
- Claude (namespaced): `/openspec/proposal`, `/openspec/apply`, `/openspec/archive`.
|
||||
- Cursor (flat, prefixed): `/openspec-proposal`, `/openspec-apply`, `/openspec-archive`.
|
||||
- Semantics:
|
||||
- Create – scaffold a change (ID, `proposal.md`, `tasks.md`, delta specs); validate strictly.
|
||||
- Apply – implement an approved change; complete tasks; validate strictly.
|
||||
- Archive – archive after deployment; update specs if needed.
|
||||
- Each command file MUST embed concise, step-by-step instructions sourced from `openspec/README.md` (see Template Content section).
|
||||
2. Store slash command files per tool:
|
||||
- Claude Code: `.claude/commands/openspec/{proposal,apply,archive}.md`
|
||||
- Cursor: `.cursor/commands/{openspec-proposal,openspec-apply,openspec-archive}.md`
|
||||
- Ensure nested directories are created.
|
||||
3. Command file format and metadata:
|
||||
- Use Markdown with optional YAML frontmatter for tool metadata (name/title, description, category/tags) when supported by the tool.
|
||||
- Place OpenSpec markers around the body only, never inside frontmatter.
|
||||
- Keep the visible slash name, file name, and any frontmatter `name`/`id` consistently aligned (e.g., `proposal`, `openspec-proposal`).
|
||||
- Namespacing: categorize these under “OpenSpec” and prefer unique IDs (e.g., `openspec-proposal`) to avoid collisions.
|
||||
4. Centralize templates: define command bodies once and reuse across tools; apply minimal per-tool wrappers (frontmatter, categories, filenames).
|
||||
5. During `openspec update`, refresh only existing slash command files (per-file basis) within markers; do not create missing files or new tools.
|
||||
|
||||
## Design Ideas
|
||||
- Introduce `SlashCommandConfigurator` to manage multiple files per tool.
|
||||
- Expose targets rather than a single `configFileName` (e.g., `getTargets(): Array<{ path: string; kind: 'slash'; id: string }>`).
|
||||
- Provide `generateAll(projectPath, openspecDir)` for init and `updateExisting(projectPath, openspecDir)` for update.
|
||||
- Per-tool adapters add only frontmatter and pathing; bodies come from shared templates.
|
||||
- Templates live in `TemplateManager` with helpers that extract concise, authoritative snippets from `openspec/README.md`.
|
||||
- Update flow logs per-file results so users see exactly which slash files were refreshed.
|
||||
|
||||
### Marker Placement
|
||||
- Markers MUST wrap only the Markdown body contents:
|
||||
- Frontmatter (if present) goes first.
|
||||
- Then `<!-- OPENSPEC:START -->` … body … `<!-- OPENSPEC:END -->`.
|
||||
- Avoid inserting markers into the YAML block to prevent parse errors.
|
||||
|
||||
### Idempotency and Creation Rules
|
||||
- `init`: create all three files for the chosen tool(s) once; subsequent `init` runs are no-ops for existing files.
|
||||
- `update`: refresh only files that exist; skip missing ones without creating new files.
|
||||
- Directory creation for `.claude/commands/openspec/` and `.cursor/commands/` is the configurator’s responsibility.
|
||||
|
||||
### Command Naming & UX
|
||||
- Claude Code: use namespacing in the slash itself for readability and grouping: `/openspec/proposal`, `/openspec/apply`, `/openspec/archive`.
|
||||
- Cursor: use flat names with an `openspec-` prefix: `/openspec-proposal`, `/openspec-apply`, `/openspec-archive`. Group via `category: OpenSpec` when supported.
|
||||
- Consistency: align file names, visible slash names, and any frontmatter `id` (e.g., `id: openspec-apply`).
|
||||
- Migration: do not rename existing commands during `update`; apply new naming only on `init` (or via an explicit migrate step).
|
||||
|
||||
## Open Questions
|
||||
- Validate exact metadata/frontmatter supported by each tool version; if unsupported, omit frontmatter and ship Markdown body only.
|
||||
- Confirm the final Cursor command file location for the targeted versions; fall back to Markdown-only if Cursor does not parse frontmatter.
|
||||
- Evaluate additional commands beyond the initial three (e.g., `/show-change`, `/validate-all`) based on user demand.
|
||||
|
||||
## Alternatives
|
||||
- Hard-code slash command text per tool (rejected: duplicates content; increases maintenance).
|
||||
- Delay Cursor support until its config stabilizes (partial accept): gate Cursor behind a feature flag until verified in real environments.
|
||||
|
||||
## Risks
|
||||
- Tool configuration formats may change, requiring updates to wrappers/frontmatter.
|
||||
- Incorrect paths or categories can hide commands; add path existence checks and clear logging.
|
||||
- Marker misuse (inside frontmatter) can break parsing; enforce placement rules in tests.
|
||||
|
||||
## Future Work
|
||||
- Support additional editors/agents that expose slash command APIs.
|
||||
- Allow users to customize command names and categories during `openspec init`.
|
||||
- Provide a dedicated command to regenerate slash commands without running full `update`.
|
||||
|
||||
## File Format Examples
|
||||
The following examples illustrate expected structure. If a tool does not support frontmatter, omit the YAML block and keep only the markers + body.
|
||||
|
||||
### Claude Code: `.claude/commands/openspec/proposal.md`
|
||||
```markdown
|
||||
---
|
||||
name: OpenSpec: Proposal
|
||||
description: Scaffold a new OpenSpec change and validate strictly.
|
||||
category: OpenSpec
|
||||
tags: [openspec, change]
|
||||
---
|
||||
<!-- OPENSPEC:START -->
|
||||
...command body from shared template...
|
||||
<!-- OPENSPEC:END -->
|
||||
```
|
||||
|
||||
Slash invocation: `/openspec/proposal` (namespaced)
|
||||
|
||||
### Cursor: `.cursor/commands/openspec-proposal.md`
|
||||
```markdown
|
||||
---
|
||||
name: /openspec-proposal
|
||||
id: openspec-proposal
|
||||
category: OpenSpec
|
||||
description: Scaffold a new OpenSpec change and validate strictly.
|
||||
---
|
||||
<!-- OPENSPEC:START -->
|
||||
...command body from shared template...
|
||||
<!-- OPENSPEC:END -->
|
||||
```
|
||||
|
||||
Slash invocation: `/openspec-proposal` (flat, prefixed)
|
||||
|
||||
## Template Content
|
||||
Templates should be brief, actionable, and sourced from `openspec/README.md` to avoid duplication. Each command body includes:
|
||||
- Guardrails: ask 1–2 clarifying questions if needed; follow minimal-complexity rules; use `pnpm` for Node projects.
|
||||
- Step list tailored to the workflow stage (proposal, apply, archive), including strict validation commands.
|
||||
- Pointers to `openspec show`, `openspec list`, and troubleshooting tips when validation fails.
|
||||
|
||||
## Testing Strategy
|
||||
- Golden snapshots for generated files per tool (frontmatter + markers + body).
|
||||
- Partial presence tests: if 1–2 files exist, `update` only refreshes those and does not create missing ones.
|
||||
- Marker placement tests: ensure markers never appear inside frontmatter; cover missing/duplicated marker recovery behavior.
|
||||
- Logging tests: `update` reports per-file updates for slash commands.
|
||||
@@ -0,0 +1,15 @@
|
||||
## ADDED Requirements
|
||||
### Requirement: Slash Command Configuration
|
||||
The init command SHALL generate slash command files for supported editors using shared templates.
|
||||
|
||||
#### Scenario: Generating slash commands for Claude Code
|
||||
- **WHEN** the user selects Claude Code during initialization
|
||||
- **THEN** create `.claude/commands/openspec/proposal.md`, `.claude/commands/openspec/apply.md`, and `.claude/commands/openspec/archive.md`
|
||||
- **AND** populate each file from shared templates so command text matches other tools
|
||||
- **AND** each template includes instructions for the relevant OpenSpec workflow stage
|
||||
|
||||
#### Scenario: Generating slash commands for Cursor
|
||||
- **WHEN** the user selects Cursor during initialization
|
||||
- **THEN** create `.cursor/commands/openspec-proposal.md`, `.cursor/commands/openspec-apply.md`, and `.cursor/commands/openspec-archive.md`
|
||||
- **AND** populate each file from shared templates so command text matches other tools
|
||||
- **AND** each template includes instructions for the relevant OpenSpec workflow stage
|
||||
@@ -0,0 +1,17 @@
|
||||
## ADDED Requirements
|
||||
### Requirement: Slash Command Updates
|
||||
The update command SHALL refresh existing slash command files for configured tools without creating new ones.
|
||||
|
||||
#### Scenario: Updating slash commands for Claude Code
|
||||
- **WHEN** `.claude/commands/openspec/` contains `proposal.md`, `apply.md`, and `archive.md`
|
||||
- **THEN** refresh each file using shared templates
|
||||
- **AND** ensure templates include instructions for the relevant workflow stage
|
||||
|
||||
#### Scenario: Updating slash commands for Cursor
|
||||
- **WHEN** `.cursor/commands/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md`
|
||||
- **THEN** refresh each file using shared templates
|
||||
- **AND** ensure templates include instructions for the relevant workflow stage
|
||||
|
||||
#### Scenario: Missing slash command file
|
||||
- **WHEN** a tool lacks a slash command file
|
||||
- **THEN** do not create a new file during update
|
||||
@@ -0,0 +1,16 @@
|
||||
# Implementation Tasks
|
||||
|
||||
## 1. Templates and Configurators
|
||||
- [ ] 1.1 Create shared templates for the Proposal, Apply, and Archive commands with instructions for each workflow stage from `openspec/README.md`.
|
||||
- [ ] 1.2 Implement a `SlashCommandConfigurator` base and tool-specific configurators for Claude Code and Cursor.
|
||||
|
||||
## 2. Claude Code Integration
|
||||
- [ ] 2.1 Generate `.claude/commands/openspec/{proposal,apply,archive}.md` during `openspec init` using shared templates.
|
||||
- [ ] 2.2 Update existing `.claude/commands/openspec/*` files during `openspec update`.
|
||||
|
||||
## 3. Cursor Integration
|
||||
- [ ] 3.1 Generate `.cursor/commands/{openspec-proposal,openspec-apply,openspec-archive}.md` during `openspec init` using shared templates.
|
||||
- [ ] 3.2 Update existing `.cursor/commands/*` files during `openspec update`.
|
||||
|
||||
## 4. Verification
|
||||
- [ ] 4.1 Add tests verifying slash command files are created and updated correctly.
|
||||
@@ -0,0 +1,12 @@
|
||||
## Why
|
||||
Validation currently errors on changes without spec deltas, even when the change is intentionally proposal-only or tooling-only. This creates false negatives and noisy CI.
|
||||
|
||||
## What Changes
|
||||
- Make change validation scope-aware: validate only artifacts that exist.
|
||||
- Only error on "No deltas found" if spec delta files exist but parse to zero deltas.
|
||||
- Keep archive stricter: if specs exist but parse to zero deltas, fail; allow `--skip-specs` for tooling-only changes.
|
||||
|
||||
## Impact
|
||||
- Affected specs: cli-validate
|
||||
- Affected code: `src/commands/validate.ts`, `src/core/validation/validator.ts`
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
## ADDED Requirements
|
||||
### Requirement: Scope-Aware Change Validation
|
||||
The validator SHALL validate only artifacts that exist for a change, avoiding errors for proposal-only or tooling-only changes.
|
||||
|
||||
#### Scenario: Proposal-only change
|
||||
- **WHEN** a change contains `proposal.md` but has no `specs/` directory or contains no `*/spec.md` files
|
||||
- **THEN** validate the proposal (Why/What sections)
|
||||
- **AND** do not require or validate spec deltas
|
||||
|
||||
#### Scenario: Delta validation when specs exist
|
||||
- **WHEN** a change contains one or more `specs/<capability>/spec.md` files
|
||||
- **THEN** validate delta-formatted specs with existing rules (SHALL/MUST, scenarios, duplicates, conflicts)
|
||||
|
||||
## MODIFIED Requirements
|
||||
### Requirement: Validation SHALL provide actionable remediation steps
|
||||
Validation output SHALL include specific guidance to fix each error, including expected structure, example headers, and suggested commands to verify fixes.
|
||||
|
||||
#### Scenario: No deltas found in change
|
||||
- **WHEN** validating a change that contains `specs/` with one or more `*/spec.md` files but the parser finds zero deltas
|
||||
- **THEN** show error "No deltas found" with guidance:
|
||||
- Ensure `openspec/changes/{id}/specs/` has `.md` files that include delta headers
|
||||
- Use delta headers: `## ADDED Requirements`, `## MODIFIED Requirements`, `## REMOVED Requirements`, `## RENAMED Requirements`
|
||||
- Each requirement must include at least one `#### Scenario:` block
|
||||
- Try: `openspec change show {id} --json --deltas-only` to inspect parsed deltas
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
## 1. Validator changes
|
||||
- [ ] 1.1 Change `validateChangeDeltaSpecs` to only emit "Change must have at least one delta" when `specs/` exists and contains at least one `*/spec.md` but parsed total deltas is 0
|
||||
- [ ] 1.2 Return valid (no error) when `specs/` directory is missing or has no `spec.md` files
|
||||
|
||||
## 2. CLI changes
|
||||
- [ ] 2.1 In bulk validation, keep current behavior (call delta validator). Behavior remains correct after 1.1
|
||||
- [ ] 2.2 Add a short INFO log in human-readable mode when a change has no `specs/` (optional)
|
||||
|
||||
## 3. Documentation
|
||||
- [ ] 3.1 Update README and template: "Validation checks only existing artifacts. Proposal-only changes are valid without spec deltas."
|
||||
|
||||
## 4. Tests
|
||||
- [ ] 4.1 Add test: proposal-only change passes validation without deltas
|
||||
- [ ] 4.2 Add test: specs present but zero parsed deltas → ERROR
|
||||
- [ ] 4.3 Add test: specs present with proper deltas → valid
|
||||
|
||||
@@ -256,6 +256,19 @@ Every requirement MUST have at least one scenario.
|
||||
|
||||
Headers matched with \`trim(header)\` - whitespace ignored.
|
||||
|
||||
#### When to use ADDED vs MODIFIED
|
||||
- ADDED: Introduces a new capability or sub-capability that can stand alone as a requirement. Prefer ADDED when the change is orthogonal (e.g., adding "Slash Command Configuration") rather than altering the semantics of an existing requirement.
|
||||
- MODIFIED: Changes the behavior, scope, or acceptance criteria of an existing requirement. Always paste the full, updated requirement content (header + all scenarios). The archiver will replace the entire requirement with what you provide here; partial deltas will drop previous details.
|
||||
- RENAMED: Use when only the name changes. If you also change behavior, use RENAMED (name) plus MODIFIED (content) referencing the new name.
|
||||
|
||||
Common pitfall: Using MODIFIED to add a new concern without including the previous text. This causes loss of detail at archive time. If you aren’t explicitly changing the existing requirement, add a new requirement under ADDED instead.
|
||||
|
||||
Authoring a MODIFIED requirement correctly:
|
||||
1) Locate the existing requirement in \`openspec/specs/<capability>/spec.md\`.
|
||||
2) Copy the entire requirement block (from \`### Requirement: ...\` through its scenarios).
|
||||
3) Paste it under \`## MODIFIED Requirements\` and edit to reflect the new behavior.
|
||||
4) Ensure the header text matches exactly (whitespace-insensitive) and keep at least one \`#### Scenario:\`.
|
||||
|
||||
Example for RENAMED:
|
||||
\`\`\`markdown
|
||||
## RENAMED Requirements
|
||||
|
||||
Reference in New Issue
Block a user