Canonical 选择笔记
AI 项目里最难处理的,往往不是"没有真相",而是太多东西都像真相。
聊天里有结论,报告里有结论,任务文件夹和 memory 里也有结论。本地刚 build 出一份页面,线上也有个能访问的版本。旧审计说还不够,新报告说已经补完。每份材料单独看,都能自圆其说。
危险就在这里。一份材料明显是错的,反而好办。真正麻烦的是,它在某个时间、某个边界内是对的,却被拿来回答另一个问题。
后来我给自己立了一条规则:先决定谁有资格回答,再看它说了什么。
冲突点:AI 会把"阶段性正确"讲成"当前正确"
最典型的例子,是那些漂亮状态词:95 分、launch ready、local candidate、PASS_WITH_WARNINGS。单独看,它们不一定错,甚至写得很谨慎。
但下一次 AI 单独捞到这些词,意思就变了。它可能记住 launch ready,忘了 local-only;记住 95 分,忘了 independent audit 曾经打回;记住页面能打开,忘了那只是本地 preview;记住"已生成",忘了还没部署到线上。
这种错误不会立刻炸掉,更像慢性污染:AI 从错误的 root 继续写,拿旧状态当当前状态,把 local-only 说成可以上线,把抽样通过说成全量完成。它还会写得很完整,甚至给出看起来稳妥的下一步。
我不怕 AI 不知道。我怕它在不知道的时候,拿一份不该负责的材料,讲出一个很顺的答案。
错误解法:找最新、找最长、找最会总结的
我以前也会偷懒。哪个文件最新,就先看哪个;哪个报告最长,就觉得它更完整;哪个 AI 最后说了一句"完成",就顺手当成当前状态。
但 AI 项目里,"最新"经常只是最新写出来,不代表最新负责。"最长"经常只是解释最多,不代表证据最硬。"总结最顺"更危险,因为它会把冲突包装成一个好听的故事。
后来我对 Canonical 的理解变了。Canonical 不是"唯一真相文件",也不是"所有东西只准看一个地方"。它更像法庭里的管辖权:不同问题,要找不同的负责来源。
我的选择规则:先问问题类型,再选真相源
我现在会先把问题拆清楚。不是一上来问"项目现在怎么样",而是问:我到底在判断什么?
- 问内容,就看内容文件。文章写成什么样,以 repo 里的 Markdown 为准,不以聊天里的摘要为准。
- 问当前进度,就看任务文件。README、notes、handoff、state 文件比一段聊天总结更有资格回答。
- 问是否能运行,就看真实输出。构建、测试、脚本结果、页面返回码,比"应该可以"更硬。
- 问是否已发布,就看线上路由。只要问题是外面的人能不能看到,本地 preview 不算答案。
- 问为什么这么决定,就看决策记录。没有 owner 放行、审计结论或明确 superseded 标记,就不能随便把旧判断升级成当前判断。
- 问历史线索,才看聊天和 memory。它们负责帮我定位,不负责替我判案。
顺序一旦定下来,很多争论会消失。不是因为材料少了,而是每份材料都有了边界。
冲突时的方法:不要总结,先裁判
最容易出错的时刻,是材料互相打架:聊天说 A,文件说 B;旧报告说过线,新 audit 说不够;本地页面是新版,线上页面还是旧版。
这种时候我不会让 AI 立刻总结。总结太早,只会把冲突包装得更好看。我会先让它做四步裁判:
- 第一步,明确问题。现在问的是内容、状态、运行、部署、验收,还是历史原因?
- 第二步,列出候选来源。哪些材料声称能回答这个问题?它们各自是什么时间、什么边界下产生的?
- 第三步,选出负责来源。谁对当前问题有直接责任,谁只是线索或旧证据?
- 第四步,标记被取代的材料。旧结论如果被新 audit、owner 决策或真实运行结果推翻,就要写明 superseded,不能留给下一次 AI 猜。
这套方法看起来慢,但比在错误真相源上继续推进便宜得多。路径一旦选错,后面每一步都在返工。
最后的结果:项目开始变安静
Canonical 规则带来的结果,不是所有材料被统一成一个文件,而是项目开始安静下来。
以前我经常要问:"你说的是哪个版本?"现在我会先问:"这个问题的真相源在哪?"找到了,就从那里继续;找不到,就先补一份当前状态文件,而不是在聊天里继续猜。
这也改变了我看 AI 输出的方式。AI 写得顺,不代表说得准;报告格式完整,不代表是 verdict;一句"已完成",如果没有对应的文件、输出、验证和边界,就只是一个待检查的说法。
Canonical 选择规则,本质上是给材料划责任。
聊天负责推进,memory 负责索引,报告负责提出主张,任务文件负责过程,真实输出负责验收,owner 决策负责放行。每个来源都有位置,项目才不会被一堆看起来都对的材料拖乱。我想要的不是一个更会总结的 AI,而是一个先知道该回到哪里确认事实的 AI。