
1. 为什么这一期 Code Mode 值得开发者关注如果你平时用 AI 编程助手写代码大概率会遇到这样一个场景让它改一个模块它动的是全局的公共函数让它修一个 Bug它顺手把旁边的函数也重构成了新写法让它在一个几万行的老项目里加功能生成结果开头很漂亮一旦要真正编译通过就需要人不断帮它“收拾烂摊子”。出现这种问题的原因并不在模型智力而在运行模式。多数 AI 编程工具默认会尽可能多地读取上下文、尽量完整地生成代码块在原型或 demo 阶段这种策略很有效可一旦面对真正需要长期演进的软件系统它就容易失控。本篇文章要聊的是 Dex Horthy 发布的技术通讯“AI That Works”第 72 期主题为“面向可扩展软件的 Code Mode”。这里有一个很容易被忽略的判断Code Mode 不是某种开发工具的专属开关而是一整套约束 AI 生成行为的运行机制。它的目标不是让 AI 多写代码而是让 AI 在给定的代码规模限制内只生成可以被评审、被验证、被回滚的增量改动。它面向的不是单文件脚本而是那种模块复杂、多人协作、需要持续迭代的可扩展软件。读完这篇文章你会得到三样东西理解 Code Mode 背后的设计动机和核心约束搞懂“evaluation mode running with code size limit: 2k”这类提示语到底在说什么知道自己手头项目是否适合用这种模式以及如果要用有哪些步骤和坑。先说清一点本文并不是某个 AI 工具的官方文档翻译而是结合这类运行模式的技术思路帮助开发者建立一套适合自己的工程方法。文章核心围绕这样一个“反直觉”的结论展开限制 AI 的代码生成范围反而能提高它在真实项目里的可用性。2. Code Mode 是什么一种受控的 AI 生成模式2.1 从“放开写”到“在约束里写”Code Mode 在概念上并不复杂它指的是让 AI 在一个受限空间内完成代码修改或生成任务。这个“受限空间”通常包括给定需要修改的文件列表。给定允许生成或修改的代码规模上限。给定一个可描述的明确任务边界。要求修改后必须通过某种验证例如单元测试、类型检查、构建脚本。这里最典型的标识性表达就是这一类运行日志evaluation mode running with code size limit: 2k翻译成人话就是当前评估模式下AI 每次生成或修改的代码量被限制在 2k 范围内。2k 可以理解为一个 token 或者字符的预算单位这里在不同的工具实现里有不同定义但它表达的核心思想是固定的——这次 AI 不允许“放开了写”它只能在一个很小的范围内动代码。为什么这个限制有价值我们可以对照一下没有限制时的人工协作流程。假设一个团队里来了一个很强的新开发他每次接到需求都会自己重构相关模块然后一次性改动几十个文件。虽然逻辑写得没问题但其他同事从 Code Review 角度很难消化这样的大改动。哪怕代码很完美一旦后续出现问题回滚成本也极高。Code Mode 做的事情是把这位“很强的新开发”改造成一位更符合软件工程习惯的协作对象每次只改一小块接口保持稳定改动范围可以预测评审能看到清晰的差异回滚时只影响当前任务。它牺牲了一部分单次生成能力换来了整体工程可控性。2.2 关键术语拆解理解 Code Mode需要清楚下面几个关键词Code Size Limit代码规模限制指 AI 单次生成或修改的代码量上限。这里的单位不同工具不一样常见的是以 token 或字符计。它从机制上保证了一次改动不会铺得太大。Evaluation Mode评估模式指 AI 生成结果后会进入一种评估阶段系统会检查结果是否满足任务描述、是否修改了限定文件之外的内容、是否通过了配置的验证命令。这种模式类似于 CI/CD 里的流水线只不过现在把检查环节前置到了生成阶段。任务边界Task Boundary指需求描述中明确规定的改动范围。例如只允许改 service 层、只允许新增一个方法、不允许动数据库脚本。任务边界越清晰Code Mode 越容易生成合适的代码。增量思维Incremental Thinking这是 Code Mode 最核心的思维转变把一次大任务拆成多个小步骤每个步骤单独生成、单独验证、单独提交。原先“AI 一次性完成一个功能”的用法在 Code Mode 下变成了“AI 一次只完成一个可验证的步骤”。2.3 为什么它和可扩展软件高度相关可扩展软件最大的技术特征是模块解耦、依赖可控、架构演进而非一次性推翻。这类项目通常有自己的分层结构、接口约定、异常处理模式和测试体系。对 AI 编程助手来说这种项目恰恰是最难处理的场景。因为 AI 模型默认的学习目标是“根据当前问题生成较完整的答案”而模块化系统往往要求“根据上下文做最小范围修改”。这两者之间存在天然张力。Code Mode 正是用来调和这种张力的工程约束。当 AI 被限定在一次只能产生小规模修改时它被迫依赖现有模块结构、遵循已有代码风格而不是另起炉灶“发明一套新设计”。长期来看软件系统的结构稳定性会高很多可维护性才能有机会形成。3. Code Mode 解决的真实开发痛点3.1 痛点一AI 生成代码存在“重构幻觉”重构幻觉这个词未必是官方术语但用它描述 AI 编程中的现象非常贴切。现象是开发者只要求修改一个方法体内的逻辑AI 却把整个类的字段命名都改成了自己更习惯的风格甚至顺手删除了看起来没用但实际在反射中使用的私有方法。这种问题在演示场景里不致命因为 demo 代码本身生命周期短。但在一个运行了三年的订单系统里这种改动轻则 Code Review 被拒重则引入线上回归。Code Mode 对这类行为的限制是直接的在代码规模预算有限的条件下AI 没有余量去大规模重构。它只能在预算范围内解决问题所以必须使用现有的类名、方法名和结构约定。3.2 痛点二评审成本不降反升很多团队引入 AI 编程助手后发现代码量产出虽然涨了但评审成本也在涨。过去看一眼改动就明白意图现在要搞清楚 AI 为什么改这里、它是否也改了别的地方。用 Code Mode 的思路AI 的产出结构发生了根本变化一次提交对应一个清晰任务差异化可读评审者不需要承担理解大规模生成逻辑的负担。在小范围、清晰边界之下AI 的产出反而容易被人理解。复杂度没有消失但被分解到了多个提交中。3.3 痛点三AI 对“全局最优”的偏好破坏了局部稳定大模型进行代码生成时倾向于在全局语义一致性上做优化。放到具体项目里如果 AI 发现某个接口命名不统一它可能会倾向于把相关调用全部改掉来达到它理解的“最优状态”。但在真实软件开发中全局重构往往需要专门排期不能夹带在功能开发里。Code Mode 的规模限制相当于一个护栏强制 AI 接受“局部不完美但局部稳定”的状态这是可扩展软件持续演进的基础。3.4 痛点四无法建立自动化的验收回路如果一个 AI 把多个文件改了一遍你想通过自动化手段验证它是否破坏了原有功能需要对比的范围非常大。而 Code Mode 下每次改动被限制在小范围内自动化验证的闭环更容易建立跑对应模块的测试、检查编译、扫描 API 变更都能在秒级完成。从这些痛点可以看到Code Mode 不是一个提高 AI 单次能力的功能它更像一个工程治理工具。它限制的并不是模型而是模型和代码库的接触面。4. 环境准备与前置条件Code Mode 并不是纯理论概念要实现它需要在工程和工具上做一些准备工作。下面以当前常见的 AI 编程工具使用方式为准给出通用性的准备清单。具体工具可以根据团队实际选择。4.1 工作环境清单项目建议操作系统Linux / macOS / Windows均可代码库Git 管理分支清晰能独立回滚AI 编程工具支持自定义代码规模约束、支持执行验证命令的工具验证命令至少有一条能在 1 分钟内完成的结果判定命令测试环境本地或 CI 均可关键是要能快速反馈语言不限但建议先从静态类型语言开始使用4.2 为什么要准备快速验证命令Code Mode 的价值核心在于 AI 生成结果能被快速评估。如果验证一条修改需要跑 20 分钟全量流水线那么整个“生成—评估—修正”循环会变得非常低效。因此正式使用前必须准备一条快速验证命令例如针对当前模块的单元测试# 以 Java/Maven 项目为例只跑当前模块的测试 mvn test -pl user-service -am # 如果当前只改了一个类可以直接用 IDE 或 surefire 指定测试类 mvn test -DtestUserServiceTest -pl user-servicePython 项目同理# 只跑指定测试文件快速反馈 pytest tests/test_user_service.py -x -q前端项目也可以配置 lint 和单测的组合命令npm run lint -- --quiet npm run test -- --runInBand tests/userService.test.ts4.3 分支策略与回滚准备Code Mode 默认 AI 可能会生成设计上有缺陷的代码因此工作分支必须做到可丢弃。强烈建议为每次 Code Mode 任务创建独立分支git checkout -b feature/ai-order-refund-fix如果 AI 生成结果混乱可以直接丢弃分支重来而不影响主分支。经验上一个任务的代码规模限制越小丢弃成本越低开发者越愿意尝试多轮修正。这也解释了为什么把“代码规模限额”做小是驱动 AI 可用性的重要因素。5. 用最小示例跑通 Code Mode 流程理论说再多不如真正跑一次“受限 AI 修改”的流程。下面通过一个非常小的 Java 重构任务演示 Code Mode 的核心用法。这里我们不绑定具体 AI 工具只关注思路和步骤你可以在自己常用的工具中用同样方式操作。5.1 任务定义假设有一个简单的用户服务当前方法逻辑冗余我们希望把“检查用户存在并返回用户名”这部分重构为独立方法。同时不希望 AI 修改其他类、不希望改动接口签名、不希望调整测试框架。先把任务描述写清楚一个带有严格边界的任务说明模板可以参考任务重构 UserService 类的 findUserName 方法 允许修改文件 - src/main/java/com/example/service/UserService.java 禁止修改文件 - src/main/java/com/example/repository/UserRepository.java - src/test/java/com/example/service/UserServiceTest.java 约束 - 方法签名保持不变 - 不修改任何注解 - 不引入第三方库 - 代码规模限制不超过 50 行新增代码 验证命令mvn test -DtestUserServiceTest -pl user-service这份任务说明就是 Code Mode 的“输入上下文”。它比单纯说“帮我重构一下 user service”要有效得多因为它给出了 AI 在生成时必须遵守的边界条件。5.2 初始代码示例为了演示效果构造一个简化的 UserService// 文件路径src/main/java/com/example/service/UserService.java package com.example.service; import com.example.repository.UserRepository; public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository userRepository; } public String findUserName(Long userId) { if (userId null) { throw new IllegalArgumentException(userId must not be null); } return userRepository.findById(userId) .map(user - user.getName()) .orElseThrow(() - new RuntimeException(user not found)); } }这个类有两个明显的问题空参数校验和“找不到用户”的异常类型不够合理。通常我们希望在 service 层校验参数在找不到用户时抛出明确的业务异常。但为了验证 Code Mode我们希望 AI 不要把整个逻辑推翻而是先抽出一个私有校验方法。关键点在 Code Mode 下重构质量不是第一目标约束遵守度才是。如果 AI 在没有被允许的情况下修改了 UserRepository 接口哪怕它给出的代码质量更高在 Code Mode 的评审体系里也应当判定为失败。这一点可以通过下面这段伪代码帮助我们理解评估要求{ task: refactor findUserName, allowedFiles: [ src/main/java/com/example/service/UserService.java ], forbiddenFiles: [ src/main/java/com/example/repository/UserRepository.java, src/test/java/com/example/service/UserServiceTest.java ], validation: { command: mvn test -DtestUserServiceTest -pl user-service, timeoutSeconds: 120 } }5.3 让 AI 做受限重构拿到上面的任务描述和代码后在 AI 编程工具中提交重构请求。一个好的 Code Mode 实测流程大约按以下步骤走。第一阶段发送任务描述等待 AI 生成 diff。第二阶段确认 diff 是否只触及允许修改的文件。第三阶段人工快速审阅特别关注是否改变方法签名、是否引入无关改动。第四阶段执行验证命令mvn test -DtestUserServiceTest -pl user-service如果测试通过再执行一次 diff 长度检查确认新增代码量确实在预算内git diff --statgit diff --numstat | awk {add$1; del$2} END {print added:, add, deleted:, del}第五阶段提交并推送形成一次干净的提交。5.4 一个参考重构结果下面给出一个符合约束的重构结果。这个结果只是参考关键是它没有触碰 UserRepository也没有改动测试// 文件路径src/main/java/com/example/service/UserService.java package com.example.service; import com.example.exception.UserNotFoundException; import com.example.repository.UserRepository; public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository userRepository; } public String findUserName(Long userId) { checkUserId(userId); return userRepository.findById(userId) .map(user - user.getName()) .orElseThrow(() - new UserNotFoundException(user not found, id userId)); } private void checkUserId(Long userId) { if (userId null) { throw new IllegalArgumentException(userId must not be null); } } }注意这里为了抽离校验逻辑引入了新的 UserNotFoundException 异常类。这在实际代码库中可能不被允许因为它创建了新文件。所以更严格的任务描述应该把“是否允许新建类”也写清楚。例如“如果必须新建异常类请先停在原地提示不要自动创建”。这就是 Code Mode 和普通 AI 使用方式最显著的区别约束贯穿整个生成过程——不是 AI 推断出什么合理就做什么而是任务允许做什么才做什么。6. 从“2k 限额”看代码规模评估逻辑网络热词中有一句非常值得剖析的日志提示evaluation mode running with code size limit:2k这句话在 AI 编程工具的真实使用中代表了一次带有代码规模限额的评估行为已启动。理解它背后的逻辑对开发者选择任务切分策略很有帮助。6.1 为什么要限制为 2k 而不是 10k 或 100k一个具体代码任务的“信息复杂度”可以分三类小任务如修改方法内部逻辑、增加参数校验。这类任务的语义空间小产生的代码影响面有限2k 限额通常足够。中任务如新增一个 service 方法、新增一个接口实现。这类任务需要理解接口与抽象通常需要阅读多个文件一次生成的代码量可能在数百行。大任务如模块拆分、权限体系调整。这类任务涉及多个边界单次修改动辄上千行。如果允许 AI 一次生成即使质量不错评审和回滚也极为困难。2k 限额本质上是一个保守的“单次可评估”尺度。在这个尺度下AI 很难绕过任务边界做大规模重构因为它“额度和上下文都不够”。它被迫只能选择局部修补的方案——刚好符合可扩展软件对稳定演进的期望。6.2 限额和任务描述的质量存在强相关限额越小任务描述的质量要求越高。如果你想用 2k 限额让 AI 完成一个完整的用户注册功能几乎不可能因为它需要的新增代码量远超预算。此时必须把功能拆成多个子任务逐步推进——先建模、再写 repository、再写 service、再写 controller、再补测试。每个子任务单独走 Code Mode 通道。这正好和微服务拆分或模块化开发中的“接口先行、实现随后”思路一致。Code Mode 推动的好处是无论人还是 AI都必须先在脑子里把一个大功能切成小块而不是直接给出一个包裹式的大结果。6.3 怎么判断当前任务适合多少限额一种务实的经验做法是没有把握时选择更小的限额。如果你给了一个很小的限额AI 总是说“代码量超限”那说明任务被定义得太大需要拆分而不是把限额调大。反过来如果连续多次生成结果都在限额边缘徘徊、经常产生截断那说明当前限额确实过紧。实际项目中可以给限额设置一个“梯度”任务形态建议限额说明修复一个方法内逻辑1k 以下改动应聚焦在单方法体增加一个 service 方法2k 以下包含调用链与参数校验新增一个接口 实现类5k 以下建议拆成接口与实现两次生成一个完整的模块雏形不推荐单次生成应分文件、分层、分提交这些数字来自工程经验不是固定标准。重要的是理解限额是“评估单位”而不是“能力上限”它决定一次产出是否容易被理解、被验证、被回滚。7. Code Mode 落地时的常见问题与排查思路真正开始使用 Code Mode 后会发现它与传统“让 AI 写代码”的体验差异很大。下面列几个高频问题并给出排查思路。问题现象可能原因排查方式解决方案AI 说“无法完成”或反复生成空 diff限额太小而任务描述过宽重新审视任务是否包含多个改动点把任务描述拆成更细的子任务AI 修改了未授权文件上下文模型弱任务说明中禁止列表不够醒目检查 git diff确认实际改动范围在任务开头和结尾各写一遍禁止文件增加最终校验脚本生成代码通过测试但风格不一致缺少风格约束检查项目是否有 checkstyle / formatter在任务描述中加入“遵循已有代码风格”等指示验证命令耗时过长测试粒度太粗观察测试调用链配置仅针对模块的测试命令或用 maven -Dtest 模式AI 总是停留在计划阶段不动手写任务要求过多、范围太大观察它是否在尝试拆解手动把它输出的拆解步骤作为下一步 prompt 再次提交生成结果频繁截断总输出 token 被限额限制查看报错中是否有 “token limit” 字样调大工具本身输出 token 上限或进一步缩小任务范围重构逻辑正确但测试被改动任务描述没有声明测试不可改查看 git diff 中的测试文件部分明确要求不允许改测试或要求先列出新增测试场景这些问题的共同点是Code Mode 下早期失败大多来自任务定义不清而不是模型能力不足。在调整模型之前先检查任务的边界是否足够严格、验证命令是否足够快、限额与任务大小是否匹配。8. 可扩展软件开发中使用 Code Mode 的最佳实践8.1 任务描述模板化建立团队级规范Code Mode 对任务描述的要求远高于普通聊天式问法。建议开发者在项目根目录放一个ai-tasks/目录用固定模板描述每个任务。这样既能约束 AI也能沉淀团队的 AI 协作经验。参考模板# 任务/ai-tasks/20250612-order-refund.md ## 目标 修复订单退款时金额精度丢失的问题。 ## 允许修改 - order-service/src/main/java/.../RefundService.java - order-service/src/main/java/.../RefundRequest.java ## 禁止修改 - 任何数据库脚本 - order-service/src/main/java/.../OrderStatus.java - 所有测试文件和 pom.xml ## 验证命令 cd order-service mvn test -DtestRefundServiceTest ## 约束 - 不改变方法签名 - 不新增依赖 - 日志输出保持 logback 格式 - 代码规模限制2k把任务描述当作代码一样进行版本管理。一条经验是如果团队中任何一位成员无法用自然语言说清任务边界那么 AI 多半也处理不好这个任务。8.2 使用 Git diff 做自动化的“范围守卫”有些经验丰富的团队会在 Code Mode 流程后加一个脚本自动检查改动是否越界。脚本的思路并不复杂读取 git diff 的文件列表与允许列表、禁止列表做比对任何一个文件不在允许列表内就直接失败。#!/usr/bin/env bash # 文件路径scripts/guard-code-mode-range.sh set -euo pipefail ALLOWED_FILE.ai-allowed-files FORBIDDEN_FILE.ai-forbidden-files git diff --name-only HEAD /tmp/changed_files.txt if [ -f $FORBIDDEN_FILE ]; then while IFS read -r f; do if grep -Fxq $f $FORBIDDEN_FILE; then echo Error: forbidden file changed: $f exit 1 fi done /tmp/changed_files.txt fi if [ -f $ALLOWED_FILE ]; then while IFS read -r f; do if [ -n $f ] ! grep -Fxq $f $ALLOWED_FILE; then echo Error: file not in allowed list: $f exit 1 fi done /tmp/changed_files.txt fi echo File range check passed配合 Git 提交钩子或者 CI 流水线可以让“AI 越界”这个问题从人工评审前就被拦截。这与传统代码工程中的 Checkstyle、SonarQube 思路一致把规则前置到自动化阶段。8.3 每个 Code Mode 任务对应一次独立提交一次任务完成并通过验证后建议立即提交。不要让一个分支上累积多个 Code Mode 任务的产出再统一提交。原因有两点第一任务与提交一一对应后回滚语义清晰第二评审者可以通过查看某次提交的 diff 理解一个任务的全部改动。git add order-service/src/main/java/.../RefundService.java git commit -m fix(order-service): 修复退款金额精度丢失问题如果某次任务生成的代码有问题只需要回滚该提交即可不需要连带影响其他 AI 任务的产出。8.4 小步验证优于大改后验证开发者在传统编程中习惯“写完功能再统一编译”在 Code Mode 中这就行不通了。因为 AI 在消费完当前上下文后下一次修改就需要重新加载验证越晚重新加载的上下文越庞大出错回溯越难。建议改成每完成一个方法、每新增一个类就执行一次最小验证命令。例如在修改 UserService 时可以单独执行一条测试命令来快速确认是否有低级错误。mvn test -DtestUserServiceTest#testFindUserName -pl user-service8.5 区分探索型任务与演进型任务如果任务是探索型的例如想快速看一个完整 demo、比对新架构方案的写法那么默认的“放开写”模式反而更有优势因为此时目标是快速试错。如果任务是演进型的例如在一个成熟模块中增加功能、修复问题、做局部重构那么无条件使用 Code Mode 是一个更安全的选择。Code Mode 不应该用来解决所有问题而是要在“大概率需要长期保留的代码”上使用。8.6 关注异常链路与边界条件AI 在 Code Mode 的小额度限制下最常忽略的是异常链路的完整性。开发者需要重点关注 AI 生成代码里是否包含异常处理逻辑是吞掉异常、抛出笼统异常还是明确定义了可恢复与不可恢复的异常类型。这里建议把“异常处理策略”直接写进任务说明。下面这段文字可以作为模板片段异常处理要求 - 输入参数为空时抛出 IllegalArgumentException - 数据不存在时抛出带上下文信息的业务异常 - repository 调用异常向上抛出不捕获吞掉8.7 不要忽视文档注释与 API 说明可扩展软件的特点是会被多个模块调用。如果 AI 在 Code Mode 下新增了方法却没有留下方法级别的 Javadoc 或说明注释后续的人类维护者很难快速理解设计意图。可以在任务描述中增加“必须为新增 public 方法编写 Javadoc”之类的约束。当然这种方法也有弊端文档过多同样会占用有限的代码规模预算。实际处理经验是接口方法、跨模块调用的 public 方法必须写私有方法允许不写。9. 总结如何把 Code Mode 思路用在自己的项目上最后做一下收束给出可以直接照做的行动清单。第一不要先急着找“启用 Code Mode 的开关”。先把手头的一个小任务用严格的边界描述方式重写一遍限制允许修改的文件、定义清楚验证命令、划出禁止触碰的模块。哪怕你在输入框里只是把这套逻辑写出来也能明显感受到 AI 输出的可控性进步。第二给团队配置一套自动化的“范围守卫”脚本。脚本本身不复杂十几行 bash 就能做到价值却非常大它让约束从“靠提示词”升级为“靠流程强制”。真实项目里流程强制的成功率远高于口头约定。第三把任务拆碎用小步调来验证。2k 限额的核心启示不是“AI 一次只能写这么点东西”而是“人一次应该只评审这么点东西”。真正限制 AI 的不是 token 预算而是人类理解与验收的吞吐率。第四Code Mode 更适合演进而非创生。在全新项目里让 AI 自由发挥没有太大问题但在老项目、大项目、多人维护的项目里每一行改动都需要为未来的可理解性负责。这种场景下有约束的修改比聪明的重写更有价值。第五记住 Code Mode 的思路不只适用于代码生成。它可以延伸到任何 AI 参与内容生产的场景写文档时限制章节数、修改配置时限制字段范围、做技术方案时限制备选方案数量。核心原则是一样的给 AI 一个人类能理解的生成边界然后用自动化的方法判断它是否越界。从评估日志中那句evaluation mode running with code size limit: 2k能看到行业正在试图回答一个深层问题我们需要的不是“更强大的 AI”而是“能放在工程体系里正常工作的 AI”。Code Mode 是目前针对这一问题给出的务实路线之一它提醒开发者软件可扩展性不仅来自架构设计也来自每一次修改的克制和可控。建议收藏这篇文章等到下次要给 AI 派发任务时先照着第 5 节的模板写一份任务描述再对照第 8 节的脚本做一个范围守卫。跑两轮之后你对“AI 编程”的看法大概率会发生改变。