You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The agentic task-board flow (Intelligence → Tasks tab) now works end-to-end — boards, an "assign to agent" path, a background dispatcher that auto-runs approved/assigned cards, update_task so runs drive their own card, and a run queue with steering modes (PRs #3326, #3317). But the UX is not production-ready: status information is hidden, refresh is poll-only and laggy, the source→board approval flow is confusing, there's no drag-and-drop, and the queue/steering controls aren't exposed at all. This issue tracks a focused UX overhaul.
Problem (grounded in current code)
1. Refresh is poll-only and laggy — background work looks frozen.
IntelligenceTasksTab.tsx:227 polls the two boards every POLL_MS = 4000; background dispatcher runs (60s tick, task_dispatcher.rs:552) update cards via write_back/update_task but emit no socket push to this tab (task_board_updated only fires inside an interactive turn — channels/providers/web.rs:~1700). Result: up to 4s staleness, no live progress, no "working" indicator, and TaskPlanAwaitingApproval (core/event_bus/events.rs:880) has no subscriber so approval prompts appear 0–4s late.
2. The board hides most of its own state.
TaskKanbanBoard.tsxcolumnFor (line 73) collapses 7 statuses into 3 columns — awaiting_approval/ready fold into "Pending", blocked/rejected fold into "Done". A user can't tell an approved card from a pending one, or why a "Done" column holds blocked/rejected cards.
blocker text renders only when status === 'blocked'; evidence is only visible inside the Brief modal with no on-card indicator that evidence exists.
3. No drag-and-drop.
Cards move via small, low-contrast left/right arrow buttons (onMove(card, -1|1), lines 281–300). Moving multiple columns = multiple clicks; weak affordance; not what a Kanban implies.
4. Source→board approval flow is non-obvious.
task-sources is a flat list, not a board, while user-tasks is a 3-column Kanban — two mental models for one "task" concept. "Work on task" opens a refinement modal; on Approve the card silently vanishes from the inbox and reappears on the personal board with no transition/confirmation. There's no way to reject/ignore a source task.
5. Queue & steering controls exist but are invisible.
run_queue defines Interrupt/Steer/Followup/Collect (agent/harness/run_queue/types.rs) and emits RunQueueMessageQueued/Delivered/... events, but a grep of app/src/components + app/src/pages finds zero usage of QueueMode/queueMode. Users get default interrupt only, with no queue-depth feedback when a message is queued vs. interrupts a run.
6. "Assign to agent" is under-communicated.
UserTaskComposer.tsx toggle (lines 184–200) is explained in small text and disabled when attaching to a thread; users create tasks and don't understand why they do/don't auto-run.
7. Run liveness / blocked-needs-you is weak.
No heartbeat/idle indicator; a wedged run only resurfaces after the 60s stale-reclaim. A run that self-blocks for a user decision surfaces the blocker only on the next poll, with no prominent "needs your input" affordance or one-click unblock.
8. Smaller gaps: tiny touch targets (arrows h-5 w-5, approve/deny text-[10px]), no per-mutation loading states, agent boards with 0 cards disappear entirely, no empty/error states in places, i18n coverage for new strings.
Proposed solution (scope: app-heavy, small core for events)
Event-driven freshness: add a socket push for background board mutations (subscribe TaskPlanAwaitingApproval/TaskRunReclaimed, emit task_board_updated from the dispatcher write path) so the board updates live; keep poll as fallback. Show a subtle "working…" / last-updated indicator.
Show real status: surface all statuses (dedicated treatment for awaiting_approval, ready, blocked, rejected) instead of bucketing into 3 columns; on-card badges for evidence/blocker; prominent "Needs your input" state for blocked cards with a one-click unblock/answer.
Drag-and-drop column moves (keep arrows as an a11y fallback), larger touch targets.
Coherent source→board flow: clearer approve/refine with a visible transition, plus a reject/ignore action; consider rendering the inbox consistently with the board.
Expose queue/steering: surface Steer / Follow-up / Collect / Interrupt in the run UI with a queue-depth indicator (wire the existing QueueMode + RunQueue* events).
Clarify "assign to agent" with stronger affordance/copy and a visible "will auto-run" state.
Polish: loading/empty/error states, keep zero-card live boards visible while running, full i18n across all locales.
Acceptance criteria (high level — likely split into sub-issues)
Board reflects background-run changes within ~1s via push (poll remains a fallback); a live "working/last-updated" indicator is shown.
All card statuses are distinguishable on the board; evidence and blocker are discoverable without opening the modal; blocked cards show a clear "needs your input" affordance.
Cards can be moved by drag-and-drop; arrow controls remain for accessibility; touch targets meet size guidance.
Source tasks can be approved and rejected/ignored, with a clear transition into the personal board.
Queue/steering modes (Interrupt/Steer/Follow-up/Collect) are usable from the run UI with a queue-depth indicator.
"Assign to agent" clearly communicates auto-run behavior.
Loading/empty/error states present; all new strings via useT() in every locale (pnpm i18n:check + pnpm i18n:english:check pass).
Diff coverage ≥ 80% — the implementing PR(s) meet the changed-lines coverage gate.
Note: deliberately broad ("fix the whole UX"). May be split into focused sub-issues (event-driven freshness · board status visibility · drag-and-drop · source-inbox flow · queue/steering UI) under this as a tracking issue.
Summary
The agentic task-board flow (Intelligence → Tasks tab) now works end-to-end — boards, an "assign to agent" path, a background dispatcher that auto-runs approved/assigned cards,
update_taskso runs drive their own card, and a run queue with steering modes (PRs #3326, #3317). But the UX is not production-ready: status information is hidden, refresh is poll-only and laggy, the source→board approval flow is confusing, there's no drag-and-drop, and the queue/steering controls aren't exposed at all. This issue tracks a focused UX overhaul.Problem (grounded in current code)
1. Refresh is poll-only and laggy — background work looks frozen.
IntelligenceTasksTab.tsx:227polls the two boards everyPOLL_MS = 4000; background dispatcher runs (60s tick,task_dispatcher.rs:552) update cards viawrite_back/update_taskbut emit no socket push to this tab (task_board_updatedonly fires inside an interactive turn —channels/providers/web.rs:~1700). Result: up to 4s staleness, no live progress, no "working" indicator, andTaskPlanAwaitingApproval(core/event_bus/events.rs:880) has no subscriber so approval prompts appear 0–4s late.2. The board hides most of its own state.
TaskKanbanBoard.tsxcolumnFor(line 73) collapses 7 statuses into 3 columns —awaiting_approval/readyfold into "Pending",blocked/rejectedfold into "Done". A user can't tell an approved card from a pending one, or why a "Done" column holds blocked/rejected cards.blockertext renders only whenstatus === 'blocked';evidenceis only visible inside the Brief modal with no on-card indicator that evidence exists.3. No drag-and-drop.
onMove(card, -1|1), lines 281–300). Moving multiple columns = multiple clicks; weak affordance; not what a Kanban implies.4. Source→board approval flow is non-obvious.
task-sourcesis a flat list, not a board, whileuser-tasksis a 3-column Kanban — two mental models for one "task" concept. "Work on task" opens a refinement modal; on Approve the card silently vanishes from the inbox and reappears on the personal board with no transition/confirmation. There's no way to reject/ignore a source task.5. Queue & steering controls exist but are invisible.
run_queuedefinesInterrupt/Steer/Followup/Collect(agent/harness/run_queue/types.rs) and emitsRunQueueMessageQueued/Delivered/...events, but a grep ofapp/src/components+app/src/pagesfinds zero usage ofQueueMode/queueMode. Users get defaultinterruptonly, with no queue-depth feedback when a message is queued vs. interrupts a run.6. "Assign to agent" is under-communicated.
UserTaskComposer.tsxtoggle (lines 184–200) is explained in small text and disabled when attaching to a thread; users create tasks and don't understand why they do/don't auto-run.7. Run liveness / blocked-needs-you is weak.
blocks for a user decision surfaces the blocker only on the next poll, with no prominent "needs your input" affordance or one-click unblock.8. Smaller gaps: tiny touch targets (arrows
h-5 w-5, approve/denytext-[10px]), no per-mutation loading states, agent boards with 0 cards disappear entirely, no empty/error states in places, i18n coverage for new strings.Proposed solution (scope: app-heavy, small core for events)
TaskPlanAwaitingApproval/TaskRunReclaimed, emittask_board_updatedfrom the dispatcher write path) so the board updates live; keep poll as fallback. Show a subtle "working…" / last-updated indicator.awaiting_approval,ready,blocked,rejected) instead of bucketing into 3 columns; on-card badges for evidence/blocker; prominent "Needs your input" state for blocked cards with a one-click unblock/answer.QueueMode+RunQueue*events).Acceptance criteria (high level — likely split into sub-issues)
useT()in every locale (pnpm i18n:check+pnpm i18n:english:checkpass).Related
update_task(feat(agent): add update_task tool — move/update a task card by id from any thread #3315).app/src/components/intelligence/IntelligenceTasksTab.tsx,UserTaskComposer.tsx,app/src/pages/conversations/components/TaskKanbanBoard.tsx,app/src/services/api/todosApi.ts; core:src/openhuman/agent/task_dispatcher.rs,agent/tools/update_task.rs,agent/harness/run_queue/,todos/ops.rs,core/event_bus/events.rs,channels/providers/web.rs.