- Move Pi Extensions Manager package UI base styles outside the mobile media query so desktop/tablet renders correctly
- Fix focus-visible rules from outline: 2px solid var(--focus-ring-strong) to box-shadow: var(--focus-ring-strong)
- Keep only mobile-specific overrides (gap, padding, max-width) inside @media (max-width: 768px)
- Remove duplicate CSS sections that resulted from previous edits
- Move base styles for package manager UI (add form, package list, source badges, etc.)
out of @media (max-width: 768px) so they apply on desktop
- Keep only true mobile overrides (form row stacking, button width, reduced padding)
inside the mobile media query
- Fix focus styling: change 'outline: 2px solid var(--focus-ring-strong)' to
'outline: none; box-shadow: var(--focus-ring-strong)' since the token is a
shadow value, not a color
- Tokenize spacing values (padding, gaps) to use CSS variables
This fixes the workflow feedback from quality gates.
- Add explicit sidebar section class names in ChatView for header, search, list, and footer layout control
- Add a mobile-only footer New Chat action while keeping the desktop header button to avoid duplicate desktop CTAs
- Update mobile chat sidebar CSS to use full-height layout with hidden header/search and a scrollable session list
- Expand ChatView tests to validate sidebar structure, mobile New Chat behavior, and mobile CSS contract rules
- Add executor regression tests for fast-mode completion paths, including tool injection, workflow-step bypass, and completion enforcement checks
- Expand dashboard API tests to verify executionMode payload behavior for createTask and updateTask requests
- Document fast-mode behavior across architecture, task management, and workflow-step docs with explicit gate bypass/enforcement details
- Replace inline heading margin styles in SettingsModal with reusable settings-section-heading--spaced class
- Tokenize settings pane horizontal spacing and margins in styles.css
- Add symmetric gutters so section headings align consistently across the settings modal
The Plugin Manager section had a global .settings-section-heading { margin: 0; }
rule that was unintentionally removing margins from all settings pane headings,
not just plugin detail headings. Scoped the rule to .plugin-settings-form so
other settings panes inherit the base spacing again.
- Replace remaining hardcoded spacing and transition values in plugin-related CSS with dashboard design tokens
- Refine plugin manager layout states by reusing shared settings empty-state styling and removing redundant local heading markup
- Show the project scope banner in the Plugins settings tab for consistency with other project-scoped sections
- Add PluginManager and SettingsModal test coverage for empty/loading class conventions, header structure, and scope banner rendering
- Add heartbeat multiplier global control UI to AgentsView with supporting behavior and tests
- Remove heartbeat multiplier field from Settings modal scheduling section and update related test coverage
- Add mobile-specific CSS adjustments for agent global controls and extend mobile view assertions
- Update docs to reflect the new heartbeat multiplier location in agents and settings references
- Expand heartbeat interval presets to enforce a 5-minute minimum and include extended 48h/72h/1w options
- Add custom heartbeat entry in AgentsView with typed minute input, save/cancel actions, and validation/clamp behavior
- Show the Custom option only when the current interval is a preset, while preserving explicit custom interval labels when needed
- Update dashboard tests and heartbeat utility tests to cover new preset boundaries, custom option behavior, and health staleness expectations
- Document the 5-minute minimum heartbeat clamp behavior in agents documentation
- Add .gm-modal to the shared mobile modal sizing rule used at the main mobile breakpoint
- Apply full-width and full-height viewport constraints so the modal no longer renders off-screen
- Add CSS coverage assertions in core-modals-mobile tests for Git Manager modal mobile sizing behavior
findLandedTaskCommit only fell back to scanning all of HEAD on git-log
exceptions. When the bounded base..HEAD range is valid but empty — e.g.
the merger fast-forward-rebased the task branch and set baseCommitSha
to the new HEAD, or later commits moved HEAD past the merge — recovery
silently returned null and re-queued the merge even though the commit
had already landed. Add an empty-stdout fallback that re-scans HEAD,
with a regression test covering the FN-2221 scenario.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a new worktree setting that fetches the configured remote and rebases
the task branch onto the latest default-branch tip before the merger attempts
to merge it back. Catches concurrent pushes from other collaborators or
fusion workers on other hosts before they surface as merge conflicts —
anything the rebase can't fast-forward flows into the existing smart/AI
resolve pipeline (attempts 1–3) rather than needing new handling.
- `settings.worktreeRebaseBeforeMerge` (bool, default true) — gates the step.
- `settings.worktreeRebaseRemote` (string, default "") — which remote to
fetch; empty falls back to git's configured remote for the default branch,
then to the sole remote if there's only one, then to "origin".
- Rebase runs inside the task's worktree; failure aborts and falls through
to the merge cascade. Rebase errors are warn-logged but never throw.
- Dashboard SettingsModal Worktrees section now has a toggle for the setting
plus a remote dropdown populated from `/api/git/remotes/detailed`. The
dropdown defaults to "Use git default" so no explicit selection is needed
on first configure.
Also aligns the Last/Next heartbeat spans on the agent list card — both now
share the `.agent-heartbeat-last, .agent-heartbeat-next, .agent-heartbeat-saving`
font-size rule with a consistent line-height and inline-flex alignment so
the labels don't drift vertically when they share a row.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add display:flex and flex-direction:column to .setup-wizard-modal for scroll containment
- Ensure .setup-wizard-content has flex:1, min-height:0, overflow-y:auto for internal scrolling
- Protect header/footer with flex-shrink:0 to prevent collapse
- Add regression test coverage for viewport-safe layout contract
- Preserve mobile full-screen modal behavior
agentHealth.tsx:
- Drop the "Disabled" label and isHeartbeatEnabled helper. Server-side
heartbeat scheduling is driven by agent.state (active/running = armed),
not by the legacy runtimeConfig.enabled flag, so surfacing "Disabled" for
agents with a stale flag on disk was misleading.
- Replace the elapsed > heartbeatTimeoutMs check with elapsed > 2× effective
interval (with a 60s floor). heartbeatTimeoutMs is the per-run work budget,
not a between-tick freshness window; using it made any agent configured
with a multi-minute+ interval show Unresponsive the moment it got more
than 60s old. The effective interval resolver now falls back to the
server-side 1h default, so agents never configured via the dropdown and
agents with an explicit interval get consistent treatment, differing only
by scheduled cadence.
AgentDetailView.tsx:
- Remove Stop buttons from active/paused/running/error (mirrors the earlier
AgentsView cleanup — Pause/Resume/Retry cover reversible transitions,
Delete stays on idle/terminated for teardown).
- Add a "Next Heartbeat" info row alongside "Last Heartbeat" for ticking
agents (active/running), computed as lastHeartbeatAt + effective interval.
Tests rewritten to cover the new semantics; dropped 14 obsolete cases that
were pinned to the old heartbeatTimeoutMs-based check and the "Disabled"
branch. 42 agentHealth tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The compact board view was a duplicate of the list view with fewer affordances
— no heartbeat dropdown, no Last/Next indicators, and its own copy of the
action buttons that kept drifting out of sync with the list view's. Drop it
entirely and migrate any saved "board" preference to "list" on load.
- Remove Board toggle button (LayoutGrid icon) and the "board" state value.
- Remove the entire board rendering branch.
- Simplify getStateCardClass to the single "agent-card" prefix.
- Remove unused LayoutGrid import.
Tree and Org Chart views remain unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove Stop buttons from active/paused/running/error in both grid and list
views; Pause/Resume/Retry cover the reversible transitions and Delete stays
available on idle/terminated for teardown. Matches the existing shape of
AgentDetailView after the earlier cleanup.
- Drop the redundant interval badge next to the heartbeat dropdown — the
selected <option> already shows the current value.
- Add a "Next: HH:MM:SS" indicator alongside "Last:" for active/running
agents, derived from lastHeartbeatAt + configuredIntervalMs (full timestamp
in the tooltip). Paused/idle/error/terminated agents show Last only since
there's no scheduled next tick.
- Remove now-unused Square and Heart icon imports.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Backup automation now emits `npx runfusion.ai backup --create` so scheduled
backups work for users on the zero-install path where `fn` is not on PATH.
`runfusion.ai` also exposes `fn` and `fusion` bins, so `npm i -g runfusion.ai`
puts them on PATH (npm does not link dep bins globally). Alias only defaults
to the dashboard when invoked as `runfusion.ai` / `runfusion`; `fn` / `fusion`
forward args verbatim so bare `fn` still prints help.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add global settings schema/types fields for persisted dashboard session state (selected project and node)
- Refactor NodeContext and current-project hooks to read/write project and node selection via global settings instead of project-local state
- Update App wiring to use the new selection flow across dashboard startup and switching behavior
- Add and expand dashboard tests for NodeContext, useCurrentProject, and view-state persistence behavior
- DevServerView.preview.test.tsx: drop manual-preview-override assertion
(the component hard-codes isManualPreviewOverride=false under the new
session model, so the badge is always "Auto"), provide both legacy and
current-API fields from createDevServerHookState, and mirror
embedContext into blockReason in createPreviewEmbedState so the
fallback panel picks up the reason text under the new destructure.
- runtime-adapter.test.ts: skip the createSession / promptWithFallback /
describeModel blocks with a TODO — the adapter loads pi.js via
CommonJS require() which vi.mock does not intercept, so the mocked
module is never actually installed. Needs a dynamic import seam
before these can run; tracking separately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace public logo.svg with the header ring+swoosh geometry to keep branding consistent
- Refresh icon-192.png and icon-512.png assets to match the updated dashboard mark
- Add PWA tests that validate logo.svg structure and ensure install icon files exist
- Document favicon/PWA brand alignment expectations in the dashboard README
- Add canonical DevServer session types for commands, runtime state, logs, and preview metadata
- Introduce session-scoped API helpers for list/create/get/start/stop/restart/delete operations under /api/devserver
- Add log history, preview URL, command detection, and SSE stream URL helpers for session-based endpoints
- Preserve migration compatibility by falling back to legacy /api/dev-server endpoints and normalizing legacy responses
- Move inline styles from AgentListModal and AgentGenerationModal into token-based stylesheet classes
- Polish NewAgentDialog step-zero layout, role grid, and AI generation button/summary presentation
- Improve AgentImportModal result stat visual hierarchy and semantic status coloring
- Expand dashboard modal CSS coverage with sectioned rules and mobile-specific refinements
- Update component and stylesheet tests to assert new class usage and modal responsive behavior
- Add ExecutionMode type contracts and executionMode field to core task interfaces
- Persist executionMode through SQLite schema mappings and TaskStore read/write paths
- Validate executionMode in dashboard route handlers and API request handling
- Expand core and dashboard test coverage for executionMode persistence and route behavior
- Replace inline agent state badge and card colors with state-specific CSS classes across list, board, tree, and org chart views
- Add reusable AgentEmptyState with create-agent CTA and wire it into all empty agent view modes
- Polish agents controls and metrics presentation in AgentsView/AgentMetricsBar with corresponding stylesheet token updates
- Extend dashboard tests for agent CSS classes, metrics bar behavior, list view rendering, and mobile view coverage
- Add a patch changeset for @gsxdsm/fusion describing the agent view UX improvements
- Extend core task types/store and dashboard API route handling to persist task reviewLevel
- Add review level controls to TaskForm, NewTaskModal, and TaskDetailModal flows
- Improve workflow step selector presentation in WorkflowResultsTab and styles for clearer review settings UX
- Document the new review level behavior and add route/form/modal tests to cover create and edit scenarios
- Add Markdown/Raw rendering toggle support to DocumentsView and TaskDocumentsTab for consistent document preview behavior
- Reuse workflow-style toggle UX and markdown CSS patterns to align with existing dashboard design conventions
- Add comprehensive tests for DocumentsView and TaskDocumentsTab toggle interactions and rendering states
- Update dashboard guide documentation to describe the new Markdown/Raw toggle behavior
- Fetch unread inbox messages whenever messageStore is available, not only wake-on-message triggers
- Include pending messages in execution prompts for task and no-task heartbeat runs across timer, assignment, and on-demand sources
- Extend heartbeat messaging tests to cover run-wide mailbox prefetch and read-marking behavior
- Document heartbeat mailbox checking semantics and messageResponseMode behavior in agents docs
- Replace Header mailbox badge class with existing header-badge style token
- Trigger model loading when the dialog opens instead of only on initial mount
- Guard NewAgentDialog effects with isOpen to avoid late async state updates after close/unmount
- Update AgentsView dialog tests to await settled UI state before asserting controls
- Harden NewAgentDialog tests with async act/waitFor patterns around render, reopen, and fetch side effects
Pre-release polish. Two related changes bundled because they both land the
project on public-release footing:
Dashboard auth
- fn dashboard now gates the HTTP API + terminal/badge WebSockets behind a
bearer token by default. Token resolution order: --token flag,
FUSION_DASHBOARD_TOKEN env, FUSION_DAEMON_TOKEN env (back-compat), or an
auto-generated fn_<32 hex>. --no-auth disables. The startup banner prints
a click-to-open URL with ?token=<token> embedded.
- Auth middleware now also accepts fn_token=<token> as a query-string
fallback so EventSource and WebSocket clients (which can't set custom
headers) still authenticate.
- setupTerminalWebSocket / setupBadgeWebSocket now refuse unauthenticated
upgrades with a proper 401 + socket close.
- Frontend: new auth.ts module captures ?token= off the URL into
localStorage (key fn.authToken), strips it from the visible URL via
replaceState, and installs a window.fetch wrapper that injects
Authorization: Bearer <token> on every same-origin /api/* request.
EventSource/WebSocket URL builders (api.ts, sse-bus.ts, useTerminal,
useBadgeWebSocket) route through appendTokenQuery().
MIT license
- LICENSE file at repo root.
- license: "MIT" on root package.json and every packages/*/package.json,
plus description/bugs metadata on the CLI package.
Docs
- docs/cli-reference.md documents --token / --no-auth / FUSION_DASHBOARD_TOKEN
and the click-to-open auth flow.
- docs/getting-started.md, docs/docker.md, README.md point at the new flow
and the CLI reference section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add stateDerived metadata to AgentHealthStatus to indicate when health text only mirrors agent.state
- Update getAgentHealthStatus to set stateDerived consistently across terminated, error, paused, running, heartbeat, idle, and disabled paths
- Update AgentDetailView, AgentListModal, and AgentsView to render icon-only health badges when labels are state-derived while preserving full labels via title tooltips
- Expand agentHealth tests with explicit stateDerived assertions and a table-driven semantics suite for representative states
- Extend isEphemeralAgent to treat metadata.internal agents as internal system agents
- Add legacy fallback detection for executor agents named verification-agent with no reportsTo
- Update AgentsView list and org tree filtering to honor the Show system agents toggle
- Add regression coverage in core and dashboard tests for default filtering and includeEphemeral visibility
- Move the assigned agent badge out of the card header into a dedicated metadata row below task details
- Add a new .card-agent-row container to control spacing and alignment for the badge block
- Update .card-agent-badge styling to use token-aligned pill radius and color-mix backgrounds while removing monospace/fixed-width conventions
- Expand TaskCard agent badge tests to verify new DOM placement and enforced badge style rules
- Update the dashboard dev-server API client for compatibility with multiple backend response shapes
- Refine useDevServer polling and SSE lifecycle handling to improve status/action reliability
- Gate dev server navigation in header/mobile overflow and fix mobile preview header wrapping styles
- Expand DevServerView and useDevServer test coverage with isolated mocks and log/status assertions
- Document the devServerView experimental feature flag in settings reference
- Add preview embed diagnostics with richer error classification and fallback state handling
- Improve PreviewIframe and DevServerView retry UX for timeout and iframe failure states
- Adjust preview layout/styles to prevent clipping and header overflow while keeping fallback panels centered
- Expand dashboard tests to cover fallback transitions, retry flows, and responsive CSS behavior
- Add usePreviewEmbed hook to derive preview embed URLs and availability state
- Add PreviewIframe component with iframe load/error wiring and deduplicated error callbacks
- Integrate preview panel actions, fallback messaging, and embedded iframe rendering in DevServerView
- Expand test coverage for usePreviewEmbed, PreviewIframe, and DevServerView preview integration scenarios
- Display heartbeat interval and timeout in seconds while persisting runtimeConfig in milliseconds
- Convert derived and persisted heartbeat values before dirty-state comparison so unchanged settings keep Save Settings disabled
- Update heartbeat validation minimums, placeholders, and hints to align with seconds-based inputs
- Expand AgentDetailView tests for pre-filled values, unchanged-state save disabling, validation, and payload conversion
- Show Run Now controls in AgentsView for active and running agents without requiring taskId
- Rename Run Heartbeat copy to Run Now and update runs-tab accessibility labels in AgentDetailView
- Add AgentsView coverage for Run Now visibility and startAgentRun invocation when no task is assigned
- Update agent runs UI static-analysis tests and add a patch changeset for @gsxdsm/fusion