AI 编程新范式:Vibe、Agentic 与 Spec 实战指南
从「让 AI 写代码」到「让 AI 按契约交付」------10 个章节,一条由浅入深的完整实践路径。
文中涉及厂商自述的量化指标均标注来源与口径,正式引用前请以发布方官方口径复核。
目录
- 三种编程范式的核心差异与企业应用场景
- [Vibe Coding 自然语言驱动开发快速上手](#Vibe Coding 自然语言驱动开发快速上手)
- [Agentic Coding 智能体工作流环境搭建](#Agentic Coding 智能体工作流环境搭建)
- [Spec Coding 规格说明书生成代码实操](#Spec Coding 规格说明书生成代码实操)
- 从需求分析到代码落地的完整演进路径
- 多范式混合使用的最佳实践策略
- 常见生成错误分析与精准排错技巧
- [提升 AI 编程产出质量的关键提示词方法](#提升 AI 编程产出质量的关键提示词方法)
- 本地项目集成与自动化测试验证流程
- 面向未来的开发者技能转型与进阶建议
01 三种编程范式的核心差异与企业应用场景
在动手之前,先把三个词的坐标系搞清楚,再把镜头拉到企业现场------看不同职能、不同变更、不同合规要求下,各自该落在哪一档。后面的 9 章都建立在这一章的地基上。
1.1 一句话定位三种范式
Vibe Coding
凭感觉下指令,不看代码只看结果。用自然语言反复描述现象,逼近一个"能跑起来"的东西。它是探索工具,不是交付方式。
Agentic Coding
把执行权交给智能体。AI 能自己规划、读写文件、跑命令与测试、根据报错自我修正。它描述的是执行方式,不规定意图怎么写。
Spec Coding
**先写结构化规格,再让智能体照着做。**规格(而非代码)是真相源与契约。它解决的是 Agent 变强后暴露的新瓶颈:AI 不知道该写什么。
1.2 关键认知:它们不在同一个维度
把三者平铺对比会造成严重误解。正确的坐标系是两条正交的轴:横轴是「AI 自主度」(执行方式) ,纵轴是「意图的形式化程度」(契约方式)。Vibe 和 Spec 是横轴之上的两种契约模式,Agentic 描述的是横轴的高端位置。
图 1 | Vibe 与 Spec 是「契约层」的两端,Agentic 是「执行层」的高端位置------三者不是并列关系。
| 低形式化(意图即写即弃) | 高形式化(规格是契约 / 真相源) | |
|---|---|---|
| 低自主(人写代码) | 传统文档驱动开发 · 重规格 · 零自主(瀑布模式) | AI 自动补全时代 · 低自主 · 低形式化(2021--22) |
| 高自主(AI 执行) | Vibe Coding · 高自主 · 低形式化 · 意图只活在一次性对话里 | Spec Coding / Agentic Eng. · 高自主 · 高形式化 · 产出可追溯 |
为什么这个坐标系重要
它解释了 Karpathy 为什么在 2025 年提出 Vibe Coding、不到一年又改口说"我们进入的是 agentic engineering"------他不是在推翻自己,而是从右上象限的视角指出:光有高自主不够,还得有高形式化。也解释了为什么 Claude Code / Cursor 的 Plan 模式只算"最轻量的 spec-first":意图先对齐再执行,但方案单次会话、用毕即弃,没有 constitution、没有归档回路。
1.3 全维度对比
| 维度 | Vibe | Agentic | Spec |
|---|---|---|---|
| 本质定位 | 低摩擦的探索方式 | AI 自主执行的工程能力 | 以规格为契约的研发方法论 |
| 真相源 | 对话历史(易失) | 代码 + 规则文件 | 规格文档(可版本控制) |
| 验证方式 | 主观:"跑起来就行" | 自动化:编译 / 测试 / lint | 规格对齐 + 验收标准 + 测试 |
| 适用规模 | 单文件、单次会话、原型 | 多文件、跨模块、长任务 | 跨人、跨会话、长期维护的系统 |
| 上手成本 | 极低 | 中:需会写规则文件与测试 | 较高:需规格写作与流程纪律 |
| 典型失败模式 | 意图漂移、幻觉接口、上下文坍塌 | 范围蔓延、级联错误、工具误用 | 过度设计、评审过载、流程僵化 |
| 团队协作 | 基本无法协作 | 可协作但缺共享契约 | 规格即协作界面 |
1.4 企业场景全景:谁在什么环节用哪一种
在企业里,范式选择几乎不由"技术偏好"决定,而由三个客观因素决定:谁在做(职能)、做什么(变更类型)、受什么约束(行业合规)。下面把这三个维度依次铺开,这也是本章最实用的一张对照地图。
1.4.1 按企业职能:每个角色该用哪一种
| 职能 / 角色 | 典型 AI 任务 | 推荐范式 | 判断理由与主要风险 |
|---|---|---|---|
| 产品 / 业务分析 | 需求原型、流程草图、竞品拆解 | Vibe | 零成本试错,产出物不进生产库。**风险:**原型被当成需求直接交付 |
| 前端 / 应用开发 | 页面迭代、组件抽象、样式微调 | Agentic + 轻量 Spec | 有 diff 与视觉回归兜底。**风险:**范围蔓延、重复造轮子 |
| 后端 / 核心服务 | 接口、数据模型、事务与并发逻辑 | 完整 Spec + Agentic | 涉及契约与数据,必须可追溯。**风险:**幻觉接口、级联错误 |
| 测试 / 质量工程 | 用例生成、边界补充、回归脚本 | Agentic(强验证约束) | 测试是 Agent 的方向盘。**风险:**覆盖真空------自己生成自己测 |
| 运维 / SRE | 部署脚本、告警规则、故障复盘 | Vibe → 归档固化 | 先跑通再固化,脚本必须留档。**风险:**直接对生产环境动手 |
| 数据 / 算法 | 取数脚本、特征工程、Notebook 分析 | Vibe / Agentic | 探索性高,但结果需可复算。**风险:**口径不一致、结论不可复现 |
| 安全 / 合规 | 扫描规则、威胁建模、审计报告 | Spec 优先 | 需要依据与留痕。**风险:**依赖生成结论、缺独立验证 |
| 技术负责人 / 架构师 | 规范、模板、架构决策、效能度量 | Spec(治理层) | 规范即代码,需版本化与评审。**风险:**规范漂移、写了没人遵守 |
1.4.2 按变更类型:规格该写到多深
| 变更类型 | 典型例子 | 推荐范式 | 规格深度 | 爆炸半径 |
|---|---|---|---|---|
| 一次性、可丢弃 | 临时报表、数据清洗、格式转换 | Vibe | 不写规格 | 极小 |
| 小步、可逆 | 文案样式、单文件修复、补注释 | Vibe / Agentic | 一句话验收 | 小 |
| 模块级 | 新增接口、重构一个类、补一个字段 | Agentic + 轻量 Spec | 验收标准 + 接口契约 | 中 |
| 跨模块 | 表结构变更 + 多端适配 + 数据迁移 | 完整 SDD | 四文档 + ADR 记录 | 大 |
| 核心 / 受监管 | 支付、权限、账务、风控、对账链路 | 完整 Spec + 强门禁 | 四文档 + ADR + 人工签核 | 极大 |
图 2 | 企业真实的一天不是"选一种范式",而是三种范式按时间顺序交替出现------这正是第 6 章要讲的分层策略。
| 维度 | 上午 · 探索(Vibe) | 白天 · 实现(Agentic) | 傍晚 · 沉淀(Spec) |
|---|---|---|---|
| 典型活动 | 把想法变成可交互原型 摸清新框架 / 新 API 行为 一次性脚本与数据清洗 快速验证需求是否成立 | 单模块功能迭代 Bug 定位与修复 重构与批量改名 先写失败测试再实现 | 跨模块变更先立规格 接口 / 数据模型评审 记录 ADR 关键决策 归档为下次变更基线 |
| 产出 | 可运行 Demo,不入主干 | 可评审的 diff + PR | 可追溯的契约文档 |
贯穿全天:版本控制 · 自动化测试 · CI 质量门禁 · 人工评审 · 审计留痕
1.4.3 按行业与合规约束:合规会直接改写技术选型
| 行业 / 属性 | 核心约束 | 范式倾向 | 额外硬性要求 |
|---|---|---|---|
| 金融 / 银行 | 可审计、可追溯、变更留痕 | Spec 主导,Agentic 执行 | 每笔变更能解释"为什么";禁止直连生产库;双人复核;Agent 不持有生产凭据 |
| 医疗 / 健康 | 隐私合规、数据敏感 | Spec 主导 | 数据脱敏;Agent 不接触生产患者数据;操作全程留痕 |
| 政企 / 国企 | 流程合规、信创适配 | Spec 主导 | 全流程审批留痕;文档先行;变更可回溯到具体规格版本 |
| 互联网 / SaaS | 迭代速度、灰度能力 | Agentic 为主 + 轻量 Spec | 契约测试兜底;强灰度与一键回滚;上线后监控告警齐备 |
| 传统制造 / 工业 | 产线安全、实时性 | Spec 主导,Agentic 受限 | 硬实时逻辑不交给 Agent;先离线 / 仿真验证再上产线;设备参数需人工签核 |
| 企业内部工具 | 低风险、需求量大 | Vibe 为主 | 凭据不外泄;产物发布前人工过一遍;避免把内部敏感数据贴进外部工具 |
1.4.4 三个典型企业剧本
剧本 A · 运营临时看板
**背景:**运营要一张"本周各渠道转化"的临时看板,明天就要看。
**怎么做:**用 Vibe 直接生成取数脚本 + 简易看板页面,跑通即可。
**为什么用 Vibe:**一次性、明天就废弃、唯一用户就是运营本人。
**落地要求:**不进主干仓库;数据库用只读账号;用完即弃。
剧本 B · 订单模块迭代
**背景:**订单列表要支持按渠道筛选,并修复一处金额精度问题。
**怎么做:**先写一段验收标准 + 明确"不做什么",再让 Agent 按任务逐个实现。
**为什么不用完整 SDD:**改动局限在单模块、同一人负责、可快速回滚。
**落地要求:**先补失败测试;每任务 30--90 分钟;全量测试通过再合并。
剧本 C · 权限模型重构
**背景:**RBAC 要支持数据行级权限,涉及 12 张表与全部接口。
**怎么做:**四文档齐备------constitution 定安全红线,requirements 写 EARS 验收,design 记录数据模型与 ADR,tasks 拆到可勾选。
**为什么必须完整:**跨人协作、受审计、长期维护、错了影响全系统授权。
**落地要求:**规格进版本库;关键节点人工签核;Agent 只在受限分支与只读库上工作。
企业里最常见的三个翻车现场
**① 原型直连生产。**Vibe 做出的"能跑"版本被当成成品交付,缺权限校验、审计日志与异常兜底。**② 规范只写不守。**AGENTS.md 写了"禁止直连生产库",却没在工具权限上真正限制,Agent 照样连了------规则引导行为,但不是安全边界 。
**③ 审查成橡皮图章。**让另一个 Agent"审查"AI 写的代码,却没有机器可判定的判据。审查 Agent 只会说"看起来不错"------这不叫审查,这叫多烧 token。
1.5 场景速选:这次任务该用哪一种
| 场景 | 推荐范式 | 判断依据 |
|---|---|---|
| 0→1 原型、一次性脚本、学习新栈 | Vibe | 爆炸半径小、活不过一周,规格收益覆盖不了成本 |
| 单人负责的模块、Bug 修复、重构 | Agentic + 轻量 Spec | 先写一句验收标准,成本增加 <10%,返工率显著下降 |
| 多人协作 / 核心系统 / 受监管链路 | 完整 SDD | 需要可追溯、可审计、跨人共享的单一真相源 |
| 维护十年以上的存量系统 | Spec-anchored | 以「变更」为单位积累规格,逐步把隐性知识显式化 |
本节的四个结论
① 不是三选一 :Agentic 是执行底座,Vibe 与 Spec 是底座之上的两种契约模式。现实主流是「Spec 定契约 + Agent 执行 + Vibe 探索」的三层结构。② 判断标准是「爆炸半径」 :改动会影响多少人、多久、多核心,决定你该投入多深的规格。
③ Vibe 不是低级 :它把"想法→可交互实物"从天级压到分钟级,这个价值无可替代;错的只是把它用在长生命周期的生产系统上。
④ 企业里由职能与合规定档 :角色、变更类型、行业约束三个维度会直接给出答案------合规等级越高、爆炸半径越大,就越往 Spec 收;越靠探索与效率,就越往 Vibe 放。
02 Vibe Coding 自然语言驱动开发快速上手
Vibe 的价值是把"想法→可交互实物"的时间从天级压到分钟级。这一节教你三分钟上手,同时给出不翻车的边界。
2.1 三分钟上手流程
图 3 | Vibe 的循环:描述 → 生成 → 贴现象 → 再生成。核心技巧是"用现象代替评价"。
#mermaid-svg-c1Z6mfHbPiKSMCMI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-c1Z6mfHbPiKSMCMI .error-icon{fill:#552222;}#mermaid-svg-c1Z6mfHbPiKSMCMI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-c1Z6mfHbPiKSMCMI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .marker.cross{stroke:#333333;}#mermaid-svg-c1Z6mfHbPiKSMCMI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-c1Z6mfHbPiKSMCMI p{margin:0;}#mermaid-svg-c1Z6mfHbPiKSMCMI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .cluster-label text{fill:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .cluster-label span{color:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .cluster-label span p{background-color:transparent;}#mermaid-svg-c1Z6mfHbPiKSMCMI .label text,#mermaid-svg-c1Z6mfHbPiKSMCMI span{fill:#333;color:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .node rect,#mermaid-svg-c1Z6mfHbPiKSMCMI .node circle,#mermaid-svg-c1Z6mfHbPiKSMCMI .node ellipse,#mermaid-svg-c1Z6mfHbPiKSMCMI .node polygon,#mermaid-svg-c1Z6mfHbPiKSMCMI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .rough-node .label text,#mermaid-svg-c1Z6mfHbPiKSMCMI .node .label text,#mermaid-svg-c1Z6mfHbPiKSMCMI .image-shape .label,#mermaid-svg-c1Z6mfHbPiKSMCMI .icon-shape .label{text-anchor:middle;}#mermaid-svg-c1Z6mfHbPiKSMCMI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .rough-node .label,#mermaid-svg-c1Z6mfHbPiKSMCMI .node .label,#mermaid-svg-c1Z6mfHbPiKSMCMI .image-shape .label,#mermaid-svg-c1Z6mfHbPiKSMCMI .icon-shape .label{text-align:center;}#mermaid-svg-c1Z6mfHbPiKSMCMI .node.clickable{cursor:pointer;}#mermaid-svg-c1Z6mfHbPiKSMCMI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .arrowheadPath{fill:#333333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-c1Z6mfHbPiKSMCMI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-c1Z6mfHbPiKSMCMI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-c1Z6mfHbPiKSMCMI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-c1Z6mfHbPiKSMCMI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .cluster text{fill:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI .cluster span{color:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-c1Z6mfHbPiKSMCMI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-c1Z6mfHbPiKSMCMI rect.text{fill:none;stroke-width:0;}#mermaid-svg-c1Z6mfHbPiKSMCMI .icon-shape,#mermaid-svg-c1Z6mfHbPiKSMCMI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-c1Z6mfHbPiKSMCMI .icon-shape p,#mermaid-svg-c1Z6mfHbPiKSMCMI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-c1Z6mfHbPiKSMCMI .icon-shape .label rect,#mermaid-svg-c1Z6mfHbPiKSMCMI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-c1Z6mfHbPiKSMCMI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-c1Z6mfHbPiKSMCMI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-c1Z6mfHbPiKSMCMI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不满意回到此
① 说清"做完的样子"
一句话描述可见结果
② 让它先生成
不打断,先看整体效果
③ 贴现象去微调
贴报错原文,不说"不对"
④ 能跑就提交
立刻 git commit
2.2 工具选择
| 工具 | 适合 | 特点 |
|---|---|---|
| Bolt.new / v0 / Lovable | 从 0 起一个可交互页面 | 浏览器内即时预览,非程序员友好,适合验证 UI 想法 |
| Replit Agent | 边写边跑、要托管 | 云端环境开箱即用,适合小工具与教学 |
| Cursor Composer | 已有仓库里做原型 | 多文件编辑能力强,可在真实项目内探索 |
2.3 让 Vibe 少翻车的表达技巧
| 不要说 | 改成 |
|---|---|
| "这个按钮不好看" | "按钮再大一点,主色改成品牌蓝 #185FA5,圆角 8px" |
| "有 bug" | "点提交后页面空白,控制台报错原文如下:<粘贴完整报错>" |
| "加个登录" | "加一个邮箱+密码登录页,登录成功跳到 /dashboard,失败在按钮下方显示红字提示" |
| "优化一下" | "列表超过 50 条时改成虚拟滚动,首屏渲染 < 200ms" |
2.4 三条自保规则
-
**先定验收,再开聊。**哪怕一句话:"做完后,我要能在 X 页面点 Y,看到 Z。"这一个习惯对结果质量的提升,超过换任何工具。
-
**小步提交。**每得到一个能跑的状态就
git commit。Vibe 的致命伤是"改着改着回不去了",频繁提交是唯一的解药。 -
**设置转正门槛。**原型一旦决定长期维护,必须补三样东西:类型/测试、一份简短规格、一次人工代码走查。这一步叫"从 vibe 到工程的转股",跳过它,原型就会变成技术债的发源地。
别在错误的场景用 Vibe
生产系统、权限/认证/支付/删库逻辑、多人协作的同一代码库、跨会话的中大型特性、受监管行业的核心链路------这些场景里 Vibe 的"边际成本随项目变长急剧上升"会迅速反噬。
03 Agentic Coding 智能体工作流环境搭建
Agentic 时代,你最重要的"代码"不是业务逻辑,而是那套决定 AI 行为边界的项目上下文。本节把它拆成可照抄的四件套。
3.1 核心理念:环境就是上下文装配
同一个模型,在同一个项目上表现可能天差地别,差别几乎全来自"喂给它的上下文质量"。所以搭建 Agentic 工作流的第一件事,不是选工具,而是把项目知识装配成机器可读的结构。现代主流 Agent 用四个机制完成这件事------它们分工清晰、互不替代:
| 机制 | 回答什么问题 | 典型载体 |
|---|---|---|
| 项目规则 | 这个项目该怎么做事? | AGENTS.md(跨工具标准)/ CLAUDE.md(Claude Code) |
| 技能 Skill | 某类重复任务怎么做? | SKILL.md,按需加载,不占常驻上下文 |
| 工具 MCP | 怎么访问外部系统与数据? | .mcp.json / .cursor/mcp.json 等 MCP 配置 |
| 子代理 Subagent | 哪类任务可以隔离出去? | 独立上下文 + 工具白名单(最小权限) |
一句话原则
规则(Rules)管"该怎么做",MCP 管"能碰到什么" ------两者要在同一个仓库里互相引用。例如AGENTS.md里应写"查表结构用db-readonly这个 MCP server,禁止直连生产库"。规则文件引导行为,但它不是安全边界;硬约束必须落在权限、hooks 与 CI 上。
3.2 仓库上下文结构(可直接照抄)
图 4 | 左侧是文件放在哪,右侧是加载优先级------常驻上下文要瘦,详细约定按需拉取。
| 仓库根目录(常驻上下文) | 分层加载原则(按需拉取) |
|---|---|
AGENTS.md --- 项目规则:命令 / 约定 / 禁区 |
① 全局规则(组织级):~/.claude/CLAUDE.md --- 跨项目通用偏好 |
CLAUDE.md --- 首行 @AGENTS.md,仅补工具专属内容 |
② 项目规则(仓库级):AGENTS.md --- 本仓库的约定与命令 |
.mcp.json --- MCP server 定义(不含密钥) |
③ 目录规则(模块级):.cursor/rules/*.mdc / .claude/rules/ 按 glob 生效 |
.agent/ 或 devprompts/ --- 分主题的详细约定(按需引用) |
④ 任务时上下文:按需检索 / 注入,用完即走,不常驻 |
.claude/skills/ --- SKILL.md:重复流程,按需加载 |
原则:常驻的越少越好,按需的越准越好 |
.claude/agents/ --- 子代理定义(工具白名单) |
3.3 AGENTS.md 该写什么(写错了等于没写)
最常见的失败是把 AGENTS.md 写成"偏好清单"或"架构说明书"。它不是文档,而是能约束行为的契约 。检验标准只有一条:Agent 在你不在场时,能否仅凭这份文件做对事。
| 该写 | 示例(好) | 不该写(坏) |
|---|---|---|
| 精确命令 | 提交前运行 pnpm test:unit,全绿才能 commit |
"记得测试你的改动" |
| 硬性边界 | 不得修改 packages/infra/ 与任何 *.sql 迁移 |
"小心不要改坏东西" |
| 项目结构要点 | 业务代码在 src/modules/*,共享工具在 src/shared |
大段架构散文 |
| 约定与惯用法 | 错误统一抛 AppError,禁止返回裸字符串错误 |
"代码要写得优雅" |
| 延伸阅读指针 | API 规范见 devprompts/api-patterns.md |
把全部细节内联进规则文件 |
# AGENTS.md(示例骨架,控制在 100--200 行)
## 项目概览
Spring Boot 3.3 + JPA 的 RBAC 权限服务。单体部署,本地文件存储。
## 常用命令
- 构建:mvn -q clean package
- 单元测试:mvn test
- 提交前必跑:mvn verify(含 Checkstyle + 测试)
- 单类测试:mvn test -Dtest=ClassName
## 代码约定
- 分层:controller → service → repository,禁止跨层直调
- 错误处理:统一抛 BusinessException,由 @ControllerAdvice 转响应
- 命名:接口 I 前缀,实现 XxxImpl
- 新增依赖必须说明理由,且不得引入 Lombok 之外的注解处理器
## 禁区(硬约束)
- 不得修改 src/main/resources/db/migration/**(迁移脚本需人工评审)
- 不得改动 application-prod.yml
- 不得访问生产数据库(MCP 仅提供 db-readonly)
## 延伸阅读
- API 契约:devprompts/api-patterns.md
- 测试规范:devprompts/testing-guidelines.md
三个易踩的坑
① 重复即失效 :任何与代码/配置重复的信息都会过期,用"指向脚本/文件"代替"复述内容"。② 常驻成本 :规则文件每次会话都会加载、消耗 token;冗长的多步流程应移入 Skill(按需加载)。
③ 语义漂移 :半年后没人更新规则文件,AI 会忠实遵守一份已经过时的约定------把"更新 AGENTS.md"写进 PR 检查清单,并在 CI 里加一个路径漂移检查(验证文件中提到的路径/命令真实存在)。
3.4 MCP:跨工具的工具层契约
MCP 是 Agent 连接外部系统(数据库、内部 API、工单系统)的事实标准接口。要注意:规则层没有跨工具标准,但工具层有------MCP 就是那个标准;只是各工具的配置文件路径与字段名不同,需要分别生成。
| 工具 | 配置文件路径 | 字段约定 |
|---|---|---|
| Claude Code | .mcp.json(项目根) |
顶层 mcpServers;注意不是 .claude/mcp.json |
| Cursor | .cursor/mcp.json |
顶层 mcpServers |
| VS Code / Copilot | .vscode/mcp.json |
用 servers 键,不是 mcpServers |
| Codex CLI | .codex/config.toml(项目)或 ~/.codex/config.toml(全局) |
TOML 格式 |
// .mcp.json(Claude Code / Cursor 通用结构;密钥用环境变量引用)
{
"mcpServers": {
"db-readonly": {
"command": "npx",
"args": ["-y", "@myorg/mcp-postgres-ro"],
"env": { "DATABASE_URL_RO": "${env:DB_URL_RO}" }
}
}
}
安全红线
一个 MCP server 可能持有凭据并访问真实系统。**配置文件与密钥不得进入共享或全局可读路径;只授予它完成任务所需的最小权限。**用环境变量引用密钥,并在.env.example里声明需要哪些变量。给 Agent 一个"只读"的数据库入口,就是把误删生产库的概率降到接近零的最简单办法。
3.5 分步搭建清单
-
**锁定验证环境。**先把测试框架跑到能一键执行(
mvn verify/pnpm test)。没有可自动判定的验证信号,Agentic 就没有方向盘与刹车,这一步不能跳过。 -
**写 AGENTS.md。**运行一次工具的
/init生成初稿,再按 3.3 的表逐条改造,压到 100--200 行,命令与边界放最前。 -
**拆出 devprompts/。**把长约定(API、测试、数据库、部署)拆成按主题的文件,AGENTS.md 只留指针。
-
**配 MCP(按需)。**先只接只读数据源,密钥走环境变量,配置提交进版本库但不含密钥。
-
**加 hooks 与权限。**危险命令(删除、强推、写生产库)设为人工确认;在 CI 里加规则文件的路径漂移检查。
-
**跑一次基线任务。**选一个中等复杂度的真实任务,观察 Agent 是否能在不追问的情况下走完闭环,把暴露的歧义逐条补回 AGENTS.md。
环境就绪的判据
把仓库交给一个"第一次接触它的 Agent",它能仅凭 AGENTS.md + 代码完成一次改动并通过验证,不需要你在旁边反复解释。达到这个状态,环境就算搭好了。
04 Spec Coding 规格说明书生成代码实操
Spec 的关键不在"写得多",而在"把 Agent 必然会自行猜测的决策点全部写死"。这一节给出一套可复用的四文档结构与一份真实示例。
4.1 四文档的单向约束关系
图 5 | 四份文档各回答一个问题,且前者约束后者。这是 SDD 与"随便写点提示词"的本质区别。
#mermaid-svg-YiM3mAft72JizhXA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YiM3mAft72JizhXA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YiM3mAft72JizhXA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YiM3mAft72JizhXA .error-icon{fill:#552222;}#mermaid-svg-YiM3mAft72JizhXA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YiM3mAft72JizhXA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YiM3mAft72JizhXA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YiM3mAft72JizhXA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YiM3mAft72JizhXA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YiM3mAft72JizhXA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YiM3mAft72JizhXA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YiM3mAft72JizhXA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YiM3mAft72JizhXA .marker.cross{stroke:#333333;}#mermaid-svg-YiM3mAft72JizhXA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YiM3mAft72JizhXA p{margin:0;}#mermaid-svg-YiM3mAft72JizhXA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YiM3mAft72JizhXA .cluster-label text{fill:#333;}#mermaid-svg-YiM3mAft72JizhXA .cluster-label span{color:#333;}#mermaid-svg-YiM3mAft72JizhXA .cluster-label span p{background-color:transparent;}#mermaid-svg-YiM3mAft72JizhXA .label text,#mermaid-svg-YiM3mAft72JizhXA span{fill:#333;color:#333;}#mermaid-svg-YiM3mAft72JizhXA .node rect,#mermaid-svg-YiM3mAft72JizhXA .node circle,#mermaid-svg-YiM3mAft72JizhXA .node ellipse,#mermaid-svg-YiM3mAft72JizhXA .node polygon,#mermaid-svg-YiM3mAft72JizhXA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YiM3mAft72JizhXA .rough-node .label text,#mermaid-svg-YiM3mAft72JizhXA .node .label text,#mermaid-svg-YiM3mAft72JizhXA .image-shape .label,#mermaid-svg-YiM3mAft72JizhXA .icon-shape .label{text-anchor:middle;}#mermaid-svg-YiM3mAft72JizhXA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YiM3mAft72JizhXA .rough-node .label,#mermaid-svg-YiM3mAft72JizhXA .node .label,#mermaid-svg-YiM3mAft72JizhXA .image-shape .label,#mermaid-svg-YiM3mAft72JizhXA .icon-shape .label{text-align:center;}#mermaid-svg-YiM3mAft72JizhXA .node.clickable{cursor:pointer;}#mermaid-svg-YiM3mAft72JizhXA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YiM3mAft72JizhXA .arrowheadPath{fill:#333333;}#mermaid-svg-YiM3mAft72JizhXA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YiM3mAft72JizhXA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YiM3mAft72JizhXA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YiM3mAft72JizhXA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YiM3mAft72JizhXA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YiM3mAft72JizhXA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YiM3mAft72JizhXA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YiM3mAft72JizhXA .cluster text{fill:#333;}#mermaid-svg-YiM3mAft72JizhXA .cluster span{color:#333;}#mermaid-svg-YiM3mAft72JizhXA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YiM3mAft72JizhXA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YiM3mAft72JizhXA rect.text{fill:none;stroke-width:0;}#mermaid-svg-YiM3mAft72JizhXA .icon-shape,#mermaid-svg-YiM3mAft72JizhXA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YiM3mAft72JizhXA .icon-shape p,#mermaid-svg-YiM3mAft72JizhXA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YiM3mAft72JizhXA .icon-shape .label rect,#mermaid-svg-YiM3mAft72JizhXA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YiM3mAft72JizhXA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YiM3mAft72JizhXA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YiM3mAft72JizhXA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} constitution.md
项目宪法 · 最高裁决权
requirements.md
要做什么 + 如何验收
design.md
怎么做 + 为何这样
tasks.md
先做什么 + 依赖谁
约束自上而下单向传递:下层不得推翻上层;歧义时以 constitution 裁决。
| 文档 | 回答的问题 | 关键内容 |
|---|---|---|
constitution.md |
不可变的全局原则 | 测试标准、架构约束、命名规范、安全红线(跨会话长期有效) |
requirements.md |
做什么 + 如何验收 | 用户故事 + 验收标准,推荐 EARS 句式 |
design.md |
怎么做 + 为何这样 | 架构、数据模型、API 契约、关键 ADR 决策记录 |
tasks.md |
先做什么 + 依赖谁 | 离散、可追踪、可逐个验证的实现任务 |
4.2 实操示例:一个"CSV 导出"功能的规格
先看一个坏 prompt,再看它对应的三份规格片段------差别不在字多,而在决策点是否被写死。
坏 prompt
「加一个把用户数据导出成 CSV 的功能,做得好看点。」
requirements.md(EARS 句式)
### REQ-001 导出入口
WHEN 管理员在用户列表页点击「导出」并选择时间范围,
THE SYSTEM SHALL 生成该范围内的用户数据 CSV 文件。
### REQ-002 字段与顺序
THE SYSTEM SHALL 按以下顺序输出列:
id, username, email, role, status, created_at
### REQ-003 大数据量策略
WHEN 导出行数 > 50000,
THE SYSTEM SHALL 改为异步生成,并在完成后以邮件发送附件,
且前端提示「导出已提交,稍后查收邮件」。
### REQ-004 编码兼容
THE SYSTEM SHALL 使用 UTF-8 with BOM 编码,以保证 Excel 直接打开无乱码。
### REQ-005 权限与审计
WHEN 发起导出,
THE SYSTEM SHALL 校验调用者具备 user:export 权限,
AND 记录一条审计日志(操作者、时间范围、行数、结果)。
### 明确不做什么(范围边界)
- 不导出已删除用户的历史快照
- 不提供自定义列选择(本期不做)
- 不支持导出为 Excel/xlsx
design.md(数据模型 + 契约 + ADR)
### 接口契约
POST /api/users/export
Content-Type: application/json
Body: { "from": "2026-01-01", "to": "2026-10-01" }
200 同步(行数 ≤ 50000):返回 CSV 流,Content-Disposition: attachment
202 异步(行数 > 50000):{ "taskId": "exp_8f3a", "channel": "email" }
403 无权限;422 时间范围非法(from > to 或跨度 > 366 天)
### 错误码
EXPORT_FORBIDDEN / EXPORT_RANGE_INVALID / EXPORT_QUOTA_EXCEEDED
### ADR-002 为什么同步阈值定在 50000
实测单次导出 5 万行约 6s,超过则网关超时风险上升;
阈值放在配置项 export.sync-threshold,便于后续调整。
### ADR-003 为什么用 BOM 而不是 GBK
下游以 Excel 为主,BOM 方案无需转码且不损失字符集;
代价是部分旧版解析器需跳过头部 3 字节,已在 README 说明。
tasks.md(可勾选、带依赖)
- [ ] T1 新增 UserExportService 与服务层单测(依赖:无)
- [ ] T2 定义 DTO 与字段顺序常量(依赖:T1)
- [ ] T3 实现权限校验 + 审计日志(依赖:T1)
- [ ] T4 实现同步导出(BOM 编码)(依赖:T2)
- [ ] T5 实现 50000 行阈值与异步任务(依赖:T4)
- [ ] T6 邮件附件通道(依赖:T5)
- [ ] T7 集成测试:权限、边界、异步三条路径(依赖:T3,T5)
- [ ] T8 更新 README 与接口文档(依赖:T7)
注意这份规格做了什么
它把 Agent 一定会自己猜的每一个点都写死了:字段与顺序、同步阈值、编码方案、权限点、审计字段、错误码、异步降级路径、以及"不做什么"。剩下的编码工作 Agent 几乎不需要再做决策。
4.3 规格质量自检清单
| 要素 | 自检问题 |
|---|---|
| 问题与动机 | 为什么做?不做的代价是什么?一两句说清了吗 |
| 范围边界 | 是否显式写出了"不做什么"?(这是范围蔓延的根源) |
| 功能需求 | 是否用 WHEN...SHALL... 句式覆盖了所有触发条件 |
| 数据模型 | 表结构、字段类型、约束、迁移策略是否明确(别让 Agent 猜列名) |
| 接口契约 | 路径、请求/响应、错误码是否齐全(防幻觉接口的关键) |
| 非功能需求 | 性能、并发、安全、合规、可观测性是否交代 |
| 失败路径 | 超时、重试、降级、幂等、部分失败怎么处理 |
| 验收方式 | 怎样算完成?哪些测试必须通过? |
| 禁区 | 哪些文件/模块不许碰,哪些依赖不许引入 |
4.4 工具选择
| 工具 | 工作流 | 适合谁 / 取舍 |
|---|---|---|
| Spec Kit | 七阶段关卡 | 社区最活跃、独有 constitution;缺点是七阶段对小型改动偏重 |
| Kiro | requirements→design→tasks | 开箱即用独立 IDE,可追踪性最好;绑定其 IDE 与模型 |
| OpenSpec | propose→apply→archive | 最轻量、不绑 IDE;因归档时更新规格,最接近 spec-anchored |
| Plan Mode | 只读研究→方案→批准→执行 | 最轻的 spec-first,SDD 入门坡道;方案不沉淀,跨人共享不够 |
必须听到的反方声音
Thoughtworks 的 Birgitta Böckeler 批评最扎实:SDD 容易"小题大做"(把小缺陷扩展成 4 个用户故事、16 条验收标准)、可能加重评审负担("我宁愿审代码,也不愿审一堆 markdown")、并可能放大评审过载与幻觉。务实回应是分档------按变更的爆炸半径决定规格深度,对单个空值检查级别的小改动,走完整流程是纯粹浪费。
05 从需求分析到代码落地的完整演进路径
前面三节各讲一种范式,这一节把它们串成一条从模糊需求到可交付代码的完整流水线,并标出每一步人类该站在哪里。
5.1 全链路流水线
图 6 | 七个阶段里,人类真正不可替代的是「立契约」与「把质量关」;中间的实现与验证交给 Agent 与自动化。
#mermaid-svg-hkFyovNtzjj2VPKR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hkFyovNtzjj2VPKR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hkFyovNtzjj2VPKR .error-icon{fill:#552222;}#mermaid-svg-hkFyovNtzjj2VPKR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hkFyovNtzjj2VPKR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hkFyovNtzjj2VPKR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hkFyovNtzjj2VPKR .marker.cross{stroke:#333333;}#mermaid-svg-hkFyovNtzjj2VPKR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hkFyovNtzjj2VPKR p{margin:0;}#mermaid-svg-hkFyovNtzjj2VPKR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hkFyovNtzjj2VPKR .cluster-label text{fill:#333;}#mermaid-svg-hkFyovNtzjj2VPKR .cluster-label span{color:#333;}#mermaid-svg-hkFyovNtzjj2VPKR .cluster-label span p{background-color:transparent;}#mermaid-svg-hkFyovNtzjj2VPKR .label text,#mermaid-svg-hkFyovNtzjj2VPKR span{fill:#333;color:#333;}#mermaid-svg-hkFyovNtzjj2VPKR .node rect,#mermaid-svg-hkFyovNtzjj2VPKR .node circle,#mermaid-svg-hkFyovNtzjj2VPKR .node ellipse,#mermaid-svg-hkFyovNtzjj2VPKR .node polygon,#mermaid-svg-hkFyovNtzjj2VPKR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hkFyovNtzjj2VPKR .rough-node .label text,#mermaid-svg-hkFyovNtzjj2VPKR .node .label text,#mermaid-svg-hkFyovNtzjj2VPKR .image-shape .label,#mermaid-svg-hkFyovNtzjj2VPKR .icon-shape .label{text-anchor:middle;}#mermaid-svg-hkFyovNtzjj2VPKR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hkFyovNtzjj2VPKR .rough-node .label,#mermaid-svg-hkFyovNtzjj2VPKR .node .label,#mermaid-svg-hkFyovNtzjj2VPKR .image-shape .label,#mermaid-svg-hkFyovNtzjj2VPKR .icon-shape .label{text-align:center;}#mermaid-svg-hkFyovNtzjj2VPKR .node.clickable{cursor:pointer;}#mermaid-svg-hkFyovNtzjj2VPKR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hkFyovNtzjj2VPKR .arrowheadPath{fill:#333333;}#mermaid-svg-hkFyovNtzjj2VPKR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hkFyovNtzjj2VPKR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hkFyovNtzjj2VPKR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hkFyovNtzjj2VPKR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hkFyovNtzjj2VPKR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hkFyovNtzjj2VPKR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hkFyovNtzjj2VPKR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hkFyovNtzjj2VPKR .cluster text{fill:#333;}#mermaid-svg-hkFyovNtzjj2VPKR .cluster span{color:#333;}#mermaid-svg-hkFyovNtzjj2VPKR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hkFyovNtzjj2VPKR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hkFyovNtzjj2VPKR rect.text{fill:none;stroke-width:0;}#mermaid-svg-hkFyovNtzjj2VPKR .icon-shape,#mermaid-svg-hkFyovNtzjj2VPKR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hkFyovNtzjj2VPKR .icon-shape p,#mermaid-svg-hkFyovNtzjj2VPKR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hkFyovNtzjj2VPKR .icon-shape .label rect,#mermaid-svg-hkFyovNtzjj2VPKR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hkFyovNtzjj2VPKR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hkFyovNtzjj2VPKR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hkFyovNtzjj2VPKR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 验证不通过,带失败信号回到实现
① 需求澄清
说清问题与验收
② 立规格
requirements / design
③ 消歧与拆解
clarify → tasks
④ Agent 实现
逐任务编码,先写失败测试
⑤ 自动验证
编译 / 测试 / lint / 扫描
⑥ 人工把关
架构 / 安全 / 偏离说明
⑦ 交付与归档
合并 · 规格归档为基线
人类主战场:①②③ 立契约、⑥ 把关质量;AI 负责 ④⑤⑦。
5.2 每个阶段的产物与人类角色
| 阶段 | 关键产物 | 谁主导 | 门禁(做不完不许进下一步) |
|---|---|---|---|
| ① 需求澄清 | 一句话问题 + 验收标准 | 产品 / 开发者 | 能用一句话说清"做完的样子" |
| ② 立规格 | requirements.md / design.md | 开发者 + Agent 辅助 | "不做什么"已写明;接口契约齐全 |
| ③ 消歧与拆解 | 澄清问答记录 / tasks.md | Agent 提问,人回答 | Agent 无未解决的歧义 |
| ④ 实现 | 代码 + 失败测试先行 | Agent | 任务粒度 30--90 分钟,逐个提交 |
| ⑤ 自动验证 | 测试报告 / 扫描结果 | CI | 全绿;覆盖率与复杂度达标 |
| ⑥ 人工把关 | 评审意见 / 偏离说明 | 人(聚焦架构与安全) | Agent 已输出"偏离说明" |
| ⑦ 交付与归档 | 合并记录 / 归档规格 | 人 + CI | 规格归档,作为下次变更基线 |
5.3 最关键的连接点:验收标准直通测试用例
整条链路里,真正把"需求"和"可验证的实现"焊在一起的,是**给定(Given)/ 当(When)/ 则(Then)**这组句式。它既是需求描述,又能几乎原样变成测试代码------这是 SDD 最实用的一个杠杆。
图 7 | 一份写好 Given/When/Then 的验收标准,本身就是测试用例的骨架------这是把"规格"变成"可执行判据"的最短路径。
#mermaid-svg-OZPNd0qXNz94tB4W{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OZPNd0qXNz94tB4W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OZPNd0qXNz94tB4W .error-icon{fill:#552222;}#mermaid-svg-OZPNd0qXNz94tB4W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OZPNd0qXNz94tB4W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OZPNd0qXNz94tB4W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OZPNd0qXNz94tB4W .marker.cross{stroke:#333333;}#mermaid-svg-OZPNd0qXNz94tB4W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OZPNd0qXNz94tB4W p{margin:0;}#mermaid-svg-OZPNd0qXNz94tB4W .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OZPNd0qXNz94tB4W .cluster-label text{fill:#333;}#mermaid-svg-OZPNd0qXNz94tB4W .cluster-label span{color:#333;}#mermaid-svg-OZPNd0qXNz94tB4W .cluster-label span p{background-color:transparent;}#mermaid-svg-OZPNd0qXNz94tB4W .label text,#mermaid-svg-OZPNd0qXNz94tB4W span{fill:#333;color:#333;}#mermaid-svg-OZPNd0qXNz94tB4W .node rect,#mermaid-svg-OZPNd0qXNz94tB4W .node circle,#mermaid-svg-OZPNd0qXNz94tB4W .node ellipse,#mermaid-svg-OZPNd0qXNz94tB4W .node polygon,#mermaid-svg-OZPNd0qXNz94tB4W .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OZPNd0qXNz94tB4W .rough-node .label text,#mermaid-svg-OZPNd0qXNz94tB4W .node .label text,#mermaid-svg-OZPNd0qXNz94tB4W .image-shape .label,#mermaid-svg-OZPNd0qXNz94tB4W .icon-shape .label{text-anchor:middle;}#mermaid-svg-OZPNd0qXNz94tB4W .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OZPNd0qXNz94tB4W .rough-node .label,#mermaid-svg-OZPNd0qXNz94tB4W .node .label,#mermaid-svg-OZPNd0qXNz94tB4W .image-shape .label,#mermaid-svg-OZPNd0qXNz94tB4W .icon-shape .label{text-align:center;}#mermaid-svg-OZPNd0qXNz94tB4W .node.clickable{cursor:pointer;}#mermaid-svg-OZPNd0qXNz94tB4W .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OZPNd0qXNz94tB4W .arrowheadPath{fill:#333333;}#mermaid-svg-OZPNd0qXNz94tB4W .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OZPNd0qXNz94tB4W .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OZPNd0qXNz94tB4W .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OZPNd0qXNz94tB4W .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OZPNd0qXNz94tB4W .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OZPNd0qXNz94tB4W .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OZPNd0qXNz94tB4W .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OZPNd0qXNz94tB4W .cluster text{fill:#333;}#mermaid-svg-OZPNd0qXNz94tB4W .cluster span{color:#333;}#mermaid-svg-OZPNd0qXNz94tB4W div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OZPNd0qXNz94tB4W .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OZPNd0qXNz94tB4W rect.text{fill:none;stroke-width:0;}#mermaid-svg-OZPNd0qXNz94tB4W .icon-shape,#mermaid-svg-OZPNd0qXNz94tB4W .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OZPNd0qXNz94tB4W .icon-shape p,#mermaid-svg-OZPNd0qXNz94tB4W .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OZPNd0qXNz94tB4W .icon-shape .label rect,#mermaid-svg-OZPNd0qXNz94tB4W .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OZPNd0qXNz94tB4W .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OZPNd0qXNz94tB4W .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OZPNd0qXNz94tB4W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 几乎原样翻译
需求侧:Gherkin 场景
Given...When...Then...
测试侧:JUnit 用例
@Test export_csv_columnOrder()
需求侧(Gherkin):
gherkin
Given 管理员已登录且有 user:export 权限
When 点击导出,时间跨度 30 天
Then 返回 CSV,列顺序为 id, username, email, role, status, created_at
And 文件以 UTF-8 BOM 编码
测试侧(JUnit):
java
@Test void export_csv_columnOrder() {
var r = export(authAdmin(), range(30));
assertThat(r.header()).isEqualTo("id,username,email,role,status,created_at");
assertTrue(r.hasUtf8Bom());
}
这条链路的分水岭
有可自动判定的验证信号(编译、测试、lint),Agent 就能自己试错、自己收敛;没有,它只能"看起来对"。所以 ⑤ 自动验证不是流程的装饰,而是 ④ 能自动化的前提。
06 多范式混合使用的最佳实践策略
2026 年真正跑得顺的团队,几乎都不是"三选一",而是按变更的爆炸半径分层。这一节给出分层模型、决策树与团队落地路线。
6.1 按爆炸半径分层
图 8 | 越往上爆炸半径越大,规格投入越重;底部的五条是三层共享的工程底线,任何一层都不能省。
| 层级 | 范式选择 | 适用场景 |
|---|---|---|
| 第 1 层 · 探索层 | Vibe:不写规格,但小步提交 | 原型 · 一次性脚本 · UI 微调 · 学习新栈 |
| 第 2 层 · 日常交付层 | Agentic + 轻量规格:先写验收标准,再让 Agent 跑 | 单模块特性 · Bug 修复 · 重构 |
| 第 3 层 · 系统层 | 完整 SDD:constitution + 规格 + 设计 + 任务 | 跨模块 · 跨人 · 长期维护 · 受监管链路 |
贯穿三层:版本控制 · 自动化验证 · 权限边界 · 审计留痕 · 人在回路
6.2 决策树:这次改动该走哪一档
| 判断问题 | 命中 | 走哪一档 |
|---|---|---|
| 这段代码三个月后还需要改吗? | 不需要 | Vibe 直接开干,记得频繁 commit |
| 改动是否局限于单文件、且你能一眼看懂整个 diff? | 是 | Agentic + 一句验收标准即可 |
| 是否涉及数据模型、接口契约、权限或资金? | 是 | 完整规格:至少写清数据模型与契约 |
| 是否有第二个人(或第二个 Agent)会碰同一块代码? | 是 | 规格必须是共享契约,进版本库 |
| 是否有现成的自动化测试能判定对错? | 否 | 先补测试再动手,否则 Agent 只能帮你"看起来对" |
| 失败后是否需要向他人解释"为什么这么设计"? | 是 | 规格即解释材料,也是审计证据 |
6.3 团队落地的三个阶段
| 阶段 | 动作 | 观察指标 | 成功判据 |
|---|---|---|---|
| 试点期 (1--4 周) | 单个小组、单仓库;建立 AGENTS.md 与验证环境;只允许 Agent 提 PR | PR 返工率、AI 代码合并率 | 团队能稳定用 Agent 完成日常小改动 |
| 规范期 (1--2 月) | 引入轻量规格模板与决策树;把 hooks、CI 质量门禁接上;建立审查 Skill | 首次通过率、评审耗时、回归缺陷数 | 中等变更能"规格先行"稳定交付 |
| 规模化期 (3 月+) | 多 Agent 编排、并行会话、多角色分工;规格归档与回归测试进 CI | 交付周期、人均产出、成本/PR | 跨模块变更也能可追溯、可审计 |
6.4 混合使用时最容易犯的四个错
① 全场景一把梭
要么所有小改动都写四文档(过度),要么生产系统也 Vibe(危险)。正确做法是让决策树而非习惯决定深度。
② 规格写完就扔
用 Plan Mode 出了方案、做完不回写归档,下次变更又要从零推理。归档规格 = 给未来省时间。
③ 用规范文件当安全边界
写了"禁止删库"就以为安全了。规则引导行为,但硬约束必须落在权限、hooks、分支保护与 CI。
④ 只有生成没有验证
多跑几个 Agent 互相审查,但没有可执行判据,结果只是多烧 token。Generator 与 Verifier 之间必须有机器可判定的判据。
四条红线(无论哪一层都不能省)
① 版本控制 :Agent 动手前先提交,产出单独分支;② 自动化验证 :没有机器可判定的信号就不算完成;③ 权限边界 :文件系统、命令、网络、凭据四层最小权限;④ 人在回路:合并需要测试全绿 + 至少一人审阅,受监管链路额外签核。
07 常见生成错误分析与精准排错技巧
AI 生成代码的错误不是随机的,它们高度集中在六类模式上。认清模式,就能把"到处救火"变成"按图排错"。
7.1 六类高频错误与识别信号
| 错误类型 | 典型表现 | 识别信号 | 根因 |
|---|---|---|---|
| 幻觉接口 | 调用不存在的 API 方法、配置键或数据库字段 | 编译通过、运行时炸;"这个方法文档里没有" | 凭训练记忆混用版本,缺少依赖规格 |
| 意图漂移 | 选了"合理默认值",但和真实需求不一致 | 代码看着对,跑出来不是你要的 | 需求中的决策点没写死,Agent 自行填空 |
| 上下文坍塌 | 长任务后半段忘记前面决策,自相矛盾 | 同一会话内前后实现风格/约定反转 | 关键决策只在对话里,没落到文件 |
| 范围蔓延 | 顺手重构了无关模块,diff 失控 | PR 里出现任务之外的改动 | 没有"不做什么"约束,任务粒度太粗 |
| 级联错误 | 修一个 bug 引入三个新 bug | 改完后红测变多而非变少 | 缺少回归保护,改动未跑全量测试 |
| 覆盖真空 | 测试"看起来很全"却没测关键分支 | 覆盖率不低,但线上仍出低级缺陷 | 测试由 AI 一并生成、无人校验有效性 |
7.2 排错五步法
图 9 | 排错五步法。核心纪律:先锁现场、再复现、后解释,最后把根因补回规格形成免疫。
#mermaid-svg-pKzhkmRVH1A6Zjlw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pKzhkmRVH1A6Zjlw .error-icon{fill:#552222;}#mermaid-svg-pKzhkmRVH1A6Zjlw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pKzhkmRVH1A6Zjlw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .marker.cross{stroke:#333333;}#mermaid-svg-pKzhkmRVH1A6Zjlw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pKzhkmRVH1A6Zjlw p{margin:0;}#mermaid-svg-pKzhkmRVH1A6Zjlw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .cluster-label text{fill:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .cluster-label span{color:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .cluster-label span p{background-color:transparent;}#mermaid-svg-pKzhkmRVH1A6Zjlw .label text,#mermaid-svg-pKzhkmRVH1A6Zjlw span{fill:#333;color:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .node rect,#mermaid-svg-pKzhkmRVH1A6Zjlw .node circle,#mermaid-svg-pKzhkmRVH1A6Zjlw .node ellipse,#mermaid-svg-pKzhkmRVH1A6Zjlw .node polygon,#mermaid-svg-pKzhkmRVH1A6Zjlw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .rough-node .label text,#mermaid-svg-pKzhkmRVH1A6Zjlw .node .label text,#mermaid-svg-pKzhkmRVH1A6Zjlw .image-shape .label,#mermaid-svg-pKzhkmRVH1A6Zjlw .icon-shape .label{text-anchor:middle;}#mermaid-svg-pKzhkmRVH1A6Zjlw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .rough-node .label,#mermaid-svg-pKzhkmRVH1A6Zjlw .node .label,#mermaid-svg-pKzhkmRVH1A6Zjlw .image-shape .label,#mermaid-svg-pKzhkmRVH1A6Zjlw .icon-shape .label{text-align:center;}#mermaid-svg-pKzhkmRVH1A6Zjlw .node.clickable{cursor:pointer;}#mermaid-svg-pKzhkmRVH1A6Zjlw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .arrowheadPath{fill:#333333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pKzhkmRVH1A6Zjlw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pKzhkmRVH1A6Zjlw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pKzhkmRVH1A6Zjlw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pKzhkmRVH1A6Zjlw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .cluster text{fill:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw .cluster span{color:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pKzhkmRVH1A6Zjlw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pKzhkmRVH1A6Zjlw rect.text{fill:none;stroke-width:0;}#mermaid-svg-pKzhkmRVH1A6Zjlw .icon-shape,#mermaid-svg-pKzhkmRVH1A6Zjlw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pKzhkmRVH1A6Zjlw .icon-shape p,#mermaid-svg-pKzhkmRVH1A6Zjlw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pKzhkmRVH1A6Zjlw .icon-shape .label rect,#mermaid-svg-pKzhkmRVH1A6Zjlw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pKzhkmRVH1A6Zjlw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pKzhkmRVH1A6Zjlw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pKzhkmRVH1A6Zjlw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 固定现场
先 commit 当前状态,保证可回滚
② 复现最小
写一条失败测试,把问题锁死
③ 先解释
让 Agent 说根因,再谈修复
④ 最小修复
只改必要处,跑全量测试
⑤ 补防线
把该写死的补进规格
③ 是关键:让 AI 先解释再动手,可避免它"随机改到看起来不报错"。
7.3 症状→根因→动作 速查表
| 你看到的症状 | 最可能的类型 | 立刻做什么 |
|---|---|---|
| 编译过了,一跑就 500 / 方法不存在 | 幻觉接口 | 把真实 API 签名/依赖版本喂进去;加契约测试锁死 |
| 功能都能跑,但行为不是你要的 | 意图漂移 | 补齐验收标准;把默认值显式写死 |
| 改到一半,Agent 开始推翻前面约定 | 上下文坍塌 | 停下,把决策写进 plan/规格,开新会话让它读回 |
| PR diff 远超预期 | 范围蔓延 | 拒收,补"不做什么",任务切到 30--90 分钟 |
| 修完 A,B/C/D 挂了 | 级联错误 | 先补回归测试,每步跑全量而非只跑相关用例 |
| 覆盖率不低,线上仍出问题 | 覆盖真空 | 先写测试再让 AI 实现;用变异测试抽检有效性 |
两个高杠杆技巧
① "先解释,后修复" :调试时明确要求 Agent 先说出根因,再动手。如果它的解释是错的,你就知道修复一定也是错的------省下大量反复。② "偏离说明" :任务收口时要求 Agent 输出"哪里没按方案做、为什么"。这一步能把静默偏离(偏离了设计却没告诉你)变成显式信息,是 SDD 落地的关键小动作。
别和 AI 硬碰硬
同一个错误纠正两次仍不奏效,就回滚重来,换一种完全不同的问法或换模型。在多轮偏航的上下文里继续拉扯,只会让错误越叠越深------这是最常见的 token 浪费来源。
08 提升 AI 编程产出质量的关键提示词方法
在 Agentic 时代,提示词工程的重心已经从"措辞技巧"转向"上下文工程"。这一节给出可复用的公式、七个模式与一份模板。
8.1 从提示词工程到上下文工程
2026 年的一个共识是:强模型已经内化了大量推理,过度指导反而会降低质量 。与其堆砌"请你一步步思考",不如把精力放在三件事上------给对上下文、收紧约束、定义验证。一条好提示词要提供四样东西:
图 10 | 提示词四要素。弱提示词只描述任务,强提示词定义整个工程问题。
| Context 上下文 | Task 任务 | Constraints 约束 | Verification 验证 |
|---|---|---|---|
| 语言 / 框架 / 版本 | 具体要建 / 改什么 | 性能 / 安全 / 兼容 | 期望的测试 |
| 架构、相关文件 | 一次只做一件事 | 禁止的做法 | 验收标准 |
| 数据形状、现有风格 | 限定目标文件 | 不许碰的文件 | 输出格式 |
弱提示词只描述任务,强提示词定义整个工程问题。
核心公式
你是 [角色/技术栈]。目标:[具体结果]。上下文:[架构/文件/数据形状]。约束:[1] [2] [3]。输出:[格式]。验收标准:[怎样算对]。
8.2 七个高杠杆提示词模式
| 模式 | 做法 | 示例要点 |
|---|---|---|
| ① 约束优先 | 先说"不要做什么",再说做什么 | "加 JWT 认证:不改现有路由、复用现有 User 模型、token 存 httpOnly cookie(非 localStorage)、24h 过期" |
| ② 给出输出形状 | 用代码骨架告诉它格式 | 贴一段目标测试的 describe/it 结构,让 AI 填实现 |
| ③ 引用现有代码 | 指向同类实现作为范式 | "完全按 src/routes/users.ts 的模式写订单接口" |
| ④ 提供数据契约 | 给输入/输出 JSON 或类型 | 贴真实响应示例 + 目标类型定义,减少字段猜错 |
| ⑤ 迭代式细化 | 一次一步,逐步收紧 | 先模型 → 再校验 → 再接口;每步小到可快速评审 |
| ⑥ 解释"为什么" | 给出动机而非只给指令 | "改用 Map 是因为需要保证插入顺序"------AI 会顺带处理相关边界 |
| ⑦ 限定范围 | 明确只碰哪些文件 | "仅在 middleware.ts 内改动,不要动其他文件" |
8.3 一份可直接套用的模板
你在这个项目里工作:Spring Boot 3.3 + JPA(阿里 Java 开发规范)。
【目标】
为「用户导出」加一个 POST /api/users/export 接口。
【上下文】
- 分层:controller → service → repository
- 复用现有 UserRepository 与 PermissionService
- 参考同类实现:src/main/java/.../UserQueryController.java
【约束】
- 不引入新的第三方依赖
- 不修改 db/migration/**
- 返回 400 处理参数非法;403 处理无权限;201 返回任务/文件标识
- 使用异步仅当行数 > 50000
【输出】
- Controller + Service + DTO 代码
- 对应的 JUnit 测试:正常、无权限、超阈值异步 三条路径
【验收标准】
- mvn verify 全绿
- 无未处理的受检异常
- 审计日志包含操作者、时间范围、行数
8.4 反模式(做了会变差)
不要做的
-
把整个文件粘进去说"修一下"------应指向具体问题区
-
连续发 4--5 个改动却不评审------分歧会累积
-
同一个错误纠正两次还硬碰------应回滚换思路
-
用 AI 做改个变量名这种琐事------比手改更慢
-
堆砌"请一步步思考"------强模型上反而降质
应该做的
-
先给版本号(框架大版本间 API 常不兼容)
-
用
@文件引用代替粘贴(保持上下文新鲜) -
复杂任务先用只读模式做研究,再动手
-
每 3--4 次修改就完整评审一遍
-
把反复用到的提示沉淀成团队模板库
一句话总结这一节
提示词不是在"求一个更好的答案",而是在设计一个让好答案可复现的接口------定义上下文、约束、失败模式与验收标准。这不是措辞技巧,是系统设计。
09 本地项目集成与自动化测试验证流程
没有自动验证的 Agentic Coding,等于让 AI 蒙眼高速驾驶。这一节把验证做成五层门禁,让"看起来对"变成"机器判定对"。
9.1 五层质量门禁
图 11 | 越靠下越全面也越慢。前两层要"快且透明",后三层才是真正的裁决。
| 层级 | 时机 | 内容 |
|---|---|---|
| 第 1 层 · 编辑时 | 编辑器 / Agent 内 | 实时类型检查、内联 lint、保存即格式化(秒级反馈,不阻断) |
| 第 2 层 · 提交前 | pre-commit hooks | 格式化 + 高价值 lint + 受影响单测(目标 30 秒内,超时会被绕过) |
| 第 3 层 · 推送后 | CI:构建 + 全量测试 | 编译、全量单测、集成测试、覆盖率门槛、依赖漏洞扫描 |
| 第 4 层 · 预发布 | E2E + 性能 + 安全 | 端到端路径、性能回归、SAST/DAST、许可证与 SBOM 检查 |
| 第 5 层 · 合并闸门 | AI 审查 + 人工签核 | 质量门禁通过 + 至少一人审阅架构与安全;受监管链路额外签核 |
越靠下越全面也越慢;前两层要"快且透明",后三层才是真正的裁决。
9.2 第 2 层:pre-commit 配置示例
# .pre-commit-config.yaml(Python 示例;Java 可用 Checkstyle + Spotless 对应实现)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace # 清理 AI 引入的无关字符
- id: end-of-file-fixer
- id: check-added-large-files
args: ['--maxkb=500']
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black # "独裁式"格式化,消除风格争论
- repo: local
hooks:
- id: fast-unit-tests
name: Fast unit tests
entry: pytest tests/unit -q --maxfail=1
language: system
pass_filenames: false
always_run: true
一个容易被忽略的设计点
pre-commit 必须快 (目标 <30 秒)且只对暂存文件相关的内容检查 。超过 30 秒,开发者就会开始用--no-verify绕过它------再好的门禁也形同虚设。阻止提交(fail)而不是仅警告,这样问题在上下文最新鲜时就被修掉。
9.3 第 3 层:CI 质量门禁
# .github/workflows/quality.yml
name: Quality Gates
on: [pull_request]
jobs:
gates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build & Test
run: mvn -B verify # 编译 + 单测 + 集成测试
- name: Coverage Gate
run: mvn jacoco:check # 低于阈值直接失败
- name: Dependency Scan
run: mvn org.owasp:dependency-check-maven:check
- name: Rule Drift Check
run: bash scripts/check-agents-paths.sh # 校验 AGENTS.md 提到的路径真实存在
注意最后一步「规则漂移检查」------它验证 AGENTS.md 里提到的路径、命令是否真实存在。这是整个配置里投入产出比最高的一项自动化:简单、枯燥,但每周都能抓到真实问题。
9.4 TDD + Agent:把"方向盘"交给测试
Kent Beck 把 TDD 称为与 AI Agent 协作时的 superpower------因为 Agent 极易引入回归,而单元测试提供了一道自动的回归防线。标准循环如下:
-
人写一条失败测试(红)------用验收标准直译,把"要什么"钉死。
-
Agent 生成最小实现(绿)------只写够让测试通过的量。
-
CI 跑全量测试------所有测试必须通过,才进入下一步。
-
Agent 重构(保持绿)------改善结构,CI 复跑验证没破坏任何东西。
-
Agent 补边界测试------补齐空值、超时、并发等边界。
-
最终 CI 检查 → 合并批准------通过即交付,并把根因与新约束回写规格。
闭环的更高形态:让 Agent 自我问责
把质量扫描器接入 Agent(如通过 MCP 连接 SonarQube),可以形成「生成 → 扫描 → 读问题 → 自动修复 → 复扫」的闭环,Agent 在提 PR 前就先把质量门禁跑通。但必须设护栏 :给修复循环设迭代上限 (如最多 N 轮),否则会出现"改坏---修好---又改坏"的死循环空转。同时要求 Agent 只在质量门禁通过后才建议提交。
9.5 一次改动的完整命令流
# 1. 锁现场
git checkout -b feat/user-export
git commit -am "chore: baseline before AI change"
# 2. 先写失败测试(红)
# 编辑测试文件,描述期望行为
mvn test -Dtest=UserExportTest # 预期:失败
# 3. 让 Agent 实现(绿)
# Agent 按 tasks.md 逐任务实现,每个任务跑全量测试
mvn verify # 预期:全绿
# 4. 收口
# 要求 Agent 输出「偏离说明」;人工评审架构与安全
git add -A && git commit -m "feat: user export (see spec/2026-10-user-export)"
# 5. 归档规格,作为下次变更基线
git add spec/ && git commit -m "docs: archive user-export spec"
验证层的判据
判断一道门禁值不值得加,只问一句:**它能否在几秒到几分钟内,给出机器可判定的对错?**能,就加进流水线;不能(比如"代码是否优雅"),就交给人,但要让人聚焦在架构与安全,而不是逐行语法。
10 面向未来的开发者技能转型与进阶建议
这场迁移的主线不是"AI 越来越会写代码",而是人类的抽象层级在不断上移。这一节谈清楚:什么在贬值、什么在升值,以及该怎么走。
10.1 抽象层级的上移
图 12 | 从写语法、写逻辑到写意图、写契约。抽象层级每上一层,人被解放一次,也对表达精度要求更高一档。
#mermaid-svg-f78Syhi5BDuFwCgx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-f78Syhi5BDuFwCgx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-f78Syhi5BDuFwCgx .error-icon{fill:#552222;}#mermaid-svg-f78Syhi5BDuFwCgx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-f78Syhi5BDuFwCgx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-f78Syhi5BDuFwCgx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-f78Syhi5BDuFwCgx .marker.cross{stroke:#333333;}#mermaid-svg-f78Syhi5BDuFwCgx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-f78Syhi5BDuFwCgx p{margin:0;}#mermaid-svg-f78Syhi5BDuFwCgx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-f78Syhi5BDuFwCgx .cluster-label text{fill:#333;}#mermaid-svg-f78Syhi5BDuFwCgx .cluster-label span{color:#333;}#mermaid-svg-f78Syhi5BDuFwCgx .cluster-label span p{background-color:transparent;}#mermaid-svg-f78Syhi5BDuFwCgx .label text,#mermaid-svg-f78Syhi5BDuFwCgx span{fill:#333;color:#333;}#mermaid-svg-f78Syhi5BDuFwCgx .node rect,#mermaid-svg-f78Syhi5BDuFwCgx .node circle,#mermaid-svg-f78Syhi5BDuFwCgx .node ellipse,#mermaid-svg-f78Syhi5BDuFwCgx .node polygon,#mermaid-svg-f78Syhi5BDuFwCgx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-f78Syhi5BDuFwCgx .rough-node .label text,#mermaid-svg-f78Syhi5BDuFwCgx .node .label text,#mermaid-svg-f78Syhi5BDuFwCgx .image-shape .label,#mermaid-svg-f78Syhi5BDuFwCgx .icon-shape .label{text-anchor:middle;}#mermaid-svg-f78Syhi5BDuFwCgx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-f78Syhi5BDuFwCgx .rough-node .label,#mermaid-svg-f78Syhi5BDuFwCgx .node .label,#mermaid-svg-f78Syhi5BDuFwCgx .image-shape .label,#mermaid-svg-f78Syhi5BDuFwCgx .icon-shape .label{text-align:center;}#mermaid-svg-f78Syhi5BDuFwCgx .node.clickable{cursor:pointer;}#mermaid-svg-f78Syhi5BDuFwCgx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-f78Syhi5BDuFwCgx .arrowheadPath{fill:#333333;}#mermaid-svg-f78Syhi5BDuFwCgx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-f78Syhi5BDuFwCgx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-f78Syhi5BDuFwCgx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f78Syhi5BDuFwCgx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-f78Syhi5BDuFwCgx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f78Syhi5BDuFwCgx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-f78Syhi5BDuFwCgx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-f78Syhi5BDuFwCgx .cluster text{fill:#333;}#mermaid-svg-f78Syhi5BDuFwCgx .cluster span{color:#333;}#mermaid-svg-f78Syhi5BDuFwCgx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-f78Syhi5BDuFwCgx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-f78Syhi5BDuFwCgx rect.text{fill:none;stroke-width:0;}#mermaid-svg-f78Syhi5BDuFwCgx .icon-shape,#mermaid-svg-f78Syhi5BDuFwCgx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-f78Syhi5BDuFwCgx .icon-shape p,#mermaid-svg-f78Syhi5BDuFwCgx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-f78Syhi5BDuFwCgx .icon-shape .label rect,#mermaid-svg-f78Syhi5BDuFwCgx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-f78Syhi5BDuFwCgx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-f78Syhi5BDuFwCgx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-f78Syhi5BDuFwCgx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 每一次上移释放生产力,也把"把事情说清楚"的成本推高
写语法
汇编 / 早期语言
写逻辑
高级语言 / 框架
写意图
自然语言驱动生成
写契约
规格 / 边界 / 验收
歧义从未像今天这样昂贵------这是本期转型的核心命题。
10.2 什么在贬值,什么在升值
| 正在贬值 | 正在升值 |
|---|---|
| 逐行手写样板与 CRUD | 结构化沟通:把模糊需求变成精确契约 |
| 记忆 API 细节(可检索替代) | 领域建模与架构判断 |
| 追求"写得最快" | 验证设计:怎么证明它对 |
| 单点编码熟练度 | 代码审计、威胁建模、AI 评测(Eval) |
| 按部就班的执行 | 任务分解与多 Agent 编排 |
一个值得记住的判断
OpenAI 的 Sean Grove 提出:写代码只占程序员价值的 10--20%,其余 80--90% 是"结构化沟通"------理解用户、提炼需求、规划与验证(该比例为修辞表达,非实测数据)。AI 越能干,这个论断越接近现实:把问题说清楚,正在成为最核心的开发技能。
10.3 分阶段进阶路线
| 阶段 | 目标 | 具体动作 |
|---|---|---|
| 0--1 月 会用 | 把 Agent 变成日常工具 | 搭好验证环境与 AGENTS.md;每天用 Agent 完成一个小改动;练习"约束优先 + 输出形状"两式提示词 |
| 1--3 月 会控 | 能控制产出质量 | 把 TDD 循环跑顺;接入 pre-commit 与 CI 门禁;建立个人排错五步法与提示词模板库 |
| 3--6 月 会设 | 能设计规格与流程 | 用四文档写真实特性;为仓库维护分层规则;能判断"这次该走哪一档"并落地决策树 |
| 6 月+ 会编 | 能编排多 Agent 交付 | 编排 Maker/Critic/Tester 多角色;把规格归档与回归测试接进 CI;沉淀团队级规范与培训 |
10.4 角色在重构,但价值没有消失
开发者的新角色
-
系统架构师:定边界、定契约、定取舍
-
意图管理者:把业务语言翻译成可执行规格
-
质量守门人:设计验证、审查架构与安全
-
Agent 编排者:分解任务、协调多角色、控成本
尚未解决的难题
-
初级工程师不再靠写 CRUD 练手,培养体系出现断层------行业还没有好答案
-
"知识空心化":团队没人真正理解系统,只会"再问一次 AI"
-
长程任务的目标保真与错误累积,仍是可靠性瓶颈
-
评测与审计的职业标准尚未成形
给个人的三条建议
**① 把"说清楚"当核心技能练。**写规格、写验收标准、写约束,比多背一个 API 更保值。**② 别放弃读代码与做验证的能力。**当 Agent 产出越来越快,能判断对错 的人才是稀缺的。
**③ 建立自己的度量。**记录返工率、首次通过率、评审耗时------用数据判断你的工作流是否真的在变好,而不是凭感觉。
写在最后
这套指南里所有的方法,本质上都在做同一件事:把"人与人之间的默契"外化成"机器可读的契约"。Vibe 让你快,Agentic 让你省,Spec 让你稳------而把三者按爆炸半径编排起来的能力,才是新范式真正的门槛。
参考来源
· Karpathy 关于 vibe coding 与 agentic engineering 的公开表述(2025--2026)
· GitHub Spec Kit / AWS Kiro / OpenSpec / BMAD-METHOD / Tessl 官方文档与发布公告
· Thoughtworks 技术雷达与 Birgitta Böckeler 关于 SDD 成熟度的分析
· 各主流 Agent 工具(Claude Code / Cursor / VS Code Copilot / Codex CLI)关于 AGENTS.md、MCP 与 hooks 的官方文档
· Kent Beck 关于 TDD 与 AI Agent 协作的观点
· 2026 年多篇关于提示词工程、上下文工程与 AI 代码质量门禁的行业实践文章
本报告中的量化指标均标注来源与口径,涉及厂商自述的数据缺少独立第三方验证,建议在正式决策材料中以官方口径复核后再引用。