Pausing an in-progress task never stuck: the pause teardown re-queued the
row to todo with a plain engine move, and the reopen block wiped
paused/pausedByAgentId/pausedReason. The graph-failure classifier then saw
an unpaused row, misread the hard-cancel as an engine-internal abort, and
auto-continued the session (graphResumeRetryCount 1/2, 2/2); once the
budget was exhausted the benign re-queue left the row dispatchable and the
scheduler re-dispatched it seconds later — an indefinite pause/resume
bounce, burning a fresh worktree + pnpm install per cycle.
- store: new moveTask option `preservePause` keeps the pause park across a
reopen-to-todo/triage move (flag-ON trait hook + flag-OFF legacy inline,
kept in sync). It never SETS a pause, only prevents clearing one.
- executor teardown: when the pause that caused the abort is still in
force, move with preservePause so the row lands in todo still parked
(scheduler skips paused/userPaused rows until explicit unpause).
- classifier: a live task pause is labeled operator intent, never
"engine abort during pause/resume"; the benign log now says
"parked … awaiting explicit unpause" instead of the contradictory
"cleared for normal scheduling" for parked rows.
Surfaces covered by tests: flag-ON hook (preserve + never-set + default
clear), classifier no-auto-continue for task-pause/user-pause/global-pause
rows in todo, provenance labels.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Grok advertises promptCapabilities.image=false and ignores ACP image
ContentBlocks (live probe: NO_IMAGE). Path-based vision works when the
agent is given an absolute file path. Include path hints in chat prompts
from .fusion/chat-attachments and carry path on ChatImageContent for
file:// uris.
Fix chat image/file attachments not rendering until re-entering the thread by reconciling the optimistic temp user bubble with the persisted user-message SSE echo during active streaming.
- In useChat, when a persisted user-role message arrives via chat:message:added while the active session is streaming, replace the optimistic temp-* bubble with the reconciled persisted message (real id + attachment filenames) instead of leaving the temp bubble in place with no refetch.
- Add regression coverage: persisted user attachment echo reconciles without duplicate/refetch, attachment-only echo reconciles content+attachments, and text-only echo still reconciles without duplicating messages.
- Extend test helper makeMessage to pass through attachments overrides.
Files changed:
.../dashboard/app/hooks/__tests__/useChat.test.ts | 160 +++++++++++++++++++++
packages/dashboard/app/hooks/useChat.ts | 13 ++
2 files changed, 173 insertions(+)
Fusion-Task-Id: FN-7849
Fusion-Task-Lineage: dbabda9c-5842-4d16-bafb-776a6536e51f
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Update the TUI splash tagline to match the README's current product positioning, with matching test and changeset.
- Changed FUSION_TAGLINE in packages/cli/src/commands/dashboard-tui/logo.ts from "multi node agent orchestrator" to "software factory", with an FNXC comment explaining the rationale
- Updated the dashboard TUI smoke test assertion to expect "software factory" instead of the old tagline
- Added a patch changeset documenting the tagline change
Files changed:
.changeset/fn-7850-tui-tagline.md | 7 +++++++
packages/cli/src/commands/dashboard-tui/__tests__/app.test.tsx | 2 +-
packages/cli/src/commands/dashboard-tui/logo.ts | 6 +++++-
3 files changed, 13 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-7850
Fusion-Task-Lineage: d8517d7c-f7dd-43af-bb57-0092c7339aad
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
AcpRuntimeAdapter.promptWithFallback ignored options, so dashboard chat
images never became ACP ContentBlock image entries. Extract images from
prompt options and pass them through buildPromptBlocks for both acp-runtime
and the Grok vendored client.
Grok emits `_x.ai/session_notification` / `_x.ai/session/update` for
hook_execution status. The ACP SDK routes those to Client.extNotification;
without it, every successful post_tool_use hook logged -32601 Method not
found. Implement no-op extMethod/extNotification on default and bridging
handlers in acp-runtime and the Grok vendored copy.
Matches pi wrapToolsWithActionGate semantics: callers that omit
actionGateContext (chat/triage) intentionally leave tools ungated.
Add a content-free warn when a non-pi runtime receives customTools without
gate context so the path is visible without inventing deny-all defaults.
Greptile P1 on PR #2011: Grok ACP (and other plugin runtimes) previously
executed engine-injected fn_* tools without the pi action-gate / permanent-
agent / RTK rewrite chain. Wrap customTools once in createResolvedAgentSession
for non-pi runtimes so loopback MCP bridges dispatch already-gated closures.
Pi still owns its own wrap chain inside createFnAgent to avoid double-wrapping.
Replace one-shot grok -p JSON with native grok agent stdio (ACP) for realtime
streaming, tool visibility, and multi-turn sessions. Vendor the ACP client
into fusion-plugin-grok-runtime, forward Fusion fn_* tools and operator MCP,
stage Fusion skills via --plugin-dir, authenticate per xAI headless docs, and
align project chat manager store resolution so Grok chat sessions can send.
Restores the GitHub star count pill on mobile Settings, which had been hidden by a prior mobile CSS override, and updates related tests to match.
- Remove the <=768px `display:none` on `.settings-github-star-btn__count` in SettingsModal.css so the count stays visible; only the redundant "Star" label text stays collapsed on mobile to save space (relies on `.settings-modal-heading` min-width: 0 to truncate the title before the pill wraps)
- Add a changeset (`@runfusion/fusion` patch) documenting the fix
- Update settings-mobile.test.tsx with a new regression test asserting the star count stays visible and formatted (e.g. "1.2k") in both the modal and embedded SettingsView on mobile, plus a helper to scan mobile-only CSS media blocks for the absence of the display:none rule, and align existing mobile CSS assertions (section-heading padding, settings-navigation base rule) with current styles
- Update SettingsModal.models-auth.test.tsx version-label assertions ("Version 1.2.3" -> "v1.2.3") and seed `fusion:settings:show-advanced` in localStorage to match current UI
Files changed:
.changeset/mobile-settings-star-count.md | 7 +++
.../dashboard/app/components/SettingsModal.css | 9 ++-
.../__tests__/SettingsModal.models-auth.test.tsx | 12 ++--
.../components/__tests__/settings-mobile.test.tsx | 66 +++++++++++++++++++++-
4 files changed, 82 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7848
Fusion-Task-Lineage: 0bbd0e81-6edb-4e9a-884d-b48fcf41f202
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds static MODEL_PRICING rows for three previously-unpriced models so their token usage renders a dollar cost instead of "—" in the dashboard.
- Add zai:glm-5.2, minimax:minimax-m3, and kimi-coding:kimi-k2.6-preview pricing rows to MODEL_PRICING, sourced from each provider's public pricing docs
- Bump pricingAsOf to 2026-07-11
- Add regression tests asserting costFor() prices these three models (not unavailable) and that lookupPricing() resolves them by provider-normalized and bare model-id keys
- Add a minor changeset documenting the pricing addition for @runfusion/fusion release notes
Files changed:
.changeset/fn-7847-model-pricing.md | 7 +++++
packages/core/src/__tests__/model-pricing.test.ts | 24 +++++++++++++++
packages/core/src/model-pricing.ts | 36 ++++++++++++++++++++++-
3 files changed, 66 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7847
Fusion-Task-Lineage: 6c138aa3-53e9-4165-909d-c8fc02acb48b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Extend the dashboard's Task Documents tab to union each task's registered documents with its task-scoped artifacts, with an inline right-pane viewer for the added artifact types.
- DocumentsView Task Documents tab now merges task documents and task-scoped artifacts per task group, sorted/grouped consistently
- Adds an inline right-pane artifact viewer (image/video/audio/pdf/inline-doc/other) reusing getArtifactCategory + artifactMediaUrl/fetchArtifact
- Selection state is a discriminated document|artifact union kept separate from Project Files selection; the standalone Artifacts gallery tab is unchanged
- Updates dashboard-guide.md to describe the merged Task Documents behavior (grouping, search, and preview now cover both documents and artifacts)
- Adds a minor changeset for @runfusion/fusion documenting the artifact-in-Task-Documents feature
- Expands DocumentsView test coverage for the new union/selection/preview behavior
Files changed:
.changeset/fn-7845-task-documents-artifacts.md | 7 +
docs/dashboard-guide.md | 6 +-
.../dashboard/app/components/DocumentsView.css | 142 +++++++-
.../dashboard/app/components/DocumentsView.tsx | 389 ++++++++++++++++++---
.../components/__tests__/DocumentsView.test.tsx | 290 ++++++++++++++-
5 files changed, 780 insertions(+), 54 deletions(-)
Fusion-Task-Id: FN-7845
Fusion-Task-Lineage: 32bbe6dc-4c02-449c-a13f-38abb8fd727d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Repositions the S/M/L size badge on task cards so it is the trailing element in the header-actions cluster, aligning its right margin with the card's top padding instead of leaving it stranded before the menu button.
- Move the `card-size-badge` span to render after the more-actions menu button within `.card-header-actions` in TaskCard.tsx
- Add FNXC layout comment documenting why the badge must be last (right-edge alignment while preserving FN-7837 no-orphaned-second-row grouping)
- Add a regression test asserting the size badge is the last child of `.card-header-actions` with no trailing sibling
- Add a patch changeset documenting the fix for release notes
Files changed:
.changeset/FN-7846-card-size-badge-right-edge.md | 7 +++++++
packages/dashboard/app/components/TaskCard.tsx | 14 +++++++++-----
.../app/components/__tests__/TaskCard.test.tsx | 21 +++++++++++++++++++++
3 files changed, 37 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-7846
Fusion-Task-Lineage: ee2c1864-e0fe-4d82-a280-59edbb923dca
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Unifies the two independent durable-agent error-recovery paths (heartbeat timer and self-healing sweep) so they share one retry budget, eligibility check, and audit surface instead of racing separate counters.
- Share the heartbeatErrorRecovery attempt budget between HeartbeatMonitor's timer-entry recovery and SelfHealingManager.recoverOrphanedAgents(), with self-healing's legacy durableErrorRecovery metadata folded into the same counter via readHeartbeatErrorRetryCount().
- Add isHeartbeatErrorRecoverable() as the single transient/non-operator-actionable eligibility check, used by both the heartbeat timer and self-healing paths (self-healing additionally allows stale-worktree module-resolution errors).
- resetHeartbeatErrorRecoveryMetadata() now strips the legacy durableErrorRecovery field so recovered agents don't retain stale sweep bookkeeping.
- Self-healing emits the shared agent:auto-recover-error-state / agent:error-retry-exhausted run-audit events with source:"self-healing", and parks the agent paused with pauseReason:"error-retry-exhausted" on budget exhaustion, matching the heartbeat-timer behavior.
- Update AGENTS.md, docs/architecture.md, and docs/agents.md to describe the consolidated recovery budget and audit surface.
- Add a patch changeset documenting the fix for @runfusion/fusion.
Files changed:
.changeset/fn-7844-error-recovery-coordination.md | 7 ++
AGENTS.md | 2 +-
docs/agents.md | 14 ++--
docs/architecture.md | 2 +-
packages/engine/src/__tests__/heartbeat-error-recovery.test.ts | 13 +++-
packages/engine/src/__tests__/self-healing.test.ts | 58 ++++++++++++++-
packages/engine/src/agent-heartbeat.ts | 35 ++++++---
packages/engine/src/self-healing.ts | 85 ++++++++++++++++++----
8 files changed, 180 insertions(+), 36 deletions(-)
Fusion-Task-Id: FN-7844
Fusion-Task-Lineage: b70dcba5-56b6-412c-8be2-ef827bee9964
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
pushAfterMerge was only implemented in the soft-deprecated legacy aiMergeTask
pipeline, so after master-plan U0 made runAiMerge the sole merge path the
setting silently did nothing and origin fell permanently behind local main.
- runAiMerge now runs a post-finalize push step: working-tree-independent
ref-to-ref push fast path; on remote divergence a detached clean-room
pull --rebase (with AI conflict resolution) pushes HEAD and CAS-advances
the local integration ref (explicit non-FF opt-in, push path only), then
runs merge-advance auto-sync and refreshes mergeDetails.commitSha.
- Push failures stay non-fatal (task finalizes done) with push:origin
run-audit events and PushToRemoteFailed task-log entries.
- Merge settings: Push Remote free-text replaced by remote + target-branch
dropdowns (Custom… escape, free-text fallback when no remotes), persisting
to the same pushRemote setting string. New GET /api/git/remotes/:name/branches
endpoint lists remote-tracking branches.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Heartbeat-managed durable agents that land in state:"error" now self-recover on the next heartbeat instead of staying stuck until an operator intervenes.
- HeartbeatTriggerScheduler keeps timers armed for durable heartbeat-managed agents in error state when the last error is transient and not operator-actionable (credential/quota/model-access/permanent-config failures stay parked).
- executeHeartbeat clears recoverable errors at run entry (error → active, clears lastError), bounded by MAX_HEARTBEAT_ERROR_RECOVERY_ATTEMPTS (settings-overridable); a successful run resets the counter.
- On budget exhaustion, the agent is parked paused with pauseReason:"error-retry-exhausted".
- Emits new run-audit events agent:auto-recover-error-state and agent:error-retry-exhausted (added to DatabaseMutationType).
- Adds heartbeat-error-recovery.test.ts and extends heartbeat-scheduler.test.ts to cover the recovery/exhaustion paths.
- Adds changeset and documents the new behavior in AGENTS.md and docs/architecture.md.
Files changed:
.changeset/fn-7835-agent-error-auto-recovery.md | 7 +
AGENTS.md | 1 +
docs/architecture.md | 2 +
.../src/__tests__/heartbeat-error-recovery.test.ts | 323 +++++++++++++++++++++
.../src/__tests__/heartbeat-scheduler.test.ts | 89 +++++-
packages/engine/src/agent-heartbeat.ts | 209 ++++++++++++-
packages/engine/src/run-audit.ts | 2 +
7 files changed, 618 insertions(+), 15 deletions(-)
Fusion-Task-Id: FN-7835
Fusion-Task-Lineage: 1bbb28a3-8eb9-40e3-8177-6658ec5dae40
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Removes the mobile stacked-card override for the Summary tab's per-model token/cost table so it stays a real, horizontally-scrollable table matching the Command Center pattern, and updates the covering tests/changeset accordingly.
- Drop the @media (max-width: 768px) block in TaskDetailModal.css that converted .task-summary-token-table rows into stacked cards (display:block, thead hidden, td::before labels), so the wrapper's overflow-x: auto and table min-width now govern mobile layout.
- Update FNXC:TaskDetailSummaryTokenCost comments to document the new horizontal-scroll contract instead of the removed stacked-card behavior, and refresh the TaskCostTab.css FNXC comment to match.
- Add a new regression test (token-table-mobile-scroll.test.ts) asserting the task-detail token table wrapper keeps overflow-x: auto, the mobile media block no longer stacks rows into cards, and the Command Center .cc-table-wrap stays scrollable.
- Update the existing TaskDetailModal summary-tab test to assert the stacked-card CSS is absent from the mobile block instead of asserting its presence.
- Add a patch changeset describing the fix for end users.
Files changed:
.changeset/mobile-token-table-scroll.md | 7 +++
.../__tests__/token-table-mobile-scroll.test.ts | 70 +++++++++++++++++++++
packages/dashboard/app/components/TaskCostTab.css | 2 +-
.../dashboard/app/components/TaskDetailModal.css | 73 ++--------------------
.../__tests__/TaskDetailModal.summary-tab.test.tsx | 13 ++--
5 files changed, 90 insertions(+), 75 deletions(-)
Fusion-Task-Id: FN-7843
Fusion-Task-Lineage: bb6dde7c-f205-45f3-984a-0fc52be5d547
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a shared urgency color source to priorityIndicator and wires it into every priority-glyph surface so low/normal/high/urgent read consistently by color, not just icon shape.
- priorityIndicator.tsx: add colorVar (low=info/blue, normal=muted, high=warning/amber, urgent=error/red) and new getPriorityColorVar() export as the single source of truth
- QuickEntryBox: tint the icon-only priority trigger and each option row in the priority picker with the matching urgency color
- TaskForm: tint the New Task inline priority glyph using the same color source
- TaskCard: render a colored priority glyph alongside the existing text label in the card-priority-badge (kept the non-normal visibility gate and badge geometry via a small CSS gap addition)
- Updated/added tests for QuickEntryBox, TaskCard (badge, badge-height, badge-wrap), and priorityIndicator to assert the new colors; added a patch changeset and a dashboard-guide.md doc update
Files changed:
.changeset/fn-7842-priority-color-coding.md | 7 +++++
docs/dashboard-guide.md | 7 +++--
.../dashboard/app/components/QuickEntryBox.tsx | 7 +++--
packages/dashboard/app/components/TaskCard.css | 2 ++
packages/dashboard/app/components/TaskCard.tsx | 6 +++-
packages/dashboard/app/components/TaskForm.tsx | 7 +++--
.../components/__tests__/QuickEntryBox.test.tsx | 17 +++++++++--
.../__tests__/TaskCard.badge-height.test.tsx | 5 ++++
.../__tests__/TaskCard.badge-wrap.test.tsx | 5 ++++
.../app/components/__tests__/TaskCard.test.tsx | 33 +++++++++++++++++++++-
.../app/utils/__tests__/priorityIndicator.test.tsx | 13 +++++----
packages/dashboard/app/utils/priorityIndicator.tsx | 16 ++++++++---
12 files changed, 103 insertions(+), 22 deletions(-)
Fusion-Task-Id: FN-7842
Fusion-Task-Lineage: 0b2d0d15-6e61-45fc-9378-bc09002bef55
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Replaces the standalone Archive button on done task cards with an Actions dropdown that groups Archive and Revert, mirroring the existing in-progress "Send back" menu pattern.
- Add a card-done-actions dropdown (Actions trigger + menu) rendered for done cards, reusing card-send-back* styling
- Move Archive into the dropdown menu; add Revert as a menu item when the task is revertable (isRevertable)
- Only render the dropdown trigger when at least one action (archive/revert) is available, avoiding an empty button shell
- Restrict the old inline card-revert-btn to archived cards only (done cards now use the dropdown)
- Add outside-click handling and aria-haspopup/aria-expanded wiring for the new menu
- Add i18n key tasks.doneActions
- Update TaskCard tests to cover the dropdown (archive/revert menu items, empty-state omission) and mock useToast in board-mobile tests for isolated TaskCard renders
- Add changeset for @runfusion/fusion (patch)
Files changed:
.changeset/fn-7839-done-card-actions-dropdown.md | 7 ++
packages/dashboard/app/components/TaskCard.tsx | 88 ++++++++++++++++++----
.../app/components/__tests__/TaskCard.test.tsx | 82 +++++++++++++++-----
.../app/components/__tests__/board-mobile.test.tsx | 15 +++-
4 files changed, 157 insertions(+), 35 deletions(-)
Fusion-Task-Id: FN-7839
Fusion-Task-Lineage: 1f8137cb-22b1-43dd-beaa-1bee0387d44b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the narrow-container (phone-width) Todo view so the visible list or
detail panel stretches to fill available height instead of inheriting the
tablet two-panel sidebar's max-height cap.
- Scope the single-panel stack rule to .todo-view-layout .todo-view-sidebar /
.todo-view-main so it wins over the later @media (max-width:768px)
sidebar max-height cap, and add height:100%/max-height:none.
- Add regression tests asserting the narrow single-panel stack is uncapped
while the tablet two-panel sidebar keeps its existing height cap.
- Add a patch changeset documenting the fix.
Files changed:
.changeset/fn-7841-todo-mobile-height.md | 7 ++++++
packages/dashboard/app/components/TodoView.css | 11 ++++++---
.../__tests__/TodoView.mobile-css.test.ts | 28 ++++++++++++++++++++++
3 files changed, 43 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-7841
Fusion-Task-Lineage: e6b497ae-2568-4cae-8b48-7f57f45c8a23
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Stops decidePlannerRecovery from recording noisy advisory confirmation interventions for merger/pull-request stages that never actually block progress when auto-merge will proceed unattended.
- decidePlannerRecovery now returns action "none" (no pending confirmation, no steering comment, no overseer:intervention entry) for merger/pull-request stages when autoMergeWillProceed === true, since this checkpoint is purely advisory in that case
- Genuine human-approval blocks (autoMergeWillProceed === false) and the neutral pure-function default (undefined) keep the await_confirmation decision intact
- Updated planner-recovery.test.ts to assert the new "none" outcome for the advisory case
- Simplified planner-overseer-intervention-wiring.test.ts to match the reduced intervention surface
- Added changeset documenting the fix as a patch-level bug fix
Files changed:
.changeset/fn-7840-advisory-merger-confirmations.md | 7 ++
packages/core/src/__tests__/planner-recovery.test.ts | 32 ++---
packages/core/src/planner-recovery.ts | 47 ++++---
packages/engine/src/__tests__/planner-overseer-intervention-wiring.test.ts | 135 +++++----------------
4 files changed, 79 insertions(+), 142 deletions(-)
Fusion-Task-Id: FN-7840
Fusion-Task-Lineage: 610a9003-f229-4e78-9948-ee0bb85193bc
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Groups TaskCard header badges so the id and right-aligned size/actions cluster never wrap, fixing the S/M/L size chip dropping to its own row when extra badges (fast-mode, priority, oversight, PR/GitHub, etc.) are present.
- Introduce hasHeaderBadges/hasHeaderActions guards and wrap the middle badge cluster in a new .card-header-badges container so only .card-header-badges wraps, while .card-id and .card-header-actions stay pinned to the top row
- Update TaskCard.css: .card-header becomes a non-wrapping flex row; .card-header-badges takes over the wrapping/flex-grow behavior previously on .card-header; .card-id gets flex-shrink: 0; .card-header-actions gets flex: 0 0 auto and align-self: flex-start; mobile media query gains .card-header-badges alongside .card-meta-badges
- Add FNXC:TaskCardLayout comments documenting the FN-7837 layout requirement (non-wrapping header row, wrapping badge cluster)
- Extend TaskCard.badge-wrap.test.tsx and TaskCard.test.tsx coverage for the new header grouping/wrap behavior
- Add changeset FN-7837-card-size-badge-alignment.md (patch, fix) for @runfusion/fusion
Files changed:
.changeset/FN-7837-card-size-badge-alignment.md | 7 +++
packages/dashboard/app/components/TaskCard.css | 29 +++++++--
packages/dashboard/app/components/TaskCard.tsx | 38 ++++++++++++
.../__tests__/TaskCard.badge-wrap.test.tsx | 70 ++++++++++++++++++++--
.../app/components/__tests__/TaskCard.test.tsx | 27 ++++++---
5 files changed, 156 insertions(+), 15 deletions(-)
Fusion-Task-Id: FN-7837
Fusion-Task-Lineage: 9f70abcf-3b23-41b3-8642-aa34a561996d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Raises Grok and Droid CLI cold-start timeout defaults from 60s to 120s and lets operators override them via environment variables.
- Grok runtime adapter: new GROK_CLI_FIRST_OUTPUT_TIMEOUT_MS env override for the first-output cold-start guard; default raised 60000ms → 120000ms; invalid/non-positive values fall back to the default
- Droid provider: new PI_DROID_CLI_FIRST_LINE_TIMEOUT_MS env override for the first-line cold-start guard; default raised 60000ms → 120000ms; invalid/non-positive values fall back to the default
- 30-minute inactivity safety net left unchanged on both adapters
- Added/updated unit tests covering the new env-driven timeout resolution and fallback behavior for both plugins
- Documented the new settings in docs/settings-reference.md and both plugin READMEs
- Added a minor changeset for @runfusion/fusion
Files changed:
.changeset/fn-7838-cli-timeout-configurable.md | 7 ++
docs/settings-reference.md | 13 ++-
plugins/fusion-plugin-droid-runtime/README.md | 8 ++
.../src/__tests__/provider.test.ts | 97 +++++++++++++++++++++-
.../fusion-plugin-droid-runtime/src/provider.ts | 26 ++++--
plugins/fusion-plugin-grok-runtime/README.md | 8 ++
.../src/__tests__/runtime-adapter.test.ts | 52 +++++++++++-
.../src/runtime-adapter.ts | 23 ++++-
8 files changed, 222 insertions(+), 12 deletions(-)
Fusion-Task-Id: FN-7838
Fusion-Task-Lineage: 7aad4470-b28f-42bd-be01-8363a1dd05e5
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Fixes the Task Documents view rendering blank/border-only rows once many task-card groups load in the scrolling sidebar; each card now opts out of flex shrink so overflow clipping no longer compresses group content out of view.
- DocumentsView.css: add `flex: 0 0 auto` to `.documents-task-sidebar-group` so cards keep their natural height instead of being shrunk by the flex column when many groups are loaded
- DocumentsView.test.tsx: add regression test rendering 54 loaded task-document groups, asserting `flex-shrink: 0` and that group heading/content text remains visible and interactive
- Add changeset documenting the patch-level fix
Files changed:
.changeset/fn-7836-task-documents-rendering.md | 7 +++
.../dashboard/app/components/DocumentsView.css | 4 ++
.../components/__tests__/DocumentsView.test.tsx | 71 ++++++++++++++++++++++
3 files changed, 82 insertions(+)
Fusion-Task-Id: FN-7836
Fusion-Task-Lineage: f07bad59-c6b9-41e3-9475-5a4339044bb4
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Renders every task document in the Artifacts tab expanded and as rendered Markdown by default, with the Markdown/Plain preference persisted across sessions instead of resetting per document.
- Replace single expandedDocKey/expandedContent state with a multi-key expandedDocKeys Set plus a per-document revisionContentByKey map so multiple documents can be expanded simultaneously.
- Default renderMarkdown to true and persist the operator's Markdown/Plain toggle choice to localStorage (fusion.taskDocuments.renderMarkdown) via readBooleanPref/writeBooleanPref helpers.
- Auto-expand newly loaded documents while preserving collapse state for documents the user has explicitly collapsed, tracked per taskId.
- Update handleStartEdit and handleViewRevision to operate per-document-key instead of a single global expanded document.
- Add changeset (@runfusion/fusion patch) describing the Artifacts-tab default-expanded Markdown behavior.
- Rework TaskDocumentsTab tests for multi-document expand/collapse, per-card markdown rendering, and localStorage-backed preference persistence.
Files changed:
.changeset/fn-7833-artifacts-tab-markdown-expand-default.md | 7 +
packages/dashboard/app/components/TaskDocumentsTab.tsx | 149 +++++++++-----
packages/dashboard/app/components/__tests__/TaskDocumentsTab.test.tsx | 223 +++++----------------
3 files changed, 160 insertions(+), 219 deletions(-)
Fusion-Task-Id: FN-7833
Fusion-Task-Lineage: 1915c594-7191-47a2-962b-18136d572cf1
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Gives the Artifacts view's Task Documents sidebar a distinct card-per-task look with more breathing room between task groups, replacing the flat bordered-row list.
- Restyle .documents-task-sidebar-group into a bordered, rounded card with shadow and inter-group gap instead of a bottom-border-only divider
- Strengthen the group header (bolder task id/title, tinted background) so it reads as a container rather than a peer row
- Add hover/selected background treatment and left-indent to .documents-task-document-item entries, scoped under .documents-task-documents-sidebar so Project Files and Artifacts stay unaffected
- Add a regression test asserting group headers remain non-selectable containers distinct from selectable document rows
- Update dashboard-guide.md wording to describe the new distinct task-card grouping
- Add changeset (patch) documenting the sidebar restyle
Files changed:
.changeset/fn-7834-task-documents-grouping.md | 7 +++
docs/dashboard-guide.md | 2 +-
.../dashboard/app/components/DocumentsView.css | 38 +++++++++++++---
.../components/__tests__/DocumentsView.test.tsx | 50 ++++++++++++++++++++++
4 files changed, 90 insertions(+), 7 deletions(-)
Fusion-Task-Id: FN-7834
Fusion-Task-Lineage: 9bac7666-19ba-410b-81dc-d9201a61d0b5
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Reworks the Task Detail terminal experience: the embedded Terminal tab now sits between Comments and Cost, its workspace picker defaults to the task's worktree, and the mobile terminal panel is shorter.
- Move the Terminal tab in Task Detail's tab strip to sit right after Comments and before Cost (previously Cost was earlier and Terminal was near the Session tab)
- TerminalModal now defaults its workspace picker to the useWorkspaces entry whose worktree matches the passed defaultCwd, but only until the operator manually changes the selection; the footer/global terminal still defaults to Project Root since it doesn't pass defaultCwd
- Reduce `.detail-section--worktree-terminal`'s mobile min-height from min(65dvh, 14 * --space-2xl) to min(50dvh, 11 * --space-2xl) so tab context and controls stay reachable above the fold
- Update docs/dashboard-guide.md to describe the new Comments → Terminal → Cost tab order and the worktree-matching picker default
- Add regression tests covering the new tab order and the default terminal workspace selection behavior
- Add a patch changeset describing the user-facing change
Files changed:
.changeset/FN-7832-task-terminal-picker-and-tab-order.md | 7 +++
docs/dashboard-guide.md | 9 +--
packages/dashboard/app/components/TaskDetailModal.css | 5 +-
packages/dashboard/app/components/TaskDetailModal.tsx | 30 +++++-----
packages/dashboard/app/components/TerminalModal.tsx | 19 +++++++
packages/dashboard/app/components/__tests__/TaskDetailModal.attachments-and-tabs.test.tsx | 15 ++---
packages/dashboard/app/components/__tests__/TaskDetailModal.worktree-terminal.test.tsx | 12 ++++
packages/dashboard/app/components/__tests__/TerminalModal.test.tsx | 64 ++++++++++++++++++++++
8 files changed, 134 insertions(+), 27 deletions(-)
Fusion-Task-Id: FN-7832
Fusion-Task-Lineage: 4ee67a65-8564-49c9-b93c-8c3eab05c073
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Adds a distinct "Reviewing" status badge that surfaces on TaskCard and ListView rows while a task's optional plan-review workflow step is actively running, reusing the unified progress predicate so board and list surfaces stay in sync.
- Add isPlanReviewRunning(task) helper in taskProgress.ts, derived from getUnifiedTaskProgress's workflow-plan-review item status
- Render a pulsing "Reviewing" badge on TaskCard header (additive to existing status badges, with title/data-testid) while plan-review is running
- Render the matching "Reviewing" badge on both grouped and ungrouped ListView row layouts for parity with TaskCard
- Add supporting CSS for .card-status-badge--reviewing and .list-status-badge--reviewing
- Add unit tests for isPlanReviewRunning and component tests for the new badge across TaskCard and ListView
- Add minor changeset documenting the new operator-facing badge
Files changed:
.changeset/tidy-reviewing-badges.md | 7 ++
packages/dashboard/app/components/ListView.css | 10 +++
packages/dashboard/app/components/ListView.tsx | 22 +++++-
packages/dashboard/app/components/TaskCard.css | 10 +++
packages/dashboard/app/components/TaskCard.tsx | 25 ++++++-
.../app/components/__tests__/ListView.test.tsx | 78 ++++++++++++++++++++++
.../app/components/__tests__/TaskCard.test.tsx | 31 +++++++++
.../app/utils/__tests__/taskProgress.test.ts | 16 ++++-
packages/dashboard/app/utils/taskProgress.ts | 10 +++
9 files changed, 205 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-7831
Fusion-Task-Lineage: d36f8c63-9b84-400a-8b10-3b9f3b04212b
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Give the Insights view header its own dedicated mobile layout so the title no longer collapses to an ellipsis and action buttons no longer crowd together at narrow widths/short heights.
- Extend the mobile header media query to also trigger on short viewports (max-height: 480px), not just narrow widths
- Force the Insights title onto its own full-width row (flex: 1 0 100%) and let it wrap actions below instead of shrinking
- Stop truncating the title span (overflow: visible; text-overflow: clip) so "Insights" is never cut to "I…"
- Let the actions cluster wrap to full width, left-aligned, with no leading margin so touch targets stay usable
- Add regression tests covering the maximal header action cluster and asserting the new mobile/tablet/desktop CSS media-query contracts
Files changed:
packages/dashboard/app/components/InsightsView.css | 29 ++++++-
.../app/components/__tests__/InsightsView.test.tsx | 88 ++++++++++++++++++++++
2 files changed, 116 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-7830
Fusion-Task-Lineage: 4c92cb43-5c08-4b76-9f51-805ffa5deec9
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Relocates the shared terminal action-control cluster into the bottom status-bar footer at every breakpoint and replaces the fixed tablet-viewport tab collapse with a container-width overflow check.
- Move font-size, Clear, Shortcuts, Preferences, connection status, pin, and pop-out controls out of the desktop header into the `.terminal-status-bar` footer at all widths (desktop/tablet/mobile/floating/docked/pinned/embedded), replacing the prior viewport-tier-based split.
- Replace `isTerminalTabletViewport()` with `evaluateTabsOverflow()`, a container-size (ResizeObserver-driven) check with hysteresis that swaps the `.terminal-tabs` strip for the existing mobile-style `.terminal-mobile-tabs` dropdown whenever the tab strip doesn't fit, independent of viewport breakpoint.
- Update TerminalModal.css to match the new footer-first layout and drop now-unused tablet-tier header rules.
- Update dashboard-guide.md terminal usage steps to describe the new always-footer control location and the width-based (not tablet-only) tab dropdown fallback.
- Expand TerminalModal.test.tsx coverage for the overflow-driven tab collapse/expand behavior and footer control placement.
- Add changeset fn-7829-terminal-shortcuts-footer.md (patch, feature) documenting the footer/tab-dropdown change; resolve an add/add conflict on the pre-existing artifacts-doc-editing-and-comment-fix.md changeset by keeping fusion/fn-7829's summary wording.
Files changed:
.../artifacts-doc-editing-and-comment-fix.md | 2 +-
.changeset/fn-7829-terminal-shortcuts-footer.md | 7 +
docs/dashboard-guide.md | 9 +-
.../dashboard/app/components/TerminalModal.css | 121 +++-----
.../dashboard/app/components/TerminalModal.tsx | 336 +++++++++++----------
.../components/__tests__/TerminalModal.test.tsx | 185 ++++++++----
6 files changed, 351 insertions(+), 309 deletions(-)
Fusion-Task-Id: FN-7829
Fusion-Task-Lineage: 443c6e69-8946-4307-8a1a-f4f90681a054
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Claude per-model weekly usage is parsed generically from the OAuth payload's
limits[] scoped entries (live probe disproved the seven_day_fable key guess).
Grok now prefers ~/.grok/auth.json OIDC credentials against
cli-chat-proxy.grok.com/v1/billing?format=credits for a real percent-used
weekly credits window, falling back to the xAI API-key validity card.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- scope session collections to the active project\n- clean up runtime stage registration in discovery tests\n- model brainstorms and plans as repeatable artifact collections\n- compact the singleton Strategy presentation
- Task Documents right pane gains in-place editing with the shared CodeMirror
FileEditor (Save via PUT /tasks/:id/documents/:key); task documents now
render markdown by default.
- Project Files pane is editable the same way via the project workspace file
API, replacing the Read-only badge contract.
- Fix "Add comment" doing nothing again: `.selection-comment-trigger:active`
tied the global `.btn:active` at (0,2,0) and lost to a bundle-order flip,
teleporting the trigger mid-press so click never fired. `:active` rules now
use `.btn.selection-comment-trigger` (0,3,0); regression test asserts the
prefix so a plain-selector revert fails.
- Align the task-document header: path box and Plain/Edit (Cancel/Save)
actions share one row, meta line sits below.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Terminal WebSocket sessions now retry with capped backoff through cold-start failures instead of giving up and requiring a manual Reconnect click.
- useTerminal tracks whether a socket has ever successfully opened via hasEverConnectedRef
- a never-connected initial connect ignores MAX_RECONNECT_ATTEMPTS and keeps retrying at capped backoff, staying in the reconnecting affordance until it opens
- mid-session drops (sockets that opened at least once) keep the existing bounded give-up behavior, and permanent 4000/4004 closes remain terminal
- context-change invalidation now uses a ref flag (contextChangedSinceLastEffectRef) consumed inside the effect instead of a transient boolean dependency, avoiding cleanup re-runs that tore down the replacement socket during context-switch/reconnect races
- manual reconnect() and context/session changes reset hasEverConnectedRef so cold-start behavior reapplies per session
- added a patch changeset and expanded useTerminal test coverage for first-launch reconnect vs. mid-session disconnect behavior
- documented the first-launch reconnect behavior in docs/dashboard-guide.md
Files changed:
.changeset/FN-7824-terminal-first-launch-autoreconnect.md | 7 +
docs/dashboard-guide.md | 3 +
packages/dashboard/app/hooks/__tests__/useTerminal.test.ts | 208 ++++++++++++++++++++-
packages/dashboard/app/hooks/useTerminal.ts | 34 +++-
4 files changed, 234 insertions(+), 18 deletions(-)
Fusion-Task-Id: FN-7824
Fusion-Task-Lineage: 7ed696d0-449e-4dc0-9be0-48b429b8c844
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
Removes the hard divider between the Settings navigation rail and content, keeps section rows single-line with ellipsis overflow, and adds a draggable/keyboard-resizable handle that persists the rail's width in localStorage across the standalone modal and embedded Settings page.
- Add a resize handle (.settings-nav-resize-handle) between .settings-navigation and .settings-content, draggable via pointer events and resizable with ArrowLeft/ArrowRight when focused
- Persist chosen width to localStorage (fusion:settings-nav-width), clamped between 200px and 420px, defaulting to 248px; restore on mount
- Make .settings-navigation the sole owner of rail width via a --settings-nav-width CSS custom property instead of a fixed width, and drop the border-right divider
- Keep nav section labels on one line with white-space: nowrap + text-overflow: ellipsis in both the modal (SettingsModal.css) and embedded (styles.css) nav item styles
- Hide the resize handle on mobile; mobile keeps the stacked section picker unaffected
- Update docs/dashboard-guide.md to describe the new divider-less rail and resize behavior
- Add SettingsModal.navResize.test.tsx covering drag-resize, keyboard-resize, and width persistence
- Add changeset .changeset/fn-7825-settings-nav-resizable.md (minor)
Files changed:
.changeset/fn-7825-settings-nav-resizable.md | 7 +
docs/dashboard-guide.md | 3 +
packages/dashboard/app/components/SettingsModal.css | 56 ++++-
packages/dashboard/app/components/SettingsModal.tsx | 124 +++++++++-
packages/dashboard/app/components/__tests__/SettingsModal.navResize.test.tsx | 268 +++++++++++++++++++++
packages/dashboard/app/styles.css | 27 ++-
6 files changed, 467 insertions(+), 18 deletions(-)
Fusion-Task-Id: FN-7825
Fusion-Task-Lineage: 34b940b4-2698-46a4-b47c-cda0b0cac564
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>