- Add zustand draft store with localStorage persistence
- Restore draft fields when reopening create-issue modal
- Clear draft only on successful submission
- Show brand-colored dot on sidebar new-issue button when draft exists
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add stable issue store mock to prevent infinite effect loop in tests
- Update expected error message in not-found test case
- Clear runtime store on workspace switch and set workspace before hydration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CommentInput: remove border-t divider, position submit button inside
editor area (bottom-right) for cleaner look
- CommentCard: add !gap-0 to override Card's default gap-4
- CommentInput/ReplyInput: strip trailing empty lines from markdown
before submit to prevent extra blank lines in rendered comments
- BoardCard: use normal text color for title instead of muted+hover
- Timeline: coalesce same actor + same action within 2 min window,
keeping only the final result (e.g. 5 status changes → 1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace mixed spacing approach (space-y + pb-3) with consistent
flex-col gap-3. Activity connector lines now use absolute positioning
to bridge between icons.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add multi-select with batch update/delete support in the list view.
Users can select issues via checkboxes (per-row or per-status-group)
and apply bulk status, priority, assignee changes or delete via a
floating toolbar.
Show issue identifier and title instead of truncated UUIDs, sort active
tasks to top, highlight running/dispatched tasks, and show contextual
timestamps.
The properties sidebar in the inbox view is not needed by default.
Add defaultSidebarOpen and layoutId props to IssueDetail so inbox
can start with the sidebar collapsed and persist its layout separately.
Re-add issue.identifier (e.g. MUL-42) to the breadcrumb nav that was
incorrectly removed during merge conflict resolution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Increase content max-width to 4xl, use ring-only border on comment
input, and reduce property sidebar value text to text-xs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the click-to-edit h1/Input toggle with a persistent inline
input that saves on blur/enter. Removes duplicate issue ID from
breadcrumbs. Uses a ref to prevent realtime updates from clobbering
in-progress edits.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cards now show muted title text by default that becomes full contrast on
hover, paired with a shadow-md elevation effect. Removes the old
opacity-based hover that made cards fade out.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace inline select + delete button with a three-dot dropdown menu
per member. Adds role descriptions, owner self-demotion protection, and
a cleaner list layout with ring border.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
member:added event now includes workspace_name. Frontend shows a toast
notification when the current user is invited. Also clears stale member
list on workspace switch.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Split 1189-line runtimes-page.tsx into focused sub-components (list, detail, ping, usage, 5 chart files, shared UI, utils)
- Add useRuntimeStore zustand store for shared runtime state across pages (agents page now uses it too)
- Add 7d/30d/90d time range selector to usage charts
- Add full-stack runtime delete: SQL query, Go handler, API route, frontend with confirmation dialog
- Remove unused daemon:heartbeat WS listener (server never broadcasts it)
Add an `instructions` text field to the agent model, allowing users to
define each agent's role, expertise, and working style. Instructions are
injected into CLAUDE.md as an "Agent Identity" section so the agent
knows who it is on every task execution.
- Migration 021: add instructions column to agent table
- Backend: create/update/get agent handlers support instructions
- ClaimTask response includes instructions for daemon injection
- execenv: inject instructions into CLAUDE.md meta-skill
- Frontend: add Instructions tab to agent detail panel
Add per-workspace auto-incrementing issue numbers with a configurable
prefix, producing identifiers like "JIA-1" instead of truncated UUIDs.
Database:
- Add issue_prefix and issue_counter to workspace table
- Add number column to issue table with UNIQUE(workspace_id, number)
- Backfill existing issues with sequential numbers
Backend:
- Issue creation atomically increments counter in a transaction
- API responses include number and identifier fields
- Support issue lookup by identifier format (KEY-N)
- Workspace prefix auto-generated from name, customizable via API
Frontend:
- Display identifier in list rows and issue detail breadcrumb
- Add issue_prefix to Workspace type, number/identifier to Issue type
Add comprehensive data visualization to the runtime detail page:
- Daily token usage stacked area chart and daily cost bar chart
- Model distribution donut chart with cost breakdown
- GitHub-style activity heatmap (13 weeks of daily token usage)
- Hourly task distribution bar chart with new backend endpoint
- Responsive 2-column grid layout for charts on wide screens
Backend: new GET /api/runtimes/{runtimeId}/activity endpoint
returning hourly task counts from agent_task_queue.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactor real-time sync from per-event precise mutations to WS-as-invalidation-signal + debounced refetch.
Backend:
- Add SubscribeAll to Event Bus — auto-broadcasts ALL events, eliminates manual 25-item allEvents list
- Add skill event constants to protocol, fix skill handler string literals
- Add title_changed activity tracking
Frontend:
- WSClient: add onAny() method for wildcard event subscription
- useRealtimeSync: rewrite to refreshMap + prefix routing + 100ms debounce
- Precise handlers only for side effects: workspace:deleted, member:removed, member:added (self-check)
- Reconnect now refetches all stores (fixes missing members/skills/workspace refresh)
- Stale-while-revalidate: fetch() only shows loading spinner on initial load, not on refetch
- Remove redundant useWSEvent in agents/page.tsx and skills-page.tsx
- WSClient.disconnect() now clears all handler registrations
Inbox bugfixes:
- Unify sidebar badge count with page count via dedupedItems + unreadCount in store
- Sort by time DESC (removed severity-first ordering)
- Ellipsis on truncated detail labels
UI:
- Status/Priority pickers: replace RadioGroup with MenuItem for auto-close on selection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add missing notifications for priority_changed and due_date_changed events
- Publish priority_changed and due_date_changed flags from UpdateIssue handler
- Add details JSONB column to inbox_item (migration 019) for structured change data
- Store from/to values in details for status, priority, assignee, and due_date changes
- Notification titles now use plain issue title; details carry structured context
- Add human-readable label maps (statusLabels, priorityLabels) in notification listeners
- Update inbox handler responses to include details field
- Frontend: InboxDetailLabel renders rich subtitles per notification type
- Status: "Set status to ● In Progress" with StatusIcon
- Priority: "Set priority to ◆ High" with PriorityIcon
- Assigned: "Assigned to Bob" with resolved actor name
- Due date: "Set due date to Apr 20"
- Comment: truncated comment body preview
- Frontend: HoverCard on inbox items shows issue title + description context
- Add due_date_changed to InboxItemType and typeLabels
- Add tests for priority_changed and due_date_changed notifications
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract shared timeAgo utility, remove duplicates from comment-card and issue-detail
- Remove unused replies prop from CommentCard
- Fix recursive delete to remove all descendant replies, not just direct children
- Improve formatActivity with human-readable status/priority labels and actor names
- Validate parent comment exists and belongs to same issue before creating reply
- Add priority_changed activity recording in activity listeners
- Fix activity SQL query to sort ASC (was DESC, then re-sorted in handler)
- Fix reply-input layout alignment and test submit button selector
- Minor: .gitignore additions, button dark mode aria-expanded fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove Card double padding (Card py-4 + inner px-4 was too much, override with !py-0)
- Use lighter border-border/50 for reply separators inside Card
- Create CommentInput component for bottom "Leave a comment" — no avatar, full
width editor, submit button in footer row below editor
- ReplyInput stays for in-card "Leave a reply" — has avatar, compact inline layout
- Two different components for two different use cases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace recursive Card-in-Card with flat thread layout:
- One Card per comment thread, parent + all replies flat inside
- Replies separated by border-t, not nested Cards
- CommentRow component handles each individual comment (header + content + edit)
- Three-dot menu shows active state when open (data-[popup-open])
- ReplyInput simplified: avatar + editor + submit button, no extra border container
- Nested replies collected recursively but rendered flat
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Activity entries now show ActorAvatar instead of a small dot (consistent with comments)
- Remove All/Comments/Activity filter toggle (comments are just a type of activity)
- Remove one-level reply restriction in backend (allow nested threading)
- Remove unused Circle import
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a parent comment is deleted, remove all its replies from the timeline
instead of promoting them to top-level (orphaned replies have no context).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix activity:created WS payload to match frontend expectations
(issue_id at top level, entry as TimelineEntry object)
- Promote child comments to top-level when parent is deleted
(both in handleDeleteComment and WS comment:deleted handler)
- Enforce one-level reply nesting: reject replies to replies with 400
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the comment-only list with a Linear-style unified timeline that
interleaves field changes and comments chronologically.
Backend:
- activity_listeners.go: records field changes (status, assignee, description,
task completed/failed) to activity_log table on domain events
- Timeline API: GET /api/issues/{id}/timeline merges activity_log + comments
sorted by created_at
- Comment reply: parent_id column + handler support for threading
Frontend:
- Unified timeline replaces comment list: activity entries as compact muted
lines, comments as Card components with reply threading
- Filter toggle (All / Comments / Activity)
- Reply UI: inline editor under comments with Cancel/Reply buttons
- Real-time sync for activity:created + comment events
- 10 new Go tests, all passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove commenter/mentioned/manual reason labels — users only need to see
who created and who is assigned. Other reasons add noise without value.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consistent with subscriber:added handler. Prevents removing a member subscriber
when an agent with the same UUID is unsubscribed (or vice versa).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When subscribing, both the optimistic setSubscribers and the WS subscriber:added
event could add the same entry. Now both paths check for existing entries using
(user_id + user_type) composite key before appending.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Members array from workspace store can contain duplicate user_ids (e.g. user
added to workspace twice). Filter by unique user_id before rendering to prevent
React duplicate key warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: backend hardcoded UserType="member" in subscribe/unsubscribe handlers,
so unsubscribing an agent actually tried to delete a member record (no-op), and
the WS event broadcast wrong user_type causing other subscribers' UI to break.
- Backend: accept optional user_type in subscribe/unsubscribe request body
- Frontend: pass userType through API client to backend
- Fixes: clicking agent checkbox no longer affects member subscriptions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix duplicate React key by using composite key (type-id) for avatars and command items
- Add Agents section to subscriber Command popover (members + agents both selectable)
- Fix subscriber matching to use both user_type and user_id (prevents cross-type collisions)
- Add max-h-64 to CommandList to prevent overflow
- toggleSubscriber now accepts userType parameter for proper agent support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Backend: subscribe/unsubscribe API now accepts optional user_id to manage other users
- Frontend: replace manual avatar stacking with shadcn AvatarGroup component
- Frontend: replace disabled-checkbox Popover with Command+Popover combo (Linear-style)
- Search/filter workspace members
- Click to toggle subscription (checkbox)
- Shows reason badge (Assignee, Creator, etc.) for auto-subscribed users
- Clean up duplicate status_change type (keep only status_changed)
- All tests pass (Go + TypeScript)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add new_comment, unassigned, assignee_changed, priority_changed, status_changed
to InboxItemType and typeLabels so inbox renders proper labels instead of raw
type strings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add comment explaining subscriber→notification listener registration order in main.go
- Add issue_status field to notifySubscribers and notifyDirect (fixes missing StatusIcon in inbox)
- Backfill existing commenters as subscribers in migration 016
- Add TODO comment for @mention duplicate notification prevention (deferred until @mention feature is enabled)
- Add context.Background() usage note for future bus-level timeout improvements
- Add toast error feedback on subscribe/unsubscribe failure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace inbox_listeners.go with a subscriber-driven notification system:
- Add issue_subscriber table with auto-subscribe on create/assign/comment
- New subscriber_listeners.go: maintains subscriber data on domain events
- New notification_listeners.go: notifySubscribers (fanout to all subscribers
minus actor) and notifyDirect (targeted, punches through unsubscribe)
- Subscriber API: list/subscribe/unsubscribe endpoints
- Frontend: subscribers section in issue detail sidebar with real-time sync
- Frontend: inbox notification grouping by (issue_id, type, actor_id)
- Remove createInboxForIssueCreator from task.go (unified through event bus)
- 21 new Go tests, all passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Runtime page: add ResizablePanelGroup with persistent layout, fix scroll
- Agents page: replace hand-rolled dropdowns with shadcn Popover/DropdownMenu,
remove redundant wrapper div, fix header height to h-12
- Skills page: widen create dialog to sm:max-w-md, stabilize tab height
- Settings: use variant="destructive" on AlertDialogAction instead of hardcoded className
- Issues list view: rewrite with base-ui Accordion grouped by status,
show all statuses (including empty), add per-group create button,
persist expand/collapse state, apply sort settings
- Issues header: show filtered issue count next to New Issue button
- Extract shared sortIssues utility from board-column for reuse
- Remove redundant StatusIcon from ListRow (already grouped by status)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace simple text buttons with macOS-style window preview cards for
Light/Dark/System theme selection, using pure CSS miniature window mockups.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add inline pickers on board cards for priority, assignee, and due date
- Add custom trigger prop to PriorityPicker, AssigneePicker, DueDatePicker for styling control
- Replace due date quick options with Calendar-based DueDatePicker in issue detail sidebar
- Use PickerWrapper to stop event propagation from pickers to Link/drag handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Redesign card layout: priority label, description line, subtle shadow, configurable properties
- Wider columns (280px) with rounded background, count badge, and card spacing
- Add SortableContext for within-column drag reordering with fractional position indexing
- Fix collision detection to prefer card targets over column droppables for reliable down-drag
- Add hidden columns panel on right side with show/hide toggle
- Consolidate header into Filter popover (status + priority) and Display popover (ordering + card properties)
- Auto-switch to manual sort when cards are dragged to preserve drag ordering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>