From 8823015e3d0b5b37cb5a7e9fe328c69e84e40674 Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Thu, 22 Jan 2026 22:33:17 -0800 Subject: [PATCH 1/3] feat(cli): add change proposal to merge init and experimental commands This change merges `openspec init` and `openspec experimental` into a single command that uses the skill-based workflow as the default. Key changes: - BREAKING: init generates skills and /opsx:* commands instead of config files - BREAKING: Config files (CLAUDE.md, .cursorrules, etc.) no longer generated - BREAKING: Old slash commands (/openspec:proposal, etc.) no longer generated - BREAKING: openspec/AGENTS.md and project.md no longer generated - Add legacy detection and cleanup with Y/N confirmation - Keep experimental as hidden alias for backward compatibility Artifacts: - proposal.md: Motivation and scope - design.md: Architecture decisions and edge case handling - specs/legacy-cleanup/spec.md: New capability for legacy artifact cleanup - specs/cli-init/spec.md: Modified init spec with skill-based workflow - tasks.md: 37 implementation tasks across 7 groups --- .../merge-init-experimental/.openspec.yaml | 2 + .../changes/merge-init-experimental/design.md | 158 ++++++++++++++++ .../merge-init-experimental/proposal.md | 32 ++++ .../specs/cli-init/spec.md | 176 ++++++++++++++++++ .../specs/legacy-cleanup/spec.md | 127 +++++++++++++ .../changes/merge-init-experimental/tasks.md | 66 +++++++ 6 files changed, 561 insertions(+) create mode 100644 openspec/changes/merge-init-experimental/.openspec.yaml create mode 100644 openspec/changes/merge-init-experimental/design.md create mode 100644 openspec/changes/merge-init-experimental/proposal.md create mode 100644 openspec/changes/merge-init-experimental/specs/cli-init/spec.md create mode 100644 openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md create mode 100644 openspec/changes/merge-init-experimental/tasks.md diff --git a/openspec/changes/merge-init-experimental/.openspec.yaml b/openspec/changes/merge-init-experimental/.openspec.yaml new file mode 100644 index 00000000..7df15340 --- /dev/null +++ b/openspec/changes/merge-init-experimental/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-01-23 diff --git a/openspec/changes/merge-init-experimental/design.md b/openspec/changes/merge-init-experimental/design.md new file mode 100644 index 00000000..363d4ffc --- /dev/null +++ b/openspec/changes/merge-init-experimental/design.md @@ -0,0 +1,158 @@ +## Context + +Currently `openspec init` and `openspec experimental` are separate commands with distinct purposes: + +- **init**: Creates `openspec/` directory, generates `AGENTS.md`/`project.md`, configures tool config files (`CLAUDE.md`, etc.), generates old slash commands (`/openspec:proposal`, etc.) +- **experimental**: Generates skills (9 per tool), generates opsx slash commands (`/opsx:new`, etc.), creates `config.yaml` + +The skill-based workflow (experimental) is the direction we're going, so we're making it the default by merging into `init`. + +## Goals / Non-Goals + +**Goals:** +- Single `openspec init` command that sets up the complete skill-based workflow +- Clean migration path for existing users with legacy artifacts +- Remove all code related to config files and old slash commands +- Keep the polished UX from experimental (animated welcome, searchable multi-select) + +**Non-Goals:** +- Supporting both workflows simultaneously +- Providing options to use the old workflow +- Backward compatibility for `/openspec:*` commands (breaking change) + +## Decisions + +### Decision 1: Merge into init, not into experimental + +**Choice**: Rewrite `init` to do what `experimental` does, then delete `experimental`. + +**Rationale**: `init` is the canonical setup command. Users expect `init` to set up their project. `experimental` was always meant to be temporary. + +**Alternatives considered**: +- Keep `experimental` as the main command → confusing name for default behavior +- Create new command → unnecessary, `init` already exists + +### Decision 2: Legacy cleanup with Y/N prompt + +**Choice**: Detect legacy artifacts, show what was found, prompt `"Legacy files detected. Upgrade and clean up? [Y/n]"`, then remove if confirmed. + +**Rationale**: Users should know what's being removed. A single Y/N is simple and decisive. No need for multiple options. + +**Alternatives considered**: +- Multiple options (keep/remove/cancel) → overcomplicated +- Silent removal → users might be surprised +- Just warn without removing → leaves cruft + +### Decision 3: Surgical removal of legacy content + +**Choice**: For files with mixed content (OpenSpec markers + user content), only remove the OpenSpec marker block. For files that are 100% OpenSpec content, delete the entire file. + +**Rationale**: Respects user customizations. CLAUDE.md might have other instructions beyond OpenSpec. + +**Edge cases**: +- **Config files with mixed content**: Remove only `` to `` block +- **Config files that are 100% OpenSpec**: Delete file entirely (check if content outside markers is empty/whitespace) +- **Old slash command directories** (`.claude/commands/openspec/`): Delete entire directory (ours) +- **`openspec/AGENTS.md` and `project.md`**: Delete (ours) +- **Root `AGENTS.md`**: Only remove OpenSpec marker block, preserve rest + +### Decision 4: Hidden alias for experimental + +**Choice**: Keep `openspec experimental` as a hidden command that delegates to `init`. + +**Rationale**: Users who learned `experimental` can still use it during transition. Hidden means it won't show in help. + +### Decision 5: Reuse existing infrastructure + +**Choice**: Reuse skill templates, command adapters, welcome screen, and multi-select from experimental. + +**Rationale**: Already built and working. Just needs to be called from init instead of experimental. + +## Risks / Trade-offs + +| Risk | Mitigation | +|------|------------| +| Users with custom `/openspec:*` commands lose them | Document in release notes; old commands are in git history | +| Mixed-content detection might be imperfect | Conservative approach: if unsure, preserve the file and warn | +| Users confused by missing config files | Clear messaging in init output about what changed | +| `openspec update` might break | Review and update `update` command to work with new structure | + +## Architecture + +### What init creates (after merge) + +``` +openspec/ + ├── config.yaml # Schema settings (from experimental) + ├── specs/ # Empty, for user's specs + └── changes/ # Empty, for user's changes + └── archive/ + +./skills/ # 9 skills per selected tool + ├── openspec-explore/SKILL.md + ├── openspec-new-change/SKILL.md + ├── openspec-continue-change/SKILL.md + ├── openspec-apply-change/SKILL.md + ├── openspec-ff-change/SKILL.md + ├── openspec-verify-change/SKILL.md + ├── openspec-sync-specs/SKILL.md + ├── openspec-archive-change/SKILL.md + └── openspec-bulk-archive-change/SKILL.md + +./commands/opsx/ # 9 slash commands per selected tool + ├── explore.md + ├── new.md + ├── continue.md + ├── apply.md + ├── ff.md + ├── verify.md + ├── sync.md + ├── archive.md + └── bulk-archive.md +``` + +### What init no longer creates + +- `CLAUDE.md`, `.cursorrules`, `.windsurfrules`, etc. (config files) +- `openspec/AGENTS.md` +- `openspec/project.md` +- Root `AGENTS.md` stub +- `.claude/commands/openspec/` (old slash commands) + +### Legacy detection targets + +| Artifact Type | Detection Method | Removal Method | +|--------------|------------------|----------------| +| Config files (CLAUDE.md, etc.) | File exists AND contains OpenSpec markers | Remove marker block; delete file if empty after | +| Old slash command dirs | Directory exists at `./commands/openspec/` | Delete entire directory | +| openspec/AGENTS.md | File exists at `openspec/AGENTS.md` | Delete file | +| openspec/project.md | File exists at `openspec/project.md` | Delete file | +| Root AGENTS.md | File exists at `AGENTS.md` AND contains OpenSpec markers | Remove marker block; delete file if empty after | + +### Code to remove + +- `src/core/configurators/` - entire directory (ToolRegistry, all config generators) +- `src/core/configurators/slash/` - entire directory (SlashCommandRegistry, old command generators) +- `src/core/templates/slash-command-templates.ts` - old `/openspec:*` content +- `src/core/templates/claude-template.ts` +- `src/core/templates/cline-template.ts` +- `src/core/templates/costrict-template.ts` +- `src/core/templates/agents-template.ts` +- `src/core/templates/agents-root-stub.ts` +- `src/core/templates/project-template.ts` +- `src/commands/experimental/` - entire directory (merged into init) +- Related test files + +### Code to migrate into init + +- Animated welcome screen (`src/ui/welcome-screen.ts`) - keep, call from init +- Searchable multi-select (`src/prompts/searchable-multi-select.ts`) - keep, call from init +- Skill templates (`src/core/templates/skill-templates.ts`) - keep +- Command generation (`src/core/command-generation/`) - keep +- Tool states detection (from `experimental/setup.ts`) - move to init + +## Open Questions + +1. **What happens to `openspec update`?** - Currently updates config files and AGENTS.md. Needs to be updated to refresh skills/commands instead. + +2. **Should we keep `openspec schemas` and other experimental subcommands?** - These are useful for the workflow. Probably keep them but remove "[Experimental]" label. diff --git a/openspec/changes/merge-init-experimental/proposal.md b/openspec/changes/merge-init-experimental/proposal.md new file mode 100644 index 00000000..c7d25dad --- /dev/null +++ b/openspec/changes/merge-init-experimental/proposal.md @@ -0,0 +1,32 @@ +## Why + +The current setup has two separate commands (`openspec init` and `openspec experimental`) that configure different parts of the OpenSpec workflow. This creates confusion about which command to run, results in partial setups, and maintains two parallel systems (config files + old slash commands vs skills + opsx commands). Making the skill-based workflow the default simplifies onboarding and establishes a single, consistent way to use OpenSpec. + +## What Changes + +- **BREAKING**: `openspec init` now generates skills and `/opsx:*` commands instead of config files and `/openspec:*` commands +- **BREAKING**: Config files (`CLAUDE.md`, `.cursorrules`, etc.) are no longer generated +- **BREAKING**: Old slash commands (`/openspec:proposal`, `/openspec:apply`, `/openspec:archive`) are no longer generated +- **BREAKING**: `openspec/AGENTS.md` and `openspec/project.md` are no longer generated +- Merge `experimental` command functionality into `init` +- Add legacy detection and auto-cleanup with Y/N confirmation +- Keep `openspec experimental` as hidden alias for backward compatibility +- Use the animated welcome screen from experimental for the unified init + +## Capabilities + +### New Capabilities + +- `legacy-cleanup`: Detect and remove legacy OpenSpec artifacts (config files, old slash commands, AGENTS.md) during init + +### Modified Capabilities + +- `cli-init`: Complete rewrite - generates skills and opsx commands instead of config files and old slash commands; removes AGENTS.md/project.md generation; adds legacy cleanup; uses experimental's animated welcome screen + +## Impact + +- **Code removal**: `ToolRegistry`, `SlashCommandRegistry`, config file generators, old slash command templates, AGENTS.md/project.md templates +- **Code migration**: Move skill generation and command adapter logic from `experimental/setup.ts` into `init.ts` +- **Commands affected**: `init` (rewritten), `experimental` (becomes hidden alias), `update` (may need adjustment) +- **User migration**: Existing users running `init` will be prompted to clean up legacy files +- **Breaking for**: Users relying on config files for passive triggering, users using `/openspec:*` commands diff --git a/openspec/changes/merge-init-experimental/specs/cli-init/spec.md b/openspec/changes/merge-init-experimental/specs/cli-init/spec.md new file mode 100644 index 00000000..db26a35d --- /dev/null +++ b/openspec/changes/merge-init-experimental/specs/cli-init/spec.md @@ -0,0 +1,176 @@ +## MODIFIED Requirements + +### Requirement: Directory Creation + +The command SHALL create the OpenSpec directory structure with config file. + +#### Scenario: Creating OpenSpec structure + +- **WHEN** `openspec init` is executed +- **THEN** create the following directory structure: +``` +openspec/ +├── config.yaml +├── specs/ +└── changes/ + └── archive/ +``` + +### Requirement: AI Tool Configuration + +The command SHALL configure AI coding assistants with skills and slash commands using a searchable multi-select experience. + +#### Scenario: Prompting for AI tool selection + +- **WHEN** run interactively +- **THEN** display animated welcome screen with OpenSpec logo +- **AND** present a searchable multi-select that shows all available tools +- **AND** mark already configured tools with "(configured ✓)" indicator +- **AND** pre-select configured tools for easy refresh +- **AND** sort configured tools to appear first in the list +- **AND** allow filtering by typing to search + +#### Scenario: Selecting tools to configure + +- **WHEN** user selects tools and confirms +- **THEN** generate skills in `./skills/` directory for each selected tool +- **AND** generate slash commands in `./commands/opsx/` directory for each selected tool +- **AND** create `openspec/config.yaml` with default schema setting + +### Requirement: Skill Generation + +The command SHALL generate Agent Skills for selected AI tools. + +#### Scenario: Generating skills for a tool + +- **WHEN** a tool is selected during initialization +- **THEN** create 9 skill directories under `./skills/`: + - `openspec-explore/SKILL.md` + - `openspec-new-change/SKILL.md` + - `openspec-continue-change/SKILL.md` + - `openspec-apply-change/SKILL.md` + - `openspec-ff-change/SKILL.md` + - `openspec-verify-change/SKILL.md` + - `openspec-sync-specs/SKILL.md` + - `openspec-archive-change/SKILL.md` + - `openspec-bulk-archive-change/SKILL.md` +- **AND** each SKILL.md SHALL contain YAML frontmatter with name and description +- **AND** each SKILL.md SHALL contain the skill instructions + +### Requirement: Slash Command Generation + +The command SHALL generate opsx slash commands for selected AI tools. + +#### Scenario: Generating slash commands for a tool + +- **WHEN** a tool is selected during initialization +- **THEN** create 9 slash command files using the tool's command adapter: + - `/opsx:explore` + - `/opsx:new` + - `/opsx:continue` + - `/opsx:apply` + - `/opsx:ff` + - `/opsx:verify` + - `/opsx:sync` + - `/opsx:archive` + - `/opsx:bulk-archive` +- **AND** use tool-specific path conventions (e.g., `.claude/commands/opsx/` for Claude) +- **AND** include tool-specific frontmatter format + +### Requirement: Success Output + +The command SHALL provide clear, actionable next steps upon successful initialization. + +#### Scenario: Displaying success message + +- **WHEN** initialization completes successfully +- **THEN** display categorized summary: + - "Created: " for newly configured tools + - "Refreshed: " for already-configured tools that were updated + - Count of skills and commands generated +- **AND** display getting started section with: + - `/opsx:new` - Start a new change + - `/opsx:continue` - Create the next artifact + - `/opsx:apply` - Implement tasks +- **AND** display links to documentation and feedback + +#### Scenario: Displaying restart instruction + +- **WHEN** initialization completes successfully and tools were created or refreshed +- **THEN** display instruction to restart IDE for slash commands to take effect + +### Requirement: Config File Generation + +The command SHALL create an OpenSpec config file with schema settings. + +#### Scenario: Creating config.yaml + +- **WHEN** initialization completes +- **AND** config.yaml does not exist +- **THEN** create `openspec/config.yaml` with default schema setting +- **AND** display config location in output + +#### Scenario: Preserving existing config.yaml + +- **WHEN** initialization runs in extend mode +- **AND** `openspec/config.yaml` already exists +- **THEN** preserve the existing config file +- **AND** display "(exists)" indicator in output + +### Requirement: Non-Interactive Mode + +The command SHALL support non-interactive operation through command-line options. + +#### Scenario: Select all tools non-interactively + +- **WHEN** run with `--tools all` +- **THEN** automatically select every available AI tool without prompting +- **AND** proceed with skill and command generation + +#### Scenario: Select specific tools non-interactively + +- **WHEN** run with `--tools claude,cursor` +- **THEN** parse the comma-separated tool IDs +- **AND** generate skills and commands for specified tools only + +#### Scenario: Skip tool configuration non-interactively + +- **WHEN** run with `--tools none` +- **THEN** create only the openspec directory structure and config.yaml +- **AND** skip skill and command generation + +### Requirement: Experimental Command Alias + +The command SHALL maintain backward compatibility with the experimental command. + +#### Scenario: Running openspec experimental + +- **WHEN** user runs `openspec experimental` +- **THEN** delegate to `openspec init` +- **AND** the command SHALL be hidden from help output + +## REMOVED Requirements + +### Requirement: File Generation + +**Reason**: AGENTS.md and project.md are no longer generated. Skills contain all necessary instructions. + +**Migration**: Skills in `./skills/` provide all OpenSpec workflow instructions. No manual file needed. + +### Requirement: AI Tool Configuration Details + +**Reason**: Config files (CLAUDE.md, .cursorrules, etc.) are replaced by skills. + +**Migration**: Use skills in `./skills/` instead of config files. Skills provide richer, tool-specific instructions. + +### Requirement: Slash Command Configuration + +**Reason**: Old `/openspec:*` slash commands are replaced by `/opsx:*` commands with richer functionality. + +**Migration**: Use `/opsx:new`, `/opsx:continue`, `/opsx:apply` instead of `/openspec:proposal`, `/openspec:apply`, `/openspec:archive`. + +### Requirement: Root instruction stub + +**Reason**: Root AGENTS.md stub is no longer needed. Skills provide tool-specific instructions. + +**Migration**: Skills are loaded automatically by supporting tools. No root stub needed. diff --git a/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md b/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md new file mode 100644 index 00000000..c650fa59 --- /dev/null +++ b/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md @@ -0,0 +1,127 @@ +## ADDED Requirements + +### Requirement: Legacy artifact detection + +The system SHALL detect legacy OpenSpec artifacts from previous init versions. + +#### Scenario: Detecting legacy config files + +- **WHEN** running `openspec init` on an existing project +- **THEN** the system SHALL check for config files with OpenSpec markers: + - `CLAUDE.md` + - `.cursorrules` + - `.windsurfrules` + - `.clinerules` + - `.kilocode_rules` + - `.github/copilot-instructions.md` + - `.amazonq/instructions.md` + - `CODEBUDDY.md` + - `IFLOW.md` + - And all other tool config files from the legacy ToolRegistry + +#### Scenario: Detecting legacy slash command directories + +- **WHEN** running `openspec init` on an existing project +- **THEN** the system SHALL check for old slash command directories: + - `.claude/commands/openspec/` + - `.cursor/commands/openspec/` (note: old format used `openspec-*.md` in commands root) + - `.windsurf/workflows/openspec-*.md` + - And equivalent directories for all tools in the legacy SlashCommandRegistry + +#### Scenario: Detecting legacy OpenSpec structure files + +- **WHEN** running `openspec init` on an existing project +- **THEN** the system SHALL check for: + - `openspec/AGENTS.md` + - `openspec/project.md` + - Root `AGENTS.md` with OpenSpec markers + +### Requirement: Legacy cleanup confirmation + +The system SHALL prompt for confirmation before removing legacy artifacts. + +#### Scenario: Prompting for cleanup when legacy detected + +- **WHEN** legacy artifacts are detected +- **THEN** the system SHALL display what was found +- **AND** prompt: "Legacy files detected. Upgrade and clean up? [Y/n]" +- **AND** default to Yes if user presses Enter + +#### Scenario: User confirms cleanup + +- **WHEN** user responds Y or presses Enter +- **THEN** the system SHALL remove legacy artifacts +- **AND** proceed with skill-based setup + +#### Scenario: User declines cleanup + +- **WHEN** user responds N +- **THEN** the system SHALL abort initialization +- **AND** display message suggesting manual cleanup or using `--force` flag + +#### Scenario: Non-interactive mode + +- **WHEN** running with `--no-interactive` or in CI environment +- **AND** legacy artifacts are detected +- **THEN** the system SHALL abort with exit code 1 +- **AND** display detected legacy artifacts +- **AND** suggest running interactively or using `--force` flag + +### Requirement: Surgical removal of config file content + +The system SHALL preserve user content when removing OpenSpec markers from config files. + +#### Scenario: Config file with only OpenSpec content + +- **WHEN** a config file contains only OpenSpec marker block (whitespace outside is acceptable) +- **THEN** the system SHALL delete the entire file + +#### Scenario: Config file with mixed content + +- **WHEN** a config file contains content outside OpenSpec markers +- **THEN** the system SHALL remove only the `` to `` block +- **AND** preserve all content before and after the markers +- **AND** clean up any resulting double blank lines + +#### Scenario: Root AGENTS.md with mixed content + +- **WHEN** root `AGENTS.md` contains OpenSpec markers AND other content +- **THEN** the system SHALL remove only the OpenSpec marker block +- **AND** preserve the rest of the file + +### Requirement: Legacy directory removal + +The system SHALL remove legacy slash command directories entirely. + +#### Scenario: Removing old slash command directory + +- **WHEN** a legacy slash command directory exists (e.g., `.claude/commands/openspec/`) +- **THEN** the system SHALL delete the entire directory and its contents +- **AND** NOT delete the parent directory (e.g., `.claude/commands/` remains) + +#### Scenario: Removing legacy OpenSpec files + +- **WHEN** `openspec/AGENTS.md` or `openspec/project.md` exists +- **THEN** the system SHALL delete these files +- **AND** NOT delete the `openspec/` directory itself + +### Requirement: Cleanup reporting + +The system SHALL report what was cleaned up. + +#### Scenario: Displaying cleanup summary + +- **WHEN** legacy cleanup completes +- **THEN** the system SHALL display a summary section: + ``` + Cleaned up legacy files: + ✗ Removed CLAUDE.md (replaced by skills) + ✗ Removed .claude/commands/openspec/ (replaced by /opsx:*) + ✗ Removed openspec/AGENTS.md (no longer needed) + ``` + +#### Scenario: No legacy detected + +- **WHEN** no legacy artifacts are found +- **THEN** the system SHALL NOT display the cleanup section +- **AND** proceed directly with skill setup diff --git a/openspec/changes/merge-init-experimental/tasks.md b/openspec/changes/merge-init-experimental/tasks.md new file mode 100644 index 00000000..0ec1cdfa --- /dev/null +++ b/openspec/changes/merge-init-experimental/tasks.md @@ -0,0 +1,66 @@ +## 1. Legacy Detection & Cleanup Module + +- [ ] 1.1 Create `src/core/legacy-cleanup.ts` with detection functions for all legacy artifact types +- [ ] 1.2 Implement `detectLegacyConfigFiles()` - check for config files with OpenSpec markers +- [ ] 1.3 Implement `detectLegacySlashCommands()` - check for old `/openspec:*` command directories +- [ ] 1.4 Implement `detectLegacyStructureFiles()` - check for AGENTS.md, project.md +- [ ] 1.5 Implement `removeMarkerBlock()` - surgically remove OpenSpec marker blocks from files +- [ ] 1.6 Implement `cleanupLegacyArtifacts()` - orchestrate removal with proper edge case handling +- [ ] 1.7 Add unit tests for legacy detection and cleanup functions + +## 2. Rewrite Init Command + +- [ ] 2.1 Replace `src/core/init.ts` with new implementation using experimental's approach +- [ ] 2.2 Import and use animated welcome screen from `src/ui/welcome-screen.ts` +- [ ] 2.3 Import and use searchable multi-select from `src/prompts/searchable-multi-select.ts` +- [ ] 2.4 Integrate legacy detection at start of init flow +- [ ] 2.5 Add Y/N prompt for legacy cleanup confirmation +- [ ] 2.6 Generate skills using existing `skill-templates.ts` +- [ ] 2.7 Generate slash commands using existing `command-generation/` adapters +- [ ] 2.8 Create `openspec/config.yaml` with default schema +- [ ] 2.9 Update success output to match new workflow (skills, /opsx:* commands) +- [ ] 2.10 Add `--force` flag to skip legacy cleanup prompt in non-interactive mode + +## 3. Remove Legacy Code + +- [ ] 3.1 Delete `src/core/configurators/` directory (ToolRegistry, all config generators) +- [ ] 3.2 Delete `src/core/templates/slash-command-templates.ts` +- [ ] 3.3 Delete `src/core/templates/claude-template.ts` +- [ ] 3.4 Delete `src/core/templates/cline-template.ts` +- [ ] 3.5 Delete `src/core/templates/costrict-template.ts` +- [ ] 3.6 Delete `src/core/templates/agents-template.ts` +- [ ] 3.7 Delete `src/core/templates/agents-root-stub.ts` +- [ ] 3.8 Delete `src/core/templates/project-template.ts` +- [ ] 3.9 Delete `src/commands/experimental/` directory +- [ ] 3.10 Update `src/core/templates/index.ts` to remove deleted exports +- [ ] 3.11 Delete related test files for removed modules + +## 4. Update CLI Registration + +- [ ] 4.1 Update `src/cli/index.ts` to remove `registerArtifactWorkflowCommands()` call +- [ ] 4.2 Keep experimental subcommands (status, instructions, schemas, etc.) but register directly +- [ ] 4.3 Remove "[Experimental]" labels from kept subcommands +- [ ] 4.4 Add hidden `experimental` command as alias to `init` + +## 5. Update Related Commands + +- [ ] 5.1 Update `openspec update` command to refresh skills/commands instead of config files +- [ ] 5.2 Remove config file refresh logic from update +- [ ] 5.3 Add skill refresh logic to update + +## 6. Testing & Verification + +- [ ] 6.1 Add integration tests for new init flow (fresh install) +- [ ] 6.2 Add integration tests for legacy detection and cleanup +- [ ] 6.3 Add integration tests for extend mode (re-running init) +- [ ] 6.4 Test non-interactive mode with `--tools` flag +- [ ] 6.5 Test `--force` flag for CI environments +- [ ] 6.6 Verify cross-platform path handling (use path.join throughout) +- [ ] 6.7 Run full test suite and fix any broken tests + +## 7. Documentation & Cleanup + +- [ ] 7.1 Update README with new init behavior +- [ ] 7.2 Document breaking changes for release notes +- [ ] 7.3 Remove any orphaned imports/references to deleted modules +- [ ] 7.4 Run linter and fix any issues From 4a687b8943035cc89d0418bebbb67c880259dca1 Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Thu, 22 Jan 2026 22:54:41 -0800 Subject: [PATCH 2/3] docs(change): preserve project.md with migration hint instead of deleting Update merge-init-experimental change artifacts to preserve openspec/project.md during legacy cleanup instead of auto-deleting it. Users will see a migration hint directing them to move content to config.yaml's context field. Changes: - design.md: Add Decision 6 documenting rationale and migration path - spec.md: Add project.md migration hint requirement and scenarios - tasks.md: Add task 1.7 for migration hint output This avoids losing user-written project documentation while guiding them to the new config.yaml approach. --- .../changes/merge-init-experimental/design.md | 26 ++++++++++- .../specs/legacy-cleanup/spec.md | 43 ++++++++++++++++--- .../changes/merge-init-experimental/tasks.md | 7 +-- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/openspec/changes/merge-init-experimental/design.md b/openspec/changes/merge-init-experimental/design.md index 363d4ffc..0737f8da 100644 --- a/openspec/changes/merge-init-experimental/design.md +++ b/openspec/changes/merge-init-experimental/design.md @@ -53,9 +53,31 @@ The skill-based workflow (experimental) is the direction we're going, so we're m - **Config files with mixed content**: Remove only `` to `` block - **Config files that are 100% OpenSpec**: Delete file entirely (check if content outside markers is empty/whitespace) - **Old slash command directories** (`.claude/commands/openspec/`): Delete entire directory (ours) -- **`openspec/AGENTS.md` and `project.md`**: Delete (ours) +- **`openspec/AGENTS.md`**: Delete (ours) - **Root `AGENTS.md`**: Only remove OpenSpec marker block, preserve rest +### Decision 6: Preserve project.md with migration hint + +**Choice**: Do NOT auto-delete `openspec/project.md`. Preserve it and show a message directing users to manually migrate content to `config.yaml`'s `context:` field. + +**Rationale**: +- `project.md` may contain valuable user-written project documentation +- The new workflow uses `config.yaml.context` for the same purpose (auto-injected into artifacts) +- Auto-deleting would lose user content; auto-migrating is complex (needs LLM to compress) +- Users can migrate manually or use `/opsx:explore` to get AI assistance + +**Migration path**: +1. During legacy cleanup, detect `openspec/project.md` but do not delete +2. Show in output: "openspec/project.md still exists - migrate content to config.yaml's context: field, then delete" +3. User migrates manually or asks Claude in explore mode: "help me migrate project.md to config.yaml" +4. User deletes project.md when ready + +**Why not auto-migrate?** +- `project.md` is verbose (sections, headers, placeholders) +- `config.yaml.context` should be concise and dense +- LLM compression would be ideal but adds complexity and non-determinism to init +- Manual migration lets users decide what's actually important + ### Decision 4: Hidden alias for experimental **Choice**: Keep `openspec experimental` as a hidden command that delegates to `init`. @@ -126,7 +148,7 @@ openspec/ | Config files (CLAUDE.md, etc.) | File exists AND contains OpenSpec markers | Remove marker block; delete file if empty after | | Old slash command dirs | Directory exists at `./commands/openspec/` | Delete entire directory | | openspec/AGENTS.md | File exists at `openspec/AGENTS.md` | Delete file | -| openspec/project.md | File exists at `openspec/project.md` | Delete file | +| openspec/project.md | File exists at `openspec/project.md` | **Preserve** - show migration hint only | | Root AGENTS.md | File exists at `AGENTS.md` AND contains OpenSpec markers | Remove marker block; delete file if empty after | ### Code to remove diff --git a/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md b/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md index c650fa59..9602e83a 100644 --- a/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md +++ b/openspec/changes/merge-init-experimental/specs/legacy-cleanup/spec.md @@ -33,7 +33,7 @@ The system SHALL detect legacy OpenSpec artifacts from previous init versions. - **WHEN** running `openspec init` on an existing project - **THEN** the system SHALL check for: - `openspec/AGENTS.md` - - `openspec/project.md` + - `openspec/project.md` (for migration messaging only, not deleted) - Root `AGENTS.md` with OpenSpec markers ### Requirement: Legacy cleanup confirmation @@ -99,12 +99,34 @@ The system SHALL remove legacy slash command directories entirely. - **THEN** the system SHALL delete the entire directory and its contents - **AND** NOT delete the parent directory (e.g., `.claude/commands/` remains) -#### Scenario: Removing legacy OpenSpec files +#### Scenario: Removing legacy AGENTS.md -- **WHEN** `openspec/AGENTS.md` or `openspec/project.md` exists -- **THEN** the system SHALL delete these files +- **WHEN** `openspec/AGENTS.md` exists +- **THEN** the system SHALL delete the file - **AND** NOT delete the `openspec/` directory itself +### Requirement: project.md migration hint + +The system SHALL preserve project.md and display a migration hint instead of deleting it. + +#### Scenario: project.md exists during upgrade + +- **WHEN** `openspec/project.md` exists during legacy cleanup +- **THEN** the system SHALL NOT delete the file +- **AND** the system SHALL display a migration hint in the output: + ``` + Manual migration needed: + → openspec/project.md still exists + Move useful content to config.yaml's "context:" field, then delete + ``` + +#### Scenario: project.md migration rationale + +- **GIVEN** project.md may contain user-written project documentation +- **AND** config.yaml's context field serves the same purpose (auto-injected into artifacts) +- **WHEN** displaying the migration hint +- **THEN** users can migrate manually or use `/opsx:explore` to get AI assistance + ### Requirement: Cleanup reporting The system SHALL report what was cleaned up. @@ -115,9 +137,16 @@ The system SHALL report what was cleaned up. - **THEN** the system SHALL display a summary section: ``` Cleaned up legacy files: - ✗ Removed CLAUDE.md (replaced by skills) - ✗ Removed .claude/commands/openspec/ (replaced by /opsx:*) - ✗ Removed openspec/AGENTS.md (no longer needed) + ✓ Removed CLAUDE.md (replaced by skills) + ✓ Removed .claude/commands/openspec/ (replaced by /opsx:*) + ✓ Removed openspec/AGENTS.md (no longer needed) + ``` +- **AND IF** `openspec/project.md` exists +- **THEN** the system SHALL display a separate migration section: + ``` + Manual migration needed: + → openspec/project.md still exists + Move useful content to config.yaml's "context:" field, then delete ``` #### Scenario: No legacy detected diff --git a/openspec/changes/merge-init-experimental/tasks.md b/openspec/changes/merge-init-experimental/tasks.md index 0ec1cdfa..9b5584fb 100644 --- a/openspec/changes/merge-init-experimental/tasks.md +++ b/openspec/changes/merge-init-experimental/tasks.md @@ -3,10 +3,11 @@ - [ ] 1.1 Create `src/core/legacy-cleanup.ts` with detection functions for all legacy artifact types - [ ] 1.2 Implement `detectLegacyConfigFiles()` - check for config files with OpenSpec markers - [ ] 1.3 Implement `detectLegacySlashCommands()` - check for old `/openspec:*` command directories -- [ ] 1.4 Implement `detectLegacyStructureFiles()` - check for AGENTS.md, project.md +- [ ] 1.4 Implement `detectLegacyStructureFiles()` - check for AGENTS.md (project.md detected separately for messaging) - [ ] 1.5 Implement `removeMarkerBlock()` - surgically remove OpenSpec marker blocks from files -- [ ] 1.6 Implement `cleanupLegacyArtifacts()` - orchestrate removal with proper edge case handling -- [ ] 1.7 Add unit tests for legacy detection and cleanup functions +- [ ] 1.6 Implement `cleanupLegacyArtifacts()` - orchestrate removal with proper edge case handling (preserves project.md) +- [ ] 1.7 Implement migration hint output for project.md - show message directing users to migrate to config.yaml +- [ ] 1.8 Add unit tests for legacy detection and cleanup functions ## 2. Rewrite Init Command From 7e9b53bf6049c273c2c8a547d9464a2e352c68f1 Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Thu, 22 Jan 2026 23:09:29 -0800 Subject: [PATCH 3/3] docs(change): resolve open questions about update command and experimental labels --- .../changes/merge-init-experimental/design.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/openspec/changes/merge-init-experimental/design.md b/openspec/changes/merge-init-experimental/design.md index 0737f8da..3701e3c2 100644 --- a/openspec/changes/merge-init-experimental/design.md +++ b/openspec/changes/merge-init-experimental/design.md @@ -175,6 +175,19 @@ openspec/ ## Open Questions -1. **What happens to `openspec update`?** - Currently updates config files and AGENTS.md. Needs to be updated to refresh skills/commands instead. +1. **What happens to `openspec update`?** - RESOLVED -2. **Should we keep `openspec schemas` and other experimental subcommands?** - These are useful for the workflow. Probably keep them but remove "[Experimental]" label. + **Current behavior**: Updates `openspec/AGENTS.md`, config files (`CLAUDE.md`, etc.) via `ToolRegistry`, and old slash commands (`/openspec:*`) via `SlashCommandRegistry`. + + **New behavior**: Rewrite to refresh skills and opsx commands instead: + - Detect which tools have skills installed (check for `.claude/skills/openspec-*/`, etc.) + - Refresh all 9 skill files per installed tool using `skill-templates.ts` + - Refresh all 9 opsx command files per installed tool using `command-generation/` adapters + - Remove imports of `ToolRegistry`, `SlashCommandRegistry`, `agentsTemplate` + - Update output messaging to reflect skills/commands instead of config files + + **Key principle**: Same as current update - only refresh existing tools, don't add new ones. + +2. **Should we keep `openspec schemas` and other experimental subcommands?** - RESOLVED + + **Decision**: Yes, keep them. Remove "[Experimental]" label from all subcommands (status, instructions, schemas, etc.). See task 4.3.