[Claude] AI 的跨会话记忆:从想法到 Knit

·

问题:每次新会话,AI 从零开始

在使用 Claude Code 这类 AI 编程助手时,我们通常依赖 CLAUDE.md.claude/ 文件夹来帮助 AI 记住项目的上下文——约定、架构、进度、决策。

但这种方法有几个根本性的问题:

  1. 记忆是静态的:你手动写进文档的内容,不会随着项目进展自动更新。项目做了两周,CLAUDE.md 可能还是最初的版本。
  2. 决策是断裂的:AI 在某个会话中做了”选 PostgreSQL 而非 MySQL”的决策,但下一个会话看不到这个决策——除非你手动写进文档。
  3. 上下文是孤立的:AI 知道当前要做什么,但不知道”为什么这样做”——上游做了什么决策、有哪些约束,这些信息丢失了。
  4. 文档会膨胀:随着项目推进,记忆文件越来越长,信息密度越来越低,AI 和人都难以从中找到关键信息。

核心矛盾:项目是一个持续演进的过程,但 AI 的记忆是一个需要手动维护的快照。

想法:用事件树做项目记忆

如果我们不用文档,而是用一棵带依赖关系的事件树来记录项目呢?

  构建用户认证系统(项目目标)
   │
   ├── 技术选型 ✅ done
   │     └── outcome: 选了 Rust + SQLite ,团队熟悉且单机部署足够
   │           │
   │           ├── 数据库设计 ✅ done
   │           │     └── outcome: 用户表 + 角色表 + 权限表,RBAC 模型
   │           │           │
   │           │           └── 实现 JWT 认证 ◐ doing  ← 当前任务
   │           │
   │           └── API 网关设计 ○ todo
   │
   └── 部署方案 ○ todo

每个事件有状态( todo / doing / done / abandoned ),事件之间有依赖关系。当一个事件完成时,记录它的决策结果( outcome )——为什么这样做、选了什么、有什么约束。

关键机制:当你查看某个事件时,系统沿依赖链向上遍历,把所有已完成事件的 outcome 自动组装成上下文。

AI 不需要翻文档、不需要人手动维护记忆。它只需要问”下一步做什么”,就能拿到:

  • 当前任务是什么
  • 上游做了哪些决策、为什么
  • 有哪些约束条件

这棵树能做什么

跨会话的决策连续性

AI 编程助手每次新会话都从零开始,但项目不是从零开始的。事件树的核心能力是把上游的决策结果自动注入到当前任务的上下文中

当一个 AI 会话开始工作前,它问系统”下一步做什么”,系统不仅告诉它当前该做哪个任务,还会沿着依赖链把前面所有已完成事件的决策结果组装在一起——选了什么技术、为什么这样设计、有哪些约束。AI 拿到的不是一个孤立的任务标题,而是站在一系列已验证的决策之上开始工作。当这个会话结束时,它把自己的决策结果写回事件树,下一个会话就能看到。决策链就这样跨会话地生长。

位置感知

在大型项目中,每个人(或每个 AI 会话)通常只负责一个局部。事件树让执行者看到自己在整体中的位置——项目的最终目标是什么,我当前的任务在哪个节点上,上游做了哪些决策把我带到了这里,下游还有哪些任务依赖我的产出。这不是简单的”待办清单”,而是带方向感的地图

计划的弹性

项目过程中计划会变。事件可以被废弃,废弃时记录原因。被废弃的事件不影响依赖链的推进(下游事件仍然可以继续),但原因会被保留在历史中。AI 知道”曾经考虑过这个方案但放弃了”,不会在未来的会话中重复提议已经否决的方向。依赖关系本身也可以被调整——新增依赖、移除依赖、拆分事件——树的结构跟着项目的理解一起演化,而不是一开始就固定不变。它可能是一个完整的计划,执行一半中途修改计划,也可能只规划了大方向,细枝末节完全没有计划,但都适用。

对人也有用

不只是给 AI 用的工具。一个人的项目也可以用它来记录想法、理清顺序、记住当时的思考过程。三五天后回来,list 一看就知道有什么没做完,show 一下就能回想起当时为什么想做这件事。

畅想:自动执行循环

上面描述的是人手动推进事件树的流程——人(或 AI 会话)问”下一步做什么”,拿到任务和上下文,执行完后手动写回结果。

但如果把这件事自动化呢?

设想这样一个循环:系统查看事件树,找到下一个可执行的任务,把任务描述和完整的决策链上下文打包,发送给执行器(一个 AI Agent ,比如 Claude Code 会话)。执行器拿到这些信息后开始工作——写代码、跑测试、解决问题。完成后,执行器把执行结果(做了什么决策、选了什么方案、遇到什么问题)反馈回来,系统自动更新事件树的状态和 outcome 。

然后系统再查看事件树。刚刚完成的任务可能解锁了新的可执行事件——原本因为依赖它而等待的任务现在就绪了。系统再次找到下一个任务,再次组装上下文,再次调用执行器。

事件树 ──查看下一步──→ 组装上下文 ──→ 调用执行器
                                    │
                              执行器完成任务
                                    │
事件树 ◀──更新状态──  接收反馈 ◀─────┘
   │
   └── 新任务就绪?──→ 是 ──→ 继续循环
                       否 ──→ 等待或通知人介入

在这个循环中,事件树扮演的不是”待办清单”,而是项目的状态机。它知道哪些任务已经完成、哪些因为依赖而就绪、哪些因为上游未完成而被阻断。执行器不需要知道项目全貌,它只需要拿到当前任务的上下文(决策链),专注于执行。事件树负责记忆和调度。

更有意思的是,执行器的反馈不只是”完成了”。如果执行器发现当前任务的某个前提假设不成立,或者需要拆分成更细的子任务,或者发现一个更好的方向需要废弃原计划——这些信息反馈回事件树,树的结构就会相应调整。树在生长,不只是在推进。

人在这个循环中的角色从”逐步推进每个任务”变成”设定目标和方向,监控进展,在需要判断时介入”。日常的执行、记忆维护、上下文传递,全部自动化。

当然,这还很远。要让这个循环真正跑起来,需要解决很多问题:执行器如何可靠地反馈结构化信息、系统如何判断反馈质量、什么时候需要人介入、如何处理执行失败。但这棵树的结构——带依赖的事件、自动组装的决策链、状态的流转——天然地支持这个方向。

现在的实现

目前 vibecoding 了一版勉强可用的 knit,核心是一个 Rust CLI 工具:

核心循环:
  knit next --json  →  读取记忆(拿到下一步 + 决策链上下文)
  执行任务
  knit report done --outcome "..."  →  写入记忆(记录决策)
  循环

10 个命令覆盖了创建、查看、编辑、报告、推荐、废弃等操作。全部输出支持 --json,AI 可以程序化消费。

存储是单文件 SQLite ,不需要服务器。LLM 推荐是可选的(knit next 可以配置 LLM 做智能排序,也可以不配置,用简单的依赖出度排序)。

事件树的 BFS 遍历自动沿依赖链收集决策链,钻石依赖会去重,被阻断的事件(上游还有未完成依赖)会标记 blocked 。废弃的事件被跳过,但原因保留。

SO ?

不知道大家怎么看这样的一个设计,我也不知道是否有一定的可行性,它看起来适合做很多方面的工作,也可以考虑它只为 agent 的项目记忆服务,目前的定位其实也有点模糊。

如果你有兴趣看看项目,里面的文档有更多信息 qkyufw/knit

欢迎评论

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *