Previously the mobile terminal header used flex-wrap to stack tabs and
the action cluster on separate rows. The actions now stay pinned to the
right edge of the header row while the tab bar flexes to fill remaining
width and remains horizontally scrollable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merges two features: FN-3039 bundles a 2.5MB Nerd Font glyph asset into the dashboard and updates the terminal to prioritize the bundled font, improving icon rendering across environments; FN-3035 tightens insight tool type definitions and adds corresponding tests. The CLI extension gains new tools
Fusion-Task-Id: FN-3039
Adds Nerd Font as the terminal font stack default with a migration to update existing user settings, updates the terminal and settings modals to reflect the new font choice, and includes corresponding tests plus a patch changeset for `@runfusion/fusion`.
Fusion-Task-Id: FN-3026
Production typecheck (tsconfig.json + tsconfig.app.json) was already
clean, but a third config that includes test files surfaced 661 errors
across 60+ test files — accumulated drift between mock fixtures and
production types. Six parallel typescript-pro agents fixed every one
without touching production code.
Per-scope before/after (errors → 0):
ChatView 183
Mailbox + Agent suite (5 files) 156
Task / Modal suite (6 files) 127
App + small components (12 files) 96
Hooks + api/auth (8 files) 48
Long tail (32 files) 51
-----------------------------------------------------------------
Total 661
Major fix categories:
- Untyped state objects inferring `never[]` / `null` literals (root
cause of ~120 errors in ChatView alone — added a single
`UseChatReturn` annotation)
- Mock objects missing fields that became required: `WorkflowStep.mode`,
`ChatMessage.thinkingOutput / metadata`, `ChatSession.projectId`,
`Task.log`, `ProjectHealth` fields, `PtyTerminalSessionInfo.createdAt`,
`Agent.metadata`, `InboxResponse.total`, etc.
- Mock objects with stale fields that no longer exist:
`AgentBudgetStatus.budgetPeriod`, `truncated` on log responses,
`OutboxResponse.unreadCount`, `MergeResult.source/target/details`
- Modal props that became required (e.g. `PlanningModeModal.onTasksCreated`)
- String literals not in narrowed unions (`Column`, `WorkflowStepPhase`,
`InsightStatus`, `AgentLogType`, etc.)
- `querySelector` returning `Element` cast to `HTMLElement` for
`@testing-library/react`'s `within()`
- Vitest mock typing: `.mock.calls` access needing `vi.mocked(...)`,
zero-param tuple handling, generic `vi.fn(() => [])` inferring
`never[]`
Helpers introduced in test files (no shared infra):
- `makeSettings(overrides)` in ModelSelectorTab.test.tsx
- `makePromptOverrides(overrides)` in AgentPromptsManager.test.tsx
- `FileBrowserTestOverrides` type alias in FileBrowser.test.tsx
- `makeInboxResponse / makeOutboxResponse` in MailboxView.test.tsx
Verification:
- tsc -p tsconfig.json: exit 0
- tsc -p tsconfig.app.json: exit 0
- tsc -p tsconfig.test-check.json (new — includes test files): exit 0
- vitest run: 9639 / 9641 (2 pre-existing failures
in terminal-mobile-keyboard-layout.test.ts
unrelated to this work; verified via
`git stash` + run on clean HEAD)
Adds packages/dashboard/tsconfig.test-check.json to keep this regression
guard available locally — same as tsconfig.app.json minus the test
exclude.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Terminal modal and agent detail view are now resizable via the native
CSS grip with sizes persisted per-modal in localStorage. Mobile keeps
fullscreen layout (resize disabled, !important overrides any persisted
desktop dimensions).
Both modals previously dismissed when a drag-resize started inside the
modal but released over the overlay — the synthesised click event
targets the common ancestor (overlay), tripping the e.target ===
e.currentTarget dismiss check. Switched to mousedown→mouseup tracking
so dismiss only fires when both events land on the overlay.
Terminal additionally observes its own pixel box via ResizeObserver
and refits xterm on every grip drag — `resize: both` doesn't emit
window resize.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Enforce terminal xterm root height fill so inline fit heights do not collapse the modal terminal area
- Defer font-size-driven fit to the next animation frame and coalesce pending fits via pendingFitRef
- Remove eager refit calls from zoom keyboard/button handlers and rely on shared font-size effect scheduling
- Expand TerminalModal tests to assert font-size controls and keyboard zoom continue to trigger xterm refits
- Widen the desktop terminal modal to improve usability and align with UX review feedback
- Stabilize terminal input lifecycle handling to avoid focus and interaction regressions
- Add regression coverage for terminal modal input behavior and mobile keyboard layout scenarios
- Include a changeset documenting the terminal modal desktop width and input fixes
- Add refresh-page actions alongside retry/reinitialize in TerminalModal bootstrap and xterm init error states
- Add terminal error action-group styling so multiple recovery buttons render cleanly
- Extend TerminalModal tests to cover new refresh controls and verify window reload behavior
- Remove unused TaskLogEntry import and drop the stale hooks eslint suppression in dashboard-tui app
- Update node management UI components to use shared form/button classes, semantic color tokens, and accessible interactions
- Refine mesh topology rendering and related dashboard tests for improved readability and behavior coverage
- Adjust discovery routes to reuse injected centralCore instances without unnecessary init/close cycles
- Add/extend tests for shared CentralCore discovery flows and model settings scope save behavior
On iOS Safari/PWA, tapping the terminal opened the on-screen keyboard but
keystrokes were silently dropped. After the earlier CSS fix (afba4ce2) the
helper textarea now covers the terminal surface and iOS focuses it natively
on tap — but the bubble-phase onPointerDown/onTouchStart handler kept
re-focusing xterm + the textarea and calling setSelectionRange during the
touch gesture. That is the same class of re-focus-mid-gesture that the
prior commit identified as disrupting iOS input attribution; moving from
capture to bubble phase wasn't enough.
- Early-return from handleTerminalGestureFocus on
(hover: none) and (pointer: coarse), so iOS handles focus with no JS
interference.
- Desktop (fine pointer) keeps the existing behavior because the textarea
stays 1x1 off-screen and still needs programmatic focus on canvas click.
- Add a regression test covering the no-op path with the media query mocked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On iOS Safari/PWA, tapping the terminal opened the keyboard but typed
keys produced no output. Focus landed on a 1×1 opacity-0.01 helper
textarea overlapped by the xterm canvas, and capture-phase gesture
handlers re-focused on every tap — a combination iOS silently drops
input events on.
- On touch-primary devices, expand .xterm-helper-textarea to cover the
entire terminal surface (100% × 100%, opacity 0, z-index 2) via
@media (hover: none) and (pointer: coarse). Taps land on the
textarea directly, so iOS grants keyboard + input events natively.
- Desktop keeps the 1×1 rule so xterm's canvas-level drag-to-select
and mouse tracking continue to work.
- Revert onPointerDownCapture/onTouchStartCapture/onClickCapture back
to bubble-phase onPointerDown/onTouchStart; capture phase was
confusing iOS's focus attribution and is no longer needed now that
taps reach the textarea directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add markOnboardingCompleted() to set completedAt timestamp when user finishes onboarding
- Add isOnboardingCompleted() to check if onboarding was completed (vs dismissed)
- Update ModelOnboardingModal to call markOnboardingCompleted on successful completion
- Skip onboarding auto-open when already completed locally
- Add completion state tracking tests in ModelOnboardingModal.test.tsx
- Add model-onboarding-state unit tests
- Update useAuthOnboarding to check local completion state before auto-opening
- Document localStorage completion state tracking pattern in .fusion/memory.md
The test was checking that loadAddon was never called with any object,
but fitAddon and webLinksAddon are both objects that are legitimately
loaded. The WebglAddon constructor check is sufficient to verify that
WebGL is not loaded on mobile.
- Add session-aware terminal fit/resize logic so deferred viewport callbacks only affect the active tab session
- Trigger a post-init re-fit when keyboard overlap is already present during async xterm initialization
- Guard data, scrollback, and exit handlers to prevent stale session output from writing into a newly active tab
- Add FN-1234 regression tests for mobile tab switching with keyboard overlap, resize propagation, and scrollback isolation
- Add retryDynamicImport helper in TerminalModal with targeted retry detection for MIME type and dynamic import fetch failures
- Retry xterm module imports with backoff delays (500ms, 1500ms, 3000ms) and preserve original error reporting when retries are exhausted
- Add TerminalModal tests covering successful retry recovery, exhausted retry fallback to init error UI, and no-retry behavior for non-retryable failures
- Add a changeset patch for @gsxdsm/fusion describing the terminal initialization fix
- Harden TerminalModal bootstrap to handle invalid/expired sessions on first open
- Add WebSocket reconnection logic for terminal sessions that become invalid mid-stream
- Create useTerminal hook with robust session lifecycle management
- Create useTerminalSessions hook for multi-session terminal coordination
- Add comprehensive tests for TerminalModal, useTerminal, and useTerminalSessions
- Document terminal first-open reliability behavior in dashboard README
- Defer fitAddon.fit() via requestAnimationFrame after CSS repaint to ensure container dimensions are settled
- Add overflow:hidden to keyboard-open CSS rule to prevent layout shift
- Add regression tests for xterm re-fit on mobile keyboard open/close
- Update terminal mobile keyboard documentation in README files
- Add CSS rules to properly handle viewport height when mobile virtual keyboard is open
- Add regression tests for keyboard-open overlap detection
- Add TerminalModal test coverage for keyboard-related height contract
- Document mobile keyboard layout behavior in dashboard README
- Lower virtual keyboard detection threshold from 150px to 80px to reduce missed detections on modern iOS Safari
- Add 30px noise filter to ignore minor viewport fluctuations that aren't real keyboard events
- Add comprehensive threshold boundary tests (80px/30px) covering edge cases for keyboard show/hide detection
When tasks fail and retry, the old worktree lingered on disk and the new
worktree got a random name causing worktrunk to report it as unassigned.
Now: retry clears worktree/branch fields, removes old worktree from disk,
and createWorktree returns the actual branch name (including -2 suffixes)
so task.branch always matches reality.
Also fixes pre-existing test failures: Terminal WebSocket mock sessions
missing lastActivityAt, and TerminalModal keyboard overlap tests leaking
cached _initialViewportHeight between tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect mobile viewport resize in TerminalModal to infer keyboard open/close
- Use visualViewport API and smooth scroll to keep terminal visible on mobile
- Add tests for scroll behavior with mobile keyboard open/close scenarios
- Fix terminal failing to render when TerminalModal is closed and reopened
- Restructure xterm initialization guard so Terminal instance and addons are recreated on subsequent opens
- Add regression test suite covering mount/unmount/remount, dispose behavior, and scrollback preservation
- Add bootstrap error state and retry logic to useTerminalSessions hook to prevent indefinite 'Starting terminal' hang
- Add error/retry UI states in TerminalModal component with CSS styling
- Add tests for useTerminalSessions bootstrap error and retry behavior
- Refactor WorkflowStepManager with template support and improved UX
- Extract CSS from inline styles to stylesheet for terminal and workflow components
- Document terminal startup error handling and non-hanging guarantee in dashboard README
- Implement visual viewport API to reposition terminal above on-screen keyboard
- Add smooth CSS transition for terminal modal height changes on mobile
- Add comprehensive regression tests for keyboard overlap and resize behavior
- Remove stale test files (NewTaskModal, TaskForm) and clean up ActivityLogModal tests
- Document mobile keyboard handling approach in dashboard README
- Route saved script launches from App.tsx directly into TerminalModal, removing the ScriptRunDialog component entirely
- Add openGeneration handling and initialCommand support to TerminalModal for reliable script execution
- Add openGeneration to initialCommand effect dependencies to prevent stale closures
- Remove 114 lines of now-unused styles.css rules related to ScriptRunDialog
- Update tests: replace ScriptRunDialog tests with TerminalModal execution tests, update App routing tests
- Update README to document terminal-based script launch behavior
- Reset isDisclosureExpanded in QuickEntryBox resetForm so disclosure collapses after task creation
- Remove sticky disclosure persistence from QuickEntryBox component
- Preserve terminal sessions across transient WebSocket disconnects with buffer/replay
- Buffer and replay initial terminal state for prompt visibility on reconnect
- Update tests for non-persistent disclosure, terminal reconnect, and server routes
- Remove unused UsageIndicator tests and TaskDetailModal test cleanup
- Restructure TerminalModal header layout to support mobile viewports with proper flex sizing
- Add CSS styles for responsive terminal header with title truncation and icon wrapping
- Add inline comment documenting mobile header layout contract
- Add comprehensive TerminalModal test suite covering mobile layout, resize behavior, and header interactions
- Clean up unrelated store test and changeset remnants from prior work
- Add backend terminal API with session management and SSE streaming
- Create useTerminal hook for command execution and history navigation
- Implement interactive TerminalModal with real-time output display
- Add terminal button to Header for quick access
- Style terminal with CSS variables and responsive design
- Add keyboard shortcuts (Ctrl+C to kill, Ctrl+L to clear, arrow keys for history)
- Add security validation for shell commands
- Add backend terminal API with SSE streaming for real-time output
- Create useTerminal hook with command history and navigation
- Refactor TerminalModal into interactive shell component
- Update App and Header for standalone terminal button
- Add CSS styles for terminal UI (prompts, output, spinner, welcome screen)
- Update tests for new terminal behavior
- Add section expansion state management with localStorage persistence
- Update section headers with chevron toggle controls
- Implement conditional task row rendering based on section state
- Add Expand All / Collapse All toolbar controls
- Add CSS styles for chevron rotation animation and section headers
- Add comprehensive tests for collapsible section behavior