Skip to content

Commit 2fa679f

Browse files
ryandemeloclay-goodclaude
authored
fix(schema): make schema init --default actually set the default (#1709)
* fix(schema): make schema init --default actually set the default --default wrote defaultSchema to openspec/config.yaml, but the config loader only reads schema, so new changes kept using spec-driven while the command reported success. Write the key that is read, and drop the dead one a previous run may have left behind. Fixes #1708 * fix(schema): preserve supported configs when setting default * docs(schema): specify default config file handling * docs(schema): protect default config migration * fix(schema): make default initialization atomic * fix(schema): hide init staging and backup dirs from discovery `schema init` stages into `.init-staging-<rand>` and moves an existing schema aside to `<name>.init-backup-<pid>-<ts>`, both inside the schemas dir. `schema fork` already did this and the resolver filters its temp names out of discovery; the init names were never added, so `listSchemas` and `listSchemasWithInfo` surfaced them as real schemas -- in shell completions, "available schemas" error lists, and change-metadata validation. The backup is the durable case: cleanup failure is deliberately tolerated with a warning, so a blocked cleanup (or a crash mid-transaction) leaves a permanent phantom schema behind. Generalize the fork-only filter to cover both commands' staging and backup names. Real schema names are kebab-case, so excluding these dot-bearing names can never hide a legitimate schema. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Clay Good <hi@claygood.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent e5e350d commit 2fa679f

7 files changed

Lines changed: 678 additions & 58 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@fission-ai/openspec": patch
3+
---
4+
5+
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.

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: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1350,11 +1350,13 @@ With no `--description` and no `--artifacts` in an interactive terminal, init pr
13501350
|---|---|
13511351
| `--description <text>` | Schema description. Default: `Custom workflow schema for <name>`. |
13521352
| `--artifacts <list>` | Comma-separated artifact IDs from `proposal`, `specs`, `design`, `tasks`. Default: all four. |
1353-
| `--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. |
13541354
| `--no-default` | Skip the prompt about the default. |
13551355
| `--force` | Overwrite an existing schema with the same name. |
13561356
| `--json` | Print the result as JSON. |
13571357

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+
13581360
**Output**
13591361

13601362
```

openspec/specs/schema-init-command/spec.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,34 @@ The CLI SHALL offer to set the newly created schema as the project default.
5050
#### Scenario: Set as default interactively
5151
- **WHEN** user runs `openspec schema init my-workflow` in interactive mode
5252
- **AND** user confirms setting as default
53-
- **THEN** system updates `openspec/config.yaml` with `defaultSchema: my-workflow`
53+
- **THEN** system updates an existing `openspec/config.yaml` or `openspec/config.yml` in place with `schema: my-workflow`
54+
- **AND** removes the legacy `defaultSchema` key when updating an existing configuration
55+
- **AND** creates `openspec/config.yaml` when neither configuration file exists
5456

5557
#### Scenario: Set as default via flag
5658
- **WHEN** user runs `openspec schema init my-workflow --default`
57-
- **THEN** system creates schema and updates `openspec/config.yaml` with `defaultSchema: my-workflow`
59+
- **THEN** system creates the schema and updates an existing `openspec/config.yaml` or `openspec/config.yml` in place with `schema: my-workflow`
60+
- **AND** removes the legacy `defaultSchema` key when updating an existing configuration
61+
- **AND** creates `openspec/config.yaml` when neither configuration file exists
5862

5963
#### Scenario: Skip setting default
6064
- **WHEN** user runs `openspec schema init my-workflow --no-default`
6165
- **THEN** system creates schema without modifying `openspec/config.yaml`
6266

67+
#### Scenario: Invalid config prevents schema creation
68+
- **GIVEN** `openspec/config.yaml` or `openspec/config.yml` is invalid YAML, is not a YAML object, is not a regular file, or is not writable
69+
- **WHEN** user runs `openspec schema init my-workflow --default`
70+
- **THEN** the command exits with a non-zero status
71+
- **AND** does not create `openspec/schemas/my-workflow/`
72+
- **AND** leaves the config byte-for-byte unchanged
73+
74+
#### Scenario: Config failure preserves a schema during forced replacement
75+
- **GIVEN** `openspec/schemas/my-workflow/` already contains user-authored files
76+
- **AND** the project config cannot be validated or atomically replaced
77+
- **WHEN** user runs `openspec schema init my-workflow --force --default`
78+
- **THEN** the command exits with a non-zero status
79+
- **AND** restores the existing schema and config byte-for-byte
80+
6381
### Requirement: Schema init outputs JSON format
6482
The CLI SHALL support `--json` flag for machine-readable output.
6583

@@ -92,4 +110,3 @@ The CLI SHALL validate all requested artifact IDs before replacing an existing p
92110
- **WHEN** the user runs `schema init` with `--force` and only valid artifact IDs
93111
- **THEN** the command replaces the existing schema with the newly generated schema
94112
- **AND** reports successful creation
95-

0 commit comments

Comments
 (0)