Skip to content

feat: show live activity line on delegated task cards - #1873

Open
mrubens wants to merge 2 commits into
developfrom
claude/sad-shirley-1b956b
Open

feat: show live activity line on delegated task cards#1873
mrubens wants to merge 2 commits into
developfrom
claude/sad-shirley-1b956b

Conversation

@mrubens

@mrubens mrubens commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Fast-session delegated-task cards were static while a task ran — just a title and a Working status. Slack task messages already surface a line of recent activity; this brings the same signal to the web card so the wait during setup-session starter tasks no longer feels dead.

  • New getLatestTaskActivityLine(runId) in apps/web/src/lib/server/task-activity.ts derives the line from the same data source behind the Slack live task card: the most recent meaningful roomote_runtime.assistant_message in task_messages for the run. Reasoning, tool calls, and transient "provider error"/"retrying" narration are excluded (parity with the worker's provisional-completion filter that gates the Slack card).
  • sandboxSession.byTaskId now returns activityLine for in-flight runs only (null once the run exits), so the card's existing 2s poll picks it up with no new client query.
  • DelegatedTaskCard renders it as one truncated text-xs line under the title; when no activity exists yet the card looks exactly as before (plain status fallback). Assistant markdown is flattened to plain text for the single-line render, leaving intra-word underscores (identifiers) intact.

How Slack derives its line (investigated)

The Slack activity line is pushed live from the worker callback stream (apps/worker/src/callbacks/slack-live-task-stream.ts): latest assistant text event, reasoning excluded, todo updates ignored, transient messages filtered. The web can't tap that in-process stream, so this reuses the persisted form of the same events — the run's task_messages rows — matching the query shape of getPersistedConflictResolutionCompletion.

Tests

  • task-activity.test.ts (server, real DB): latest eligible message wins; prompts/reasoning ignored; transient retry/provider-error narration skipped; run isolation; markdown flattening, identifier underscores, truncation.
  • DelegatedTaskCard.client.test.tsx: renders the activity line while working; falls back to the plain status when absent.
  • pnpm lint, pnpm check-types, pnpm knip, and the surrounding sandbox-session / fast-sessions / SessionWorkspace suites pass.

Fast-session task cards were static while a task ran (title + Working).
Surface the latest meaningful assistant message for the in-flight run —
the same data source behind the Slack live task card's activity line —
as one truncated line on the card, updating with the existing 2s poll
and falling back to the plain status when no activity exists yet.
@roomote-community

roomote-community Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

1 issue outstanding. See task

  • apps/web/src/lib/server/task-activity.ts:68 Scan beyond ten transient messages so recovery status does not erase the last activity line.
  • apps/web/src/lib/server/task-activity.ts:62 Use stable pagination while retry rows continue arriving so an eligible activity line cannot be skipped.

Reviewed 364696c

),
)
.orderBy(desc(taskMessages.ts), desc(taskMessages.createdAt))
.limit(10);

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.

Limiting this to 10 rows means the card becomes blank whenever ten transient retry/provider-error messages follow the last eligible update. Those rows are intentionally skipped, while the Slack card retains its prior eligible message. Continue scanning until an eligible row is found (and add a regression test with more than ten transient rows) so the card does not lose its activity line during repeated recovery.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 364696c: the lookup now scans newest-first in batches until it finds an eligible assistant message instead of stopping at 10 rows, so the card keeps its prior activity line through long retry storms. Added a regression test with 25 transient rows stacked on top of the eligible message (crossing the batch boundary).

A hard 10-row limit blanked the card whenever more transient
provider-error/retry messages than that followed the last eligible
assistant message. Scan newest-first in batches until an eligible
message is found, so the card keeps its prior line like Slack does.
// eligible one; scan newest-first in batches until an eligible message is
// found so the card keeps its prior activity line, matching Slack.
const batchSize = 20;
for (let offset = 0; ; offset += batchSize) {

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.

Offset pagination is unstable while the retry storm is still writing rows. If a new transient message lands after the first batch, it shifts the remaining rows down: the next offset(20) can re-read a row from the first batch, then return a short page and null without ever visiting the formerly 21st eligible message. That recreates the blank activity line this change is meant to prevent. Use a stable keyset cursor (including a deterministic tie-breaker) or a single-query approach, and cover an insert between batches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant