Skip to content

💄 style(tasks): polish kanban columns, status labels, priority hotkeys#14137

Merged
arvinxx merged 10 commits into
canaryfrom
style/task-polish
Apr 25, 2026
Merged

💄 style(tasks): polish kanban columns, status labels, priority hotkeys#14137
arvinxx merged 10 commits into
canaryfrom
style/task-polish

Conversation

@arvinxx

@arvinxx arvinxx commented Apr 24, 2026

Copy link
Copy Markdown
Member

💻 Change Type

  • 🐛 fix
  • 💄 style

🔀 Description of Change

Two small changes:

Fix — Task activity shows "Untitled" for running topics

Task activity rows were rendering Untitled for in-progress topics. Root cause: the activity builder reads taskTopics.handoff.title, which is populated only after a topic completes (LLM-generated summary). Until then it fell through to a hardcoded Untitled constant, so newly-started tasks always showed Untitled in the activity list — confusing users after clicking "Start task".

The fix adds a middle layer to the fallback chain:

handoff.title  →  topics.title  →  "Untitled"
   (done)        (running)         (edge case)
  • TaskTopicModel.findWithHandoff now left-joins the topics table to return title alongside handoff. This also repairs buildTaskPrompt in src/server/routers/lambda/task.ts:226, which already expected t.title but never received it.
  • TaskService activity builder uses handoff?.title || t.title || UNTITLED_TOPIC_TITLE so running topics show the task name (e.g. 小说) and completed topics still show the LLM summary.

Style — ToolSearch inspector tag polish

Tag in the Claude Code ToolSearch inspector is now a pill (fully-rounded, slightly more padding) to read more as a chip.

🧪 How to Test

  • Tested locally
  • Added/updated tests (existing tests cover the path; no regression)
  • No tests needed

Manual steps:

  1. Create a task with a non-empty name (e.g. 小说).
  2. Click Start task.
  3. While the topic is still running, the activity row should display the task name (小说) instead of Untitled.
  4. After the topic finishes and summary is generated, the row should display the LLM-generated handoff title.

Verified:

  • src/server/services/task/index.test.ts — 21/21 passed
  • packages/database/src/models/__tests__/taskTopic.test.ts — 8/8 passed
  • bun run type-check — clean (one pre-existing .next/dev/types error unrelated)

📸 Screenshots / Videos

Before After
Running topic shows Untitled #1 · 3s Running topic shows 小说 #1 · 3s
Completed topic shows Untitled if summary unavailable Completed topic shows handoff summary or task name

🤖 Generated with Claude Code

@vercel

vercel Bot commented Apr 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lobehub Ready Ready Preview, Comment Apr 24, 2026 5:20pm

Request Review

@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Apr 24, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 65.30612% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.53%. Comparing base (043d2a8) to head (b70317e).
⚠️ Report is 3 commits behind head on canary.

Additional details and impacted files
@@             Coverage Diff             @@
##           canary   #14137       +/-   ##
===========================================
- Coverage   86.12%   67.53%   -18.60%     
===========================================
  Files         610     2192     +1582     
  Lines       51406   188781   +137375     
  Branches     8689    19560    +10871     
===========================================
+ Hits        44273   127488    +83215     
- Misses       7005    61165    +54160     
  Partials      128      128               
Flag Coverage Δ
app 60.58% <69.56%> (?)
database 92.22% <0.00%> (-0.03%) ⬇️
packages/agent-runtime 79.82% <ø> (ø)
packages/context-engine 83.23% <ø> (ø)
packages/conversation-flow 92.40% <ø> (ø)
packages/file-loaders 87.02% <ø> (ø)
packages/memory-user-memory 74.74% <ø> (ø)
packages/model-bank 99.89% <ø> (ø)
packages/model-runtime 84.06% <ø> (ø)
packages/prompts 70.14% <ø> (ø)
packages/python-interpreter 92.90% <ø> (ø)
packages/ssrf-safe-fetch 0.00% <ø> (ø)
packages/utils 88.41% <ø> (ø)
packages/web-crawler 88.66% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Store 67.15% <31.57%> (∅)
Services 53.07% <ø> (∅)
Server 66.58% <100.00%> (∅)
Libs 53.30% <ø> (∅)
Utils 80.04% <ø> (-13.43%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

arvinxx and others added 10 commits April 25, 2026 01:11
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task activity rows rendered "Untitled" while the topic was still running
because the activity builder read `handoff.title` (populated post-summary)
and fell back straight to a hardcoded constant. Join `topics` in
`findWithHandoff` and fall through `handoff.title → topics.title → Untitled`
so running topics show the task name instead of "Untitled".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…low fold default

Replace WorkflowCollapse.defaultStreamingExpanded (bool) with
defaultWorkflowExpandLevel ('collapsed' | 'semi' | 'full'), threaded
through MessageItem → AssistantGroup → Group → WorkflowCollapse and
exposed on ChatList (applies to the default item renderer only).
When set, pins both the initial state and post-completion reset so
'full' keeps tool-call groups expanded across streaming → complete;
pending intervention still forces expansion.

Apply 'full' in the task detail TopicChatDrawer so viewers see all
tool details by default. Migrate the Onboarding caller from
defaultWorkflowExpanded={false} to defaultWorkflowExpandLevel='collapsed'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SWR's function-form refreshInterval is evaluated on effect mount and after each
timer fires. When the first call runs with cache.data=undefined, our function
returned 0 — so no timer was ever scheduled, and polling never started even
after the fetch populated the cache. Drive polling from a reactive zustand
selector instead, so refreshInterval is a stable number that flips once the
task/topic status is known.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
"Paused" read like the task was stopped by the user. The actual semantic is
"agent has finished a run and is waiting for user to review and nudge it next" —
so rename the label in STATUS_META and the matching i18n keys (status.paused
and the kanban column needsInput). Also promote paused into USER_SELECTABLE_STATUSES
so users can explicitly park a task back into this state from the context menu.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expose a dedicated "Canceled" column in the kanban board so canceled tasks no
longer blend into the done column. Defaults to hidden (alongside done) to keep
the board compact, and maps the new column key through COLUMN_STATUS_ICON plus
the i18n table that KanbanColumn already referenced but was missing an entry
for.
- Use colorTextSecondary (brighter than colorTextDescription) for non-urgent
  priority icons so they read against the row background.
- Add a static label string to PRIORITY_META so callers can pass it as the
  i18n defaultValue instead of an empty string — prevents unlocalised UI when
  a translation is missing mid-rollout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The task context menu already supported number shortcuts to switch status. Extend
that to priority: when the user hovers the Priority submenu, pressing 1–5 picks
the corresponding priority level. A ref tracks which submenu is active (defaults
to Status on open) so the keydown handler knows which list to index into.

Also pick up meta.label as the i18n defaultValue for priority entries, matching
the new PRIORITY_META field so missing translations fall back to readable text
instead of an empty string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The vertical collapsed header was getting noisy with "Hidden · 2" style
duplication — the count is already implied by the expanded tooltip, and the
vertical orientation makes the trailing number crowd the icon.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surface the 1–N keyboard shortcuts next to each status/priority entry, with a
check icon on the currently selected value. Extract the render into a shared
menuExtra helper so TaskStatusTag and TaskPriorityTag share the same pattern
instead of each inlining its own layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@arvinxx arvinxx force-pushed the style/task-polish branch from 8d92cca to b70317e Compare April 24, 2026 17:14
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:S This PR changes 10-29 lines, ignoring generated files. labels Apr 24, 2026
@arvinxx arvinxx merged commit d4a12c0 into canary Apr 25, 2026
49 of 50 checks passed
@arvinxx arvinxx deleted the style/task-polish branch April 25, 2026 04:16
@arvinxx arvinxx changed the title 🐛 fix(tasks): preserve topic title when handoff is missing 💄 style(tasks): polish kanban columns, status labels, priority hotkeys Apr 25, 2026
arvinxx added a commit that referenced this pull request Apr 25, 2026
)

* 🔥 feat(tasks): drop per-agent /agent/:aid/tasks routes again

PR #13887 reintroduced the per-agent Tasks surface (sidebar entry, route
files, agentId-scoped breadcrumb/list/board, /agent/:aid/tasks/:taskId
navigation) that #14109 had removed in favor of unified /tasks and
/task/:id. Restore the unified-only model: drop the agent sidebar Tasks
nav item, delete the agent-scoped route files, strip agent-tasks blocks
from both desktopRouter configs, and revert the agentId props and
per-agent navigate paths in AgentTasksPage / KanbanBoard / Breadcrumb /
TaskDetailPage. Preserves #14137's canceled kanban column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(agent): redirect any agent sub-route before opening new topic

handleNewTopic only checked /profile and /channel, so on /agent/:aid/page,
/agent/:aid/cron/:cronId or other sub-routes the redirect was skipped and
mutate() opened a new topic on a non-chat screen — looking ineffective to
the user. Match useTopicNavigation's pattern: derive an agent base path
from params (with topicId when present) and treat anything longer than
that as a sub-route, so adding new sub-routes never re-introduces this gap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(agent): always push agent chat route before opening new topic

The previous fix conditioned the redirect on isInAgentSubRoute, which
left the URL untouched on /agent/:aid/:topicId — opening a new topic
while the URL still pointed at the previous one. Drop the conditional
and always push /agent/:aid: it covers every sub-route (/profile,
/channel, /page, /cron/:cronId, …) and strips any stale :topicId so
the URL matches the freshly opened topic. Restores Nav.test.tsx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Innei pushed a commit that referenced this pull request Apr 25, 2026
* 💄 style(claude-code): polish ToolSearch inspector tag

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(tasks): preserve topic title when handoff is missing

Task activity rows rendered "Untitled" while the topic was still running
because the activity builder read `handoff.title` (populated post-summary)
and fell back straight to a hardcoded constant. Join `topics` in
`findWithHandoff` and fall through `handoff.title → topics.title → Untitled`
so running topics show the task name instead of "Untitled".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ✨ feat(conversation): add defaultWorkflowExpandLevel to control workflow fold default

Replace WorkflowCollapse.defaultStreamingExpanded (bool) with
defaultWorkflowExpandLevel ('collapsed' | 'semi' | 'full'), threaded
through MessageItem → AssistantGroup → Group → WorkflowCollapse and
exposed on ChatList (applies to the default item renderer only).
When set, pins both the initial state and post-completion reset so
'full' keeps tool-call groups expanded across streaming → complete;
pending intervention still forces expansion.

Apply 'full' in the task detail TopicChatDrawer so viewers see all
tool details by default. Migrate the Onboarding caller from
defaultWorkflowExpanded={false} to defaultWorkflowExpandLevel='collapsed'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(tasks): restart detail polling after data arrives

SWR's function-form refreshInterval is evaluated on effect mount and after each
timer fires. When the first call runs with cache.data=undefined, our function
returned 0 — so no timer was ever scheduled, and polling never started even
after the fetch populated the cache. Drive polling from a reactive zustand
selector instead, so refreshInterval is a stable number that flips once the
task/topic status is known.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 💄 style(tasks): rename paused label to "Pending review"

"Paused" read like the task was stopped by the user. The actual semantic is
"agent has finished a run and is waiting for user to review and nudge it next" —
so rename the label in STATUS_META and the matching i18n keys (status.paused
and the kanban column needsInput). Also promote paused into USER_SELECTABLE_STATUSES
so users can explicitly park a task back into this state from the context menu.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ✨ feat(tasks): add canceled kanban column

Expose a dedicated "Canceled" column in the kanban board so canceled tasks no
longer blend into the done column. Defaults to hidden (alongside done) to keep
the board compact, and maps the new column key through COLUMN_STATUS_ICON plus
the i18n table that KanbanColumn already referenced but was missing an entry
for.

* 💄 style(tasks): brighten priority icon and add label fallback

- Use colorTextSecondary (brighter than colorTextDescription) for non-urgent
  priority icons so they read against the row background.
- Add a static label string to PRIORITY_META so callers can pass it as the
  i18n defaultValue instead of an empty string — prevents unlocalised UI when
  a translation is missing mid-rollout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ✨ feat(tasks): route 1–N hotkeys to hovered status/priority submenu

The task context menu already supported number shortcuts to switch status. Extend
that to priority: when the user hovers the Priority submenu, pressing 1–5 picks
the corresponding priority level. A ref tracks which submenu is active (defaults
to Status on open) so the keydown handler knows which list to index into.

Also pick up meta.label as the i18n defaultValue for priority entries, matching
the new PRIORITY_META field so missing translations fall back to readable text
instead of an empty string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 💄 style(tasks): drop column count from collapsed hidden panel header

The vertical collapsed header was getting noisy with "Hidden · 2" style
duplication — the count is already implied by the expanded tooltip, and the
vertical orientation makes the trailing number crowd the icon.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 💄 style(tasks): show hotkey hint and check in status/priority menu

Surface the 1–N keyboard shortcuts next to each status/priority entry, with a
check icon on the currently selected value. Extract the render into a shared
menuExtra helper so TaskStatusTag and TaskPriorityTag share the same pattern
instead of each inlining its own layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Innei pushed a commit that referenced this pull request Apr 25, 2026
)

* 🔥 feat(tasks): drop per-agent /agent/:aid/tasks routes again

PR #13887 reintroduced the per-agent Tasks surface (sidebar entry, route
files, agentId-scoped breadcrumb/list/board, /agent/:aid/tasks/:taskId
navigation) that #14109 had removed in favor of unified /tasks and
/task/:id. Restore the unified-only model: drop the agent sidebar Tasks
nav item, delete the agent-scoped route files, strip agent-tasks blocks
from both desktopRouter configs, and revert the agentId props and
per-agent navigate paths in AgentTasksPage / KanbanBoard / Breadcrumb /
TaskDetailPage. Preserves #14137's canceled kanban column.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(agent): redirect any agent sub-route before opening new topic

handleNewTopic only checked /profile and /channel, so on /agent/:aid/page,
/agent/:aid/cron/:cronId or other sub-routes the redirect was skipped and
mutate() opened a new topic on a non-chat screen — looking ineffective to
the user. Match useTopicNavigation's pattern: derive an agent base path
from params (with topicId when present) and treat anything longer than
that as a sub-route, so adding new sub-routes never re-introduces this gap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* 🐛 fix(agent): always push agent chat route before opening new topic

The previous fix conditioned the redirect on isInAgentSubRoute, which
left the URL untouched on /agent/:aid/:topicId — opening a new topic
while the URL still pointed at the previous one. Drop the conditional
and always push /agent/:aid: it covers every sub-route (/profile,
/channel, /page, /cron/:cronId, …) and strips any stale :topicId so
the URL matches the freshly opened topic. Restores Nav.test.tsx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant