让编程代理记住代码库,先写清隐性约束
作者在约140次PR实践中发现,堆叠历史对话、失败案例和交接文档容易增加维护负担。文章提出将单位约定、外部依赖、必跑测试和生成文件规则等隐性知识集中记录,补足代理无法从代码引用中发现的信息。
AI 深度解读
AI 编程助手每次开新会话都要重新认识项目,问题可能不在模型记性差,而在代码没有记录那些「改之前必须知道」的约定。作者独自开发一款类似 Bannerlord 的策略游戏,在约 140 个 PR 中尝试过灌聊天记录、堆最佳实践、写交接文档,最后选择了一份按文件查询的知识映射。
他的结论是:让助手在修改前拿到相关规则、风险和检查命令,比持续扩充会话历史更有用。这个思路值得借鉴,但 140 个 PR 是探索经历,并不是效果提升的对照实验。
助手能找到调用关系,却找不到团队的默认约定
作者观察到,编程助手沿着 import 找调用方、读测试、修改函数,通常能完成合理的编辑。难点在于,有些约束根本不在依赖关系里。
例如,金额以分为单位;某张表还被移动端读取,不能随便删列;改过支付逻辑必须跑端到端测试;当前文件由模板生成,应该修改模板。这些知识可能藏在人的脑子里、旧 Slack 消息里,或者修改代码前没人打开的 README 中。
作者此前的尝试没有解决这个问题。粘贴成功会话,只是把输入从代码换成聊天历史;不断补充最佳实践和失败案例,让指令变成例外集合;每个任务都写报告和交接文档,则带来了维护成本和文档冲突。
需要补上的,是文件与隐含约束之间的联系。
一份 map.json,怎么让修改前的上下文更具体
作者把做法封装成开源 CLI:readfirst。知识放在 .readfirst/map.json 中,按文件分组,每组记录三类信息:
checks写修改后要执行的命令,以及命令覆盖什么。risks写新接手的人容易踩到的坑。rules写代码必须维持的约定,以及违反后的影响。
下面这个分组把账单目录、测试命令和金额单位放在一起:
{
"id": "src-billing",
"title": "charging cards",
"files": ["src/billing/**"],
"checks": [{ "run": "npm test -- billing", "why": "charges and refunds" }],
"risks": [{ "text": "amounts are in cents" }]
}
关键是 files 这一行:它把知识绑定到路径,查询具体文件时才知道该返回哪一组内容。示例没有列出 rules,也不代表这个字段不需要维护。
修改前运行 npx readfirst read src/billing/charge.ts,工具只输出适用于该文件的规则、风险、检查项,以及通过 import 关系找到的测试和调用方。原文标明,这部分依赖分析支持 JS/TS 和 Python。
要让助手执行这一步,作者建议在 CLAUDE.md、AGENTS.md 或 .cursorrules 中加入一句指令:
Before changing a file, run `npx readfirst read <file>` and follow what it says.
要注意其中的 Before changing a file:它要求助手先查询再修改。不过,这仍是一条行为指令,原文没有证明助手每次都会遵守。
文件有人覆盖,不代表知识永远正确
作者也意识到,过期映射可能比没有映射更糟,因此提供了 GitHub Action,引用方式是 - uses: jeonghun917/readfirst@v0。
它会在每个 PR 中发布一条评论,汇总变更文件对应的规则、风险和检查项,并在后续 push 时更新。映射不再覆盖代码时,例如新增文件没有归入任何分组,检查会失败,促使开发者在同一个 PR 中修复映射。
这里要区分两件事:检查能发现文件没有归组,却未必知道「金额单位已经改了,但风险说明还写着分」。原文没有说明如何自动验证知识内容是否仍然成立。
首次建图也需要投入。npx readfirst init 根据目录起草分组,npx readfirst prompt 给用户自己的助手生成补全任务说明。CLI 和 Action 使用 MIT 许可证,没有运行时依赖,不发起网络或模型调用,也不需要账号。
另有托管方案:安装 GitHub App,在 issue 评论 /readfirst fill,服务会读取仓库及 README、CLAUDE.md、docs 等现有资料,再提交映射 PR。每条风险附带来源文件和行号,供人工核验。每个账号首次托管建图免费。
作者展示了 Express 副本中的 jeonghun917/express#2:生成内容指出,res.sendFile 要求绝对路径或提供 opts.root,默认拒绝点文件;放宽限制可能暴露用户输入路径指向的文件。它还识别出,test/acceptance/ 会通过真实应用运行示例,修改示例也可能影响 npm test。
这些例子说明它能提取已有线索,不能证明它能发现尚未被任何人记录的业务约定。
我的判断
我认同按文件提供上下文的方向。相较于把所有经验塞进一个全局说明文件,它更容易让当前修改拿到相关信息,也方便评审者检查约束是否被遵守。
但作者没有给出错误率、返工次数、耗时或 token 消耗的前后对照。这套方法目前应被视为个人项目中的经验方案。
它适合约束分散、交接频繁的代码库;如果项目很小,少量就近注释和一份清晰的 AGENTS.md 可能已经够用。能用类型、测试或 CI 强制保证的规则,仍应尽量写成可执行检查。映射更适合承接那些暂时无法自动验证、却会影响修改决策的知识。
能拿来做什么
- 从一个经常被 AI 改错的 Node 模块开始,记录真实发生过的风险、必须保留的约定和对应测试命令,再判断维护成本是否值得。
- 对生成文件、跨端共享数据结构等位置,明确写出应该改哪里、哪些消费者会受影响,避免只留下「不要乱改」的模糊提醒。
- 把映射更新纳入 PR 评审,同时核对内容是否过期;新增文件通过覆盖检查,只是维护的第一步。
- 使用自动生成的映射时,逐条核对来源文件和行号,再确认测试命令能否执行,把草稿补成团队愿意负责的约定。