OPSX 工作流
欢迎在 Discord 上提供反馈。
这是什么?
OPSX 现在是 OpenSpec 的标准工作流。
它是一种流畅、迭代的工作流,用于处理 OpenSpec 的变更。不再有僵化的阶段——只有你可以随时采取的行动。
为何存在
旧版 OpenSpec 工作流虽然可用,但它是封闭的:
- 指令被硬编码 — 埋藏在 TypeScript 中,你无法更改
- 全有或全无 — 一个大命令创建所有内容,无法单独测试各个部分
- 固定结构 — 对所有人都是相同的工作流,无法自定义
- 黑盒 — 当 AI 输出不佳时,你无法调整提示词
OPSX 将其开放。 现在任何人都可以:
- 试验指令 — 编辑模板,看看 AI 是否表现更好
- 细粒度测试 — 独立验证每个构件的指令
- 自定义工作流 — 定义你自己的构件和依赖关系
- 快速迭代 — 更改模板,立即测试,无需重新构建
旧版工作流: OPSX:
┌────────────────────────┐ ┌────────────────────────┐
│ 硬编码在包中 │ │ schema.yaml │◄── 你编辑这个
│ (无法更改) │ │ templates/*.md │◄── 或者这个
│ ↓ │ │ ↓ │
│ 等待新版本发布 │ │ 立即生效 │
│ ↓ │ │ ↓ │
│ 祈祷它变得更好 │ │ 自己测试 │
└────────────────────────┘ └────────────────────────┘这是为所有人准备的:
- 团队 — 创建符合你们实际工作方式的工作流
- 高级用户 — 调整提示词,为你的代码库获得更好的 AI 输出
- OpenSpec 贡献者 — 无需发布即可试验新方法
我们都在学习什么最有效。OPSX 让我们共同学习。
用户体验
线性工作流的问题: 你处于“规划阶段”,然后是“实施阶段”,然后是“完成”。但实际工作并非如此。你实施某项内容,发现设计有误,需要更新规格说明,然后继续实施。线性阶段与工作的实际发生方式相冲突。
OPSX 方法:
- 操作,而非阶段 — 创建、实施、更新、归档 — 随时执行任何操作
- 依赖是促成因素 — 它们展示的是可能性,而不是接下来必须做什么
提案 ──→ 规格说明 ──→ 设计 ──→ 任务 ──→ 实施设置
bash
# 确保你已安装 openspec — 技能会自动生成
openspec init这会在 .claude/skills/(或等效位置)中创建技能,AI 编码助手会自动检测到它们。
默认情况下,OpenSpec 使用 core 工作流配置文件(propose、explore、apply、sync、archive)。如果你想要扩展的工作流命令(new、continue、ff、verify、bulk-archive、onboard),请使用 openspec config profile 进行配置,并使用 openspec update 应用。
在设置过程中,系统会提示你创建一个项目配置(openspec/config.yaml)。这是可选的,但推荐使用。
项目配置
项目配置允许你设置默认值,并将项目特定的上下文注入到所有构件中。
创建配置
配置在 openspec init 期间创建,或手动创建:
yaml
# openspec/config.yaml
schema: spec-driven
context: |
技术栈:TypeScript, React, Node.js
API 约定:RESTful, JSON 响应
测试:Vitest 用于单元测试,Playwright 用于端到端测试
风格:ESLint 配合 Prettier,严格的 TypeScript
rules:
proposal:
- 包含回滚计划
- 识别受影响的团队
specs:
- 场景使用 Given/When/Then 格式
design:
- 复杂流程包含序列图配置字段
| 字段 | 类型 | 描述 |
|---|---|---|
schema | 字符串 | 新变更的默认模式(例如,spec-driven) |
context | 字符串 | 注入到所有构件指令中的项目上下文 |
rules | 对象 | 按构件 ID 键控的每构件规则 |
工作原理
模式优先级(从高到低):
- CLI 标志(
--schema <name>) - 变更元数据(变更目录中的
.openspec.yaml) - 项目配置(
openspec/config.yaml) - 默认值(
spec-driven)
上下文注入:
- 上下文被添加到每个构件的指令前面
- 包裹在
<context>...</context>标签中 - 帮助 AI 理解你项目的约定
规则注入:
- 规则仅针对匹配的构件注入
- 包裹在
<rules>...</rules>标签中 - 出现在上下文之后、模板之前
按模式划分的构件 ID
spec-driven(默认):
proposal— 变更提案specs— 规格说明design— 技术设计tasks— 实施任务
配置验证
rules中的未知构件 ID 会生成警告- 模式名称会根据可用模式进行验证
- 上下文有 50KB 大小限制
- 无效的 YAML 会报告行号
故障排除
“规则中的未知构件 ID:X”
- 检查构件 ID 是否与你的模式匹配(参见上面的列表)
- 运行
openspec schemas --json查看每个模式的构件 ID
配置未被应用:
- 确保文件位于
openspec/config.yaml(不是.yml) - 使用验证器检查 YAML 语法
- 配置更改立即生效(无需重启)
上下文过大:
- 上下文限制为 50KB
- 请总结或链接到外部文档
命令
| 命令 | 功能 |
|---|---|
/opsx:propose | 创建变更并一步生成规划构件(默认快速路径) |
/opsx:explore | 思考想法、调查问题、澄清需求 |
/opsx:new | 开始一个新的变更脚手架(扩展工作流) |
/opsx:continue | 创建下一个构件(扩展工作流) |
/opsx:ff | 快进规划构件(扩展工作流) |
/opsx:apply | 实施任务,根据需要更新构件 |
/opsx:verify | 根据构件验证实施(扩展工作流) |
/opsx:sync | 将增量规格说明同步到主干(默认工作流,可选) |
/opsx:archive | 完成后归档 |
/opsx:bulk-archive | 归档多个已完成的变更(扩展工作流) |
/opsx:onboard | 端到端变更的引导式演练(扩展工作流) |
用法
探索想法
/opsx:explore思考想法、调查问题、比较选项。无需结构 — 只是一个思考伙伴。当想法成熟时,过渡到 /opsx:propose(默认)或 /opsx:new//opsx:ff(扩展)。
开始一个新变更
/opsx:propose创建变更并生成实施前所需的规划构件。
如果你启用了扩展工作流,可以改用:
text
/opsx:new # 仅创建脚手架
/opsx:continue # 一次创建一个构件
/opsx:ff # 一次创建所有规划构件创建构件
/opsx:continue根据依赖关系显示可以创建的内容,然后创建一个构件。重复使用以逐步构建你的变更。
/opsx:ff add-dark-mode一次创建所有规划构件。当你清楚要构建什么时使用。
实施(灵活部分)
/opsx:apply处理任务,完成后勾选。如果你同时处理多个变更,可以运行 /opsx:apply <name>;否则它应该从对话中推断,如果无法判断则提示你选择。
完成
/opsx:archive # 完成后移至归档(如果需要,会提示同步规格说明)何时更新 vs. 重新开始
你总是可以在实施前编辑你的提案或规格说明。但何时精炼会变成“这是不同的工作”?
提案捕获的内容
提案定义三件事:
- 意图 — 你正在解决什么问题?
- 范围 — 什么在范围内/外?
- 方法 — 你将如何解决?
问题是:哪个改变了,改变了多少?
更新现有变更当:
相同意图,精炼执行
- 你发现了未考虑的边缘情况
- 方法需要调整但目标不变
- 实施表明设计略有偏差
范围缩小
- 你意识到完整范围太大,想先发布 MVP
- “添加深色模式” → “添加深色模式切换(系统偏好在 v2 中)”
学习驱动的修正
- 代码库结构与你想象的不同
- 依赖项未按预期工作
- “使用 CSS 变量” → “改用 Tailwind 的 dark: 前缀”
开始新变更当:
意图根本改变
- 问题本身现在不同了
- “添加深色模式” → “添加包含自定义颜色、字体、间距的综合主题系统”
范围爆炸
- 变更增长如此之大,本质上已是不同的工作
- 更新后原始提案将面目全非
- “修复登录错误” → “重写认证系统”
原始变更可完成
- 原始变更可以标记为“完成”
- 新工作独立存在,不是精炼
- 完成“添加深色模式 MVP” → 归档 → 新变更“增强深色模式”
启发式方法
┌─────────────────────────────────────┐
│ 这是同一项工作吗? │
└──────────────┬──────────────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
相同意图? >50% 重叠? 原始变更能否
相同问题? 相同范围? 在没有这些更改
│ │ 的情况下“完成”?
│ │ │
┌────────┴────────┐ ┌──────┴──────┐ ┌───────┴───────┐
│ │ │ │ │ │
是 否 是 否 否 是
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
更新 新建 更新 新建 更新 新建| 测试 | 更新 | 新变更 |
|---|---|---|
| 身份 | “同一事物,精炼” | “不同的工作” |
| 范围重叠 | >50% 重叠 | <50% 重叠 |
| 完成度 | 没有更改就无法“完成” | 可以完成原始工作,新工作独立存在 |
| 故事 | 更新链讲述连贯的故事 | 补丁会比澄清更令人困惑 |
原则
更新保留上下文。新变更提供清晰度。
当你的思考历史有价值时选择更新。 当重新开始比修补更清晰时选择新建。
可以把它想象成 git 分支:
- 在开发同一功能时持续提交
- 当是真正的新工作时开始新分支
- 有时合并部分功能,然后为第二阶段重新开始
有何不同?
传统方案 (/openspec:proposal) | OPSX (/opsx:*) | |
|---|---|---|
| 结构 | 一个大型提案文档 | 离散的、相互依赖的构件 |
| 工作流 | 线性阶段:规划 → 实施 → 归档 | 流动的操作 —— 随时可执行任何操作 |
| 迭代 | 回溯修改较为困难 | 随着认知更新而更新构件 |
| 定制化 | 固定结构 | 基于模式驱动(可自定义构件) |
关键洞察: 工作并非线性。OPSX 不再假装它是。
架构深入解析
本节将解释 OPSX 的底层工作原理,以及它与传统工作流的对比。 本节中的示例使用了扩展命令集(new、continue 等);默认的 core 用户可以将相同的流程映射为 propose → apply → sync → archive。
设计理念:阶段与动作
┌─────────────────────────────────────────────────────────────────────────────┐
│ 传统工作流 │
│ (阶段锁定,全有或全无) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 规划阶段 │ ───► │ 实施阶段 │ ───► │ 归档阶段 │ │
│ │ │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ /openspec:proposal /openspec:apply /openspec:archive │
│ │
│ • 一次性创建所有工件 │
│ • 实施期间无法回头更新规格 │
│ • 阶段门控强制线性推进 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ OPSX 工作流 │
│ (流畅动作,迭代式) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ 动作(而非阶段) │ │
│ │ │ │
│ │ new ◄──► continue ◄──► apply ◄──► archive │ │
│ │ │ │ │ │ │ │
│ │ └──────────┴───────────┴───────────┘ │ │
│ │ 任意顺序 │ │
│ └────────────────────────────────────────────┘ │
│ │
│ • 逐个创建工件或快速前进 │
│ • 实施期间可更新规格/设计/任务 │
│ • 依赖关系驱动进度,阶段概念不存在 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘组件架构
传统工作流使用 TypeScript 中的硬编码模板:
┌─────────────────────────────────────────────────────────────────────────────┐
│ 传统工作流组件 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 硬编码模板(TypeScript 字符串) │
│ │ │
│ ▼ │
│ 工具特定的配置器/适配器 │
│ │ │
│ ▼ │
│ 生成的命令文件(.claude/commands/openspec/*.md) │
│ │
│ • 结构固定,无工件感知 │
│ • 更改需要修改代码并重新构建 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘OPSX使用外部模式和依赖图引擎:
┌─────────────────────────────────────────────────────────────────────────────┐
│ OPSX 组件 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 模式定义(YAML) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ name: spec-driven │ │
│ │ artifacts: │ │
│ │ - id: proposal │ │
│ │ generates: proposal.md │ │
│ │ requires: [] ◄── 依赖关系 │ │
│ │ - id: specs │ │
│ │ generates: specs/**/*.md ◄── Glob 模式 │ │
│ │ requires: [proposal] ◄── 在 proposal 完成后启用 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 工件图引擎 │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ • 拓扑排序(依赖排序) │ │
│ │ • 状态检测(文件系统存在性) │ │
│ │ • 丰富的指令生成(模板 + 上下文) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 技能文件(.claude/skills/openspec-*/SKILL.md) │
│ │
│ • 跨编辑器兼容(Claude Code、Cursor、Windsurf) │
│ • 技能通过 CLI 查询结构化数据 │
│ • 通过模式文件完全可定制 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘依赖图模型
工件构成一个有向无环图(DAG)。依赖关系是启用条件,而非门控:
proposal
(根节点)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(需要: (需要:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(需要:
specs, design)
│
▼
┌──────────────┐
│ APPLY 阶段 │
│ (需要: │
│ tasks) │
└──────────────┘状态转换:
BLOCKED ────────────────► READY ────────────────► DONE
│ │ │
缺失依赖 所有依赖 文件存在于
均为 DONE 文件系统信息流
传统工作流 — 代理接收静态指令:
用户:"/openspec:proposal"
│
▼
┌─────────────────────────────────────────┐
│ 静态指令: │
│ • 创建 proposal.md │
│ • 创建 tasks.md │
│ • 创建 design.md │
│ • 创建 specs/<capability>/spec.md │
│ │
│ 不感知已有内容或工件间的依赖关系 │
└─────────────────────────────────────────┘
│
▼
代理一次性创建所有工件OPSX — 代理查询丰富上下文:
用户:"/opsx:continue"
│
▼
┌──────────────────────────────────────────────────────────────────────────┐
│ 步骤 1:查询当前状态 │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ $ openspec status --change "add-auth" --json │ │
│ │ │ │
│ │ { │ │
│ │ "artifacts": [ │ │
│ │ {"id": "proposal", "status": "done"}, │ │
│ │ {"id": "specs", "status": "ready"}, ◄── 首个就绪 │ │
│ │ {"id": "design", "status": "ready"}, │ │
│ │ {"id": "tasks", "status": "blocked", "missingDeps": ["specs"]}│ │
│ │ ] │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ 步骤 2:获取就绪工件的丰富指令 │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ $ openspec instructions specs --change "add-auth" --json │ │
│ │ │ │
│ │ { │ │
│ │ "template": "# Specification\n\n## ADDED Requirements...", │ │
│ │ "dependencies": [{"id": "proposal", "path": "...", "done": true}│ │
│ │ "unlocks": ["tasks"] │ │
│ │ } │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ 步骤 3:读取依赖 → 创建一个工件 → 显示解锁内容 │
└──────────────────────────────────────────────────────────────────────────┘迭代模型
传统工作流 — 迭代不便:
┌─────────┐ ┌─────────┐ ┌─────────┐
│/proposal│ ──► │ /apply │ ──► │/archive │
└─────────┘ └─────────┘ └─────────┘
│ │
│ ├── “等等,设计有误”
│ │
│ ├── 选项:
│ │ • 手动编辑文件(破坏上下文)
│ │ • 放弃并重新开始
│ │ • 强行推进,稍后修复
│ │
│ └── 没有官方的“回退”机制
│
└── 一次性创建所有工件OPSX — 自然迭代:
/opsx:new ───► /opsx:continue ───► /opsx:apply ───► /opsx:archive
│ │ │
│ │ ├── “设计有误”
│ │ │
│ │ ▼
│ │ 只需编辑 design.md
│ │ 然后继续!
│ │ │
│ │ ▼
│ │ /opsx:apply 从上次中断处继续
│ │
│ └── 创建一个工件,显示解锁内容
│
└── 搭建变更框架,等待指示自定义模式
使用模式管理命令创建自定义工作流:
bash
# 从头创建新模式(交互式)
openspec schema init my-workflow
# 或者以现有模式为起点进行分叉
openspec schema fork spec-driven my-workflow
# 验证你的模式结构
openspec schema validate my-workflow
# 查看模式解析来源(调试时有用)
openspec schema which my-workflow模式存储在 openspec/schemas/(项目本地,版本控制)或 ~/.local/share/openspec/schemas/(用户全局)。
模式结构:
openspec/schemas/research-first/
├── schema.yaml
└── templates/
├── research.md
├── proposal.md
└── tasks.md示例 schema.yaml:
yaml
name: research-first
artifacts:
- id: research # 在 proposal 之前添加
generates: research.md
requires: []
- id: proposal
generates: proposal.md
requires: [research] # 现在依赖于 research
- id: tasks
generates: tasks.md
requires: [proposal]依赖图:
research ──► proposal ──► tasks总结
| 方面 | 传统工作流 | OPSX |
|---|---|---|
| 模板 | 硬编码 TypeScript | 外部 YAML + Markdown |
| 依赖关系 | 无(一次性全部) | 带拓扑排序的 DAG |
| 状态 | 基于阶段的心智模型 | 文件系统存在性 |
| 定制化 | 编辑源码,重新构建 | 创建 schema.yaml |
| 迭代 | 阶段锁定 | 流畅,可编辑任何内容 |
| 编辑器支持 | 工具特定的配置器/适配器 | 单一技能目录 |
架构
架构定义了存在的制品及其依赖关系。当前可用:
- 规范驱动(默认):提案 → 规范 → 设计 → 任务
bash
# 列出可用架构
openspec schemas
# 查看所有架构及其解析来源
openspec schema which --all
# 交互式创建新架构
openspec schema init my-workflow
# 复刻现有架构以进行自定义
openspec schema fork spec-driven my-workflow
# 使用前验证架构结构
openspec schema validate my-workflow技巧
- 使用
/opsx:explore在提交更改前梳理思路 - 当你明确目标时使用
/opsx:ff,探索时使用/opsx:continue - 在
/opsx:apply过程中,如果发现问题 —— 修复制品,然后继续 - 任务通过
tasks.md中的复选框跟踪进度 - 随时检查状态:
openspec status --change "name"
反馈
目前还比较粗糙。这是有意为之——我们正在探索什么方法有效。