本系列共 7 篇文章 :
- OpenSpec 教程 : ① 核心理念 为什么要在写代码前先写 Spec
- OpenSpec 教程 : ② 安装 & 初始化
- OpenSpec 教程 : ③ 目录结构 & 核心概念
- OpenSpec 教程 : ④ 核心工作流:OPSX 命令
- OpenSpec 教程 : ⑤ Delta Spec — 存量项目核心
- OpenSpec 教程 : ⑥ 进阶:CLI 工具 & 自定义
- OpenSpec 教程 : ⑦ 实战:与 Claude Code 结合 用 SDD 开发游戏账号交易平台的"账号估价"功能
把 core 和 expanded 的所有命令放在一起,形成完整的命令地图, 方便整体理解:
思考阶段
/opsx:explore ← 探索想法,调查问题,不产生代码
规划阶段(core)
/opsx:propose ← new + ff 的组合,一步到位
规划阶段(expanded,细粒度控制)
/opsx:new ← 只建文件夹
/opsx:continue ← 逐步生成 artifact,每次一个
/opsx:ff ← 快进生成所有 artifact
实现阶段(core)
/opsx:apply ← 按 tasks.md 逐条实现代码
/opsx:sync ← 同步代码和 artifact 的状态
验证阶段(expanded)
/opsx:verify ← 检查完整性、正确性、一致性
归档阶段(core)
/opsx:archive ← 归档单个 change
归档阶段(expanded)
/opsx:bulk-archive ← 批量归档多个 change,处理冲突
引导流程(expanded)
/opsx:onboard ← 存量项目的 SDD 冷启动引导
最高频的路径是:遇到想不清楚的问题先 explore,想清楚了直接 propose,实现完跑 verify,没问题就 archive。sync 和 bulk-archive 是辅助工具,在出现实现和预期脱节或需要批量处理时才会用到
/opsx:propose:提案
/opsx:propose <change-name>
change-name 用连字符命名,描述这次变更的核心意图:
/opsx:propose account-auto-pricing
/opsx:propose order-status-notification
/opsx:propose search-filter-by-server
/opsx:propose payment-alipay-integration
执行后 Claude 会追问你几个问题来填充 proposal.md,通常是:要解决什么问题、预期的解决思路、有没有已知的约束或排除项。你的回答不需要精确,几句话即可——AI 会帮你整理成结构化格式。
如果你已经想清楚了,也可以一次性把背景都给出去:
/opsx:propose account-auto-pricing
卖家发布账号时不知道定价多少,导致长期滞销或低价损失。
希望在发布页面提供参考价格区间,基于过去 90 天同类账号
的历史成交价计算。首版用统计方法,不做机器学习。
输出四个文件
执行完成后,openspec/changes/account-auto-pricing/ 目录里会出现:
openspec/changes/account-auto-pricing/
├── proposal.md
├── specs/
│ └── account/
│ └── spec.md ← Delta Spec
├── design.md
└── tasks.md
实际上 /opsx:propose 是 core profile 里的快捷方式
- 它等价于依次执行
/opsx:new+/opsx:ff——先创建 change 文件夹,再快进生成全部 artifact - 也可以用
/opsx:new+/opsx:continue逐步生成,每次只创建一个文件,方便在中途审查和调整
典型内容
proposal.md
# Proposal: account-auto-pricing
## Problem
卖家发布账号时缺乏定价参考。平台数据显示,无参考价格的账号
平均挂单时长是有参考价格账号的 2.3 倍。
## Solution
在账号发布流程中新增估价服务,基于过去 90 天同类账号成交价
计算 P25/P50/P75 分位数,返回低/均/高三档参考价格区间。
## Success criteria
- 卖家发布账号时能看到估价区间
- 估价响应时间 < 500ms(P95)
- 覆盖平台前 10 大游戏品类
## Out of scope
- 机器学习模型(首版用规则+统计)
- 实时竞品价格抓取
specs/account/spec.md (Delta Spec)
# Delta for Account Domain
## ADDED Requirements
### Requirement: Account pricing suggestion
The system MUST provide a price suggestion when a seller creates a new listing.
#### Scenario: Normal pricing
- GIVEN a seller submits (game_type=LOL, level=150, rare_items=[skin_legendary])
- WHEN the pricing service is called with sufficient historical data
- THEN return { low: 280, mid: 350, high: 480, currency: "CNY", sample_size: 42 }
- AND response time SHALL be under 500ms at P95
#### Scenario: Insufficient data
- GIVEN fewer than 5 comparable transactions exist
- WHEN the pricing service is called
- THEN return { insufficient_data: true, low: null, mid: null, high: null }
design.md
# Design: account-auto-pricing
## Architecture
AccountController → PricingService → PricingRepository → Redis 缓存层
## Key decisions
- 算法:P25/P50/P75 分位数,取过去 90 天数据
- 缓存:Redisson,key = pricing:{game_type}:{level_bucket},TTL 30min
- 降级:Redis 不可用时查 DB;DB 超时 200ms 返回 insufficient_data
## API contract
GET /api/v1/accounts/pricing?game_type=LOL&level=150
Response: { low, mid, high, currency, sample_size }
tasks.md
# Tasks: account-auto-pricing
## 1. 数据层
- [ ] 1.1 account_transaction 表新增索引 idx_pricing
- [ ] 1.2 PricingRepository.findComparablePrices()
## 2. 服务层
- [ ] 2.1 PricingService.suggest() 核心逻辑
- [ ] 2.2 Redisson 缓存封装
- [ ] 2.3 降级逻辑
## 3. 接口层
- [ ] 3.1 GET /api/v1/accounts/pricing Controller
- [ ] 3.2 参数校验
## 4. 测试
- [ ] 4.1 PricingServiceTest(三个场景)
- [ ] 4.2 集成测试:P95 响应时间断言
/opsx:propose 的输出质量取决于你给的上下文有多清晰。Claude 在生成这四个文件时会读取 openspec/specs/ 里的已有规格和项目的 CLAUDE.md,但对业务背景的理解完全依赖你在 propose 时的描述。
几个提高输出质量的实践:
- 说清楚"为什么现在做"(触发因素或数据支撑)
- 点名不做什么(Out of scope 防止范围蔓延)
- 如果有明确的技术约束提前说(比如"必须用 RocketMQ 异步")
这些信息进 proposal,design 和 tasks 就会自动反映出来,不需要在后续步骤里反复纠正方向。
生成完之后不要急着跑 /opsx:apply,先把四个文件通读一遍。如果 design 里的技术决策不对、tasks 的粒度太粗、或者 specs 里漏了某个边界场景,现在改代价最低——改一个 Markdown 文件,而不是改一堆已经生成的代码。
/opsx:ff 和 /opsx:continue 的区别
依赖链
要理解这两个命令,先要理解 OpenSpec 的 artifact 生成顺序。四个文件之间存在依赖关系:
proposal.md → specs/ → design.md → tasks.md
proposal 决定了 specs 的边界,specs 的行为约束决定了 design 的技术选型,design 的方案决定了 tasks 的分解粒度。这条依赖链是 /opsx:new、/opsx:continue、/opsx:ff 三个命令存在的原因——它们都是围绕"按依赖顺序生成 artifact"这件事设计的,只是步进粒度不同。
这三个命令属于 expanded profile,需要先开启:
openspec config profile # 选 expanded
openspec update
# 重启 Claude Code
/opsx:new
创建 change 文件夹
/opsx:new account-auto-pricing
只做一件事:创建 openspec/changes/account-auto-pricing/ 目录,不生成任何文件。输出类似:
Created openspec/changes/account-auto-pricing/
Schema: spec-driven
Ready to create: proposal
Use /opsx:continue to create it, or /opsx:ff to create all artifacts.
单独用 /opsx:new 的场景很少,通常它是 /opsx:continue 或 /opsx:ff 的前置步骤。
/opsx:continue
每次生成一个 artifact
/opsx:continue
每次调用只生成依赖链里下一个尚未创建的文件,然后停下来等你审查。第一次调用生成 proposal.md,你看完觉得没问题,再调用一次生成 specs/,依此类推:
第一次 /opsx:continue:
Change: account-auto-pricing
Artifact status:
◆ proposal (ready)
○ specs (blocked - needs: proposal)
○ design (blocked - needs: specs)
○ tasks (blocked - needs: design)
Creating proposal.md...
✓ Created openspec/changes/account-auto-pricing/proposal.md
Now available: specs
Run /opsx:continue to create the next artifact.
第二次 /opsx:continue:
✓ proposal (done)
◆ specs (ready)
○ design (blocked)
○ tasks (blocked)
Creating specs...
✓ Created openspec/changes/account-auto-pricing/specs/account/spec.md
第三次 /opsx:continue:
✓ proposal (done)
✓ specs (done)
◆ design (ready)
...
适合的场景:你对这个功能的思路还没完全想清楚,或者这是个高风险的改动,想在每个阶段都仔细看一遍再往下走。看完 proposal 发现方向不对,直接编辑 proposal.md 再 continue,比跑完全程再改代价低得多。
/opsx:ff
快进,一次生成所有 artifact
/opsx:ff account-auto-pricing
Fast-forward 的缩写。一口气把 proposal、specs、design、tasks 四个文件全部生成,中间不停顿:
Fast-forwarding account-auto-pricing...
✓ Creating proposal.md
✓ Creating specs/account/spec.md
✓ Creating design.md
✓ Creating tasks.md
All planning artifacts complete!
适合的场景:需求已经想得很清楚,或者这是个改动范围小、风险低的功能,不需要在每个 artifact 之间停下来审查。
/opsx:propose 这个命令本质上就是 /opsx:new + /opsx:ff 的组合——先建文件夹,再快进生成全部文件。所以日常用 /opsx:propose 就够了,只有在需要更细粒度控制时才需要把这两步拆开。
选择原则
用 /opsx:ff(或直接 /opsx:propose)的情况:需求清晰、改动范围小、想快速进入实现阶段。这是日常开发里的默认选择。
用 /opsx:continue 的情况主要有三种。
- 需求本身还模糊,想边写 proposal 边理清思路,看完再决定 specs 怎么写
- 改动涉及多个域或者架构层面,specs 写完之后需要认真确认行为约束没有遗漏,再让 AI 去写 design
- 团队协作场景,proposal 由产品侧写,specs 由开发审查后再继续,每个阶段需要人工介入和确认
对于个人开发的上下文,/opsx:ff 是绝大多数情况下的正确选择。/opsx:continue 留给那些你自己都还没想清楚、需要边写边想的功能
中途切换也没关系
OpenSpec 支持并行处理多个 change,随时可以切换。 比如你在用 /opsx:continue 逐步推进 account-auto-pricing,突然来了个紧急 bug 需要处理:
/opsx:new fix-pricing-cache-bug
/opsx:ff fix-pricing-cache-bug
/opsx:apply fix-pricing-cache-bug
/opsx:archive fix-pricing-cache-bug
# bug 修完,回到原来的功能
/opsx:continue account-auto-pricing # 从上次中断的地方继续
change 文件夹的隔离设计保证了多个并行任务互不干扰,这是它比纯对话式开发更可靠的地方——上下文不会因为临时插入一个 bug fix 而混乱。
/opsx:apply:让 AI 按图索骥地写代码
/opsx:apply account-auto-pricing
如果当前只有一个活跃的 change,可以省略名称直接执行:
/opsx:apply
OpenSpec 会自动识别 openspec/changes/ 下唯一的未完成变更。如果有多个并行 change,需要显式指定名称。
执行前 AI 读取什么
/opsx:apply 触发后,Claude 在写任何代码之前会先读取三类上下文:
第一类 : 变更 : change 文件夹里的全部 artifact
proposal.md了解业务背景specs/了解行为约束和验收标准design.md了解技术方案和关键决策tasks.md获取要执行的具体任务列表
第二类是规范 : openspec/specs/ 主目录里的已有规范,了解系统现有行为,避免新代码破坏已有功能的逻辑
第三类是项目的 CLAUDE.md,获取编码规范、架构约定、禁止事项等项目级约束
这三类上下文叠加,构成 AI 实现这个功能所需的完整图景。和直接说"帮我实现账号估价功能"相比,区别在于 AI 不再需要猜测你的意图——design.md 里已经写明了用 Redisson 而不是直接用 Jedis,用分位数而不是均值,缓存 TTL 是 30 分钟而不是任意值。
执行过程:逐条勾选 tasks
AI 按照 tasks.md 里的编号顺序逐条实现,每完成一条就把对应的 [ ] 改成 [x]:
Implementing account-auto-pricing...
✓ 1.1 account_transaction 表新增索引 idx_pricing
→ 生成 V003__add_pricing_index.sql
✓ 1.2 PricingRepository.findComparablePrices()
→ 生成 PricingRepository.java + PricingRepositoryMapper.xml
✓ 2.1 PricingService.suggest() 核心逻辑
→ 生成 PricingService.java
✓ 2.2 Redisson 缓存封装
→ 修改 PricingService.java,注入 RedissonClient
✓ 2.3 降级逻辑
→ 修改 PricingService.java,添加 try-catch + timeout 处理
✓ 3.1 GET /api/v1/accounts/pricing Controller
→ 生成 PricingController.java
✓ 3.2 参数校验
→ 修改 PricingController.java,添加 @Valid 注解和枚举校验
✓ 4.1 PricingServiceTest
→ 生成 PricingServiceTest.java(三个测试场景)
✓ 4.2 集成测试
→ 生成 PricingControllerIntegrationTest.java
All tasks complete!
tasks.md 实时更新,随时打开都能看到当前进度。如果中途对话被打断,下次执行 /opsx:apply 时 AI 会读取 tasks.md 的状态,从第一个未勾选的任务继续,而不是从头开始。
生成代码的质量更可预测
没有 spec 的情况下让 AI 实现"账号估价功能",它会做很多隐性决策:缓存用不用、用什么客户端、降级策略怎么写、接口参数叫什么名字。这些决策不一定错,但未必和你的项目约定一致,审查代码时需要逐一核查。
有了 design.md 之后,这些决策已经在编码前确定下来。AI 拿到的不是一个模糊的意图,而是一份有约束、有边界、有技术细节的执行规格。生成的代码是 spec 的实现,而不是 AI 的自由发挥。
以 PricingService 为例,design.md 里写明了调用链和缓存策略,apply 生成的代码会直接对应这些决策:
@Service
@RequiredArgsConstructor
public class PricingService {
private final PricingRepository pricingRepository;
private final RedissonClient redissonClient; // design 里指定了用 Redisson
private static final int MIN_SAMPLE_SIZE = 5; // specs 里的约束
private static final long CACHE_TTL_MINUTES = 30; // design 里的决策
public PricingResult suggest(AccountPricingQuery query) {
String cacheKey = "pricing:" + query.getGameType()
+ ":" + query.getLevelBucket(); // design 里的 key 格式
RBucket<PricingResult> bucket = redissonClient.getBucket(cacheKey);
PricingResult cached = bucket.get();
if (cached != null) return cached;
List<BigDecimal> prices = pricingRepository
.findComparablePrices(query.getGameType(), query.getLevelBucket(), 90);
if (prices.size() < MIN_SAMPLE_SIZE) {
return PricingResult.insufficient(); // specs 里的 insufficient_data 场景
}
PricingResult result = calculatePercentiles(prices); // P25/P50/P75
bucket.set(result, CACHE_TTL_MINUTES, TimeUnit.MINUTES);
return result;
}
}
每一行都能在 spec 或 design 里找到来源。这是 SDD 和直接 prompt 最本质的区别:代码的每个关键决策都有文档依据,而不是 AI 的推断结果。
中途修改 tasks 和 design
apply 执行过程中,如果发现某个 task 的实现方向不对,可以直接中断,修改 design.md 或 tasks.md,然后重新执行 /opsx:apply。AI 会从第一个未勾选的 task 继续,已完成的部分不会重复执行。
比如执行到 task 2.2 时发现缓存 key 的粒度设计有问题,中断后修改 design.md 里的 key 规则,再执行 /opsx:apply,AI 从 2.2 重新开始,之前已完成的数据层代码不受影响。
这是 tasks.md 作为进度状态文件的核心价值——它不只是一个清单,而是一个可恢复的执行断点,让 apply 的过程天然支持中断和重试。
apply 完之后
代码生成完毕后,下一步是 /opsx:verify——对照 specs/ 里的 Scenario 验证实现是否完整、正确、与设计一致。verify 不阻断流程,但它会把遗漏和不一致明确指出来,让你决定是现在修还是记录下来留待后续处理。
/opsx:verify:归档前的质量检查
/opsx:verify account-auto-pricing
在 /opsx:apply 完成、准备归档之前执行。它不修改任何文件,只做检查和报告。
三个检查维度
verify 的输出分三个维度,对应三个不同层面的质量问题。
COMPLETENESS(完整性)
检查实现是否覆盖了所有计划中的内容:
COMPLETENESS
✓ tasks.md 中全部 9 个任务已勾选完成
✓ specs/ 中的所有 Requirement 都有对应代码实现
⚠ Scenario "Insufficient data" 未找到对应测试用例
完整性检查做两件事:
- 一是核查
tasks.md里是否所有[ ]都变成了[x],有未完成的 task 会直接报出来; - 二是遍历
specs/里的每个 Scenario(场景),检查代码库里是否存在覆盖这个场景的测试。
第二件事是 Scenario 格式存在的核心价值之一。GIVEN/WHEN/THEN 结构不只是文档规范,它让 AI 能够把 spec 里的场景描述和测试代码里的断言逻辑做语义匹配。一个 Scenario: Insufficient data 对应的测试方法名里应该出现 insufficient 或类似关键词,测试体里应该断言 insufficient_data: true。完全靠关键词匹配不是百分之百精确,但能捕获大多数明显遗漏
CORRECTNESS(正确性)
检查实现是否与规格定义的行为一致:
CORRECTNESS
✓ API 返回结构 { low, mid, high, currency, sample_size } 与 specs 一致
✓ Scenario "Normal pricing" 的边界条件已处理
⚠ Scenario "Insufficient data" 触发条件:specs 定义 < 5 条记录,
代码实现为 <= 5,差一条
正确性检查会把 specs 里的具体约束和代码实现做对照。比如 specs 写的是 fewer than 5(严格小于),但代码写的是 <= 5,这是一个差一的逻辑错误,verify 会精确指出来。
API 的响应结构、方法的返回类型、参数的校验范围——这些在 specs 里有明确描述的约束都在 correctness 的检查范围内。
COHERENCE(一致性)
检查代码与技术方案是否对齐:
COHERENCE
✓ 缓存 key 格式 pricing:{game_type}:{level_bucket} 与 design.md 一致
✓ 降级逻辑触发条件与 design.md 描述匹配
⚠ design.md 约定使用 P25/P50/P75 分位数,
代码实现为 P20/P50/P80,存在偏差
Coherence 检查的是 design.md 里的技术决策在代码里是否得到了忠实执行。缓存策略、降级逻辑、算法选型、命名约定——这些在 design 里写下来的东西,AI 在 apply 时理论上应该遵循,但偶尔会出现漂移。Coherence 把这些漂移显式地暴露出来。
输出格式
完整的 verify 报告长这样:
COMPLETENESS
✓ 全部 9 个 tasks 已勾选
✓ Requirement "Account pricing suggestion" 有代码实现
⚠ Scenario "Insufficient data" 未找到对应测试覆盖
CORRECTNESS
✓ 返回结构与 specs 一致
⚠ insufficient_data 触发条件:specs 定义 < 5,代码实现 <= 5
COHERENCE
✓ 缓存 key 格式与 design.md 一致
✓ 降级策略与 design.md 匹配
⚠ design.md 约定 P25/P50/P75,代码实现为 P20/P50/P80
SUMMARY
─────────────────────────────────
Critical issues: 0
Warnings: 3
Ready to archive: Yes (with warnings)
Recommendations:
1. 补充 "Insufficient data" 场景的测试用例
2. 修正 insufficient_data 触发条件(< 5 而非 <= 5)
3. 将分位数还原为 P25/P50/P75,或更新 design.md 说明变更原因
Warning 和 Critical 的区别
Verify 不阻断归档流程。Warning 不会阻止 archive,但它会把需要处理的问题明确指出来,让你决定是现在修还是记录下来留待后续处理。
实践中,三类问题的处理优先级不同。
- Correctness 里的逻辑错误(比如
< 5vs<= 5这种差一错误)应该立刻修,这类问题上线后会产生真实的 bug,修改成本在这里最低。 - Completeness 里的测试覆盖缺失视情况而定,如果是核心边界场景(insufficient data 这种)应该补,如果是次要场景可以记录在 tasks.md 里作为后续 tech debt。
- Coherence 里的漂移最灵活——如果代码里的 P20/P50/P80 是有意为之(比如测试后发现效果更好),那就更新 design.md 说明变更原因;如果是 AI 的无意漂移,改回 P25/P50/P75。
这个判断逻辑体现了 SDD 的核心态度:spec 是约束,不是枷锁。发现实现和 spec 不一致时,可以改代码让它符合 spec,也可以改 spec 让它反映新的决策,但不能让两者静默地不一致
Verify 的本质价值
在没有 spec 的纯对话式开发里,代码写完之后通常只有一种检查方式:人工审查。你需要靠记忆对照最初的需求,检查每个场景是否都处理了,每个技术决策是否都落地了。这既费时又不可靠,尤其在对话上下文很长之后。
Verify 把这个检查过程自动化了,且它的检查基准是结构化的文档而不是人的记忆。每个 Warning 背后都有一条具体的 spec 条目或 design 决策作为参照,不是泛泛的"感觉有问题",而是"specs 第 12 行定义的行为在代码里找不到对应实现"。
对于游戏账号交易平台这种长期演进的项目,verify 还有一个间接价值:每次归档前的检查报告会随 change 一起存进 archive/ 目录,形成一份质量审计日志。六个月后回看某个功能的开发过程,不只能看到最终的代码,还能看到当时 verify 发现了什么问题、如何处置的。这是纯代码历史无法提供的上下文。
/opsx:archive:把变更固化进系统规范
基本用法
/opsx:archive account-auto-pricing
同样,只有一个活跃 change 时可以省略名称。Archive 是一个 change 生命周期的终点,执行后这个变更就从"进行中"变成了"已完成",不可逆。
归档时发生的两件事
Archive 命令做两件事,顺序固定。
第一件:Delta Spec 合并进主 spec
openspec/changes/account-auto-pricing/specs/account/spec.md 里的 Delta Spec 会被合并进 openspec/specs/account/spec.md。合并规则直接对应 Delta Spec 的三个区块:
ADDED区块里的内容追加进主 spec 的对应域,成为新的 Requirement 条目MODIFIED区块里的内容找到主 spec 里对应的旧 Requirement,用新版本替换掉,旧版本描述(Previously: ...)不保留在主 spec 里,只留在 archive 目录里供回溯REMOVED区块里标记的 Requirement 从主 spec 里删除
以账号估价功能为例,归档前后主 spec 的变化:
归档前 openspec/specs/account/spec.md:
# Account Domain Specs
## Requirements
### Requirement: Account listing
The system MUST allow sellers to create account listings...
归档后:
# Account Domain Specs
## Requirements
### Requirement: Account listing
The system MUST allow sellers to create account listings...
### Requirement: Account pricing suggestion
The system MUST provide a price suggestion when a seller creates a new listing.
#### Scenario: Normal pricing
- GIVEN a seller submits (game_type=LOL, level=150, rare_items=[skin_legendary])
- WHEN the pricing service is called with sufficient historical data
- THEN return { low: 280, mid: 350, high: 480, currency: "CNY", sample_size: 42 }
- AND response time SHALL be under 500ms at P95
#### Scenario: Insufficient data
- GIVEN fewer than 5 comparable transactions exist
- WHEN the pricing service is called
- THEN return { insufficient_data: true, low: null, mid: null, high: null }
Delta Spec 消失了,它的内容已经变成主 spec 的一部分。这是"活文档"的真实含义——每次功能迭代后,主 spec 自动更新,始终反映系统的当前行为。
第二件:change 文件夹移入 archive 目录
openspec/changes/account-auto-pricing/ ← 消失
openspec/changes/archive/
└── 2026-04-08-account-auto-pricing/ ← 出现,带日期前缀
├── proposal.md
├── specs/
│ └── account/
│ └── spec.md ← 原始 Delta Spec,完整保留
├── design.md
└── tasks.md ← 所有条目都已勾选 [x]
日期前缀由 OpenSpec 自动添加,格式是 YYYY-MM-DD。如果同一天有多个归档,按归档顺序排列,不会冲突。
多个 change 同时涉及同一个域
当两个并行进行的 change 都修改了 account 域的 spec,归档时会产生冲突检测:
/opsx:bulk-archive
Found 2 changes ready to archive:
- account-auto-pricing (touches specs/account/)
- account-vip-discount (touches specs/account/)
Checking for spec conflicts...
⚠ Both changes modify specs/account/spec.md
Inspecting codebase to resolve...
Both changes are implemented. Will merge in chronological order:
1. account-auto-pricing (created 2026-04-01)
2. account-vip-discount (created 2026-04-05)
Archive both? [Y/n]
OpenSpec 会检测冲突,按创建时间的先后顺序依次合并,先归档早创建的 change,再归档晚创建的,确保合并结果的确定性。
Archive 后 openspec view 的变化
归档完成后运行 openspec view 可以看到仪表盘的变化:
OpenSpec Dashboard
════════════════════════════════════════════════════
Summary:
● Specifications: 2 specs, 5 requirements
● Active Changes: 0 in progress
● Completed Changes: 1
Specifications
────────────────────────────────────────────────────
▪ account 3 requirements ← 归档后新增了 1 条
▪ order 2 requirements
Completed Changes
────────────────────────────────────────────────────
✓ account-auto-pricing (2026-04-08)
════════════════════════════════════════════════════
Specifications 里的 requirement 数量增加,对应 Delta Spec 合并的结果。Active Changes 归零,Completed Changes 出现新记录。
Archive 的不可逆性与 Git 的关系
Archive 操作本身没有撤销命令。但因为 openspec/ 整个目录都是普通文件,和源代码一起受 Git 管理,任何时候都可以通过 git revert 回滚。
这也是 OpenSpec 设计里一个刻意的选择:不自己实现版本控制,完全依赖 Git。openspec/specs/ 的每一次变化、openspec/changes/archive/ 的每一次新增,都会出现在 git log 里,和代码变更同步提交,同步回滚,不存在 spec 和代码版本不一致的风险。
实践上,建议每次 archive 都单独提交一个 commit,commit message 用变更名称命名:
git add openspec/
git commit -m "spec: archive account-auto-pricing"
这样 git log 就变成了一份双层历史:代码 commit 记录实现细节,spec commit 记录业务意图。未来定位某个功能是什么时候、为什么加进来的,git log openspec/specs/account/spec.md 就能给出清晰的答案。
完整的生命周期回顾
Archive 执行完之后,一个 change 的完整生命周期就结束了:
/opsx:propose → 建立对齐(proposal + specs + design + tasks)
/opsx:apply → AI 按 tasks 逐条实现代码
/opsx:verify → 对照 specs 检查完整性、正确性、一致性
/opsx:archive → Delta Spec 合并进主 spec,change 移入 archive
下一个功能开发时,openspec/specs/ 里已经有了这次功能的规格,新的 Delta Spec 在它的基础上继续叠加。随着每次迭代,主 spec 越来越完整,逐渐成为整个平台行为的权威文档——不是一次性写完就搁置的 Word 文件,而是和代码一起持续演进的活文档。
/opsx:explore:先想清楚再动手
/opsx:explore 是一个"思考伙伴"模式,专门用于在提交变更之前探索想法和调查问题。 它是 core profile 默认激活的四个命令之一,和 propose、apply、archive 并列。
/opsx:explore
/opsx:explore account-auto-pricing ← 关联到已有 change
不带参数时进入自由探索模式,带 change 名称时 Claude 会先读取该 change 的已有 artifact 作为上下文。
explore 能做什么,不能做什么
Explore 模式是一种"stance"(立场),不是工作流。它没有固定步骤,没有必须产出的文件,AI 可以读取文件、搜索代码、提出架构图、比较方案、创建 OpenSpec artifact——但绝对不能写应用代码或实现功能。如果用户在 explore 模式里要求实现某个功能,AI 会提醒先退出 explore 模式。
这个约束是刻意设计的。Explore 阶段的价值在于"想清楚",如果可以顺手写代码,就会重新滑回"边聊边写"的模式,失去 SDD 的意义。
典型对话示例
你:/opsx:explore
游戏账号平台需要加限流,不确定用哪种方案
Claude:让我看看你现在的架构...
[读取 Controller 层代码]
我看到三种适合你这个栈的方案:
1. Spring 拦截器(简单,按接口限流)
2. Redis + Redisson 令牌桶(可扩展,支持分布式)
3. 网关层限流(如果有 API Gateway 的话)
你们现在的 QPS 量级是多少?高峰期是账号发布
还是搜索浏览?
你:高峰是搜索,QPS 大概 500-1000
Claude:那 Redisson 令牌桶是最合适的。你已经在用
Redisson 了,不需要引入新依赖。
┌─────────────────────────────────┐
│ 请求 → 拦截器 → 令牌桶检查 │
│ ↓ │
│ 有令牌 → 放行 │
│ 无令牌 → 429 响应 │
└─────────────────────────────────┘
要开始写 change 吗?
/opsx:new api-rate-limiting
探索结束后 Claude 会主动提议:想法成熟了可以开始一个 change。用户决定,AI 不会自动转入 propose 流程。
explore 和直接 propose 的选择
Explore 适合性能优化、调试、架构决策、需求不明确的场景。需求已经清楚的功能直接用 /opsx:propose 更快。 判断标准很简单:如果你知道要做什么,跳过 explore;如果你只知道有个问题要解决,但不确定怎么解,先 explore。
关联到已有 change
Explore 还有一个容易被忽视的用法:在 apply 执行过程中遇到预料之外的复杂情况时,用它来深入调查:
你:/opsx:explore account-auto-pricing
task 2.2 的缓存实现遇到了问题,
发现 levelBucket 的分桶粒度导致命中率很低
Claude:[读取 account-auto-pricing 的 design.md 和 tasks.md]
你现在在 task 2.2。让我看看分桶策略的问题...
[分析代码和历史成交数据分布]
问题在于 LOL 账号等级集中在 100-200 段,
按 50 级分桶导致这段的数据都混在一起,
样本量虽然够,但价格区间太宽,参考价值低。
建议两个方向:
A. 热门等级段细化分桶(50→10 级)
B. 改用百分位分桶,自适应数据分布
要更新 design.md 然后继续吗?
这是 explore 最有价值的使用场景之一:不是在实现前探索,而是在实现中途遇到问题时用来分析和决策,然后带着新的理解回去更新 design 和 tasks,继续 apply
/opsx:onboard:存量代码库的第一次 SDD 仪式
为什么存量项目需要特殊处理
全新项目用 OpenSpec 很自然——每个功能从 propose 开始,spec 随着功能一起生长,最终 openspec/specs/ 里的内容和代码库完全同步。
存量项目面对的是另一个局面。交易平台项目已经跑了一段时间,账号发布、订单流转、支付对账这些核心流程早就实现了,但没有任何 spec 文件。这时候直接跑 /opsx:propose 开始新功能,新功能的 Delta Spec 里 MODIFIED 区块会找不到主 spec 里的对应条目,/opsx:verify 也没有基准可以对照。
/opsx:onboard 解决的正是这个冷启动问题:在没有任何既有 spec 的情况下,引导你走完第一次完整的 SDD 流程,同时建立起 openspec/specs/ 的初始基础。
执行过程:11 个阶段,约 15 分钟
/opsx:onboard 是一个交互式引导流程,用你的实际代码库作为素材,带你走完一次从头到尾的完整 OpenSpec 流程。
执行命令:
/opsx:onboard
Claude 会按照以下顺序引导你:
阶段一:扫描代码库,识别业务域
Claude 读取项目的包结构、Controller 层、Service 层和数据库 schema,自动识别出主要的业务域:
Scanning your codebase...
Detected business domains:
- account (AccountController, AccountService, account_listing 表)
- order (OrderController, OrderService, order 表)
- payment (PaymentController, PaymentService, payment_record 表)
- user (UserController, AuthService, user 表)
Does this look right? [Y/n]
阶段二:选择一个小改动作为练习素材
Onboard 不会试图把整个代码库的所有行为都文档化——那是一个无底洞。它的策略是找一个真实的小改动,带你走完完整的 SDD 流程,顺带建立起第一批 spec 文件:
Let's find something small to improve in your codebase.
I noticed a few opportunities:
1. AccountController 的参数校验逻辑分散,可以统一
2. OrderService 里有一个 TODO: 添加超时订单自动取消
3. 搜索接口缺少分页参数的边界校验
Which would you like to work on? (or describe your own)
选择一个,或者直接描述你自己想做的改动。
阶段三到七:依次生成 artifact
和正常的 SDD 流程完全一样——proposal、specs、design、tasks 依次生成,每个阶段 Claude 都会停下来让你确认或修改。和 /opsx:ff 不同,onboard 在每个 artifact 之间都有解释,告诉你这个文件的作用是什么、为什么要这样写。
对于初次接触 OpenSpec 的人,这些解释本身就是学习材料。
阶段八:实现代码
Now let's implement the change. Running /opsx:apply...
✓ 1.1 统一参数校验注解
✓ 1.2 提取公共校验工具类
✓ 2.1 添加对应单元测试
All tasks complete!
阶段九:验证
Running /opsx:verify...
COMPLETENESS ✓ 全部任务已完成
CORRECTNESS ✓ 实现与 spec 一致
COHERENCE ✓ 与 design 一致
Ready to archive.
阶段十:归档
Running /opsx:archive...
✓ Merged specs into openspec/specs/account/spec.md
✓ Archived to openspec/changes/archive/2026-04-08-account-validation/
阶段十一:回顾与下一步
Onboarding complete! Here's what we built:
openspec/specs/account/spec.md ← 第一份主 spec,2 个 Requirement
.claude/skills/ ← 已配置的 OpenSpec 命令
Your codebase is now OpenSpec-ready. Next steps:
- Run /opsx:propose for your next feature
- Continue adding specs for other domains as you work
已有代码库的核心策略:增量建档
Onboard 结束后,openspec/specs/ 里只有一个域的一两条 Requirement,远远不能覆盖整个平台的现有行为。这是刻意的设计。
对于存量项目,OpenSpec 的建议策略是:不要试图一次性把所有现有行为都写成 spec,而是随着每次功能迭代,把涉及的域顺带文档化。
具体来说,开发新功能"账号估价"时,Delta Spec 里的 MODIFIED 区块会引用"账号发布"这个已有行为——这时候顺手把"账号发布"的基础行为补进主 spec,作为 Delta Spec 的前提。归档后,openspec/specs/account/spec.md 就同时包含了旧行为和新行为的规格。
六个月下来,每次迭代都顺带建档,openspec/specs/ 会自然地覆盖最高频的业务域,而那些从未被修改过的边缘功能就算没有 spec 也无关紧要——它们稳定运行,不需要 AI 辅助理解。
这个策略叫"按需建档",比"一次性全量文档化"要现实得多,也更符合存量项目的实际节奏。
如果不想走 onboard 流程
对于已经熟悉 SDD 流程、只是想快速给存量代码库建立初始 spec 的情况,可以跳过 onboard,直接手写第一批主 spec 文件:
mkdir -p openspec/specs/account
touch openspec/specs/account/spec.md
然后用已有的业务知识填写,格式和 Delta Spec 类似,但不需要 ADDED/MODIFIED/REMOVED 区块——主 spec 直接写 Requirement 和 Scenario:
# Account Domain Specs
## Requirements
### Requirement: Account listing creation
The system MUST allow authenticated sellers to create account listings.
#### Scenario: Valid listing submission
- GIVEN an authenticated seller
- WHEN submitting account attributes (game_type, level, server, rare_items)
- THEN a listing is created with status PENDING_REVIEW
- AND the seller receives a listing ID
这份手写的主 spec 不需要完整,把最核心的几条 Requirement 写进去就够了。后续每次迭代的 Delta Spec 在它的基础上叠加,主 spec 会越来越完整。
Onboard 和手写主 spec 的选择标准很简单:如果你对 OpenSpec 的流程还不熟悉,走 onboard;如果你已经看完了前面几篇文章,直接手写主 spec 更快。两条路的终点是一样的——openspec/specs/ 里有了初始基础,后续的 SDD 流程可以正常运转。
强力辅助
/opsx:sync:保持 artifact 和代码同步
/opsx:sync 属于 expanded workflow 命令集。 它解决一个在 apply 过程中常见的漂移问题:实现过程中发现原来的设计有问题,直接改了代码,但 tasks.md 或 design.md 还没更新,导致 artifact 和代码不一致。
/opsx:sync account-auto-pricing
Sync 会扫描当前已实现的代码,对照 tasks.md 的勾选状态,找出"代码里已经有了但 tasks.md 没有勾选的"以及"tasks.md 里勾选了但代码里找不到对应实现的"两类不一致,输出一份同步建议报告,然后让你确认是否更新。
典型使用场景是在 apply 执行到一半时,发现某个 task 的实现比预期复杂,拆成了两个函数而不是一个,导致 tasks.md 里的描述已经不准确了。sync 可以把实际实现状态重新反映到 artifact 里,让 verify 有准确的基准可以检查。
/opsx:bulk-archive 批量归档多个已完成 change
当并行推进了多个 change,都完成了 verify,需要一次性归档时
/opsx:bulk-archive
Bulk-archive 会先列出所有已完成的 change,验证各自的 specs 是否存在冲突,如果多个 change 同时修改了同一个域的 spec,会检测冲突并给出合并顺序建议,确认后再依次归档。
Found 3 completed changes:
- account-auto-pricing (9/9 tasks complete)
- order-refund-flow (6/6 tasks complete)
- search-filter-v2 (4/4 tasks complete)
Checking for spec conflicts...
⚠ account-auto-pricing 和 search-filter-v2 都涉及 specs/account/
Inspecting to resolve...
Will merge in chronological order:
1. account-auto-pricing (created 2026-04-01)
2. search-filter-v2 (created 2026-04-03)
3. order-refund-flow (no conflicts)
Archive all 3? [Y/n]
确认后依次归档,每个 change 的 Delta Spec 按顺序合并进对应的主 spec,保证合并结果的确定性。