feat(timeline): agent activity timeline panel for a task#618
Conversation
Build a chronological, live-updating activity timeline of a task's
lifecycle from the event_log: state transitions (queued -> processing ->
blocked -> done), retries, blocks, and completion with real timestamps
and short labels.
- db: GetTaskTimeline() maps event_log rows into labeled, chronological
entries; status transitions render as "queued -> processing". Status
changes now persist their old/new values in event_log metadata, and
RetryTask records a distinct task.retry event.
- ui: Activity Timeline section in the detail view, refreshed on the
periodic Refresh() tick so it updates live as new events land.
- web: GET /api/tasks/{id}/timeline endpoint plus live "timeline" SSE
events on the existing per-task stream for the web detail page.
- tests: db timeline builder + labels, web endpoint, and live TUI refresh.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
QA surfaced that the blocked/done status transitions were each shown twice — once as a "processing -> blocked" transition and again as a bare "Blocked"/"Completed" lifecycle row emitted at the same second. Suppress the redundant lifecycle rows (keeping any real blocked reason) so each block/finish appears once, and key the TUI icon off the transition's target status (done -> check, blocked -> stop, etc). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
✅ QA: Agent activity timelineDrove the real ty TUI + web API against an isolated throwaway instance ( TUI detail view — Activity TimelineRenders chronologically with real timestamps, status-aware icons, and the retry feedback. The redundant bare Web API —
|

Summary
Gives a task a compact, chronological activity timeline of its lifecycle, built from the
event_logand updating live via the existing SSE feed. Borrows the "agent state timeline" idea from herdr-insight.A task now shows an accurate, ordered event timeline with real timestamps — state transitions (
queued → processing → blocked → done), retries, blocks, and completion — that updates live as new events land.Changes
internal/dbGetTaskTimeline(taskID, limit)builds chronological (oldest-first)TaskTimelineEntryvalues fromevent_log, mapping each row to a short label (Created,Completed,Blocked,Retried, andqueued → processingstyle transitions).{old,new}values in theevent_logmetadata column (recordEventMeta/marshalEventMetadata), so transition labels are accurate.RetryTaskrecords a distincttask.retryevent so retries are visible on the timeline.internal/ui(TUI detail view)Refresh()tick and folded into the render cache key, so it updates live as events land (no manual reopen).internal/webGET /api/tasks/{id}/timelinereturns the timeline as JSON with real UTC timestamps.timelineevents as new lifecycle events occur, so the web detail page can update live.Tests
internal/db: timeline builder (chronological order, transitions, retry, limit, empty) + label mapping table.internal/web: timeline endpoint (shape, RFC3339 timestamps, transition label) + invalid-id.internal/ui: timeline renders in detail content and updates live after a new event onRefresh().go build ./...,go testfor the three touched packages, andgolangci-lint run(v2.8.0) all pass.Follow-ups
internal/web/ui/dist, built out-of-repo behind theuibuild tag) needs a small frontend change to render the new endpoint/SSEtimelineevents; the backend API + stream are ready for it.🤖 Generated with Claude Code