Commit Graph

11231 Commits

Author SHA1 Message Date
gsxdsm
c110b72df1 FN-7902: persist thinkingLevel across mission/planning interview sessions
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>
2026-07-12 20:05:08 -07:00
gsxdsm
23cb061af2 FN-7898: add in-chat thinking-level control next to the attach button
Adds a Brain-icon popover control in the chat composer that lets users change an existing session's reasoning-effort level mid-conversation, extending the existing create-time-only thinking-level picker.

- Add ChatThinkingLevelControl component (Brain-icon trigger + popover) wired into ChatView's direct-session composer, gated to non-CLI model-loop sessions only
- Extend PATCH /api/chat/sessions/:id to accept an optional thinkingLevel field, validated via existing validateThinkingLevel helper; null/empty string explicitly clears back to the inherited default, omitting the key leaves it untouched
- Add useChat().setSessionThinkingLevel hook method to call the new PATCH capability
- Add i18n strings (thinkingLevelButton) across all locales and regenerate packages/i18n/src/resources.d.ts
- Add changeset for @runfusion/fusion (minor) and update docs/dashboard-guide.md

Files changed:
 .changeset/fn-7898-chat-thinking-level-control.md  |   7 +
 docs/dashboard-guide.md                            |   2 +
 packages/dashboard/app/api/legacy.ts               |   4 +-
 .../app/components/ChatThinkingLevelControl.tsx    | 133 +++++++++++
 packages/dashboard/app/components/ChatView.css     |  73 ++++++
 packages/dashboard/app/components/ChatView.tsx     |  20 ++
 .../__tests__/ChatThinkingLevelControl.test.tsx    | 103 ++++++++
 .../__tests__/ChatView.message-edit.test.tsx       |   1 +
 .../components/__tests__/ChatView.test-harness.tsx |   1 +
 .../__tests__/ChatView.thinking-level.test.tsx     | 262 +++++++++++++++++++++
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 108 +++++++++
 packages/dashboard/app/hooks/useChat.ts            |  59 +++++
 .../dashboard/src/__tests__/chat-routes.test.ts    |  83 +++++++
 .../dashboard/src/routes/register-chat-routes.ts   |  35 ++-
 packages/i18n/locales/en/app.json                  |   1 +
 packages/i18n/locales/es/app.json                  |   1 +
 packages/i18n/locales/fr/app.json                  |   1 +
 packages/i18n/locales/ko/app.json                  |   1 +
 packages/i18n/locales/zh-CN/app.json               |   1 +
 packages/i18n/locales/zh-TW/app.json               |   1 +
 packages/i18n/src/resources.d.ts                   |  96 ++++++--
 21 files changed, 970 insertions(+), 23 deletions(-)

Fusion-Task-Id: FN-7898

Fusion-Task-Lineage: a052a6ef-d2d3-45af-9b92-221996780b1b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 20:00:50 -07:00
gsxdsm
0e6f94dbe6 fix: offer the planning retry for needs-replan Todo cards in triage-less workflows
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>
2026-07-12 19:51:35 -07:00
gsxdsm
d4bbbcccc6 fix: stop Ideas-intake cards from auto-processing and keep replans in the workflow's own planner column
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>
2026-07-12 19:47:27 -07:00
gsxdsm
635d78248b FN-7900: persist thinkingLevel override for schedule and routine AI steps
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>
2026-07-12 19:43:41 -07:00
gsxdsm
7a51f95b38 FN-7901: persist thinkingLevel for insight model selection
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>
2026-07-12 19:39:42 -07:00
gsxdsm
b98314923c FN-7899: add thinking-level editing to Agent Detail, Onboarding, and bulk task model selectors
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>
2026-07-12 19:18:25 -07:00
gsxdsm
02fdb4c089 FN-7897: reserve footer space for pinned below-mode terminal
Fix the pinned (below-mode) terminal panel rendering underneath the fixed ExecutorStatusBar footer, so its bottom action-control row stays visible on desktop and mobile alike.

- Add a footerVisible prop to TerminalModal, wired from App.tsx's executorFooterVisible state
- Add .terminal-below-host--with-footer CSS modifier that redeclares --executor-footer-height and reserves padding-bottom (with the Android Chrome ICB offset), matching the .project-content--with-footer/.left-sidebar-nav--with-footer/.right-dock--with-footer precedent
- Update dashboard-guide.md terminal walkthrough to describe the new footer-avoidance behavior
- Add/extend TerminalModal tests covering the footerVisible prop and CSS modifier
- Add a patch changeset for @runfusion/fusion documenting the fix

Files changed:
 .../fn-7897-pinned-terminal-footer-overlap.md      |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 packages/dashboard/app/App.tsx                     |   1 +
 .../dashboard/app/components/TerminalModal.css     |  12 ++
 .../dashboard/app/components/TerminalModal.tsx     |  17 ++-
 .../components/__tests__/TerminalModal.test.tsx    | 135 ++++++++++++++++++++-
 6 files changed, 170 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7897

Fusion-Task-Lineage: e22db6a9-35a8-46a1-8c15-186eaf5267fd

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 19:00:16 -07:00
gsxdsm
f7e678bc8d FN-7894: fix conversation history rendering user's own-answer text as [object Object]
Resolves planning interview history showing raw stringified objects instead of the user's typed "Other" answer text.

- Add getResponseValue resolution that mirrors the server's `_other` reserved-key contract, extracting the free-text answer separately from `_comment` metadata.
- Add formatResponse support for an `other` override across single_select, multi_select, and confirm question types, appending "(user's own answer)" suffix.
- Add safeFormatScalar helper to safely stringify non-string scalar/object response values instead of relying on bare String()/JSON.stringify() branches.
- Add regression tests covering text/single_select/multi_select/confirm question types with `_other` responses, plus the existing `_comment` metadata path.

Files changed:
 .../app/components/ConversationHistory.tsx         |  96 +++++++++++++----
 .../__tests__/ConversationHistory.test.tsx         | 117 +++++++++++++++++++++
 2 files changed, 191 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-7894

Fusion-Task-Lineage: 06444248-23cd-4fac-9afc-b2e2c7366cbe

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 18:47:08 -07:00
gsxdsm
ddf2f3d956 FN-7888: wire onDeleteTask through right-dock Tasks list
Restores the Delete affordance in the right-dock Tasks list, which previously rendered TaskCard hosts without a delete handler so the menu action silently did nothing.
- Thread onDeleteTask prop through DockTaskList into TaskCard
- Pass onDeleteTask through overflowViewRegistry's Tasks view render props
- Wire onDeleteTask from useRightDockController into both DockTaskList call sites
- Add regression coverage for desktop context-menu and mobile pointer-up delete flows in TaskCard, DockTaskList, and RightDock tests
- Add a patch changeset documenting the fix

Files changed:
 .changeset/fn-7888-task-delete.md                  |  7 ++++
 packages/dashboard/app/components/DockTaskList.tsx |  9 ++++-
 .../app/components/__tests__/DockTaskList.test.tsx | 16 +++++++-
 .../app/components/__tests__/RightDock.test.tsx    | 16 +++++++-
 .../app/components/__tests__/TaskCard.test.tsx     | 44 ++++++++++++++++++++++
 .../app/components/overflowViewRegistry.tsx        |  4 +-
 .../app/components/useRightDockController.tsx      |  2 +
 7 files changed, 93 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7888

Fusion-Task-Lineage: 22767aba-fb92-4ac3-8348-ee0cea4345c2

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 18:13:33 -07:00
gsxdsm
dabedcf79c FN-7890: cap report-a-bug GitHub URL by encoded length, not raw body length
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>
2026-07-12 18:10:55 -07:00
gsxdsm
c341b58bde FN-7889: align task card header action icons to the id's optical centerline
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>
2026-07-12 18:06:38 -07:00
gsxdsm
db9a9453db FN-7887: migrate ChatView copy-response to shared clipboard helper
Fixes ChatView's provider-response copy button falsely reporting failure on non-secure origins (mobile/HTTP) by routing through the shared clipboard utility instead of calling navigator.clipboard directly.

- Replaced direct navigator.clipboard.writeText call in handleCopyResponse with the shared copyTextToClipboard helper (secure-context guard + execCommand fallback)
- Added regression tests covering secure Clipboard API success, execCommand fallback success, and combined failure paths
- Added changeset documenting the fix as the last direct clipboard caller found during the FN-7885 preflight

Files changed:
 .changeset/fn-7887-chatview-clipboard.md           |   7 +
 packages/dashboard/app/components/ChatView.tsx     |  16 +-
 .../__tests__/ChatView.copy-response.test.tsx      | 169 +++++++++++++++++++++
 3 files changed, 183 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-7887

Fusion-Task-Lineage: bff1084b-7c64-420d-9479-bb8c4c584175

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 17:59:19 -07:00
gsxdsm
6ea53966f6 FN-7885: migrate remaining direct clipboard callers to shared copyTextToClipboard helper
Replaces the last direct navigator.clipboard.writeText() call sites across dashboard components and the reports plugin with the shared copyTextToClipboard helper, fixing copy actions that crashed or silently failed on non-secure origins (HTTP/mobile).

- Migrated AgentDetailView, AgentErrorDetailsModal, CliBinaryPanel, GitManagerModal, LoginInstructions, PrPanel, SecretsView, and StashConflictModal to use copyTextToClipboard (secure-context guard + execCommand fallback, boolean result handling) instead of calling navigator.clipboard directly.
- Migrated the fusion-plugin-reports ShareBlocksPanel to the same helper and added a vitest alias so the plugin's subpath import resolves to the dashboard's copyToClipboard util instead of collapsing to its package root.
- Added ./app/utils/copyToClipboard subpath export to @fusion/dashboard's package.json.
- Added/extended tests covering copy success, fallback, and failure paths for AgentDetailView, CliBinaryPanel, AgentErrorDetailsModal, GitManagerModal, SecretsView, StashConflictModal, and ShareBlocksPanel.
- Added a patch changeset documenting the fix for @runfusion/fusion.

Files changed:
 .changeset/fn-7885-clipboard-migration.md          |  7 ++
 packages/dashboard/app/components/AgentDetailView.tsx   | 16 ++++-
 packages/dashboard/app/components/AgentErrorDetailsModal.tsx      |  5 +-
 packages/dashboard/app/components/CliBinaryPanel.tsx    | 16 +++--
 packages/dashboard/app/components/GitManagerModal.tsx   | 16 ++++-
 packages/dashboard/app/components/LoginInstructions.tsx | 21 +++---
 packages/dashboard/app/components/PrPanel.tsx      |  9 ++-
 packages/dashboard/app/components/SecretsView.tsx  | 11 ++-
 packages/dashboard/app/components/StashConflictModal.tsx          | 13 ++--
 packages/dashboard/app/components/__tests__/AgentDetailView.copy.test.tsx        | 56 +++++++++++++++
 packages/dashboard/app/components/__tests__/AgentErrorDetailsModal.test.tsx      | 18 +++++
 packages/dashboard/app/components/__tests__/CliBinaryPanel.copy.test.tsx         | 68 ++++++++++++++++++
 packages/dashboard/app/components/__tests__/GitManagerModal.test.tsx  | 23 ++++++
 packages/dashboard/app/components/__tests__/SecretsView.test.tsx  | 82 ++++++++++++++++++++++
 packages/dashboard/app/components/__tests__/StashConflictModal.test.tsx          | 25 ++++++-
 packages/dashboard/package.json                    |  4 ++
 plugins/fusion-plugin-reports/src/dashboard/components/ShareBlocksPanel.tsx  |  5 +-
 plugins/fusion-plugin-reports/src/dashboard/components/__tests__/ShareBlocksPanel.test.tsx | 43 +++++++++++-
 plugins/fusion-plugin-reports/vitest.config.ts     |  2 +
 19 files changed, 402 insertions(+), 38 deletions(-)

Fusion-Task-Id: FN-7885
Fusion-Task-Lineage: 122a54ea-962b-4ae1-98ac-c28e03f4f8ca
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 17:54:21 -07:00
gsxdsm
3a37f48e78 FN-7883: expand Command Center bug report with full diagnostics bundle
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>
2026-07-12 17:42:39 -07:00
gsxdsm
2e7fce21ae FN-7884: reset durable-agent error state on engine restart
Engine startup now treats itself as an implicit operator retry for durable heartbeat agents stuck in error, clearing eligible error states and re-arming heartbeats instead of waiting for the steady-state sweep's cooldown/exhaustion gates.

- Add SelfHealingManager.resetDurableAgentErrorStateOnStartup(), run first in runStartupRecovery(), which resets shared heartbeatErrorRecovery/legacy durableErrorRecovery metadata, clears lastError/pauseReason, flips eligible error and error-retry-exhausted-parked durable agents to active, and re-arms their heartbeat
- Preserve suppression for operator-actionable, stale worktree/module-resolution, user-paused, error-unrecoverable, ephemeral, disabled-runtime, and actively-executing agents
- Add agent:reset-error-state-on-startup run-audit mutation type with ids/counts/outcomes-only metadata (agentId, priorState, priorPauseReason, source)
- Add changeset FN-7884 (patch) documenting the operator-facing behavior
- Update AGENTS.md and docs/agents.md, docs/architecture.md to describe the new startup reset path alongside existing FN-7835/FN-7844/FN-7859/FN-7878 recovery docs
- Extend self-healing.test.ts with coverage for the new startup reset behavior and its exclusions

Files changed:
 .changeset/fn-7884-restart-error-reset.md          |   7 ++
 AGENTS.md                                          |   1 +
 docs/agents.md                                     |   4 +-
 docs/architecture.md                               |   2 +-
 packages/engine/src/__tests__/self-healing.test.ts | 127 ++++++++++++++++++++-
 packages/engine/src/run-audit.ts                   |   1 +
 packages/engine/src/self-healing.ts                |  88 +++++++++++++-
 7 files changed, 223 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7884
Fusion-Task-Lineage: fe64f6af-3ff3-4876-8308-8a75591c45f1
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 17:39:29 -07:00
gsxdsm
e92a342b1e FN-7882: fix Copy diagnostics crash on non-secure origins
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>
2026-07-12 17:32:41 -07:00
gsxdsm
b84bd11256 FN-7881: fix System-controls refresh button mobile layout
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>
2026-07-12 17:09:15 -07:00
gsxdsm
c745990aa2 FN-7879: deliver one-time Postgres-migration inbox notice on first 0.59 startup
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>
2026-07-12 17:02:33 -07:00
gsxdsm
56c745240a FN-7880: shorten Reset Settings button to "Reset" on mobile
Shortens the Settings footer's Reset Settings button label to Reset at the mobile breakpoint to preserve footer space, while desktop/tablet keep the full label; confirmation dialog and reset behavior are unchanged.

- Add settings.reset.buttonShort i18n key (en, zh-CN) and typed resources.d.ts entry
- SettingsModal reset button now renders buttonShort ("Reset") when viewportMode === "mobile", otherwise the existing "Reset Settings" label
- Update settings-mobile.test.tsx to assert the compact mobile label and add coverage across modal/embedded x mobile/desktop viewport combinations
- Update docs/dashboard-guide.md to document the mobile-only compact label
- Add changeset (patch) for @runfusion/fusion

Files changed:
 .changeset/fn-7880-reset-mobile-label.md           |  7 ++++
 docs/dashboard-guide.md                            |  6 ++--
 packages/dashboard/app/components/SettingsModal.tsx |  7 +++-
 packages/dashboard/app/components/__tests__/settings-mobile.test.tsx | 37 +++++++++++++++++++++-
 packages/i18n/locales/en/app.json                  |  1 +
 packages/i18n/locales/zh-CN/app.json               |  1 +
 packages/i18n/src/resources.d.ts                   |  1 +
 7 files changed, 56 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7880

Fusion-Task-Lineage: e636e73d-172e-4a6e-bb51-078520fd05ab

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 16:48:04 -07:00
gsxdsm
504dc69f02 FN-7878: default heartbeat error recovery to recoverable for generic durable-agent failures
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>
2026-07-12 16:25:48 -07:00
gsxdsm
990583261e FN-7877: fix Command Center System tab spacing and canonicalize status colors
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>
2026-07-12 16:11:34 -07:00
gsxdsm
37c0816f57 docs: clarify Homebrew trusted install 2026-07-12 15:37:02 -07:00
gsxdsm
2ffebef022 Address PR feedback: redact TUI/console log path too (#2028)
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>
2026-07-12 14:42:09 -07:00
gsxdsm
f1b6a6340c Address review feedback: System panel hardening (#2028)
Correctness/reliability:
- engine restart-all: compensating pause on resume failure so a project
  is never left marked active with a dead engine
- desktop restart: app.quit() (runs before-quit teardown) not app.exit(0)
- supervisor: SIGINT/SIGTERM during crash-backoff exit immediately;
  stopping-latch prevents respawn after intentional shutdown
- coalesce concurrent /system/restart requests (restartScheduled guard)
- rebuild job completion chain given a .catch (no stranded activeJob)

Security:
- same-origin CSRF guard on all mutating /system/* POSTs (safe under
  --no-auth / desktop)
- redact secrets in host-process log history (reuse core redactSecrets)
- report-bug: confirm before including server logs + escape ``` fences
- sanitize restart reason; Object.hasOwn scope-guard (prototype-key 500)

Frontend:
- log tail dedup (drop redundant REST backfill; SSE heartbeat stops 45s
  reconnect churn) + X-Accel-Buffering:no on both SSE routes
- restart-wait 90s timeout re-enables controls
- hydrate buffered rebuild lines on mount (mid-build panel open)

Maintainability + tests:
- engineAvailable reflects centralCore; hoisted systemLogs option; typed
  desktop systemControl DTO
- add tests: SSE routes, exit-86 respawn, compiled-binary respawn,
  engine-restart recovery, log redaction

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 14:42:09 -07:00
gsxdsm
a227b19a22 feat: add Command Center System panel with rebuild/restart controls, Plugins tab, and supervised-by-default dashboard
- 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>
2026-07-12 14:42:09 -07:00
gsxdsm
cbe07ee86b fix(engine): address PR #2027 review — tighten auth exclusions, accurate park accounting
- 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>
2026-07-12 13:57:08 -07:00
gsxdsm
c4fad2d793 fix(engine): auto-recover agents from transient OAuth token-rotation 401s
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>
2026-07-12 13:57:08 -07:00
gsxdsm
ee7af2513f fix(MAIN-008): address PR review feedback (#2020)
- Label namespaced mcp__* tools as resourceType "mcp" (not "research") so approvals/audit/dedupe keys describe external MCP actions
- Guard getTask in resumeApprovalAfterUnwindIfNeeded so deferred resume cannot mask execute() finally outcomes
2026-07-12 13:56:36 -07:00
Tchorizo
23c732b2a8 docs(MAIN-008): complete Step 7 — document deterministic MCP approval lifecycle
Agent: engineer
Fusion-Task-Id: MAIN-008
Co-authored-by: Fusion <noreply@runfusion.ai>
2026-07-12 13:56:36 -07:00
Tchorizo
b688266a02 test(MAIN-008): complete Step 4 — validate shared MCP lifecycle surfaces
Agent: engineer
Fusion-Task-Id: MAIN-008
Co-authored-by: Fusion <noreply@runfusion.ai>
2026-07-12 13:56:36 -07:00
Tchorizo
555f916ebb fix(MAIN-008): complete Step 3 — resume approved MCP calls once
Agent: engineer
Fusion-Task-Id: MAIN-008
Co-authored-by: Fusion <noreply@runfusion.ai>
2026-07-12 13:56:36 -07:00
Tchorizo
e977fadda9 fix(MAIN-008): complete Step 2 — stabilize MCP executor bootstrap
Agent: engineer
Fusion-Task-Id: MAIN-008
Co-authored-by: Fusion <noreply@runfusion.ai>
2026-07-12 13:56:36 -07:00
gsxdsm
ee1d978984 FN-7876: add custom terminal shortcut buttons to SessionTerminal mobile key bar
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>
2026-07-12 13:22:05 -07:00
gsxdsm
a4dde88ff6 FN-7874: add Discord get-help link and central-DB wording to storage banner
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>
2026-07-12 13:17:47 -07:00
gsxdsm
2c7df1bd78 FN-7875: split archived pre-0.50 release notes out of root CHANGELOG.md
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>
2026-07-12 13:10:52 -07:00
gsxdsm
b77e12351e FN-7872: add custom terminal shortcut buttons to the Preferences panel
Lets users define, edit, and remove custom terminal shortcut buttons (label + injected key sequence) from the terminal Preferences panel, persisted client-side.

- Add a customShortcuts list to terminalPreferences (kb-terminal-preferences localStorage) with add/edit/remove management
- Add decodeTerminalShortcutSequence to decode \n, \t, \r, \e/\x1b, and \\ escapes for injected sequences
- Render custom shortcut buttons in TerminalModal's shortcut panel, injecting via the focus-preserving sendLiteralShortcut path
- Add management UI (add/edit/remove) for custom shortcuts in the terminal Preferences panel, styled in TerminalModal.css
- Extend TerminalModal and terminalPreferences test coverage for the new custom shortcut behavior
- Document custom terminal shortcuts in docs/dashboard-guide.md
- Add a minor changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7872-terminal-custom-shortcuts.md    |   7 +
 docs/dashboard-guide.md                            |   7 +-
 .../dashboard/app/components/TerminalModal.css     | 106 +++++++++++
 .../dashboard/app/components/TerminalModal.tsx     | 202 ++++++++++++++++++++-
 .../components/__tests__/TerminalModal.test.tsx    | 183 +++++++++++++++++++
 .../utils/__tests__/terminalPreferences.test.ts    |  68 +++++++
 .../dashboard/app/utils/terminalPreferences.ts     | 140 +++++++++++++-
 7 files changed, 708 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-7872

Fusion-Task-Lineage: 9b2df0da-0eb7-4cec-a42b-767e23ff4c2c

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 13:06:08 -07:00
gsxdsm
ad3d26d365 FN-7873: fix mobile floating-window header drag being intersected by page pan-y lockdown
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>
2026-07-12 13:00:56 -07:00
gsxdsm
5de1d9e7b0 FN-7871: center task-id chip with header badge row on TaskCard
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>
2026-07-12 12:55:36 -07:00
gsxdsm
bb86844f8d FN-7869: add hide done toggle to Todo list view
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>
2026-07-12 12:52:30 -07:00
gsxdsm
06ec0e606e FN-7866: add auto-save toggle for the workspace file editor (default on)
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>
2026-07-12 12:49:37 -07:00
gsxdsm
bc30ce8aa1 FN-7857: deliver plugin skill bodies to agent sessions and the Skills view
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>
2026-07-12 12:47:38 -07:00
gsxdsm
7fccd73d84 test(engine): update moveTask 3rd-arg assertion undefined -> {} (executor pause-abort always passes options object) 2026-07-12 12:44:05 -07:00
gsxdsm
73172bb45c test(engine): update heartbeat expectations for FN-7835/FN-7859 error-unrecoverable reason + paused state transitions 2026-07-12 12:44:05 -07:00
gsxdsm
8d59df4531 test(engine): add wrapToolsWithRtkRewrite/PermanentAgentGating/ActionGate to pi.js mocks (openclaw + reviewer) 2026-07-12 12:44:05 -07:00
gsxdsm
fb3e843bc2 test(i18n): add storageMigrationNotice keys to all non-en locales 2026-07-12 12:44:05 -07:00
gsxdsm
09e8e71680 FN-7870: remove left accent stripe and row border from Todo sidebar list items
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>
2026-07-12 12:33:29 -07:00
gsxdsm
8884f50765 FN-7868: add Commit and Push button to Git Manager changes panel
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>
2026-07-12 12:30:13 -07:00
gsxdsm
b10f823672 FN-7867: make task-card priority badges icon-only to stop meta-badge wrapping
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>
2026-07-12 12:26:54 -07:00
gsxdsm
139ae7e4bc FN-7854: fix desktop chat losing messaging tools from stale MessageStore wiring
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>
2026-07-12 12:24:11 -07:00