Codex总是改多了?用AGENTS.md和自动测试限制修改边界

📅 2026/8/1 15:28:50
Codex总是改多了?用AGENTS.md和自动测试限制修改边界
一名开发者给Codex的任务只有一句话修复优惠券为空时接口报错的问题。十分钟后Bug确实修了但项目里多出了这些变化一个新的工具函数两个文件被统一格式化原有导出名称被调整测试框架配置被重写顺手升级了一个依赖与Bug无关的类型定义也被修改。每一项单独看都能解释组合在一起却让代码审查变得很难到底哪一行是必要修改哪一行只是AI认为“顺便优化一下”这类问题不能只靠一句“不要乱改”解决。更可靠的工程方法是把控制拆成四层仓库长期规则AGENTS.md当前任务边界任务提示结果正确性自动测试和静态检查修改必要性Git Diff人工审查AGENTS.md负责告诉Codex这个项目长期怎么工作任务提示负责限制这一次要做什么自动化命令负责证明代码能运行Git Diff负责确认它没有越界。一、AGENTS.md究竟解决什么问题根据Codex官方文档Codex会在开始工作前读取AGENTS.md并根据所在目录建立一条指令链。它适合保存长期有效的仓库信息例如项目使用什么运行环境安装、测试和Lint命令是什么哪些目录不能随意修改是否允许增加生产依赖公共接口能否重命名Bug修复必须补什么测试交付时需要报告哪些验证结果。AGENTS.md不是每次任务都要重新粘贴的超长提示词更像是“写给代码代理看的项目协作说明”。官方文档列出的主要加载逻辑可以概括为全局AGENTS.md↓项目根目录AGENTS.md↓当前路径中的子目录AGENTS.mdCodex从项目根目录向当前工作目录逐层查找规则。同一条规则发生冲突时更接近当前目录的文件会在合并后出现得更晚因此优先级更高。例如shop-api/├── AGENTS.md├── src/│ └── pricing.js└── services/└── payments/├── AGENTS.override.md└── refund.js根目录的AGENTS.md可以要求所有服务运行通用测试payments目录中的AGENTS.override.md则可以补充支付业务的特殊限制。但要注意AGENTS.md是行为指导不是操作系统级的权限隔离。它可以要求Codex不要修改某个目录却不能代替文件权限、沙箱、审批机制和CI检查。如果某项规则绝对不能被绕过应当通过权限、测试、Hooks或CI进行机械约束。Codex官方AGENTS.md说明https://learn.chatgpt.com/docs/agent-configuration/agents-md二、先准备一个可以复现的Bug下面使用一个不依赖第三方库的Node.js示例。项目结构codex-scope-case/├── AGENTS.md├── package.json├── src/│ └── pricing.js└── tests/└── pricing.test.jspackage.json{“name”: “codex-scope-case”,“private”: true,“scripts”: {“test”: “node --test”,“lint”: “node --check src/pricing.js node --check tests/pricing.test.js”}}原始的pricing.js“use strict”;function calculateTotal(items, coupon) {const subtotal items.reduce((sum, item) sum item.price * item.quantity,0);const percent coupon.percent;return Number((subtotal * (1 - percent / 100)).toFixed(2));}module.exports { calculateTotal };有优惠券时这段代码可以正常运行calculateTotal([{ price: 80, quantity: 1 },{ price: 60, quantity: 2 }],{ percent: 10 });// 180没有传入优惠券时calculateTotal([{ price: 80, quantity: 1 },{ price: 60, quantity: 2 }]);程序会访问undefined.percent最终抛出TypeError。问题并不复杂真正需要控制的是修复这个Bug时有没有必要重写价格模块、修改导出形式或者增加一个新的依赖答案显然是否定的。三、给项目写一份能执行的AGENTS.md可以在项目根目录创建下面这份文件Repository expectationsRuntime and commandsUse Node.js 20 or newer.Runnpm testafter behavior changes.Runnpm run lintbefore reporting completion.Change boundariesPrefer the smallest change that fixes the reproduced failure.Do not add production dependencies without explicit approval.Do not rename public exports unless the task explicitly requires it.Do not modify unrelated files or reformat the whole repository.Verification and handoffAdd or update a regression test for every bug fix.Report the root cause, changed files, commands run, results, and remaining risks.If a required command cannot run, state the exact blocker; do not claim success.这份规则不长但每一条都能对应到具体行为。写清楚真实命令“修改后请测试”太模糊。Codex可能不知道应该运行哪个测试也可能只检查代码表面是否合理。写成npm test和npm run lint后完成条件变得可以执行。写清楚不能顺手做什么“保持代码整洁”很容易被理解成允许大范围格式化和重构。“不要修改无关文件”“不要重命名公共导出”“增加生产依赖前需要明确批准”边界更加具体。要求交付证据不要只让Codex说“已经修复”。要求它列出根因、修改文件、运行命令和测试结果开发者才能快速判断这次交付是否可信。四、AGENTS.md不能替代当前任务提示AGENTS.md应该保存长期规则不适合塞入只针对某一个Bug的临时要求。这次任务可以这样写目标修复src/pricing.js在coupon未传入时抛出TypeError的问题。复现条件calculateTotal(items)不传第二个参数时失败。修改范围只修改解决该问题所需的文件。不要重构价格计算流程不要新增依赖不要修改公共导出名称。验证要求保留有优惠券时的现有行为新增“coupon缺失时返回原始小计”的回归测试运行npm test运行npm run lint检查git diff和git diff --check。交付格式说明根因、修改文件、验证结果和剩余风险。这段提示把官方推荐的四类信息都补齐了| 信息 | 本案例内容 || Goal | 修复coupon为空时的TypeError || Context | src/pricing.js及现有计算行为 || Constraints | 不重构、不加依赖、不改公共导出 || Done when | 测试、Lint、Diff检查全部完成 |模糊任务通常会迫使Codex自己补充假设。任务边界越清楚它越容易把精力放在真正需要修改的位置。五、什么叫“最小修改”针对当前Bug核心修改只需要一行修改前const percent coupon.percent;修改后const percent coupon?.percent ?? 0;完整结果“use strict”;function calculateTotal(items, coupon) {const subtotal items.reduce((sum, item) sum item.price * item.quantity,0);const percent coupon?.percent ?? 0;return Number((subtotal * (1 - percent / 100)).toFixed(2));}module.exports { calculateTotal };这个修改保留了原有结构没有创建新模块没有修改函数名称没有修改导出方式没有引入依赖没有重写金额计算逻辑没有处理任务范围外的优惠券校验规则。这里最后一点很重要。开发者可能会想到继续限制百分比必须位于0到100之间但当前需求只是修复coupon缺失。如果项目还没有定义非法百分比应该抛错、截断还是忽略Codex就不应该擅自决定业务规则。最小修改不是代码行数越少越好而是每一项修改都能直接对应已确认的需求或验证要求。六、Bug修复必须有回归测试测试文件使用Node.js内置的node:test不需要安装第三方测试框架“use strict”;const test require(“node:test”);const assert require(“node:assert/strict”);const {calculateTotal} require(“…/src/pricing”);const items [{ price: 80, quantity: 1 },{ price: 60, quantity: 2 }];test(“applies a percentage coupon”, () {assert.equal(calculateTotal(items, { percent: 10 }),180);});test(“returns the subtotal when coupon is missing”, () {assert.equal(calculateTotal(items),200);});test(“does not mutate the input array”, () {const before structuredClone(items);calculateTotal(items, { percent: 10 });assert.deepEqual(items, before);});运行测试npm test验证结果tests 3pass 3fail 0再执行语法检查npm run lint本案例中node --check会分别检查业务文件和测试文件的JavaScript语法。这组示例已在Node.js环境中实际运行3项测试全部通过Lint命令也正常完成。七、测试通过还不够必须检查Diff自动测试回答的是“已覆盖的行为有没有通过”Git Diff回答的是“究竟改了什么”。可以依次执行git status --shortgit diff --statgit diff – src/pricing.js tests/pricing.test.jsgit diff --check四个命令分别解决不同问题| 命令 | 主要用途 || git status --short | 查看哪些文件发生了变化 || git diff --stat | 快速识别修改规模是否异常 || git diff – 文件路径 | 逐行审查核心文件 || git diff --check | 检查空白错误和冲突标记等问题 |理想情况下这个任务只应该涉及M src/pricing.jsM tests/pricing.test.js如果Diff里出现package.json、锁文件、README或者其他业务模块就应该停下来追问这项修改是否解决当前Bug所必需是否属于AGENTS.md禁止的无关改动是否需要拆成另一个任务是否应该回退这部分变化Codex本身也提供代码审查能力。在Git仓库中可以使用/review检查未提交改动、指定提交或相对基础分支的差异。官方说明指出专用Review流程会报告有优先级的发现而不会直接修改工作树。官方代码审查说明https://learn.chatgpt.com/docs/code-review八、把AGENTS.md分层而不是无限加长当项目越来越大根目录AGENTS.md很容易变成几百行的规则集合最后既难维护也容易让关键约束被淹没。更合理的组织方式是shop-api/├── AGENTS.md├── src/│ ├── catalog/│ └── payments/│ ├── AGENTS.override.md│ └── refund.js└── tests/根目录保留全项目通用规则AGENTS.mdRun npm test after behavior changes.Do not add production dependencies without approval.Preserve public API compatibility.支付目录保存局部高风险规则src/payments/AGENTS.override.mdDo not change rounding behavior without a documented business decision.Never log card data, tokens, passwords, or complete payment payloads.Run npm run test:payments after changing payment logic.Every payment-state change requires a rollback or compensation-path review.这样做有两个好处第一普通模块不会被支付业务的特殊规则干扰。第二当Codex在payments目录工作时更接近该目录的规则会覆盖或补充根目录说明。官方文档还提到Codex通常在一次运行或一次TUI会话开始时建立指令链。如果修改了AGENTS.md但当前任务仍在沿用旧规则可以重新启动会话在目标目录确认加载情况。九、哪些内容不应该写进AGENTS.mdAGENTS.md很重要但并不适合承载所有信息。不要写临时任务需求“今天只修复第238号Issue”属于当前提示不是长期仓库规则。不要写无法执行的口号例如写出世界上最好的代码。始终保证百分百没有Bug。所有代码都必须完美。这些表达没有可验证标准无法帮助Codex判断完成状态。不要堆入大量格式规则格式、Lint和类型检查能够交给工具时应尽量由CI和命令执行而不是让AGENTS.md塞满几十条缩进与换行要求。不要存放敏感数据密码、Token、生产数据库地址、用户隐私和内部密钥都不应该写进AGENTS.md或任务提示。不要把规则文件当权限系统真正禁止写入的目录应通过沙箱、系统权限、审批策略或自动检查保护。提示词只能降低越界概率不能提供强制安全边界。十、把“别改多了”变成可以检查的流程一套适合真实项目的最小修改闭环可以固定为读取AGENTS.md复现问题确认根因提出最小修改计划修改必要文件添加回归测试运行最相关测试运行Lint或类型检查检查Git Diff报告结果和风险还可以在任务提示中加入下面这段通用要求先定位根因并说明最小修改计划再开始编辑。修改后运行最相关测试和项目规定的检查命令。检查git status、git diff和git diff --check。如果出现与任务无关的文件变化先停止并说明原因。最终输出根因修改文件验证命令与结果未覆盖风险。这段要求比“认真一点”“不要乱改”“帮我全部检查好”更有效因为每一步都有可观察结果。十一、工具订阅不是代码质量保证AGENTS.md、自动测试和Diff审查解决的是工程流程问题不是订阅充值问题。无论使用ChatGPT Plus、Codex、Claude Pro、Cursor还是Kiro工具都不会自动理解每个项目的业务边界更不会天然替代测试和人工Review。如果有ChatGPT Plus、Claude Pro、Grok、Gemini Advanced等会员充值需求可以通过gpt328了解。它是第三方AI会员充值平台解决的是订阅充值流程问题不是代码托管、API中转或自动测试平台。使用前应看清套餐说明、账号要求、到账说明和售后规则。真正决定AI编程结果是否可信的仍然是上下文、约束、验证和审查。十二、最终结论Codex“改得太多”通常来自四类问题仓库没有提供长期工程规则当前任务只写目标没有写修改边界测试命令没有进入完成标准交付前没有审查Git Diff。AGENTS.md可以让Codex进入仓库时先理解项目规则但它不是安全沙箱也不能替代CI。一套更稳妥的分工是| 控制层 | 解决的问题 || AGENTS.md | 项目长期如何工作 || 当前任务提示 | 这一次允许改什么 || 自动测试和Lint | 修改后是否满足已知要求 || Git Diff审查 | 是否出现无关或高风险改动 || 权限、沙箱和CI | 对关键边界进行机械约束 |当“不要改多了”被拆成明确规则、验证命令和审查步骤后Codex的修改才会从“看起来完成了”变成“可以验证、可以解释、可以交付”。