Codex 改完代码,我不会先看写得漂不漂亮,而是先核对这 4 件事
前两篇完成了组件修改前的准备:先查调用链,再从用户行为、公开契约、状态、副作用和生命周期等层面划清影响范围。
现在 Codex 已经完成修改,终于到了看代码的时候。
这一步很容易陷入一个习惯:从第一行差异开始读,看看变量名好不好、函数拆得是否合理、写法是否优雅。
我现在不会这样开始。
AI 生成的代码往往足够像一份正常实现。命名完整、分支齐全、注释合理,甚至比原项目更整齐。如果审查从“写得像不像好代码”开始,我很容易顺着实现思路往下读,却忘了更重要的事情:
这是不是我要求修改的那一组差异;
每一处变化是否都能对应需求;
原本要求保持不变的行为有没有被改变;
所谓完成是否有真实证据。
所以我审查 Codex 的前端改动时,先核对 4 件事:
审查对象到底是哪一批差异;
每处修改为什么必须存在;
修改后的行为是否真的正确;
完成结论由什么证据支撑。
代码风格和局部写法要看,但它们不应该抢在任务正确性之前。
第一件事:先固定审查对象,不让差异范围含糊
“请审查刚才的修改”听起来很明确,在真实工作区里可能并不明确。
当前目录中可能同时存在:
Codex 本轮修改;
我之前尚未提交的修改;
格式化工具产生的变化;
生成文件;
其他任务留下的文件;
暂存和未暂存的不同版本;
新增但尚未跟踪的文件。
如果不先固定审查范围,我可能把用户原有改动误认为 AI 越界,也可能漏掉 Codex 新增但没有进入预期差异的文件。
OpenAI 的 Codex 代码审查文档把审查范围明确区分为相对基础分支、未提交修改、指定提交和自定义范围,并提醒审查视图反映的是仓库状态,不只包含 Codex 自己编辑的内容。
这对我最大的提醒是:
审查不是“看看现在有什么变化”,而是明确“当前结论针对哪一批变化”。
我会先记录四项范围信息
# 本次审查范围 - 对比基线: - 包含的文件: - 明确排除的已有修改: - 新增、删除、重命名和生成文件:
对比基线可以是任务开始前状态、基础分支、某个提交或本轮修改,具体取决于当前工作流。关键是审查结论和基线一致。
先看文件级变化,不急着钻进代码
我会先扫一遍:
修改了多少文件;
哪些是新增、删除或重命名;
是否出现计划外目录;
是否有大面积格式变化;
是否有依赖、配置、锁文件或生成文件变化;
是否存在任务说明里没有提到的公共模块。
这一轮的目标是发现“范围形状”异常。
比如任务只要求调整一个页面交互,差异里却出现公共请求层、全局样式和依赖锁文件。即使每一处改动都有解释,我也会先暂停,要求说明它们为什么是完成当前目标的必要条件。
第二件事:把每处差异映射回任务目标
固定范围后,我不会立刻评价实现好坏,而是先问:
这一处变化对应哪个需求结果?
我会把差异分成四类。
目标变化
直接实现用户要求的行为。例如新增筛选入口、调整事件负载、处理失败恢复。
必要支撑
不是用户直接看到的结果,但为目标变化提供契约、类型、状态或验证支持。
兼容调整
为了保持既有调用方和旧行为,需要补充的适配。
无关变化
与当前目标没有必要关系的重命名、抽取、格式化、依赖升级、样式整理或技术债修复。
一份可信差异应该能解释前三类,并主动剔除第四类。
我使用一张差异映射表
| 文件或差异块 | 变化类型 | 对应目标 | 为什么必要 | 验证方式 |
|---|---|---|---|---|
| 页面入口 | 目标变化 | 用户可以触发新行为 | 直接实现入口 | 页面操作 |
| 组件事件类型 | 必要支撑 | 父页面取得新结果 | 保持契约清楚 | 类型检查与调用方检查 |
| 包装组件适配 | 兼容调整 | 上层调用继续工作 | 事件需要透传 | 包装链回归 |
| 无关工具函数重构 | 无关变化 | 无 | 当前任务不需要 | 应移出本次差异 |
这张表能暴露两种问题。
第一种是遗漏:任务目标没有任何差异对应,说明实现可能只覆盖了部分路径。
第二种是越界:差异块找不到目标或必要支撑,只能用“顺手优化”解释。
第三件事:按行为路径检查正确性,不按代码顺序检查
逐行读代码当然重要,但前端正确性更适合沿用户路径检查。
我会先把任务拆成几条场景:
正常路径;
失败路径;
边界输入;
连续操作;
关闭、返回和重新进入;
权限或条件分支;
与既有行为的回归路径。
然后沿每条路径读差异。
例如一个表单提交修改,我不会只看submit函数是否写得合理,而会沿下面的顺序看:
用户输入 → 校验 → 按钮状态 → 请求参数 → 成功处理 → 列表或详情刷新 → 关闭与清理
失败路径则是:
用户输入 → 校验通过 → 请求失败 → Loading 恢复 → 输入保留或恢复 → 错误反馈 → 是否可重试
代码可能分散在页面、组件、状态和请求层,但用户路径是连续的。
正确性不等于“代码能执行”
我会检查:
状态来源是否仍然唯一;
参数转换是否符合接口契约;
事件触发时机是否与调用方一致;
成功和失败是否对称收尾;
旧请求是否可能覆盖新状态;
默认值和空值是否改变含义;
权限和可见性是否在正确层处理;
关闭、卸载和返回时是否残留状态。
类型正确、语法正确和构建通过,只能覆盖其中一部分。
把“看起来合理”换成可反驳的问题
比如不要只问:
这个 Loading 处理合理吗?
而是问:
请求失败时它在哪个分支恢复?
连续点击是否可能产生第二次请求?
关闭弹窗后请求返回,会更新哪一份状态?
同一页面的其他动作是否共用这个 Loading?
问题越具体,越容易找到差异中的真实缺口。
第四件事:检查完成证据,而不是接受实现说明
Codex 的交付说明可能会列出:
已增加某功能;
已处理某边界;
已运行某检查;
已完成相关修改。
这些是过程陈述,不自动等于完成证据。
我会把证据分成五类:
差异证据
实际修改是否与计划和影响范围一致,有没有计划外文件和无关变化。
静态证据
类型、Lint、构建和其他项目检查是否运行,它们覆盖哪些文件和规则。
测试证据
哪些已有测试运行,哪些新增或调整;测试证明了哪个行为,哪些路径仍未覆盖。
页面证据
目标页面是否真实运行,正常、失败、连续操作和生命周期路径是否验证。
未验证说明
当前环境无法确认什么,为什么无法确认,需要谁在什么条件下继续检查。
如果 Codex 只说“测试通过”,我还会问:运行的是什么测试、是否覆盖本次变化、有没有跳过、失败后是否修正并重新运行。
完成结论只能覆盖证据实际到达的范围。
我审查一批前端差异的顺序
把前面四件事连起来,我通常按下面顺序执行。
第一步:恢复任务基线
重新读取目标、允许范围、禁止项、调用链、影响范围和验收标准。
没有基线,审查只能变成个人代码偏好。
第二步:固定差异范围
确认对比基线、文件状态、新增删除以及与用户已有改动的边界。
第三步:扫文件级异常
查计划外文件、公共模块、依赖配置、大面积格式化和生成内容。
第四步:建立目标映射
让每个需求结果对应到差异,让每个差异说明存在理由。
第五步:沿行为路径读代码
先正常、失败和边界,再检查连续操作、生命周期和回归。
第六步:复查完整差异
局部修正以后重新看全量,防止不同修改块组合后产生新问题。
第七步:核对验证证据
明确已通过、未通过和未验证,不能用实现完成代替验收完成。
一个方法演示:为什么局部正确仍然可能整体错误
下面仅用于说明审查思路,不代表真实项目经历。
假设目标是:保存成功后刷新当前列表,并保留筛选条件和页码。
Codex 修改了弹窗组件:
保存成功后触发事件;
关闭弹窗;
重置表单;
父页面收到事件后刷新列表。
每个差异块单独看都合理。
沿行为路径审查时,却可能发现顺序是:
保存成功 → 关闭并清理当前编辑对象 → 触发 saved 事件 → 父页面读取已被清理的上下文 → 刷新时回到默认查询状态
问题不在某一行语法,而在多个合理动作组合后的时序。
如果我只逐文件看“弹窗是否正确”“父页面是否正确”,很可能漏掉;沿完整用户路径看,问题会直接暴露。
审查意见也要有质量标准
我不会给 Codex 留这种意见:
这里不够优雅;
这个写法不太好;
建议再优化一下;
注意边界情况。
它们没有说明问题发生在哪里,也没有说明什么结果才算修好。
一条可执行审查意见至少包含:
问题 + 触发条件 + 影响 + 证据 + 修正边界
例如:
问题:关闭弹窗时先清理了当前记录,saved 事件随后才触发。 触发条件:保存成功且父页面依赖当前记录刷新局部数据。 影响:父页面拿不到正确标识,可能退回全量刷新或刷新错误对象。 证据:组件关闭分支与事件触发顺序,以及父页面监听逻辑。 修正边界:保持事件名称和父页面查询状态不变,只调整成功路径的触发与清理顺序,并回归失败和主动取消路径。
这样的反馈才能直接进入下一轮修正和验证。
哪些信号说明差异还不能接受
审查基线不清楚;
存在无法归属的新增文件;
需求目标没有对应差异;
差异只能用“顺手优化”解释;
公共契约变化没有调用方检查;
正常路径正确,失败和生命周期没有收尾;
类型和构建通过,但页面行为未验证;
修复一处后没有重看完整差异;
交付说明把未运行的检查写成完成;
无法区分 AI 修改与用户原有改动。
任何一项成立,我都会把任务保持在“待审查”或“待验证”,而不是因为代码已经写完就进入交付。
写在最后
我审查 Codex 的前端代码,不从“写得漂不漂亮”开始,而是先核对:
当前审查的是哪一批差异;
每处变化能否映射到任务目标;
正常、失败、边界和生命周期行为是否正确;
完成结论是否有对应证据。
代码审查不是欣赏实现,而是用任务基线反驳实现中的错误假设。
下一篇我会把这一套审查顺序压缩成一张前端差异检查清单,分别从正确性、修改范围和副作用三个层面列出具体问题,并给出审查结论和反馈模板。
本系列持续更新。接下来会用这张清单把“看代码”变成可重复执行的验收动作,为后面的静态检查、单测和页面验证分工做准备。
参考资料
OpenAI Codex 文档:代码审查范围、优先级发现和行级反馈
OpenAI Codex 用例:复杂任务应以可审查产物和评估方式推动迭代
