第 1 章 AI 会写代码,为什么项目还是失控?

发布时间:2026/10/14 1:15:39

第 1 章 AI 会写代码,为什么项目还是失控? 把一段需求丢给 AI Coding Agent几十秒后一个能跑的服务就出现在目录里。依赖装好了路由分好了连 README 都写得有模有样。过去要搭一天的脚手架现在是一杯咖啡的事。写代码这件事的门槛从来没有这么低过。但只要项目活过第一个下午味道就开始不对了今天加的字段和上周的决定打架AI 信誓旦旦地说按之前的约定来可那个约定从来没有被写下来过。每一次演示都很顺真有人用起来却处处不对。这一章先不急着上工具我们先把为什么会失控这件事拆开看清楚。看完你会发现这基本不是模型笨的问题。一、一次性 Prompt 的局限事情通常是这样开始的一个普通的工作日下午你想做个短链接服务在对话框里敲了一句话。帮我写一个短链接服务用户提交一个长 URL返回一个短链接 访问短链接能跳转到原来的地址。AI 的反应快得让人愉快它自己选了 FastAPI 和 SQLite生成了数据模型、路由和一个简单的提交页面末尾还附了启动命令。你照着跑起来先用 curl 提交一个长 URL拿到一串六个字符的短链再请求这个短链看到 302 状态码和指向原地址的 Location 头。它真的能用那一刻你几乎相信剩下的工作只是把需求一句句告诉它。但这句话从诞生起就有一个身份问题它是一次性的生成指令不是工程契约。Prompt 活在对话框里对话会关闭上下文会被截断新开一个会话它就不存在了。代码留在仓库里需求留在聊天记录里两者从第一天起就分处两个地方。以后任何一次它到底应该怎么表现的追问都得靠人翻记录或者重新解释一遍。你可能会想那把 Prompt 写好一点不就行了。角色设定、给几个示例、让它一步步想这些 Prompt Engineering 的技巧确实有用但它们优化的都是同一件事单次生成的质量。技巧随会话生灭没有留下任何持久的东西而一个项目真正的难点不在第一次生成在第二十次修改的时候新的决定还认不认第一周定下的规矩。技巧回答不了这个问题因为它没有提供一个可以持久引用、可以审查、可以回归的落点。再深一层看第一天的成功其实只发生在一条极窄的路径上。你脑子里有一个短链接服务该有的样子AI 脑子里有一个从训练数据和这句话里拼出来的样子。两个版本在提交 URL 再跳转这一条路径上重合了于是看起来完全一致但是至于这条路径之外的世界是什么样没有任何中间产物把两者的差异放到台面上。第一天的成功让人放心地继续往里加东西后来你会发现偏差恰恰不是在失败时产生的它是在一连串成功里悄悄累积起来的。二、上下文漂移、隐性假设与需求偏差第二天你让它加访问统计周末又加了过期时间和删除接口。每一次单独看都完成得很漂亮人们习惯把后面的麻烦笼统地说成AI 不懂我但拆开看这里面其实是三种根因完全不同的机制。第一种是上下文漂移。长对话是有寿命的早期说过的约束会在不断增长的上下文里被稀释或者被后来的新决定悄悄覆盖。最初选 SQLite 的时候AI 提过一句先做单机版做统计功能时可以换存储。到第三天讨论统计功能这句话早已不在有效上下文里它顺手把统计表设计成依赖 SQLite 自增主键和本地文件的样子。再过一周你问要不要上 Redis 计数它给出的方案和第一天的表结构直接矛盾。而这两个互相打架的决定看起来都经过了 AI 的同意因为没有任何地方记录过当初的约定到底是什么。第二种是隐性假设它更隐蔽。凡是 Prompt 没说的AI 都会自己补一个默认答案而且不会主动声明。你让它支持过期对话是这样的。我 短链接要支持过期。 AI 已加 expires_at 字段过期后链接仍可访问只是管理页标记为已过期。过期之后到底还能不能跳转这是一个产品决定它一句话就替你做了。回头清点一下同类的决定到处都是。slug 长度定成六位字符集按大小写不敏感处理同一个长 URL 重复提交每次都生成新链删除接口不做鉴权。每一个单看都合理合在一起构成了一个从来没有人审批过的产品。更麻烦的是不同会话里的默认值还会互相不一致这次按六位算下次的新功能里悄悄按八位算。第三种是需求偏差这一次问题出在人的一侧。它指的是你以为自己说清楚了和对方实际理解到的两者之间的差。“访问统计在你心里默认是真实用户的浏览量在 AI 那里就是每来一个请求加一”。于是爬虫、监控探活、你自己的 curl 测试全部计入了统计数字。这不是 AI 答错了是问题本身从来没有被精确定义过而代码用一种确定的方式把模糊处永久锁死了。这三种偏差在传统开发里也存在但过去有一道天然的拦阻。工程师在把需求翻译成代码的路上会拦下大量这类问题因为他要为这段逻辑负责。他会抬头问一句过期了还能跳吗统计要不要过滤爬虫。现在翻译动作由 AI 瞬间完成功能直接以可运行代码的形态交付生成速度远快于人的 review 速度那道阻拦环节整个消失了偏差第一次拥有了和成品一样的交付速度。三、“代码能运行为什么不等于需求已实现”第二周服务准备给同事用了直到这一刻每一次演示都是成功的因为演示走的永远是同一条 happy path提交、跳转、看着数字往上涨。但能跑这件事的迷惑性也就在这里。可运行只证明了一件极小的事在这组输入、这个环境、这次执行里没有报错。并发下会怎样边界输入会怎样数据累积一个月之后又是什么样它一样都没有回答。短链的 slug 是随机生成的六位字符代码里没有任何唯一约束兜底。当两个请求恰好生成同一个 slug后一条记录会指向不同的地址线上就是一次随机跳错。这种事在演示里永远不会发生所以它一直像不存在一样。就算每条 happy path 都不报错问题也没有结束Agent 天然朝最顺的路径收敛。让它实现功能它的最优解是让主流程跑通而不是主动把异常处理、权限控制、数据生命周期补齐因为那些东西在 Prompt 里根本不存在写了反而可能引入它自己无法验证的复杂度。于是删除接口没有鉴权谁都能删。删了映射行统计表里的数据还留着。expires_at 字段加了跳转逻辑却压根不检查它。这些不是通常意义上的 bug而是没人要求所以没做。但从需求角度看它们让功能处在一种危险的半成品状态界面上的完成度看起来有九成实际可上线度是零。比这些都关键的是完成由谁定义。当一个项目没有可执行的验收标准时这个词就由生成方自己解释了。人怎么判断做完了跑一下点一下看一眼。可肉眼能验证的只是我此刻走到的那条路径人却会不自觉地把它当成全部路径。补单元测试也不能自动解决这个问题因为测试只能断言人想得到、并且亲手写下来的东西。“过期链接不该跳转”、PV 要过滤爬虫如果从来没有作为验收条件存在过任何测试框架都不会替你发明它们。测试在这里验证的是代码不是需求。于是偏差开始复利累积每一层没被发现的偏差都会成为下一轮生成的上下文AI 会忠实地在错误的地基上继续盖楼。它会基于那份掺着爬虫流量的统计数字再给你做一个热门链接 Top 10。项目不是在某一刻突然坏掉的它是在一连串绿灯里慢慢变成一个谁也说不清正确行为到底是什么的系统。等你终于想修第一个要回答的问题已经不是怎么改代码而是这东西到底应该怎么表现。而这个问题本来应该在第一天下午就回答。四、AI 编程需要怎样的工程约束回头看这个短链接服务没有一处是因为模型不够聪明。它每一次都完成了被要求的事问题出在被要求的方式本身承载不了工程意图。这其实不是新问题在过去几十年里软件团队用一整套东西管住从意图到代码这段路需求文档、设计评审、接口契约、验收标准、任务拆解。它们的共同作用是让意图显形假设被摆到桌上讨论过“完成也有一个不依赖写代码者自觉的客观判据。AI 时代最讽刺的一幕就在这里人因为直接说话就能出代码”把这一整层东西全省了然后重新吃了一遍它们当年要解决的亏。那么具体要补回来什么最底层的一条意图得有一个持久、可审查、能版本化的落点。新会话、新成员、换一个 Agent都从同一个地方读取需求而不是各自从聊天记录里拼凑。短链接项目里过期后能不能跳之所以反复摇摆就是因为答案只存在于某次对话的某一行里。光有一个存放的地方还不够这个落点还必须把 What、Why 和 How 分开。先确认要解决什么问题、什么样子算成功再进入技术选型。短链接项目里的存储选型和过期策略是 AI 在生成代码的同一秒钟顺手定掉的技术决定伪装成需求一起溜了进来等你发现的时候两者已经焊死。而一份结构正确的规格照样可能在关键处保持沉默。歧义必须在动手之前被系统性地逼问出来由人做决定而不是由模型在生成时用默认值静默填补。“过期能不能跳”、“删除要不要鉴权”、“爬虫算不算访问”这些问题的答案就是需求本身澄清的过程和结论都得留下记录。逼问出来的需求还得能验证。验收场景应当先于代码或者至少和代码同时存在给定什么条件、触发什么动作、应当看到什么结果一条条可以核对。没有这一层完成永远是生成方自己宣布的短链接项目里那条永远不被演示走到的 slug 碰撞路径就是这样隐身了整整两周。前面几条管住的是开工之前还得有东西管住开工之后。实现过程要能持续对照原始意图做检查哪些需求还没有代码对应哪些代码找不到需求来源新决定和最早定下的原则冲不冲突这些要在合入之前暴露而不是上线之后靠用户发现。这几条约束没有一条是新东西真正变了的是它们的成本。过去这些事全靠流程和人兜底文档从头手写评审要把相关的人凑齐验收还得人工一遍遍回归成本高到大多数小项目干脆放弃。而 AI 把从规格到代码这段翻译的成本压到接近零之后情况第一次不一样了约束有可能不再是躺在 Wiki 里的一份 PDF而是一条机器读得懂的流水线规格既能驱动生成也能反过来作为检查的依据这正是下一节要给它命名的东西。五、从 Prompt Engineering 转向 Spec-Driven Development过去两年大家练的是 Prompt Engineering它的优化对象是怎么对模型说这一句话技巧随会话生灭最终的产出物只有代码。Spec-Driven Development以下简称 SDD换了一个主轴。规格不再是写完就扔的脚手架而是项目的主要产物和真相来源代码退居为规格在某个语言、某个框架下的一次具体表达。Spec Kit 把这件事称为一次权力反转。过去几十年代码是王规格服务于代码代码往前走规格很快掉队两者之间的鸿沟靠人手工填从来没有真正填满过。SDD 把关系倒过来让代码服务于规格。当一份规格足够精确、完整、没有歧义实现就可以被反复生成规格和实现之间不再有需要手工翻译的鸿沟只有一次又一次的转换。这里必须立刻补一句边界免得它听起来像银弹。规格不会自动正确和人一样会写出错误的、自相矛盾的、短视的规格那是另一类问题专栏第 15 章会专门谈。SDD 保证的不是人不犯错而是让意图、假设、决策和验收全部显形可以审查可以回归。错误从埋在代码里变成摆在纸面上这已经是很大的不同。用这一套回看短链接服务如果重来一次顺序应该是这样。先立一次项目原则把代码质量、测试标准、兼容性的底线定下来。然后写功能规格说清楚这个服务解决什么问题哪些用户故事优先slug 的规则是什么过期行为是什么什么样的请求算一次有效访问。规格出来之后专门做一轮澄清把过期能不能跳、删除要不要鉴权这类高影响歧义在写代码之前问完。之后才进入技术计划选存储设计表和接口把有风险的未知项标出来。计划再被切成带依赖关系的任务切片。动手实现之前先做一次跨产物检查确认规格、计划和任务没有互相打架。最后才是实现并且反复对照规格检查缺口直到真正收敛。这个顺序里的每一步都对应着上一节的一条约束也都对应着短链接项目里真实发生过的一次事故。不过这套流程如果全靠手工维护很容易变成另一重形式负担。文档写一套、代码做一套的事行业里见得太多。Spec Kit 要解决的就是这个问题它把这条流水线做成了 CLI、模板和 AI Coding Agent 命令的组合让规格不只是文档而是能驱动生成、也能驱动检查的可执行产物。下一章我们就拆开看它到底是什么由哪些部分组成初始化之后你的项目里会多出什么。小结短链接服务的失控不是任何一次生成失败造成的它在每一步上都成功了。真正的病根是一次性 Prompt 承载不了跨时间的工程意图偏差通过上下文漂移、隐性假设和缺失的验收标准像利息一样滚大。能跑是生成方的视角需求已实现需要外部判据没有可执行的验收和对照检查一个项目的完成度只能由写代码的那一方自己宣布。所以出路不是把 Prompt 写得更长而是换一个主轴让规格成为持久、可验证、能够驱动生成的中心产物。下一章进入 Spec Kit看这些约束具体怎么变成一条条命令和一个个文件。
延伸阅读

更多相关文章

2026/10/14 1:15:39

SpringBoot整合Shiro权限框架实战:从认证授权到常见问题排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 1:10:39

组合数学计数法则:加法与乘法原理及排列组合实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 2:30:44

量化软件推荐 参数搜索和独立验证三款工具怎样选

量化软件推荐,准备反复修改参数的人可以比较BigQuant、牛股王股票和青柠量化。愿意自己记录表达式及模型改动,可评估BigQuant;希望先限定现有因子与交易模型的少量调整,可检查牛股王股票;需要参数实验室及步进样本外验…

2026/10/14 2:30:44

【单片机课设毕设项目】基于单片机的智能婴儿床心率体温监测与图像远程监护装置设计 基于WIFI的婴儿监护生理环境监测与哄睡联动系统设计(032709)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/14 2:30:44

个人量化软件对比 三款工具如何解释少数交易拉高收益

个人量化软件对比,面对一条收益不错、却可能由少数交易贡献的曲线,可以比较米筐研究工具、牛股王股票和掘金量化。需要自行阅读头寸、流水并设计收益归因,可了解米筐RQAlpha Plus;希望从单次收益、盈亏比和历史明细开始复核&#…

2026/10/14 2:30:44

【单片机毕设案例分享】基于STM32的智能婴儿床多参数监测与远程联动控制装置设计 基于物联网的婴儿床生理环境监测与摄像头监护系统设计(032709)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于单片机,STM32单片机,51单片机,J…

2026/10/14 2:30:44

机械工程读研值不值?从产业周期到导师选择的全链条决策指南

每年到了保研、考研的时间点,总有一批机械工程专业的本科生在纠结同一个问题:到底要不要读硕士。问这个问题的学生,往往不是成绩最拔尖的那批,也不是完全不想读书的那批,而是处于中间状态的大多数——能找工作&#xf…

2026/10/13 5:19:27

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/13 17:09:18

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/12 12:54:07

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/14 0:00:33

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:33

macOS/iOS高精度计时:mach_absolute_time原理与实战

1. 项目概述:为什么mach_absolute_time是 macOS/iOS 时间测量的“黄金标准”在 macOS 和 iOS 开发中,我见过太多人用CFAbsoluteTimeGetCurrent()或NSDate.timeIntervalSinceReferenceDate做性能打点,结果在高精度场景下被系统时钟跳变、NTP 同…

2026/10/14 0:00:33

SCORM课件演示与测试全解析:从API通信到自动化验证

简介:这是一套遵循SCORM标准的交互式课件演示与测试资源,面向E-Learning课程开发者、LMS平台测试人员及在线教学从业者,用于验证课件在不同学习管理系统中的识别、传递与跟踪能力。压缩包共28个文件,约12.07MB,以swf动…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑