我理解的 AI 软件工程不是让 AI 写代码而是让系统变成 AI 能工作的环境从一条 Spec 讲起把需求分析、架构设计、Coding、测试、发布重新串一遍 ——附一条真实需求的完整走查范例一、从一个特别典型的翻车现场说起「业扩预受理增加一个校验」——AI 很快就写出了代码能编译测试也能跑架构师一看改错地方了。这个场景我太熟悉了。我们在推进 AI 研发工具链的过程中被问得最多的一句话就是模型都能写代码了为什么还要折腾这么多规范和流程我的答案是不是模型不够强是我们没给它一个能工作的环境。给 AI 一个全新项目它往往表现不错——没有历史包袱技术栈公开架构简单规模可控。但把它扔进一个跑了十几年的存量系统里它不知道这个页面是不是业务入口不知道这个接口属于哪个服务、能不能跨中心调用不知道这个字段来自哪张表更不知道这条规则是全国通用还是只适用于某个省。所以我习惯把 AI 软件工程拆成三层来看缺任何一层AI 都只会「表现得像会写代码」而不是「像一个懂系统的人」层次回答的问题对应手段规范 SpecAI 要做什么、做到什么程度SDD需求 → 规范 → 方案 → 任务 → 实现 → 验证上下文 ContextAI 工作时应该知道什么业务规则、架构边界、数据模型、私有技术栈、存量代码环境 HarnessAI 能不能可靠地工作技能、工具、护栏、评测、反馈回路很多人把精力全砸在第一层把 Prompt 写得更长更细却忽略了后两层——这恰恰是企业 AI Coding 的分水岭。下面这条需求我会在后面的每一层里都拿它当例子你可以一路看它是怎么被走完的。贯穿全文的范例需求 M-2026-0930业务方原话就是这么一句话交给我们的「低压居民新装预受理的时候如果这个客户名下已经有一块在用的低压表就不让他再受理了提示他已有用电户号。」看起来是一句话实际上是三个坑什么叫「在用」提示几条拦在哪一层二、把工具链摊开看五个阶段人和 AI 各干什么我一直反对把 AI 软件工程讲成「一个更聪明的编程助手」。它真正的样子是把研发流程重新切一遍并且明确每一段里人和 AI 的分工阶段工具链动作人决策与把关AI生成与执行① 需求分析/constitution/clarify定目标与动机What / Why、澄清歧义、确认边界结合输入提问、起草规范初稿② 架构设计/specify/plan评审方案、拍板取舍、确认 Spec 与验收口径融合知识与规则生成 Spec、出技术方案、拆任务③ Coding/tasks/implement定接口与规范约束、Code Review 把关按规范生成代码、同步产出测试与文档④ 测试/analyze/test定验收标准与质量门禁、判断是否可发布自动跑回归与验证、比对规范一致性⑤ 发布/implement· 上线决策上线与灰度范围、异常时决定回滚执行部署与监控、回流数据、报告偏差这张表里有一条分界线我认为是整套方法能跑通的关键人负责「做什么、做到什么程度」AI 负责「怎么生成、怎么执行」。决策权和事实裁决权在人手上生成和执行的工作量交给 AI。这一条守住了团队就不会陷入「AI 写了一大堆、没人敢负责」的窘境守不住就会出现最危险的一句话——「AI 检查全部通过」。Checklist 全绿不等于事实正确我见过 AI 自检全过、人工抽查时序图和接口字段后仍然发现语义丢失的案例。这一条需求落在五个阶段里各自要交付什么后面第三节会展开阶段交付物谁签字① 需求分析一句话需求 → 澄清清单 边界定义业务方 需求负责人② 架构设计Spec 段落 影响范围 改动文件清单架构师③ Coding代码改动 单元测试 API 契约变更开发 Code Reviewer④ 测试用例集 四层验证结论测试 质量门禁⑤ 发布灰度策略 监控指标 回流知识条目研发负责人三、范例走查这条需求是怎么一步步被走完的这一节是全篇最想让你看的部分。同一条需求分别在五个阶段留下了什么样的真实产物——你会发现「AI 软件工程」不是概念而是一串可以照着抄的文件。阶段 ① 需求分析把一句话拆成可验证的规则先落项目宪法/constitution它是这个项目所有需求的共同约束写一次、长期生效# .ai-sdd/constitution.md节选 ## 架构约束 - C1 业务校验必须落在服务层禁止只做前端校验。 - C2 跨域数据必须通过对方域提供的接口获取禁止直连对方库表。 - C3 对外错误码统一 MKT-XXXX新增错误码需在错误码表登记。 ## 流程约束 - C4 未通过 /clarify 澄清歧义的需求不得进入编码。 - C5 每个需求必须附带验收口径与回滚方案。然后是/clarify——AI 提问人来裁决这是全流程里我认为最值钱的一段对话AI需求里的在用包含哪些状态系统里计量点状态有待装 / 在用 / 暂停 / 已销户 / 已拆表。 人算在用和暂停不含待装和已销户。 AI同一证件号码下有多块在用表时提示几条 人最多列 3 条多余的提示等共 N 户不能撑爆页面。 AI拦截位置是提交受理还是校验按钮 人点校验就拦不要等到提交才发现。 AI老用户走增容的场景要不要一起拦 人只拦新装业务类型 低压居民新装增容放行——这正是我们要引导他去办的。 AI这条规则全国通用还是分省 人全国通用。分省的重复户规则另有一条本需求不涉及。五轮问答下来一句话需求变成了 5 条可验证的判定条件。这五条不是我拍的是人确认过的——注意最后两个问题的价值如果没有 ContextAI 根本不知道有「增容」这个兄弟流程也不知道规则有分省口径。阶段 ② 架构设计Spec 定下来再谈怎么做/specify把澄清结果固化成 Spec/plan结合 Context 出技术方案。产物大概是这样# Spec: 低压居民新装预受理-重复用电户校验M-2026-0930 ## 业务规则 R1 业务类型 低压居民新装 时才执行本校验。 R2 取证件号码名下计量点状态 ∈ {在用, 暂停} 视为已有用电户。 R3 命中则拦截返回 MKT-3021携带已有用电户号最多 3 条 总数。 R4 触发时机受理页点击校验。 R5 全国通用不区分省份。 ## 验收口径 A1 命中 1 户提示含该户号受理不可继续。 A2 命中 3 户提示前 3 个 等共 N 户。 A3 证件号名下仅有已销户记录放行。 A4 业务类型 增容不触发本校验。 A5 客户域接口超时放行并记录告警不阻断受理。# Plan: M-2026-0930 ## 影响范围 - acceptance-service AddrAcceptServiceImpl校验入口 - acceptance-web 受理页校验按钮错误码映射 - 配置 rule_config RULE_LOWVOLT_DUP_CHECK开关 上限条数 ## 复用而非新写 - 客户域已有接口 queryMeterPointsByCertNo(certNo, statusSet) v2 已支持状态集合入参 → 直接复用不要新开接口避免 C2 违规。 ## 风险 - 存量受理高峰期该接口 QPS 上升需确认客户域限流阈值 - 状态集合口径若与计费侧不一致可能出现同户不同判 → 需与计费确认。 ## 任务拆分 T1 配置项与错误码登记 T2 服务层校验实现 T3 前端提示 T4 单测与用例这里最典型的一幕是「复用而非新写」AI 没有去写一条新的查询 SQL而是先在 Context 里找到客户域已有的 v2 接口。这就是有 Context 和没 Context 的差别——没有它AI 八成就直连库表了代码能跑但违反了 C2。阶段 ③ Coding照规范生成不是凭空发挥/implement产出的改动大致长这样示意--- a/acceptance-service/src/main/java/.../AddrAcceptServiceImpl.java b/acceptance-service/src/main/java/.../AddrAcceptServiceImpl.java // R1 仅低压居民新装触发A4 增容放行 if (!BizType.LOW_VOLT_RESIDENT_NEW.equals(req.getBizType())) { return PreCheckResult.pass(); } // R2 复用客户域接口禁止直连C1/C2 ListMeterPoint points customerClient.queryMeterPointsByCertNo( req.getCertNo(), MeterStatus.IN_USE, MeterStatus.SUSPEND); if (points.isEmpty()) { return PreCheckResult.pass(); // A3 } // R3 最多展示 3 条 总数 return PreCheckResult.reject( ErrorCode.MKT_3021, metersPreview(points, 3));同步产出错误码MKT-3021登记、RULE_LOWVOLT_DUP_CHECK配置项、单测 4 条对应 A1–A4。注意第 ③ 阶段 AI 的产出里已经带了测试这是它和人最大的差别——写代码和写测试一步完成但「测试是否覆盖了该覆盖的」仍然由人判。阶段 ④ 测试四层验证最后一层最容易漏/analyze/test跑完验收口径 A1–A5 全绿。但我们的门禁要求多问四句验证层问题本例结论能不能编译/跑起来构建与单测通过需求是否实现A1–A5 逐条比对 Spec R1–R5通过有没有违反系统边界是否直连库表、是否跨域、错误码是否登记通过复用 v2 接口Context 与实际是否一致客户域接口签名、状态枚举是否变了发现偏差v2 接口新增了待装状态Context 事实卡未更新第四层就是我们踩过的坑功能全过但 Context 已经悄悄过期。如果这次不修下一次 AI 拿着旧事实卡做需求就会再错一次。阶段 ⑤ 发布灰度、监控、然后回流灰度先放开 5% 受理量观察 24 小时关注命中率与客户域超时率监控MKT-3021触发次数、客户域接口 P99、放行告警A5 分支计数回滚RULE_LOWVOLT_DUP_CHECK一键关闭无需回滚代码——把开关做进配置是这类校验需求的标配回流Harvest本次确认了两条可复用的知识 → ①「跨域查询客户计量点一律走 queryMeterPointsByCertNo」②「状态口径需与计费侧对齐含待装状态」。它们被写回 Context供下一个需求使用。一条需求走完系统里多了三样东西一段受规范约束的代码、一份被校正的 Context、两条能复用的知识。这才是我说的「知识跟着真实需求生长」。四、Spec 是唯一事实来源但它需要三类输入我们那套流程里最重要的一句话是规范Spec是唯一事实来源。需求、设计、代码、测试、文档全部对着它对齐而不是各说各话。但 Spec 不会凭空长出来。它需要三类输入缺一类就会写偏用户的 Prompt——意图、边界、验收期望。这是人给的方向决定「做什么」。本体 / 行业知识——领域模型、术语体系、合规要求。它决定了 AI 用的词和业务对得上不会把「更名过户」和「换表增容」当成同一类流程。内部知识库 Wiki——业务规则与系统现状。哪条规则是全国通用、哪条只在某个省生效这个接口属于哪个域、允不允许跨中心调用。同一个需求只给 Prompt 和给三类输入差别有多大拿上面那条需求做个对照只给 Prompt做法 A三类输入齐全做法 B输入「低压新装预受理加个校验客户已有在用表就不让受理」同一句话 项目宪法 领域术语表 受理/客户域 ContextAI 理解「在用表」 任意状态未删除的计量点「在用」 在用 暂停排除待装/已销户R2改动位置前端预校验看起来最快服务层校验符合 C1数据来源自行拼 SQL 查计量点表复用客户域 v2 接口符合 C2遗漏增容被误拦超时直接报错阻断受理增容放行A4超时放行告警A5返工架构评审打回重做一次通过评审差别不在于 AI 聪明不聪明而在于它有没有可能知道这些事。这里必须说清楚一个误区把文档堆给 AI ≠ 给了 AI 知识。很多团队一上手就是建目录、疯狂写 Markdown业务规则一份、架构一份、接口一份、数据库一份攒出几百份文档说「你都看看」。这只是把企业 Wiki 搬到了 AI 面前。真正的做法是让正确的信息在正确的时间、以正确的粒度进入模型——给 Agent 一张地图而不是一本一千页的说明书。五、Context 怎么组织决定这套东西是资产还是负担我把企业 Context 拆成五层指令什么不能做、工具能做什么、技能开发 SOP、项目知识业务规则、架构、数据模型、API 契约、代码模式、私有技术栈、运行时当前需求、对话历史、已验证的证据。其中第四层「项目知识」是绝大多数企业最缺的一层也是最值得投入的一层。它适合按三档来组织地图 → 目录 → 事实。地图context-index.yaml# .ai-sdd/context/context-index.yaml节选 version: 1 modules: acceptance: # 业扩受理域 catalog: business/acceptance/README.md facts: - id: rule-dup-meter-point file: business/acceptance/rules/rule-dup-meter-point.md level: A # 证据等级 state: current # 当前状态 or 目标状态 load_when: [预受理, 计量点校验, 重复户] - id: arch-call-boundary file: system/arch/call-boundary.md level: A state: current load_when: [跨域调用, 新增对外接口] customer: facts: - id: api-query-meter-points-v2 file: system/api/customer/query-meter-points-v2.md level: A load_when: [按证件号查计量点, 客户域]地图本身不解释知识它只说三件事有哪些知识、在哪、什么时候该加载。AI 拿到「预受理加校验」这个需求命中load_when自然只加载受理域和客户域这两小块而不是把整个系统吃进去。事实一条业务规则长什么样# .ai-sdd/context/business/acceptance/rules/rule-dup-meter-point.md id: rule-dup-meter-point title: 低压居民新装预受理——重复用电户校验 level: A state: current rule: | 业务类型 低压居民新装时按证件号码查询计量点 状态 ∈ {在用, 暂停} 视为已有用电户命中则拦截返回 MKT-3021 携带已有用电户号最多 3 条 总数不含待装、已销户。 全国通用不区分省份。 evidence: - 源码: AddrAcceptServiceImpl.java:214原有复用逻辑 - 配置: rule_config.RULE_LOWVOLT_DUP_CHECK - 接口: customer/queryMeterPointsByCertNo v2 reuse: 增容、更名过户等流程可引用本规则的状态口径 last_verified: 2026-09-30 verified_by: 张XX架构师注意这几个字段——它们才是让 Context 可信的东西level证据等级、state当前还是目标、evidence凭什么这么说、verified_by谁签的字。没有这几项一条知识就只是「有人这么写过」。证据分级同一条知识写法天差地别等级来源可以怎么用对应写法示例A源码、配置、接口实测事实基线可直接作为规则「接口 v2 支持状态集合入参源码 sign 确认」B注释、目录结构、文件名需交叉验证后才可用「包名暗示属于受理域待确认」C / D命名推断、泛化规律只能当假设禁止写入事实层「猜测暂停状态也应拦截未验证」X密钥、账号、生产地址绝对禁入—AI 很容易把「我猜这个接口应该是这样」写成「系统就是这样」这两者根本不是一回事。状态边界Current 与 Target 不能混回到我们的例子。这次需求本身没有改变「在用」的定义所以事实卡是state: current。但假设这次需求就是要重新定义「在用」比如把暂停也算作可用那么正确的做法是context/business/acceptance/rules/rule-dup-meter-point.md # state: current现状 context/changes/2026-0930-dup-check/rules/rule-dup-meter-point.md # state: target本次目标文档写电费计算是同步调用、代码里其实是异步不能简单地把文档删掉说「代码才是真理」——因为这次需求本身可能就是要从同步改成异步。两套状态分开放AI 才不会把「目标方案」误当成「现状」。还有一个容易忽视的细节别为了「好读」把 Context 压缩坏了。很多人嫌文档长压一压结果压掉的往往是分支条件、接口字段、异步关系、异常路径这些最要命的地方。Context 工程追求的是最小必要 Context而不是最短 Context——提炼不等于精简。六、闭环的关键AI 提出人确认然后回写知识不会因为「整理过一次」就永久可用。我的做法是让它跟着真实需求生长四个动作循环。每个动作都产生一份看得见的输出① Discover找缺口——需求来了先别写代码让 AI 说清「我还缺什么」需求 M-2026-0930 的知识缺口清单 [已有] 受理流程主链路、业务类型枚举来自 business/acceptance/README.md [缺失] ① 计量点状态枚举的完整取值与业务含义 ② 按证件号查计量点的合法接口是否已有 v2 ③ 该规则是否分省是否有省份差异配置 [待确认] ④ 与计费侧在用口径是否一致可能影响判定结果过去是人告诉 AI 该看什么现在是 AI 自己说清它缺什么——这张清单直接交给了架构师十分钟就回填完毕。② Update补知识——AI 提出、人确认、再入库产出一份变更报告Context 变更报告 #C-2026-0930-02 新增: system/api/customer/query-meter-points-v2.md level A已验证 修订: business/acceptance/rules/rule-dup-meter-point.md 补充待装状态说明 索引: context-index.yaml 新增 2 条映射 确认人: 张XX 依据: 客户域负责人确认 源码 sign不是 AI 说什么就写什么而是走一遍「AI 提出 → 人确认 → 制定合并方案 → 写入 → 同步索引 → 变更报告」。因为错误的 Context 比没有 Context 更危险。③ Harvest做回流——PR 合并后问一句「这次有没有发现新知识」本次开发发现的新知识2 条 - 跨域查询客户计量点一律走 queryMeterPointsByCertNo v2禁止直连库表 - 计量点状态口径需与计费侧对齐当前含待装 建议提升为通用 Context是涉及所有受理类需求的跨域查询④ Review定期体检——每周只读体检只给建议、不改知识库Context 体检报告 2026-W40 - 时效性: 3 条事实卡 last_verified 超 90 天建议复核 - 冲突: 计费域与受理域对暂停的描述不一致1 处 - 冗余: 2 处重复的调用链说明建议合并 - 分离性: 通过通用知识与 change 临时知识未混放这跟代码治理的思路是一样的。 对应到图里这条回流线我特意标成「**人确认后回写**」。规范的生命周期里变更决策权始终在人这边——AI 可以高效地扫描代码、分析调用链、执行修改、跑测试、出报告但它不适合独立判断业务事实是什么、两套架构描述哪个对、一条规则是不是全局规则、一个高风险改动能不能上线。 ## 七、反过来看六个不要做 1. **不要把模型当外包**只丢一个 Prompt不给系统知识然后抱怨它改错地方。 2. **不要成立专项组一次性整理完系统**抽代码、写文档、画架构图几个月后交出一套厚厚的「AI 知识库」真正写代码时 AI 还是找不到代码。脱离真实需求整理出来的知识抽象层次不一致、容易过期还会把单次需求误认成通用规则。 3. **不要把 Prompt 写成小说**从一句话堆成几十页开发规范问题通常不在「说得不够多」而在「该知道的它不知道」。 4. **不要为了好读压坏 Context**如上。 5. **不要把「AI 检查全部通过」当质量结论**AI 扩大检查覆盖面人做最终裁决。 6. **不要把人从关键节点上撤掉**需求和验收标准、方案取舍、上线与回滚这三个节点的签字权必须在人手上。 ## 八、想开始就按这五步走 这套东西不需要一上来就建「企业级 AI 知识中台」也不用先成立十几人的专项组。照着下面这张**第一周清单**抄一遍就能起步 markdown # 试点启动清单第一周 [ ] 选定 1 个真实需求业务真实、马上要开发、验收标准明确、有中等复杂度 → 范例低压居民新装预受理-重复用电户校验 [ ] 写 1 份项目宪法constitution.md3–5 条架构约束 2 条流程约束 → 范例C1 校验必须落服务层、C2 禁止直连他人库表、C3 错误码登记 [ ] 建 1 张地图context-index.yaml 2 个域目录受理域、客户域 [ ] 填 5 条事实1 条业务规则 1 张架构图 1 条调用链 1 个 API 1 个代码模式 [ ] 走完一次 DiscoverAI 缺口清单→ 人确认 → 补 Context [ ] 走完五阶段产出Spec、代码、用例、四层验证结论、灰度与回滚方案 [ ] 做一次 Harvest把本次知识回流成通用 Context目标 ≥ 2 条对应到方法上就是这五步挑一个真实需求当起点业务真实、马上要开发、有明确验收标准、有一定复杂度。先做 Context Discover再补 Context让 AI 说清涉及哪些业务规则、哪些系统、哪些服务、要确认哪些 API、当前知识库缺什么。第一版不用多一条业务规则、一张架构图、一条调用链、一个 API 说明、一个代码模式够用就行。先出设计确认后再 Coding需求理解、影响范围、方案、要改的文件、调用关系、数据变化、风险、测试方案确认完再写代码。这时 AI 手上的上下文已经不是「你是一名高级程序员」而是「这是我们的系统、这是当前需求、这是正确的调用链、这是不能越过的架构边界、这是应该改的代码位置」。验证要过四层能不能编译、需求是否实现、有没有违反系统边界、Context 里的知识和实际代码是否还一致。最后一层最容易被忽略但它决定了下一次 AI 还能不能继续相信这些 Context。Harvest 新知识回流成通用 Context能被后续需求复用的就从一次性的改动结论提升为通用知识。回头看我们那张工具链图里其实只讲清楚了四件事把规则写清楚、从规范自动生成、渐进式改造、知识沉淀。对应的收益也很朴素——项目延期少一点、返工少一点、文档准确率高一点、风险可控、知识不随人员流失。九、最后变的是工程师的活过去两年我们习惯比较哪个模型写代码更强、哪个 Agent 跑分更高、哪个工具更快。这些都重要但进入企业之后还有一个变量经常被忽略你的系统到底是不是一个 AI 可以理解和工作的环境。如果架构知识都在某个架构师脑子里业务规则散落在微信群里接口说明堆在各种文档里代码没有清晰边界测试跑不起来历史决策无处追溯——那么就算换上最强的模型AI 也很难稳定工作。反过来如果业务知识、系统架构、数据模型、代码模式、工具、技能、规则、测试和历史决策能逐渐变成 AI 可以发现、读取、调用和验证的工程资产那么模型每提升一次能力整个团队都会一起受益。所以我的结论是AI 软件工程不是让 AI 替你写代码而是把「懂业务和架构的人 一套 AI 能理解的工程环境 一组 Agent 一套验证和治理机制」组装起来。设计环境、明确意图、建立反馈回路——这三件事做好AI 才真正成为系统里的工程师。