Commit Graph

2264 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
gsxdsm
9024f3a639 feat: agent-created visual artifacts end-to-end + redesigned category gallery with doc editing
Agents could never get screenshots/wireframes/mocks into the Artifacts view:
fn_artifact_register was gated on assignedAgentId (never set in default
ephemeral mode), the only image payload source was inline base64, and no
prompt ever told agents to register visual deliverables.

- always expose fn_artifact_register to executor sessions ("executor" author
  fallback), resolve relative paths against the task worktree, and default
  taskId to the executing task (heartbeat task lane too)
- add a `path` payload source: file read with 50MB cap, extension MIME
  inference, PNG/JPEG/GIF/WebP signature + SVG sniff validation, persisted
  through managed artifact storage
- executor/heartbeat/planning prompts + engine-tools reference now instruct
  agents to register screenshots, wireframes, mockups, and recordings
- new ArtifactsGallery: Images/Docs/PDFs/Videos/Audio/Other category sections
  and filter chips, visual tile grid + lightbox, embedded PDF viewer, audio
  player rows, download rows; mobile-responsive down to the 768px breakpoint
- doc artifacts open a full viewer rendered as markdown by default with an
  in-place edit mode using the shared CodeMirror FileEditor; persisted via new
  GET/PATCH /api/artifacts/:id + TaskStore.updateArtifact and live-refreshed
  through the new artifact:updated SSE event

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:42:10 -07:00
gsxdsm
21fb8f6786 FN-7802: recover phantom-worktree tasks stuck merge-active with scopeOverride
Fixes phantom-worktree context bleed where the engine refused to start a
coding agent in a missing worktree for in-review/merge-active tasks even
when scopeOverride=1, stranding them past the normal recovery paths and
retry budget.

- Add isMergeActiveMissingWorktreeSessionStartFailure/isInReviewMissingWorktreeSessionStartFailure classifiers and MERGE_ACTIVE_MISSING_WORKTREE_STATUSES (merging/merging-pr/merging-fix) in restart-recovery-coordinator.ts, exported from @fusion/engine.
- Self-healing: reorder missing-worktree-review-failures sweep earlier, extend the in-review sweep to also match merge-active missing-worktree failures with a triple-proof-guarded, bounded (recoveryRetryCount) stale-metadata clear and fresh session-start retry budget reset.
- Self-healing: extend scopeOverride worktree-metadata reconciliation to safely clear phantom worktree/branch/session metadata for in-review tasks stuck in a merge-active sub-status, narrowly scoped to avoid clobbering genuinely live in-progress/mid-step tasks (FN-5256 guard preserved).
- CLI (task.ts), pi extension (extension.ts), and dashboard route (register-task-workflow-routes.ts) retry paths now bypass the merge-active status gate via a signature-only check, clearing worktree/branch/sessionFile and requeuing to todo while preserving progress.
- Add regression coverage across self-healing.test.ts, restart-recovery-coordinator.test.ts, extension.test.ts, task-retry.test.ts, and routes-tasks-ops.test.ts; update mockCoreEngine.ts test scaffolding.
- Update docs/architecture.md, docs/self-healing-backward-move-audit.md, docs/task-management.md, and AGENTS.md to describe the new merge-active missing-worktree recovery behavior.
- Add changeset (patch) for @runfusion/fusion.

Files changed:
 .changeset/fn-7802-phantom-worktree-merge-active-recovery.md      |   7 +
 AGENTS.md                                                          |   1 +
 docs/architecture.md                                               |   4 +-
 docs/self-healing-backward-move-audit.md                           |   5 +-
 docs/task-management.md                                            |   2 +-
 packages/cli/src/__tests__/extension.test.ts                       |  64 +++++
 packages/cli/src/__tests__/task-retry.test.ts                      |  49 ++++
 packages/cli/src/commands/task.ts                                  |  28 +-
 packages/cli/src/extension.ts                                      |  26 +-
 packages/dashboard/src/__tests__/routes-tasks-ops.test.ts          |  52 ++++
 packages/dashboard/src/routes/register-task-workflow-routes.ts     |  25 +-
 packages/dashboard/src/test/mockCoreEngine.ts                      |  11 +
 packages/engine/src/__tests__/restart-recovery-coordinator.test.ts |  20 ++
 packages/engine/src/__tests__/self-healing.test.ts                 | 297 +++++++++++++++++++++
 packages/engine/src/index.ts                                       |  13 +
 packages/engine/src/restart-recovery-coordinator.ts                |  19 +-
 packages/engine/src/self-healing.ts                                | 157 +++++++++--
 17 files changed, 744 insertions(+), 36 deletions(-)

Fusion-Task-Id: FN-7802

Fusion-Task-Lineage: 5897105b-6b5c-49d5-a8e8-519902182861

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 22:25:21 -07:00
gsxdsm
60b8b4e4c5 FN-7805: redesign quick-add priority indicators as icon-only controls
Redesigns the Quick Add composer's priority selector to icon-only glyph buttons and relocates GitHub tracking beside attach, backed by a new shared priorityIndicator helper.

- Add packages/dashboard/app/utils/priorityIndicator.tsx as the single source of ArrowUp/ArrowDown/Flag/TriangleAlert priority glyphs, shared by QuickEntryBox and TaskForm
- Rework QuickEntryBox.tsx to render icon-only priority/Fast controls and move GitHub tracking + Priority into the .quick-entry-primary-group, with matching QuickEntryBox.css layout updates
- Update TaskForm.tsx to reuse the new priorityIndicator helper instead of duplicating icon/label logic
- Update quick-entry height-parity/trigger-height tests and QuickEntryBox/TaskForm/NewTaskModal tests for the new icon-only layout
- Add priorityIndicator.test.tsx covering the shared helper
- Update docs/dashboard-guide.md and add changeset fn-7805-quick-add-priority-indicators.md (patch, feature)

Files changed:
 .../fn-7805-quick-add-priority-indicators.md       |   7 +
 docs/dashboard-guide.md                            |   3 +-
 .../quick-entry-action-row-height-parity.test.tsx  |  13 +-
 .../quick-entry-workflow-trigger-height.test.tsx   |  10 +-
 .../dashboard/app/components/QuickEntryBox.css     |  19 +-
 .../dashboard/app/components/QuickEntryBox.tsx     | 197 +++++++++++----------
 packages/dashboard/app/components/TaskForm.tsx     |  33 ++--
 .../app/components/__tests__/NewTaskModal.test.tsx |   3 +
 .../components/__tests__/QuickEntryBox.test.tsx    | 113 ++++++++----
 .../app/components/__tests__/TaskForm.test.tsx     |   3 +
 .../app/utils/__tests__/priorityIndicator.test.tsx |  21 +++
 packages/dashboard/app/utils/priorityIndicator.tsx |  30 ++++
 12 files changed, 300 insertions(+), 152 deletions(-)

Fusion-Task-Id: FN-7805

Fusion-Task-Lineage: 404fe8d6-0851-44cb-b31d-f47896aaaaba

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 22:25:21 -07:00
gsxdsm
725ce45c5d FN-7799: fix false-negative Git repository detection blocking task execution
Replace the boolean isGitRepository() check with a tri-state Git detection so environmental git failures (dubious ownership, missing git binary, timeouts) are no longer misreported as "not a Git repository", which previously blocked all task execution in valid repos and survived engine restarts.

- Add detectGitRepository() in worktree-pool.ts returning repo / not-repo / error (with reason: dubious-ownership, git-missing, timeout, unknown), classified from git's stderr; bound the git rev-parse call with a 10s timeout and maxBuffer; keep isGitRepository() as a backward-compatible wrapper
- Route the executor dispatch preflight guard through detectGitRepository(): only emit the original "not a Git repository / run git init" fatal on a positive not-repo verdict; on error, throw a distinct accurate error naming the real git failure, including the safe.directory remedy for dubious ownership
- Route the in-process runtime startup warning through the same tri-state detection so it only warns "not a Git repository" on a positive not-repo verdict
- Add a regression test locking extractWorktreeConflictInfo() to NOT misclassify a dubious-ownership git worktree add failure as not-git-repo
- Add targeted tests across worktree-pool, executor-worktree, and in-process-runtime test suites covering repo/not-repo/dubious-ownership/git-missing/timeout classifications on Windows OneDrive-style and POSIX paths
- Add changeset and a docs/solutions/logic-errors write-up of the false-negative root cause and fix

Files changed:
 .changeset/fn-7799-git-detection-false-negative.md |  7 +++
 .../logic-errors/git-detection-false-not-repo.md   | 54 ++++++++++++++++
 .../engine/src/__tests__/executor-worktree.test.ts | 61 +++++++++++++++++++
 .../engine/src/__tests__/worktree-pool.test.ts     | 71 +++++++++++++++++++---
 packages/engine/src/executor.ts                    | 38 +++++++++---
 .../runtimes/__tests__/in-process-runtime.test.ts  | 53 ++++++++++++++--
 packages/engine/src/runtimes/in-process-runtime.ts | 16 ++++-
 packages/engine/src/worktree-pool.ts               | 66 ++++++++++++++++++--
 8 files changed, 334 insertions(+), 32 deletions(-)

Fusion-Task-Id: FN-7799
Fusion-Task-Lineage: 25a84283-bf47-472b-8a98-a10bf7e494de
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 21:19:22 -07:00
gsxdsm
c258fc1590 FN-7796: switch Grok CLI headless prompts to the reliable single-object JSON output
Narrative: the streaming-json headless contract intermittently emitted only thought events then stopReason:Cancelled with zero text, leaving Chat replies silently empty; the adapter now spawns grok with --output-format json, buffers stdout, and parses the single JSON response on process close, with streaming-json parsing kept only as a diagnostic fallback.

- Change grok CLI invocation from --output-format streaming-json to --output-format json (cli-stream.ts)
- Add GrokCliJsonResponse type ({text, stopReason, sessionId, requestId, thought}) and parseJsonOutput() to stream-parser.ts, keeping legacy NDJSON line parsing for fallback/diagnostics
- Rework runtime-adapter.ts to buffer full stdout, parse it via parsePromptOutput (JSON object first, NDJSON fallback), and surface a formatTerminalNoTextDiagnostic when a non-EndTurn stopReason yields no assistant text
- Rename first-line/inactivity timeout bookkeeping from line-based to output/chunk-based (FIRST_OUTPUT_TIMEOUT_MS, firstOutputReceived, firstStdoutChunk) since stdout is no longer consumed via readline
- Update cli-stream/runtime-adapter/stream-parser tests to cover the JSON response path and the Cancelled/no-text diagnostic
- Update docs/grok-cli-contract.md and plugin README to document the json output-format contract and diagnostics
- Add changeset fn-7796-grok-cli-reliable-headless.md (patch, fix)

Files changed:
 .changeset/fn-7796-grok-cli-reliable-headless.md   |   7 +
 docs/grok-cli-contract.md                          | 108 ++++++++-----
 plugins/fusion-plugin-grok-runtime/README.md       |  16 +-
 .../src/__tests__/cli-stream.test.ts               |   4 +-
 .../src/__tests__/runtime-adapter.test.ts          |  73 ++++++++-
 .../src/__tests__/stream-parser.test.ts            |  80 +++++----
 .../fusion-plugin-grok-runtime/src/cli-stream.ts   |  14 +-
 .../src/runtime-adapter.ts                         | 180 ++++++++++++---------
 .../src/stream-parser.ts                           |  65 ++++++--
 plugins/fusion-plugin-grok-runtime/src/types.ts    |  13 +-
 10 files changed, 373 insertions(+), 187 deletions(-)

Fusion-Task-Id: FN-7796

Fusion-Task-Lineage: c920fcf0-98f8-42ec-867a-7f76c0aca1b7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 12:57:41 -07:00
gsxdsm
3d5cc0ada4 FN-7795: add thinking-level selectors to fallback model pickers
Adds a per-lane thinking-level selector to every fallback model picker across global, project, and workflow Settings surfaces, wiring them into the existing null-as-delete save paths.

- Add inline thinking-level dropdowns to the global Fallback Model, workflow-declared planning/validator fallback lanes, and the project-scoped Title Summarizer fallback picker via CustomModelDropdown's `showThinkingLevel`.
- Route `planningFallbackThinkingLevel`/`validatorFallbackThinkingLevel` through workflow settings PATCH and `titleSummarizerFallbackThinkingLevel` through project settings save-split, both with null-as-delete semantics on reset.
- Move Title Summarizer fallback out of the workflow-declared model pairs into a dedicated project-scoped lane in ProjectModelsSection so its thinking companion isn't tied to workflow settings.
- Update WorkflowSettingsPanel to surface the new fallback thinking companion keys.
- Extend/adjust tests (settings-save-split, settings-sections, SettingsModal.models-auth, WorkflowSettingsPanel, core settings-migration) to cover the new selectors and save routing.
- Document the fallback thinking-level runtime behavior in docs/settings-reference.md and docs/dashboard-guide.md.
- Add a minor changeset describing the new fallback thinking-level selectors.

Files changed:
 .changeset/fn-7795-fallback-thinking-selectors.md  |   7 +
 docs/dashboard-guide.md                            |   4 +-
 docs/settings-reference.md                         |  10 +-
 packages/core/src/__tests__/settings-migration.test.ts  |  14 +-
 packages/dashboard/app/__tests__/settings-save-split.test.ts      |  35 +++++
 packages/dashboard/app/__tests__/settings-sections.test.tsx       | 163 ++++++++++++++++++++-
 packages/dashboard/app/components/WorkflowSettingsPanel.tsx       |   6 +-
 packages/dashboard/app/components/__tests__/SettingsModal.models-auth.test.tsx   |  11 +-
 packages/dashboard/app/components/__tests__/WorkflowSettingsPanel.test.tsx       |  38 +++++
 packages/dashboard/app/components/settings/save-split.ts          |   9 +-
 packages/dashboard/app/components/settings/sections/GlobalModelsSection.tsx      |   8 +-
 packages/dashboard/app/components/settings/sections/ProjectModelsSection.tsx     |  58 ++++++--
 12 files changed, 328 insertions(+), 35 deletions(-)

Fusion-Task-Id: FN-7795

Fusion-Task-Lineage: ec990d47-defe-4717-993a-56988afe8d7d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 12:02:46 -07:00
gsxdsm
fc4acd4d66 FN-7794: apply fallback model's own thinking level when swapping in at runtime
Adds fallbackThinkingLevel plumbing so, when Fusion swaps from a primary model to a configured fallback model (executor, validator/reviewer, merger, planning, title-summarizer, heartbeat, and workflow-step lanes), the fallback's own configured thinking level is applied instead of silently reusing the primary lane's level.

- Add fallbackThinkingLevel option to AgentRuntimeOptions (agent-runtime.ts), AgentOptions (pi.ts), and ReviewOptions (reviewer.ts)
- Add per-lane resolvers: resolveExecutorFallbackThinkingLevel, resolvePlanningFallbackThinkingLevel, resolveValidatorFallbackThinkingLevel, resolveTitleSummarizerFallbackThinkingLevel, resolveMergerFallbackThinkingLevel (agent-session-helpers.ts), each following fallback-provider precedence and falling back to the primary lane/default thinking level when unset
- Export new resolvers from packages/engine/src/index.ts
- Apply the resolved fallback thinking level in createFnAgent's applyThinkingLevelIfSupported once a session has swapped to the fallback model (pi.ts)
- Wire fallbackThinkingLevel through executor session creation (workflow-step, task validator, child-agent, and main executor session paths), merger session creation, and heartbeat session creation
- Promote the fallback thinking level alongside the fallback model/provider when the no-visible-key Grok CLI fallback is promoted to primary, so the cleared fallback pair doesn't leave the session on the superseded primary's thinking level
- Route workflow-step fallback thinking level by which fallback candidate (validatorFallback vs globalFallback) actually matched
- Document fallbackThinkingLevel runtime-swap behavior in docs/settings-reference.md
- Add minor changeset for @runfusion/fusion
- Add regression tests covering fallback thinking-level resolution and application (agent-session-helpers.test.ts, pi.test.ts) and a shared test helper (executor-test-helpers.ts)

Files changed:
 .changeset/fn-7794-fallback-thinking-level.md      |   7 ++
 docs/settings-reference.md                         |   3 +
 .../src/__tests__/agent-session-helpers.test.ts    |  38 ++++++
 .../engine/src/__tests__/executor-test-helpers.ts  |  23 ++++
 packages/engine/src/__tests__/pi.test.ts           | 136 +++++++++++++++++++++
 packages/engine/src/agent-heartbeat.ts             |   3 +-
 packages/engine/src/agent-runtime.ts               |   5 +
 packages/engine/src/agent-session-helpers.ts       |  54 ++++++++
 packages/engine/src/executor.ts                    |  31 ++++-
 packages/engine/src/index.ts                       |   5 +
 packages/engine/src/merger.ts                      |   7 +-
 packages/engine/src/pi.ts                          |  16 ++-
 packages/engine/src/reviewer.ts                    |   6 +
 13 files changed, 327 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7794

Fusion-Task-Lineage: c94d621a-ccbd-42b2-9fe6-cb619418ad90

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 11:53:07 -07:00
gsxdsm
de67b57517 FN-7791: bridge image task attachments into the artifact registry
Image attachments added via TaskStore.addAttachment now surface as first-class image artifacts, reusing the existing artifact listing/SSE/media pipeline instead of duplicating bytes.

- addAttachment() registers a URI-only "image" artifact (metadata.source: "attachment") pointing at the already-written attachments/<file> path whenever an image mimeType is attached; registration is best-effort and swallows the archived/soft-deleted-task rejection so addAttachment keeps its always-succeeds contract for valid images.
- deleteAttachment() now removes any bridged artifact rows for a filename before deleting the attachment file, so /api/artifacts/:id/media can never point at a deleted attachment.
- register-task-workflow-routes.ts's resolveArtifactMediaPath now accepts task-scoped attachments/<file> URIs (in addition to artifacts/<file>) so the media route can stream bridged image-attachment artifacts; task-less artifacts remain restricted to .fusion/artifacts/.
- docs/storage.md documents the attachment→artifact bridge behavior and the media route's accepted URI prefixes.
- Added a changeset (@runfusion/fusion: minor) describing the user-facing Artifacts view change.
- Extended store-attachments and artifacts-route-integration tests to cover the new bridging and deletion behavior.

Files changed:
 .changeset/fn-7791-image-attachments-artifacts.md  |  7 +++
 docs/storage.md                                    |  3 +-
 packages/core/src/__tests__/store-attachments.test.ts   | 59 +++++++++++++++++++++-
 packages/core/src/store.ts                         | 58 ++++++++++++++++++++-
 packages/dashboard/src/routes/__tests__/artifacts-route-integration.test.ts  | 40 +++++++++++++++
 packages/dashboard/src/routes/register-task-workflow-routes.ts    |  9 +++-
 6 files changed, 172 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7791

Fusion-Task-Lineage: 4df47880-6161-4a8b-933a-2f6fc2fed953

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 11:30:21 -07:00
gsxdsm
84fb5138fc FN-7793: add fallback-lane thinking-level settings foundation
Adds the schema/storage foundation for per-fallback-lane thinking-level settings, without any runtime or UI consumption yet.

- Add global `fallbackThinkingLevel` default settings key.
- Add workflow-declared `planningFallbackThinkingLevel` and `validatorFallbackThinkingLevel` companion settings (enum-validated against THINKING_LEVELS) alongside their existing fallback provider/model pairs.
- Add project-scoped `titleSummarizerFallbackThinkingLevel` default settings key.
- Extend `GlobalSettings`/`ProjectSettings` TypeScript interfaces with the new optional `ThinkingLevel` fields and FNXC documentation comments.
- Update settings-schema `MovedProjectSettingsKey` type to include the new workflow-moved thinking-level keys.
- Update `docs/settings-reference.md` and `docs/storage.md` to document the new keys and correct workflow-vs-project scope for the pre-existing planning/validator fallback provider/model keys.
- Extend `effective-settings-overlay` and `settings-parity` unit tests to cover the new keys' scope and inheritance behavior.
- Add changeset `.changeset/fallback-thinking-levels.md` (minor).

Files changed:
 .changeset/fallback-thinking-levels.md             |  7 +++++++
 docs/settings-reference.md                         |  4 ++++
 docs/storage.md                                    | 12 +++++++----
 .../__tests__/effective-settings-overlay.test.ts   |  6 ++++++
 .../core/src/__tests__/settings-parity.test.ts     | 10 ++++++++++
 packages/core/src/builtin-workflow-settings.ts     | 23 +++++++++++++++++++++-
 packages/core/src/settings-schema.ts               | 10 +++++++++-
 packages/core/src/types.ts                         | 12 +++++++++++
 8 files changed, 78 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7793
Fusion-Task-Lineage: 0e4bac3e-01d2-4d17-9f0a-af87e8a66eee
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 11:26:16 -07:00
gsxdsm
db9b9d22c4 FN-7790: align grok CLI runtime adapter with real xAI grok CLI contract
Align the Grok CLI runtime plugin adapter with the real xAI grok CLI stream contract so tool responses are no longer silently dropped, and update tests/docs to match.

- Rework stream-parser.ts to parse the actual grok CLI event/message shape instead of the previously assumed schema
- Trim runtime-adapter.ts and types.ts down to the fields the real CLI contract emits, removing speculative/unsupported fields
- Update cli-stream.ts to match the corrected event handling
- Rewrite runtime-adapter, stream-parser, and cli-stream test suites to exercise the real CLI contract end-to-end
- Update docs/grok-cli-contract.md and plugin README to document the verified contract
- Add changeset for the grok-runtime plugin fix

Files changed:
 .changeset/fn-7790-grok-cli-real-contract.md       |   7 +
 docs/grok-cli-contract.md                          | 432 +++++++--------------
 plugins/fusion-plugin-grok-runtime/README.md       | 149 ++-----
 .../src/__tests__/cli-stream.test.ts               |  22 +-
 .../src/__tests__/runtime-adapter.test.ts          | 250 ++++--------
 .../src/__tests__/stream-parser.test.ts            | 108 ++----
 .../fusion-plugin-grok-runtime/src/cli-stream.ts   |  22 +-
 .../src/runtime-adapter.ts                         | 109 ++----
 .../src/stream-parser.ts                           |  27 +-
 plugins/fusion-plugin-grok-runtime/src/types.ts    | 104 +----
 10 files changed, 338 insertions(+), 892 deletions(-)

Fusion-Task-Id: FN-7790

Fusion-Task-Lineage: 377e86c4-c005-46a5-9eb4-69e858c38b79

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 10:57:04 -07:00
gsxdsm
d80cdd2b3b FN-7787: honor assigned agent's runtimeConfig model in task execution sessions
Task execution sessions previously ignored the assigned permanent agent's
runtimeConfig model whenever the executor was handed an agents-less
worktree AgentStore, silently drifting to the pi runtime's built-in
default model instead of the configured one.

- Add TaskExecutor.getAuthoritativeAssignedAgent(): falls back to the
  authoritative project `.fusion` AgentStore when the live executor's
  worktree AgentStore has no record of the assigned agent, so
  runtimeConfig resolution matches chat-session behavior.
- Replace direct `this.options.agentStore.getAgent(...)` lookups across
  step-session, workflow-graph, and legacy execution paths with the new
  authoritative lookup helper.
- Warn and audit (`noModelResolved` / `runtimeBuiltInFallbackModel`) when
  a non-mock, non-test-mode session resolves no provider/model pair and
  falls back to the runtime's built-in default, so the drift is visible
  instead of silent.
- Add regression tests covering assigned-agent runtime-config resolution
  and the new runtime-resolved audit fields.
- Add changeset (patch) and update docs/settings-reference.md and
  AGENTS.md.

Files changed:
 .changeset/fuzzy-fable-fallback.md                 |  7 +++
 AGENTS.md                                          |  1 +
 docs/settings-reference.md                         |  2 +-
 .../executor-assigned-agent-runtime-config.test.ts | 68 ++++++++++++++++++++++
 .../run-audit-session-runtime-resolved.test.ts     | 44 ++++++++++++++
 packages/engine/src/agent-session-helpers.ts       | 31 +++++++---
 packages/engine/src/executor.ts                    | 43 +++++++++-----
 7 files changed, 174 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-7787

Fusion-Task-Lineage: 40fccad5-2e67-4ee2-8199-4548ce9025c6

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 10:13:38 -07:00
gsxdsm
30bd7790e7 FN-7788: diagnose zero-NDJSON Grok CLI headless exits as a real failure
Fixes the residual "Grok CLI still returns no message immediately" case where a headless run exits code 0 but never emits any parsed NDJSON event, previously treated as a silent success.

- Detect a code-0 close with zero parsed NDJSON events and surface a diagnostic explaining the likely cause (wrong/unsupported grok binary falling into interactive mode and hitting EOF on stdin).
- Track and emit assistant text/diagnostics via a new appendMessage/emitDiagnosticText path so onText and session.state.errorMessage stay in sync, including on spawn failure and inactivity/first-line timeouts.
- Add first-line/inactivity timeout diagnostics with concrete elapsed-time messaging instead of silent kills.
- Add regression coverage in runtime-adapter.test.ts and grok-runtime-routing.test.ts for the zero-NDJSON exit path.
- Document the contract update in docs/grok-cli-contract.md.
- Add a patch changeset for @runfusion/fusion.

Files changed:
$(cat /tmp/diffstat_fn7788.txt)

Fusion-Task-Id: FN-7788

Fusion-Task-Lineage: dbb238a9-9601-47fc-8a88-40817d749337

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 10:01:49 -07:00
gsxdsm
a32307f8f1 FN-7778: resolve plugin-contributed skills per requesting project instead of daemon root
Fixes plugin skills silently disappearing when the fn daemon is started outside the project that enabled the contributing plugin, by making skill resolution project-aware instead of scoped to the daemon's root PluginLoader.

- getPluginSkills now resolves per requesting rootDir against project_plugin_states rather than the daemon-root PluginLoader scope
- Plugins skipped as disabled are now logged at load time for visibility
- Wired the new project-aware resolution through dashboard.ts, serve.ts, and daemon.ts CLI commands
- Added regression coverage in plugin-loader.test.ts and skills-adapter.test.ts
- Documented the project-scoped behavior in docs/PLUGIN_AUTHORING.md and docs/agents.md
- Added a patch changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7778-plugin-skills-project-scope.md  |  7 +++
 docs/PLUGIN_AUTHORING.md                           |  2 +
 docs/agents.md                                     |  2 +-
 packages/cli/src/commands/daemon.ts                | 68 +++++++++++++++++++--
 packages/cli/src/commands/dashboard.ts             | 71 ++++++++++++++++++++--
 packages/cli/src/commands/serve.ts                 | 68 +++++++++++++++++++--
 packages/core/src/__tests__/plugin-loader.test.ts  | 69 +++++++++++++++++++++
 packages/core/src/plugin-loader.ts                 | 29 ++++++---
 .../dashboard/src/__tests__/skills-adapter.test.ts | 29 +++++++++
 packages/dashboard/src/skills-adapter.ts           | 19 ++++--
 10 files changed, 337 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7778
Fusion-Task-Lineage: 5d9a8ff2-ed0e-4859-bf9c-a16f715b081d
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 08:18:47 -07:00
gsxdsm
f5fd8b84f8 FN-7780: move agent-created badge to bottom row on task cards
Moves the agent-created badge out of the task card header's meta-badges row into its own bottom row so it no longer causes header wrapping.

- Moved .card-agent-created-badge out of .card-meta-badges into a new .card-agent-badge-row in TaskCard.tsx
- Updated hasCardMetaBadges guard logic and TaskCard.css to support the new bottom row layout
- Added TaskCard.badge-wrap.test.tsx regression coverage and extended TaskCard.test.tsx
- Updated docs/dashboard-guide.md
- Added changeset fn-7780-agent-badge-bottom-row.md (patch, fix category)

Files changed:
 .changeset/fn-7780-agent-badge-bottom-row.md       |  7 +++
 docs/dashboard-guide.md                            |  3 +-
 packages/dashboard/app/components/TaskCard.css     | 12 ++++
 packages/dashboard/app/components/TaskCard.tsx     | 29 ++++++----
 .../__tests__/TaskCard.badge-wrap.test.tsx         | 66 ++++++++++++++++++++++
 .../app/components/__tests__/TaskCard.test.tsx     | 34 ++++++++---
 6 files changed, 131 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-7780

Fusion-Task-Lineage: 6a6cd9f6-a9ce-488f-969d-520459c8631b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 08:06:08 -07:00
gsxdsm
5729fe292c FN-7781: add optional workflow step toggles to task edit form
Enables editing a task's optional workflow steps directly from TaskForm edit mode, sourcing the step catalog from the resolved task workflow instead of re-seeding from defaultOn.

- TaskForm loads optional-step catalog from the task's resolved workflow when editing and exposes toggles for enabling/disabling optional steps
- TaskDetailModal passes through the additional workflow context needed for edit-mode step toggling
- Added changeset for @runfusion/fusion (minor)
- Updated docs/dashboard-guide.md to describe the new edit-mode workflow step behavior
- Added test coverage in TaskForm.test.tsx and TaskDetailModal.models-progress-workflow.test.tsx

Files changed:
 .changeset/fn-7781-edit-workflow-steps.md          |  7 ++
 docs/dashboard-guide.md                            |  5 +-
 .../dashboard/app/components/TaskDetailModal.tsx   |  6 ++
 packages/dashboard/app/components/TaskForm.tsx     | 76 +++++++++++++-----
 ...skDetailModal.models-progress-workflow.test.tsx | 90 ++++++++++++++++++++++
 .../app/components/__tests__/TaskForm.test.tsx     | 51 ++++++++++++
 6 files changed, 214 insertions(+), 21 deletions(-)

Fusion-Task-Id: FN-7781

Fusion-Task-Lineage: e44d9383-cfe7-4da1-9f20-8191211651cf

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 08:03:35 -07:00
gsxdsm
035caca6c8 FN-7775: Add thinking level selection to new chat model picker
Adds a per-session thinking-level selector to the new chat model dropdown, persisting the choice through the chat store and engine session options.

- Adds thinkingLevel column to chat_sessions with a db migration
- Extends chat-store, chat-types, and chat.ts to read/write thinkingLevel
- ChatView model selector now exposes a thinking-level control alongside model choice
- useChat and register-chat-routes plumb thinkingLevel through session creation/API
- engine/src/index.ts passes thinkingLevel as defaultThinkingLevel session option
- Adds a minor changeset and updates settings-reference/dashboard-guide docs
- Adds/updates unit tests across core and dashboard packages

Files changed:
 .changeset/fn-7775-chat-thinking-level.md          |  7 ++
 docs/dashboard-guide.md                            |  1 +
 docs/settings-reference.md                         |  2 +-
 packages/core/src/__tests__/chat-store.test.ts     | 15 +++-
 packages/core/src/__tests__/db-migrate.test.ts     | 33 ++++++++
 packages/core/src/chat-store.ts                    | 12 ++-
 packages/core/src/chat-types.ts                    |  6 ++
 packages/core/src/db.ts                            | 14 +++-
 packages/dashboard/app/api/legacy.ts               |  2 +-
 packages/dashboard/app/components/ChatView.tsx     | 16 +++-
 .../__tests__/ChatView.core-interactions.test.tsx  | 75 +++++++++++++++---
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 17 +++-
 packages/dashboard/app/hooks/useChat.ts            |  6 +-
 .../dashboard/src/__tests__/chat-manager.test.ts   | 90 ++++++++++++++++++++++
 packages/dashboard/src/chat.ts                     | 23 ++++++
 .../dashboard/src/routes/register-chat-routes.ts   | 25 +++++-
 packages/engine/src/index.ts                       |  1 +
 17 files changed, 318 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-7775

Fusion-Task-Lineage: e16c7d3b-361e-4908-87ad-10be17a47c47

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 08:00:34 -07:00
gsxdsm
57c3d7ceb8 FN-7776: evaluate promptContribution.condition against effective plugin settings
Plugin prompt contributions declared a `condition` field in the SDK, but the host never evaluated it, so gated prompt content always rendered unconditionally.

- Add packages/core/src/plugin-prompt-condition.ts implementing a minimal, non-eval `settings["key"] === "value"` / `!==` condition grammar
- Wire condition evaluation into plugin-runner.ts / agent-instructions.ts / executor.ts / reviewer.ts / triage.ts / agent-heartbeat.ts so prompt contributions are filtered by effective plugin settings at each call site
- Extend plugin-types.ts and core index.ts/index.gate.ts to expose the new evaluator and condition typing
- Document the condition grammar in docs/PLUGIN_AUTHORING.md
- Add regression tests covering the evaluator and its wiring through plugin-runner and agent-instructions
- Add changeset (@runfusion/fusion minor, feature) describing the new gating behavior

Files changed:
 .changeset/fn-7776-prompt-condition.md             |  7 ++
 docs/PLUGIN_AUTHORING.md                           | 13 ++-
 .../src/__tests__/plugin-prompt-condition.test.ts  | 90 ++++++++++++++++++++
 packages/core/src/index.gate.ts                    |  6 ++
 packages/core/src/index.ts                         |  6 ++
 packages/core/src/plugin-prompt-condition.ts       | 51 +++++++++++
 packages/core/src/plugin-types.ts                  | 10 ++-
 .../src/__tests__/agent-instructions.test.ts       | 33 ++++++--
 .../engine/src/__tests__/plugin-runner.test.ts     | 98 +++++++++++++++++++++-
 packages/engine/src/agent-heartbeat.ts             |  2 +-
 packages/engine/src/agent-instructions.ts          |  6 +-
 packages/engine/src/executor.ts                    | 28 +++++--
 packages/engine/src/plugin-runner.ts               | 64 ++++++++++++--
 packages/engine/src/reviewer.ts                    |  2 +-
 packages/engine/src/triage.ts                      |  2 +-
 packages/plugin-sdk/src/index.ts                   |  4 +
 16 files changed, 385 insertions(+), 37 deletions(-)

Fusion-Task-Id: FN-7776

Fusion-Task-Lineage: ba8dcd52-260a-4166-a712-f3dd39b81b15

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 07:46:52 -07:00
gsxdsm
70330bcffb FN-7779: render No message placeholder for empty assistant chat replies
Empty final assistant chat messages (e.g. Grok CLI runs that finish with no text) now show a muted "No message" placeholder instead of a blank bubble, in both Chat and Planner Chat via the shared StandardChatSurface component.

- Add isEmptyAssistantMessage check in StandardChatMessageItem: only applies to final persisted assistant messages with no content, tool calls, thinking output, attachments, or failure info
- Render a new .chat-message-content--empty block with the "No message" i18n string when the check matches
- Add shared CSS rule combining --waiting and --empty muted/italic styling, switching to var(--font-size-sm)
- Add "chat.noMessage" translation key to en/app.json and regenerate resources.d.ts
- Document the new behavior in docs/dashboard-guide.md
- Add a patch changeset for @runfusion/fusion
- Add StandardChatSurface.empty-message.test.tsx covering empty/whitespace content, populated content, tool calls, thinking output, attachments, failure info, non-assistant roles, and streaming waiting/thinking states

Files changed:
$(cat /tmp/diffstat_fn7779.txt)

Fusion-Task-Id: FN-7779

Fusion-Task-Lineage: d3ae068e-acba-4b4c-85d6-a788aa24a53b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 07:40:22 -07:00
gsxdsm
df8ad460af FN-7772: add per-lane thinking level for workflow model lanes
Adds a per-workflow-lane thinking-level setting so execution, planning, and
review model lanes can each specify their own reasoning-effort/thinking
level, threaded through engine phase precedence so lane-specific settings
override the workflow default.

- Add workflow lane thinking-level settings to builtin workflow settings and
  settings schema, with new types in core.
- Thread lane thinking-level precedence through model-resolution and engine
  phase execution (executor, step-session-executor, triage,
  agent-session-helpers).
- Surface per-lane thinking-level controls in the dashboard
  WorkflowSettingsPanel and ProjectModelsSection.
- Add/adjust tests for workflow settings, agent-session-helpers, and the
  dashboard settings panels.
- Update settings-reference.md and workflow-steps.md docs.
- Add changeset for the new feature (minor).

Files changed:
 .changeset/fn-7772-workflow-lane-thinking.md       |  7 ++++
 docs/settings-reference.md                         | 10 ++---
 docs/workflow-steps.md                             |  4 +-
 .../core/src/__tests__/workflow-settings.test.ts   | 41 ++++++++++++++++++++
 packages/core/src/builtin-workflow-settings.ts     | 27 ++++++++++++-
 packages/core/src/index.ts                         |  4 +-
 packages/core/src/model-resolution.ts              | 45 +++++++++++++++++++++-
 packages/core/src/settings-schema.ts               |  3 ++
 packages/core/src/types.ts                         |  6 +++
 .../app/components/WorkflowSettingsPanel.tsx       | 35 ++++++++++++++---
 .../__tests__/SettingsModal.models-auth.test.tsx   |  7 +++-
 .../__tests__/WorkflowSettingsPanel.test.tsx       | 31 +++++++++++++++
 .../settings/sections/ProjectModelsSection.tsx     | 39 ++++++++++++++++---
 .../src/__tests__/agent-session-helpers.test.ts    | 13 ++++---
 .../engine/src/__tests__/executor-test-helpers.ts  |  1 +
 packages/engine/src/agent-session-helpers.ts       | 19 +++++----
 packages/engine/src/executor.ts                    |  4 +-
 packages/engine/src/step-session-executor.ts       |  2 +-
 packages/engine/src/triage.ts                      |  8 +++-
 19 files changed, 264 insertions(+), 42 deletions(-)

Fusion-Task-Id: FN-7772

Fusion-Task-Lineage: 70aba3a9-66c2-4bb0-aff9-acabc7b98818

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 02:21:01 -07:00
gsxdsm
235ff4c65e FN-7771: add per-node thinking level for workflow model bindings
Adds a per-node thinking-level override (config.thinkingLevel) for workflow IR model bindings so individual workflow nodes can set reasoning effort independently of the global default.

- Extend workflow-ir types/schema and workflow-steps-to-ir conversion to carry config.thinkingLevel per node
- Wire thinkingLevel through executor and step-session-executor so the engine applies the per-node override during model calls
- Add a thinking-level control to WorkflowNodeEditor for authoring per-node overrides in the dashboard
- Add/extend tests covering IR round-trip, steps-to-ir conversion, executor model binding, and the WorkflowNodeEditor UI
- Document the new setting in docs/workflow-steps.md
- Add changeset for @runfusion/fusion (minor)

Files changed:
 .changeset/fn-7771-workflow-node-thinking.md       |  7 +++
 docs/workflow-steps.md                             | 10 ++-
 packages/core/src/__tests__/workflow-ir.test.ts    | 42 +++++++++++++
 .../src/__tests__/workflow-steps-to-ir.test.ts     | 15 +++++
 packages/core/src/store.ts                         |  1 +
 packages/core/src/types.ts                         |  9 +++
 packages/core/src/workflow-ir.ts                   | 21 +++++++
 packages/core/src/workflow-steps-to-ir.ts          |  5 ++
 .../app/components/WorkflowNodeEditor.tsx          | 42 ++++++++++++-
 .../__tests__/WorkflowNodeEditor.test.tsx          | 73 ++++++++++++++++++++++
 .../engine/src/__tests__/executor-test-helpers.ts  |  5 ++
 .../__tests__/executor-workflow-step-model.test.ts | 31 +++++++++
 .../src/__tests__/workflow-step-review.test.ts     | 53 ++++++++++++++++
 packages/engine/src/executor.ts                    | 61 ++++++++++++++++--
 packages/engine/src/step-session-executor.ts       | 12 +++-
 packages/engine/src/workflow-node-handlers.ts      | 29 ++++++++-
 16 files changed, 404 insertions(+), 12 deletions(-)

Fusion-Task-Id: FN-7771

Fusion-Task-Lineage: 5dbe3efb-773d-47db-9412-b740eb1d7745

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 01:49:15 -07:00
gsxdsm
5f14a58d3b FN-7770: add per-lane thinking-level overrides for project & global model settings
Adds an optional thinking-effort/reasoning override per model lane in Settings (project and global), resolved with precedence task > lane > global default, and reconciles this work with the already-landed FN-7768 inline thinking-level control on CustomModelDropdown (kept the shared shouldShowThinking/thinkingBadgeLabel implementation to avoid duplicating the selector/badge UI).

- Add lane thinking-level settings schema fields and runtime precedence (task > lane > global default) in @fusion/core
- Wire per-lane thinking selectors into GlobalModelsSection and ProjectModelsSection via CustomModelDropdown's existing showThinkingLevel/thinkingLevel/onThinkingLevelChange/defaultThinkingLevel props
- Resolve merger thinking level from the default lane rather than the title-summarizer lane in engine session helpers/executor/merger/triage
- Update settings-reference docs and add a minor changeset for the new lane thinking overrides
- Add/expand test coverage: settings-parity, store-settings, settings-sections, agent-session-helpers
- Add new i18n key models.options.defaultWithLevel across locales

Files changed:
 .changeset/fn-7770-lane-thinking.md                |   7 ++
 docs/settings-reference.md                         |   8 ++
 .../core/src/__tests__/settings-parity.test.ts     |  17 ++++
 packages/core/src/__tests__/store-settings.test.ts |  42 +++++++++
 packages/core/src/settings-schema.ts               |  14 +++
 packages/core/src/types.ts                         |  16 ++++
 .../app/__tests__/settings-sections.test.tsx       | 100 ++++++++++++++++++---
 .../app/components/CustomModelDropdown.css         |   1 +
 .../dashboard/app/components/SettingsModal.tsx     |  37 ++++++++
 .../settings/sections/GlobalModelsSection.tsx      |   9 +-
 .../settings/sections/ProjectModelsSection.tsx     |  12 ++-
 .../app/components/settings/sections/context.ts    |   2 +
 .../src/__tests__/agent-session-helpers.test.ts    |  36 ++++++++
 packages/engine/src/agent-session-helpers.ts       |  60 +++++++++++++
 packages/engine/src/executor.ts                    |  14 +--
 packages/engine/src/merger-ai.ts                   |  12 ++-
 packages/engine/src/merger.ts                      |  12 +--
 packages/engine/src/pr-response-run-ops.ts         |   4 +-
 packages/engine/src/step-session-executor.ts       |   3 +-
 packages/engine/src/triage.ts                      |   5 +-
 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 +-
 packages/i18n/src/resources.d.ts                   |   3 +
 27 files changed, 390 insertions(+), 42 deletions(-)

Fusion-Task-Id: FN-7770
Fusion-Task-Lineage: 3418c621-ac99-4cd4-a435-9348da03972f
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 01:15:40 -07:00
gsxdsm
3cda9d830a FN-7768: inline thinking-level control in CustomModelDropdown and migrate task/agent surfaces
Adds an inline thinking-level selector to CustomModelDropdown and migrates existing model-selection surfaces (task form, quick entry, new agent dialog, model selection modal/tab) to use it instead of their own bespoke thinking-level controls.

- CustomModelDropdown: add inline thinking-level control (CSS + component logic)
- ModelSelectionModal / ModelSelectorTab: drop local thinking-level UI in favor of the dropdown's inline control
- NewAgentDialog: migrate to the shared inline thinking-level control
- QuickEntryBox: remove now-redundant thinking-level UI, delegate to CustomModelDropdown
- TaskForm: migrate to the shared inline thinking-level control
- Add/update tests for CustomModelDropdown, ModelSelectionModal, ModelSelectorTab, NewAgentDialog, QuickEntryBox, TaskForm
- Add changeset for @runfusion/fusion (feature)
- Update dashboard guide docs

Files changed:
 .changeset/fn-7768-inline-thinking-dropdown.md     |  7 ++
 docs/dashboard-guide.md                            |  1 +
 .../app/components/CustomModelDropdown.css         | 33 +++++++++
 .../app/components/CustomModelDropdown.tsx         | 69 ++++++++++++++++-
 .../app/components/ModelSelectionModal.tsx         | 32 +-------
 .../dashboard/app/components/ModelSelectorTab.tsx  | 33 +--------
 .../dashboard/app/components/NewAgentDialog.tsx    | 18 +----
 .../dashboard/app/components/QuickEntryBox.tsx     | 59 +--------------
 packages/dashboard/app/components/TaskForm.tsx     | 23 +-----
 .../__tests__/CustomModelDropdown.test.tsx         | 72 ++++++++++++++++++
 .../__tests__/ModelSelectionModal.test.tsx         | 48 +++++++++---
 .../components/__tests__/ModelSelectorTab.test.tsx |  3 +-
 .../components/__tests__/NewAgentDialog.test.tsx   | 86 ++++++++++++++++++++++
 .../components/__tests__/QuickEntryBox.test.tsx    | 42 +++++++----
 .../app/components/__tests__/TaskForm.test.tsx     |  7 +-
 15 files changed, 354 insertions(+), 179 deletions(-)

Fusion-Task-Id: FN-7768
Fusion-Task-Lineage: 8f32731b-9865-4902-9420-62d3c0295805
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-10 00:48:14 -07:00
gsxdsm
18841d76a0 FN-7761: fix Grok CLI auth to use logged-in CLI instead of requiring API key
Packaged fn serve/daemon/dashboard hosts previously failed with a misleading missing-API-key error for grok-cli agents even though the operator was already logged in via the Grok CLI. This fixes routing so those hosts eagerly ensure the bundled Grok Runtime plugin is installed/loaded before session creation, and no longer silently falls back to the key-requiring direct endpoint when no key is visible.

- Eagerly ensure the bundled fusion-plugin-grok-runtime in serve, daemon, and dashboard commands before loadAllPlugins() so runtime id "grok" is available on fresh installs without manual plugin-settings setup.
- agent-session-helpers.ts: deriveGrokRuntimeHintForNoVisibleKey now throws an actionable error (naming both remediations: install/enable the Grok CLI runtime plugin, or set GROK_API_KEY) instead of silently falling through to the key-requiring pi/openai-completions path when the runtime can't be loaded.
- Update docs/grok-cli-contract.md to document the FN-7761 packaged-host wiring and new no-silent-fallback behavior.
- Add regression tests for the packaged bootstrap behavior and bundled-plugin install path.
- Add changeset for @runfusion/fusion (patch, category: fix).

Files changed:
 .changeset/fn-7761-grok-cli-packaged-routing.md    |  7 +++++
 docs/grok-cli-contract.md                          | 19 +++++++++----
 .../__tests__/grok-runtime-bootstrap.test.ts       | 31 ++++++++++++++++++++++
 packages/cli/src/commands/daemon.ts                | 17 +++++++++++-
 packages/cli/src/commands/dashboard.ts             | 20 +++++++++++++-
 packages/cli/src/commands/serve.ts                 | 19 +++++++++++--
 .../__tests__/bundled-plugin-install.test.ts       | 17 ++++++++++++
 .../src/__tests__/grok-runtime-routing.test.ts     | 17 ++++++------
 packages/engine/src/agent-session-helpers.ts       | 15 +++++++++--
 9 files changed, 142 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-7761
Fusion-Task-Lineage: 3be5f054-965c-4e8a-ad91-6e61d4dc4a42
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 23:43:15 -07:00
gsxdsm
fed5d3d951 FN-7759: fix GPT-5.6 codex models missing from model dropdown
Ensure GPT-5.6 codex models (luna, sol, terra) actually surface in the codex model picker by validating the openai-codex supplemental merge against the real pi-coding-agent ModelRegistry instead of only a mocked one.

- Harden openai-models.ts supplemental merge logic against real ModelRegistry auth filtering, registerProvider full-replacement, and OAuth provider validation
- Add @earendil-works/pi-coding-agent devDependency to @fusion/core for real-registry testing
- Add regression test (openai-models.test.ts) exercising the real registry path
- Extend register-model-routes-openai-codex-supplemental.test.ts dashboard test coverage
- Update docs/settings-reference.md
- Add changeset fn-7759-codex-gpt-5-6-dropdown.md (patch, fix)

Files changed:
 .changeset/fn-7759-codex-gpt-5-6-dropdown.md       |   7 ++
 docs/settings-reference.md                         |   2 +-
 packages/core/package.json                         |   1 +
 packages/core/src/__tests__/openai-models.test.ts  |  68 +++++++++++++
 packages/core/src/openai-models.ts                 | 107 ++++++++++++++++-----
 ...-model-routes-openai-codex-supplemental.test.ts |  77 +++++++++++++--
 pnpm-lock.yaml                                     |  68 +++++++++++++
 7 files changed, 300 insertions(+), 30 deletions(-)

Fusion-Task-Id: FN-7759

Fusion-Task-Lineage: 4c03838f-b8d8-4f6f-ae55-c3356c1c3176

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 23:12:02 -07:00
gsxdsm
2be6040b02 FN-7758: route Grok CLI fallback models through the CLI runtime when no API key is visible
Fix Grok CLI 'missing API key' false-positive by extending the no-visible-key routing invariant to configured fallback models, not just the default provider.
- deriveGrokRuntimeHintForNoVisibleKey now also triggers when the fallback provider is grok-cli
- new applyGrokCliNoKeyRuntimeOptions promotes a grok-cli fallback model into the primary session (stripping the provider-qualified model prefix) instead of leaving it as an unused fallback
- docs/grok-cli-contract.md updated to describe the fallback-routing contract
- added regression tests in grok-runtime-routing.test.ts, chat-manager.test.ts, and chat-manager-room-hybrid.test.ts
- added changeset fn-7758-grok-cli-no-key-routing.md (patch)

Files changed:
 .changeset/fn-7758-grok-cli-no-key-routing.md      |   7 ++
 docs/grok-cli-contract.md                          |  29 +++--
 .../src/__tests__/chat-manager-room-hybrid.test.ts |  36 +++++++
 .../dashboard/src/__tests__/chat-manager.test.ts   |  41 +++++++
 packages/dashboard/src/chat.ts                     |  16 ++-
 .../src/__tests__/grok-runtime-routing.test.ts     | 118 +++++++++++++++++++++
 packages/engine/src/agent-session-helpers.ts       |  36 ++++++-
 7 files changed, 266 insertions(+), 17 deletions(-)

Fusion-Task-Id: FN-7758

Fusion-Task-Lineage: 6b564b21-50ab-4c3e-b0d7-7fded2091d90

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 22:19:22 -07:00
gsxdsm
f7c6f560c0 FN-7753: route grok-cli execution through the grok CLI when no Fusion-visible GROK_API_KEY resolves
Route grok-cli model selections through the grok CLI runtime when no Fusion-visible GROK_API_KEY is available.

- Add read-only isGrokApiKeyFusionVisible() in packages/core/src/grok-provider.ts, refactored to share user-settings-file reading with hydrateGrokApiKeyFromUserSettings without mutating process.env or logging key material.
- In packages/engine/src/agent-session-helpers.ts, auto-derive the existing "grok" runtimeHint when defaultProvider is grok-cli, no key is Fusion-visible, and the grok plugin runtime is registered; explicit runtime hints and mock/test-mode routing remain unchanged, and the provider-qualified model prefix is stripped before handoff.
- Normalize provider-qualified model ids (grok-cli/<id>, grok/<id>) in the grok-runtime plugin's runtime-adapter and CLI stream spawn so the concrete model reaches `grok --model`, with the historical grok/default fallback preserved for the no-model path.
- Update docs (grok-cli-contract.md, settings-reference.md, plugin README) and add/extend tests covering the new fallback behavior, model normalization, and CLI streaming.
- Add changeset fn-7753-grok-cli-no-key-fallback.md (patch, fix).

Files changed:
 .changeset/fn-7753-grok-cli-no-key-fallback.md     |   7 ++
 docs/grok-cli-contract.md                          |  83 ++++++++++------
 docs/settings-reference.md                         |   6 +-
 .../__tests__/grok-provider-user-settings.test.ts  |  46 +++++++++
 packages/core/src/grok-provider.ts                 |  39 +++++++-
 packages/core/src/index.gate.ts                    |   1 +
 packages/core/src/index.ts                         |   1 +
 .../src/__tests__/grok-runtime-routing.test.ts     | 107 +++++++++++++++++++--
 packages/engine/src/agent-session-helpers.ts       |  52 +++++++++-
 plugins/fusion-plugin-grok-runtime/README.md       |  46 +++++----
 .../src/__tests__/cli-stream.test.ts               |  70 ++++++++++++++
 .../src/__tests__/runtime-adapter.test.ts          |  28 ++++++
 .../fusion-plugin-grok-runtime/src/cli-stream.ts   |   6 ++
 .../src/runtime-adapter.ts                         |  24 ++++-
 14 files changed, 443 insertions(+), 73 deletions(-)

Fusion-Task-Id: FN-7753

Fusion-Task-Lineage: 30ef7265-1ba9-47fd-8c4e-87b02f6a1d78

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 21:36:14 -07:00
gsxdsm
d2c2a4cab1 FN-7754: seed OpenAI GPT-5.6 Codex models into pi createFnAgent registry
Wires the GPT-5.6 codenamed OpenAI Codex models (gpt-5.6-luna/sol/terra) into the engine pi model-registry seeding surface, mirroring the dashboard's /api/models supplemental merge so the models are no longer missing from pi.

- Call mergeSupplementalOpenAiCodexModels() in createFnAgent (packages/engine/src/pi.ts) alongside the existing Anthropic supplemental merge
- Add regression tests covering synthesis of missing GPT-5.6 rows and dedupe against pinned catalog entries
- Update docs/settings-reference.md to describe the additive surfacing on both /api/models and the engine/pi registry-seeding path
- Add a patch changeset for @runfusion/fusion

Files changed:
 .changeset/fn-7754-openai-gpt-5-6-pi-surface.md    |  7 +++
 docs/settings-reference.md                         |  2 +-
 .../src/__tests__/pi-create-fn-agent.test.ts       | 63 ++++++++++++++++++++++
 packages/engine/src/pi.ts                          |  6 +++
 4 files changed, 77 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7754

Fusion-Task-Lineage: b61b6812-c94b-46d8-b187-445ccdd6e4e9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 21:30:34 -07:00
gsxdsm
547740bb66 FN-7751: move mobile settings search toggle inline with section picker
Relocates the mobile-only settings search icon toggle so it sits inline next to the section dropdown instead of its own row above it, tightening the mobile Settings header.

- Move the settings-search-toggle button out of the standalone .settings-search row into a new .settings-mobile-section-picker-control-row alongside the mobile section <select>.
- Preserve FN-7713 expand/hide toggle behavior and active-query preservation; desktop/tablet layout unaffected.
- Add CSS for .settings-mobile-section-picker-control-row to lay out the select and toggle button inline.
- Update settings-mobile tests to assert the toggle renders next to the section picker.
- Add changeset (patch) documenting the fix.

Files changed:
 .../fn-7751-mobile-settings-search-inline.md       |  7 ++
 docs/dashboard-guide.md                            |  4 +-
 .../dashboard/app/components/SettingsModal.css     | 23 ++++--
 .../dashboard/app/components/SettingsModal.tsx     | 89 +++++++++++-----------
 .../components/__tests__/settings-mobile.test.tsx  | 38 ++++++++-
 5 files changed, 105 insertions(+), 56 deletions(-)

Fusion-Task-Id: FN-7751

Fusion-Task-Lineage: 8bb9a32b-80f4-4b73-a366-d23e97106b73

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-09 20:13:20 -07:00