用 Codex 做新行为或修回归,把失败测试本身当成完成合同:测试没红起来不许改产品代码,绿了才允许重构,完成以测试输出为准,不看模型口头说做完。

要点
- 官方把“怎样算做完”写成可观察条件。ChatGPT Learn 的 Best practices 建议提示里写 Goal、Context、Constraints 和 Done when;例子是测试通过、行为改变、或某个 bug 不再复现。
AGENTS.md也应写清“做完意味着什么、怎么验证”。(Best practices) - OpenAI Cookbook 要求每个实施阶段带上最小的失败检查(red)、刚好够用的实现(green),以及只在行为与范围保持不变时才重构;验证命令必须真实跑过,计划里的命令不能抄成“已经通过”。(Iterating development workflows with Codex)
- 官方把 issue 做成可测 PR 的用例里写得更硬:新测试应能区分新旧行为,最好在旧代码上先失败、改完再通过;未跑过的检查禁止写成通过;不要靠删断言或放宽授权去换绿。(Turn an issue into a tested pull request)
- 本篇把完成合同落到测试文件上。提示词按“先红后绿再重构”分轮写死可改范围:红轮只动测试、绿轮只动产品代码、重构必须在绿之后并且再跑同一组测试。这和“在提示里写允许路径与验证命令”是两件事,也和改 bug 时的 Review→Repair→Validate 闭环不是同一套节拍。
- 第三方实践把假绿当成最大风险:绿轮若改了测试文件,或把精确断言改松、给用例加 skip,或只跑了不相关的绿条,都不能算完成。红灯还应失败在预期断言上,编译或 import 报错不算有效的红。(Easton:Codex Test-Driven Development)
- Codex CLI 能在本地仓库里读文件、改文件,并跑你机器上已有的测试命令。(Codex CLI)命令名以仓库脚本和你本机帮助为准,下文里的
npm test只是占位。
正文
场景
你让 Codex 给结账接口补重试。它改了四处文件,回一句“测试已经过了”,没有命令,也没有输出摘录。你打开 diff,测试文件也动了:原来断言要精确匹配错误码 PAYMENT_TIMEOUT,现在改成了“有值就算过”。产品代码看起来绿了,合同被改瘦了。
另一种翻车更隐蔽。模型和测试、实现写在同一轮里。你从头到尾没见过红灯,也就没法确认这条测试真能抓住旧行为。口头“做完了”在这里值不了多少钱。
站内另两篇已经分别写过:改 bug 时先补红灯回归测试,再走 Review→Repair→Validate;多文件重构时在提示里写清允许路径、禁止事项和验证命令。那些纪律还要用。本篇只攻一件更硬的事:把“怎样算做完”从一段文字,落到一份会失败的测试文件上,并用分轮提示把红绿重构三步锁死。
可跟做步骤/可抄工作流
先把完成合同写成一份会失败的测试
Best practices 把 Done when 解释成“完成前必须为真的事”,例如测试通过。Cookbook 又补了一句:每个阶段要包含最小的、有意义的失败检查。合在一起,合同是一张测试文件,加上一条你会亲自看的命令。单写“请按最佳实践实现重试”不够。
合同至少要钉死四件事:测哪一个行为,用哪一条命令,红的时候失败在哪条断言,以及绿了之后哪些文件不该再被改。缺了测试文件,Done when 只是愿望清单;缺了命令和输出,模型口头说绿也不算证据。
官方把 issue 做成可测 PR 的示例里,专门留了 red.log 和 green.log:同一组测试在旧实现上失败,在修复后通过。你不一定要照抄那个分页用例,但这个证据形态值得借过来。
常驻纪律放进 AGENTS.md,本轮合同放进提示
Best practices 建议:提示里反复奏效的规矩,搬进 AGENTS.md。文件要短,写清测试命令、约束,以及怎样算做完。下面这段是常驻纪律,不是某一轮的任务说明书。测试命令换成你仓库里的真实脚本:
## Tests as the definition of done
- For new behavior and regression fixes, follow red → green → refactor.
- RED: add or extend one failing test first. Run the focused command.
Do not edit production code in this step. Paste the failing test name
and assertion. A compile or import error is not a valid red.
- GREEN: change only production code. Make the smallest change that
turns that test green. Do not edit, delete, skip, or weaken tests,
and do not rewrite fixtures to match the implementation.
- REFACTOR: only after the focused tests are green. Do not change
test files. Rerun the same command and paste the result.
- Never mark work complete from a verbal “tests passed”. Record the
exact command, exit code, and a short pass/fail excerpt.
- Do not start the next behavior until the current cycle has evidence.
本轮要锁哪一个行为、哪一份测试文件和哪一条命令,仍要写在当条提示里。AGENTS.md 管“每次都成立的规矩”,提示管“这一轮的合同”。
分三轮写提示,不要把红绿重构揉进一句“顺便都做了”
下面三轮提示是可抄骨架,命令和路径按项目替换。分轮的好处是每一轮的可写范围不同,模型更难在写测试时偷偷把实现做完,也更难在修实现时把断言改松。第三方作者 Easton 在 2026 年 7 月的公开实践里用的也是这套分相锁文件的写法,官方 Cookbook 则把 red/green/refactor/verification 写进阶段计划。两者对齐的是节拍,Easton 文里的具体提示不是 OpenAI 产品功能名。
红轮|只改测试,禁止动产品代码
Read AGENTS.md and the existing tests for 【模块】. Do not edit production code.
Behavior under test:
【一句话:例如 支付超时后最多重试 2 次,第三次仍失败则返回 PAYMENT_TIMEOUT】
Test file (create or extend, one behavior only):
【tests/payments/retry.test.ts 或仓库里的等价路径】
Command (must actually run):
【例如 npm test -- tests/payments/retry.test.ts】
Tasks:
1) Write or extend ONE test that fails for the right reason against the current code.
2) Run the command above.
3) Stop with: test file path, the exact command, exit code, failing test name,
and the assertion excerpt. If it failed because of compile or import errors,
fix only the test setup and rerun; do not touch production code.
4) Do not implement the behavior in this turn.
红轮结束,你要看见失败输出。没贴红灯,就还没取得改产品代码的门票。
绿轮|只改产品代码,禁止改测试
The red test is in place. Do not modify test files, fixtures, or snapshots.
Production paths you may edit:
【src/payments/** 等允许列表】
Make the smallest production change that turns the same test green.
Then run the same command:
【同一条测试命令】
Stop with:
1) the exact command, exit code, and passing summary;
2) the list of changed files;
3) confirmation that test files were not modified.
If the test is still red, fix production code only. Do not weaken the test.
Do not start refactoring in this turn.
绿轮结束,先看 diff。测试文件出现在变更列表里,这轮就作废,回到红轮的测试原文再跑。
重构轮|必须已经绿,再整理结构,并重跑同一组测试
Focused tests are green. Refactor production code only, without changing behavior.
Allowed: rename for clarity, remove duplication, extract helpers.
Not allowed: new behavior, test-file edits, dependency upgrades, lockfile changes.
Afterward, rerun:
【同一条测试命令,必要时再加包级测试】
Stop with the command, exit code, passing excerpt, and changed file list.
If a test goes red, revert or fix the refactor; do not edit tests to recover green.
Cookbook 写过:重构只在批准的行为与范围保持不变时才允许。测试又红了,说明这轮已经不是重构,要么撤回,要么把它当成新的行为,重新走红轮。
完成时要交的证据,以及你自己点的几下
官方把 issue 做成可测 PR 的手递模板,要求每条验收标准都指向测试或其他证据,写明命令、结果和被测到的提交或工作区状态;未跑的检查单独列出,不能写成通过。消费端可以压成这一小段,让模型按这个格式收尾:
### Test results
- Command:
- Exit code:
- Excerpt (fail or pass):
- Tested state (branch / commit / working tree):
### Changed files
- Production:
- Tests (must be empty in green and refactor turns):
### Remaining risk
- Untested cases or checks not run:
模型自称完成后,你再点这六下:
- 红轮是否贴出过失败输出,并且失败在预期断言,而不是编译报错?
- 新测试是不是就在锁这个行为,而不是一条无关的绿条?
- 绿轮的
git diff --stat是否没改测试文件、夹具和快照? - 有没有新增 skip、only,或把精确断言改松?
- 重构是否发生在绿之后,并且同一条命令又跑过一遍?
- 报告里的命令和摘录,是观察结果,还是把计划原文抄过来了?
任一项对不上,就不合并。让它回到对应那一轮,不要在同一条已经跑偏的对话里“再修一下试试”。
真实用户诀窍/反例
- 诀窍:红灯是改产品代码的门票。 没看到失败输出,就不进入绿轮。
- 诀窍:红要红在断言上。 第三方实践特别提醒,模块找不到或编译失败,只能说明测试还没站稳,不能证明它抓住了目标行为。
- 诀窍:一次只锁一个行为。 并行堆多条新红,diff 会缠在一起,假绿更难查。
- 诀窍:绿轮把测试文件设为禁区。 实现过不了,只许改产品代码。
- 诀窍:重构轮不再发明新行为。 新行为回去走红轮,另开一条合同。
- 反例:一句“实现功能并补测试”把三轮揉在一起。 常见结果是实现和测试一起写完,你没见过红,也不知道测试会不会抓旧行为。
- 反例:只接受“测试已经过了”这六个字。 Best practices 的常见错误之一,就是没告诉模型该怎么跑构建和测试;你也别接受没有命令和摘录的完成报告。
- 反例:为了绿去改断言、给用例加 skip,或改掉夹具。 官方在可测 PR 用例里写明,不要靠删断言或放宽检查换绿。
- 反例:把本篇当成“允许路径清单”或“Review→Repair→Validate”的重复。 路径合同管改哪里,修复闭环管多轮找问题;本篇管的是测试文件本身就是完成定义。
适用边界
- 本稿覆盖:在本地仓库用 Codex CLI 或 IDE 里的 Codex,为新行为或回归修复写“先红后绿再重构”的提示,并把测试文件当作完成合同。不保证某一版本的斜杠命令或按钮文案长期不变,以你客户端现页和
codex --help为准。 - 探索性原型、一次性脚本、还没有稳定测试框架的仓库,不太适合把这套纪律跑满。可以先补最小的可观察检查,再谈严格分轮。
- 本流程不替代代码审查和 CI。本地绿了,还要看 diff 和必要的状态检查;官方可测 PR 用例也把未跑过的检查单独列出。
- 生产热修、不可逆数据操作,以及密钥与部署,仍须独立审批和沙箱纪律。测试变绿不等于允许自动提交或发布。
- Easton 文中的分相提示和假绿对照是公开实践,不是 OpenAI 官方功能开关。Cookbook 里的
harness/build等文件也是可选约定,不是 Codex 自动要求的目录。