Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
96f6cac
chore: add changeset for stores beta and config JSON parsing (#1267)
TabishB Jun 28, 2026
546224e
Version Packages (#1248)
openspec-release-bot[bot] Jun 28, 2026
a325305
fix(resolution): converge validate, view, and archive onto canonical …
clay-good Jul 3, 2026
65a7233
docs: add cloudflare documentation deployment website (#1285)
clay-good Jul 3, 2026
5956a8e
Fix `archive` exit code on validation failure (#1311)
danilopopeye Jul 6, 2026
a70dacc
feat(skills): propose /opsx:update planning-artifact update skill (#1…
clay-good Jul 7, 2026
9a0dfb5
refactor: unify requirement reader and surface #498 (#1281)
clay-good Jul 7, 2026
a5bfeda
feat(skills): auto-approve the openspec CLI in generated skills and c…
clay-good Jul 7, 2026
7e21cc5
fix archive scenario drift for #1246 (#1252)
zhangsan582 Jul 7, 2026
4ef0761
docs: clarify change name format (#1261)
ercanerdogan Jul 7, 2026
8ac624b
chore: remove stale npm lockfile (#1319)
TabishB Jul 7, 2026
3f0ca3f
feat: add Trae command adapter (#1090)
jjxyxsjr Jul 7, 2026
8886e3a
feat: add Oh My Pi (OMP) tool support (#1276)
xianzheTM Jul 7, 2026
871dece
chore: remove scheduled docs workflow (#1324)
TabishB Jul 8, 2026
296ecbc
Fix Windows CI flake hardening (#1325)
TabishB Jul 8, 2026
8e9e457
ci(release): add beta prerelease workflow (#1327)
clay-good Jul 8, 2026
93e27a7
fix empty store registration (#1328)
TabishB Jul 8, 2026
3903e62
chore: add changeset for stores beta and config JSON parsing (#1267)
TabishB Jun 28, 2026
95275be
fix(resolution): converge validate, view, and archive onto canonical …
clay-good Jul 3, 2026
ff62e1b
Complete upstream Fission-AI 1.5.0 sync merge
abdullahcw Jul 10, 2026
a788539
Merge pull request #1 from yumna-collab/fix/complete-upstream-1.5.0-sync
yumna-collab Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/add-skill-cli-auto-approval.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fission-ai/openspec": patch
---

### Features

- **Auto-approve the OpenSpec CLI in generated skills and commands** — every generated `SKILL.md` (all tools) and every Claude Code `/opsx:*` slash command now carries `allowed-tools: Bash(openspec:*)` in its frontmatter, so agents that honor the Agent Skills standard run `openspec` commands without prompting for approval on each call; tools that don't recognize the field ignore it. Scope is limited to the `openspec` CLI; because `allowed-tools` pre-approves rather than restricts, every other tool a skill or command uses stays available under your normal permission settings.
7 changes: 7 additions & 0 deletions .changeset/add-trae-command-adapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fission-ai/openspec": minor
---

### New Features

- **TRAE command adapter** — Added command adapter for Trae IDE, enabling generation of `.trae/commands/opsx-<id>.md` files for custom slash commands
7 changes: 7 additions & 0 deletions .changeset/fix-archive-exit-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@fission-ai/openspec": patch
---

### Bug Fixes

- **`archive` exits non-zero when blocked in human mode** — `openspec archive <change> -y` (and any non-`--json` invocation) no longer returns exit code 0 when validation fails and nothing is archived. The three blocking paths in human mode — delta-spec validation failure, spec rebuild failure, and rebuilt-spec validation failure — now set `process.exitCode = 1`, matching the existing `--json` behavior. Previously the command printed "Validation failed" (or "Aborted. No files were changed.") and exited 0, letting scripts and CI believe the archive succeeded. Aligns `archive` with the same exit-code guarantee already approved for `apply` instructions (#1250).
9 changes: 9 additions & 0 deletions .changeset/fix-validate-view-resolution-parity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@fission-ai/openspec": patch
---

### Bug Fixes

- **`validate` resolves changes like `status`** — `openspec validate <change>` (and `--all`/`--changes` and the interactive selector) now resolves a change by directory existence, matching `status`/`instructions`, instead of requiring `proposal.md`. A scaffolded or still-authoring change is validated rather than reported as `Unknown item`, and a resolved-but-invalid change now exits non-zero. Delta discovery also recurses the nested `specs/<area>/<capability>/spec.md` layout. (#1182)
- **Task progress reads nested/glob `tasks.md`** — `openspec view`, `list`, and the `archive` incomplete-task gate now resolve task progress through the tracked-tasks artifact's `generates` glob (the same file-resolution `status` uses), so a change whose tasks live in nested `tasks.md` files is classified correctly and can no longer archive while unfinished. (#1202)
- **SHALL/MUST body-keyword hint applies to main specs** — A main-spec requirement whose normative keyword sits only in the `### Requirement:` header now receives the same targeted "move it to the body line" remediation as a change delta, emitted exactly once. (#1156)
16 changes: 16 additions & 0 deletions .changeset/spec-parser-reading-fidelity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@fission-ai/openspec": patch
---

### Bug Fixes

- **Requirement reading fidelity** — The requirement reader used by `validate <change>`, `validate <spec>`, and `archive` is now unified into one fence-, metadata-, and multi-line-aware extraction, closing the known divergences between the change-delta path and the main-spec path (the remaining ones are documented in the change's design doc):
- A `SHALL`/`MUST` keyword that wraps onto a later body line is detected instead of dropped (#361).
- Metadata lines (`**ID**:`, `**Priority**:`) before the description are skipped on the spec path, matching the change path (#418). A requirement written entirely as metadata (e.g. `**Constraint**: The system MUST ...`) keeps that line as its text instead of being emptied.
- A fenced code block before the prose line no longer becomes the requirement text (#312).
- A `#### Scenario:` inside a fenced example no longer counts as a real scenario in `validate <change>`, matching `validate <spec>`.
- `SHALL`/`MUST` detection uses one whole-word predicate across all readers, and a requirement with no body text falls back to its header title on both paths.

Displayed requirement text (e.g. in JSON output and delta descriptions) now reflects the full requirement body rather than only its first line. Archived spec content is unchanged — the archive rebuild reads raw `### Requirement:` blocks, not the parsed text.

- **Surface non-canonical delta headers** — `validate <change>` now emits an INFO note when an `## ADDED`/`## MODIFIED Requirements` section contains a level-3 header that is not a canonical `### Requirement:` header (one the delta reader silently skips, such as a stray `### Documentation Requirements` divider). The note never changes the `valid` result, including under `--strict` (#498).
76 changes: 76 additions & 0 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Docs site

# The documentation site (website/) mirrors docs/*.md via scripts/sync-docs.mjs,
# which runs as the first step of `pnpm run build`. This workflow rebuilds that
# mirror:
# - on every push to main that touches docs/ or website/,
# - manually via the Actions tab,
# - and as a build-only check on pull requests.
#
# The Cloudflare Pages deploy step is temporarily disabled until setup is ready.
# When re-enabled, deploys require two repository secrets: CLOUDFLARE_API_TOKEN
# and CLOUDFLARE_ACCOUNT_ID. Set the site's public URL via the DOCS_SITE_URL
# repository variable (used for OG/sitemap absolute URLs).

on:
push:
branches: [main]
paths:
- 'docs/**'
- 'website/**'
- '.github/workflows/deploy-docs.yml'
pull_request:
paths:
- 'docs/**'
- 'website/**'
- '.github/workflows/deploy-docs.yml'
workflow_dispatch:

# Never run two docs site jobs at once; let an in-flight job finish.
concurrency:
group: deploy-docs
cancel-in-progress: false

jobs:
build-and-deploy:
# Keep enabled forks from spending CI on their own copy of this workflow.
# PRs from forks into Fission-AI/OpenSpec still run in the base repository.
if: ${{ github.repository == 'Fission-AI/OpenSpec' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: pnpm
cache-dependency-path: website/pnpm-lock.yaml

- name: Install dependencies
working-directory: website
run: pnpm install --frozen-lockfile

- name: Build site (mirrors docs/*.md, then next build)
working-directory: website
env:
NEXT_PUBLIC_SITE_URL: ${{ vars.DOCS_SITE_URL }}
run: pnpm run build

# Temporarily disabled until Cloudflare setup is ready.
# - name: Deploy to Cloudflare Pages
# # Only deploy from main on the canonical repo. This keeps PRs build-only,
# # keeps forks (no secrets) build-only, and because the wrangler command
# # below hardcodes `--branch=main` (a *production* deploy) prevents a
# # `workflow_dispatch` on a feature branch from overwriting the live site.
# if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/main' && github.repository == 'Fission-AI/OpenSpec' }}
# uses: cloudflare/wrangler-action@v3
# with:
# apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
# workingDirectory: website
# command: pages deploy out --project-name=openspec-docs --branch=main
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ CLAUDE.md

# Pnpm
.pnpm-store/
/package-lock.json
result

# OpenCode
Expand All @@ -164,3 +165,6 @@ opencode.json
# Codewalla telemetry identity (project-local fallback — primary is ~/.config/openspec/)
.openspec/telemetry-identity
.windsurf/...

# Trae
.trae/
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,24 @@

**Breaking:** Existing changes with `tasks.md` but no `plan.md` are blocked until a plan is added.

## 1.5.0

### Minor Changes

- [#1267](https://github.com/Fission-AI/OpenSpec/pull/1267) [`96f6cac`](https://github.com/Fission-AI/OpenSpec/commit/96f6cacb206c65bee30066f6a1f4e9b855a0d783) Thanks [@TabishB](https://github.com/TabishB)! - ### New Features

- **Stores (very early beta)** — Introduces stores as a simpler way to organize specs and changes, replacing the workspace and initiative model. This feature is in very early beta — expect rough edges and breaking changes in upcoming releases.

### Bug Fixes

- **Config parsing** — Configuration values wrapped in JSON containers are now parsed correctly.

### Patch Changes

- [#1240](https://github.com/Fission-AI/OpenSpec/pull/1240) [`cbf386b`](https://github.com/Fission-AI/OpenSpec/commit/cbf386bd6888f103f8ff7d59b3eab98ce5b57998) Thanks [@zied-jlassi](https://github.com/zied-jlassi)! - fix(adapters): escape carriage returns in generated YAML frontmatter

`escapeYamlValue` flagged `\r` as a character requiring quoting but never escaped it, leaving a literal carriage return inside the double-quoted scalar where YAML line folding/normalization could silently corrupt the value (realistic with CRLF-authored command descriptions). Carriage returns are now escaped as `\r`. The helper — previously duplicated verbatim across five adapters (bob, claude, cursor, pi, windsurf) — is extracted into a shared `command-generation/yaml.ts` module so the behavior stays consistent and is fixed in one place.

## 1.4.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ AI coding assistants are powerful but unpredictable when requirements live only
- **Work fluidly** — update any artifact anytime with `/opsx:modify`; no rigid phase gates
- **Jira-native workflow** — propose from ticket keys, enrich from Jira during apply, traceability in proposal Impact
- **MCP-powered** — Atlassian, Context7, and browser MCPs built into generated skills
- **Use your tools** — works with 20+ AI assistants via slash commands
- **Use your tools** — works with 30+ AI assistants via slash commands

## Updating OpenSpec

Expand Down
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ That second one matters more than it looks. OpenSpec has two halves: a command l

**I learn by example.** The [Examples & Recipes](examples.md) page walks through real changes start to finish: a small feature, a bug fix, a refactor, an exploration.

**The AI just drafted a plan — now what?** Read it. [Reviewing a Change](reviewing-changes.md) shows the two-minute pass that catches a wrong turn while it's still cheap, and [Writing Good Specs](writing-specs.md) covers what a plan worth approving is made of.

**I work on a team.** [OpenSpec on a Team](team-workflow.md) shows how a change maps onto a branch and a pull request, and how teammates review a plan before the code.

**I'm coming from the old workflow.** The [Migration Guide](migration-guide.md) explains what changed and why, and promises your existing work is safe.

**I want to bend it to my team's process.** [Customization](customization.md) covers project config, custom schemas, and shared context.
Expand Down Expand Up @@ -52,6 +56,9 @@ That second one matters more than it looks. OpenSpec has two halves: a command l
| [Workflows](workflows.md) | Common patterns and when to reach for each command |
| [MCP Setup](mcp-setup.md) | Atlassian, Context7, and browser MCP configuration |
| [Examples & Recipes](examples.md) | Full walkthroughs of real changes, copy-pasteable |
| [Writing Good Specs](writing-specs.md) | What a strong requirement and scenario look like, and how to right-size a change |
| [Reviewing a Change](reviewing-changes.md) | The two-minute pass on a drafted plan before any code is written |
| [OpenSpec on a Team](team-workflow.md) | How changes fit branches, pull requests, and review |
| [Using OpenSpec in an Existing Project](existing-projects.md) | Adopting OpenSpec on a large brownfield codebase |
| [Editing & Iterating on a Change](editing-changes.md) | Update artifacts, go back, reconcile manual edits |
| [Commands](commands.md) | Reference for every `/opsx:*` slash command |
Expand Down
4 changes: 2 additions & 2 deletions docs/agent-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ setup/register: `{ "store": {id, root, metadata_path?}, "registry": {path, regis
`no_openspec_root`, `no_root_with_registered_stores`, `no_registered_stores`, `unknown_store`, `store_identity_mismatch`, `unhealthy_store_root`, `store_path_not_supported`, `invalid_store_pointer`, `initiative_option_removed`, `areas_option_removed`; pass-through: `invalid_store_id`, `invalid_store_registry`, `invalid_store_metadata`.

### OpenSpec-root health (error, no fix)
`openspec_store_root_missing`, `openspec_root_missing`, `openspec_config_missing`, `openspec_specs_missing`, `openspec_changes_missing`, `openspec_archive_missing`, plus `_not_directory` variants of each.
`openspec_store_root_missing`, `openspec_store_root_not_directory`, `openspec_root_missing`, `openspec_root_not_directory`, `openspec_config_missing`, `openspec_config_not_file`, `openspec_specs_not_directory`, `openspec_changes_not_directory`, `openspec_archive_not_directory`. During the stores beta, `openspec/specs/`, `openspec/changes/`, and `openspec/changes/archive/` may be absent in a healthy root; they are only health errors when present but not directories.

### Store registry/identity/state
`invalid_store_id`, `invalid_store_registry`, `invalid_store_metadata`, `store_registry_busy`, `store_not_found`, `no_store_registry`, `store_registry_changed`, `store_metadata_missing`, `store_metadata_id_mismatch`, `store_metadata_invalid`, `store_id_conflict`, `store_path_conflict`, `store_already_registered` (info).

### Store setup/register/remove
`store_setup_id_required`, `store_setup_path_required`, `store_setup_path_not_directory`, `store_setup_inside_git_repo`, `store_setup_non_empty_directory`, `store_setup_cancelled`, `store_path_required`, `store_path_missing`, `store_path_not_directory`, `store_register_root_unhealthy`, `store_register_identity_confirmation_required`, `store_register_cancelled`, `store_remote_empty`, `store_remote_requires_hand_edit`, `store_remove_confirmation_required`, `store_remove_cancelled`, `store_remove_path_not_directory`, `store_remove_metadata_missing`, `store_root_missing` (warning in remove, error in doctor), `store_root_not_directory`.
`store_setup_id_required`, `store_setup_path_required`, `store_setup_path_not_directory`, `store_setup_inside_git_repo`, `store_setup_non_empty_directory`, `store_setup_cancelled`, `store_path_required`, `store_path_missing`, `store_path_not_directory`, `store_root_pointer_declared`, `store_register_root_unhealthy`, `store_register_identity_confirmation_required`, `store_register_cancelled`, `store_remote_empty`, `store_remote_requires_hand_edit`, `store_remove_confirmation_required`, `store_remove_cancelled`, `store_remove_path_not_directory`, `store_remove_metadata_missing`, `store_root_missing` (warning in remove, error in doctor), `store_root_not_directory`.

### Store git
`store_git_init_failed`, `store_git_identity_missing`, `store_git_commit_failed`, `store_git_no_commits` (warning), `store_clone_fragile_directories` (warning), `store_remote_divergence` (info, doctor).
Expand Down
16 changes: 14 additions & 2 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ openspec init [path] [options]

`--profile custom` uses whatever workflows are currently selected in global config (`openspec config profile`).

**Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `lingma`, `vibe`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`
**Supported tool IDs (`--tools`):** `amazon-q`, `antigravity`, `auggie`, `bob`, `claude`, `cline`, `codex`, `forgecode`, `codebuddy`, `continue`, `costrict`, `crush`, `cursor`, `factory`, `gemini`, `github-copilot`, `iflow`, `junie`, `kilocode`, `kimi`, `kiro`, `lingma`, `vibe`, `oh-my-pi`, `opencode`, `pi`, `qoder`, `qwen`, `roocode`, `trae`, `windsurf`

> This list mirrors `AI_TOOLS` in `src/core/config.ts`. See [Supported Tools](supported-tools.md) for each tool's skill and command paths.

Expand Down Expand Up @@ -215,7 +215,12 @@ openspec store setup team-context --path ~/openspec/team-context --no-init-git -

### `openspec store register`

Register an existing local store folder.
Register an existing local store folder. During the stores beta, a root may be
registered before any changes exist, specs have been applied, or changes have
been archived; in that case `openspec/changes/`, `openspec/specs/`, and
`openspec/changes/archive/` may be absent until normal commands create them.
A config-only repo that declares `store: <id>` remains a pointer to another
store and is not registered as a store root unless that pointer is removed.

```bash
openspec store register [path] [options]
Expand Down Expand Up @@ -620,6 +625,13 @@ Create a change directory and optional checked-in metadata in the resolved OpenS
openspec new change <name> [options]
```

Change names must use lowercase kebab-case. They start with a lowercase letter,
then contain lowercase letters, numbers, and single hyphens. They cannot start
with a number, contain spaces, underscores, uppercase letters, consecutive
hyphens, or leading/trailing hyphens. When including an external ticket ID,
prefix it with a word, for example `ticket-123-add-notifications` instead of
`123-add-notifications`.

**Options:**

| Option | Description |
Expand Down
Loading