Commit Graph

11182 Commits

Author SHA1 Message Date
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
gsxdsm
fce8c757b8 Updated roadmap 2026-07-12 12:13:41 -07:00
gsxdsm
b8c18becd3 FN-7865: make artifact viewer popups full-screen sheets on mobile
Fixes the artifact viewer FloatingWindow (image/video/PDF/document) so it opens as a full-screen sheet on mobile instead of a small draggable/resizable desktop-style window.

- Add a mobile-breakpoint override for .artifacts-gallery-window that clamps the FloatingWindow to inset:0/100vw/100dvh with no border/radius/shadow
- Hide the FloatingWindow resize handle and disable header drag cursor/touch-action on mobile so the sheet can't be dragged or resized like the desktop window
- Add a CSS-contract regression test (ArtifactsGallery.css.test.ts) asserting the mobile sheet rules exist while desktop keeps the header drag affordance
- Update dashboard-guide.md docs to describe desktop draggable/resizable behavior vs. mobile full-screen sheet behavior
- Add a patch changeset for @runfusion/fusion documenting the fix

Files changed:
 .changeset/fn-7865-artifact-viewer-mobile-sheet.md |  7 +++
 docs/dashboard-guide.md                            |  5 +-
 .../dashboard/app/components/ArtifactsGallery.css  | 28 +++++++++-
 .../__tests__/ArtifactsGallery.css.test.ts         | 63 ++++++++++++++++++++++
 4 files changed, 100 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7865

Fusion-Task-Lineage: 0b5dfaee-3f7b-4a2e-968c-324182ae7953

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 12:10:38 -07:00
gsxdsm
95a808af6e FN-7864: add inline artifact preview/link to artifact-registered mail messages
Artifact-registration mailbox notifications now render a shared inline preview and open-artifact link instead of plain text metadata.

- Add MailboxArtifactAttachment component rendering an inline image/document preview plus an "open artifact" link from message.metadata (artifactId/artifactType/mimeType) via artifactMediaUrl
- Wire MailboxModal and MailboxView to render the new attachment for artifact-registered messages, with supporting CSS
- Emit metadata.mimeType from notifyArtifactRegistered in agent-tools.ts so mailbox surfaces can pick the right preview affordance without an extra artifact fetch
- Add/extend tests for the new component and for MailboxView/agent-artifact-tools coverage
- Update dashboard guide docs and add a changeset for the feature

Files changed:
 .changeset/fn-7864-artifact-mail-link.md           |   7 ++
 docs/dashboard-guide.md                            |   2 +-
 .../app/components/MailboxArtifactAttachment.tsx   | 103 +++++++++++++++++++++
 packages/dashboard/app/components/MailboxModal.css |  74 +++++++++++++++
 packages/dashboard/app/components/MailboxModal.tsx |  15 +++
 packages/dashboard/app/components/MailboxView.tsx  |  15 +++
 .../__tests__/MailboxArtifactAttachment.test.tsx   |  65 +++++++++++++
 .../app/components/__tests__/MailboxView.test.tsx  |  93 +++++++++++++++++++
 .../src/__tests__/agent-artifact-tools.test.ts     |  32 ++++++-
 packages/engine/src/agent-tools.ts                 |   5 +
 10 files changed, 409 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-7864

Fusion-Task-Lineage: a6502e18-5f7f-4c67-80fb-a709e4a52c50

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 12:01:00 -07:00
gsxdsm
9cfb40e137 FN-7863: add bounded execute-node self-requeue loop guard
Bounds the execute->pause-abort->todo dispatch loop so a task can no longer requeue forever with no visible signal or terminal state.

- Track a progress-anchored `executeRequeueLoopCount`/`executeRequeueLoopSignature` pair on the task row (current step + step statuses) so slow no-progress requeue cycles are counted independently of the scheduler's wall-clock `dispatchStormCount` guard.
- Warn visibly in the task log at `EXECUTE_REQUEUE_LOOP_VISIBLE_THRESHOLD` (3) and terminalize non-paused, non-terminal tasks at `MAX_EXECUTE_REQUEUE_LOOP_CYCLES` (6) with `status:"failed"` and an `EXECUTION_DISPATCH_LOOP_EXHAUSTED:` error, preserving worktree/branch/step progress.
- Emit a new `task:execution-dispatch-loop-terminalized` run-audit mutation type with ids/counts/outcomes-only metadata.
- Reset the loop counters on real progress, manual retry, forward moves (in-review/done/archived), and unpause, in both the executor and scheduler.
- Add DB migration 142 (`executeRequeueLoopCount`, `executeRequeueLoopSignature` columns) plus store read/write/reset plumbing.
- Add reliability-interactions coverage for the new loop guard and extend store-persistence tests for the new columns.
- Document the new behavior in AGENTS.md and docs/architecture.md.

Files changed:
 AGENTS.md                                              |   1 +
 docs/architecture.md                                   |   2 +
 packages/core/src/__tests__/store-persistence.test.ts  |  45 +++++
 packages/core/src/db.ts                                |  17 +-
 packages/core/src/manual-retry-reset.ts                |   1 +
 packages/core/src/store.ts                             |  22 ++-
 packages/core/src/types.ts                             |  11 ++
 .../execute-requeue-loop-guard.test.ts                 | 188 +++++++++++++++
 packages/engine/src/executor.ts                        |  67 +++++++-
 packages/engine/src/run-audit.ts                       |   2 +
 packages/engine/src/scheduler.ts                       |   8 +-
 11 files changed, 355 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-7863
Fusion-Task-Lineage: db40507f-5851-435e-8854-c1ed695b4154
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:56:54 -07:00
gsxdsm
0c97c161ee FN-7860: honor plugin skillFiles paths for skill body resolution
Plugin skills declared with PluginSkillContribution.skillFiles were silently ignored by the host, forcing plugin authors into a flat skills/<name>/SKILL.md layout instead of category subdirectories.

- Add packages/core/src/plugin-skill-paths.ts with resolvePluginSkillBodyPath (honors skillFiles[0] relative to plugin root, falls back to skills/<name>/SKILL.md, rejects path traversal) and resolvePluginRootFromEntryPath
- Track per-plugin absolute roots in PluginLoader and expose pluginRoot alongside each getPluginSkills() contribution
- Thread pluginRoot/skillFiles through PluginRunner, dashboard server/chat structural types, and skills-adapter so discovered plugin skill path/relativePath resolve via the new traversal-guarded resolver when a pluginRoot is available, keeping the old name-derived path for backward compatibility otherwise
- Export resolvePluginSkillBodyPath/resolvePluginRootFromEntryPath/PluginSkillBodyPath from @fusion/core
- Update docs/PLUGIN_AUTHORING.md and add unit tests covering the new resolver and updated plugin-loader/skills-adapter/plugin-runner behavior
- Add changeset (@runfusion/fusion: minor, category: fix)

Files changed:
 .changeset/fn-7860-plugin-skillfiles.md            |  7 ++
 docs/PLUGIN_AUTHORING.md                           |  4 +-
 packages/core/src/__tests__/plugin-loader.test.ts  | 23 +++++++
 .../core/src/__tests__/plugin-skill-paths.test.ts  | 75 ++++++++++++++++++++++
 packages/core/src/index.ts                         |  5 ++
 packages/core/src/plugin-loader.ts                 | 20 +++++-
 packages/core/src/plugin-skill-paths.ts            | 58 +++++++++++++++++
 .../dashboard/src/__tests__/skills-adapter.test.ts | 75 +++++++++++++++++++++-
 packages/dashboard/src/chat.ts                     |  2 +-
 packages/dashboard/src/server.ts                   |  2 +-
 packages/dashboard/src/skills-adapter.ts           | 19 ++++--
 .../engine/src/__tests__/plugin-runner.test.ts     |  2 +-
 packages/engine/src/plugin-runner.ts               |  4 +-
 13 files changed, 280 insertions(+), 16 deletions(-)

Fusion-Task-Id: FN-7860

Fusion-Task-Lineage: 720cf527-9c6f-4877-838e-5fb64bd86556

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:52:24 -07:00
gsxdsm
7a7c12847e FN-7862: align task-id, badges, and header actions on a shared baseline in board card header
Aligns the task card header so the id chip, first badge row, and right-side size/action controls share a consistent centered vertical baseline, using the existing card chip height tokens for row rhythm on both desktop and mobile while preserving FN-7837 wrapping behavior.

- Give .card-header-badges and .card-id a shared min-height (--card-chip-height) and switch .card-id to inline-flex with centered items and line-height:1 so it lines up with sibling chips instead of sitting on its own baseline
- Add min-height (--card-chip-height) to .card-header-actions so the right-aligned size/action cluster matches the id/badge row height
- Add a mobile-breakpoint override giving .card-id, .card-header-badges, and .card-header-actions a shared --card-chip-height-mobile min-height, extending the existing FN-4365/FN-4351/FN-7837 compact mobile header comment
- Add/extend TaskCard.badge-wrap tests: a shared expectSharedHeaderBaseline() assertion helper, new in-progress and no-badges alignment test cases, and a test asserting the mobile header rhythm CSS rule is present in loaded app CSS

Files changed:
 packages/dashboard/app/components/TaskCard.css     |  23 +++--
 .../__tests__/TaskCard.badge-wrap.test.tsx         | 100 ++++++++++++++++++++-
 2 files changed, 116 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7862

Fusion-Task-Lineage: 1d66fbd6-30bc-4a76-9eb4-3b8734ddadc3

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:39:07 -07:00
gsxdsm
67cc025562 FN-7859: park non-recoverable durable heartbeat errors instead of stalling in bare error
Debug org agents error state recovery regression: durable heartbeat-managed
agents with a non-recoverable error (permanent/credential/model-access/
config, not stale-worktree/module-resolution) were previously left
indefinitely in bare `state:"error"` with no operator-visible reason,
and CLI agent inspection tools did not surface error/pause diagnostics.

- Timer path (`HeartbeatMonitor`) and run-entry recovery now classify
  non-recoverable durable heartbeat errors and park the agent `paused`
  with `pauseReason:"error-unrecoverable"` instead of restart-looping or
  sitting in `error` forever.
- `SelfHealingManager` mirrors the same non-recoverable classification in
  its recovery sweep, parking with the same reason/metadata and skipping
  the exhausted/next-retry gates for that terminal bucket.
- New `agent:error-parked-unrecoverable` run-audit event type emitted by
  both the heartbeat and self-healing paths (ids/counts/outcomes-only
  metadata).
- `fn_agent_show` now prints `Last Error`, `Pause Reason`, and a compact
  `Error Recovery` counter line; `fn_list_agents` prints the same
  diagnostics only for agents currently in `error`/`paused`.
- Updated `AGENTS.md`, `docs/agents.md`, and `docs/architecture.md` to
  document the new terminal-park behavior and CLI diagnostics surface.
- Added a changeset (`@runfusion/fusion` patch) describing the
  operator-facing fix.

Files changed:
 .changeset/fn-7859-org-agent-error-diagnostics.md  |  7 ++
 AGENTS.md                                          |  2 +-
 docs/agents.md                                     |  3 +-
 docs/architecture.md                               |  4 +-
 packages/cli/src/__tests__/extension.test.ts       | 68 ++++++++++++++++
 packages/cli/src/extension.ts                      | 64 +++++++++++++++
 .../src/__tests__/heartbeat-error-recovery.test.ts | 47 ++++++++++-
 packages/engine/src/__tests__/self-healing.test.ts | 94 ++++++++++++++++++----
 packages/engine/src/agent-heartbeat.ts             | 71 +++++++++++++++-
 packages/engine/src/run-audit.ts                   |  1 +
 packages/engine/src/self-healing.ts                | 46 +++++++++--
 11 files changed, 375 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-7859

Fusion-Task-Lineage: 09b2035d-e8a0-438f-b1ab-1b0048b35c76

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:34:48 -07:00
gsxdsm
e559b2b538 FN-7853: preserve chat thread during active streaming turns
Fix useChat so already-rendered user/assistant messages no longer flicker away while an agent turn is actively streaming.

- useChat.ts: during an active streaming turn for the current session, treat stale/empty/cross-session loadMessages responses as append-only against the visible thread instead of replacing it, merging any genuinely new same-session messages in and skipping the session-cache write when the active thread is being preserved.
- ChatView.streaming-thread.test.tsx: add coverage asserting the rendered thread stays visible across mid-turn session-update/tool-call/stale-reload churn.
- useChat.test.ts: add hook-level regression tests for the append-only/merge/cache-skip behavior during active streaming.
- docs/architecture.md, docs/dashboard-guide.md: document the append-only mid-turn thread-stability behavior.
- Add changeset (patch) for @runfusion/fusion describing the user-facing fix.

Files changed:
 .../fn-7853-chat-mid-turn-message-stability.md     |   7 +
 docs/architecture.md                               |   1 +
 docs/dashboard-guide.md                            |   1 +
 .../__tests__/ChatView.streaming-thread.test.tsx   | 130 +++++++++++++
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 208 +++++++++++++++++++++
 packages/dashboard/app/hooks/useChat.ts            |  35 +++-
 6 files changed, 380 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-7853

Fusion-Task-Lineage: d9909469-082c-4eeb-81fb-b36d1a9e4705

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:26:53 -07:00
gsxdsm
20c6db9534 FN-7861: make pause/unpause task state update the board immediately
Patch useTasks pauseTask/unpauseTask to update local hook state and the project SWR task cache immediately on API success, instead of waiting for SSE/poll to reconcile paused state.

- pauseTask/unpauseTask now bump fetchVersionRef, patch the in-memory tasks list, and patch/clear the project SWR cache the same way retryTask/bypassReview already do
- guards against stale in-flight fetches clobbering the just-applied paused/unpaused state and against missing-id cache entries
- adds regression tests covering immediate local+cache reflection for pause and unpause, stale in-flight fetch ordering, and missing-id stability
- adds a patch changeset documenting the user-facing fix

Files changed:
 .changeset/fn-7861-immediate-pause-state.md        |   7 +
 .../dashboard/app/hooks/__tests__/useTasks.test.ts | 151 +++++++++++++++++++++
 packages/dashboard/app/hooks/useTasks.ts           |  66 ++++++++-
 3 files changed, 222 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-7861

Fusion-Task-Lineage: fefbaf4f-8eb7-44a7-a1e2-ac8471a726bd

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:23:23 -07:00
gsxdsm
9bb74595c2 FN-7852: add one-time SQLite→embedded Postgres storage notice banner
Adds a dismissible, one-time dashboard banner announcing the upcoming SQLite→embedded-Postgres storage backend change.

- New self-contained StorageMigrationNoticeBanner component with title/body copy and a dismiss control that persists via localStorage key fusion:storage-migration-notice-dismissed
- Wire the banner into DashboardBanners alongside the CLI binary install banner for project-scoped views
- Add en locale strings (storageMigrationNotice.title/body/dismissLabel) in app.json
- Add component test coverage for render/dismiss/persistence behavior
- Document the notice in docs/dashboard-guide.md
- Add a minor changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7852-storage-migration-notice.md     |  7 ++
 docs/dashboard-guide.md                            |  2 +
 .../components/StorageMigrationNoticeBanner.css    | 73 +++++++++++++++++++
 .../components/StorageMigrationNoticeBanner.tsx    | 65 +++++++++++++++++
 .../StorageMigrationNoticeBanner.test.tsx          | 82 ++++++++++++++++++++++
 .../app/components/dashboard/DashboardBanners.tsx  | 11 ++-
 packages/i18n/locales/en/app.json                  |  5 ++
 7 files changed, 242 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7852

Fusion-Task-Lineage: e3235cce-9ca3-4830-8733-a2ec46c53246

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:19:52 -07:00
gsxdsm
c13d2ee9c2 FN-7858: honor per-project plugin-skill toggles in session merging
Session skill merging (collectPluginSkillNames) previously ignored per-project
Skills view enable/disable toggles and only consulted each plugin's static
default, so a user disabling a plugin skill in the Skills view would still see
it merged into live agent sessions. Extracted the effective-enablement
resolver shared by dashboard discovery and engine session assembly into
@fusion/core so both surfaces stay in sync.

- Added packages/core/src/skill-settings.ts with computeSkillId/parseSkillId/
  normalizeStoredSkillPath/getSkillSettingState/resolvePluginSkillEnabled,
  exported from @fusion/core's index.
- packages/dashboard/src/skills-adapter.ts now re-exports and delegates to the
  shared @fusion/core resolver instead of duplicating its own
  getSkillSettingState/computeSkillId/parseSkillId implementations.
- packages/engine/src/session-skill-context.ts: collectPluginSkillNames now
  accepts a projectRootDir, reads project settings via skill-resolver's newly
  exported readProjectSettings/resolveProjectRoot, and calls
  resolvePluginSkillEnabled instead of only checking the plugin's static
  skill.enabled flag; mergePluginSkills passes projectRootDir through.
- packages/engine/src/skill-resolver.ts: exported readProjectSettings and
  ProjectSkillSettings for reuse by session-skill-context.
- Updated docs/plugin-management.md to document that per-project Skills view
  toggles now apply to runtime agent sessions, not just discovery.
- Added unit tests for the new core resolver and updated dashboard/engine
  tests to cover per-project toggle overrides in session merging.
- Added a patch changeset for @runfusion/fusion.

Files changed:
 .changeset/fn-7858-plugin-skill-session-toggle.md  |   7 ++
 docs/plugin-management.md                          |   4 +-
 packages/core/src/__tests__/skill-settings.test.ts |  62 +++++++++
 packages/core/src/index.ts                         |   8 ++
 packages/core/src/skill-settings.ts                | 102 +++++++++++++++
 .../dashboard/src/__tests__/skills-adapter.test.ts |  60 ++++++++-
 packages/dashboard/src/skills-adapter.ts           | 107 +++-------------
 .../src/__tests__/session-skill-context.test.ts    | 140 ++++++++++++++++++++-
 packages/engine/src/session-skill-context.ts       |  23 +++-
 packages/engine/src/skill-resolver.ts              |   4 +-
 10 files changed, 409 insertions(+), 108 deletions(-)

Fusion-Task-Id: FN-7858

Fusion-Task-Lineage: 90e44d24-e385-4a74-b8e4-3c864ec39a95

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:15:52 -07:00
gsxdsm
729298fa36 FN-7855: refresh persisted plugin manifest metadata on reload/re-import
Path-registered plugin reload/restart now refreshes persisted manifest metadata instead of leaving stale version/settingsSchema in the store.

- PluginLoader.loadPlugin/reloadPlugin call a new refreshPersistedManifestMetadata helper after each fresh module import, generalizing the previously bundled-only refresh to path-registered plugins
- Refresh is metadata-only (version, settingsSchema) via a stable-JSON comparison, preserving per-project enablement and saved setting values, and is a no-op when nothing changed
- PluginStore.PluginUpdateInput/updatePlugin gain a settingsSchema field (undefined = unchanged, null = explicitly clear) so updatePlugin can persist manifest schema changes independently of setting values
- Docs: add a "Updating path-registered plugins" section to docs/PLUGIN_AUTHORING.md describing the new reload/refresh loop
- Tests: add coverage in plugin-loader.test.ts and plugin-store.test.ts for manifest metadata refresh on load/reload and settingsSchema persistence
- Add a patch changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7855-plugin-manifest-refresh.md     |   7 +
 docs/PLUGIN_AUTHORING.md                          |  10 ++
 packages/core/src/__tests__/plugin-loader.test.ts | 177 ++++++++++++++++++++++
 packages/core/src/__tests__/plugin-store.test.ts  |  42 +++++
 packages/core/src/plugin-loader.ts                |  53 +++++++
 packages/core/src/plugin-store.ts                 |  10 ++
 6 files changed, 299 insertions(+)

Fusion-Task-Id: FN-7855
Fusion-Task-Lineage: f4d94023-5a27-4059-a7a5-61f524c171b8
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 11:11:50 -07:00
gsxdsm
8b601810e0 fix(FN-7851): enforce per-agent assignment policy across all task-routing binding primitives
Issue #2015: product-code executor tasks were repeatedly routed to a
liaison-only agent because every routing path gated only on the coarse
role field, and several binding primitives had no guard at all.

- Add runtimeConfig.assignmentPolicy ("auto" | "explicit-only" | "none");
  "none" can never be bound to implementation tasks by ANY path — no
  override bypasses it (the liaison guarantee)
- Route every binding surface through one shared evaluator
  (evaluateImplementationTaskBind): claimTaskForAgent, the previously
  unguarded checkoutTask/assignTask primitives, selectNextTaskForAgent
  (including the in-progress re-selection loop), scheduler auto-assign
  pool, heartbeat inbox/auto-claim, fn_delegate_task, CLI agent-id
  validation, and dashboard assign/checkout/inbox routes
- Lock project isolation with a regression test: a foreign-project
  agent id is rejected by every binding primitive
- Expose Assignment Policy in Agent Detail settings; document in
  docs/agents.md; add changeset

Fusion-Task-Id: FN-7851

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 10:04:29 -07:00
gsxdsm
f23619c2d4 fix: preserve user pause across executor pause teardown (FN-7851 pause-bounce loop)
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>
2026-07-12 10:04:29 -07:00
gsxdsm
5f4ad172f4 fix: give Grok ACP absolute paths for chat image attachments
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.
2026-07-12 09:56:26 -07:00
gsxdsm
3d7eaeabee FN-7849: reconcile streaming user-message echo to render chat attachments immediately
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>
2026-07-12 00:26:51 -07:00
gsxdsm
0a74059113 FN-7850: change dashboard TUI splash tagline to "software factory"
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>
2026-07-12 00:17:41 -07:00
gsxdsm
f82a3d2840 chore(release): v0.58.0
Version bump via changesets.
2026-07-11 23:50:00 -07:00
gsxdsm
7e60b0dcab docs: note chat image ContentBlocks on Grok ACP promptWithFallback 2026-07-11 23:46:08 -07:00
gsxdsm
c2d3bf0e8a fix: forward chat image attachments into Grok/ACP session/prompt
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.
2026-07-11 23:46:08 -07:00
gsxdsm
70cca2f96b fix: accept Grok ACP extension notifications without Method not found
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.
2026-07-11 23:46:08 -07:00
gsxdsm
a850cb7ead fix: document non-pi customTools fail-open when gate context omitted
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.
2026-07-11 23:34:35 -07:00
gsxdsm
0b4ce01ea8 fix: gate customTools for non-pi runtimes before createSession
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.
2026-07-11 23:34:35 -07:00
gsxdsm
40a01f1d0f fix: Grok ACP skill packaging paths and dead-session follow-up prompts 2026-07-11 23:23:31 -07:00
gsxdsm
82f007b273 fix: resolve Grok ACP adapter TypeScript errors for CI typecheck/build 2026-07-11 23:23:31 -07:00
gsxdsm
de8d00a475 fix: address CI lint failures in chat routes and grok MCP schema server 2026-07-11 23:23:31 -07:00
gsxdsm
6267a762a4 feat: drive Grok CLI sessions over ACP with tools, skills, and MCP
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.
2026-07-11 23:23:31 -07:00
gsxdsm
b613a87e75 FN-7848: keep GitHub star count visible in mobile Settings header
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>
2026-07-11 23:18:49 -07:00
gsxdsm
d99c04cded FN-7847: add pricing for GLM-5.2, MiniMax-M3, and Kimi K2.6
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>
2026-07-11 23:10:58 -07:00
gsxdsm
9b7623bc4c test: fix heartbeat getSettings mock + recoveryEligible (FN-7835), skip planner confirmation gate (FN-7840), chat engine mock, dashboard lucide+tabs 2026-07-11 23:08:36 -07:00
gsxdsm
dd95634262 FN-7845: show task-scoped artifacts alongside Task Documents
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>
2026-07-11 22:43:34 -07:00
gsxdsm
9ac4da0794 FN-7846: move task card size badge to the right edge of header actions
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>
2026-07-11 22:40:49 -07:00
gsxdsm
1a7f35dac6 chore: ignore .orca directory
Keep Orca local workspace state out of version control.
2026-07-11 22:35:36 -07:00
gsxdsm
c9d0211bec FN-7844: coordinate heartbeat and self-healing durable-agent error recovery
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>
2026-07-11 22:31:30 -07:00
gsxdsm
4397cafb94 fix: wire push-after-merge into the unified runAiMerge path with remote/branch dropdown settings
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>
2026-07-11 22:16:48 -07:00
gsxdsm
391ff0d269 FN-7835: auto-clear durable agent error state and retry on next heartbeat
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>
2026-07-11 22:16:48 -07:00
gsxdsm
be1950b79c FN-7843: keep task-detail per-model token tables horizontally scrollable on mobile
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>
2026-07-11 22:16:48 -07:00
gsxdsm
c7c6c5a8c4 FN-7842: color-code priority icons by urgency across quick add, task form, and task cards
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>
2026-07-11 22:16:48 -07:00
gsxdsm
3da3f377c9 FN-7839: group done-card Archive and Revert actions into one dropdown
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>
2026-07-11 22:16:48 -07:00
gsxdsm
0b5c5517d8 FN-7841: fix mobile Todo single-panel stack to fill full height
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>
2026-07-11 22:16:48 -07:00
gsxdsm
14b7244bcb FN-7840: suppress advisory merger/pull-request await-confirmation interventions
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>
2026-07-11 22:16:48 -07:00
gsxdsm
66e91f96ae FN-7837: fix task card size badge wrapping onto a misaligned second row
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>
2026-07-11 22:16:47 -07:00
gsxdsm
cc743eec38 FN-7838: make CLI agent cold-start timeouts configurable via env vars
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>
2026-07-11 22:16:47 -07:00
gsxdsm
b3ed63dae9 FN-7836: fix Task Documents sidebar cards collapsing to blank rows under flex shrink
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>
2026-07-11 22:16:47 -07:00
gsxdsm
1540473db8 test(dashboard): add Cost (FN-7820) + Terminal (FN-7826) tabs to expected arrays + settings description allowlist 2026-07-11 21:41:30 -07:00
gsxdsm
72aae17200 test(dashboard): mock @fusion/engine in chat.test.ts to stop transitive core-export cascade 2026-07-11 21:41:30 -07:00
gsxdsm
4fb360631c FN-7833: render task Artifacts documents as Markdown, expanded by default
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>
2026-07-11 20:50:59 -07:00
gsxdsm
06bf0b85b9 FN-7834: restyle Task Documents sidebar with clearer task-card grouping
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>
2026-07-11 20:48:20 -07:00
gsxdsm
49faf0afe2 FN-7832: reorder Task Detail tabs and default terminal picker to task worktree
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>
2026-07-11 20:46:05 -07:00