diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 00000000..15e3da59 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,114 @@ +# OpenSpec Extension for Gemini CLI + +OpenSpec is an AI-native system for spec-driven development. It helps developers and AI agents maintain a shared understanding of project requirements and technical designs through a structured workflow. + +## Prerequisites + +This extension requires the OpenSpec CLI. + +**Auto-Initialization Instruction**: +When the user starts a session or tries to use OpenSpec: +1. **Check for CLI**: Run `openspec --version`. + - If found, use `openspec` for all commands. + - If missing, **automatically attempt to install it globally** by running: + ```bash + npm install -g "@fission-ai/openspec" + ``` + - If the installation fails or the user cancels the tool call, fall back to: + ```bash + npx "@fission-ai/openspec" + ``` + or + ```bash + pnpm dlx "@fission-ai/openspec" + ``` +2. **Check for Slash Commands**: Verify if `.gemini/commands/openspec/` exists and contains `proposal.toml`, `apply.toml`, and `archive.toml`. + - If missing, **automatically generate them** using the logic defined in the "Maintenance: Slash Command Synchronization" section below. + - Inform the user: "OpenSpec slash commands have been generated. You may need to restart the CLI to see them." +3. **Check for Project Initialization**: Verify if the `openspec/` directory exists in the project root. + - If missing, automatically run `openspec init` to scaffold the project structure. +4. **Populate Project Context**: + - **Trigger**: When `openspec init` completes and suggests "Populate your project context", you MUST perform this immediately. + - **Action**: Read `openspec/project.md`, analyze project config (`package.json`, etc.), and fill in the details. **Do not** ask the user to do this manually. + +## Core Mandates for Gemini Agents + +- **Specs are Truth**: Always read `openspec/specs/` to understand the current state of a capability. +- **Changes are Proposals**: All modifications to behavior or requirements MUST start as a proposal in `openspec/changes/`. +- **Minimize Confirmations**: Do not ask for permission for low-risk read operations or standard project scaffolding if the user's intent is clear. Assume consent for actions explicitly requested. +- **Three-Stage Workflow**: + 1. **Stage 1: Creating Changes**: Scaffold `proposal.md`, `tasks.md`, and spec deltas. Validate with `openspec validate --strict`. + 2. **Stage 2: Implementing Changes**: Follow `tasks.md` sequentially. + 3. **Stage 3: Archiving Changes**: Move completed changes to `archive/` using `openspec archive `. + +## Essential CLI Commands + +When working in an OpenSpec-enabled project, you can use these commands: + +- `openspec list`: Show active changes. +- `openspec list --specs`: Show existing capabilities. +- `openspec show `: View details of a change or spec. +- `openspec validate `: Validate a change against the project's specs. +- `openspec init`: Initialize OpenSpec in a new project. +- `openspec update`: Update instruction files (like `AGENTS.md`). + +## Directory Structure + +- `openspec/project.md`: Project-specific conventions and tech stack. +- `openspec/specs/`: Current requirements and scenarios (the "truth"). +- `openspec/changes/`: Pending proposals and implementation tasks. + +## Writing Specs + +Requirements must be normative (SHALL/MUST). Every requirement MUST have at least one scenario using the following format: + +```markdown +#### Scenario: Name +- **WHEN** action or condition +- **THEN** expected result +``` + +For more detailed instructions, refer to `openspec/AGENTS.md`. + +## Maintenance: Slash Command Synchronization + +The slash commands for this extension (`.gemini/commands/openspec/*.toml`) are generated artifacts. The single source of truth for their content is `src/core/templates/prompts.ts`. + +**Instruction**: When `src/core/templates/prompts.ts` is modified, or when asked to "update slash commands", you MUST regenerate the TOML files in `.gemini/commands/openspec/` using the following logic: + +1. **Read** `src/core/templates/prompts.ts` to extract the exported constants. +2. **Construct** the prompt body for each command by joining the relevant constants with `\n\n`: + - **proposal**: `PROPOSAL_GUARDRAILS` + `PROPOSAL_STEPS` + `PROPOSAL_REFERENCES` + - **apply**: `BASE_GUARDRAILS` + `APPLY_STEPS` + `APPLY_REFERENCES` + - **archive**: `BASE_GUARDRAILS` + `ARCHIVE_STEPS` + `ARCHIVE_REFERENCES` +3. **Generate** the TOML files with the following structure (preserving the `` markers inside the prompt string): + + **File**: `.gemini/commands/openspec/proposal.toml` + ```toml + description = "Scaffold a new OpenSpec change and validate strictly." + prompt = """ + + {PROPOSAL_BODY} + + """ + ``` + + **File**: `.gemini/commands/openspec/apply.toml` + ```toml + description = "Implement an approved OpenSpec change and keep tasks in sync." + prompt = """ + + {APPLY_BODY} + + """ + ``` + + **File**: `.gemini/commands/openspec/archive.toml` + ```toml + description = "Archive a deployed OpenSpec change and update specs." + prompt = """ + + {ARCHIVE_BODY} + + """ + ``` diff --git a/README.md b/README.md index 7b6c7354..e84dfd38 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ These tools have built-in OpenSpec commands. Select the OpenSpec integration whe | **Crush** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.crush/commands/openspec/`) | | **Cursor** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` | | **Factory Droid** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.factory/commands/`) | -| **Gemini CLI** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (`.gemini/commands/openspec/`) | +| **Gemini CLI** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` (Native Extension available) | | **GitHub Copilot** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.github/prompts/`) | | **iFlow (iflow-cli)** | `/openspec-proposal`, `/openspec-apply`, `/openspec-archive` (`.iflow/commands/`) | | **Kilo Code** | `/openspec-proposal.md`, `/openspec-apply.md`, `/openspec-archive.md` (`.kilocode/workflows/`) | @@ -128,6 +128,22 @@ These tools automatically read workflow instructions from `openspec/AGENTS.md`. +### Gemini CLI Extension (Native) + +OpenSpec is available as a native extension for the [Gemini CLI](https://geminicli.com). This provides deep contextual awareness and native slash commands without manual configuration. + +**Install the extension:** +```bash +gemini extensions install https://github.com/Fission-AI/OpenSpec +``` + +**Benefits:** +- **Zero Configuration**: Automatically sets up `/openspec` slash commands. +- **Native Context**: Gemini becomes "OpenSpec-aware" instantly. +- **Auto-Maintenance**: The agent can self-repair its command definitions from the source of truth. + +*Note: You still need the [OpenSpec CLI](#step-1-install-the-cli-globally) installed globally for the agent to perform operations.* + ### Install & Initialize #### Prerequisites diff --git a/gemini-extension.json b/gemini-extension.json new file mode 100644 index 00000000..8b58a92a --- /dev/null +++ b/gemini-extension.json @@ -0,0 +1,5 @@ +{ + "name": "openspec", + "version": "0.16.0", + "contextFileName": "GEMINI.md" +} diff --git a/openspec/changes/add-mcp-server/proposal.md b/openspec/changes/add-mcp-server/proposal.md new file mode 100644 index 00000000..3aa7dbad --- /dev/null +++ b/openspec/changes/add-mcp-server/proposal.md @@ -0,0 +1,29 @@ +# Proposal: Add MCP Server Support + +## Context +Currently, OpenSpec integrates with AI agents via CLI commands and static configuration files (slash commands). While effective, this requires manual setup for some agents and lacks the rich interactivity offered by the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/). + +## Goal +Implement a native MCP server within the OpenSpec CLI using modern tools (e.g., `fastmcp` or `@modelcontextprotocol/sdk`). This will: +1. Allow any MCP-compliant agent (Claude Desktop, Gemini CLI, etc.) to discover and use OpenSpec tools and resources without custom configuration files. +2. Enable the Gemini CLI extension to be a thin wrapper around this native MCP server. +3. Align the project structure with modern standards by moving `openspec/` to `.openspec/` during initialization. + +## Migration Path +To support existing users, the CLI will include an automatic migration flow: +- **Detection**: `openspec init` (or a dedicated `openspec migrate` command) will detect legacy `openspec/` directories. +- **Auto-rename**: Prompt the user to rename `openspec/` to `.openspec/`. +- **Instruction Refresh**: Automatically run `openspec update` after the rename to ensure all assistant instructions point to the new location. +- **Backward Compatibility**: The CLI will continue to look for `openspec/` if `.openspec/` is missing, but will issue a deprecation warning. + +## Solution +1. **Add `openspec serve` command**: Starts the MCP server over stdio. +2. **Use Modern MCP Tools**: Leverage libraries like `fastmcp` or the official SDK to simplify server implementation and type safety. +3. **Expose Tools**: Convert existing CLI commands (`list`, `show`, `validate`, `archive`) into MCP tools. +4. **Expose Resources**: Provide direct read access to specs and changes via `openspec://` URIs. +5. **Expose Prompts**: Serve the standard proposal/apply/archive prompts via `prompts/list`. +6. **Migrate Directory**: Update `init` to scaffold in `.openspec/` instead of `openspec/`. +7. **Gemini Extension**: Create the `gemini-extension.json` manifest to register this MCP server capability. +8. **CI Validation**: Add a CI check to ensure `gemini-extension.json` version stays in sync with `package.json`. + +This "modernizes" the integration, making it cleaner, more robust, and easier to maintain. \ No newline at end of file diff --git a/openspec/changes/add-mcp-server/specs/ci-sync/spec.md b/openspec/changes/add-mcp-server/specs/ci-sync/spec.md new file mode 100644 index 00000000..e48b5b2e --- /dev/null +++ b/openspec/changes/add-mcp-server/specs/ci-sync/spec.md @@ -0,0 +1,17 @@ +# Delta for ci-sync + +## ADDED Requirements +### Requirement: Extension Version Synchronization +The system SHALL ensure that the version in `gemini-extension.json` matches the version in `package.json` during the CI process. + +#### Scenario: Version mismatch in CI +- **GIVEN** `package.json` has version `0.18.0` +- **AND** `gemini-extension.json` has version `0.17.0` +- **WHEN** the CI pipeline runs +- **THEN** the version check step SHALL fail +- **AND** report the mismatch to the logs + +#### Scenario: Version match in CI +- **GIVEN** both files have version `0.18.0` +- **WHEN** the CI pipeline runs +- **THEN** the version check step SHALL pass diff --git a/openspec/changes/add-mcp-server/specs/cli-init/spec.md b/openspec/changes/add-mcp-server/specs/cli-init/spec.md new file mode 100644 index 00000000..3520f6b6 --- /dev/null +++ b/openspec/changes/add-mcp-server/specs/cli-init/spec.md @@ -0,0 +1,28 @@ +# Delta for cli-init + +## MODIFIED Requirements +### Requirement: Directory Creation +The command SHALL create the complete OpenSpec directory structure in a hidden directory `.openspec/` to reduce clutter. + +#### Scenario: Creating OpenSpec structure +- **WHEN** `openspec init` is executed +- **THEN** create the following directory structure: +``` +.openspec/ +├── project.md +├── AGENTS.md +├── specs/ +└── changes/ + └── archive/ +``` + +### Requirement: Legacy Migration +The `init` command SHALL detect legacy `openspec/` directories and offer to migrate them to `.openspec/`. + +#### Scenario: Migrating legacy directory +- **GIVEN** a project with an existing `openspec/` directory +- **AND** no `.openspec/` directory exists +- **WHEN** executing `openspec init` +- **THEN** prompt the user: "Detected legacy 'openspec/' directory. Would you like to migrate it to '.openspec/'?" +- **AND** if confirmed, rename the directory +- **AND** update all managed AI instructions to point to the new location diff --git a/openspec/changes/add-mcp-server/specs/cli-spec/spec.md b/openspec/changes/add-mcp-server/specs/cli-spec/spec.md new file mode 100644 index 00000000..72e5b309 --- /dev/null +++ b/openspec/changes/add-mcp-server/specs/cli-spec/spec.md @@ -0,0 +1,10 @@ +# Delta for cli-spec + +## ADDED Requirements +### Requirement: Serve Command +The system SHALL provide a `serve` command to start the Model Context Protocol (MCP) server. + +#### Scenario: Start MCP Server +- **WHEN** executing `openspec serve` +- **THEN** start the MCP server using stdio transport +- **AND** keep the process alive to handle requests diff --git a/openspec/changes/add-mcp-server/specs/mcp-server/spec.md b/openspec/changes/add-mcp-server/specs/mcp-server/spec.md new file mode 100644 index 00000000..3532a8c1 --- /dev/null +++ b/openspec/changes/add-mcp-server/specs/mcp-server/spec.md @@ -0,0 +1,31 @@ +# MCP Server Specification + +## Purpose +Define the capabilities of the OpenSpec Model Context Protocol (MCP) server. This server enables native integration with MCP-compliant agents (including the Gemini CLI extension) by exposing tools, resources, and prompts dynamically. + +## ADDED Requirements +### Requirement: Expose Tools +The server SHALL expose core OpenSpec capabilities as MCP tools. + +#### Scenario: List Tools +- **WHEN** the client requests `tools/list` +- **THEN** return `openspec_list`, `openspec_show`, `openspec_validate`, `openspec_archive` tools +- **AND** include descriptions and JSON schemas for arguments + +### Requirement: Expose Resources +The server SHALL expose specs and changes as MCP resources. + +#### Scenario: List Resources +- **WHEN** the client requests `resources/list` +- **THEN** return a list of available specs and changes with `openspec://` URIs + +#### Scenario: Read Resource +- **WHEN** the client requests `resources/read` for a valid URI +- **THEN** return the content of the corresponding file (markdown or JSON) + +### Requirement: Expose Prompts +The server SHALL expose standard OpenSpec prompts. + +#### Scenario: List Prompts +- **WHEN** the client requests `prompts/list` +- **THEN** return `proposal`, `apply`, `archive` prompts \ No newline at end of file diff --git a/openspec/changes/add-mcp-server/tasks.md b/openspec/changes/add-mcp-server/tasks.md new file mode 100644 index 00000000..bed1d891 --- /dev/null +++ b/openspec/changes/add-mcp-server/tasks.md @@ -0,0 +1,35 @@ +# Implementation Tasks + +## 1. Dependencies +- [ ] 1.1 Install `fastmcp` (or `@modelcontextprotocol/sdk` + `zod`) as a dependency. + +## 2. Directory Migration (openspec -> .openspec) +- [ ] 2.1 Update `src/core/config.ts` (or equivalent) to look for `.openspec` folder by default, falling back to `openspec` for backward compatibility. +- [ ] 2.2 Update `src/core/init.ts` to scaffold the project in `.openspec/`. +- [ ] 2.3 Implement migration detection in `openspec init`: if `openspec/` exists, prompt to rename to `.openspec/`. +- [ ] 2.4 Create a standalone `openspec migrate` command for explicit migration. +- [ ] 2.5 Verify `openspec init` creates the new hidden directory structure. + +## 3. MCP Server Implementation +- [ ] 3.1 Create `src/mcp/server.ts` to initialize the MCP server instance (using `fastmcp` if applicable). +- [ ] 3.2 Implement `src/mcp/tools.ts` to map `list`, `show`, `validate`, `archive` to MCP tools. +- [ ] 3.3 Implement `src/mcp/resources.ts` to expose specs and changes as resources (`openspec://...`). +- [ ] 3.4 Implement `src/mcp/prompts.ts` to expose `proposal`, `apply`, `archive` prompts. +- [ ] 3.5 Connect everything in `src/mcp/index.ts`. + +## 4. CLI Integration +- [ ] 4.1 Register `serve` command in `src/cli/index.ts`. +- [ ] 4.2 Implement `src/commands/serve.ts` to start the MCP server. + +## 5. Gemini Extension +- [ ] 5.1 Create/Update `gemini-extension.json` to define the extension and point to the MCP server. +- [ ] 5.2 Ensure `GEMINI.md` reflects the new MCP-based architecture. + +## 6. CI Validation +- [ ] 6.1 Create a version sync script (e.g., `scripts/check-extension-version.mjs`) to compare `package.json` and `gemini-extension.json`. +- [ ] 6.2 Add a "Check extension version sync" step to `.github/workflows/ci.yml`. + +## 7. Verification +- [ ] 6.1 Verify `openspec serve` starts and communicates over stdio. +- [ ] 6.2 Verify tools, resources, and prompts are discoverable by an MCP client. +- [ ] 6.3 Verify `openspec init` creates `.openspec/`. \ No newline at end of file diff --git a/openspec/changes/archive/2025-12-21-add-gemini-extension-support/proposal.md b/openspec/changes/archive/2025-12-21-add-gemini-extension-support/proposal.md new file mode 100644 index 00000000..0d29deec --- /dev/null +++ b/openspec/changes/archive/2025-12-21-add-gemini-extension-support/proposal.md @@ -0,0 +1,18 @@ +# Add Gemini CLI Extension Support + +## Goal +Transform the OpenSpec repository into a valid Gemini CLI extension to enhance the development experience for users employing the Gemini CLI. + +## Motivation +Integrating with Gemini CLI allows us to provide deep, project-specific context and potentially custom tools directly to the AI agent. This "eases the integration path" by making the agent "OpenSpec-aware" out of the box when this extension is installed or linked. + +## Proposed Solution +1. **Extension Manifest**: Create a `gemini-extension.json` file in the project root. This file defines the extension metadata and points to the context file. +2. **Context File**: Create a `GEMINI.md` file in the project root. This file will contain high-level instructions, architectural overviews, and usage guides for OpenSpec, tailored for the Gemini agent. It should reference or inline key parts of `AGENTS.md` and `openspec/project.md`. +3. **Unified Prompts**: Extract core slash command prompts into a shared `src/core/templates/prompts.ts` file. This ensures that all agent integrations (Claude, Cursor, Gemini, etc.) use the same underlying instructions. +4. **Native Slash Commands**: Create native Gemini CLI slash command files (`.toml`) in `.gemini/commands/openspec/` that consume the unified prompts. This allows users to trigger OpenSpec workflows directly via `/openspec:proposal`, etc. + +## Benefits +- **Contextual Awareness**: Gemini CLI will automatically understand OpenSpec commands (`openspec init`, `openspec change`, etc.) and conventions without manual prompting. +- **Standardization**: Ensures that the AI assistant follows the project's specific coding and contribution guidelines. +- **Extensibility**: Lay the groundwork for future MCP server integrations (e.g., tools to automatically validate specs or scaffold changes). diff --git a/openspec/changes/archive/2025-12-21-add-gemini-extension-support/specs/cli-init/spec.md b/openspec/changes/archive/2025-12-21-add-gemini-extension-support/specs/cli-init/spec.md new file mode 100644 index 00000000..19f56b87 --- /dev/null +++ b/openspec/changes/archive/2025-12-21-add-gemini-extension-support/specs/cli-init/spec.md @@ -0,0 +1,8 @@ +## ADDED Requirements +### Requirement: Slash Command Safety +All generated slash command templates SHALL include safety guardrails. + +#### Scenario: CLI Availability Check +- **WHEN** generating slash commands for any tool +- **THEN** the template SHALL include an instruction to verify the `openspec` CLI is installed and available in the environment +- **AND** guide the user to install it via `npm install -g @fission-ai/openspec` if missing diff --git a/openspec/changes/archive/2025-12-21-add-gemini-extension-support/tasks.md b/openspec/changes/archive/2025-12-21-add-gemini-extension-support/tasks.md new file mode 100644 index 00000000..e10a8028 --- /dev/null +++ b/openspec/changes/archive/2025-12-21-add-gemini-extension-support/tasks.md @@ -0,0 +1,8 @@ +- [x] Create `gemini-extension.json` in the project root @file:gemini-extension.json +- [x] Create `GEMINI.md` in the project root with OpenSpec context @file:GEMINI.md +- [x] Extract slash command prompts to a shared location for unified usage across agents +- [x] Configure `GEMINI.md` to auto-generate slash commands from shared prompts +- [x] Document CLI installation prerequisites in `GEMINI.md` and shared prompts +- [x] Add maintenance instructions to `GEMINI.md` for syncing slash commands from `prompts.ts` +- [x] Update `README.md` with Gemini CLI Extension installation and benefits +- [x] Verify the extension can be linked locally using `gemini extensions link .` (Manual verification) diff --git a/openspec/specs/cli-init/spec.md b/openspec/specs/cli-init/spec.md index 8f6abd75..eca973a2 100644 --- a/openspec/specs/cli-init/spec.md +++ b/openspec/specs/cli-init/spec.md @@ -309,6 +309,14 @@ The command SHALL support non-interactive operation through command-line options - **AND** preserve any existing content outside the managed markers while replacing the stub text inside them - **AND** create the stub regardless of which native AI tools are selected +### Requirement: Slash Command Safety +All generated slash command templates SHALL include safety guardrails. + +#### Scenario: CLI Availability Check +- **WHEN** generating slash commands for any tool +- **THEN** the template SHALL include an instruction to verify the `openspec` CLI is installed and available in the environment +- **AND** guide the user to install it via `npm install -g @fission-ai/openspec` if missing + ## Why Manual creation of OpenSpec structure is error-prone and creates adoption friction. A standardized init command ensures: diff --git a/src/core/templates/prompts.ts b/src/core/templates/prompts.ts new file mode 100644 index 00000000..d1e82959 --- /dev/null +++ b/src/core/templates/prompts.ts @@ -0,0 +1,51 @@ +const BT = String.fromCharCode(96); + +export const BASE_GUARDRAILS = `**Guardrails** +- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. +- Keep changes tightly scoped to the requested outcome. +- Refer to ${BT}openspec/AGENTS.md${BT} (located inside the ${BT}openspec/${BT} directory—run ${BT}ls openspec${BT} or ${BT}openspec update${BT} if you don't see it) if you need additional OpenSpec conventions or clarifications. +- If the ${BT}openspec${BT} CLI is not installed or available in the shell, guide the user to install it globally via ${BT}npm install -g @fission-ai/openspec${BT} before proceeding.`; + +export const PROPOSAL_GUARDRAILS = `${BASE_GUARDRAILS} +- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files. +- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.`; + +export const PROPOSAL_STEPS = `**Steps** +1. Review ${BT}openspec/project.md${BT}, run ${BT}openspec list${BT} and ${BT}openspec list --specs${BT}, and inspect related code or docs (e.g., via ${BT}rg${BT}/${BT}ls${BT}) to ground the proposal in current behaviour; note any gaps that require clarification. +2. Choose a unique verb-led ${BT}change-id${BT} and scaffold ${BT}proposal.md${BT}, ${BT}tasks.md${BT}, and ${BT}design.md${BT} (when needed) under ${BT}openspec/changes//${BT}. +3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing. +4. Capture architectural reasoning in ${BT}design.md${BT} when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs. +5. Draft spec deltas in ${BT}changes//specs//spec.md${BT} (one folder per capability) using ${BT}## ADDED|MODIFIED|REMOVED Requirements${BT} with at least one ${BT}#### Scenario:${BT} per requirement and cross-reference related capabilities when relevant. +6. Draft ${BT}tasks.md${BT} as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work. +7. Validate with ${BT}openspec validate --strict${BT} and resolve every issue before sharing the proposal.`; + +export const PROPOSAL_REFERENCES = `**Reference** +- Use ${BT}openspec show --json --deltas-only${BT} or ${BT}openspec show --type spec${BT} to inspect details when validation fails. +- Search existing requirements with ${BT}rg -n "Requirement:|Scenario:" openspec/specs${BT} before writing new ones. +- Explore the codebase with ${BT}rg ${BT}, ${BT}ls${BT}, or direct file reads so proposals align with current implementation realities.`; + +export const APPLY_STEPS = `**Steps** +Track these steps as TODOs and complete them one by one. +1. Read ${BT}changes//proposal.md${BT}, ${BT}design.md${BT} (if present), and ${BT}tasks.md${BT} to confirm scope and acceptance criteria. +2. Work through tasks sequentially, keeping edits minimal and focused on the requested change. +3. Confirm completion before updating statuses—make sure every item in ${BT}tasks.md${BT} is finished. +4. Update the checklist after all work is done so each task is marked ${BT}- [x]${BT} and reflects reality. +5. Reference ${BT}openspec list${BT} or ${BT}openspec show ${BT} when additional context is required.`; + +export const APPLY_REFERENCES = `**Reference** +- Use ${BT}openspec show --json --deltas-only${BT} if you need additional context from the proposal while implementing.`; + +export const ARCHIVE_STEPS = `**Steps** +1. Determine the change ID to archive: + - If this prompt already includes a specific change ID (for example inside a ${BT}${BT} block populated by slash-command arguments), use that value after trimming whitespace. + - If the conversation references a change loosely (for example by title or summary), run ${BT}openspec list${BT} to surface likely IDs, share the relevant candidates, and confirm which one the user intends. + - Otherwise, review the conversation, run ${BT}openspec list${BT}, and ask the user which change to archive; wait for a confirmed change ID before proceeding. + - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet. +2. Validate the change ID by running ${BT}openspec list${BT} (or ${BT}openspec show ${BT}) and stop if the change is missing, already archived, or otherwise not ready to archive. +3. Run ${BT}openspec archive --yes${BT} so the CLI moves the change and applies spec updates without prompts (use ${BT}--skip-specs${BT} only for tooling-only work). +4. Review the command output to confirm the target specs were updated and the change landed in ${BT}changes/archive/${BT}. +5. Validate with ${BT}openspec validate --strict${BT} and inspect with ${BT}openspec show ${BT} if anything looks off.`; + +export const ARCHIVE_REFERENCES = `**Reference** +- Use ${BT}openspec list${BT} to confirm change IDs before archiving. +- Inspect refreshed specs with ${BT}openspec list --specs${BT} and address any validation issues before handing off.`; \ No newline at end of file diff --git a/src/core/templates/slash-command-templates.ts b/src/core/templates/slash-command-templates.ts index be21328a..86f247e0 100644 --- a/src/core/templates/slash-command-templates.ts +++ b/src/core/templates/slash-command-templates.ts @@ -1,58 +1,20 @@ -export type SlashCommandId = 'proposal' | 'apply' | 'archive'; - -const baseGuardrails = `**Guardrails** -- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. -- Keep changes tightly scoped to the requested outcome. -- Refer to \`openspec/AGENTS.md\` (located inside the \`openspec/\` directory—run \`ls openspec\` or \`openspec update\` if you don't see it) if you need additional OpenSpec conventions or clarifications.`; - -const proposalGuardrails = `${baseGuardrails}\n- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files. -- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.`; - -const proposalSteps = `**Steps** -1. Review \`openspec/project.md\`, run \`openspec list\` and \`openspec list --specs\`, and inspect related code or docs (e.g., via \`rg\`/\`ls\`) to ground the proposal in current behaviour; note any gaps that require clarification. -2. Choose a unique verb-led \`change-id\` and scaffold \`proposal.md\`, \`tasks.md\`, and \`design.md\` (when needed) under \`openspec/changes//\`. -3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing. -4. Capture architectural reasoning in \`design.md\` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs. -5. Draft spec deltas in \`changes//specs//spec.md\` (one folder per capability) using \`## ADDED|MODIFIED|REMOVED Requirements\` with at least one \`#### Scenario:\` per requirement and cross-reference related capabilities when relevant. -6. Draft \`tasks.md\` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work. -7. Validate with \`openspec validate --strict\` and resolve every issue before sharing the proposal.`; - +import { + PROPOSAL_GUARDRAILS, + PROPOSAL_STEPS, + PROPOSAL_REFERENCES, + BASE_GUARDRAILS, + APPLY_STEPS, + APPLY_REFERENCES, + ARCHIVE_STEPS, + ARCHIVE_REFERENCES +} from './prompts.js'; -const proposalReferences = `**Reference** -- Use \`openspec show --json --deltas-only\` or \`openspec show --type spec\` to inspect details when validation fails. -- Search existing requirements with \`rg -n "Requirement:|Scenario:" openspec/specs\` before writing new ones. -- Explore the codebase with \`rg \`, \`ls\`, or direct file reads so proposals align with current implementation realities.`; - -const applySteps = `**Steps** -Track these steps as TODOs and complete them one by one. -1. Read \`changes//proposal.md\`, \`design.md\` (if present), and \`tasks.md\` to confirm scope and acceptance criteria. -2. Work through tasks sequentially, keeping edits minimal and focused on the requested change. -3. Confirm completion before updating statuses—make sure every item in \`tasks.md\` is finished. -4. Update the checklist after all work is done so each task is marked \`- [x]\` and reflects reality. -5. Reference \`openspec list\` or \`openspec show \` when additional context is required.`; - -const applyReferences = `**Reference** -- Use \`openspec show --json --deltas-only\` if you need additional context from the proposal while implementing.`; - -const archiveSteps = `**Steps** -1. Determine the change ID to archive: - - If this prompt already includes a specific change ID (for example inside a \`\` block populated by slash-command arguments), use that value after trimming whitespace. - - If the conversation references a change loosely (for example by title or summary), run \`openspec list\` to surface likely IDs, share the relevant candidates, and confirm which one the user intends. - - Otherwise, review the conversation, run \`openspec list\`, and ask the user which change to archive; wait for a confirmed change ID before proceeding. - - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet. -2. Validate the change ID by running \`openspec list\` (or \`openspec show \`) and stop if the change is missing, already archived, or otherwise not ready to archive. -3. Run \`openspec archive --yes\` so the CLI moves the change and applies spec updates without prompts (use \`--skip-specs\` only for tooling-only work). -4. Review the command output to confirm the target specs were updated and the change landed in \`changes/archive/\`. -5. Validate with \`openspec validate --strict\` and inspect with \`openspec show \` if anything looks off.`; - -const archiveReferences = `**Reference** -- Use \`openspec list\` to confirm change IDs before archiving. -- Inspect refreshed specs with \`openspec list --specs\` and address any validation issues before handing off.`; +export type SlashCommandId = 'proposal' | 'apply' | 'archive'; export const slashCommandBodies: Record = { - proposal: [proposalGuardrails, proposalSteps, proposalReferences].join('\n\n'), - apply: [baseGuardrails, applySteps, applyReferences].join('\n\n'), - archive: [baseGuardrails, archiveSteps, archiveReferences].join('\n\n') + proposal: [PROPOSAL_GUARDRAILS, PROPOSAL_STEPS, PROPOSAL_REFERENCES].join('\n\n'), + apply: [BASE_GUARDRAILS, APPLY_STEPS, APPLY_REFERENCES].join('\n\n'), + archive: [BASE_GUARDRAILS, ARCHIVE_STEPS, ARCHIVE_REFERENCES].join('\n\n') }; export function getSlashCommandBody(id: SlashCommandId): string {