schema.yaml
schema 定义的每个字段,无论用于读取还是编写 schema。
schema.yaml 列出工作流创建的规划文件。它还定义这些文件的顺序,以及向实现交接的方式。
位置
项目 schema 位于 openspec/schemas/<name>/ 下:
openspec/schemas/review-first/
├── schema.yaml
└── templates/
├── proposal.md
└── tasks.mdOpenSpec 会在三个位置查找该目录。首个匹配项生效。
| 副本 | 目录 |
|---|---|
| 1. 项目 | <project>/openspec/schemas/<name>/ |
| 2. 用户,macOS 和 Linux | ~/.local/share/openspec/schemas/<name>/ |
| 2. 用户,Windows | %LOCALAPPDATA%\openspec\schemas\<name>\ |
| 3. 包 | 随 CLI 安装的 schema |
如果设置了 XDG_DATA_HOME,则在所有平台上,用户目录都会移动到 $XDG_DATA_HOME/openspec/schemas/<name>/。
目录名是 --schema、config.yaml 和 .openspec.yaml 使用的查找键。如果 name 字段与目录名不同,OpenSpec 仍使用目录名进行查找。
openspec schema which <name> 会打印当前生效的目录,以及它所遮蔽的所有较低优先级副本。
顶层字段
| 字段 | 约定 |
|---|---|
name | 必填。 作为 schema 名称存储的非空字符串。查找仍使用目录名。 |
version | 必填。 作为 schema 修订版本存储的正整数。该值不会改变 OpenSpec 的行为。 |
description | 由 openspec schemas 打印的可选字符串。若无值,则 schema 没有描述。 |
artifacts | 必填。 非空的工件条目列表。 |
apply | 可选的 apply 设置。如果没有该块,OpenSpec 使用 apply 默认值。 |
工件字段
artifacts 下的每个条目定义一个规划文件或一组文件。
| 字段 | 约定 |
|---|---|
id | 必填。 用于依赖项、项目规则、命令和 apply 设置中的唯一非空字符串。 |
generates | 必填。 相对路径或 glob,告知智能体在变更文件夹内将工件写入何处。 |
description | 必填。 在发送给智能体的指令中标识该工件的字符串。 |
template | 必填。 指向 schema 的 templates/ 文件夹中工件格式的相对路径。 |
instruction | 可选指导,告知智能体应生成哪些内容。 |
requires | 必须先完成的工件 ID 列表。默认值:[]。 |
generates
该路径从变更文件夹开始。对于名为 add-auth 的变更:
generates: proposal.md工件写入此处:
openspec/changes/add-auth/proposal.mdglob 可匹配多个文件:
generates: specs/**/*.md这会匹配 openspec/changes/add-auth/specs/ 下的 Markdown 文件。
OpenSpec 在 generates 中识别以下 glob 形式:
- 通配符和字符类:包含
*、?或[的值,例如specs/**/*.md和review-[ab].md。 - 花括号展开:例如
review-{api,ui}.md这样的备选项,以及file-{1..3}.md这样的范围。 - 扩展 glob(extglob):诸如
@(proposal|design).md、+(proposal|design).md和!(proposal|design).md的模式。
字面文件名:仅开头的 ! 不会使其成为 glob。若要指定该文件,请使用 generates: '!review.md'。诸如 (proposal|design).md 的普通圆括号以及诸如 review-{api}.md 的单元素花括号也会保持字面形式。
OpenSpec 会拒绝绝对路径、包含 .. 路径段的路径,以及花括号或圆括号嵌套超过 16 层的 glob,例如 {a,{b,{c,...}}}。实际模式只需一到两层。它还会拒绝花括号展开为超过 1,024 个模式的 glob,例如重复十一次的 {a,b},或 file-{1..5000}.md 这样的范围。错误消息为 Artifact output pattern expands to more than 1024 patterns。实际模式通常只会展开为少数几个。
完成判定
OpenSpec 会检查输出是否存在。它不会通过读取文件来判断工件是否完成。
generates 值 | 完成条件 |
|---|---|
proposal.md | 该文件存在。 |
specs/**/*.md | 该 glob 至少匹配一个文件。 |
template
该路径从 schema 的 templates/ 文件夹开始。在 review-first schema 中:
template: proposal.mdOpenSpec 读取此文件:
openspec/schemas/review-first/templates/proposal.mdOpenSpec 会将模板内容作为输出格式提供给智能体。它不会将模板复制到变更文件夹中。
OpenSpec 会拒绝绝对路径以及包含 .. 路径段的路径。
requires
- 依赖项:
requires中的每个 ID 都必须指向同一 schema 中的另一个工件。 - 就绪状态:当某个工件的所有依赖项都完成后,该工件才会变为就绪。
- 无效依赖图:缺失的 ID、重复的 ID 和依赖循环会导致验证失败。
- 并列情况:当多个工件都已就绪时,它们在
artifacts中的顺序决定 OpenSpec 先返回哪一个。
Apply 字段
apply 定义实现开始前必须存在的内容。
| 字段 | 约定 |
|---|---|
requires | 必填。 在 apply 指令变为就绪前必须存在的工件的非空列表。 |
tracks | 可选的相对路径或 glob,用于变更文件夹中的 Markdown 任务文件。默认值:null。 |
instruction | 可选指导,在 apply 就绪时发送给智能体。默认情况下,OpenSpec 使用内置指导。 |
工件的 requires 控制规划顺序。apply.requires 控制 apply 指令何时变为就绪。
tracks
该路径从变更文件夹开始。对于名为 add-auth 的变更,tracks: tasks.md 会读取:
openspec/changes/add-auth/tasks.md诸如 tracks: "**/tasks.md" 的 glob 会读取每个匹配文件,例如 backend/tasks.md 和 frontend/tasks.md。OpenSpec 会合并它们的任务和进度。请为工件的 generates 字段使用相同的值,以便状态和列表跟踪相同的文件。generates 中的花括号限制(深度 16 层、最多展开为 1,024 个模式)同样适用于此处。
如果没有文件匹配,或匹配的文件中没有任何带任务文本的复选框,apply 会保持阻塞状态。OpenSpec 会计入以下复选框形式:
- [ ] Pending task
- [x] Completed task
* [X] Completed task
+ [ ] Pending task
1. [ ] Pending task
2) [x] Completed task任何 Markdown 列表标记均可使用:-、*、+,或最多九位数字后跟 . 或 )。允许前导空格。spec-driven 页面中的 tasks.md 部分 定义了默认 schema 生成的更严格格式。
被跟踪的文件决定 apply 状态:
blocked:没有文件匹配,或没有任何可读文件包含带任务文本的复选框。ready:至少有一个任务待处理,或某个匹配文件无法读取,而另一个文件提供了任务。all_done:每个被跟踪的任务都已勾选,并且每个匹配文件都已读取。
如果某个匹配文件无法读取,apply 会保留可读文件中的任务和进度,但不会将该变更标记为 all_done。Apply JSON 输出 会标明每个不可用文件及其原因。
OpenSpec 会拒绝绝对路径以及包含 .. 路径段的路径。
Apply 默认值
| 行为 | 默认值 |
|---|---|
| 必需工件 | schema 中的每个工件 |
| 进度跟踪 | 无跟踪文件 |
| 智能体指导 | 内置 apply 指导 |
完整示例
name: review-first
version: 1
description: Proposal and implementation checklist
artifacts:
- id: proposal
generates: proposal.md
description: Why the change is needed and what it affects
template: proposal.md
instruction: |
Explain the problem, the proposed change, and its impact.
requires: []
- id: tasks
generates: tasks.md
description: Trackable implementation checklist
template: tasks.md
instruction: |
Break the approved proposal into ordered implementation tasks.
requires:
- proposal
apply:
requires:
- tasks
tracks: tasks.md
instruction: |
Work through the pending tasks and mark each one complete.验证
openspec schema validate <name> 会检查:
- 字段类型和必填字段
- 相对路径
- 工件 ID、依赖项和循环
apply.requiresID:每个都必须是 schema 中的工件- 模板文件
如果 schema 包含未知的 apply.requires ID,则不会加载,因此使用它的每个命令都会报告该错误。
当 apply.tracks 与某个工件的 generates 值不完全相等时,验证会发出警告,但不会失败。OpenSpec 通过比较这两个字符串来查找被跟踪的工件,因此任何不一致都会使其无法判断该文件属于哪个工件的进度。这包括像 task.md 这样的拼写错误,也包括 tracks: tasks/main.md 与 generates: tasks/*.md 这样的组合:glob 确实会生成该文件,但字符串仍然不同。无论哪种情况,apply 都会继续读取该文件,但 openspec list 和 openspec status 会改为统计 tasks.md。
验证不会捕获以下错误:
| 错误 | 会发生什么 |
|---|---|
字段拼写错误,例如 instrution | OpenSpec 会忽略它。验证不会报告该拼写错误。 |
name 与 schema 目录不同 | 验证通过。OpenSpec 仍使用目录名进行查找。 |