fix(gui): the collapsed plan hint accounts for parallel active items

Lifting the single-in_progress cap makes a list shape reachable that the
web surfaces never received. Two sites derived their one-line summary with
todos.find(t => t.status === 'in_progress') — the collapsed TodoPanel header
and the todo_write row — which was total under the old cap and silently
dropped every active item but the first once several could match: a plan
with three running tasks collapsed to the name of one. The expanded list
was always correct, so neither PR's tests covered it.

Both sites now take planSummary in contract/todo-plan-model.ts, the
domain-shared face both the skeleton and toolviews domains may import; the
duplicated derivation was why one find could be fixed while the other
stayed wrong. The hint names the first active item and suffixes +<n> for
the rest, so the collapsed line reports how many tasks are running.

The web fixture's todo sample now runs two items in_progress, so the
assembled web transcript replays a parallel plan: the row reads
'1/4 已完成 · 实现 fixture 样本 +1' over the built bundles.
This commit is contained in:
Chinesezjc
2026-07-27 14:25:02 +08:00
parent b2a4341ceb
commit f8b0bd31d3
13 changed files with 167 additions and 38 deletions

View File

@@ -1,6 +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
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-07-26-todo-parallel-in-progress.md
2026-07-26-todo-parallel-in-progress.md: eb8d78e2fe2895d952a355226ac518b9ccd40f98
2026-07-26-todo-parallel-in-progress.zh.md: e610165f0170d92535a3709cc23dab8c77d2767f

View File

@@ -27,6 +27,12 @@ A coded invariant can only see the list, not the runtime: whether two `in_progre
- **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.
## The display surfaces are part of the change
Lifting the cap makes a list shape reachable that no renderer had ever received, so this branch stacks on the [web todo display](2026-07-23-web-todo-display.md) rather than landing beside it: both change `tool-todo`, and the GUI is where a parallel plan becomes visible. Two web sites derived their one-line summary with `todos.find(t => t.status === 'in_progress')` — the collapsed plan-strip header and the `todo_write` row — and under the old cap that `find` was total, since at most one item could match. With several active it silently dropped every active item but the first: a four-item plan with three running tasks collapsed to the name of one, and the row read `0/8 已完成 · <one task>` while seven others were in flight. The expanded list was always correct (it maps every item), which is why neither PR's tests caught it — only the collapsed header and the row lost information.
Both sites now take `planSummary` in `contract/todo-plan-model.ts`, the domain-shared face the skeleton and toolviews domains may both import. Duplicated derivation was the reason one `find` could be fixed while the other stayed wrong, and the counts were already computed twice. The hint names the first active item and suffixes `+<n>` for the rest, so the collapsed line reports how many tasks are running instead of implying one. Naming every active item was rejected: the hint is a single line next to the composer, and an unbounded join would overflow it — the count degrades predictably where a list does not.
## 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.
A todo list can now faithfully mirror parallel execution, and every UI renders several active markers at once: the TUI's per-status prefix needed no change, and the web surfaces needed the shared derivation above. 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. The web fixture's todo sample now runs two items `in_progress`, so the assembled web transcript replays a parallel plan and would fail again if either surface returned to single-active derivation.

View File

@@ -27,6 +27,12 @@ Status: implemented
- **保留上限并增加一个显式的并行 opt-in 标志**——为服务常见场景而给每次调用增加一个额外参数;这个标志对顺序工作而言只是噪声,而且仍然无法验证。
- **把活跃条目限制在一个可配置的上限内**——任何固定数字都是任意的,而为列表连贯性设一个随部署变化的可调参数没有原则性价值。
## 展示面是本次改动的一部分
解除上限使一种此前任何渲染器都不曾收到的列表形状变得可达,因此本分支 stack(栈叠)在 [web todo 展示](2026-07-23-web-todo-display.md)之上,而不是与之并行落地:两者都改 `tool-todo`,而 GUI 正是并行计划变得可见的地方。web 有两处用 `todos.find(t => t.status === 'in_progress')` 推导单行摘要——折叠态的计划横条表头与 `todo_write` 工具行——在旧上限下这个 `find` 是完备的,因为最多只能有一个条目匹配。一旦有多个活跃项,它会静默丢掉除第一个之外的全部活跃条目:一个四条目、三个任务在跑的计划折叠后只显示其中一个的名字,工具行读作 `0/8 已完成 · <一个任务>`,而另外七个仍在进行。展开态的列表始终正确(它遍历每个条目),这也是两个 PR 的测试都没抓到它的原因——只有折叠表头与工具行丢失了信息。
现在两处都改用 `contract/todo-plan-model.ts` 中的 `planSummary`,即 skeleton 与 toolviews 两个 domain 都可导入的域间共享面。重复的推导正是一处 `find` 被修好而另一处仍然错误的原因,而计数本来就被算了两遍。提示语给出第一个活跃条目,并为其余活跃项追加 `+<n>` 后缀,因此折叠行报告的是有多少任务在跑,而不是暗示只有一个。列出全部活跃条目被否决了:提示语是紧邻输入框的单行,无上界的拼接会溢出——在列表做不到的地方,计数能够可预测地降级。
## 后果
现在 todo 列表可以忠实反映并行执行,UI 也能一次渲染多个活跃标记(TUI 按状态区分的前缀无需改动即可处理这种情况)。工具不再拒绝一种此前无效的快照形状,因此该改动兼容此前所有合法的调用;被移除的只是错误路径。面向模型的描述发生了变化,这重新记录了 tool-catalog 页面以及固定 schema 的组装后快照 transcript(文本记录)。
现在 todo 列表可以忠实反映并行执行,并且每个 UI 都能一次渲染多个活跃标记:TUI 按状态区分的前缀无需改动,web 各展示面则需要上述共享推导。工具不再拒绝一种此前无效的快照形状,因此该改动兼容此前所有合法的调用;被移除的只是错误路径。面向模型的描述发生了变化,这重新记录了 tool-catalog 页面以及固定 schema 的组装后快照 transcript(文本记录)。web fixture 的 todo 样本现在有两个条目处于 `in_progress`,因此组装后的 web transcript 回放的是一个并行计划;若任一展示面退回单活跃项推导,它会再次失败。