AI 时代下,需求文档的黄金模式:Spec

0 评论 345 浏览 1 收藏 29 分钟

一位不懂代码的产品经理,用175天独立搭建起覆盖Web端、运营后台、数据采集、自动写作、短视频与支付会员的完整系统。他复盘了从失败到成功的需求开发模式,提出Spec三份文档(需求、设计、任务)缺一不可,并强调强制力必须落在机器上。本文深度拆解AI时代需求可判定性的核心瓶颈与Agent工具链的实战经验。

一个不懂代码的产品经理,用 175 天做出一套覆盖 Web 端、运营后台、后端接口、数据采集、自动写作、自动制作短视频与支付会员的系统。并在此过程中探索出新时代的需求开发模式:Spec,摸索出一套完整的agent工具链。

结论有四:瓶颈在需求的可判定性,不在代码产能;需求、设计、任务三份文档各回答一个不可替代的问题,缺一即失效;AI 读代码读不出人当时的设计意图,一套文档系统是它不走偏的前提;强制力必须落在机器上,落在文档里的规则等于没有规则。

一、六个月,我做出了什么

1.1 系统构成

后三行不依赖算法,只是业务规则加流程编排——AI 最擅长的部分。短视频系统还留着伏笔:每期框架固定,只换一个配置文件;脚本按「时长、画面、口播、屏上文字」四列写成表格,确认后才制作。四列脚本就是一份可验收的需求,当时我还不这么叫它。

1.2 三组数字

二、面向 AI 写需求:一条失败路径的复盘

2.1 起点只是一个点子

每个交易日收盘后,我要手工翻十几个页面,把涨停梯队、板块强弱、资金流向抄进笔记,约两小时。我想压到十分钟。

第一版只解决这一件事,两条约束。功能收敛:只做一屏看完今天的大盘,不做选股、回测、交易,功能一多必然半成品,而半成品没有用户,包括你自己。骨架留口子:前端不是页面,是面板注册表加布局引擎;后端不是几个接口,是一张表对应一个数据源、一个口径对应一处定义。

合起来是一句话:功能收敛在用户看得见的那个点,扩展性放在你看得见的骨架上。

4 月 28 日至 5 月 4 日,34 次提交,七次标题是面板增删或改版,零份需求文档。第一版是聊出来的。这没有错,第一版需要的是速度;错的是把这个习惯带进了第二个月。

2.2 技术选型:让 AI 交证据,而不是给建议

最常见的问法是「我想做一个股票看板,用什么技术栈」。这个问法必然失败:模型不知道你的约束与成本上限,也不知道自己哪一条查不到,只能返回一份不知哪一年的最佳实践清单。

有效的问法有三段:

这是我要做的五件事;

这是我能接受的部署与维护成本;

请逐个查这些候选的真实限制,给我一张对照表,并明确告诉我哪一条你查不到。

第三句是关键——把「我不知道」变成一个合法输出。

提问之后是实测:给每个候选写只读探针,在真实时段跑一段窗口,记录字段、单位、限流与异常形态,再与文档逐条对照。一个源文档三处不符,另一个首轮六处、累计八处。

由此定规:结论必须标类型,实测过标「已实测」,只读文档标「文档」,后者不得当事实用。它后来升格为需求规范的硬性要求:口径、公式、数量级必须用生产数据或实测核实,来源与日期写在旁边。

能被验证的选型才可信。「强烈推荐」却拿不出实测证据的,按猜测处理。

2.3 传统需求流程与它的五份产物

传统软件的工作流是一条串行链:

需求文档 → 设计稿 → 需求评审 → 技术评审 → 技术排期 → 开发 → 测试 → 上线。

它沉淀出五份产物,每份都有明确的读者:

链条成立有一个隐含前提:每一环的读者都是人。人能补全空白,能在不确定时开口问,能用常识拒绝荒谬的实现。

交给 AI,前提立刻失效。五种形态,全部来自真实记录。

  1. 边界未覆盖:只写正常情况,没写数据为空、停牌、跨日、开关关闭。实现只处理正常路径,异常要么报错,要么静默返回空。
  2. 功能点遗漏:一段话塞五件事,交付三件半。没有编号,无法逐条比对,甚至无法判定它错。
  3. 验收缺失:做完我说感觉不对,它改一版,我仍觉得不对。循环四轮,发现双方对「对」的定义不同。
  4. 口径未核实:「涨幅按前复权计算」——哪一种,谁定的,查过吗。更严重的一次:一个后台面板上线后数据恒为 0,需求默认「这张表有人写入」,而事实上没有生产者。表存在,不等于有数据。
  5. 异常无交代:接口失败时静默还是报错,没人写,于是静默失败了三个月。

同一个根因:这种文体不提供判据。散文能表达意图,回答不了「做到没有」,也回答不了「谁说了算」。

需求文档不是写给人看的说明,是写给执行者的合同。合同没有违约判定,就等于没有合同。

2.4 精简到三份,一份都不能再少

五份里,代码与测试用例不是文档,是结果。要设计的是另外三份的位置。

  1. 需求文档,回答要什么、怎样算做到。读者同时是人(评审)与 AI(实现),两者都必须能判定。
  2. 设计文档,回答怎么做。含交互设计(用户看到什么、操作后发生什么)与技术设计(数据从哪来、存在哪、接口什么形状)。合并成一份,因为二者常是同一个决定:一个面板能有什么交互,取决于它的数据从哪来。
  3. 开发任务文档,回答按什么顺序做、每步做完怎么验。它把设计切成可独立验收的单元,带编号与依赖。

还能再砍吗?逐一试。

  1. 去需求文档,只剩设计与任务:「为什么做、做到什么程度算完成」无处可查。AI 会按设计做出一个能跑的东西,但无人能判定它是否满足初衷。设计回答怎么做,不回答做什么。
  2. 去设计文档,只剩需求与任务:任务只能按需求条目机械切分,切出的单元之间没有共享决策,各自选一套方案,最后拼不起来。返工代价高于写一份设计。
  3. 去任务文档,只剩需求与设计:这是最常见的省法,也最贵。AI 会一次实现整份设计,你只能整体接受或整体打回,无法逐段验收;「哪些做完了」也失去载体。

三份各回答一个不可替代的问题:要什么、怎么做、做到哪算完。需求给判据,设计给方案,任务给进度。缺一份,闭环上就有一个环节没有产物,只能靠人的记忆兜住——而人的记忆,正是这套流程要替换掉的东西。

Kiro 的 Spec 就是这三份:requirements、design、tasks。它没有发明新结构,只是把这条已被验证的产物链做成了有阶段、有追溯的工程流程。

2.5 发现 Spec

发现过程是一次针对失败清单的检索。先问为什么 AI 写出来总差一点,得到规格驱动开发(Spec-Driven Development);再问主流方案各自强制了什么,得到一份关于 Kiro Spec 工作流的完整说明,从三份文档的职责到启动方式到执行模式,至今留在项目文档里;最后拿这些方案逐条比对失败清单——不看工具多强,看它能治哪个病。

比对之后,Spec 的最小结构是:

意图 + 判据 + 边界。

意图是一句话说清这次要改什么。判据是每条验收只有一个通过与否的判定,能给数值就给数值,必须写错误路径。边界是至少一条「不做什么」,以及会出事的那几个状态。

按这个定义,很多产物不算 Spec:

「先写需求,不许先写设计」反直觉,却是地基:一旦先想方案,需求就被方案裹挟——你会只写这个方案能满足的需求,把方案做不到的部分悄悄删掉。这条后来写进了规范第一段。

2.6 各家模式:一个坐标系

比排名更有用的,是两个轴。强制力:有没有人或机器在管,写了不执行会怎样。验证:有没有东西检验「代码真的实现了 Spec」。

主流方案放进去,绝大多数落在左下角:既无强制,也无验证。它们的本质是更好的模板。

(截至 2026 年 10 月的公开信息,星数与定价会变。)

另有一条路线在 2026 年初放弃持久 Spec,改把代码约定反向提炼成标准注入上下文。这不是退步,是另一个赌注:如果模型足够强,也许不需要持久文档,只需要持久标准。

我从 Trae 迁到 Kiro:Trae 的 Spec 要自己维护,工具不管评审与执行;Kiro 把 Spec 做成流程的一等公民,有阶段、有面板、有追溯,且自带结构约束逼我按顺序走。对不写代码的人,「被流程推着走」比「给我充分自由」有用——自由是负担,因为我缺少判断自由是否被滥用的能力。第三条理由在 2.7 展开。

2.7 Kiro 的产出形态

一份 Kiro Spec 正是 2.4 推出的三份:需求、设计、任务。需求用 EARS 句式写,设计写方案,任务带依赖与编号,且每条回指需求编号。

一份真实的需求文档,开头依次是简介(一句话说清做什么,并说明实现分四层)、术语表(逐条定义系统、面板外壳组件、默认布局常量)、然后是编号需求。术语表在写需求之前先把词固定下来,后面所有条款都引用它。歧义靠定义消除,不靠反复解释。

EARS 的价值不在整齐,在它强迫你说出触发条件:

<系统>应……

当<事件>时,<系统>应……

在<状态>期间,<系统>应……

如果<条件>,那么<系统>应……

第一行是能力,第二行是离散事件,第三行是持续状态,第四行是错误路径。不写触发条件的「验收」,等于没写。

三个直接收益:需求可判定,不再争论「对不对」,只检查某一条过没过;需求可追溯,漏掉哪个功能点,任务清单与需求编号对一遍就知道;执行有节奏,任务切成最小单元后模型一次只干一件,可以一件一件验收。

Kiro 真正教会我的不是「写三份文档」,是把一件事拆成能被逐个判定的最小单元。这个能力与工具无关。

2.8 但我还是离开了:四类缺陷

  1. 分类不够用:只有功能与缺陷两种 Spec。「改一个统计口径」「加一条 CI 检查」「重写一份规则文件」算什么?全塞进「功能」,档位虚高,写作者开始敷衍。
  2. 仪式成本过高:改五十行也要走三份文档。当流程成本高于收益,人不会反抗,人会绕过——直接在对话框里改,Spec 目录慢慢变成摆设。
  3. 完成状态不可信:面板上点「完成」很好看,但代码到底做没做,只有提交历史知道。面板上的勾不是状态的真相。
  4. 格式靠自觉,漂移无人拦:一个自动校验 Spec 格式的钩子,连续四次静默失效:匹配规则被过度转义,要求路径含字面反斜杠,从未匹配;内联脚本被 shell 吃掉,反斜杠被吞、反引号被当作命令替换;取路径用错字段名,每次报错退出,而宿主把非零退出码当作静默失败;判据是手写的重新实现,从未与权威实现差分——一次对照就查出十几份「权威判错、脚本判过」。

四次失效,一次都没有报警。护栏存在,不等于护栏生效。

另有三颗小钉子:Spec 锁在工具目录,换工具即断;按额度计费,写得越多越贵;写入大文件会被连接重置掐断。

这不是 Kiro 做得差,而是通用工具与具体项目之间必然存在的缝。缝只能由项目自己补。2026 年 9 月,我把整套东西搬到 Claude,把踩过的每一个坑写成一条一条的规则。

三、我重建的这套模式

2026 年 9 月 23 日,新体系上线。此后一个月,27 套新格式 spec、206 张施工单跑在这套规则上。规则本身 312 行,纯 markdown,任何 agent 与人都按同一份写。

3.1 六条原则

重建这套模式为三件事:让 AI 少漏功能;让需求不必都付三份文档的成本;让每一次代码改动都先读 spec 再动手——不了解当初的决定,改出来的东西一定走偏。

Kiro 的问题不在要求三份文档,而在要求所有事情都付这份成本;也不在格式本身,而在格式之外没有东西保证需求写全了,更没有东西保证后来的人会去读它。六条原则围绕这三点。

  1. 分类先于流程:不同性质的事归口不同,需求才不会被塞进不合身的模板里丢掉细节。分类错了,后面所有档位都是错的。
  2. 成本随风险走:五十行的改动不该付三份文档的代价。流程成本高于收益时,人不会反抗,人会绕过——绕过之后,连那三份文档也没有了。
  3. 先读后改:动任何一处代码前,先读它当初的 spec 与守卫测试。代码只说明现在是什么,spec 说明为什么是这样。跳过这一步,改出来的东西就算能跑,也未必是当初要的。
  4. 验收先于实现:每条验收只有一个通过与否的判定,编号可追,能给数值就给数值,必须写错误路径。AI 最典型的失效不是做错,是少做,而少做只能靠逐条比对发现。
  5. 状态只有一个真源:功能点有没有做完,看复选框与提交历史,不看面板。面板上的勾是自述,提交是事实。
  6. 强制力落在机器上:写在文档里的规则是愿望,写进 pre-commit 的规则才是规则。人能忘,脚本不会。

3.2 第一步:四类分流

判据依次问三句:改的是研发体系吗?原本的行为是错的吗?用户能看到的行为要变吗?

类型还决定验证纪律:缺陷先复现,改造先证明旧行为,新功能验新行为与相邻行为,工程任务验门槛真的拦得住。

这一条直接解掉 Kiro 的第一个缺陷——「改一个统计口径」不再被塞进「功能」,它有了自己的归口。

3.3 第二步:先调研,再定档

定档前必须调研,深度到能写出四行:根因(或目标)、影响面(调用方与消费方清单,以及怎么列出来的)、同类(同一写法还有哪些位置,怎么枚举的)、改法(能一句话说清就写一句,说不清就写卡在哪)。

调研只读:不改代码,不改仓库文件,复现脚本放临时目录。先读相关的旧 spec、守卫测试与既有实现,再看调用方与消费方。结论涉及「多少行、什么值、有没有这种数据」的,查生产库。

四行只写一处:A 档写进 commit message,B 档写进 spec 第一节,C 档进需求与设计。

为什么必须有这一步:定档若靠拍脑袋,档位就退化成形容词。而调研本身是最便宜的一步——它花的是一小时,省的是返工。

3.4 第三步:三档

「一句话说清」的标准不是行数,是一个提交做得完、一次验证验得完。要分几步做、每步各自验证的,算说不清,走 B。

改动量不参与定档。判的是要不要分步,不是大小。

A 档是整套设计里最关键的零件:它把流程成本压到零。没有 A 档,所有小改动都会被迫走 B,然后所有人学会绕过 B——这正是 Kiro 第二个缺陷的成因。给流程留一个诚实的出口,比强行要求所有人守规矩有效。

C 档另有一条硬规矩:批准字段必须是单独一个提交,之后才能推进任务。改一行代码,不可能顺手把批准也改了。

3.5 第四步:风险独立加码

风险不定档,在已定的档位上叠加。风险大的一票生效,不会被「改动小」「范围小」冲淡。

这条把「成本随风险走」落成了可执行的判据。也是我踩过坑的地方:改一个统计口径,代码只有三行,但下游三个面板的口径全变——这种改动的风险是中,档位可以是 A,但 A 也必须先报。

3.6 第五步:状态真源移进提交历史

一个任务一个提交,复选框从 [ ] 改成 [x] 与代码在同一个提交里。验证的命令与实际输出摘要写进 commit message,不写进文档。要看某个任务怎么验的,跑 git log –grep。

状态行跟着任务提交走:第一个推进任务的提交改成「执行中」,最后一个任务的提交改成「已完成」,不留到之后另补。

于是状态的真源变成了「复选框 + git log」两样东西,都可以被机器读,都可以被第三方复核。面板不再参与判断。

代价是失去一张好看的进度图。收益是两句话都成立:任何一句「做完了」都能被一条提交反驳或证实;漏掉哪个功能点,把任务与需求编号对一遍就露出来。

3.7 第六步:机器门槛只查结构

spec-lint.py 挂在 pre-commit 上,只查六样:任务行格式、状态只有三种、有任务节、每个顶层任务写了验证、批准后才能推进任务、需求与任务的追溯是否闭合。

其余一概不查。理由写在规范里:格式对不等于内容对。 能自动判的只有结构,内容判据只能靠人。

这条克制来自反面经验。那个连续四次静默失效的钩子,教训不只是「护栏要验证」,还有第二层:修完之后跑存量,大量 spec 不通过,当时抽查两类现象就结案为「都是历史格式,非脚本误判」——那个结论本身是误判。逐个复现后,57 个红里有 24 个是脚本自己的缺陷。这训练出了「lint 红了不用管」的习惯,比不装护栏更糟。

所以现在的判据里有一条自我约束:给任何兜底记功之前,先构造一个它应该拦住的输入,看它拦不拦。 拦不住的检查,不如不装。

3.8 第七步:完工冻结,与活文档分离

一份 spec 完工后,正文冻结。之后发现的问题在记录节追加,不回头改正文;要改行为,开新 spec。

同时立一条规矩:「现在系统是什么样」去看代码和活文档,不看 spec。 spec 是变更快照,它记录的是「那一刻决定了什么」,不是「今天是什么样」。

归档按状态分两层:待完成/ 与 已完成/,主题目录下放若干套 spec。代码注释、migration、提交说明引用 spec 时一律不带状态层路径——这样搬家不会打断任何引用。

这几条合起来解决一个隐蔽的问题:如果 spec 既当历史又当现状,它必然在半年后开始撒谎,而读它的人(人或模型)无法分辨哪一句过期了。分开之后,撒谎的机会从结构上消失了。

3.9 与 Kiro 的对照

3.10 代价

不讲代价的方法论是广告。

C 档的写作成本可能超过写代码。 一份完整 spec 要写需求、设计、任务三份,再加证据登记与决策登记。改动越复杂,这个比例越难看。它换来的是不漏功能与可追溯,但不是每件事都值得。

规则本身要维护。 312 行会漂。规范里已经出现了「已知误报」「已知漏口」这样的章节——这不是严谨,是不得不承认的负债。

规则越多,越可能只被读一半。 我给的解法是分层:§1–§6 必做,§7 是清单,§8 是参考。但分层只降低误读概率,不消除它。

A 档依赖诚实。 不写文件意味着没人核对你是否真的做了调研。commit message 有格式,但拦不住敷衍。这是这套设计里最脆的一环,我没有更好的解法。

它是为「一个人 + 多个 agent」设计的。 换成五个人协作,状态真源、批准流程、归档规则都要重写。别直接搬。

四、小结

AI 读代码,读不出人当时的设计意图。 代码记录结果,不记录原因。一个 if 为什么在那里,可能是三年前的合规要求;一个字段为什么允许为空,可能是上游某次事故的补丁。这些都进不了函数名。人可以靠记忆和同事补全,记忆会过期,人会走;AI 连记忆都没有,手里只有代码。只让它读代码,它只能按「看起来合理」的方式改——而合理与当初的意图无关。

所以维护一套文档系统,是 AI 写代码不走偏的前提,不是额外负担。 需求、设计、任务三份各回答一个不可替代的问题:要什么、怎么做、做到哪算完。缺一份,AI 就有一半的输入靠猜。而写进文档还不够——不读,等于没有。这也是为什么「先读旧 spec 再动手」被写成了调研的第一步。

强制力必须落在机器上。 这是六个月里最贵的一课。规则写进文档,靠自觉执行;规则写进 pre-commit,才靠机器执行。而机器也会骗你——所以每装一道护栏,都要先构造一个它应该拦住的输入。

这一代的开发方式,底座是 Spec:不是文档洁癖,是把人类的设计意图外置成 AI 可读、可查、可追的东西。工具会换,这份外置的意图不能没有。

下一篇写产品本身:从零到一怎么选型、怎么定项目规范、怎么让文档活起来而不是烂掉。

专栏作家

臻龙,人人都是产品专栏作家,全面发展型产品经理,喜欢认知心理学与神经科学,特别钟爱讨论抽象算法问题,欢迎撕逼交流。

本文为作者独家发布于人人都是产品经理。未经本站许可,禁止转载。谢谢合作。

题图来自unsplash,基于CC0协议

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
海报
评论
评论请登录
  1. 目前还没评论,等你发挥!