关于 openspec-update-change
用于审查和修订现有 OpenSpec 变更规划文档的技能,不修改实现代码。它会核对文档间的一致性,并在用户确认后写入修改,同时遵守存储区和文件范围规则。
主要功能
- 01选择待处理的变更
- 02检查规划文档一致性
- 03写入前提出修改供确认
- 04仅修改规划文件
- 05支持已注册的 OpenSpec 存储区
适用场景
- 01需求变化后修订变更计划
- 02解决规划文档间的矛盾
- 03更新计划而不触碰源代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fission-ai/ openspec --skill openspec-update-change安装后在 Claude Code 中输入/openspec-update-change确认已加载。
详细介绍
修订变更现有的规划文档,并确保内容一致。切勿编辑代码。
存储选择: 如果用户指定了存储(存储是指在此机器上注册的独立 OpenSpec 仓库),或相关工作位于某个存储中,请运行 openspec store list --json 来查找已注册的存储 ID,然后在读取或写入规范和变更的命令(new change、status、instructions、list、show、validate、archive、doctor、context、schemas、view)中传入 --store <id>。选定后,在工作流的其余部分始终使用 --store <id>。下文中所有未指定存储的命令示例均为简写:运行前请追加该标志。例如,应运行 openspec status --change "<name>" --json --store "<id>",而不是下文所示的未指定存储的形式。其他命令不接受此标志。命令输出的提示已包含该标志;后续命令也要保留它。未指定存储时,命令会作用于最近的本地 openspec/ 根目录。
项目检查: 以下步骤要求项目已使用 OpenSpec。在首次执行会写入内容的步骤(new change、archive、sync specs 或编写工件文件)之前,请确认项目有根目录:运行 openspec list --json(如果已选择存储,则传入 --store <id>,因为此时该存储就是根目录),并读取 root。root 为对象表示项目已完成设置。"root": null 表示尚未设置——此处没有 openspec/ 目录,像 openspec new change 这样的写入操作会产生副作用并创建该目录。该命令还会以非零状态码退出,这就是预期结果,并非 CLI 故障;请读取 JSON,不要重试或绕过。
如果 status 的错误消息以 Declared in 或 Invalid store declaration in 开头,并指出此项目的 openspec/config.yaml(或 config.yml),那么 "root": null 并不表示尚未设置:该项目通过其声明的存储使用 OpenSpec,但此机器无法解析该存储(存储尚未注册,或 store: 行格式错误)。不要将其视为未初始化,也不要继续执行下方分支:停止写入,并向用户显示该错误的 message 和 fix。
否则,如果没有根目录,接下来如何处理取决于进入此工作流的方式:
- 自动选择:你自行选择了此工作流,用户既未提及 OpenSpec,也未提及此技能或运行其斜杠命令。停止使用 OpenSpec,并像未安装 OpenSpec 一样正常响应请求。不要要求用户进行任何设置,也不要提及 OpenSpec 设置。
- 明确请求 OpenSpec:用户提及了 OpenSpec、此技能,或运行了其斜杠命令。停止写入,并询问用户接下来如何处理:设置此项目(
openspec init)、指定已有存储(--store <id>),或本次请求不使用 OpenSpec 继续。等待用户答复。
无论哪种情况,都不得通过副作用创建根目录:用户未要求前,不要运行 openspec init;不要手动创建 openspec/ 文件;不要让命令创建它。
输入: 可选指定变更名称。如果未指定,请检查能否根据对话上下文推断。如果含糊或不明确,则必须提示用户从可用变更中选择。
此工作流用于修订已存在的工件;/openspec-continue-change 用于创建尚不存在的工件。
步骤
-
选择变更
如果提供了名称,请使用该名称。否则:
- 如果用户在对话中提到了某项变更,则根据上下文推断
- 如果只有一项进行中的变更,则自动选择
- 如果有多项可能的变更,则运行
openspec list --json,按最近修改时间排序获取可用变更,并请用户选择一项
提示用户时,将最近修改的 3–4 项变更作为选项,并显示:
- 变更名称
- 状态(例如“0/5 项任务”“已完成”“无任务”)
- 修改时间距今多久(根据
lastModified字段)
将最近修改的变更标记为“(推荐)”,因为它很可能就是用户想要更新的变更。 始终声明:“使用变更:”,并说明如何覆盖(例如,
/openspec-update-change <other>)。 -
获取变更的工件
openspec status --change "<name>" --json解析 JSON 以了解当前状态。响应包含:
schemaName:正在使用的工作流架构(例如,“spec-driven”)artifacts:包含工件及其状态(“done”“skipped”“ready”“blocked”)的数组isPlanningComplete:用于指示所有规划工件是否已完成的布尔值。旧版 CLI 将相同值显示为isComplete。planningHome、changeRoot、artifactPaths和actionContext:路径和范围上下文。请使用这些值,不要假定仓库内的路径。
工件 ID 和路径来自当前使用的架构——不要假定它们,也不要针对硬编码的工件名称编写分支逻辑。自定义架构必须能够直接使用。
要编辑的文件是
artifactPaths.<id>.existingOutputPaths——这些是磁盘上实际存在的文件,通配符工件的路径已展开为具体文件(例如,specs/**/*.md),还包括步骤 4 中允许在部分填充的通配符工件下添加的任何已确认具体路径。不要写入resolvedOutputPath:对于通配符工件,它仍然是通配符模式,而不是实际文件。 -
了解请求
- 如果用户提出了具体的修订要求(“设计现在使用 X”),则以此为编辑起点。
- 如果用户只说“更新”或“让内容保持一致”,则将其视为一致性审查:阅读现有工件,并检查它们之间是否存在矛盾、缺漏或重复。
-
阅读并协调
- 阅读请求涉及的制品以及变更中其他已存在的制品。
- 在对话中起草所请求的编辑,不要在文件中编辑。明确其具体变更内容;第 5 步负责所有写入。然后对照起草的编辑检查其他每个已存在的制品,方向不限:对后续制品的编辑可能需要修订较早的制品,不只是反过来。构建顺序是有用的阅读顺序,但不限制可修订的制品。
- 记录所有现在不一致、缺失或相互矛盾的内容。
- 提议修订已存在的文件(
existingOutputPaths)。如果某个制品没有任何现有输出文件,且状态为ready或blocked,请注明并指引用户前往/openspec-continue-change创建这些文件。保持skipped制品不变;不要将其视为缺失,也不要将其交给 continue 工作流处理。 - glob 制品(例如
specs/**/*.md)在至少匹配一个文件后会标记为done,而 continue 工作流只处理ready制品。当协调过程中发现existingOutputPaths非空的 glob 制品缺少文件时:- 运行
openspec instructions "<artifact-id>" --change "<name>" --json,并使用其中的instruction和template。将context和rules视为约束;不要将其复制到文件中。如果指令报告skipped: true,则不要创建文件。从磁盘读取当前依赖文件;如果缺少必需的、未跳过的依赖文件,请停止并要求用户先恢复它。 - 在
changeRoot内选择一个符合artifactPaths.<id>.outputPath且尚不存在的具体路径。解析任何符号链接的父目录后,确认该路径仍位于changeRoot内。glob 的resolvedOutputPath不是有效目标。 - 将新文件纳入第 5 步的拟议修订中,并仅在用户确认后创建。
- 确认后,在创建前立即刷新状态和指令。确认该制品仍在范围内、未被跳过且已有部分内容;重复上述具体路径检查。
- 使用目标已存在时会失败的创建操作。如果
instruction将创建工作委托给其他技能或命令,仅当其能够遵守已确认的路径和这些防护要求时才调用;否则停止。如果任何检查失败,或已确认的草稿不再有效,请停止并与用户协调,而不是替换现有内容或另选路径。
- 运行
- 如果变更已经协调一致,请说明这一点,不要提议任何修订。
-
确认并逐个应用制品
- 此步骤负责此工作流中的所有制品写入;此前的步骤都不得编辑制品。
- 展示每项拟议修订及其原因,包括第 4 步中起草的所请求编辑。只有在用户确认后才写入。
- 如果用户拒绝某项修订,不要写入——保持该制品不变。
- 当需要大幅重写时,先获取该制品的规则和模板:
openspec instructions "<artifact-id>" --change "<name>" --json
-
指出下一步(仅提供指引——绝不要执行)
existingOutputPaths为空且状态为ready或blocked的制品 -> 建议使用/openspec-continue-change创建它们。- 变更已实施(任务已勾选/已应用)-> 代码可能已不再符合修订后的计划;建议使用
/openspec-apply-change将差异应用到代码中。 - 所有内容均已完成并实施 -> 建议使用
/openspec-archive-change。
输出 每次调用后,都显示:
- 修改了哪些制品(以及哪些拟议修改遭到拒绝)
- 在已有部分内容的 glob 制品下创建的任何文件
- 任何推迟到
/openspec-continue-change处理的事项(尚无文件且状态为ready或blocked的制品,绝不包括状态为skipped的制品) - 当前变更的进展情况以及建议执行的下一条命令
注意事项
- 仅处理规划制品,绝不编辑实现代码。如果修订后的计划意味着需要修改代码,请停止并指向
/openspec-apply-change。 - 使用
openspec status报告的制品 ID 和路径;切勿根据硬编码的制品名称进行分支判断。 - 仅编辑
existingOutputPaths中的具体文件,以及在步骤 4 中确认允许在部分填充的 glob 制品下创建的任何具体路径;绝不写入 globresolvedOutputPath。 - 不要推进构建进度:如果某个制品的
existingOutputPaths为空且状态为ready或blocked,则应由/openspec-continue-change处理。保持skipped制品不变。唯一允许的新文件范围,是在existingOutputPaths非空的 glob 制品下确认的具体路径。 - 写入前,须向用户确认每项修改。
- 如果请求改变的是变更的意图,而非对其进行完善,请建议重新开始,并使用
/openspec-new-change(“更新还是重新开始”判断准则)。