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

@@ -84,6 +84,10 @@ describe('createFixtureApi', () => {
const times = events.slice(todoAt - 1, todoAt + 2).map(e => e.time)
expect(times[0]).toBeLessThanOrEqual(times[1] ?? 0)
expect(times[1]).toBeLessThanOrEqual(times[2] ?? 0)
// The sample is a parallel plan: the tool permits several in_progress, so
// the surfaces fed from here are exercised against more than one active item.
const snapshot = events[todoAt] as { data: { todos: { status: string }[] } }
expect(snapshot.data.todos.filter(t => t.status === 'in_progress')).toHaveLength(2)
})
it('create adds a session and pushes host/session-added to open host streams', async () => {