2026/11/2 4:01:43

从氛围编码到AI原生软件工程:用SDD和Harness让AI编程可控

从氛围编码到AI原生软件工程:用SDD和Harness让AI编程可控 过去大半年“氛围编码”vibe coding基本成了 AI 编程的代名词。你只要把一段想法丢给 AI它噼里啪啦生成一大片代码本地跑起来有界面、有接口体验确实上头。可一旦进入真实交付情况就完全不一样了代码要复用、接口要稳定、别人要接手、线上要兜底“氛围感拉满”的流程会迅速变成事故现场。我见过太多团队从“AI 真香”一路走到“AI 写的代码不敢合”问题从来不在模型能力而在流程里少了两层东西——把需求讲清楚的规范层和把 AI 执行过程管起来的工程层。这篇文章想聊的就是这两层用 SDDSpec-Driven Development规范驱动开发定义边界用 Harness 做编排与护栏把氛围编码升级成真正可控的 AI 原生软件工程。1. 氛围编码的失控现场为什么非改不可1.1 氛围编码到底爽在哪先说说氛围编码原本的好处。它最大的价值是降低了“从想法到可运行代码”的门槛。以前写一个原型可能要搭工程、建目录、写样板代码现在把需求几句话发给模型几分钟内能拿到一版能跑的代码。对于一次性脚本、Demo、个人玩具项目这套方式确实高效我自己也用它做探索性实验。这里要强调一下我不是全盘否定氛围编码而是说它适合的场景边界很明确——人的判断要在关键节点覆盖到位。只要没有任何约束问题就会慢慢堆积。我也见过一些团队把氛围编码直接用于生产项目理由是“先跑起来再说”。短期看确实快但快感集中在第一次生成等到功能迭代、缺陷修复、人员交接开始之后模型生成的代码就像一盘散沙谁都不敢轻易碰。它把编码成本提前转移成了维护成本而维护成本往往高出几个数量级。1.2 失控的四个典型症状第一是需求漂移。AI 的每次输出都基于你给它的一次 prompt而 prompt 描述天然是模糊的。比如你说“做一个用户列表页面”它可能理解成做全部用户也可能理解成做分页列表第二次说“再加一个筛选”它往往会重写整个页面把第一次的逻辑带偏。第二是上下文断点。我在一个项目里试过让 AI 连续改了五天需求到第三天之后它开始忘记第四天加过的字段第五天提交的版本直接把第三天的功能删了。原因很简单上下文窗口装不下整个历史模型只能在有限的视野里“想办法”。第三是不可验证。氛围编码的项目往往没有测试、没有契约只有一坨能跑的代码谁都不确定改完会不会破坏线上最后只能靠人肉回归。第四是安全与依赖失控。AI 会写出不存在的依赖包名会把密钥直接写进配置会调用一个有安全漏洞的旧版本库而这个过程没有任何自动扫描。这四个症状叠加起来就是典型的“氛围编码债务”跑得越快欠得越多。1.3 升级路径规范层加工程层SDD 解决的是“干什么”的问题。它把一段模糊的自然语言需求翻译成一份结构化的、可测试的规范AI 只需要在规范划定的范围内做翻译和执行。Harness 解决的是“怎么保证干对”的问题它把 AI 的编码过程变成一条流水线喂什么上下文、允许调用哪些工具、在什么环境执行、如何验证结果、何时必须由人接管全部可配置可观测。做类比氛围编码像是让一个能力强但不熟悉团队规则的实习生放开手写代码SDD 是给他一份列清楚验收标准的任务书Harness 是给整条流水线装上仪表盘和安全阀。所谓 AI 原生软件工程不是把 AI 塞进旧流程里当打字机而是围绕 AI 的能力重新设计需求、实现、验证、交付的链路让 AI 在边界内干活人在关键节点做决策。2. SDD 规范驱动开发把模糊需求变成可测试契约2.1 为什么先写规范比多写 prompt 更管用我一开始也迷信 prompt 工程觉得把提示词写得越长越细AI 输出就越准确。实际测试下来prompt 越长前后矛盾的可能性反而越高因为模型只会“平均地”参考所有上下文。相比之下一份结构清晰的 spec 更稳定它把信息分成固定区块接口契约是一组机器可读的路径和格式验收标准是一组可以执行断言的句子模型不容易漏掉关键约束。我做过一个直接对比。普通 prompt 是“给前端写一个创建用户的接口”模型会自由发挥可能返回 200可能返回 201错误格式每次都不一样。改成 spec 里的写法之后“根据 spec/todos.md 实现。POST /todos 接收 title 和 due_date返回 201 和 todo 对象未登录用户一律返回 401title 为空返回 422。”模型的可选择空间被压缩了出错率大幅下降。人不一定要写详细设计但一定要把那些不可妥协的规则说清楚。2.2 一份合格的 spec 长什么样我在实践中会固定用几个区块顺序也很讲究背景与目标、范围、契约、数据模型、业务规则、验收标准、禁止事项。顺序决定了模型理解时的权重背景和目标要让模型知道为什么做范围要告诉它别碰什么契约才是硬约束。下面是我常用的 spec 模板以带认证的待办事项 API 为例# 待办事项 API Spec ## 背景与目标 用户需要管理自己的待办事项支持创建、列表、标记完成。 ## 范围 - IN: 用户注册、登录、待办的核心接口 - OUT: 不做后台管理端不做团队协作不做提醒 ## 接口契约 - POST /auth/register - 201 {id, username} - POST /auth/login - 200 {token} - POST /todos - 201 {id, title, done} - GET /todos - 200 {items: []} - PATCH /todos/{id} - 200 {id, title, done} ## 数据模型 - User: id, username, password_hash, created_at - Todo: id, user_id, title, done, created_at, due_date ## 业务规则 - 用户只能访问自己的 Todo越权返回 403 - title 为空时返回 422 - 所有时间字段使用 ISO 8601 格式UTC ## 验收标准可执行断言 1. 未带 token 访问 GET /todos 返回 401 2. 用户 A 无法通过 PATCH 修改用户 B 的 todo返回 403 3. 创建 todo 成功后GET /todos 能查到该记录 4. 空 title 创建返回 422数据库无新增记录 ## 禁止事项 - 禁止在代码库中写入明文密钥 - 禁止引入未锁定版本的第三方依赖 - 禁止修改 spec 文件本身的验收标准这份 spec 通常一两百行就够不需要写到伪代码级。其中最有价值的是“禁止事项”区它能把 AI 最容易犯的错提前堵死。比如禁止修改验收标准就是防止模型在实现不了的时候悄悄把“考试题目”改简单。2.3 规范写多细才合适两个原则原则一契约硬、实现软。接口路径、状态码、数据模型、验收标准是契约必须写死内部类怎么划分、用什么框架、数据库访问用不用 ORM这些是实现建议可以不写或只给提示。原则二验收标准要能对应测试。每条验收标准最好能翻译成一条测试断言而不是“响应应该很快”这种模糊表述。写 spec 的时候我会反复问自己这条标准 AI 能通过吗我能自动化验证吗如果两个答案都是否它就还没有资格进入 spec。另一个分寸问题是别把 spec 写成设计文档。我见过团队拿 SDD 的名义写了上百页详细设计结果 AI 没节省时间人先累死了。SDD 的目标是压缩歧义不是把实现方案都定死。好的 spec 是需求方和 AI 之间的接口契约而不是一份蓝图。3. Harness 工程 AI让模型的每一步都被编排和验证3.1 Harness 不是模型是 AI 的编排层这里说的 Harness不是某一家公司的产品名而是一类把大模型编码能力收编进工程流水线的框架。热词里经常出现 DeepSeek Harness、Claude Code 实战、CodeBuddy 的 Harness 案例说的都是同一个思路模型还是那个模型但我们不让它裸奔而是给它戴上一套“驾驶系统”——包括上下文装配、工具调用、沙箱执行、自动评估、反馈循环、人工审核闸门。直接用 Chat 窗口和用 Harness 的区别就像让一个开发者在没有任何规范、没有测试环境、没有 Code Review 的情况下提交代码和让他按 CI/CD 流水线走一遍再合并的区别。后者明显多了一层保障。围绕 DeepSeek 构建的 Harness 让人可以在本地或私有化环境里部署模型再通过工作流插件对接到代码仓库、测试框架和安全检查工具这是很多团队愿意尝试它的原因。3.2 核心模块拆解Harness 最核心的价值是把模型执行过程拆成可独立开关、可观测、可替换的环节。下面这六个模块基本覆盖了一条完整的 AI 编码流水线模块职责常见落地形式上下文装配决定给模型看哪些文件、哪些 spec、哪些历史决策自动读取 spec、索引、最近提交 diff工具调用让模型在受限范围内执行命令、读写文件白名单 shell、文件读写 API、Git 操作封装沙箱执行隔离生成代码的运行环境Docker 容器、临时目录、受限网络自动评测用测试和规则判断生成结果是否合格pytest、lint 规则、安全扫描、契约测试反馈循环把失败信息结构化地回传给模型进行下一次迭代失败日志、测试输出、错误摘要人审闸门在关键节点要求人工确认生成 diff 后等待 approve敏感操作用人工授权每个模块单独看都不算新但组合起来的效果是质变模型从一个“生产代码的野马”变成了一个“在跑道内反复试跑的选手”。尤其是反馈循环和人审闸门的组合它让 AI 的每一次失败都变成可追溯的学习材料而不是对话框里的一条错误信息。3.3 DeepSeek Harness 的落地形态示例我演示用的配置里Harness 通过一个 workflow 文件描述整条链路。它负责在每一轮迭代前把 spec 注入上下文限定模型只能读取 src 和 tests 目录检测到测试失败后把失败信息回写并把最终改动整理成 diff 等待人工审核。下面是一个反映常见结构的示意配置workflow: name: spec-driven-api model: deepseek-chat context: spec_path: ./spec/todos.spec.md read_dirs: [src, tests] write_dirs: [src, tests] steps: - name: generate input: spec target: src/ - name: test command: pytest - name: lint command: ruff check src tests - name: security-scan command: bandit -r src gates: on_fail: feedback max_iterations: 5 require_human_review: true这不是某个固定产品的真实配置而是反映常见结构的示例。你手里的 DeepSeek Harness 版本可能把 workflow 叫 pipeline或把 gates 叫 quality gates但核心思路一致。Skill 机制也是这个生态里很实用的一部分你可以把“先写 spec、再生成实现、最后跑测试”这整套动作封装成一个 skill后续项目里一键调用连配置都不用重写。4. 实操实录用 SDD Harness 走通一个 API 项目闭环4.1 场景与目标我挑一个很常见的场景开发一个带认证的待办事项 API。之所以选它是因为它涉及用户鉴权、数据隔离、校验、异常处理足够体现 SDD 的约束力和 Harness 的兜底价值。目标是让 AI 在尽量少的人工干预下产出一个能通过全部验收测试的版本。这个场景很适合作为团队的第一个 SDD 试点业务逻辑不复杂但又有明确的越权、鉴权边界测试容易写验收标准也容易自动化。一旦这套流程跑通再往复杂业务推广团队对 AI 产出的信任基础已经有了。4.2 第一步编写 spec参照第 2 节的规范我把需求拆成接口契约和验收标准。这个动作看起来是在写文档实际上是在为后续所有环节建立事实源。Spec 是需求方给 AI 的“考题”也是 Harness 给 AI 的“评分标准”没有它后面所有测试都失去依据。写完 spec 后我会自己读三遍第一遍看需求方懂了没有第二遍看 AI 会不会有歧义第三遍看每条验收标准能不能变成测试。这一步非常关键spec 里的模糊点之后一定会变成 AI 的迷惑点而 Harness 不会帮我们理解需求它只会把需求执行得更彻底。也就是说spec 里的每一个坑最后都会原封不动地出现在代码缺陷里。4.3 第二步定义 Harness 工作流这一步相当于给 AI 立规矩。我配置的 workflow 有几个关键决策第一让 AI 只能读写 src 和 tests 目录防止它乱改配置文件第二先跑测试再跑 lint 和安全扫描每个步骤失败都作为反馈进入下一轮第三最多迭代五轮超过就必须人工介入。为什么测试要在生成之后就立刻跑因为 AI 生成代码的认知盲区在于它看不到自己代码的运行效果。它以为写完了实际上路由没注册、依赖没注入、鉴权中间件没接。只有让测试结果直接反馈回上下文它才有机会真正修正行为。如果只是让它继续写迭代会变成原地打转甚至越改越乱。4.4 执行现场与结果实际执行时我看到的日志大致是这样的[1/5] generate: spec read, 8 files written [1/5] test: FAIL 2/14 (missing auth on GET /todos) [1/5] feedback: 401 check missing, see test_todo_auth.py:18 [2/5] generate: added auth middleware, updated routers [2/5] test: PASS 14/14 [2/5] lint: 3 warnings (unused import) [2/5] security-scan: no issues [2/5] human_review: pending - approved第一次生成大概率会因为忘记校验鉴权而挂掉两个测试Harness 会把断言失败的位置和期望行为回传给模型。第二次迭代时模型会补上中间件和依赖注入。整个过程中人需要做的是在最后看 diff、确认 spec 没有被偷改、然后合并。整条链路跑下来AI 第一次通过率大概在百分之七八十剩下的由反馈循环补足。这里有个容易被忽略的点不要让 AI 修改 spec 或测试来“迎合”实现结果。我在 feedback 提示语里会固定写明禁止修改 tests 和 spec否则模型很可能选择删掉失败的测试来让流水线变绿那整个门禁就形同虚设了。这属于典型的“作弊行为”必须从机制上堵死。5. 高发问题排查与避坑参考5.1 插件加载失败Harness 最常见的启动问题很多人在安装 DeepSeek Harness 时会碰到harness failed to load plugins或者web boot: 2 entries did not activate这类报错。这个报错我很熟悉基本都出在插件目录和版本匹配上。Harness 的插件机制会在启动时扫描 plugins 目录逐个验证插件清单和主程序约定的接口版本只要有一个插件没有正确声明依赖或版本对不上就会在启动阶段被标记为未激活。遇到这类报错第一反应不要是重装。先打开日志确认具体是哪几个条目没激活再验证插件目录里有没有重复版本。下面是常见的排查思路现象可能原因处理方式插件未激活插件与主程序版本不匹配查看插件 manifest 中的 apiVersion与主程序文档核对启动报 entries did not activate插件清单字段缺失或依赖未安装用 debug 模式启动定位具体是哪几个条目未激活安装过程反复失败依赖子组件缺失按官方文档补齐依赖后重试不要重复执行同一条安装命令我自己的教训是这类报错大部分和插件目录结构有关插件的配置文件需要放在指定层级放错一层就会启动失败。所以排查时先看目录树再看日志不要盲目更新主程序版本。5.2 模型输出不稳定怎么判断该不该信任即便有 Harness模型有时也会输出风格差异很大的代码。我的处理方法是把“稳定”寄托在测试与契约上而不是模型复现的一致性上。每个版本先跑测试和 lint任何失败都进入反馈循环同一轮迭代内只让 AI 修改一个明确目标不要同时提“加功能、重构、修样式”这种多指令请求。上下文过长时我会从反馈信息中裁剪掉早期对话只保留最近一轮的状态快照防止模型被淹没在历史里。还有一个原则值得强调AI 生成的代码必须能回滚。Harness 的项目目录我用 Git 快照管理每一轮迭代生成前都会记一次 tag如果第四轮把一切都改崩了我会回滚到第二轮再调整约束而不是让 AI 在错误版本上继续修补。这样既节省时间也避免让失败状态污染后续上下文。5.3 团队落地从试点到门禁如果团队要引入这套流程我的建议是别一上来就全量切换。选一个非核心模块比如内部工具的后端 API试跑两周。Spec 评审要纳入日常例会让需求方、开发、测试一起过一遍验收标准AI 生成的代码必须有专人 Code Review团队约定里写清楚“模型产出不等于可直接合入”。安全边界同样要注意给模型的工具权限默认最小化不要让它访问生产数据库不要给它生产环境的 API Key。Harness 执行环境最好与 CI 集成让每次 AI 提交都走同样的测试与扫描流水线。等流程稳定后再逐步扩大到更核心的业务模块。我见过最快的团队用了三周就把一条主力业务接口的迭代切到了 SDD Harness 流程上前提是前面的试点把坑都踩完了。回顾我自己从氛围编码切换到 SDD Harness 的过程最大的感受不是“AI 变聪明了”而是“我们要对 AI 说的话变少了但要说清楚了”。以前我会花大量时间在对话框里反复调 prompt像在跟一个记忆很短的同事解释同一个需求现在我把绝大部分精力放在写 spec 和调工作流上模型只需要被正确约束它就能稳定地做好剩下的活。最后分享一个小技巧每次写完 spec先别急着丢给 AI自己照着验收标准假装执行一遍如果中途你会冒出“这个情况算不算满足”的疑问那 AI 一定也会迷路先把它在 spec 里写死再开始。这套流程不一定适合所有项目但对认真交付的团队来说它值得一试。