Skip to content

Commit 80b9031

Browse files
committed
fix(guidance): harden spec inventory discovery against current main
2 parents 308e8df + a0ddb60 commit 80b9031

64 files changed

Lines changed: 5405 additions & 379 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/explore-explicit-write-confirmation.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/plain-ascii-explore-diagrams.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# @fission-ai/openspec
22

3+
## 1.11.0
4+
5+
### Minor Changes
6+
7+
- [#1301](https://github.com/Fission-AI/OpenSpec/pull/1301) [`a7353ae`](https://github.com/Fission-AI/OpenSpec/commit/a7353aea9a0b23762602badf5055a157a76f62b1) Thanks [@m-tanner](https://github.com/m-tanner)! - Add `openspec status --all`, which reports every active change in one process instead of one CLI spawn per change. `--all --json` emits a single `{ "changes": [ <status>, ... ], "root" }` envelope sorted by change name; a change that fails to load contributes `{ "changeName", "status": [diagnostic] }` in place rather than aborting the sweep. A partial failure exits 1 in both text and JSON modes while preserving the complete JSON envelope. Mutually exclusive with `--change`.
8+
9+
- [#980](https://github.com/Fission-AI/OpenSpec/pull/980) [`dd7cea3`](https://github.com/Fission-AI/OpenSpec/commit/dd7cea3ffed4a22421dce02f54c37c4f076b44f0) Thanks [@bsmedberg-xometry](https://github.com/bsmedberg-xometry)! - show: add `--diff`, which renders each delta requirement against the requirement it replaces in the main spec instead of reprinting the whole block. A MODIFIED requirement has to carry every scenario it keeps, so reviewers could not see what a change actually altered without diffing files by hand. `openspec show <change> --diff` now prints a colorized unified diff per requirement (additions green, removals red), the full text of ADDED requirements, the authored Reason/Migration text of REMOVED ones, and FROM/TO for RENAMED ones; a requirement that is renamed and modified in the same delta is diffed against its old name. `--json --diff` keeps the existing payload shape and adds each applicable `diff` and `warning` field to MODIFIED deltas only. Main specs resolve against the same root as the change, so `--store <id>` diffs against that store. Without `--diff`, `openspec show <change>` prints exactly what it printed before.
10+
11+
### Patch Changes
12+
13+
- [#830](https://github.com/Fission-AI/OpenSpec/pull/830) [`109f81f`](https://github.com/Fission-AI/OpenSpec/commit/109f81f17d3bb99eb6fb2c9a33ec9e8ab0680bb2) Thanks [@alfred-openspec](https://github.com/alfred-openspec)! - Write Antigravity skills and workflows to `.agents/`, arbitrate its shared skill tree with other tools, and safely migrate an existing `.agent/` install.
14+
15+
- [#1712](https://github.com/Fission-AI/OpenSpec/pull/1712) [`04b37ac`](https://github.com/Fission-AI/OpenSpec/commit/04b37ac1d5c852385d2effbff196ddb4fdd1700c) Thanks [@Marzx13](https://github.com/Marzx13)! - archive: preserve a requirement's original position when renaming it instead of moving the renamed block to the end of the spec.
16+
17+
- [#1716](https://github.com/Fission-AI/OpenSpec/pull/1716) [`7010e26`](https://github.com/Fission-AI/OpenSpec/commit/7010e268907598c385eb6686699928fbd5a3a733) Thanks [@aymanxdev](https://github.com/aymanxdev)! - explore: require explicit, scope-bound confirmation before the skill uses any command or tool that can create, edit, move, or delete a file. The explore skill's guardrails let "if the user asks" cover answers to its own clarifying questions, so an agent could treat a design discussion as a go-ahead and start creating schemas or editing `openspec/config.yaml` uninvited. The skill and the `/opsx:explore` command now instruct the agent to name the proposed artifacts or files, ask a direct yes/no question, and wait for confirmation in a separate message before writing. Read-only commands and tools remain available without confirmation, and expanding the confirmed scope requires another confirmation.
18+
19+
- [#1199](https://github.com/Fission-AI/OpenSpec/pull/1199) [`ab81a4b`](https://github.com/Fission-AI/OpenSpec/commit/ab81a4b43a7bd769b1d2a33457b7b708b8c52516) Thanks [@leo-ar](https://github.com/leo-ar)! - Improve Fish completions so command, subcommand, flag, and indexed positional completions no longer fall back to filesystem suggestions unless the target is a real path.
20+
21+
- [#1010](https://github.com/Fission-AI/OpenSpec/pull/1010) [`e5e350d`](https://github.com/Fission-AI/OpenSpec/commit/e5e350d04b5d635b56846f46a212b097cd00eeb6) Thanks [@Dansyuqri](https://github.com/Dansyuqri)! - Draw explore-mode diagrams with plain ASCII. The worked examples in the explore skill and `/opsx:explore` command used Unicode box-drawing, arrow, and marker glyphs, whose display width varies across terminals, fonts, and locales. Agents copied the style, causing padded boxes and aligned tables to drift.
22+
23+
- [`2fa679f`](https://github.com/Fission-AI/OpenSpec/commit/2fa679f180424d46ce7d8789eb85138397844a89) Thanks [@ryandemelo](https://github.com/ryandemelo)! - Make `schema init --default` validate and stage config changes before installing a schema, and roll back both files if either install fails. The staging and backup directories it creates are excluded from schema discovery, so they are never offered as real schemas.
24+
25+
- [#1671](https://github.com/Fission-AI/OpenSpec/pull/1671) [`126c5d6`](https://github.com/Fission-AI/OpenSpec/commit/126c5d6c59d63b7e70314bcc776104c7cc548819) Thanks [@kitimark](https://github.com/kitimark)! - `openspec validate` now reports a `## Purpose` that is still the placeholder archive writes for a new capability, instead of passing it. The placeholder is longer than the 50-character brevity floor, so until now the one check meant to catch a Purpose nobody wrote was satisfied by the exact text saying nobody wrote one — a spec whose Purpose read `Does stuff.` failed `--strict` while a spec whose Purpose said nothing at all passed. A capability could carry the placeholder indefinitely while every command reported success.
26+
27+
It is a warning, so a project that already has placeholders on disk keeps validating by default and only `--strict` fails. The message says to edit the main spec directly, since a `## Purpose` in a delta is read only when the capability is created and cannot replace an existing one.
28+
29+
Detection is narrow. The placeholder archive generates is recognised through the same definition that writes it, wherever it appears in the Purpose. Otherwise only a `TBD` or `TODO` opening the Purpose counts, so `The retry budget is TBD pending benchmarks` is still a valid Purpose and a word like `TBDs` is not a marker. Fenced code inside the Purpose is quoted material rather than the Purpose speaking, so a spec that documents the placeholder keeps passing. An empty Purpose is unchanged, and a Purpose reported as a placeholder is no longer also reported as too brief, so a bare `TBD` yields one finding rather than two.
30+
31+
`openspec archive` is unaffected: it validates rebuilt specs without `--strict`, so a spec archive writes still passes the validation it would have passed before, and the text archive writes is unchanged.
32+
333
## 1.10.0
434

535
### Minor Changes

docs-lab/Notes.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,6 @@ the agent to consume it. Running `openspec update` should refresh them.
7676

7777
Product issues found while verifying the schema system (all file refs current as of today):
7878

79-
- `schema init --default` writes a `defaultSchema:` key to openspec/config.yaml that nothing
80-
reads (schema.ts:961-978; readProjectConfig parses only schema/context/rules/operations/
81-
references/store). The flag should write `schema:` or be removed. The docs now say to set
82-
`schema:` by hand.
8379
- `schema init` next-steps output prints a command that doesn't exist in that form:
8480
"Use with: openspec new --schema <name>" (schema.ts:999); real syntax is
8581
`openspec new change <name> --schema <name>`.

docs-lab/reference/cli.md

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Your agent runs most of these during the workflow.
3131
| Command | What it does |
3232
|---|---|
3333
| [`openspec new`](#openspec-new) | Create a new change directory. |
34-
| [`openspec status`](#openspec-status) | Artifact completion status for a change. |
34+
| [`openspec status`](#openspec-status) | Artifact completion status for one or every active change. |
3535
| [`openspec instructions`](#openspec-instructions) | Instructions for creating an artifact, applying, or archiving. |
3636
| [`openspec templates`](#openspec-templates) | Resolved template paths for a schema's artifacts. |
3737
| [`openspec schemas`](#openspec-schemas) | List available workflow schemas. |
@@ -460,6 +460,7 @@ Prints a change or spec, as markdown or JSON.
460460

461461
```bash
462462
openspec show add-rate-limit # change: prints proposal.md
463+
openspec show add-rate-limit --diff # change: append requirement diffs
463464
openspec show api # spec: prints spec.md
464465
openspec show api --json --no-scenarios # spec JSON without scenario text
465466
```
@@ -481,6 +482,7 @@ With no name, show asks change or spec, then lists items to pick from. Outside a
481482
| `--no-interactive` | Never prompt: a missing name becomes an error. |
482483
| `--deltas-only` | JSON, change: restrict output to deltas. Change JSON is already delta-only, so output matches plain `--json`. |
483484
| `--requirements-only` | Deprecated alias for `--deltas-only`. Warns on stderr. |
485+
| `--diff` | Change: append per-requirement delta diffs. Ignored with a warning for specs. |
484486
| `--requirements` | JSON, spec: keep requirement text, empty the `scenarios` arrays. |
485487
| `--no-scenarios` | JSON, spec: same output as `--requirements`. |
486488
| `-r, --requirement <id>` | JSON, spec: output one requirement by 1-based position. Can't combine with `--requirements`. |
@@ -502,6 +504,10 @@ Unauthenticated clients can exhaust the API.
502504
- Add per-client rate limiting to the public API.
503505
```
504506

507+
For a change, `--diff` prints the proposal first, then a `Specifications Changed (diffs)` section. ADDED requirements include their full text. REMOVED requirements retain the authored Reason and Migration. RENAMED requirements show FROM and TO. MODIFIED requirements show a unified diff against the matching main requirement.
508+
509+
If a MODIFIED header matches only after folding case or whitespace, the output includes both the diff and a warning that archive matching is exact. If the main spec or requirement is missing, the output warns and prints the full delta block. A MODIFIED block with no textual difference prints `(no textual changes)`.
510+
505511
A change with `--json` is delta-shaped:
506512

507513
```json
@@ -532,6 +538,8 @@ A change with `--json` is delta-shaped:
532538
}
533539
```
534540

541+
`--json --diff` keeps this top-level shape. A MODIFIED delta gains a `diff` string, a `warning` string, or both. Other operations are unchanged. An empty `diff` string means the main and delta blocks are textually identical.
542+
535543
A spec with `--json` lists its requirements with scenarios:
536544

537545
```json
@@ -566,7 +574,7 @@ An unknown name suggests near matches: `Unknown item 'does-not-exist'. Did you m
566574
**Exit codes**
567575

568576
- `0`: item printed.
569-
- `1`: unknown or ambiguous name, no name outside a terminal, an out-of-range `-r` index, or `--requirements` combined with `-r`.
577+
- `1`: unknown or ambiguous name, no name outside a terminal, an out-of-range `-r` index, `--requirements` combined with `-r`, or a delta or main spec cannot be read for `--diff`.
570578

571579
## openspec view
572580

@@ -866,25 +874,30 @@ With `--json`:
866874

867875
## openspec status
868876

869-
Reports artifact completion status for a change.
877+
Reports artifact completion status for one change or every active change.
870878

871879
```bash
872880
openspec status --change add-rate-limit # checklist view
873881
openspec status --change add-rate-limit --json # structured report
882+
openspec status --all # every active change
883+
openspec status --all --json # one batch report
874884
```
875885

876-
`--change` is required. Without it, status exits 1 and lists the available changes, even when only one exists:
886+
When active changes exist, use exactly one of `--change` or `--all`. Without either, status exits 1 and lists the available changes, even when only one exists:
877887

878-
```
879-
✖ Error: Missing required option --change. Available changes:
888+
```text
889+
✖ Error: Missing required option --change (or --all for every active change). Available changes:
880890
add-rate-limit
881891
```
882892

893+
When the project has no active changes, status prints `No active changes. Create one with: openspec new change <name>` and exits 0 even without either flag. With `--all --json`, the same empty state is `{ "changes": [], "message": "No active changes.", "root": ... }`.
894+
883895
**Options**
884896

885897
| Flag | Effect |
886898
|---|---|
887899
| `--change <id>` | The change to report on, by folder name. |
900+
| `--all` | Report every active change, sorted by name. Can't be combined with `--change`. |
888901
| `--schema <name>` | Override the schema auto-detected from `openspec/config.yaml`. An unknown name is an error. |
889902
| `--json` | Print a structured report instead of text. |
890903
| `--store <id>` | Use a registered store as the OpenSpec root instead of the current project. |
@@ -946,10 +959,30 @@ Progress: 2/4 artifacts complete
946959
}
947960
```
948961

962+
With `--all --json`, `changes` contains the same status object for each change, without a per-change `root`. The selected root appears once on the envelope. This example trims the per-change status fields shown above:
963+
964+
```json
965+
{
966+
"changes": [
967+
{
968+
"changeName": "add-rate-limit",
969+
"schemaName": "spec-driven",
970+
"artifacts": []
971+
}
972+
],
973+
"root": {
974+
"path": "/Users/you/projects/my-app",
975+
"source": "nearest"
976+
}
977+
}
978+
```
979+
980+
If one change can't load, the batch continues. Its entry contains `changeName` and a `status` diagnostic while the other entries remain available. The command exits 1, including in JSON mode, so CI doesn't accept an incomplete report as successful. JSON output remains one parseable document.
981+
949982
**Exit codes**
950983

951-
- `0`: status printed.
952-
- `1`: `--change` missing, the change doesn't exist, or the schema override is unknown.
984+
- `0`: every requested status printed; an empty `--all` report also exits 0.
985+
- `1`: a requested change failed to load, `--change` or `--all` is missing, the two flags were combined, the change doesn't exist, or the schema override is unknown.
953986

954987
## openspec instructions
955988

@@ -1317,11 +1350,13 @@ With no `--description` and no `--artifacts` in an interactive terminal, init pr
13171350
|---|---|
13181351
| `--description <text>` | Schema description. Default: `Custom workflow schema for <name>`. |
13191352
| `--artifacts <list>` | Comma-separated artifact IDs from `proposal`, `specs`, `design`, `tasks`. Default: all four. |
1320-
| `--default` | Writes `defaultSchema` to `openspec/config.yaml`. Nothing reads that key. To make the schema the default, set `schema: <name>` there yourself. |
1353+
| `--default` | Writes `schema: <name>` to the existing `openspec/config.yaml` or `openspec/config.yml`. Creates `openspec/config.yaml` if neither exists. New changes use this schema. |
13211354
| `--no-default` | Skip the prompt about the default. |
13221355
| `--force` | Overwrite an existing schema with the same name. |
13231356
| `--json` | Print the result as JSON. |
13241357

1358+
Schema creation and the `--default` config update are one operation. If OpenSpec cannot validate or write the config, it leaves both the config and any existing schema unchanged.
1359+
13251360
**Output**
13261361

13271362
```

docs-lab/reference/supported-tools.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The id goes to `openspec init --tools <id>` to skip the picker ([CLI](cli.md)).
1515
| Tool | `--tools` id | Skills | Skill invocation | Commands | Command invocation |
1616
|---|---|---|---|---|---|
1717
| Amazon Q Developer | `amazon-q` | `.amazonq/skills/` | `/openspec-apply-change` | `.amazonq/prompts/` | `@opsx-apply` |
18-
| Antigravity | `antigravity` | `.agent/skills/` | `/openspec-apply-change` | `.agent/workflows/` | `/opsx-apply` |
18+
| Antigravity | `antigravity` | `.agents/skills/` | `/openspec-apply-change` | `.agents/workflows/` | `/opsx-apply` |
1919
| Auggie (Augment CLI) | `auggie` | `.augment/skills/` | `/openspec-apply-change` | `.augment/commands/` | `/opsx-apply` |
2020
| Bob Shell | `bob` | `.bob/skills/` | `/openspec-apply-change` | `.bob/commands/` | `/opsx-apply` |
2121
| Claude Code | `claude` | `.claude/skills/` | `/openspec-apply-change` | `.claude/commands/opsx/` | `/opsx:apply` |
@@ -62,6 +62,17 @@ The id goes to `openspec init --tools <id>` to skip the picker ([CLI](cli.md)).
6262

6363
A tool not listed here behaves exactly as its row reads.
6464

65+
### Antigravity
66+
67+
- **Current folder**: Antigravity v1.20.5 and later read workspace skills and
68+
workflows from `.agents/`.
69+
- **Legacy folder**: after OpenSpec writes replacements, it removes equivalent
70+
generated files from `.agent/`. Custom files and changed generated files stay in
71+
`.agent/` for you to review.
72+
- **Shared skills**: Antigravity shares `.agents/skills/` with Codex, Zed Agent, and
73+
the `agents` target. OpenSpec writes that skill tree once while still writing
74+
Antigravity commands to `.agents/workflows/`.
75+
6576
### Cline
6677

6778
Cline reads commands from `.clinerules/workflows/`, not from its `.cline/` folder.
@@ -73,9 +84,10 @@ Skills stay in `.cline/skills/`.
7384
`/openspec-<skill>` form ([upstream issue](https://github.com/openai/codex/issues/11817)).
7485
- **No command files**: Codex runs skills directly, so init skips commands even when
7586
delivery includes them and prints `Commands skipped for: codex (uses skills)`.
76-
- **Shared folder**: Codex skills land in `.agents/skills/`, the same tree the shared
77-
`agents` target uses. Selecting both keeps one tree, and its handoffs spell both
78-
`$openspec-*` and `/openspec-*`.
87+
- **Shared folder**: Codex skills land in `.agents/skills/`, the same tree Antigravity,
88+
Zed Agent, and the `agents` target use. Selecting more than one keeps a single
89+
compatible tree, and its handoffs spell both `$openspec-*` and `/openspec-*` when
90+
Codex owns it.
7991
- **Legacy path**: skills installed under `.codex/skills/` by older versions are
8092
migrated on the next `openspec update`.
8193

@@ -110,8 +122,10 @@ init prints this reminder after install.
110122

111123
- **When it fits**: any tool that reads the shared `.agents/skills/` folder,
112124
including tools with no row in the matrix.
113-
- **Alongside other targets**: fine, since each target writes its own folder. Codex
114-
shares this one; see the [Codex note](#codex).
125+
- **Alongside other targets**: Antigravity, Codex, Zed Agent, and this target share
126+
one physical skill tree. OpenSpec records one writer in `.openspec-target` and
127+
writes the tree once per run. Each tool's separate command files are still
128+
generated.
115129
- **What OpenSpec claims**: only the `openspec-*` folders and the
116130
`.openspec-target` marker. Anything else under `.agents/` is left alone.
117131
- **`AGENTS.md`**: not created or edited. The target is the `.agents/` folder, not

0 commit comments

Comments
 (0)