【译】Spec 驱动开发的问题在哪?

Spec 驱动开发(Spec-Driven Development, SDD)通常会失败,原因和所有“文档优先”的举措失败的原因一样:唯一值得 100% 信任的文档只有代码本身。
设计文档、更新日志、README、架构图、入职 Wiki——所有这些几乎在写完的那一刻就已经过时了。
保持书面文档与不断变化的系统同步,需要持续的成本。而工程师天生适合“爆发式”工作:写文档,发布功能,然后继续下一个任务。更新文档是一项不可见的工作,它在任何给定的一天都会与其他所有事情竞争优先级,而且几乎每次都会输掉。
我们尝试过流程,尝试过工具,尝试过将其作为团队价值观。但都没用,因为我们一直在要求人类做一件人类本身就不擅长坚持的事情。
这就是 Spec 驱动开发通常失败的地方。这个想法听起来很美好:在使用 AI 编程智能体(Coding Agents)时,先写下你想要什么,然后再让它们去执行。这显然比把提示词粘贴到聊天窗口里祈祷好运要强。
但是,Spec(规格说明书)也是一种文档。 我们刚刚已经确认了文档的命运。
两者的区别在于风险。一份过时的设计文档会误导下一个读它的工程师。而一份过时的 Spec 会误导那些“不懂事”的 AI 智能体。它们会自信地执行一个不再符合现实的计划,并且不会标记出任何问题。
这也是为什么我们在构建 Intent 时,一直在思考的问题:如果 Spec 不需要你去维护呢?如果它能自己维护自己呢?
我们的方案是这样的:
Spec 既不是人类的产物,也不是智能体的产物。双方都从它读取,也都向它写入。
- 你描述你想构建什么。
- 一个协调智能体(Coordinator Agent)会草拟一份 Spec,并将其分解为任务。
- 你查看它,编辑它,在任何代码运行之前批准它。
- 一旦智能体开始工作,它们会写回更新:它们发现了什么,什么发生了变化,遇到了哪些计划中没有的限制。
- 你可以随时暂停,重写部分 Spec,智能体将从新的状态继续工作。
试想一下,当你把任务交给一个优秀的初级工程师时会发生什么。你给他们一个 Ticket,他们去工作。当他们发现 API 不支持 Ticket 假设的分页方式时,他们会自己更新 Ticket。他们不会等你发现不对劲。他们不会直接构建错误的东西。他们会回来说:“这个假设是错的,这是我做的替代方案,原因如下。” 你审查他们的更新,然后批准或驳回。
这就是我们想要的开发者与 Spec 之间的关系。Ticket 保持诚实,因为双方都在维护它。
这个“初级工程师”的类比其实比你想象的更深。一个好的初级工程师不会叙述每一行代码。他们会展示改变方向的决策:“我发现代码库里已经有一个现成的 Auth Context,所以我接入了那个,而不是新建一个。” 这就是信号。这也是你希望从智能体那里得到的。
正确把握这种粒度,实际上是系统中真正有趣的设计问题之一。太细了,Spec 就会变成噪音,你学会了忽略它。太粗了,你就又回到了猜测发生了什么的境地。
一个任务实际上看起来是这样的:
你写道:“在设置页面添加一个暗黑模式切换开关,并遵循系统偏好。”
协调智能体读取你的代码库,草拟了一份 Spec,包含三个子任务:添加切换组件,将其连接到偏好存储,更新 CSS 变量。
你扫描了一下,发现它漏掉了“跨会话持久化选择”这一点,于是你加了一行。
你批准了。
智能体开始工作。
十五分钟后,其中一个智能体更新了 Spec:“在代码库中发现现有的主题上下文提供程序(Theme Context Provider)。已接入该提供程序,代替创建新的存储。”
你审查代码变更(按智能体和任务清晰分组)。
现在的 Spec 反映的是实际构建的内容,而不是最初计划的内容。而且没有人需要刻意去更新它。
软件开发中每一个“文档优先”的举措失败的原因都是相同的:它要求开发人员做持续的维护工作,这种工作没人看得到,也没人奖励。
除非智能体承担它们那部分的维护工作,否则 SDD 也会因同样的原因失败。
如果智能体可以写代码,它们就可以更新计划。
让它们去做吧。

