* feat(agents): reply as thread instead of top-level comment
When an agent responds to a user comment, the reply is now nested under
the triggering comment (parent_id) instead of appearing as a separate
top-level comment. Also enables on_comment trigger by default for newly
created agents.
- Add trigger_comment_id column to agent_task_queue (migration 028)
- Pass triggering comment ID through EnqueueTaskForIssue → task → createAgentComment
- Include parent_id in WebSocket broadcast for agent comments
- Default agent creation includes both on_assign and on_comment triggers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(cli): add --parent flag to comment add for threaded replies
The agent posts comments via the CLI, so the correct fix is giving it a
--parent flag rather than wiring trigger_comment_id through the task
infrastructure. The agent reads the comment list, decides which comment
to reply to, and passes --parent <comment-id>.
- Add --parent flag to `multica issue comment add`
- Update agent runtime instructions to explain --parent usage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(daemon): pass trigger_comment_id to agent execution context
The agent now knows which comment triggered its task and gets an explicit
instruction to reply to it using --parent. The trigger_comment_id flows
from the DB through the claim response, daemon Task struct, and into
issue_context.md where the agent sees it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(comments): agent replies to thread root, matching frontend behavior
When the triggering comment is itself a reply (has parent_id), resolve
to the thread root so the agent's reply stays in the same flat thread.
This matches the frontend where all replies share the top-level parent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(cli): show parent_id and full IDs in comment list
The table output now includes a PARENT column and shows full comment IDs
(not truncated) so agents can see thread structure and use --parent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(daemon): instruct agents to always use --output json
Agents now see explicit guidance to use --output json for all read
commands, ensuring they get structured data with full IDs and parent_id
for proper threading.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(daemon): differentiate comment-trigger vs assign-trigger context
When triggered by a comment, the agent now gets clear instructions:
- Primary goal is to read and respond to the comment
- Do NOT change issue status just because you replied
- Only change status if explicitly requested
This prevents the agent from seeing "In Review" and stopping, since
it now understands the task is to reply, not to re-evaluate the issue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(daemon): split workflow by trigger type in CLAUDE.md/AGENTS.md
The Workflow section in the agent's runtime config now shows a
comment-reply workflow when triggered by a comment (read comments,
find trigger, reply, don't change status) vs the full assignment
workflow (set in_progress, do work, set in_review).
Previously the agent always saw the assignment workflow, causing it
to check the issue status, see "In Review", and stop without reading
or replying to the triggering comment.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(daemon): remove duplicate workflow from issue_context.md
Workflow instructions now live only in CLAUDE.md/AGENTS.md (runtime_config.go).
issue_context.md keeps just the task data: issue ID, trigger type, and
triggering comment ID.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(task): skip duplicate comment on completion for comment-triggered tasks
When triggered by a comment, the agent posts its own reply via CLI
with --parent. The task completion path was also creating a comment
from the agent's stdout output, resulting in duplicates. Now only
assignment-triggered tasks auto-post output as a comment. Error
messages from FailTask are still posted regardless of trigger type.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend WS messages now include actor_id from the Event struct.
Frontend useRealtimeSync skips the debounced refetch when the event
was triggered by the current user, eliminating unnecessary re-renders
of heavy components (~400ms after each user action).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a new "My Issues" page accessible from the sidebar, positioned
between Inbox and Issues. Issues are grouped into three collapsible
sections: assigned to me, assigned to my agents, and created by me.
Add Assignee and Creator filter categories to the issue board filter menu,
using DropdownMenu sub-menus with hover-visible checkboxes (shadcn official
data-selected pattern from PR #6862).
Key changes:
- view-store: add assigneeFilters, includeNoAssignee, creatorFilters state
with positive selection model (empty = no filter, selected = show only matching)
- issues-header: two-level DropdownMenu — category list → sub-menu with
searchable checkbox items, issue counts, avatar grouping (Members/Agents)
- utils/filter: extract shared filterIssues() to eliminate duplication
between issues-page and issues-header
- Workspace switch clears actor filters via deferred subscription
(dynamic import to avoid circular dependency)
- 10 new filter behavior tests covering assignee, creator, no-assignee,
and combined filter scenarios
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace semi-transparent glassmorphism menus with solid popover backgrounds.
Re-downloaded dropdown-menu, context-menu, select, combobox, menubar, and
button via `npx shadcn add --overwrite`. Also removed `focus:**:text-accent-foreground`
from DropdownMenuCheckboxItem to prevent color cascade into nested components.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Status labels use colored pill badges (solid bg for active, muted for inactive)
- Board columns have tinted backgrounds matching their status color
- Priority badges use orange (--priority) design token for clear distinction from status
- Issue cards restructured: identifier, title, then assignee/priority/date row
- Agent avatar default color changed from blue to gray
- New Issue button in header changed to solid/primary style
- Reduced hover shadow on board cards
- Added inheritColor prop to StatusIcon and PriorityIcon for badge use
Server-side (primary): Apply redact.Text/InputMap on task message
content, output, and input fields before DB persistence and WebSocket
broadcast. Extended redact package with GitLab tokens, JWTs, connection
strings, and PASSWORD/SECRET/TOKEN env var patterns.
Frontend (fallback): redactSecrets utility mirrors server patterns,
applied in buildTimeline and ToolCallRow render as a safety net.
Browser UA stylesheet sets font-family: monospace on <code> and <pre>,
overriding the inherited Geist Mono from parent containers. Apply
font-mono explicitly on these elements so they use the project's
monospace font instead of the browser default.
- Fix duplicate icons in tool call rows (use chevron only for expand/collapse)
- Show detailed tool information (WebSearch queries, Agent prompts, Skill names)
- Add thinking/reasoning rows with Brain icon and expandable content
- Show tool results as separate chronological entries with previews
- Add TaskRunHistory component for viewing past agent execution logs
- Add listTasksByIssue API endpoint and task-runs route
- Support thinking content blocks in agent SDK (MessageThinking type)
- Improve callID→toolName mapping in daemon message forwarding
When an agent is working on an issue, users can now see real-time output
in the issue detail page instead of waiting for completion.
Backend:
- Add task_message table and migration for persisting agent messages
- Add POST /api/daemon/tasks/{id}/messages endpoint for daemon to report
structured messages (tool_use, tool_result, text, error) in batches
- Add GET /api/daemon/tasks/{id}/messages for catch-up after reconnect
- Add GET /api/issues/{id}/active-task to check for running tasks
- Broadcast task:message events via WebSocket
- Daemon forwards agent session messages with 500ms text throttling
Frontend:
- Add AgentLiveCard component showing live tool calls, text output,
and progress indicators with auto-scroll
- Wire into issue detail timeline with WS subscription and HTTP catch-up
- Card appears when agent is working, disappears on completion/failure
Add Slack-style emoji reactions to comments and issue descriptions with
full-stack support: database tables, REST API endpoints, real-time
WebSocket sync, optimistic UI updates, and inbox notifications.
- New `comment_reaction` and `issue_reaction` tables with migrations
- POST/DELETE endpoints for adding/removing reactions on both comments
and issue descriptions
- Real-time WS events (reaction:added/removed, issue_reaction:added/removed)
- Shared ReactionBar component with quick emoji picker and full emoji-mart
picker (lazy-loaded)
- Optimistic add/remove with rollback on failure
- Inbox notifications for comment author and issue creator when reacted to
- Reactions included in timeline, comment list, and issue detail responses
- Add redact package to detect and mask secrets (AWS keys, private keys,
API tokens, bearer tokens, credentials, home paths) in agent output
before posting as comments in TaskService
- Enforce agent visibility on issue assignment: private agents can only
be assigned by their owner or workspace admins
- Add visibility picker (workspace/private) to CreateAgentDialog,
default to private
- Grey out unassignable private agents in the assignee picker with
lock icon indicator
The backend already supports on_comment triggers but the frontend was
missing the UI to configure them. Adds the "On Comment" trigger type
and "Add On Comment" button alongside the existing On Assign and
Scheduled options.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Set openOnClick: true so clicking a link opens it in a new tab
- Add Cmd+Click / Ctrl+Click handler as fallback (skips mention:// links)
- Override prosemirror-markdown link serializer to always use [text](url)
format instead of <url> autolink syntax, fixing angle brackets appearing
when copying links from the editor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
router.replace() triggers a full server navigation cycle in Next.js 15+,
which can stall after a page refresh (no client route cache), preventing
useSearchParams from updating and making inbox items unclickable.
window.history.replaceState() updates the URL synchronously without
triggering server navigation, which is the recommended approach for
URL state management in Next.js 14.1+.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add items-center for vertical centering between icons and text
- Add truncate on activity text to prevent line wrapping
- Unify icon/avatar sizes to 16px for visual consistency
- Remove connector line (will revisit later)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>