|
| 1 | +## Context |
| 2 | + |
| 3 | +Currently `openspec init` and `openspec experimental` are separate commands with distinct purposes: |
| 4 | + |
| 5 | +- **init**: Creates `openspec/` directory, generates `AGENTS.md`/`project.md`, configures tool config files (`CLAUDE.md`, etc.), generates old slash commands (`/openspec:proposal`, etc.) |
| 6 | +- **experimental**: Generates skills (9 per tool), generates opsx slash commands (`/opsx:new`, etc.), creates `config.yaml` |
| 7 | + |
| 8 | +The skill-based workflow (experimental) is the direction we're going, so we're making it the default by merging into `init`. |
| 9 | + |
| 10 | +## Goals / Non-Goals |
| 11 | + |
| 12 | +**Goals:** |
| 13 | +- Single `openspec init` command that sets up the complete skill-based workflow |
| 14 | +- Clean migration path for existing users with legacy artifacts |
| 15 | +- Remove all code related to config files and old slash commands |
| 16 | +- Keep the polished UX from experimental (animated welcome, searchable multi-select) |
| 17 | + |
| 18 | +**Non-Goals:** |
| 19 | +- Supporting both workflows simultaneously |
| 20 | +- Providing options to use the old workflow |
| 21 | +- Backward compatibility for `/openspec:*` commands (breaking change) |
| 22 | + |
| 23 | +## Decisions |
| 24 | + |
| 25 | +### Decision 1: Merge into init, not into experimental |
| 26 | + |
| 27 | +**Choice**: Rewrite `init` to do what `experimental` does, then delete `experimental`. |
| 28 | + |
| 29 | +**Rationale**: `init` is the canonical setup command. Users expect `init` to set up their project. `experimental` was always meant to be temporary. |
| 30 | + |
| 31 | +**Alternatives considered**: |
| 32 | +- Keep `experimental` as the main command → confusing name for default behavior |
| 33 | +- Create new command → unnecessary, `init` already exists |
| 34 | + |
| 35 | +### Decision 2: Legacy cleanup with Y/N prompt |
| 36 | + |
| 37 | +**Choice**: Detect legacy artifacts, show what was found, prompt `"Legacy files detected. Upgrade and clean up? [Y/n]"`, then remove if confirmed. |
| 38 | + |
| 39 | +**Rationale**: Users should know what's being removed. A single Y/N is simple and decisive. No need for multiple options. |
| 40 | + |
| 41 | +**Alternatives considered**: |
| 42 | +- Multiple options (keep/remove/cancel) → overcomplicated |
| 43 | +- Silent removal → users might be surprised |
| 44 | +- Just warn without removing → leaves cruft |
| 45 | + |
| 46 | +### Decision 3: Surgical removal of legacy content |
| 47 | + |
| 48 | +**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. |
| 49 | + |
| 50 | +**Rationale**: Respects user customizations. CLAUDE.md might have other instructions beyond OpenSpec. |
| 51 | + |
| 52 | +**Edge cases**: |
| 53 | +- **Config files with mixed content**: Remove only `<!-- OPENSPEC:START -->` to `<!-- OPENSPEC:END -->` block |
| 54 | +- **Config files that are 100% OpenSpec**: Delete file entirely (check if content outside markers is empty/whitespace) |
| 55 | +- **Old slash command directories** (`.claude/commands/openspec/`): Delete entire directory (ours) |
| 56 | +- **`openspec/AGENTS.md`**: Delete (ours) |
| 57 | +- **Root `AGENTS.md`**: Only remove OpenSpec marker block, preserve rest |
| 58 | + |
| 59 | +### Decision 6: Preserve project.md with migration hint |
| 60 | + |
| 61 | +**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. |
| 62 | + |
| 63 | +**Rationale**: |
| 64 | +- `project.md` may contain valuable user-written project documentation |
| 65 | +- The new workflow uses `config.yaml.context` for the same purpose (auto-injected into artifacts) |
| 66 | +- Auto-deleting would lose user content; auto-migrating is complex (needs LLM to compress) |
| 67 | +- Users can migrate manually or use `/opsx:explore` to get AI assistance |
| 68 | + |
| 69 | +**Migration path**: |
| 70 | +1. During legacy cleanup, detect `openspec/project.md` but do not delete |
| 71 | +2. Show in output: "openspec/project.md still exists - migrate content to config.yaml's context: field, then delete" |
| 72 | +3. User migrates manually or asks Claude in explore mode: "help me migrate project.md to config.yaml" |
| 73 | +4. User deletes project.md when ready |
| 74 | + |
| 75 | +**Why not auto-migrate?** |
| 76 | +- `project.md` is verbose (sections, headers, placeholders) |
| 77 | +- `config.yaml.context` should be concise and dense |
| 78 | +- LLM compression would be ideal but adds complexity and non-determinism to init |
| 79 | +- Manual migration lets users decide what's actually important |
| 80 | + |
| 81 | +### Decision 4: Hidden alias for experimental |
| 82 | + |
| 83 | +**Choice**: Keep `openspec experimental` as a hidden command that delegates to `init`. |
| 84 | + |
| 85 | +**Rationale**: Users who learned `experimental` can still use it during transition. Hidden means it won't show in help. |
| 86 | + |
| 87 | +### Decision 5: Reuse existing infrastructure |
| 88 | + |
| 89 | +**Choice**: Reuse skill templates, command adapters, welcome screen, and multi-select from experimental. |
| 90 | + |
| 91 | +**Rationale**: Already built and working. Just needs to be called from init instead of experimental. |
| 92 | + |
| 93 | +## Risks / Trade-offs |
| 94 | + |
| 95 | +| Risk | Mitigation | |
| 96 | +|------|------------| |
| 97 | +| Users with custom `/openspec:*` commands lose them | Document in release notes; old commands are in git history | |
| 98 | +| Mixed-content detection might be imperfect | Conservative approach: if unsure, preserve the file and warn | |
| 99 | +| Users confused by missing config files | Clear messaging in init output about what changed | |
| 100 | +| `openspec update` might break | Review and update `update` command to work with new structure | |
| 101 | + |
| 102 | +## Architecture |
| 103 | + |
| 104 | +### What init creates (after merge) |
| 105 | + |
| 106 | +``` |
| 107 | +openspec/ |
| 108 | + ├── config.yaml # Schema settings (from experimental) |
| 109 | + ├── specs/ # Empty, for user's specs |
| 110 | + └── changes/ # Empty, for user's changes |
| 111 | + └── archive/ |
| 112 | +
|
| 113 | +.<tool>/skills/ # 9 skills per selected tool |
| 114 | + ├── openspec-explore/SKILL.md |
| 115 | + ├── openspec-new-change/SKILL.md |
| 116 | + ├── openspec-continue-change/SKILL.md |
| 117 | + ├── openspec-apply-change/SKILL.md |
| 118 | + ├── openspec-ff-change/SKILL.md |
| 119 | + ├── openspec-verify-change/SKILL.md |
| 120 | + ├── openspec-sync-specs/SKILL.md |
| 121 | + ├── openspec-archive-change/SKILL.md |
| 122 | + └── openspec-bulk-archive-change/SKILL.md |
| 123 | +
|
| 124 | +.<tool>/commands/opsx/ # 9 slash commands per selected tool |
| 125 | + ├── explore.md |
| 126 | + ├── new.md |
| 127 | + ├── continue.md |
| 128 | + ├── apply.md |
| 129 | + ├── ff.md |
| 130 | + ├── verify.md |
| 131 | + ├── sync.md |
| 132 | + ├── archive.md |
| 133 | + └── bulk-archive.md |
| 134 | +``` |
| 135 | + |
| 136 | +### What init no longer creates |
| 137 | + |
| 138 | +- `CLAUDE.md`, `.cursorrules`, `.windsurfrules`, etc. (config files) |
| 139 | +- `openspec/AGENTS.md` |
| 140 | +- `openspec/project.md` |
| 141 | +- Root `AGENTS.md` stub |
| 142 | +- `.claude/commands/openspec/` (old slash commands) |
| 143 | + |
| 144 | +### Legacy detection targets |
| 145 | + |
| 146 | +| Artifact Type | Detection Method | Removal Method | |
| 147 | +|--------------|------------------|----------------| |
| 148 | +| Config files (CLAUDE.md, etc.) | File exists AND contains OpenSpec markers | Remove marker block; delete file if empty after | |
| 149 | +| Old slash command dirs | Directory exists at `.<tool>/commands/openspec/` | Delete entire directory | |
| 150 | +| openspec/AGENTS.md | File exists at `openspec/AGENTS.md` | Delete file | |
| 151 | +| openspec/project.md | File exists at `openspec/project.md` | **Preserve** - show migration hint only | |
| 152 | +| Root AGENTS.md | File exists at `AGENTS.md` AND contains OpenSpec markers | Remove marker block; delete file if empty after | |
| 153 | + |
| 154 | +### Code to remove |
| 155 | + |
| 156 | +- `src/core/configurators/` - entire directory (ToolRegistry, all config generators) |
| 157 | +- `src/core/configurators/slash/` - entire directory (SlashCommandRegistry, old command generators) |
| 158 | +- `src/core/templates/slash-command-templates.ts` - old `/openspec:*` content |
| 159 | +- `src/core/templates/claude-template.ts` |
| 160 | +- `src/core/templates/cline-template.ts` |
| 161 | +- `src/core/templates/costrict-template.ts` |
| 162 | +- `src/core/templates/agents-template.ts` |
| 163 | +- `src/core/templates/agents-root-stub.ts` |
| 164 | +- `src/core/templates/project-template.ts` |
| 165 | +- `src/commands/experimental/` - entire directory (merged into init) |
| 166 | +- Related test files |
| 167 | + |
| 168 | +### Code to migrate into init |
| 169 | + |
| 170 | +- Animated welcome screen (`src/ui/welcome-screen.ts`) - keep, call from init |
| 171 | +- Searchable multi-select (`src/prompts/searchable-multi-select.ts`) - keep, call from init |
| 172 | +- Skill templates (`src/core/templates/skill-templates.ts`) - keep |
| 173 | +- Command generation (`src/core/command-generation/`) - keep |
| 174 | +- Tool states detection (from `experimental/setup.ts`) - move to init |
| 175 | + |
| 176 | +## Open Questions |
| 177 | + |
| 178 | +1. **What happens to `openspec update`?** - RESOLVED |
| 179 | + |
| 180 | + **Current behavior**: Updates `openspec/AGENTS.md`, config files (`CLAUDE.md`, etc.) via `ToolRegistry`, and old slash commands (`/openspec:*`) via `SlashCommandRegistry`. |
| 181 | + |
| 182 | + **New behavior**: Rewrite to refresh skills and opsx commands instead: |
| 183 | + - Detect which tools have skills installed (check for `.claude/skills/openspec-*/`, etc.) |
| 184 | + - Refresh all 9 skill files per installed tool using `skill-templates.ts` |
| 185 | + - Refresh all 9 opsx command files per installed tool using `command-generation/` adapters |
| 186 | + - Remove imports of `ToolRegistry`, `SlashCommandRegistry`, `agentsTemplate` |
| 187 | + - Update output messaging to reflect skills/commands instead of config files |
| 188 | + |
| 189 | + **Key principle**: Same as current update - only refresh existing tools, don't add new ones. |
| 190 | + |
| 191 | +2. **Should we keep `openspec schemas` and other experimental subcommands?** - RESOLVED |
| 192 | + |
| 193 | + **Decision**: Yes, keep them. Remove "[Experimental]" label from all subcommands (status, instructions, schemas, etc.). See task 4.3. |
0 commit comments