摘要:用过 AI 编程助手(Claude Code、Codex、Cursor 等同类工具)的开发者,很容易遇到两类问题:一是需求边做边改、返工频繁;二是 AI 生成的代码边界混乱、越改越不敢动。本文把「怎么指挥 AI」与「被生成的代码该守住什么架构底线」合并成一套完整闭环:先把项目约定写进规则文件,再先计划后执行,控制好对话与上下文;在代码侧用分层、模型先行、工程纪律和状态机作为护栏;最后用 Skills / Hooks / MCP 与多 Agent 扩展协作,并从成熟 Agent 运行时结构反推可迁移的架构认知。全文不依赖特定框架与模型版本,方法可迁移到任意技术栈。
开篇:为什么光会「提问」还不够
一个容易被忽略的事实
大多数 AI 编程助手在每次开启新会话时,都会先扫描、阅读当前项目的目录结构、文件命名、文件抬头注释和已有文档,再开始理解任务。这意味着:
- 目录层次清晰、命名一致、文件有抬头说明、关键约定有文档,助手就能更快建立项目认知,减少来回翻找的等待时间与上下文消耗;
- 反之,目录混乱、命名随意、缺少说明,助手每次都要重新猜测你的意图,返工和跑偏的概率明显上升。
换句话说,项目本身的工程质量,就是 AI 协作效率的上限。很多时候我们抱怨 AI 写得慢、理解错,真正的原因不在模型,而在项目没有把约束交代清楚。
两个常见误区
- 把 AI 只当成代码补全工具:想到哪里写到哪里,缺少前置的规范与计划,结果是单段代码看着没问题,拼到一起结构失控。
- 只丢「结果」,不给「约束与路径」:只说「帮我做个登录功能」,却不说明现有数据模型、存储方式、路由边界和异常要求,助手只能按自己的默认假设发挥,可控性很差。
本文的核心观点
速度与标准件交给 AI,边界、契约、一致性与状态流转必须由人守住。
用好 AI Coding 的前提是四件事:把工程规范前置、把任务切小、把上下文握在自己手里、把分层与状态机当作不可逾越的护栏。本文把实践中沉淀的方法整理成一条开发闭环:
#mermaid-svg-7j1HxK1Ce9IfNWTO{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-7j1HxK1Ce9IfNWTO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7j1HxK1Ce9IfNWTO .error-icon{fill:#552222;}#mermaid-svg-7j1HxK1Ce9IfNWTO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7j1HxK1Ce9IfNWTO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .marker.cross{stroke:#333333;}#mermaid-svg-7j1HxK1Ce9IfNWTO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7j1HxK1Ce9IfNWTO p{margin:0;}#mermaid-svg-7j1HxK1Ce9IfNWTO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .cluster-label text{fill:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .cluster-label span{color:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .cluster-label span p{background-color:transparent;}#mermaid-svg-7j1HxK1Ce9IfNWTO .label text,#mermaid-svg-7j1HxK1Ce9IfNWTO span{fill:#333;color:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .node rect,#mermaid-svg-7j1HxK1Ce9IfNWTO .node circle,#mermaid-svg-7j1HxK1Ce9IfNWTO .node ellipse,#mermaid-svg-7j1HxK1Ce9IfNWTO .node polygon,#mermaid-svg-7j1HxK1Ce9IfNWTO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .rough-node .label text,#mermaid-svg-7j1HxK1Ce9IfNWTO .node .label text,#mermaid-svg-7j1HxK1Ce9IfNWTO .image-shape .label,#mermaid-svg-7j1HxK1Ce9IfNWTO .icon-shape .label{text-anchor:middle;}#mermaid-svg-7j1HxK1Ce9IfNWTO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .rough-node .label,#mermaid-svg-7j1HxK1Ce9IfNWTO .node .label,#mermaid-svg-7j1HxK1Ce9IfNWTO .image-shape .label,#mermaid-svg-7j1HxK1Ce9IfNWTO .icon-shape .label{text-align:center;}#mermaid-svg-7j1HxK1Ce9IfNWTO .node.clickable{cursor:pointer;}#mermaid-svg-7j1HxK1Ce9IfNWTO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .arrowheadPath{fill:#333333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7j1HxK1Ce9IfNWTO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7j1HxK1Ce9IfNWTO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7j1HxK1Ce9IfNWTO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7j1HxK1Ce9IfNWTO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .cluster text{fill:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO .cluster span{color:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO 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-7j1HxK1Ce9IfNWTO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7j1HxK1Ce9IfNWTO rect.text{fill:none;stroke-width:0;}#mermaid-svg-7j1HxK1Ce9IfNWTO .icon-shape,#mermaid-svg-7j1HxK1Ce9IfNWTO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7j1HxK1Ce9IfNWTO .icon-shape p,#mermaid-svg-7j1HxK1Ce9IfNWTO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7j1HxK1Ce9IfNWTO .icon-shape .label rect,#mermaid-svg-7j1HxK1Ce9IfNWTO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7j1HxK1Ce9IfNWTO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7j1HxK1Ce9IfNWTO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7j1HxK1Ce9IfNWTO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 状态流转贯穿
反馈沉淀
① 规范前置
规则文件沉淀项目约定
② 计划先行
Plan 讨论 → SPEC 冻结
③ 对话与上下文控制
给对的信息 · 按功能切分会话
④ 架构护栏
分层 · 模型先行 · 工程纪律
⑤ 扩展与多 Agent
Skills / Hooks / MCP · 子代理协作
⑥ 架构认知升华
从成熟运行时反推可迁移方法论
状态机思维
状态 / 流转 / 失败 / 补偿 / 一致性
前三个环节解决「怎么指挥 AI」;第四、第六环节解决「被生成的代码长什么样、人要守住什么」;第五环节是跨工具能力与团队沉淀;状态机思维作为暗线贯穿工程护栏,并把经验回流到规则文件,形成持续改进的闭环。
本文适合谁
- 已经用过 AI 编程助手,但经常遇到返工多、代码散乱、对话越长越失控的开发者;
- 想建立一套不依赖特定工具、可以长期复用的 AI 协作流程;
- 同时关心「提示词技巧」和「代码架构质量」两方面的工程实践者。
如果你只想找几条快捷键或一句神奇提示词,本文可能不是你要找的内容。
第 1 章 开工前:先把项目约定写进规则文件
本章解决什么问题:让 AI 在动手之前就理解项目的约定、边界和常见坑,减少每次重复交代和因误解产生的返工。
1.1 心智模型:把 AI 当成第一天入职的新同事
可以把 AI 编程助手想象成一位第一天入职、能力很强但完全不了解项目背景的新同事:
- 他读代码很快,仓库里已经写清楚的东西不需要你再口头复述;
- 但团队的隐性约定、环境里的坑、不希望他走的弯路,必须有人书面交代;
- 交代方式越客观、越具体,他的执行越稳定。
规则文件(不同工具的名字不同,如 CLAUDE.md 或其他项目规范文件,常见的还有AGENTS.md)就是给这位「新同事」的项目说明书。它通常放在项目根目录或约定的规则目录中,助手每次启动会话时会优先阅读。
1.2 规则文件写什么、不写什么
判断标准只有一条:只写 AI 从代码本身读不到的内容。代码已经表达清楚的信息,写进规则文件只是在占用上下文。
| 应该写进规则文件 | 不应该写进规则文件 |
|---|---|
| AI 猜不到的自定义构建 / 启动脚本与命令 | 读代码就能知道的基本信息(如「这是一个 Web 项目」) |
| 与默认约定不同的代码风格偏好 | 编程语言本身已经标准化的语法与规范 |
| 测试命令、偏好的测试框架与执行方式 | 大段完整 API 文档(给链接或文档路径即可,不要全文粘贴) |
| 关键架构决策及其背景原因 | 频繁变动、每次都要改的内容 |
| 特殊开发环境的坑(环境变量、依赖、本地配置) | 逐文件逐一罗列(助手自己会读目录树) |
| 已经踩过的常见陷阱与修复方式 | 「写整洁代码」「遵循最佳实践」这类空泛口号 |
1.3 分层配置:全局、项目、子目录三层
规则文件不是单一文件,而是一套层级系统,助手会按目录层级自动叠加读取:
#mermaid-svg-uZ0LpDTFhDSC516Z{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-uZ0LpDTFhDSC516Z .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uZ0LpDTFhDSC516Z .error-icon{fill:#552222;}#mermaid-svg-uZ0LpDTFhDSC516Z .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uZ0LpDTFhDSC516Z .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uZ0LpDTFhDSC516Z .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uZ0LpDTFhDSC516Z .marker.cross{stroke:#333333;}#mermaid-svg-uZ0LpDTFhDSC516Z svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uZ0LpDTFhDSC516Z p{margin:0;}#mermaid-svg-uZ0LpDTFhDSC516Z .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z .cluster-label text{fill:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z .cluster-label span{color:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z .cluster-label span p{background-color:transparent;}#mermaid-svg-uZ0LpDTFhDSC516Z .label text,#mermaid-svg-uZ0LpDTFhDSC516Z span{fill:#333;color:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z .node rect,#mermaid-svg-uZ0LpDTFhDSC516Z .node circle,#mermaid-svg-uZ0LpDTFhDSC516Z .node ellipse,#mermaid-svg-uZ0LpDTFhDSC516Z .node polygon,#mermaid-svg-uZ0LpDTFhDSC516Z .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uZ0LpDTFhDSC516Z .rough-node .label text,#mermaid-svg-uZ0LpDTFhDSC516Z .node .label text,#mermaid-svg-uZ0LpDTFhDSC516Z .image-shape .label,#mermaid-svg-uZ0LpDTFhDSC516Z .icon-shape .label{text-anchor:middle;}#mermaid-svg-uZ0LpDTFhDSC516Z .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uZ0LpDTFhDSC516Z .rough-node .label,#mermaid-svg-uZ0LpDTFhDSC516Z .node .label,#mermaid-svg-uZ0LpDTFhDSC516Z .image-shape .label,#mermaid-svg-uZ0LpDTFhDSC516Z .icon-shape .label{text-align:center;}#mermaid-svg-uZ0LpDTFhDSC516Z .node.clickable{cursor:pointer;}#mermaid-svg-uZ0LpDTFhDSC516Z .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uZ0LpDTFhDSC516Z .arrowheadPath{fill:#333333;}#mermaid-svg-uZ0LpDTFhDSC516Z .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uZ0LpDTFhDSC516Z .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uZ0LpDTFhDSC516Z .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uZ0LpDTFhDSC516Z .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uZ0LpDTFhDSC516Z .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uZ0LpDTFhDSC516Z .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uZ0LpDTFhDSC516Z .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uZ0LpDTFhDSC516Z .cluster text{fill:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z .cluster span{color:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z 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-uZ0LpDTFhDSC516Z .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uZ0LpDTFhDSC516Z rect.text{fill:none;stroke-width:0;}#mermaid-svg-uZ0LpDTFhDSC516Z .icon-shape,#mermaid-svg-uZ0LpDTFhDSC516Z .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uZ0LpDTFhDSC516Z .icon-shape p,#mermaid-svg-uZ0LpDTFhDSC516Z .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uZ0LpDTFhDSC516Z .icon-shape .label rect,#mermaid-svg-uZ0LpDTFhDSC516Z .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uZ0LpDTFhDSC516Z .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uZ0LpDTFhDSC516Z .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uZ0LpDTFhDSC516Z :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 全局规则
个人跨项目通用偏好
项目规则
纳入 Git,团队成员共享
子目录规则 A
对应模块专属约定
子目录规则 B
对应模块专属约定
- 全局规则:放个人通用偏好,例如偏好的语言风格、测试框架习惯、提交信息习惯,在所有项目生效。
- 项目规则 :放当前项目特有的架构约束、代码风格、启动命令、常见陷阱,纳入 Git 由团队共享,保证团队内每个助手执行标准一致。
- 子目录规则:在多模块或前后端共存的仓库中特别有用,前端目录放前端约定,后端目录放后端约定,进入对应目录时自动加载,互不干扰。
规则文件内部还可以通过引用语法(如 @文档路径)引入外部详细文档,主规则文件只保留精简的索引与决策指引,避免单个文件膨胀。
1.4 四条编写原则
原则一:只写代码读不到的约束。 能从目录、命名、现有实现推断出来的内容不重复写,把上下文留给真正需要人工补充的约定。
原则二:语言客观、工程化,去掉情绪化修饰。 AI 以文本为单位理解输入,「最高水准」「极致优雅」「无懈可击」这类词对执行没有实际指导意义,只会消耗上下文。有效的写法是具体、可执行的技术约束,例如:「所有外部网络调用必须捕获异常并记录日志」「公开函数必须标注类型」。
原则三:从小开始,按踩过的坑累积。 不要一开始就试图写一本完整手册。更实用的做法是:每当 AI 在项目里做错一件事,就把对应约束补进规则文件一条。随着使用次数增加,规则文件会自然长成匹配项目的最小必要集合。
原则四:篇幅克制,只保留原则性约束。 规则文件的特点应该是短、原则性强、不纠缠细节;细节交给对应目录下的具体文档,需要时再通过引用链接读取。
1.5 规则文件的飞轮效应
持续维护规则文件会形成一个正向循环:
#mermaid-svg-stTCxFPFBAhjb5pr{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-stTCxFPFBAhjb5pr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-stTCxFPFBAhjb5pr .error-icon{fill:#552222;}#mermaid-svg-stTCxFPFBAhjb5pr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-stTCxFPFBAhjb5pr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-stTCxFPFBAhjb5pr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-stTCxFPFBAhjb5pr .marker.cross{stroke:#333333;}#mermaid-svg-stTCxFPFBAhjb5pr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-stTCxFPFBAhjb5pr p{margin:0;}#mermaid-svg-stTCxFPFBAhjb5pr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-stTCxFPFBAhjb5pr .cluster-label text{fill:#333;}#mermaid-svg-stTCxFPFBAhjb5pr .cluster-label span{color:#333;}#mermaid-svg-stTCxFPFBAhjb5pr .cluster-label span p{background-color:transparent;}#mermaid-svg-stTCxFPFBAhjb5pr .label text,#mermaid-svg-stTCxFPFBAhjb5pr span{fill:#333;color:#333;}#mermaid-svg-stTCxFPFBAhjb5pr .node rect,#mermaid-svg-stTCxFPFBAhjb5pr .node circle,#mermaid-svg-stTCxFPFBAhjb5pr .node ellipse,#mermaid-svg-stTCxFPFBAhjb5pr .node polygon,#mermaid-svg-stTCxFPFBAhjb5pr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-stTCxFPFBAhjb5pr .rough-node .label text,#mermaid-svg-stTCxFPFBAhjb5pr .node .label text,#mermaid-svg-stTCxFPFBAhjb5pr .image-shape .label,#mermaid-svg-stTCxFPFBAhjb5pr .icon-shape .label{text-anchor:middle;}#mermaid-svg-stTCxFPFBAhjb5pr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-stTCxFPFBAhjb5pr .rough-node .label,#mermaid-svg-stTCxFPFBAhjb5pr .node .label,#mermaid-svg-stTCxFPFBAhjb5pr .image-shape .label,#mermaid-svg-stTCxFPFBAhjb5pr .icon-shape .label{text-align:center;}#mermaid-svg-stTCxFPFBAhjb5pr .node.clickable{cursor:pointer;}#mermaid-svg-stTCxFPFBAhjb5pr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-stTCxFPFBAhjb5pr .arrowheadPath{fill:#333333;}#mermaid-svg-stTCxFPFBAhjb5pr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-stTCxFPFBAhjb5pr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-stTCxFPFBAhjb5pr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-stTCxFPFBAhjb5pr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-stTCxFPFBAhjb5pr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-stTCxFPFBAhjb5pr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-stTCxFPFBAhjb5pr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-stTCxFPFBAhjb5pr .cluster text{fill:#333;}#mermaid-svg-stTCxFPFBAhjb5pr .cluster span{color:#333;}#mermaid-svg-stTCxFPFBAhjb5pr 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-stTCxFPFBAhjb5pr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-stTCxFPFBAhjb5pr rect.text{fill:none;stroke-width:0;}#mermaid-svg-stTCxFPFBAhjb5pr .icon-shape,#mermaid-svg-stTCxFPFBAhjb5pr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-stTCxFPFBAhjb5pr .icon-shape p,#mermaid-svg-stTCxFPFBAhjb5pr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-stTCxFPFBAhjb5pr .icon-shape .label rect,#mermaid-svg-stTCxFPFBAhjb5pr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-stTCxFPFBAhjb5pr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-stTCxFPFBAhjb5pr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-stTCxFPFBAhjb5pr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 新的错误继续沉淀
AI 犯错一次
把教训记录为规则
下次同类问题不再犯
整体错误率持续下降
这个循环的关键在于「记录」动作:错误发生后不只是人工修正代码,而是把背后的约束条件写回规则文件,让同类错误在之后自动规避。规则文件因此成为项目经验的沉淀载体,而不是一次性的静态文档。
1.6 一个反面示例暴露的六类问题
下面用一个匿名化的反面示例说明常见误区。示例项目是一个基于工作流框架构建的多智能体系统,规则文件初稿写成了「角色宣言」风格:
markdown
# 示例 Agent 系统
**Role**:你是 AI Agent 开发的最高水准,兼具深厚的领域底蕴。你的任务是打造一个极致优雅、深度智能的系统,卓越是唯一标准。
## 核心哲学
- 极简主义与美学:追求功能的同时执着于架构优雅与代码美感。
- 代码风格:简洁,一行胜千行,拒绝冗余的防御性代码。
- 功能验证:所有变更均需通过严格测试。
- 文档即生存证明:无文档的功能即不存在。
## 文档索引
- 用户手册:README.md
- 文档首页:docs/index.md
这份初稿的问题可以归纳为六类:
| 问题类型 | 具体表现 | 为什么无效 |
|---|---|---|
| 情绪化角色定位 | 「最高水准」「极致优雅」「无懈可击」 | 没有可执行标准,浪费上下文 |
| 缺少关键技术约束 | 没有错误处理策略、性能要求、测试标准、领域特殊要求 | 助手缺少必须遵守的硬边界 |
| 文档索引缺少决策指引 | 只列文档路径,不说明「做什么事该读哪个文档」 | 助手无法快速定位所需资料 |
| 代码风格走向极端 | 笼统拒绝防御性代码,缺少 import 顺序、类型注解等具体标准 | 在需要健壮性的场景容易埋坑 |
| 缺少工作流程 | 没有说明先读什么、改什么、测什么、更新什么文档,何时必须询问用户 | 执行顺序依赖助手自由发挥 |
| 缺少架构概览 | 没有说明模块划分、数据流与组件依赖关系 | 助手难以判断改动归属 |
1.7 推荐的规则文件结构
针对上述问题,优化后的规则文件应围绕「怎么理解项目、怎么动手、何时查文档、何时停下来问人」组织。下面是一个可直接套用的匿名化模板骨架:
markdown
# 示例项目开发指南
## 项目架构
<!-- 一句话定位 + 目录职责 + 核心数据流 -->
目录:
- agents/ 智能体实现
- tools/ 外部数据源与工具客户端
- logic/ 业务逻辑层
- core/ 配置与核心模块
- docs/ 详细文档
数据流:消息输入 → 服务入口 → Agent 编排 → 工具调用 → 外部数据源 → 结果分析 → 输出回复
## 标准工作流程
### 修改现有功能
1. 理解需求,不确定时先询问用户
2. 读取相关文件(参考下方「何时读取哪些文件」)
3. 做最小化修改,只改动必要部分
4. 运行相关测试验证变更
5. 同步更新对应文档与本规则文件
### 添加新功能
1. 确认采用的架构模式与模块归属
2. 按「常见开发场景」添加工具 / 客户端
3. 为核心路径编写测试
4. 补充配置项与环境变量示例
5. 编写对应说明文档
## 何时读取哪些文件
| 任务类型 | 必读文件 | 可选参考 |
| --- | --- | --- |
| 修改 Agent 逻辑 | 对应入口文件 + 模块文档 | 工具目录 |
| 新增数据源 | 现有工具客户端 + 业务模型 | 工具规范文档 |
| 修改配置 | 配置模块 + 环境变量示例 | 部署文档 |
| 修改对外接口 | 服务入口 + 接口规范 | 配置模块 |
## 代码标准
### 命名规范
- 函数:snake_case
- 类:PascalCase
- 常量:UPPER_SNAKE_CASE
- 私有成员:前导下划线 _name
### 必须遵守
- I/O 操作使用异步方式
- 公开函数必须带有类型注解
- 外部调用必须捕获异常并记录日志
- 密钥与凭证只从环境变量读取,不硬编码
- 日志中对敏感信息做脱敏
- 用户输入必须做校验
### 禁止事项
- 不保留未使用的导入
- 不添加「以防万一」的冗余功能
- 重复三次以上再考虑抽象
- 安全敏感场景不跳过输入校验
## 测试要求
- 新增工具函数必须配套单元测试
- 修改 Agent 逻辑后手动验证完整流程
## 何时必须询问用户
- 需求描述模糊,缺少明确目标
- 存在多种实现方案且没有明显最优解
- 需要删除现有功能
- 需要修改对外接口、可能影响调用方
- 不确定某个文件或功能的用途
## 快速命令
<!-- 开发、测试、构建、部署等常用命令集中放在这里 -->
可以看到,优化后的结构把「情绪化宣言」替换成了可执行的流程、明确的边界和决策索引。这一章沉淀的分层、命名、命令、常见坑等约定,会在第 4 章进一步展开为代码层面的工程护栏。
第 2 章 计划先行:Plan 模式与需求冻结,把返工挡在写代码之前
本章解决什么问题:避免「边做边改」,把需求对齐和方案评审放到写代码之前,用前置计划降低返工率。
2.1 两种模式的分工
主流 AI 编程助手一般提供两类工作状态:计划模式 与执行模式。两者职责应当分开,而不是混用。
| 工作状态 | 职责 | 是否产生代码改动 | 适用阶段 |
|---|---|---|---|
| 计划模式 | 理解需求、分析方案、比较取舍、输出方案与步骤,只做无副作用的讨论与评审 | 否,不直接改文件 | 需求对齐、方案设计、评审阶段 |
| 执行模式 | 在方案确定后按既定指令落地代码、运行命令、完成确定性改动 | 是 | 方案冻结后的实现阶段 |
把方案讨论和代码改动放在前置阶段完成,替代「边写边改」的低效模式:先在计划模式把方向谈清楚,再进入执行模式一次性落地。
2.2 什么时候值得先开计划模式
一个很实用的判断标准:如果你需要跟一位同事解释清楚才能让他完成的任务,就值得先走计划模式;如果一句话就能说清,直接执行即可。
- 适合计划模式:新功能模块设计、跨多个文件的重构、涉及状态流转或事务的核心功能、需要在多个技术方案之间取舍的任务。
- 适合直接执行:修复一个明确报错、改动一处样式、补充一段已知写法的样板代码。
判断依据不是任务大小,而是「意图与约束是否需要对齐」。
2.3 通行三步流程
实践中一套稳定的流程是「先讨论、再固化、后执行」:
#mermaid-svg-Lv2cLPJZYq9SVoN9{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-Lv2cLPJZYq9SVoN9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .error-icon{fill:#552222;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .marker.cross{stroke:#333333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 p{margin:0;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .cluster-label text{fill:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .cluster-label span{color:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .cluster-label span p{background-color:transparent;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .label text,#mermaid-svg-Lv2cLPJZYq9SVoN9 span{fill:#333;color:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .node rect,#mermaid-svg-Lv2cLPJZYq9SVoN9 .node circle,#mermaid-svg-Lv2cLPJZYq9SVoN9 .node ellipse,#mermaid-svg-Lv2cLPJZYq9SVoN9 .node polygon,#mermaid-svg-Lv2cLPJZYq9SVoN9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .rough-node .label text,#mermaid-svg-Lv2cLPJZYq9SVoN9 .node .label text,#mermaid-svg-Lv2cLPJZYq9SVoN9 .image-shape .label,#mermaid-svg-Lv2cLPJZYq9SVoN9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .rough-node .label,#mermaid-svg-Lv2cLPJZYq9SVoN9 .node .label,#mermaid-svg-Lv2cLPJZYq9SVoN9 .image-shape .label,#mermaid-svg-Lv2cLPJZYq9SVoN9 .icon-shape .label{text-align:center;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .node.clickable{cursor:pointer;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .arrowheadPath{fill:#333333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Lv2cLPJZYq9SVoN9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Lv2cLPJZYq9SVoN9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Lv2cLPJZYq9SVoN9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .cluster text{fill:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .cluster span{color:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 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-Lv2cLPJZYq9SVoN9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Lv2cLPJZYq9SVoN9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .icon-shape,#mermaid-svg-Lv2cLPJZYq9SVoN9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .icon-shape p,#mermaid-svg-Lv2cLPJZYq9SVoN9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .icon-shape .label rect,#mermaid-svg-Lv2cLPJZYq9SVoN9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Lv2cLPJZYq9SVoN9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Lv2cLPJZYq9SVoN9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Lv2cLPJZYq9SVoN9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 计划模式讨论
描述需求,来回打磨方案
② 编辑器固化指令
把确认的细节与约束写成完整执行说明
③ 切回执行模式
方案已充分对齐,批量完成实现
- 计划模式下来回讨论:先描述需求,助手给出方案;对不满意的环节,可以明确指出「第三步换一种方式」「这里换成另一个技术选型」,反复调整直到方案收敛。
- 用编辑器固化一份执行指令:方案基本确定后,打开本地默认编辑器,把讨论中确认的方案细节、约束条件、边界要求完整写进执行说明,保存后作为下一步输入。
- 切换到执行模式批量落地:计划已经讨论充分,就可以放心让助手按既定方案连续执行,不需要逐步反复确认。
这套流程的价值在于:方案的不确定性被消灭在写代码之前,执行阶段不再因为思路摇摆而大面积返工。
2.4 给「约束与路径」,而不是只给「结果」
计划阶段最影响可控性的,是输入信息的粒度。下面两种表达的可控性差异非常明显:
| 表达方式 | 输入示例 | 问题 |
|---|---|---|
| 只给结果(不推荐) | 「给我做一个鉴权系统。」 | 模型、存储、路由、过期策略全部由助手猜测,后续容易推翻重来 |
| 给约束与路径(推荐) | 「基于现有的用户模型实现邮箱 / 密码登录;会话存入缓存并设置过期时间;通过中间件保护受保护路由。」 | 现有模型、存储方式、策略、路由边界都已限定,助手在明确约束内实现 |
第一条指令只定义了「要什么」,第二条指令定义了「基于什么、怎么做、边界在哪里」。越具体的文件路径、技术选型和参考模式,助手越知道往哪走。 这一点会在第 3 章的对话原则中继续展开。
2.5 大型需求:采访 → SPEC → 评审 → 冻结 → 执行
对于复杂功能,单次计划讨论仍然可能漏掉需求盲点。实践中更稳妥的是一套五步规格流程:
#mermaid-svg-KKjDTn5O0Vbn2tjw{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-KKjDTn5O0Vbn2tjw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KKjDTn5O0Vbn2tjw .error-icon{fill:#552222;}#mermaid-svg-KKjDTn5O0Vbn2tjw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KKjDTn5O0Vbn2tjw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .marker.cross{stroke:#333333;}#mermaid-svg-KKjDTn5O0Vbn2tjw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KKjDTn5O0Vbn2tjw p{margin:0;}#mermaid-svg-KKjDTn5O0Vbn2tjw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .cluster-label text{fill:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .cluster-label span{color:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .cluster-label span p{background-color:transparent;}#mermaid-svg-KKjDTn5O0Vbn2tjw .label text,#mermaid-svg-KKjDTn5O0Vbn2tjw span{fill:#333;color:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .node rect,#mermaid-svg-KKjDTn5O0Vbn2tjw .node circle,#mermaid-svg-KKjDTn5O0Vbn2tjw .node ellipse,#mermaid-svg-KKjDTn5O0Vbn2tjw .node polygon,#mermaid-svg-KKjDTn5O0Vbn2tjw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .rough-node .label text,#mermaid-svg-KKjDTn5O0Vbn2tjw .node .label text,#mermaid-svg-KKjDTn5O0Vbn2tjw .image-shape .label,#mermaid-svg-KKjDTn5O0Vbn2tjw .icon-shape .label{text-anchor:middle;}#mermaid-svg-KKjDTn5O0Vbn2tjw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .rough-node .label,#mermaid-svg-KKjDTn5O0Vbn2tjw .node .label,#mermaid-svg-KKjDTn5O0Vbn2tjw .image-shape .label,#mermaid-svg-KKjDTn5O0Vbn2tjw .icon-shape .label{text-align:center;}#mermaid-svg-KKjDTn5O0Vbn2tjw .node.clickable{cursor:pointer;}#mermaid-svg-KKjDTn5O0Vbn2tjw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .arrowheadPath{fill:#333333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KKjDTn5O0Vbn2tjw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KKjDTn5O0Vbn2tjw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KKjDTn5O0Vbn2tjw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KKjDTn5O0Vbn2tjw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .cluster text{fill:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw .cluster span{color:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw 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-KKjDTn5O0Vbn2tjw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KKjDTn5O0Vbn2tjw rect.text{fill:none;stroke-width:0;}#mermaid-svg-KKjDTn5O0Vbn2tjw .icon-shape,#mermaid-svg-KKjDTn5O0Vbn2tjw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KKjDTn5O0Vbn2tjw .icon-shape p,#mermaid-svg-KKjDTn5O0Vbn2tjw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KKjDTn5O0Vbn2tjw .icon-shape .label rect,#mermaid-svg-KKjDTn5O0Vbn2tjw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KKjDTn5O0Vbn2tjw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KKjDTn5O0Vbn2tjw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KKjDTn5O0Vbn2tjw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 架构式采访
补全需求边界与约束盲点
② 生成 SPEC 规格文档
结构化固化方案
③ 方案评审
④ 需求冻结
⑤ 新会话按 SPEC 执行
- 架构式采访:让助手以架构师视角反向提问,补全需求边界、技术约束、异常场景、非功能需求(性能、并发、可观测性等)等容易被忽略的盲点。
- 生成 SPEC 规格文档:把讨论结果整理成结构化规格文档,明确目标、模块划分、接口契约、数据模型、异常处理与验收标准。
- 方案评审:人工核对规格文档是否符合预期,补齐遗漏。
- 需求冻结:评审通过后锁定方案,执行过程中不随意变更需求;确需变更时回到评审流程重新走 SPEC。
- 新会话按冻结 SPEC 执行:另起一个干净会话,基于已冻结的规格文档开发,避免前期讨论的冗余上下文干扰实现。
规格文档应纳入版本管理,作为后续开发、测试与验收的统一依据。需要特别注意的是:计划阶段就要先想清楚数据模型、状态与契约,而不是等代码写起来再补------这正好衔接第 4 章「模型先行」的工程护栏。
第 3 章 对话与上下文:给对的信息,而不是给全部信息
本章解决什么问题:用更少但更准的上下文完成任务,避免对话变长后注意力分散、输出质量下降。
3.1 三条提示原则
同样是向助手描述任务,表达方式直接影响结果可控性。可以归纳为三条原则:
| 原则 | 做法 | 价值 |
|---|---|---|
| 具体化 | 指定文件路径、业务场景、技术选型、参考模式 | 消除歧义,让助手在正确位置动手 |
| 指向已有模式 | 给一个写得好的现有实现作为范本,让它「照着这个做」 | 复用团队既有风格,比文字描述十行更有效 |
| 描述症状,不猜原因 | 报出现象与复现路径,让助手自己定位根因 | 避免人工预判把排查方向带偏 |
助手阅读代码的能力很强,给它一个现成范本,往往比用一堆文字描述风格要求更准确。而排查问题时,在没有确认根因前直接断言「是某个模块有问题」,反而可能让助手顺着错误假设走下去;正确做法是先描述可观察的症状与复现条件。
3.2 三组不推荐 / 推荐对照
第一组:新功能需求
| 不推荐(模糊) | 推荐(具体 + 指向范本) |
|---|---|
| 帮我加个搜索功能 | 在导航栏组件中添加搜索框,针对文章列表数据做模糊匹配,参考现有筛选下拉组件的交互样式 |
第二组:接口排查
| 不推荐(信息缺失) | 推荐(具体接口 + 现象 + 相关文件) |
|---|---|
| 接口报错了,帮我看看 | POST /api/orders 在数量大于 100 时返回 500,检查请求入口对应的参数校验与数据库写入逻辑 |
第三组:性能优化
| 不推荐(空泛目标) | 推荐(量化瓶颈 + 现状 + 目标) |
|---|---|
| 优化一下性能 | 首页加载约 4 秒,主要瓶颈在仪表盘组件一次性拉取全部用户数据;改为分页加载,每页 20 条 |
可以看到,推荐写法都包含了位置、现状、约束或目标,助手不需要再反复追问。
3.3 排查时结合调试工具
对于 Web 应用,助手看不到浏览器里真实发生的网络交互,排查接口问题时应主动结合开发者工具:把请求方法、路径、请求参数、响应状态码和响应体一并提供给助手,避免双方在抽象描述里反复猜测。前端样式问题则附上 DOM 结构、相关样式与实际渲染表现,定位效率会明显提高。
3.4 上下文会在远未用满时开始退化
AI 助手存在上下文长度上限,对话越长,对当前任务的注意力越容易被稀释;输出质量往往在上下文还没有占满时就开始下降。上下文管理的核心原则是:
不是给所有信息,而是给对的信息。让助手看到解决当前问题需要的上下文,而不是整个项目的百科全书。
常用的上下文控制做法有五种:
- 给对话定范围:一个会话只聚焦一个功能或任务,不把互不相关的需求塞进同一段对话。
- 用外部记忆:把计划、进度、决策写入真实文件(如规则文件、规格文档、任务清单),而不是全部依赖对话历史。
- 必要时复制重置:需要切换到全新任务时,把关键上下文固化到文件后开启新会话。
- 知道何时清空:任务完成或方向跑偏时主动结束当前会话,而不是无限延续。
- 建立「AI 无状态」的心智模型:助手每次会话并不天然记住历史,需要持久化的信息必须落在文件里。
3.5 以一个解耦功能为一次开发单位
结合前面的规则文件与计划模式,推荐的会话粒度是:以一个解耦、内聚的功能作为一次多轮对话单位。
#mermaid-svg-WeVNi0YYyUD45s0x{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-WeVNi0YYyUD45s0x .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WeVNi0YYyUD45s0x .error-icon{fill:#552222;}#mermaid-svg-WeVNi0YYyUD45s0x .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WeVNi0YYyUD45s0x .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WeVNi0YYyUD45s0x .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WeVNi0YYyUD45s0x .marker.cross{stroke:#333333;}#mermaid-svg-WeVNi0YYyUD45s0x svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WeVNi0YYyUD45s0x p{margin:0;}#mermaid-svg-WeVNi0YYyUD45s0x .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WeVNi0YYyUD45s0x .cluster-label text{fill:#333;}#mermaid-svg-WeVNi0YYyUD45s0x .cluster-label span{color:#333;}#mermaid-svg-WeVNi0YYyUD45s0x .cluster-label span p{background-color:transparent;}#mermaid-svg-WeVNi0YYyUD45s0x .label text,#mermaid-svg-WeVNi0YYyUD45s0x span{fill:#333;color:#333;}#mermaid-svg-WeVNi0YYyUD45s0x .node rect,#mermaid-svg-WeVNi0YYyUD45s0x .node circle,#mermaid-svg-WeVNi0YYyUD45s0x .node ellipse,#mermaid-svg-WeVNi0YYyUD45s0x .node polygon,#mermaid-svg-WeVNi0YYyUD45s0x .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WeVNi0YYyUD45s0x .rough-node .label text,#mermaid-svg-WeVNi0YYyUD45s0x .node .label text,#mermaid-svg-WeVNi0YYyUD45s0x .image-shape .label,#mermaid-svg-WeVNi0YYyUD45s0x .icon-shape .label{text-anchor:middle;}#mermaid-svg-WeVNi0YYyUD45s0x .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WeVNi0YYyUD45s0x .rough-node .label,#mermaid-svg-WeVNi0YYyUD45s0x .node .label,#mermaid-svg-WeVNi0YYyUD45s0x .image-shape .label,#mermaid-svg-WeVNi0YYyUD45s0x .icon-shape .label{text-align:center;}#mermaid-svg-WeVNi0YYyUD45s0x .node.clickable{cursor:pointer;}#mermaid-svg-WeVNi0YYyUD45s0x .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WeVNi0YYyUD45s0x .arrowheadPath{fill:#333333;}#mermaid-svg-WeVNi0YYyUD45s0x .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WeVNi0YYyUD45s0x .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WeVNi0YYyUD45s0x .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WeVNi0YYyUD45s0x .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WeVNi0YYyUD45s0x .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WeVNi0YYyUD45s0x .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WeVNi0YYyUD45s0x .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WeVNi0YYyUD45s0x .cluster text{fill:#333;}#mermaid-svg-WeVNi0YYyUD45s0x .cluster span{color:#333;}#mermaid-svg-WeVNi0YYyUD45s0x 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-WeVNi0YYyUD45s0x .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WeVNi0YYyUD45s0x rect.text{fill:none;stroke-width:0;}#mermaid-svg-WeVNi0YYyUD45s0x .icon-shape,#mermaid-svg-WeVNi0YYyUD45s0x .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WeVNi0YYyUD45s0x .icon-shape p,#mermaid-svg-WeVNi0YYyUD45s0x .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WeVNi0YYyUD45s0x .icon-shape .label rect,#mermaid-svg-WeVNi0YYyUD45s0x .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WeVNi0YYyUD45s0x .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WeVNi0YYyUD45s0x .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WeVNi0YYyUD45s0x :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 审查通过,上下文作废
规则文件
静态约束与约定
计划模式讨论
数据传递 · 类型 · 接口 · 路由 · 业务作用域
沿固定代码链路实现
完成后审查该功能
开启新会话处理下一个功能
一次功能开发沿固定链路推进,下面是一套通用的前后端代码链路示意(不同项目目录命名可能不同,职责分层是通用的):
#mermaid-svg-LXFNLnCnvAgJScLP{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-LXFNLnCnvAgJScLP .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LXFNLnCnvAgJScLP .error-icon{fill:#552222;}#mermaid-svg-LXFNLnCnvAgJScLP .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LXFNLnCnvAgJScLP .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LXFNLnCnvAgJScLP .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LXFNLnCnvAgJScLP .marker.cross{stroke:#333333;}#mermaid-svg-LXFNLnCnvAgJScLP svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LXFNLnCnvAgJScLP p{margin:0;}#mermaid-svg-LXFNLnCnvAgJScLP .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LXFNLnCnvAgJScLP .cluster-label text{fill:#333;}#mermaid-svg-LXFNLnCnvAgJScLP .cluster-label span{color:#333;}#mermaid-svg-LXFNLnCnvAgJScLP .cluster-label span p{background-color:transparent;}#mermaid-svg-LXFNLnCnvAgJScLP .label text,#mermaid-svg-LXFNLnCnvAgJScLP span{fill:#333;color:#333;}#mermaid-svg-LXFNLnCnvAgJScLP .node rect,#mermaid-svg-LXFNLnCnvAgJScLP .node circle,#mermaid-svg-LXFNLnCnvAgJScLP .node ellipse,#mermaid-svg-LXFNLnCnvAgJScLP .node polygon,#mermaid-svg-LXFNLnCnvAgJScLP .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LXFNLnCnvAgJScLP .rough-node .label text,#mermaid-svg-LXFNLnCnvAgJScLP .node .label text,#mermaid-svg-LXFNLnCnvAgJScLP .image-shape .label,#mermaid-svg-LXFNLnCnvAgJScLP .icon-shape .label{text-anchor:middle;}#mermaid-svg-LXFNLnCnvAgJScLP .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LXFNLnCnvAgJScLP .rough-node .label,#mermaid-svg-LXFNLnCnvAgJScLP .node .label,#mermaid-svg-LXFNLnCnvAgJScLP .image-shape .label,#mermaid-svg-LXFNLnCnvAgJScLP .icon-shape .label{text-align:center;}#mermaid-svg-LXFNLnCnvAgJScLP .node.clickable{cursor:pointer;}#mermaid-svg-LXFNLnCnvAgJScLP .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LXFNLnCnvAgJScLP .arrowheadPath{fill:#333333;}#mermaid-svg-LXFNLnCnvAgJScLP .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LXFNLnCnvAgJScLP .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LXFNLnCnvAgJScLP .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LXFNLnCnvAgJScLP .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LXFNLnCnvAgJScLP .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LXFNLnCnvAgJScLP .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LXFNLnCnvAgJScLP .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LXFNLnCnvAgJScLP .cluster text{fill:#333;}#mermaid-svg-LXFNLnCnvAgJScLP .cluster span{color:#333;}#mermaid-svg-LXFNLnCnvAgJScLP 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-LXFNLnCnvAgJScLP .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LXFNLnCnvAgJScLP rect.text{fill:none;stroke-width:0;}#mermaid-svg-LXFNLnCnvAgJScLP .icon-shape,#mermaid-svg-LXFNLnCnvAgJScLP .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LXFNLnCnvAgJScLP .icon-shape p,#mermaid-svg-LXFNLnCnvAgJScLP .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LXFNLnCnvAgJScLP .icon-shape .label rect,#mermaid-svg-LXFNLnCnvAgJScLP .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LXFNLnCnvAgJScLP .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LXFNLnCnvAgJScLP .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LXFNLnCnvAgJScLP :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 数据模型层
业务服务层
接口适配层
路由层
前端请求层
前端视图层
具体做法是:规则文件提供静态约束;计划阶段讨论清楚数据如何传递、字段类型、接口规范、路由归属与业务作用域;沿上述链路完成实现并审查;审查通过后,这次对话的上下文就可以作废。把上下文主动权握在自己手里------通过规则文件和清晰的功能边界控制,而不是把大量信息堆进单次提示词。
3.6 常用会话操作速查
不同工具的具体命令名称可能不同,下表按功能归纳,对应到自己使用的工具即可:
| 操作 | 用途 | 触发时机 |
|---|---|---|
| 清空当前会话 | 切换到完全不相关的任务 | 任务主题发生变化 |
| 压缩上下文 | 压缩过长的对话历史 | 会话变长、助手开始变慢或遗忘 |
| 中断当前操作 | 停止正在执行的任务 | 助手走向了不想要的方向 |
| 回滚 | 撤销错误改动,恢复指定历史状态 | 助手改坏了代码,需要回到某个节点 |
| 恢复历史会话 | 继续上一次未完成的对话 | 终端意外关闭后需要接续 |
| 按编号恢复会话 | 回到某个指定历史会话继续 | 需要接续更早的任务 |
| 侧链提问 | 问一个不相关的小问题,不污染主上下文 | 临时疑问、概念确认 |
第 4 章 护栏:AI 生成代码必须守住的工程边界
本章解决什么问题:回答「AI 生成的代码应该长什么样」。工具侧方法再充分,代码如果没有分层边界和工程纪律,依然会越改越乱。本章给出一套不绑定具体框架的通用护栏。
4.1 两个心智转变
在指挥 AI 写代码之前,先完成两个认知转变:
- 后端不是「写接口」,而是一套协议驱动的分层系统:每个接口只是系统对外暴露的入口,背后要有清晰的职责分层。
- 前端不是「堆页面」,而是状态、路由、请求、渲染的协调系统:页面只是最终呈现,请求、状态、组件各有归属。
工程的目标不是「先跑通就行」,而是让变化可控、职责清楚、别人(包括之后重新接手的自己和 AI)能顺利接手。AI 可以快速生成标准代码,但边界、契约和一致性需要人提前划定。
4.2 后端分层与单向依赖
通用后端职责可以分为四层,依赖方向只能自上而下,禁止跨层反向调用:
#mermaid-svg-SXtah8P3tLZYUwAs{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-SXtah8P3tLZYUwAs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SXtah8P3tLZYUwAs .error-icon{fill:#552222;}#mermaid-svg-SXtah8P3tLZYUwAs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SXtah8P3tLZYUwAs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SXtah8P3tLZYUwAs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SXtah8P3tLZYUwAs .marker.cross{stroke:#333333;}#mermaid-svg-SXtah8P3tLZYUwAs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SXtah8P3tLZYUwAs p{margin:0;}#mermaid-svg-SXtah8P3tLZYUwAs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SXtah8P3tLZYUwAs .cluster-label text{fill:#333;}#mermaid-svg-SXtah8P3tLZYUwAs .cluster-label span{color:#333;}#mermaid-svg-SXtah8P3tLZYUwAs .cluster-label span p{background-color:transparent;}#mermaid-svg-SXtah8P3tLZYUwAs .label text,#mermaid-svg-SXtah8P3tLZYUwAs span{fill:#333;color:#333;}#mermaid-svg-SXtah8P3tLZYUwAs .node rect,#mermaid-svg-SXtah8P3tLZYUwAs .node circle,#mermaid-svg-SXtah8P3tLZYUwAs .node ellipse,#mermaid-svg-SXtah8P3tLZYUwAs .node polygon,#mermaid-svg-SXtah8P3tLZYUwAs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SXtah8P3tLZYUwAs .rough-node .label text,#mermaid-svg-SXtah8P3tLZYUwAs .node .label text,#mermaid-svg-SXtah8P3tLZYUwAs .image-shape .label,#mermaid-svg-SXtah8P3tLZYUwAs .icon-shape .label{text-anchor:middle;}#mermaid-svg-SXtah8P3tLZYUwAs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SXtah8P3tLZYUwAs .rough-node .label,#mermaid-svg-SXtah8P3tLZYUwAs .node .label,#mermaid-svg-SXtah8P3tLZYUwAs .image-shape .label,#mermaid-svg-SXtah8P3tLZYUwAs .icon-shape .label{text-align:center;}#mermaid-svg-SXtah8P3tLZYUwAs .node.clickable{cursor:pointer;}#mermaid-svg-SXtah8P3tLZYUwAs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SXtah8P3tLZYUwAs .arrowheadPath{fill:#333333;}#mermaid-svg-SXtah8P3tLZYUwAs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SXtah8P3tLZYUwAs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SXtah8P3tLZYUwAs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SXtah8P3tLZYUwAs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SXtah8P3tLZYUwAs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SXtah8P3tLZYUwAs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SXtah8P3tLZYUwAs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SXtah8P3tLZYUwAs .cluster text{fill:#333;}#mermaid-svg-SXtah8P3tLZYUwAs .cluster span{color:#333;}#mermaid-svg-SXtah8P3tLZYUwAs 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-SXtah8P3tLZYUwAs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SXtah8P3tLZYUwAs rect.text{fill:none;stroke-width:0;}#mermaid-svg-SXtah8P3tLZYUwAs .icon-shape,#mermaid-svg-SXtah8P3tLZYUwAs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SXtah8P3tLZYUwAs .icon-shape p,#mermaid-svg-SXtah8P3tLZYUwAs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SXtah8P3tLZYUwAs .icon-shape .label rect,#mermaid-svg-SXtah8P3tLZYUwAs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SXtah8P3tLZYUwAs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SXtah8P3tLZYUwAs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SXtah8P3tLZYUwAs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 路由层
只负责路由分发与中间件
接口适配层
入参出参 · 参数校验 · 错误转译
业务服务层
业务规则 · 事务 · 状态流转 · 聚合与联查
数据模型 / 访问层
只表达数据结构与数据访问,不塞入业务流程
| 层级 | 职责边界 | 不应该做的事 |
|---|---|---|
| 路由层 | 路由注册、中间件挂载 | 不写业务逻辑 |
| 接口适配层 | 接收参数、参数校验、组装响应、错误转译 | 不直接访问数据库、不写业务规则 |
| 业务服务层 | 业务规则、事务边界、状态流转、数据聚合 | 不接触请求上下文对象、不直接拼数据库细节 |
| 数据模型 / 访问层 | 数据结构定义、数据读写 | 不承载业务流程与状态判断 |
核心纪律是单向依赖:上层可以调用下层,下层不感知上层;业务规则集中在业务服务层,数据结构集中在模型层。这样做的目的是隔离复杂度------改动某一层时,影响面被限制在该层内部。
4.3 前端分层与边界
前端同样需要职责分层,请求、状态、组件、页面各守边界:
#mermaid-svg-sgjEb68GzKylGG7m{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-sgjEb68GzKylGG7m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sgjEb68GzKylGG7m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sgjEb68GzKylGG7m .error-icon{fill:#552222;}#mermaid-svg-sgjEb68GzKylGG7m .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sgjEb68GzKylGG7m .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sgjEb68GzKylGG7m .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sgjEb68GzKylGG7m .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sgjEb68GzKylGG7m .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sgjEb68GzKylGG7m .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sgjEb68GzKylGG7m .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sgjEb68GzKylGG7m .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sgjEb68GzKylGG7m .marker.cross{stroke:#333333;}#mermaid-svg-sgjEb68GzKylGG7m svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sgjEb68GzKylGG7m p{margin:0;}#mermaid-svg-sgjEb68GzKylGG7m .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sgjEb68GzKylGG7m .cluster-label text{fill:#333;}#mermaid-svg-sgjEb68GzKylGG7m .cluster-label span{color:#333;}#mermaid-svg-sgjEb68GzKylGG7m .cluster-label span p{background-color:transparent;}#mermaid-svg-sgjEb68GzKylGG7m .label text,#mermaid-svg-sgjEb68GzKylGG7m span{fill:#333;color:#333;}#mermaid-svg-sgjEb68GzKylGG7m .node rect,#mermaid-svg-sgjEb68GzKylGG7m .node circle,#mermaid-svg-sgjEb68GzKylGG7m .node ellipse,#mermaid-svg-sgjEb68GzKylGG7m .node polygon,#mermaid-svg-sgjEb68GzKylGG7m .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sgjEb68GzKylGG7m .rough-node .label text,#mermaid-svg-sgjEb68GzKylGG7m .node .label text,#mermaid-svg-sgjEb68GzKylGG7m .image-shape .label,#mermaid-svg-sgjEb68GzKylGG7m .icon-shape .label{text-anchor:middle;}#mermaid-svg-sgjEb68GzKylGG7m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sgjEb68GzKylGG7m .rough-node .label,#mermaid-svg-sgjEb68GzKylGG7m .node .label,#mermaid-svg-sgjEb68GzKylGG7m .image-shape .label,#mermaid-svg-sgjEb68GzKylGG7m .icon-shape .label{text-align:center;}#mermaid-svg-sgjEb68GzKylGG7m .node.clickable{cursor:pointer;}#mermaid-svg-sgjEb68GzKylGG7m .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sgjEb68GzKylGG7m .arrowheadPath{fill:#333333;}#mermaid-svg-sgjEb68GzKylGG7m .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sgjEb68GzKylGG7m .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sgjEb68GzKylGG7m .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sgjEb68GzKylGG7m .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sgjEb68GzKylGG7m .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sgjEb68GzKylGG7m .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sgjEb68GzKylGG7m .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sgjEb68GzKylGG7m .cluster text{fill:#333;}#mermaid-svg-sgjEb68GzKylGG7m .cluster span{color:#333;}#mermaid-svg-sgjEb68GzKylGG7m 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-sgjEb68GzKylGG7m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sgjEb68GzKylGG7m rect.text{fill:none;stroke-width:0;}#mermaid-svg-sgjEb68GzKylGG7m .icon-shape,#mermaid-svg-sgjEb68GzKylGG7m .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sgjEb68GzKylGG7m .icon-shape p,#mermaid-svg-sgjEb68GzKylGG7m .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sgjEb68GzKylGG7m .icon-shape .label rect,#mermaid-svg-sgjEb68GzKylGG7m .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sgjEb68GzKylGG7m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sgjEb68GzKylGG7m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sgjEb68GzKylGG7m :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 视图层(页面)
负责交互与展示
请求层
统一收口所有后端请求
可复用组件层
表单、表格等通用交互
全局状态层
承载跨页面、长生命周期状态
- 页面只负责交互与展示,不在页面里散落书写请求;
- 所有后端请求统一收口到请求层,后端协议变化时只改这一处;
- 可复用交互抽成组件,不重复造表单和表格;
- 全局状态进入统一状态管理,组件不私自修改共享状态。
4.4 五条工程原则
把分层思想提炼成五条可执行原则,作为 AI 生成代码时必须遵守的护栏:
| 原则 | 含义 | 反例 |
|---|---|---|
| 分层是复杂度隔离手段 | 目录划分服务于职责隔离,不是习惯形式 | 把业务规则散落到各个层级 |
| 单向依赖是防失控底线 | 依赖方向固定,避免循环依赖与跨层乱调 | 模型层反向调用业务层 |
| 统一契约是协作成本控制 | 入参、出参、错误结构保持统一约定 | 每个接口自造响应格式 |
| 初始化注册是交付的一部分 | 路由、菜单、权限、配置、迁移等注册动作属于交付内容 | 代码写完却没有注册接入系统 |
| 代码生成只负责标准件,业务价值必须手写把关 | AI 生成样板与骨架,核心业务规则由人确认 | 把复杂业务判断完全交给生成结果 |
4.5 先设计模型,再写功能
接到一个新功能,不要急着让 AI 生成页面和接口,先把数据模型想清楚。需要先回答五个问题:
- 领域对象是什么:这个功能围绕哪个业务实体展开?
- 关键字段和类型是什么:每个字段的含义、类型、是否可空、约束是什么?
- 状态有哪些,谁能推动状态变化:实体处于哪些状态,哪些动作可以触发流转?
- 查询维度和分页结构是什么:列表按什么条件筛选、如何排序、分页结构如何定义?
- 哪些字段是单一事实来源:同一信息只在一个地方定义,避免多处重复维护。
模型定义清楚之后,接口、业务逻辑和页面才有稳定的依托。这与第 2 章计划阶段「先定模型、状态与契约」是一致的。
4.6 标准开发顺序
一个功能从模型到联调,推荐按下面的顺序推进,每一步为下一步提供稳定输入:
#mermaid-svg-NiNfp1Xq0A8bu7u9{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-NiNfp1Xq0A8bu7u9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .error-icon{fill:#552222;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .marker.cross{stroke:#333333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 p{margin:0;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .cluster-label text{fill:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .cluster-label span{color:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .cluster-label span p{background-color:transparent;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .label text,#mermaid-svg-NiNfp1Xq0A8bu7u9 span{fill:#333;color:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .node rect,#mermaid-svg-NiNfp1Xq0A8bu7u9 .node circle,#mermaid-svg-NiNfp1Xq0A8bu7u9 .node ellipse,#mermaid-svg-NiNfp1Xq0A8bu7u9 .node polygon,#mermaid-svg-NiNfp1Xq0A8bu7u9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .rough-node .label text,#mermaid-svg-NiNfp1Xq0A8bu7u9 .node .label text,#mermaid-svg-NiNfp1Xq0A8bu7u9 .image-shape .label,#mermaid-svg-NiNfp1Xq0A8bu7u9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .rough-node .label,#mermaid-svg-NiNfp1Xq0A8bu7u9 .node .label,#mermaid-svg-NiNfp1Xq0A8bu7u9 .image-shape .label,#mermaid-svg-NiNfp1Xq0A8bu7u9 .icon-shape .label{text-align:center;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .node.clickable{cursor:pointer;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .arrowheadPath{fill:#333333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NiNfp1Xq0A8bu7u9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NiNfp1Xq0A8bu7u9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NiNfp1Xq0A8bu7u9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .cluster text{fill:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .cluster span{color:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 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-NiNfp1Xq0A8bu7u9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NiNfp1Xq0A8bu7u9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .icon-shape,#mermaid-svg-NiNfp1Xq0A8bu7u9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .icon-shape p,#mermaid-svg-NiNfp1Xq0A8bu7u9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .icon-shape .label rect,#mermaid-svg-NiNfp1Xq0A8bu7u9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NiNfp1Xq0A8bu7u9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NiNfp1Xq0A8bu7u9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NiNfp1Xq0A8bu7u9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 模型与请求定义
② 业务服务层
③ 接口适配层
④ 路由层
⑤ 装配注册
路由 · 菜单 · 权限 · 迁移 · 插件
⑥ 前端请求 · 状态 · 视图
⑦ 联调 · 补权限 · 补文档 · 补测试
顺序的意义在于:先固定数据结构,再写业务规则,再暴露接口,最后接前端;装配注册(路由、菜单、权限、数据迁移、插件挂载)不是收尾装饰,而是功能真正接入系统的必要环节。
4.7 六条工程纪律
在具体实现过程中,需要守住以下纪律:
| 纪律 | 说明 |
|---|---|
| 生成物不手改 | 由工具或模板自动生成的文件只维护源头定义,不直接修改生成物 |
| 响应与错误体系统一 | 成功响应与错误走统一标准结构,不在单个功能里自造 code、msg 字段 |
| 鉴权统一 | 认证与权限校验走统一机制,不为每个功能发明一套认证逻辑 |
| 注释即协作契约 | 接口注释是团队协作约定的一部分,不是可有可无的装饰 |
| 单一事实来源 | 一个信息只保留一个可信来源,避免「双份真相」不一致 |
| 优先维护源头 | 接口定义、装配定义、配置定义、前端请求与状态才是源头;看到生成物先追溯源头,不直接改生成物 |
4.8 接口契约基础:HTTP 方法与状态码
分层之上,接口层还要遵守统一的 HTTP 语义约定。下面是常用方法的语义、幂等性与安全性对照(示例路径使用通用资源名 /orders、/users):
| 方法 | 语义 | 幂等性 | 安全性 | 示例 |
|---|---|---|---|---|
| GET | 获取资源 | 是 | 是 | GET /orders 查询订单列表 |
| POST | 创建资源 | 否 | 否 | POST /orders 创建订单 |
| PUT | 全量更新资源 | 是 | 否 | PUT /orders/1 全量更新订单 |
| PATCH | 部分更新资源 | 否 | 否 | PATCH /orders/1 部分更新订单 |
| DELETE | 删除资源 | 是 | 否 | DELETE /orders/1 删除订单 |
幂等性:同一请求重复执行多次,结果与执行一次相同;安全性:请求不改变服务端资源状态。
常用状态码与使用场景:
| 状态码 | 含义 | 使用场景 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 资源创建成功 |
| 204 | No Content | 删除成功,无返回体 |
| 400 | Bad Request | 参数错误 |
| 401 | Unauthorized | 未认证 |
| 403 | Forbidden | 已认证但无权限 |
| 404 | Not Found | 资源不存在 |
| 500 | Internal Server Error | 服务器内部错误 |
统一方法语义与状态码使用,可以让前后端协作和后续排查都有一致依据。
4.9 贯穿案例:一个订单功能如何交代边界
下面用一个通用的订单 / 支付功能,演示在让 AI 生成之前,人需要先划定哪些边界。案例中的表名、路径均为通用示例。
4.9.1 订单域核心字段
先确定订单模型至少包含以下字段:
| 字段 | 含义 |
|---|---|
| 业务单号 | 系统内部生成的订单唯一标识 |
| 外部支付单号 | 支付渠道返回的交易标识 |
| 用户标识 | 订单归属用户 |
| 金额 | 订单交易金额 |
| 支付渠道 | 发起支付的渠道类型 |
| 状态 | 当前订单状态 |
| 回调时间 | 支付结果回调到达时间 |
| 原始回调报文 | 渠道返回的原始数据留档,用于排查与对账 |
4.9.2 动作接口拆分
业务动作不应该塞进一个大接口,而要按职责拆成独立动作:
| 动作接口 | 职责 |
|---|---|
| 创建订单 | 生成待支付订单,校验业务前置条件 |
| 发起支付 | 向支付渠道发起支付,返回支付凭证 |
| 查询支付 | 主动向渠道查询最新支付状态 |
| 支付回调 | 接收渠道异步通知,更新订单状态 |
| 关闭订单 | 关闭超时未支付订单 |
| 退款 | 发起退款并更新退款状态 |
4.9.3 公开路由与私有路由
后台管理接口走需要登录态的私有路由;而支付回调由外部渠道主动调用,不会携带后台登录态,必须走公开路由,由回调自身的验签机制保证可信。这是路由边界上容易被忽略的一点。
4.9.4 业务服务层的五项关键约束
支付相关功能真正的复杂度集中在业务服务层,需要明确交代以下约束:
| 约束 | 要求 |
|---|---|
| 幂等 | 同一个回调重复到达,只能成功处理一次,不重复更新余额或流水 |
| 事务 | 订单状态、余额变动、流水写入必须在同一事务内完成,保证一致性 |
| 验签 | 不能信任回调参数本身,必须先校验签名确认来源可信 |
| 状态机 | 订单状态只能按既定方向流转,不允许随意逆转 |
| 对账 | 同时支持主动查单与被动回调两条路径,保证状态可核对 |
4.9.5 订单状态流转
订单是一个典型状态机,核心状态与流转如下:
#mermaid-svg-xN5oOLHQAuIz11se{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-xN5oOLHQAuIz11se .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-xN5oOLHQAuIz11se .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-xN5oOLHQAuIz11se .error-icon{fill:#552222;}#mermaid-svg-xN5oOLHQAuIz11se .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-xN5oOLHQAuIz11se .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-xN5oOLHQAuIz11se .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-xN5oOLHQAuIz11se .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-xN5oOLHQAuIz11se .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-xN5oOLHQAuIz11se .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-xN5oOLHQAuIz11se .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-xN5oOLHQAuIz11se .marker{fill:#333333;stroke:#333333;}#mermaid-svg-xN5oOLHQAuIz11se .marker.cross{stroke:#333333;}#mermaid-svg-xN5oOLHQAuIz11se svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-xN5oOLHQAuIz11se p{margin:0;}#mermaid-svg-xN5oOLHQAuIz11se defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-xN5oOLHQAuIz11se g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-xN5oOLHQAuIz11se g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-xN5oOLHQAuIz11se g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-xN5oOLHQAuIz11se g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-xN5oOLHQAuIz11se g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-xN5oOLHQAuIz11se .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-xN5oOLHQAuIz11se .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-xN5oOLHQAuIz11se .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-xN5oOLHQAuIz11se .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-xN5oOLHQAuIz11se .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-xN5oOLHQAuIz11se .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-xN5oOLHQAuIz11se .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-xN5oOLHQAuIz11se .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-xN5oOLHQAuIz11se .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-xN5oOLHQAuIz11se .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-xN5oOLHQAuIz11se .edgeLabel .label text{fill:#333;}#mermaid-svg-xN5oOLHQAuIz11se .label div .edgeLabel{color:#333;}#mermaid-svg-xN5oOLHQAuIz11se .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-xN5oOLHQAuIz11se .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-xN5oOLHQAuIz11se .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-xN5oOLHQAuIz11se .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-xN5oOLHQAuIz11se .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-xN5oOLHQAuIz11se .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xN5oOLHQAuIz11se .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xN5oOLHQAuIz11se #statediagram-barbEnd{fill:#333333;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-xN5oOLHQAuIz11se .cluster-label,#mermaid-svg-xN5oOLHQAuIz11se .nodeLabel{color:#131300;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-xN5oOLHQAuIz11se .note-edge{stroke-dasharray:5;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-note text{fill:black;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram-note .nodeLabel{color:black;}#mermaid-svg-xN5oOLHQAuIz11se .statediagram .edgeLabel{color:red;}#mermaid-svg-xN5oOLHQAuIz11se #dependencyStart,#mermaid-svg-xN5oOLHQAuIz11se #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-xN5oOLHQAuIz11se .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-xN5oOLHQAuIz11se :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 支付成功回调 / 主动查单确认
超时关闭或主动取消
退款成功
待支付
已支付
已关闭
已退款
4.9.6 前端页面与接入闭环
前端通常只需要两类页面:订单列表页、订单详情 / 状态变更 / 补单页。如果功能需要进入后台菜单,还必须补齐菜单注册、权限点配置与数据迁移,形成「代码 + 路由 + 菜单 + 权限 + 配置」的完整闭环------这正是 4.6 中装配注册环节的具体体现。
4.10 生成代码与业务代码的判别
在审查 AI 产出时,需要区分两类代码:
- 标准生成式 CRUD 样板:围绕单张数据表的标准增删改查,目录结构、接口形态高度模板化,可以由工具批量生成。
- 围绕既有业务规则的定制代码:绑定具体业务流程、状态流转、外部协作与一致性约束,无法用通用样板覆盖,需要人参与设计与把关。
判断一个模块是不是标准骨架,就看它的路由、接口、服务、前端请求与页面是否全部呈现模板化的标准 CRUD 结构;而像订单支付这类包含状态机、事务、验签和对账的功能,属于必须人工划定边界的业务代码。
第 5 章 真正的复杂度在状态流转,不在 CRUD
本章解决什么问题:帮助识别业务里真正复杂的部分,避免把所有功能都当成「增删改查」处理,同时给出判断代码质量和阅读代码的系统方法。
5.1 很多核心功能本质上是状态机
一个常见误解是:后台系统大部分功能就是 CRUD。实际上,系统里真正核心、最容易出错的功能,往往围绕状态流转展开,例如:
- 登录态的建立、保持与失效;
- 流式响应的开始、输出中、结束与中断;
- 异步任务的排队、执行中、成功、失败与重试;
- 多步骤协作任务的阶段推进;
- 订单与扣费状态的变化。
这些功能的复杂度不在「数据的增删改查」,而在状态之间如何流转、哪一步会失败、失败之后如何恢复。设计这类功能时,思维重心应当从「数据表有哪些字段」转向「状态如何变化」。
5.2 设计功能前先回答五个状态问题
每设计一个包含状态的功能,先依次回答下面五个问题:
- 有哪些状态:列出实体全部可能处于的状态,不遗漏中间态与异常态。
- 怎么流转:哪些动作可以触发状态变化,流转方向是否可逆。
- 哪一步可能失败:每个流转节点的失败点与失败表现是什么。
- 失败后怎么补偿:失败后回滚、重试、补偿或人工介入的策略是什么。
- 谁负责一致性:跨模块或跨外部系统时,由谁保证最终状态一致。
这五个问题回答清楚,状态机的骨架就基本成型;反过来,如果这五个问题模糊,代码实现很容易在边界情况下出现状态错乱。
5.3 判断一个实现是否合理
审查一段 AI 生成或已有代码时,可以用下面五个维度逐项检查:
| 检查维度 | 具体判断问题 |
|---|---|
| 边界是否清晰 | 各层、各组件职责是否明确,有没有越界调用 |
| 依赖方向是否正确 | 是否保持单向依赖,有无循环依赖与跨层调用 |
| 数据类型是否统一 | 同一字段在前后端、各层之间类型是否一致 |
| 是否形成完整闭环 | 是否完成注册、权限、菜单、配置、迁移等接入动作 |
| 改动影响面是否受控 | 未来修改某功能时,影响范围能否被限定在预期范围内 |
这张检查表既是人工评审标准,也可以在计划阶段作为约束写进提示词或规则文件,让 AI 生成时主动对照。
5.4 阅读代码的正确姿势
接手或排查功能时,不要一上来就扎进数据库表或超长页面模板,而应当按固定链路从上向下追踪。
后端阅读主线:
#mermaid-svg-uGU6egw2jRAlrusI{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-uGU6egw2jRAlrusI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uGU6egw2jRAlrusI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uGU6egw2jRAlrusI .error-icon{fill:#552222;}#mermaid-svg-uGU6egw2jRAlrusI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uGU6egw2jRAlrusI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uGU6egw2jRAlrusI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uGU6egw2jRAlrusI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uGU6egw2jRAlrusI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uGU6egw2jRAlrusI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uGU6egw2jRAlrusI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uGU6egw2jRAlrusI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uGU6egw2jRAlrusI .marker.cross{stroke:#333333;}#mermaid-svg-uGU6egw2jRAlrusI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uGU6egw2jRAlrusI p{margin:0;}#mermaid-svg-uGU6egw2jRAlrusI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uGU6egw2jRAlrusI .cluster-label text{fill:#333;}#mermaid-svg-uGU6egw2jRAlrusI .cluster-label span{color:#333;}#mermaid-svg-uGU6egw2jRAlrusI .cluster-label span p{background-color:transparent;}#mermaid-svg-uGU6egw2jRAlrusI .label text,#mermaid-svg-uGU6egw2jRAlrusI span{fill:#333;color:#333;}#mermaid-svg-uGU6egw2jRAlrusI .node rect,#mermaid-svg-uGU6egw2jRAlrusI .node circle,#mermaid-svg-uGU6egw2jRAlrusI .node ellipse,#mermaid-svg-uGU6egw2jRAlrusI .node polygon,#mermaid-svg-uGU6egw2jRAlrusI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uGU6egw2jRAlrusI .rough-node .label text,#mermaid-svg-uGU6egw2jRAlrusI .node .label text,#mermaid-svg-uGU6egw2jRAlrusI .image-shape .label,#mermaid-svg-uGU6egw2jRAlrusI .icon-shape .label{text-anchor:middle;}#mermaid-svg-uGU6egw2jRAlrusI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uGU6egw2jRAlrusI .rough-node .label,#mermaid-svg-uGU6egw2jRAlrusI .node .label,#mermaid-svg-uGU6egw2jRAlrusI .image-shape .label,#mermaid-svg-uGU6egw2jRAlrusI .icon-shape .label{text-align:center;}#mermaid-svg-uGU6egw2jRAlrusI .node.clickable{cursor:pointer;}#mermaid-svg-uGU6egw2jRAlrusI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uGU6egw2jRAlrusI .arrowheadPath{fill:#333333;}#mermaid-svg-uGU6egw2jRAlrusI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uGU6egw2jRAlrusI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uGU6egw2jRAlrusI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uGU6egw2jRAlrusI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uGU6egw2jRAlrusI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uGU6egw2jRAlrusI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uGU6egw2jRAlrusI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uGU6egw2jRAlrusI .cluster text{fill:#333;}#mermaid-svg-uGU6egw2jRAlrusI .cluster span{color:#333;}#mermaid-svg-uGU6egw2jRAlrusI 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-uGU6egw2jRAlrusI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uGU6egw2jRAlrusI rect.text{fill:none;stroke-width:0;}#mermaid-svg-uGU6egw2jRAlrusI .icon-shape,#mermaid-svg-uGU6egw2jRAlrusI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uGU6egw2jRAlrusI .icon-shape p,#mermaid-svg-uGU6egw2jRAlrusI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uGU6egw2jRAlrusI .icon-shape .label rect,#mermaid-svg-uGU6egw2jRAlrusI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uGU6egw2jRAlrusI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uGU6egw2jRAlrusI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uGU6egw2jRAlrusI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 程序入口
装配 / 依赖注册
服务层
业务规则层
数据访问层
前端阅读主线:
#mermaid-svg-re6i77VU4B9YMhKc{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-re6i77VU4B9YMhKc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-re6i77VU4B9YMhKc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-re6i77VU4B9YMhKc .error-icon{fill:#552222;}#mermaid-svg-re6i77VU4B9YMhKc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-re6i77VU4B9YMhKc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-re6i77VU4B9YMhKc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-re6i77VU4B9YMhKc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-re6i77VU4B9YMhKc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-re6i77VU4B9YMhKc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-re6i77VU4B9YMhKc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-re6i77VU4B9YMhKc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-re6i77VU4B9YMhKc .marker.cross{stroke:#333333;}#mermaid-svg-re6i77VU4B9YMhKc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-re6i77VU4B9YMhKc p{margin:0;}#mermaid-svg-re6i77VU4B9YMhKc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-re6i77VU4B9YMhKc .cluster-label text{fill:#333;}#mermaid-svg-re6i77VU4B9YMhKc .cluster-label span{color:#333;}#mermaid-svg-re6i77VU4B9YMhKc .cluster-label span p{background-color:transparent;}#mermaid-svg-re6i77VU4B9YMhKc .label text,#mermaid-svg-re6i77VU4B9YMhKc span{fill:#333;color:#333;}#mermaid-svg-re6i77VU4B9YMhKc .node rect,#mermaid-svg-re6i77VU4B9YMhKc .node circle,#mermaid-svg-re6i77VU4B9YMhKc .node ellipse,#mermaid-svg-re6i77VU4B9YMhKc .node polygon,#mermaid-svg-re6i77VU4B9YMhKc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-re6i77VU4B9YMhKc .rough-node .label text,#mermaid-svg-re6i77VU4B9YMhKc .node .label text,#mermaid-svg-re6i77VU4B9YMhKc .image-shape .label,#mermaid-svg-re6i77VU4B9YMhKc .icon-shape .label{text-anchor:middle;}#mermaid-svg-re6i77VU4B9YMhKc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-re6i77VU4B9YMhKc .rough-node .label,#mermaid-svg-re6i77VU4B9YMhKc .node .label,#mermaid-svg-re6i77VU4B9YMhKc .image-shape .label,#mermaid-svg-re6i77VU4B9YMhKc .icon-shape .label{text-align:center;}#mermaid-svg-re6i77VU4B9YMhKc .node.clickable{cursor:pointer;}#mermaid-svg-re6i77VU4B9YMhKc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-re6i77VU4B9YMhKc .arrowheadPath{fill:#333333;}#mermaid-svg-re6i77VU4B9YMhKc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-re6i77VU4B9YMhKc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-re6i77VU4B9YMhKc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-re6i77VU4B9YMhKc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-re6i77VU4B9YMhKc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-re6i77VU4B9YMhKc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-re6i77VU4B9YMhKc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-re6i77VU4B9YMhKc .cluster text{fill:#333;}#mermaid-svg-re6i77VU4B9YMhKc .cluster span{color:#333;}#mermaid-svg-re6i77VU4B9YMhKc 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-re6i77VU4B9YMhKc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-re6i77VU4B9YMhKc rect.text{fill:none;stroke-width:0;}#mermaid-svg-re6i77VU4B9YMhKc .icon-shape,#mermaid-svg-re6i77VU4B9YMhKc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-re6i77VU4B9YMhKc .icon-shape p,#mermaid-svg-re6i77VU4B9YMhKc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-re6i77VU4B9YMhKc .icon-shape .label rect,#mermaid-svg-re6i77VU4B9YMhKc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-re6i77VU4B9YMhKc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-re6i77VU4B9YMhKc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-re6i77VU4B9YMhKc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 程序入口
路由定义
前端请求层
状态层
视图层
单个功能追踪主线:从用户操作出发,沿前后端一路追到数据:
#mermaid-svg-8m3i6RNPBqJVmIf6{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-8m3i6RNPBqJVmIf6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8m3i6RNPBqJVmIf6 .error-icon{fill:#552222;}#mermaid-svg-8m3i6RNPBqJVmIf6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8m3i6RNPBqJVmIf6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .marker.cross{stroke:#333333;}#mermaid-svg-8m3i6RNPBqJVmIf6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8m3i6RNPBqJVmIf6 p{margin:0;}#mermaid-svg-8m3i6RNPBqJVmIf6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .cluster-label text{fill:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .cluster-label span{color:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .cluster-label span p{background-color:transparent;}#mermaid-svg-8m3i6RNPBqJVmIf6 .label text,#mermaid-svg-8m3i6RNPBqJVmIf6 span{fill:#333;color:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .node rect,#mermaid-svg-8m3i6RNPBqJVmIf6 .node circle,#mermaid-svg-8m3i6RNPBqJVmIf6 .node ellipse,#mermaid-svg-8m3i6RNPBqJVmIf6 .node polygon,#mermaid-svg-8m3i6RNPBqJVmIf6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .rough-node .label text,#mermaid-svg-8m3i6RNPBqJVmIf6 .node .label text,#mermaid-svg-8m3i6RNPBqJVmIf6 .image-shape .label,#mermaid-svg-8m3i6RNPBqJVmIf6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8m3i6RNPBqJVmIf6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .rough-node .label,#mermaid-svg-8m3i6RNPBqJVmIf6 .node .label,#mermaid-svg-8m3i6RNPBqJVmIf6 .image-shape .label,#mermaid-svg-8m3i6RNPBqJVmIf6 .icon-shape .label{text-align:center;}#mermaid-svg-8m3i6RNPBqJVmIf6 .node.clickable{cursor:pointer;}#mermaid-svg-8m3i6RNPBqJVmIf6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .arrowheadPath{fill:#333333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8m3i6RNPBqJVmIf6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8m3i6RNPBqJVmIf6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8m3i6RNPBqJVmIf6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8m3i6RNPBqJVmIf6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .cluster text{fill:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 .cluster span{color:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 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-8m3i6RNPBqJVmIf6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8m3i6RNPBqJVmIf6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8m3i6RNPBqJVmIf6 .icon-shape,#mermaid-svg-8m3i6RNPBqJVmIf6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8m3i6RNPBqJVmIf6 .icon-shape p,#mermaid-svg-8m3i6RNPBqJVmIf6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8m3i6RNPBqJVmIf6 .icon-shape .label rect,#mermaid-svg-8m3i6RNPBqJVmIf6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8m3i6RNPBqJVmIf6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8m3i6RNPBqJVmIf6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8m3i6RNPBqJVmIf6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 前端入口页面
前端请求层
接口定义
服务层
业务规则层
数据层
先建立全局链路认知,再深入具体实现,能避免在单个文件里迷失细节,也更容易发现边界是否被破坏。
第 6 章 扩展能力三层:Skills、Hooks 与 MCP
本章解决什么问题:理解 AI 编程助手三类扩展机制各自的定位与确定性差异,把重复经验沉淀为可复用能力。
6.1 三层解耦的能力模型
主流 AI 编程助手的扩展能力可以分为三层,分别对应规则、执行与集成三个维度:
#mermaid-svg-XfG3m0XZHfTU91Xz{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-XfG3m0XZHfTU91Xz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XfG3m0XZHfTU91Xz .error-icon{fill:#552222;}#mermaid-svg-XfG3m0XZHfTU91Xz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XfG3m0XZHfTU91Xz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XfG3m0XZHfTU91Xz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XfG3m0XZHfTU91Xz .marker.cross{stroke:#333333;}#mermaid-svg-XfG3m0XZHfTU91Xz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XfG3m0XZHfTU91Xz p{margin:0;}#mermaid-svg-XfG3m0XZHfTU91Xz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz .cluster-label text{fill:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz .cluster-label span{color:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz .cluster-label span p{background-color:transparent;}#mermaid-svg-XfG3m0XZHfTU91Xz .label text,#mermaid-svg-XfG3m0XZHfTU91Xz span{fill:#333;color:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz .node rect,#mermaid-svg-XfG3m0XZHfTU91Xz .node circle,#mermaid-svg-XfG3m0XZHfTU91Xz .node ellipse,#mermaid-svg-XfG3m0XZHfTU91Xz .node polygon,#mermaid-svg-XfG3m0XZHfTU91Xz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XfG3m0XZHfTU91Xz .rough-node .label text,#mermaid-svg-XfG3m0XZHfTU91Xz .node .label text,#mermaid-svg-XfG3m0XZHfTU91Xz .image-shape .label,#mermaid-svg-XfG3m0XZHfTU91Xz .icon-shape .label{text-anchor:middle;}#mermaid-svg-XfG3m0XZHfTU91Xz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XfG3m0XZHfTU91Xz .rough-node .label,#mermaid-svg-XfG3m0XZHfTU91Xz .node .label,#mermaid-svg-XfG3m0XZHfTU91Xz .image-shape .label,#mermaid-svg-XfG3m0XZHfTU91Xz .icon-shape .label{text-align:center;}#mermaid-svg-XfG3m0XZHfTU91Xz .node.clickable{cursor:pointer;}#mermaid-svg-XfG3m0XZHfTU91Xz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XfG3m0XZHfTU91Xz .arrowheadPath{fill:#333333;}#mermaid-svg-XfG3m0XZHfTU91Xz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XfG3m0XZHfTU91Xz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XfG3m0XZHfTU91Xz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XfG3m0XZHfTU91Xz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XfG3m0XZHfTU91Xz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XfG3m0XZHfTU91Xz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XfG3m0XZHfTU91Xz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XfG3m0XZHfTU91Xz .cluster text{fill:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz .cluster span{color:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz 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-XfG3m0XZHfTU91Xz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XfG3m0XZHfTU91Xz rect.text{fill:none;stroke-width:0;}#mermaid-svg-XfG3m0XZHfTU91Xz .icon-shape,#mermaid-svg-XfG3m0XZHfTU91Xz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XfG3m0XZHfTU91Xz .icon-shape p,#mermaid-svg-XfG3m0XZHfTU91Xz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XfG3m0XZHfTU91Xz .icon-shape .label rect,#mermaid-svg-XfG3m0XZHfTU91Xz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XfG3m0XZHfTU91Xz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XfG3m0XZHfTU91Xz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XfG3m0XZHfTU91Xz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 建议性遵从
确定性校验
规则层 · Skills
知识与工作流封装,教 AI 怎么做
执行层 · Hooks
生命周期强制钩子,关键节点自动执行
集成层 · MCP
外部系统连接器,让 AI 触达外部世界
| 机制 | 本质 | 执行确定性 | 典型适用场景 |
|---|---|---|---|
| Skills | Markdown 指令与工作流封装 | 高,但非 100%(建议性遵从) | 领域知识、可复用工作流、固定操作步骤 |
| Hooks | 生命周期脚本钩子 | 100% 确定性自动执行 | 格式化、代码检查、安全校验等强制动作 |
| MCP | 外部工具 / 系统连接器 | 由对应服务能力决定 | 数据库、内部 API、设计稿、错误日志、仓库与工单等外部系统 |
三者定位一句话概括:Skills 教助手怎么做,Hooks 在关键节点自动执行检查,MCP 把外部世界接进来。
6.2 Skills:从最常重复的那句话开始
Skills 的本质是把反复出现的操作步骤封装成可调用的知识单元。它通常由一份精简的说明文档和少量配套脚本组成,甚至可以只包含文档。
提炼方式很简单:回想自己最常对助手重复的那句话。例如每次提交前都说「先跑测试、格式化代码,再提交」,这就是一个 Skill 的雏形------把这些步骤写进 Skill 说明,之后用一条指令即可触发整套流程。Skills 存放在工具约定的本地规则目录下,按目录结构组织即可。
6.3 Hooks:在确定节点强制执行
Hooks 是挂在助手生命周期节点上的脚本,比如文件保存后、提交前,由工具确定性地自动执行,不受模型自由发挥影响。它适合承载必须强制保证的动作:代码格式化、静态检查、安全规则校验等。
编写 Hooks 不需要从零手写配置,可以直接用自然语言要求助手生成钩子配置并写入项目设置文件,再根据实际命令核对即可。建议把团队不可妥协的红线规则交给 Hooks 强制执行,而不是只写在文档里靠自觉遵守。
6.4 MCP:连接外部系统
MCP 解决的是「助手只能读写本地代码,无法触达外部系统」的问题。通过标准化连接器,助手可以在受控权限内访问外部工具与服务。常见通用场景包括:
| 连接器类型 | 能力 | 价值 |
|---|---|---|
| 数据库连接器 | 查询与读取数据库 | 无需人工复制查询结果贴给助手 |
| 内部 API 连接器 | 调用内部服务接口 | 让助手直接获取运行时数据 |
| 设计稿连接器 | 读取设计稿结构与样式 | 把设计信息直接转化为前端代码参考 |
| 错误日志连接器 | 获取线上错误日志与上下文 | 助手据此自动定位线上问题 |
| 仓库与工单连接器 | 操作代码仓库、任务与工单 | 支撑自动化的项目流程管理 |
6.5 团队级能力沉淀
把三层扩展结合起来,可以形成团队内部的能力复用体系:通用工作流封装为 Skills,强制规范交给 Hooks,外部系统能力通过 MCP 标准化接入。通用能力一次封装之后,团队内所有助手共享同一套标准,避免每个人重复摸索。这与第 1 章规则文件的团队共享思路一脉相承。
第 7 章 多 Agent 与子代理协作
本章解决什么问题:在主会话上下文有限、专业能力需要分工的情况下,用多个专职 Agent 分担专项任务,实现边开发边审计、专业能力标准化复用。
7.1 主会话的两个局限
单一会话在复杂任务中会遇到两类问题:
- 上下文溢出:任务涉及的文件、资料和讨论不断累积,挤占主会话上下文空间;
- 专业能力不足:主会话需要同时扮演开发、评审、测试等多种角色,难以在每个专项上保持深入。
子代理(Subagent)运行在独立的上下文窗口中,不占用主会话的上下文空间,可以针对特定场景定制专职专家,正好缓解这两个问题。
7.2 专家角色库
可以预定义一批通用专家角色,明确每个专家的权限、工具集与模型规格,开发过程中按需调用,实现专业能力的标准化复用:
| 专家角色 | 职责 | 权限特点 |
|---|---|---|
| 安全评审专家 | 审查代码安全风险、鉴权与输入校验问题 | 通常配置为只读,不直接修改代码 |
| 性能优化专家 | 识别性能瓶颈并给出优化方案 | 可读取相关代码与运行数据 |
| 测试专家 | 编写测试用例、补全覆盖边界 | 仅操作测试相关文件 |
| 代码合规专家 | 检查代码规范、命名与结构一致性 | 只读或受限修改 |
| 架构设计专家 | 评估方案结构与边界划分 | 侧重分析与建议 |
7.3 并行会话与子代理的区别
两者适用场景不同,不要混用:
- 并行会话 :适合处理互不相关的独立任务,各自独立推进,彼此不共享上下文。
- 子代理 :适合在当前任务内部调用一个专家处理特定环节,例如刚写完认证代码,就让安全审查专家当场 review;适合边开发边审计的协作模式。
7.4 角色定义与权限边界
每个子代理通过角色定义文件声明名称、可用工具、权限模式,甚至可以指定使用的模型规格。只读型专家应配置为不可修改代码,只输出审查意见;需要动手实现的角色再授予对应文件的写入权限。权限最小化可以避免专项代理越权改动无关代码。
7.5 写---审---改迭代循环
最经典的多 Agent 协作模式是实现者与评审者配合,形成迭代闭环:
#mermaid-svg-oLQ4JnQQhln038nV{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-oLQ4JnQQhln038nV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-oLQ4JnQQhln038nV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-oLQ4JnQQhln038nV .error-icon{fill:#552222;}#mermaid-svg-oLQ4JnQQhln038nV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-oLQ4JnQQhln038nV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-oLQ4JnQQhln038nV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-oLQ4JnQQhln038nV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-oLQ4JnQQhln038nV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-oLQ4JnQQhln038nV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-oLQ4JnQQhln038nV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-oLQ4JnQQhln038nV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-oLQ4JnQQhln038nV .marker.cross{stroke:#333333;}#mermaid-svg-oLQ4JnQQhln038nV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-oLQ4JnQQhln038nV p{margin:0;}#mermaid-svg-oLQ4JnQQhln038nV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-oLQ4JnQQhln038nV .cluster-label text{fill:#333;}#mermaid-svg-oLQ4JnQQhln038nV .cluster-label span{color:#333;}#mermaid-svg-oLQ4JnQQhln038nV .cluster-label span p{background-color:transparent;}#mermaid-svg-oLQ4JnQQhln038nV .label text,#mermaid-svg-oLQ4JnQQhln038nV span{fill:#333;color:#333;}#mermaid-svg-oLQ4JnQQhln038nV .node rect,#mermaid-svg-oLQ4JnQQhln038nV .node circle,#mermaid-svg-oLQ4JnQQhln038nV .node ellipse,#mermaid-svg-oLQ4JnQQhln038nV .node polygon,#mermaid-svg-oLQ4JnQQhln038nV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-oLQ4JnQQhln038nV .rough-node .label text,#mermaid-svg-oLQ4JnQQhln038nV .node .label text,#mermaid-svg-oLQ4JnQQhln038nV .image-shape .label,#mermaid-svg-oLQ4JnQQhln038nV .icon-shape .label{text-anchor:middle;}#mermaid-svg-oLQ4JnQQhln038nV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-oLQ4JnQQhln038nV .rough-node .label,#mermaid-svg-oLQ4JnQQhln038nV .node .label,#mermaid-svg-oLQ4JnQQhln038nV .image-shape .label,#mermaid-svg-oLQ4JnQQhln038nV .icon-shape .label{text-align:center;}#mermaid-svg-oLQ4JnQQhln038nV .node.clickable{cursor:pointer;}#mermaid-svg-oLQ4JnQQhln038nV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-oLQ4JnQQhln038nV .arrowheadPath{fill:#333333;}#mermaid-svg-oLQ4JnQQhln038nV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-oLQ4JnQQhln038nV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-oLQ4JnQQhln038nV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oLQ4JnQQhln038nV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-oLQ4JnQQhln038nV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oLQ4JnQQhln038nV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-oLQ4JnQQhln038nV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-oLQ4JnQQhln038nV .cluster text{fill:#333;}#mermaid-svg-oLQ4JnQQhln038nV .cluster span{color:#333;}#mermaid-svg-oLQ4JnQQhln038nV 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-oLQ4JnQQhln038nV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-oLQ4JnQQhln038nV rect.text{fill:none;stroke-width:0;}#mermaid-svg-oLQ4JnQQhln038nV .icon-shape,#mermaid-svg-oLQ4JnQQhln038nV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-oLQ4JnQQhln038nV .icon-shape p,#mermaid-svg-oLQ4JnQQhln038nV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-oLQ4JnQQhln038nV .icon-shape .label rect,#mermaid-svg-oLQ4JnQQhln038nV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-oLQ4JnQQhln038nV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-oLQ4JnQQhln038nV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-oLQ4JnQQhln038nV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Writer Agent
实现功能 · 写代码 · 跑测试
Reviewer Agent
审查输出 · 指出问题 · 提出改进
- 实现者:按需求编写代码并运行测试;
- 评审者:审查实现者的输出,指出问题并给出改进建议;
- 实现者:根据评审反馈修改代码,再次提交审查,循环往复直到通过。
这种分工把「写」与「审」的视角分开,评审者不受实现思路的束缚,更容易发现遗漏问题。当任务规模较大时,也可以让多个 Agent 分工协作,由系统协调各自职责,而不是由人工逐个调度每一步。
第 8 章 从成熟 Agent 运行时结构反推可复用的架构设计
本章解决什么问题:跳出「怎么用工具」的层面,从一款成熟 AI 编程工具的代码结构中,提炼对自建 Agent 项目有参考价值的架构设计原则。本章只讨论通用工程方法,不针对特定厂商、产品或事件做评价。
8.1 阅读立场
研读成熟项目的代码结构,价值不在于复刻它的具体命令或功能,而在于理解它如何把「可运行、可扩展、可裁剪、可远程、可治理、可迁移」这些容易相互冲突的目标收敛到一套统一的运行时设计中。下面按技术选型、分层边界、安全、资源调度、扩展与平台化六个维度归纳。
8.2 技术选型服务于长期目标
成熟运行时的技术选型不是单点技术堆砌,而是围绕「承载复杂编排、便于迁移复用」形成协同:
| 选型方向 | 背后目标 |
|---|---|
| 强类型语言 | 用类型系统承载命令模型、状态模型、工具协议、消息协议等多类结构化协议,保证跨环境迁移时结构一致 |
| 状态驱动的终端视图层 | 把终端界面抽象为状态驱动视图,使同一套运行时兼容终端界面、弹窗、审批面板、任务面板等多种交互形态,解耦界面与业务逻辑 |
| 命令分发与核心调度解耦 | 成熟的命令分发能力作为入口外壳,核心调度逻辑收敛在编排层,降低入口变更对核心运行时的影响 |
| 能力开关与动态导入 | 支持多发行版与实验能力的按需启用 / 禁用,为按需裁剪和轻量化迁移提供基础 |
8.3 清晰的三层迁移边界
传统项目迁移容易出现「模块破碎」,根因往往是边界模糊。成熟运行时通常划分为三层:
#mermaid-svg-ENrqA4xEMpGJ2vfl{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-ENrqA4xEMpGJ2vfl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ENrqA4xEMpGJ2vfl .error-icon{fill:#552222;}#mermaid-svg-ENrqA4xEMpGJ2vfl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ENrqA4xEMpGJ2vfl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .marker.cross{stroke:#333333;}#mermaid-svg-ENrqA4xEMpGJ2vfl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ENrqA4xEMpGJ2vfl p{margin:0;}#mermaid-svg-ENrqA4xEMpGJ2vfl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .cluster-label text{fill:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .cluster-label span{color:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .cluster-label span p{background-color:transparent;}#mermaid-svg-ENrqA4xEMpGJ2vfl .label text,#mermaid-svg-ENrqA4xEMpGJ2vfl span{fill:#333;color:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .node rect,#mermaid-svg-ENrqA4xEMpGJ2vfl .node circle,#mermaid-svg-ENrqA4xEMpGJ2vfl .node ellipse,#mermaid-svg-ENrqA4xEMpGJ2vfl .node polygon,#mermaid-svg-ENrqA4xEMpGJ2vfl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .rough-node .label text,#mermaid-svg-ENrqA4xEMpGJ2vfl .node .label text,#mermaid-svg-ENrqA4xEMpGJ2vfl .image-shape .label,#mermaid-svg-ENrqA4xEMpGJ2vfl .icon-shape .label{text-anchor:middle;}#mermaid-svg-ENrqA4xEMpGJ2vfl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .rough-node .label,#mermaid-svg-ENrqA4xEMpGJ2vfl .node .label,#mermaid-svg-ENrqA4xEMpGJ2vfl .image-shape .label,#mermaid-svg-ENrqA4xEMpGJ2vfl .icon-shape .label{text-align:center;}#mermaid-svg-ENrqA4xEMpGJ2vfl .node.clickable{cursor:pointer;}#mermaid-svg-ENrqA4xEMpGJ2vfl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .arrowheadPath{fill:#333333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ENrqA4xEMpGJ2vfl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ENrqA4xEMpGJ2vfl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ENrqA4xEMpGJ2vfl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ENrqA4xEMpGJ2vfl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .cluster text{fill:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl .cluster span{color:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl 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-ENrqA4xEMpGJ2vfl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ENrqA4xEMpGJ2vfl rect.text{fill:none;stroke-width:0;}#mermaid-svg-ENrqA4xEMpGJ2vfl .icon-shape,#mermaid-svg-ENrqA4xEMpGJ2vfl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ENrqA4xEMpGJ2vfl .icon-shape p,#mermaid-svg-ENrqA4xEMpGJ2vfl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ENrqA4xEMpGJ2vfl .icon-shape .label rect,#mermaid-svg-ENrqA4xEMpGJ2vfl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ENrqA4xEMpGJ2vfl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ENrqA4xEMpGJ2vfl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ENrqA4xEMpGJ2vfl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 入口壳层
轻量化 · 快速路径 · 延迟加载 · 低耦合
总装配编排层
初始化顺序 · 命令注册 · 模式分流 · 权限配置 · 扩展装配
能力层
命令 · 工具 · 服务 · 状态 · 远程 · 插件等具体功能实现
- 入口壳层:承担快速路径处理、特殊命令直达、核心能力延迟加载,对外交互入口与核心逻辑低耦合;
- 总装配编排层:负责初始化顺序管控、命令注册、模式分流、权限配置、远程会话管理以及扩展能力装配,是运行时的调度中枢;
- 能力层:承接编排层调度,落地具体业务功能。
这种分层支持非整体迁移:需要移植到自有产品时,可以保留运行时编排逻辑、权限边界模型与扩展协议,只替换模型服务、工具实现与界面层。
8.4 安全边界内置到运行时
与把安全校验当作外围附加模块不同,成熟运行时把信任模型、权限模式、交互 / 非交互模式作为初始化和能力启用的前置条件:文件系统、代码语言服务、插件、外部连接器、远程会话等核心能力,在启用之前都要先经过安全边界校验,而不是无条件执行。
这种设计的价值是:核心系统在迁移到企业内网、受控工作站、自动化执行环境时,安全边界模型可以直接复用,保证「能力可管控」的规则不随迁移丢失。
8.5 资源调度成为基础设施
成熟 AI 工程并不只关注提示词优化,而是把大模型应用的核心瓶颈转化为基础设施能力:
| 调度方向 | 做法 | 解决的问题 |
|---|---|---|
| 上下文生命周期管理 | 压缩、微观压缩、内容裁剪等全周期机制 | 会话上下文持续膨胀 |
| 推理成本保护 | 提示缓存保护作为运行时设计约束 | 降低重复推理资源消耗 |
| 流式工具执行 | 工具调用流水线化调度 | 提升外部工具调用效率与稳定性 |
| 推理资源调度 | 降级模型、思考模式、额度预算等策略 | 精细化管控模型资源消耗 |
这些设计把「模型调用」从单次 API 请求,升级为可治理的推理系统。
8.6 扩展能力作为一等公民
成熟运行时不依赖静态内建能力封闭运行,而是通过标准化、长期稳定的扩展接口把能力生产开放给外部生态。核心运行时与生态扩展可以分期解耦:迁移时不需要一次性移植全部插件、技能与连接器,只要核心编排层和扩展协议保持稳定,生态能力可以逐步补齐。
8.7 平台化的统一特征
当系统从工具形态演进为平台形态,通常会形成若干统一机制:
| 统一机制 | 含义 |
|---|---|
| 统一运行时状态管理 | 全局状态来源与变更方式一致 |
| 统一会话模型 | 会话生命周期、历史与上下文结构统一 |
| 统一扩展入口 | 扩展能力通过同一套接口接入 |
| 统一权限与信任模型 | 不同能力遵循同一套授权规则 |
| 统一本地 / 远程模式切换 | 同一套逻辑支持本地与远程执行形态 |
| 统一上下文与模型调用策略 | 上下文管理与模型选择规则集中管控 |
| 统一配置演进机制 | 配置随版本升级有一致的迁移方式 |
8.8 架构代价与后续演进
分层与装配设计并非没有代价:总装配编排层随着功能增加,容易膨胀为职责过重的超大文件。系统进入平台治理阶段后,新功能开发不再是主要难点,真正的挑战是从历史兼容逻辑与产品分支中提纯平台内核,实现装配层的解耦与轻量化。这反映了架构从「功能迭代」走向「平台治理」的必然过程。
8.9 对自建 Agent 项目的启示
结合前面几章的方法,自建 Agent 项目可以优先关注:先划清入口、编排与能力三层边界;把权限校验前置为运行时默认约束;把上下文、成本与工具执行当作基础设施设计;尽早定义稳定的扩展协议;用统一约定替代分散的局部实现。
结语:可迁移到任何仓库的五条认知
回到全文主线,无论使用哪款 AI 编程工具、面向哪种技术栈,以下五条认知最值得沉淀下来:
- 用「边界」而不是「代码量」理解系统:系统是否健康,取决于职责边界是否清晰,而不是代码写了多少。
- 用「源定义」而不是「生成结果」定位修改点:优先维护源头,追溯生成文件的来源,不直接改动生成物。
- 用「分层职责」而不是「哪里方便就写哪里」组织实现:按固定分层组织代码,而不是顺着当下的便利随意摆放逻辑。
- 用「状态机」而不是「CRUD 幻觉」理解真实业务:抓住状态、流转、失败与补偿,而不是把一切简化为增删改查。
- 用「统一约定」而不是「局部聪明」换取长期可维护性:一致性约定比单点的灵活技巧更能支撑长期协作。
本文开头的开发闭环在实践中持续运转:
#mermaid-svg-K3ciT1DFUvLb5WnI{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-K3ciT1DFUvLb5WnI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-K3ciT1DFUvLb5WnI .error-icon{fill:#552222;}#mermaid-svg-K3ciT1DFUvLb5WnI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-K3ciT1DFUvLb5WnI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-K3ciT1DFUvLb5WnI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-K3ciT1DFUvLb5WnI .marker.cross{stroke:#333333;}#mermaid-svg-K3ciT1DFUvLb5WnI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-K3ciT1DFUvLb5WnI p{margin:0;}#mermaid-svg-K3ciT1DFUvLb5WnI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI .cluster-label text{fill:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI .cluster-label span{color:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI .cluster-label span p{background-color:transparent;}#mermaid-svg-K3ciT1DFUvLb5WnI .label text,#mermaid-svg-K3ciT1DFUvLb5WnI span{fill:#333;color:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI .node rect,#mermaid-svg-K3ciT1DFUvLb5WnI .node circle,#mermaid-svg-K3ciT1DFUvLb5WnI .node ellipse,#mermaid-svg-K3ciT1DFUvLb5WnI .node polygon,#mermaid-svg-K3ciT1DFUvLb5WnI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-K3ciT1DFUvLb5WnI .rough-node .label text,#mermaid-svg-K3ciT1DFUvLb5WnI .node .label text,#mermaid-svg-K3ciT1DFUvLb5WnI .image-shape .label,#mermaid-svg-K3ciT1DFUvLb5WnI .icon-shape .label{text-anchor:middle;}#mermaid-svg-K3ciT1DFUvLb5WnI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-K3ciT1DFUvLb5WnI .rough-node .label,#mermaid-svg-K3ciT1DFUvLb5WnI .node .label,#mermaid-svg-K3ciT1DFUvLb5WnI .image-shape .label,#mermaid-svg-K3ciT1DFUvLb5WnI .icon-shape .label{text-align:center;}#mermaid-svg-K3ciT1DFUvLb5WnI .node.clickable{cursor:pointer;}#mermaid-svg-K3ciT1DFUvLb5WnI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-K3ciT1DFUvLb5WnI .arrowheadPath{fill:#333333;}#mermaid-svg-K3ciT1DFUvLb5WnI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-K3ciT1DFUvLb5WnI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-K3ciT1DFUvLb5WnI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-K3ciT1DFUvLb5WnI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-K3ciT1DFUvLb5WnI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-K3ciT1DFUvLb5WnI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-K3ciT1DFUvLb5WnI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-K3ciT1DFUvLb5WnI .cluster text{fill:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI .cluster span{color:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI 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-K3ciT1DFUvLb5WnI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-K3ciT1DFUvLb5WnI rect.text{fill:none;stroke-width:0;}#mermaid-svg-K3ciT1DFUvLb5WnI .icon-shape,#mermaid-svg-K3ciT1DFUvLb5WnI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-K3ciT1DFUvLb5WnI .icon-shape p,#mermaid-svg-K3ciT1DFUvLb5WnI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-K3ciT1DFUvLb5WnI .icon-shape .label rect,#mermaid-svg-K3ciT1DFUvLb5WnI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-K3ciT1DFUvLb5WnI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-K3ciT1DFUvLb5WnI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-K3ciT1DFUvLb5WnI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 经验回流为新的规范
规范前置
计划冻结
上下文自控
架构护栏
扩展协作
架构认知
AI 负责速度与标准件生成,人负责判断、边界、契约与一致性。把规范前置、任务切小、上下文握在手里、分层与状态机守住底线,AI Coding 才能从「偶尔写得快」变成「长期稳定交付」。
如果这篇文章对你有帮助,欢迎收藏备用;实践中遇到新的坑点,也可以按第 1 章的方式持续沉淀回自己的项目规则文件。