AI 写完代码,程序员的工作才刚开始
今天傍晚 17 点 23 分,一篇文章完成排版,成功写进了微信草稿箱。
状态文件里有非空的草稿标识,文章状态是 drafted,审计记录写着本次新增 1 篇。证据挺齐,草稿总数也确实从 2 变成了 3。
两分钟后,外层监控给同一次运行下了另一个结论。
hard_failure,硬失败。
好家伙,草稿已经安安静静躺在后台了,监控在门口拉响警报,说这事没成。
顺着本地记录往下看,原因并不玄学。监控会扫描完整运行输出,寻找认证失败、权限拒绝之类的错误关键词。偏偏输出里还包含说明文档和测试样例,那些文字为了教人排错,本来就会写到各种失败提示。扫描器不认识上下文,看见词就判案,于是把「文档正在描述一种错误」当成了「系统刚刚发生这种错误」。
更有意思的是,外层记录自己还写着 drafts_before=2 和 drafts_after=3。
同一行日志,一边承认新草稿出现了,一边宣布运行硬失败。
这不是模型不会写文章,也不是接口没有返回结果。真正出错的地方,在代码生成之后。
成功到底由什么定义,哪一种证据优先,监控能读哪些输入,误报出现时谁来判断,系统该在什么条件下停下。模型可以很快写出正则、计数器和状态机,但它不会替团队承担这些选择。
我自己的判断可能有点刺耳。
AI 写完代码之后,程序员真正的工作才开始。
不是因为 AI 写得一定差。恰恰相反,生成速度越快,这句话越重要。以前写代码会占掉交付里的大半时间,很多含糊之处也在敲键盘的过程中慢慢暴露。现在模型很快就能给你一套能跑的实现,思考时间被压缩了,没想清楚的东西却没有消失,只是一起被打包进了产物。
代码更便宜了,错误地相信代码也更便宜了。
这才是 AI 编程最危险、也最有意思的地方。
把问题定义成可判定的结果
很多团队给 AI 的任务,看起来像需求,其实只是一句愿望。
「把这条流程做稳定一点。」
「加个监控,失败时告警。」
「帮我优化一下性能。」
人类同事听完也得追问,稳定是成功率、延迟,还是重复执行不产生脏数据。失败是进程退出非零、目标产物缺失,还是用户没有拿到结果。性能是 P95 延迟、吞吐、成本,还是高峰期不雪崩。
模型没有读心术。它会把没写出来的定义,用最像答案的默认值补上。厉害了,需求里的空白也能自动补全,只不过补出来的未必是你要的世界。
今天这次误判就卡在这里。外层监控把「输出里出现错误词」当成失败,把「目标草稿确实新增」也记了下来,却没有规定两种证据冲突时谁说了算。实现层面每一行都能解释,系统层面却没有一个稳定的成功定义。
程序员要做的第一件事,不是马上让 AI 改正则,而是把问题改写成一个可判定的合同。
目标产物是什么,成功必须留下哪几份证据,失败需要满足哪些条件,证据冲突时采用什么优先级,无法判断时是重试、降级,还是交给人。
拿草稿流程来说,最接近用户价值的证据,是目标系统返回非空草稿标识,并且本地状态记为已保存。退出码和关键词扫描可以做辅助信号,但不能在没有解释冲突的情况下推翻目标产物。
这种写法看着慢,实际会让 AI 快很多。任务不再是「帮我修一下误报」,而会变成「当目标产物已确认存在时,文档示例中的错误词不得覆盖成功状态。补回归测试,覆盖成功产物与错误词同时出现的场景」。
前一句会得到一堆猜测。
后一句会得到可验收的修改。
Anthropic 在智能体评估指南里强调,复杂任务需要选择合适的 grader,也就是负责判分的机制。这个词听起来像模型评测术语,落到普通软件里就是一句老话,别让不懂目标的裁判决定输赢。
所以每次把任务交给 AI 前,可以先逼自己回答一个问题。
如果它说已经完成,我拿什么证明?
答不出来,先别生成。

模型可以快速生成路线,程序员要先钉住终点与判分规则。
边界不是限制能力,是限制损失
定义清楚结果之后,下一件事不是把权限全开,让模型跑快一点。
而是画边界。
AI 编程经常给人一种错觉,既然它能改文件、跑测试、查网页、调用接口,那就让它一路做到底。省得人盯着,多爽。
我非常理解这种冲动。每确认一次权限、每人工点一次按钮,自动化的浪漫就少一分。可一旦任务进入真实系统,边界决定的不是它能不能完成,而是它做错时最多能错到哪里。
哪些目录可写,哪些数据可读,能否访问生产环境,能否创建外部资源,能否给真实用户发消息,能否删除记录,能否重试带副作用的操作,预算和时间上限是多少,碰到不确定输入时必须停在哪一步。
这些不是安全部门才关心的表格。它们就是程序设计。
NIST 的 AI 风险管理框架把角色责任、人类监督、系统适用范围、测试验证和生产监控放在同一条生命周期里。翻成人话,谁能做什么、做到哪一步、出了事由谁接手,应该和功能一起设计,不是上线前补一张免责说明。
边界意识可以拆成三层。
权限边界决定它有资格动什么。数据边界决定它能看见什么。影响边界决定一次错误最多伤到多少用户、多少资金、多少不可逆状态。
今天的草稿流程有一条很朴素的边界,只能保存草稿,不能替人发布。这条限制没有让自动化变笨,反而让整条链路可以放心大胆地试。标题不够好还能改,图片不合适还能换,判断错了也没有直接触达所有读者。
这就是边界的价值。
它不是把 AI 关进笼子,而是给探索铺护栏。
Google SRE 关于金丝雀发布的章节讲的也是同一件事。先让少量真实流量接触新版本,用更小的影响面换取更真实的证据,再决定是否扩大。自动化并没有被削弱,只是每一步都带着可回退的半径。
一个实用动作是,在任务描述里单独写一段「禁止做什么」。
不要只列抽象原则,要列不可逆动作。不得发布,不能群发,不能删除真实数据,不能改工作区之外的文件,不能在没有幂等保护时重试写操作,不能把密钥和个人信息带进日志。
模型最需要的往往不是更多自由,而是更清楚的悬崖边缘。
验收不是跑一遍测试,是构造可信证据
写代码的人很容易把「测试通过」和「需求完成」画等号。
AI 让这个习惯更危险了。因为测试也能生成,截图也能生成,日志摘要也能生成。你让它实现功能并证明自己,它完全可能交给你一套内部自洽的答案。
代码说自己没问题,测试说代码没问题,摘要说测试没问题。
棒棒的,一个封闭宇宙。
验收能力的关键,不是测试数量,而是证据是否独立、是否贴近用户结果、是否覆盖最可能被忽略的边缘。
单元测试证明局部逻辑符合预期。集成测试证明组件接得起来。端到端测试证明真实路径能走通。生产观测证明真实用户和真实数据没有把假设撞碎。这几层证据不能互相替代。
今天的误报恰好是一堂很好的验收课。只测错误关键词能否被识别,测试会通过。只测草稿计数是否增加,测试也会通过。真正缺的用例,是让「目标产物成功」和「输出里包含错误示例」同时出现,看判定器能不能分清主证据与噪声。
这类用例有个朴素的名字,反例。
不要只问系统什么时候该成功,还要问它在哪些看起来很像失败的情况下仍应成功。反过来也一样,进程退出 0、界面显示绿色、日志写着完成,不代表用户一定拿到了结果。
GitHub 对 required status checks 的说明里有很多类似边角。检查对应的是哪个提交,跳过的任务会留下什么状态,状态来自哪个应用,这些细节都会改变「绿灯」能不能作为合并依据。
验收从来不是看见一个绿勾就回家。
它是在设计一套证据链,让错误很难靠表面正常蒙混过关,也让成功不容易被无关噪声误杀。
我比较喜欢给 AI 产物做四次追问。
它证明了什么,它没有证明什么,哪个证据最接近真实用户,哪一种反例最可能让当前结论翻车。
四句问完,很多看着挺完整的实现会突然开始漏风。
别嫌麻烦。AI 把编码时间省下来的那部分,本来就该花在这里。

真正的完成,不是代码落盘,而是证据跨过了真实结果。
判断力是在冲突信号里选主证据
如果所有指标都一致,程序员不太需要判断力。
测试全绿,监控正常,用户满意,账单下降,延迟变短。谁来都能按下通过。
麻烦总出在信号打架的时候。
草稿标识存在,但进程退出非零。离线评测变好,但线上投诉增加。平均延迟下降,长尾却变差。安全扫描报警,但命中的只是测试夹具。模型给了高置信答案,引用页面却没支撑那个结论。
判断力不是拍脑袋。它是在不完整信息里,知道哪些证据离目标更近,哪些指标容易被污染,哪些代价不可逆,什么时候该继续收集信息。
今天这组记录里,离目标最近的是草稿系统返回的标识和草稿数量变化。关键词扫描离目标更远,而且输入里混入了文档与测试文本。两个信号冲突时,合理动作不是简单相信绿色,也不是简单相信红色,而是沿着证据来源往回走。
谁产生了这个信号。
它测量的是用户结果,还是某个代理变量。
它会不会被当前输入结构污染。
如果信错了,代价是什么。
这四个问题就是一次小型的工程判断。
Anthropic 关于有效智能体的工程文章建议从简单、可组合的模式开始,只有简单方案不够时才增加复杂度,并用完整评估支撑升级。这里面藏着很重要的判断习惯,别因为 AI 能做十步,就默认任务需要十步。
复杂系统最爱制造一种假勤奋。多加一个分类器,多套一层监控,多建一个评分器,看起来可靠性在上升,实际可能只是多了几个会互相矛盾的裁判。
有时候正确修复不是再加一条更聪明的正则,而是承认关键词扫描只能当线索,不能当终审。
有时候也不能只认目标产物。外部系统可能返回标识后异步处理失败,本地计数也可能读到旧缓存。这时就该再补一层独立核验,而不是把某个指标封成永远正确的神谕。
判断力最难的部分,是允许自己暂时不下结论。
证据不够就标成待确认,影响面太大就停下来,两个高质量信号冲突就交给人。程序员不是必须永远给答案的人,程序员是知道什么时候还不能给答案的人。
好奇心不是追新工具,是不接受一个顺眼的解释
聊 AI 时代的程序员,很多文章会落到持续学习。
每天看新模型,周末试新框架,收藏几十篇教程。焦虑像浏览器标签页一样越开越多,知识没进脑子,内存先爆了。
我不是说学习不重要。问题在于,「持续学习」太容易成为一句不需要验收的正确废话。
真正有用的好奇心,通常没有那么体面。
它会盯着一行奇怪的日志不放。
为什么草稿数增加了,结果还是失败。
为什么匹配器会读到说明文档。
为什么测试样例里的错误词能污染真实判定。
为什么成功定义依赖退出码,而退出码又会被同一个误判逻辑改写。
这种好奇心不是为了显得懂得多,而是拒绝在第一个顺眼的解释上停下。
有点子牛逼的工程师,不一定记得最多 API。他可能只是比别人多问了一次「这个信号到底从哪儿来」,然后发现整个团队一直在优化一个代理指标。
好奇心还有另一面,愿意做小实验。
删掉文档输入再跑会怎样,只保留结构化事件会怎样,把目标产物设为最高优先级会不会漏掉异步失败,把错误分类限制在运行事件而不是整段文本能不能降低误报。
每个问题都可以变成一个最小实验。一次只动一个变量,保留前后证据,允许结果推翻原判断。
这比漫无目的追新框架难,也比收藏教程值钱。
开工前,先写一张五行纸
如果你明天就要把一个真实任务交给 AI,不妨先别急着打开对话框。
拿张纸,写五行。
这一轮真正要解决的问题是什么,完成后谁会得到什么结果。
模型可以读写和调用到哪里,哪些动作必须禁止,最大损失半径多大。
我准备用什么证据验收,哪个证据离真实用户最近,反例是什么。
信号冲突时采用什么优先级,什么情况必须交给人判断。
还有哪个地方让我觉得奇怪,能不能用一个小实验把猜测变成证据。
这五行分别对应定义问题、边界意识、验收能力、判断力与好奇心。
它们不会替你写出一个函数,却会决定那个函数该不该存在,能动哪些数据,怎样才算完成,出了异常要相信谁。
OpenAI 的 Evals 接口可以帮团队把测试标准和 grader 变成可重复运行的系统,Google 的金丝雀方法可以把真实验证限制在较小影响面。但工具只能执行你写下的标准,不能替你决定什么值得优化。
这也是我越来越确信的一件事。
未来最稀缺的程序员,不是手速最快的人,也不是每天知道最多模型名字的人。
他能把一个模糊愿望压成可判定的问题,能给强大的工具画清边界,能为结果设计独立证据,能在冲突信号里承担判断,还保留一点不肯糊弄过去的好奇心。
今天那篇草稿早已成功躺进后台。
真正需要修的,从来不只是那条判错的规则。
而是我们对「完成」这两个字,到底有没有想清楚。