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:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
2026-06-29-todo-write-tool.md: df1bee2801b0e01b290b63f6edbe2e5b1be80cb7
|
||||
2026-06-29-todo-write-tool.zh.md: 7fa5cb2aad2b32ef0662df04ff6576be14a3a8e7
|
||||
2026-06-29-todo-write-tool.md: be5618148d1b4d9f292f27418df1d2576c737d73
|
||||
2026-06-29-todo-write-tool.zh.md: 20a8df6030819baeba19380d3b6b75b32c9d239b
|
||||
|
||||
@@ -6,7 +6,7 @@ English | [中文](2026-06-29-todo-write-tool.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
The harness gives the model bash and subagent tools but no way to record a structured task list. A todo list serves two co-equal purposes: it steers the model to plan multi-step work and keep the active task unambiguous (at most one active, exactly one while work remains), and it gives an interactive host a live progress checklist. Every reference coding agent surveyed (claude-code, opencode, codex, oh-my-pi, pi) ships some form of this; the harness had nothing.
|
||||
The harness gives the model bash and subagent tools but no way to record a structured task list. A todo list serves two co-equal purposes: it steers the model to plan multi-step work and keep the active work unambiguous, and it gives an interactive host a live progress checklist. Every reference coding agent surveyed (claude-code, opencode, codex, oh-my-pi, pi) ships some form of this; the harness had nothing.
|
||||
|
||||
## Decision
|
||||
|
||||
@@ -34,7 +34,7 @@ Each list belongs to the calling agent session, and non-agent calls are rejected
|
||||
|
||||
### Validation: the cheap middle
|
||||
|
||||
The schema enforces type/required/enum. Beyond that, `execute` rejects empty or duplicate `content` and more than one `in_progress` task. claude-code leaves single-in-progress to the prompt; oh-my-pi enforces it in code. We take the middle: enforce the cheap invariants that make a plan *coherent* (no blank tasks, no dupes, at most one active), but leave ordering and the discipline of keeping the list current to the model via the tool description. A rejected write returns an `isError` result so the model self-corrects.
|
||||
The schema enforces type/required/enum. Beyond that, `execute` rejects empty or duplicate `content`: enforce the cheap invariants that make a plan *coherent* (no blank tasks, no dupes), but leave ordering, active-task discipline, and keeping the list current to the model via the tool description. A rejected write returns an `isError` result so the model self-corrects. The original design also capped the list at one `in_progress` task; that cap was removed for parallel work — the [parallel in-progress Agent Note](2026-07-26-todo-parallel-in-progress.md) owns that decision.
|
||||
|
||||
## Why no cordis-catalog entry / no `@mode`
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Status: implemented
|
||||
|
||||
## 问题
|
||||
|
||||
harness 为模型提供了 bash 和 subagent 工具,却没有办法记录结构化的任务列表。todo 列表有两个同等重要的用途:引导模型规划多步骤工作并保持当前活跃任务明确(最多一个活跃,有剩余工作时恰好一个);同时为交互式宿主提供实时进度清单。调研的所有参考编码 agent(智能体)(claude-code、opencode、codex、oh-my-pi、pi)都提供了某种形式的此功能;本 harness 此前没有。
|
||||
harness 为模型提供了 bash 和 subagent 工具,却没有办法记录结构化的任务列表。todo 列表有两个同等重要的用途:引导模型规划多步骤工作并保持当前活跃工作明确;同时为交互式宿主提供实时进度清单。调研的所有参考编码 agent(智能体)(claude-code、opencode、codex、oh-my-pi、pi)都提供了某种形式的此功能;本 harness 此前没有。
|
||||
|
||||
## 决策
|
||||
|
||||
@@ -34,7 +34,7 @@ claude-code V1 的条目是 `{ content, status, activeForm }`;后来(V2)
|
||||
|
||||
### 校验:低成本的中间路线
|
||||
|
||||
schema 强制 type/required/enum。在此之上,`execute` 拒绝为空或重复的 `content`,以及超过一个 `in_progress` 任务。claude-code 将单一 in_progress 交给提示词约束;oh-my-pi 在代码中强制。我们取中间路线:强制执行使计划*连贯*的低成本不变式(无空任务、无重复、最多一个活跃),但将排序和保持列表最新的纪律通过工具描述交给模型。被拒绝的写入返回 `isError` 结果,使模型自行修正。
|
||||
schema 强制 type/required/enum。在此之上,`execute` 拒绝为空或重复的 `content`:强制执行使计划*连贯*的低成本不变式(无空任务、无重复),但将排序、活跃任务纪律和保持列表最新通过工具描述交给模型。被拒绝的写入返回 `isError` 结果,使模型自行修正。原始设计还将列表限制为最多一个 `in_progress` 任务;该上限已为并行工作移除——[并行 in-progress Agent Note](2026-07-26-todo-parallel-in-progress.md) 拥有该决定。
|
||||
|
||||
## 为何没有 cordis-catalog 条目 / 没有 `@mode`
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
2026-07-26-todo-parallel-in-progress.md: 1e7268407755957df216b684625164c54a93596f
|
||||
2026-07-26-todo-parallel-in-progress.zh.md: b15a5180ccb4caf456c93719b1bb5897b6023898
|
||||
@@ -0,0 +1,32 @@
|
||||
# Agent Note: Allow several `in_progress` todos at once
|
||||
|
||||
Status: implemented
|
||||
|
||||
English | [中文](2026-07-26-todo-parallel-in-progress.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
The [original `todo_write` design](2026-06-29-todo-write-tool.md) enforced at most one `in_progress` task per list, both in `execute` and in the durable-log invariant. That invariant assumes sequential work, but the harness runs genuinely parallel work — concurrent subagents through the delegation tool, background bash commands, workflow fan-out — and a list that can name only one active task cannot represent it. The model was forced to either mislabel parallel tasks as `pending` or merge them into one vague item, and the UI progress checklist under-reported what was actually running.
|
||||
|
||||
## Decision
|
||||
|
||||
Remove the single-`in_progress` cap everywhere it was enforced and let any number of tasks be `in_progress`:
|
||||
|
||||
- `execute` in `packages/todo/tool-todo/src/index.ts` no longer counts `in_progress` items; the `at most one task may be in_progress` error is gone from the tool's stable failure set.
|
||||
- The durable-log invariant in `packages/todo/tool-todo/src/invariant.ts` no longer rejects snapshots with several active items, so previously-persisted logs are unaffected and parallel snapshots replay cleanly.
|
||||
- The tool description now instructs the model to mark every actively-worked task `in_progress` — several during parallel work, one for sequential work — and to keep at least one while work remains.
|
||||
|
||||
The remaining coded invariants are unchanged: non-empty trimmed unique `content`, valid status enum. This supersedes the "at most one active" clause of the [original design's validation decision](2026-06-29-todo-write-tool.md); the rest of that Agent Note (whole-list replace, log-backed state, single owner) stands.
|
||||
|
||||
## Why guidance, not a parallelism-aware invariant
|
||||
|
||||
A coded invariant can only see the list, not the runtime: whether two `in_progress` items are legitimate depends on whether work is actually running concurrently, which the tool cannot observe. Enforcing a cap was therefore wrong in exactly the cases parallelism made it matter, and any replacement (for example, capping active items at the live subagent count) would couple the tool to runtimes it deliberately knows nothing about. The discipline of matching `in_progress` marks to genuinely concurrent work moves to the tool description, the same place ordering and list freshness already live.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- **Keep the cap and add an explicit parallel opt-in flag** — an extra argument on every call to serve the common case; the flag would be noise for sequential work and still unverifiable.
|
||||
- **Cap active items at a configured maximum** — any fixed number is arbitrary, and a deployment-varying tunable for list coherence has no principled value.
|
||||
|
||||
## Consequences
|
||||
|
||||
A todo list can now faithfully mirror parallel execution, and UIs render several active markers at once (the TUI's per-status prefix already handles this with no change). The tool no longer rejects a formerly-invalid snapshot shape, so the change is compatible with every previously valid call; only the error path was removed. The model-facing description changed, which re-recorded the tool-catalog page and the assembled snapshot transcripts that pin the schema.
|
||||
@@ -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(文本记录)。
|
||||
Reference in New Issue
Block a user