From fbdb4db2dc6d46578fcd78781915699b7463669f Mon Sep 17 00:00:00 2001 From: Clay Good Date: Mon, 19 Oct 2026 14:55:52 -0500 Subject: [PATCH 1/4] chore(openspec): refresh 4 stale change deltas and archive them Rebase each change's MODIFIED blocks onto the current main specs, keeping scenarios and wording that landed after the change was written, then archive. Archived in the order the changes shipped, so each block builds on the ones before it. Part of the Loft study follow-up (OPE-58). Co-Authored-By: Claude Opus 5.5 --- .../.openspec.yaml | 0 .../proposal.md | 0 .../specs/ai-tool-paths/spec.md | 46 +++++-- .../specs/cli-init/spec.md | 13 ++ .../specs/cli-update/spec.md | 12 +- .../specs/command-generation/spec.md | 12 +- .../tasks.md | 0 .../proposal.md | 0 .../specs/cli-init/spec.md | 0 .../specs/command-generation/spec.md | 13 ++ .../tasks.md | 0 .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/command-generation/spec.md | 6 + .../tasks.md | 0 .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/ai-tool-paths/spec.md | 0 .../specs/cli-init/spec.md | 0 .../specs/cli-update/spec.md | 14 +- .../specs/command-generation/spec.md | 16 ++- .../tasks.md | 0 openspec/specs/ai-tool-paths/spec.md | 130 ++++++++++++++++++ openspec/specs/cli-init/spec.md | 86 ++++++++++++ openspec/specs/cli-update/spec.md | 88 +++++++++++- openspec/specs/command-generation/spec.md | 72 +++++++++- 28 files changed, 470 insertions(+), 38 deletions(-) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/.openspec.yaml (100%) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/proposal.md (100%) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/specs/ai-tool-paths/spec.md (83%) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/specs/cli-init/spec.md (80%) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/specs/cli-update/spec.md (90%) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/specs/command-generation/spec.md (70%) rename openspec/changes/{add-devin-desktop-support => archive/2026-10-19-add-devin-desktop-support}/tasks.md (100%) rename openspec/changes/{add-skill-cli-auto-approval => archive/2026-10-19-add-skill-cli-auto-approval}/proposal.md (100%) rename openspec/changes/{add-skill-cli-auto-approval => archive/2026-10-19-add-skill-cli-auto-approval}/specs/cli-init/spec.md (100%) rename openspec/changes/{add-skill-cli-auto-approval => archive/2026-10-19-add-skill-cli-auto-approval}/specs/command-generation/spec.md (69%) rename openspec/changes/{add-skill-cli-auto-approval => archive/2026-10-19-add-skill-cli-auto-approval}/tasks.md (100%) rename openspec/changes/{fix-opencode-commands-directory => archive/2026-10-19-fix-opencode-commands-directory}/.openspec.yaml (100%) rename openspec/changes/{fix-opencode-commands-directory => archive/2026-10-19-fix-opencode-commands-directory}/design.md (100%) rename openspec/changes/{fix-opencode-commands-directory => archive/2026-10-19-fix-opencode-commands-directory}/proposal.md (100%) rename openspec/changes/{fix-opencode-commands-directory => archive/2026-10-19-fix-opencode-commands-directory}/specs/command-generation/spec.md (93%) rename openspec/changes/{fix-opencode-commands-directory => archive/2026-10-19-fix-opencode-commands-directory}/tasks.md (100%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/.openspec.yaml (100%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/design.md (100%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/proposal.md (100%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/specs/ai-tool-paths/spec.md (100%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/specs/cli-init/spec.md (100%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/specs/cli-update/spec.md (90%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/specs/command-generation/spec.md (75%) rename openspec/changes/{make-codex-skills-only => archive/2026-10-19-make-codex-skills-only}/tasks.md (100%) diff --git a/openspec/changes/add-devin-desktop-support/.openspec.yaml b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/.openspec.yaml similarity index 100% rename from openspec/changes/add-devin-desktop-support/.openspec.yaml rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/.openspec.yaml diff --git a/openspec/changes/add-devin-desktop-support/proposal.md b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/proposal.md similarity index 100% rename from openspec/changes/add-devin-desktop-support/proposal.md rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/proposal.md diff --git a/openspec/changes/add-devin-desktop-support/specs/ai-tool-paths/spec.md b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/ai-tool-paths/spec.md similarity index 83% rename from openspec/changes/add-devin-desktop-support/specs/ai-tool-paths/spec.md rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/ai-tool-paths/spec.md index 9829f48533..6b9b0d4a4d 100644 --- a/openspec/changes/add-devin-desktop-support/specs/ai-tool-paths/spec.md +++ b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/ai-tool-paths/spec.md @@ -98,12 +98,18 @@ The `AI_TOOLS` array SHALL include `skillsDir` for tools that support the Agent - **WHEN** looking up the `cursor` tool - **THEN** `skillsDir` SHALL be `.cursor` -#### Scenario: Windsurf paths defined +#### Scenario: Devin Desktop paths defined + +- **WHEN** looking up the `devin` tool +- **THEN** `skillsDir` SHALL be `.devin` +- **AND** workflow files SHALL be written to `.devin/workflows/opsx-.md` +- **AND** `detectionPaths` SHALL include both `.devin` and the legacy `.windsurf`, so a project set up before the rebrand is still recognized -- **GIVEN** RETIRED — Windsurf was rebranded to Devin Desktop and `windsurf` is no longer a tool id -- **WHEN** looking up the `windsurf` tool -- **THEN** no `AI_TOOLS` entry SHALL exist for it -- **AND** the id SHALL resolve to `devin`, whose `skillsDir` is `.devin` and whose `detectionPaths` still include the legacy `.windsurf` +#### Scenario: Legacy Windsurf tool ID + +- **WHEN** initializing with `openspec init --tools windsurf` +- **THEN** the `windsurf` alias SHALL resolve to `devin` +- **AND** when skill delivery is enabled, skills SHALL be generated under `.devin/skills/`, not `.windsurf/skills/` #### Scenario: Kimi Code paths defined @@ -118,18 +124,30 @@ The `AI_TOOLS` array SHALL include `skillsDir` for tools that support the Agent - **AND** `setupNote` SHALL explain that project `.hermes/skills` must be added to `skills.external_dirs` in `~/.hermes/config.yaml` - **AND** `openspec init` and `openspec update` SHALL display the note whenever `hermes` is configured -#### Scenario: Devin Desktop paths defined +#### Scenario: DeepSeek Harness paths defined -- **WHEN** looking up the `devin` tool -- **THEN** `skillsDir` SHALL be `.devin` -- **AND** workflow files SHALL be written to `.devin/workflows/opsx-.md` -- **AND** `detectionPaths` SHALL include both `.devin` and the legacy `.windsurf`, so a project set up before the rebrand is still recognized +- **WHEN** looking up the `dsh` tool +- **THEN** `skillsDir` SHALL be `.dsh` +- **AND** auto-detection SHALL require `.dsh` to be a directory +- **AND** OpenSpec SHALL write dsh skills under `/.dsh/skills/` using platform-native path joining + +#### Scenario: Grok Build paths defined + +- **WHEN** looking up the `grok` tool +- **THEN** `skillsDir` SHALL be `.grok` + +#### Scenario: Warp paths and detection defined + +- **WHEN** looking up the `warp` tool +- **THEN** `skillsDir` SHALL be `.warp` +- **AND** `detectionPaths` SHALL include `.warp` and `WARP.md` -#### Scenario: Retired tool ids resolve on the command line +#### Scenario: Warp invokes skills without command files -- **WHEN** a retired brand is named on the command line, such as `--tools windsurf` -- **THEN** it SHALL resolve to the current tool id `devin` rather than erroring as unknown -- **AND** generation SHALL write the current directory `.devin/`, not the retired one +- **WHEN** generating workflows for the `warp` tool with delivery set to `commands` +- **THEN** skills SHALL remain installed in `.warp/skills/` +- **AND** no command adapter or command files SHALL be required +- **AND** each skill SHALL be directly invocable by its `/openspec-*` name #### Scenario: Tools without skillsDir diff --git a/openspec/changes/add-devin-desktop-support/specs/cli-init/spec.md b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/cli-init/spec.md similarity index 80% rename from openspec/changes/add-devin-desktop-support/specs/cli-init/spec.md rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/cli-init/spec.md index 2b23f76af0..6dcfab3d5c 100644 --- a/openspec/changes/add-devin-desktop-support/specs/cli-init/spec.md +++ b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/cli-init/spec.md @@ -22,6 +22,13 @@ The command SHALL generate Agent Skills for selected AI tools. - **AND** each SKILL.md SHALL contain YAML frontmatter with name and description - **AND** each SKILL.md SHALL contain the skill instructions +#### Scenario: Pre-approving the OpenSpec CLI in skill frontmatter + +- **WHEN** generating a skill's YAML frontmatter +- **THEN** the frontmatter SHALL include an `allowed-tools` field with the value `Bash(openspec:*)` +- **AND** an agent that honors `allowed-tools` SHALL run `openspec` commands from the skill without prompting for approval +- **AND** because `allowed-tools` pre-approves rather than restricts, any other tool the skill uses SHALL remain available under the user's existing permission settings + #### Scenario: Devin skills reference skills rather than workflows - **GIVEN** the Devin Local agent does not support workflows and its documentation directs users to skills instead @@ -64,6 +71,12 @@ The command SHALL generate opsx slash commands only for selected tools that have - **THEN** OpenSpec SHALL treat it as a supported tool with `skillsDir: '.kimi-code'` - **AND** command-file generation SHALL be skipped because no Kimi adapter is registered +#### Scenario: Grok Build skips command-file generation + +- **WHEN** the user selects Grok Build during initialization +- **THEN** OpenSpec SHALL treat it as a supported tool with `skillsDir: '.grok'` +- **AND** command-file generation SHALL be skipped because no Grok adapter is registered + #### Scenario: Generating workflows for Devin Desktop - **WHEN** the user selects Devin Desktop during initialization diff --git a/openspec/changes/add-devin-desktop-support/specs/cli-update/spec.md b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/cli-update/spec.md similarity index 90% rename from openspec/changes/add-devin-desktop-support/specs/cli-update/spec.md rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/cli-update/spec.md index d8227b28e2..04d35c6c43 100644 --- a/openspec/changes/add-devin-desktop-support/specs/cli-update/spec.md +++ b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/cli-update/spec.md @@ -4,7 +4,7 @@ ### Requirement: Slash Command Updates -The update command SHALL refresh existing slash command files for configured tools without creating new ones, and ensure the OpenCode archive command accepts change ID arguments. +The update command SHALL refresh existing slash command files for configured adapter-backed tools without creating new ones, keep legacy command cleanup safe, treat Codex custom prompts as legacy artifacts that are cleaned up rather than refreshed, and ensure the OpenCode archive command accepts change ID arguments. #### Scenario: Updating slash commands for Antigravity - **WHEN** `.agent/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` @@ -77,17 +77,17 @@ The update command SHALL refresh existing slash command files for configured too - **AND** refresh `.devin/skills/openspec-*/SKILL.md` with `/openspec-*` skill references, the one invocation both Devin agents accept #### Scenario: Updating slash commands for Kilo Code -- **WHEN** `.kilocode/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` +- **WHEN** `.kilo/command/` contains OpenSpec-managed `opsx-*.md` command files for the configured profile - **THEN** refresh each file using shared templates wrapped in OpenSpec markers - **AND** ensure templates include instructions for the relevant workflow stage - **AND** skip creating missing files (the update command only refreshes what already exists) #### Scenario: Updating slash commands for Codex -- **GIVEN** the global Codex prompt directory contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` +- **GIVEN** the global Codex prompt directory contains OpenSpec-managed Codex prompt files - **WHEN** a user runs `openspec update` -- **THEN** refresh each file using the shared slash-command templates (including placeholder guidance) -- **AND** preserve any unmanaged content outside the OpenSpec marker block -- **AND** skip creation when a Codex prompt file is missing +- **THEN** the command SHALL NOT refresh Codex prompt files +- **AND** it SHALL treat those files as legacy cleanup candidates +- **AND** it SHALL preserve unmanaged files by deleting only exact allowlisted OpenSpec-owned filenames under the resolved global Codex prompt directory after replacement skills exist #### Scenario: Updating slash commands for GitHub Copilot - **WHEN** `.github/prompts/` contains `openspec-proposal.prompt.md`, `openspec-apply.prompt.md`, and `openspec-archive.prompt.md` diff --git a/openspec/changes/add-devin-desktop-support/specs/command-generation/spec.md b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/command-generation/spec.md similarity index 70% rename from openspec/changes/add-devin-desktop-support/specs/command-generation/spec.md rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/command-generation/spec.md index 07ba141aba..5c0c1a5f93 100644 --- a/openspec/changes/add-devin-desktop-support/specs/command-generation/spec.md +++ b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/specs/command-generation/spec.md @@ -11,13 +11,14 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **WHEN** implementing a tool adapter - **THEN** `ToolCommandAdapter` SHALL require: - `toolId`: string identifier matching `AIToolOption.value` - - `getFilePath(commandId: string)`: returns file path for command (relative from project root, or absolute for global-scoped tools like Codex) + - `getFilePath(commandId: string)`: returns file path for command relative from project root unless a supported scoped install resolver provides an absolute target for that adapter - `formatFile(content: CommandContent)`: returns complete file content with frontmatter #### Scenario: Claude adapter formatting - **WHEN** formatting a command for Claude Code -- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields +- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `allowed-tools`, `category`, `tags` fields +- **AND** the `allowed-tools` field SHALL have the value `Bash(openspec:*)` so Claude Code runs `openspec` commands from the slash command without prompting for approval - **AND** file path SHALL follow pattern `.claude/commands/opsx/.md` #### Scenario: Cursor adapter formatting @@ -43,3 +44,10 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **WHEN** formatting a command for Trae - **THEN** the adapter SHALL output YAML frontmatter with `name` and `description` fields - **AND** file path SHALL follow pattern `.trae/commands/opsx-.md` + +#### Scenario: OpenCode adapter formatting + +- **WHEN** formatting a command for OpenCode +- **THEN** the adapter SHALL output YAML frontmatter with `description` field +- **AND** file path SHALL follow pattern `.opencode/commands/opsx-.md` using `path.join('.opencode', 'commands', ...)` for cross-platform compatibility +- **AND** the adapter SHALL transform colon-based command references (`/opsx:name`) to hyphen-based (`/opsx-name`) in the body diff --git a/openspec/changes/add-devin-desktop-support/tasks.md b/openspec/changes/archive/2026-10-19-add-devin-desktop-support/tasks.md similarity index 100% rename from openspec/changes/add-devin-desktop-support/tasks.md rename to openspec/changes/archive/2026-10-19-add-devin-desktop-support/tasks.md diff --git a/openspec/changes/add-skill-cli-auto-approval/proposal.md b/openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/proposal.md similarity index 100% rename from openspec/changes/add-skill-cli-auto-approval/proposal.md rename to openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/proposal.md diff --git a/openspec/changes/add-skill-cli-auto-approval/specs/cli-init/spec.md b/openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/specs/cli-init/spec.md similarity index 100% rename from openspec/changes/add-skill-cli-auto-approval/specs/cli-init/spec.md rename to openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/specs/cli-init/spec.md diff --git a/openspec/changes/add-skill-cli-auto-approval/specs/command-generation/spec.md b/openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/specs/command-generation/spec.md similarity index 69% rename from openspec/changes/add-skill-cli-auto-approval/specs/command-generation/spec.md rename to openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/specs/command-generation/spec.md index d593b38fa3..9ee5a90023 100644 --- a/openspec/changes/add-skill-cli-auto-approval/specs/command-generation/spec.md +++ b/openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/specs/command-generation/spec.md @@ -30,3 +30,16 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **WHEN** formatting a command for Windsurf - **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields - **AND** file path SHALL follow pattern `.windsurf/workflows/opsx-.md` + +#### Scenario: Trae adapter formatting + +- **WHEN** formatting a command for Trae +- **THEN** the adapter SHALL output YAML frontmatter with `name` and `description` fields +- **AND** file path SHALL follow pattern `.trae/commands/opsx-.md` + +#### Scenario: OpenCode adapter formatting + +- **WHEN** formatting a command for OpenCode +- **THEN** the adapter SHALL output YAML frontmatter with `description` field +- **AND** file path SHALL follow pattern `.opencode/commands/opsx-.md` using `path.join('.opencode', 'commands', ...)` for cross-platform compatibility +- **AND** the adapter SHALL transform colon-based command references (`/opsx:name`) to hyphen-based (`/opsx-name`) in the body diff --git a/openspec/changes/add-skill-cli-auto-approval/tasks.md b/openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/tasks.md similarity index 100% rename from openspec/changes/add-skill-cli-auto-approval/tasks.md rename to openspec/changes/archive/2026-10-19-add-skill-cli-auto-approval/tasks.md diff --git a/openspec/changes/fix-opencode-commands-directory/.openspec.yaml b/openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/.openspec.yaml similarity index 100% rename from openspec/changes/fix-opencode-commands-directory/.openspec.yaml rename to openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/.openspec.yaml diff --git a/openspec/changes/fix-opencode-commands-directory/design.md b/openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/design.md similarity index 100% rename from openspec/changes/fix-opencode-commands-directory/design.md rename to openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/design.md diff --git a/openspec/changes/fix-opencode-commands-directory/proposal.md b/openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/proposal.md similarity index 100% rename from openspec/changes/fix-opencode-commands-directory/proposal.md rename to openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/proposal.md diff --git a/openspec/changes/fix-opencode-commands-directory/specs/command-generation/spec.md b/openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/specs/command-generation/spec.md similarity index 93% rename from openspec/changes/fix-opencode-commands-directory/specs/command-generation/spec.md rename to openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/specs/command-generation/spec.md index f00cb3ce8d..3109996be3 100644 --- a/openspec/changes/fix-opencode-commands-directory/specs/command-generation/spec.md +++ b/openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/specs/command-generation/spec.md @@ -30,6 +30,12 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields - **AND** file path SHALL follow pattern `.windsurf/workflows/opsx-.md` +#### Scenario: Trae adapter formatting + +- **WHEN** formatting a command for Trae +- **THEN** the adapter SHALL output YAML frontmatter with `name` and `description` fields +- **AND** file path SHALL follow pattern `.trae/commands/opsx-.md` + #### Scenario: OpenCode adapter formatting - **WHEN** formatting a command for OpenCode diff --git a/openspec/changes/fix-opencode-commands-directory/tasks.md b/openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/tasks.md similarity index 100% rename from openspec/changes/fix-opencode-commands-directory/tasks.md rename to openspec/changes/archive/2026-10-19-fix-opencode-commands-directory/tasks.md diff --git a/openspec/changes/make-codex-skills-only/.openspec.yaml b/openspec/changes/archive/2026-10-19-make-codex-skills-only/.openspec.yaml similarity index 100% rename from openspec/changes/make-codex-skills-only/.openspec.yaml rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/.openspec.yaml diff --git a/openspec/changes/make-codex-skills-only/design.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/design.md similarity index 100% rename from openspec/changes/make-codex-skills-only/design.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/design.md diff --git a/openspec/changes/make-codex-skills-only/proposal.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/proposal.md similarity index 100% rename from openspec/changes/make-codex-skills-only/proposal.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/proposal.md diff --git a/openspec/changes/make-codex-skills-only/specs/ai-tool-paths/spec.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/ai-tool-paths/spec.md similarity index 100% rename from openspec/changes/make-codex-skills-only/specs/ai-tool-paths/spec.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/ai-tool-paths/spec.md diff --git a/openspec/changes/make-codex-skills-only/specs/cli-init/spec.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/cli-init/spec.md similarity index 100% rename from openspec/changes/make-codex-skills-only/specs/cli-init/spec.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/cli-init/spec.md diff --git a/openspec/changes/make-codex-skills-only/specs/cli-update/spec.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/cli-update/spec.md similarity index 90% rename from openspec/changes/make-codex-skills-only/specs/cli-update/spec.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/cli-update/spec.md index 4eae91011f..18f18e8ba2 100644 --- a/openspec/changes/make-codex-skills-only/specs/cli-update/spec.md +++ b/openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/cli-update/spec.md @@ -2,7 +2,7 @@ ### Requirement: Slash Command Updates -The update command SHALL refresh existing slash command files for configured adapter-backed tools without creating new ones, keep legacy command cleanup safe, and treat Codex custom prompts as legacy artifacts that are cleaned up rather than refreshed. +The update command SHALL refresh existing slash command files for configured adapter-backed tools without creating new ones, keep legacy command cleanup safe, treat Codex custom prompts as legacy artifacts that are cleaned up rather than refreshed, and ensure the OpenCode archive command accepts change ID arguments. #### Scenario: Updating slash commands for Antigravity - **WHEN** `.agent/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` @@ -50,11 +50,17 @@ The update command SHALL refresh existing slash command files for configured ada - **AND** skip creating missing files during update #### Scenario: Updating slash commands for OpenCode -- **WHEN** `.opencode/command/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` +- **WHEN** `.opencode/commands/` contains OpenSpec-managed `opsx-*.md` command files for the configured profile (for example `opsx-propose.md`, `opsx-apply.md`, and `opsx-archive.md`) - **THEN** refresh each file using shared templates +- **AND** transform command references to hyphen form (for example `/opsx-propose`), as for every tool whose command files are named `opsx-` - **AND** ensure templates include instructions for the relevant workflow stage - **AND** ensure the archive command includes `$ARGUMENTS` placeholder in frontmatter for accepting change ID arguments +#### Scenario: Legacy OpenCode command path cleanup +- **WHEN** a project still has command files under the legacy singular path `.opencode/command/` (for example `opsx-*.md` or `openspec-*.md`) +- **THEN** `openspec init` or legacy cleanup SHALL remove those files and generate replacements under `.opencode/commands/` +- **AND** `openspec update` SHALL NOT refresh files that remain only under `.opencode/command/` + #### Scenario: Updating slash commands for Windsurf - **WHEN** `.windsurf/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` - **THEN** refresh each file using shared templates wrapped in OpenSpec markers @@ -62,12 +68,12 @@ The update command SHALL refresh existing slash command files for configured ada - **AND** skip creating missing files (the update command only refreshes what already exists) #### Scenario: Updating slash commands for Kilo Code -- **WHEN** `.kilocode/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` +- **WHEN** `.kilo/command/` contains OpenSpec-managed `opsx-*.md` command files for the configured profile - **THEN** refresh each file using shared templates wrapped in OpenSpec markers - **AND** ensure templates include instructions for the relevant workflow stage - **AND** skip creating missing files (the update command only refreshes what already exists) -#### Scenario: Codex prompt files are not refreshed +#### Scenario: Updating slash commands for Codex - **GIVEN** the global Codex prompt directory contains OpenSpec-managed Codex prompt files - **WHEN** a user runs `openspec update` - **THEN** the command SHALL NOT refresh Codex prompt files diff --git a/openspec/changes/make-codex-skills-only/specs/command-generation/spec.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/command-generation/spec.md similarity index 75% rename from openspec/changes/make-codex-skills-only/specs/command-generation/spec.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/command-generation/spec.md index e4d0c10db8..38f33fc783 100644 --- a/openspec/changes/make-codex-skills-only/specs/command-generation/spec.md +++ b/openspec/changes/archive/2026-10-19-make-codex-skills-only/specs/command-generation/spec.md @@ -15,7 +15,8 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting #### Scenario: Claude adapter formatting - **WHEN** formatting a command for Claude Code -- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields +- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `allowed-tools`, `category`, `tags` fields +- **AND** the `allowed-tools` field SHALL have the value `Bash(openspec:*)` so Claude Code runs `openspec` commands from the slash command without prompting for approval - **AND** file path SHALL follow pattern `.claude/commands/opsx/.md` #### Scenario: Cursor adapter formatting @@ -30,6 +31,19 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields - **AND** file path SHALL follow pattern `.windsurf/workflows/opsx-.md` +#### Scenario: Trae adapter formatting + +- **WHEN** formatting a command for Trae +- **THEN** the adapter SHALL output YAML frontmatter with `name` and `description` fields +- **AND** file path SHALL follow pattern `.trae/commands/opsx-.md` + +#### Scenario: OpenCode adapter formatting + +- **WHEN** formatting a command for OpenCode +- **THEN** the adapter SHALL output YAML frontmatter with `description` field +- **AND** file path SHALL follow pattern `.opencode/commands/opsx-.md` using `path.join('.opencode', 'commands', ...)` for cross-platform compatibility +- **AND** the adapter SHALL transform colon-based command references (`/opsx:name`) to hyphen-based (`/opsx-name`) in the body + ## ADDED Requirements ### Requirement: Codex is not a command generation target diff --git a/openspec/changes/make-codex-skills-only/tasks.md b/openspec/changes/archive/2026-10-19-make-codex-skills-only/tasks.md similarity index 100% rename from openspec/changes/make-codex-skills-only/tasks.md rename to openspec/changes/archive/2026-10-19-make-codex-skills-only/tasks.md diff --git a/openspec/specs/ai-tool-paths/spec.md b/openspec/specs/ai-tool-paths/spec.md index 4216c4cf4d..54d6d7e3b7 100644 --- a/openspec/specs/ai-tool-paths/spec.md +++ b/openspec/specs/ai-tool-paths/spec.md @@ -38,6 +38,8 @@ The `AI_TOOLS` array SHALL include `skillsDir` for tools that support the Agent - **WHEN** looking up the `devin` tool - **THEN** `skillsDir` SHALL be `.devin` +- **AND** workflow files SHALL be written to `.devin/workflows/opsx-.md` +- **AND** `detectionPaths` SHALL include both `.devin` and the legacy `.windsurf`, so a project set up before the rebrand is still recognized #### Scenario: Legacy Windsurf tool ID @@ -160,3 +162,131 @@ OpenSpec SHALL provide a vendor-neutral `agents` tool target rooted at the share - **GIVEN** a project contains `.agents` but no `.agents/skills` path - **WHEN** OpenSpec detects available tools - **THEN** `agents` SHALL NOT be reported as available + +### Requirement: Codex skills path is the supported Codex integration path +The system SHALL identify `.codex/skills/` as the supported Codex OpenSpec workflow path. + +#### Scenario: Codex skills path defined +- **WHEN** looking up the `codex` tool +- **THEN** the system SHALL provide `.codex` as the Codex skills base directory +- **AND** generated Codex skills SHALL be written under `/.codex/skills/` + +#### Scenario: Codex command path is not advertised as supported +- **WHEN** displaying AI tool path documentation or command-generation metadata +- **THEN** the system SHALL present Codex as a skills-only OpenSpec integration +- **AND** it SHALL NOT advertise `$CODEX_HOME/prompts/opsx-.md` as a generated Codex command path + +### Requirement: Codex global prompt cleanup path resolution +The system SHALL resolve the legacy Codex prompt cleanup directory using Codex home semantics. + +#### Scenario: CODEX_HOME is set +- **WHEN** cleaning up previously managed Codex prompt files +- **AND** `CODEX_HOME` is set +- **THEN** the system SHALL inspect the `prompts` directory under the resolved `CODEX_HOME` path + +#### Scenario: CODEX_HOME is unset +- **WHEN** cleaning up previously managed Codex prompt files +- **AND** `CODEX_HOME` is not set +- **THEN** the system SHALL inspect the `prompts` directory under the user's default `.codex` home + +#### Scenario: Cross-platform Codex prompt paths +- **WHEN** resolving Codex skills or legacy prompt cleanup paths on Windows, macOS, or Linux +- **THEN** the system SHALL construct paths with platform path utilities +- **AND** it SHALL preserve correct path separators for the current operating system + +### Requirement: Codex-managed legacy prompt cleanup patterns reflect the final managed surfaces +The system SHALL identify managed Codex prompt cleanup targets using the final split patterns for global and repo-local artifacts. + +#### Scenario: Global legacy Codex prompts use an exact directory and filename allowlist +- **WHEN** detecting managed legacy Codex prompt files in the resolved Codex prompt directory +- **THEN** the system SHALL match only exact historical OpenSpec-owned filenames directly under that resolved directory +- **AND** it SHALL infer the represented workflow IDs from those filenames +- **AND** the allowlist SHALL include `opsx-update.md` mapped to the `update` workflow + +#### Scenario: Repo-local openspec compatibility prompt names +- **WHEN** detecting legacy Codex prompt files in the project tree +- **THEN** the system SHALL match repo-local files named `.codex/prompts/openspec-*.md` + +#### Scenario: Other Codex prompts are unmanaged +- **WHEN** a Codex prompt file does not match the managed pattern for its scope +- **THEN** cleanup SHALL leave that file unchanged + +### Requirement: Migrating OpenSpec content out of a renamed tool's former directory + +When a tool's directory is renamed, OpenSpec-managed content left in the former +location SHALL be moved to the current one. Content the user wrote SHALL never +be moved or deleted. + +Some renames are safe to apply silently and some are not, so each former root +declares whether leaving it needs the user's consent. Kimi CLI is gone, so +`.kimi` can be vacated without asking. Windsurf's `.windsurf` cannot: a +pre-rebrand Windsurf build reads only that directory, and nothing on disk +distinguishes that user from one who took the rebrand. + +#### Scenario: Moving a former directory that needs no consent + +- **WHEN** `openspec init` or `openspec update` runs and OpenSpec-managed content is found under a former root marked as needing no consent, such as `.kimi` +- **THEN** move it to the tool's current directory without prompting +- **AND** report what moved + +#### Scenario: Offering a move that needs consent + +- **GIVEN** OpenSpec skills or command files under `.windsurf/` +- **WHEN** `openspec update` runs interactively without `--force` +- **THEN** explain that Windsurf is now Devin Desktop, that `.devin/` is the current directory, and that Devin Local does not read `.windsurf/` at all +- **AND** ask before moving anything +- **AND** on decline, leave every file untouched and state that `.windsurf/` will no longer be refreshed until it is moved + +#### Scenario: Unattended runs take the move + +- **WHEN** `openspec update` runs with `--force`, or non-interactively +- **THEN** perform the move without prompting, reporting what moved + +#### Scenario: Selecting a renamed tool is consent + +- **WHEN** `openspec init` configures a tool that has OpenSpec content under a former root +- **THEN** move that content as part of setup, rather than leaving the user with two installs of one tool + +#### Scenario: Both directories already hold OpenSpec content + +- **GIVEN** the same OpenSpec-managed skill or command exists under both the former and the current root +- **WHEN** the move runs +- **THEN** the copy under the current root SHALL win, rather than being merged or overwritten +- **AND** only the file OpenSpec generated SHALL be removed from the former root — for a skill directory that is `SKILL.md` alone, never the directory and whatever else it holds +- **AND** one rule SHALL govern skills and command files alike: the former copy SHALL be removed only when it is byte-identical to the surviving one +- **AND** a former copy that differs SHALL be left where it is, since the difference may be a customization +- **AND** files left behind for that reason SHALL be reported, so the user knows two copies now exist + +#### Scenario: Every former file differs, so nothing is movable + +- **GIVEN** every OpenSpec-managed file under the former root differs from its counterpart under the current one +- **WHEN** the move runs +- **THEN** report the files left in place, rather than staying silent because nothing moved +- **AND** NOT offer to move anything, since there is nothing movable to consent to +- **AND** NOT report a migration that did not happen + +#### Scenario: One root is a symbolic link to the other + +- **GIVEN** the former and current roots resolve to the same directory, as when a user symlinks one at the other to straddle the rename +- **WHEN** the move runs +- **THEN** recognize that source and destination are the same file and change nothing, rather than deleting the only copy + +#### Scenario: User files survive the move + +- **GIVEN** a former root also holds files the user wrote, such as a hand-written workflow beside the generated ones +- **WHEN** the move runs +- **THEN** move only the files OpenSpec generates — each skill's `SKILL.md` and command files named `opsx-*` +- **AND** delete the former directory only when the move leaves it empty + +#### Scenario: A user file beside a generated skill is not carried into a directory OpenSpec prunes + +- **GIVEN** a former skill directory holds `SKILL.md` alongside a file the user wrote +- **AND** OpenSpec removes whole skill directories it owns, as under commands-only delivery or for a workflow outside the active profile +- **WHEN** the move runs +- **THEN** move `SKILL.md` alone and leave the user's file under the former root +- **AND** never move the enclosing directory, which would hand that file to a later removal + +#### Scenario: The move is idempotent + +- **WHEN** `openspec update` runs again after a completed move +- **THEN** find nothing to migrate and report nothing diff --git a/openspec/specs/cli-init/spec.md b/openspec/specs/cli-init/spec.md index 058326c6ec..9353cfa4d0 100644 --- a/openspec/specs/cli-init/spec.md +++ b/openspec/specs/cli-init/spec.md @@ -199,6 +199,21 @@ The command SHALL generate Agent Skills for selected AI tools. - **AND** each SKILL.md SHALL contain YAML frontmatter with name and description - **AND** each SKILL.md SHALL contain the skill instructions +#### Scenario: Pre-approving the OpenSpec CLI in skill frontmatter + +- **WHEN** generating a skill's YAML frontmatter +- **THEN** the frontmatter SHALL include an `allowed-tools` field with the value `Bash(openspec:*)` +- **AND** an agent that honors `allowed-tools` SHALL run `openspec` commands from the skill without prompting for approval +- **AND** because `allowed-tools` pre-approves rather than restricts, any other tool the skill uses SHALL remain available under the user's existing permission settings + +#### Scenario: Devin skills reference skills rather than workflows + +- **GIVEN** the Devin Local agent does not support workflows and its documentation directs users to skills instead +- **WHEN** generating skills for the `devin` tool +- **THEN** rewrite `/opsx:` references in the skill body to the matching `/openspec-` invocation, which both Devin agents accept +- **AND** the getting-started hint SHALL name `/openspec-propose` rather than a workflow +- **AND** under commands-only delivery, where no Devin skills are written, both the workflow bodies and the hint SHALL fall back to `/opsx-` + ### Requirement: Slash Command Generation The command SHALL generate opsx slash commands only for selected tools that have a registered command adapter, while keeping adapterless tools valid for skill generation. @@ -239,6 +254,13 @@ The command SHALL generate opsx slash commands only for selected tools that have - **THEN** OpenSpec SHALL treat it as a supported tool with `skillsDir: '.grok'` - **AND** command-file generation SHALL be skipped because no Grok adapter is registered +#### Scenario: Generating workflows for Devin Desktop + +- **WHEN** the user selects Devin Desktop during initialization +- **THEN** create one workflow file per profile workflow at `.devin/workflows/opsx-.md` +- **AND** include frontmatter with `name`, `description`, `category`, and `tags` +- **AND** rewrite `/opsx:` references in the body to `/opsx-`, the name Devin registers for a workflow file + ### Requirement: Config File Generation The command SHALL create an OpenSpec config file with schema settings. @@ -327,6 +349,70 @@ The `openspec init` command SHALL support Oh My Pi as a configurable tool, gener - **THEN** command-file generation SHALL be skipped because no `agents` adapter is registered - **AND** `agents` SHALL be listed among the tools reported as having commands skipped +### Requirement: Codex initialization uses the skills-invocable command surface +`openspec init` SHALL treat Codex as a skills-invocable tool, not as an adapter-backed command-file tool. + +#### Scenario: Codex command surface resolution +- **WHEN** a user runs `openspec init` and selects Codex +- **THEN** the command SHALL resolve Codex command surface capability as `skills-invocable` +- **AND** it SHALL apply delivery behavior through the shared command-surface capability model when that model is available +- **AND** it SHALL NOT use a Codex-specific delivery predicate that duplicates command-surface capability rules + +### Requirement: Codex initialization uses skills only +`openspec init` SHALL configure Codex through generated OpenSpec skills without generating Codex custom prompt files. + +#### Scenario: Initializing Codex with default delivery +- **WHEN** a user runs `openspec init` and selects Codex +- **AND** the active delivery mode is `both` +- **THEN** the command SHALL create the selected OpenSpec skill files under `.codex/skills/` +- **AND** it SHALL NOT create Codex prompt files under `$CODEX_HOME/prompts` or the default Codex prompt directory + +#### Scenario: Initializing Codex with skills delivery +- **WHEN** a user runs `openspec init` and selects Codex +- **AND** the active delivery mode is `skills` +- **THEN** the command SHALL create the selected OpenSpec skill files under `.codex/skills/` +- **AND** it SHALL NOT create Codex prompt files + +#### Scenario: Initializing Codex with commands delivery +- **WHEN** a user runs `openspec init` and selects Codex +- **AND** the active delivery mode is `commands` +- **THEN** the command SHALL still create the selected OpenSpec skill files under `.codex/skills/` +- **AND** it SHALL skip Codex command-file generation because Codex is `skills-invocable` + +### Requirement: Codex initialization cleanup removes managed legacy prompts +`openspec init` SHALL remove previously managed global Codex prompt files only after replacement Codex skills exist, without deleting user-authored Codex prompts. + +#### Scenario: Cleanup removes allowlisted global Codex prompt files after replacement exists +- **WHEN** initialization cleanup runs +- **AND** the Codex prompt directory contains exact allowlisted managed global Codex prompt files +- **AND** replacement Codex skills exist for the workflows represented by those prompt filenames +- **THEN** the command SHALL remove those managed Codex prompt files +- **AND** it SHALL leave other Codex prompt files unchanged + +#### Scenario: Non-interactive initialization preserves unreplaced global Codex prompts +- **WHEN** `openspec init` runs without interaction and without `--force` +- **AND** the resolved global Codex prompt directory contains exact allowlisted managed Codex prompt files +- **AND** replacement Codex skills do not yet exist for at least one detected prompt workflow +- **THEN** the command SHALL preserve the unreplaced Codex prompt files +- **AND** it SHALL continue to leave unmanaged Codex prompt files unchanged + +#### Scenario: Non-interactive initialization removes replaced global Codex prompts +- **WHEN** `openspec init` runs without interaction and without `--force` +- **AND** the resolved global Codex prompt directory contains exact allowlisted managed Codex prompt files +- **AND** replacement Codex skills exist for the workflows represented by those prompt filenames +- **THEN** the command SHALL remove those managed Codex prompt files +- **AND** it SHALL leave unmanaged Codex prompt files unchanged + +#### Scenario: Initialization preview lists deferred global prompts cleanup separately +- **WHEN** `openspec init` detects managed global Codex prompt files before tool setup +- **THEN** the command SHALL present deferred global prompts cleanup in a separate section from immediate repo-local removals +- **AND** that section SHALL list the concrete prompt paths +- **AND** it SHALL explain that those global prompts are removed only after matching replacement skills are installed + +#### Scenario: Cleanup reports Codex skills as the replacement +- **WHEN** initialization cleanup reports removed Codex prompt files +- **THEN** the cleanup summary SHALL indicate that the removed prompt files are replaced by Codex skills + ## Why Manual creation of OpenSpec structure is error-prone and creates adoption friction. A standardized init command ensures: diff --git a/openspec/specs/cli-update/spec.md b/openspec/specs/cli-update/spec.md index bc5f01eed9..f19062cdb2 100644 --- a/openspec/specs/cli-update/spec.md +++ b/openspec/specs/cli-update/spec.md @@ -53,12 +53,12 @@ The update command SHALL always update the core OpenSpec files and display an AS ### Requirement: Slash Command Updates -The update command SHALL refresh existing slash command files for configured tools without creating new ones, and ensure the OpenCode archive command accepts change ID arguments. +The update command SHALL refresh existing slash command files for configured adapter-backed tools without creating new ones, keep legacy command cleanup safe, treat Codex custom prompts as legacy artifacts that are cleaned up rather than refreshed, and ensure the OpenCode archive command accepts change ID arguments. #### Scenario: Updating slash commands for Antigravity - **WHEN** `.agent/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` - **THEN** refresh the OpenSpec-managed portion of each file so the workflow copy matches other tools while preserving the existing single-field `description` frontmatter -- **AND** skip creating any missing workflow files during update, mirroring the behavior for Windsurf and other IDEs +- **AND** skip creating any missing workflow files during update, mirroring the behavior for Devin Desktop and other IDEs #### Scenario: Updating slash commands for Claude Code - **WHEN** `.claude/commands/openspec/` contains `proposal.md`, `apply.md`, and `archive.md` @@ -113,11 +113,18 @@ The update command SHALL refresh existing slash command files for configured too - **AND** `openspec update` SHALL NOT refresh files that remain only under `.opencode/command/` #### Scenario: Updating slash commands for Windsurf -- **WHEN** `.windsurf/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` +- **WHEN** the legacy Windsurf location `.windsurf/workflows/`, now Devin's, contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` - **THEN** refresh each file using shared templates wrapped in OpenSpec markers - **AND** ensure templates include instructions for the relevant workflow stage - **AND** skip creating missing files (the update command only refreshes what already exists) +#### Scenario: Updating workflows for Devin Desktop +- **WHEN** Devin Desktop is a configured tool (its `.devin/` directory exists) +- **THEN** write `.devin/workflows/opsx-.md` for each workflow in the active profile, from shared templates +- **AND** emit frontmatter with `name`, `description`, `category`, and `tags` +- **AND** transform command references to hyphen form (for example `/opsx-propose`), the name Devin registers for a workflow file +- **AND** refresh `.devin/skills/openspec-*/SKILL.md` with `/openspec-*` skill references, the one invocation both Devin agents accept + #### Scenario: Updating slash commands for Kilo Code - **WHEN** `.kilo/command/` contains OpenSpec-managed `opsx-*.md` command files for the configured profile - **THEN** refresh each file using shared templates wrapped in OpenSpec markers @@ -125,11 +132,11 @@ The update command SHALL refresh existing slash command files for configured too - **AND** skip creating missing files (the update command only refreshes what already exists) #### Scenario: Updating slash commands for Codex -- **GIVEN** the global Codex prompt directory contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` +- **GIVEN** the global Codex prompt directory contains OpenSpec-managed Codex prompt files - **WHEN** a user runs `openspec update` -- **THEN** refresh each file using the shared slash-command templates (including placeholder guidance) -- **AND** preserve any unmanaged content outside the OpenSpec marker block -- **AND** skip creation when a Codex prompt file is missing +- **THEN** the command SHALL NOT refresh Codex prompt files +- **AND** it SHALL treat those files as legacy cleanup candidates +- **AND** it SHALL preserve unmanaged files by deleting only exact allowlisted OpenSpec-owned filenames under the resolved global Codex prompt directory after replacement skills exist #### Scenario: Updating slash commands for GitHub Copilot - **WHEN** `.github/prompts/` contains `openspec-proposal.prompt.md`, `openspec-apply.prompt.md`, and `openspec-archive.prompt.md` @@ -185,3 +192,70 @@ The `openspec update` command SHALL refresh Oh My Pi skill files and command fil #### Scenario: Updating Oh My Pi command files - **WHEN** `openspec update` runs and Oh My Pi is a configured tool - **THEN** command files are written to `.omp/commands/opsx-.md` for each workflow in the active profile, creating them if they do not yet exist and overwriting them if they do + +### Requirement: Codex update uses the skills-invocable command surface +`openspec update` SHALL treat Codex as a skills-invocable tool, not as an adapter-backed command-file tool. + +#### Scenario: Codex command surface resolution +- **WHEN** `openspec update` detects Codex as a configured tool +- **THEN** the command SHALL resolve Codex command surface capability as `skills-invocable` +- **AND** it SHALL apply delivery behavior through the shared command-surface capability model when that model is available +- **AND** it SHALL NOT use a Codex-specific delivery predicate that duplicates command-surface capability rules + +### Requirement: Codex update uses skills only +`openspec update` SHALL refresh Codex through generated OpenSpec skills without generating or refreshing Codex custom prompt files. + +#### Scenario: Legacy Codex prompt migration infers workflows from the legacy filenames +- **WHEN** `openspec update` upgrades an unconfigured Codex tool from detected exact allowlisted global legacy Codex prompt files +- **THEN** it SHALL infer the replacement workflow IDs from the detected prompt filenames where possible +- **AND** it SHALL use that inferred workflow subset for the replacement Codex skills instead of expanding to the current profile's full workflow set + +#### Scenario: Updating Codex with default delivery +- **WHEN** a project has Codex OpenSpec skills configured +- **AND** the active delivery mode is `both` +- **THEN** `openspec update` SHALL refresh the selected Codex skill files under `.codex/skills/` +- **AND** it SHALL NOT create or refresh Codex prompt files under `$CODEX_HOME/prompts` or the default Codex prompt directory + +#### Scenario: Updating Codex with commands delivery +- **WHEN** a project has Codex configured +- **AND** the active delivery mode is `commands` +- **THEN** `openspec update` SHALL keep Codex usable by refreshing selected Codex skills +- **AND** it SHALL skip Codex command-file generation because Codex is skills-invocable +- **AND** it SHALL NOT remove Codex skills solely because the global delivery mode is `commands` + +#### Scenario: Updating Codex with skills delivery +- **WHEN** a project has Codex configured +- **AND** the active delivery mode is `skills` +- **THEN** `openspec update` SHALL refresh selected Codex skills +- **AND** it SHALL treat OpenSpec-managed Codex prompt files as legacy cleanup candidates +- **AND** it SHALL NOT delete global Codex prompt files through ordinary delivery reconciliation without accepted or forced cleanup + +### Requirement: Codex update cleanup removes managed legacy prompts +`openspec update` SHALL clean up previously managed Codex prompt files from the resolved global Codex prompt directory only after replacement Codex skills exist. + +#### Scenario: Forced update cleanup removes Codex prompts +- **WHEN** a user runs `openspec update --force` +- **AND** the resolved Codex prompt directory contains exact allowlisted managed global Codex prompt files +- **AND** replacement Codex skills exist for the workflows represented by those prompt filenames +- **THEN** the command SHALL remove those managed Codex prompt files +- **AND** it SHALL leave non-OpenSpec Codex prompt files unchanged + +#### Scenario: Configured Codex cleanup completes after skills refresh +- **WHEN** an approved or forced update detects an allowlisted global Codex prompt whose configured project is missing the replacement skill +- **AND** the configured-tool update installs that replacement skill, including under `delivery=commands` +- **THEN** the command SHALL perform deferred global prompt cleanup after the configured-tool update loop +- **AND** it SHALL remove the replaced prompt in the same update run + +#### Scenario: Interactive update cleanup includes Codex prompts +- **WHEN** a user runs `openspec update` interactively +- **THEN** the preview SHALL list immediate repo-local removals separately from deferred global prompts cleanup +- **AND** the deferred section SHALL list the concrete global prompt paths before the user confirms cleanup +- **AND** managed Codex prompt files are detected +- **THEN** the cleanup prompt SHALL include those files in the cleanup plan +- **AND** accepting cleanup SHALL remove only the prompt files whose replacement Codex skills exist + +#### Scenario: Non-interactive update without force does not delete prompts +- **WHEN** a user runs `openspec update` without interaction and without `--force` +- **AND** managed Codex prompt files are detected +- **THEN** the command SHALL warn that legacy cleanup requires `--force` or an interactive run +- **AND** it SHALL NOT delete Codex prompt files diff --git a/openspec/specs/command-generation/spec.md b/openspec/specs/command-generation/spec.md index cb270ae914..6cff864b2c 100644 --- a/openspec/specs/command-generation/spec.md +++ b/openspec/specs/command-generation/spec.md @@ -4,6 +4,7 @@ Define tool-agnostic command content and adapter contracts for generating tool-specific OpenSpec command files. ## Requirements + ### Requirement: CommandContent interface The system SHALL define a tool-agnostic `CommandContent` interface for command data. @@ -28,13 +29,14 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **WHEN** implementing a tool adapter - **THEN** `ToolCommandAdapter` SHALL require: - `toolId`: string identifier matching `AIToolOption.value` - - `getFilePath(commandId: string)`: returns file path for command (relative from project root, or absolute for global-scoped tools like Codex) + - `getFilePath(commandId: string)`: returns file path for command relative from project root unless a supported scoped install resolver provides an absolute target for that adapter - `formatFile(content: CommandContent)`: returns complete file content with frontmatter #### Scenario: Claude adapter formatting - **WHEN** formatting a command for Claude Code -- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields +- **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `allowed-tools`, `category`, `tags` fields +- **AND** the `allowed-tools` field SHALL have the value `Bash(openspec:*)` so Claude Code runs `openspec` commands from the slash command without prompting for approval - **AND** file path SHALL follow pattern `.claude/commands/opsx/.md` #### Scenario: Cursor adapter formatting @@ -45,9 +47,15 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting #### Scenario: Windsurf adapter formatting -- **WHEN** formatting a command for Windsurf +- **GIVEN** RETIRED — Windsurf was rebranded to Devin Desktop and its config directory moved +- **WHEN** looking for a Windsurf adapter +- **THEN** none SHALL be registered — it is replaced by the Devin adapter below, not kept alongside a second adapter for the same product + +#### Scenario: Devin Desktop adapter formatting + +- **WHEN** formatting a command for Devin Desktop - **THEN** the adapter SHALL output YAML frontmatter with `name`, `description`, `category`, `tags` fields -- **AND** file path SHALL follow pattern `.windsurf/workflows/opsx-.md` +- **AND** file path SHALL follow pattern `.devin/workflows/opsx-.md` #### Scenario: Trae adapter formatting @@ -55,6 +63,13 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **THEN** the adapter SHALL output YAML frontmatter with `name` and `description` fields - **AND** file path SHALL follow pattern `.trae/commands/opsx-.md` +#### Scenario: OpenCode adapter formatting + +- **WHEN** formatting a command for OpenCode +- **THEN** the adapter SHALL output YAML frontmatter with `description` field +- **AND** file path SHALL follow pattern `.opencode/commands/opsx-.md` using `path.join('.opencode', 'commands', ...)` for cross-platform compatibility +- **AND** the adapter SHALL transform colon-based command references (`/opsx:name`) to hyphen-based (`/opsx-name`) in the body + ### Requirement: Command generator function The system SHALL provide a `generateCommand` function that combines content with adapter. @@ -115,3 +130,52 @@ The body content of commands SHALL be shared across all tools. - **WHEN** generating the 'explore' command for Claude and Cursor - **THEN** both SHALL use the same `body` content - **AND** only the frontmatter, the file path, and the spelling of `/opsx:*` command references SHALL differ + +### Requirement: Legacy cleanup for renamed OpenCode command directory + +The legacy cleanup module SHALL detect and remove old OpenCode command files from the previous singular `.opencode/command/` directory path. + +#### Scenario: Detect old singular-path OpenCode command files + +- **WHEN** running legacy artifact detection on a project with files matching `.opencode/command/opsx-*.md` or `.opencode/command/openspec-*.md` +- **THEN** the system SHALL include those files in the legacy slash command files list via `LEGACY_SLASH_COMMAND_PATHS` +- **AND** `LegacySlashCommandPattern.pattern` SHALL accept `string | string[]` to support multiple glob patterns per tool + +#### Scenario: Clean up old OpenCode command files on init + +- **WHEN** a user runs `openspec init` in a project with old `.opencode/command/` artifacts +- **THEN** the system SHALL remove the old files +- **AND** generate new command files at `.opencode/commands/` + +#### Scenario: Auto-cleanup legacy artifacts in non-interactive mode + +- **WHEN** a user runs `openspec init` in non-interactive mode (e.g., CI) and legacy artifacts are detected +- **THEN** the system SHALL auto-cleanup legacy artifacts without requiring `--force` +- **AND** legacy slash command files (100% OpenSpec-managed) SHALL be removed +- **AND** config file cleanup SHALL only remove OpenSpec markers (never delete user files) + +### Requirement: Codex is not a command generation target +The command-generation system SHALL exclude Codex from active command adapter lookup and generation. + +#### Scenario: Codex adapter lookup +- **WHEN** callers request a command adapter for `codex` +- **THEN** the registry SHALL return no command adapter +- **AND** command-file generation callers SHALL treat Codex the same as other skills-only tools + +#### Scenario: Generating commands for all registered adapters +- **WHEN** callers enumerate registered command adapters +- **THEN** the returned adapter list SHALL NOT include Codex +- **AND** no generated command path SHALL point to a Codex global prompt directory + +#### Scenario: Codex command adapter module is not exported +- **WHEN** callers import supported command adapters through the command-generation adapter index +- **THEN** Codex SHALL NOT be exported as a supported command adapter + +### Requirement: Skills-only command skip behavior remains valid for Codex +The system SHALL skip Codex command-file generation while still allowing Codex skill generation. + +#### Scenario: Command generation requested for selected Codex tool +- **WHEN** a selected tool is Codex +- **AND** command generation would otherwise be included by delivery mode +- **THEN** the command generation step SHALL skip Codex command files +- **AND** the Codex skill generation step SHALL remain valid From f6c0b8f51dfa0999d7af68e6eec8ed46dba1cf8e Mon Sep 17 00:00:00 2001 From: Clay Good Date: Thu, 29 Oct 2026 12:42:44 -0500 Subject: [PATCH 2/4] chore(openspec): point codex at .agents/skills and clarify devin update The refreshed specs still sent Codex skills to .codex/skills, but config.ts writes them to the shared .agents root and keeps .codex only as a legacy root. Update also writes every active-profile Devin workflow, including missing ones, and moves .windsurf content under the consent rules rather than refreshing it in place. Co-Authored-By: Claude Opus 5.5 --- openspec/specs/ai-tool-paths/spec.md | 7 ++++--- openspec/specs/cli-init/spec.md | 6 +++--- openspec/specs/cli-update/spec.md | 15 ++++++++------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/openspec/specs/ai-tool-paths/spec.md b/openspec/specs/ai-tool-paths/spec.md index 54d6d7e3b7..ec7bf19326 100644 --- a/openspec/specs/ai-tool-paths/spec.md +++ b/openspec/specs/ai-tool-paths/spec.md @@ -164,12 +164,13 @@ OpenSpec SHALL provide a vendor-neutral `agents` tool target rooted at the share - **THEN** `agents` SHALL NOT be reported as available ### Requirement: Codex skills path is the supported Codex integration path -The system SHALL identify `.codex/skills/` as the supported Codex OpenSpec workflow path. +The system SHALL identify `.agents/skills/` as the supported Codex OpenSpec workflow path, with `.codex/skills/` kept only as a legacy location. #### Scenario: Codex skills path defined - **WHEN** looking up the `codex` tool -- **THEN** the system SHALL provide `.codex` as the Codex skills base directory -- **AND** generated Codex skills SHALL be written under `/.codex/skills/` +- **THEN** the system SHALL provide `.agents` as the Codex skills base directory, the shared root Codex reads +- **AND** generated Codex skills SHALL be written under `/.agents/skills/` +- **AND** the system SHALL list `.codex` as a legacy skills root, used for detection and migrated to `.agents/skills/` after the replacement skills are written, leaving user-authored files in place #### Scenario: Codex command path is not advertised as supported - **WHEN** displaying AI tool path documentation or command-generation metadata diff --git a/openspec/specs/cli-init/spec.md b/openspec/specs/cli-init/spec.md index 12479d444f..e3b83fc528 100644 --- a/openspec/specs/cli-init/spec.md +++ b/openspec/specs/cli-init/spec.md @@ -364,19 +364,19 @@ The `openspec init` command SHALL support Oh My Pi as a configurable tool, gener #### Scenario: Initializing Codex with default delivery - **WHEN** a user runs `openspec init` and selects Codex - **AND** the active delivery mode is `both` -- **THEN** the command SHALL create the selected OpenSpec skill files under `.codex/skills/` +- **THEN** the command SHALL create the selected OpenSpec skill files under `.agents/skills/` - **AND** it SHALL NOT create Codex prompt files under `$CODEX_HOME/prompts` or the default Codex prompt directory #### Scenario: Initializing Codex with skills delivery - **WHEN** a user runs `openspec init` and selects Codex - **AND** the active delivery mode is `skills` -- **THEN** the command SHALL create the selected OpenSpec skill files under `.codex/skills/` +- **THEN** the command SHALL create the selected OpenSpec skill files under `.agents/skills/` - **AND** it SHALL NOT create Codex prompt files #### Scenario: Initializing Codex with commands delivery - **WHEN** a user runs `openspec init` and selects Codex - **AND** the active delivery mode is `commands` -- **THEN** the command SHALL still create the selected OpenSpec skill files under `.codex/skills/` +- **THEN** the command SHALL still create the selected OpenSpec skill files under `.agents/skills/` - **AND** it SHALL skip Codex command-file generation because Codex is `skills-invocable` ### Requirement: Codex initialization cleanup removes managed legacy prompts diff --git a/openspec/specs/cli-update/spec.md b/openspec/specs/cli-update/spec.md index 2bded18b93..56b27c3c5d 100644 --- a/openspec/specs/cli-update/spec.md +++ b/openspec/specs/cli-update/spec.md @@ -59,7 +59,7 @@ The update command SHALL refresh existing slash command files for configured ada #### Scenario: Updating slash commands for Antigravity - **WHEN** `.agent/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` - **THEN** refresh the OpenSpec-managed portion of each file so the workflow copy matches other tools while preserving the existing single-field `description` frontmatter -- **AND** skip creating any missing workflow files during update, mirroring the behavior for Devin Desktop and other IDEs +- **AND** skip creating any missing legacy workflow files during update, mirroring the behavior for other IDEs' legacy command files #### Scenario: Updating slash commands for Claude Code - **WHEN** `.claude/commands/openspec/` contains `proposal.md`, `apply.md`, and `archive.md` @@ -115,13 +115,14 @@ The update command SHALL refresh existing slash command files for configured ada #### Scenario: Updating slash commands for Windsurf - **WHEN** the legacy Windsurf location `.windsurf/workflows/`, now Devin's, contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` -- **THEN** refresh each file using shared templates wrapped in OpenSpec markers -- **AND** ensure templates include instructions for the relevant workflow stage -- **AND** skip creating missing files (the update command only refreshes what already exists) +- **THEN** do not refresh those files in place, since they are legacy workflow files handled by legacy cleanup +- **AND** treat other OpenSpec-managed content under `.windsurf/` as belonging to Devin Desktop, moving it to `.devin/` under the consent rules in the ai-tool-paths requirement "Migrating OpenSpec content out of a renamed tool's former directory" and refreshing it there +- **AND** do not create missing legacy `openspec-*` workflow files #### Scenario: Updating workflows for Devin Desktop -- **WHEN** Devin Desktop is a configured tool (its `.devin/` directory exists) -- **THEN** write `.devin/workflows/opsx-.md` for each workflow in the active profile, from shared templates +- **WHEN** Devin Desktop is a configured tool (OpenSpec skills or workflow files exist under `.devin/`) +- **THEN** write `.devin/workflows/opsx-.md` for each workflow in the active profile, from shared templates, creating any that are missing and overwriting the rest +- **AND** this creation is the active-profile exception to the existing-file-only rules above (see Tool-Agnostic Updates), not a Devin-only behavior - **AND** emit frontmatter with `name`, `description`, `category`, and `tags` - **AND** transform command references to hyphen form (for example `/opsx-propose`), the name Devin registers for a workflow file - **AND** refresh `.devin/skills/openspec-*/SKILL.md` with `/openspec-*` skill references, the one invocation both Devin agents accept @@ -216,7 +217,7 @@ The `openspec update` command SHALL refresh Oh My Pi skill files and command fil #### Scenario: Updating Codex with default delivery - **WHEN** a project has Codex OpenSpec skills configured - **AND** the active delivery mode is `both` -- **THEN** `openspec update` SHALL refresh the selected Codex skill files under `.codex/skills/` +- **THEN** `openspec update` SHALL refresh the selected Codex skill files under `.agents/skills/` - **AND** it SHALL NOT create or refresh Codex prompt files under `$CODEX_HOME/prompts` or the default Codex prompt directory #### Scenario: Updating Codex with commands delivery From aaa69150d7caa75706516afe60861a2265ddc759 Mon Sep 17 00:00:00 2001 From: Clay Good Date: Thu, 29 Oct 2026 14:18:38 -0500 Subject: [PATCH 3/4] docs(openspec): say update writes Kilo Code's active-profile commands The Kilo Code scenario still said update only refreshes existing `.kilo/command/opsx-*.md` files and skips missing ones. Update writes every active-profile command file for a configured tool when the delivery setting includes commands, creating missing ones. The scenario now says so, and the Slash Command Updates requirement scopes its "without creating new ones" rule to files outside the active profile. Co-Authored-By: Claude Opus 5.5 --- openspec/specs/cli-update/spec.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openspec/specs/cli-update/spec.md b/openspec/specs/cli-update/spec.md index 56b27c3c5d..9c9a6b744a 100644 --- a/openspec/specs/cli-update/spec.md +++ b/openspec/specs/cli-update/spec.md @@ -54,7 +54,7 @@ The update command SHALL always update the core OpenSpec files and display an AS ### Requirement: Slash Command Updates -The update command SHALL refresh existing slash command files for configured adapter-backed tools without creating new ones, keep legacy command cleanup safe, treat Codex custom prompts as legacy artifacts that are cleaned up rather than refreshed, and ensure the OpenCode archive command accepts change ID arguments. +The update command SHALL refresh existing slash command files for configured adapter-backed tools without creating new ones outside the active profile, keep legacy command cleanup safe, treat Codex custom prompts as legacy artifacts that are cleaned up rather than refreshed, and ensure the OpenCode archive command accepts change ID arguments. #### Scenario: Updating slash commands for Antigravity - **WHEN** `.agent/workflows/` contains `openspec-proposal.md`, `openspec-apply.md`, and `openspec-archive.md` @@ -128,10 +128,10 @@ The update command SHALL refresh existing slash command files for configured ada - **AND** refresh `.devin/skills/openspec-*/SKILL.md` with `/openspec-*` skill references, the one invocation both Devin agents accept #### Scenario: Updating slash commands for Kilo Code -- **WHEN** `.kilo/command/` contains OpenSpec-managed `opsx-*.md` command files for the configured profile -- **THEN** refresh each file using shared templates wrapped in OpenSpec markers +- **WHEN** Kilo Code is configured and the delivery setting includes commands +- **THEN** write `.kilo/command/opsx-.md` for each workflow in the active profile, from shared templates wrapped in OpenSpec markers, creating any that are missing and overwriting the rest - **AND** ensure templates include instructions for the relevant workflow stage -- **AND** skip creating missing files (the update command only refreshes what already exists) +- **AND** this is the active-profile exception described under Tool-Agnostic Updates #### Scenario: Updating slash commands for Codex - **GIVEN** the global Codex prompt directory contains OpenSpec-managed Codex prompt files From de627232cca72828053f8a1d63a3c89b62ae367d Mon Sep 17 00:00:00 2001 From: Clay Good Date: Fri, 30 Oct 2026 09:07:47 -0500 Subject: [PATCH 4/4] docs(openspec): state the Codex skill exception and where references are rewritten ai-tool-paths said a former skill copy is removed only when it is byte-identical, but migration also drops a former SKILL.md that differs only in generated parts (version, line endings or BOM, older Codex references), via isLegacyCodexSkillEquivalentToCurrent. The spec now names that exception. command-generation credited the OpenCode adapter with rewriting `/opsx:` references; generateCommand does it before the adapter formats the file, as the spec's own generator requirement says. Co-Authored-By: Claude Opus 5.5 --- openspec/specs/ai-tool-paths/spec.md | 1 + openspec/specs/command-generation/spec.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openspec/specs/ai-tool-paths/spec.md b/openspec/specs/ai-tool-paths/spec.md index ec7bf19326..40ead1c728 100644 --- a/openspec/specs/ai-tool-paths/spec.md +++ b/openspec/specs/ai-tool-paths/spec.md @@ -255,6 +255,7 @@ distinguishes that user from one who took the rebrand. - **THEN** the copy under the current root SHALL win, rather than being merged or overwritten - **AND** only the file OpenSpec generated SHALL be removed from the former root — for a skill directory that is `SKILL.md` alone, never the directory and whatever else it holds - **AND** one rule SHALL govern skills and command files alike: the former copy SHALL be removed only when it is byte-identical to the surviving one +- **AND** the one exception is a former `SKILL.md` that differs from the surviving one only in what OpenSpec generated: the recorded generator version, line endings or a byte-order mark, or the older Codex command references. It SHALL be removed too, because nothing in it is user-authored - **AND** a former copy that differs SHALL be left where it is, since the difference may be a customization - **AND** files left behind for that reason SHALL be reported, so the user knows two copies now exist diff --git a/openspec/specs/command-generation/spec.md b/openspec/specs/command-generation/spec.md index 6cff864b2c..749091c6ec 100644 --- a/openspec/specs/command-generation/spec.md +++ b/openspec/specs/command-generation/spec.md @@ -68,7 +68,7 @@ The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting - **WHEN** formatting a command for OpenCode - **THEN** the adapter SHALL output YAML frontmatter with `description` field - **AND** file path SHALL follow pattern `.opencode/commands/opsx-.md` using `path.join('.opencode', 'commands', ...)` for cross-platform compatibility -- **AND** the adapter SHALL transform colon-based command references (`/opsx:name`) to hyphen-based (`/opsx-name`) in the body +- **AND** the generated file body SHALL use hyphen-based command references (`/opsx-name`), rewritten from the colon-based form (`/opsx:name`) by `generateCommand` before the adapter formats it ### Requirement: Command generator function