Add a dedicated merger model lane (project + global provider/model/thinking) so merge-agent sessions no longer share only the default model, without inheriting executor/planner/reviewer lanes.
Extends the shared Settings search index so queries like "chat" surface the Project Models section's Direct-chat default fields, which previously had no matching searchable terms.
- Add chat-related searchableText keywords (chat, new chat, chat default, chat model, chat agent, etc.) to the project-models SETTINGS_SECTIONS entry
- Add searchableKeys covering the i18n chat-default labels (chatHeading, chatDescription, chatNewSessionMode*, chatDefaultKind/Model/Agent) so translated labels are also indexed
- Export SettingsSection type plus normalizeSettingsSearchText/sectionMatchesSettingsSearch/filterSettingsSectionsForSearch/SETTINGS_SECTIONS from SettingsModal.tsx for direct unit testing
- Add SettingsModal.search.test.ts covering chat-query matches and a negative case (unrelated Remote Access term does not match)
- Add changeset fn-7942-settings-search-chat.md (patch, fix category)
Files changed:
.changeset/fn-7942-settings-search-chat.md | 7 +++
.../dashboard/app/components/SettingsModal.tsx | 50 +++++++++++++++++++---
.../__tests__/SettingsModal.search.test.ts | 41 ++++++++++++++++++
3 files changed, 92 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-7942
Fusion-Task-Lineage: fa044908-7ada-4334-a789-6d2bf08afdb8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
## Summary
Fixes all remaining full-suite failures from run 29231108919
(FN-7923–7931 drift) + expands the structural mock-completeness guard to
cover dashboard tests.
## Fixes
### Dashboard (shard 4) — 4 files
- **`TaskCard.cli-states.test.tsx`** — Proxy lucide-react mock needed
`has`/`getOwnPropertyDescriptor` traps; TaskCard now imports
`priorityIndicator.tsx` which reads `ArrowDown` at module-init. Vitest
validates ESM named exports via `in`/descriptor, not `get`. Also added
`useToast` mock.
- **`SettingsModalNodeRouting.test.tsx`** — Pass
`initialSection="node-routing"` (it's in
`ADVANCED_SETTINGS_SECTION_IDS`, nav hidden by default).
- **`styles-css-rgba-tokenization.test.ts`** — Removed stale
`.settings-sidebar` color-mix expectation (FN-7825 made it
structural-only).
- **`mcp-helper-forwarding.test.ts`** — Added
`resolvePlanningThinkingLevel` to `@fusion/engine` mock (insight
extraction calls it before MCP forwarding).
### Structural guard expansion
- **`.tsx` blind spot fixed** — `collectTs` and test file filter now
include `.tsx` files
- **Shorthand property extraction** — key extractor now matches both
`key: value` and `key,` (shorthand)
- **Convention mapping** — `.test.tsx → .tsx` source resolution added
- **Dashboard test coverage** — `@fusion/engine` barrel check now scans
`packages/dashboard/src/__tests__/`
- **7 latent mock gaps completed** — `pr-conflict-resolver`,
`project-pause-resume-routes`, `routes-approval-sandbox-provisioning`,
`routes-approval`, `routes-worktrunk`, `session-reconnect`,
`setup-routes`
### Engine (shards 1+2) — zero real failures
All 3 failing files are local-only (`@agentclientprotocol/sdk` + pi-ai
staleness). CI resolves them from lockfile.
## Verification
- Gate (with expanded guard): exit 0 ✅
- Dashboard (5 non-local files): 36/36 passed ✅
- 3 files skipped locally (`@agentclientprotocol/sdk`) — CI will verify
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Improved test reliability by completing module mocks across dashboard
and routing scenarios.
* Updated settings and task card test coverage to reflect current UI
behavior.
* Enhanced mock validation to cover additional test files, TypeScript
React files, and shorthand exports.
* Prevented failures related to missing providers, engine helpers, and
planning configuration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Nudge the text+chevron Actions/Send-back chip up by a quarter space-xs so
it no longer sits optically below the ⋯ menu and size badge on the locked
chip-height row.
Lock .card-id and .card-header-actions to the chip height so the mobile
28px ⋯ touch target cannot stretch the row and sink Actions/size below
FN-####. Cancel residual menu layout growth and extend badge-wrap
regression coverage for the shared locked-row contract.
Follow-up to FN-7928: fix vertical alignment of the Send-back/Actions trigger, menu button, and size badge in the mobile task-card header actions.
- Set line-height: 1 on .card-menu-btn, .card-size-badge, and .card-send-back-btn so their text/icon baselines match instead of drifting from default line-height.
- Add align-items: center to .card-header-actions at the mobile breakpoint so Send back, menu, and size badge share one optical vertical centerline.
- Add padding-block to .card-size-badge to keep the badge's rendered height consistent with the neighboring controls after the line-height fix.
- Add regression tests (TaskCard.badge-wrap.test.tsx) asserting the mobile header-actions rule set (min-height, align-items, gap) and per-control line-height/padding declarations, plus an awaiting-user-input coverage case exercising the send-back/menu/size-badge centerline together.
Files changed:
packages/dashboard/app/components/TaskCard.css | 16 ++++
.../__tests__/TaskCard.badge-wrap.test.tsx | 92 ++++++++++++++++++++++
2 files changed, 108 insertions(+)
Fusion-Task-Id: FN-7933
Fusion-Task-Lineage: e3d52b36-2446-4cdf-8faf-5c94b0f52786
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the in-chat model/thinking (Brain) popup being cut off inside a narrow floating Chat window or compact dock on a wide desktop viewport.
- Key the popover's viewport-fitting inset layout on ChatView's .chat-view--narrow class (chat surface width) instead of only the @media (max-width: 768px) browser-viewport query, so narrow floating/docked chat surfaces get the fitted layout too.
- Add narrow-surface CSS rules for .chat-thinking-level-root, .chat-thinking-popover, .chat-thinking-agent-list, and .chat-thinking-popover-list to constrain position/width/max-height to the chat surface.
- Add a CSS-contract regression test asserting both the desktop popover sizing and the new narrow-surface rules stay in sync.
- Update docs/dashboard-guide.md to describe the popup staying fitted to the chat surface for narrow floating Chat windows/compact docks, not just mobile/tablet viewports.
- Add a patch changeset for @runfusion/fusion documenting the fix.
Files changed:
.changeset/fn-7934-chat-narrow-model-popup.md | 7 +++++
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/components/ChatView.css | 22 +++++++++++++++
.../__tests__/ChatThinkingLevelControl.test.tsx | 32 ++++++++++++++++++++++
4 files changed, 63 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7934
Fusion-Task-Lineage: 30c461c5-a153-4005-8a8c-24f02916a934
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds validatorThinkingLevel and planningThinkingLevel task fields so the Reviewer and Planning AI lanes can override reasoning effort independently of the shared task thinkingLevel, with dashboard UI, storage, and runtime fallback wiring.
- Add validatorThinkingLevel and planningThinkingLevel to Task/TaskCreateInput types (packages/core/src/types.ts)
- Persist the new fields in the SQLite schema and store read/write/replication paths (packages/core/src/db.ts, store.ts, mesh-task-replication.ts)
- Wire executor and triage lanes to fall back per-lane thinking level -> task.thinkingLevel -> existing settings/lane fallback (packages/engine/src/executor.ts, triage.ts)
- Add per-lane thinking-level selectors to the ModelSelectorTab UI, alongside the existing thinking-level control (packages/dashboard/app/components/ModelSelectorTab.tsx)
- Expose the new fields through the legacy task API and task-workflow routes (packages/dashboard/app/api/legacy.ts, packages/dashboard/src/routes/register-task-workflow-routes.ts)
- Document the new settings in dashboard-guide.md and settings-reference.md
- Add a minor changeset and unit/integration test coverage for store persistence, routes, UI, and agent-session helpers
Files changed:
.changeset/per-lane-task-thinking.md | 7 ++
docs/dashboard-guide.md | 2 +
docs/settings-reference.md | 2 +-
.../src/__tests__/store-thinking-levels.test.ts | 43 +++++++
packages/core/src/db.ts | 15 ++-
packages/core/src/mesh-task-replication.ts | 4 +
packages/core/src/store.ts | 24 +++-
packages/core/src/types.ts | 12 ++
packages/dashboard/app/api/legacy.ts | 2 +
.../dashboard/app/components/ModelSelectorTab.tsx | 126 ++++++++++++++++++++-
.../components/__tests__/ModelSelectorTab.test.tsx | 50 +++++++-
.../src/__tests__/routes-tasks-ops.test.ts | 74 ++++++++++++
.../src/routes/register-task-workflow-routes.ts | 19 +++-
.../src/__tests__/agent-session-helpers.test.ts | 15 +++
packages/engine/src/executor.ts | 16 ++-
packages/engine/src/triage.ts | 8 +-
16 files changed, 395 insertions(+), 24 deletions(-)
Fusion-Task-Id: FN-7932
Fusion-Task-Lineage: 4202f774-aab9-41d2-86a0-f5277dd0f848
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the portaled terminal workspace picker menu appearing invisible behind the floating terminal modal by z-layering it above the panel's floatingZ and hiding it until it is positioned.
- Compute terminalWorkspaceMenuFloatingZ one layer above the floating modal's floatingZ (min 5000) so the portaled listbox always renders above the floating terminal stack.
- Position the workspace picker menu synchronously via useLayoutEffect before paint, instead of relying only on the async rAF-driven position update.
- Keep the menu invisible and non-interactive (visibility: hidden, pointer-events: none) until computed trigger-relative coordinates are applied, avoiding a flash at stale/fallback CSS coordinates.
- Add regression tests covering floating-mode z-index layering/pre-rAF positioning and docked/below/embedded/mobile workspace-picker positioning.
- Add a patch changeset describing the fix.
Files changed:
.changeset/terminal-workspace-picker-floating.md | 7 ++
.../dashboard/app/components/TerminalModal.tsx | 37 +++++--
.../components/__tests__/TerminalModal.test.tsx | 120 +++++++++++++++++++++
3 files changed, 156 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-7931
Fusion-Task-Lineage: 41736804-3f99-4cb7-a0fb-f755a86ffc62
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Declutters the terminal footer by dropping steady-state noise: the redundant 'Connected' status text (the header status dot already conveys connection state) and the persistent zoom/shortcuts/escape help copy.
- Remove .terminal-shortcuts / .terminal-shortcuts--header CSS rules (including responsive breakpoint overrides) as orphaned styling
- Stop rendering the 'Connected' text and the Ctrl++/- zoom / Shortcuts panel / Esc close help span in TerminalModal's footer
- Drop the now-unused terminal.helpText locale key from all 6 locales (en, es, fr, ko, zh-CN, zh-TW) and regenerate resources.d.ts
- Update TerminalModal tests to match the trimmed footer markup and add a regression test asserting the connected-status text and shortcut help are omitted
- Add a patch changeset documenting the fix
Files changed:
.changeset/remove-terminal-footer-noise.md | 7 +++++
.../dashboard/app/components/TerminalModal.css | 34 ---------------------
.../dashboard/app/components/TerminalModal.tsx | 7 +++--
.../components/__tests__/TerminalModal.test.tsx | 35 +++++++++++++++++-----
packages/i18n/locales/en/app.json | 1 -
packages/i18n/locales/es/app.json | 1 -
packages/i18n/locales/fr/app.json | 1 -
packages/i18n/locales/ko/app.json | 1 -
packages/i18n/locales/zh-CN/app.json | 1 -
packages/i18n/locales/zh-TW/app.json | 1 -
packages/i18n/src/resources.d.ts | 1 -
11 files changed, 40 insertions(+), 50 deletions(-)
Fusion-Task-Id: FN-7930
Fusion-Task-Lineage: 2b8acb5d-c4d4-4766-ba84-b2691a7eb5e8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes vertical baseline drift among the Send-back button, ⋯ menu button, and size badge inside .card-header-actions by normalizing their line-height, plus adds regression coverage.
- Set line-height: 1 on .card-menu-btn and .card-send-back-btn so their inline-flex content no longer drifts off-center relative to the size badge
- Add FNXC:TaskCardLayout comment documenting the FN-7928 requirement and its coexistence with prior FN-7889/FN-7862/FN-7837/FN-4351 header rules
- Add a badge-wrap regression test asserting Send-back/menu/size controls share one optical centerline across in-progress, done, triage, no-menu, and no-size card states
Files changed:
packages/dashboard/app/components/TaskCard.css | 6 +
packages/dashboard/app/components/__tests__/TaskCard.badge-wrap.test.tsx | 136 +++++++++++++++++++++
2 files changed, 142 insertions(+)
Fusion-Task-Id: FN-7928
Fusion-Task-Lineage: 1b4ad644-8495-4ea1-8687-0849d6a3319b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Narrative: Reworked TaskCard footer/meta layout so the cost badge (and its sibling footer-right chips) render inline at the bottom-right of the card-meta row when the footer has no leading content, instead of always sitting in a separate footer row beside the time badge.
- Extracted the footer-right chip cluster (cost, time, retry, near-duplicate, undo-of, GitHub tracking) into a shared `footerRightCluster` render, computed once instead of duplicated inline.
- Added `footerHasLeadingContent`/`footerRightHasContent`/`placeFooterRightInMeta` derivations so the cluster moves into `.card-meta` (bottom-right, inline with other tags) when there's no files-changed button or GitHub-import leading content, and the meta row is visible; otherwise it keeps the existing `.card-footer-row` placement for in-progress/tracked cards.
- Updated dashboard-guide.md wording to describe the cost badge as appearing 'with the card's other footer/meta chips' rather than 'beside the execution-time badge'.
- Extended TaskCard.test.tsx coverage for the new placement behavior.
- Desktop local-runtime.ts: kept the previously-unused `reason` parameter on `requestRestart` explicitly referenced (void reason) for API parity/lint cleanliness, unrelated cosmetic cleanup carried in the same branch.
Files changed:
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/TaskCard.tsx | 242 +++++++++++----------
.../app/components/__tests__/TaskCard.test.tsx | 96 +++++++-
packages/desktop/src/local-runtime.ts | 4 +-
4 files changed, 222 insertions(+), 122 deletions(-)
Fusion-Task-Id: FN-7923
Fusion-Task-Lineage: 7e4c3109-f39e-45c0-af13-358ce54f945c
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
The task-detail Refine overlay used a raw onClick backdrop handler with a stopPropagation-wrapped inner modal, so the same click/touch sequence that opened Refine could bubble into the backdrop handler and close it right away; route it through the shared useOverlayDismiss contract instead so it behaves like every other dashboard modal.
- Compute refineOverlayDismissProps via useOverlayDismiss(handleCloseRefineModal) and spread it onto the refine overlay instead of a plain onClick handler
- Drop the redundant stopPropagation-only onClick from the inner .detail-refine-modal div now that the overlay itself no longer misfires on the opening interaction
- Update docs/dashboard-guide.md to document that the Refine modal (Board and List entry points) stays open until an explicit close or an enabled backdrop dismissal
- Add TaskDetailModal.refine.test.tsx regression coverage for the modal staying open across the opening interaction and honoring the dismiss-preference gate
- Add a patch changeset summarizing the fix for @runfusion/fusion release notes
Files changed:
.changeset/fn-7927-refine-modal.md | 7 +
docs/dashboard-guide.md | 8 +-
.../dashboard/app/components/TaskDetailModal.tsx | 12 +-
.../__tests__/TaskDetailModal.refine.test.tsx | 182 +++++++++++++++++++++
4 files changed, 201 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-7927
Fusion-Task-Lineage: c7e7cd4a-d103-47e6-93ce-6577147b4795
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
## Summary
Fixes ALL failing shards from the latest full-suite run (29225946428)
AND adds a structural gate check to prevent the recurring mock-export
drift pattern that has caused every full-suite failure across rounds
1–9.
## What broke (run 29225946428, commit 504b0f8b0)
| Shard | Root cause | Tests fixed |
|---|---|---|
| **3 (CLI)** | `workflowValidateParams` (FN-7911) missing from
`@fusion/engine` mock | 8 files |
| **3 (CLI)** | `skill-sync.test.ts` — `fn_workflow_validate` missing
from engine-tools.md | 1 file |
| **4 (dashboard)** | 6 chat default settings keys missing from
description allowlist | 1 file |
| **1+2 (engine)** | `additionalSkillPaths` missing from
`buildSessionSkillContext` mocks (FN-1510/1511) | 10 tests |
| **1+2 (engine)** | heartbeat FN-7878 changed paused→error for generic
run failures | 1 test |
| **1+2 (engine)** | executor `updateTask` exact-match →
`objectContaining` (new fields) | 2 tests |
| **1+2 (engine)** | `connectMcpSessionTools` mock missing for pi.test
MCP forwarding | 1 test |
## Structural fix — `scripts/check-mock-completeness.mjs` (the "fix for
good")
**New gate check** added to `pnpm test:gate`. Statically validates every
hardcoded `vi.mock("@fusion/dashboard")` and `vi.mock("@fusion/engine")`
factory covers all named imports the source file uses. Runs in <0.2s, no
module evaluation.
**How it works:**
1. Extracts named exports from each barrel
(`packages/dashboard/src/index.ts`, `packages/engine/src/index.ts`)
2. For each test file with a hardcoded `vi.mock` factory (no
`importOriginal`/`importActual` spread):
- Resolves source files the test covers (static + dynamic imports,
convention mapping)
- Extracts what those source files named-import from the barrel
- Resolves spread helpers (e.g. `...workflowAuthoringEngineMock`) by
reading the helper's exported keys
- Reports any barrel exports that are named-imported by source but
absent from the mock
**Why this fixes the recurring pattern:** Every round 1–9 failure was a
new barrel export imported by source but missing from a test mock. This
check catches it at gate time, before merge — not after the full-suite
fails on main.
Also completed all 15 latent mock gaps the guard found on first run (9
dashboard + 6 engine), including expanding the centralized
`workflowAuthoringEngineMock` helper with all `extension.ts` named
imports.
## Verification
- Gate (with new check): exit 0 ✅
- CLI: 355/355 passed ✅
- Engine (6 fixed files): 250/250 passed ✅
- i18n + settings: verified ✅
- Mock completeness guard: ✅ (0 issues)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Documented a new non-destructive workflow validation tool that
performs a dry-run and returns typed validation errors.
* **Tests**
* Updated and strengthened CLI, dashboard, extension, and engine tests
with more accurate mock exports and more resilient assertions.
* Adjusted expectations for session/heartbeat and retry-related
behaviors.
* **Chores**
* Added an automated mock-completeness gate and integrated it into the
test quality gate to keep mocks aligned with available platform exports.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Reworks chat message footer affordances: the scroll-to-top control now only becomes visible once a message's top is actually clipped above the visible thread viewport, and the edit pencil moves from a standalone action row into the timestamp footer beside user messages.
- ChatView measures assistant message tops on scroll/message changes (rAF-scheduled) and tracks which message IDs are currently clipped above the `.chat-messages` container edge
- StandardChatMessageItem accepts a new `isTopClipped` prop; the go-to-top button stays DOM-mounted (for tests/a11y) but is visually hidden via CSS until clipped
- Merged the assistant thinking/copy/scroll-to-top actions into a single collapsible footer row instead of separate action rows
- Moved the user-message edit pencil into an inline `chat-message-time-row` next to the relative timestamp instead of a standalone action row above it
- Updated ChatView.css for the new inline layout, collapsed-row state, and hidden/visible scroll-to-top button states
- Updated message-edit and scroll-to-top tests to cover the new inline placement and clipped-visibility behavior
- Added changeset and docs/dashboard-guide.md note describing the new behavior
Files changed:
.changeset/fn-7918-chat-inline-icons.md | 7 ++
docs/dashboard-guide.md | 6 +-
packages/dashboard/app/components/ChatView.css | 80 +++++++++++++++-------
packages/dashboard/app/components/ChatView.tsx | 52 +++++++++++++-
.../app/components/StandardChatSurface.tsx | 33 +++++++--
.../__tests__/ChatView.message-edit.test.tsx | 34 ++++++++-
.../__tests__/ChatView.scroll-to-top.test.tsx | 75 +++++++++++++++++++-
7 files changed, 253 insertions(+), 34 deletions(-)
Fusion-Task-Id: FN-7918
Fusion-Task-Lineage: 76206cd2-94a8-47be-b282-94943e184d01
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Artifact-registration mail messages now expose the task that produced the artifact so users can jump straight to it from the mailbox.
- MailboxArtifactAttachment renders a "View task" button when message.metadata.taskId is present and an onOpenTask handler is supplied, alongside the existing Open artifact affordance
- MailboxModal and MailboxView thread taskId metadata and onOpenTask through to MailboxArtifactAttachment for both the message-list and detail-pane renders
- MainContent wires MailboxView's onOpenTask to the shared fetchTaskDetail -> openDetailTask path, with a toast on failure, so mailbox reuses the existing task-detail flow
- docs/dashboard-guide.md documents the new View task affordance for artifact notifications
- adds a minor changeset for @runfusion/fusion describing the new mail notification behavior
- extends MailboxArtifactAttachment and MailboxView tests to cover the new taskId/onOpenTask wiring
Files changed:
.changeset/fn-7924-artifact-mail-view-task-link.md | 7 ++++
docs/dashboard-guide.md | 2 +-
.../app/components/MailboxArtifactAttachment.tsx | 20 ++++++++++
packages/dashboard/app/components/MailboxModal.css | 2 +-
packages/dashboard/app/components/MailboxModal.tsx | 6 +++
packages/dashboard/app/components/MailboxView.tsx | 6 +++
.../__tests__/MailboxArtifactAttachment.test.tsx | 35 ++++++++++++++++-
.../app/components/__tests__/MailboxView.test.tsx | 45 +++++++++++++++++++++-
.../app/components/dashboard/MainContent.tsx | 6 +++
9 files changed, 124 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-7924
Fusion-Task-Lineage: 800102e1-9025-40da-8130-9ab0e8acd747
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Centers the Chat composer's attach and model/thinking icon buttons with the single-line message input across desktop, tablet, and mobile, while keeping them bottom-aligned when the textarea grows multi-line.
- Size .chat-attach-btn, .chat-thinking-level-root, and .chat-thinking-btn to --chat-input-control-size (matching the send button/textarea min-height) instead of the old calc(var(--space-lg) * 2) / * 2.25) sizing
- Replace the separate mobile touch-target overrides for .chat-attach-btn and .chat-thinking-btn with a shared rule using the same --chat-input-control-size sizing
- Add a regression test asserting the attach/thinking controls use --chat-input-control-size and align-self: flex-end, and no longer use the old calc()-based sizing
- Add a patch changeset for @runfusion/fusion documenting the composer icon centering fix
Files changed:
.changeset/chat-composer-icon-centering.md | 7 +++++
packages/dashboard/app/components/ChatView.css | 30 ++++++++++++----------
.../ChatView.chat-input-autosize.test.tsx | 28 ++++++++++++++++++++
3 files changed, 52 insertions(+), 13 deletions(-)
Fusion-Task-Id: FN-7917
Fusion-Task-Lineage: aba1d5ea-21ee-4b27-90f2-11aca7c4a5fa
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Ensures every draggable modal surface (terminal, artifacts viewer, and other
FloatingWindow delegates) keeps touch-action: none on its drag handle so
tablet touch-drag is captured by FloatingWindow's pointermove stream instead
of being intersected by page pan, and backs the contract with tests.
- Add touch-action: none to .artifacts-gallery-viewer-header, the headerless
FloatingWindow's delegated drag handle, matching the other movable modal
handles.
- Add a FloatingWindow test asserting touch-action: none is present across
every tablet movable-modal drag handle (terminal, artifacts, workflow
editor, automation, mission interview, PR create, file browser, right
dock, new task modal, quick chat FAB) and absent from broad tablet
pan-y overrides.
- Add a FloatingWindow test exercising the captured tablet touch-drag path
for a headerless delegated handle (pointerdown/move/up with
pointerType: "touch").
- Fix TerminalModal drag test to send pointerType: "touch" on
pointerdown/move/up so it exercises the same tablet touch-drag contract.
- Add changeset for the tablet drag fix.
Files changed:
.changeset/fn-7922-tablet-modal-drag.md | 7 ++
.../dashboard/app/components/ArtifactsGallery.css | 5 ++
.../components/__tests__/FloatingWindow.test.tsx | 76 +++++++++++++++++++++-
.../components/__tests__/TerminalModal.test.tsx | 6 +-
4 files changed, 90 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7922
Fusion-Task-Lineage: 0d63ced5-faa7-4362-a42d-884b4c889ebf
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fix the in-chat Brain popup's model picker on touch viewports: pointerdown outside-close was treating the portaled CustomModelDropdown menu as outside the popup, dismissing it before the tap could register a model selection, and the mobile popover was mis-anchored off-screen.
- ChatThinkingLevelControl: treat pointerdown targets inside the portaled `.model-combobox-dropdown--portal` menu as inside the popup so touch taps select the model instead of closing the popup first
- ChatView.css: clamp the popover to the viewport width via max-width/max-inline-size, and on mobile anchor it to the chat input area with tokenized left/right gutters instead of a collapsing left:0 width
- Add a portal-aware regression test covering pointerdown-inside-portal selection, genuine outside-pointerdown close, and the mobile CSS anchoring contract
- Add changeset (patch) and update dashboard guide docs to describe mobile/tablet behavior
Files changed:
.changeset/fn-7916-chat-mobile-model-selector.md | 7 ++
docs/dashboard-guide.md | 3 +-
.../app/components/ChatThinkingLevelControl.tsx | 10 ++-
packages/dashboard/app/components/ChatView.css | 17 +++-
.../ChatThinkingLevelControl.portal.test.tsx | 97 ++++++++++++++++++++++
5 files changed, 130 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7916
Fusion-Task-Lineage: bcc2d9ad-0be6-4e23-b643-eebf93aae3c6
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Removes the redundant DollarSign icon rendered inside the task-card cost badge, since the formatted cost label already includes a currency symbol and showing both duplicated the "$".
- Drop the leading DollarSign icon from the cost badge span in TaskCard.tsx (and its now-unused lucide-react import)
- Add an FNXC comment documenting that formatCost already includes the currency symbol, so no icon should duplicate it
- Update TaskCard tests to assert the cost badge renders no icon (svg) and to cover aria-label/title text for both populated and empty-cost states
Files changed:
packages/dashboard/app/components/TaskCard.tsx | 7 +++++--
packages/dashboard/app/components/__tests__/TaskCard.test.tsx | 5 ++++-
2 files changed, 9 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7920
Fusion-Task-Lineage: 9404ba50-944b-430d-b7ad-0613ec75c42d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the workflow editor's fullscreen prompt overlay having an inert-looking mobile Expand button because a static z-index of 10000 sat below the mobile workflow editor's full-screen FloatingWindow sheet (10100+ shared floating-stack band).
- Have the fullscreen prompt overlay claim a fresh shared floating-stack z-index via nextFloatingZ() when opened, instead of relying on the static CSS z-index: 10000 fallback
- Track the claimed z-index in new promptFullscreenZ state, applying it as an inline style on the portaled overlay and clearing it on collapse/Escape
- Update FNXC comments in WorkflowNodeEditor.css and floatingWindowStack.ts documenting the shared z-index contract and why the static value is now only a fallback
- Add regression tests asserting the prompt fullscreen overlay's z-index exceeds the workflow editor's floating window z-index on desktop, mobile prompt nodes, mobile gate nodes, and after re-opening after collapse
Files changed:
.../app/components/WorkflowNodeEditor.css | 1 +
.../app/components/WorkflowNodeEditor.tsx | 25 ++++++-
.../__tests__/WorkflowNodeEditor.test.tsx | 81 ++++++++++++++++++++++
.../app/components/floatingWindowStack.ts | 2 +-
4 files changed, 106 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7914
Fusion-Task-Lineage: e230309a-3b53-4e42-9e63-7516597b6c24
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Extend the chat brain-icon popup and its backing session PATCH route so an
active Direct chat's model or agent can be switched mid-conversation instead
of only being set at creation time.
- Add a Model/Agent section to ChatThinkingLevelControl (the brain-icon
popup) for picking a model provider/model or retargeting to a real agent
without leaving the chat.
- Extend PATCH /api/chat/sessions/:id to accept modelProvider/modelId (as a
validated pair via the existing validateModelPair helper) and agentId,
forwarding only the keys present in the body so omitted fields leave the
session's stored target untouched.
- Add chat-store updateSession support for the agentId clause alongside the
existing model/thinkingLevel fields, and a useChat.setSessionModel hook
for the dashboard to call the new PATCH capability.
- Update i18n locale strings (en/es/fr/ko/zh-CN/zh-TW) and dashboard-guide.md
docs for the new switcher UI.
- Add unit/integration test coverage across chat-store, chat-manager,
chat-routes, useChat, ChatThinkingLevelControl, and ChatView for the new
model/agent switch behavior.
- Add changeset fn-7908-chat-model-agent-switcher.md (minor,
@runfusion/fusion).
Files changed:
.changeset/fn-7908-chat-model-agent-switcher.md | 7 +
docs/dashboard-guide.md | 3 +-
packages/core/src/__tests__/chat-store.test.ts | 21 ++
packages/core/src/chat-store.ts | 8 +
packages/core/src/chat-types.ts | 2 +
packages/dashboard/app/api/legacy.ts | 11 +-
.../app/components/ChatThinkingLevelControl.tsx | 219 ++++++++++++++++++---
packages/dashboard/app/components/ChatView.css | 135 ++++++++++++-
packages/dashboard/app/components/ChatView.tsx | 23 ++-
.../__tests__/ChatThinkingLevelControl.test.tsx | 109 +++++++++-
.../__tests__/ChatView.thinking-level.test.tsx | 67 ++++++-
.../dashboard/app/hooks/__tests__/useChat.test.ts | 166 +++++++++++++++-
packages/dashboard/app/hooks/useChat.ts | 56 ++++++
.../dashboard/src/__tests__/chat-manager.test.ts | 38 ++++
.../dashboard/src/__tests__/chat-routes.test.ts | 117 ++++++++++-
.../dashboard/src/routes/register-chat-routes.ts | 48 ++++-
packages/i18n/locales/en/app.json | 8 +-
packages/i18n/locales/es/app.json | 8 +-
packages/i18n/locales/fr/app.json | 8 +-
packages/i18n/locales/ko/app.json | 8 +-
packages/i18n/locales/zh-CN/app.json | 8 +-
packages/i18n/locales/zh-TW/app.json | 8 +-
22 files changed, 1007 insertions(+), 71 deletions(-)
Fusion-Task-Id: FN-7908
Fusion-Task-Lineage: b1104865-9b0c-4d77-973e-89152fe245e0
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Chat thinking-level Default entries hardcoded "off" instead of showing the project/global resolved default, misleading operators about which level would actually apply.
- ChatView now fetches Settings via fetchSettings on mount and derives resolvedDefaultThinkingLevel from settings.defaultThinkingLevel (falling back to "off")
- Threads resolvedDefaultThinkingLevel into NewChatDialog and the in-chat ChatThinkingLevelControl (Brain popup) so both surfaces show e.g. "Default (medium)" instead of always "Default (off)"
- ChatThinkingLevelControl accepts a new optional defaultThinkingLevel prop (defaults to "off" for backward compatibility) used only for the Default/clear option label
- Updates dashboard-guide.md to document the resolved-default label behavior in both the New Chat dialog and the in-chat Brain popup
- Adds/updates tests: new ChatThinkingLevelControl coverage for the label prop, new ChatView.thinking-level test coverage for the resolved default, and mocks fetchSettings in the other ChatView test suites that render ChatView
- Adds a patch changeset for @runfusion/fusion
Files changed:
.changeset/fn-7905-chat-thinking-default.md | 7 ++++
docs/dashboard-guide.md | 5 +--
.../app/components/ChatThinkingLevelControl.tsx | 9 +++--
packages/dashboard/app/components/ChatView.tsx | 36 ++++++++++++++++---
.../__tests__/ChatThinkingLevelControl.test.tsx | 16 +++++++++
.../__tests__/ChatView.chat-commands.test.tsx | 1 +
.../__tests__/ChatView.content-search.test.tsx | 1 +
.../__tests__/ChatView.context-window.test.tsx | 1 +
.../__tests__/ChatView.copy-response.test.tsx | 1 +
.../__tests__/ChatView.core-contracts.test.tsx | 1 +
.../__tests__/ChatView.core-interactions.test.tsx | 1 +
.../components/__tests__/ChatView.core.test.tsx | 1 +
.../__tests__/ChatView.default-model-icon.test.tsx | 1 +
.../__tests__/ChatView.hash-mention.test.tsx | 1 +
.../components/__tests__/ChatView.mobile.test.tsx | 1 +
.../__tests__/ChatView.sessions-rooms.test.tsx | 1 +
.../__tests__/ChatView.streaming-thread.test.tsx | 1 +
.../__tests__/ChatView.thinking-level.test.tsx | 42 ++++++++++++++++++++++
18 files changed, 119 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-7905
Fusion-Task-Lineage: 7290aa8a-f812-43c3-8ba5-fc31a3f4579e
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Threads an optional per-session reasoning-effort (thinkingLevel) through mission planning and planning-mode agent sessions so the selected level survives draft reopen, session start, and agent rebuild.
- Add ThinkingLevel to DraftInputPayload/session state in planning.ts; persist and restore it in inputPayload alongside model overrides, threading it into createDraftSession, startExistingSession, createSessionWithAgent, initializeAgent, createPlanningAgent, and ensureSessionAgent as defaultThinkingLevel.
- Preserve thinkingLevel across draft syncs in ai-session-store.ts's updateDraft so it isn't erased when the model pair is unchanged.
- Extend mission-interview.ts session state/persistence and createMissionInterviewAgent/createMissionInterviewSession to accept and persist a validated thinkingLevel, defaulting the agent's reasoning effort from it.
- Validate thinkingLevel against THINKING_LEVELS in mission-routes.ts's POST /api/missions/interview/start and thread it through to the interview session.
- Update PlanningModeModal.tsx and MissionInterviewModal.tsx to surface and submit the selected thinking level; update legacy.ts API client to pass it through.
- Extend register-planning-subtask-routes.ts to accept/validate/forward thinkingLevel for subtask planning routes.
- Add regression coverage in mission-interview.test.ts, routes-planning.test.ts, and session-persistence-roundtrip.test.ts.
- Add changeset for @runfusion/fusion (minor): persisted thinking-level controls for Mission Interview and Planning mode.
Files changed:
.changeset/quiet-dragons-think.md | 7 ++
packages/dashboard/app/api/legacy.ts | 14 ++-
.../app/components/MissionInterviewModal.tsx | 21 +++-
.../dashboard/app/components/PlanningModeModal.tsx | 34 ++++--
.../src/__tests__/mission-interview.test.ts | 34 ++++++
.../src/__tests__/routes-planning.test.ts | 17 ++-
.../session-persistence-roundtrip.test.ts | 16 +++
packages/dashboard/src/ai-session-store.ts | 13 +-
packages/dashboard/src/mission-interview.ts | 30 ++++-
packages/dashboard/src/mission-routes.ts | 14 ++-
packages/dashboard/src/planning.ts | 70 ++++++++---
packages/dashboard/src/routes.ts | 11 +-
.../src/routes/register-planning-subtask-routes.ts | 135 +++++++++++++++------
13 files changed, 330 insertions(+), 86 deletions(-)
Fusion-Task-Id: FN-7902
Fusion-Task-Lineage: 751fb238-fd67-4870-975d-3b10dadde1a0
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
The task cards already show Retry for needs-replan/planning/failed states, but
the retry route only offered the planning retry when the card sat in "triage",
so plan-in-place workflows (Coding (Ideas) replans in Todo) got a 400 "not in a
retryable state". The retrySpecification gate is now workflow-aware: a Todo card
whose workflow declares no "triage" column takes the planning-retry path;
default-workflow Todo cards keep the generic-retry semantics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Root cause of the reported incident: store init ran the retired flag-off
evacuation on every open, dumping Coding (Ideas) intake cards into triage
where they were auto-planned and executed. Init now always runs the
workflow-aware integrity pass (with a stale-selection mis-mapping guard and
per-pass IR memoization) and evacuation remains toggle-only.
Engine rebounds (Plan Review REVISE, stale-spec, fs-validation) resolve a
workflow-aware replan column instead of hardcoding triage; needs-replan now
counts as unplanned for hold-release dispatch so rejected plans cannot
re-execute; triage rediscovers needs-replan todo cards and refinement seed
prompts (shared buildRefinementSeedPrompt/isUnplannedSeedPrompt); the
fs-validation rebound sets needs-replan so unreadable-prompt tasks re-spec
instead of livelocking.
Dashboard: the All-workflows board renders column-orphaned tasks instead of
silently dropping them (hidden columns stay hidden), and the FN-7591 refetch
also fires for present-but-unrepresentable workflow mappings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a persisted, optional per-step reasoning-effort (thinkingLevel) override for AI-capable schedule and routine automation steps, surfaced in the editors and validated at the route layer.
- Add optional AutomationStep.thinkingLevel field (packages/core/src/automation.ts), riding the existing JSON steps blob so no DB migration is needed; runtime application of the level is deferred to a follow-up.
- Validate thinkingLevel in dashboard route step validation against the shared THINKING_LEVELS set, rejecting unknown values (packages/dashboard/src/routes.ts).
- Add Thinking Level controls to RoutineEditor, ScheduleForm, and ScheduleStepsEditor so users can set/inherit the override per step.
- Extend core and dashboard test suites (automation-store, routine-store, RoutineEditor, ScheduleForm, ScheduleStepsEditor, routes-automation) to cover persistence, validation, and UI behavior.
- Update dashboard-guide.md docs and add a minor changeset for the new feature.
Files changed:
.changeset/fn-7900-automation-thinking-level.md | 7 +
docs/dashboard-guide.md | 3 +-
.../core/src/__tests__/automation-store.test.ts | 45 ++++++
packages/core/src/__tests__/routine-store.test.ts | 46 +++++++
packages/core/src/automation.ts | 9 ++
.../dashboard/app/components/RoutineEditor.tsx | 21 ++-
packages/dashboard/app/components/ScheduleForm.tsx | 28 +++-
.../app/components/ScheduleStepsEditor.tsx | 21 ++-
.../components/__tests__/RoutineEditor.test.tsx | 99 +++++++++++++-
.../app/components/__tests__/ScheduleForm.test.tsx | 137 +++++++++++++++++--
.../__tests__/ScheduleStepsEditor.test.tsx | 83 +++++++++--
.../src/__tests__/routes-automation.test.ts | 152 +++++++++++++++++++++
packages/dashboard/src/routes.ts | 10 ++
13 files changed, 622 insertions(+), 39 deletions(-)
Fusion-Task-Id: FN-7900
Fusion-Task-Lineage: 812a9a8c-ad0f-462f-b1c6-9900f70e4261
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a persisted Thinking Level (reasoning-effort) selector to manual insight generation, threading the selection through the dashboard API, insight run metadata, and retries.
- Add inline Thinking Level selector to the InsightsView model-config popover, persisted to localStorage (fusion-insight-thinking)
- Thread thinkingLevel through triggerInsightRun (legacy API client) and useInsights.runInsights
- Validate and store thinkingLevel in insight run inputMetadata.metadata on the POST /insights/run route; resolve it via resolvePlanningThinkingLevel for the actual generation call
- Recover and reapply the original run's thinkingLevel on retry (retryInsightRunLifecycle) so retries reuse the same reasoning-effort setting
- Export resolvePlanningThinkingLevel from @fusion/engine
- Document the new Thinking Level selector in docs/dashboard-guide.md
- Add a minor changeset for @runfusion/fusion
Files changed:
.changeset/fn-7901-insight-thinking-level.md | 7 ++
docs/dashboard-guide.md | 1 +
.../app/__tests__/insight-model-selector.test.tsx | 41 ++++++++++-
packages/dashboard/app/api/legacy.ts | 2 +
packages/dashboard/app/components/InsightsView.tsx | 24 +++++-
.../app/hooks/__tests__/useInsights.test.ts | 36 ++++++++-
packages/dashboard/app/hooks/useInsights.ts | 6 +-
.../src/__tests__/insights-routes.test.ts | 86 ++++++++++++++++++++++
packages/dashboard/src/insights-routes.ts | 36 ++++++++-
packages/engine/src/index.ts | 1 +
10 files changed, 227 insertions(+), 13 deletions(-)
Fusion-Task-Id: FN-7901
Fusion-Task-Lineage: a6249526-e97d-403e-b853-e497d16f425b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Bring thinking-level (reasoning effort) editing to every remaining model selector surface that previously lacked it, so operators can set it consistently from Agent Detail, Agent Onboarding, and the List view's bulk task editor, in addition to the batch-update-models API and route that back them.
- Agent Detail config tab: persist/edit a built-in agent's runtimeConfig.thinkingLevel inline via the shared model dropdown, with dirty-state and reset tracking.
- Agent Onboarding modal: replace the read-only thinking-level input with an editable control wired into the same model dropdown used for creation.
- List view bulk edit toolbar: add a "no change" / "use default" / explicit-level thinking selector alongside executor/reviewer model and node overrides, wired through to the bulk apply action.
- Dashboard API client (`batchUpdateTaskModels`) and `/api/tasks/batch-update-models` route: accept and validate an optional `thinkingLevel` field (against `THINKING_LEVELS`), applying it per task alongside existing model/node updates.
- Update dashboard-guide.md docs and add regression tests across AgentDetailView, AgentOnboardingModal, ListView, and the batch-update-models route.
- Add a minor changeset documenting the feature for release notes.
Files changed:
.changeset/thinking-level-selector-parity.md | 7 ++
docs/dashboard-guide.md | 5 +-
packages/dashboard/app/api/legacy.ts | 3 +
.../dashboard/app/components/AgentDetailView.tsx | 20 +++++-
.../app/components/AgentOnboardingModal.tsx | 11 +++-
packages/dashboard/app/components/ListView.tsx | 54 +++++++++++++---
.../__tests__/AgentDetailView.settings.test.tsx | 45 +++++++++++++
.../__tests__/AgentDetailView.test-helpers.ts | 19 +++++-
.../__tests__/AgentOnboardingModal.test.tsx | 41 +++++++++++-
.../app/components/__tests__/ListView.test.tsx | 43 ++++++++++++-
.../src/__tests__/routes-tasks-ops.test.ts | 75 ++++++++++++++++++++++
.../src/routes/register-task-workflow-routes.ts | 22 +++++--
12 files changed, 323 insertions(+), 22 deletions(-)
Fusion-Task-Id: FN-7899
Fusion-Task-Lineage: fd584ce4-42b3-4c20-8de5-4d3c8963f593
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the Report-a-Bug flow producing a GitHub "request URL too long" error by budgeting truncation against the actual encoded URL GitHub receives instead of the raw diagnostics body length.
- Replace the raw BUG_URL_BODY_CAP (5500 chars) with BUG_URL_MAX_ENCODED (8000 chars), measured against the final GitHub issue URL (base URL + ?body= + encodeURIComponent(body)).
- Add buildBugReportIssueUrl() which binary-searches the largest body prefix (by code point) whose encoded URL still fits the budget, appending a truncation marker when needed.
- doReportBug now calls buildBugReportIssueUrl(body) instead of manually slicing the body and encoding it inline.
- Update tests to assert the final URL length stays under BUG_URL_MAX_ENCODED and to exercise a diagnostics bundle whose JSON (quotes/braces) expands significantly under percent-encoding.
Files changed:
.../__tests__/SystemControlsArea.test.tsx | 9 +++--
.../command-center/areas/SystemControlsArea.tsx | 47 +++++++++++++++++-----
2 files changed, 44 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7890
Fusion-Task-Lineage: fcadafcd-0bbc-4c06-b2ec-c2b124d736db
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Vertically nudges the card-header-actions cluster (size badge/menu icons) to share the same optical centerline as the mono task id, matching the existing id nudge.
- Add a translateY(calc(var(--space-xs) / 4)) transform to .card-header-actions in TaskCard.css, mirroring the FN-7871 id nudge
- Document the change with an FNXC comment explaining the FN-7889 requirement and its relationship to FN-7871/FN-7862/FN-7837
- Extend the TaskCard.badge-wrap.test.tsx regression test to assert the actions cluster's transform matches the id's transform and stays tokenized (no raw px values)
Files changed:
packages/dashboard/app/components/TaskCard.css | 6 +++++-
.../dashboard/app/components/__tests__/TaskCard.badge-wrap.test.tsx | 4 ++++
2 files changed, 9 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7889
Fusion-Task-Lineage: d4743b8f-c7d7-4c3b-9b68-f632dd6e0b7b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Replace the bug-report flow's last-5-error-lines excerpt with the full buildDiagnostics() bundle (health, runtime/system info, recent logs) behind a single confirmation prompt.
- doReportBug now reuses buildDiagnostics() instead of independently fetching a 5-line error excerpt
- Single confirm() prompt covers the whole diagnostics bundle instead of only recent errors
- Diagnostics are embedded as a collapsible <details> JSON code block under a new ### Diagnostics section
- Preserved existing safeguards: fenceSafe() neutralization of embedded code fences and BUG_URL_BODY_CAP truncation
- Added tests covering: full bundle inclusion on confirm, omission on decline, fence-breakout neutralization, and oversized-bundle truncation
Files changed:
.../__tests__/SystemControlsArea.test.tsx | 96 ++++++++++++++++++++++
.../command-center/areas/SystemControlsArea.tsx | 53 +++++++-----
2 files changed, 128 insertions(+), 21 deletions(-)
Fusion-Task-Id: FN-7883
Fusion-Task-Lineage: 44dd26de-d0f6-427b-a082-59d580f31674
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Route Command Center diagnostics copy through the shared clipboard helper so it no longer throws on non-secure origins (e.g. mobile http://fusionstudio:4040).
- Replace direct navigator.clipboard.writeText call in SystemControlsArea's diagnostics copy handler with copyTextToClipboard, which guards for secure-context clipboard support and falls back to document.execCommand("copy").
- Surface a distinct failure toast ("Could not copy diagnostics to clipboard") when neither clipboard path succeeds, instead of crashing.
- Add regression tests covering the execCommand fallback, the secure-context Clipboard API path, and the failure-toast path when both copy mechanisms are unavailable.
- Add a patch changeset documenting the fix.
Files changed:
.changeset/fn-7882-copy-diagnostics-fix.md | 7 ++
.../__tests__/SystemControlsArea.test.tsx | 87 +++++++++++++++++++++-
.../command-center/areas/SystemControlsArea.tsx | 13 +++-
3 files changed, 102 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-7882
Fusion-Task-Lineage: eceb93bf-b32d-4127-b370-4779cb4e4e27
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Keeps the Command Center System tab's refresh button inline with the section title and pinned to the far right at all breakpoints, instead of dropping below the title on mobile.
- Add a scoped .cc-area-section-header.cc-system-controls-header CSS override (row + space-between) that wins over the shared mobile column-collapse rule for the System tab only
- Add data-testid="cc-system-refresh" to the refresh button for test targeting
- Add regression tests asserting the header stays row-aligned in the DOM and the CSS override is present at the 768px breakpoint
- Add a patch changeset documenting the fix
Files changed:
.changeset/fn-7881-system-refresh-inline.md | 7 +++++++
.../__tests__/SystemControlsArea.test.tsx | 23 ++++++++++++++++++++++
.../command-center/areas/SystemControlsArea.css | 22 +++++++++++++++++++++
.../command-center/areas/SystemControlsArea.tsx | 3 ++-
4 files changed, 54 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7881
Fusion-Task-Lineage: 80c6fd78-b7e0-4899-b509-b69b8d21e82d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a best-effort, idempotent dashboard inbox notice announcing the upcoming embedded-Postgres storage migration, delivered once per project on the first engine start under the Fusion 0.59.x release line.
- New `deliverPostgresMigrationNoticeIfNeeded` in `@fusion/engine` (`postgres-migration-notice.ts`) builds and sends a `system` -> `user` inbox message via `MessageStore`, gated to version `0.59.x` by `isPostgresMigrationNoticeVersion`
- Idempotency via existing inbox message `metadata.kind = "postgres-migration-notice"` marker (no new settings key or table), so restarts never duplicate the notice
- Delivery is fully best-effort: any `MessageStore` failure is caught, logged as a warning, and never blocks or fails `ProjectEngine.start()`
- `ProjectEngine.start()` invokes the notice after runtime start, using an injected `cliPackageVersion` threaded from the CLI layer through `EngineManagerOptions` / `ProjectEngineOptions` so the engine never imports CLI/dashboard code directly
- `daemon.ts`, `dashboard.ts`, and `serve.ts` resolve the published `@runfusion/fusion` version via `getCliPackageVersion` / `isUnresolvedCliPackageVersion` and pass it into `ProjectEngineManager`
- Exported new symbols (`POSTGRES_MIGRATION_HELP_URL`, `POSTGRES_MIGRATION_NOTICE_KIND`, `deliverPostgresMigrationNoticeIfNeeded`, `isPostgresMigrationNoticeVersion`, related types) from `@fusion/engine`, and `isUnresolvedCliPackageVersion` from `@fusion/dashboard`
- New unit tests covering version matching and single-delivery/idempotency behavior
- Docs updated (`docs/agents.md`, `docs/dashboard-guide.md`) to describe the one-time notice and its dedup key
- Changeset added for `@runfusion/fusion` (minor, feature)
Files changed:
.changeset/fn-7879-postgres-migration-inbox-notice.md | 7 ++
docs/agents.md | 1 +
docs/dashboard-guide.md | 1 +
packages/cli/src/commands/daemon.ts | 6 +-
packages/cli/src/commands/dashboard.ts | 5 +
packages/cli/src/commands/serve.ts | 6 +-
packages/dashboard/src/index.ts | 2 +-
packages/engine/src/__tests__/postgres-migration-notice.test.ts | 140 +++++++++++++++++++++
packages/engine/src/index.ts | 9 ++
packages/engine/src/postgres-migration-notice.ts | 107 ++++++++++++++++
packages/engine/src/project-engine-manager.ts | 6 +
packages/engine/src/project-engine.ts | 12 ++
12 files changed, 299 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7879
Fusion-Task-Lineage: 201877e5-6bdc-4168-a8ac-ae0e50ec8308
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Wraps the System tab's controls and stats areas in a shared flex container so vertical rhythm is consistent, and canonicalizes hard-coded status colors to design tokens.
- Wrap SystemControlsArea + SystemStatsArea in a new .cc-system-tab flex container with --space-lg gap, replacing the bare React fragment, so Server logs and Live system health sections get consistent breathing room.
- Add responsive gap rule for .cc-system-tab under the 768px breakpoint.
- Replace hard-coded --danger/--warning fallback colors in SystemControlsArea.css with canonical --color-error/--color-warning tokens.
- Add SystemControlsArea test coverage.
- Add a patch changeset documenting the spacing fix.
Files changed:
.changeset/fn-7877-system-tab-spacing.md | 7 +
.../components/command-center/CommandCenter.css | 15 ++
.../components/command-center/CommandCenter.tsx | 8 +-
.../__tests__/SystemControlsArea.test.tsx | 157 +++++++++++++++++++++
.../command-center/areas/SystemControlsArea.css | 8 +-
5 files changed, 189 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-7877
Fusion-Task-Lineage: eb4a97ed-5442-43e8-8d38-348fc3e220a8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>