Keep the chat sidebar from crowding tablet chat while the software keyboard is open.
- extend mobile keyboard detection so tablet chat can react to visual viewport keyboard changes
- hide the chat sidebar and resize handle while the tablet keyboard is open, then restore prior visibility when it closes
- add regression coverage for tablet keyboard behavior plus desktop and mobile guardrails
Files changed:
packages/dashboard/app/components/ChatView.tsx | 39 +++++-
packages/dashboard/app/components/__tests__/ChatView.mobile-render.test.tsx | 139 ++++++++++++++++++++-
packages/dashboard/app/hooks/useMobileKeyboard.ts | 7 +-
3 files changed, 171 insertions(+), 14 deletions(-)
Fusion-Task-Id: FN-6178
Fusion-Task-Lineage: 7acdb76a-135f-4b9c-ab50-708eec03b2c6
Open fresh tabs for follow-up script launches instead of reusing the current terminal.
- track whether an initial command arrived with modal open versus after the terminal was already active
- create a new terminal tab for later script commands, wait for that tab to become active, then send the command there
- expand TerminalModal coverage for first-open versus follow-up script execution and clarify modal-manager script handoff expectations
Files changed:
packages/dashboard/app/components/TerminalModal.tsx | 80 ++++++++++-
.../components/__tests__/TerminalModal.test.tsx | 150 ++++++++++++++++++---
.../app/hooks/__tests__/useModalManager.test.ts | 4 +-
3 files changed, 207 insertions(+), 27 deletions(-)
Fusion-Task-Id: FN-6169
Fusion-Task-Lineage: a7e57a9b-dc3a-432f-bff1-195b62555852
Prevent stale terminal connection metadata from replaying after it has already been delivered.
- only retain scrollback and connected payloads when no listeners are registered yet
- clear buffered terminal events after live subscribers receive them
- add regression coverage for scrollback and connected replay behavior
Files changed:
.../app/hooks/__tests__/useTerminal.test.ts | 50 ++++++++++++++++++++++
packages/dashboard/app/hooks/useTerminal.ts | 23 ++++++----
2 files changed, 65 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-6116
Fusion-Task-Lineage: 5876fe24-2e90-4ef1-9e8b-5abce40555b4
Update dashboard tests to mirror constructor-based browser APIs and xterm addons.
- rewrite SessionTerminal mobile test doubles as constructable function mocks so xterm and addon instances initialize like real classes
- replace the useDocuments AbortController stub with a class-based mock to preserve constructor semantics during fetch cancellation tests
Files changed:
.../__tests__/SessionTerminal.mobile.test.tsx | 21 +++++++++++++++++----
.../app/hooks/__tests__/useDocuments.test.ts | 8 ++++----
2 files changed, 21 insertions(+), 8 deletions(-)
Fusion-Task-Id: FN-6078
Fusion-Task-Lineage: d8e0a9aa-6c7c-44c1-b9d4-5196924531c1
Open the board workflow editor directly to the selected workflow, including on mobile.
- pass the selected workflow id from the board toolbar through app modal state into the workflow editor
- preselect the requested workflow when loading workflows, while preserving settings/create entry points and mobile fallback behavior
- cover the new workflow targeting behavior in board, modal manager, and workflow editor tests and document the mobile editor flow
Files changed:
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/App.tsx | 4 +-
packages/dashboard/app/components/AppModals.tsx | 1 +
packages/dashboard/app/components/Board.tsx | 6 +-
packages/dashboard/app/components/WorkflowNodeEditor.tsx | 13 ++++-
packages/dashboard/app/components/__tests__/Board.test.tsx | 4 ++
packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx | 68 ++++++++++++++++++++++
packages/dashboard/app/hooks/__tests__/useModalManager.test.ts | 42 +++++++++++++
packages/dashboard/app/hooks/useModalManager.ts | 16 +++--
Fusion-Task-Id: FN-6037
Fusion-Task-Lineage: e983e699-5376-434f-af03-39ce5a300029
Add first-load loading states so task activity and agent log views do not flash empty states.
- show a loading status row in the task detail Activity tab while detail history is still loading
- keep agent logs in a loading state until the active task/project context has completed its initial fetch
- add accessible loading markup, regression tests, and dashboard guide documentation for the new behavior
Files changed:
docs/dashboard-guide.md | 1 +
.../dashboard/app/components/AgentLogViewer.css | 18 +++
.../dashboard/app/components/AgentLogViewer.tsx | 2 +-
.../dashboard/app/components/TaskDetailModal.css | 17 +++
.../dashboard/app/components/TaskDetailModal.tsx | 7 +-
.../components/__tests__/AgentLogViewer.test.tsx | 3 +-
.../components/__tests__/TaskDetailModal.test.tsx | 144 +++++++++++++++++++++
.../app/hooks/__tests__/useAgentLogs.test.ts | 74 +++++++++++
packages/dashboard/app/hooks/useAgentLogs.ts | 14 +-
9 files changed, 276 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-6040
Fusion-Task-Lineage: cd4b8f7f-63cd-4d75-be00-d362e915f4e8
Restore mobile auto-merge dashboard stability and broaden regression coverage.
- share the mobile media query between viewport detection and board stabilization so landscape phones stay on the mobile path
- add an integration regression suite for toggling auto-merge across mobile, tablet, desktop, rollback, and task review surfaces
- expand dashboard and CLI tests, keep the new published changeset, and preserve related vitest coverage lists and safety comments
Files changed:
$(git diff --cached --stat)
Fusion-Task-Id: FN-5972
Fusion-Task-Lineage: f3a3bbae-21c2-451b-b24f-848cc12d0542
- Fix: ProjectSelector dropdown now scrolls (max-height + overflow-y)
when project list exceeds visible area, with scrollIntoView on
keyboard navigation
- Feat: Always-visible search input with type-ahead filtering,
HighlightMatch text highlighting, exact match detection + auto-select
on Enter
- Feat: Project bookmarking via localStorage (useProjectBookmarks hook),
star toggle on each item, bookmarked section shown at top of dropdown
- Refactor: Header.tsx now imports standalone ProjectSelector instead
of using an inline copy that lacked these features
- Tests: 131 tests passing across ProjectSelector + useProjectBookmarks
Adds /api/pull-requests routes (list, detail, merge/approve/retry/close/
automerge — all re-fetch authoritative state before acting), a
PullRequestView rendering every entity state distinctly (creating/failed/
unverified/responding/await-review/conflict) with the action bar, live
auto-merge gate reason, and conflict CTA; TaskCard PR node-state badge +
link; and the R16 column-move-backward guard. User actions route through
the existing releaseHeldTaskByEvent primitives. Maps the new PR node kinds
in the workflow editor's kind resolver. 13 route tests + lazy-view guard
green; component test runs in CI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mount CliChatSurface in ChatView for cli-backed chat sessions (sessions carrying
cliExecutorAdapterId): the message-pane + composer region is delegated to the
surface (transcript/raw-terminal toggle for hybrid/native adapters, terminal-only
for the generic adapter), while regular sessions keep the standard composer. The
existing message list and composer JSX are captured once as render thunks and
passed through, so there is no parallel message/composer UI.
Add a narrow telemetry seam: TelemetryHub gains an optional onEvent tap (also
settable post-construction via setEventListener) invoked with each sanitized
event after routing — best-effort, a throwing listener never breaks ingest. This
is the seam the CliChatSessionRunner uses to build the durable transcript from
the same sanitized events the hook route already feeds the hub, without the hub
becoming a general subscriber bus.
Fix the stale @fusion/engine vi.mocks across dashboard tests: object-literal
mocks that fully replace the module now also return listCliAdapterDescriptors
(added by U15's cli-agent-settings route, evaluated at module load). Mocks that
spread importOriginal/importActual already pick it up.
Tests: new ChatView.cli-mount.test.tsx (cli session → CliChatSurface, regular
session → normal composer, generic → terminal-only); telemetry-hub onEvent tap
coverage. chat-attachment-routes, chat-cli-sessions, cli-agent-hooks-route,
ChatView.cli-toggle all green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Show a one-time GitHub star prompt after a task first reaches done.
- detect task status transitions into done and trigger the prompt only in project view
- add a dismissible GitHub star prompt component plus localStorage-backed persistence hook
- cover the new prompt behavior with component, hook, and transition helper tests
- document the prompt behavior and styling guidance in the dashboard guide
Files changed:
docs/dashboard-guide.md | 3 +
packages/dashboard/app/App.tsx | 21 +++++-
.../dashboard/app/components/GitHubStarPrompt.css | 76 ++++++++++++++++++++++
.../dashboard/app/components/GitHubStarPrompt.tsx | 53 +++++++++++++++
.../app/components/__tests__/App.test.tsx | 12 +++-
.../components/__tests__/GitHubStarPrompt.test.tsx | 40 ++++++++++++
.../hooks/__tests__/useGitHubStarPrompt.test.ts | 64 ++++++++++++++++++
.../dashboard/app/hooks/useGitHubStarPrompt.ts | 46 +++++++++++++
8 files changed, 313 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-5967
Fusion-Task-Lineage: 5fffdf4d-61d8-4ac8-bcf4-8b453b639b28
- gate Quick Chat's session-activation auto-flush to the pre-session
queue only, so a restored queue cannot be sent before the restore
effect's authoritative fetchChatSession check resolves (real flaw —
the original test passed only because the mocked fetch resolved in a
microtask and beat the effect)
- add slow-fetch regression tests in both hooks proving the restored
queue stays un-flushed while server validation is pending
- assert attachChatStream ran before triggering its onDone in the
quick-chat regression test
- drop redundant Promise.resolve() wrapper around fetchChatSession in
useQuickChat's restore effect
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-entering a chat flushed the restored queued message based on the
client's stale isGenerating flag (a route-level enrichment the
chat:session:updated SSE payload lacks), firing a send that aborted the
live generation server-side and could lose the message entirely. The
restore path in useChat and useQuickChat now asks the server first:
attach and defer the flush while generating, send immediately only when
no generation is in flight, and keep the bubble on a failed check.
FixesRunfusion/Fusion#1279
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migration (multi-agent sweep over 216 files, 60 batches):
- Every user-visible dashboard + TUI string moved to t() with the exact
English inline default (en rendering byte-identical)
- Catalogs merged from per-batch fragments: en/zh-CN/zh-TW/fr/es now
carry ~5,930 keys each across common/app/errors/cli namespaces;
CLI bundles regenerated (6 locales incl. ko)
Integration fixes:
- 18 type errors: reserved {{count}} interpolations renamed, malformed
plural call, hand-rolled t-param types replaced with TFunction<"app">
- 23 lint errors: superseded label constants/helpers removed
- ExecutorStatusBar hook-order violation (keyboard-open early return
moved below hooks)
- TUI tests wrapped in I18nextProvider (uninitialized fallback renders
literal {{placeholders}}); dashboard vitest.setup boots a minimal en
i18next instance for the same reason
Known WIP (next commits): ~457 residual strings across 50 batches,
Korean drafts for swept keys, and a dashboard test-suite pass that is
still being stabilized (~283 failures under investigation — fake-timer
waitFor interaction, likely stale node_modules vs merged lockfile).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- ko added to SUPPORTED_LOCALES and every enumeration site (config,
settings enum, help text, tests); Korean catalogs authored for all
current keys; CLI bundles regenerated for 6 locales; 한국어 endonym
- README translated into zh-CN, zh-TW, fr, es, ko; every README carries
a language-switcher line and the localized ones note that English is
canonical
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Main independently landed the same pausedReason persistence fix (column in
the task INSERT/upsert, TaskRow type, rowToTask mapping) with the column
ordered between paused and userPaused; adopt main's ordering and drop this
branch's duplicate entries so the values array stays aligned. Union the
dashboard package.json deps (main's compound-engineering plugin alongside
this branch's sorted pi-coding-agent/cli-printing-press/cursor-runtime).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolves the remaining review threads:
- Reset to auto-detect across all three layers (Greptile): store passes
language:null through as null-as-delete; dashboard gains an Auto option
(clearLanguage + hasExplicitChoice in useLanguage, re-detects from
navigator, syncs cross-tab); CLI accepts 'fn settings set language auto'.
Catalog keys added for all five locales; tests at every layer.
- CLI i18n test singleton: afterEach locale restore so zh-CN/fr switches
can't leak across cases (CodeRabbit nitpick)
- useLocaleFormat memoized per locale for stable formatter identities
(CodeRabbit nitpick)
- settings-reference.md documents the auto reset path
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a React Flow (@xyflow/react) based WorkflowNodeEditor: a lazy-loaded modal
with a workflow list, a node palette (prompt/script/gate/merge-boundary),
drag-to-connect edges, a per-node inspector, and save with compile-validation
that surfaces non-linear graphs as a banner. Pure irToFlow/flowToIr mapping
round-trips the v1 IR plus editor layout. Reachable via a Graph editor button in
the Workflow Steps manager; mounted in AppModals behind a new modal-manager
flag. Adds a vendor-reactflow Vite chunk and a feature changeset.
- Extract a shared normalizeToSupportedLocale helper in @fusion/i18n used by
both the CLI env detection and the dashboard navigator detection
(convertDetectedLanguage), fixing multi-subtag navigator tags (zh-Hans-CN)
and unifying Chinese script resolution.
- Add a cross-tab storage listener to useLanguage so a language change in one
tab propagates to others.
- Dedup the namespace lists into packages/i18n/namespaces.json, consumed by
config.ts and all three build scripts (no more 3-way drift risk).
- Add tests: dashboard i18n/index.ts (document.lang mirror, init non-blocking),
useLanguage concurrent-hydration race + cross-tab adoption,
normalizeToSupportedLocale, namespace-source consistency.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add useLanguage (three-tier persistence mirroring useTheme: localStorage cache
+ server GlobalSettings write-through + hydrate-on-mount, local choice wins)
and a LanguageSelector rendered in the Settings Appearance section. Switching
applies in place via i18n.changeLanguage — no reload, so unsaved state and
in-flight agent views survive. Endonyms name each language in its own script.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep queued chat composer state when users move between sessions and only clear it when the session is truly discarded.
- stop clearing persisted pending chat messages during session switches in useChat and useQuickChat
- clear persisted queued messages only when creating a fresh session or archiving/deleting an existing session
- add regression coverage for navigation, reselection, pre-session queueing, and cleanup behavior across chat and quick chat hooks
Files changed:
.../dashboard/app/hooks/__tests__/useChat.test.ts | 246 ++++++++++++++++++++-
.../app/hooks/__tests__/useQuickChat.test.ts | 150 +++++++++++++
packages/dashboard/app/hooks/useChat.ts | 9 +-
packages/dashboard/app/hooks/useQuickChat.ts | 5 +-
4 files changed, 396 insertions(+), 14 deletions(-)
Fusion-Task-Id: FN-5921
Fusion-Task-Lineage: 8916f862-77f5-4d5b-be9a-412e8a71a47d
Keep quick chat warm and restore the last opened conversation per project.
- persist the active quick chat session id in per-project local storage and restore it before falling back to latest activity
- retain in-memory quick chat state across close/reopen while resetting chat state correctly when the project changes
- add storage, hook, and FAB coverage for restored sessions, warm reopen behavior, and project switching; document the updated quick chat behavior
Files changed:
docs/dashboard-guide.md | 3 +-
packages/dashboard/app/components/QuickChatFAB.tsx | 29 ++++--
.../app/components/__tests__/QuickChatFAB.test.tsx | 112 +++++++++++++++++++--
.../__tests__/quickChatLastSessionStorage.test.ts | 55 ++++++++++
.../app/hooks/__tests__/useQuickChat.test.ts | 70 +++++++++++++
.../app/hooks/quickChatLastSessionStorage.ts | 41 ++++++++
packages/dashboard/app/hooks/useQuickChat.ts | 25 +++++
7 files changed, 319 insertions(+), 16 deletions(-)
Fusion-Task-Id: FN-5884
Fusion-Task-Lineage: 4d689611-1824-41db-8fc2-d543407316ff
Handle empty usage responses without leaving the panel in its loading skeleton.
- add a hasFetched flag to useUsageData so the UI can distinguish initial loading from an empty completed response
- update UsageIndicator to render the skeleton only before the first fetch completes and show the empty state afterward
- refresh dashboard hook and component tests to cover empty fetches, refresh behavior, and the new loading semantics
Files changed:
.../dashboard/app/components/UsageIndicator.tsx | 19 +-
.../components/__tests__/UsageIndicator.test.tsx | 395 +++++++++++----------
.../app/hooks/__tests__/useUsageData.test.ts | 42 ++-
packages/dashboard/app/hooks/useUsageData.ts | 5 +
4 files changed, 245 insertions(+), 216 deletions(-)
Fusion-Task-Id: FN-5886
Fusion-Task-Lineage: 8fa901a9-3167-4e33-a082-e5de95f692da
Prevent rapid auto-merge toggles from desynchronizing dashboard settings state.
- Track auto-merge state in a ref so each toggle reads and writes the latest value
- Apply optimistic updates from the ref and roll back correctly on failed setting updates
- Add regression coverage for rapid double-toggle behavior in useAppSettings
- Add a patch changeset for @runfusion/fusion describing the dashboard blank-state fix
Files changed:
.changeset/fn-5751-auto-merge-toggle.md | 5 ++++
.../app/hooks/__tests__/useAppSettings.test.ts | 27 ++++++++++++++++++++++
packages/dashboard/app/hooks/useAppSettings.ts | 20 +++++++++++-----
3 files changed, 46 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-5751
Fusion-Task-Lineage: 1a0090ff-4015-46b8-a974-3accbbdce919