最近处理一个需求让我对“Spec Coding”有了完全不一样的理解产品经理只是想把系统里所有面向终端用户的“用户”统一改成“客户”这一个单词结果AI配合现有规格文档最终产出了将近500行代码文档。一开始我也觉得夸张但把变更过程完整过了一遍之后我意识到这才是AI辅助开发该有的样子——文档不再是文档而是代码的另一种存在形式。这篇文章想聊清楚三件事Spec Coding到底是什么为什么改一个单词会牵出500行的文档以及如果你想在自己项目里落地这套玩法有哪些可以直接照抄的步骤和必须避开的坑。适合对AI编程感兴趣、被“AI写代码很爽但需求变更很痛”困扰过、或者想提升团队需求传达效率的人。1. 起因把“用户”改成“客户”一个单词怎么会带出500行文档1.1 需求看起来真的很小当时的需求背景不复杂。业务侧把合作方统称为“客户”而系统里大量文案、字段、接口注释还在用“用户”。产品提了个变更单把面向终端用户的“用户”统一改成“客户”。放到传统开发流程里这基本就是一个“全局替换回归测试”的小活。多数人会直接打开IDECtrlShiftH把所有“用户”换成“客户”跑一遍测试然后提交代码。但在Spec Coding工作流里事情不是这么走的。因为规格文档里每一个术语都不是孤立存在的。就拿“用户”这个词来说它在规格仓库里至少出现在这些位置领域事件名称比如UserCreated数据库字段注释比如created_by_user_idAPI错误消息比如USER_NOT_FOUND权限角色描述比如普通用户测试用例里的actor比如当用户登录系统时示例数据和数据字典状态机描述里的主体定义一个单词改了这些位置必须全部同步改否则规格内部就出现语义分裂测试驱动会失败代码也会产生坏味道。这就是为什么AI最后产出了500行文档——它不是想炫技而是在规格约束下做一次完整的语义迁移。1.2 传统改法与Spec Coding改法的岔路口传统方式处理这种变更最大的问题是没人能证明“改全了”。全局替换只能处理字符串完全一致的情况但“用户”和“客户”在代码里可能以不同的形态出现比如user、User、USER、user_id、end_user一旦人工筛选漏掉几乎是必然的。我见过太多线上事故是这样发生的界面文案改成了“客户”但订单导出的Excel表头还是“用户”异常日志里一半写user一半写customer排查问题的人被误导了三小时。Spec Coding的思路是反过来的先认账再干活。它承认“一个单词的变更一定会波及其他产物”所以把所有的引用关系显式记录在文档里然后让AI基于这些文档做影响分析和逐项修改。两种方式的对比非常明显维度传统改法Spec Coding改法修改对象直接改代码文件先改规格再投影到代码/测试/文档怎么验证改全了靠测试用例覆盖率规格一致性检查测试双保险需求追溯散落在commit message里在impact-analysis里全量记录单个词变更成本看着低但漏改风险高看着高但每处修改都可追踪部门协作价值几乎为零产品、开发、测试读同一份文档说白了传统方式追求的是“这次改完就行”Spec Coding追求的是“这次改完下次还能改得起”。2. Spec Coding的本质AI写的不是代码是可执行的需求投影2.1 先分清楚让AI写代码和让AI写规格境界完全不同很多朋友对AI编程的理解是这样的把需求描述扔给AIAI生成几十行代码你复制粘贴跑通就完事。这没错但这只是“AI辅助编码”离Spec Coding还有一段距离。Spec Coding全称可以理解为Specification Coding也就是规格驱动编码。它强调的不是“让AI帮你写实现”而是“让AI先把需求变成一份精确、结构化、可验证的规格文档再让规格文档自动投影出代码、测试用例、接口契约和其他派生文档”。举一个生活化的类比。普通AI编程就像你直接告诉装修工人“我要一个原木色餐桌”工人凭经验给你做出来。Spec Coding则是你先请设计师画一套完整的施工图图纸上标明尺寸、材质、连接方式、承重标准然后工人照着图纸施工。餐桌最后一个螺丝松了你知道一定是图纸哪一步出了问题而不是靠猜。对应到开发里好处就非常明显需求可追溯每行代码都能找到它对应的规格条目。测试可验证验收标准在写代码之前就定义好了。代码可解释AI不会突然给你来一段“野路子”写法。变更可评估改一个单词的影响范围会在动手之前就被文档化。2.2 三层投影行为、契约、验证我在实践里习惯把Spec Coding的投影分成三层AI的所有产出都在这个框架里规规矩矩地运行。第一层是行为投影。这层描述系统“应该做什么”。最典型的载体是用户故事和Gherkin场景文件。举例场景客户查看自己的订单状态 假如 客户 “张三” 已登录系统 当 张三打开订单详情页 那么 页面展示当前订单的state字段 并且 state字段的取值来自订单状态机第二层是契约投影。这层描述系统“对外以什么结构交互”。OpenAPI、JSON Schema、数据库表结构都属于契约层。AI会根据行为投影生成或更新这些接口定义保证对外通信的一致性。第三层是验证投影。这层把行为投影和契约投影进一步转成自动化测试。AI生成测试骨架、断言逻辑、测试数据确保最终代码确实满足规格。这三层之间保持单向依赖行为投影决定契约投影契约投影决定验证投影。日常开发里AI一般会一次性产出但真正出问题的时候我们永远是回过去改最上游的行为投影然后在让AI逐层刷新下游而不是直接去改一个TestCase里的魔法数字。3. 动手实操用AI做一次“改一个单词”的Spec Coding变更3.1 准备一个规格仓库让“文档”先于代码这一节我会用一个具体例子演示。假设系统里有一个订单状态模块原来的规格里用STATUS表示“状态”现在产品要求全部改成STATE理由是业务方已经统一术语后续还要对接外部系统必须消除歧义。第一步是建立规格仓库目录。我们的做法是每个业务能力模块一个目录里面至少包含六类文件specs/ 0001-order-status/ README.md # 模块说明与最新变更摘要 terminology.md # 术语表 domain-model.md # 领域模型与状态机描述 api-contract.yaml # OpenAPI接口契约 features/ order-lifecycle.feature # Gherkin行为场景 tests/ # 由spec生成的测试骨架 adr/ 0003-rename-status-to-state.md # 架构决策记录这套目录的好处是AI拿到之后能在几秒钟内建立一个“完整上下文快照”。它知道这个模块有哪些领域概念、对外暴露什么接口、行为场景长什么样、历史上做过哪些决策。这一切就是它后续修改的依据。如果项目还没有这种规格仓库建议不要急着让AI写代码先让AI生成一份最小规格哪怕只覆盖一个核心业务动作也要先建立“文档先于代码”的纪律。否则Spec Coding就是空中楼阁。3.2 关键提示词与AI产出拆解当需求变更进来我会给AI发一个明确的变更指令而不是模糊地说“帮我把STATUS改成STATE”。实测下来下面的提示词模板效果最稳定你现在是规格驱动开发引擎。 需求变更将订单状态模块中的术语 STATUS 改为 STATE。 原因统一业务口径消除与外部系统交互时的语义歧义。 范围仅限 specs/0001-order-status/ 目录。 任务 1. 审查该目录下的所有文件定位所有出现 STATUS 的位置。 2. 生成 impact-analysis.md列出每一个位置的文件名、当前内容、影响级别。 3. 依次更新 terminology.md、domain-model.md、api-contract.yaml、order-lifecycle.feature。 4. 根据更新后的规格同步调整 tests/ 下所有测试骨架。 5. 输出最终的变更说明包含变更理由、影响清单、逐文件diff说明、需要人工确认的风险点。 硬性约束 - 禁止修改与STATUS无关的内容包括其他字段、文案、业务逻辑。 - 禁止在规格中新增或删除字段。 - STATUS作为内部枚举值真实存在时保留对应枚举只重命名标识符。AI执行完之后产出物大致长这样变更结果 - impact-analysis.md 64行 - terminology.md 32行 - domain-model.md 88行 - api-contract.yaml 142行 - order-lifecycle.feature 96行 - tests/ 120行 - README.md 28行 合计约570行这套文件加起来确实接近500行。注意AI并没有写任何“功能实现代码”它写的是“代码的文档”——术语定义、契约、场景、测试、影响分析。但这些文档比代码更接近业务真相。3.3 为什么不能直接全局替换很多人会问为什么不直接让AI全局把STATUS替换成STATE因为在规格里“STATUS”这个词在不同位置代表完全不同的语义在api-contract.yaml里status是响应字段名对应一个字符串枚举。在domain-model.md里STATUS可能是一个枚举类型名称内部还有PENDING、PAID、SHIPPED这些值。在order-lifecycle.feature里订单状态是自然语言描述根本不会出现大写的STATUS。在tests/里可能会有ORDER_STATUS_MISMATCH这样的错误码常量。如果无脑替换API文档里的字段名也许能直接改但领域模型里的枚举类名和具体值需要分开处理错误的常量名也不能跟着一起改。AI基于规格文档做修改时它看到的是语义而不是字符串。这正是Spec Coding对比普通AI编程最有价值的地方AI不只是“找到并替换”而是“理解并迁移”。4. 那500行到底装了什么一份代码文档的内容拆解4.1 逐文件拆解术语、模型、契约、场景、测试这500行不是垃圾输出每一块都有它的位置。我按下表拆过一遍读者可以对号入座文件行数主要内容为什么这次变更要动它impact-analysis.md约64行受影响位置清单、影响级别、风险点为整个变更提供证据链也是人工审查的入口terminology.md约32行STATUS与STATE的定义、别名、禁用词术语表是语义事实源必须先改domain-model.md约88行状态机节点、字段映射、实体属性说明领域模型里的状态属性名需要跟随重命名api-contract.yaml约142行OpenAPI字段名、枚举示例、错误码对外契约一旦不一致客户端立刻爆破order-lifecycle.feature约96行所有场景里的用户动作、状态断言行为规格必须与领域模型保持一致tests/约120行测试文件名、测试夹具、断言字段测试是规格的验证投影不能留旧术语README.md约28行变更说明、迁移指引、注意事项给下一个开发者和业务方留底拆解之后你会发现每一类文档都在回答不同角色的问题。产品经理关心术语表是否改对了后端关心API契约能不能兼容测试关心断言逻辑是否还成立运维关心错误码有没有变化。如果没有Spec Coding机制这个问题没有任何人能一次性说清。4.2 为什么这些文档能被当成“代码”来管理“文档即代码”不是一句口号它有很具体的工程含义。首先这些文档全都是纯文本结构化格式Markdown、YAML、Gherkin。它们可以被Git跟踪可以被diff可以被code review可以设置行级注释。其次它们可以被自动化工具解析。比如CI里跑一个脚本检查terminology.md中的术语是否与api-contract.yaml中的字段命名一致不一致就报警。这就是“可执行的文档”。这一点改变了我们debug的方式。以前代码报错我只能看堆栈现在规格不一致我直接在CI日志里看到“订单状态模块的术语表中已定义STATE但contract中仍存在status字段请检查。”问题定位时间从小时级缩短到分钟级。4.3 这500行有哪些部分是真正需要人review的AI能把所有文档联动更新但不代表人可以闭眼merge。我在实际review中总结出三个机器容易犯、必须人盯死的点。第一AI在改写自然语言场景时容易把语义悄悄变掉。比如原本是“客户提交订单后系统将STATUS置为PENDING”AI可能改成“系统将状态置为待处理”表面上对但“待处理”如果没在术语表里定义过就会引入新的歧义。第二AI对枚举值的处理偏保守可能只改了字段名没改内部枚举值导致契约与测试对不上。第三impact-analysis里AI声称“已全部更新”但它列的清单是否完整需要人抽查至少一两个原始引用点。我把这种review叫做“抽查清单对照法”人只需要挑3到5个受影响的文件手动确认修改是否符合语义不需要重新读一遍500行。其余部分交给规格一致性检查。5. 三个月的实战踩坑Spec Coding失控的高发场景与收敛手段5.1 翻车现场一AI太配合把范围越扩越大第一次带团队跑Spec Coding时我让AI把订单模块里的STATUS改成STATE它除了完成正事还顺手帮我把“订单”改成“采购订单”、“已支付”改成“支付完成”。它的理由写得很正经“为了全仓库术语统一。”问题在于这个仓库里同时存在“订单”和“采购订单”两个概念本次需求根本没打算动它们。AI的好心直接污染了跨模块的其他文档CI检查也报出大量无关ant差异review成本一下翻倍。后来我在所有变更提示词里固定加了两句话只改我指定的术语严禁修改任何与本次变更无关的业务语义。再加一条如果AI发现其他术语不一致只能写进“备选观察项”不许在本次变更中直接修改。从此AI乖了很多。5.2 翻车现场二规格与代码失联文档变成一次性用品还有一个特别容易掉的坑文档写得很漂亮但代码改完之后没人回头更新规格。两周后另一个人让AI改数据字典AI按旧规格生成结果产生出一批与线上代码脱节的文档。这个问题本质上是流程纪律的问题。解决办法是在PR模板里加一个勾选项“如果本次变更涉及业务概念、接口字段或状态取值必须同步更新对应规格文档。”同时让CI检查规格文档的更新时间是否早于代码文件。如果程序化地保证“文档先于代码”失联问题会大幅减少。5.3 翻车现场三粒度失控整个仓库变成“改不起的大文件”第三个坑比较隐蔽团队为了让AI生成更准把所有细节都塞进规格文档。结果一个中等模块的规格仓库膨胀到两万多行任何一次小需求变更AI都要把所有文件过一遍输出的影响分析动辄上千行人根本审不完。这是典型的“粒度失控”。规格不是越细越好它只需要承担三类信息业务术语、行为场景、对外契约。具体的页面布局、数据库索引、代码风格都不应该进入核心规格。我给团队定的经验法则是一份规格文档如果一屏看不清核心内容那它已经太胖了。保持精简Spec Coding才有生命力。5.4 收个尾我用“三层约束法”让AI老实下来外加一个影响面指纹技巧针对AI自由发挥的问题我最终沉淀出一套“三层约束法”现在写进了所有Spec Coding项目的system prompt里。领域约束AI必须遵守术语表中已定义的语义不新增未定义术语不改变业务规则。范围约束AI只能处理本次变更指定的模块与字段禁止扩大范围禁止顺手优化。格式约束AI必须按目录模板输出字段名不可增删编号规则不可改变。这三层约束放在提示词最前面能显著降低AI“创作热情”带来的风险。但只靠提示词还不够我建议在规格仓库里加一种轻量机制。我现在会给每份需求变更生成一个“影响面指纹”它就是一个由变更涉及术语组成的简短集合比如{ORDER, STATE}写进impact-analysis.md的头部。下一次任何人或AI要评估一个新变更是否与之前变更冲突时只需要比对指纹交集秒级完成不用再把几百行文档从头读一遍。这个技巧是我三个月实践下来最出乎意料地实用的一个。它让团队从“害怕改一个单词”变成“欢迎改一个单词”因为每次变更都像给系统做一次免费的语义体检所有隐藏的引用关系都会被暴露出来然后再被妥善修复。Spec Coding真正让我上头的点是它把AI从“代码生成器”变成了“规格翻译官”。它没有消灭开发者的工作而是帮我们把工作重心往上移了一层——从纠结代码怎么写变成了专注语义怎么定。这一层的变化才是未来几年AI编程最有价值的演进方向。