feat(todo): allow several in_progress todos at once

Remove the single-in_progress cap from todo_write execute validation and
the durable-log invariant so a task list can mirror genuinely parallel
work (concurrent subagents, background commands). Update the tool
description to instruct marking every actively worked task in_progress,
refresh the tool catalog and keyless snapshot expected outputs, and
record the decision in a new Agent Note superseding the original cap.
This commit is contained in:
Chinesezjc
2026-07-26 02:50:47 +08:00
parent 6f50208ea3
commit 876065a97d
44 changed files with 150 additions and 68 deletions
@@ -0,0 +1,32 @@
# Agent Note: 允许同时存在多个 `in_progress` todo
Status: implemented
[English](2026-07-26-todo-parallel-in-progress.md) | 中文
## 问题
[原始 `todo_write` 设计](2026-06-29-todo-write-tool.md)在 `execute` 和持久日志不变式中都强制每个列表至多一个 `in_progress` 任务。该不变式假设工作是顺序进行的,但 harness 会运行真正并行的工作(通过委派工具启动的并发 subagent、后台 bash 命令、工作流扇出),而一个只能标出单个活跃任务的列表无法表示这种情况。模型被迫要么把并行任务错误标记为 `pending`,要么把它们合并成一个含糊的条目,导致 UI 进度清单少报了实际正在运行的工作。
## 决策
在所有强制它的位置移除单一 `in_progress` 上限,允许任意数量的任务处于 `in_progress`:
- `packages/todo/tool-todo/src/index.ts` 中的 `execute` 不再统计 `in_progress` 条目;`at most one task may be in_progress` 错误已从工具稳定的失败集合中移除。
- `packages/todo/tool-todo/src/invariant.ts` 中的持久日志不变式不再拒绝含多个活跃条目的快照,因此此前持久化的日志不受影响,并行快照也能干净回放。
- 工具描述现在指示模型把每个正在处理的任务标记为 `in_progress`(并行工作时可以有多个,顺序工作时只有一个),并在仍有工作未完成时至少保留一个。
其余编码的不变式保持不变:`content` 去除首尾空白后非空且唯一、status 为合法枚举值。本决定取代[原始设计的校验决策](2026-06-29-todo-write-tool.md)中「至多一个活跃」的条款;该 Agent Note 的其余部分(整列表替换、日志支撑的状态、单一所有者)依然成立。
## 为何用指引而非感知并行的不变式
编码的不变式只能看到列表,看不到运行时:两个 `in_progress` 条目是否合理,取决于工作是否真的在并发运行,而这一点工具无法观测。因此,恰恰在并行让上限变得重要的场景里,强制上限反而是错的;任何替代方案(例如把活跃条目数限制为在线 subagent 的数量)都会把工具耦合到它有意一无所知的运行时上。把 `in_progress` 标记与真正并发的工作对应起来这一纪律,转移到工具描述中,也就是排序与列表新鲜度已经所在的地方。
## 曾考虑的替代方案
- **保留上限并增加一个显式的并行 opt-in 标志**——为服务常见场景而给每次调用增加一个额外参数;这个标志对顺序工作而言只是噪声,而且仍然无法验证。
- **把活跃条目限制在一个可配置的上限内**——任何固定数字都是任意的,而为列表连贯性设一个随部署变化的可调参数没有原则性价值。
## 后果
现在 todo 列表可以忠实反映并行执行,UI 也能一次渲染多个活跃标记(TUI 按状态区分的前缀无需改动即可处理这种情况)。工具不再拒绝一种此前无效的快照形状,因此该改动兼容此前所有合法的调用;被移除的只是错误路径。面向模型的描述发生了变化,这重新记录了 tool-catalog 页面以及固定 schema 的组装后快照 transcript(文本记录)。