Commit Graph

11122 Commits

Author SHA1 Message Date
gsxdsm
05d30ffee7 feat(dashboard): editable task documents & project files in Artifacts view; fix Add-comment CSS-order regression
- 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>
2026-07-11 19:31:50 -07:00
gsxdsm
53427cde2c fix: prevent stale planning notifications 2026-07-11 19:15:20 -07:00
gsxdsm
79264d4990 FN-7824: auto-reconnect terminal on first launch instead of parking disconnected
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>
2026-07-11 18:52:28 -07:00
gsxdsm
26f0c5ae8a FN-7825: add resizable Settings navigation rail with persisted width
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>
2026-07-11 18:48:59 -07:00
gsxdsm
41998a6c75 FN-7828: fix cramped padding on notifications failure-mode settings card
Wraps the failure-notification mode fields in the shared .notification-provider-body wrapper so the card's padding/gutters match sibling provider cards on desktop and mobile.

- Wrap failure-notification mode select and delay input in .notification-provider-body within NotificationsSection.tsx
- Add FNXC:SettingsLayout comment documenting why .notification-provider-body is needed (parent .notification-provider-card has no own padding)
- Add regression test asserting the failure-notification mode field nests inside .notification-provider-body, itself inside .notification-provider-card
- Add changeset (patch) documenting the fix

Files changed:
 .changeset/fuzzy-notification-padding.md           |  7 +++
 .../app/__tests__/settings-sections.test.tsx       | 18 ++++++++
 .../settings/sections/NotificationsSection.tsx     | 50 ++++++++++++----------
 3 files changed, 53 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-7828

Fusion-Task-Lineage: 734c652d-400e-4cb1-b6a9-3a001f0b10b7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:44:57 -07:00
gsxdsm
9d06141808 FN-7827: unclamp workflow editor shell height/width so canvas fills modal and tracks resizes
Fixes the workflow editor shell inheriting the shared .modal max-height: 80vh clamp, which prevented the canvas from filling the FloatingWindow/embedded host and tracking resizes.

- Add max-width: none and max-height: none to .wf-editor-modal so FloatingWindow and the embedded pane own sizing instead of the shared .modal clamp.
- Add regression test asserting the shell stays unclamped across desktop FloatingWindow, embedded, and mobile hosts (not just the reported 80vh repro).

Files changed:
 .../app/components/WorkflowNodeEditor.css          |  6 ++++++
 .../__tests__/WorkflowNodeEditor.css.test.ts       | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+)

Fusion-Task-Id: FN-7827

Fusion-Task-Lineage: a39ff6ba-3e72-4f7b-802c-ba1317ca37e9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:37:14 -07:00
gsxdsm
17d7bd19ef FN-7826: make Task Detail interactive Terminal tab always available
Removes the single-worktree gate on the Task Detail Terminal tab so it renders for every task, defaulting its first shell to the task worktree when present and otherwise falling back to the project root.

- TaskDetailModal.tsx: showWorktreeTerminalTab is now always true (drops the isWorkspaceTask/single-worktree gate and its stale fallback effect); taskWorktreeCwd still feeds defaultCwd when a worktree is recorded, and the tab renders without requiring taskWorktreeCwd
- Adds a changeset documenting the behavior change (minor, feature) for @runfusion/fusion
- docs/dashboard-guide.md: updates the Terminal tab description to state it is always available, with worktree-or-project-root cwd fallback, including for multi-repo workspace tasks
- Expands TaskDetailModal.worktree-terminal.test.tsx coverage for the no-worktree and workspace-task cases now that the tab is always shown

Files changed:
 .changeset/FN-7826-worktree-terminal-always-available.md          |  7 +++
 docs/dashboard-guide.md                                           |  4 +-
 packages/dashboard/app/components/TaskDetailModal.tsx             | 12 ++---
 .../TaskDetailModal.worktree-terminal.test.tsx                    | 57 +++++++++++++++++++---
 4 files changed, 63 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-7826

Fusion-Task-Lineage: f87504fe-9330-4392-bdbe-33bba006d96c

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:31:14 -07:00
gsxdsm
ee5c2a80e6 FN-7823: fix terminal header wrapping and spacing on narrow desktop panels
Prevent the terminal header's shortcut/status text and action controls from wrapping onto multiple lines when the floating or docked terminal panel is narrow at desktop breakpoints.

- Add white-space: nowrap to .terminal-shortcuts--header so header help text stays on one line
- Add white-space: nowrap to .terminal-connection-status to keep connection status text from wrapping
- Rely on existing .terminal-actions min-width: 0 + overflow-x: auto pattern for horizontal scrolling instead of wrapping
- Add regression test asserting the nowrap/scroll rules and that mobile still hides these elements
- Add changeset documenting the fix

Files changed:
 .changeset/fn-7823-terminal-header-nowrap.md        |  7 +++++++
 packages/dashboard/app/components/TerminalModal.css |  9 +++++++++
 .../app/components/__tests__/TerminalModal.test.tsx | 21 +++++++++++++++++++++
 3 files changed, 37 insertions(+)

Fusion-Task-Id: FN-7823

Fusion-Task-Lineage: 36426985-a489-41ec-9d79-f8b02862d504

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:28:19 -07:00
gsxdsm
937650472a FN-7820: add Cost tab to task detail and optional card cost badge
Adds a shared cost-derivation utility and surfaces token/cost info in a new Cost tab on the task detail modal, plus an opt-in per-card cost badge on the board.

- Extract token-cost calculation into a shared taskTokenCost helper (read-time costFor derivation) reused by the Summary tab, new Cost tab, and card badge
- Add TaskDetailModal Cost tab (TaskCostTab.tsx/.css) showing cost breakdown for a task
- Simplify TaskSummaryTab by delegating cost math to the shared helper
- Add default-off project setting showCostBadgeOnCards (settings-schema.ts, types.ts) with a SettingsModal/AppearanceSection toggle
- Add CostBadgeContext to thread the setting into TaskCard without prop drilling
- Show an optional cost badge on TaskCard when the setting is enabled
- Update i18n strings across en/es/fr/ko/zh-CN/zh-TW locales
- Update docs (dashboard-guide.md, settings-reference.md) and add changeset fn-7820-cost-tab-and-card-badge.md

Files changed:
 .changeset/fn-7820-cost-tab-and-card-badge.md      |   7 ++
 docs/dashboard-guide.md                            |   4 +
 docs/settings-reference.md                         |   1 +
 .../core/src/__tests__/settings-defaults.test.ts   |  13 ++
 packages/core/src/settings-schema.ts               |   5 +
 packages/core/src/types.ts                         |   5 +
 packages/dashboard/app/App.tsx                     |   5 +
 .../dashboard/app/components/SettingsModal.tsx     |   6 +
 packages/dashboard/app/components/TaskCard.css     |   7 +-
 packages/dashboard/app/components/TaskCard.tsx     |  27 +++-
 packages/dashboard/app/components/TaskCostTab.css  |  51 ++++++++
 packages/dashboard/app/components/TaskCostTab.tsx  |  91 ++++++++++++++
 .../dashboard/app/components/TaskDetailModal.tsx   |  14 ++-
 .../dashboard/app/components/TaskSummaryTab.tsx    | 123 +-----------------
 .../app/components/__tests__/TaskCard.test.tsx     |  81 +++++++++++-
 .../app/components/__tests__/TaskCostTab.test.tsx  |  55 ++++++++
 .../TaskDetailModal.attachments-and-tabs.test.tsx  |  11 +-
 .../settings/sections/AppearanceSection.tsx        |   8 ++
 .../sections/__tests__/AppearanceSection.test.tsx  |  20 +++
 .../settings-default-descriptions.test.tsx         |   1 +
 .../dashboard/app/context/CostBadgeContext.tsx     |  19 +++
 packages/dashboard/app/hooks/useAppSettings.ts     |  15 +++
 .../app/utils/__tests__/taskTokenCost.test.ts      |  62 +++++++++
 packages/dashboard/app/utils/taskTokenCost.ts      | 139 +++++++++++++++++++++
 packages/i18n/locales/en/app.json                  |  29 ++++-
 packages/i18n/locales/es/app.json                  |  30 ++++-
 packages/i18n/locales/fr/app.json                  |  27 +++-
 packages/i18n/locales/ko/app.json                  |  30 ++++-
 packages/i18n/locales/zh-CN/app.json               |  30 ++++-
 packages/i18n/locales/zh-TW/app.json               |  30 ++++-
 30 files changed, 789 insertions(+), 157 deletions(-)

Fusion-Task-Id: FN-7820

Fusion-Task-Lineage: d33c5678-a68c-4b29-9db1-8ff0369dfd72

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
0a90dc4b55 FN-7821: refresh-then-recheck OAuth credentials before dispatching expiry notifications
Aligns OAuthExpiryMonitor's ntfy push notifications with the /api/auth/status refresh-then-recheck logic that drives the in-app OAuthReloginBanner, so providers that silently auto-refresh (e.g. GitHub Copilot's ephemeral token) no longer trigger false "OAuth token expired" pushes with no matching banner.

- OAuthExpiryMonitor.check() now performs a best-effort authStorage.getApiKey() refresh and reloads/re-resolves the credential before dispatching oauth-token-expired, instead of relying solely on the stored expiry timestamp
- resolveEffectiveOAuthCredential() now also guards against non-finite expires values in addition to non-numeric ones
- Updated docs/dashboard-guide.md and docs/settings-reference.md to describe the refresh-then-recheck behavior generically (not just Claude/Anthropic) and documented the FN-7821 fix in FNXC provenance comments
- Added regression tests covering the refresh-then-recheck flow in oauth-expiry-monitor.test.ts
- Added a patch changeset describing the fix for release notes

Files changed:
 .changeset/fn-7821-oauth-expiry-notification-banner-consistency.md               |   7 +
 docs/dashboard-guide.md                                                          |   6 +-
 docs/settings-reference.md                                                       |   6 +-
 packages/engine/src/notification/__tests__/oauth-expiry-monitor.test.ts          | 146 ++++++++++++++++++++-
 packages/engine/src/notification/oauth-expiry-monitor.ts                         |  48 ++++++-
 5 files changed, 199 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-7821

Fusion-Task-Lineage: 5954592c-adda-4fd4-b205-265860eddf3d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
3da9da28f3 FN-7818: replace placeholder Cursor icon with official brand mark
Swap the hand-drawn Cursor CLI placeholder SVG for Cursor's official cube/arrow brand mark and ensure model-id-shaped provider strings resolve to it.

- Replace CursorCliIcon's placeholder rounded-square+badge SVG with Cursor's official cube/arrow brand mark path data
- Add cursor -> cursor-cli mapping in inferProviderIconKey so cursor, cursor-agent, and cursor/<model> strings resolve to the branded icon instead of falling through to the generic CPU icon
- Update ProviderIcon and providerIconKey tests to cover the new brand mark paths and provider-string inference
- Add a patch changeset documenting the fix

Files changed:
 .changeset/fn-7818-cursor-logo.md                  |  7 +++++
 packages/dashboard/app/components/ProviderIcon.tsx | 33 +++++++++++-----------
 .../app/components/__tests__/ProviderIcon.test.tsx | 12 ++++++--
 .../app/utils/__tests__/providerIconKey.test.ts    |  4 +++
 packages/dashboard/app/utils/providerIconKey.ts    |  8 ++++++
 5 files changed, 44 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-7818

Fusion-Task-Lineage: 73e85e18-e98a-4dc3-b89d-f831525620de

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:07:00 -07:00
gsxdsm
a2c9b0fd52 FN-7817: Simplify Cursor usage credential to a single documented CURSOR_API_KEY path
Consolidates Cursor Admin API key resolution onto one documented env var so the usage/admin credential path is reachable and unambiguous, replacing the prior dual CURSOR_ADMIN_API_KEY/CURSOR_API_KEY and multi-provider-id lookup.

- Replace CURSOR_ADMIN_API_KEY (preferred) + CURSOR_API_KEY alias with a single CURSOR_API_KEY env var, mirroring the GROK_API_KEY precedent
- Simplify readCursorApiKey to check CURSOR_API_KEY then fall back to the single "cursor" authStorage entry via readConfiguredApiKey (drop the cursor/cursor-cli/cursor-agent provider-id loop)
- Export readCursorApiKey and fetchCursorUsage for direct test coverage
- Update the no-auth error message and settings-reference.md docs to reference only CURSOR_API_KEY, clarifying cursor-cli OAuth/session auth vs the separate Admin API usage-metering credential
- Add changeset (@runfusion/fusion: minor) documenting the credential-path change
- Add/adjust usage.test.ts coverage for readCursorApiKey precedence (env over authStorage) and the updated credential-absent error message

Files changed:
 .changeset/fn-7817-cursor-api-key.md           |  7 ++++
 docs/settings-reference.md                     |  8 ++--
 packages/dashboard/src/__tests__/usage.test.ts | 53 +++++++++++++++++++++++++-
 packages/dashboard/src/usage.ts                | 52 ++++++++-----------------
 4 files changed, 77 insertions(+), 43 deletions(-)

Fusion-Task-Id: FN-7817

Fusion-Task-Lineage: 86ac3d47-8e80-4159-abee-6c41aae56407

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:06:59 -07:00
gsxdsm
d40f24d20a FN-7816: add Cursor usage card to the Usage activity dropdown
Adds a Cursor provider fetcher to the dashboard usage aggregator so operators with a Cursor Admin API key see spend-based usage alongside the other providers.

- usage.ts: add fetchCursorUsage() using the Cursor Admin API POST https://api.cursor.com/teams/spend with Basic auth (API key as username), resolving the key from CURSOR_ADMIN_API_KEY (preferred) or CURSOR_API_KEY, falling back to fusion-auth/pi-configured api keys; maps teamMemberSpend overallSpendCents/spendCents and hardLimitOverrideDollars/monthlyLimitDollars into a "Monthly spend" usage window with a reset derived from subscriptionCycleStart
- usage.ts: wire fetchCursorUsage into fetchAllProviderUsage's parallel provider fetch list (with withTimeout + no-auth demotion) and update the provider-list comment
- UsageIndicator.tsx: map the "Cursor" provider name to the existing cursor-cli icon token/SVG
- usage.test.ts: add CURSOR_ADMIN_API_KEY/CURSOR_API_KEY env stubbing and a full fetchCursorUsage regression suite (ok/zero-utilization/no-auth/error/expired-key/parse-failure cases)
- UsageIndicator.test.tsx: cover the Cursor icon mapping
- docs/settings-reference.md: document that the Usage dropdown Cursor card requires a Cursor Admin API key (session-only cursor-agent login is insufficient)
- add a minor changeset for @runfusion/fusion documenting the new Cursor usage card

Files changed:
 .changeset/fn-7816-cursor-usage.md                 |   7 +
 docs/settings-reference.md                         |   4 +
 packages/dashboard/app/components/UsageIndicator.tsx |   7 +
 packages/dashboard/app/components/__tests__/UsageIndicator.test.tsx |  26 +++
 packages/dashboard/src/__tests__/usage.test.ts     | 157 ++++++++++++++
 packages/dashboard/src/usage.ts                    | 240 ++++++++++++++++++++-
 6 files changed, 440 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7816
Fusion-Task-Lineage: 4cec63d8-4ddc-40f3-8d16-5e4078da5eba
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 18:06:59 -07:00
gsxdsm
c12653e22c test(cli): add isInReviewMissingWorktreeSessionStartFailure mock + update docs screenshot list 2026-07-11 18:06:45 -07:00
gsxdsm
51d5f9a28f test: fix executor artifact-register assertion (FN-7790) + i18n versionShort parity 2026-07-11 18:06:45 -07:00
gsxdsm
4679c4960f Address PR review feedback (#2006)
- fix: fragments are hidden in the add-step dialog when the target edge is
  inside a foreach/loop/optional-group (they expand to top-level subgraphs
  and cannot splice into a template-child edge), and
  spliceInsertedSubgraphOnEdge now refuses container-internal edges as a
  second line of defense (Greptile P1 x2).
- test: add-step modal container-target hiding, multi-entry/exit splice
  fan-out, internal-cycle entries fallback, ambiguous merge-inbound
  lifecycle fallback, and edge-targeted "as optional group" wiring
  (CodeRabbit nitpicks).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
f6806f06cb feat: live lifecycle warning analysis with one-click Fix / Fix all
Lifecycle warnings now recompute client-side from the live graph for
editable workflows, so the banner reflects edits immediately instead of
waiting for a save round-trip. The two deterministically fixable codes gain
one-click fixes in the banner (all view modes):
- missing-merge-region inserts a Merge boundary in front of end;
- missing-completion-summary inserts the canonical completion-summary node
  (config from @fusion/core's completionSummaryNode) upstream of the merge
  region when one exists, else in front of end.
"Fix all" on the collapsed summary line applies both in order, producing
start → summary → merge → end on a fresh workflow in one click. The other
three codes are structural judgment calls and stay manual.

analyzeWorkflowLifecycle + completionSummaryNode are pure and now re-export
through core's browser-safe types.ts alias entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
72a98aed18 Address PR review feedback (#2006): lowercase currentcolor per stylelint value-keyword-case
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
d79e2d62af Address PR review feedback + compact lifecycle warnings banner (#2006)
- fix: edge-targeted fragment and "insert as optional group" picks from the
  add-step dialog now splice the inserted subgraph into the targeted edge
  (entries inherit the original routing condition, exits feed the old
  target, subgraph moves into the source's column band) instead of dropping
  disconnected fixed-position nodes (Greptile P1).
- feat: the lifecycle warnings banner is now a one-line collapsible
  disclosure (count summary, details on expand) so it no longer dominates
  the editor header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
a25cf9cfe3 docs: add simplified workflow view screenshots
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
68f4abc574 fix: remount simple canvas per workflow so fitView tracks the new graph
Switching or creating a workflow could leave the simplified canvas fitted to
the previous graph's bounds (an apparently empty canvas after New workflow).
Keying the canvas's ReactFlowProvider on the workflow id forces a fresh
measure + initial fitView per workflow; the in-place refit still handles
inserts/deletes within one workflow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
bcbd97cc1c feat: simplified workflow editor view with Simple/Advanced/List modes
Adds a simplified graphical node editor as the workflow editor's default
view: a modern vertical auto-laid-out React Flow canvas with insert-on-edge
"+" affordances and a searchable, categorized add-step dialog (node kinds +
fragments + step templates). A segmented Simple/Advanced/List switch
(persisted in localStorage) keeps the full advanced canvas untouched and
retains the old compact row editor as the List fallback. Mobile's graph tab
gains the touch-friendly simplified canvas with the row list as fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:06:22 -07:00
gsxdsm
28ad1fd5f3 Address PR review feedback (#2003)
- parseInsightsContent: only top-level bullets (column 0 on the raw line) start
  a new insight; indented sub-bullets stay inside their parent insight with
  indentation preserved, so counts no longer inflate
- regression test for indented sub-bullets

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:16:49 -07:00
gsxdsm
690a49f8da docs: add post-review-fix insights screenshot for PR #2003
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:16:49 -07:00
gsxdsm
d44da531ff Address PR review feedback (#2003)
- parseInsightsContent: append continuation lines to the previous bullet so
  multiline insights render in full instead of truncating after the first line
- .memory-insight-item: white-space: pre-wrap so continuation breaks display
- regression tests for per-bullet parsing, counts, and multiline continuations

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:16:49 -07:00
gsxdsm
1d2d73ba5c fix(memory): fix insights parsing + modernize Memory, Insights, Todos, and agent Memory UI
- parseInsightsContent stripped bullet prefixes before filtering for them, so every
  insights category rendered as one blob and counts were wrong (5 shown vs 84 real)
- drop dead GET /memory and GET /memory/stats mount fetches from useMemoryData and
  stop refetching the file list on every file selection
- Memory view: full-width layout, accent tabs, 2-column Engines card grid, remove
  duplicated capability badges, correct spacing-token-as-font-size rules
- Todos: single-row items with quiet inline action cluster (stacked on narrow/mobile)
- Insights: flat card list (no card-in-card), 28px/16px actions muted until hover
- Agent Memory tab: shared FileEditor (CodeMirror) for memory files, per-section save
  actions, distinct inline-toggle aria-labels, fix {{date}} i18n interpolation
- PR screenshots under docs/assets/memory-ui-review-2026-07/

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:16:49 -07:00
Phil Larson
7f418b7d10 fix(missions): clear terminal fix task links 2026-07-11 17:04:22 -07:00
Phil Larson
6ee86c5db7 fix(missions): address lifecycle review blockers 2026-07-11 17:04:22 -07:00
Phil Larson
c68b053162 fix(missions): reconcile lifecycle invariants 2026-07-11 17:04:22 -07:00
gsxdsm
11fce4e4bb docs(settings): refresh complete screenshot coverage 2026-07-11 17:03:36 -07:00
gsxdsm
3daf29d5dd docs(settings): capture advanced disclosure matrix 2026-07-11 17:03:36 -07:00
gsxdsm
9b22927f3c feat(settings): simplify section details and layout 2026-07-11 17:03:36 -07:00
gsxdsm
19055c6c0e feat(settings): simplify advanced controls 2026-07-11 17:03:36 -07:00
gsxdsm
bf300f3336 test(FN-7811): align document view tests after rebase
Fusion-Task-Id: FN-7811
2026-07-11 00:03:14 -07:00
gsxdsm
6317fcddb5 FN-7813: add embedded worktree-rooted multi-tab Terminal to Task Detail
Add an interactive, worktree-rooted, multi-tab Terminal tab to the Task Detail
view, distinct from the pre-existing CLI-agent Session tab.

- TaskDetailModal gains a new embedded Terminal tab (single non-workspace
  task with one recorded worktree) that mounts TerminalModal in a new
  `embedded` render mode, rooted at the task's worktree
- Rename the existing agent-session tab label to "Session" to disambiguate
  it from the new Terminal tab
- useTerminalSessions gains task-scoped session storage and a `defaultCwd`
  option so embedded terminal tabs persist separately from footer/global
  project terminal tabs and start in the task worktree
- TerminalModal/CSS updated to support the embedded layout mode
- Update lazy-loaded-views docs test and AGENTS.md exclusion list to cover
  the new `LazyTerminalModal` task-detail-internal surface
- Document the new Session/Terminal tab split in docs/dashboard-guide.md
- Add i18n strings for the new Terminal tab across all locales
- Add a changeset (minor) for @runfusion/fusion

Files changed:
 .changeset/FN-7813-worktree-terminal-tab.md        |   7 +
 AGENTS.md                                          |   2 +-
 docs/dashboard-guide.md                            |   3 +
 .../app/__tests__/lazy-loaded-views-docs.test.ts   |   4 +-
 .../dashboard/app/components/TaskDetailModal.css   |  17 +++
 .../dashboard/app/components/TaskDetailModal.tsx   |  41 +++++-
 .../dashboard/app/components/TerminalModal.css     |  51 +++++++
 .../dashboard/app/components/TerminalModal.tsx     |  71 +++++++---
 .../__tests__/TaskDetailModal.test-helpers.ts      |   3 +
 .../TaskDetailModal.worktree-terminal.test.tsx     | 139 ++++++++++++++++++
 .../components/__tests__/TerminalModal.test.tsx    |  29 ++++
 .../hooks/__tests__/useTerminalSessions.test.ts    | 157 +++++++++++++++++++++
 .../dashboard/app/hooks/useTerminalSessions.ts     |  63 ++++++---
 packages/i18n/locales/en/app.json                  |   3 +-
 packages/i18n/locales/es/app.json                  |   3 +-
 packages/i18n/locales/fr/app.json                  |   3 +-
 packages/i18n/locales/ko/app.json                  |   3 +-
 packages/i18n/locales/zh-CN/app.json               |   3 +-
 packages/i18n/locales/zh-TW/app.json               |   3 +-
 19 files changed, 550 insertions(+), 55 deletions(-)

Fusion-Task-Id: FN-7813

Fusion-Task-Lineage: 4ef86a15-347a-4862-b01c-5063d8004cb8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 00:01:10 -07:00
gsxdsm
bd0e99b31f FN-7814: add xAI/Grok usage card to the Usage dropdown
Adds a Grok (xAI) provider fetcher to the dashboard's usage aggregation so a Grok card now appears in the Usage dropdown when credentials are configured.
- Add fetchGrokUsage() in usage.ts: resolves the API key from GROK_API_KEY env, then ~/.grok/user-settings.json, then grok-cli auth storage, and validates it against GET https://api.x.ai/v1/api-key
- Since xAI exposes no subscription usage meter for inference keys, the card reports auth-validity status (ok/no-auth/error) with an empty usage-window list rather than fabricating quota data
- Surfaces clear error messages for expired/blocked keys and non-200 responses; omits the card entirely when no credentials are found
- Register fetchGrokUsage in fetchAllProviderUsage's parallel provider fetch list alongside Claude, Codex, Gemini, Minimax, Zai, and GitHub Copilot
- Add extensive test coverage in usage.test.ts for key-source precedence, ok/error/no-auth states, and blocked/expired key handling
- Add changeset (.changeset/fn-7814-grok-usage.md) documenting the new minor feature

Files changed:
 .changeset/fn-7814-grok-usage.md               |   7 ++
 packages/dashboard/src/__tests__/usage.test.ts | 157 +++++++++++++++++++++++++
 packages/dashboard/src/usage.ts                |  95 ++++++++++++++-
 3 files changed, 257 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-7814

Fusion-Task-Lineage: cac497a9-5a57-4ba5-a7ea-8a01b89a0cbd

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 00:01:10 -07:00
gsxdsm
56b20a76af FN-7812: extend select-to-comment popover to Task Documents right pane
Adds select-to-comment parity to the Task Documents right pane in the Artifacts view, reusing the existing Project Files selection-comment pattern (useSelectionComment/SelectionCommentPopover) so operators can highlight task-document content and send it to a new task.

- Add markdown/plain preview refs and useSelectionComment hooks scoped to the selected Task Document, following the existing Plain/Markdown render toggle
- Gate the Task Documents selection popover on activeTab === "tasks" and the selected task document (separate from the Project Files popover, which stays gated on activeTab === "project") so tab switches never cross-render popovers
- Compose the New Task description source as `taskId/key` for task-document selections, mirroring the file-path convention used for Project Files
- Add regression tests covering plain/markdown task-document selection, empty-pane gating, tab isolation between Task Documents and Project Files popovers, and the mobile detail pane
- Update dashboard-guide.md to document select-to-comment support for Task Documents alongside Project Files
- Add a minor changeset for @runfusion/fusion documenting the feature (depends on FN-7811)

Files changed:
 .changeset/fn-7812-task-documents-select-to-comment.md            |  7 ++
 docs/dashboard-guide.md                                           |  4 +-
 packages/dashboard/app/components/DocumentsView.tsx                | 37 ++++++---
 packages/dashboard/app/components/__tests__/DocumentsView.test.tsx | 93 ++++++++++++++++++++++
 4 files changed, 130 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-7812

Fusion-Task-Lineage: ace10d70-35fd-42fe-8a4a-e2c2c7c7c27b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 00:01:10 -07:00
gsxdsm
595d323ce6 FN-7811: convert Task Documents tab to left-sidebar list + right-pane viewer
Reworks the Artifacts view's Task Documents tab to reuse the Project Files left-sidebar/right-pane layout instead of expandable task-grouped cards, giving both tabs a consistent browsing pattern.

- Replace the collapsible TaskGroup/DocumentCard components with a documents-project-layout sidebar listing documents grouped by task (with revision metadata and task status badges) and a right pane rendering the selected document's content
- Add separate selectedTaskDocumentId selection state so tab switching never leaks Project Files content into Task Documents (and vice versa), with desktop/mobile gating matching the Project Files pattern
- Preserve the existing Plain/Markdown render toggle for task document content; select-to-comment stays Project-Files-only for this change (tracked as follow-up)
- Update DocumentsView.css for the new sidebar/right-pane structure and rewrite DocumentsView.test.tsx coverage for the new interaction model
- Update docs/dashboard-guide.md to describe the shared sidebar/right-pane browsing pattern for Task Documents
- Add changeset fn-7811-task-documents-sidebar.md (minor)

Files changed:
 .changeset/fn-7811-task-documents-sidebar.md       |   7 +
 docs/dashboard-guide.md                            |   4 +-
 .../dashboard/app/components/DocumentsView.css     | 181 ++++--------
 .../dashboard/app/components/DocumentsView.tsx     | 308 ++++++++++-----------
 .../components/__tests__/DocumentsView.test.tsx    | 116 ++++++--
 5 files changed, 299 insertions(+), 317 deletions(-)

Fusion-Task-Id: FN-7811

Fusion-Task-Lineage: e943ebf8-6e8e-4f5f-a55c-99c949be2624

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-11 00:01:10 -07:00
gsxdsm
281d1a3371 FN-7809: collapse List view to single-pane layout on tablet-narrow widths
Fixes the List view's two-pane split layout clipping primary controls and the
expanded quick-add composer on tablet-width viewports (769-1024px) by
switching those widths to the same single-pane card/detail layout already
used on mobile.

- Add `useSinglePaneList` gate in ListView.tsx (`viewportMode === "mobile" || "tablet"`) driving split-vs-single-pane structure, detail routing, and resize-handle wiring, while touch-only long-press behavior stays on `isMobile`.
- Extend the mobile-only responsive CSS breakpoints in ListView.css from `max-width: 768px` to `max-width: 1024px` so tablet gets the same toolbar/card scaffolding as mobile, while desktop split rules remain unchanged above that tier.
- Add `list-view--single-pane` root class and route tablet clicks through the single-pane `onOpenDetail` path instead of the desktop split-pane selection.
- Update docs/dashboard-guide.md to describe the tablet single-pane behavior and add an FNXC:ListView comment recording the FN-7809 rationale.
- Add regression tests covering tablet single-pane rendering, tablet detail-open routing, and updated CSS-fixture assertions for the widened breakpoint.
- Add a patch changeset describing the fix for @runfusion/fusion release notes.

Files changed:
 .changeset/fn-7809-list-tablet-single-pane.md      |  7 +++
 docs/dashboard-guide.md                            |  6 +-
 packages/dashboard/app/components/ListView.css     | 11 ++--
 packages/dashboard/app/components/ListView.tsx     | 49 ++++++++-------
 .../app/components/__tests__/ListView.test.tsx     | 69 +++++++++++++++++++++-
 5 files changed, 112 insertions(+), 30 deletions(-)

Fusion-Task-Id: FN-7809
Fusion-Task-Lineage: 9e5f8bb7-13ee-4a58-81b1-eb5a9911bd4e
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 23:57:59 -07:00
gsxdsm
c530b238b4 FN-7810: fix stale-echo detection to preserve trailing newline edits in FileEditor
Replace the FileEditor's bounded self-echo Set with monotonic edit versions so trailing-newline edits (e.g. after a markdown header or at end-of-file) are never dropped when an older content prop races the live CodeMirror document.

- Track a monotonic localEditVersionRef and a contentEditVersionsRef map (content -> version) instead of a size-capped Set of echoed strings, avoiding eviction of stale values during long editing sessions.
- Compare a stale prop's known edit version against the live document's version and the last accepted prop version to decide if it is a stale self-echo, at any session length.
- Update FNXC:FileViewer comment to document the FN-7810 rationale for switching from bounded-Set self-echo detection to edit-version comparison.
- Add regression tests covering trailing markdown-header and plain-text newline edits across markdown/non-markdown file paths, and a long-session (20+ edit) case that previously could evict the self-echo tracking.

Files changed:
 packages/dashboard/app/components/FileEditor.tsx                | 32 +++++++----
 .../app/components/__tests__/FileEditor.test.tsx                 | 64 +++++++++++++++++++++-
 2 files changed, 83 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-7810
Fusion-Task-Lineage: 9dd68746-e772-4fa3-b648-6f3138d1e36e
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 23:57:59 -07:00
gsxdsm
e90a9c4f51 fix: auto-heal wedged SQLite connections in place instead of wedging until process restart
A long-lived connection can go SQLITE_NOTADB ('file is not a database' on
every query) while the on-disk file stays intact — observed 2026-07-10 on the
live dashboard, which then failed every API request and poll cycle until the
process was restarted, because all corruption recovery ran at open time only.

The sqlite adapter now detects connection-corruption errors, closes the dead
handle, reopens the same path, replays connection-scoped PRAGMAs, verifies
with quick_check, and retries the failed operation once when outside an
explicit transaction. Prepared statements are generation-tracked and
re-prepare transparently after a reopen; a lost transaction's unwind is
absorbed so the original error propagates cleanly. Reopens are rate-limited,
and real on-disk corruption still defers to the open-time recovery machinery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:57:59 -07:00
gsxdsm
7d29367bc5 fix(FN-7786): hide sub-cent partial costs
Fusion-Task-Id: FN-7786
2026-07-10 23:50:15 -07:00
gsxdsm
9bed076ab0 fix(FN-7786): handle mixed zero cost feedback
Fusion-Task-Id: FN-7786
2026-07-10 23:50:15 -07:00
gsxdsm
fbea66d0f2 fix(FN-7786): show partial Command Center costs
Fusion-Task-Id: FN-7786
2026-07-10 23:50:15 -07:00
Phil Larson
122e404494 docs: clarify overseer badge access paths 2026-07-10 23:47:55 -07:00
Phil Larson
42a606ab5c docs: address overseer badge review notes 2026-07-10 23:47:55 -07:00
Phil Larson
dbb29d449a docs: explain planner overseer eye badge 2026-07-10 23:47:55 -07:00
gsxdsm
8fa2ad0ecd Address PR review feedback (#1996)
- contain fn_artifact_register path payloads: realpath-canonicalized
  containment before stat/read — relative paths require and must stay
  inside baseDir, absolute paths allowed only under baseDir or the OS
  temp dir (deliberate allowance for browser/screenshot tooling);
  the process.cwd() fallback is gone, symlink escapes rejected
- bind task-scoped heartbeat artifact registration to the acquired
  worktree (baseDir: sessionCwd rebind after acquisition); no-task
  heartbeat prompt now says to pass absolute temp-dir paths
- enforce exactly-one payload source (content/uri/dataBase64/path);
  content+uri combos are now rejected to match the documented contract
- add FNXC rationale comments at both visual-artifact instruction sites
  in the planning prompts (sync contract with the executor prompt)
- media route: statSync -> await stat from node:fs/promises
- range tests ride the in-memory MockSocket harness (TestResponse gains
  binary-safe bodyBuffer; real-TCP helper deleted) and assert the full
  206 Content-Range/Content-Length contract for every range form
- add PdfViewer coverage (iframe src/title) in DocumentsView tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00
gsxdsm
324a794d62 feat: draggable/resizable artifact viewer windows, Artifacts-first landing tab, uniform mobile tabs
- artifact viewers (image/video lightbox, PDF viewer, doc viewer) now host in
  the shared FloatingWindow: draggable by the viewer header, resizable by
  edge/corner handles, geometry persisted per viewer kind, closed by button
  or Escape; FloatingWindow gains an ariaLabel prop so headerless windows
  keep an accessible dialog name
- the Artifacts view leads with the Artifacts tab and always lands on it;
  Project Files and Task Documents are secondary tabs (the old auto-select
  effect is gone)
- mobile tab buttons rendered at mismatched heights (two-line "Project
  Files"/"Task Documents" grew past 44px while one-line "Artifacts" stayed
  at 44px); tabs now pin to the uniform 44px control height with
  non-wrapping labels in a scrollable row

Verified live: window dragged (264,146 -> 144,164) and resized
(1024x720 -> 872x618) in a real browser; mobile 390x844 lands on Artifacts
with uniform tab buttons.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00
gsxdsm
a8eafbbb14 feat: video, HTML mockup, and PDF artifact support end-to-end
Video was registrable but effectively unusable, and HTML/PDF deliverables
had no first-class path from agents to the gallery.

- media route now serves HTTP byte ranges (Accept-Ranges, 206 +
  Content-Range, 416 on unsatisfiable) so <video>/<audio> seeking works
  and Safari plays media at all
- video attachments (mp4/webm/mov, 100MB cap vs 5MB for other types)
  bridge into the artifact registry like images; multer transport ceiling
  raised to 100MB with per-type caps enforced in the store
- fn_artifact_register path payloads are signature-validated for video
  (ftyp box / EBML header) and PDF (%PDF- prefix), mirroring images
- HTML doc artifacts (mimeType text/html) render as live sandboxed
  iframe previews by default in the doc viewer, with a Preview/Source
  toggle and the same FileEditor edit mode
- executor/heartbeat/planning prompts and tool descriptions now cover
  the full type matrix: images, videos, audio, HTML mockups, PDFs, and
  markdown docs, each with the registration recipe

Verified live: range requests (200/206/416) via curl, an ffmpeg-generated
mp4 playing to completion in the gallery lightbox, and an interactive
HTML mockup rendering in the sandboxed preview.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00