很多开发者第一次使用 ChatGPT Plus / Pro + Codex 排查 Bug,最常见的方式还是:
text
把报错复制给 AI
↓
问:
这个错误怎么解决?
对于简单错误,这样完全没问题。
例如:
text
TypeError: Cannot read properties of undefined
或者:
text
ModuleNotFoundError
AI 通常很快就能给出方向。
但真正进入生产项目以后,我们遇到的 Bug 往往不是这样。
真实问题更可能是:
text
订单偶尔重复创建
或者:
text
支付成功了,
但订单仍然显示待支付
或者:
text
只有部分用户登录失败
甚至:
text
线上偶发 500,
本地完全无法复现
这种问题最大的特点是:
错误现象和真正 Root Cause 往往相距很远。
例如:
text
Frontend 报错
↓
实际是 Backend 返回异常
↓
Backend 异常
↓
实际是 Database Transaction rollback
↓
Transaction rollback
↓
实际是某个 webhook 重复执行
所以真正的软件 Debug 从来不是:
text
看到 Error
↓
修改报错这一行
而更接近:
text
Symptom
↓
Evidence
↓
Timeline
↓
Call Chain
↓
Hypothesis
↓
Reproduction
↓
Root Cause
↓
Fix
↓
Regression Test
这也是 Codex 非常适合参与的一类工程任务。
因为 Debug 本质上需要大量:
- 搜索;
- 读取;
- 比较;
- 跟踪调用;
- 运行测试;
- 分析日志;
- 检查最近修改;
- 不断验证假设。
这些恰恰非常适合 Coding Agent。
一、Debug 最忌讳的事情:看到报错就修改代码
例如线上日志:
text
TypeError:
Cannot read properties of undefined
reading 'id'
at OrderService.createOrder
很多人看到以后会直接让 Codex:
text
修复这个 undefined 错误。
AI 很可能改成:
typescript
if (!user) {
return;
}
或者:
typescript
const userId = user?.id;
错误消失了。
但是问题真的解决了吗?
不一定。
真正应该问的是:
text
为什么 user 会是 undefined?
可能是:
text
Authentication Middleware
没有执行
或者:
text
Session Cache
读到了过期数据
甚至:
text
某条 Internal API
绕过了正常 Authentication Pipeline
如果只是:
typescript
user?.id
那么实际上是:
text
隐藏异常
而不是:
text
修复 Root Cause
所以 Debug 第一原则应该是:
不要把 Error Message 当 Root Cause。
二、建议 Codex 使用 Investigation First
遇到线上 Bug,第一条 Prompt 最好不要是:
text
帮我修。
而是:
text
先调查,不要修改任何代码。
例如:
markdown
# Incident
线上偶发:
TypeError:
Cannot read properties of undefined (reading 'id')
位置:
OrderService.createOrder
# Requirement
先不要修改代码。
请调查:
1. createOrder 的调用入口;
2. user 从哪里获取;
3. Authentication 如何注入 user;
4. 哪些调用路径可能没有 user;
5. 相关测试;
6. 最近是否修改过 Authentication 或 Order;
7. 是否可能由异步任务调用。
最后输出:
- 调用链;
- 可能 Root Cause;
- 每个假设的证据;
- 下一步如何验证。
这样 Codex 的第一阶段就是:
text
Read
Search
Trace
Compare
而不是:
text
Edit
三、Debug 可以理解成"假设搜索"
一个 Bug 刚出现时,我们往往不知道原因。
比如:
text
支付成功,
订单没有变成 PAID。
最开始可能有五种假设:
text
H1:
支付 Webhook 没有收到。
H2:
Webhook 收到,但验证失败。
H3:
Payment 更新成功,
Order 更新失败。
H4:
数据库更新成功,
Cache 没刷新。
H5:
Backend 正常,
Frontend 读的是旧数据。
Debug 的过程其实就是:
text
Hypothesis
↓
Evidence
↓
Reject / Confirm
最后逐步减少:
text
5 个假设
↓
3 个
↓
2 个
↓
1 个 Root Cause
Codex 很适合帮助完成这个过程。
四、让 Codex 明确维护 Hypothesis List
可以输入:
text
针对这个 Bug,
不要直接给一个原因。
列出 3-5 个最可能假设。
每个假设包含:
- 为什么可能;
- 支持证据;
- 反对证据;
- 如何验证;
- 当前置信度。
每拿到新证据后更新假设列表。
例如:
text
H1 Webhook 未收到
Confidence: 20%
Evidence Against:
日志存在 payment_webhook_received
H2 Webhook 重复处理
Confidence: 60%
Evidence:
同一个 event_id 出现两次
H3 Cache stale
Confidence: 20%
Evidence:
DB 中订单已经 PAID
API 返回仍然 PENDING
这样 Agent 不容易:
text
第一眼看到什么
↓
就认定什么
五、日志是 Debug 最重要的 Runtime Context
代码告诉你:
text
系统理论上应该怎么运行
日志告诉你:
text
系统实际上发生了什么
这是完全不同的两种 Context。
假设代码设计:
text
Payment
↓
Order
↓
Inventory
但日志:
text
10:00:00 payment received
10:00:00 order updated
10:00:01 payment retry received
10:00:01 order updated again
10:00:01 inventory deducted again
立刻能看到:
text
Webhook Retry
↓
没有幂等保护
这比单纯读代码更容易发现 Root Cause。
六、日志一定要结构化
差的日志:
text
payment success
好一点:
text
payment success order=123
更好的:
json
{
"event": "payment_succeeded",
"order_id": "ord_123",
"payment_id": "pay_456",
"provider_event_id": "evt_789",
"trace_id": "trace_abc",
"timestamp": "..."
}
对于 Codex 来说,后者非常有价值。
因为它可以通过:
text
order_id
payment_id
event_id
trace_id
把不同系统的日志串起来。
七、Trace ID 是线上 Debug 的神器
一个用户请求可能经过:
text
API Gateway
↓
Order Service
↓
Payment Service
↓
Inventory Service
↓
Database
↓
Message Queue
如果每一个地方的日志都有:
text
trace_id=abc123
那么 Codex 可以搜索:
text
abc123
得到完整 Timeline:
text
10:31:04.001
API request received
10:31:04.020
Order created
10:31:04.040
Inventory reserved
10:31:04.100
Payment request started
10:31:05.300
Payment timeout
10:31:05.350
Order rollback
10:31:06.100
Payment webhook succeeded
10:31:06.200
Order not found
这个 Timeline 几乎直接解释了 Bug。
八、推荐让 Codex 先生成 Timeline
对于分布式系统 Bug,可以输入:
text
根据这些日志构建事件时间线。
按时间排序。
每一行包含:
- timestamp
- service
- event
- request/order/payment id
- trace id
- result
然后指出:
1. 第一个异常点;
2. 后续异常是原因还是结果;
3. 哪一个事件最可能导致最终用户看到的问题。
这比直接问:
text
日志有什么问题?
更有效。
九、Exception Stack Trace 不应该只看最后一行
例如:
text
DatabaseError
at OrderRepository.save
at OrderService.create
at CheckoutService.checkout
at CheckoutController.post
很多人只看:
text
OrderRepository.save
然后开始检查 SQL。
但真正重要的是:
text
整条调用链
例如:
text
CheckoutController
↓
CheckoutService
↓
OrderService
↓
OrderRepository
Codex 可以进一步搜索每一层:
text
Controller 传入什么?
Service 是否修改数据?
Transaction 在哪开始?
save 前状态是什么?
十、让 Codex 做 Stack Trace Mapping
一个很实用的 Prompt:
text
把这个异常堆栈映射回代码仓库。
对于每一个 Stack Frame:
1. 找到对应文件;
2. 找到对应函数;
3. 说明它在调用链里的职责;
4. 找出输入来自哪里;
5. 找出可能异常条件。
最后输出:
Request
→ Controller
→ Service
→ Repository
→ Failure Point
这非常适合陌生项目。
十一、Source Map 和生产堆栈也很重要
前端生产环境经常看到:
text
at a (main.8f72c.js:1:38291)
基本不可读。
如果项目有 Source Map,就可以还原成:
text
src/features/cart/useCheckout.ts
line 84
对于 AI Debug 来说:
text
可读 Stack Trace
本身就是高质量 Context。
所以 Agent-Friendly 的生产系统不仅是:
text
代码仓库适合 AI
还包括:
text
Observability 适合 AI
十二、Git 是 Debug 的另一个超级 Context
当一个 Bug:
text
昨天还没有
今天突然出现
非常重要的问题就是:
text
最近改了什么?
Codex 可以:
bash
git log --oneline -20
然后:
bash
git diff <good_commit>..<bad_commit>
这就是经典:
text
Regression Analysis
十三、先找"Good"和"Bad"
例如:
text
版本 v1.8.3
正常
版本 v1.8.4
出现 Bug
那么 Search Space 就从:
text
整个代码仓库
缩小成:
text
v1.8.3 → v1.8.4
之间的 Diff
假设只有:
text
17 个 Commit
问题瞬间简单很多。
十四、让 Codex 做 Regression Diff Analysis
Prompt:
text
这个 Bug 在 v1.8.3 不存在,
v1.8.4 开始出现。
先不要修改代码。
检查这两个版本之间的 Git Diff。
重点寻找和以下模块相关的修改:
- checkout
- payment
- transaction
- inventory
输出:
1. 可疑 Commit;
2. 为什么可疑;
3. 修改前行为;
4. 修改后行为;
5. 如何验证是不是该 Commit 引入。
这对线上 Regression 特别好用。
十五、Git Bisect + Codex 是非常强的组合
如果:
text
Good Commit
和:
text
Bad Commit
之间有:
text
500 个 Commit
手工看 Diff 很麻烦。
可以用:
bash
git bisect
二分查找。
流程:
text
500 commits
↓
250
↓
125
↓
62
↓
31
↓
...
很快就能定位引入 Bug 的 Commit。
十六、如果有自动复现测试,Bisect 会更强
例如有脚本:
bash
npm test -- checkout-regression
结果:
text
0
=
正常
非 0
=
Bug
就可以自动:
text
git bisect run
这时候 Codex 能把:
text
代码搜索
+
Git
+
自动测试
结合起来。
这已经是非常强的 Agent Debug Workflow。
十七、线上 Bug 最重要的能力之一:Reproduce
如果无法复现:
text
Fix 很难验证
例如:
text
偶尔重复创建订单
如果只是:
text
看代码
↓
猜一个地方
↓
修改
风险很高。
最理想:
text
先构造一个失败测试
十八、Bug Fix 的标准流程
推荐:
text
Production Incident
↓
Collect Evidence
↓
Reproduce
↓
Regression Test FAIL
↓
Root Cause
↓
Minimal Fix
↓
Regression Test PASS
↓
Existing Tests
↓
Review
可以直接告诉 Codex:
text
不要先修改生产代码。
第一目标是构造稳定复现。
成功复现以后:
1. 保留 Regression Test;
2. 确认修复前测试失败;
3. 再修改代码;
4. 修复后确认通过。
十九、为什么 Regression Test 比"我试了一下"更重要?
因为线上 Bug 最怕:
text
今天修好
↓
两个月以后又出现
Regression Test 相当于:
text
把这次事故变成永久知识
以后任何修改重新触发:
text
CI FAIL
这就是:
text
Incident
↓
Executable Knowledge
二十、一个真实示例:订单重复创建
假设线上反馈:
text
部分用户点击一次结算,
偶尔产生两个订单。
先不要猜:
text
用户点了两次
因为也可能是:
text
HTTP Retry
Load Balancer Retry
Mobile Network Retry
Frontend Double Submit
Backend Timeout Retry
二十一、先收集证据
Codex 调查:
text
两个订单:
ord_1001
ord_1002
user_id 相同
cart_id 相同
金额相同
创建时间相差 80ms
日志:
text
request_id=req_a
checkout_session=chk_1
request_id=req_b
checkout_session=chk_1
这说明:
text
确实有两个 HTTP Request
但还不能说是用户双击。
二十二、接着检查 API Idempotency
代码:
typescript
async function checkout(sessionId: string) {
return createOrder(sessionId);
}
没有:
text
Unique Constraint
Idempotency Key
Existing Order Check
两个请求同时进来:
text
Request A
查询:
没有订单
Request B
查询:
没有订单
A create
B create
于是:
text
Duplicate Order
这就是 Race Condition。
二十三、为什么简单"先查再创建"不够?
代码:
typescript
const existing = await findOrder(sessionId);
if (!existing) {
await createOrder(sessionId);
}
看起来已经防重复。
但并发:
text
A find → null
B find → null
A insert
B insert
仍然重复。
这就是:
text
Check-Then-Act Race Condition
Codex Debug 时应该主动检查:
text
这个判断是否原子?
二十四、真正 Fix 可能在 Database Constraint
比如:
sql
UNIQUE(checkout_session_id)
然后:
text
第一次 INSERT
成功
第二次 INSERT
违反 Unique Constraint
再由 Service:
text
读取已有订单
这种实现通常比:
text
只靠前端 disabled button
可靠很多。
二十五、Regression Test 应该模拟并发
不是:
text
连续调用两次
而是:
text
同时调用
例如测试概念:
text
session = same
request A
request B
run concurrently
assert:
只存在一个 order
这才能真正覆盖 Root Cause。
二十六、第二个示例:支付成功但订单仍然待支付
现象:
text
Payment Provider
显示 Success
用户订单:
PENDING_PAYMENT
可能假设:
text
Webhook 没收到
Signature Verification Failed
Order Update Failed
Transaction Rollback
Cache Stale
Event Lost
二十七、通过 Trace 缩小问题
日志:
text
payment_webhook_received
signature_verified
payment_updated
order_mark_paid
transaction_commit
数据库:
text
orders.status = PAID
但是 API:
json
{
"status": "PENDING_PAYMENT"
}
这时候:
text
Backend 写数据库
显然已经成功。
问题范围缩小:
text
Read Path
而不是:
text
Write Path
二十八、继续追 getOrder()
调用链:
text
GET /orders/:id
↓
OrderService.get()
↓
Redis
↓
PENDING_PAYMENT
发现:
text
markPaid()
更新数据库以后:
text
没有 invalidate cache
Root Cause:
text
Stale Cache
这个例子非常典型。
如果一开始只看 Payment Webhook:
text
可能折腾半天都找不到。
二十九、Debug 应该区分 Write Path 和 Read Path
很多数据问题都应该问:
text
写进去了吗?
读出来对吗?
例如:
text
DB 正确
API 错误
说明:
text
Read Path
有问题。
如果:
text
DB 就错误
说明:
text
Write Path
需要继续调查。
这个简单分层非常有效。
三十、第三个示例:只有部分用户登录失败
这种 Bug 很容易让人困惑:
text
大部分用户正常
5% 用户失败
此时关键问题不是:
text
登录逻辑有没有 Bug?
而是:
text
失败用户和成功用户有什么不同?
三十一、让 Codex 做 Cohort Comparison
例如:
text
对比成功用户和失败用户。
检查:
- account age
- auth provider
- password hash version
- MFA
- region
- device
- token type
- user status
- migration version
不要先改代码。
最终发现:
text
失败用户
全部是 2024 年以前创建
继续:
text
旧账号 password_hash 使用 bcrypt
新账号使用 argon2
最近代码删除了:
text
bcrypt fallback
Root Cause 直接明确。
三十二、这类 Bug 本质上是 Data-Dependent Bug
特点:
text
代码路径相同
数据不同
结果不同
所以 Debug 不应该只看代码。
还要看:
text
Input Distribution
Data Version
Migration State
User Cohort
三十三、第四类 Bug:Environment-Dependent
典型:
text
本地正常
线上失败
这时候最重要的问题:
text
环境有什么不同?
例如:
text
Node Version
Python Version
OS
Timezone
Locale
Database Version
Environment Variable
Feature Flag
Dependency Version
Network
Production Data
三十四、让 Codex 做 Environment Diff
Prompt:
text
本地无法复现,
生产环境稳定复现。
先比较环境差异。
列出:
- runtime version
- dependency lock
- database version
- timezone
- locale
- env flags
- feature flags
- infrastructure
- production-only middleware
不要假设代码一定有问题。
这个思路非常重要。
三十五、经典案例:Timezone Bug
例如本地:
text
UTC+8
生产:
text
UTC
代码:
python
date.today()
业务逻辑:
text
当天 00:00 结算
结果:
text
部分时间段
生产计算日期和用户日期不同
这种问题你只盯着业务代码,很容易找不到。
三十六、Feature Flag 也是常见原因
例如:
text
10% 用户 Bug
刚好:
text
new_checkout
=
10% rollout
那就应该立刻怀疑:
text
Feature Flag
所以 Incident Prompt 可以加入:
text
检查:
- feature flags
- experiments
- staged rollout
三十七、第五类 Bug:Concurrency Bug
最难的一类之一:
text
单线程测试正常
线上偶发失败
可能涉及:
text
Race Condition
Deadlock
Lost Update
Double Execution
TOCTOU
Lock Order
这类 Bug 很适合 Codex 做代码搜索,但一定要配合:
text
并发测试
三十八、让 Codex 主动寻找共享状态
Prompt:
text
调查这个并发 Bug。
重点检查:
- shared mutable state;
- transaction boundary;
- locks;
- unique constraints;
- check-then-act;
- read-modify-write;
- retries;
- duplicate message delivery;
- async task duplication。
标出所有可能发生竞态的位置。
三十九、消息队列系统要默认考虑"重复投递"
很多 Queue / Event 系统都应该按:
text
At-Least-Once
思维设计。
即:
text
同一个事件
可能收到两次
如果 Handler:
typescript
onPaymentSucceeded(event) {
inventory.deduct(...)
}
没有幂等:
text
重复事件
↓
重复扣库存
所以 Debug Event System 时:
text
Event ID
Idempotency
Retry
Deduplication
是必须检查的。
四十、不要忽略 Timeout
例如:
text
Client Request
↓
Backend 处理
↓
Database 成功
↓
Response 返回前网络超时
Client 认为:
text
失败
然后 Retry。
Backend:
text
再次执行
于是重复创建。
实际上:
text
第一次请求已经成功
这就是典型的:
text
Unknown Outcome Problem
需要:
text
Idempotency
解决。
四十一、Codex Debug 时应该区分 Error 和 Symptom
例如用户看到:
text
订单重复
这是:
text
Symptom
日志里:
text
UniqueViolation
这是:
text
Error
而真正原因可能是:
text
两个 Request 共用 session
但没有幂等设计
这是:
text
Root Cause
三者不能混淆。
四十二、推荐要求 Codex 输出三层结论
每次 Debug 最后输出:
markdown
## Symptom
用户观察到什么。
## Immediate Failure
系统在哪一步失败。
## Root Cause
为什么会走到这个失败状态。
这样能避免:
text
把异常堆栈最后一行
当成根因
四十三、Debug 还需要检查 Error Handling
有时候真正的 Bug 被错误处理隐藏。
例如:
python
try:
update_order()
except Exception:
pass
于是:
text
Order Update Failed
但系统:
text
继续返回 200
日志也没有。
最终用户看到:
text
状态没更新
开发者没有任何 Error。
四十四、禁止 Silent Failure
可以在 AGENTS.md 加:
markdown
# Debugging
When investigating unexpected state:
search for:
- swallowed exceptions;
- empty catch blocks;
- fallback values;
- ignored promises;
- ignored return codes.
Do not hide failures
by adding broader exception handling.
这对 Codex 很实用。
四十五、Ignored Promise 也是 JavaScript 常见问题
例如:
typescript
updateOrderStatus(orderId, "PAID");
return response;
如果:
text
没有 await
可能出现:
text
Response 已返回
Process 结束 / Error
更新未完成
应该:
typescript
await updateOrderStatus(...)
或者明确设计成异步任务。
Codex Debug Node 项目时应该主动检查:
text
missing await
unhandled promise
fire-and-forget
四十六、Python 也有类似问题
例如:
python
asyncio.create_task(update_order())
如果:
text
没有监控任务结果
异常可能完全丢失。
这类后台 Task 在生产 Debug 中非常常见。
四十七、日志量很大时,不要全部塞给 Codex
例如:
text
500MB 日志
直接全部提供不是好办法。
更合理:
text
先通过:
trace_id
order_id
user_id
error_code
时间窗口
筛选。
例如:
text
Incident:
21:00-21:05
Order:
ord_123
Trace:
abc456
只取相关日志。
这就是:
text
Log Context Engineering
四十八、先 Narrow,再 Deep Read
流程:
text
全部日志
↓
时间窗口
↓
服务
↓
Trace ID
↓
关键事件
↓
完整调用链
这和代码仓库的 Context Engineering 完全一样。
四十九、线上 Incident 可以建立标准模板
可以直接保存:
markdown
# Incident
## Symptom
用户看到什么?
## Impact
影响范围:
- users
- requests
- orders
- region
## First Seen
时间。
## Known Good
最后正常版本/时间。
## Known Bad
开始异常版本/时间。
## Evidence
- stack trace
- logs
- trace id
- request id
- screenshots
- metrics
## Investigation
Do not modify code initially.
Investigate:
1. call chain
2. recent changes
3. environment difference
4. data difference
5. concurrency
6. cache
7. external services
## Output
- timeline
- hypotheses
- evidence
- root cause confidence
- reproduction plan
五十、确认 Root Cause 后再切换 Implementation Mode
例如调查阶段结论:
text
Root Cause:
Payment Webhook
可能重复投递。
Handler 没有幂等保护。
同 event_id
可执行两次 Inventory Deduction。
这时候再输入:
text
现在进入 Implementation。
要求:
1. 增加 Regression Test;
2. 模拟同一个 event_id 处理两次;
3. 修改前测试必须失败;
4. 实现幂等保护;
5. 修改后测试通过;
6. 不改变 Public API;
7. 不增加 Redis;
8. Review Transaction 行为。
这才是高质量 Debug。
五十一、为什么 Fix 必须尽量小?
Incident 阶段最危险的是:
text
顺便重构
例如 Bug:
text
Webhook 重复处理
AI:
text
顺便把整个 Payment 模块改成 Event Sourcing
完全没必要。
线上 Bug Fix 应该优先:
text
Smallest Safe Fix
因为:
text
Diff 越大
↓
Regression Surface 越大
五十二、可以设置 Incident Change Budget
例如:
text
这是生产 Incident Fix。
预期:
2-5 files
禁止:
- framework upgrade
- dependency upgrade
- architecture rewrite
- unrelated refactoring
如果需要超过 8 个文件,
先说明为什么。
这个约束对 Codex 很有效。
五十三、Debug 完成以后要做 Git Diff Review
Prompt:
text
现在 Review 本次 Incident Fix。
对照 Root Cause 检查:
1. 修改是否真的阻断 Root Cause;
2. 是否只是隐藏 Error;
3. 是否引入新竞态;
4. 是否改变正常请求行为;
5. Regression Test 是否覆盖原始场景;
6. 是否有无关修改;
7. 是否新增 Silent Failure;
8. 是否影响 Backward Compatibility。
五十四、还要问一个关键问题:如果再次发生,我们能不能更快发现?
优秀的 Incident Fix 不只是:
text
把 Bug 修掉
还应该:
text
Improve Observability
例如这次 Debug 很难,是因为没有:
text
event_id
那就增加。
如果缺:
text
trace_id
就补。
如果异常被吞:
text
增加 Error Log
如果不知道重复:
text
增加 Counter
五十五、每一次 Incident 都应该改善系统可观测性
可以形成:
text
Incident
↓
Fix
+
Regression Test
+
Observability Improvement
例如:
text
重复 Webhook
以后增加:
text
payment_webhook_duplicate_total
Metric。
一旦异常增长:
text
马上报警
下次 Debug 就容易很多。
五十六、Debug Agent 和 Observability Agent 可以分开
复杂 Incident 可以:
text
Agent A
Code Investigation
Agent B
Logs / Trace
Agent C
Git Regression
Agent D
Database State
Agent E
Tests
全部先只读。
最后:
text
Lead Agent
整合 Timeline
+
Root Cause
这种多 Agent 调查特别适合线上复杂问题。
五十七、为什么 Debug 比 Feature 更适合多 Agent Research?
因为调查本身通常:
text
Read Heavy
Write Light
例如:
text
查日志
查 SQL
查 Git
查代码
查 Metrics
互相冲突很少。
所以:
text
Parallel Investigation
往往收益很高。
五十八、但是只能有一个 Root Cause Owner
多个 Agent 可能给出:
text
不同结论
最终应该由一个:
text
Lead
统一:
text
Evidence
而不是:
text
五个 Agent 各修一个自己怀疑的地方
否则会变成:
text
Shotgun Debugging
也就是:
text
不知道哪里错
↓
到处改
↓
看看会不会好
这是 Debug 最应该避免的方式。
五十九、不要用"Bug 消失"证明 Root Cause 正确
例如你加了:
text
sleep(100)
Bug 不出现了。
这不代表:
text
sleep 是正确修复
它可能只是改变 Timing。
并发 Bug 尤其如此。
Root Cause 必须有:
text
Causal Explanation
即:
text
为什么这个条件
一定会导致这个 Bug
以及:
text
为什么这个 Fix
阻止了这个条件
六十、让 Codex 输出 Causal Chain
例如:
text
Client timeout
↓
Client retries request
↓
Server lacks idempotency
↓
Both requests pass existence check
↓
Two orders inserted
↓
User sees duplicate orders
Fix:
text
Unique checkout_session constraint
↓
Only one insert can succeed
↓
Retry resolves existing order
↓
Duplicate impossible
这就是完整:
text
Causal Chain
六十一、一个成熟 Debug 报告应该包含什么?
建议:
markdown
# Root Cause Report
## Incident
## Impact
## Timeline
## Symptom
## Root Cause
## Causal Chain
## Why Existing Tests Missed It
## Fix
## Regression Test
## Validation
## Observability Improvement
## Remaining Risks
Codex 可以自动帮你生成这份报告。
六十二、为什么"为什么测试没发现"非常重要?
因为 Bug 能进入生产,说明:
text
系统保护层存在缺口
例如:
text
没有并发测试
或者:
text
Mock 永远不会 Retry
或者:
text
测试数据库没有旧用户数据
Incident 修复以后应该补上这个缺口。
否则:
text
同类型 Bug
以后还会出现。
六十三、把 Incident 转成永久 Guardrail
例如:
事故
text
N+1
Guardrail:
text
Query Count Test
事故
text
重复订单
Guardrail:
text
Unique Constraint
+
Concurrency Test
事故
text
旧账号无法登录
Guardrail:
text
Legacy Password Fixture
事故
text
Cache Stale
Guardrail:
text
Cache Invalidation Test
这就是工程成熟度。
六十四、推荐放进 AGENTS.md 的 Debug Rules
可以直接复制:
markdown
# Debugging Rules
For non-trivial bugs:
1. Investigate before editing.
2. Distinguish symptom from root cause.
3. Build the relevant call chain.
4. Use runtime evidence when available.
5. Check logs, traces, and recent git changes.
6. Reproduce the issue before fixing when practical.
7. Add a regression test.
8. Confirm the regression test fails before the fix.
9. Implement the smallest correct fix.
10. Confirm the regression test passes afterward.
11. Run related existing tests.
12. Review the final diff.
Do not:
- hide exceptions;
- add broad catch blocks;
- weaken tests;
- add arbitrary retries;
- add sleeps to mask race conditions;
- refactor unrelated modules during incident fixes.
Root cause claims should be supported by evidence.
这套规则非常适合 Codex 长期使用。
六十五、一个可直接复制的 Codex Debug Task Template
markdown
# Incident
描述线上现象。
# Impact
影响:
- users
- requests
- orders
- regions
# Known Good
最后正常时间或版本。
# Known Bad
开始异常时间或版本。
# Evidence
提供:
- error
- stack trace
- trace id
- logs
- metrics
- sample ids
# Investigation
Do not modify code yet.
Investigate:
1. relevant call chain;
2. runtime timeline;
3. recent git changes;
4. data differences;
5. environment differences;
6. concurrency;
7. cache;
8. external dependencies;
9. related tests.
# Hypotheses
For each hypothesis provide:
- evidence for;
- evidence against;
- confidence;
- verification step.
# Reproduction
Create the smallest reliable reproduction.
# Root Cause
Explain the causal chain.
# Fix
Implement the smallest correct change.
# Regression Test
The test must fail before the fix
and pass afterward.
# Validation
Run:
- targeted tests
- relevant integration tests
- lint
- typecheck
# Review
Check:
- regression
- race condition
- hidden error
- backward compatibility
- unrelated diff
# Final Report
Output:
1. symptom
2. root cause
3. causal chain
4. files changed
5. tests
6. observability improvements
7. remaining risks
六十六、ChatGPT Plus / Pro + Codex 真正改变 Debug 的地方是什么?
以前排查线上问题:
text
开发者
↓
翻日志
↓
搜代码
↓
看 Git
↓
看 DB
↓
写测试
↓
改代码
↓
继续跑
这其中有大量机械工作。
Codex 可以帮助承担:
text
日志筛选
调用链追踪
Git Diff 分析
Stack Trace Mapping
Hypothesis 整理
测试生成
代码搜索
Regression Review
开发者则更集中于:
text
判断证据
确认业务语义
决定修复策略
评估风险
六十七、最终 Debug Workflow
可以总结成:
text
Incident
↓
Collect Evidence
↓
Build Timeline
↓
Map Call Chain
↓
Generate Hypotheses
↓
Eliminate Hypotheses
↓
Reproduce
↓
Regression Test FAIL
↓
Root Cause
↓
Minimal Fix
↓
Regression Test PASS
↓
Existing Tests
↓
Git Diff Review
↓
Observability Improvement
↓
Human Review
这才是一套完整的:
Agentic Debugging
六十八、总结
使用 ChatGPT Plus / Pro + Codex 排查线上 Bug,最重要的不是:
text
把报错复制给 AI
而是让 Codex 进入一个完整的 Debug 闭环:
text
Evidence
+
Logs
+
Trace
+
Code
+
Git
+
Tests
+
Runtime
其中最核心的原则可以浓缩成几句话:
text
先调查,
后修改。
先复现,
后修复。
先找 Root Cause,
不要只处理 Symptom。
所有结论尽量有证据。
所有 Bug 尽量留下 Regression Test。
真正成熟的 Codex Debug Workflow,也不应该是:
AI 看到哪里报错,就自动改哪里。
而应该是:
AI 帮助开发者把一个模糊的线上现象逐步缩小成一个可解释、可复现、可验证的 Root Cause。
最终形成:
text
Human Defines Incident
Codex Investigates
Logs Provide Evidence
Tests Reproduce
Codex Fixes
System Verifies
Human Decides
当这套流程建立起来以后,ChatGPT Plus / Pro + Codex 的价值就不再只是"帮我写代码"。
它开始真正参与:
text
Incident Investigation
Root Cause Analysis
Regression Prevention
Software Reliability
而这正是 Coding Agent 从代码生成工具走向真实软件工程系统的重要一步。