和 AI 共事一个月 · 35 个踩过的坑
背景
这 20 天我的 AI 协作场景是 Claude Code:有本地 bash/文件/脚本权限、能调 MCP 服务查内网、能后台跑几小时 agent。对比纯对话式 AI,它的出错面和人工放权面都大得多 —— 一条脚本可能真的在我电脑上跑、commit 真的进本地仓、schtask 真的凌晨 3 点自动触发。
所以 35 个坑里只有极少数是 AI 幻觉 (hallucination) 这种老生常谈。更多是:
- 它能用工具 → 它把我的工具用错了
- 它有自主推进权 → 它在边界上踩过线了
- 它有上下文 → 上下文污染了它的判断
下面按这三条钩子分组、每类内按首犯日期排序。条目编号保留 1-35 原号,方便和文末的月度分布表交叉对照。
它能用工具 → 把我的工具用错了 (12 条)
AI 拉起工具调用的那一刻走偏:并行改串行、杀错进程、curl 测试判错、commit 忘 push、调 AI 工具的自身配置错位。这类坑最快被发现,因为现象是“命令失败”或“工具报错”,但代价往往不止一次失败。
1. 多文件追踪要并行读 · 不要串行 (4/20)
跨仓库追一条代码路径时,我一开始要求 AI 先看 A、再看 B、再看 C。它非常听话地串行读,10 个文件等 40 秒。实际上 Read/Grep 工具完全可以一次发 10 个并行调用,10 秒搞定。
教训:长链路追踪,提示词里就说并行读下面 N 个文件。别让它默认串行。
9. 发给用户的脚本必须本机模拟 (4/23)
AI 写了个 .bat 发给同事抓日志,本地我 Read 看了内容、语法 review 了一遍,签字放行。同事视频反馈:双击一闪而过。查了才发现 AI 用 Write 工具默认写 LF 行尾,cmd 把整个 bat 当一行,@echo off 后面的命令根本没执行。
教训:发给别人的脚本,本机用 cmd //c 真跑一遍,pause 用 stdin 注入通过。静态 review 抓不到行尾、编码、权限 token 这种运行时问题。
11. 长时间等待 30 分钟主动检查 (4/24)
我让 AI 后台跑 agent 做代码扫描。设定 2 小时,但 agent 60 分钟就卡住了,AI 没去看,傻等到我回来发现。
教训:任何后台任务/agent/等 MCP 响应,静默超 30 分钟主动查一次。
16. 不要 taskkill 用户正在跑的 Streamlit (5/2)
全量回归测试完 AI 想清理环境,跑了 taskkill //IM python.exe 一锅端。把我正在用的开发服务器也杀了。
教训:杀进程必须 PID 精确杀,用 tasklist | grep 先看清楚再动手。
17. Streamlit 回归测试 HTTP 200 不够 (5/2)
AI 的回归测试脚本只 curl / 看 HTTP 状态码,返 200 就通过。问题是 Streamlit 抛 Traceback 时错误页也返 200 —— 它把异常渲染成 HTML 显示出来。
教训:Streamlit 测试必须 grep Traceback/NameError 行数,0 行才算过。
25. commit 完就 push (5/8)
某个项目本地领先 origin/main 3 天 6 条 commit 我才发现。AI 合理化了最后再统一推。但第二天我就要在另一台设备上 pull —— 拉到的会是老版本。
教训:commit 和 push 当成同一个动作。会话末必查 git log origin..HEAD。
26. memory 只认 cwd (5/8)
这条是 Claude Code 特定的 bug (其他 AI 工具未必踩),但背后的通病值得说:Claude Code 的 project memory 目录是按 cwd 映射的。从不同路径起的 shell 写出的 memory 会进不同文件夹,两边各自更新,悄悄分叉了一段时间才被我发现。
教训:AI 工具配置的"项目目录"概念基于启动路径,不是当前命令路径 —— 工具状态按启动环境绑定是行业通病,不止一个工具这样。固定从一个 cwd 启动是底线。
30. 并行优先 + A/B/C 方案仍问
两种默认值的边界:执行性问题并行跑不问,决策性问题停下来问。
31. 长等 30 分钟主动检查
和第 11 条同一条规则的不同切面。等待是高成本行为,沉默成本翻倍。
33. 已知线程安全遗留不重复报
Code review 里有一组历史遗留问题已确认独立 patch 在排队。每次 review 都报一遍是噪声,要把豁免清单喂给 AI。
34. Memory 优先级约定 (P0/P1/P2/P3)
记忆库里每条规则/参考前缀标优先级。P0 日常必守、P1 高频踩坑、P2 低频参考、P3 短期状态。没有优先级的记忆就是一堆没索引的文本。
35. 先查 review 系统再动手
诊断 bug 前先查一下代码 review 系统有没有现成修复 CL —— 有一次我凭记忆推断要改 A 模块,AI 真去改了,结果别人早就用完全不同的思路在 B 模块修好了。
教训:AI 的直觉是从代码出发反向推,但真实修复链在 review 系统里。先查已有 CL 比凭空推理快 10 倍。
它有自主推进权 → 在边界上踩过线了 (11 条)
AI 必须回答「该不该做、做到什么程度、做完怎么算数」的那一刻走偏:跨模块的越界修复、该不该合入、默认执行到哪停、自主运行到什么尺度。这类坑最隐蔽,因为代码能跑、build 能过、投票全绿。
2. 应用侧能调通 ≠ 应用侧就该改 (4/21)
应用层能绕开一个框架 bug,不代表应用层就该去绕。决策权、通用性、受影响范围 —— 这三问没过,就算代码合进去了也是给后面挖坑。
教训:AI 会默认哪里能改就在哪里改,你得替它守该不该改这关。
4. 不要反复确认 proceed · 默认 yes (4/21)
AI 工具权限系统经常弹 Do you want to proceed? 1. Yes 2. Yes and don’t ask again 3. No。我一开始每次都等我回复。后来干脆写进记忆:proceed 类提示默认 yes,真正分岔 (A/B/C 方案选择) 或破坏性操作 (force push / rm -rf) 才问。
教训:效率瓶颈不在 AI,在 AI 等人的那些弹窗。
6. 用户离开时的自主推进模式 (4/23)
我出门 90 分钟,让 AI 自己推进。回来发现它等在第一个问题那儿没动,理由是怕做错。后来把离线自主写成硬规则:任务只读 + 输出落盘临时目录、不 push、不写回外部系统、遇到分岔列出选项等我回来看。
教训:自主推进不是给自由度,是给明确的安全围栏。
8. 不再反复确认,但方案选择要问 (4/23)
第 4 条的补丁。默认 yes 不等于从不问。A/B/C 技术方案、破坏性操作、需要业务判断的仍然要问。边界是:执行性问题默认 yes,决策性问题必须问。
12. JNI 数据路径 ExceptionClear 是正确选择 (4/29)
Code review 时 AI 把每帧调用的 JNI 回调里的 ExceptionClear 标成吞异常缺陷。但那是高频数据路径,抛异常会连累整个进程;清异常保连接是设计选择不是 bug。
教训:review 规则要区分控制路径和数据路径,AI 默认一视同仁会误伤。
13. 重构 CL 用 R/P/N 评审 · 不按 bugfix 判 -1 (4/29)
纯重构 CL 标准是不引入新问题 + 不改变行为,历史遗留问题按 P 类豁免。AI 第一版 review 拿 bugfix 口径说修复比例太低判 -1,我差点帮它 vote。
教训:review 前告诉 AI CL 类型 (R/Bugfix/Feature/Refactor),它才知道该套哪把尺子。
19. commit msg 写得漂亮 ≠ 方向正确 (5/3)
AI 生成的 commit msg 可以 Root Cause/Solution/BackTrack/Test 八字段俱全、日志证据三行逐行标注 —— 格式上挑不出毛病。但内容里那句应用侧应该兼容本身就是个错判,格式越漂亮越容易让 reviewer 放行。
教训:review CL 先跑分层启发式,过完再看 commit msg。格式合规 +0 分,内容判断才给分。
20. 投票系统五绿 ≠ 该 merge (5/3)
我们这边的 CL 合入前要过 5 档自动投票 (代码审查 + 测试验证 + 格式检查 + AI 扫描 + CI),五档全绿 AI 就自动把它列进等合清单。但其中一条是白名单 workaround —— 合入等于永久给下游留一块特判代码。
教训:投票系统的盲点是"代码对不对 + 规则过不过",它不检查"该不该存在"。任何自动化关卡都是有盲区的,全绿只是"没撞墙",不是"方向对"。
21. 周报 KPI 容易过度推断 (5/4)
自动化周报让 AI 聚合本周合入的十几条代码变更,它全都当成交付成果计入 KPI。实际上里面有白名单 workaround (现象消根因留)、批量改 commit msg 的 no-op 变更、纯格式调整。这些混在数字里,KPI 看起来很漂亮但站不住脚。
教训:统计 KPI 的 agent 要有 hard stop:强制展示状态快照 + 至少一个反例类别,避免单方向累积。
27. 夜间长跑自主运行配方 (5/8)
最反直觉的一条。某晚我给了 AI 一个 6 小时窗口自主跑。早上起来看 —— 它只实际干了 2 小时,中间停滞 3-4 小时。根因是 Claude Code 是 turn-based (回合制,不说话就不动),没有自驱机制。
补丁是 7 条硬纪律:开工前 10 分钟预编排 10-15 个任务图 + 标依赖、把慢任务扔后台、用 Monitor 跟进度、自己用 ScheduleWakeup 每 20 分钟醒一次、偏保守不赌博、收工时生成 README 交接、执行性问题默认 yes。
教训:AI 的自主不是天生的,是你用调度纪律搭出来的。
32. 渐进 bugfix 优先
本周 bug 清单选题,优先确定性高 + 易修 + 改动小,3 条小的 > 1 条高风险大改。AI 默认会拿最难的显摆,要主动扭回来。
它有上下文 → 上下文污染了它的判断 (12 条)
AI 从「已知前文」推「新资料」的那一刻走偏:基于 subject 推 diff、基于关键词推根因、基于部分样本推分布、基于前一张截图推下一张、基于合并均值推子段。这类坑最贵,因为错误推理一旦写进报告、CL、策略,会连累下游一整条链。
3. R/P/N 分类要做二轮扫描 (4/21)
重构 CL review 时我用 R (重构) / P (遗留豁免) / N (新增) 三类评审。AI 第一轮只抓语义迁移型 R,漏掉两类隐形 R:判守收紧/放宽 (原 if (a > 0) 变 if (a > 0 && b != null) —— 行为变了);accidental bugfix (重构捎带修了老 bug 但 commit msg 没写)。
教训:让它跑完第一轮后主动追问有没有条件判断收紧/放宽了,有没有捎带修 bug 但没写。
5. 日志里的 error tag ≠ 根因 (4/21)
看到 ERROR / FAILED / Exception AI 会本能地当问题源。但很多 error 是正常 stop 流程发出来的 (比如断开连接时 socket close 触发的错误日志)。
教训:先问一句这条 error 是在正常停止路径上发出来的吗。
7. offline 脚本基准日必校 (4/23)
我写了一个盘前综述脚本固定用某天的 snapshot 做 baseline。跑了一周没人发现,直到某天结论对不上 —— snapshot 里的上个交易日是四天前了。
教训:任何固定 baseline 日期的脚本,执行前先比较 baseline 日期 vs 当前最新数据日期,差一天以上必须重算。
10. 分布类 claim 要等全样本 (4/24)
量化回测跑到 70% 我就去看中间结果,AI 基于那 70% 给了个某因子 alpha 稳定正向的判断。跑完一看,剩下 30% 是熊市段,结论反转。
教训:按 code 字典序分批回测时子集有系统性偏差 (前面大股后面小股,或按时间切前牛后熊)。小于 70% 别下分布类 verdict。
14. CL subject 不是 ground truth · diff 才是 (4/30)
AI 习惯先读 commit subject,基于那个标题去理解改动。但 subject 是对问题定性 (作者想让你看到的叙事),diff 是实际改了什么 (作者真的做了什么),两者经常不一致。最常见的情形:subject 说"修复 X 场景",diff 实际是加了一条白名单特判 —— 现象消了但根因没动。
教训:review 提示词里明确写以 diff 为准,subject 仅作参考。
15. trace 对照工单先验机型/分支 (4/30)
stack trace 看起来完美命中工单里的根因,AI 说就是这个。我顺手查了下机型代号 —— 工单是 A 机型,日志是 B 机型。同 SoC 但分支不同,代码可能差 200 个 commit。
教训:trace verdict 前,先交叉验证机型代号 + ROM 分支前缀,两个都匹配才算命中。
18. 闭合因果链 + 能改代码 ≠ 真因 (5/3)
AI 从日志一路推到源码某行,画了一条完美因果链,还准备了修复 diff。我问了一句为什么只有这台机器复现 —— 答不上来。真相是用户在开发者选项打开了一个冷门开关,改变了框架的兜底行为。代码能改、build 能过、现象能消,全是巧合。
教训:任何已定位的结论前,强制问一句谁让这条分支被走到。答不出就没到根因。
22. 时间必须拉本地时钟 (5/6)
AI 没有内置时钟。一开始它基于最后一个后台事件 05:35 推断现在大约 05:30 让我早睡。实际当时已经 07:16 早上了。工具事件时间戳是那个事件发生时的时间,不是你回复时的时间。
教训:每次涉及时间主动 date 或 Get-Date 拉本地时钟。
23. 盘前排序 · 动能优先于基本面 (5/6)
长假后首日或情绪窗口,前一交易日涨停 + 巨量的股票次日再连板的概率约 19.8%,比基本面最强那批 (估值低 + 业绩好) 高了 3 倍以上。AI 默认按基本面打分,这种"情绪接力"的机会完全被忽略。
教训:量化系统的因子权重要随情绪窗口动态切换。节后首日给动能维度加权,而不是用同一套打分跑全年。
24. 看截图先读元信息 (5/7)
用户发一张浏览器截图,上下文刚讲过 X 平台,AI 就默认这张图也是 X 平台。实际图里地址栏明明显示 Y 平台,它没看。类似情况一周内栽了两次。
教训:看截图硬规则 —— 先 stat + md5 确认文件是新的、再读地址栏/页面标题、最后看主视觉。
28. 策略评估 3 大反模式 (5/8)
连续两次栽在同款:辛普森悖论 + 样本偏斜 + 持仓期依赖。3 年合并均值看着漂亮,分年看每年都垫底 —— 因为某一年单点爆发把全局拉起来了。
教训:新策略必过三问:分年 alpha 分布、样本时间/行业分布、持仓期敏感性。合并 mean 是有毒的门面数字。
29. 敏捷过滤器要和 alpha 源方向一致 (5/9)
给一条低估值深跌反弹策略加了个情绪上行过滤器 (近 5 日涨停率高),本以为会更敏锐,9 年回测每一年都比原策略差 —— 9 年合并 Sharpe 从 +3.99 变 -2.04,直接反向。
失败根因:原策略要找的最佳买点是市场冷静时、深跌股见底但情绪还没点燃。新过滤器要求"情绪已经热起来了"—— 两个方向正相反。
教训:加过滤器前先问 alpha 来自哪个方向,过滤器的方向一致吗。
按月看分布
做了这篇博文之前我跑了一个月度统计脚本。
三类总量:
| 类别 | 总数 | 特点 |
|---|---|---|
| 工具 | 12 | 现象最直接,命令失败/工具报错就暴露 |
| 边界 | 11 | 最隐蔽,代码能跑、build 能过、投票全绿 |
| 上下文 | 12 | 最贵,错误推理连累下游一整条链 |
按首犯日期分布 (仅 29 条有明确日期的事故):
| 月份 | 新增 | 工具 | 边界 | 上下文 |
|---|---|---|---|---|
| 2026-04 (30 天) | 15 | 3 | 6 | 6 |
| 2026-05 (9 天) | 14 | 4 | 4 | 6 |
第 30-35 条是反复验证、跨场景的纪律性规则,不属于单次事故,未计入时序分布。
最想说的一点:不是越用越 ready,而是坑的形态在换。
4 月的坑集中在「边界」和「上下文」—— 80% 都是 AI 在"该不该做"和"从已知推未知"时走偏。5 月「上下文」没降,「边界」减少了一半,但「工具」翻了一倍 —— 我用得更深,调的工具更多,工具层的坑自然起来。
所以 KPI 不是每月 feedback 数量下降。是换题速度:同一类坑不该连续两个月占头。
5/10-5/12 新增 4 条 (35 → 39)
这 3 天栽的 4 条新坑,两条是 AI 时间感知失控,两条是工具层配置细节。
36. hook 误触发 · 白天说"我去睡了"被当真起跑 (5/11)
(上下文钩子)
我在午后 14:28 测试 hook 是否识别夜跑意图,发了"我去睡了,你跑 6 小时,自主运行到明早 8 点"。hook 识别意图 + flag 建立 + AI 马上起跑 6 小时任务图 —— 问题是它完全没核对本机时间,把 14:28 当成 22:28 响应,整个夜跑的时间戳叙事错位 8 小时。
后果:它真跑了 6 小时任务(Agent 起、文件落盘都是真的),但 README 写"22:29 起跑 04:48 收工"实际是"14:30-20:50"。我中间看了一眼觉得不对劲,等到晚上 20:52 回来要它分析"夜跑只跑了 6 分钟就交互",它才发现自己从头到尾在虚假时间戳下工作。
教训:AI 有"夜晚"强先验,听到"我去睡"就自动绑 22:xx。hook 激活的第一个 Bash 必须是 date 对准本机真实时间 —— 然后我给 hook 本身加了 20:00-08:00 的时间窗,白天再听到"我去睡了"只警告不起跑。
37. schtask IgnoreNew 吞掉 trigger · 盘中 3 轮数据凭空消失 (5/11)
(工具钩子)
Windows 任务计划的默认 MultipleInstancesPolicy=IgnoreNew,遇到慢任务会静默丢下次 trigger。我的盘中脚本 14:00 那轮网络慢到 20+ 秒完成,正好压到 14:20 触发窗口,scheduler 直接丢弃新实例 —— 连 14:40/15:00 后续两轮也被某个二次状态 bug 跟着断链。日志零记录,只能从"Next Run 跳到明天"反推。
后果:盘中下午 3 轮 deep 分析数据永久丢失,14:00-15:00 市场演变成黑洞。
教训:schtask 配重复间隔时默认改 Queue,并配 ExecutionTimeLimit 强制超时。更根本的是脚本里每路 I/O 加抢占式 timeout,单轮硬上限远小于 trigger 间隔。“Running” 状态不等于任务真在跑,必须监控产出文件。
38. run_daily.bat 写了 briefing 脚本但忘了接进来 (5/11)
(工具钩子)
5/10 我让 AI 写了个 S6F 实盘日报脚本 briefing_live_s6f_portfolio.py,独立测试通过。5/11 是真实盘第一天,收盘后我等 Server 酱微信推送看首日盈亏 —— 等到 19:00 没来。扫日志才发现:AI 只写了脚本没改 run_daily.bat,收盘流程里压根没调用这个 briefing。
两个问题叠在一起:(1) AI 当天做 code 改动时没顺手把"调用点"也改了;(2) 我没跑过真端到端,只看了新脚本独立单测。
教训:写"被定时任务 / 工作流调的脚本"时,把接入点改动写进同一个 commit。不然就是独立测试过但生产环境永远不跑的幽灵脚本。
39. Edit 改 bat 文件默认 LF 行尾 · cmd 当一整行解析 (5/11)
(工具钩子)
再犯第 9 号坑的姊妹版。AI 用 Edit 工具往 run_daily.bat 里插了 6 行 Step 3.5,sed 看起来全是换行正常,但实际 hex dump 里插入的那段是 LF (0a) 而不是 CRLF (0d 0a)。整个 Step 3.5 被 cmd 当一整行解析,echo / python 命令全部失效。
关键是诊断过程我也被误导:sed 输出自动转 CRLF 为 LF 让我一度以为修复后还是 LF。后来 Python rb 模式直接数字节才确认真的修好了。
教训:用 Edit 改 .bat 后立即跑 Python 或 dos2unix -n 校验一次全文 CRLF,不依赖 sed。修完仍要 cmd //c 真跑验证 exit code 0。
一句话总结
AI 不是夸夸机也不是 bug 机,它是一个极擅长执行但不懂业务边界的合作者。你不能把判断外包给它,但可以把执行几乎全部外包给它 —— 前提是你把边界、工具、纪律写进可复用的规则库。
这 35 条就是我 20 天攒的那本规则册。下个月末我还会再发一篇月度滚动,看题目又换到了哪儿。