Commit Graph
5777 Commits
Author SHA1 Message Date
207a4bf4e9 feat(ui): raise tooltip open delay to 500ms with instant hand-off (MUL-8313) (#9623)
* feat(ui): raise tooltip open delay to 500ms with instant hand-off (MUL-8313)

- One TOOLTIP_OPEN_DELAY (500ms) shared by TooltipProvider and
  DeferredTooltip; drop the hard-coded 200 in the theme provider and the
  redundant nested provider in the create-issue footer.
- Make the instant window explicit (TOOLTIP_INSTANT_WINDOW, 400ms, Base UI's
  default) and let DeferredTooltip, which Base UI's delay group never sees,
  join it: tooltip popups record when they mount and unmount, and a deferred
  tooltip hovered while one is showing or just closed opens immediately.
- Close delay stays 0.

Co-authored-by: multica-agent <[email protected]>

* chore: remove accidentally committed pr-body.md

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 15:09:56 +08:00
Multica Eveandmultica-agent 55be334864 fix(taskfailure): classify Kiro dispatch failure as retryable provider_network (MUL-8314) (#9621)
Co-authored-by: multica-agent <[email protected]>
2026-10-28 15:01:37 +08:00
3647fd2245 feat(ui): use TruncatedTooltip for truncated labels across the app (MUL-8313) (#9618)
* feat(ui): use TruncatedTooltip for truncated labels across the app (MUL-8313)

Replace native title attributes (and one plain Tooltip) whose content only
repeats a truncated label with TruncatedTooltip, so the full text shows in the
design-system tooltip and only when it is actually cut off.

TruncatedTooltip now builds on DeferredTooltip, which gains a shouldOpen
guard, so nothing but the trigger mounts until the first hover. That keeps it
cheap in dense surfaces such as table cells, board column headers, and label
chips.

Co-authored-by: multica-agent <[email protected]>

* fix(ui): open TruncatedTooltip on keyboard focus and wrap long values (MUL-8313)

- DeferredTooltip gains an opt-in openOnFocus path (open on focus, close on
  blur, same popup/shouldOpen gates; focus caused by a pointer press stays
  closed) and a contentClassName. TruncatedTooltip enables both, restoring
  the keyboard full-name tooltip in the project picker.
- TruncatedTooltip lets the bubble break long unbroken values (hashes, URLs)
  so they wrap inside the max-width popup instead of overflowing it.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 14:25:41 +08:00
FrezcandFrezc a8e7561421 [MUL-8300] fix(lark): resolve outbound references to workspace links (#9604)
* fix(lark): resolve outbound references to workspace links

* test(wecom): use normal budget for no-holder state assertion

* fix(channel): preserve Markdown reference source boundaries

* fix(lark): format references with one workspace lookup

* fix(deps): update x/net for HTML parser advisory

---------

Co-authored-by: Frezc <[email protected]>
2026-10-28 14:06:16 +08:00
d51665feb6 feat(ui): show project picker name tooltip only when truncated (MUL-8313) (#9617)
Add TruncatedTooltip, a wrapper over the shared Tooltip that measures the
trigger right before opening and stays closed when no descendant clips its
content. PickerItem gains a truncationTooltip prop, and the project picker
uses it so short project names no longer pop a redundant bubble.

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 13:47:36 +08:00
ca593b3103 MUL-8302: fix(daemon): preserve task environment in Hermes tool shells (#9607)
* fix(daemon): preserve task environment in Hermes tool shells

* fix(daemon): complete Hermes task env and preserve derived isolation (MUL-8302)

Co-authored-by: multica-agent <[email protected]>

* fix(deps): patch x/net HTML vulnerability (MUL-8302)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 13:45:15 +08:00
d9f5dee413 fix(projects): reveal full project names in the picker (MUL-8291) (#9591)
* fix: show full project names in the project picker

* test(projects): drop picker tooltip tests

The change is a one-line reuse of PickerItem's existing tooltip; the
added tests mostly exercised that shared primitive.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 13:35:13 +08:00
3e4dcef95f MUL-8312: fix(i18n): unify Chinese review copy across clients (#9615)
* fix(i18n): translate in_review as 審查 in zh-Hant copy

The zh-Hant strings rendered 审核 as the rare form 稽覈. Use 審查,
matching the existing zh-Hant agents and squads copy.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* fix(i18n): align Chinese review request notifications

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Yushen <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 13:31:53 +08:00
mrlonely 84e56b6b00 MUL-8256 fix(runtime): recover stalled HTTP/2 connections (#9551)
* fix(daemon): recover stalled HTTP/2 control-plane connections

* fix(daemon): recover stalled skill bundle connections

* fix(runtime): share HTTP/2 recovery across persistent clients
2026-10-28 13:08:35 +08:00
JimmyChia 8ffcc88dbd fix(desktop): show spelling suggestions in right-click menu (#9608) 2026-10-28 10:10:14 +08:00
6388272a8a fix(github): skip PR merge status move when the project workflow lacks the target (#9598)
A merged PR moved its issue to the workspace's pr_merge_status even when the
issue's project workflow does not list that status, bypassing the check a
manual status change goes through. The decision now loads the project
workflow and returns not_in_workflow instead; the issue page renders nothing
for it, so the issue silently stays where it is. Default workflows and issues
outside any project are unchanged.

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-28 10:04:38 +08:00
Bohan Jiangandmultica-agent d7d1831fcf feat(cli): add run-targeted retries with a fresh option (#9592)
Co-authored-by: multica-agent <[email protected]>
2026-10-27 18:18:32 +08:00
Multica Eveandmultica-agent a008d893dd MUL-8292: refactor(brief): move Available Commands detail behind --help (#9596)
* MUL-8292: refactor(brief): move Available Commands detail behind --help pointers

Each bullet keeps its signature and the behaviour needed at the call site;
wakeup condition catalogue, PR snapshot mechanics, actor filters and the
repeated file rules now live only in --help and the multica-platform
references. Issue brief 17,300 -> 16,372 bytes (-928); chat and autopilot
briefs drop by the same amount. New TestAvailableCommandsKeepsCompressedContracts
pins the kept contracts and guards the moved detail from drifting back.

Co-authored-by: multica-agent <[email protected]>

* MUL-8292: fix(brief): keep Available Commands rules self-contained in every kind

Review follow-up on #9596:
- comment list / issue create / comment add pointed at Workflow step 2 and
  Comment Formatting, which chat and autopilot briefs do not have; the
  bounded-read recipe and the workdir file rule are inline again.
- repo checkout restores both keep conditions and the clean-checkout case.
- wakeup scopes last_error to missing PR links/snapshots; a pending check or
  unmet condition records nothing.
Contract test now runs every kind x provider, and a new test fails when the
shared section references a heading or workflow step the kind lacks.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-27 18:17:27 +08:00
Multica Eveandmultica-agent aec9b0b169 MUL-8287: docs(changelog): release 0.7.1 (#9593)
* docs(changelog): release 0.7.1

Co-authored-by: multica-agent <[email protected]>

* docs(changelog): retitle 0.7.1 and tighten wording

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-27 17:39:22 +08:00
Multica Eveandmultica-agent 317e17f123 MUL-8287: fix(web): stop sending workspace titles to Google Analytics (#9595)
* fix(web): report route labels as GA page_title instead of workspace titles

Co-authored-by: multica-agent <[email protected]>

* fix(web): pin GA page_title via set so navigation updates take effect

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-27 17:03:32 +08:00
0a83848c0d MUL-8284: docs(agents): require buy-in for speculative edge cases; trim duplicated rules (#9585)
* docs(agents): require buy-in before adding speculative edge-case complexity (MUL-8284)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* docs(agents): trim duplicated rules (MUL-8284)

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 15:58:26 +08:00
984d9db74b MUL-7695: fix(desktop): stop daemon before Windows update install (#9582)
* fix(desktop): stop bundled daemon before Windows update install (MUL-7695)

On Windows the running daemon locks the bundled multica.exe. The NSIS
installer only replaces it when it can kill the daemon via PowerShell/CIM;
otherwise its Retry path extracts while ignoring errors and the old daemon
binary silently survives the update (#8823).

Stop the daemon from the app before handing off to the installer:
- "Restart to update": stop an idle daemon and wait for the process to
  exit; with active tasks, ask to install now, install when tasks finish,
  or cancel.
- Quit-time auto install: stop an idle daemon first; with active tasks,
  skip this quit's install instead of letting the installer kill them.
- Bounded by a 15s timeout that falls back to the previous installer
  behaviour, and resumes the daemon if quitAndInstall never quits.

macOS and Linux are unchanged.

Co-authored-by: multica-agent <[email protected]>

* fix(desktop): cancel stale update preparation and coordinate quit

Co-authored-by: multica-agent <[email protected]>

* fix(desktop): keep the daemon exit barrier across update flow handoff

A superseding update flow (quit during Restart to update, or a manual
install during a deferred stop) used to abort the old flow, resume the
daemon, and treat the vanished /health endpoint as ready while the old
PID was still holding multica.exe.

- Record the PID and original deadline once an update stop is actually
  issued; a successor whose probe finds /health gone keeps waiting on it.
- Handoff no longer resumes the daemon; flows that end without
  installing (cancel, wait, busy quit, error) resume it instead.

Co-authored-by: multica-agent <[email protected]>

* fix(desktop): inherit the issued stop barrier while health still responds

A successor update flow only reused the earlier stop's PID barrier when
/health had already vanished. If the same daemon was still answering while
draining, it re-stopped it and restarted the 15s clock, stretching the
agreed upper bound on waiting.

Prefer an existing barrier for the same PID regardless of health, skip
the busy check for a daemon whose stop was already issued, and drop the
barrier only when a different PID is live.

Co-authored-by: multica-agent <[email protected]>

* fix(desktop): keep waiting on a draining PID when a new daemon starts

A different live PID does not prove the previously stopped daemon has
exited: legacy CLIs take no profile lock, so a Start from the runtime card
can bring up a successor while the old process still holds multica.exe.

Track every issued update stop as its own barrier. A successor stops the
new daemon as usual but stays blocked until each barrier PID has exited or
reached its own deadline; barriers are cleared only on a settled result or
when the install is abandoned, and kept when the new daemon is busy.

Co-authored-by: multica-agent <[email protected]>

* fix(desktop): simplify Windows update shutdown coordination

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
Co-authored-by: Bohan-J <[email protected]>
2026-10-27 15:47:51 +08:00
Sodaandmultica-agent b8306f975c MUL-7130: feat(issues): add overview and sub-issues to the outline (#8135)
Rebased onto current main. The outline now carries reply ticks and folds
resolved threads, so the description and sub-issues destinations are rebuilt
on that item model: they are prepended as section items, keep their ticks
when reply ticks drop past MAX_RAIL_TICKS, and the active row is tracked by
item id instead of position so sub-issues appearing or a thread folding no
longer shifts the highlight. Adds the new strings to fr and zh-Hant.

Co-authored-by: multica-agent <[email protected]>
2026-10-27 15:04:07 +08:00
188971168d fix(runtimes): spell out Qoder Cloud Agents instead of QCA (MUL-8282) (#9581)
* fix(runtimes): spell out Qoder Cloud Agents instead of QCA

The UI, docs, landing copy and server messages called the product "QCA"
in labels such as "QCA Agent", "QCA runtime" and API errors like "QCA
token is required". Use the full name Qoder Cloud Agents everywhere a
person reads it, and add it to the brand list in the naming conventions
so the abbreviation does not come back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* fix(runtimes): refine Qoder Cloud Agents copy (MUL-8282)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: 安辰 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 14:06:52 +08:00
ac673fbf19 MUL-7384: fix(onboarding): require confirmed daemon setup targets (#8907)
* fix(onboarding): show self-host setup command when daemon URLs configured (fixes #8425)

* fix(onboarding): fail closed until daemon setup target is confirmed (MUL-7384)

Co-authored-by: multica-agent <[email protected]>

* fix(onboarding): preserve legacy self-host setup commands (MUL-7384)

Co-authored-by: multica-agent <[email protected]>

* fix(i18n): restore Traditional Chinese locale parity (MUL-7384)

Co-authored-by: multica-agent <[email protected]>

* test(daemon): pin Pi upstream cancellation handoff (MUL-7384)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 13:19:05 +08:00
c11b3375f5 MUL-8269: fix(runtimes): price Bedrock-served Anthropic ids and DeepSeek-V4.1-Flash (#9561)
* fix(runtimes): price Bedrock-served Anthropic ids and DeepSeek-V4.1-Flash

Bedrock reports Anthropic models as `<region>.anthropic.<id>` with an
inference-profile version on snapshots (`us.anthropic.claude-sonnet-5`,
`eu.anthropic.claude-sonnet-4-5-20250929-v1:0`). Neither resolver accepted
that shape: the backend alias rules anchor on `/`, `:` or start-of-string,
and the frontend `canonicalCandidates` only strips `/` and `:` routing
prefixes, so the vendor and region prefixes survived into the lookup. Every
Bedrock-served turn therefore missed the rate table and rendered as $0.00
plus an "unmapped models" warning, while the tokens were still counted in
`task_usage` (cost_usd_ticks is provider-reported and NULL for Anthropic, so
nothing else was pricing them either).

Strip the Bedrock vendor/region prefix and the `-v<digit>:<digit>` profile
version on both sides, before the existing dot↔dash normalisation. Only
`anthropic.`-prefixed ids are rewritten, so non-Anthropic Bedrock models
(`us.amazon.nova-*`) stay unmapped rather than borrowing a Claude rate.

DeepSeek-V4.1-Flash is also missing: the catalog lists v4-flash and v4-pro
only, and there is deliberately no family fallback, so `deepseek-v4.1-flash`
and OpenRouter's dated `deepseek-v4.1-flash-1017` both went unpriced. Add the
official `deepseek-flash` sheet rate ($0.15/$0.60, cache read $0.003, cache
write mirrors input) and one alias rule that admits the dated snapshot —
DeepSeek documents that id as the model actually served for the undated slug,
so it is the same SKU at the same rate, not a second tier.

Both tables are updated together (server/internal/metrics/pricing.go drives
the Prometheus counters, packages/views/runtimes/utils.ts drives the
dashboard) and both suites pin the new ids, including the negative cases: a
later SKU, a `-preview` qualifier or a non-Anthropic Bedrock id must stay
unmapped.

* ci: re-run (previous backend-tests failure was in channel-media reconciler timing tests, unrelated)

* fix(runtimes): align Flash pricing and constrain Bedrock aliases (MUL-8269)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 13:02:58 +08:00
16a067f30a MUL-8270: fix(db): keep lease claims within query limits (#9563)
* fix(storage): claim one cleanup object per statement

* fix(tasks): bound stale dispatch recovery candidates

* fix(db): restore English lease claim documentation

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 12:59:48 +08:00
73f5664ca4 MUL-8263 fix(agents): reject reserved custom arguments on save (#9560)
* fix(agents): reject reserved custom arguments on save

* fix(agents): validate OMP session arguments before saving

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 12:59:25 +08:00
bcf40040e0 MUL-8233: fix Pi cancellation and guard unconfirmed cleanup (#9557)
* fix(agent): join Pi cancellation cleanup and guard continuation

Co-authored-by: multica-agent <[email protected]>

* fix(agent): preserve Pi completion and negotiate cleanup

Co-authored-by: multica-agent <[email protected]>

* perf(agent): avoid Pi exit delay and index cleanup guards

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 12:37:13 +08:00
Multica Eveandmultica-agent e3f265ae5a MUL-8280: refactor(issues): trim issue sidebar header actions (#9580)
* MUL-8280: refactor(issues): trim issue sidebar header actions

- Drop settings-only '…' menus from Properties, Quick Actions, Wakeups
  and Plugins; keep the Pull requests menu, which carries a per-issue
  action (keep status on merge).
- Remove the Quick Actions '+' (workspace-level creation belongs in
  Settings) and hide the section again when there are no actions.
- Restore the inline '+ Add property' row with its popover instead of
  the header icon.

Co-authored-by: multica-agent <[email protected]>

* MUL-8280: fix(issues): bound the add property list to the viewport

The Popover that replaced the header DropdownMenu has no height bound,
so a long property catalog pushed its tail options off-screen. Cap it
to --available-height and scroll inside, and add an e2e that wheels to
the last option and picks it.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-27 12:29:04 +08:00
小七 ff6d3207c8 fix(agent): keep per-run usage when Claude resume baseline capture fails (#9567)
When a resume's baseline capture fails, the result event's modelUsage
was stored as the task's usage as-is. On newer Claude Code a resumed
session restores its cumulative counters, so that reported total spans
every prior task in the session: the #8781 inflation returned for every
baseline-unavailable mode. The reported trigger is a custom runtime
profile whose command is a wrapper script that sets CLAUDE_CONFIG_DIR
internally - the daemon resolves the transcript from its own env
(os.Environ() + agent custom_env) and never sees it, so every resume
logged 'claude usage baseline unavailable' and stored the running
session total (observed ~10x on a session's 7th task).

The code already distinguishes a transcript that exists but has no
cost-state (older Claude Code reports per-run totals there; behavior
preserved, pinned by existing tests) from one that cannot be found at
all. For the latter the reported modelUsage is now treated as
non-authoritative: usage keeps the stream-derived per-run totals, and
the reported totals are only recorded for the resume-rejected recapture
where the run is known to have started a fresh session of its own.
Affected modes now degrade to a conservative per-run approximation
instead of silently storing a cumulative total; the WRN stays, reworded
to say what actually happens.

Out of scope, per the adjudication on the issue: per-profile env vars
(schema/feature) and expanding $HOME/~ in custom_env values (makes the
manual workaround portable but leaves the default inflation path live).

Ablation: reverting only server/pkg/agent/claude.go on this branch makes
both new tests fail again with the cumulative total stored
(700/30/800/80 instead of the per-run 70/0/80/8).

Fixes #9564

Generated-by: GLM-5.3-Flash (ZCode)
2026-10-27 12:27:02 +08:00
Multica Eveandmultica-agent b18ed90235 MUL-8246: fix(issues): smaller sidebar headings, trailing arrow (#9579)
* fix(issues): shrink sidebar section headings and trail the disclosure arrow (MUL-8246)

Co-authored-by: multica-agent <[email protected]>

* fix(issues): restore the compact sidebar section count chip (MUL-8246)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-27 11:58:52 +08:00
fa37dcef3f MUL-8277 fix(issues): load every Gantt page when the server caps page size (#9573)
* fix(issues): load every Gantt page when the server caps page size

The Gantt fetch asked for 500 issues per page, but ListIssues clamps
limit to 100. The 100-issue first page looked like a short final page,
so projects with more than 100 scheduled issues lost every bar after
the first 100.

Request pages of 100 and advance the offset by the number of issues
actually returned.

Fixes #9572

* docs(issues): clarify Gantt page limit must match server cap

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-27 11:52:11 +08:00
YYClaw fae0a9060c feat(issues): unify sidebar layout and execution summaries (#9532) 2026-10-27 11:47:41 +08:00
a097f592be MUL-8260 feat(web): fit the mobile web app to iPhone Duo (#9558)
* MUL-8260 fix(web): let the mobile nav drawer scroll as one on short screens

On iPhone Duo's outer display in landscape (368px tall) the drawer's pinned
header and footer left the nav list a three-row scroll window, hiding Issues,
Projects, Agents and the rest. At 640px tall or less the whole drawer now
scrolls as one column; taller screens keep the pinned layout.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* MUL-8260 feat(web): dock the nav and keep list/detail panes from md up

On iPhone Duo's inner screen held sideways (951px) the nav could only open
as an overlay sheet and the inbox and chat folded to one column, because the
compact breakpoint sat at lg (MUL-5842). Move it to md: from 768px the nav is
a docked column that starts collapsed (the auto-collapse band now spans
md-xl) and the trigger docks it open, and inbox and chat keep both panes.
Below 768px nothing changes.

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

* MUL-8260 test(desktop): exercise the compact shell below the new md breakpoint

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 19:14:36 +08:00
ZnandZn 8aead14ab8 fix(issues): resolve local directory hint from assigned agent daemon (#8948)
Co-authored-by: Zn <[email protected]>
2026-10-26 18:40:23 +08:00
Multica Eveandmultica-agent 7c50af7b66 MUL-8094: feat(wakeups): accept blocked in --until-issue-state (#9553)
* feat(wakeups): accept blocked in --until-issue-state

Lets a coordinator wait for a specific child to reach blocked, alongside the
existing in_review handoff, without waiting for the child to close.
Exact status key match, same as in_review.

Refs #9344

Co-authored-by: multica-agent <[email protected]>

* fix(i18n): keep blocked state key in lowercase English in zh wakeup copy

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-26 18:20:16 +08:00
2213734215 MUL-8253 feat(web): opt-in Google Analytics via GOOGLE_ANALYTICS_ID (#9544)
* feat(web): opt-in Google Analytics via GOOGLE_ANALYTICS_ID (MUL-8253)

Co-authored-by: multica-agent <[email protected]>

* fix(i18n): add missing zh-Hant keys for model override and scheduled wakeup

Co-authored-by: multica-agent <[email protected]>

* fix(web): keep credential-bearing URLs out of Google Analytics

Co-authored-by: multica-agent <[email protected]>

* feat(selfhost): pass GOOGLE_ANALYTICS_ID through compose and helm

Co-authored-by: multica-agent <[email protected]>

* fix(web): stop GA for the document after sensitive navigation

Co-authored-by: multica-agent <[email protected]>

* test(views): await subscription cleanup and dialog focus

Co-authored-by: multica-agent <[email protected]>

* fix(web): stop GA before credential-bearing link clicks and form submits

GA4 enhanced measurement reports outbound/download link_url and
form_destination without a URL change, so signed attachment downloads
leaked their signature. Stop the tag for the document in a window
capture listener before gtag's own listeners observe the interaction.
Object URLs are exempt. Adds jsdom tests and a live gtag.js regression
covering the ~5s batch delay.

Co-authored-by: multica-agent <[email protected]>

* test(web): slim GA tests; move views test fixes to #9555

Drop the opt-in live-tag e2e spec (never runs in CI) and condense the GA
unit tests to the cases that guard against credential leaks. The two
unrelated views test-timing fixes now live in #9555.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
Co-authored-by: Bohan-J <[email protected]>
2026-10-26 18:04:40 +08:00
Multica Eveandmultica-agent 9b78e3c309 feat(agents): show model column by default and keep list search across navigation (MUL-8224) (#9550)
- Model column is visible by default; v0 persisted view prefs are migrated
  once to un-hide it (users can re-hide from the Display panel).
- Agents list search moves from page useState into the view store as
  session-only state, so opening an agent and going back keeps the query.
  It is never persisted and is cleared on workspace switch.

Refs #9500

Co-authored-by: multica-agent <[email protected]>
2026-10-26 17:23:20 +08:00
hanshou101 346f441b3b fix(views): keep the step inspector reachable on phones (#9484)
The run dialog is `calc(100vw - 4rem)` wide, while the step inspector is a
fixed 26rem pane that never shrinks. On a phone the pane is wider than the
dialog, so it spills past the dialog's `overflow-hidden` box - and its close
button spills with it. The reader can open a step but has no control that
returns to the step list, because the list is squeezed to zero width and the
only way out is clipped off-screen.

Let the pane fill the row below `md`, where the list has no room to share
anyway, and keep the 26rem side pane from `md` up.

Verified in a real browser at 390/443/768/1440px: the close button is inside
the dialog at every width and tapping it brings the list back; the 768px and
1440px layouts are unchanged (list 288px/608px next to the 416px pane).
2026-10-26 17:06:48 +08:00
Frezc e30ae35301 fix(search): treat out-of-range issue numbers as text (#9501) 2026-10-26 16:49:59 +08:00
Shi Peipei f4250e4298 MUL-8215: fix(runtimes): show Qoder Cloud Agents without encryption setup
Merged via Multica issue MUL-8215 approval.
2026-10-26 16:49:04 +08:00
9543a0c65a MUL-6546 fix(util): ignore mentions inside markdown code blocks and inline code (#7397)
* test(util): mentions inside markdown code should not trigger agent runs

Failing tests for upstream #7237 suggestion 4: fenced code blocks,
inline code spans, and unterminated fences must suppress mention
parsing; blockquote mentions deliberately stay active.

Signed-off-by: Sanjay <[email protected]>
Signed-off-by: Sanjay Ramadugu <[email protected]>

* fix(util): ignore mentions inside markdown code

ParseMentions now suppresses mentions inside fenced code blocks
(backtick and tilde fences, info strings, fences longer than three
characters) and inline code spans, including multi-backtick spans.
An unterminated fence suppresses everything after it.

Blockquote mentions are deliberately still returned: quoting a mention
in a reply is a real notification, not documentation of the syntax.

Upstream #7237, suggestion 4.

Signed-off-by: Sanjay Ramadugu <[email protected]>

* fix(util): parse mentions from goldmark link nodes

Drop the hand-rolled fence scanner. Walk CommonMark Link nodes so code
spans, nested fences, and longer closers stay inert, and update the
squad briefing contract to prove pasted roster syntax still triggers.

* fix(util): require canonical visible mention links

* fix(util): ignore sanitized HTML in mention labels

Co-authored-by: multica-agent <[email protected]>

* fix(util): exclude inert template mention labels

Co-authored-by: multica-agent <[email protected]>

---------

Signed-off-by: Sanjay <[email protected]>
Signed-off-by: Sanjay Ramadugu <[email protected]>
Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 16:34:39 +08:00
Dante 2de89ff46e MUL-8244: fix(agent): preserve recovered Antigravity stream responses (#9534)
* fix(agent): tolerate recovered Antigravity stream interruptions

* fix(agent): preserve failed Antigravity interruptions
2026-10-26 16:30:18 +08:00
ac963e9b08 MUL-7981: fix(execenv): fork past a re-dispatched task's fallback branch (#9547)
* fix(execenv): let a re-dispatched task fork past its own busy-branch fallback (#9198)

When the conversation branch is held by another worktree, a local_directory worktree task forks onto <branch>-<task key>. That name is deterministic, so the same task re-dispatched while the branch is still busy hit 'a branch named ... already exists' and failed every attempt. Fork a fresh timestamped branch instead, leaving the earlier attempt's branch (and any partial work on it) untouched.

Co-authored-by: multica-agent <[email protected]>

* fix(execenv): keep picking an unused fallback branch name on repeated re-dispatch

A second-granular suffix still collides when the same task is prepared more than twice within one second. Try a bounded sequence of fallback names (<alt>, <alt>-<unix>, <alt>-<unix>-N) instead of failing on the first collision; earlier attempts' branches stay untouched. Addresses review on #9547.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 16:19:37 +08:00
Multica Eveandmultica-agent a53cbab942 fix(workflow): brief handler-less steps as one span (MUL-8231) (#9546)
* fix(workflow): brief a handler-less step as the assignee's span to the next handoff (MUL-8231)

Co-authored-by: multica-agent <[email protected]>

* fix(workflow): leave done to a human from an unconfigured in_review (MUL-8231)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-agent <[email protected]>
2026-10-26 16:04:52 +08:00
0a17a5b9fb fix(i18n): add zh-Hant strings missing after concurrent merges (MUL-8031) (#9548)
zh-Hant (#9507) landed alongside #9497 and #9223, which each added EN keys
the new locale did not carry. locales/parity.test.ts fails on main:

- issues: activity.wakeup_created_scheduled (#9497)
- agents: tab_body.runtime_config.model_override_{label,hint,placeholder} (#9223)

Translate them from the zh-Hans strings.

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 15:59:06 +08:00
苗大 5b72b8cd4e fix(editor): clamp html block layout at the collapse point in the same render its height arrives (#9271)
A fenced ```html block reports its document height through the sandbox
bridge. The frame applied that height to the block's layout one frame
before its collapse clip measured the same DOM, so a tall document
painted at full height and then folded back to the clamp. On a
virtualized issue timeline that round trip is a total-height shock —
observed +93% then -46% of the scroll height within ~60ms — and it
renders as visible flicker whenever a scroll lands on the block, worst
on a minimap jump that mounts the block mid-flight.

Pass the measured height to DynamicBlock as bodyHeight: the collapse
decision then derives from the reported height in the same render it
arrives, so the frame's clip applies in the same layout pass the height
lands in. The body keeps laying out at the full document height under
the clip, so expanding stays instant and nothing is rebuilt. Previews
whose height the frame cannot know (mermaid) keep the ResizeObserver
path unchanged.

Enlarging stays outside that shock too. The inline clip no longer
depends on fullscreen: the dialog is fixed-position and fills its own
box, while the in-place footprint keeps holding the clamp — and the
reserved placeholder shrinks to the clamp with it — so opening and
closing the enlarged surface never re-expands the timeline. A reload
re-reports the laid-out height through the same channel, so the
collapse decision tracks the reloaded document.

Refs #8083.
2026-10-26 15:29:08 +08:00
ZIceandmultica-agent 1ad7fa1f94 fix(lark): preserve rich-text post file attachments (#9302)
Co-authored-by: multica-agent <[email protected]>
2026-10-26 15:24:10 +08:00
小七 f9b3065ae1 fix(handler): serialize project resource read-modify-write with a row lock (#9240)
UpdateProjectResource derives every column it writes back from the row
read at the top of the request, but the read and the write ran outside
any transaction. Two concurrent partial updates could interleave as
read-read-write-write, and the second writer's stale snapshot silently
reverted the first writer's change: a label-only PUT reverted a racing
ref update to an old Git ref, and a label-only PUT on a local_directory
restored a stale execution mode (reported in #9238 with a deterministic
interleaving that fails 15/15 under -race -count=3).

Serialize the flow with SELECT ... FOR UPDATE inside a short transaction
(GetProjectResourceInWorkspaceForUpdate + Begin/WithTx, same shape as
CreateAgent). Competing updates block on the row until the write lands,
then re-read fresh. This keeps the local_directory legacy label-mirror
writeback intact, which a presence-aware column rewrite alone would have
broken for mirror-triggered ref updates.

Review follow-ups:

- The regression test no longer leaves the race to the scheduler. Before
  resuming the paused label request, it waits until the ref request has
  either completed outright (the only exit on the pre-fix code, which
  never blocks) or is blocked waiting for the label request's row lock
  (the only exit with the fix, seen as wait_event_type='Lock' on the
  backend running the FOR UPDATE query, checked via pg_stat_activity).
  The two signals are mutually exclusive, so the test fails
  deterministically without the lock and passes with it.
- findLocalDirectoryConflict and requireWorktreeCapableDaemon now read
  through caller-provided queries instead of the handler's pool: on the
  update path they run inside the transaction, so a locked request no
  longer borrows a second pooled connection per request.
- Added a local_directory concurrency case: a label-only update racing
  an execution_mode update through the label-mirror ref rewrite.

The regression tests fail on the pre-fix code ("stored ref = main, want
the concurrent ref update (release)" / "stored execution_mode = worktree,
want the concurrent mode update (cleared = in_place)") and pass with the
lock, 20/20 runs each way.

Fixes #9238

Generated-by: GLM-5.3-Flash (ZCode)
2026-10-26 15:20:52 +08:00
苗大 25086ae73b MUL-8220: fix(issues): stop repeating "wake" in time wakeup entries; remove unused KEEP_ENV setting (#9497)
* fix(issues): stop repeating "wake" in a time wakeup's timeline entry

A time rule's label already reads "wake at ..." (or "every hour", "每小时唤醒"),
so the created entry said "…09:00 唤醒唤醒 Agent" in Chinese and
"Wake at 09:00 · wake Agent" elsewhere. Time rules now use a sentence that
names the agent first: "为 Agent 添加了唤醒:…09:00 唤醒".

* refactor(daemon): remove the unused MULTICA_KEEP_ENV_AFTER_TASK setting

Its only reader went away when run directories stopped being removed at the
end of a run so later runs on the same issue can reuse them (ce2b263ea).
Retention is controlled by the MULTICA_GC_* settings.
2026-10-26 15:18:37 +08:00
e8fdcfd226 MUL-6623 feat(agent): add host-local Devin CLI over ACP (#7485)
* feat(agent): add host-local Devin CLI over ACP

Spawn `devin acp` via the shared ACP client. Local CLI only — not
cloud Devin VMs/Playbooks/Secrets. Model via `devin acp --model`.
Catalog from `devin models list --format json` (families/variants).

* fix: skip Devin ACP handshake when browser auth is also offered

* fix: close dim case string so Devin compiles

Missing quote after dim broke runtime_config.go and every Go CI job.

* fix: stop runtimeConfigPath recursion on Devin

Devin is a builtin whose ProtocolFamily is itself. Recursing on that
overflowed the stack and killed backend-tests.

* test(agent): cover Devin model failures and final-answer delivery

Co-authored-by: multica-agent <[email protected]>

* fix(agent): honor Devin model aliases and stored login (MUL-6623)

Co-authored-by: multica-agent <[email protected]>

* fix(agent): drain Kiro panic details before terminating runtime (MUL-6623)

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Sol-Boy <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 15:11:05 +08:00
21e7299707 MUL-8230: feat(i18n): add Traditional Chinese (zh-Hant) locale (#9507)
* feat(i18n): add zh-Hant locale to web and desktop

Add Traditional Chinese (zh-Hant) as a supported locale with a full
translation of the shared views bundles. Browser tags zh-TW/zh-HK/
zh-Hant now resolve to zh-Hant instead of collapsing to zh-Hans; the
document lang is zh-TW, and docs/use-case links reuse the /zh pages.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit a6b3f6ba53a605c3e06fd6c4d30fd9df6fca8645)

* feat(mobile): add zh-Hant locale

Ship Traditional Chinese bundles for mobile and resolve zh-Hant/TW/HK/MO
device locales to them instead of falling back to English.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 04563c22662bdb735a9a6c04be784abd9f87da06)

* feat(ui-lab): add zh-Hant locale

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 1351ea572ed5d885d8a29034d6c0317de58641ea)

* feat(server): accept zh-Hant as user language

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 50dfe77a4c45452fc877c62497aba226d5aaa426)

* fix(i18n): sync zh-Hant with upstream copy changes

Upstream added conversation-starter, instruction-preview and board column
strings, removed restated descriptions (MUL-8162) and renamed Qoder Cloud
Agents. Mirror those key additions, removals and rewordings in zh-Hant so
the locale parity test passes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 3a97dfc7e0bbf7568925f735c00fc69b6d94313d)

* fix(i18n): add zh-Hant copy for member-scoped runtime visibility

Mirror the runtime visibility "members" choice and the reworded revoke
dialog in zh-Hant so the locale parity test keeps passing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* fix(i18n): replace Mainland terms in zh-Hant copy with Taiwan usage

Several zh-Hant strings were converted character by character from
zh-Hans and kept Mainland vocabulary, which reads wrong to Traditional
Chinese users: 郵箱 → 信箱, 賬單/賬號 → 帳單/帳號, and similar. Values
only; no keys added or removed.

* fix(i18n): polish zh-Hant copy from review

- 分割槽 → 分區 and 許可權 → 權限 (OpenCC phrase mis-conversions)
- drop stray blank lines before zh-Hant workspace names

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 15:09:38 +08:00
8a95f0d3b9 MUL-8205 feat(lark): deliver reply images and files (#9477)
* feat(lark): deliver reply images and files

Based on #8332 by @zprial, addressing its review of bounded delivery,
resource uploads, uncertain sends, file fallback and HTTP boundary tests.

Render bound images with the reply text in one card, pair video/audio
uploads with their message types, preserve pending-send uncertainty and
normalize Markdown destinations before matching bound attachments.

Keep runtime artifact ingestion and deployment-specific configuration
outside this change. Add transport, ownership and rendering regressions
and document the behavior in all supported languages.

* refactor(lark): scope attachment transfer slots to the patcher

The concurrency semaphore was a package-level global while the admission
and pending tiers lived on each Patcher. Move it onto the Patcher so all
three limits share one scope and tests no longer mutate global state.

MUL-8205

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: multica-eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-26 15:05:40 +08:00
Multica Eveandmultica-agent 56d9e98f17 docs(skill): state workflow step scope and handler-less steps in projects reference (MUL-8231) (#9543)
Co-authored-by: multica-agent <[email protected]>
2026-10-26 14:53:16 +08:00