返回博客

知识库的散文件问题:归档不是整理,是决策

任何长期运作的知识库,根目录都会慢慢积累一批「无主」散文件——会议复盘、某次事故的处理记录、架构调研笔记、临时性的技术备忘。

它们有个共同特征:当时记下来是对的,但没人把它们挂到正式的 issue 体系里。于是这些文件就浮在根目录,既不是已知问题的一部分,也不是可以直接删除的垃圾。

我以前的处理方式是「有空了批量看一遍然后挪一挪」。实践下来发现这是在把决策问题当整理问题处理——两者思维方式完全不同。

核心难点:归属判断

散文件归档最容易踩的坑不是「怎么写入目标 issue」,而是「归到哪里」的判断。

我踩过的典型错误:把一份 04-07 的技术备忘归到了时间最接近的 issue,结果发现这份备忘里描述的具体 commit 其实属于另一个跨越更长时间段的 issue。时间近不等于归属正确。

正确的归属判断有明确的优先级:

  1. linked-commits 是第一证据。 先查目标 issue 的 linked-commits 字段里有没有这份文件描述的 commit SHA。有 → 归那里,不管时间远近。
  2. 主题覆盖范围是第二判断。 散文件涉及的知识主题,能不能被某个现有 issue 的 scope 完整容纳?能 → 合入。不能 → 新建 issue,不要强行塞。
  3. 反碎片化原则。 不要「一文件一 issue」,那只是在旧碎片上叠加新碎片。默认优先合入已有 issue,新建是逃生口而不是常规路径。

并发执行时的单写者纪律

如果散文件数量多,很自然会想到并行处理——N 个文件,派 N 个 agent,同时跑完。这是对的,但有个容易被忽视的死角:多个 agent 同时操作一个共享文件(比如 INDEX.md)。

并发写同一文件不会报错,但会丢数据。Agent A 读到的是 Agent B 写入前的状态,B 写完后 A 用旧状态覆盖 B 的变更,静默丢失。

处理方式很简单:共享文件指定唯一写入者。在每个 agent 的任务 prompt 里明确写「禁止写 INDEX.md」,只留一个 agent(通常是负责新建 issue 的那个,因为它已经在操作编号上下文了)来统一处理 INDEX.md 的更新。

并行不等于各写各的

多 agent 并行处理时,任何被多方依赖的「共享状态文件」都需要提前指定唯一写入者,并在其他所有 agent 的 prompt 里显式禁止。「不冲突」不是自然发生的,需要设计。

范围纪律:抵抗「顺手扩展」的诱惑

做归档任务时,执行过程中经常会在根目录发现「这个任务范围以外」的散文件。直觉是顺手把它们也处理掉,毕竟都看到了。

这是会导致任务发散的常见陷阱。

如果原始 issue 列举了 N 个文件,就处理这 N 个,多余的记录下来留给下一个 issue,不要在当前任务里扩展范围。原因是:范围一旦扩展,就很难判断「完成」的边界在哪里,而且扩展进来的文件没有经过前期的归属分析,容易出错。

归档任务完成的标志是:原始 issue 里列举的散文件全部处理完毕、已移入 archive/ 目录、对应 issue 已更新、INDEX.md 状态已同步。根目录剩余的其他散文件,是下一轮的工作,不是这一轮的遗留。

长文件的分块读取

散文件里偶尔有很长的一份——几千行的事故复盘、完整的架构设计文档。把整份文件一次性塞进上下文会触及 token 限制,agent 要么截断要么放弃。

正确做法是在分配任务前就预分块,在 agent prompt 里明确指定:

Read offset=1 limit=400
Read offset=400 limit=900

这不是让 agent 自己决定怎么读,而是预先算好边界告诉它。agent 遇到长文件时的默认行为不可靠,主动指定分块是确定性更高的做法。

一句话心法

散文件归档的本质是「归属决策」,commit SHA 是比时间戳更可靠的证据,而并行执行时的单写者纪律是保证结果一致性的工程底线。