关于 openspec-ff-change
此技能会快速完成 OpenSpec 规划:创建变更,并生成实现前所需的规划文档。适合希望一次完成规划流程的用户;代码修改不在其范围内。
主要功能
- 01创建变更框架
- 02按依赖顺序生成文档
- 03起草前检查项目上下文
- 04处理必需和条件性文档
- 05将实现留给独立流程
适用场景
- 01准备待实现的变更
- 02生成相互关联的规划文档
- 03规划功能或修复而不修改代码
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fission-ai/ openspec --skill openspec-ff-change安装后在 Claude Code 中输入/openspec-ff-change确认已加载。
详细介绍
通过快进完成产物创建——一次性生成开始实施所需的一切。
存储库选择: 如果用户指定了存储库(存储库是指在这台机器上注册的独立 OpenSpec 仓库),或相关工作位于某个存储库中,请运行 openspec store list --json 以发现已注册的存储库 ID,然后在读取或写入规范和变更的命令中传入 --store <id>(new change、status、instructions、list、show、validate、archive、doctor、context、schemas、view)。选定后,在工作流剩余部分始终使用 --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,而不要重试或绕过检查。
如果 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/ 文件;也不要让命令创建它。
输入:用户的请求应包含变更名称(kebab-case),或描述他们想要构建的内容。
步骤
-
如果未提供明确的输入,询问他们想构建什么
向用户开放式提问(不要提供预设选项):
“你想处理什么变更?请描述你想构建或修复的内容。”
根据他们的描述推导出 kebab-case 名称(例如,“添加用户身份验证” →
add-user-auth)。重要:在弄清楚用户想构建什么之前,不要继续。
-
创建变更目录
openspec new change "<name>"这会在 CLI 解析出的规划主目录中创建一个脚手架变更。
-
获取制品构建顺序
openspec status --change "<name>" --json解析 JSON,获取:
applyRequires:实现前所需制品 ID 的数组(例如,["tasks"])artifacts:所有制品的列表,每个制品都包含其status和requires边(即它直接依赖的制品 ID)planningHome、changeRoot、artifactPaths和actionContext:路径和范围上下文。请使用这些信息,不要假定路径位于仓库本地。
-
创建所需集合中的每个制品
使用待办列表跟踪制品进度。
按依赖顺序遍历制品(先处理没有待处理依赖项的制品):
a. 对于每个状态为
ready(依赖项均已满足)的制品:- 获取说明:
openspec instructions <artifact-id> --change "<name>" --json - 说明 JSON 包含:
context:项目背景(对你的约束——不要写入输出)rules:制品专属规则(对你的约束——不要写入输出)template:输出文件需采用的结构instruction:针对该制品类型的架构专属指南skipped/warning:当变更声明了 skip_specs,且不得创建该制品时会出现——停止并选择另一个制品resolvedOutputPath:解析后的输出路径或模式dependencies:需阅读以了解上下文的已完成制品
- 阅读所有已完成的依赖文件以了解上下文——务必从磁盘重新读取,即使你之前在对话中看过这些文件(用户可能已编辑过)
- 起草前检查相关项目:先阅读
context和rules,再检查openspec/之外相关的实现、附近的测试、配置和文档。检查应保持只读,并与变更范围相称;将发现复用于后续制品,并仅在需要时进一步检查。- 根据请求和项目上下文确定目标项目;规划目录可能与代码分开。如果目标不明确,请询问。对于绿地项目或非代码变更,请检查可用的结构和相关文档。如果源代码不可用,说明限制;若这会实质影响计划,请向用户询问。
- 根据检查结果确定范围、方案和任务。区分观察到的行为、假设和拟议的新增内容;如果与现有规范冲突,请明确指出,不要默默决定采用哪一方。
- 现在就进行此项探索,不要把通用的“探索代码库”或“制定计划”任务留给实现阶段。必要的后续调查应明确针对尚未解决的问题。
- 创建任何内容前先确定输出路径。如果
resolvedOutputPath是 glob 模式,请按照instruction在changeRoot内选择符合该模式的具体路径,并在解析符号链接后验证其父目录和文件本身(如果文件已存在)均位于changeRoot内;如果不在,请停止并告知用户。否则,输出路径就是resolvedOutputPath - 如果
instruction字段要求使用特定技能或命令来创建文件,仅当它能将制品写入该输出路径时才调用;否则停止并告知用户。随后验证该输出路径上的制品文件确实存在 - 否则使用
template作为结构创建制品文件,并将其写入该输出路径 - 将
context和rules作为约束,但不要将它们复制到文件中 - 简要显示进度:“✓ 已创建 ”
b. 继续操作,直到必需集合中的每个产物都存在(而不仅仅是
apply.requires) - 创建每个产物后,重新运行
openspec status --change "<name>" --json - 必需集合由
applyRequires及从这些产物出发、沿着status --json中的requires边可到达的所有产物组成——沿依赖关系递归遍历(spec-driven 会递归包含 proposal、specs、design、tasks)。集合以外的产物保持不变 status只检查文件是否存在,因此applyRequires中的产物显示为done,并不代表其依赖项也存在——过早写入tasks.md会将tasks标记为done,即使specs从未写入。请根据每个产物的requires边构建必需集合,而不是看其status:即使产物为done,它仍会列出自己的依赖项- 如果产物当前的
status为"skipped",则视为已满足:此变更在.openspec.yaml中声明了skip_specs,因此其文件不得存在。切勿尝试创建此类文件 - 创建必需集合中所有缺失的产物,然后重新检查——创建一个产物可能会解除其他产物的阻塞状态
- 仅当
status已报告产物为skipped,或其自身的instruction说明该产物为有条件创建时,才可跳过:运行openspec instructions <artifact-id> --change "<name>" --json,且仅当其instruction字段标明该产物为可选时才跳过(例如“仅在……时创建”)。Spec-driven 中的design.md符合此条件;specs只有在上述skipped状态下才符合条件,不得自行判断。告知用户,不要再考虑创建该产物 - 依赖项用于协助创建,不是门槛:如果必需产物仅因你跳过了一个有条件的依赖项而仍处于
blocked状态,也要照常编写 - 当必需集合中的每个产物都处于
done、skipped状态,或已被有意跳过时,停止
c. 如果产物需要用户输入(上下文存在关键不明确之处):
- 请用户澄清
- 然后继续创建
- 获取说明:
-
显示最终状态
openspec status --change "<name>"
输出
完成所有产物后,进行总结:
- 变更名称和位置
- 列出已创建的产物并简要说明;同时列出跳过的任何有条件产物及原因
- 已就绪内容:“所有实现所需的产物均已就绪。”
- 提示:“运行
/openspec-apply-change或让我来实现,即可开始处理任务。”
产物创建指南
- 遵循
openspec instructions中针对每种产物类型的instruction字段——这是权威指南,即使产物名称很熟悉也应如此 - 如果
instruction字段要求使用特定技能或命令创建产物,请调用该技能或命令,而不是直接编写产物;但仅在选定并检查输出路径后,且该技能或命令能够写入该路径时才这样做 - Schema 定义了每种产物应包含的内容——请遵循
- 创建新产物前,请先阅读其依赖产物以了解上下文
- 使用
template作为输出文件的结构,并填写其中各部分 - 重要:
context和rules是对你的约束,不是文件内容- 不要将
<context>、<rules>、<project_context>块复制到产物中 - 这些内容用于指导你撰写,但绝不能出现在输出中
- 不要将
防护措施
- 创建实现阶段传递依赖的所有产物,而不仅是
apply.requires中列出的产物 ID - 创建新产物前,务必重新从磁盘读取依赖产物,而不是依赖对话记录中的内容(文件可能已在你上次查看后发生变化)
- 如果上下文存在关键不明确之处,请询问用户;但优先做出合理判断以保持进度
- 如果已存在同名变更,建议继续处理该变更
- 每次写入后,都要确认产物文件存在,再继续下一项