Skip to content

openspec new change prints Schema: spec-driven even when config.yaml selects a custom schema #2117

Closed

Description

@cabi

Version

1.14.3 (also present on main @ c794978f)

What happens

With schema: <custom-schema> set in openspec/config.yaml, openspec new change <id> prints

Schema: spec-driven

even though artifact resolution (instructions, status) correctly uses the custom schema.

Why (two root causes)

  1. src/commands/workflow/new-change.ts computes the resolved value but persists the raw flag instead:
146:  const resolvedSchema = options.schema ?? root.defaultSchema;   // spinner only
152:  schema: options.schema,                                        // undefined when no --schema
  1. Fixing line 152 alone is not enough: root.defaultSchema is hardcoded to 'spec-driven' and never reflects config.yaml:
// src/core/root-selection.ts:66 (type at :64, same literal at :127)
defaultSchema: 'spec-driven',

The schema configured in config.yaml is only reachable via readProjectConfig(projectRoot)?.schema, the route instructions.ts already takes.

Fix

Resolve from the project config and persist the resolved value:

const projectConfig = readProjectConfig(projectRoot);
const resolvedSchema = options.schema ?? projectConfig?.schema ?? root.defaultSchema;
...
schema: resolvedSchema,

Cosmetic only, but it misleads agents (and humans) auditing which schema a change was created under; I hit exactly that during a custom-schema run. A version-pinned patch with this fix (verified end to end: JSON payload, persisted .openspec.yaml, and text output) lives at https://github.com/cabi/openspec-cdd (patches/ + smoke test S26).

Activity

  1. surlymochan commented on Oct 19, 2026

    @surlymochan
    Contributor

    I tried this on 1.14.3 and it looks narrower than described: only the spinner line is wrong. The Schema: line, --json, and .openspec.yaml all already show the custom schema.

    Repro: openspec init --tools none, then openspec schema fork spec-driven my-flow, set schema: my-flow in openspec/config.yaml, and run openspec new change add-thing:

    - Creating change 'add-thing' with schema 'spec-driven'...
    Created change 'add-thing' at openspec/changes/add-thing/
    Schema: my-flow
    Next: openspec status --change add-thing
    

    .openspec.yaml has schema: my-flow, and --json gives "schema": "my-flow".

    That matches the code on main. createChange (src/utils/change-utils.ts around line 146) already resolves explicit option, then readProjectConfig(projectRoot)?.schema, then defaultSchema. It persists that value and returns it as result.schema, and printCreatedChangeHuman prints that. Passing schema: options.schema on line 152 is what lets the config fallback work. Only resolvedSchema on line 146, used just for the spinner text, skips the config.

    So I think the minimal fix is to give the spinner the same resolution (or drop the schema from the spinner message). Changing what gets persisted, or root.defaultSchema, shouldn't be needed. One thing I didn't test is a --store-selected root, in case that's the path where you saw the wrong value persisted.

  2. added a commit that references this issue on Oct 22, 2026
    832e2cf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions