为什么 Spec 不是终点,而只是中间产物?软件研发正在从 Spec 驱动,走向表示驱动(RDD)

企业研发 AI 自动化软件研发研发流程表示驱动 RDD
2026-03-25

当执行不再稀缺时,软件研发的核心问题不再是“如何实现”,而是“如何让任务被系统准确表达”。

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:Spec 需要解释才能执行,但无法被系统直接执行
图1: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 不是一开始就存在的,而是在复杂度上升时逐渐显式化的。

图2:只有在“高复杂度 + 难表达”的场景下,Representation 才成为必要
图2:只有在“高复杂度 + 难表达”的场景下,Representation 才成为必要

一个简单需求,为什么会不稳定?#

在实践中,有一个看起来非常简单的需求:
_在订单列表页中,新增一个筛选条件「待发货」,
_点击后,仅展示状态为 _waiting_ 的订单。

最开始,我们尝试用一种非常直接的方式来执行:

latex
在订单列表页中新增一个筛选条件「待发货」,
点击后展示状态为 waiting 的订单。

在单次执行时,结果看起来是“正确的”。

但当我们开始多次执行,或者在不同上下文下运行时,会逐渐出现一些不一致:

  • 有时筛选条件被加在错误的位置
  • 有时默认选中状态不一致
  • 有时列表不会自动刷新
  • 有时筛选逻辑写对了,但 UI 没有联动

这些问题有一个共同特点:
代码“看起来大致正确”,但行为不稳定。

一开始,很容易把这些问题归因到模型或提示词。

但在对比多个 case 之后,会发现一个更本质的原因:
任务本身,并没有被完整表达出来。

从“描述任务”,到“表达任务”#

在这个 case 中,原始描述中其实缺少了几类关键信息:

边界(scope)

  • 筛选条件应该加在列表顶部还是已有筛选区域中?
  • 是否复用现有筛选组件?

约束(constraints)

  • 是否允许多选?
  • 是否会影响其他筛选条件?

完成标准(acceptance)

  • 点击后列表是否需要立即刷新?
  • 是否需要展示空状态组件?
  • 默认进入页面时是否选中?

当这些信息没有被明确表达时:
系统只能“猜测”任务,而不是“执行”任务。

一个最小的结构变化#

在后续的尝试中,我们没有一开始引入完整的 Task IR,
而是只补充了最关键的三类信息:

latex
scope:
- 订单列表页筛选区域
- 使用现有筛选组件

constraints:
- 单选,不与其他筛选条件叠加
- 保持现有筛选逻辑不变

acceptance:
- 点击「待发货」后,仅展示 status=waiting 的订单
- 列表立即刷新
- 若结果为空,展示空状态组件

当这些结构被补齐之后,结果开始变得明显不同:

  • 多次执行结果基本一致
  • UI 行为与预期对齐
  • 不再需要反复补 prompt

这时会出现一个很直观的变化:
**问题不再是“模型能不能写出来”,
**而是“任务有没有被表达完整”。

一个很小,但重要的变化#

这个 case 并不复杂,但它揭示了一件更普遍的事情:
**即使是简单任务,一旦开始要求“稳定执行”,
**就需要从“描述任务”,走向“表达任务”。

也正是在这样的过程中,
Task IR 并不是一开始就被引入的,
而是随着问题的出现,被一点点“逼出来”的。

系统不会理解“差不多”,它只会执行“被明确表达的部分”。

图3:任务复杂度越高,执行方式越需要从 Prompt 走向 Representation
图3:任务复杂度越高,执行方式越需要从 Prompt 走向 Representation

七、从 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 变得更加结构化,
只要执行仍然依赖解释过程,
它就无法成为系统级的可执行结构。

图4:Spec 产生多种可能路径,而 Representation 将执行收敛为单一路径
图4:Spec 产生多种可能路径,而 Representation 将执行收敛为单一路径

八、这意味着什么?#

当研发开始从 Spec 驱动走向表示驱动,会带来几件非常实际的变化:

1. 任务表达成为核心能力#

不再是:
“会不会写代码”

而是:
“能不能把任务表达成系统可执行的结构”

2. 研发流程开始重构#

从:
需求 → 开发 → 测试

变成:
理解 → 表示 → 执行 → 验证

3. Agent / Skill / 自动化能力的基础发生变化#

所有这些能力,最终都依赖:
是否存在稳定的“表示层”

九、结语#

当执行者发生变化时,软件研发并不会只是“更快”。
它会开始改变结构。

过去,我们关注的是:
如何更高效地实现功能。

而现在,问题正在变成:
如何让任务被系统准确地表达。

Spec 解决的是“人如何理解任务”。
但当系统开始执行时,我们需要的是另一种东西。
一种可以被表达、被执行、也可以被验证的结构。
当这种结构逐渐出现时,软件研发也开始从“被使用”,走向“被运行”。

Spec 描述任务,解决理解问题;
Representation 让任务成为系统的一部分,解决执行问题。

加载中...
加载评论中...