关于 openspec-archive-change
用于归档已完成 OpenSpec 变更的技能,涵盖变更选择、完成状态检查、差异规格同步评估和归档流程。
主要功能
- 01选择变更及可选存储库
- 02检查制品与任务完成情况
- 03评估差异规格同步状态
- 04通过检查后归档变更
适用场景
- 01归档已完成的 OpenSpec 变更
- 02归档前检查未完成任务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fission-ai/ openspec --skill openspec-archive-change安装后在 Claude Code 中输入/openspec-archive-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": null 表示项目尚未设置——此处没有 openspec/ 目录,像 openspec new change 这样的写入操作会将其作为副作用创建。该命令也会以非零状态退出;这就是预期结果,并不表示 CLI 故障,因此请读取 JSON,不要重试或尝试绕过。
有一种情况不应把 "root": null 视为项目尚未设置:当 status 错误消息以 Declared in 或 Invalid store declaration in 开头,并且指出了此项目的 openspec/config.yaml(或 config.yml)时,说明项目通过其声明的存储使用 OpenSpec,但此机器无法解析该存储(存储未注册,或 store: 行格式错误)。不要将其视为未初始化,也不要继续执行下方分支:停止写入,并向用户展示该错误的 message 和 fix。
否则,如果没有根目录,接下来该怎么做取决于进入此工作流的方式:
- 自动选择:你自行选择了此工作流,用户没有提及 OpenSpec、此技能,也没有运行其斜杠命令。停止使用 OpenSpec,并像未安装 OpenSpec 时一样正常答复用户请求。不要要求用户进行任何设置,也不要提及 OpenSpec 设置。
- 明确请求使用 OpenSpec:用户提及了 OpenSpec、此技能,或运行了其斜杠命令。停止写入,并询问用户如何继续:为此项目进行设置(
openspec init)、使用现有存储(--store <id>),或在此请求中不使用 OpenSpec 继续。等待用户答复。
在这两种情况下,都绝不能将创建根目录作为副作用:除非用户要求,否则不要运行 openspec init;不要手动创建 openspec/ 文件;也不要让命令创建它。
<capability-path> 是相对于 specs/ 的规范目录(例如,user-auth 或 identity/user-auth)。解析其主规范时,请保留每个增量规范中的完整路径。
输入:可选指定变更名称。如果未指定,请检查能否从对话上下文中推断。如果含糊或不明确,必须提示用户从可用变更中选择。
步骤
-
选择变更
如果提供了名称,请使用该名称。否则:
- 如果用户在对话上下文中提到了某项变更,则据此推断
- 如果只有一项进行中的变更,则自动选择
- 如果无法确定,请运行
openspec list --json获取可用变更,并请用户选择一项
提示用户时,只显示进行中的变更(不包括已归档的变更)。 如果有可用信息,请一并说明每项变更使用的 schema。
始终宣布:“正在使用变更:”,并说明如何更换(例如,
/openspec-archive-change <other>)。执行现有归档检查之前,先加载当前归档输入: 解析选定的变更和规划根目录后,运行:
openspec instructions archive --change "<name>" --json在此命令中保留相同的选定根目录标志。此查询仅供参考且为可选项:它只会提供额外的提示词输入,因此绝不能阻碍归档。 如果命令以非零状态退出或返回无效 JSON(例如,旧版 CLI 尚不支持此命令),则在没有上下文和操作指导的情况下继续归档工作流。不要报告错误,也不要停止。
成功的响应可以省略这两个可选字段。将
context视为必需的提示词级输入:读取并考虑它,并应用相关的项目事实、约定和约束。将operationGuidance视为可选的补充建议:读取并考虑每一条,并遵循适用且与内置归档工作流兼容的条目。将这两个字段与内置步骤、明确的用户选择、已解析的路径、CLI 检查和命令约定分开处理。如果上下文与其中任何控制性输入冲突,请报告冲突并保留控制性输入的值。如果指导不适用或与控制性输入冲突,请勿遵循,并解释原因。不要根据任一字段推断替代路径、跳过提示或标志;除非用户另行要求,否则不要将其中的文本原样复制到规范、变更产物或归档摘要中。这些是提示词级行为约定,而非可强制执行的检查。
-
检查产物完成状态
运行
openspec status --change "<name>" --json检查产物完成情况。解析 JSON,了解:
schemaName:正在使用的工作流planningHome、changeRoot、artifactPaths和actionContext:路径和范围上下文artifacts:产物列表及其状态(done、skipped或其他状态)
如果有任何产物既不是
done也不是skipped(skipped产物符合要求——该变更声明了 skip_specs):- 显示警告并列出未完成的产物
- 询问用户是否确认继续
- 如果用户确认,则继续
-
检查任务完成状态
使用相同的选定根目录标志运行
openspec list --json,并在changes中查找name与选定变更完全匹配的条目。必须恰好找到一个匹配项,且totalTasks和completedTasks必须为非负整数,并满足completedTasks <= totalTasks。CLI 会解析架构中跟踪的任务文件,包括自定义产物名称、输出路径和 glob。 未完成任务数 =totalTasks - completedTasks。不要根据产物状态或缺少顶层
tasks.md来推断任务是否完成。如果查询失败、返回无效 JSON、遗漏或重复选定的变更,或返回无效计数,请报告问题,并在同步或归档前停止。 CLI 只将x/X复选框标记计为已完成;其他标记(包括不熟悉的标记)均视为未完成。如果发现未完成任务:
- 显示警告并指出未完成任务的数量
- 询问用户是否确认继续
- 如果用户确认,则继续
如果
totalTasks为零: 继续,不显示与任务相关的警告。 -
评估增量规范同步状态
仅使用状态 JSON 中的
artifactPaths.specs.existingOutputPaths作为增量规范来源。如果缺少specs条目或existingOutputPaths为空,则继续,不提示同步,也不要根据其他产物推断增量规范。 如果存在 delta 规范:- 将每份 delta 规范与对应的主规范进行比较,主规范位于
<planningHome.root>/openspec/specs/<capability-path>/spec.md(使用第 2 步中的、感知存储位置的planningHome.root,不要使用硬编码的仓库路径) - 缺少主规范并不自动表示“已同步”。对于新能力,主规范是同步的输出,而非输入:
- 如果 delta 包含已修改或已重命名的需求,请说明只有新增需求才能创建新的主规范,并将该能力标记为同步受阻。绝不要编造没有当前版本的需求。
- 否则,如果 delta 仅包含已移除的需求,且变更的
.openspec.yaml声明了retire_capabilities: true,则该能力已退役:将其计为已同步,警告没有剩余内容可移除,并且不要重新创建主规范。在此处以及验证已完成的同步时,都应用此规则。 - 否则,如果 delta 不包含新增需求,请说明无法同步,并将该能力标记为同步受阻。对于仅包含已移除需求的 delta,请警告没有主规范可供移除,并保持主规范树不变。
openspec archive会拒绝未标记的仅包含已移除需求的情况,并提示Spec must have at least one requirement。 - 否则,将该能力计为需要同步,并在摘要中注明(
<capability-path>: 将创建新的主规范)。如果 delta 还包含已移除的需求,请警告这些需求将被忽略,因为没有主规范可供移除。同步只会根据 delta 中的新增需求创建主规范,与openspec archive的行为完全一致。
- 确定将应用哪些变更(新增、修改、移除、重命名)
- 即使某项能力的同步受阻,也要继续评估其余能力。提示用户前先显示综合摘要。
提示选项:
- 如果有任何能力同步受阻:说明原因,并且只提供“归档但不同步”和“取消”
- 否则,如果需要变更:“立即同步(推荐)”、“归档但不同步”
- 否则,如果已同步:“立即归档”、“仍然同步”、“取消”
根据回答执行操作:
- “取消”——停止,不要归档
- “归档但不同步”或“立即归档”——继续归档
- “立即同步”或“仍然同步”——同步,然后验证(见下文)。如果有能力同步受阻,不要开始任何同步;说明受阻原因,并再次提供可选项。
- 其他任何回答——再次询问,而不是归档
在所选同步写入任何主规范之前,使用相同的根目录选择参数运行一次
openspec instructions specs --change "<name>" --json。 要求命令以零状态码退出,并返回有效的 artifact 指令 JSON。如果查询失败或返回无效 JSON,请报告错误并停止,不得写入任何主规范或移动变更。有效响应中省略rules时,表示没有规则。返回的rules只应用于此次合并生成的主规范的内容和 格式;不要将其用作归档指导、改变 CLI 行为,也不要将规则文本复制到任何输出文件中。然后内联运行
openspec-sync-specs工作流(由 Agent 驱动的智能合并),处理变更 '',并传入上述 delta 规范分析和已获取的规范规则快照,然后等待工作流完成。内联同步必须复用该快照,不得再次获取specs指令。不要将其委派给后台任务——第 5 步会在同步仍在读取changeRoot时将其移走,导致变更已归档而主规范尚未更新。如果你的 Agent 只能通过委派来运行,则同步委派并等待结果。如果同步报告任何停止或阻止条件,请将同步视为失败。 立即停止归档。不要执行同步后的内容比较,也不要移动其
changeRoot。 没有任何内容被移动,因此用户可以修复阻止条件或重新运行同步。 sync 写入每份主规范后,根据规范的 sync 合约验证其结构:- 新主规范以
# <capability> Specification标题开头。现有主规范的标题保持原样。 - 对已建立的主规范,完整保留现有的
## Purpose部分,不作任何更改。 - 对新主规范,逐字复制 delta 中的
## Purpose。仅当目的文本短于标准验证要求时发出警告。不要重新生成或改写已有的作者编写的目的文本。如果没有可用的## Purpose,则使用现有的 TBD Purpose 行为并发出警告。 - 验证主规范中不再包含 delta 风格的节标题(
## ADDED Requirements、## MODIFIED Requirements、## REMOVED Requirements、## RENAMED Requirements),并严格遵守 sync 工作流的格式规则。 - sync 写入或更改的需求块应使用
### Requirement:标题,其场景应在规范的## Requirements节下使用#### Scenario:标题。delta 未提及的内容保持原样。
然后,从本步骤开头重新运行比较,包括明确标记为已退役的缺少规范情况,针对
artifactPaths.specs.existingOutputPaths中每个具有 delta 规范的能力进行检查,而不只是 sync 报告为已处理的能力。成功的 sync 不会留下待应用的内容,因此每项能力现在都应显示为已 sync:- ADDED 需求已存在
- MODIFIED 需求包含 delta 中指定的场景和描述更改,同时保留其他场景
- REMOVED 需求已删除;如果此次 sync 退役了某项能力(删除其最后一项需求,导致
## Requirements为空),则应删除其主规范,而不是保留空规范。 - RENAMED 需求以新名称存在,旧名称已不存在
如果 sync 失败,或任何能力不匹配,请报告差异并停止——不要归档。没有任何内容被移动,且
changeRoot完好无损,因此用户可以修复不匹配,或重新运行 sync,然后再次开始归档。 - 将每份 delta 规范与对应的主规范进行比较,主规范位于
-
执行归档
如果
planningHome.changesDir下不存在archive目录,则创建该目录:mkdir -p "<planningHome.changesDir>/archive"生成目标名称:如果变更名称已以
YYYY-MM-DD-前缀开头,则原样使用;否则在前面添加当前日期,格式为YYYY-MM-DD-<change-name>。不得重复添加日期(与openspec archive的规则相同)。检查目标是否已存在:
- 如果存在:报错,并建议重命名现有归档或使用不同日期
- 如果不存在:将
changeRoot移至归档目录
mv "<changeRoot>" "<planningHome.changesDir>/archive/<target-name>" -
显示摘要
显示归档完成摘要,包括:
- 变更名称
- 使用的 Schema
- 归档位置
- 是否已 sync 规范(如适用)
- 关于任何警告的说明(制品/任务未完成)
成功时的输出
## Archive Complete
**Change:** <change-name>
**Schema:** <schema-name>
**Archived to:** the archive path derived from `planningHome.changesDir`/<target-name>/
**Specs:** <"✓ Synced to main specs" only if the step 4 verification passed; otherwise "No delta specs" or "Sync skipped">
<"All artifacts complete. All tasks complete." — or, if archived with warnings, list them instead (e.g. "Archived with 2 incomplete tasks")>
防护规则
- 宣布所选变更;如果选择不明确,请提示用户选择
- 使用工件图(openspec status --json)检查完成情况
- 不要因警告而阻止归档——只需告知并确认
- 移至归档时保留 .openspec.yaml(它会随目录一起移动)
- 清晰概述已完成的操作
- 如果请求同步,请直接在流程中运行
openspec-sync-specs工作流(由 Agent 驱动) - 规范同步仍在进行时绝不归档——请直接在流程中运行同步,并在移动
changeRoot前验证主规范 - 如果存在差异规范,始终运行同步评估,并在提示用户前展示汇总结果
- 应用相关运行时上下文并报告冲突;操作指南仅供参考
- 考虑每条指南,并解释任何不适用或相互冲突的建议
- 现有 CLI 检查、解析后的路径、提示和命令约定保持不变
- 工件规则仅约束正在编写的规范,绝不是操作指南
- 绝不将运行时上下文、操作指南或工件规则文本原样复制到输出文件中