Commit Graph

1521 Commits

Author SHA1 Message Date
Fusion
d8eb39dab7 feat(FN-2726): add bulk node override support in dashboard workflows
- Extend batch task update APIs and route handlers to accept nodeId overrides alongside model settings
- Update ListView bulk edit UX to load nodes and apply node overrides through batch updates
- Add node routing visibility improvements in task detail/settings UI and align related labels/styles
- Expand dashboard/API test coverage for node override batch updates and bulk edit behavior
2026-04-28 14:25:56 -07:00
Fusion
a59aeab987 feat(FN-2870): merge fusion/fn-2870 (auto-resolved)
- fix(FN-2870): default cloudflare quick tunnel to enabled
2026-04-28 14:25:56 -07:00
Fusion
feb213c4ef feat(FN-2885): upgrade routing controls and task timing UI
- Redesign the task Routing tab with effective-node summary rows, unhealthy node signaling, and direct per-task override selection
- Add robust override update handling (loading/saving states, stale-task guards, clear override action, and in-progress lock messaging)
- Extend TaskCard execution time indicator behavior to in-review cards and add focused regression coverage
- Refresh dashboard tests and styling for routing and node-status presentation, and remove an unused remote settings API import
2026-04-28 14:25:56 -07:00
Fusion
3d44398920 feat(FN-2845): streamline node routing configuration in dashboard
- Add a reusable ProjectNodeSelector component and hook RoutingTab to it for per-task node overrides
- Move default node and unavailable-node policy controls into the dedicated Node Routing settings section
- Add descriptive routing guidance text and project-level note in SettingsModal
- Expand dashboard tests for routing tab behavior and node routing settings UX
2026-04-28 14:25:56 -07:00
Fusion
9a1c21f373 fix(FN-2867): simplify remote access settings activation flow
- Remove the separate "Activate Provider" action from SettingsModal and rely on save-only provider configuration
- Ensure saving remote settings enables the selected active provider and keeps provider flags consistent
- Seed remoteAccess defaults in remote settings routes when project settings are missing instead of returning conflicts
- Expand dashboard tests to cover first-use/default remote settings behavior and updated provider lifecycle expectations
2026-04-28 14:25:56 -07:00
Fusion
f37515120f feat(FN-2873): align settings header refresh action
- Move the check-for-updates refresh button into the settings header actions group for consistent placement
- Keep update check behavior unchanged, including loading state, disabled state, and aria labeling
- Set the refresh icon size explicitly to match surrounding header controls
- Simplify mobile CSS by removing obsolete settings-update-check wrap overrides
2026-04-28 14:25:56 -07:00
Fusion
5b11f33c3c feat(FN-2875): add done-task elapsed time ceiling rounding
- Add formatElapsedDurationDone to render done task elapsed time with ceiling-based minute/hour/day rounding
- Keep in-progress time indicator logic on existing floor-based formatElapsedDuration behavior
- Route done-card time indicator rendering through the new done-specific formatter
- Expand TaskCard tests to cover done rounding semantics and preserve in-progress rounding expectations
2026-04-28 14:25:56 -07:00
Fusion
ad0a1f489b fix(FN-2883): reset merge state when re-entering in-progress
- Reset merge metadata, verification counters, and workflow results when tasks move from in-review/done back to in-progress
- Reopen verification-related steps (or the last step fallback) so re-verification runs from a pending state
- Add execute-time guard to clear stale mergeDetails on in-progress tasks before continuing
- Prevent resumeOrphaned fast-path recovery when completed in-progress tasks still carry merge metadata
- Add targeted executor and TaskForm tests covering FN-2883 regression paths
2026-04-28 14:25:56 -07:00
Fusion
f3b098cc15 feat(FN-2724): add interactive task routing controls
- Replace the static routing panel with a dedicated Routing tab that shows effective node, source, and policy details
- Add per-task node override selection with optimistic save/rollback, clear override action, and in-progress lock messaging
- Tighten PATCH /tasks/:id nodeId validation (empty/non-string rejection) while preserving node override conflict enforcement
- Update dashboard route and modal tests, including new RoutingTab coverage and tab-order assertions
2026-04-28 14:25:56 -07:00
Fusion
7227b8786b feat(FN-2874): add failed-task retry action to dashboard cards
- Wire onRetryTask from App through Board/Column/WorktreeGroup/ListView into TaskCard
- Add a Retry button with loading/disabled state to failed task error boxes in TaskCard
- Update failed-card styles to use design tokens and add retry button visual states
- Add TaskCard tests covering retry visibility, callback invocation, loading, and error toast behavior
- Add a patch changeset for @runfusion/fusion documenting the dashboard retry shortcut
2026-04-28 14:25:56 -07:00
Fusion
a7670dd612 fix(FN-2872): reduce blocked-task log noise and clarify routing details
- Add a Node Routing section in TaskDetailModal showing override, effective node/source, unavailable-node policy, and blocking reason
- Remove duplicate blocked-state heartbeat log output when the blocked reason has not changed
- Silence runtime onBlocked logging to avoid repeated blocked-task log spam
2026-04-28 14:25:56 -07:00
gsxdsm
7d66ffa9cc feat(FN-2864): merge fusion/fn-2864 2026-04-28 14:25:56 -07:00
Fusion
8160f6fcf6 test(FN-2863): expand quick chat default-model recovery coverage
- Assert default-model auto-selection initializes a model session with project-scoped context
- Verify quick chat input stays disabled until default-model session bootstrap completes
- Add parity coverage for default-model initialization when agents are present
2026-04-28 14:25:56 -07:00
Fusion
cb5c628f00 fix(FN-2863): retry quick chat session init for default model
- Allow session initialization to retry when the same target key is selected but no active session exists
- Gate duplicate-init short-circuit behind activeSession/sessionsLoading so model-mode startup can recover
- Expand the effect dependency list to track session readiness inputs used by the retry guard
2026-04-28 14:25:56 -07:00
Fusion
81c6f01e9e feat(FN-2723): show node health in dashboard routing selectors
- Add node status indicators and labels to task creation, quick entry, task form, and settings node selectors
- Surface selected node health in list bulk-edit controls with status dot styling for online/connecting/offline/error states
- Update dashboard component CSS and shared styles for consistent node status presentation
- Include changeset documenting unavailable-node routing policy and default node behavior
2026-04-28 14:25:56 -07:00
Fusion
ff58623c32 fix(FN-2861): harden planning session recovery and retry UX
- Add planning and subtask retry routes with session-lock checks and proper API error mapping
- Improve planning session execution with timeout/abort handling, stop-generation support, and resilient stream catch-up behavior
- Update Planning Mode modal to handle reconnects, retry-from-error flow, stop action, and cross-tab session state synchronization
- Expand dashboard tests for planning routes, planning session behavior, and PlanningModeModal retry/error coverage
2026-04-28 14:25:55 -07:00
gsxdsm
596982dd75 feat(FN-2862): merge fusion/fn-2862 2026-04-28 14:25:55 -07:00
Fusion
c9f75a3aad fix(FN-2859): reduce background AI pill height in executor footer
- Tighten background task indicator pill padding to reduce vertical footprint
- Lower line-height to keep icon/text alignment after the size reduction
- Reduce mobile min-height so the footer pill no longer appears oversized
2026-04-28 14:25:55 -07:00
Fusion
6d5ca2cc91 test(FN-2733): expand memory dreams regression coverage
- Add ProjectEngine memory dreams wiring tests for startup ordering, settings-change resync, and unrelated-setting no-op behavior
- Cover degraded-mode startup and settings-update failure paths to ensure sync errors are logged without stopping the engine
- Extend MemoryView Dream Now tests for success, failure toast handling, and disabled loading-state behavior
2026-04-28 14:25:55 -07:00
Fusion
f19ecac8f5 feat(FN-2848): add manual memory dream API trigger
- Add POST /api/memory/dream route that runs project and agent dream processing with AI prompt execution
- Expose triggerMemoryDreams() in dashboard legacy API client for direct dream invocation
- Switch SettingsModal and useMemoryData Dream Now actions from automation lookup to the new endpoint
- Update dashboard route, hook, and settings modal tests to cover success and error handling
- Add a patch changeset for @runfusion/fusion documenting the new endpoint and client helper
2026-04-28 14:25:55 -07:00
Fusion
1d9d9f4e7f feat(FN-2843): auto-select quick chat default model
- Extend /models API responses to include optional defaultProvider/defaultModelId from global settings, including empty and error paths
- Update QuickChatFAB to prefer the configured default model on load and fall back to first-model selection only when no agents exist
- Move quick chat model tag/title-wrap inline styles into QuickChatFAB.css using dashboard design tokens
- Add QuickChatFAB tests covering default-model auto-selection with and without agents and legacy behavior when no default is configured
2026-04-28 14:25:55 -07:00
Fusion
7414184705 feat(FN-2837): add infusion.ai links to update notices
- Add a Learn more link to the update-available banner alongside release notes
- Refactor SettingsModal update-result rendering into a shared helper and include the infusion.ai link when updates exist
- Add dedicated SettingsModal link styling with hover and focus-visible states using dashboard tokens
- Update banner and settings tests to assert the new Learn more link behavior
- Add a patch changeset for @runfusion/fusion documenting the update notice link addition
2026-04-28 14:25:55 -07:00
Fusion
270db8a16c feat(FN-2842): polish workflow result expand toggle styling
- Add dedicated styles for the workflow result expand icon button with token-based sizing and alignment
- Add hover and focus-visible states for clearer interaction feedback and keyboard accessibility
- Increase mobile touch target sizing for both workflow edit and expand toggles using design tokens
2026-04-28 14:25:55 -07:00
Fusion
7dc8a43a4e fix(FN-2838): prevent mobile zoom on dashboard form inputs
- Add global `touch-action: manipulation` on html/body to reduce gesture-triggered zoom
- Set mobile input font-size to 16px for terminal, nodes, and scripts modal form fields
- Extend mobile CSS regression tests to assert the global touch-action rule
2026-04-28 14:25:55 -07:00
Fusion
0b8ffa1528 feat(FN-2732): add manual dream processing actions in dashboard
- Extend useMemoryData with triggerDreamNow and dreamRunning state by locating and invoking the Memory Dreams automation
- Add Dream Now actions to MemoryView and SettingsModal memory settings with loading UI, success/error toasts, and file refresh in MemoryView
- Expand hook and component tests to cover dream-trigger visibility and execution flows in both views
- Update terminal mobile keyboard layout CSS contract expectations for the current mobile modal width and min-height rules
2026-04-28 14:25:55 -07:00
Fusion
789afc30b0 feat(FN-2721): enforce node override guard across task workflows
- Add a core node-override-guard module, export it from @fusion/core, and enforce conflicts in store updates
- Add API route and CLI extension safeguards so nodeId override updates are blocked when ownership would conflict
- Wire node override routing and validation through dashboard quick-create, list, modal, settings, and task form/detail surfaces
- Add focused unit and integration tests for core guard logic, workflow routes, and dashboard node override UX
2026-04-28 14:25:55 -07:00
Fusion
3174f0dc64 chore(release): v0.7.1
Version bump via changesets.
2026-04-28 14:25:55 -07:00
gsxdsm
ce6dcefef2 fix(dashboard): mobile polish, modal layout fixes, keyboard-aware terminal + add 0.7.1 changeset
- WorkflowStepManager: fix React error #310 ("Rendered more hooks than during
  the previous render") that broke the workflow steps panel from loading.
  `useOverlayDismiss` was being called after `if (!isOpen) return null`, so
  the hook count differed between open/closed renders. Move the hook above
  the early return.
- ModelOnboardingModal: API-key input + Save button now span the full card
  width on mobile via negative inline margins that bleed past the card's
  horizontal padding, so the form sits flush to the card edges instead of
  picking up a chunky left indent from the icon-row's flex start position.
- TerminalModal: same desktop-min-width-pinning bug as the onboarding modal.
  Reset min-width/min-height to 0 on mobile with `!important` so persisted
  desktop sizes from useModalResizePersist cannot re-pin the modal at 480×320
  on smaller phones. Also add `!important` to the keyboard-overlap height/
  max-height so the visual-viewport adjustment wins against the new
  fullscreen rule — without this the terminal stayed at 100dvh while the
  mobile keyboard covered the bottom of the screen.
- Add 0.7.1 changeset covering the full mobile polish + paperclip CLI parity
  + plugin runtime registry fallback + SCHEMA_VERSION bump series.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:35:48 -07:00
gsxdsm
67f9b6a18a fix(dashboard): portal NewAgentDialog so it escapes the AgentsView stacking context
On mobile the dialog was rendering with its top hidden behind the in-page
\"Agents\" header. The dialog wasn't actually positioned wrong — its overlay
is `position: fixed; inset: 0`. The problem was that NewAgentDialog
rendered as a child of `.agents-view` (which has `overflow: hidden` and
`position: relative`), and an ancestor stacking context combined with the
relative+overflow parent prevented the fixed overlay from escaping above
the page header in the painter's order.

Render the dialog through `createPortal(..., document.body)` so the
overlay attaches at the document root, escaping every parent stacking
context. This is the standard React modal pattern.

All 9639 dashboard tests still pass — React Testing Library queries
traverse portals transparently.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:23:45 -07:00
gsxdsm
66df2c7149 fix(dashboard): mobile polish — single-row api key input, NewAgentDialog safe-area + scroll
ModelOnboardingModal:
- API-key row was forced to flex-direction: column on mobile, stacking the
  input above the Save button and doubling the vertical space inside the
  already-cramped provider card. Switch to flex-direction: row with the
  input growing (flex: 1, left-aligned) and Save shrunk to its label
  (right-aligned). Tighten input/button min-height to 32px and shrink the
  button's inline padding.
- Tighten surrounding form: gap → --space-xs, label font-size → 11px with
  no margin-bottom, helper paragraphs → 11px / line-height 1.35.

NewAgentDialog:
- Top of the dialog was cut off under the iOS notch / status bar. Added
  env(safe-area-inset-top) to the mobile header padding-top, and
  env(safe-area-inset-bottom) to the footer padding-bottom so the home
  indicator doesn't cover the action buttons.
- Body wasn't scrolling because the flex child kept its default
  min-height: auto, making the dialog grow past the viewport and never
  trigger overflow-y: auto. Added min-height: 0 + flex: 1 1 auto on the
  body, and flex-shrink: 0 on the header/footer/steps so only the body
  gives up height.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:18:31 -07:00
gsxdsm
8e5b761669 fix(dashboard): compact onboarding provider cards on mobile
Previous mobile rule forced .onboarding-provider-card to flex-direction:
column with --space-lg padding, so the icon, body, and actions each took
their own full-width row and every card rendered ~140px tall on a phone.

Keep the icon inline beside the name + description (the row layout the
desktop already uses, just tighter), shrink the icon container to
list-item-bullet size, drop name/description font sizes a notch, and rely
on the existing flex-wrap so the API-key form / action buttons still drop
to their own row underneath. Also evenly split simple action rows (Connect
/ Skip) across the full width for easier tap targets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:15:09 -07:00
gsxdsm
700943a952 fix(dashboard): mobile layout polish for onboarding/new-agent modals + settings auth gutter
- ModelOnboardingModal: the desktop base set min-width: 640px / min-height:
  480px and the mobile media query only reset max-width — but min-width
  always wins over max-width in size resolution, so the modal stayed pinned
  at 640px and overflowed any phone narrower than that. Compounding it,
  useModalResizePersist writes inline width/height from saved desktop
  sessions (e.g. 1100px), and inline styles beat the media query. Reset
  min-width/min-height to 0 in the mobile rule and force fullscreen
  (100vw/100dvh) with !important so the persisted desktop size cannot
  re-pin the modal off-screen. Also disable resize on mobile.

- NewAgentDialog: had no mobile media query at all. Added a max-width: 768px
  block that drops the overlay padding, fills 100vw/100dvh, removes the
  border-radius, tightens header/footer/steps padding, locks body scroll
  with overscroll-behavior: contain + -webkit-overflow-scrolling: touch
  (so iOS doesn't bubble the scroll up and trap users above the footer),
  and stacks the footer buttons full-width. Also switched the desktop
  max-height from 100vh to 100dvh so iOS Safari's collapsing URL bar
  doesn't push the footer under the address bar.

- SettingsModal auth panel: reduced .auth-panel-body padding-inline from
  --space-xl (24px) to --space-md (12px) so each provider card gets more
  horizontal room — the cards are dense enough that the wider gutter
  wasted visible width without any visual benefit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:14:21 -07:00
gsxdsm
0a3c28d872 chore(dashboard): UI polish — Hermes logo, settings header heights, simplify agent card actions
- Use bundled Nous Research SVG (inverted) on the Hermes runtime card
  instead of the generic ProviderIcon.
- Lock GitHub-star and Help buttons in the settings header to a uniform
  26px height so the differing icon sizes don't misalign them.
- Drop the inline Delete button from the idle/terminated agent-card
  states — deletion stays available from the agent detail view.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:27:41 -07:00
gsxdsm
a6697ee7ca feat(paperclip-runtime): route Paperclip calls through paperclipai CLI in Local CLI mode
The Paperclip runtime card's Local CLI tab previously only derived an apiUrl
from the local config and then made HTTP calls itself, so the Test action and
the company/agent pickers ignored the user's onboarded CLI auth context.

Add CLI-backed variants for every Paperclip call that has a `paperclipai`
counterpart, and route through them when transport=cli — both from the
settings card and from the runtime adapter's prompt path.

- New plugin functions spawning `paperclipai … --json`:
  * probePaperclipViaCli, listCompaniesViaCli, listCompanyAgentsViaCli
    (settings card test + pickers)
  * createIssueViaCli, getIssueViaCli, agentsMeViaCli (runtime hot path)
- New dashboard routes: /providers/paperclip/cli-status, /cli-companies,
  /cli-agents (read-only façades over the plugin's CLI helpers)
- PaperclipRuntimeCard: branches on transport=cli to use the cli-* fetchers
- PaperclipRuntimeAdapter: stores transport on the session and routes
  createIssue/getIssue + identity derivation through CLI variants in CLI mode;
  raises a clear error when agentId is unset in CLI mode (paperclipai has no
  /agents/me equivalent)
- getIssueComments / wakeAgent / getRunEvents stay on HTTP (no matching
  paperclipai subcommands) and continue to use the apiKey discovered from
  the local paperclipai config, so CLI mode still works end-to-end
- Tests: 9 new paperclip-client tests covering each CLI variant + 5 new
  adapter tests for the Local-CLI transport branch (64/64 plugin tests pass)
- Update routes.test for the existing BUNDLED_PLUGIN_RUNTIMES fallback so
  the bundled hermes/openclaw/paperclip entries are expected alongside
  installed plugins

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:06:20 -07:00
Fusion
a3a6794c41 feat(FN-2718): add unavailable node policy setting and validation
- Define and export unavailable node policy types in core settings interfaces
- Add project-level unavailable node policy default and runtime validation helper
- Add core unit coverage for unavailable node policy parsing and acceptance cases
- Guard Paperclip mint requests to include companyId only when available for type-safe payloads
- Document unavailable node policy in the settings reference
2026-04-27 22:40:08 -07:00
Fusion
d3e1c28cef fix(plugins): re-export probe symbols + declare plugin deps in dashboard
- Hermes / OpenClaw plugin index.ts now re-export `probeHermesBinary` /
  `probeOpenClawBinary` and their status types so the dashboard's
  `runtime-provider-probes.ts` façade can import them via the public
  package entry instead of deep paths.
- Dashboard `package.json` adds `@fusion-plugin-examples/hermes-runtime`,
  `…/openclaw-runtime`, `…/paperclip-runtime` as workspace deps so
  pnpm symlinks them into `packages/dashboard/node_modules/`. Without
  these, the new probe imports failed with "Cannot find module" during
  `pnpm typecheck`.

This clears 6 of the 9 outstanding typecheck errors. The remaining 3 are
in the in-flight Hermes plugin rewrite (runtime-adapter still imports
from a deleted `./pi-module.js`; the new `index.ts` calls a factory
with the wrong arg type) and should be resolved by the same change set
that landed the rewrite.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 22:17:54 -07:00
gsxdsm
1a1bec1fb4 test(dashboard): align CSS-contract + onboarding tests with current contracts
Two long-standing test failures, root-caused and fixed.

terminal-mobile-keyboard-layout.test.ts (2 tests)
  CSS structure changed: the desktop terminal modal moved its initial
  width/height into companion `:not([style*="width"])` /
  `:not([style*="height"])` rules so persisted resize values can win
  over the default. The tests still searched the base block. Updated
  the helpers to extract from each rule explicitly, asserting:
    width: min(1800px, …)            in the :not([style*="width"]) rule
    max-width: calc(100vw - …)       in the base rule
    85vh                             somewhere in the :not([style*="height"]) rule
    min-height + max-height: calc(100dvh - 40px)  in the base rule
  Same constraints, just reflecting the current selector layout.

ModelOnboardingModal.test.tsx (2 tests)
  Component refactor (commit f3d918997) made the "what GitHub unlocks"
  feature list conditional on `!isGitHubReady`, so the test that mocks
  `authenticated: true` no longer sees "Import issues as tasks". And
  the gh-CLI optional explanation copy was rewritten to "OAuth from
  the dashboard is optional" instead of "OAuth integration in
  Settings → Authentication is optional". Updated:
    - "shows connected state": assert the new connected-state
      sentence ("GitHub is connected — issue imports …") instead of
      the now-hidden feature list line.
    - "explains gh CLI auth": use getAllByText for the two-place
      "GitHub CLI is already authenticated" copy and match the
      current "OAuth from the dashboard is optional" sentence.
  Also adds the missing `afterEach` import to silence its TS error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 20:16:45 -07:00
gsxdsm
aa86dcc05c fix(dashboard): scale stats values to fit metric box without overflow
Token counts on the task detail Stats panel could overflow the metric
box for large values (e.g. 10-digit comma-separated totals). Switched
each metric to a container-query inline-size context and gave the
value a fluid font-size of `clamp(13px, 13cqw, 28px)` so it grows to
fill the box up to a 28px cap and shrinks down to 13px on narrow grid
columns. Combined with `min-width: 0`, `overflow-wrap: anywhere`, and
the metric's `overflow: hidden`, long values now stay within the box
and short values render as large as they can without dominating.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 20:06:06 -07:00
gsxdsm
f3d918997c fix(dashboard): wider/resizable onboarding modal + GitHub CLI-aware messaging
- ModelOnboardingModal: native CSS resize with persisted size via
  useModalResizePersist; default ~1100px wide; modal scrolls inside
  the content area instead of clipping.
- Provider cards flex-wrap so the API-key form drops to a full-width
  row instead of being squished into a fixed side column. Connected
  badge no longer stretches the full body width.
- Step changes now reset content scrollTop so each page lands at the
  top.
- GitHub step: prominent GitHub mark via ProviderIcon; when gh CLI is
  authenticated the intro reads as 'you are all set', primary CTA
  becomes 'Continue with gh CLI auth', and a secondary
  'Connect OAuth (optional)' button is offered.
- CustomModelDropdown: highlight init runs once per open session, and
  filter changes reset highlight to top + scrollTop=0, fixing the
  scroll-fight when filtering models.
- TUI dashboard: at >=150 cols, Stats panel sits to the left of Logs;
  bottom row drops to Utilities + Settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 20:05:45 -07:00
gsxdsm
4b9fd3dd64 fix(dashboard): clear all 661 test-file type errors
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>
2026-04-27 19:59:52 -07:00
gsxdsm
8c554211f3 fix(dashboard): card timer matches stats panel + resizable Changes diff modal
Two related dashboard fixes.

1. Card timer mismatch: the board card timer chip showed only workflow
   runtime (e.g. <1m on FN-2716) while the task detail Stats panel
   reported "Total execution time" of 7m+ for the same task. Cause —
   the slim board listing strips `task.log` to keep payloads small, so
   the card's client-side `[timing]` log scan returned 0. Now the slim
   path aggregates `[timing] … in <N>ms` durations server-side into a
   new `task.timedExecutionMs` field before stripping the log; the
   card prefers this aggregate, falling back to the client scan when
   the full log is loaded (TaskDetailModal). Wire payload stays slim.

2. View Changes diff modal: defaulted to `90vw × 80vh` and was not
   user-resizable. Switched to `min(95vw, 2200px) × min(90vh, ...)`
   default with `resize: both`, persisted via useModalResizePersist
   (`fusion:changes-diff-modal-size`). Mobile keeps fullscreen layout.
   Overlay dismiss switched to the shared `useOverlayDismiss` hook so
   resize-drags that release on the overlay don't close the modal.

Updated the diff modal's regression tests to match the new constraint
shape (still asserts max-height clamps to viewport via calc()).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 19:55:46 -07:00
gsxdsm
938b0c62a0 fix(dashboard): no resize-drag dismiss across all resizable modals + Claude CLI in Authenticated group
When a user drags the native CSS resize grip from inside a modal and
releases the mouse over the overlay, the synthesised click event
targets the common ancestor (the overlay) — fooling the existing
e.target === e.currentTarget dismiss check. Audited every modal with
`resize: both` and switched them to a shared mousedown→mouseup tracking
pattern (new useOverlayDismiss hook) so dismiss only fires when both
events land on the overlay.

Modals fixed: TaskDetail, Settings, FileBrowser, GitHubImport,
GitManager, ScheduledTasks, Scripts, WorkflowStepManager. (Terminal
and AgentDetail were already fixed in 56e8e7324; PlanningModeModal
already had the right pattern inline.)

Also: in Settings → Authentication, the "Anthropic via Claude CLI"
card now lives inside the Authenticated group when authenticated and
the Available group otherwise, instead of floating at the top.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 19:36:24 -07:00
gsxdsm
56e8e73244 fix(dashboard): resizable terminal + agent detail modals, no resize-drag dismiss
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>
2026-04-27 19:30:05 -07:00
gsxdsm
cdddc602f9 feat(dashboard): add fireworksai and qwen-ai provider id aliases
Two more brand-id spellings observed in the wild that previously fell
through to the generic Cpu glyph:
  fireworksai → FireworksIcon (joins fireworks / fireworks-ai)
  qwen-ai     → QwenIcon       (joins qwen / qwen-coder / alibaba / tongyi)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 19:25:10 -07:00
gsxdsm
bb340206bf feat(dashboard): add Cerebras / Groq / Vercel icons + cover all pi-ai catalog providers
Audited the pi-ai built-in model catalog provider IDs against the
ProviderIcon registry and filled every remaining gap.

New icons:
  --provider-cerebras    (#f1592a)  → CerebrasIcon (concentric arcs)
  --provider-groq        (#f55036)  → GroqIcon     (lightning bolt)
  --provider-vercel      (text)     → VercelIcon   (triangle wordmark)

New aliases routed to existing icons:
  minimax-cn               → MiniMaxIcon
  azure-openai-responses   → AzureIcon
  google-gemini-cli        → GeminiIcon
  google-generative-ai     → GeminiIcon
  opencode-go              → OpencodeIcon
  vercel-ai-gateway        → VercelIcon

After this commit every provider id emitted by `@mariozechner/pi-ai`'s
register-builtins (anthropic, openai, openai-codex, google,
google-vertex, google-gemini-cli, google-antigravity,
amazon-bedrock, mistral, openrouter, fireworks, cerebras, groq,
huggingface, kimi-coding, minimax, minimax-cn, zai, xai, opencode,
opencode-go, github-copilot, azure-openai-responses,
vercel-ai-gateway) plus the user-curated set (qwen, lm-studio,
hugging-face, alibaba/tongyi, hf, lmstudio…) renders a brand icon
instead of falling back to the generic Cpu glyph.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 19:22:42 -07:00
gsxdsm
13b502497c feat(dashboard): add Qwen, LM Studio, Hugging Face, Mistral, Azure, Fireworks logos + Gemini aliases
Adds six new provider icons rendered as inline SVG, each backed by a new
brand token in styles.css:
  --provider-qwen          (Qwen / Tongyi)
  --provider-lmstudio      (LM Studio)
  --provider-huggingface   (Hugging Face)
  --provider-mistral       (Mistral AI)
  --provider-azure         (Microsoft Azure / Azure OpenAI)
  --provider-fireworks     (Fireworks AI)

Aliases registered:
  qwen / qwen-coder / alibaba / tongyi
  lmstudio / lm-studio
  huggingface / hugging-face / hf
  mistral / mistral-ai
  azure / azure-openai
  fireworks / fireworks-ai

Also extends the Gemini icon to cover every Google-product alias the
catalog throws at it: google-vertex, vertex, google-cloud-code,
cloud-code, antigravity (in addition to the existing google,
gemini, google-antigravity).

Tests cover each new mapping (and confirm the Gemini alias group all
resolves to the gemini icon with --provider-gemini color).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 19:07:32 -07:00
gsxdsm
e8fb9672b5 fix(dashboard): onboarding step buttons + tighter auth provider spacing
- ModelOnboardingModal: completed/skipped step indicators render as
  <button> so they're clickable for review. Without explicit reset,
  browsers gave them their default white-ish background. Added
  background: transparent + border/padding/font-family resets to
  .model-onboarding-step-indicator so it inherits cleanly from the
  surrounding card on every theme.
- SettingsModal authentication: tightened spacing around providers —
  group margin 16→10, group label margin 8→4, provider card margin
  8→4, header padding 12 16 → 8 12. Less wasted space between rows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 18:59:37 -07:00
gsxdsm
3b3d456ca8 fix(dashboard): mobile rendering for resizable modals
The Settings, Workflow Steps, Automations (and friends) modals all carried
desktop `min-width: 480-520px` constraints from the resize work. On phones
that pushed them off-screen, and the overlay's 10vh top padding plus a
fractional `height: 80vh` left awkward gaps top and bottom.

Apply the same `@media (max-width: 768px)` full-screen-sheet treatment
that File Browser already had to every resize-aware modal: drop the
overlay padding, set width/height to `100vw`/`100dvh`, zero out the
min-* / max-* constraints, and disable `resize` (touchscreens can't grab
the corner grip anyway).

Also tightened the existing File Browser and GitHub Import overrides to
match (`min-width: 0`, `min-height: 0`, `resize: none`).

For TaskDetailModal the mobile rules go inside the existing first
`@media (max-width: 768px)` block to keep the FN-1331 detail-body
padding regression test happy (it captures from the first 768px media
query greedily).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 18:10:24 -07:00
gsxdsm
1fe59be960 feat(dashboard,cli): update-check frequency, GitHub star button, more resizable modals
Update-check frequency (end-to-end)
- Add `updateCheckFrequency: "manual" | "on-startup" | "daily" | "weekly"`
  to GlobalSettings (default: "daily").
- Backend `performUpdateCheck` honors the frequency: TTL = day/week,
  `manual` returns cache or empty without hitting npm, `on-startup`
  refreshes once per process lifetime then serves cache. `/refresh`
  route forces network regardless.
- Settings → Updates surfaces a working `<select>` for the cadence,
  disabled when auto-checks are off entirely.
- Tests: 4 new cases covering ttlForFrequency mapping, weekly window,
  manual semantics, on-startup once-per-process behavior.

TUI update notice
- Read cached update result synchronously on TUI startup. When an
  update is available, render a yellow notice line on the splash and
  a colored ● next to the version in the status bar.

Settings modal header polish
- Add "Star on GitHub" pill (icon + Star + cached star count from the
  GitHub API, 1h localStorage TTL) and "Help" button (opens project
  Discussions). Both link to the Runfusion/Fusion repo.
- Star button auto-hides after the user clicks it (intent = star),
  tracked in localStorage `fusion:github-star-clicked`.
- Settings → General gets a "Show Star on GitHub button" checkbox so
  users can hide it preemptively. New global setting
  `showGitHubStarButton: boolean` (default true) gates rendering.

More resizable modals
- Task Detail modal: 85vh default, resize: both, persisted via
  useModalResizePersist (key `fusion:task-detail-modal-size`).
- Quick Chat FAB: full 8-direction resize (4 corners + 4 edges) via
  pointer-event handlers; persisted to
  `fusion:quick-chat-size-<projectId>`. Each handle has the right
  cursor + role="separator" for accessibility.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 17:55:15 -07:00
gsxdsm
b3b0ce7cb0 feat(dashboard): UI polish pass — resizable modals, themed scrollbars, settings overhaul
Modal resize + size persistence
- Extract `useModalResizePersist` hook (ResizeObserver + localStorage),
  apply to Files, Git Manager, GitHub Import, Workflow Steps, Automations
  (ScheduledTasks), and Settings modals. Each gets `resize: both`, sane
  min/max constraints, and a unique storage key.
- Bump default heights so the modals feel less cramped (Git: 92vh,
  Workflow/Automation: 80vh, Settings: 80vh / 1100px).

Scrollbar theme
- Add a global `*::-webkit-scrollbar*` + `scrollbar-color` rule in
  styles.css so chat, document, system stats, file browser, usage
  indicator, etc. inherit the theme. Existing per-component overrides
  (.board, .column-body, .settings-sidebar, planning modal) still win.

Document view
- Collapse "Show hidden" toggle and search input onto the same row as
  the Project Files / Task Documents segmented control. Stack again
  below 768px.

Mailbox / Todos
- Match Todos header treatment to the Mailbox header (typography,
  padding, border).
- Add top spacing above Mailbox Inbox/Outbox/Agents tab bar so the
  vertical gaps balance.

Settings
- Wider, resizable, persisted Settings modal.
- Project Models description and Authentication panel get proper
  horizontal padding.
- Reorder project sidebar so "General" is first.
- Plugins page: clean margins, integrate refresh button, exclude
  bundled runtimes from the "Installed Plugins" list (they were
  appearing twice — once erroring, once in their own section).
- New "Updates" panel with auto-check toggle + "Check now" button
  (frequency control noted as needing a backend schema field).

Background sessions
- Fix stale "AI N" / planning-icon badge: `handleDeleted` in
  `useBackgroundSessions` now writes a tombstone, advances the
  timestamp guard, and broadcasts completion so the cross-tab
  sync store stops resurrecting the deleted session on the next
  merge tick. Added regression test.
- Re-fetch list on SSE reconnect so terminal events fired during a
  network blip don't get permanently lost.

System stats
- Refresh button uses correct single class (was getting both `btn`
  and `btn-icon`, which conflicted on padding/border).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 17:26:07 -07:00