Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions openspec/changes/simplify-skill-installation/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,60 @@ What's installed in `.claude/skills/` (etc.) is the source of truth, not config.
- `init`: First time setup, or when you want to change which tools are configured
- `update`: After changing config, or to refresh templates to latest version

### 8. Existing User Migration

When `openspec init` or `openspec update` encounters a project with existing workflows but no `profile` field in global config, it performs a one-time migration to preserve the user's current setup.

**Rationale:** Without migration, existing users would default to `core` profile, causing `propose` to be added on top of their 10 workflows — making things worse, not better. Migration ensures existing users keep exactly what they have.

**Triggered by:** Both `init` (re-init on existing project) and `update`. The migration check is a shared function called early in both commands, before profile resolution.

**Detection logic:**
```typescript
// Shared migration check, called by both init and update:
function migrateIfNeeded(projectPath: string, tools: AiTool[]): void {
const globalConfig = readGlobalConfig();
if (globalConfig.profile) return; // already migrated or explicitly set

const installedWorkflows = scanInstalledWorkflows(projectPath, tools);
if (installedWorkflows.length === 0) return; // new user, use core defaults

// Existing user — migrate to custom profile
writeGlobalConfig({
...globalConfig,
profile: 'custom',
delivery: 'both',
workflows: installedWorkflows,
});
}
```

**Scanning logic:**
- Scan all tool directories (`.claude/skills/`, `.cursor/skills/`, etc.) for workflow directories/files
- Match only against `ALL_WORKFLOWS` constant — ignore user-created custom skills/commands
- Map directory names back to workflow IDs (e.g., `openspec-explore/` → `explore`, `opsx-explore.md` → `explore`)
- Take the union of detected workflow names across all tools

**Edge cases:**
- **User manually deleted some workflows:** Migration scans what's actually installed, respecting their choices
- **Multiple projects with different workflow sets:** First project to trigger migration sets global config; subsequent projects use it
- **User has custom (non-OpenSpec) skills in the directory:** Ignored — scanner only matches known workflow IDs from `ALL_WORKFLOWS`
- **Migration is idempotent:** If `profile` is already set in config, no re-migration occurs
- **Non-interactive (CI):** Same migration logic, no confirmation needed — it's preserving existing state

**Alternatives considered:**
- Migrate during `init` instead of `update`: Init already has its own flow (tool selection, etc.). Mixing migration with init creates confusing UX
- Don't migrate, just default to core: Breaks existing users by adding `propose` and showing "extra workflows" warnings
- Migrate at global config read time: Too implicit, hard to show feedback to user

### 9. Generic Next-Step Guidance in Templates

Workflow templates use generic, concept-based next-step guidance rather than referencing specific workflow commands. For example, instead of "run `/opsx:propose`", templates say "create a change proposal".

**Rationale:** Conditional cross-referencing (where each template checks which other workflows are installed and renders different command names) adds significant complexity to template generation, testing, and maintenance. Generic guidance avoids this entirely while still being useful — users already know their installed workflows.

**Note:** If we find that users consistently struggle to map concepts to commands, we can revisit this with conditional cross-references. For now, simplicity wins.

### 7. Fix Multi-Select Keybindings
Comment on lines +151 to 205

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Section numbering is out of order — sections 8 and 9 precede section 7 in the file.

Sections 8 ("Existing User Migration") and 9 ("Generic Next-Step Guidance") were inserted before the existing section 7 ("Fix Multi-Select Keybindings") rather than after it. Consider renumbering or reordering to keep the document sequential.

🧰 Tools
🪛 LanguageTool

[style] ~183-~183: To elevate your writing, try using a synonym here.
Context: ... global config read time: Too implicit, hard to show feedback to user ### 9. Generi...

(HARD_TO)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openspec/changes/simplify-skill-installation/design.md` around lines 139 -
193, The section numbering is out of order: "### 8. Existing User Migration" and
"### 9. Generic Next-Step Guidance" appear before "### 7. Fix Multi-Select
Keybindings"; renumber or reorder these headings so the document flows
sequentially (e.g., move "Existing User Migration" and "Generic Next-Step
Guidance" after "Fix Multi-Select Keybindings" or renumber them to 7/8/9
consistently), and update any in-file references or cross-links that mention the
old section numbers to the new numbers; locate headings by the exact strings
"### 8. Existing User Migration", "### 9. Generic Next-Step Guidance", and "###
7. Fix Multi-Select Keybindings" to apply the fix.


Change from tab-to-confirm to industry-standard space/enter.
Expand Down
33 changes: 21 additions & 12 deletions openspec/changes/simplify-skill-installation/proposal.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,30 +127,39 @@ Workflows: (space to toggle, enter to save)
[ ] onboard
```

### 8. Backwards Compatibility
### 8. Backwards Compatibility & Migration

- Existing users with all workflows keep them (extra workflows not in profile are preserved)
- `openspec init` sets up new projects using current profile config
- `openspec update` applies config changes to existing projects (adds missing workflows, refreshes templates)
**Existing users keep their current setup.** When `openspec update` runs on a project with existing workflows and no `profile` in global config, it performs a one-time migration:

1. Scans installed workflow files across all tool directories in the project
2. Writes `profile: "custom"`, `delivery: "both"`, `workflows: [<detected>]` to global config
3. Refreshes templates but does NOT add or remove any workflows
4. Displays: "Migrated: custom profile with N existing workflows"

After migration, subsequent `init` and `update` commands respect the migrated config.

**Key behaviors:**
- Existing users' workflows are preserved exactly as-is (no `propose` added automatically)
- Both `init` (re-init) and `update` trigger migration on existing projects if no profile is set
- `openspec init` on a **new** project (no existing workflows) uses global config, defaulting to `core`
- `init` with a custom profile shows what will be installed and prompts to proceed or reconfigure
- Migration message mentions `propose` and suggests `openspec config profile core` to opt in
- After migration, users can opt into `core` profile via `openspec config profile core`
- Workflow templates conditionally reference only installed workflows in "next steps" guidance

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Documentation inconsistency with design.md section 9.

Line 149 states templates "conditionally reference only installed workflows" in next-step guidance, but design.md section 9 explicitly documents the opposite decision — generic, concept-based guidance was chosen to avoid conditional cross-referencing complexity. Consider aligning this bullet with the design decision.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openspec/changes/simplify-skill-installation/proposal.md` at line 149, The
proposal's line "Workflow templates conditionally reference only installed
workflows in 'next steps' guidance" conflicts with the design decision in
design.md section 9 which specifies using generic, concept-based guidance;
update the bullet in proposal.md (the line containing that quoted phrase) to
match design.md section 9 by replacing the conditional/installed-workflows
wording with language that states templates provide generic, concept-based
next-step guidance rather than conditionally referencing installed workflows,
and ensure the phrasing mirrors the terminology used in design.md for
consistency.

- Delivery changes are applied: switching to `skills` removes command files, switching to `commands` removes skill files
- All workflows remain available via custom profile

## Capabilities

### New Capabilities

- `profiles`: Support for workflow profiles (core, custom) with interactive configuration
- `delivery-config`: User preference for delivery method (skills, commands, both)
- `profiles`: Workflow profiles (core, custom), delivery preferences, global config storage, interactive picker
- `propose-workflow`: Combined workflow that creates change + generates all artifacts
- `user-config`: Extend existing global config with profile/delivery settings
- `available-tools`: Detect what AI tools the user has from existing directories

### Modified Capabilities

- `cli-init`: Smart defaults with auto-detection and confirmation
- `tool-selection-ux`: Space to select, Enter to confirm
- `skill-generation`: Conditional based on profile and delivery settings
- `command-generation`: Conditional based on profile and delivery settings
- `cli-init`: Smart defaults with tool auto-detection, profile-based skill/command generation
- `cli-update`: Profile support, delivery changes, one-time migration for existing users

## Impact

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ The init command SHALL generate skills based on the active profile, not a fixed
- **WHEN** user runs init with profile `custom`
- **THEN** the system SHALL generate skills only for workflows listed in config `workflows` array

#### Scenario: Propose workflow included in skill templates
- **WHEN** generating skills
- **THEN** the system SHALL include the `propose` workflow as an available skill template

### Requirement: Command generation per tool (REPLACES fixed 9-command mandate)
The init command SHALL generate commands based on profile AND delivery settings.

Expand All @@ -31,6 +35,26 @@ The init command SHALL generate commands based on profile AND delivery settings.
- **WHEN** delivery is set to `both`
- **THEN** the system SHALL generate both skill and command files for profile workflows

#### Scenario: Propose workflow included in command templates
- **WHEN** generating commands
- **THEN** the system SHALL include the `propose` workflow as an available command template

### Requirement: Tool auto-detection
The init command SHALL detect installed AI tools by scanning for their configuration directories in the project root.

#### Scenario: Detection from directories
- **WHEN** scanning for tools
- **THEN** the system SHALL check for directories matching each supported AI tool's configuration directory (e.g., `.claude/`, `.cursor/`, `.windsurf/`)
- **THEN** all tools with a matching directory SHALL be returned as detected

#### Scenario: Detection covers all supported tools
- **WHEN** scanning for tools
- **THEN** the system SHALL check for all tools defined in the supported tools configuration that have a configuration directory

#### Scenario: No tools detected
- **WHEN** no tool configuration directories exist in project root
- **THEN** the system SHALL return an empty list of detected tools

### Requirement: Smart defaults init flow
The init command SHALL work with sensible defaults and tool confirmation, minimizing required user input.

Expand Down Expand Up @@ -68,12 +92,40 @@ The init command SHALL work with sensible defaults and tool confirmation, minimi
- **THEN** the system SHALL NOT prompt for tool selection
- **THEN** the system SHALL proceed with default profile and delivery

#### Scenario: Init success message
#### Scenario: Init success message (propose installed)
- **WHEN** init completes successfully
- **AND** `propose` is in the active profile
- **THEN** the system SHALL display a tool-appropriate success message
- **THEN** for tools using colon syntax (Claude Code): "Start your first change: /opsx:propose \"your idea\""
- **THEN** for tools using hyphen syntax (Cursor, others): "Start your first change: /opsx-propose \"your idea\""

#### Scenario: Init success message (propose not installed, new installed)
- **WHEN** init completes successfully
- **AND** `propose` is NOT in the active profile
- **AND** `new` is in the active profile
- **THEN** for tools using colon syntax: "Start your first change: /opsx:new \"your idea\""
- **THEN** for tools using hyphen syntax: "Start your first change: /opsx-new \"your idea\""

#### Scenario: Init success message (neither propose nor new)
- **WHEN** init completes successfully
- **AND** neither `propose` nor `new` is in the active profile
- **THEN** the system SHALL display: "Done. Run 'openspec config profile' to configure your workflows."

### Requirement: Init performs migration on existing projects
The init command SHALL perform one-time migration when re-initializing an existing project, using the same shared migration logic as the update command.

#### Scenario: Re-init on existing project (no profile set)
- **WHEN** user runs `openspec init` on a project with existing workflow files
- **AND** global config does not contain a `profile` field
- **THEN** the system SHALL perform one-time migration before proceeding (see `specs/cli-update/spec.md`)
- **THEN** the system SHALL proceed with init using the migrated config

#### Scenario: Init on new project (no existing workflows)
- **WHEN** user runs `openspec init` on a project with no existing workflow files
- **AND** global config does not contain a `profile` field
- **THEN** the system SHALL NOT perform migration
- **THEN** the system SHALL use `core` profile defaults

### Requirement: Init respects global config
The init command SHALL read and apply settings from global config.

Expand All @@ -90,6 +142,33 @@ The init command SHALL read and apply settings from global config.
- **THEN** the system SHALL use the flag value instead of config value
- **THEN** the system SHALL NOT update the global config

### Requirement: Init shows profile confirmation for non-default profiles
The init command SHALL show what profile is being applied when it differs from `core`, allowing the user to adjust before proceeding.

#### Scenario: Init with custom profile (interactive)
- **WHEN** user runs `openspec init` interactively
- **AND** global config specifies `profile: "custom"` with workflows
- **THEN** the system SHALL display: "Applying custom profile (<count> workflows): <workflow-names>"
- **THEN** the system SHALL prompt: "Proceed? (y/n) Or run 'openspec config profile' to change."
- **WHEN** user confirms
- **THEN** the system SHALL proceed with init using the custom profile

#### Scenario: Init with custom profile — user declines
- **WHEN** user declines the profile confirmation prompt
- **THEN** the system SHALL display: "Run 'openspec config profile' to update your profile, then try again."
- **THEN** the system SHALL exit with code 0 (no error)

#### Scenario: Init with core profile (no confirmation needed)
- **WHEN** user runs `openspec init` interactively
- **AND** profile is `core` (default)
- **THEN** the system SHALL NOT show a profile confirmation prompt
- **THEN** the system SHALL proceed directly

#### Scenario: Non-interactive init with custom profile
- **WHEN** user runs `openspec init` non-interactively
- **AND** global config specifies a custom profile
- **THEN** the system SHALL proceed without confirmation (CI assumes intentional config)

### Requirement: Init preserves existing workflows
The init command SHALL NOT remove workflows that are already installed, but SHALL respect delivery setting.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,84 @@ The update command SHALL add or remove files based on the delivery setting.
- **AND** global config specifies `delivery: both`
- **THEN** the system SHALL generate/update both skill and command files

### Requirement: One-time migration for existing users
The update command SHALL detect existing users (no `profile` in global config + existing workflows) and migrate them to `custom` profile before applying updates.

#### Scenario: First update after upgrade (existing user)
- **WHEN** user runs `openspec update`
- **AND** global config does not contain a `profile` field
- **AND** project has existing workflow files installed
- **THEN** the system SHALL scan installed workflows across all tool directories in the project
- **THEN** the system SHALL only match workflow names present in `ALL_WORKFLOWS` constant (ignoring user-created custom skills)
- **THEN** the system SHALL take the union of detected workflow names across all tools
- **THEN** the system SHALL write to global config: `profile: "custom"`, `delivery: "both"`, `workflows: [<detected>]`
- **THEN** the system SHALL display: "Migrated: custom profile with <count> workflows (<workflow-names>)"
- **THEN** the system SHALL display: "New in this version: /opsx:propose (combines new + ff). Try 'openspec config profile core' for the streamlined 4-workflow experience."
- **THEN** the system SHALL proceed with normal update logic (using the migrated config)
- **THEN** the result SHALL be template refresh only (no workflows added or removed)

#### Scenario: Migration with partial workflows (user manually removed some)
- **WHEN** user runs `openspec update`
- **AND** global config does not contain a `profile` field
- **AND** project has fewer than the original 10 workflows installed
- **THEN** the system SHALL migrate with only the workflows that are actually present
- **THEN** the migrated `workflows` array SHALL reflect the user's current state, not the original set

#### Scenario: Migration with multiple tools having different workflow sets
- **WHEN** user runs `openspec update`
- **AND** project has multiple tools configured (e.g., Claude Code, Cursor)
- **AND** different tools have different workflows installed
- **THEN** the system SHALL take the union of all detected workflows across all tools
- **THEN** the migrated `workflows` array SHALL include any workflow that exists in at least one tool

#### Scenario: No migration needed (profile already set)
- **WHEN** user runs `openspec update`
- **AND** global config already contains a `profile` field
- **THEN** the system SHALL NOT perform migration
- **THEN** the system SHALL proceed with normal update logic using existing config

#### Scenario: No migration needed (no existing workflows)
- **WHEN** user runs `openspec update`
- **AND** global config does not contain a `profile` field
- **AND** project has no existing workflow files
- **THEN** the system SHALL NOT perform migration
- **THEN** the system SHALL use `core` profile defaults

#### Scenario: Migration is idempotent
- **WHEN** user runs `openspec update` multiple times
- **THEN** migration SHALL only occur on the first run (when `profile` field is absent)
- **THEN** subsequent runs SHALL use the existing global config without re-scanning

#### Scenario: Non-interactive migration
- **WHEN** user runs `openspec update` non-interactively (e.g., in CI)
- **AND** migration is triggered
- **THEN** the system SHALL perform migration without prompting
- **THEN** the system SHALL display the migration summary to stdout

### Requirement: Update detects new tool directories
The update command SHALL notify the user if new AI tool directories are detected that aren't currently configured.

#### Scenario: New tool directory detected
- **WHEN** user runs `openspec update`
- **AND** a new tool directory is detected (e.g., `.windsurf/` exists but Windsurf is not configured)
- **THEN** the system SHALL display: "Detected new tool: Windsurf. Run 'openspec init' to add it."
- **THEN** the system SHALL NOT automatically add the new tool
- **THEN** the system SHALL proceed with update for currently configured tools only

#### Scenario: No new tool directories
- **WHEN** user runs `openspec update`
- **AND** no new tool directories are detected
- **THEN** the system SHALL NOT display any tool detection message

### Requirement: Update requires an OpenSpec project
The update command SHALL only run inside an initialized OpenSpec project.

#### Scenario: Update outside a project
- **WHEN** user runs `openspec update`
- **AND** no `openspec/` directory exists in the current working directory
- **THEN** the system SHALL display: "No OpenSpec project found. Run 'openspec init' to set up."
- **THEN** the system SHALL exit with code 1

### Requirement: Extra workflows preserved
The update command SHALL NOT remove workflow files that aren't in the current profile.

Expand Down
Loading
Loading