用「一个目录 + 一个 markdown 文件」构建零数据库、零集成的任务队列,通过状态机(pending/taken/done/dropped)实现跨项目 Agent handover。
当你在多个项目间运行 agent 时,发现的问题几乎立刻就会越界——一个 session 在修工具时发现了另一个项目的 bug,一个 repo 的审查产生了三个待办。我的第一反应很直觉:让 session 直接去那边修。结果就是两个 agent 同时编辑同一棵树,审计了五次冲突后,我禁止了这个做法。一个 session 唯一允许对另一个项目做的写操作,是往队列里写入一条记录。
这个队列技术含量低得丢人:每个目标一个目录,每个任务一个 markdown 文件,front matter 里一行状态:pending、taken、done、dropped。没有数据库,没有集成,唯一的面板是一页 summary,从文件本身生成。文件永远待在原地作为历史记录,接收方的下一个 session 启动时会自动拿到它的 pending 条目,选择接手(take)、推迟(defer)或丢弃(drop),答案直接写入条目,所以不会有任何东西问第二遍。
handovers/
├── board.md generated from the entries, one page
├── site/
│ ├── 004-syndication.md status: done
│ └── 007-display-shapes.md status: pending
└── tooling/
└── 012-retry-helper.md status: taken
生命周期是四个状态加两条侧门:
take evidence pasted
pending ──────────────▶ taken ──────────────────────────▶ done
│ ▲ │
│ │ date reached └──▶ dropped, reason written into the entry
│ │
▼ │
snoozed, at most a week severity: risk ignores the snooze and
resurfaces every session until dealt with
一个完整的条目可以放在一屏内:
---
status: done
severity: normal
created: 2026-08-09
---
# Align the retry helper with the new timeout API
The ask: the helper still passes an option the API dropped in v3.
Update the call sites and run the suite.
Context: the failing CI run, and the changelog entry that dropped it.
Acceptance: `npm test` exits 0 with the retry cases green.
Evidence: "12 passed, 0 failed", pasted by the taker, 2026-08-10.
然而让它真正work的不是格式,而是三条写作规则——这些规则来自观察它失败的经历。
每条 entry 都必须带一个验收测试。正文要写得让接收方 session 不需要任何额外信息:需求、上下文链接、以及如何判断完成了。没写这条的条目一周后再看就像谜语,而谜语只会被丢弃。
Done 必须有证据。需要粘贴一行显示验收测试通过的内容。
这条规则直接来自我抓到有人声称工作完成了,但三十秒的检查就能证伪。
而"不存在"的声明必须说清楚检查了什么。有个条目曾经用"没有记录表明这个值是有意的"来为自己辩护,而记录里偏偏就写着这个值,就在隔壁文件里。那天我基于一个假前提做了裁决。此后,"没有文档说明 X"必须和"我在哪里找过"的列表一起写。
另外还有一套表示时间和紧迫性的小词汇:snooze 字段让条目隐藏到某个日期,最长一周,因为我的环境变化太快,停车太久就没意义了。还有一个 risk severity 等级,它完全忽略 snooze,每次 session 都会重新浮出水面直到有人处理。
我最喜欢的一点是:同一个队列同时服务人类和机器。我的夜间自动化程序和交互式 session 消耗同样的条目,对于标记为"需要我"的条目就跳过,翻转同样的状态,也遵守同样的证据规则。一套协议,没有翻译层。在 agent 之间的协调上,我越来越发现一个装着诚实文本文件的目录,比我试过的任何更聪明的方案都好用。
这个队列最精彩的故事不在本文里。那天晚上我的 agent 把同一个功能建了两遍——每一个文件都说了真话,而我是那个没做到的部分。