用途
修 Bug 不是把报错文字藏起来,而是完成一条证据链:固定现象,收集日志,写出修复前会失败的测试,定位根因,做最小修复,跑回归测试,最后审查 diff。 本页只用一个案例贯穿:用户会话过期后刷新页面,POST /api/session/refresh 返回 500。产品约定的正确行为是:有效刷新令牌返回 200;过期或撤销令牌返回 401 和 SESSION_EXPIRED;客户端收到该响应后清理会话并跳转登录页;不改变公开路由、有效响应,也不把令牌写入日志。
本文假定项目使用 Node.js、npm、Vitest 和 Git。实际框架、目录和脚本以仓库为准;先看 package.json,不要为了照抄示例而新增测试框架或创建平行实现。
完成标准
一次合格的修复要能回答:- 谁在什么环境下遇到了什么现象?
- 哪些确定步骤可以重新触发?
- 日志哪一行提供了调用位置,哪一行只是症状?
- 哪个测试在修复前失败,并表达了用户可观察的契约?
- 哪个状态或数据假设被违反,才是根因?
- 为什么这组改动是最小修复?
- 原失败测试、相关测试和工程检查是否通过?
- diff 是否只有目标实现、测试和必要文件?
案例上下文
用户报告:登录后放置超过一小时,再打开订单页,Network 面板显示:1. 先建立安全检查点
检查目录、分支和工具
在项目根目录执行:git status 已有他人或其他任务的改动,记录文件名,不要使用 git reset --hard 或 git restore . 清理它们。
工作区干净且团队流程允许时,可以先打检查点:
先只读调查
启动 Codex:git status、git diff,让它撤回调查改动或切到只读模式。
2. 把现象写成复现配方
“登录后有时失败”不是复现步骤。复现配方必须包含初始数据、操作顺序、实际输出和期望输出。时间相关问题使用固定时钟或固定过期时间,不要在测试中真的等待一小时。 先查看脚本,不要盲目安装依赖:session-service.ts 抛出异常,当前错误处理器把它包装成 500。无法复现时不能直接修,转到“环境与数据问题”。
3. 用日志取证
日志要帮助确认:是否进入正确路由;令牌被判断为有效、过期、撤销还是未知;数据库返回null、undefined 还是连接异常;错误发生在哪个调用点;错误处理器如何映射;是否泄露秘密。
让 Codex 区分证据和假设:
refreshSession 发生了 TypeError,但还不能单独证明查询为空的原因。候选原因包括过期令牌、用户被删除、数据库连接故障或 schema 不一致。堆栈行号是坐标,不是根因。
若日志出现下列内容,先遮盖后再交给 Codex:
4. 先写修复前失败的测试
没有失败测试,Codex 可能只让 500 消失。先让它阅读已有测试的 fixture、请求工具、时钟和断言风格:git diff 和测试日志确认。
测试应表达契约,而不是实现行号:
5. 根据调用链定位根因
让 Codex 对每一步列文件、函数、输入、输出和异常:session.id 抛出通用 TypeError,统一错误处理器没有识别领域状态,于是返回 500。根因不是“加一个 try/catch”。
再排除相邻原因:
6. 环境与数据问题
无法复现不等于代码没有问题。先比较以下项目:
启动失败时先运行:
expiresAt、revokedAt、jti 和时区即可,不要记录真实令牌。
7. 提出并实施最小修复
根因有证据后,先让 Codex 规划边界:200 加空 token,这会让客户端误以为刷新成功。
确认方案后输入:
8. 审查 diff
先看范围:- 空结果判断是否早于
session.id? - 只有明确 session 状态才返回 401 吗?
- 数据库异常仍为 500 吗?
- 有效 token 响应是否完全保持?
- 是否改变 JSON、路由或客户端依赖?
- 是否输出令牌、Cookie 或完整用户对象?
- 测试是否真的控制了过期时间?
- 是否夹带重命名、格式化或重构?
9. 分层验证
原失败测试
重新运行修复前的同一条命令:相关测试和工程检查
再运行仓库已有的相关测试:npm run 并报告“未提供”,不要把命令不存在算成代码失败。相关场景至少应覆盖:
手工验收
本地服务可安全启动时:10. 失败分支
选错文件
若 Codex 改了请求链路不会经过的旧模块:只加 try/catch
若数据库断开也变成 401:测试绿但没复现
检查 mock 是否绕过生产分支、过期时间是否生效、请求是否命中路由、断言是否只检查“有响应”。让测试在修复前重新运行,必须能失败才能证明它锁住了 Bug。环境失败
端口占用、缺少原生模块、数据库连接失败或 Node 版本不兼容先记录为环境失败:扩大成重构
11. 最终验收与交付
执行:- 目录、分支和既有用户改动正确保留。
- 原始现象有可复制步骤。
- 日志已脱敏,没有令牌和个人数据。
- 回归测试在修复前确实失败。
- 根因与调用链、错误类型和失败输出一致。
- 只改变必要状态分支。
- 有效 token 行为没有改变。
- 过期 token 返回
401 SESSION_EXPIRED。 - 数据库异常没有被吞成 401。
- 原失败测试、相关测试和可用的 lint/build 已通过。
-
git diff --check通过,文件范围可解释。 - 没有提交、推送或访问生产服务。
可直接使用的 Codex 输入
小结
参考/codex/14-workflows.md、参考/codex/06-first-task.md、参考/codex/13-prompting.md。