ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

【OpenSpec 实操】把模糊需求一步步细化成可执行规范

【OpenSpec 实操】把模糊需求一步步细化成可执行规范

很多人第一次接触 OpenSpec,会误以为它适合“需求已经很清楚”的项目。其实恰恰相反,它最有价值的场景之一,就是你只有一个模糊目标,却还不知道系统到底该怎么做。
这时候,OpenSpec 不是要求你一开始就写出完美 spec,而是帮你把“模糊问题”一步步压缩成“可验证行为”。

先理解一个误区

很多项目失败,不是因为没人写需求,而是因为一开始就把“想法”当成了“需求”,又把“需求”当成了“实现方案”。
比如一句话:“做一个审批系统。”这其实什么都没说清楚。谁发起,谁审批,驳回后怎么办,通知谁,异常怎么处理,全都还是空白。

OpenSpec 的作用,不是替你凭空补完这些细节,而是给你一个结构,让你有地方承认“不确定”,并把这些不确定逐步消化掉。

OpenSpec 在这个场景里的角色

如果一句话概括:

  • proposal 用来承认你现在知道什么、不知道什么。
  • spec 用来定义系统必须如何表现。
  • design 用来解释准备如何实现。
  • tasks 用来把事情拆成可以执行的步骤。

所以,OpenSpec 不是一份文档,而是一套“从模糊到清晰”的工作流。

最常见的问题

当一个需求刚出现时,很多人会卡在这里:

  • 业务目标模糊。
  • 用户场景不完整。
  • 异常情况没想过。
  • 规则边界不明确。
  • 技术方案也没谱。

这时如果直接让 AI 写代码,结果往往是“看起来能跑,但和真正要的东西不一致”。
因为 AI 最擅长补全,而你最怕的恰恰是它在你没定义清楚时替你做了错误补全。

所以,第一原则不是“赶紧实现”,而是“先把错误自由度压下去”。

Skill 1:先写问题,不急着写答案

当你还不清楚怎么做时,第一步不要写 spec,先写一个最小 proposal。

你可以用下面这个模板:

## Why 我们要解决什么问题? ## Goal 这一期最小目标是什么? ## In Scope 这次明确要做什么? ## Out of Scope 这次明确不做什么? ## Open Questions 还有哪些关键问题没想清楚?

比如你收到一个需求:
“做一个请假审批能力。”

不要马上进入实现,先写:

## Why 员工请假目前靠线下沟通,流程不可追踪,统计困难。 ## Goal 实现最小可用的线上请假审批流程。 ## In Scope 员工提交请假申请; 主管审批; 审批结果通知员工。 ## Out of Scope 暂不支持转签、加签、抄送、销假。 ## Open Questions 超过几天是否需要二级审批? 驳回后是否允许修改重提? 通知方式是站内信还是邮件?

这一步非常关键,因为它把“没想清楚”从脑子里拿到了文档里。
一旦未知被列出来,需求就开始变得可讨论。

Skill 2:不要问“需求够不够细”,要问“能不能验证”

很多人写需求时会问:
“这够不够细?”
其实更有用的问题是:
“别人能不能根据这段话判断系统是否做对了?”

这就是 OpenSpec 的核心转折点:从描述想法,转向描述行为。

比如:

不好:

系统支持请假审批。

这个说法太空。
你根本无法据此判断系统做得对不对。

更好:

### Requirement: Submit Leave Request 系统 SHALL 允许员工提交请假申请。 #### Scenario: 提交成功 - WHEN 员工填写请假日期和原因并提交 - THEN 系统创建一条请假记录 - AND 状态为 PENDING_APPROVAL

为什么这个更好?
因为它已经可以验收了。你可以看结果、测状态、验证流程。

所以,需求细化的本质不是“写得更长”,而是“写得更可验证”。

Skill 3:用场景把细节逼出来

如果你不知道还缺什么,不要发呆,直接写场景。

最少先写三类场景:

  • 成功场景。
  • 失败场景。
  • 边界场景。

继续用请假审批举例。

成功场景

#### Scenario: 提交成功 - WHEN 员工填写完整信息并提交 - THEN 系统创建请假单 - AND 状态为 PENDING_MANAGER_APPROVAL

失败场景

#### Scenario: 缺少原因 - WHEN 员工未填写请假原因就提交 - THEN 系统拒绝提交 - AND 提示原因不能为空

边界场景

#### Scenario: 超过三天 - WHEN 员工提交超过 3 天的请假 - THEN 系统在主管同意后进入二级审批

你会发现,一旦你开始写场景,需求细节会自动浮现出来:

  • 原因是否必填?
  • 3 天是自然日还是工作日?
  • 谁是二级审批人?
  • 二级审批通过后状态是什么?
  • 驳回时是否必须填写理由?

也就是说,细节很多时候不是“凭空想出来”的,而是“在写场景时暴露出来”的。

Skill 4:区分 spec 和 design

这是很多人用 OpenSpec 时最容易混乱的地方。

spec 管什么

spec 管的是:

  • 系统行为。
  • 业务规则。
  • 权限约束。
  • 状态变化。
  • 验收条件。

例如:

  • 超过 3 天需要二级审批。
  • 驳回时必须填写原因。
  • 审批完成后通知申请人。

这些都应写进 spec。

design 管什么

design 管的是:

  • 状态机怎么设计。
  • 用几张表。
  • 审批链怎么查。
  • 通知通过什么机制发送。
  • 如何做幂等与补偿。

例如:

  • 使用 leave_requests 和 approval_records 两张表。
  • 审批流由状态机驱动。
  • 通知走异步消息队列。
  • 主管关系从组织架构服务实时查询。

这些更适合写到 design。

一句话区分:

  • spec:系统应该怎么表现。
  • design:系统准备怎么实现。

当你不清楚需求时,先别急着做 design。
因为你连“应该怎么表现”都没定,技术方案很容易提前跑偏。

Skill 5:复杂需求不要写成一个大块

很多需求之所以越写越乱,是因为试图用一份大文档把所有问题一次说完。
OpenSpec 更好的方法是拆分。

还是请假系统,可以拆成这些 Requirement:

  • Submit Leave Request
  • Manager Approval
  • Department Approval
  • Rejection Handling
  • Notification

每个 Requirement 下再写自己的 Scenario。
这样你不会面对一坨“审批系统需求说明”,而是在处理一组可管理的行为单元。

这对 AI 也非常重要。
因为 AI 对局部、明确、结构化的约束响应得更稳定,对大段模糊描述的理解则更容易漂移。

Skill 6:允许“带问号的规范”存在

很多人卡住,是因为总觉得“没想清楚就不能写”。
其实恰恰应该反过来:因为没想清楚,所以更要写。

你可以在 proposal 或 design 里显式保留未决项:

## Open Questions - 请假时长计算按自然日还是工作日? - 驳回后是否允许修改原单重提? - 二级审批是否需要按部门配置?

这不是不专业,而是专业。
因为你把风险和认知空洞前置暴露了,而不是把它们留给后续实现阶段爆炸。

Skill 7:从“需求描述”升级到“验收语言”

如果你想让 OpenSpec 真正落地,最关键的一步是:
不要只写“系统要支持什么”,而要写“做到什么算完成”。

比如:

普通写法:

支持消息通知。

更好的写法:

### Requirement: Approval Notification 系统 SHALL 在审批结束后通知申请人。 #### Scenario: 审批通过通知 - WHEN 请假单状态变为 APPROVED - THEN 系统向申请人发送审批通过通知 #### Scenario: 审批驳回通知 - WHEN 请假单状态变为 REJECTED - THEN 系统向申请人发送驳回通知 - AND 通知中包含驳回原因

这种写法的价值在于:

  • 产品能看懂。
  • 开发能实现。
  • 测试能验收。
  • AI 不容易自由发挥。

这就是 OpenSpec 真正的协作价值。

一个可直接套用的实操流程

当你拿到一个模糊需求时,可以直接按下面这套走。

第一步:写最小 proposal

目标是把模糊问题装进结构里,不追求完整,只追求边界清晰。

模板:

## Why ## Goal ## In Scope ## Out of Scope ## Open Questions

第二步:列核心动作

问自己:用户和系统之间最核心的动作有哪些?

例如请假审批:

  • 提交申请
  • 审批申请
  • 驳回申请
  • 通知结果

每个动作先单独成一个 Requirement。

第三步:每个动作写 3 个场景

至少写:

  • 正常成功。
  • 常见失败。
  • 一个边界情况。

这是最容易逼出需求细节的步骤。

第四步:把实现细节移到 design

一旦你开始写:

  • 数据库结构
  • 服务边界
  • 状态机
  • 消息机制
  • 重试与补偿

说明你进入 design 了,不要再混在 spec 里。

第五步:拆任务

把已经明确的内容拆成 tasks:

- [ ] 建请假单表 - [ ] 新增提交申请接口 - [ ] 增加主管审批接口 - [ ] 增加驳回原因校验 - [ ] 实现审批完成通知 - [ ] 编写接口测试

这样需求才真正开始可执行。

一个最小完整示例

下面给你一个非常小的完整例子。

proposal.md

## Why 员工请假流程目前依赖线下沟通,无法追踪审批状态。 ## Goal 上线最小可用的请假审批功能。 ## In Scope 员工提交请假; 主管审批; 结果通知。 ## Out of Scope 不支持转签、加签、抄送。 ## Open Questions 超过几天需要二审? 驳回后是否允许修改后重提?

spec.md

### Requirement: Submit Leave Request 系统 SHALL 支持员工提交请假申请。 #### Scenario: 提交成功 - WHEN 员工填写请假日期和原因并提交 - THEN 系统创建请假单 - AND 状态为 PENDING_MANAGER_APPROVAL #### Scenario: 缺少原因 - WHEN 员工未填写原因提交 - THEN 系统拒绝提交 - AND 返回错误提示 ### Requirement: Manager Approval 系统 SHALL 支持直属主管审批请假申请。 #### Scenario: 审批通过 - WHEN 主管批准申请 - THEN 系统将状态更新为 APPROVED #### Scenario: 审批驳回 - WHEN 主管驳回申请 - THEN 系统将状态更新为 REJECTED - AND 记录驳回原因

design.md

## Data Model leave_requests approval_records ## Decisions 审批状态使用状态机管理。 通知采用异步发送。 驳回原因字段为必填。

tasks.md

- [ ] 创建请假单表 - [ ] 创建审批记录表 - [ ] 开发提交申请接口 - [ ] 开发主管审批接口 - [ ] 增加驳回原因校验 - [ ] 增加审批结果通知 - [ ] 编写测试

这个例子不复杂,但已经展示出一个重要原则:
你不需要一开始什么都想清楚,才能开始写 OpenSpec。
你可以在写的过程中,把模糊的需求逐层压实。

最后的方法论

如果把这篇文章压缩成一句工作原则,就是:

OpenSpec 不是用来记录“我已经想清楚的需求”,而是用来帮助我把“还没想清楚的需求”逐步想清楚。

真正实操时,记住这 4 句话就够了:

  • 先写问题,不急着写方案。
  • 先写行为,不急着写实现。
  • 先写场景,用场景逼出细节。
  • 把未知显式列出来,而不是藏在脑子里。

可复制模板

你可以把下面这段直接当作一个 skill 使用。

模糊需求细化模板

# 1. Proposal ## Why 要解决什么问题? ## Goal 本期最小目标是什么? ## In Scope 这次确定做什么? ## Out of Scope 这次明确不做什么? ## Open Questions 还有哪些关键问题没想清楚? # 2. Spec ### Requirement: [核心动作1] 系统 SHALL ... #### Scenario: 成功 - WHEN ... - THEN ... #### Scenario: 失败 - WHEN ... - THEN ... #### Scenario: 边界 - WHEN ... - THEN ... ### Requirement: [核心动作2] 系统 SHALL ... # 3. Design ## Data Model ## State Machine ## API Design ## Risks ## Decisions # 4. Tasks - [ ] ... - [ ] ... - [ ] ...

适合放进项目的说明

你也可以把下面这段写进团队规范里:

当需求不清晰时,不直接进入编码。
先用 proposal 明确目标、范围和未决问题;
再用 spec 定义行为和场景;
复杂实现细节进入 design;
最后通过 tasks 驱动实现。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进