Threads an optional per-session reasoning-effort (thinkingLevel) through mission planning and planning-mode agent sessions so the selected level survives draft reopen, session start, and agent rebuild.
- Add ThinkingLevel to DraftInputPayload/session state in planning.ts; persist and restore it in inputPayload alongside model overrides, threading it into createDraftSession, startExistingSession, createSessionWithAgent, initializeAgent, createPlanningAgent, and ensureSessionAgent as defaultThinkingLevel.
- Preserve thinkingLevel across draft syncs in ai-session-store.ts's updateDraft so it isn't erased when the model pair is unchanged.
- Extend mission-interview.ts session state/persistence and createMissionInterviewAgent/createMissionInterviewSession to accept and persist a validated thinkingLevel, defaulting the agent's reasoning effort from it.
- Validate thinkingLevel against THINKING_LEVELS in mission-routes.ts's POST /api/missions/interview/start and thread it through to the interview session.
- Update PlanningModeModal.tsx and MissionInterviewModal.tsx to surface and submit the selected thinking level; update legacy.ts API client to pass it through.
- Extend register-planning-subtask-routes.ts to accept/validate/forward thinkingLevel for subtask planning routes.
- Add regression coverage in mission-interview.test.ts, routes-planning.test.ts, and session-persistence-roundtrip.test.ts.
- Add changeset for @runfusion/fusion (minor): persisted thinking-level controls for Mission Interview and Planning mode.
Files changed:
.changeset/quiet-dragons-think.md | 7 ++
packages/dashboard/app/api/legacy.ts | 14 ++-
.../app/components/MissionInterviewModal.tsx | 21 +++-
.../dashboard/app/components/PlanningModeModal.tsx | 34 ++++--
.../src/__tests__/mission-interview.test.ts | 34 ++++++
.../src/__tests__/routes-planning.test.ts | 17 ++-
.../session-persistence-roundtrip.test.ts | 16 +++
packages/dashboard/src/ai-session-store.ts | 13 +-
packages/dashboard/src/mission-interview.ts | 30 ++++-
packages/dashboard/src/mission-routes.ts | 14 ++-
packages/dashboard/src/planning.ts | 70 ++++++++---
packages/dashboard/src/routes.ts | 11 +-
.../src/routes/register-planning-subtask-routes.ts | 135 +++++++++++++++------
13 files changed, 330 insertions(+), 86 deletions(-)
Fusion-Task-Id: FN-7902
Fusion-Task-Lineage: 751fb238-fd67-4870-975d-3b10dadde1a0
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
The task cards already show Retry for needs-replan/planning/failed states, but
the retry route only offered the planning retry when the card sat in "triage",
so plan-in-place workflows (Coding (Ideas) replans in Todo) got a 400 "not in a
retryable state". The retrySpecification gate is now workflow-aware: a Todo card
whose workflow declares no "triage" column takes the planning-retry path;
default-workflow Todo cards keep the generic-retry semantics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Root cause of the reported incident: store init ran the retired flag-off
evacuation on every open, dumping Coding (Ideas) intake cards into triage
where they were auto-planned and executed. Init now always runs the
workflow-aware integrity pass (with a stale-selection mis-mapping guard and
per-pass IR memoization) and evacuation remains toggle-only.
Engine rebounds (Plan Review REVISE, stale-spec, fs-validation) resolve a
workflow-aware replan column instead of hardcoding triage; needs-replan now
counts as unplanned for hold-release dispatch so rejected plans cannot
re-execute; triage rediscovers needs-replan todo cards and refinement seed
prompts (shared buildRefinementSeedPrompt/isUnplannedSeedPrompt); the
fs-validation rebound sets needs-replan so unreadable-prompt tasks re-spec
instead of livelocking.
Dashboard: the All-workflows board renders column-orphaned tasks instead of
silently dropping them (hidden columns stay hidden), and the FN-7591 refetch
also fires for present-but-unrepresentable workflow mappings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a persisted, optional per-step reasoning-effort (thinkingLevel) override for AI-capable schedule and routine automation steps, surfaced in the editors and validated at the route layer.
- Add optional AutomationStep.thinkingLevel field (packages/core/src/automation.ts), riding the existing JSON steps blob so no DB migration is needed; runtime application of the level is deferred to a follow-up.
- Validate thinkingLevel in dashboard route step validation against the shared THINKING_LEVELS set, rejecting unknown values (packages/dashboard/src/routes.ts).
- Add Thinking Level controls to RoutineEditor, ScheduleForm, and ScheduleStepsEditor so users can set/inherit the override per step.
- Extend core and dashboard test suites (automation-store, routine-store, RoutineEditor, ScheduleForm, ScheduleStepsEditor, routes-automation) to cover persistence, validation, and UI behavior.
- Update dashboard-guide.md docs and add a minor changeset for the new feature.
Files changed:
.changeset/fn-7900-automation-thinking-level.md | 7 +
docs/dashboard-guide.md | 3 +-
.../core/src/__tests__/automation-store.test.ts | 45 ++++++
packages/core/src/__tests__/routine-store.test.ts | 46 +++++++
packages/core/src/automation.ts | 9 ++
.../dashboard/app/components/RoutineEditor.tsx | 21 ++-
packages/dashboard/app/components/ScheduleForm.tsx | 28 +++-
.../app/components/ScheduleStepsEditor.tsx | 21 ++-
.../components/__tests__/RoutineEditor.test.tsx | 99 +++++++++++++-
.../app/components/__tests__/ScheduleForm.test.tsx | 137 +++++++++++++++++--
.../__tests__/ScheduleStepsEditor.test.tsx | 83 +++++++++--
.../src/__tests__/routes-automation.test.ts | 152 +++++++++++++++++++++
packages/dashboard/src/routes.ts | 10 ++
13 files changed, 622 insertions(+), 39 deletions(-)
Fusion-Task-Id: FN-7900
Fusion-Task-Lineage: 812a9a8c-ad0f-462f-b1c6-9900f70e4261
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a persisted Thinking Level (reasoning-effort) selector to manual insight generation, threading the selection through the dashboard API, insight run metadata, and retries.
- Add inline Thinking Level selector to the InsightsView model-config popover, persisted to localStorage (fusion-insight-thinking)
- Thread thinkingLevel through triggerInsightRun (legacy API client) and useInsights.runInsights
- Validate and store thinkingLevel in insight run inputMetadata.metadata on the POST /insights/run route; resolve it via resolvePlanningThinkingLevel for the actual generation call
- Recover and reapply the original run's thinkingLevel on retry (retryInsightRunLifecycle) so retries reuse the same reasoning-effort setting
- Export resolvePlanningThinkingLevel from @fusion/engine
- Document the new Thinking Level selector in docs/dashboard-guide.md
- Add a minor changeset for @runfusion/fusion
Files changed:
.changeset/fn-7901-insight-thinking-level.md | 7 ++
docs/dashboard-guide.md | 1 +
.../app/__tests__/insight-model-selector.test.tsx | 41 ++++++++++-
packages/dashboard/app/api/legacy.ts | 2 +
packages/dashboard/app/components/InsightsView.tsx | 24 +++++-
.../app/hooks/__tests__/useInsights.test.ts | 36 ++++++++-
packages/dashboard/app/hooks/useInsights.ts | 6 +-
.../src/__tests__/insights-routes.test.ts | 86 ++++++++++++++++++++++
packages/dashboard/src/insights-routes.ts | 36 ++++++++-
packages/engine/src/index.ts | 1 +
10 files changed, 227 insertions(+), 13 deletions(-)
Fusion-Task-Id: FN-7901
Fusion-Task-Lineage: a6249526-e97d-403e-b853-e497d16f425b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Bring thinking-level (reasoning effort) editing to every remaining model selector surface that previously lacked it, so operators can set it consistently from Agent Detail, Agent Onboarding, and the List view's bulk task editor, in addition to the batch-update-models API and route that back them.
- Agent Detail config tab: persist/edit a built-in agent's runtimeConfig.thinkingLevel inline via the shared model dropdown, with dirty-state and reset tracking.
- Agent Onboarding modal: replace the read-only thinking-level input with an editable control wired into the same model dropdown used for creation.
- List view bulk edit toolbar: add a "no change" / "use default" / explicit-level thinking selector alongside executor/reviewer model and node overrides, wired through to the bulk apply action.
- Dashboard API client (`batchUpdateTaskModels`) and `/api/tasks/batch-update-models` route: accept and validate an optional `thinkingLevel` field (against `THINKING_LEVELS`), applying it per task alongside existing model/node updates.
- Update dashboard-guide.md docs and add regression tests across AgentDetailView, AgentOnboardingModal, ListView, and the batch-update-models route.
- Add a minor changeset documenting the feature for release notes.
Files changed:
.changeset/thinking-level-selector-parity.md | 7 ++
docs/dashboard-guide.md | 5 +-
packages/dashboard/app/api/legacy.ts | 3 +
.../dashboard/app/components/AgentDetailView.tsx | 20 +++++-
.../app/components/AgentOnboardingModal.tsx | 11 +++-
packages/dashboard/app/components/ListView.tsx | 54 +++++++++++++---
.../__tests__/AgentDetailView.settings.test.tsx | 45 +++++++++++++
.../__tests__/AgentDetailView.test-helpers.ts | 19 +++++-
.../__tests__/AgentOnboardingModal.test.tsx | 41 +++++++++++-
.../app/components/__tests__/ListView.test.tsx | 43 ++++++++++++-
.../src/__tests__/routes-tasks-ops.test.ts | 75 ++++++++++++++++++++++
.../src/routes/register-task-workflow-routes.ts | 22 +++++--
12 files changed, 323 insertions(+), 22 deletions(-)
Fusion-Task-Id: FN-7899
Fusion-Task-Lineage: fd584ce4-42b3-4c20-8de5-4d3c8963f593
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the Report-a-Bug flow producing a GitHub "request URL too long" error by budgeting truncation against the actual encoded URL GitHub receives instead of the raw diagnostics body length.
- Replace the raw BUG_URL_BODY_CAP (5500 chars) with BUG_URL_MAX_ENCODED (8000 chars), measured against the final GitHub issue URL (base URL + ?body= + encodeURIComponent(body)).
- Add buildBugReportIssueUrl() which binary-searches the largest body prefix (by code point) whose encoded URL still fits the budget, appending a truncation marker when needed.
- doReportBug now calls buildBugReportIssueUrl(body) instead of manually slicing the body and encoding it inline.
- Update tests to assert the final URL length stays under BUG_URL_MAX_ENCODED and to exercise a diagnostics bundle whose JSON (quotes/braces) expands significantly under percent-encoding.
Files changed:
.../__tests__/SystemControlsArea.test.tsx | 9 +++--
.../command-center/areas/SystemControlsArea.tsx | 47 +++++++++++++++++-----
2 files changed, 44 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7890
Fusion-Task-Lineage: fcadafcd-0bbc-4c06-b2ec-c2b124d736db
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Vertically nudges the card-header-actions cluster (size badge/menu icons) to share the same optical centerline as the mono task id, matching the existing id nudge.
- Add a translateY(calc(var(--space-xs) / 4)) transform to .card-header-actions in TaskCard.css, mirroring the FN-7871 id nudge
- Document the change with an FNXC comment explaining the FN-7889 requirement and its relationship to FN-7871/FN-7862/FN-7837
- Extend the TaskCard.badge-wrap.test.tsx regression test to assert the actions cluster's transform matches the id's transform and stays tokenized (no raw px values)
Files changed:
packages/dashboard/app/components/TaskCard.css | 6 +++++-
.../dashboard/app/components/__tests__/TaskCard.badge-wrap.test.tsx | 4 ++++
2 files changed, 9 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7889
Fusion-Task-Lineage: d4743b8f-c7d7-4c3b-9b68-f632dd6e0b7b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Replace the bug-report flow's last-5-error-lines excerpt with the full buildDiagnostics() bundle (health, runtime/system info, recent logs) behind a single confirmation prompt.
- doReportBug now reuses buildDiagnostics() instead of independently fetching a 5-line error excerpt
- Single confirm() prompt covers the whole diagnostics bundle instead of only recent errors
- Diagnostics are embedded as a collapsible <details> JSON code block under a new ### Diagnostics section
- Preserved existing safeguards: fenceSafe() neutralization of embedded code fences and BUG_URL_BODY_CAP truncation
- Added tests covering: full bundle inclusion on confirm, omission on decline, fence-breakout neutralization, and oversized-bundle truncation
Files changed:
.../__tests__/SystemControlsArea.test.tsx | 96 ++++++++++++++++++++++
.../command-center/areas/SystemControlsArea.tsx | 53 +++++++-----
2 files changed, 128 insertions(+), 21 deletions(-)
Fusion-Task-Id: FN-7883
Fusion-Task-Lineage: 44dd26de-d0f6-427b-a082-59d580f31674
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Route Command Center diagnostics copy through the shared clipboard helper so it no longer throws on non-secure origins (e.g. mobile http://fusionstudio:4040).
- Replace direct navigator.clipboard.writeText call in SystemControlsArea's diagnostics copy handler with copyTextToClipboard, which guards for secure-context clipboard support and falls back to document.execCommand("copy").
- Surface a distinct failure toast ("Could not copy diagnostics to clipboard") when neither clipboard path succeeds, instead of crashing.
- Add regression tests covering the execCommand fallback, the secure-context Clipboard API path, and the failure-toast path when both copy mechanisms are unavailable.
- Add a patch changeset documenting the fix.
Files changed:
.changeset/fn-7882-copy-diagnostics-fix.md | 7 ++
.../__tests__/SystemControlsArea.test.tsx | 87 +++++++++++++++++++++-
.../command-center/areas/SystemControlsArea.tsx | 13 +++-
3 files changed, 102 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-7882
Fusion-Task-Lineage: eceb93bf-b32d-4127-b370-4779cb4e4e27
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Keeps the Command Center System tab's refresh button inline with the section title and pinned to the far right at all breakpoints, instead of dropping below the title on mobile.
- Add a scoped .cc-area-section-header.cc-system-controls-header CSS override (row + space-between) that wins over the shared mobile column-collapse rule for the System tab only
- Add data-testid="cc-system-refresh" to the refresh button for test targeting
- Add regression tests asserting the header stays row-aligned in the DOM and the CSS override is present at the 768px breakpoint
- Add a patch changeset documenting the fix
Files changed:
.changeset/fn-7881-system-refresh-inline.md | 7 +++++++
.../__tests__/SystemControlsArea.test.tsx | 23 ++++++++++++++++++++++
.../command-center/areas/SystemControlsArea.css | 22 +++++++++++++++++++++
.../command-center/areas/SystemControlsArea.tsx | 3 ++-
4 files changed, 54 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7881
Fusion-Task-Lineage: 80c6fd78-b7e0-4899-b509-b69b8d21e82d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a best-effort, idempotent dashboard inbox notice announcing the upcoming embedded-Postgres storage migration, delivered once per project on the first engine start under the Fusion 0.59.x release line.
- New `deliverPostgresMigrationNoticeIfNeeded` in `@fusion/engine` (`postgres-migration-notice.ts`) builds and sends a `system` -> `user` inbox message via `MessageStore`, gated to version `0.59.x` by `isPostgresMigrationNoticeVersion`
- Idempotency via existing inbox message `metadata.kind = "postgres-migration-notice"` marker (no new settings key or table), so restarts never duplicate the notice
- Delivery is fully best-effort: any `MessageStore` failure is caught, logged as a warning, and never blocks or fails `ProjectEngine.start()`
- `ProjectEngine.start()` invokes the notice after runtime start, using an injected `cliPackageVersion` threaded from the CLI layer through `EngineManagerOptions` / `ProjectEngineOptions` so the engine never imports CLI/dashboard code directly
- `daemon.ts`, `dashboard.ts`, and `serve.ts` resolve the published `@runfusion/fusion` version via `getCliPackageVersion` / `isUnresolvedCliPackageVersion` and pass it into `ProjectEngineManager`
- Exported new symbols (`POSTGRES_MIGRATION_HELP_URL`, `POSTGRES_MIGRATION_NOTICE_KIND`, `deliverPostgresMigrationNoticeIfNeeded`, `isPostgresMigrationNoticeVersion`, related types) from `@fusion/engine`, and `isUnresolvedCliPackageVersion` from `@fusion/dashboard`
- New unit tests covering version matching and single-delivery/idempotency behavior
- Docs updated (`docs/agents.md`, `docs/dashboard-guide.md`) to describe the one-time notice and its dedup key
- Changeset added for `@runfusion/fusion` (minor, feature)
Files changed:
.changeset/fn-7879-postgres-migration-inbox-notice.md | 7 ++
docs/agents.md | 1 +
docs/dashboard-guide.md | 1 +
packages/cli/src/commands/daemon.ts | 6 +-
packages/cli/src/commands/dashboard.ts | 5 +
packages/cli/src/commands/serve.ts | 6 +-
packages/dashboard/src/index.ts | 2 +-
packages/engine/src/__tests__/postgres-migration-notice.test.ts | 140 +++++++++++++++++++++
packages/engine/src/index.ts | 9 ++
packages/engine/src/postgres-migration-notice.ts | 107 ++++++++++++++++
packages/engine/src/project-engine-manager.ts | 6 +
packages/engine/src/project-engine.ts | 12 ++
12 files changed, 299 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7879
Fusion-Task-Lineage: 201877e5-6bdc-4168-a8ac-ae0e50ec8308
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Durable agents were parking as error-unrecoverable on any non-transient-pattern failure, even generic/unknown blips that manual Retry immediately fixed; this changes the default to recoverable and reserves immediate unrecoverable parking for operator-actionable errors.
- isHeartbeatErrorRecoverable now returns true unless the error is operator-actionable (auth/model/billing/scope) or a stale worktree/module-resolution error, instead of requiring a transient-pattern match via classifyError
- Add OAuth scope-requirement and insufficient-scope patterns to the operator-actionable error detector so those still park immediately
- Update heartbeat-error-recovery, heartbeat-executor, self-healing, and transient-error-detector tests to cover the new default-recoverable behavior
- Update AGENTS.md and docs/architecture.md durable-agent error recovery notes to describe the new recoverable-by-default policy
- Add changeset documenting the fix
Files changed:
.changeset/fn-7878-recoverable-default.md | 7 ++
AGENTS.md | 2 +-
docs/architecture.md | 4 +-
.../src/__tests__/heartbeat-error-recovery.test.ts | 90 +++++++++++++++++++---
.../src/__tests__/heartbeat-executor.test.ts | 17 ++--
packages/engine/src/__tests__/self-healing.test.ts | 45 ++++++-----
.../src/__tests__/transient-error-detector.test.ts | 7 +-
packages/engine/src/agent-heartbeat.ts | 8 +-
packages/engine/src/transient-error-detector.ts | 2 +
9 files changed, 137 insertions(+), 45 deletions(-)
Fusion-Task-Id: FN-7878
Fusion-Task-Lineage: 6f929af9-ceef-404f-95c9-98f26478f020
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Wraps the System tab's controls and stats areas in a shared flex container so vertical rhythm is consistent, and canonicalizes hard-coded status colors to design tokens.
- Wrap SystemControlsArea + SystemStatsArea in a new .cc-system-tab flex container with --space-lg gap, replacing the bare React fragment, so Server logs and Live system health sections get consistent breathing room.
- Add responsive gap rule for .cc-system-tab under the 768px breakpoint.
- Replace hard-coded --danger/--warning fallback colors in SystemControlsArea.css with canonical --color-error/--color-warning tokens.
- Add SystemControlsArea test coverage.
- Add a patch changeset documenting the spacing fix.
Files changed:
.changeset/fn-7877-system-tab-spacing.md | 7 +
.../components/command-center/CommandCenter.css | 15 ++
.../components/command-center/CommandCenter.tsx | 8 +-
.../__tests__/SystemControlsArea.test.tsx | 157 +++++++++++++++++++++
.../command-center/areas/SystemControlsArea.css | 8 +-
5 files changed, 189 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-7877
Fusion-Task-Lineage: eb4a97ed-5442-43e8-8d38-348fc3e220a8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Move redactSecrets to the log/warn/error entry points so both the
recorded history (served over /system/logs) and the TUI/console output
are masked — previously only the stored entry was redacted while the raw
message still printed to the terminal. Add assertions for both the
console and TUI-target output paths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- pnpm dev / new pnpm start default to the dashboard command
- fn dashboard (and bare fn/fusion/npx, incl. packaged binaries) now runs
supervised by default via an attached foreground child (TUI-safe);
--no-supervise opts out; FUSION_RESTART_EXIT_CODE=86 = intentional restart
- New /api/system routes: info, restart, rebuild jobs with SSE output,
engine restart, agents restart-all, plugins reload-all, log tail
- System tab: rebuild & restart (source checkouts only, hidden elsewhere),
restart server/engine/agents, backup DB, live server logs, copy
diagnostics, report bug; new Plugins tab reusing PluginManager
- Desktop restart via Electron app.relaunch(); DashboardLogSink now keeps a
bounded history + listener feed for the log viewer
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Exclude revoked/suspended/disabled/deactivated keys, inactive subscriptions,
and locked accounts from the transient-auth classifier: no retry fixes those,
so they stay operator-actionable even inside an authentication_error envelope.
- Self-healing sweep logs unrecoverable-error parks separately from
recovered-to-active agents (return value still counts actions taken).
- Document same-session retry continuation semantics at the heartbeat
withRateLimitRetry call site (side-effect replay concern).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A routine Claude Max OAuth token rotation (~8h) fails the in-flight call with
401 authentication_error "Invalid authentication credentials" even though
refreshed credentials already exist on disk. Three compounding defects turned
that into a fleet-wide operator-action park:
- The heartbeat prompt path never ran under withRateLimitRetry (executor/
triage/merger all do), so the 401 immediately failed the run. Now wrapped.
- The 401 matched the operator-actionable /credential/ pattern and defaulted
to "permanent", so FN-7859 parked agents paused/error-unrecoverable. A new
shared isTransientAuthCredentialError classifier (also used by
rate-limit-retry) classifies rotation 401s transient + not operator-
actionable; OAuth scope-grant and API-key failures still park.
- Heartbeat failure classification ran on the stack-bearing error detail;
stack frames like "at withRateLimitRetry (.../rate-limit-retry.ts)" match
the usage-limit /rate[_\s]?limit/ pattern. Classification and
agent.lastError now use the message; stderrExcerpt keeps the full detail.
Self-healing additionally un-parks agents previously paused with
error-unrecoverable whose lastError now classifies recoverable, bounded by
the shared heartbeat error-recovery budget.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extends the embedded Task Detail SessionTerminal to surface the shared, user-defined terminal shortcuts (from FN-7872's kb-terminal-preferences localStorage) as tappable buttons in its mobile accessory key bar.
- Read customShortcuts via the shared readTerminalPreferences() store on mount and refresh live on the storage event
- Render each custom shortcut as a mobile-only accessory-bar button that injects decodeTerminalShortcutSequence(value) through the focus-preserving keepFocus + sendInput path, clearing sticky Ctrl like the built-in ^C key
- Suppress the buttons for read-only/replay/idle/ended sessions via the existing canAcceptInput gate; desktop embedded terminals get no key bar
- Add .cli-terminal-key--custom styling for the new buttons
- Update docs/dashboard-guide.md to describe the mobile custom-shortcut key bar behavior
- Add a minor changeset for @runfusion/fusion documenting the feature
- Add SessionTerminal.mobile.test.tsx coverage for rendering, injection, live updates, and read-only suppression
Files changed:
.changeset/fn-7876-session-terminal-custom-shortcuts.md | 7 ++
docs/dashboard-guide.md | 2 +-
packages/dashboard/app/components/SessionTerminal.css | 5 ++
packages/dashboard/app/components/SessionTerminal.tsx | 31 +++++++
packages/dashboard/app/components/__tests__/SessionTerminal.mobile.test.tsx | 94 ++++++++++++++++++++++
5 files changed, 138 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7876
Fusion-Task-Lineage: 61d62ad2-7357-4eb4-b542-6e17deea1e5e
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a hardened Discord support link and clarifies that project databases move to the central Fusion database in the storage update notice banner.
- Add a "Get help" button/link to the Fusion Discord (https://discord.gg/ksrfuy7WYR) in StorageMigrationNoticeBanner, with new .storage-migration-notice-banner__actions/__help CSS (desktop + mobile layout)
- Revise the banner body copy to state that project databases will be served from the central Fusion database instead of each project's local .fusion/fusion.db SQLite file
- Add storageMigrationNotice.getHelp/getHelpLabel i18n keys and update en/app.json body copy; sync placeholder keys across es/fr/ko/zh-CN/zh-TW locales and regenerate resources.d.ts
- Extend StorageMigrationNoticeBanner tests to cover the new help link (href/target/rel) and updated body copy, including dismissed/error-path cases
- Add a minor changeset for @runfusion/fusion documenting the banner change
Files changed:
.changeset/fn-7874-storage-banner-get-help.md | 7 ++++++
.../components/StorageMigrationNoticeBanner.css | 26 ++++++++++++++++++++++
.../components/StorageMigrationNoticeBanner.tsx | 16 ++++++++++++-
.../StorageMigrationNoticeBanner.test.tsx | 16 +++++++++++--
packages/i18n/locales/en/app.json | 4 +++-
packages/i18n/locales/es/app.json | 7 ++++++
packages/i18n/locales/fr/app.json | 7 ++++++
packages/i18n/locales/ko/app.json | 7 ++++++
packages/i18n/locales/zh-CN/app.json | 7 ++++++
packages/i18n/locales/zh-TW/app.json | 7 ++++++
packages/i18n/src/resources.d.ts | 7 ++++++
11 files changed, 107 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7874
Fusion-Task-Lineage: baa88812-18ca-4910-a641-8d6e23f602a6
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a deterministic changelog-archive split so scripts/release.mjs stops regenerating one ever-growing root CHANGELOG.md and instead keeps only current release notes at the root while durably archiving pre-0.50.0 history.
- Add scripts/lib/changelog-archive.mjs with partitionVersionsByCutoff (splits a version-ordered list at the 0.50.0 cutoff, preserving order and treating non-parseable keys as archived) and archivePointerLine (renders the "older releases" pointer appended to the current changelog).
- Rework scripts/release.mjs's syncRootChangelog to build CHANGELOG.md (current versions + archive pointer) and a new CHANGELOG-archive.md (versions before 0.50.0) via a shared buildRootChangelogLines/normalizeChangelogLines helper instead of one monolithic file.
- Add scripts/__tests__/changelog-archive.test.mjs covering cutoff partitioning, boundary/patch handling, non-parseable keys, custom cutoffs, and the archive pointer text.
- Regenerate CHANGELOG.md (now only 0.50.0+) and add CHANGELOG-archive.md containing the pre-0.50.0 history moved out of the root file.
Files changed:
CHANGELOG-archive.md | 10882 +++++++++++++++++++++++
CHANGELOG.md | 11717 ++-----------------------
scripts/__tests__/changelog-archive.test.mjs | 58 +
scripts/lib/changelog-archive.mjs | 56 +
scripts/release.mjs | 49 +-
5 files changed, 11710 insertions(+), 11052 deletions(-)
Fusion-Task-Id: FN-7875
Fusion-Task-Lineage: 220e6aa1-54fb-4800-a86e-6d8d21f6bf18
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Restores reliable single-finger dragging of movable FloatingWindow headers on mobile by reasserting touch-action: none at the mobile breakpoint, and adds regression coverage for the touch drag path.
- Reassert touch-action: none on movable FloatingWindow headers within the mobile media query, excluding full-screen sheet variants (chat, task-detail, workflow-editor, automation, mission-interview, file-browser, pr-create, artifacts-gallery), so the drag-handle contract isn't overridden by the global pan-y lockdown on mobile.
- Add a test verifying the movable mobile drag-handle selector keeps touch-action: none alongside the other opted-out draggable selectors (right-dock-expand-modal header, terminal header).
- Add a test exercising the captured pointermove drag path (pointerdown/move/up with pointer capture) confirming the window repositions correctly on touch input.
- Add a patch changeset for @runfusion/fusion documenting the fix.
Files changed:
.changeset/fn-7873-mobile-modal-header-drag.md | 7 +++
packages/dashboard/app/components/FloatingWindow.css | 8 +++
packages/dashboard/app/components/__tests__/FloatingWindow.test.tsx | 59 ++++++++++++++++++++++
3 files changed, 74 insertions(+)
Fusion-Task-Id: FN-7873
Fusion-Task-Lineage: 96f2b199-549e-4cab-a42b-05946a7bae86
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Center the task-id chip with the header badge row on TaskCard.
- Add a subtle translateY nudge (calc(var(--space-xs) / 4)) to .card-id in TaskCard.css so the mono task id optically aligns with the first-row badges/icons, while preserving the existing FN-7862 flex-start anchor and FN-7837 badge-wrap contract.
- Add an FNXC:TaskCardLayout comment documenting the FN-7871 requirement and rationale for the nudge.
- Update TaskCard.badge-wrap.test.tsx to assert the new transform value on the rendered .card-id element and to assert the tokenized transform rule (and absence of a raw px translateY) directly in the loaded CSS.
Files changed:
packages/dashboard/app/components/TaskCard.css | 5 +++++
.../app/components/__tests__/TaskCard.badge-wrap.test.tsx | 9 ++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7871
Fusion-Task-Lineage: 0c79d482-42d3-4e34-8844-3113c3e75ad7
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a per-project Hide done / Show done toggle to the Todo list items header so operators can declutter long selected lists while completion counts still reflect all items.
- Add hideDone state persisted per project via localStorage (kb-dashboard-todo-hide-done key registered in projectStorage)
- Filter rendered todo items to hide completed ones when the toggle is active, while keeping list stats/progress counts based on all items
- Adjust up/down item reordering to operate correctly against the visible (filtered) list while still reordering the underlying full item list
- Add an empty-state message when all items are hidden by the toggle, with Eye/EyeOff icon + i18n strings (todo.hideDone, todo.showDone, todo.allDoneHidden)
- Add regression tests covering the toggle, persistence, filtering, and empty state
- Document the Hide done / Show done control in the dashboard guide
Files changed:
docs/dashboard-guide.md | 3 +
packages/dashboard/app/components/TodoView.css | 45 ++++++++++
packages/dashboard/app/components/TodoView.tsx | 66 +++++++++++++--
.../app/components/__tests__/TodoView.test.tsx | 99 ++++++++++++++++++++++
packages/dashboard/app/utils/projectStorage.ts | 1 +
packages/i18n/locales/en/app.json | 3 +
6 files changed, 210 insertions(+), 7 deletions(-)
Fusion-Task-Id: FN-7869
Fusion-Task-Lineage: 9c334aba-e802-43b8-963c-0f2daf727583
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a shared, persisted auto-save preference for workspace text-file editing, defaulted to on, surfaced as a toolbar toggle in both the Files modal and right-dock Files view.
- Add useAutoSavePreference hook: persists the fn-file-editor-auto-save localStorage preference, broadcasts same-window changes via a custom event (storage events only reach other documents), and defaults to true.
- Extend useWorkspaceFileEditor with an autoSave flag that debounces (800ms) and triggers save() for a loaded, editable file with real pending changes, keyed by workspace+file+content to avoid re-firing on failed writes.
- Add an Auto-save toggle button to FileEditor's toolbar (autoSaveEnabled/onToggleAutoSave/canToggleAutoSave props), hidden for read-only/preview/binary files.
- Wire the shared preference into FileBrowserModal and DockFilesView, disabling auto-save for binary files in the modal.
- Add fileEditor.autoSave / fileEditor.toggleAutoSave i18n strings and document the new default behavior in docs/dashboard-guide.md.
- Add/extend tests covering the new hook, debounced auto-save behavior, and toolbar toggle wiring across FileEditor, FileBrowserModal, and DockFilesView.
Files changed:
docs/dashboard-guide.md | 3 +
.../dashboard/app/components/DockFilesView.tsx | 6 +-
.../dashboard/app/components/FileBrowserModal.tsx | 20 ++--
packages/dashboard/app/components/FileEditor.tsx | 17 +++-
.../components/__tests__/DockFilesView.test.tsx | 37 ++++++-
.../components/__tests__/FileBrowserModal.test.tsx | 86 +++++++++++++---
.../app/components/__tests__/FileEditor.test.tsx | 56 +++++++++++
.../hooks/__tests__/useAutoSavePreference.test.ts | 66 +++++++++++++
.../hooks/__tests__/useWorkspaceFileEditor.test.ts | 108 +++++++++++++++++++++
.../dashboard/app/hooks/useAutoSavePreference.ts | 79 +++++++++++++++
.../dashboard/app/hooks/useWorkspaceFileEditor.ts | 47 ++++++++-
packages/i18n/locales/en/app.json | 2 +
12 files changed, 500 insertions(+), 27 deletions(-)
Fusion-Task-Id: FN-7866
Fusion-Task-Lineage: 0604de18-666d-4872-abce-2a3886c9ea55
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Plugin-contributed skills previously registered only a name for sessions and the dashboard, so their SKILL.md bodies were never actually loaded — fix threads real body paths through to both session creation and the Skills UI.
- Resolve each enabled plugin skill's body path via @fusion/core's resolvePluginSkillBodyPath and thread its body dir (plus parent dir) into every session-creating lane (executor primary/retry/verification-fix/step/child-agent, triage, reviewer, merger, agent-heartbeat, cron-runner) as additionalSkillPaths, unioned with existing CE skill dirs.
- Add collectPluginSkillNames/mergePluginSkills additionalSkillPaths plumbing in session-skill-context.ts so plugin skill discovery paths flow the same way as native/role-fallback skills.
- Update dashboard skills-adapter.ts to read plugin skill SKILL.md and reference files from disk (via the traversal-guarded reader) instead of returning a runtime-placeholder/"not found" response for plugin-sourced skills.
- Document the plugin skill body delivery mechanism in docs/PLUGIN_AUTHORING.md.
- Add regression coverage: plugin-skill-body-delivery.test.ts, expanded session-skill-context.test.ts and skills-adapter.test.ts.
- Add changeset fn-7857-plugin-skill-body-delivery.md (minor, fix).
Files changed:
.changeset/fn-7857-plugin-skill-body-delivery.md | 7 ++
docs/PLUGIN_AUTHORING.md | 3 +
.../dashboard/src/__tests__/skills-adapter.test.ts | 92 ++++++++++++++++------
packages/dashboard/src/skills-adapter.ts | 33 ++------
.../__tests__/plugin-skill-body-delivery.test.ts | 75 ++++++++++++++++++
.../src/__tests__/session-skill-context.test.ts | 84 +++++++++++++++++++-
packages/engine/src/agent-heartbeat.ts | 3 +-
packages/engine/src/cron-runner.ts | 2 +
packages/engine/src/executor.ts | 25 ++++--
packages/engine/src/merger.ts | 10 ++-
packages/engine/src/reviewer.ts | 2 +
packages/engine/src/session-skill-context.ts | 43 ++++++++--
packages/engine/src/step-session-executor.ts | 5 +-
packages/engine/src/triage.ts | 3 +-
14 files changed, 318 insertions(+), 69 deletions(-)
Fusion-Task-Id: FN-7857
Fusion-Task-Lineage: 9ba4c305-8b38-4ae8-85b3-4c87205ef767
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Flattens the Todo sidebar list rows so active/hover states read through background and text color only, without per-row borders or the active-row left accent stripe.
- Removed `border: 1px solid transparent` and hover `border-color` from `.todo-list-item`
- Added hover text color instead of hover border to keep hover state visible
- Removed the `border-color` and inset box-shadow accent stripe from `.todo-list-item--active`
- Added a CSS contract test asserting sidebar list rows stay flat (no left accent stripe, no per-row borders)
Files changed:
packages/dashboard/app/components/TodoView.css | 9 +++++----
.../components/__tests__/TodoView.mobile-css.test.ts | 19 +++++++++++++++++++
2 files changed, 24 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7870
Fusion-Task-Lineage: 78db20c0-7e53-427c-95da-7c9d5fa828d7
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a one-click commit-and-push affordance to the Git Manager modal's Changes panel, letting users commit staged changes and immediately push the active branch without a separate step.
- Add handleCommitAndPush callback in GitManagerModal that reuses createCommit and pushBranch, refreshes file changes/status on success, and surfaces a distinct toast (with the local commit hash preserved) if the push step fails after a successful commit
- Wire commitAndPush through to ChangesPanel and render a new "Commit and Push" button beside the existing Commit button, disabled while committing, when the message is empty, or when there are no staged files
- Add test coverage for the commit-and-push flow, including the partial-failure case where commit succeeds but push fails
- Add a minor changeset documenting the new Git Manager feature
Files changed:
.changeset/fn-7868-git-manager-commit-push.md | 7 +++
.../dashboard/app/components/GitManagerModal.tsx | 64 +++++++++++++++++++-
.../components/__tests__/GitManagerModal.test.tsx | 68 ++++++++++++++++++++++
3 files changed, 138 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7868
Fusion-Task-Lineage: 8b6913db-6f2a-45ab-b99d-a5c11ce53439
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Board TaskCard priority badges no longer render visible priority text, so the .card-meta-badges row cannot wrap onto a new line when a priority label widens it.
- TaskCard.tsx: drop the visible priority-label <span>, add title/aria-label with the full priority label, and keep the label reachable via a visually-hidden span for assistive tech
- TaskCard.css: update the FNXC comment on .card-priority-badge to reflect the icon-only rationale (spacing/geometry rules unchanged, still shared with the Task Detail chip/select)
- TaskCard.test.tsx: assert icon-only rendering (no visible text node/span), title/aria-label correctness, visually-hidden label content, and that the badge is absent for tasks without a priority; loosen the mocked lucide icons to forward arbitrary props
- Add a patch changeset documenting the icon-only priority badge fix
Files changed:
.changeset/icon-only-priority-badges.md | 7 +++++
packages/dashboard/app/components/TaskCard.css | 2 +-
packages/dashboard/app/components/TaskCard.tsx | 12 ++++++---
.../app/components/__tests__/TaskCard.test.tsx | 30 +++++++++++++++++-----
4 files changed, 39 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7867
Fusion-Task-Lineage: 5c845c23-0a9f-47b4-9a75-6c410b507ef4
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Project-scoped chat managers can be cached before the project engine boots, so fn_send_message/fn_read_messages were silently dropped for lazily-booted (desktop) sessions while browser sessions kept them; the fix refreshes the cached manager's MessageStore post-construction and surfaces a diagnostic + chat-stream warning when the reduced tool schema condition occurs instead of failing silently.
Key changes:
- ChatManager gains setMessageStore() to refresh a cached manager's MessageStore post-construction, mirroring the existing setPluginRunner() refresh seam
- getOrCreateScopedChatManager()/resolveScopedChatManager() now accept and wire an optional MessageStore, upgrading already-cached managers instead of leaving them stale
- register-chat-routes.ts now passes engine.getMessageStore() through to the scoped chat manager resolver
- ChatManager emits a new 'warning' chat-stream event (code: tool-schema-reduced) plus a diagnostics.warn() call when a bound agent has no MessageStore, so reduced tool schema is agent-visible instead of a silent per-call failure
- Added regression tests covering MessageStore wiring/refresh in chat-project-services and chat-manager, plus a patch changeset documenting the fix
Files changed:
.changeset/fn-7854-chat-tool-schema-parity.md | 7 ++
.../dashboard/src/__tests__/chat-manager.test.ts | 124 ++++++++++++++++++++-
.../src/__tests__/chat-project-services.test.ts | 67 +++++++++++
packages/dashboard/src/chat-project-services.ts | 10 +-
packages/dashboard/src/chat.ts | 39 +++++++
.../dashboard/src/routes/register-chat-routes.ts | 2 +-
6 files changed, 245 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7854
Fusion-Task-Lineage: 1d1ee3e7-608b-4b7d-be45-138b38b27f17
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>