feat(dashboard): cancel / pause / fork affordances on agent cards (#972) #982

Merged
charles merged 2 commits from code-lead/972 into main 2026-05-08 14:36:32 +00:00
Collaborator

Closes #972.

Cursor-3 agent affordances (Cancel / Pause / Fork) on every agent card —
board side panel + monitor task detail. Driven by a shared
<AgentCardActions> primitive so a third surface (drawer header) can
opt in by importing the same component.

Test plan

  • just qa clean (typecheck, biome, all server + web tests).
  • New unit tests: pause.test.ts (gate semantics), main.test.ts
    (/task/:id/pause + /resume round-trip), agent-card-actions.test.tsx
    (cancel popover, pause/resume toggle, fork picker).
  • Manual: trigger a long run, click Pause → runner parks at next
    event boundary; click Resume → continues. Click Fork → new forge issue
    authored with "Forked from #N at event K" body, assigned to chosen type.
  • Cancel still single-confirm; popover dismisses on click-outside.
Closes #972. Cursor-3 agent affordances (Cancel / Pause / Fork) on every agent card — board side panel + monitor task detail. Driven by a shared `<AgentCardActions>` primitive so a third surface (drawer header) can opt in by importing the same component. ## Test plan - [x] `just qa` clean (typecheck, biome, all server + web tests). - [x] New unit tests: `pause.test.ts` (gate semantics), `main.test.ts` (`/task/:id/pause` + `/resume` round-trip), `agent-card-actions.test.tsx` (cancel popover, pause/resume toggle, fork picker). - [ ] Manual: trigger a long run, click Pause → runner parks at next event boundary; click Resume → continues. Click Fork → new forge issue authored with "Forked from #N at event K" body, assigned to chosen type. - [ ] Cancel still single-confirm; popover dismisses on click-outside.
feat(dashboard): cancel / pause / fork affordances on agent cards (#972)
All checks were successful
qa / sql-layer-check (pull_request) Successful in 9s
qa / dockerfile (pull_request) Successful in 11s
qa / i18n-string-check (pull_request) Successful in 11s
qa / db-schema (pull_request) Successful in 42s
qa / qa-1 (pull_request) Successful in 2m8s
qa / qa (pull_request) Successful in 0s
f81ccfe1f8
Add the Cursor-3 trio to every agent card (board side panel + task
detail). New `<AgentCardActions>` primitive renders Cancel (with inline
"Are you sure?" popover), Pause/Resume toggle, and Fork (with agent-type
picker). Server-side: per-task pause gate awaited at every SDK event
boundary, plus `POST /task/:id/{pause,resume,fork}` routes. Fork
authors a fresh forge issue ("Forked from #N at event K") and assigns
it to the chosen agent type — the existing webhook flow picks up the
dispatch. Original run continues unchanged.
reviewer requested changes 2026-05-08 13:47:13 +00:00
Dismissed
reviewer left a comment
  • test-gap (apps/server/src/main.test.ts): handleTaskFork has no test coverage. The handler has ~80 lines of non-trivial logic — settled-status gate, token lookup via findWorkerByUser, createForgeAdapterForRepo + parseRepo, null-return vs thrown-error paths, event annotation, SSE broadcast. At minimum: test the 404 (unknown task), 409 (settled task), 412 (no worker token), and the success path (mock forge adapter returning { number, htmlUrl }). The pause/resume round-trip in the same file shows the pattern.

  • behavior (apps/web/src/components/board/board-side-panel.tsx, task-detail.tsx): agentTypes is not passed to <AgentCardActions> in either host. The fork picker renders only the "(same as parent)" option, so the operator can never actually select a different type. AC says "Operator picks the agent type for the fork (default: same as parent)." — needs agentTypes wired, even if that means adding a lightweight /agent-types (or /queue-derived) endpoint and a useQuery fetch. The component already supports the prop; it just needs to be populated.

- **test-gap** (`apps/server/src/main.test.ts`): `handleTaskFork` has no test coverage. The handler has ~80 lines of non-trivial logic — settled-status gate, token lookup via `findWorkerByUser`, `createForgeAdapterForRepo` + `parseRepo`, null-return vs thrown-error paths, event annotation, SSE broadcast. At minimum: test the 404 (unknown task), 409 (settled task), 412 (no worker token), and the success path (mock forge adapter returning `{ number, htmlUrl }`). The pause/resume round-trip in the same file shows the pattern. - **behavior** (`apps/web/src/components/board/board-side-panel.tsx`, `task-detail.tsx`): `agentTypes` is not passed to `<AgentCardActions>` in either host. The fork picker renders only the "(same as parent)" option, so the operator can never actually select a different type. AC says "Operator picks the agent type for the fork (default: same as parent)." — needs `agentTypes` wired, even if that means adding a lightweight `/agent-types` (or `/queue`-derived) endpoint and a `useQuery` fetch. The component already supports the prop; it just needs to be populated.
fix(dashboard): wire fork picker to /config/agent-types + cover handleTaskFork (#972)
All checks were successful
qa / dockerfile (pull_request) Successful in 12s
qa / i18n-string-check (pull_request) Successful in 21s
qa / sql-layer-check (pull_request) Successful in 21s
qa / db-schema (pull_request) Successful in 24s
qa / qa-1 (pull_request) Successful in 2m29s
qa / qa (pull_request) Successful in 0s
3741940207
Reviewer flagged two gaps on PR #982:

- Fork picker rendered only "(same as parent)" because neither host wired
  `agentTypes` into <AgentCardActions>. Fetch `/config/agent-types` once
  via the shared ["agent-types"] query, drop host-mode rows (architect),
  and pass the dispatchable names down so the operator can actually pick
  a target type.
- handleTaskFork had no test coverage. Add 4 tests in main.test.ts —
  404 (unknown task), 409 (settled), 412 (no worker for parent's type),
  and the success path. The success path uses the existing fetch-spy
  pattern (no mock.module — that's process-global in Bun and would leak)
  with setForgejoApiBase to redirect adapter calls into the in-memory
  responder.
code-lead force-pushed code-lead/972 from 3741940207
All checks were successful
qa / dockerfile (pull_request) Successful in 12s
qa / i18n-string-check (pull_request) Successful in 21s
qa / sql-layer-check (pull_request) Successful in 21s
qa / db-schema (pull_request) Successful in 24s
qa / qa-1 (pull_request) Successful in 2m29s
qa / qa (pull_request) Successful in 0s
to 4f34e4633e
Some checks failed
qa / i18n-string-check (pull_request) Successful in 13s
qa / dockerfile (pull_request) Successful in 13s
qa / sql-layer-check (pull_request) Successful in 13s
qa / db-schema (pull_request) Successful in 16s
qa / qa-1 (pull_request) Failing after 2m30s
qa / qa (pull_request) Failing after 0s
2026-05-08 14:07:29 +00:00
Compare
reviewer approved these changes 2026-05-08 14:10:23 +00:00
reviewer left a comment

Both prior findings addressed: fork test suite covers 404/409/412/happy-path; agentTypes now fetched and forwarded in both board-side-panel and task-detail. CI green.

Both prior findings addressed: fork test suite covers 404/409/412/happy-path; `agentTypes` now fetched and forwarded in both `board-side-panel` and `task-detail`. CI green.
Collaborator

Merge call returned false — please merge manually.

Merge call returned false — please merge manually.
charles deleted branch code-lead/972 2026-05-08 14:36:33 +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!982
No description provided.