mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-03 22:13:19 +08:00
Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a88186909 | ||
|
|
493605756f | ||
|
|
7d07101363 | ||
|
|
c0f29044f9 | ||
|
|
7fe45ca330 | ||
|
|
c8e2072e3a | ||
|
|
cd5e49346f | ||
|
|
a18d992fa1 | ||
|
|
4df6a4889b | ||
|
|
9b5007dbc3 | ||
|
|
cce787ec40 | ||
|
|
94d651de8c | ||
|
|
040e382d64 | ||
|
|
caafd7c9bf | ||
|
|
144528257d | ||
|
|
af0b3418d0 | ||
|
|
7fd5417ed0 | ||
|
|
5ac1e12b83 | ||
|
|
fd7ad273c7 | ||
|
|
ea6f380fea | ||
|
|
765df47ad3 | ||
|
|
64d476f8b9 | ||
|
|
afdca0d5da | ||
|
|
61eb999f7c | ||
|
|
3d3bf96061 | ||
|
|
d199dfa407 | ||
|
|
d7d186088e | ||
|
|
6a3a1263fe | ||
|
|
1e94443a35 | ||
|
|
a0608d0bab | ||
|
|
e4c32dbe07 | ||
|
|
2d4c98e196 | ||
|
|
be6659cd39 | ||
|
|
4ba26902df | ||
|
|
5fd8e9d66c | ||
|
|
4108563731 | ||
|
|
fbef555041 | ||
|
|
92731e2263 | ||
|
|
c574e7992d | ||
|
|
62d4391268 | ||
|
|
4573c28048 | ||
|
|
0541f93ddd | ||
|
|
be51bcbc6a | ||
|
|
1d34e72f10 | ||
|
|
36fbc898da | ||
|
|
afb73cf9ec | ||
|
|
697738bc9b | ||
|
|
37686944a9 | ||
|
|
53081fb2a2 | ||
|
|
5e2e02c090 | ||
|
|
a3cee3c2f2 | ||
|
|
f27e5e809a | ||
|
|
6b545f6ebb | ||
|
|
661059b54f |
@@ -1,13 +0,0 @@
|
||||
---
|
||||
"@fission-ai/openspec": patch
|
||||
---
|
||||
|
||||
### Improvements
|
||||
|
||||
- **Nix flake maintenance** — Version now read dynamically from package.json, reducing manual sync issues
|
||||
- **Nix build optimization** — Source filtering excludes node_modules and artifacts, improving build times
|
||||
- **update-flake.sh script** — Detects when hash is already correct, skipping unnecessary rebuilds
|
||||
|
||||
### Other
|
||||
|
||||
- Updated Nix CI actions to latest versions (nix-installer v21, magic-nix-cache v13)
|
||||
@@ -3,6 +3,8 @@ name: CI
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
merge_group:
|
||||
branches: [main]
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
@@ -42,7 +44,7 @@ jobs:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -81,7 +83,7 @@ jobs:
|
||||
name: Test (${{ matrix.label }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 15
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name == 'push'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -242,7 +244,7 @@ jobs:
|
||||
validate-changesets:
|
||||
name: Validate Changesets
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'merge_group'
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
@@ -275,7 +277,7 @@ jobs:
|
||||
name: All checks passed
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test_pr, lint, nix-flake-validate]
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
if: always() && (github.event_name == 'pull_request' || github.event_name == 'merge_group')
|
||||
steps:
|
||||
- name: Verify all checks passed
|
||||
run: |
|
||||
@@ -301,7 +303,7 @@ jobs:
|
||||
name: All checks passed
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test_matrix, lint, nix-flake-validate]
|
||||
if: always() && github.event_name != 'pull_request'
|
||||
if: always() && github.event_name == 'push'
|
||||
steps:
|
||||
- name: Verify all checks passed
|
||||
run: |
|
||||
|
||||
+10
@@ -149,3 +149,13 @@ CLAUDE.md
|
||||
# Pnpm
|
||||
.pnpm-store/
|
||||
result
|
||||
|
||||
# OpenCode
|
||||
.opencode/
|
||||
opencode.json
|
||||
|
||||
# Codex
|
||||
.codex/
|
||||
|
||||
# Bob
|
||||
.bob/
|
||||
|
||||
@@ -1,5 +1,79 @@
|
||||
# @fission-ai/openspec
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#952](https://github.com/Fission-AI/OpenSpec/pull/952) [`cce787e`](https://github.com/Fission-AI/OpenSpec/commit/cce787ec4083da2b27781f6786f5ce0002909a7b) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
|
||||
|
||||
- **Junie support** — Added tool and command generation for JetBrains Junie
|
||||
- **Lingma IDE support** — Added configuration support for Lingma IDE
|
||||
- **ForgeCode support** — Added tool support for ForgeCode
|
||||
- **IBM Bob support** — Added support for IBM Bob coding assistant
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **Shell completions opt-in** — Completion install is now opt-in, fixing PowerShell encoding corruption
|
||||
- **Copilot auto-detection** — Prevented false GitHub Copilot detection from a bare `.github/` directory
|
||||
- **pi.dev command generation** — Fixed command reference transforms and template argument passing
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#760](https://github.com/Fission-AI/OpenSpec/pull/760) [`61eb999`](https://github.com/Fission-AI/OpenSpec/commit/61eb999f7c6c0fc98d2e7f3678756fce6a3f4378) Thanks [@fsilvaortiz](https://github.com/fsilvaortiz)! - fix: OpenCode adapter now uses `.opencode/commands/` (plural) to match OpenCode's official directory convention. Fixes #748.
|
||||
|
||||
- [#759](https://github.com/Fission-AI/OpenSpec/pull/759) [`afdca0d`](https://github.com/Fission-AI/OpenSpec/commit/afdca0d5dab1aa109cfd8848b2512333ccad60c3) Thanks [@fsilvaortiz](https://github.com/fsilvaortiz)! - fix: `openspec status` now exits gracefully when no changes exist instead of throwing a fatal error. Fixes #714.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#747](https://github.com/Fission-AI/OpenSpec/pull/747) [`1e94443`](https://github.com/Fission-AI/OpenSpec/commit/1e94443a3551b228eecbc89e95d96d3b9600a192) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features
|
||||
|
||||
- **Profile system** — Choose between `core` (4 essential workflows) and `custom` (pick any subset) profiles to control which skills get installed. Manage profiles with the new `openspec config profile` command
|
||||
- **Propose workflow** — New one-step workflow creates a complete change proposal with design, specs, and tasks from a single request — no need to run `new` then `ff` separately
|
||||
- **AI tool auto-detection** — `openspec init` now scans your project for existing tool directories (`.claude/`, `.cursor/`, etc.) and pre-selects detected tools
|
||||
- **Pi (pi.dev) support** — Pi coding agent is now a supported tool with prompt and skill generation
|
||||
- **Kiro support** — AWS Kiro IDE is now a supported tool with prompt and skill generation
|
||||
- **Sync prunes deselected workflows** — `openspec update` now removes command files and skill directories for workflows you've deselected, keeping your project clean
|
||||
- **Config drift warning** — `openspec config list` warns when global config is out of sync with the current project
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Fixed onboard preflight giving a false "not initialized" error on freshly initialized projects
|
||||
- Fixed archive workflow stopping mid-way when syncing — it now properly resumes after sync completes
|
||||
- Added Windows PowerShell alternatives for onboard shell commands
|
||||
|
||||
## 1.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#627](https://github.com/Fission-AI/OpenSpec/pull/627) [`afb73cf`](https://github.com/Fission-AI/OpenSpec/commit/afb73cf9ec59c6f8b26d0c538c0218c203ba3c56) Thanks [@TabishB](https://github.com/TabishB)! - ### Bug Fixes
|
||||
|
||||
- **OpenCode command references** — Command references in generated files now use the correct `/opsx-` hyphen format instead of `/opsx:` colon format, ensuring commands work properly in OpenCode
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#625](https://github.com/Fission-AI/OpenSpec/pull/625) [`53081fb`](https://github.com/Fission-AI/OpenSpec/commit/53081fb2a26ec66d2950ae0474b9a56cbc5b5a76) Thanks [@TabishB](https://github.com/TabishB)! - ### Bug Fixes
|
||||
|
||||
- **Codex global path support** — Codex adapter now resolves global paths correctly, fixing workflow file generation when run outside the project directory (#622)
|
||||
- **Archive operations on cross-device or restricted paths** — Archive now falls back to copy+remove when rename fails with EPERM or EXDEV errors, fixing failures on networked/external drives (#605)
|
||||
- **Slash command hints in workflow messages** — Workflow completion messages now display helpful slash command hints for next steps (#603)
|
||||
- **Windsurf workflow file path** — Updated Windsurf adapter to use the correct `workflows` directory instead of the legacy `commands` path (#610)
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#550](https://github.com/Fission-AI/OpenSpec/pull/550) [`86d2e04`](https://github.com/Fission-AI/OpenSpec/commit/86d2e04cae76a999dbd1b4571f52fa720036be0c) Thanks [@jerome-benoit](https://github.com/jerome-benoit)! - ### Improvements
|
||||
|
||||
- **Nix flake maintenance** — Version now read dynamically from package.json, reducing manual sync issues
|
||||
- **Nix build optimization** — Source filtering excludes node_modules and artifacts, improving build times
|
||||
- **update-flake.sh script** — Detects when hash is already correct, skipping unnecessary rebuilds
|
||||
|
||||
### Other
|
||||
|
||||
- Updated Nix CI actions to latest versions (nix-installer v21, magic-nix-cache v13)
|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -36,7 +36,7 @@ Our philosophy:
|
||||
> [!TIP]
|
||||
> **New workflow now available!** We've rebuilt OpenSpec with a new artifact-guided workflow.
|
||||
>
|
||||
> Run `/opsx:onboard` to get started. → [Learn more here](docs/opsx.md)
|
||||
> Run `/opsx:propose "your idea"` to get started. → [Learn more here](docs/opsx.md)
|
||||
|
||||
<p align="center">
|
||||
Follow <a href="https://x.com/0xTab">@0xTab on X</a> for updates · Join the <a href="https://discord.gg/YctCnvvshC">OpenSpec Discord</a> for help and questions.
|
||||
@@ -46,17 +46,14 @@ Our philosophy:
|
||||
|
||||
Using OpenSpec in a team? [Email here](mailto:teams@openspec.dev) for access to our Slack channel.
|
||||
|
||||
<!-- TODO: Add GIF demo of /opsx:new → /opsx:archive workflow -->
|
||||
<!-- TODO: Add GIF demo of /opsx:propose → /opsx:archive workflow -->
|
||||
|
||||
## See it in action
|
||||
|
||||
```text
|
||||
You: /opsx:new add-dark-mode
|
||||
You: /opsx:propose add-dark-mode
|
||||
AI: Created openspec/changes/add-dark-mode/
|
||||
Ready to create: proposal
|
||||
|
||||
You: /opsx:ff # "fast-forward" - generate all planning docs
|
||||
AI: ✓ proposal.md — why we're doing this, what's changing
|
||||
✓ proposal.md — why we're doing this, what's changing
|
||||
✓ specs/ — requirements and scenarios
|
||||
✓ design.md — technical approach
|
||||
✓ tasks.md — implementation checklist
|
||||
@@ -101,10 +98,12 @@ cd your-project
|
||||
openspec init
|
||||
```
|
||||
|
||||
Now tell your AI: `/opsx:new <what-you-want-to-build>`
|
||||
Now tell your AI: `/opsx:propose <what-you-want-to-build>`
|
||||
|
||||
If you want the expanded workflow (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:sync`, `/opsx:bulk-archive`, `/opsx:onboard`), select it with `openspec config profile` and apply with `openspec update`.
|
||||
|
||||
> [!NOTE]
|
||||
> Not sure if your tool is supported? [View the full list](docs/supported-tools.md) – we support 20+ tools and growing.
|
||||
> Not sure if your tool is supported? [View the full list](docs/supported-tools.md) – we support 25+ tools and growing.
|
||||
>
|
||||
> Also works with pnpm, yarn, bun, and nix. [See installation options](docs/installation.md).
|
||||
|
||||
|
||||
+63
-21
@@ -1,6 +1,6 @@
|
||||
# CLI Reference
|
||||
|
||||
The OpenSpec CLI (`openspec`) provides terminal commands for project setup, validation, status inspection, and management. These commands complement the AI slash commands (like `/opsx:new`) documented in [Commands](commands.md).
|
||||
The OpenSpec CLI (`openspec`) provides terminal commands for project setup, validation, status inspection, and management. These commands complement the AI slash commands (like `/opsx:propose`) documented in [Commands](commands.md).
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -67,6 +67,8 @@ These options work with all commands:
|
||||
|
||||
Initialize OpenSpec in your project. Creates the folder structure and configures AI tool integrations.
|
||||
|
||||
Default behavior uses global config defaults: profile `core`, delivery `both`, workflows `propose, explore, apply, archive`.
|
||||
|
||||
```
|
||||
openspec init [path] [options]
|
||||
```
|
||||
@@ -83,8 +85,11 @@ openspec init [path] [options]
|
||||
|--------|-------------|
|
||||
| `--tools <list>` | Configure AI tools non-interactively. Use `all`, `none`, or comma-separated list |
|
||||
| `--force` | Auto-cleanup legacy files without prompting |
|
||||
| `--profile <profile>` | Override global profile for this init run (`core` or `custom`) |
|
||||
|
||||
**Supported tools:** `amazon-q`, `antigravity`, `auggie`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `opencode`, `qoder`, `qwen`, `roocode`, `windsurf`
|
||||
`--profile custom` uses whatever workflows are currently selected in global config (`openspec config profile`).
|
||||
|
||||
**Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
|
||||
|
||||
**Examples:**
|
||||
|
||||
@@ -101,6 +106,9 @@ openspec init --tools claude,cursor
|
||||
# Configure for all supported tools
|
||||
openspec init --tools all
|
||||
|
||||
# Override profile for this run
|
||||
openspec init --profile core
|
||||
|
||||
# Skip prompts and auto-cleanup legacy files
|
||||
openspec init --force
|
||||
```
|
||||
@@ -113,8 +121,9 @@ openspec/
|
||||
├── changes/ # Proposed changes
|
||||
└── config.yaml # Project configuration
|
||||
|
||||
.claude/skills/ # Claude Code skill files (if claude selected)
|
||||
.cursor/rules/ # Cursor rules (if cursor selected)
|
||||
.claude/skills/ # Claude Code skills (if claude selected)
|
||||
.cursor/skills/ # Cursor skills (if cursor selected)
|
||||
.cursor/commands/ # Cursor OPSX commands (if delivery includes commands)
|
||||
... (other tool configs)
|
||||
```
|
||||
|
||||
@@ -122,7 +131,7 @@ openspec/
|
||||
|
||||
### `openspec update`
|
||||
|
||||
Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files.
|
||||
Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files using your current global profile, selected workflows, and delivery mode.
|
||||
|
||||
```
|
||||
openspec update [path] [options]
|
||||
@@ -428,29 +437,28 @@ openspec status --change add-dark-mode --json
|
||||
```
|
||||
Change: add-dark-mode
|
||||
Schema: spec-driven
|
||||
Progress: 2/4 artifacts complete
|
||||
|
||||
Artifacts:
|
||||
✓ proposal proposal.md exists
|
||||
✓ specs specs/ exists
|
||||
◆ design ready (requires: specs)
|
||||
○ tasks blocked (requires: design)
|
||||
|
||||
Next: Create design using /opsx:continue
|
||||
[x] proposal
|
||||
[ ] design
|
||||
[x] specs
|
||||
[-] tasks (blocked by: design)
|
||||
```
|
||||
|
||||
**Output (JSON):**
|
||||
|
||||
```json
|
||||
{
|
||||
"change": "add-dark-mode",
|
||||
"schema": "spec-driven",
|
||||
"changeName": "add-dark-mode",
|
||||
"schemaName": "spec-driven",
|
||||
"isComplete": false,
|
||||
"applyRequires": ["tasks"],
|
||||
"artifacts": [
|
||||
{"id": "proposal", "status": "complete", "path": "proposal.md"},
|
||||
{"id": "specs", "status": "complete", "path": "specs/"},
|
||||
{"id": "design", "status": "ready", "requires": ["specs"]},
|
||||
{"id": "tasks", "status": "blocked", "requires": ["design"]}
|
||||
],
|
||||
"next": "design"
|
||||
{"id": "proposal", "outputPath": "proposal.md", "status": "done"},
|
||||
{"id": "design", "outputPath": "design.md", "status": "ready"},
|
||||
{"id": "specs", "outputPath": "specs/**/*.md", "status": "done"},
|
||||
{"id": "tasks", "outputPath": "tasks.md", "status": "blocked", "missingDeps": ["design"]}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -767,6 +775,7 @@ openspec config <subcommand> [options]
|
||||
| `unset <key>` | Remove a key |
|
||||
| `reset` | Reset to defaults |
|
||||
| `edit` | Open in `$EDITOR` |
|
||||
| `profile [preset]` | Configure workflow profile interactively or via preset |
|
||||
|
||||
**Examples:**
|
||||
|
||||
@@ -794,6 +803,37 @@ openspec config reset --all --yes
|
||||
|
||||
# Edit config in your editor
|
||||
openspec config edit
|
||||
|
||||
# Configure profile with action-based wizard
|
||||
openspec config profile
|
||||
|
||||
# Fast preset: switch workflows to core (keeps delivery mode)
|
||||
openspec config profile core
|
||||
```
|
||||
|
||||
`openspec config profile` starts with a current-state summary, then lets you choose:
|
||||
- Change delivery + workflows
|
||||
- Change delivery only
|
||||
- Change workflows only
|
||||
- Keep current settings (exit)
|
||||
|
||||
If you keep current settings, no changes are written and no update prompt is shown.
|
||||
If there are no config changes but the current project files are out of sync with your global profile/delivery, OpenSpec will show a warning and suggest running `openspec update`.
|
||||
Pressing `Ctrl+C` also cancels the flow cleanly (no stack trace) and exits with code `130`.
|
||||
In the workflow checklist, `[x]` means the workflow is selected in global config. To apply those selections to project files, run `openspec update` (or choose `Apply changes to this project now?` when prompted inside a project).
|
||||
|
||||
**Interactive examples:**
|
||||
|
||||
```bash
|
||||
# Delivery-only update
|
||||
openspec config profile
|
||||
# choose: Change delivery only
|
||||
# choose delivery: Skills only
|
||||
|
||||
# Workflows-only update
|
||||
openspec config profile
|
||||
# choose: Change workflows only
|
||||
# toggle workflows in the checklist, then confirm
|
||||
```
|
||||
|
||||
---
|
||||
@@ -880,6 +920,8 @@ openspec completion uninstall
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `OPENSPEC_TELEMETRY` | Set to `0` to disable telemetry |
|
||||
| `DO_NOT_TRACK` | Set to `1` to disable telemetry (standard DNT signal) |
|
||||
| `OPENSPEC_CONCURRENCY` | Default concurrency for bulk validation (default: 6) |
|
||||
| `EDITOR` or `VISUAL` | Editor for `openspec config edit` |
|
||||
| `NO_COLOR` | Disable color output when set |
|
||||
@@ -888,7 +930,7 @@ openspec completion uninstall
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Commands](commands.md) - AI slash commands (`/opsx:new`, `/opsx:apply`, etc.)
|
||||
- [Commands](commands.md) - AI slash commands (`/opsx:propose`, `/opsx:apply`, etc.)
|
||||
- [Workflows](workflows.md) - Common patterns and when to use each command
|
||||
- [Customization](customization.md) - Create custom schemas and templates
|
||||
- [Getting Started](getting-started.md) - First-time setup guide
|
||||
|
||||
+63
-12
@@ -6,23 +6,70 @@ For workflow patterns and when to use each command, see [Workflows](workflows.md
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Default Quick Path (`core` profile)
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:propose` | Create a change and generate planning artifacts in one step |
|
||||
| `/opsx:explore` | Think through ideas before committing to a change |
|
||||
| `/opsx:new` | Start a new change |
|
||||
| `/opsx:apply` | Implement tasks from the change |
|
||||
| `/opsx:archive` | Archive a completed change |
|
||||
|
||||
### Expanded Workflow Commands (custom workflow selection)
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:new` | Start a new change scaffold |
|
||||
| `/opsx:continue` | Create the next artifact based on dependencies |
|
||||
| `/opsx:ff` | Fast-forward: create all planning artifacts at once |
|
||||
| `/opsx:apply` | Implement tasks from the change |
|
||||
| `/opsx:verify` | Validate implementation matches artifacts |
|
||||
| `/opsx:sync` | Merge delta specs into main specs |
|
||||
| `/opsx:archive` | Archive a completed change |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes at once |
|
||||
| `/opsx:onboard` | Guided tutorial through the complete workflow |
|
||||
|
||||
The default global profile is `core`. To enable expanded workflow commands, run `openspec config profile`, select workflows, then run `openspec update` in your project.
|
||||
|
||||
---
|
||||
|
||||
## Command Reference
|
||||
|
||||
### `/opsx:propose`
|
||||
|
||||
Create a new change and generate planning artifacts in one step. This is the default start command in the `core` profile.
|
||||
|
||||
**Syntax:**
|
||||
```text
|
||||
/opsx:propose [change-name-or-description]
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
| Argument | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `change-name-or-description` | No | Kebab-case name or plain-language change description |
|
||||
|
||||
**What it does:**
|
||||
- Creates `openspec/changes/<change-name>/`
|
||||
- Generates artifacts needed before implementation (for `spec-driven`: proposal, specs, design, tasks)
|
||||
- Stops when the change is ready for `/opsx:apply`
|
||||
|
||||
**Example:**
|
||||
```text
|
||||
You: /opsx:propose add-dark-mode
|
||||
|
||||
AI: Created openspec/changes/add-dark-mode/
|
||||
✓ proposal.md
|
||||
✓ specs/ui/spec.md
|
||||
✓ design.md
|
||||
✓ tasks.md
|
||||
Ready for implementation. Run /opsx:apply.
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
- Use this for the fastest end-to-end path
|
||||
- If you want step-by-step artifact control, enable expanded workflows and use `/opsx:new` + `/opsx:continue`
|
||||
|
||||
---
|
||||
|
||||
### `/opsx:explore`
|
||||
|
||||
Think through ideas, investigate problems, and clarify requirements before committing to a change.
|
||||
@@ -42,7 +89,7 @@ Think through ideas, investigate problems, and clarify requirements before commi
|
||||
- Investigates the codebase to answer questions
|
||||
- Compares options and approaches
|
||||
- Creates visual diagrams to clarify thinking
|
||||
- Can transition to `/opsx:new` when insights crystallize
|
||||
- Can transition to `/opsx:propose` (default) or `/opsx:new` (expanded workflow) when insights crystallize
|
||||
|
||||
**Example:**
|
||||
```text
|
||||
@@ -66,7 +113,7 @@ AI: Let me investigate your current auth setup...
|
||||
|
||||
You: Let's go with JWT. Can we start a change for that?
|
||||
|
||||
AI: Ready when you are. Run /opsx:new add-jwt-auth to begin.
|
||||
AI: Ready when you are. Run /opsx:propose add-jwt-auth to begin.
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
@@ -79,7 +126,9 @@ AI: Ready when you are. Run /opsx:new add-jwt-auth to begin.
|
||||
|
||||
### `/opsx:new`
|
||||
|
||||
Start a new change. Creates the change folder structure and scaffolds it with the selected schema.
|
||||
Start a new change scaffold. Creates the change folder and waits for you to generate artifacts with `/opsx:continue` or `/opsx:ff`.
|
||||
|
||||
This command is part of the expanded workflow set (not included in the default `core` profile).
|
||||
|
||||
**Syntax:**
|
||||
```
|
||||
@@ -565,13 +614,15 @@ Different AI tools use slightly different command syntax. Use the format that ma
|
||||
|
||||
| Tool | Syntax Example |
|
||||
|------|----------------|
|
||||
| Claude Code | `/opsx:new`, `/opsx:apply` |
|
||||
| Cursor | `/opsx-new`, `/opsx-apply` |
|
||||
| Windsurf | `/opsx-new`, `/opsx-apply` |
|
||||
| Copilot | `/opsx-new`, `/opsx-apply` |
|
||||
| Trae | `/openspec-new-change`, `/openspec-apply-change` |
|
||||
| Claude Code | `/opsx:propose`, `/opsx:apply` |
|
||||
| Cursor | `/opsx-propose`, `/opsx-apply` |
|
||||
| Windsurf | `/opsx-propose`, `/opsx-apply` |
|
||||
| Copilot (IDE) | `/opsx-propose`, `/opsx-apply` |
|
||||
| Trae | Skill-based invocations such as `/openspec-propose`, `/openspec-apply-change` (no generated `opsx-*` command files) |
|
||||
|
||||
The functionality is identical regardless of syntax.
|
||||
The intent is the same across tools, but how commands are surfaced can differ by integration.
|
||||
|
||||
> **Note:** GitHub Copilot commands (`.github/prompts/*.prompt.md`) are only available in IDE extensions (VS Code, JetBrains, Visual Studio). GitHub Copilot CLI does not currently support custom prompt files — see [Supported Tools](supported-tools.md) for details and workarounds.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+73
-27
@@ -7,10 +7,10 @@ This guide explains the core ideas behind OpenSpec and how they fit together. Fo
|
||||
OpenSpec is built around four principles:
|
||||
|
||||
```
|
||||
fluid not rigid — no phase gates, work on what makes sense
|
||||
fluid not rigid — no phase gates, work on what makes sense
|
||||
iterative not waterfall — learn as you build, refine as you go
|
||||
easy not complex — lightweight setup, minimal ceremony
|
||||
brownfield-first — works with existing codebases, not just greenfield
|
||||
easy not complex — lightweight setup, minimal ceremony
|
||||
brownfield-first — works with existing codebases, not just greenfield
|
||||
```
|
||||
|
||||
### Why These Principles Matter
|
||||
@@ -28,19 +28,19 @@ brownfield-first — works with existing codebases, not just greenfield
|
||||
OpenSpec organizes your work into two main areas:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ openspec/ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ ┌──────────────────────────────┐ │
|
||||
│ │ specs/ │ │ changes/ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Source of truth │◄─────│ Proposed modifications │ │
|
||||
│ │ How your system │ merge│ Each change = one folder │ │
|
||||
│ │ currently works │ │ Contains artifacts + deltas │ │
|
||||
│ │ │ │ │ │
|
||||
│ └─────────────────────┘ └──────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
┌────────────────────────────────────────────────────────────────────┐
|
||||
│ openspec/ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ ┌───────────────────────────────┐ │
|
||||
│ │ specs/ │ │ changes/ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Source of truth │◄─────│ Proposed modifications │ │
|
||||
│ │ How your system │ merge│ Each change = one folder │ │
|
||||
│ │ currently works │ │ Contains artifacts + deltas │ │
|
||||
│ │ │ │ │ │
|
||||
│ └─────────────────────┘ └───────────────────────────────┘ │
|
||||
│ │
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Specs** are the source of truth — they describe how your system currently behaves.
|
||||
@@ -133,6 +133,52 @@ The system MUST expire sessions after 30 minutes of inactivity.
|
||||
- **SHOULD** — recommended, but exceptions exist
|
||||
- **MAY** — optional
|
||||
|
||||
### What a Spec Is (and Is Not)
|
||||
|
||||
A spec is a **behavior contract**, not an implementation plan.
|
||||
|
||||
Good spec content:
|
||||
- Observable behavior users or downstream systems rely on
|
||||
- Inputs, outputs, and error conditions
|
||||
- External constraints (security, privacy, reliability, compatibility)
|
||||
- Scenarios that can be tested or explicitly validated
|
||||
|
||||
Avoid in specs:
|
||||
- Internal class/function names
|
||||
- Library or framework choices
|
||||
- Step-by-step implementation details
|
||||
- Detailed execution plans (those belong in `design.md` or `tasks.md`)
|
||||
|
||||
Quick test:
|
||||
- If implementation can change without changing externally visible behavior, it likely does not belong in the spec.
|
||||
|
||||
### Keep It Lightweight: Progressive Rigor
|
||||
|
||||
OpenSpec aims to avoid bureaucracy. Use the lightest level that still makes the change verifiable.
|
||||
|
||||
**Lite spec (default):**
|
||||
- Short behavior-first requirements
|
||||
- Clear scope and non-goals
|
||||
- A few concrete acceptance checks
|
||||
|
||||
**Full spec (for higher risk):**
|
||||
- Cross-team or cross-repo changes
|
||||
- API/contract changes, migrations, security/privacy concerns
|
||||
- Changes where ambiguity is likely to cause expensive rework
|
||||
|
||||
Most changes should stay in Lite mode.
|
||||
|
||||
### Human + Agent Collaboration
|
||||
|
||||
In many teams, humans explore and agents draft artifacts. The intended loop is:
|
||||
|
||||
1. Human provides intent, context, and constraints.
|
||||
2. Agent converts this into behavior-first requirements and scenarios.
|
||||
3. Agent keeps implementation detail in `design.md` and `tasks.md`, not `spec.md`.
|
||||
4. Validation confirms structure and clarity before implementation.
|
||||
|
||||
This keeps specs readable for humans and consistent for agents.
|
||||
|
||||
## Changes
|
||||
|
||||
A change is a proposed modification to your system, packaged as a folder with everything needed to understand and implement it.
|
||||
@@ -224,7 +270,7 @@ Delta specs describe **what's changing** relative to the current specs. See [Del
|
||||
|
||||
The design captures **technical approach** and **architecture decisions**.
|
||||
|
||||
```markdown
|
||||
````markdown
|
||||
# Design: Add Dark Mode
|
||||
|
||||
## Technical Approach
|
||||
@@ -260,7 +306,7 @@ CSS Variables (applied to :root)
|
||||
- `src/contexts/ThemeContext.tsx` (new)
|
||||
- `src/components/ThemeToggle.tsx` (new)
|
||||
- `src/styles/globals.css` (modified)
|
||||
```
|
||||
````
|
||||
|
||||
**When to update the design:**
|
||||
- Implementation reveals the approach won't work
|
||||
@@ -512,17 +558,17 @@ openspec/
|
||||
## How It All Fits Together
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
┌──────────────────────────────────────────────────────────────────────────────┐
|
||||
│ OPENSPEC FLOW │
|
||||
│ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ 1. START │ /opsx:new creates a change folder │
|
||||
│ │ 1. START │ /opsx:propose (core) or /opsx:new (expanded) │
|
||||
│ │ CHANGE │ │
|
||||
│ └───────┬────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ 2. CREATE │ /opsx:ff or /opsx:continue │
|
||||
│ │ 2. CREATE │ /opsx:ff or /opsx:continue (expanded workflow) │
|
||||
│ │ ARTIFACTS │ Creates proposal → specs → design → tasks │
|
||||
│ │ │ (based on schema dependencies) │
|
||||
│ └───────┬────────┘ │
|
||||
@@ -541,13 +587,13 @@ openspec/
|
||||
│ └───────┬────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ 5. ARCHIVE │────►│ Delta specs merge into main specs │ │
|
||||
│ │ CHANGE │ │ Change folder moves to archive/ │ │
|
||||
│ └────────────────┘ │ Specs are now the updated source of truth │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
|
||||
│ │ 5. ARCHIVE │────►│ Delta specs merge into main specs │ │
|
||||
│ │ CHANGE │ │ Change folder moves to archive/ │ │
|
||||
│ └────────────────┘ │ Specs are now the updated source of truth │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
└──────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**The virtuous cycle:**
|
||||
|
||||
+20
-40
@@ -4,33 +4,22 @@ This guide explains how OpenSpec works after you've installed and initialized it
|
||||
|
||||
## How It Works
|
||||
|
||||
OpenSpec helps you and your AI coding assistant agree on what to build before any code is written. The workflow follows a simple pattern:
|
||||
OpenSpec helps you and your AI coding assistant agree on what to build before any code is written.
|
||||
|
||||
**Default quick path (core profile):**
|
||||
|
||||
```text
|
||||
/opsx:propose ──► /opsx:apply ──► /opsx:archive
|
||||
```
|
||||
┌────────────────────┐
|
||||
│ Start a Change │ /opsx:new
|
||||
└────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────┐
|
||||
│ Create Artifacts │ /opsx:ff or /opsx:continue
|
||||
│ (proposal, specs, │
|
||||
│ design, tasks) │
|
||||
└────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────┐
|
||||
│ Implement Tasks │ /opsx:apply
|
||||
│ (AI writes code) │
|
||||
└────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────────┐
|
||||
│ Archive & Merge │ /opsx:archive
|
||||
│ Specs │
|
||||
└────────────────────┘
|
||||
|
||||
**Expanded path (custom workflow selection):**
|
||||
|
||||
```text
|
||||
/opsx:new ──► /opsx:ff or /opsx:continue ──► /opsx:apply ──► /opsx:verify ──► /opsx:archive
|
||||
```
|
||||
|
||||
The default global profile is `core`, which includes `propose`, `explore`, `apply`, and `archive`. You can enable the expanded workflow commands with `openspec config profile` and then `openspec update`.
|
||||
|
||||
## What OpenSpec Creates
|
||||
|
||||
After running `openspec init`, your project has this structure:
|
||||
@@ -131,23 +120,12 @@ The change folder moves to `openspec/changes/archive/` for audit history.
|
||||
|
||||
Let's walk through adding dark mode to an application.
|
||||
|
||||
### 1. Start the Change
|
||||
### 1. Start the Change (Default)
|
||||
|
||||
```
|
||||
You: /opsx:new add-dark-mode
|
||||
```text
|
||||
You: /opsx:propose add-dark-mode
|
||||
|
||||
AI: Created openspec/changes/add-dark-mode/
|
||||
Ready to create: proposal
|
||||
```
|
||||
|
||||
### 2. Create Artifacts
|
||||
|
||||
Use `/opsx:ff` (fast-forward) to create all planning artifacts at once:
|
||||
|
||||
```
|
||||
You: /opsx:ff
|
||||
|
||||
AI: Creating artifacts for add-dark-mode...
|
||||
✓ proposal.md — why we're doing this, what's changing
|
||||
✓ specs/ — requirements and scenarios
|
||||
✓ design.md — technical approach
|
||||
@@ -155,7 +133,9 @@ AI: Creating artifacts for add-dark-mode...
|
||||
Ready for implementation!
|
||||
```
|
||||
|
||||
### 3. What Gets Created
|
||||
If you've enabled the expanded workflow profile, you can also do this as two steps: `/opsx:new` then `/opsx:ff` (or `/opsx:continue` incrementally).
|
||||
|
||||
### 2. What Gets Created
|
||||
|
||||
**proposal.md** - Captures the intent:
|
||||
|
||||
@@ -218,7 +198,7 @@ The system SHALL allow users to choose between light and dark themes.
|
||||
- [ ] 3.2 Update components to use CSS variables
|
||||
```
|
||||
|
||||
### 4. Implement
|
||||
### 3. Implement
|
||||
|
||||
```
|
||||
You: /opsx:apply
|
||||
@@ -234,7 +214,7 @@ AI: Working through tasks...
|
||||
|
||||
During implementation, if you discover the design needs adjustment, just update the artifact and continue.
|
||||
|
||||
### 5. Archive
|
||||
### 4. Archive
|
||||
|
||||
```
|
||||
You: /opsx:archive
|
||||
|
||||
+43
-23
@@ -8,7 +8,7 @@ OPSX replaces the old phase-locked workflow with a fluid, action-based approach.
|
||||
|
||||
| Aspect | Legacy | OPSX |
|
||||
|--------|--------|------|
|
||||
| **Commands** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` | `/opsx:new`, `/opsx:continue`, `/opsx:apply`, and more |
|
||||
| **Commands** | `/openspec:proposal`, `/openspec:apply`, `/openspec:archive` | Default: `/opsx:propose`, `/opsx:apply`, `/opsx:archive` (expanded workflow commands optional) |
|
||||
| **Workflow** | Create all artifacts at once | Create incrementally or all at once—your choice |
|
||||
| **Going back** | Awkward phase gates | Natural—update any artifact anytime |
|
||||
| **Customization** | Fixed structure | Schema-driven, fully hackable |
|
||||
@@ -46,7 +46,7 @@ Only OpenSpec-managed files that are being replaced:
|
||||
- Windsurf: `.windsurf/workflows/openspec-*.md`
|
||||
- Cline: `.clinerules/workflows/openspec-*.md`
|
||||
- Roo: `.roo/commands/openspec-*.md`
|
||||
- GitHub Copilot: `.github/prompts/openspec-*.prompt.md`
|
||||
- GitHub Copilot: `.github/prompts/openspec-*.prompt.md` (IDE extensions only; not supported in Copilot CLI)
|
||||
- And others (Augment, Continue, Amazon Q, etc.)
|
||||
|
||||
The migration detects whichever tools you have configured and cleans up their legacy files.
|
||||
@@ -84,6 +84,9 @@ Don't worry about getting it perfect. We're still learning what works best here,
|
||||
|
||||
Both `openspec init` and `openspec update` detect legacy files and guide you through the same cleanup process. Use whichever fits your situation:
|
||||
|
||||
- New installs default to profile `core` (`propose`, `explore`, `apply`, `archive`).
|
||||
- Migrated installs preserve your previously installed workflows by writing a `custom` profile when needed.
|
||||
|
||||
### Using `openspec init`
|
||||
|
||||
Run this if you want to add new tools or reconfigure which tools are set up:
|
||||
@@ -141,7 +144,7 @@ Run this if you just want to migrate and refresh your existing tools to the late
|
||||
openspec update
|
||||
```
|
||||
|
||||
The update command also detects and cleans up legacy artifacts, then refreshes your skills to the latest version.
|
||||
The update command also detects and cleans up legacy artifacts, then refreshes generated skills/commands to match your current profile and delivery settings.
|
||||
|
||||
### Non-Interactive / CI Environments
|
||||
|
||||
@@ -275,30 +278,43 @@ The AI will help you identify what's essential vs. what can be trimmed.
|
||||
|
||||
## The New Commands
|
||||
|
||||
After migration, you have 9 OPSX commands instead of 3:
|
||||
Command availability is profile-dependent:
|
||||
|
||||
**Default (`core` profile):**
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:propose` | Create a change and generate planning artifacts in one step |
|
||||
| `/opsx:explore` | Think through ideas with no structure |
|
||||
| `/opsx:new` | Start a new change |
|
||||
| `/opsx:continue` | Create the next artifact (one at a time) |
|
||||
| `/opsx:ff` | Fast-forward—create all planning artifacts at once |
|
||||
| `/opsx:apply` | Implement tasks from tasks.md |
|
||||
| `/opsx:verify` | Validate implementation matches specs |
|
||||
| `/opsx:sync` | Preview spec merge (optional—archive prompts if needed) |
|
||||
| `/opsx:archive` | Finalize and archive the change |
|
||||
|
||||
**Expanded workflow (custom selection):**
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/opsx:new` | Start a new change scaffold |
|
||||
| `/opsx:continue` | Create the next artifact (one at a time) |
|
||||
| `/opsx:ff` | Fast-forward—create planning artifacts at once |
|
||||
| `/opsx:verify` | Validate implementation matches specs |
|
||||
| `/opsx:sync` | Preview/spec-merge without archiving |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes at once |
|
||||
| `/opsx:onboard` | Guided end-to-end onboarding workflow |
|
||||
|
||||
Enable expanded commands with `openspec config profile`, then run `openspec update`.
|
||||
|
||||
### Command Mapping from Legacy
|
||||
|
||||
| Legacy | OPSX Equivalent |
|
||||
|--------|-----------------|
|
||||
| `/openspec:proposal` | `/opsx:new` then `/opsx:ff` |
|
||||
| `/openspec:proposal` | `/opsx:propose` (default) or `/opsx:new` then `/opsx:ff` (expanded) |
|
||||
| `/openspec:apply` | `/opsx:apply` |
|
||||
| `/openspec:archive` | `/opsx:archive` |
|
||||
|
||||
### New Capabilities
|
||||
|
||||
These capabilities are part of the expanded workflow command set.
|
||||
|
||||
**Granular artifact creation:**
|
||||
```
|
||||
/opsx:continue
|
||||
@@ -332,14 +348,14 @@ Too bad. Phase gates don't let you go back easily.
|
||||
OPSX uses actions, not phases:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ ACTIONS (not phases) │
|
||||
│ │
|
||||
┌───────────────────────────────────────────────┐
|
||||
│ ACTIONS (not phases) │
|
||||
│ │
|
||||
│ new ◄──► continue ◄──► apply ◄──► archive │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────┴───────────┴───────────┘ │
|
||||
│ any order │
|
||||
└────────────────────────────────────────┘
|
||||
│ │ │ │ │ │
|
||||
│ └──────────┴───────────┴─────────────┘ │
|
||||
│ any order │
|
||||
└───────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Dependency Graph
|
||||
@@ -542,9 +558,10 @@ project/
|
||||
│ └── config.yaml # NEW: Project configuration
|
||||
├── .claude/
|
||||
│ └── skills/ # NEW: OPSX skills
|
||||
│ ├── openspec-propose/ # default core profile
|
||||
│ ├── openspec-explore/
|
||||
│ ├── openspec-new-change/
|
||||
│ └── ...
|
||||
│ ├── openspec-apply-change/
|
||||
│ └── ... # expanded profile adds new/continue/ff/etc.
|
||||
├── CLAUDE.md # OpenSpec markers removed, your content preserved
|
||||
└── AGENTS.md # OpenSpec markers removed, your content preserved
|
||||
```
|
||||
@@ -558,12 +575,15 @@ project/
|
||||
|
||||
### Command Cheatsheet
|
||||
|
||||
```
|
||||
/opsx:new Start a change
|
||||
/opsx:continue Create next artifact
|
||||
/opsx:ff Create all planning artifacts
|
||||
```text
|
||||
/opsx:propose Start quickly (default core profile)
|
||||
/opsx:apply Implement tasks
|
||||
/opsx:archive Finish and archive
|
||||
|
||||
# Expanded workflow (if enabled):
|
||||
/opsx:new Scaffold a change
|
||||
/opsx:continue Create next artifact
|
||||
/opsx:ff Create planning artifacts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
+24
-9
@@ -65,6 +65,8 @@ openspec init
|
||||
|
||||
This creates skills in `.claude/skills/` (or equivalent) that AI coding assistants auto-detect.
|
||||
|
||||
By default, OpenSpec uses the `core` workflow profile (`propose`, `explore`, `apply`, `archive`). If you want the expanded workflow commands (`new`, `continue`, `ff`, `verify`, `sync`, `bulk-archive`, `onboard`), configure them with `openspec config profile` and apply with `openspec update`.
|
||||
|
||||
During setup, you'll be prompted to create a **project config** (`openspec/config.yaml`). This is optional but recommended.
|
||||
|
||||
## Project Configuration
|
||||
@@ -155,13 +157,17 @@ rules:
|
||||
|
||||
| Command | What it does |
|
||||
|---------|--------------|
|
||||
| `/opsx:propose` | Create a change and generate planning artifacts in one step (default quick path) |
|
||||
| `/opsx:explore` | Think through ideas, investigate problems, clarify requirements |
|
||||
| `/opsx:new` | Start a new change |
|
||||
| `/opsx:continue` | Create the next artifact (based on what's ready) |
|
||||
| `/opsx:ff` | Fast-forward — create all planning artifacts at once |
|
||||
| `/opsx:new` | Start a new change scaffold (expanded workflow) |
|
||||
| `/opsx:continue` | Create the next artifact (expanded workflow) |
|
||||
| `/opsx:ff` | Fast-forward planning artifacts (expanded workflow) |
|
||||
| `/opsx:apply` | Implement tasks, updating artifacts as needed |
|
||||
| `/opsx:sync` | Sync delta specs to main (optional—archive prompts if needed) |
|
||||
| `/opsx:verify` | Validate implementation against artifacts (expanded workflow) |
|
||||
| `/opsx:sync` | Sync delta specs to main (expanded workflow, optional) |
|
||||
| `/opsx:archive` | Archive when done |
|
||||
| `/opsx:bulk-archive` | Archive multiple completed changes (expanded workflow) |
|
||||
| `/opsx:onboard` | Guided walkthrough of an end-to-end change (expanded workflow) |
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -169,13 +175,21 @@ rules:
|
||||
```
|
||||
/opsx:explore
|
||||
```
|
||||
Think through ideas, investigate problems, compare options. No structure required - just a thinking partner. When insights crystallize, transition to `/opsx:new` or `/opsx:ff`.
|
||||
Think through ideas, investigate problems, compare options. No structure required - just a thinking partner. When insights crystallize, transition to `/opsx:propose` (default) or `/opsx:new`/`/opsx:ff` (expanded).
|
||||
|
||||
### Start a new change
|
||||
```
|
||||
/opsx:new
|
||||
/opsx:propose
|
||||
```
|
||||
Creates the change and generates planning artifacts needed before implementation.
|
||||
|
||||
If you've enabled expanded workflows, you can instead use:
|
||||
|
||||
```text
|
||||
/opsx:new # scaffold only
|
||||
/opsx:continue # create one artifact at a time
|
||||
/opsx:ff # create all planning artifacts at once
|
||||
```
|
||||
You'll be asked what you want to build and which workflow schema to use.
|
||||
|
||||
### Create artifacts
|
||||
```
|
||||
@@ -299,6 +313,7 @@ Think of it like git branches:
|
||||
## Architecture Deep Dive
|
||||
|
||||
This section explains how OPSX works under the hood and how it compares to the legacy workflow.
|
||||
Examples in this section use the expanded command set (`new`, `continue`, etc.); default `core` users can map the same flow to `propose → apply → archive`.
|
||||
|
||||
### Philosophy: Phases vs Actions
|
||||
|
||||
@@ -356,7 +371,7 @@ This section explains how OPSX works under the hood and how it compares to the l
|
||||
│ Hardcoded Templates (TypeScript strings) │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Configurators (18+ classes, one per editor) │
|
||||
│ Tool-specific configurators/adapters │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Generated Command Files (.claude/commands/openspec/*.md) │
|
||||
@@ -604,7 +619,7 @@ artifacts:
|
||||
| **State** | Phase-based mental model | Filesystem existence |
|
||||
| **Customization** | Edit source, rebuild | Create schema.yaml |
|
||||
| **Iteration** | Phase-locked | Fluid, edit anything |
|
||||
| **Editor Support** | 18+ configurator classes | Single skills directory |
|
||||
| **Editor Support** | Tool-specific configurator/adapters | Single skills directory |
|
||||
|
||||
## Schemas
|
||||
|
||||
|
||||
+71
-48
@@ -1,44 +1,61 @@
|
||||
# Supported Tools
|
||||
|
||||
OpenSpec works with 20+ AI coding assistants. When you run `openspec init`, you'll be prompted to select which tools you use, and OpenSpec will configure the appropriate integrations.
|
||||
OpenSpec works with many AI coding assistants. When you run `openspec init`, OpenSpec configures selected tools using your active profile/workflow selection and delivery mode.
|
||||
|
||||
## How It Works
|
||||
|
||||
For each tool you select, OpenSpec installs:
|
||||
For each selected tool, OpenSpec can install:
|
||||
|
||||
1. **Skills** — Reusable instruction files that power the `/opsx:*` workflow commands
|
||||
2. **Commands** — Tool-specific slash command bindings
|
||||
1. **Skills** (if delivery includes skills): `.../skills/openspec-*/SKILL.md`
|
||||
2. **Commands** (if delivery includes commands): tool-specific `opsx-*` command files
|
||||
|
||||
By default, OpenSpec uses the `core` profile, which includes:
|
||||
- `propose`
|
||||
- `explore`
|
||||
- `apply`
|
||||
- `archive`
|
||||
|
||||
You can enable expanded workflows (`new`, `continue`, `ff`, `verify`, `sync`, `bulk-archive`, `onboard`) via `openspec config profile`, then run `openspec update`.
|
||||
|
||||
## Tool Directory Reference
|
||||
|
||||
| Tool | Skills Location | Commands Location |
|
||||
|------|-----------------|-------------------|
|
||||
| Amazon Q Developer | `.amazonq/skills/` | `.amazonq/prompts/` |
|
||||
| Antigravity | `.agent/skills/` | `.agent/workflows/` |
|
||||
| Auggie (Augment CLI) | `.augment/skills/` | `.augment/commands/` |
|
||||
| Claude Code | `.claude/skills/` | `.claude/commands/opsx/` |
|
||||
| Cline | `.cline/skills/` | `.clinerules/workflows/` |
|
||||
| CodeBuddy | `.codebuddy/skills/` | `.codebuddy/commands/opsx/` |
|
||||
| Codex | `.codex/skills/` | `.codex/prompts/` |
|
||||
| Continue | `.continue/skills/` | `.continue/prompts/` |
|
||||
| CoStrict | `.cospec/skills/` | `.cospec/openspec/commands/` |
|
||||
| Crush | `.crush/skills/` | `.crush/commands/opsx/` |
|
||||
| Cursor | `.cursor/skills/` | `.cursor/commands/` |
|
||||
| Factory Droid | `.factory/skills/` | `.factory/commands/` |
|
||||
| Gemini CLI | `.gemini/skills/` | `.gemini/commands/opsx/` |
|
||||
| GitHub Copilot | `.github/skills/` | `.github/prompts/` |
|
||||
| iFlow | `.iflow/skills/` | `.iflow/commands/` |
|
||||
| Kilo Code | `.kilocode/skills/` | `.kilocode/workflows/` |
|
||||
| OpenCode | `.opencode/skills/` | `.opencode/command/` |
|
||||
| Qoder | `.qoder/skills/` | `.qoder/commands/opsx/` |
|
||||
| Qwen Code | `.qwen/skills/` | `.qwen/commands/` |
|
||||
| RooCode | `.roo/skills/` | `.roo/commands/` |
|
||||
| Trae | `.trae/skills/` | `.trae/skills/` (via `/openspec-*`) |
|
||||
| Windsurf | `.windsurf/skills/` | `.windsurf/commands/opsx/` |
|
||||
| Tool (ID) | Skills path pattern | Command path pattern |
|
||||
|-----------|---------------------|----------------------|
|
||||
| Amazon Q Developer (`amazon-q`) | `.amazonq/skills/openspec-*/SKILL.md` | `.amazonq/prompts/opsx-<id>.md` |
|
||||
| Antigravity (`antigravity`) | `.agent/skills/openspec-*/SKILL.md` | `.agent/workflows/opsx-<id>.md` |
|
||||
| Auggie (`auggie`) | `.augment/skills/openspec-*/SKILL.md` | `.augment/commands/opsx-<id>.md` |
|
||||
| IBM Bob Shell (`bob`) | `.bob/skills/openspec-*/SKILL.md` | `.bob/commands/opsx-<id>.md` |
|
||||
| Claude Code (`claude`) | `.claude/skills/openspec-*/SKILL.md` | `.claude/commands/opsx/<id>.md` |
|
||||
| Cline (`cline`) | `.cline/skills/openspec-*/SKILL.md` | `.clinerules/workflows/opsx-<id>.md` |
|
||||
| CodeBuddy (`codebuddy`) | `.codebuddy/skills/openspec-*/SKILL.md` | `.codebuddy/commands/opsx/<id>.md` |
|
||||
| Codex (`codex`) | `.codex/skills/openspec-*/SKILL.md` | `$CODEX_HOME/prompts/opsx-<id>.md`\* |
|
||||
| ForgeCode (`forgecode`) | `.forge/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
|
||||
| Continue (`continue`) | `.continue/skills/openspec-*/SKILL.md` | `.continue/prompts/opsx-<id>.prompt` |
|
||||
| CoStrict (`costrict`) | `.cospec/skills/openspec-*/SKILL.md` | `.cospec/openspec/commands/opsx-<id>.md` |
|
||||
| Crush (`crush`) | `.crush/skills/openspec-*/SKILL.md` | `.crush/commands/opsx/<id>.md` |
|
||||
| Cursor (`cursor`) | `.cursor/skills/openspec-*/SKILL.md` | `.cursor/commands/opsx-<id>.md` |
|
||||
| Factory Droid (`factory`) | `.factory/skills/openspec-*/SKILL.md` | `.factory/commands/opsx-<id>.md` |
|
||||
| Gemini CLI (`gemini`) | `.gemini/skills/openspec-*/SKILL.md` | `.gemini/commands/opsx/<id>.toml` |
|
||||
| GitHub Copilot (`github-copilot`) | `.github/skills/openspec-*/SKILL.md` | `.github/prompts/opsx-<id>.prompt.md`\*\* |
|
||||
| iFlow (`iflow`) | `.iflow/skills/openspec-*/SKILL.md` | `.iflow/commands/opsx-<id>.md` |
|
||||
| Junie (`junie`) | `.junie/skills/openspec-*/SKILL.md` | `.junie/commands/opsx-<id>.md` |
|
||||
| Kilo Code (`kilocode`) | `.kilocode/skills/openspec-*/SKILL.md` | `.kilocode/workflows/opsx-<id>.md` |
|
||||
| Kiro (`kiro`) | `.kiro/skills/openspec-*/SKILL.md` | `.kiro/prompts/opsx-<id>.prompt.md` |
|
||||
| OpenCode (`opencode`) | `.opencode/skills/openspec-*/SKILL.md` | `.opencode/commands/opsx-<id>.md` |
|
||||
| Pi (`pi`) | `.pi/skills/openspec-*/SKILL.md` | `.pi/prompts/opsx-<id>.md` |
|
||||
| Qoder (`qoder`) | `.qoder/skills/openspec-*/SKILL.md` | `.qoder/commands/opsx/<id>.md` |
|
||||
| Qwen Code (`qwen`) | `.qwen/skills/openspec-*/SKILL.md` | `.qwen/commands/opsx-<id>.toml` |
|
||||
| RooCode (`roocode`) | `.roo/skills/openspec-*/SKILL.md` | `.roo/commands/opsx-<id>.md` |
|
||||
| Trae (`trae`) | `.trae/skills/openspec-*/SKILL.md` | Not generated (no command adapter; use skill-based `/openspec-*` invocations) |
|
||||
| Windsurf (`windsurf`) | `.windsurf/skills/openspec-*/SKILL.md` | `.windsurf/workflows/opsx-<id>.md` |
|
||||
|
||||
\* Codex commands are installed in the global Codex home (`$CODEX_HOME/prompts/` if set, otherwise `~/.codex/prompts/`), not your project directory.
|
||||
|
||||
\*\* GitHub Copilot prompt files are recognized as custom slash commands in IDE extensions (VS Code, JetBrains, Visual Studio). Copilot CLI does not currently consume `.github/prompts/*.prompt.md` directly.
|
||||
|
||||
## Non-Interactive Setup
|
||||
|
||||
For CI/CD or scripted setup, use the `--tools` flag:
|
||||
For CI/CD or scripted setup, use `--tools` (and optionally `--profile`):
|
||||
|
||||
```bash
|
||||
# Configure specific tools
|
||||
@@ -49,34 +66,40 @@ openspec init --tools all
|
||||
|
||||
# Skip tool configuration
|
||||
openspec init --tools none
|
||||
|
||||
# Override profile for this init run
|
||||
openspec init --profile core
|
||||
```
|
||||
|
||||
**Available tool IDs:** `amazon-q`, `antigravity`, `auggie`, `claude`, `cline`, `codebuddy`, `codex`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `kilocode`, `opencode`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
|
||||
**Available tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `forgecode`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kiro`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
|
||||
|
||||
## What Gets Installed
|
||||
## Workflow-Dependent Installation
|
||||
|
||||
For each tool, OpenSpec generates 10 skill files that power the OPSX workflow:
|
||||
OpenSpec installs workflow artifacts based on selected workflows:
|
||||
|
||||
| Skill | Purpose |
|
||||
|-------|---------|
|
||||
| `openspec-explore` | Thinking partner for exploring ideas |
|
||||
| `openspec-new-change` | Start a new change |
|
||||
| `openspec-continue-change` | Create the next artifact |
|
||||
| `openspec-ff-change` | Fast-forward through all planning artifacts |
|
||||
| `openspec-apply-change` | Implement tasks |
|
||||
| `openspec-verify-change` | Verify implementation completeness |
|
||||
| `openspec-sync-specs` | Sync delta specs to main (optional—archive prompts if needed) |
|
||||
| `openspec-archive-change` | Archive a completed change |
|
||||
| `openspec-bulk-archive-change` | Archive multiple changes at once |
|
||||
| `openspec-onboard` | Guided onboarding through a complete workflow cycle |
|
||||
- **Core profile (default):** `propose`, `explore`, `apply`, `archive`
|
||||
- **Custom selection:** any subset of all workflow IDs:
|
||||
`propose`, `explore`, `new`, `continue`, `apply`, `ff`, `sync`, `archive`, `bulk-archive`, `verify`, `onboard`
|
||||
|
||||
These skills are invoked via slash commands like `/opsx:new`, `/opsx:apply`, etc. See [Commands](commands.md) for the full list.
|
||||
In other words, skill/command counts are profile-dependent and delivery-dependent, not fixed.
|
||||
|
||||
## Adding a New Tool
|
||||
## Generated Skill Names
|
||||
|
||||
Want to add support for another AI coding assistant? Check out the [command adapter pattern](../CONTRIBUTING.md) or open an issue on GitHub.
|
||||
When selected by profile/workflow config, OpenSpec generates these skills:
|
||||
|
||||
---
|
||||
- `openspec-propose`
|
||||
- `openspec-explore`
|
||||
- `openspec-new-change`
|
||||
- `openspec-continue-change`
|
||||
- `openspec-apply-change`
|
||||
- `openspec-ff-change`
|
||||
- `openspec-sync-specs`
|
||||
- `openspec-archive-change`
|
||||
- `openspec-bulk-archive-change`
|
||||
- `openspec-verify-change`
|
||||
- `openspec-onboard`
|
||||
|
||||
See [Commands](commands.md) for command behavior and [CLI](cli.md) for `init`/`update` options.
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
+33
-7
@@ -28,7 +28,32 @@ OPSX (fluid actions):
|
||||
|
||||
> **Customization:** OPSX workflows are driven by schemas that define artifact sequences. See [Customization](customization.md) for details on creating custom schemas.
|
||||
|
||||
## Workflow Patterns
|
||||
## Two Modes
|
||||
|
||||
### Default Quick Path (`core` profile)
|
||||
|
||||
New installs default to `core`, which provides:
|
||||
- `/opsx:propose`
|
||||
- `/opsx:explore`
|
||||
- `/opsx:apply`
|
||||
- `/opsx:archive`
|
||||
|
||||
Typical flow:
|
||||
|
||||
```text
|
||||
/opsx:propose ──► /opsx:apply ──► /opsx:archive
|
||||
```
|
||||
|
||||
### Expanded/Full Workflow (custom selection)
|
||||
|
||||
If you want explicit scaffold-and-build commands (`/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:verify`, `/opsx:sync`, `/opsx:bulk-archive`, `/opsx:onboard`), enable them with:
|
||||
|
||||
```bash
|
||||
openspec config profile
|
||||
openspec update
|
||||
```
|
||||
|
||||
## Workflow Patterns (Expanded Mode)
|
||||
|
||||
### Quick Feature
|
||||
|
||||
@@ -408,15 +433,16 @@ For full command details and options, see [Commands](commands.md).
|
||||
|
||||
| Command | Purpose | When to Use |
|
||||
|---------|---------|-------------|
|
||||
| `/opsx:propose` | Create change + planning artifacts | Fast default path (`core` profile) |
|
||||
| `/opsx:explore` | Think through ideas | Unclear requirements, investigation |
|
||||
| `/opsx:new` | Start a change | Beginning any new work |
|
||||
| `/opsx:continue` | Create next artifact | Step-by-step artifact creation |
|
||||
| `/opsx:ff` | Create all planning artifacts | Clear scope, ready to build |
|
||||
| `/opsx:new` | Start a change scaffold | Expanded mode, explicit artifact control |
|
||||
| `/opsx:continue` | Create next artifact | Expanded mode, step-by-step artifact creation |
|
||||
| `/opsx:ff` | Create all planning artifacts | Expanded mode, clear scope |
|
||||
| `/opsx:apply` | Implement tasks | Ready to write code |
|
||||
| `/opsx:verify` | Validate implementation | Before archiving, catch mismatches |
|
||||
| `/opsx:sync` | Merge delta specs | Optional—archive prompts if needed |
|
||||
| `/opsx:verify` | Validate implementation | Expanded mode, before archiving |
|
||||
| `/opsx:sync` | Merge delta specs | Expanded mode, optional |
|
||||
| `/opsx:archive` | Complete the change | All work finished |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes | Parallel work, batch completion |
|
||||
| `/opsx:bulk-archive` | Archive multiple changes | Expanded mode, parallel work |
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-21
|
||||
@@ -0,0 +1,93 @@
|
||||
## Why
|
||||
|
||||
Parallel changes often touch the same capabilities and `cli-init`/`cli-update` behavior, but today there is no machine-readable way to express sequencing, dependencies, or expected merge order.
|
||||
|
||||
This creates three recurring problems:
|
||||
|
||||
- teams cannot tell which change should land first
|
||||
- large changes are hard to split into safe mergeable slices
|
||||
- parallel work can accidentally reintroduce assumptions already removed by another change
|
||||
|
||||
We need lightweight planning metadata and CLI guidance so contributors can safely stack plans on top of each other.
|
||||
|
||||
## What Changes
|
||||
|
||||
### 1. Add lightweight stack metadata for changes
|
||||
|
||||
Extend change metadata to support sequencing and decomposition context, for example:
|
||||
|
||||
- `dependsOn`: changes that must land first
|
||||
- `provides`: capability markers exposed by this change
|
||||
- `requires`: capability markers needed by this change
|
||||
- `touches`: capability/spec areas likely affected (advisory only; warning signal, not a hard dependency)
|
||||
- `parent`: optional parent change for split work
|
||||
|
||||
Metadata is optional and backward compatible for existing changes.
|
||||
|
||||
Ordering semantics:
|
||||
|
||||
- `dependsOn` is the source of truth for execution/archive ordering
|
||||
- `provides`/`requires` are capability contracts for validation and planning visibility
|
||||
- `provides`/`requires` do not create implicit dependency edges; authors must still declare required ordering via `dependsOn`
|
||||
|
||||
### 2. Add stack-aware validation
|
||||
|
||||
Enhance change validation to detect planning issues early:
|
||||
|
||||
- missing dependencies
|
||||
- dependency cycles
|
||||
- archive ordering violations (for example, attempting to archive a change before all `dependsOn` predecessors are archived)
|
||||
- unmatched capability markers (for example, `requires` marker with no provider in active history emits non-blocking warning)
|
||||
- overlap warnings when active changes touch the same capability
|
||||
|
||||
Validation should fail only for deterministic blockers (for example cycles or missing required dependencies), and keep overlap checks as actionable warnings.
|
||||
|
||||
### 3. Add sequencing visibility commands
|
||||
|
||||
Add lightweight CLI support to inspect and execute plan order:
|
||||
|
||||
- `openspec change graph` to show dependency DAG/order
|
||||
- `openspec change graph` validates for cycles first; when cycles are present it fails with the same deterministic cycle error as stack-aware validation
|
||||
- `openspec change next` to suggest unblocked changes ready to implement/archive
|
||||
|
||||
### 4. Add split scaffolding for large changes
|
||||
|
||||
Add helper workflow to decompose large proposals into stackable slices:
|
||||
|
||||
- `openspec change split <change-id>` scaffolds child changes with `parent` + `dependsOn`
|
||||
- generates minimal proposal/tasks stubs for each child slice
|
||||
- converts the source change into a parent planning container (no duplicate child implementation tasks)
|
||||
- re-running split for an already-split source change returns a deterministic actionable error unless `--overwrite` (alias `--force`) is passed
|
||||
- `--overwrite` / `--force` fully regenerates managed child scaffold stubs and metadata links for the split, replacing prior scaffold content
|
||||
|
||||
### 5. Document stack-first workflow
|
||||
|
||||
Update docs to describe:
|
||||
|
||||
- how to model dependencies and parent/child slices
|
||||
- when to split a large change
|
||||
- how to use graph/next validation signals during parallel development
|
||||
- migration guidance for `openspec/changes/IMPLEMENTATION_ORDER.md`:
|
||||
- machine-readable change metadata becomes the normative dependency source
|
||||
- `IMPLEMENTATION_ORDER.md` remains optional narrative context during transition
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `change-stacking-workflow`: Dependency-aware sequencing and split scaffolding for change planning
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `cli-change`: Adds graph/next/split planning commands and stack-aware validation messaging
|
||||
- `change-creation`: Supports parent/dependency metadata when creating or splitting changes
|
||||
- `openspec-conventions`: Defines optional stack metadata conventions for change proposals
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/core/project-config.ts` and related parsing/validation utilities for change metadata loading
|
||||
- `src/core/config-schema.ts` (or dedicated change schema) for stack metadata validation
|
||||
- `src/commands/change.ts` and/or `src/core/list.ts` for graph/next/split command behavior
|
||||
- `src/core/validation/*` for dependency cycle and overlap checks
|
||||
- `docs/cli.md`, `docs/concepts.md`, and contributor guidance for stack-aware workflows
|
||||
- tests for metadata parsing, graph ordering, next-item suggestions, and split scaffolding
|
||||
@@ -0,0 +1,15 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Stack Metadata Scaffolding
|
||||
Change creation workflows SHALL support optional dependency metadata for new or split changes.
|
||||
|
||||
#### Scenario: Create change with stack metadata
|
||||
- **WHEN** a change is created with stack metadata inputs
|
||||
- **THEN** creation SHALL persist metadata fields in change configuration
|
||||
- **AND** persisted metadata SHALL be validated against change metadata schema rules
|
||||
|
||||
#### Scenario: Split-generated child metadata
|
||||
- **WHEN** child changes are generated from a split workflow
|
||||
- **THEN** each child SHALL include a `parent` link to the source change
|
||||
- **AND** SHALL include dependency metadata needed for deterministic sequencing
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Stack Metadata Model
|
||||
The system SHALL support optional metadata on active changes to express sequencing and decomposition relationships.
|
||||
|
||||
#### Scenario: Optional stack metadata is present
|
||||
- **WHEN** a change includes stack metadata fields
|
||||
- **THEN** the system SHALL parse and expose `dependsOn`, `provides`, `requires`, `touches`, and `parent`
|
||||
- **AND** validation SHALL enforce normalized field shapes and value types (`dependsOn`/`provides`/`requires`/`touches` as string arrays, `parent` as string when present)
|
||||
|
||||
#### Scenario: Backward compatibility without stack metadata
|
||||
- **WHEN** a change does not include stack metadata
|
||||
- **THEN** existing behavior SHALL continue without migration steps
|
||||
- **AND** validation SHALL not fail solely because stack metadata is absent
|
||||
|
||||
### Requirement: Change Dependency Graph
|
||||
The system SHALL provide dependency-aware ordering for active changes.
|
||||
|
||||
#### Scenario: Build dependency order
|
||||
- **WHEN** users request stack planning output
|
||||
- **THEN** the system SHALL compute a dependency graph across active changes
|
||||
- **AND** SHALL return a deterministic topological order for unblocked changes
|
||||
|
||||
#### Scenario: Tie-breaking within the same dependency depth
|
||||
- **WHEN** multiple unblocked changes share the same topological dependency depth
|
||||
- **THEN** ordering SHALL break ties lexicographically by change ID
|
||||
- **AND** repeated runs over the same input SHALL return the same order
|
||||
|
||||
#### Scenario: Dependency cycle detection
|
||||
- **WHEN** active changes contain a dependency cycle
|
||||
- **THEN** validation SHALL fail with cycle details before archive or sequencing actions proceed
|
||||
- **AND** output SHALL include actionable guidance to break the cycle
|
||||
|
||||
### Requirement: Capability marker and overlap semantics
|
||||
The system SHALL treat capability markers as validation contracts and `touches` as advisory overlap signals.
|
||||
|
||||
#### Scenario: Required capability provided by an active change
|
||||
- **WHEN** change B declares `requires` marker `X`
|
||||
- **AND** active change A declares `provides` marker `X`
|
||||
- **THEN** validation SHALL require B to declare an explicit ordering edge in `dependsOn` to at least one active provider of `X`
|
||||
- **AND** validation SHALL fail if no explicit dependency is declared
|
||||
|
||||
#### Scenario: Requires marker without active provider
|
||||
- **WHEN** a change declares a `requires` marker
|
||||
- **AND** no active change declares the corresponding `provides` marker
|
||||
- **THEN** validation SHALL NOT infer an implicit dependency edge
|
||||
- **AND** ordering SHALL continue to be determined solely by explicit `dependsOn` relationships
|
||||
|
||||
#### Scenario: Requires marker satisfied by archived history
|
||||
- **WHEN** a change declares a `requires` marker
|
||||
- **AND** no active change provides that marker
|
||||
- **AND** at least one archived change in history provides that marker
|
||||
- **THEN** validation SHALL NOT warn solely about missing provider
|
||||
- **AND** SHALL continue to use explicit `dependsOn` for active ordering
|
||||
|
||||
#### Scenario: Requires marker missing in full history
|
||||
- **WHEN** a change declares a `requires` marker
|
||||
- **AND** no active or archived change in history provides that marker
|
||||
- **THEN** validation SHALL emit a non-blocking warning naming the change and missing marker
|
||||
- **AND** SHALL NOT infer an implicit dependency edge
|
||||
|
||||
#### Scenario: Overlap warning for shared touches
|
||||
- **WHEN** multiple active changes declare overlapping `touches` values
|
||||
- **THEN** validation SHALL emit a warning listing the overlapping changes and touched areas
|
||||
- **AND** validation SHALL NOT fail solely on overlap
|
||||
@@ -0,0 +1,27 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Stack Planning Commands
|
||||
The change CLI SHALL provide commands for dependency-aware sequencing of active changes.
|
||||
|
||||
#### Scenario: Show dependency graph
|
||||
- **WHEN** a user runs `openspec change graph`
|
||||
- **THEN** the CLI SHALL display dependency relationships for active changes
|
||||
- **AND** SHALL include a deterministic recommended order for execution
|
||||
|
||||
#### Scenario: Show next unblocked changes
|
||||
- **WHEN** a user runs `openspec change next`
|
||||
- **THEN** the CLI SHALL list changes that are not blocked by unresolved dependencies
|
||||
- **AND** SHALL use deterministic tie-breaking when multiple options are available
|
||||
|
||||
### Requirement: Split Large Change Scaffolding
|
||||
The change CLI SHALL support scaffolding child slices from an existing large change.
|
||||
|
||||
#### Scenario: Split command scaffolds child changes
|
||||
- **WHEN** a user runs `openspec change split <change-id>`
|
||||
- **THEN** the CLI SHALL create child change directories with proposal/tasks stubs
|
||||
- **AND** generated metadata SHALL include `parent` and dependency links back to the source change
|
||||
|
||||
#### Scenario: Re-running split on an already-split change
|
||||
- **WHEN** a user runs `openspec change split <change-id>` for a parent whose generated child directories already exist
|
||||
- **THEN** the CLI SHALL fail with a deterministic, actionable error
|
||||
- **AND** SHALL NOT mutate existing child change content unless an explicit overwrite mode is requested
|
||||
@@ -0,0 +1,29 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Stack-Aware Change Planning Conventions
|
||||
OpenSpec conventions SHALL define optional metadata fields for sequencing and decomposition across concurrent changes.
|
||||
|
||||
#### Scenario: Declaring change dependencies
|
||||
- **WHEN** authors need to sequence related changes
|
||||
- **THEN** conventions SHALL define how to declare dependencies and provided/required capability markers
|
||||
- **AND** validation guidance SHALL distinguish hard blockers from soft overlap warnings
|
||||
|
||||
#### Scenario: Dependency source of truth during migration
|
||||
- **WHEN** both stack metadata and `openspec/changes/IMPLEMENTATION_ORDER.md` are present
|
||||
- **THEN** conventions SHALL treat per-change stack metadata as the normative dependency source
|
||||
- **AND** `IMPLEMENTATION_ORDER.md` SHALL be treated as optional narrative guidance
|
||||
|
||||
#### Scenario: Explicit ordering remains required for capability markers
|
||||
- **WHEN** authors use `provides` and `requires` markers to describe capability contracts
|
||||
- **THEN** conventions SHALL require explicit `dependsOn` edges for ordering relationships
|
||||
- **AND** conventions SHALL prohibit treating `requires` as an implicit dependency edge
|
||||
|
||||
#### Scenario: Declaring advisory overlap via touches
|
||||
- **WHEN** a change may affect capability/spec areas shared by concurrent changes without requiring ordering
|
||||
- **THEN** conventions SHALL allow authors to declare `touches` with advisory area identifiers (for example capability IDs, spec area names, or paths)
|
||||
- **AND** tooling SHALL treat `touches` as informational only (no implicit dependency edge, non-blocking validation signal)
|
||||
|
||||
#### Scenario: Declaring parent-child split structure
|
||||
- **WHEN** a large change is decomposed into smaller slices
|
||||
- **THEN** conventions SHALL define parent-child metadata and expected ordering semantics
|
||||
- **AND** docs SHALL describe when to split versus keep a single change
|
||||
@@ -0,0 +1,39 @@
|
||||
## 1. Metadata Model
|
||||
|
||||
- [ ] 1.1 Add optional stack metadata fields (`dependsOn`, `provides`, `requires`, `touches`, `parent`) to change metadata schema
|
||||
- [ ] 1.2 Keep metadata backward compatible for existing changes without new fields
|
||||
- [ ] 1.3 Add tests for valid/invalid metadata and schema evolution behavior
|
||||
|
||||
## 2. Stack-Aware Validation
|
||||
|
||||
- [ ] 2.1 Detect dependency cycles and fail validation with deterministic errors
|
||||
- [ ] 2.2 Detect missing `dependsOn` targets (referenced change ID does not exist) and detect changes transitively blocked by unresolved/cyclic dependency paths
|
||||
- [ ] 2.3 Add overlap warnings for active changes that touch the same capability/spec areas
|
||||
- [ ] 2.4 Emit advisory warnings for unmatched `requires` markers when no provider exists in active history
|
||||
- [ ] 2.5 Add tests for cycle, missing dependency, overlap warning, and unmatched `requires` cases
|
||||
|
||||
## 3. Sequencing Commands
|
||||
|
||||
- [ ] 3.1 Add `openspec change graph` to display dependency order for active changes
|
||||
- [ ] 3.2 Add `openspec change next` to suggest unblocked changes in recommended order
|
||||
- [ ] 3.3 Add tests for topological ordering and deterministic tie-breaking (lexicographic by change ID at equal depth)
|
||||
|
||||
## 4. Split Scaffolding
|
||||
|
||||
- [ ] 4.1 Add `openspec change split <change-id>` to scaffold child slices
|
||||
- [ ] 4.2 Ensure generated children include parent/dependency metadata and stub proposal/tasks files
|
||||
- [ ] 4.3 Convert the source change into a parent planning container as part of split (no duplicate child implementation tasks)
|
||||
- [ ] 4.4 Add tests for split output structure, source-change parent conversion, and deterministic re-split error behavior when overwrite mode is not requested
|
||||
- [ ] 4.5 Implement and test explicit overwrite mode for `openspec change split` (`--overwrite` / `--force`) for controlled re-splitting
|
||||
|
||||
## 5. Documentation
|
||||
|
||||
- [ ] 5.1 Document stack metadata and sequencing workflow in `docs/concepts.md`
|
||||
- [ ] 5.2 Document new change commands and usage examples in `docs/cli.md`
|
||||
- [ ] 5.3 Add guidance for breaking large changes into independently mergeable slices
|
||||
- [ ] 5.4 Document migration guidance for `openspec/changes/IMPLEMENTATION_ORDER.md` as optional narrative, not dependency source of truth
|
||||
|
||||
## 6. Verification
|
||||
|
||||
- [ ] 6.1 Run targeted tests for change parsing, validation, and CLI commands
|
||||
- [ ] 6.2 Run full test suite (`pnpm test`) and resolve regressions
|
||||
@@ -1,60 +0,0 @@
|
||||
## 1. Project Setup and Command Registration
|
||||
|
||||
- [x] 1.1 Create directory structure: `src/core/dashboard/` with `index.ts`, `server.ts`, `data.ts`, `markdown.ts`
|
||||
- [x] 1.2 Register `openspec dashboard` command in `src/cli/index.ts` with `--port` and `--no-open` options
|
||||
- [x] 1.3 Create `DashboardCommand` class in `src/core/dashboard/index.ts` that validates openspec directory exists
|
||||
|
||||
## 2. Data Gathering Module
|
||||
|
||||
- [x] 2.1 Implement `getChangesData()` in `data.ts` that returns draft/active/completed changes with artifact existence status (proposal.md, specs/, design.md, tasks.md)
|
||||
- [x] 2.2 Implement `getSpecsData()` in `data.ts` that returns specs grouped by domain prefix with requirement counts
|
||||
- [x] 2.3 Implement `getArchiveData()` in `data.ts` that returns archived changes with parsed dates, sorted reverse chronologically
|
||||
- [x] 2.4 Implement `getSummary()` in `data.ts` that aggregates counts for dashboard summary section
|
||||
- [x] 2.5 Implement `getArtifactContent()` in `data.ts` that reads a markdown file by relative path with path traversal protection
|
||||
|
||||
## 3. Markdown Renderer
|
||||
|
||||
- [x] 3.1 Implement markdown-to-HTML converter in `markdown.ts` handling headings, paragraphs, bold, italic, and line breaks
|
||||
- [x] 3.2 Add support for fenced code blocks and inline code
|
||||
- [x] 3.3 Add support for unordered lists, ordered lists, and checkboxes
|
||||
- [x] 3.4 Add support for blockquotes, horizontal rules, and links
|
||||
|
||||
## 4. HTTP Server and API
|
||||
|
||||
- [x] 4.1 Implement HTTP server in `server.ts` using Node.js built-in `http` module
|
||||
- [x] 4.2 Add route `GET /` that serves the embedded single-page HTML dashboard
|
||||
- [x] 4.3 Add route `GET /api/summary` returning aggregated project data
|
||||
- [x] 4.4 Add route `GET /api/changes` returning changes with artifact status
|
||||
- [x] 4.5 Add route `GET /api/specs` returning specs grouped by domain
|
||||
- [x] 4.6 Add route `GET /api/archive` returning archive entries with pagination (default 50)
|
||||
- [x] 4.7 Add route `GET /api/artifact?path=<relative>` returning rendered markdown HTML with path traversal guard
|
||||
- [x] 4.8 Implement port selection with auto-increment from default 3000 to 3010
|
||||
- [x] 4.9 Implement cross-platform browser opening (open/xdg-open/start)
|
||||
- [x] 4.10 Add graceful shutdown on SIGINT/SIGTERM
|
||||
|
||||
## 5. Dashboard HTML/CSS/JS
|
||||
|
||||
- [x] 5.1 Create embedded HTML template with navigation tabs for Changes, Specs, and Archive sections
|
||||
- [x] 5.2 Implement Changes view with status grouping (draft/active/completed), artifact indicators, and progress bars
|
||||
- [x] 5.3 Implement Specs view with domain-prefix grouping and requirement count display
|
||||
- [x] 5.4 Implement Archive view with date-based listing and "load more" pagination
|
||||
- [x] 5.5 Implement artifact detail panel that fetches and displays rendered markdown on click
|
||||
- [x] 5.6 Add basic responsive CSS styling with monospace fonts matching terminal aesthetic
|
||||
|
||||
## 6. Testing
|
||||
|
||||
- [x] 6.1 Add unit tests for markdown renderer in `test/core/dashboard/markdown.test.ts`
|
||||
- [x] 6.2 Add unit tests for data gathering functions in `test/core/dashboard/data.test.ts`
|
||||
- [x] 6.3 Add unit tests for path traversal prevention in artifact endpoint
|
||||
- [x] 6.4 Add unit tests for port selection logic
|
||||
- [x] 6.5 Add unit tests for domain grouping logic
|
||||
- [x] 6.6 Add unit tests for archive date parsing
|
||||
|
||||
## 7. Polish and Integration
|
||||
|
||||
- [x] 7.1 Add CLI help text for the dashboard command
|
||||
- [x] 7.2 Add shell completion entries for dashboard command and its options
|
||||
- [x] 7.3 Handle edge cases: empty project, missing directories, unparseable specs
|
||||
- [x] 7.4 Ensure cross-platform path handling with `path.join()` throughout
|
||||
- [x] 7.5 Run linting and fix any issues (`pnpm run lint`)
|
||||
- [x] 7.6 Run full test suite (`pnpm test`)
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-21
|
||||
@@ -0,0 +1,161 @@
|
||||
## Context
|
||||
|
||||
OpenSpec today assumes project-local installation for most generated artifacts, with Codex command prompts as the main global exception. This mixed model works, but it is implicit and not user-configurable.
|
||||
|
||||
The requested change is to support user-selectable install scope (`global` or `project`) for tool skills/commands, defaulting to `global` for new configurations while preserving legacy project-local behavior until explicit migration.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Provide a single scope preference that users can set globally and override per run
|
||||
- Default new users to `global` scope
|
||||
- Make install path resolution deterministic and explicit across tools/surfaces
|
||||
- Preserve current behavior for users with older config files that do not yet define `installScope`
|
||||
- Avoid silent partial installs; surface effective scope decisions in output
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Implementing project-local config file support for global settings
|
||||
- Defining global install paths for tools where upstream location conventions are unknown
|
||||
- Changing workflow/profile semantics (`core`, `custom`, `delivery`) in this change
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Scope model in global config
|
||||
|
||||
Add install scope preference to global config:
|
||||
|
||||
```ts
|
||||
type InstallScope = 'global' | 'project';
|
||||
|
||||
interface GlobalConfig {
|
||||
// existing fields...
|
||||
installScope?: InstallScope;
|
||||
}
|
||||
```
|
||||
|
||||
Defaults:
|
||||
|
||||
- New configs SHOULD write `installScope: global` explicitly.
|
||||
- Existing configs without this field continue to load safely through schema evolution and SHALL resolve effective default as `project` until users explicitly set `installScope`.
|
||||
|
||||
### 2. Explicit tool scope support metadata
|
||||
|
||||
Extend `AI_TOOLS` metadata with optional scope support declarations per surface:
|
||||
|
||||
```ts
|
||||
interface ToolInstallScopeSupport {
|
||||
skills?: InstallScope[];
|
||||
commands?: InstallScope[];
|
||||
}
|
||||
```
|
||||
|
||||
Resolution rules:
|
||||
|
||||
1. If scope support metadata is absent for a tool surface, treat it as project-only support for conservative backward compatibility.
|
||||
2. Try preferred scope.
|
||||
3. If unsupported, use alternate scope when supported.
|
||||
4. If neither is supported, fail with actionable error.
|
||||
|
||||
This enables default-global behavior while remaining safe for tools that only support project-local paths.
|
||||
|
||||
### 3. Scope-aware install target resolver
|
||||
|
||||
Introduce shared resolver utilities to compute effective target paths for:
|
||||
|
||||
- skills root directory
|
||||
- command output files
|
||||
|
||||
Resolver input:
|
||||
|
||||
- tool id
|
||||
- requested scope
|
||||
- project root
|
||||
- environment context (`CODEX_HOME`, etc.)
|
||||
|
||||
Resolver output:
|
||||
|
||||
- effective scope per surface
|
||||
- concrete target paths
|
||||
- optional fallback reasons for user-facing output
|
||||
|
||||
Platform behavior:
|
||||
|
||||
- Resolver outputs are OS-aware and normalized for the current platform.
|
||||
- Windows global targets MUST use Windows path conventions (for example `%USERPROFILE%\.codex\prompts` fallback for Codex when `CODEX_HOME` is unset), not POSIX defaults.
|
||||
|
||||
### 4. Context-aware command adapter paths
|
||||
|
||||
Update command generation contract so adapters receive install context for path resolution. This avoids hardcoded absolute/relative assumptions and centralizes scope decisions.
|
||||
|
||||
Example direction:
|
||||
|
||||
```ts
|
||||
getFilePath(commandId: string, context: InstallContext): string
|
||||
```
|
||||
|
||||
### 5. CLI behavior and UX
|
||||
|
||||
`init`:
|
||||
|
||||
- Uses configured install scope by default; if absent in a legacy config, uses migration-safe effective default (`project`).
|
||||
- Supports explicit override flag (`--scope global|project`).
|
||||
- In interactive mode, displays chosen scope and any per-tool fallback decisions before writing files.
|
||||
|
||||
`update`:
|
||||
|
||||
- Applies current scope preference (or override); if absent in a legacy config, uses migration-safe effective default (`project`).
|
||||
- Performs drift detection using effective scoped paths and last-applied scope state.
|
||||
- Reports effective scope decisions in summary output.
|
||||
|
||||
`config`:
|
||||
|
||||
- `openspec config profile` interactive flow includes install scope selection.
|
||||
- `openspec config list` shows `installScope` with source annotation (`explicit`, `new-default`, or `legacy-default`).
|
||||
|
||||
### 6. Cleanup safety during scope changes
|
||||
|
||||
When scope changes:
|
||||
|
||||
- Writes occur in the new effective targets.
|
||||
- Cleanup/removal is limited to OpenSpec-managed files for the relevant tool/workflow IDs.
|
||||
- Output explicitly states which scope locations were updated and which were cleaned.
|
||||
|
||||
### 7. Scope drift state tracking
|
||||
|
||||
Track last successful effective scope per tool/surface in project-managed state.
|
||||
|
||||
Rules:
|
||||
|
||||
1. Drift is detected when current resolved scope differs from last successful scope for a configured tool/surface.
|
||||
2. Scope support MUST be validated for all configured tools/surfaces before any write starts.
|
||||
3. Update writes to newly resolved targets first, verifies completeness, then removes managed files at previous targets.
|
||||
4. If new-target writes are partial or verification fails, command SHALL abort old-target cleanup and report actionable failure with incomplete/new and preserved/old paths.
|
||||
5. Cleanup failures do not rollback new writes; command returns actionable failure with leftover paths to resolve.
|
||||
|
||||
### 8. Coordination with command-surface capability changes
|
||||
|
||||
If `add-tool-command-surface-capabilities` lands, planning logic must evaluate scope resolution and delivery/capability behavior together (scope × delivery × command surface).
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
**Risk: Cross-project shared global state**
|
||||
Global installs are shared across projects. Updating global artifacts from one project affects all projects using that tool scope.
|
||||
→ Mitigation: make scope explicit in output; keep profile/delivery global and deterministic.
|
||||
|
||||
**Risk: Tool-specific unknown global conventions**
|
||||
Not all tools document a stable global install location.
|
||||
→ Mitigation: use explicit scope support metadata; fallback or fail instead of guessing.
|
||||
|
||||
**Risk: Adapter API churn**
|
||||
Changing adapter path contracts touches many files/tests.
|
||||
→ Mitigation: migrate in one pass with adapter contract tests and existing end-to-end generation tests.
|
||||
|
||||
## Rollout Plan
|
||||
|
||||
1. Add config schema + defaults for install scope.
|
||||
2. Add tool scope capability metadata and resolver utilities.
|
||||
3. Upgrade command adapter contract and generator path plumbing.
|
||||
4. Integrate scope-aware behavior into init/update.
|
||||
5. Add documentation and test coverage.
|
||||
@@ -0,0 +1,101 @@
|
||||
## Why
|
||||
|
||||
OpenSpec installation paths are currently inconsistent:
|
||||
|
||||
- Most skills and commands are written to project-local directories.
|
||||
- Codex commands are already global (`$CODEX_HOME/prompts` or `~/.codex/prompts`).
|
||||
- Users cannot choose a consistent install scope strategy across tools.
|
||||
|
||||
This creates friction for users who prefer user-level setup and expect tool artifacts to be managed globally by default.
|
||||
|
||||
## What Changes
|
||||
|
||||
### 1. Add install scope preference with legacy-safe defaults
|
||||
|
||||
Introduce a global install scope setting with two modes:
|
||||
|
||||
- `global` (default for newly created configs)
|
||||
- `project`
|
||||
|
||||
The setting is stored in global config and can be overridden per command run.
|
||||
For schema-evolved legacy configs where `installScope` is absent, effective default remains `project` until users opt in to global scope.
|
||||
|
||||
### 2. Add scope-aware path resolution for skills and commands
|
||||
|
||||
Refactor path resolution so both `init` and `update` compute install targets from:
|
||||
|
||||
- selected scope preference (`global` or `project`)
|
||||
- tool capability metadata (which scopes each tool/surface supports)
|
||||
- runtime context (project root, home directories, env overrides)
|
||||
|
||||
### 3. Add per-tool capability metadata for scope support
|
||||
|
||||
Extend tool metadata to explicitly declare scope support per surface:
|
||||
|
||||
- skills scope support
|
||||
- commands scope support
|
||||
|
||||
When preferred scope is unsupported for a tool/surface, the system uses deterministic fallback rules and reports the effective scope in output.
|
||||
|
||||
### 4. Make command generation context-aware
|
||||
|
||||
Extend command adapter path resolution so adapters receive install context (scope + environment context), instead of only command ID. This removes special-case handling and allows consistent scope behavior across tools.
|
||||
|
||||
### 5. Update init/update UX and behavior
|
||||
|
||||
- `openspec init`:
|
||||
- accepts scope override flag
|
||||
- uses configured scope or migration-aware default (new configs default global; legacy configs preserve project until migration)
|
||||
- applies scope-aware generation and cleanup planning
|
||||
- `openspec update`:
|
||||
- applies current scope preference
|
||||
- syncs artifacts in effective scope per tool/surface
|
||||
- tracks last successful effective scope per tool/surface for deterministic scope-drift detection
|
||||
- reports effective scope decisions clearly
|
||||
|
||||
### 6. Extend config UX and docs
|
||||
|
||||
- Add install scope control in `openspec config profile` interactive flow.
|
||||
- Extend `openspec config list` output with install scope source (`explicit`, `new-default`, `legacy-default`).
|
||||
- Add explicit migration guidance and prompt path so legacy users can opt into `global` scope.
|
||||
- Update supported tools and CLI docs to explain scope behavior and fallback rules.
|
||||
|
||||
### 7. Coordinate with command-surface capability delivery rules
|
||||
|
||||
`cli-init` and `cli-update` planning SHALL compose:
|
||||
|
||||
- install scope (`global | project`)
|
||||
- delivery mode (`both | skills | commands`)
|
||||
- command surface capability (`adapter | skills-invocable | none`)
|
||||
|
||||
This proposal remains focused on scope resolution, but implementation and test coverage should include mixed-tool cases to avoid regressions when combined with `add-tool-command-surface-capabilities`.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `installation-scope`: Scope preference model and effective scope resolution for tool artifact installation.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `global-config`: Persist install scope preference with schema evolution defaults.
|
||||
- `cli-config`: Configure and inspect install scope preferences.
|
||||
- `ai-tool-paths`: Add tool-level scope support metadata and path strategy.
|
||||
- `command-generation`: Scope-aware adapter path resolution via install context.
|
||||
- `cli-init`: Scope-aware initialization planning and output.
|
||||
- `cli-update`: Scope-aware update sync, drift detection, and output.
|
||||
- `migration`: Scope-aware migration scanning with install-scope-aware workflow lookup.
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/core/global-config.ts` - new install scope fields and defaults
|
||||
- `src/core/config-schema.ts` - validation support for install scope config keys
|
||||
- `src/commands/config.ts` - interactive profile/config UX additions for install scope
|
||||
- `src/core/config.ts` - tool scope capability metadata
|
||||
- `src/core/available-tools.ts` and `src/core/shared/tool-detection.ts` - scope-aware configured detection
|
||||
- `src/core/command-generation/types.ts` and adapter implementations - context-aware file path resolution
|
||||
- `src/core/init.ts` - scope-aware generation/removal planning
|
||||
- `src/core/update.ts` - scope-aware sync/removal/drift planning
|
||||
- `src/core/migration.ts` - scope-aware workflow scanning support
|
||||
- `docs/supported-tools.md` and `docs/cli.md` - install scope behavior documentation
|
||||
- `test/core/init.test.ts`, `test/core/update.test.ts`, adapter tests, config tests - scope coverage
|
||||
@@ -0,0 +1,35 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: AIToolOption skillsDir field
|
||||
The `AIToolOption` interface SHALL include scope support metadata in addition to path metadata.
|
||||
|
||||
#### Scenario: Scope support metadata present
|
||||
- **WHEN** a tool entry is defined in `AI_TOOLS`
|
||||
- **THEN** it MAY declare supported install scopes for skills and commands
|
||||
- **AND** this metadata SHALL be used for effective scope resolution
|
||||
|
||||
#### Scenario: Scope support metadata absent
|
||||
- **WHEN** a tool entry in `AI_TOOLS` omits scope support metadata for a surface
|
||||
- **THEN** resolver behavior SHALL default that surface to project-only support
|
||||
- **AND** effective scope resolution SHALL apply normal preferred/fallback rules against that default
|
||||
|
||||
### Requirement: Path configuration for supported tools
|
||||
Path metadata SHALL support both project and global install targets via resolver logic.
|
||||
|
||||
#### Scenario: Project scope path
|
||||
- **WHEN** effective scope is `project` for skills
|
||||
- **THEN** `skillsDir` SHALL be treated as a tool-specific container path under project root
|
||||
- **AND** managed skill artifacts SHALL be written under `<projectRoot>/<skillsDir>/skills/`
|
||||
- **AND** tool definitions SHALL set `skillsDir` accordingly (for example `.openspec` -> `.openspec/skills/`)
|
||||
|
||||
#### Scenario: Global scope path
|
||||
- **WHEN** effective scope is `global` for a supported tool/surface
|
||||
- **THEN** paths SHALL resolve to tool-specific global directories
|
||||
- **AND** environment overrides (for example `CODEX_HOME`) SHALL be respected where applicable
|
||||
|
||||
#### Scenario: Windows global path resolution for Codex commands
|
||||
- **WHEN** effective scope is `global`
|
||||
- **AND** tool is Codex
|
||||
- **AND** platform is Windows
|
||||
- **THEN** command targets SHALL resolve to `%CODEX_HOME%\prompts` when `CODEX_HOME` is set
|
||||
- **AND** SHALL otherwise resolve to `%USERPROFILE%\.codex\prompts`
|
||||
@@ -0,0 +1,21 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Install scope configuration via profile flow
|
||||
The config profile workflow SHALL allow users to configure install scope preference.
|
||||
|
||||
#### Scenario: Interactive profile includes install scope
|
||||
- **WHEN** user runs `openspec config profile`
|
||||
- **THEN** the interactive flow SHALL include install scope selection with values `global` and `project`
|
||||
- **AND** the currently configured value SHALL be pre-selected
|
||||
|
||||
#### Scenario: Save install scope
|
||||
- **WHEN** user confirms config profile changes
|
||||
- **THEN** selected install scope SHALL be saved to global config
|
||||
|
||||
### Requirement: Install scope visibility in config output
|
||||
The config command SHALL display install scope preference in human-readable output.
|
||||
|
||||
#### Scenario: Config list shows install scope
|
||||
- **WHEN** user runs `openspec config list`
|
||||
- **THEN** output SHALL include current install scope value
|
||||
- **AND** indicate whether value is default or explicit
|
||||
@@ -0,0 +1,28 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Init install scope selection
|
||||
The init command SHALL support install scope selection for generated artifacts.
|
||||
|
||||
#### Scenario: Scope defaults to global
|
||||
- **WHEN** user runs `openspec init` without explicit scope override
|
||||
- **THEN** init SHALL use global config install scope
|
||||
- **AND** if unset, SHALL resolve migration-aware default (`global` for newly created configs, `project` for legacy schema-evolved configs)
|
||||
|
||||
#### Scenario: Scope override via flag
|
||||
- **WHEN** user runs `openspec init --scope project`
|
||||
- **THEN** init SHALL use `project` as preferred scope for that run
|
||||
- **AND** SHALL NOT mutate persisted global config unless user explicitly changes config
|
||||
|
||||
### Requirement: Init uses effective scope resolution
|
||||
The init command SHALL resolve effective scope per tool surface before generating files.
|
||||
|
||||
#### Scenario: Effective scope with fallback
|
||||
- **WHEN** selected tool/surface does not support preferred scope
|
||||
- **AND** supports alternate scope
|
||||
- **THEN** init SHALL generate files at alternate effective scope
|
||||
- **AND** SHALL display fallback note in summary
|
||||
|
||||
#### Scenario: Unsupported scope selection
|
||||
- **WHEN** selected tool/surface supports neither preferred nor alternate scope
|
||||
- **THEN** init SHALL fail before writing files
|
||||
- **AND** SHALL provide clear error guidance
|
||||
@@ -0,0 +1,34 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Update install scope selection
|
||||
The update command SHALL support install scope selection for sync operations.
|
||||
|
||||
#### Scenario: Scope defaults to global config value
|
||||
- **WHEN** user runs `openspec update` without explicit scope override
|
||||
- **THEN** update SHALL use configured install scope
|
||||
- **AND** if unset, SHALL resolve migration-aware default (`global` for newly created configs, `project` for legacy schema-evolved configs)
|
||||
|
||||
#### Scenario: Scope override via flag
|
||||
- **WHEN** user runs `openspec update --scope project`
|
||||
- **THEN** update SHALL use `project` as preferred scope for that run
|
||||
|
||||
### Requirement: Scope-aware sync and drift detection
|
||||
The update command SHALL evaluate configured state and drift using effective scoped paths.
|
||||
|
||||
#### Scenario: Scoped drift detection
|
||||
- **WHEN** update evaluates whether tools are up-to-date
|
||||
- **THEN** it SHALL inspect files at effective scoped targets for each tool/surface
|
||||
- **AND** SHALL compare current resolved scope against last successful effective scope for each tool/surface
|
||||
- **AND** SHALL treat a difference as sync-required drift
|
||||
|
||||
#### Scenario: Scope fallback during update
|
||||
- **WHEN** preferred scope is unsupported for a configured tool/surface
|
||||
- **AND** alternate scope is supported
|
||||
- **THEN** update SHALL apply fallback scope resolution
|
||||
- **AND** SHALL report fallback in output
|
||||
|
||||
#### Scenario: Unsupported scope during update
|
||||
- **WHEN** configured tool/surface supports neither preferred nor alternate scope
|
||||
- **THEN** scope support SHALL be validated for all configured tools/surfaces before any write
|
||||
- **AND** update SHALL fail without performing file writes when incompatibilities are detected
|
||||
- **AND** SHALL report incompatible tools with remediation steps
|
||||
@@ -0,0 +1,22 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: ToolCommandAdapter interface
|
||||
The system SHALL provide install-context-aware command path resolution.
|
||||
|
||||
#### Scenario: Adapter interface structure
|
||||
- **WHEN** implementing a tool adapter
|
||||
- **THEN** command file path resolution SHALL receive install context (including effective scope and environment context)
|
||||
- **AND** SHALL return the effective command output path for that context
|
||||
|
||||
#### Scenario: Codex global path remains supported
|
||||
- **WHEN** resolving Codex command paths in global scope
|
||||
- **THEN** the adapter SHALL target `$CODEX_HOME/prompts` when `CODEX_HOME` is set
|
||||
- **AND** SHALL otherwise target `~/.codex/prompts`
|
||||
|
||||
### Requirement: Command generator function
|
||||
The command generator SHALL pass install context into adapter path resolution for all generated commands.
|
||||
|
||||
#### Scenario: Scoped command generation
|
||||
- **WHEN** generating commands for a tool with a resolved effective scope
|
||||
- **THEN** generated command paths SHALL match that effective scope
|
||||
- **AND** the formatted command body/frontmatter behavior SHALL remain tool-specific and unchanged
|
||||
@@ -0,0 +1,24 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Install scope field in global config
|
||||
The global config schema SHALL include install scope preference.
|
||||
|
||||
#### Scenario: Config shape supports install scope
|
||||
- **WHEN** reading or writing global config
|
||||
- **THEN** config SHALL support `installScope` with allowed values `global` and `project`
|
||||
|
||||
#### Scenario: Schema evolution default
|
||||
- **WHEN** loading legacy config without `installScope`
|
||||
- **THEN** the system SHALL preserve schema compatibility without mutating the file
|
||||
- **AND** effective install scope SHALL resolve to `project` until user explicitly sets `installScope`
|
||||
- **AND** preserve all other existing fields
|
||||
|
||||
#### Scenario: New config default
|
||||
- **WHEN** creating a new global config
|
||||
- **THEN** the system SHALL persist `installScope: global` by default
|
||||
- **AND** users MAY switch to `project` explicitly
|
||||
|
||||
#### Scenario: Invalid install scope value
|
||||
- **WHEN** config validation receives an invalid install scope value
|
||||
- **THEN** the value SHALL be rejected
|
||||
- **AND** the system SHALL preserve the existing valid configuration
|
||||
@@ -0,0 +1,71 @@
|
||||
## Purpose
|
||||
|
||||
Define the install scope model for OpenSpec-generated skills and commands, including scope preference, effective scope resolution, and fallback/error semantics.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Install scope preference model
|
||||
The system SHALL support a user-level install scope preference with values `global` and `project`.
|
||||
|
||||
#### Scenario: Default install scope
|
||||
- **WHEN** install scope is not explicitly configured
|
||||
- **THEN** the system SHALL resolve a migration-aware default:
|
||||
- **AND** use `global` for newly created configs
|
||||
- **AND** use `project` for legacy schema-evolved configs until explicit migration
|
||||
|
||||
#### Scenario: Explicit install scope
|
||||
- **WHEN** user configures install scope to `project`
|
||||
- **THEN** generation and update flows SHALL use `project` as the preferred scope
|
||||
|
||||
### Requirement: Effective scope resolution by tool surface
|
||||
The system SHALL compute effective scope per tool surface (skills, commands) based on preferred scope and tool capability support.
|
||||
|
||||
#### Scenario: Preferred scope is supported
|
||||
- **WHEN** preferred scope is supported for a tool surface
|
||||
- **THEN** the system SHALL use that scope as the effective scope
|
||||
|
||||
#### Scenario: Preferred scope is unsupported but alternate is supported
|
||||
- **WHEN** preferred scope is not supported for a tool surface
|
||||
- **AND** the alternate scope is supported
|
||||
- **THEN** the system SHALL use the alternate scope as effective scope
|
||||
- **AND** SHALL record a fallback note for user-facing output
|
||||
|
||||
#### Scenario: No supported scope
|
||||
- **WHEN** neither `global` nor `project` is supported for a tool surface
|
||||
- **THEN** the command SHALL fail before writing files
|
||||
- **AND** SHALL display actionable remediation
|
||||
|
||||
### Requirement: Effective scope reporting
|
||||
The system SHALL report effective scope decisions in command output when they differ from the preferred scope.
|
||||
|
||||
#### Scenario: Fallback reporting
|
||||
- **WHEN** fallback resolution occurs for any selected/configured tool surface
|
||||
- **THEN** init/update summaries SHALL include effective scope notes per affected tool
|
||||
|
||||
### Requirement: Cross-platform path behavior
|
||||
Install scope resolution SHALL produce platform-correct target paths.
|
||||
|
||||
#### Scenario: Global scope path on Windows
|
||||
- **WHEN** effective scope is `global`
|
||||
- **AND** the command runs on Windows
|
||||
- **THEN** resolved target paths SHALL use Windows path conventions and separators
|
||||
- **AND** SHALL NOT reuse POSIX-style home-relative defaults directly
|
||||
|
||||
### Requirement: Cleanup safety for scope transitions
|
||||
Scope transitions SHALL update new targets first and clean old managed targets safely.
|
||||
|
||||
#### Scenario: Automatic cleanup for managed files on scope change
|
||||
- **WHEN** update or init applies a scope transition for a configured tool/surface
|
||||
- **THEN** the system SHALL write new artifacts in the new effective scope before cleanup
|
||||
- **AND** SHALL automatically remove only OpenSpec-managed files in the previous effective scope
|
||||
|
||||
#### Scenario: Cleanup scope boundaries
|
||||
- **WHEN** cleanup runs after a scope transition
|
||||
- **THEN** the system SHALL leave non-managed files untouched
|
||||
- **AND** SHALL limit removal scope to the affected tool/workflow-managed paths
|
||||
|
||||
#### Scenario: Cleanup failure after successful writes
|
||||
- **WHEN** new artifacts were written successfully in the new scope
|
||||
- **AND** cleanup of old managed targets fails
|
||||
- **THEN** the command SHALL report failure with leftover cleanup paths
|
||||
- **AND** SHALL NOT rollback successfully written new-scope artifacts
|
||||
@@ -0,0 +1,61 @@
|
||||
## 1. Global Config + Validation
|
||||
|
||||
- [ ] 1.1 Add `installScope` (`global` | `project`) to `GlobalConfig` with explicit `global` default for newly created configs
|
||||
- [ ] 1.2 Update config schema validation and known-key checks to include install scope
|
||||
- [ ] 1.3 Add schema-evolution tests ensuring missing `installScope` in legacy configs resolves to effective `project` until explicit migration
|
||||
- [ ] 1.4 Extend `openspec config list` output to show install scope and source (`explicit`, `new-default`, `legacy-default`)
|
||||
|
||||
## 2. Tool Capability Metadata + Resolvers
|
||||
|
||||
- [ ] 2.1 Extend `AI_TOOLS` metadata to declare scope support per surface (skills/commands)
|
||||
- [ ] 2.2 Add shared install-target resolver for skills and commands using requested scope + tool support
|
||||
- [ ] 2.3 Implement deterministic fallback/error behavior when preferred scope is unsupported, including default behavior when scope support metadata is absent
|
||||
- [ ] 2.4 Add unit tests for scope resolution (preferred, fallback, and hard-fail paths)
|
||||
|
||||
## 3. Command Generation Contract
|
||||
|
||||
- [ ] 3.1 Update `ToolCommandAdapter` path contract to accept install context
|
||||
- [ ] 3.2 Update `generateCommand`/`generateCommands` to pass context through adapters
|
||||
- [ ] 3.3 Migrate all command adapters to the new path contract
|
||||
- [ ] 3.4 Update adapter tests for scoped path behavior (including Codex global path semantics)
|
||||
|
||||
## 4. Init Command Scope Support
|
||||
|
||||
- [ ] 4.1 Add scope override flag to `openspec init` (`--scope global|project`)
|
||||
- [ ] 4.2 Resolve effective scope per tool/surface before writing artifacts
|
||||
- [ ] 4.3 Apply scope-aware generation/removal planning for skills and commands
|
||||
- [ ] 4.4 Surface effective scope decisions and fallback notes in init summary output
|
||||
- [ ] 4.5 Add init tests for global default, project override, and fallback/error scenarios
|
||||
|
||||
## 5. Update Command Scope Support
|
||||
|
||||
- [ ] 5.1 Add scope override flag to `openspec update` (`--scope global|project`)
|
||||
- [ ] 5.2 Make configured-tool detection and drift checks scope-aware
|
||||
- [ ] 5.3 Persist and read last successful effective scope per tool/surface for deterministic scope-drift detection
|
||||
- [ ] 5.4 Apply scope-aware sync/removal with consistent fallback/error behavior
|
||||
- [ ] 5.5 Ensure scope changes update managed files in new targets and clean old managed targets safely
|
||||
- [ ] 5.6 Add update tests for global/project/fallback/error and repeat-run idempotency
|
||||
|
||||
## 6. Config UX
|
||||
|
||||
- [ ] 6.1 Extend `openspec config profile` interactive flow to select install scope
|
||||
- [ ] 6.2 Preserve install scope when using preset shortcuts unless explicitly changed
|
||||
- [ ] 6.3 Ensure non-interactive config behavior remains deterministic with clear errors
|
||||
- [ ] 6.4 Add/adjust config command tests for install scope flows
|
||||
- [ ] 6.5 Add migration UX for legacy users to opt into `global` scope explicitly
|
||||
|
||||
## 7. Documentation
|
||||
|
||||
- [ ] 7.1 Update `docs/supported-tools.md` with scope behavior and effective-scope fallback notes
|
||||
- [ ] 7.2 Update `docs/cli.md` examples for init/update scope options
|
||||
- [ ] 7.3 Document cross-project implications of global installs
|
||||
- [ ] 7.4 Add existing-user migration guide covering legacy-default behavior and explicit opt-in to `installScope: global`
|
||||
|
||||
## 8. Verification
|
||||
|
||||
- [ ] 8.1 Run targeted tests for config, adapters, init, and update
|
||||
- [ ] 8.2 Run full test suite (`pnpm test`) and resolve regressions
|
||||
- [ ] 8.3 Manual smoke test: init/update with `installScope=global`
|
||||
- [ ] 8.4 Manual smoke test: init/update with `--scope project`
|
||||
- [ ] 8.5 Verify path resolution behavior on Windows CI (or cross-platform unit tests with mocked Windows paths)
|
||||
- [ ] 8.6 Verify combined behavior matrix for mixed tools across scope × delivery × command-surface capability
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-20
|
||||
@@ -0,0 +1,45 @@
|
||||
## Why
|
||||
|
||||
We need a faster, more reliable way to manually validate CLI behavior changes like profile/delivery sync, migration behavior, and tool-detection UX.
|
||||
|
||||
Today, manual review is mostly ad hoc: each developer sets up state differently, runs a different command order, and checks outputs informally. This makes regressions easy to miss and slows iteration on CLI UX work.
|
||||
|
||||
An 80/20 solution is to add a lightweight smoke harness for deterministic non-interactive flows, plus a short manual checklist for interactive prompt behavior.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add a lightweight QA smoke harness for OpenSpec CLI behavior with isolated per-run sandbox state
|
||||
- Use `Makefile` targets as the primary entrypoint:
|
||||
- `make qa` (default local QA entrypoint)
|
||||
- `make qa-smoke` (deterministic non-interactive suite)
|
||||
- `make qa-interactive` (prints/opens manual interactive checklist)
|
||||
- Implement smoke logic in a script (invoked by Make targets), not in Make itself
|
||||
- Ensure each scenario runs in an isolated sandbox with temporary `HOME`, `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, and `CODEX_HOME`
|
||||
- Capture scenario artifacts for inspection (command output, exit code, and before/after filesystem state)
|
||||
- Add a focused scenario set for high-risk behavior:
|
||||
- init core output generation
|
||||
- non-interactive detected-tool behavior
|
||||
- migration when profile is unset
|
||||
- delivery cleanup (`both -> skills`, `both -> commands`)
|
||||
- commands-only update detection
|
||||
- new tool directory detection messaging
|
||||
- invalid profile override validation
|
||||
- Add a short interactive checklist for keypress/prompt UX verification (Space toggle, Enter confirm, detected pre-selection)
|
||||
- Wire CI to run the smoke suite on Linux as a fast regression gate
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `qa-smoke-harness`: Deterministic, sandboxed CLI smoke validation with a single developer entrypoint
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `developer-qa-workflow`: Standardized local/CI QA flow for CLI behavior and migration-sensitive scenarios
|
||||
|
||||
## Impact
|
||||
|
||||
- `Makefile` - Add `qa`, `qa-smoke`, and `qa-interactive` targets
|
||||
- `scripts/qa-smoke.sh` (or equivalent) - Implement sandbox setup, scenario execution, and assertions
|
||||
- `docs/` - Add/update contributor-facing QA instructions and interactive checklist usage
|
||||
- CI workflow - Add smoke target execution as a lightweight regression gate
|
||||
@@ -0,0 +1,49 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Makefile QA Entry Point
|
||||
|
||||
The repository SHALL provide Makefile targets as the primary developer entrypoint for CLI QA flows.
|
||||
|
||||
#### Scenario: Default QA target runs smoke suite
|
||||
|
||||
- **WHEN** a developer runs `make qa`
|
||||
- **THEN** the command SHALL execute the non-interactive smoke suite
|
||||
- **AND** exit with status code 0 only when all smoke scenarios pass
|
||||
|
||||
#### Scenario: Smoke suite target is directly invokable
|
||||
|
||||
- **WHEN** a developer runs `make qa-smoke`
|
||||
- **THEN** the command SHALL execute the same smoke suite used by `make qa`
|
||||
- **AND** return a non-zero exit code on assertion failure
|
||||
|
||||
#### Scenario: Interactive checklist target exists
|
||||
|
||||
- **WHEN** a developer runs `make qa-interactive`
|
||||
- **THEN** the command SHALL provide the manual interactive verification checklist
|
||||
- **AND** SHALL NOT run interactive prompt automation by default
|
||||
|
||||
### Requirement: Sandboxed Smoke Scenario Runner
|
||||
|
||||
The smoke suite SHALL run CLI scenarios in isolated sandboxes so tests are repeatable and do not depend on machine-global state.
|
||||
|
||||
#### Scenario: Scenario execution is environment-isolated
|
||||
|
||||
- **WHEN** a smoke scenario runs
|
||||
- **THEN** it SHALL use temporary values for `HOME`, `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, and `CODEX_HOME`
|
||||
- **AND** global config from the host machine SHALL NOT affect scenario outcomes
|
||||
|
||||
#### Scenario: Scenario artifacts are captured for review
|
||||
|
||||
- **WHEN** a smoke scenario completes
|
||||
- **THEN** the runner SHALL capture command output and exit status
|
||||
- **AND** SHALL capture enough filesystem state to inspect before/after behavior
|
||||
|
||||
#### Scenario: High-risk workflow coverage exists
|
||||
|
||||
- **WHEN** the smoke suite executes
|
||||
- **THEN** it SHALL include scenarios covering profile/delivery behavior and migration-sensitive flows
|
||||
- **AND** include at least:
|
||||
- non-interactive tool detection
|
||||
- migration when profile is unset
|
||||
- delivery cleanup (`both -> skills`, `both -> commands`)
|
||||
- commands-only update detection
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-19
|
||||
@@ -0,0 +1,111 @@
|
||||
## Why
|
||||
|
||||
OpenSpec currently assumes command delivery maps directly to command adapters. That assumption does not hold for all tools.
|
||||
|
||||
Trae is a concrete example: it invokes OpenSpec workflows via skill entries (for example `/openspec-new-change`) rather than adapter-generated command files. In this model, skills are the command surface.
|
||||
|
||||
Today, this creates a behavior gap:
|
||||
|
||||
- `delivery=commands` can remove skills
|
||||
- tools without adapters skip command generation
|
||||
- result: selected tools like Trae can end up with no invocable workflow artifacts
|
||||
|
||||
This is more than a prompt UX issue because non-interactive and CI flows bypass interactive guidance. We need a capability-aware model in core generation logic.
|
||||
|
||||
## What Changes
|
||||
|
||||
### 1. Add explicit command-surface capability metadata
|
||||
|
||||
Add an optional field in tool metadata to describe how a tool exposes commands:
|
||||
|
||||
- `adapter`: command files are generated through a command adapter
|
||||
- `skills-invocable`: skills are directly invocable as commands
|
||||
- `none`: no OpenSpec command surface
|
||||
|
||||
Field should be optional. Default behavior is inferred from adapter registry presence: tools with a registered adapter resolve to `adapter`; tools with no adapter registration and no explicit annotation resolve to `none`.
|
||||
Capability values use kebab-case string tokens for consistency with serialized metadata conventions.
|
||||
|
||||
Initial explicit override:
|
||||
|
||||
- Trae -> `skills-invocable`
|
||||
|
||||
### 2. Make delivery behavior capability-aware
|
||||
|
||||
Update `init` and `update` to compute effective artifact actions per tool from:
|
||||
|
||||
- global delivery (`both | skills | commands`)
|
||||
- tool command surface capability
|
||||
|
||||
Behavior matrix:
|
||||
|
||||
- `both`:
|
||||
- generate skills for all tools with `skillsDir` (including `skills-invocable`)
|
||||
- generate command files only for `adapter` tools
|
||||
- `none`: no artifact action; MAY emit compatibility warning
|
||||
- `skills`:
|
||||
- generate skills for all tools with `skillsDir` (including `skills-invocable`)
|
||||
- remove adapter-generated command files
|
||||
- `none`: no artifact action; MAY emit compatibility warning
|
||||
- `commands`:
|
||||
- `adapter`: generate commands, remove skills
|
||||
- `skills-invocable`: generate (or keep if up-to-date) skills as command surface; do not remove them
|
||||
- `none`: fail fast with clear error
|
||||
|
||||
### 3. Add preflight validation and clearer output
|
||||
|
||||
Before writing/removing artifacts, validate selected/configured tools against delivery mode:
|
||||
|
||||
- interactive flow: show clear compatibility note before confirmation
|
||||
- non-interactive flow: fail with deterministic error listing incompatible tools and supported alternatives
|
||||
|
||||
Update summaries to show effective delivery outcomes per tool (for example, when commands mode still installs skills for skills-invocable tools).
|
||||
|
||||
### 4. Update docs and tests
|
||||
|
||||
- document capability model and Trae behavior under delivery modes
|
||||
- ensure CLI docs and supported-tools docs reflect effective behavior
|
||||
- add test coverage for:
|
||||
- `init --tools trae` with `delivery=commands`
|
||||
- `update` with Trae configured under `delivery=commands`
|
||||
- mixed selections (`claude + trae`) across all delivery modes
|
||||
- explicit error path for tools with no command surface under `delivery=commands`
|
||||
|
||||
### 5. Coordinate with install-scope behavior
|
||||
|
||||
When combined with `add-global-install-scope`, init/update planning must compose:
|
||||
|
||||
- install scope (`global | project`)
|
||||
- delivery mode (`both | skills | commands`)
|
||||
- command surface capability (`adapter | skills-invocable | none`)
|
||||
|
||||
Implementation tests should cover mixed-tool matrices to ensure deterministic behavior when both changes are active.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `tool-command-surface`: Capability model that classifies tools as `adapter`, `skills-invocable`, or `none` to drive delivery behavior
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `cli-init`: Delivery handling becomes tool-capability-aware with preflight compatibility validation
|
||||
- `cli-update`: Delivery sync becomes tool-capability-aware with consistent compatibility validation and messaging
|
||||
- `supported-tools-docs`: Documents command-surface semantics for non-adapter tools
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/core/config.ts` - add optional command-surface metadata and Trae override
|
||||
- `src/core/command-generation/registry.ts` (or shared helper) - capability inference from adapter presence
|
||||
- `src/core/init.ts` - capability-aware generation/removal planning + compatibility validation + summary messaging
|
||||
- `src/core/update.ts` - capability-aware sync/removal planning + compatibility validation + summary messaging
|
||||
- `src/core/shared/tool-detection.ts` - include capability-aware detection so `skills-invocable` tools remain detectable under `delivery=commands`, and `none` tools are excluded from command-surface artifact detection
|
||||
- `docs/supported-tools.md` and `docs/cli.md` - document delivery behavior and compatibility notes
|
||||
- `test/core/init.test.ts` and `test/core/update.test.ts` - add coverage for skills-invocable behavior and mixed-tool delivery scenarios
|
||||
|
||||
## Sequencing Notes
|
||||
|
||||
- This change is intended to stack safely with `simplify-skill-installation` by introducing additive, capability-specific requirements for init/update.
|
||||
- If `simplify-skill-installation` merges first, this change should be rebased and keep the capability-aware rule as the source of truth for `delivery=commands` behavior on `skills-invocable` tools.
|
||||
- If this change merges first, the `simplify-skill-installation` branch should be rebased to avoid re-introducing a global "commands-only means no skills for all tools" assumption.
|
||||
- If `add-global-install-scope` merges first, this change should be rebased to compose capability-aware behavior on top of scope-resolved path decisions from that change.
|
||||
- If this change merges first, `add-global-install-scope` should be rebased to preserve Section 5 composition rules (`install scope` + `delivery mode` + `command surface capability`) without overriding capability-aware command-surface outcomes.
|
||||
@@ -0,0 +1,121 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Command surface capability resolution
|
||||
The init command SHALL resolve each selected tool's command surface using explicit metadata first, then deterministic inference.
|
||||
|
||||
#### Scenario: Explicit command surface override
|
||||
- **WHEN** a tool declares an explicit command-surface capability
|
||||
- **THEN** init SHALL use that explicit capability
|
||||
- **AND** SHALL NOT override it based on adapter presence
|
||||
|
||||
#### Scenario: Inferred command surface from adapter presence
|
||||
- **WHEN** a tool does not declare an explicit command-surface capability
|
||||
- **AND** a command adapter is registered for the tool
|
||||
- **THEN** init SHALL infer `adapter` as the command surface
|
||||
|
||||
#### Scenario: Inferred command surface for skills-only tool
|
||||
- **WHEN** a tool does not declare an explicit command-surface capability
|
||||
- **AND** no command adapter is registered for the tool
|
||||
- **AND** the tool has a configured `skillsDir`
|
||||
- **THEN** init SHALL infer `skills-invocable` as the command surface
|
||||
|
||||
#### Scenario: Inferred command surface without adapter or skills
|
||||
- **WHEN** a tool does not declare an explicit command-surface capability
|
||||
- **AND** no command adapter is registered for the tool
|
||||
- **AND** the tool has no `skillsDir`
|
||||
- **THEN** init SHALL infer `none` as the command surface
|
||||
|
||||
### Requirement: Delivery compatibility by tool command surface
|
||||
The init command SHALL apply delivery settings using each tool's command surface capability, not adapter presence alone.
|
||||
|
||||
#### Scenario: Both delivery for adapter-backed tool
|
||||
- **WHEN** user runs `openspec init` with a selected tool that has a command adapter
|
||||
- **AND** delivery is set to `both`
|
||||
- **THEN** the system SHALL generate command files for active workflows using that adapter
|
||||
- **AND** SHALL generate or refresh managed skills when the tool has `skillsDir`
|
||||
|
||||
#### Scenario: Both delivery for skills-invocable tool
|
||||
- **WHEN** user runs `openspec init` with a selected tool whose command surface is `skills-invocable`
|
||||
- **AND** delivery is set to `both`
|
||||
- **THEN** the system SHALL generate or refresh managed skill directories when the tool has `skillsDir`
|
||||
- **AND** SHALL NOT require adapter-generated command files for that tool
|
||||
|
||||
#### Scenario: Both delivery for none command surface
|
||||
- **WHEN** user runs `openspec init` with a selected tool whose command surface is `none`
|
||||
- **AND** delivery is set to `both`
|
||||
- **THEN** the system SHALL perform no command-surface artifact action for that tool
|
||||
- **AND** MAY emit a compatibility note indicating no command surface is available
|
||||
|
||||
#### Scenario: Skills delivery for adapter-backed tool
|
||||
- **WHEN** user runs `openspec init` with a selected tool that has a command adapter
|
||||
- **AND** delivery is set to `skills`
|
||||
- **THEN** the system SHALL generate or refresh managed skill directories when the tool has `skillsDir`
|
||||
- **AND** SHALL remove managed adapter-generated command files for that tool
|
||||
|
||||
#### Scenario: Skills delivery for skills-invocable tool
|
||||
- **WHEN** user runs `openspec init` with a selected tool whose command surface is `skills-invocable`
|
||||
- **AND** delivery is set to `skills`
|
||||
- **THEN** the system SHALL generate or refresh managed skill directories when the tool has `skillsDir`
|
||||
- **AND** SHALL NOT require adapter-generated command files for that tool
|
||||
|
||||
#### Scenario: Skills delivery for none command surface
|
||||
- **WHEN** user runs `openspec init` with a selected tool whose command surface is `none`
|
||||
- **AND** delivery is set to `skills`
|
||||
- **THEN** the system SHALL perform no command-surface artifact action for that tool
|
||||
- **AND** MAY emit a compatibility note indicating no command surface is available
|
||||
|
||||
#### Scenario: Commands delivery for adapter-backed tool
|
||||
- **WHEN** user runs `openspec init` with a selected tool that has a command adapter
|
||||
- **AND** delivery is set to `commands`
|
||||
- **THEN** the system SHALL generate command files for active workflows using that adapter
|
||||
- **AND** the system SHALL remove managed skill directories for that tool
|
||||
|
||||
#### Scenario: Commands delivery for skills-invocable tool
|
||||
- **WHEN** user runs `openspec init` with a selected tool whose command surface is `skills-invocable`
|
||||
- **AND** delivery is set to `commands`
|
||||
- **THEN** the system SHALL generate or refresh managed skill directories for active workflows
|
||||
- **AND** the system SHALL NOT remove those managed skill directories as part of commands-only cleanup
|
||||
- **AND** the system SHALL NOT require a command adapter for that tool
|
||||
|
||||
#### Scenario: Commands delivery for mixed tool selection
|
||||
- **WHEN** user runs `openspec init` with multiple tools
|
||||
- **AND** selected tools include both adapter-backed and skills-invocable command surfaces
|
||||
- **AND** delivery is set to `commands`
|
||||
- **THEN** the system SHALL apply commands-only behavior per tool capability
|
||||
- **AND** the resulting install SHALL include command files for adapter-backed tools and skills for skills-invocable tools
|
||||
|
||||
#### Scenario: Commands delivery for unsupported command surface
|
||||
- **WHEN** user runs `openspec init` with a selected tool that has no command surface capability
|
||||
- **AND** delivery is set to `commands`
|
||||
- **THEN** the system SHALL fail before generating or deleting artifacts
|
||||
- **AND** the error SHALL list incompatible tool IDs and explain supported alternatives (`both` or `skills`)
|
||||
|
||||
#### Scenario: Interactive handling for unsupported command surface
|
||||
- **WHEN** user runs `openspec init` interactively
|
||||
- **AND** delivery is set to `commands`
|
||||
- **AND** selected tools include one or more tools with command surface `none`
|
||||
- **THEN** the CLI SHALL show a compatibility error and return to the interactive selection flow for correction
|
||||
- **AND** SHALL not perform artifact writes until a valid selection is confirmed
|
||||
|
||||
### Requirement: Init compatibility signaling
|
||||
The init command SHALL clearly signal command-surface compatibility outcomes in both interactive and non-interactive flows.
|
||||
|
||||
#### Scenario: Interactive compatibility note
|
||||
- **WHEN** init runs interactively
|
||||
- **AND** delivery is `commands`
|
||||
- **AND** selected tools include skills-invocable command surfaces
|
||||
- **THEN** the system SHALL display a compatibility note before the confirmation prompt indicating those tools will use skills as their command surface
|
||||
|
||||
#### Scenario: Non-interactive compatibility summary for skills-invocable tools
|
||||
- **WHEN** init runs non-interactively (including `--tools` usage)
|
||||
- **AND** delivery is `commands`
|
||||
- **AND** selected tools include one or more `skills-invocable` command surfaces
|
||||
- **THEN** the command SHALL proceed with exit code 0
|
||||
- **AND** the command SHALL write deterministic compatibility summary lines to stdout indicating those tools will use managed skills as their command surface
|
||||
|
||||
#### Scenario: Non-interactive compatibility failure
|
||||
- **WHEN** init runs non-interactively (including `--tools` usage)
|
||||
- **AND** delivery is `commands`
|
||||
- **AND** selected tools include any tool with no command surface capability
|
||||
- **THEN** the command SHALL exit with code 1
|
||||
- **AND** the command SHALL write deterministic, actionable guidance for resolving the selection to stderr
|
||||
@@ -0,0 +1,48 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Delivery sync by command surface capability
|
||||
The update command SHALL synchronize artifacts using each configured tool's command surface capability.
|
||||
|
||||
#### Scenario: Commands delivery for adapter-backed configured tool
|
||||
- **WHEN** user runs `openspec update`
|
||||
- **AND** delivery is set to `commands`
|
||||
- **AND** a configured tool has an adapter-backed command surface
|
||||
- **THEN** the system SHALL generate or refresh command files for active workflows
|
||||
- **AND** the system SHALL remove managed skill directories for that tool
|
||||
|
||||
#### Scenario: Commands delivery for skills-invocable configured tool
|
||||
- **WHEN** user runs `openspec update`
|
||||
- **AND** delivery is set to `commands`
|
||||
- **AND** a configured tool has `skills-invocable` command surface capability
|
||||
- **THEN** the system SHALL generate or refresh managed skill directories for active workflows
|
||||
- **AND** the system SHALL NOT remove those managed skill directories as part of commands-only cleanup
|
||||
- **AND** the system SHALL NOT attempt to require adapter-generated command files for that tool
|
||||
|
||||
#### Scenario: Commands delivery with unsupported command surface
|
||||
- **WHEN** user runs `openspec update`
|
||||
- **AND** delivery is set to `commands`
|
||||
- **AND** a configured tool has no command surface capability
|
||||
- **THEN** the system SHALL fail with exit code 1 before applying partial updates
|
||||
- **AND** the output SHALL identify incompatible tools and recommended remediation
|
||||
|
||||
### Requirement: Configured-tool detection for skills-invocable command surfaces
|
||||
The update command SHALL treat tools with skills-invocable command surfaces as configured when managed skill artifacts are present, including under commands delivery.
|
||||
|
||||
#### Scenario: Skills-invocable tool under commands delivery
|
||||
- **WHEN** user runs `openspec update`
|
||||
- **AND** delivery is set to `commands`
|
||||
- **AND** a tool has no adapter-generated command files
|
||||
- **AND** that tool is marked `skills-invocable` and has managed skills installed
|
||||
- **THEN** the system SHALL include the tool in configured-tool detection
|
||||
- **AND** the system SHALL apply normal version/profile/delivery sync to that tool
|
||||
|
||||
### Requirement: Update summary reflects effective per-tool delivery
|
||||
The update command SHALL report effective artifact behavior when delivery intent and artifact type differ due to tool capability.
|
||||
|
||||
#### Scenario: Summary for skills-invocable tools in commands delivery
|
||||
- **WHEN** update completes successfully
|
||||
- **AND** delivery is `commands`
|
||||
- **AND** at least one updated tool is `skills-invocable`
|
||||
- **THEN** output SHALL include a clear note that those tools use skills as their command surface
|
||||
- **AND** output SHALL avoid implying that command generation was skipped due to an error
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
## 0. Stacking Coordination
|
||||
|
||||
- [ ] 0.1 Rebase this change on latest `main` before implementation
|
||||
- [ ] 0.2 If `simplify-skill-installation` is merged first, preserve its profile/delivery model and apply this change as a capability-aware refinement
|
||||
- [ ] 0.3 If this change merges first, ensure follow-up rebases do not reintroduce a blanket "commands = remove all skills" rule
|
||||
- [ ] 0.4 If `add-global-install-scope` is merged, verify combined scope × delivery × command-surface behavior remains deterministic
|
||||
|
||||
## 1. Tool Command-Surface Capability Model
|
||||
|
||||
- [ ] 1.1 Extend tool metadata in `src/core/config.ts` with an optional command-surface capability field
|
||||
- [ ] 1.2 Define supported capability values: `adapter`, `skills-invocable`, `none`
|
||||
- [ ] 1.3 Mark Trae as `skills-invocable`
|
||||
- [ ] 1.4 Add a shared capability resolver (explicit metadata override first, inferred fallback from adapter presence second)
|
||||
- [ ] 1.5 Add focused unit tests for capability resolution (explicit override, inferred adapter, inferred none)
|
||||
|
||||
## 2. Init: Capability-Aware Delivery Planning
|
||||
|
||||
- [ ] 2.1 Refactor init generation logic to compute per-tool effective actions (generate/remove skills and commands) instead of using only global booleans
|
||||
- [ ] 2.2 In `delivery=commands`, keep/generate skills for `skills-invocable` tools and do not remove those managed skill directories
|
||||
- [ ] 2.3 In `delivery=commands`, fail fast before writes when any selected tool resolves to `none`
|
||||
- [ ] 2.4 Update init output to clearly report effective behavior for `skills-invocable` tools (skills used as command surface)
|
||||
- [ ] 2.5 Ensure init no longer reports "no adapter" for tools intentionally using `skills-invocable`
|
||||
- [ ] 2.6 Add/adjust init tests for `delivery=commands` + `trae` (skills retained/generated, no adapter error), mixed tools (`claude,trae`) with per-tool expected outputs, and deterministic failure path for unsupported command surface (`none`)
|
||||
|
||||
## 3. Update: Capability-Aware Sync and Drift Detection
|
||||
|
||||
- [ ] 3.1 Refactor update sync logic to apply delivery behavior per tool capability (not globally per run)
|
||||
- [ ] 3.2 In `delivery=commands`, keep/generate managed skills for `skills-invocable` tools
|
||||
- [ ] 3.3 In `delivery=commands`, fail before partial updates when configured tools include a `none` command surface
|
||||
- [ ] 3.4 Update profile/delivery drift detection to avoid perpetual drift for `skills-invocable` tools under commands delivery
|
||||
- [ ] 3.5 Ensure configured-tool detection still includes `skills-invocable` tools under commands delivery when managed skills exist
|
||||
- [ ] 3.6 Update summary output so skills-invocable behavior is reported as expected behavior (not implicit skip/error)
|
||||
- [ ] 3.7 Add/adjust update tests for `delivery=commands` + configured Trae (skills retained/generated), idempotent second update (no false drift loop), mixed configured tools (`claude` + `trae`), and deterministic preflight failure for unsupported command surface (`none`)
|
||||
|
||||
## 4. UX and Error Messaging
|
||||
|
||||
- [ ] 4.1 Add interactive init compatibility note for `delivery=commands` when selected tools include `skills-invocable`
|
||||
- [ ] 4.2 Add deterministic non-interactive error text with incompatible tool IDs and suggested alternatives (`both` or `skills`)
|
||||
- [ ] 4.3 Align init and update wording so capability-related behavior/messages are consistent
|
||||
|
||||
## 5. Documentation Updates
|
||||
|
||||
- [ ] 5.1 Update `docs/supported-tools.md` to document command-surface semantics for Trae and clarify delivery interactions
|
||||
- [ ] 5.2 Update `docs/cli.md` delivery guidance to explain capability-aware behavior for `delivery=commands`
|
||||
- [ ] 5.3 Add a short troubleshooting note for "commands-only + unsupported tool" failures
|
||||
|
||||
## 6. Verification
|
||||
|
||||
- [ ] 6.1 Run targeted tests: `test/core/init.test.ts` and `test/core/update.test.ts`
|
||||
- [ ] 6.2 Run any new capability/unit test files added in this change
|
||||
- [ ] 6.3 Run full test suite (`pnpm test`) and resolve regressions
|
||||
- [ ] 6.4 Manual smoke check: `openspec init --tools trae` with `delivery=commands`
|
||||
- [ ] 6.5 Manual smoke check: mixed tools (`claude,trae`) with `delivery=commands`
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-01-30
|
||||
@@ -0,0 +1,3 @@
|
||||
# opencode-command-references
|
||||
|
||||
Transform /opsx: to /opsx- in both commands and skills for OpenCode
|
||||
@@ -0,0 +1,70 @@
|
||||
## Context
|
||||
|
||||
OpenCode is one of many supported AI tools. Each tool has:
|
||||
- A **command adapter** (in `src/core/command-generation/adapters/`) for generating tool-specific command files
|
||||
- **Skills** generated via `generateSkillContent()` in `src/core/shared/skill-generation.ts`
|
||||
|
||||
Currently:
|
||||
- Commands go through the adapter system which can transform content per-tool
|
||||
- Skills use a single shared function with no tool-specific transformation
|
||||
|
||||
The templates in `src/core/templates/skill-templates.ts` use Claude's colon-based format (`/opsx:new`) as the canonical format. Tools that use different formats need transformation at generation time.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Transform all `/opsx:` command references to `/opsx-` for OpenCode in both commands and skills
|
||||
- Create a shared, reusable transformation utility
|
||||
- Keep the transformation opt-in via a callback parameter (not hard-coded tool detection)
|
||||
|
||||
**Non-Goals:**
|
||||
- Modifying the canonical template format (templates stay with `/opsx:`)
|
||||
- Applying transformation to other tools (only OpenCode for now)
|
||||
- Creating a full adapter system for skills (overkill for current needs)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Shared Utility Function
|
||||
|
||||
**Choice**: Create `transformToHyphenCommands()` in `src/utils/command-references.ts`
|
||||
|
||||
**Rationale**:
|
||||
- Single source of truth for the transformation logic
|
||||
- Can be used by both command adapter and skill generation
|
||||
- Easy to test in isolation
|
||||
- Follows existing utils pattern in the codebase
|
||||
|
||||
**Alternatives considered**:
|
||||
- Inline the transformation in each location - Duplicates logic, harder to maintain
|
||||
|
||||
### Decision 2: Callback Parameter for Skill Generation
|
||||
|
||||
**Choice**: Add optional `transformInstructions?: (instructions: string) => string` parameter to `generateSkillContent()`
|
||||
|
||||
**Rationale**:
|
||||
- Flexible - callers define the transformation, not the generation function
|
||||
- No coupling - `generateSkillContent()` doesn't need to know about tool formats
|
||||
- Extensible - could support other transformations in the future
|
||||
- Follows inversion of control principle
|
||||
|
||||
**Alternatives considered**:
|
||||
- Add tool ID parameter and switch on it - Creates coupling, harder to extend
|
||||
- Create skill adapter system parallel to commands - Over-engineering for current needs
|
||||
- Transform in templates directly - Breaks single-source-of-truth principle
|
||||
|
||||
### Decision 3: Apply at Generation Sites
|
||||
|
||||
**Choice**: Pass transformer in `init.ts` and `update.ts` when `tool.value === 'opencode'`
|
||||
|
||||
**Rationale**:
|
||||
- These are the only two places that generate skills
|
||||
- Simple conditional check, no new abstractions needed
|
||||
- Easy to extend to other tools if needed later
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Other `/opsx:` patterns exist that shouldn't be transformed | All occurrences in templates are command invocations - verified by inspection |
|
||||
| Future tools may need same transformation | Utility is shared and easy to reuse; can add to other tools' generation |
|
||||
| Callback adds complexity to function signature | Optional parameter with sensible default (no transformation) |
|
||||
@@ -0,0 +1,32 @@
|
||||
## Why
|
||||
|
||||
OpenCode uses hyphen-based command syntax (`/opsx-new`) but our templates contain colon-based references (`/opsx:new`). This creates inconsistency where generated command files and skill files contain references that don't match the actual command invocation syntax, confusing both the AI and users.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Create a shared transformation utility (`transformToHyphenCommands`) for converting `/opsx:` to `/opsx-`
|
||||
- Update the OpenCode command adapter to transform body text using this utility
|
||||
- Add an optional `transformInstructions` callback parameter to `generateSkillContent()`
|
||||
- Update `init.ts` and `update.ts` to pass the transformer when generating skills for OpenCode
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
None - this is a bug fix, not a new capability.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
None - no spec-level behavior changes. This is an implementation fix in the OpenCode adapter and skill generation that doesn't change any external requirements or contracts.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Code**:
|
||||
- `src/utils/command-references.ts` (new file)
|
||||
- `src/utils/index.ts` (export)
|
||||
- `src/core/shared/skill-generation.ts` (add callback parameter)
|
||||
- `src/core/command-generation/adapters/opencode.ts` (use transformer)
|
||||
- `src/core/init.ts` (pass transformer for OpenCode)
|
||||
- `src/core/update.ts` (pass transformer for OpenCode)
|
||||
- **Users**: OpenCode users will see correct `/opsx-` command references in both generated command files AND skill files
|
||||
- **Other tools**: No impact - transformation only applies to OpenCode
|
||||
@@ -0,0 +1,9 @@
|
||||
# No Spec Changes
|
||||
|
||||
This is a bug fix that doesn't modify any external requirements or contracts.
|
||||
|
||||
The proposal's Capabilities section indicates:
|
||||
- **New Capabilities**: None
|
||||
- **Modified Capabilities**: None
|
||||
|
||||
No spec files are needed for this implementation-only fix.
|
||||
@@ -0,0 +1,22 @@
|
||||
## 1. Implementation
|
||||
|
||||
- [x] 1.1 Create `src/utils/command-references.ts` with `transformToHyphenCommands()` function
|
||||
- [x] 1.2 Export `transformToHyphenCommands` from `src/utils/index.ts`
|
||||
- [x] 1.3 Update `generateSkillContent()` in `src/core/shared/skill-generation.ts` to accept optional `transformInstructions` callback
|
||||
- [x] 1.4 Update OpenCode adapter in `src/core/command-generation/adapters/opencode.ts` to use `transformToHyphenCommands()` for body text
|
||||
- [x] 1.5 Update `init.ts` to pass transformer when generating skills for OpenCode
|
||||
- [x] 1.6 Update `update.ts` to pass transformer when generating skills for OpenCode
|
||||
|
||||
## 2. Testing
|
||||
|
||||
- [x] 2.1 Create `test/utils/command-references.test.ts` with unit tests for `transformToHyphenCommands()`
|
||||
- [x] 2.2 Add test to `test/core/command-generation/adapters.test.ts` for OpenCode body transformation
|
||||
- [x] 2.3 Add test to `test/core/shared/skill-generation.test.ts` for transformer callback
|
||||
|
||||
## 3. Verification
|
||||
|
||||
- [x] 3.1 Run `npx vitest run test/utils/command-references.test.ts test/core/command-generation/adapters.test.ts test/core/shared/skill-generation.test.ts` to ensure tests pass
|
||||
- [x] 3.2 Run `pnpm run build` to ensure no TypeScript errors
|
||||
- [x] 3.3 Run `openspec init --tools opencode` in a temp directory and verify:
|
||||
- Command files in `.opencode/command/` contain `/opsx-` references (not `/opsx:`)
|
||||
- Skill files in `.opencode/skills/` contain `/opsx-` references (not `/opsx:`)
|
||||
+2
-2
@@ -18,7 +18,7 @@ Each AI tool has:
|
||||
- Create a generic, extensible command generation system
|
||||
|
||||
**Non-Goals:**
|
||||
- Global path installation (deferred to future work)
|
||||
- Global path installation for tools other than Codex (Codex uses absolute adapter paths today)
|
||||
- Multi-tool generation in single command (future enhancement)
|
||||
- Unifying with existing SlashCommandConfigurator (separate systems for now)
|
||||
|
||||
@@ -41,7 +41,7 @@ interface AIToolOption {
|
||||
**Rationale**:
|
||||
- Skills follow Agent Skills spec: `<toolDir>/skills/` - suffix is standard
|
||||
- Commands need per-tool formatting, handled by adapters (not a simple path)
|
||||
- Global paths deferred - can extend interface later
|
||||
- Global paths supported — Codex adapter returns absolute paths via os.homedir()
|
||||
|
||||
### 2. Strategy/Adapter pattern for command generation
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ 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 relative file path for command
|
||||
- `getFilePath(commandId: string)`: returns file path for command (relative from project root, or absolute for global-scoped tools like Codex)
|
||||
- `formatFile(content: CommandContent)`: returns complete file content with frontmatter
|
||||
|
||||
#### Scenario: Claude adapter formatting
|
||||
@@ -49,7 +49,7 @@ 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/commands/opsx/<id>.md`
|
||||
- **AND** file path SHALL follow pattern `.windsurf/workflows/opsx-<id>.md`
|
||||
|
||||
### Requirement: Command generator function
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-25
|
||||
@@ -0,0 +1,48 @@
|
||||
## Context
|
||||
|
||||
The OpenCode adapter in `src/core/command-generation/adapters/opencode.ts` currently generates command files at `.opencode/command/opsx-<id>.md` (singular `command`). OpenCode's official documentation uses `.opencode/commands/` (plural), and every other adapter in the codebase follows the plural convention for commands directories. The legacy cleanup module in `src/core/legacy-cleanup.ts` also references the singular form for detecting old artifacts.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Align the OpenCode adapter path with OpenCode's official `.opencode/commands/` convention
|
||||
- Add the old singular path `.opencode/command/` to legacy cleanup so existing installations are properly cleaned
|
||||
- Update documentation to reflect the corrected path
|
||||
- Update test assertions to match the new path
|
||||
|
||||
**Non-Goals:**
|
||||
- Changing the OpenCode skill path (`.opencode/skills/`) — already correct
|
||||
- Modifying any other adapter's directory structure
|
||||
- Adding migration prompts or interactive upgrade flows
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Direct path rename in adapter
|
||||
|
||||
**Decision:** Change `path.join('.opencode', 'command', ...)` to `path.join('.opencode', 'commands', ...)` in the adapter's `getFilePath` method.
|
||||
|
||||
**Rationale:** This is a single-line change that aligns with the established pattern across all other adapters. No abstraction or indirection needed.
|
||||
|
||||
**Alternatives considered:**
|
||||
- Add a configuration option for the directory name — rejected as over-engineering for a bug fix
|
||||
- Keep singular and add plural as alias — rejected as it creates ambiguity about which is canonical
|
||||
|
||||
### 2. Legacy cleanup via existing constant map
|
||||
|
||||
**Decision:** Update the `LEGACY_SLASH_COMMAND_PATHS` entry for `'opencode'` from `'.opencode/command/openspec-*.md'` to `'.opencode/command/opsx-*.md'` (the old singular path becomes the legacy pattern) and ensure the new path is handled by the current command generation pipeline.
|
||||
|
||||
**Rationale:** The existing legacy cleanup infrastructure uses `LEGACY_SLASH_COMMAND_PATHS` as an explicit lookup. The old singular-path pattern already matches the legacy format (`openspec-*` prefix from the old SlashCommandRegistry era). The current command generation uses the `opsx-*` prefix, so we also need to add a legacy pattern for `opsx-*` files in the old singular directory.
|
||||
|
||||
**Alternatives considered:**
|
||||
- Add a separate migration script — rejected; the existing legacy cleanup mechanism handles this scenario
|
||||
|
||||
### 3. Documentation update
|
||||
|
||||
**Decision:** Update the `docs/supported-tools.md` table entry for OpenCode from `.opencode/command/opsx-<id>.md` to `.opencode/commands/opsx-<id>.md`.
|
||||
|
||||
**Rationale:** Documentation must match the actual generated paths.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[Existing installations have files at old path]** → Mitigated by legacy cleanup detecting `.opencode/command/` artifacts. On next `openspec init`, old files are cleaned up and new files written to `.opencode/commands/`.
|
||||
- **[Users referencing old path in custom scripts]** → Low risk. The old path was incorrect per OpenCode's specification, so custom references were already misaligned.
|
||||
@@ -0,0 +1,26 @@
|
||||
## Why
|
||||
|
||||
The OpenCode adapter uses `.opencode/command/` (singular) for its commands directory, but OpenCode's official documentation specifies `.opencode/commands/` (plural). Every other adapter in the codebase also uses plural directory names (`.claude/commands/`, `.cursor/commands/`, `.factory/commands/`, etc.). This inconsistency was introduced in Oct 2025 without documented rationale. Fixes [#748](https://github.com/Fission-AI/OpenSpec/issues/748).
|
||||
|
||||
## What Changes
|
||||
|
||||
- OpenCode adapter path changes from `.opencode/command/` to `.opencode/commands/`
|
||||
- Legacy cleanup adds `.opencode/command/` (old singular path) for backward compatibility
|
||||
- Documentation updated to reflect the new plural path
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
_None._
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `command-generation`: OpenCode adapter path changes from singular `command/` to plural `commands/` to match OpenCode's official directory convention
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/core/command-generation/adapters/opencode.ts` — adapter path
|
||||
- `src/core/legacy-cleanup.ts` — legacy cleanup pattern + add old singular path
|
||||
- `docs/supported-tools.md` — documentation table
|
||||
- `test/core/command-generation/adapters.test.ts` — test assertion
|
||||
@@ -0,0 +1,63 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: ToolCommandAdapter interface
|
||||
|
||||
The system SHALL define a `ToolCommandAdapter` interface for per-tool formatting.
|
||||
|
||||
#### Scenario: Adapter interface structure
|
||||
|
||||
- **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)
|
||||
- `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
|
||||
- **AND** file path SHALL follow pattern `.claude/commands/opsx/<id>.md`
|
||||
|
||||
#### Scenario: Cursor adapter formatting
|
||||
|
||||
- **WHEN** formatting a command for Cursor
|
||||
- **THEN** the adapter SHALL output YAML frontmatter with `name` as `/opsx-<id>`, `id`, `category`, `description` fields
|
||||
- **AND** file path SHALL follow pattern `.cursor/commands/opsx-<id>.md`
|
||||
|
||||
#### Scenario: Windsurf adapter 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-<id>.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-<id>.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: 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)
|
||||
@@ -0,0 +1,19 @@
|
||||
## 1. Adapter Fix
|
||||
|
||||
- [x] 1.1 Update `src/core/command-generation/adapters/opencode.ts`: change `path.join('.opencode', 'command', ...)` to `path.join('.opencode', 'commands', ...)` and update the JSDoc comment
|
||||
|
||||
## 2. Legacy Cleanup
|
||||
|
||||
- [x] 2.1 Update `src/core/legacy-cleanup.ts`: update the `'opencode'` entry in `LEGACY_SLASH_COMMAND_PATHS` to detect both `opsx-*.md` and `openspec-*.md` patterns at `.opencode/command/` for backward compatibility
|
||||
|
||||
## 3. Documentation
|
||||
|
||||
- [x] 3.1 Update `docs/supported-tools.md`: change OpenCode command path from `.opencode/command/opsx-<id>.md` to `.opencode/commands/opsx-<id>.md`
|
||||
|
||||
## 4. Tests
|
||||
|
||||
- [x] 4.1 Update `test/core/command-generation/adapters.test.ts`: change the OpenCode file path assertion from `path.join('.opencode', 'command', 'opsx-explore.md')` to `path.join('.opencode', 'commands', 'opsx-explore.md')`
|
||||
|
||||
## 5. Changeset
|
||||
|
||||
- [x] 5.1 Create a changeset file (`.changeset/fix-opencode-commands-directory.md`) with a patch bump describing the path fix
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-25
|
||||
@@ -0,0 +1,38 @@
|
||||
## Context
|
||||
|
||||
`statusCommand` in `src/commands/workflow/status.ts` calls `validateChangeExists()` from `shared.ts` as its first operation. When no `--change` option is provided and no change directories exist, `validateChangeExists` throws: `No changes found. Create one with: openspec new change <name>`. This error propagates up as a fatal CLI error (non-zero exit code).
|
||||
|
||||
This is correct behavior for commands like `apply` and `show` that require a change to operate on. However, `status` is an informational command — it should report the current state, even when that state is "no changes exist."
|
||||
|
||||
The error surfaces during onboarding (issue #714) when AI agents call `openspec status` before any change has been created.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Make `openspec status` exit with code 0 and a friendly message when no changes exist
|
||||
- Support both text and JSON output modes for the no-changes case
|
||||
- Keep all other commands' validation behavior unchanged
|
||||
|
||||
**Non-Goals:**
|
||||
- Changing the behavior of `validateChangeExists` (keep it strict for all consumers; only extract its internal helper)
|
||||
- Changing the onboard template or skill instructions
|
||||
- Handling the case where `--change` is provided but the specific change doesn't exist (this should remain an error)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Extract `getAvailableChanges` and check before validation
|
||||
|
||||
**Rationale**: Extract the private `getAvailableChanges` closure from `validateChangeExists` into a public exported function in `shared.ts`. Then, in `statusCommand`, call `getAvailableChanges` *before* `validateChangeExists` to detect the no-changes case early and handle it gracefully. This avoids using try/catch for control flow and eliminates any coupling to error message strings.
|
||||
|
||||
**Alternative considered**: Catching the error from `validateChangeExists` by matching `error.message.startsWith('No changes found')`. Rejected because string coupling is fragile — if the error message changes, the catch silently stops working.
|
||||
|
||||
**Alternative considered**: Adding a `throwOnEmpty` parameter to `validateChangeExists`. Rejected because it adds complexity to a shared function for a single consumer's needs and mixes UX concerns into a validation utility.
|
||||
|
||||
### Keep `validateChangeExists` strict
|
||||
|
||||
**Rationale**: `validateChangeExists` remains unchanged in behavior — it still throws for all error cases. The graceful handling lives entirely in `statusCommand`, which is the appropriate layer for UX decisions. Other commands (`apply`, `show`, `instructions`) are unaffected.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Extra filesystem read when no `--change` is provided and changes *do* exist (`getAvailableChanges` is called first, then `validateChangeExists` performs its own read) → Mitigation: `statusCommand` returns early before reaching `validateChangeExists` when no changes exist, so the double-read only occurs when changes are present — minimal overhead.
|
||||
- [Risk] Other commands may also benefit from graceful no-changes handling in the future → Mitigation: `getAvailableChanges` is now public and reusable, making it easy to apply the same pattern elsewhere.
|
||||
@@ -0,0 +1,25 @@
|
||||
## Why
|
||||
|
||||
When `openspec status` is called without `--change` and no changes exist (e.g., during onboarding on a freshly initialized project), the CLI throws a fatal error: `No changes found. Create one with: openspec new change <name>`. This breaks the onboarding flow because AI agents may call `openspec status` before any change has been created, causing the agent to halt or report failure. Fixes [#714](https://github.com/Fission-AI/OpenSpec/issues/714).
|
||||
|
||||
## What Changes
|
||||
|
||||
- `openspec status` will exit gracefully (code 0) with a friendly message when no changes exist, instead of throwing a fatal error
|
||||
- `openspec status --json` will return a valid JSON object with an empty changes array when no changes exist
|
||||
- Other commands (`apply`, `show`, etc.) retain their current strict validation behavior
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `graceful-status-empty`: Graceful handling of `openspec status` when no changes exist, covering both text and JSON output modes
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
_None — `validateChangeExists` was internally refactored to delegate to the newly exported `getAvailableChanges`, but its behavior and public contract are unchanged. Other consumers are unaffected._
|
||||
|
||||
## Impact
|
||||
|
||||
- `src/commands/workflow/shared.ts` — extract `getAvailableChanges` as a public function (validation behavior unchanged)
|
||||
- `src/commands/workflow/status.ts` — check for available changes before validation, handle empty case gracefully
|
||||
- Tests for the status command need to cover the new graceful behavior
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user