为什么 Spec 不是终点,而只是中间产物?软件研发正在从 Spec 驱动,走向表示驱动(RDD)
当执行不再稀缺时,软件研发的核心问题不再是“如何实现”,而是“如何让任务被系统准确表达”。
Spec 并不能解决这个问题,它只是一个开始。
我们已经可以用一句话生成代码。
但在真实项目中,
这件事往往不稳定,甚至不可复现。
问题并不在模型能力,
而在于我们如何表达任务。
一、我们以为问题已经被解决了#
如果从今天的工具能力出发,软件研发看起来已经进入了一个非常“顺滑”的阶段。
有 PRD,有设计稿,有接口定义,有代码上下文。
把这些信息整理成一份 spec,交给 AI,就可以生成代码。
很多团队已经开始这样尝试:
- 写一份更清晰的 spec
- 喂给 Coding Agent
- 等待代码生成
看起来,问题已经被解决了。
甚至进一步,会有人得出一个结论:
只要 spec 写得足够好,AI 就可以稳定完成研发任务。
但在真实项目中,事情并没有这么顺利。
同一份 spec,多次执行结果并不一致。
有些逻辑会遗漏,有些边界会处理不完整。
往往需要不断补充 prompt、反复调整表达,才能逐渐接近预期结果。
这时候,很容易把问题归因到:
- 模型能力不够
- 上下文不够完整
- 提示词写得不够好
但如果观察足够多的实际 case,会慢慢意识到:
问题并不在“AI 能不能写代码”,
而在“任务是否被稳定地表达出来”。
二、问题不在执行,而在表达#
当 AI 还只是辅助工具时,这个问题并不明显。
因为人始终在“执行链路”中:
- spec 有歧义 → 人会补充理解
- 行为不明确 → 人会做决策
- 边界缺失 → 人会兜底
也就是说:
人,本身就是一个“补全表达”的系统。
但当执行开始逐步交给 Agent / 系统时,这个前提开始失效:
- 系统不会自动补全上下文
- 系统无法“理解意图中的模糊部分”
- 系统需要明确的边界与条件
这时候,问题发生了转移:
执行能力不再是瓶颈,
表达能力开始成为瓶颈。
三、Spec 到底在解决什么问题?#
要理解这个变化,需要先把一个问题说清楚:
Spec,本质上是什么?
Spec 在不同语境下含义并不完全一致。
在一些场景中,它指的是协议或标准(例如 API spec);
在软件研发中,它也可以指需求规格说明。
但在 AI Coding 的语境下,Spec 更常被用来指:
一种面向人和模型理解的任务描述方式。
在今天的实践中,Spec 也在发生变化。
像 spec-kit 这样的尝试,正在让 Spec 变得更加结构化,
并可以被 Agent 直接使用,从而参与执行过程。
也就是说,Spec 已经不再只是“文档”,
而是一种可以参与执行链路的表达形式。
但这里有一个关键区别:
参与执行,并不等于可以被系统直接执行。
它的设计目标,是约束任务的表达方式,
让人和 Agent 能在同一语境下理解,并通过解释过程引导执行任务。
但这也意味着:
- 它允许模糊
- 它依赖上下文
- 它默认有人参与解释
而这在“人参与执行”的阶段没有问题。
但当执行者变成系统时,就会出现一个断层:
Spec 并不是为“系统执行”设计的。
也就是说,即便如此,Spec 仍然没有消除一个关键特征:
它依然允许解释空间的存在。
四、当执行交给系统时,会发生什么?#
当任务从“人参与执行”转向“系统执行”时,有三个变化会变得非常明显:
1. 模糊性不再被容忍#
例如:
“在订单列表页增加一个筛选条件”
对于人来说,这句话是可以被补全的:
- 筛选项是什么
- 默认状态是什么
- 切换后如何影响列表
但对于系统来说:
这是一段不完整的表达。
2. 上下文不再自动存在#
人可以结合:
- 过往经验
- 当前页面结构
- 业务常识
去理解任务。
但系统需要的是:
显式提供的上下文。
3. 验证标准必须明确#
人可以“感觉差不多了”。
但系统必须知道:
- 什么算完成
- 什么算错误
- 是否需要重试
这三个变化,本质指向同一件事:
系统需要的不是“描述”,而是“可执行的表示”。
五、什么是“表示”?#
这里的“表示”,不是指某种具体格式(比如 JSON),而是一种更本质的东西:
一种可以被系统理解、执行,并且可验证的任务表达方式。
在实践中,一个“可执行的表示”通常需要具备三个最基本的要素:
1. 明确边界(scope)#
- 改哪些文件
- 影响哪些模块
- 不应该触碰什么
2. 明确约束(constraints)#
- 必须遵循哪些规则
- 不能破坏哪些已有逻辑
- 需要符合哪些规范
3. 明确完成标准(acceptance)#
- 什么情况下算完成
- 页面或行为应达到什么状态
- 是否需要验证结果
当这些信息被补齐后,任务才开始具备一个重要特征:
它不再依赖“人来补全”,而可以被系统直接执行。
在我们的实践中,这种结构被进一步沉淀为:
Task IR(任务中间表示)
六、为什么不是所有任务都需要 Task IR?#
这里有一个非常重要的观察。
在实际验证中,我们发现:
并不是所有任务,一开始都需要完整的 Task IR。
一类任务:可以直接执行#
例如:
- 给 select 增加一个选项
- 修改按钮颜色
这些任务的特点是:
- 影响范围单一
- 没有复杂逻辑
- 不需要额外验证链路
在这种情况下:
一句话 + Agent,就可以完成。
一类任务:需要“补一点结构”#
例如:
- 页面增加筛选逻辑
- 列表根据条件切换数据
这类任务开始出现:
- 状态变化
- 行为差异
- 基本验证需求
这时,仅靠自然语言就开始不稳定。
通常需要补充一些关键信息:
- scope
- constraints
- acceptance
一类任务:必须完整结构化#
例如:
- 跨页面改造
- 多任务组合执行
- 需要重复验证的需求
在这种情况下:
必须引入完整的 Task IR,才能保证执行稳定性。
这也带来一个更重要的结论:
IR 不是一开始就存在的,而是在复杂度上升时逐渐显式化的。
一个简单需求,为什么会不稳定?#
在实践中,有一个看起来非常简单的需求:
_在订单列表页中,新增一个筛选条件「待发货」,
_点击后,仅展示状态为 _waiting_ 的订单。
最开始,我们尝试用一种非常直接的方式来执行:
在单次执行时,结果看起来是“正确的”。
但当我们开始多次执行,或者在不同上下文下运行时,会逐渐出现一些不一致:
- 有时筛选条件被加在错误的位置
- 有时默认选中状态不一致
- 有时列表不会自动刷新
- 有时筛选逻辑写对了,但 UI 没有联动
这些问题有一个共同特点:
代码“看起来大致正确”,但行为不稳定。
一开始,很容易把这些问题归因到模型或提示词。
但在对比多个 case 之后,会发现一个更本质的原因:
任务本身,并没有被完整表达出来。
从“描述任务”,到“表达任务”#
在这个 case 中,原始描述中其实缺少了几类关键信息:
边界(scope)
- 筛选条件应该加在列表顶部还是已有筛选区域中?
- 是否复用现有筛选组件?
约束(constraints)
- 是否允许多选?
- 是否会影响其他筛选条件?
完成标准(acceptance)
- 点击后列表是否需要立即刷新?
- 是否需要展示空状态组件?
- 默认进入页面时是否选中?
当这些信息没有被明确表达时:
系统只能“猜测”任务,而不是“执行”任务。
一个最小的结构变化#
在后续的尝试中,我们没有一开始引入完整的 Task IR,
而是只补充了最关键的三类信息:
当这些结构被补齐之后,结果开始变得明显不同:
- 多次执行结果基本一致
- UI 行为与预期对齐
- 不再需要反复补 prompt
这时会出现一个很直观的变化:
**问题不再是“模型能不能写出来”,
**而是“任务有没有被表达完整”。
一个很小,但重要的变化#
这个 case 并不复杂,但它揭示了一件更普遍的事情:
**即使是简单任务,一旦开始要求“稳定执行”,
**就需要从“描述任务”,走向“表达任务”。
也正是在这样的过程中,
Task IR 并不是一开始就被引入的,
而是随着问题的出现,被一点点“逼出来”的。
系统不会理解“差不多”,它只会执行“被明确表达的部分”。
七、从 Spec 驱动,到表示驱动(RDD)#
如果把这些变化放在一起看,会发现一条非常清晰的迁移路径。
过去:Spec-Driven Development#
过去的软件研发,是 Spec-Driven Development:
Spec → AI → Code
Spec 是核心输入,AI 负责执行。
现在:Representation-Driven Development(RDD)#
而现在,系统开始走向另一种结构:
Input → Representation → Execution → Validation
- 输入来自多源(PRD / Design / Repo)
- 中间形成可执行的表示(Representation)
- 系统执行任务
- 自动化验证结果
但真正的变化,并不只是流程的增加。
而在于:
Spec 不再是终点,而只是表示的一种投影。
换句话说:
- Spec 是“面向理解与引导执行的表达”
- Representation 是“给系统执行的”
Spec 的流行,是因为我们在用更好的方式“描述任务”;
但 Representation 的出现,是因为我们开始需要:
让系统真正执行任务。
RDD 并不是对 Spec 的增强,
而是将“描述任务”转变为“构建可执行结构”。
即使 Spec 变得更加结构化,
只要执行仍然依赖解释过程,
它就无法成为系统级的可执行结构。
八、这意味着什么?#
当研发开始从 Spec 驱动走向表示驱动,会带来几件非常实际的变化:
1. 任务表达成为核心能力#
不再是:
“会不会写代码”
而是:
“能不能把任务表达成系统可执行的结构”
2. 研发流程开始重构#
从:
需求 → 开发 → 测试
变成:
理解 → 表示 → 执行 → 验证
3. Agent / Skill / 自动化能力的基础发生变化#
所有这些能力,最终都依赖:
是否存在稳定的“表示层”
九、结语#
当执行者发生变化时,软件研发并不会只是“更快”。
它会开始改变结构。
过去,我们关注的是:
如何更高效地实现功能。
而现在,问题正在变成:
如何让任务被系统准确地表达。
Spec 解决的是“人如何理解任务”。
但当系统开始执行时,我们需要的是另一种东西。
一种可以被表达、被执行、也可以被验证的结构。
当这种结构逐渐出现时,软件研发也开始从“被使用”,走向“被运行”。
Spec 描述任务,解决理解问题;
Representation 让任务成为系统的一部分,解决执行问题。