跳转到内容

项目记忆

Memory 是 Chord 的可选跨会话记忆:把用户偏好、稳定的项目事实和可复用工作流沉淀为项目内的可检索记录,减少重复说明。自动抽取默认关,需要 memory.enabled: true 才开;已有的 MEMORY.md 照样加载。读取与编辑始终可见。

memory: 下的配置项见配置与认证。

  • 项目根目录的 MEMORY.md 是记忆入口和有界索引;详细记录位于 .chord/memory/records/<record-id>.md。所有仓库文件引用都使用项目根相对路径,整个项目目录移动后仍然有效。
  • MEMORY.md 与 AGENTS.md 不同:AGENTS.md 是项目必须遵守的高权威指令;MEMORY.md 是可能过时、需要核验的历史背景。它不会覆盖当前用户请求、不会授予权限,也不会要求执行命令。只有你主动整理的内容才可能成为团队规则(例如迁移进 AGENTS.md 或 .chord/skills/),Chord 不做自动升级。
  • 抽取由配置显式开启。 在 ~/.config/chord/config.yaml(或项目的 .chord/config.yaml)设置 memory.enabled: true 开启自动抽取。项目级配置按与其他配置一致的规则覆盖用户级配置,因此项目可以强制关闭(或打开)自己的抽取。开启后,冻结的历史会话可能被发送给模型并写入 MEMORY.md 等普通项目文件。关闭时,Chord 不发送历史、不写记忆文件,但仍会读取已有的 MEMORY.md。
  • 加载是自动的。 只要项目里有 MEMORY.md,新会话就会读取一次并把有界摘要注入会话上下文;摘要大小固定,不随记录数量增长。后台抽取提交新记录后,无需手动命令,摘要会在会话本来就要重建提示缓存的时机生效:新建或恢复会话、持久压缩、切换工作目录,或系统提示词、工具发生变化。若在下一个请求就替换,服务商会把整段对话当作未缓存输入重新计费。Memory 使用纪律(把记忆当作不可信、可能过时的背景,依赖前先核验)只在有记忆加载时才进入系统提示词;自动抽取提示只有在抽取开启时才追加。
  • Memory 不管本会话的恢复。 长会话续跑靠检查点和引用的状态文件,不是 MEMORY.md。Memory 只装你之前亲口说过、还没搬进 AGENTS.md 或项目文档的那点背景。
  • 这份 Memory 摘要已经注入到当前会话时,对这一轮来说它就等同于当前 MEMORY.md 的已读副本。Chord 不应为了重新打开 MEMORY.md 本身、或「确认」和注入内容一致而额外做一次文件读取。真正需要核验的是索引中的结论:按需打开对应 record,或更优先用代码、测试、文档等一手证据确认。
  • 自动抽取在会话冻结后后台进行。使用主模型池时(完整 fallback 语义,遵循用户的推理配置),只在主 agent 空闲时调用模型,新用户消息到来时会被抢占取消,稍后重试。用 memory.model_pool 指定专用模型池时,agent 工作期间也会运行,且不会被抢占。抽取模型看到的是有界的 AGENTS.md、当前活跃记忆,以及净化后的用户消息和已完成的助手回复(压缩摘要单独标成历史)。工具调用、工具结果和 .chord/notes/ 不在这份输入里,所以工作模型写进笔记的内容不会被当成你亲口说的。当前分支、提交、push、rebase、worktree 等临时状态不会成为长期记忆。
  • 亲口说是门槛,不是通行证。 候选得是你说过的、以后这个项目的会话还用得上、还没进 AGENTS.md 或文档的内容;当时不问你就进行不下去的事也算。你随口提过的本机路径、主机名、这台电脑上的目录布局,仍然不算 Memory。模型自己发现、以后还能再发现的事实,归项目文档或直接丢掉:有保留价值就写成升格建议等你审,没价值就丢。升格建议是等人审的门,不是自动召回:你没搬过去之前,它不会像 Memory 那样每轮注入。
  • 每条自动记录都有类型(偏好/事实/工作流/教训)、来源和认知状态;assistant 的历史陈述不会被升级为已验证事实。正文会分别说明结论、为什么值得跨会话保留,以及以后在什么场景下怎么用;没有实质展开价值的短句不会为了凑索引而单独建 record。完全重复的结论不会再次写入;修订后的记录会替代 MEMORY.md 中的旧索引项,旧 record 仍作为来源记录保留。结论里只写子系统或项目相对路径;当次提交 SHA、临时 pin、绝对路径、偶发 flaky 噪音不要写进正文。record 文件是只读输入,Chord 不会改写它,手改也不是更正结论的方式:summary 或 statement 一旦超过长度上限,这条记录就不再加载。更正走索引——删掉对应行(或交给抽取 retire),后续抽取会写入更正后的新记录。
  • 索引会被整理。 抽取同时会判断已有条目:不再成立、本来就不该记、或已经由项目规则表达的,会被移出索引,record 文件仍留作来源。你亲口说过的内容不在此列,只有 assistant 自己总结的条目才能这样移出。索引涨到注入预算能装下的条数后,会额外跑一轮只看索引本身(不带会话记录)的整理,把规模压回预算之内,早期或较弱模型写下的记忆因此不会变成永久负担。
  • 索引的行序就是注入优先级。 有界摘要从 managed 区顶部开始填,预算用完就丢掉后面的,所以新写入的条目排在前面。想让某条更早注入,在 MEMORY.md 里把它上移即可,你调整的顺序会在后续自动写入中保留。
  • 升格建议只进待审目录,不会动你的规则。 某条结论该进项目指令(必须始终生效)或项目文档(有用但很少触发,不值得每轮占预算)时,Chord 会把建议和拟写文本写成 .chord/memory/promotions/ 下的一个文件,并把该条目移出索引;你亲口说过的内容除外,这类条目在你认可建议之前会一直留在索引里。它不会自己改 AGENTS.md 或你的文档:逐个 review 文件,认可的搬过去,然后删掉该文件。
  • 抽取前后都会做敏感信息清洗(token/key、URL 凭据、PEM/私钥块、高危环境变量赋值等),但这只是 best-effort 防护,不承诺识别任意自定义秘密格式,普通的 Git diff 审阅仍是必要的边界。MEMORY.md 中 <!-- chord:managed:start --> 与 <!-- chord:managed:end --> 之间的内容是 Chord 自动维护的索引,之外的内容由你维护,Chord 不会覆盖。新条目只会由后台抽取写入,工作中的会话不会半路加条目。删除记录时直接删掉索引里对应的行即可:record 文件会保留为 orphan,不会被自动挂回,你也可以自行删除该文件。
  • 同一项目还有别的 Chord 会话在跑时,别手改 MEMORY.md:后台提交会同时重写 managed 区,可能撞车。先关掉那些会话,或者交给自动整理去做。
  • 自动抽取开启时,状态栏会显示 MEMORY 标识(与 LOOP / YOLO 一致)。模型返回无法解析的结果(坏 JSON、未知字段,或整段不是 JSON 对象)时,会换模型池里的下一个模型再采样一次;只有这次重试也失败,或者初始化、MEMORY.md 的 managed 区不可用时,标识才变成 MEMORY-FAIL,同时用一行提示说明原因。已经进入索引的记忆照常注入,下一次成功抽取后标识恢复为 MEMORY。
  • Memory 文件是普通项目文件:Chord 不自动修改 .gitignore,不自动暂存或提交。项目可以选择跟踪它们,也可以通过 .gitignore 或 .git/info/exclude 保持本地私有;所有自动变化都会形成普通工作树 diff。