
这段时间“vibe coding”这个词在开发者圈子里是真的火——用自然语言描述个大致想法让AI噼里啪啦把代码写了自己也懒得逐行看跑通了就感觉“人机合一”。我在不少技术社区看到新手用这种方式一晚上搭出个小工具确实爽。但爽完之后等需求稍微复杂一点、项目稍微长大一点问题就来了AI改版几次之后改懵了自己也不知道当前代码到底在干嘛甚至因为一句描述不当整个模块的逻辑都悄悄跑偏。我自己也踩过这类坑后来真正稳住工作流的关键就是把“vibe”换成“spec”——也就是从“凭感觉描述”切换成“按规格说明驱动”。所谓spec-driven简单说就是先写一份清晰的规格文档把功能边界、输入输出、验收标准都定清楚再让AI照着干活。这篇文章我会直接拆解传统vibe coding到底痛在哪、spec-driven为什么能治这个痛并且给出可以直接抄走的一套落地模板和实操流程。适合正在用AI辅助写代码的新手也适合想把AI编程纳入正规项目流程的团队。1. 传统vibe coding的四个典型翻车现场问题不在AI在方式先说明一下我不反对vibe coding我自己也用。但用归用它的问题不能回避。你如果不清楚它会在什么地方坑你那真的很容易把一个小项目写成一场灾难。1.1 上下文漂移AI“改着改着就忘了自己要干嘛”这是最经典的一类问题。你跟AI对话式开发连续聊了30多轮第二轮说“用户信息要存数据库”第20轮说“这里改成从接口读”到第27轮让它在原逻辑上加个缓存。AI并不会像人一样牢牢记住“第2轮定的方案”和“第20轮改的需求”之间的冲突它只会根据近期对话推测你的意图。结果就是它把第20轮的“从接口读”改没了回到了第2轮的数据库直连甚至为第27轮的缓存写了一套根本用不上的逻辑。你发现的时候还不一定马上能定位因为改动是局部的不对比中间版本根本看不出来。我见过有人调侃这是“AI失忆”但其实更准确的说法是对话式开发没有一个稳定的需求基线。所有需求都散在聊天记录里而聊天记录越堆越长AI对早期内容的引用就越模糊。1.2 隐藏债务你根本不清楚AI在项目里悄悄埋了什么东西我有个朋友做过一个实验让AI给他写一个带登录、积分、订单三个模块的小商城然后自己不看代码直接部署。最终跑起来确实没问题但事后审计代码时发现AI一共引入了十多个依赖库其中两个是他听都没听过的冷门库还有一个版本的传递依赖存在已知漏洞。这种“隐藏债务”是vibe coding最大的雷。因为你的关注点都在功能层面——能跑页面上有东西接口有返回——但代码内部的依赖管理、异常路径、安全边界、资源释放AI不会主动跟你报备。它追求的是“完成任务”不是“健康设计”。你可以说“用的时候小心点就行”但事实是你根本不知道哪里需要小心。1.3 测试缺失改一处崩一片你还找不到是谁干的传统vibe coding工作流里几乎没有人会要求AI先写测试再写实现因为大家的心理预期是“先看效果回头再补测试”。但AI改代码是全局性的它可能为了满足你一个新需求重构了某个底层util函数然后所有调用方一起出问题。如果是人手开发你能通过git blame快速找到改动点但AI的提交信息通常写得很泛比如“refactor code”或“update logic”你很难从提交历史里获得有效信息。更别说很多vibe coder根本不做细粒度提交让AI直接改完覆盖。等出bug的时候你连“哪次改动引入的”都说不清。1.4 验收无锚点你说不清“做好了”到底长什么样最后这个问题最致命在vibe coding模式下“完成”是一个感觉不是一个标准。AI说“已经实现好了”你看着界面觉得差不多但没有一份明确列出的验收条件你根本不知道它有没有漏掉边界情况、有没有处理异常输入。比如你让它做一个URL短链服务它给你生成了能用的短链生成逻辑。但雪花算法ID重复怎么办用户输入非法URL怎么办短链过期后数据库清理策略怎么设计这些如果没有提前写进规格里AI大概率是不处理的——因为它不知道“做完”包括这些。2. Spec-Driven的核心思路从“让AI自由发挥”变成“让AI按图施工”前面那些坑讨论到最后其实会指向一个共同根源需求没有以结构化方式传给AI。对话内容都是自然语言散句缺乏结构AI从中提取的优先级、边界、约束很可能跟你的意图不一致。Spec-Driven就是把这块补齐。2.1 认知转变规格文档不是文档负担是给AI的“安全带”很多人一听“先写规格文档”就头大觉得这是又回到了重流程的老路。但理解一下原理就不会这么想AI在没有约束时的自由发挥能力既是优势也是危险。给它清晰的规格等于是给它一副骨架让它在这个骨架范围内发挥创意、填充肌肉和血管。这样做之后它生成代码的方向性和稳定性都会大幅提升。我自己的感受是花在写规格上的时间相比省下的调试和返工时间大概是1比4甚至更多。写一份核心规格可能只需要20到40分钟但它能让AI少跑偏好几次。2.2 最小可用Spec包含哪些要素不需要写一本论文完整的软件规格说明有很多种格式比如传统的SRS软件需求规格说明书有各种IEEE标准格式。但个人和小团队用根本不需要那么重。我实际用下来一份能压住场面的最小Spec只需要四块对象回答什么问题具体内容项目目标为什么要做这个项目要解决的痛点、给谁用、核心价值范围边界做到什么程度为止做什么、明确不做什么、禁止引入什么功能规格每个功能具体要哪些行为输入、处理逻辑、输出、异常行为、权限校验验收标准怎样才算“完成”可执行的测试样例、表现指标、代码约束这四块不是学术要求而是每一块都在解决前面提到的某类痛点项目目标防止AI偏航范围边界防止AI无限扩大改动功能规格把“输入输出和异常”钉死验收标准给你一个不说“我感觉还行”而是能说“对这就是完成了”的依据。2.3 Spec-Driven和“先写一堆设计文档再开发”不是一回事这里要区分一下很多人听到spec以为就是老掉牙的“瀑布流”——先写全量文档、冻结需求再进入开发。那是误解。Spec-Driven是“需求锚定任务分块”的方法论不是“文档写一次就不改了”。实践中spec是可以迭代的你花15分钟写个v1版本AI按v1做出第一个功能块当你验证后发现需求理解错了改spec的v2版本再让AI改对应模块。它和敏捷开发并行不悖而且因为每个change都对应spec中的更新你天然就有了变更记录和回滚锚点。3. 一份能落地的Spec长什么样完整模板与拆解实例光说概念还不够我直接给一份我实际用过的模板并且用一个真实小项目拆解给你看。这个项目是一个“Markdown笔记转HTML静态站”的小工具拿它做例子很合适因为它足够小、功能边界也清晰。3.1 项目目标与范围边界这一部分怎么定AI才不会“过度设计”项目目标这一段我通常用两到三句话写清楚给谁用、解决什么问题、核心交付是什么。别写愿景写“接下来这个迭代的目标”就行。项目目标v1.0 - 目标用户独立开发者需要将本地Markdown笔记批量导出为可部署的静态HTML。 - 核心价值一条命令完成全部转换无需手动处理页面模板和资源引用。 - 本迭代交付支持单目录下的Markdown批量转换生成index.html和文章详情页。范围边界是很容易被忽略的一段但特别关键。AI有个特性你只说“做什么”它会忍不住把“相关的”也做了。比如你让它做Markdown转HTML它可能顺手给你加一个主题切换功能理由是这个“很合理”。但对你来说这可能是额外的样式负担、额外的测试面。范围边界就是打预防针范围边界v1.0 - 不做在线编辑器、多用户系统、自定义主题市场、明确说这些是v2.x的候选功能。 - 禁止引入重型前端框架如Vue/React、引入非必要的构建链如Webpack。 - 依赖限制仅允许使用自带的markdown解析库或者你明确指定的库。这一小段写下来AI就不会自作主张地“锦上添花”了。3.2 功能规格的撰写范式把“行为”拆成输入、处理、输出功能规格是整个Spec的核心。我建议每条功能都按照“输入→处理→输出→异常”的结构来写而不是写一句话描述。功能F1批量转换Markdown为HTML - 输入指定目录下的所有.md文件含子目录。 - 处理 1. 解析每个文件的frontmatter提取title、date、tags字段。 2. 将Markdown正文转换为HTML。 3. 使用模板生成完整HTML页面将本地图片路径改为相对路径。 4. 生成所有文章的索引页index.html按日期倒序排列。 - 输出构建目录下生成index.html和post/子目录下的文章文件。 - 异常 1. 目录不存在时输出错误信息并退出退出码1。 2. 单个文件解析失败时跳过该文件并在日志中记录警告不能中断整体流程。 3. frontmatter缺失时用文件名作为title不报错。你有没有发现光是把“异常”这两条写出来就堵掉了好几个vibe coding常见的坑AI通常会因为一个坏文件就整个崩溃或者因为frontmatter少了字段而报错。有了显式的异常行为定义AI一次性就能写对。每个功能都这样写可能会让你觉得“是不是太多了”我的经验是关键的3到5个核心功能值得这样写边缘小功能可以简单一行描述。不要过度工程化规格本身。3.3 验收标准与测试锚点让“完成”有可操作的判断依据验收标准是最能被vibe coder跳过的部分也是我后来最喜欢单独花时间写的一部分。它不一定复杂一小段可执行的描述就行。验收标准F1 - 给定测试目录包含5个有效md文件、1个损坏md文件、1个缺frontmatter的md文件执行转换命令。 - 预期命令执行成功index.html正确列出5篇文章并按日期倒序损坏文件被跳过且路径记录在日志中缺frontmatter的文件生成成功且文件名作为title。 - 执行时间不应超过10秒针对不超过100个文件的目录。有了这个你不需要和AI说“你可不可以确保健壮性”你只需要把验收标准贴给它并告诉它“实现完成后自己按这个标准给你列出的样例数据做一次自检”。这个操作直接把“AI自由发挥”变成了“AI自我验收”。3.4 变更记录的节奏管理Spec不是写一次就冻结的石头最后谈一下迭代。Spec它天然是活文档。我推荐的做法是每次改spec时在文档末尾维护一个“变更记录”表格版本日期变更内容影响范围v0.12025-01-10初版规格全部功能v0.22025-01-12补充F1的异常处理策略F1v0.32025-01-15新增F4生成RSS订阅文件全局这个表格不必写入AI去执行但它对你和团队很重要当你发现某个功能改乱了可以回看spec哪个版本做过变更让AI只针对对应部分做增量修改。这比在聊天记录里翻上下文高效得多。4. 在真实项目里跑通Spec-Driven工作流从开工到验收的全流程这一节是纯实操。我拿一个真实项目讲讲spec-driven的完整循环包括几条可以直接用的提示词框架和遇到问题时怎么办。4.1 推荐的迭代节奏“先窄后宽跑通之后再扩展”很多人第一次用spec-driven时最容易犯的错是把第一个版本的规格写得太雄心勃勃把所有功能都列出来。结果AI生成的代码量巨大你的检查负担也大出现问题根本分不清是哪块逻辑造成的。更好的节奏是这样第一个迭代只做最小闭环。比如上面那个Markdown转HTML工具第一个迭代只做“单篇文章转换”不做索引页不做子目录扫描。跑通这个最小闭环后再在spec里追加第二个功能让AI增量实现。每轮新增功能量控制在“你拿半小时能人工过一遍代码”的程度。这个节奏的核心优势是问题一旦出现你能快速定位是“这轮新增的代码”导致的而不是在一大片AI生成代码里捞针。我甚至会在每轮迭代时明确告诉AI“不要修改与本次需求无关的文件。”这句话能大量减少AI顺手重构的冲动。4.2 让AI按照Spec执行的提示词框架可以直接复制使用很多人以为spec-driven就是“把spec丢给AI”然后就好了。不是的你需要给AI一个清晰的任务指令否则它可能会把spec泛泛地读一遍然后按自己的节奏来。我常用的提示词框架是这样的你正在参与一个spec-driven开发任务。请严格遵循以下流程 1. 阅读规格文档《xxx》的全部内容包括范围边界和验收标准。 2. 如果规格中存在歧义或缺失的细节先列出问题清单不要擅自假设。 3. 按照本迭代的功能条目F1、F2逐条实现不要修改与这些条目无关的文件。 4. 实现完成后按照验收标准进行自测并逐项报告结果。 5. 只报告结论和必要的变更说明不要额外解释你“还能做什么”。如果你在用GitHub Copilot或者Cursor这类工具可以把spec文档放在项目根目录如spec.md并在每轮对话开始时让它先“读spec.md确认需求”。我自己用下来这套提示词最大的作用不是“教AI做事”而是建立秩序你要求它列问题清单它就不会在你没授权时自己脑补你要求它按验收标准自测它就不会说“完成”但不验证。4.3 我踩过的坑和应对这三个点几乎每次都中招哪怕有了spec实践里依然有几个高频坑我先帮你踩了你注意避开。第一个坑是“ai对spec视而不见”。有时候你在对话窗口发了一整份specAI嘴上说“已了解”但写出来的代码还是跑偏了。应对办法是让它在回答开头先复述它理解的验收标准和功能边界如果复述内容不对你马上纠正再让它动手。这一步只花一分钟但能避免一次大返工。第二个坑是“ai过早抽象”。有些AI逻辑性很强你让它实现两个相似功能它会立刻抽象出通用基类或宏大的工具函数。但是需求变了你只想改A功能却发现它的抽象影响到了B和C。我的策略是在spec里加上“避免不必要的抽象”或者在提示词里写明“在你的抽象设计成本达到必要性之前先复制代码实现”。等确实有第三个重复点再讨论抽象方案。第三个坑是“依赖库选择自作主张”。这个问题我在1.2小节提过UI类项目尤其严重。AI为了一个进度条效果可能引入一个很酷但维护状态不明的npm库。我现在会在spec中单独写一行“新增任何第三方依赖前必须暂停实现列出备选库和选择理由等待确认。”这一步能多花几分钟但可以让你的依赖树保持可控。4.4 当AI质疑Spec时怎么办这是好信号不要压制这是个很有意思的现象当你给了AI一份规格文档时有时候AI会在回复里说“检测到规格中某处定义与现有代码不一致建议调整”或者“验收标准中第3条可能存在歧义”。很多人的第一反应是“AI怎么不听话让它做就完事了”。但我建议你把这种信号当成礼物。AI在逻辑一致性检查方面已经很强它发现spec内部矛盾确实可能有问题。这是spec-driven模式独有的优势有了明确的规格文档AI才有能力、才有依据去做“需求审查”。传统vibe coding里AI不会这么做因为它没有参考点。处理方式也很简单如果AI提出的质疑是对的直接更新spec并告诉AI“已确认按你的建议修订”如果AI的理解跑偏了则把spec相关条目再明确一遍纠正认知。5. 从个人开发到小团队协作Spec-Driven还能怎么扩展最后聊聊Spec-Driven的成长路径。这个方案不只是给个人开发者用的它的复用性和扩展性我觉得比想象中更大。5.1 单人项目Spec就是你的“第二大脑”我用了一段时间后发现spec.md最大的受益者不是AI而是未来的自己。三个星期后你回头改一个模块翻代码的效率远不如翻spec文档来的高效。spec里的功能定义、决策记录、变更记录就是当时的“你”留给以后的“你”的便签。有条件的我建议把spec放在git仓库里每次更新单独提交一次commit message写成“update spec: F3 add pagination logic”。这样做之后你的git历史里就同时有了“需求变更历史”和“代码变更历史”排查问题的时候双线对应效率高很多。5.2 多人协作把“评审代码”变成“评审Spec与代码的差距”在做小团队协作时spec-driven也有它的独特价值。传统团队里做code review大家讨论的是代码风格、实现逻辑而有了spec之后review多了一个核心维度这段代码是否符合规格定义。评审人看到PR时可以先打开对应的spec版本逐条比对代码实现。哪条没有覆盖、哪条多实现了、异常处理是不是按规格定义做的一目了然。这个流程对新人特别友好因为新人还不熟悉团队的代码库但他有了spec就能理解改动意图。5.3 后续更新方向这个文档我会持续迭代的部分因为我正在多个不同规模的项目里持续使用这套玩法所以这个主题的博文会有比较多的实践迭代空间。后面我打算按这几个方向继续更新内容结合不同类型项目的spec范本比如纯前端项目、AI Agent项目、数据同步服务针对不同AI工具Cursor、Copilot、或者开源模型本地部署的spec注入姿势更复杂的团队分工模式比如PM写目标、技术负责人写功能规格、AI负责实现如何分权我目前把自己的模板和样例都放在一个持续更新的项目里每轮迭代带来的经验教训也会同步进来。如果你也在尝试spec-driven建议先拿一个小而真实的项目练手别一上来就重构你的大系统。把规格写清楚让AI按图施工你会发现以前那种“AI写码我追责”的无力感其实是可以被一套好流程轻松消解的。