Add four new sections: How it Works (4-step onboarding guide), Open Source
(self-host / no lock-in highlights), FAQ (centered accordion), and Footer
(link columns + giant logo with Game of Life animation).
Add scroll-driven features section with 4 tabs (Teammates, Autonomous,
Skills, Runtimes) using IntersectionObserver for auto-switching on scroll.
Replace hero placeholder with actual product screenshot. Remove background
gradient overlay.
The inbox left panel had the header inside the overflow-y-auto container,
causing it to scroll away with the list items. Changed to flex-col layout
with shrink-0 header and flex-1 overflow-y-auto content area.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The ListInbox endpoint defaulted to LIMIT 50 while the frontend fetched
all items without pagination, causing items beyond the first 50 to be
silently dropped.
When a user @mentions someone in an issue description (create or update),
the mentioned users were notified via inbox but not added as subscribers.
This adds subscriber registration for mentioned users in both the
issue:created and issue:updated event listeners, mirroring the existing
notification logic.
Add getActiveTaskForIssue, listTasksByIssue, and listTaskMessages mocks
to the issue detail page test. These are now called unconditionally since
the assigneeType guard was removed.
AgentLiveCard and TaskRunHistory were gated on assigneeType === "agent",
so mention-triggered tasks on non-agent-assigned issues never showed
their execution logs. Remove that guard so any issue with agent tasks
displays live output and execution history.
Also populate IssueID in ListTaskMessages response so the live card's
WS event filtering works correctly on catch-up after reconnect.
Rewrite README.md from a developer-focused quick start to a user-facing
project overview covering features, cloud vs self-host, CLI usage, and
architecture. Add SELF_HOSTING.md with complete deployment instructions
including configuration reference, database setup, reverse proxy examples
(Caddy/nginx), agent daemon setup, and upgrade procedures.
Same issue as inbox: without a key, React reuses the AgentDetail
instance when switching agents. This causes activeTab and SettingsTab
form values (name, description, visibility, maxTasks) to persist
from the previously selected agent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the small one-line sonner toast with a richer card showing:
- Green checkmark with "Issue created" title
- Status icon + issue identifier + title on second line
- Clickable "View issue" link to navigate to the new issue
When a task is executed by a mentioned agent (not the assigned one),
the live card now resolves the agent name from activeTask.agent_id
instead of using the assignee-based agentName prop.
When a comment @mentions anyone but not the assignee agent, the
assignee's on_comment trigger is now suppressed. This prevents the
assignee agent from being re-triggered when users share results with
colleagues or ask other agents for help.
The rule: @mention is an intent signal — if you're talking to someone
else, the assignee agent should not respond.
When a user @mentions an agent in any issue's comment, the system now
enqueues a task for that agent. The agent reads the issue context and
replies to the triggering comment thread.
Changes:
- Add shared util.ParseMentions for mention parsing (used by both
comment handler and notification listeners)
- Add EnqueueTaskForMention to TaskService for explicit agent targeting
- Add on_mention trigger type support in agent trigger config
- Add HasPendingTaskForIssueAndAgent SQL query for per-agent dedup
- Add enqueueMentionedAgentTasks in CreateComment handler
Safety: prevents self-trigger (agent mentioning itself), dedup with
assignee on_comment trigger, terminal issue status check, and per-agent
pending task dedup.
Without a key, React reuses the IssueDetail component instance when
switching between inbox items. This causes stale internal state
(e.g. TaskRunHistory tasks) from the previous issue to persist,
showing execution history from a different issue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Load root .env in next.config.ts so REMOTE_API_URL is available
- Default fallback remains localhost:8080 (no impact on existing setups)
- Add REMOTE_API_URL to .env.example with documentation
Comment body was using RichTextEditor in read-only mode which doesn't
support IssueMentionCard rendering. Switch to Markdown component so
mention://issue/ links render as rich cards with status + title.
Instead of regex-parsing markdown content to find attachment URLs
(fragile), the frontend now tracks uploaded attachment IDs and sends
them with the comment creation request. The backend links them by ID.
Frontend: upload returns attachment ID, comment/reply inputs collect
IDs during editing session, pass as attachment_ids on submit.
Backend: CreateComment accepts attachment_ids, links by ID+issue scope.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After creating an issue, a success toast appears showing the issue
identifier (e.g. MUL-72) with a "View issue" action button that
navigates to the issue detail page. Similar to Linear's behavior.
- Add Delete/DeleteKeys/KeyFromURL methods to S3Storage
- DeleteAttachment handler now removes the S3 object after DB delete
- DeleteComment collects attachment URLs before CASCADE, then cleans S3
- DeleteIssue collects all attachment URLs (issue + comment level) before CASCADE, then cleans S3
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Tiptap Mention extension's createInlineMarkdownSpec serializes
mentions as shortcodes [@ id="..." label="..."] — the .extend()
renderMarkdown override may not reliably take effect.
Added a robust fallback: post-process the editor's markdown output
by replacing shortcodes with [@Label](mention://type/id) using the
Tiptap JSON document for type info. Also preprocess stored shortcodes
in the Markdown renderer for backward compatibility.
The API at multica-api.copilothub.ai sets CloudFront signed cookies
with Domain=.copilothub.ai, but fetch() defaults to credentials:
'same-origin'. Since the frontend (multica-app.copilothub.ai) and API
are cross-origin, the browser silently drops Set-Cookie headers without
credentials: 'include'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix mention markdown serialization: use renderMarkdown (tiptap/markdown 3.x API)
instead of addStorage.markdown.serialize which was silently ignored
- Add IssueMentionCard component showing status icon + identifier + title
- Update Markdown renderer to use card for mention://issue/ links
The migration from tiptap-markdown to @tiptap/markdown (38e92040)
changed the getMarkdown API location. The old package stored it at
editor.storage.markdown.getMarkdown(), but @tiptap/markdown adds it
directly as editor.getMarkdown(). This caused getEditorMarkdown() to
always return "", preventing description (and any markdown content)
from being saved when creating or editing issues/comments.
Merge main to pick up 028_task_trigger_comment migration. Renumber
daemon_token migration to 029. Fix execenv tests that expected CLI hints
in issue_context.md after they were moved to CLAUDE.md.
Issue daemon auth tokens (mdt_) on pairing session claim, bound to
workspace_id + daemon_id with 1-year expiry. Add DaemonAuth middleware
that validates these tokens and falls back to JWT/PAT for backward
compatibility. Apply middleware to all daemon routes except pairing
endpoints.
* feat(cli): add `multica update` command
Detects whether multica was installed via Homebrew (by resolving the
binary symlink and checking if it lives under a Homebrew prefix).
- Brew installs: runs `brew upgrade multica` automatically.
- Non-brew installs: prints instructions for installing via brew or
downloading from GitHub releases.
- Checks latest version from the GitHub releases API and skips
the update if already up to date.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(cli): use fully-qualified tap name in brew upgrade
Use `brew upgrade multica-ai/tap/multica` instead of `brew upgrade multica`
to avoid any potential name collision with core formulae.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The migration from tiptap-markdown to @tiptap/markdown in 38e92040
broke comment creation. The old package stored getMarkdown() on
editor.storage.markdown, but the official @tiptap/markdown extension
adds it directly to the editor instance (editor.getMarkdown()).
This caused getEditorMarkdown() to always return "", making the
submit button permanently disabled and preventing any comments.
Also fix stale submitting ref in useIssueTimeline dependency array.