变更元数据(.openspec.yaml)
每个变更所存储元数据的受支持字段与校验规则。
位置
每个变更将其元数据保存在 openspec/changes/<change-name>/.openspec.yaml 中,位于其工件(artifacts)旁边。创建变更时,会写入该文件,并填充 schema 和 created 字段。
字段
| 键 | 类型 | 必填 | 作用 |
|---|---|---|---|
schema | string | 是 | 该变更遵循的工作流模式(schema) |
created | string,YYYY-MM-DD | 否 | 记录变更创建的日期 |
goal | string | 否 | 记录该变更的目标 |
affected_areas | 字符串列表 | 否 | 记录该变更预期影响的领域 |
initiative | 映射:store 和 id | 否 | 记录该变更所属的倡议(initiative) |
skip_specs | boolean | 否 | 声明该变更不产生任何 spec 增量,因此零增量可通过校验 |
retire_capabilities | boolean | 否 | 授权归档(archive)删除该变更清空的能力(capability) |
schema
该变更遵循的工作流模式。它在变更创建时设置,并优先于项目配置,因此即使之后 openspec/config.yaml 发生变化,变更仍保留其模式。运行 openspec schemas 可列出可用的模式名称。
initiative
该变更所属的倡议,由一个存储库 ID 和一个倡议 ID 组成,两者均采用 kebab-case:
initiative:
store: platform-specs
id: unify-billing除 store 和 id 之外的键将被拒绝。目前没有任何命令读取此链接。
skip_specs
声明该变更有意不产生任何 spec 增量:纯重构、工具或文档变更。设置此标志后,校验接受零增量,并且本应生成 spec 文件的工件被视为已完成。若在 specs/ 下已存在 spec 文件时设置此标志,则属于校验错误。
retire_capabilities
授权归档(archive)退役(retire)一个能力。当此变更的 REMOVED 增量移除了某个能力所拥有的最后一个需求时,归档将删除该能力的主 spec 文件,而不是停止。此标志的存在是因为该删除操作只能通过 git 恢复,因此仍由作者决定。
扩展键
以一个小写 x- 开头的顶层键属于你,用于存放其他工具或你的团队在变更旁边保留的数据,例如跟踪器 ID 或负责人:
schema: spec-driven
x-tracker: SB-5497
x-jiraKey: ABC-1
x-owner:
team: payments- 名称:小写
x-前缀后跟至少一个字符,且任何位置都不含空白字符。前缀之后的大小写或拼写任意,因此x-jiraKey和x-trackerID均符合条件。X-Tracker、单独的x-以及x- tracker不符合条件,并将被报告为未知键。 - 值:任意 YAML 值。OpenSpec 不读取或校验它,也不会改变任何行为。
- 作用域:仅限顶层。
initiative内部的x-键仍会被拒绝,就像该处的任何其他键一样。 - 校验:扩展键永远不会被报告为未知,因此
openspec validate --strict对携带它们的变更会通过。 - 归档:该文件随变更一起移动,保持不变,包括扩展键。
示例
一个填写完整的 .openspec.yaml:
schema: spec-driven
created: 2026-08-14
goal: Add magic-link login to the API
affected_areas:
- auth
- api校验
每当命令写入或读取该文件时,都会对其进行校验。写入失败会抛出异常且不写入任何内容。读取现有文件时,若 YAML 无效、字段违反其约定或模式名称不可用,则会失败。文件缺失不算错误,该变更被视为没有元数据。
与 config.yaml 不同,错误值绝不会被丢弃并附带警告。元数据错误会停止命令。
- 未知顶层键:OpenSpec 会忽略它们。
status、instructions、validate和archive会报告它们没有作用。JSON 输出会在其结构化结果中携带该警告。扩展键 不属于未知键,且永远不会被报告。 - 严格校验:
openspec validate --strict将未知键警告视为失败。仅包含扩展键作为额外键的变更会通过。