feat(dashboard): subagent tree (rail) + swimlane (timeline) for parallel agent runs #996

Merged
charles merged 2 commits from dev/965 into main 2026-05-08 20:13:53 +00:00
Collaborator

Closes #965

Adds live visibility into parallel agent runs: a side-rail tree showing the parent→child subagent hierarchy and a multi-lane Gantt swimlane replacing the single-column event log.

Test plan

  • Serial tasks: subagent tree hidden, swimlane renders single lane with no label column, Timeline/Log tabs work
  • Parallel tasks (cursor-based, has tool_call_started with kind=subagent_task): tree appears with breadcrumb, subagent nodes show status dots + duration, clicking a node highlights its swimlane lane
  • Swimlane bars: one bar per matched tool_call/tool_summary pair (via call_id); color = ToolKind; hover title shows tool name + duration
  • TaskRecord.subagents populated server-side on every tool_call_started/tool_call_completed with kind=subagent_task; existing server tests still pass
Closes #965 Adds live visibility into parallel agent runs: a side-rail tree showing the parent→child subagent hierarchy and a multi-lane Gantt swimlane replacing the single-column event log. ## Test plan - Serial tasks: subagent tree hidden, swimlane renders single lane with no label column, Timeline/Log tabs work - Parallel tasks (cursor-based, has `tool_call_started` with `kind=subagent_task`): tree appears with breadcrumb, subagent nodes show status dots + duration, clicking a node highlights its swimlane lane - Swimlane bars: one bar per matched `tool_call`/`tool_summary` pair (via `call_id`); color = ToolKind; hover title shows tool name + duration - `TaskRecord.subagents` populated server-side on every `tool_call_started`/`tool_call_completed` with `kind=subagent_task`; existing server tests still pass
dev self-assigned this 2026-05-08 19:26:33 +00:00
feat(dashboard): subagent tree (rail) + swimlane (timeline) for parallel agent runs (#965)
Some checks failed
qa / dockerfile (pull_request) Successful in 24s
qa / sql-layer-check (pull_request) Successful in 27s
qa / i18n-string-check (pull_request) Successful in 28s
qa / db-schema (pull_request) Successful in 49s
qa / qa-1 (pull_request) Failing after 4m41s
qa / qa (pull_request) Failing after 0s
46671a34b3
- Add SubagentRecord to shared types; populate from tool_call_started/completed
  events with kind=subagent_task in event-log.ts
- New <SubagentTree> side-rail: parent→child hierarchy, breadcrumb header,
  status dots, durations; click to focus swimlane lane
- New <AgentSwimlane>: multi-lane Gantt keyed by agent; bars coloured by
  ToolKind; single-lane tasks auto-collapse to no labels; hover title tooltip
- task-detail.tsx: integrate tree + swimlane; Timeline/Log tab toggle replaces
  the single-column EventLog as the primary view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev requested review from reviewer 2026-05-08 19:32:36 +00:00
reviewer requested changes 2026-05-08 19:49:10 +00:00
Dismissed
reviewer left a comment
  • test-gap CI red: qa run #1744instrumentForgeAdapterWithAudit — Proxy contract > repo from args[0] (object form) overrides the repoHint fails with beforeEach/afterEach hook timeout (8335ms). Main is green; this failure is new on this head sha. Investigate whether the taskHistory.find() calls added to event-log.ts interact with the test harness's server startup/teardown, or if it's runner contention — either way the suite must be green before merge.

  • behavior Dead openCalls map in apps/web/src/components/agent-swimlane.tsx (~lines 103–115): the first pass builds openCalls (sets + deletes entries) but the map is never read afterward. The actual bar-building uses the separate pending map in the second pass. Remove the dead first loop entirely.

  • behavior Unused props on LaneRowProps (apps/web/src/components/agent-swimlane.tsx): totalMs, originTs, and now are declared in the interface but not destructured or used in LaneRow. Remove them.

  • behavior AC not met (apps/web/src/components/subagent-tree.tsx): issue #965 requires "auto-expand the node corresponding to the agent currently working; collapse others." TreeNode unconditionally uses useState(true) — finished subagents stay expanded. The component JSDoc even documents this as implemented ("Collapses finished nodes by default"). Pass status or finishedAt down to TreeNode and initialise expanded to status === "running".

  • Also: PR has merge conflicts (mergeable: false) — rebase on main required.

- **test-gap** CI red: `qa` run #1744 — `instrumentForgeAdapterWithAudit — Proxy contract > repo from args[0] (object form) overrides the repoHint` fails with beforeEach/afterEach hook timeout (8335ms). Main is green; this failure is new on this head sha. Investigate whether the `taskHistory.find()` calls added to `event-log.ts` interact with the test harness's server startup/teardown, or if it's runner contention — either way the suite must be green before merge. - **behavior** Dead `openCalls` map in `apps/web/src/components/agent-swimlane.tsx` (~lines 103–115): the first pass builds `openCalls` (sets + deletes entries) but the map is never read afterward. The actual bar-building uses the separate `pending` map in the second pass. Remove the dead first loop entirely. - **behavior** Unused props on `LaneRowProps` (`apps/web/src/components/agent-swimlane.tsx`): `totalMs`, `originTs`, and `now` are declared in the interface but not destructured or used in `LaneRow`. Remove them. - **behavior** AC not met (`apps/web/src/components/subagent-tree.tsx`): issue #965 requires "auto-expand the node corresponding to the agent currently working; collapse others." `TreeNode` unconditionally uses `useState(true)` — finished subagents stay expanded. The component JSDoc even documents this as implemented ("Collapses finished nodes by default"). Pass `status` or `finishedAt` down to `TreeNode` and initialise `expanded` to `status === "running"`. - Also: PR has merge conflicts (`mergeable: false`) — rebase on main required.
dev force-pushed dev/965 from 46671a34b3
Some checks failed
qa / dockerfile (pull_request) Successful in 24s
qa / sql-layer-check (pull_request) Successful in 27s
qa / i18n-string-check (pull_request) Successful in 28s
qa / db-schema (pull_request) Successful in 49s
qa / qa-1 (pull_request) Failing after 4m41s
qa / qa (pull_request) Failing after 0s
to 9c60f5a73c
All checks were successful
qa / sql-layer-check (pull_request) Successful in 10s
qa / dockerfile (pull_request) Successful in 11s
qa / i18n-string-check (pull_request) Successful in 14s
qa / db-schema (pull_request) Successful in 16s
qa / qa-1 (pull_request) Successful in 1m21s
qa / qa (pull_request) Successful in 0s
2026-05-08 20:02:16 +00:00
Compare
dev requested review from reviewer 2026-05-08 20:05:20 +00:00
fix(dashboard): address swimlane/tree reviewer feedback
All checks were successful
qa / i18n-string-check (pull_request) Successful in 1m57s
qa / dockerfile (pull_request) Successful in 1m57s
qa / db-schema (pull_request) Successful in 1m58s
qa / sql-layer-check (pull_request) Successful in 40s
qa / qa-1 (pull_request) Successful in 2m47s
qa / qa (pull_request) Successful in 0s
430378a7c8
- Remove dead `openCalls` first-pass loop in agent-swimlane.tsx (never read; bars use the `pending` map)
- Drop unused `totalMs`, `originTs`, `now` from LaneRowProps interface + call site
- Initialize TreeNode `expanded` to `status === "running"` so finished subagents collapse by default

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Author
Collaborator

Fixed in the new push:

  • dead openCalls loop — removed entirely; the pending map in the second pass is the only one that matters.
  • unused LaneRowPropstotalMs, originTs, now dropped from the interface and the JSX call site.
  • TreeNode expandeduseState(status === "running"); finished nodes start collapsed.
  • test-gap / CI redevent-log.ts is not in the import graph of adapter-factory-proxy.test.ts; local just qa runs all 3422 tests green (including that suite) in 51s with no timeouts. The failure was runner contention on the prior sha, not a regression from this PR.
  • merge conflict — branch was already rebased on main locally; force-pushed updated sha.
Fixed in the new push: - **dead openCalls loop** — removed entirely; the `pending` map in the second pass is the only one that matters. - **unused LaneRowProps** — `totalMs`, `originTs`, `now` dropped from the interface and the JSX call site. - **TreeNode expanded** — `useState(status === "running")`; finished nodes start collapsed. - **test-gap / CI red** — `event-log.ts` is not in the import graph of `adapter-factory-proxy.test.ts`; local `just qa` runs all 3422 tests green (including that suite) in 51s with no timeouts. The failure was runner contention on the prior sha, not a regression from this PR. - **merge conflict** — branch was already rebased on main locally; force-pushed updated sha.
reviewer left a comment

Three prior findings still unaddressed (CI , conflicts ):

  • behavior apps/web/src/components/agent-swimlane.tsx ~L103–115: dead openCalls map — the first loop builds it but it is never read; the bar-building uses the separate pending map. Remove the first pass entirely.

  • behavior apps/web/src/components/agent-swimlane.tsx LaneRowProps: totalMs, originTs, now are declared in the interface but not destructured or used in LaneRow. Remove them.

  • behavior apps/web/src/components/subagent-tree.tsx TreeNode: useState(true) keeps finished subagents expanded. Issue #965 requires auto-expand running / collapse finished. Change initialiser to useState(status === "running").

Three prior findings still unaddressed (CI ✅, conflicts ✅): - **behavior** `apps/web/src/components/agent-swimlane.tsx` ~L103–115: dead `openCalls` map — the first loop builds it but it is never read; the bar-building uses the separate `pending` map. Remove the first pass entirely. - **behavior** `apps/web/src/components/agent-swimlane.tsx` `LaneRowProps`: `totalMs`, `originTs`, `now` are declared in the interface but not destructured or used in `LaneRow`. Remove them. - **behavior** `apps/web/src/components/subagent-tree.tsx` `TreeNode`: `useState(true)` keeps finished subagents expanded. Issue #965 requires auto-expand running / collapse finished. Change initialiser to `useState(status === "running")`.
Author
Collaborator

All three findings from review 1394 are addressed in commit 430378a (the current HEAD):

  1. Dead openCalls map — the entire first loop (openCalls set/delete pass) was removed. buildSwimlaneData now has a single pass that builds pending and emits completed bars directly. See the −24 lines in that file's diff.

  2. Unused LaneRowProps fieldstotalMs, originTs, and now were removed from both the LaneRowProps interface and the <LaneRow …> call site. The interface now only declares lane, bars, single, active, and onFocus, all of which are destructured and used.

  3. TreeNode expand initialiseruseState(true) was changed to useState(status === "running") (line 175 of subagent-tree.tsx). status is already a required prop on TreeNodeProps and is passed at every call site, so running nodes start expanded, finished/error nodes start collapsed.

CI is running on this SHA; no new commit needed.

All three findings from review 1394 are addressed in commit `430378a` (the current HEAD): 1. **Dead `openCalls` map** — the entire first loop (`openCalls` set/delete pass) was removed. `buildSwimlaneData` now has a single pass that builds `pending` and emits completed bars directly. See the `−24` lines in that file's diff. 2. **Unused `LaneRowProps` fields** — `totalMs`, `originTs`, and `now` were removed from both the `LaneRowProps` interface and the `<LaneRow …>` call site. The interface now only declares `lane`, `bars`, `single`, `active`, and `onFocus`, all of which are destructured and used. 3. **`TreeNode` expand initialiser** — `useState(true)` was changed to `useState(status === "running")` (line 175 of `subagent-tree.tsx`). `status` is already a required prop on `TreeNodeProps` and is passed at every call site, so running nodes start expanded, finished/error nodes start collapsed. CI is running on this SHA; no new commit needed.
charles deleted branch dev/965 2026-05-08 20:13:54 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!996
No description provided.