ChipCode 的项目记忆:哪些东西该写进文件,哪些不该
AI 忘事这件事,本质上是它每次都从零开始。
你以为你在跟一个记得昨天的人聊,实际上你在跟一个刚认识你的人聊。你说过十遍的编码规范,第十一遍还是要说。
解法大家都知道:把重要的东西写下来。但“重要的东西”具体是哪些?写多了是噪声,写少了不管用。
这篇讲 ChipCode 在这件事上的取舍。
两种记忆,别混在一起
先分清楚两件事:
会话记忆是这次对话里说过的内容。它天然存在,因为上下文就在那儿。关掉窗口就没了,这是对的——大部分对话不值得留。
项目记忆是跨会话要活下来的东西。它必须落在磁盘上,因为内存里的东西不可靠。
我们只做后者。会话记忆交给模型自己的上下文窗口,不额外存。
这个决定的意义在于:项目记忆是可审阅的。 用户能看到它、能改它、能 diff 它、能回滚它。而藏在某处的向量库不行。
该写进文件的四类东西
我们观察了大量真实项目,总结出四类必须落盘的:
一、板卡事实
型号、主频、Flash 大小、引脚占用、外设冲突。
# 板卡
- 型号:STM32F103C8T6,72MHz
- PA5:板载 LED(低电平点亮)
- PB12:被 USB 占用,不可用
- PA9/PA10:UART1,接串口模块
这类信息的价值是防止它编。你不写,它就会给你一个“典型接法”,而典型接法在你的板子上通常是错的。
二、编码约定
C 标准、内存策略、日志走哪个串口、命名风格。
# 约定
- C99,不用动态内存
- 日志走 UART2,禁用 printf 到 stdout
- 命名 snake_case,不用驼峰
- 中断里不做浮点
这些是“说一遍就够、不说就每次都错”的东西。写下来的成本是五分钟,收益是整个项目周期。
三、验收条件
这一条最重要,也最容易被忽略。
# 验收
- [ ] 上电 3 秒内进入待机,电流 < 20mA
- [ ] 连续按 3 次,计数为 3(允许 1 次抖动容错)
- [ ] 断电重启后时间误差 < 1s/天
写成勾选列表,每条都能判断“过没过”。
为什么它比前两类更重要?因为前两类影响“写得对不对”,这一类影响“做没做完”。前者错了好修,后者错了会误以为已经交付。
四、构建与烧录命令
不是每个项目都用标准命令。有些要带特殊参数、有些要先跑一个脚本生成头文件。
# 构建
- 编译:`make -j4 BOARD=bluepill`
- 烧录:`openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c "program build/fw.elf verify reset exit"`
写下来的好处是让 AI 别猜。它猜错的概率不低,而猜错的代价是一次失败的构建加上一段误诊。
不该写进文件的三类东西
有该写的,就有不该写的。我们踩过“什么都往里塞”的坑,结果是文件变成了一本没人读的流水账。
一、一次性的调试过程
“我试了 A 不行,试了 B 也不行,最后 C 可以。”
这段过程对当时的你有用,对三天后的你是噪声。它会被读进上下文,占着位置,还可能误导——因为 AI 会以为“A 和 B 都不能用”是结论,而实际上那只是你那天的环境问题。
过程记录应该进日志,不该进项目记忆。
二、临时代码片段
“先这么写着,回头改。”
这种片段一旦进了记忆,就会被当成“项目里的既有写法”被模仿。三个月后你在代码里看到五处同样的临时代码,来源就是它。
三、情绪和判断
“这个库很难用”“这个方案不行”。
写下来的人知道自己在抱怨,读的人(尤其是 AI)会把它当成事实依据。它会在下次选型时绕开这个库,理由是一条三周前的抱怨。
该写事实,不写评价。 如果确实要记录“为什么不用某个库”,那就写清楚具体的失败原因和复现条件,而不是“不好用”。
一个具体的结构
我们现在的项目目录里是这样:
project/
├── .chipcode/
│ ├── board.md # 板卡事实
│ ├── conventions.md # 编码约定
│ ├── acceptance.md # 验收条件(可勾选)
│ └── evidence.jsonl # 证据账本(append-only)
└── src/
前三个是人写的,第四个是系统写的。
这个划分很重要:人写意图,系统写事实。
acceptance.md 里的条件是“我希望它做到什么”,evidence.jsonl 里的是“它实际做到了什么”。两者分开存,才能对得上——如果混在一起,就成了自己给自己打分。
为什么不用向量库
技术上当然可以做:把项目文档切片、embedding、检索。
我们没做,原因有三个:
一是可审阅性。 用户需要能打开文件、看到原文、改一个字。向量库做不到这个,“检索出来的一段”和“文件里的第 12 行”是两种体验。
二是可 diff。 项目记忆会变。变了之后要知道变了什么——改了一条验收条件,还是删了一条约定。文件能 diff,向量库不能。
三是规模不匹配。 一个嵌入式项目的记忆文件通常不超过 200 行。这个规模下,全文读进去比检索更准,也更省事。
向量库解决的是“一百万条里找相关”的问题。我们面对的是“二十条里全都要”的问题。
最后
项目记忆这个东西,做得好用的时候你是感觉不到它的。
你只会觉得“这次它居然记得我用 C99”,而不会想到是因为三天前你写了一个文件。
反过来,一旦它失效,你立刻能感觉到——因为你要把同一段话再说一遍。
我们在这个功能上花的功夫,大部分不在“怎么存”,而在“什么该存”。前者是工程问题,后者是判断问题。判断错了,存得再好也没用。