Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e6256ee
docs: preserve domain archive requirements on upstream baseline
terryzhong Jul 15, 2026
0b2aae5
feat: add domain archive path helpers
terryzhong Jul 15, 2026
4da6b26
fix: propagate unexpected change discovery errors
terryzhong Jul 15, 2026
b0f16da
fix: move store archive roots to sibling archive
terryzhong Jul 15, 2026
31393c8
test: cover createChange archive scaffolding
terryzhong Jul 15, 2026
131d12b
docs: correct task 2 report metadata
terryzhong Jul 15, 2026
beae2e9
feat: wire recursive change consumers
terryzhong Jul 15, 2026
937a6ce
test: tighten view dashboard section assertions
terryzhong Jul 15, 2026
e54e8c1
feat: add domain-aware change creation
terryzhong Jul 15, 2026
01422f3
fix: harden domain change paths
terryzhong Jul 15, 2026
97b36dd
feat: preserve change domains during archive
terryzhong Jul 15, 2026
0d154ce
fix: validate archive change IDs before mutation
terryzhong Jul 15, 2026
76783c7
refactor: centralize change ID resolution
terryzhong Jul 15, 2026
c9c692b
feat: update workflows for mandatory domains
terryzhong Jul 15, 2026
4e10658
fix: preserve domain-qualified workflow IDs
terryzhong Jul 15, 2026
d639990
chore: remove internal task reports
terryzhong Jul 15, 2026
3b1cab2
fix: complete final review hardening
terryzhong Jul 15, 2026
09c3f38
docs: remove trailing whitespace
terryzhong Jul 15, 2026
1efce07
fix: close final domain archive review findings
terryzhong Jul 15, 2026
f6896fa
fix(cli): secure change resolution and recursive legacy list
terryzhong Jul 15, 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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@

- [#587](https://github.com/Fission-AI/OpenSpec/pull/587) [`943e0d4`](https://github.com/Fission-AI/OpenSpec/commit/943e0d41026d034de66b9442d1276c01b293eb2b) Thanks [@TabishB](https://github.com/TabishB)! - ### Bug Fixes

- Fixed incorrect archive path in onboarding documentation — the template now shows the correct path `openspec/changes/archive/YYYY-MM-DD-<name>/` instead of the incorrect `openspec/archive/YYYY-MM-DD--<name>/`
- Legacy behavior: fixed the then-current nested archive path in onboarding documentation. Current releases use the sibling `openspec/archive/YYYY-MM-DD-<name>/` layout.

## 1.0.0

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ AI: Implementing tasks...
All tasks complete!

You: /opsx:archive
AI: Archived to openspec/changes/archive/2025-01-23-add-dark-mode/
AI: Archived to openspec/archive/2025-01-23-add-dark-mode/
Specs updated. Ready for the next feature.
```

Expand Down
6 changes: 3 additions & 3 deletions docs/agent-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ Change: `{ "id", "title", "deltaCount", "deltas": [...], "root" }`. Spec: `{ "id
### 4.7 `new change <name> --json`
Success: `{ "change": { "id", "path", "metadataPath", "schema" }, "root" }`. Failure: `{ "change": null, "status": [d] }`, exit 1.

### 4.8 `archive <name> --json`
Success: `{ "archive": { "change", "archivedAs": "YYYY-MM-DD-name", "path", "specsUpdated", "totals"? }, "root" }`. Failure: `{ "archive": null, "root"?, "status": [d] }`, exit 1. JSON mode is strictly non-interactive: every prompt point becomes an `archive_*` code.
### 4.8 `archive <change-id> --json`
Success: `{ "archive": { "change", "archivedAs": "[domain/]YYYY-MM-DD-name", "path", "specsUpdated", "totals"? }, "root" }`. The optional `domain/` contains every domain segment from the full change ID. Failure: `{ "archive": null, "root"?, "status": [d] }`, exit 1. JSON mode is strictly non-interactive: every prompt point becomes an `archive_*` code.

### 4.9 `doctor --json`
`{ "root": { "path", "source", "store_id"?, "healthy", "status": [] }, "store": { "id", "metadata": {present,valid,remote?}, "origin_url"?, "status": [] } | null, "references": [...], "status": [] }`. Health findings of any severity exit 0. Failure payload: `{ "root": null, "store": null, "references": [], "status": [d] }`, exit 1.
Expand Down Expand Up @@ -97,7 +97,7 @@ 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_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.
`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/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).
Expand Down
17 changes: 9 additions & 8 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ These commands support `--json` output for programmatic use by AI agents and scr
| `openspec store remove <id>` | Delete a registered local store folder | `--yes --json` for non-interactive deletion |
| `openspec store list` | Browse registered stores | `--json` for structured registrations |
| `openspec store doctor` | Check local store setup | `--json` for structured diagnostics |
| `openspec new change <id>` | Create repo-local change scaffolding | `--json`, plus `--store <id>` to use a registered store as the OpenSpec root |
| `openspec new change <id>` | Create repo-local change scaffolding | Explicit `--domain <path>` or `--domain ""`; add `--json` for structured output and `--store <id>` for a registered Store |
| `openspec workset create [name]` | Compose a personal working view | `--member <path> --json` for non-interactive composition |
| `openspec workset list` | Browse saved worksets | `--json` for structured views |
| `openspec workset remove <name>` | Delete a saved view | `--yes --json` for non-interactive removal |
Expand Down Expand Up @@ -218,7 +218,7 @@ openspec store setup team-context --path ~/openspec/team-context --no-init-git -
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.
`openspec/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.

Expand Down Expand Up @@ -571,7 +571,7 @@ Validating add-dark-mode...
Archive a completed change and merge delta specs into main specs.

```
openspec archive [change-name] [options]
openspec archive [change-id] [options]
```

**Arguments:**
Expand Down Expand Up @@ -609,7 +609,7 @@ openspec archive update-ci-config --skip-specs
1. Validates the change (unless `--no-validate`)
2. Prompts for confirmation (unless `--yes`)
3. Merges delta specs into `openspec/specs/`
4. Moves change folder to `openspec/changes/archive/YYYY-MM-DD-<name>/`
4. Moves a root change to `openspec/archive/YYYY-MM-DD-<name>/`, or preserves its domain at `openspec/archive/<domain>/YYYY-MM-DD-<name>/`

---

Expand All @@ -622,7 +622,7 @@ These commands support the artifact-driven OPSX workflow. They're useful for bot
Create a change directory and optional checked-in metadata in the resolved OpenSpec root.

```bash
openspec new change <name> [options]
openspec new change <name> --domain <path|""> [options]
```

Change names must use lowercase kebab-case. They start with a lowercase letter,
Expand All @@ -639,14 +639,15 @@ prefix it with a word, for example `ticket-123-add-notifications` instead of
| `--description <text>` | Description to add to `README.md` |
| `--goal <text>` | Optional goal metadata to store with the change |
| `--schema <name>` | Workflow schema to use |
| `--domain <path>` | Mandatory domain decision; use a slash-delimited path, or `--domain ""` for root placement |
| `--store <id>` | Store id to use as the OpenSpec root (a store is a standalone OpenSpec repo you've registered) |
| `--json` | Output JSON |

Examples:

```bash
openspec new change add-billing-api
openspec new change add-billing-api --store team-context --json
openspec new change add-billing-api --domain billing
openspec new change add-billing-api --domain "" --store team-context --json
```

### `openspec status`
Expand All @@ -661,7 +662,7 @@ openspec status [options]

| Option | Description |
|--------|-------------|
| `--change <id>` | Change name (prompts if omitted) |
| `--change <id>` | Full slash-delimited change ID (prompts if omitted) |
| `--schema <name>` | Schema override (auto-detected from change's config) |
| `--json` | Output as JSON |

Expand Down
16 changes: 8 additions & 8 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ Create the next artifact in the dependency chain. Creates one artifact at a time

**Syntax:**
```
/opsx:continue [change-name]
/opsx:continue [change-id]
```

**Arguments:**
Expand Down Expand Up @@ -274,7 +274,7 @@ Implement tasks from the change. Works through the task list, writing code and c

**Syntax:**
```
/opsx:apply [change-name]
/opsx:apply [change-id]
```

**Arguments:**
Expand Down Expand Up @@ -336,7 +336,7 @@ Revise a change's existing planning artifacts and keep them coherent with one an

**What it does:**

- Reads the change's artifacts via `openspec status --change <name> --json`
- Reads the change's artifacts via `openspec status --change <change-id> --json`
- Applies your requested revision, or reviews the artifacts for contradictions if you didn't name one
- Reconciles the other existing artifacts in any direction (a design edit may ripple back to the proposal)
- Confirms every edit with you before writing, one artifact at a time
Expand Down Expand Up @@ -373,7 +373,7 @@ Validate that implementation matches your change artifacts. Checks completeness,

**Syntax:**
```
/opsx:verify [change-name]
/opsx:verify [change-id]
```

**Arguments:**
Expand Down Expand Up @@ -498,7 +498,7 @@ Archive a completed change. Finalizes the change and moves it to the archive fol

**Syntax:**
```
/opsx:archive [change-name]
/opsx:archive [change-id]
```

**Arguments:**
Expand All @@ -510,7 +510,7 @@ Archive a completed change. Finalizes the change and moves it to the archive fol
- Checks artifact completion status
- Checks task completion (warns if incomplete)
- Offers to sync delta specs if not already synced
- Moves change folder to `openspec/changes/archive/YYYY-MM-DD-<name>/`
- Moves a root change to `openspec/archive/YYYY-MM-DD-<name>/`, or a domain change to `openspec/archive/<domain>/YYYY-MM-DD-<name>/`
- Preserves all artifacts for audit trail

**Example:**
Expand All @@ -531,7 +531,7 @@ AI: Archiving add-dark-mode...
You: Yes

AI: ✓ Synced specs to openspec/specs/ui/spec.md
✓ Moved to openspec/changes/archive/2025-01-24-add-dark-mode/
✓ Moved to openspec/archive/2025-01-24-add-dark-mode/

Change archived successfully.
```
Expand Down Expand Up @@ -716,7 +716,7 @@ The command couldn't identify which change to work on.
All artifacts are either complete or blocked by missing dependencies.

**Solutions:**
- Run `openspec status --change <name>` to see what's blocking
- Run `openspec status --change <change-id>` to see what's blocking
- Check if required artifacts exist
- Create missing dependency artifacts first

Expand Down
4 changes: 2 additions & 2 deletions docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Packaging a change as a folder has several benefits:

2. **Parallel work.** Multiple changes can exist simultaneously without conflicting. Work on `add-dark-mode` while `fix-auth-bug` is also in progress.

3. **Clean history.** When archived, changes move to `changes/archive/` with their full context preserved. You can look back and understand not just what changed, but why.
3. **Clean history.** When archived, changes move to the sibling `archive/` tree with their full domain context preserved. You can look back and understand not just what changed, but why.

4. **Review-friendly.** A change folder is easy to review — open it, read the proposal, check the design, see the spec deltas.

Expand Down Expand Up @@ -543,7 +543,7 @@ openspec/

1. **Merge deltas.** Each delta spec section (ADDED/MODIFIED/REMOVED) is applied to the corresponding main spec.

2. **Move to archive.** The change folder moves to `changes/archive/` with a date prefix for chronological ordering.
2. **Move to archive.** The change folder moves to the sibling `archive/` tree with a date prefix for chronological ordering and its domain path preserved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the adjacent archive diagram to the sibling layout.

Lines 527-539 still show openspec/changes/archive, contradicting this revised process and the PR’s new openspec/archive structure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/concepts.md` at line 546, Update the archive diagram adjacent to the
“Move to archive” step in docs/concepts.md to show the sibling openspec/archive
layout instead of openspec/changes/archive, while preserving the date prefix and
domain path structure.


3. **Preserve context.** All artifacts remain intact in the archive. You can always look back to understand why a change was made.

Expand Down
6 changes: 3 additions & 3 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ rules:

```bash
# Without config
openspec new change my-feature --schema spec-driven
openspec new change my-feature --schema spec-driven --domain ""

# With config - schema is automatic
openspec new change my-feature
openspec new change my-feature --domain ""
```

**Context and rules injection:**
Expand Down Expand Up @@ -241,7 +241,7 @@ Once created, use your schema with:

```bash
# Specify on command
openspec new change feature --schema my-workflow
openspec new change feature --schema my-workflow --domain platform

# Or set as default in config.yaml
schema: my-workflow
Expand Down
2 changes: 1 addition & 1 deletion docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ You: /opsx:archive

AI: Archiving add-logout-button...
✓ Merged specs into openspec/specs/auth/spec.md
✓ Moved to openspec/changes/archive/2026-06-22-add-logout-button/
✓ Moved to openspec/archive/2026-06-22-add-logout-button/
Done. Ready for the next change.
```

Expand Down
2 changes: 1 addition & 1 deletion docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ A spec that describes only what's changing, using `ADDED`, `MODIFIED`, and `REMO

### Where do archived changes go?

To `openspec/changes/archive/YYYY-MM-DD-<name>/`, with all artifacts preserved. Nothing is deleted; the change just moves out of your active list.
To `openspec/archive/YYYY-MM-DD-<name>/` for a root change, or `openspec/archive/<domain>/YYYY-MM-DD-<name>/` for a domain change, with all artifacts preserved. Nothing is deleted; the change just moves out of your active list.

## Configuration and customization

Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ When you archive a change:
2. **MODIFIED** requirements replace the existing version
3. **REMOVED** requirements are deleted from the main spec

The change folder moves to `openspec/changes/archive/` for audit history.
The change folder moves to the sibling `openspec/archive/` tree for audit history, preserving any domain path.

## Example: Your First Change

Expand Down Expand Up @@ -248,7 +248,7 @@ You: /opsx:archive

AI: Archiving add-dark-mode...
✓ Merged specs into openspec/specs/ui/spec.md
✓ Moved to openspec/changes/archive/2025-01-24-add-dark-mode/
✓ Moved to openspec/archive/2025-01-24-add-dark-mode/
Done! Ready for the next feature.
```

Expand Down
2 changes: 1 addition & 1 deletion docs/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Terms are grouped by topic, then alphabetized within each group.

## The lifecycle

**Archive.** The act of finishing a change. Its delta specs merge into the main specs, and the change folder moves to `openspec/changes/archive/YYYY-MM-DD-<name>/`. After archiving, your specs describe the new reality. See [Concepts](concepts.md#archive).
**Archive.** The act of finishing a change. Its delta specs merge into the main specs, and the change folder moves to `openspec/archive/YYYY-MM-DD-<name>/` or the domain-preserving `openspec/archive/<domain>/YYYY-MM-DD-<name>/`. After archiving, your specs describe the new reality. See [Concepts](concepts.md#archive).

**Sync.** Merging a change's delta specs into the main specs *without* archiving the change. Usually automatic (archive offers to do it), but available on its own as `/opsx:sync` for long-running changes. See [Commands](commands.md#opsxsync).

Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ npm uninstall -g @fission-ai/openspec # or: pnpm rm -g / yarn global remove /
rm -rf openspec/
```

Think before you do this: `openspec/specs/` and `openspec/changes/archive/` are your record of how the system behaves and why it changed. If you might want that history, keep the folder (or keep it in git) even after uninstalling.
Think before you do this: `openspec/specs/` and `openspec/archive/` are your record of how the system behaves and why it changed. If you might want that history, keep the folder (or keep it in git) even after uninstalling.

**3. Remove generated AI tool files (optional).** OpenSpec writes skill and command files into per-tool directories like `.claude/skills/openspec-*/`, `.cursor/commands/opsx-*`, and so on. Delete the `openspec-*` skills and `opsx-*` commands for whichever tools you configured. The exact paths per tool are listed in [Supported Tools](supported-tools.md).

Expand Down
2 changes: 1 addition & 1 deletion docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ proposal ──► specs ──► design ──► tasks ──► implement

You can revisit any of them at any time. They're enablers, not gates. (More on that below.)

**5. Archiving folds the change back into the truth.** When the work is done, you archive the change. Its delta specs merge into your main specs, and the change folder moves to `changes/archive/` with a date stamp. Now your specs describe the new reality, and you're ready for the next change. The cycle closes.
**5. Archiving folds the change back into the truth.** When the work is done, you archive the change. Its delta specs merge into your main specs, and the change folder moves to the sibling `archive/` tree with a date stamp and its domain preserved. Now your specs describe the new reality, and you're ready for the next change. The cycle closes.

## The picture

Expand Down
11 changes: 6 additions & 5 deletions docs/stores-beta/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,20 @@ OpenSpec root: ready
Registry: registered

Next: run normal OpenSpec commands against this store, for example:
openspec new change <change-id> --store team-plans
openspec new change <name> --domain <path> --store team-plans
openspec new change <name> --domain "" --store team-plans
Share this store by committing and pushing it like any Git repo.
```

```bash
openspec new change add-login --store team-plans
openspec new change add-login --domain auth --store team-plans
```

```
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
Created change 'add-login' at /Users/you/openspec/team-plans/openspec/changes/add-login/
Created change 'auth/add-login' at /Users/you/openspec/team-plans/openspec/changes/auth/add-login/
Schema: spec-driven
Next: openspec status --change add-login --store team-plans
Next: openspec status --change auth/add-login --store team-plans
```

That's the whole model. From here the lifecycle is exactly what you know —
Expand Down Expand Up @@ -309,7 +310,7 @@ tells you which case you're in.
A stale checkout shows stale specs until *you* pull; references are
indexed live from whatever is on disk.
- **Empty planning folders can be absent.** A new store may not have
`openspec/changes/`, `openspec/specs/`, or `openspec/changes/archive/` in Git
`openspec/changes/`, `openspec/specs/`, or `openspec/archive/` in Git
yet. That is accepted during the beta; those folders appear once normal
commands create files for them.
- **Pointer repos stay pointers.** A config-only repo whose
Expand Down
Loading