Commit Graph

2814 Commits

Author SHA1 Message Date
Timothy Laurent
d6ad56a173 fix(dashboard): address PR review feedback for model filtering and insights
- Always apply configured-provider filter (even when empty set)
- Convert getConfiguredProviderNames to async (fs/promises)
- Validate model overrides as non-empty provider+model pair
- Clear stale persisted insight model when no longer available
- Replace hardcoded max-height with design token in overflow menu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:10:45 -07:00
Timothy Laurent
86712d4966 feat(insights): model selector with favorites, provider filtering, and configured-providers-only API
- Wire up CustomModelDropdown in InsightsView with favorites support:
  favoriteProviders, favoriteModels, and toggle callbacks
- Auto-promote resolved planning provider as implicit favorite when
  no explicit favorites are set
- Filter /models API to only return providers with credentials in
  Fusion's own auth stores (primary + legacy .pi + models.json),
  excluding supplemental stores (Codex CLI, Claude Code, env vars)
  that surface unconfigured providers
- Still allow enabled extension providers (Claude CLI, Droid CLI,
  llama.cpp) when their settings toggles are on

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:10:45 -07:00
Timothy Laurent
65d15f77b5 fix(insights): fetch models internally so model dropdown is populated
InsightsView accepted a models prop that was never passed from App.tsx.
Now fetches models via fetchModels() on mount (same pattern as ChatView),
falling back to the prop if provided.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:10:45 -07:00
Timothy Laurent
6a1f48e069 fix(settings): prevent project-level global keys from overriding global settings
getSettingsFast() and getSettings() spread project-level settings over
global settings without filtering by scope. A stale project-level
experimentalFeatures: {} in SQLite would override the global
experimentalFeatures: { insights: true, ... }, making all experimental
features invisible in the dashboard.

Now both methods strip global-only keys from project settings before
the merge, matching the behavior of getSettingsByScopeFast().

Also adds max-height and overflow-y to the overflow dropdown menu.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:10:45 -07:00
Timothy Laurent
c6571eea4e test(api): add triggerInsightRun model params tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:10:44 -07:00
Timothy Laurent
6e81daf98f fix(insights): preserve custom model selection across retries
Stores modelProvider/modelId in the run's inputMetadata.metadata at
creation time, then recovers it in the retry handler so the user's
explicit model choice survives a transient failure and retry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:10:44 -07:00
Timothy Laurent
41af820f1d fix(insights): validate localStorage model values and tighten fallback condition
- Guard against malformed localStorage values (e.g. "provider/") by
  validating both parts are non-empty before sending to the server
- Only wire settings fallback when both provider AND modelId are
  explicitly provided, preventing mismatched provider/modelId combos

Addresses ISSUE-002 and ISSUE-003 from code quality review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:09:39 -07:00
Timothy Laurent
4f674f2085 feat(insights): add collapsible model selector to InsightsView with gear trigger
Adds a Settings gear button to the InsightsView action bar that toggles a
collapsible model configuration row. The row contains a CustomModelDropdown
allowing users to override the insight generation model. Selections persist
to localStorage under the "fusion-insight-model" key. A yellow indicator dot
appears on the gear when a non-default model is active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:09:39 -07:00
Timothy Laurent
dbe5b02024 feat(insights): thread model selection through useInsights hook
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:09:39 -07:00
Timothy Laurent
507467d687 feat(api): add optional model params to triggerInsightRun
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:09:38 -07:00
Timothy Laurent
1dcf9be93f feat(insights): accept optional model override in POST /run with settings fallback; fix retry handler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 14:09:38 -07:00
gsxdsm
8b2b4f69e8 Merge pull request #51 from Runfusion/codex/testing-suite-quality-prd
test: harden and slim local test workflow
2026-05-07 10:18:35 -07:00
gsxdsm
9cc98fd85a fix: resume distributed task ID counter past existing IDs; extract plugin view types
The dashboard task-create route now uses the distributed task ID allocator
(FN-3450). On projects whose tasks had been allocated through the legacy
config.nextId counter, the allocator's `ensureStateRow` was seeding a fresh
prefix at sequence 1, so new tasks restarted at FN-001 even when FN-3700
already existed. ensureStateRow now seeds past:

- the legacy config.nextId counter (when configured taskPrefix matches), and
- one past the highest numeric suffix on any existing tasks/archivedTasks row
  for the prefix.

A regression test seeds FN-3700 in a fresh DB and asserts the next reservation
returns FN-3701, not FN-001.

Plugin dashboard view contracts are now exposed via a slim type-only module
(`@fusion/dashboard/app/plugins/types`). External plugin tsc builds previously
imported `pluginViewRegistry`, transitively pulling in dashboard runtime
sources (React components, CSS, lucide-react). The dependency-graph plugin's
import + path mapping is updated to use the new module.

Schema housekeeping: drop unused scaffolding tables left over from an earlier
migration via a new idempotent migration (v67). Fresh DBs see no change;
existing DBs that ran the older migration get the orphan tables dropped on
next init.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 09:41:42 -07:00
Fusion
21b7d41680 feat(FN-3087): document graph plugin in plugin authoring guide
Documentation-only finish for FN-3087, adding changeset and README updates for the dependency graph plugin and plugin authoring guide.

Fusion-Task-Id: FN-3087
2026-05-07 08:49:19 -07:00
Fusion
41a1e1a2f2 feat(FN-3638): extract roadmap domain into plugin and define plugin route s
This merge restructures the roadmap plugin by removing its duplicated domain logic (roadmap store, ordering, handoff, and types — ~3,000 lines deleted) and completing the plugin SDK scaffold with proper route status/body contracts and type exports. It also introduces eval settings infrastructure wit

Fusion-Task-Id: FN-3638
2026-05-07 08:49:19 -07:00
Fusion
f51ec4d3b5 feat(FN-3554): expand AI agent interview onboarding flow
Reuses the experimental onboarding modal for both create and edit, makes
onboarding mode-aware, and plumbs draft handling through the agent detail
view, new agent dialog, and import/export/generation routes.

Fusion-Task-Id: FN-3554
2026-05-07 08:49:18 -07:00
Fusion
78f62b18b6 feat(FN-3393): add eval settings with scheduled eval project settings UI
Adds a scheduled eval settings feature (FN-3393) with a new `evalSettings` contract in core, type-safe numeric validation, a project settings UI section, and an API route for persisting the payload. The bulk of the changes are in the settings modal and supporting test coverage. Two smaller, unrelate

Fusion-Task-Id: FN-3393
2026-05-07 08:49:18 -07:00
Fusion
9057421112 feat(FN-3091): add plugin view remount routing test coverage
Adds test coverage for plugin view remount routing behavior in the App component.

Fusion-Task-Id: FN-3091
2026-05-07 08:49:18 -07:00
Aron Prins
06d022670a test(FN-000): address PR review feedback 2026-05-07 17:32:21 +02:00
Aron Prins
9a1d9b59c6 test(FN-000): slim dashboard default tests 2026-05-07 17:27:16 +02:00
Aron Prins
a9f2fb65ef test(FN-000): resolve dashboard test noise 2026-05-07 17:27:15 +02:00
Aron Prins
46072542cf test(FN-000): harden local test suite 2026-05-07 17:26:51 +02:00
Fusion
3575b5e445 feat(FN-3581): honor runtime model precedence for assigned agents
This merge delivers five major feature clusters: a fully rebuilt dependency graph plugin with draggable nodes, position persistence, modular architecture, highlighting and selection states, toolbar navigation, and keyboard controls; a new roadmap plugin with domain store, ordering logic, and compreh

Fusion-Task-Id: FN-3581
2026-05-07 06:45:45 -07:00
Fusion
d135ecf1f0 feat(FN-3636): add roadmap plugin with domain store and ordering logic
Merges the roadmap plugin scaffold (FN-3636): a new `plugins/fusion-plugin-roadmap` workspace with domain types (`roadmap-types.ts`), a store layer (`roadmap-store.ts`, `roadmap-ordering.ts`, `roadmap-handoff.ts`), and comprehensive test suites. Also lands graph position persistence for the dependen

Fusion-Task-Id: FN-3636
2026-05-07 06:28:10 -07:00
Fusion
054404b175 feat(FN-3463): refine ScriptsModal responsive token usage
Refines responsive CSS token usage in the ScriptsModal component by swapping hardcoded values for design token variables.

Fusion-Task-Id: FN-3463
2026-05-07 05:40:22 -07:00
Fusion
7abfe7f9d1 feat(FN-3623): add stash diff viewing UI and backend contract
Merges FN-3623 stash diff inspection system (backend contract, GitManagerModal viewing UI with new API route and tests) and FN-3088 dependency graph hover/selection highlighting. The stash diff work dominates the commit count and touches the core GitManagerModal, while the graph plugin gains new hig

Fusion-Task-Id: FN-3623
2026-05-07 05:09:57 -07:00
Fusion
dca07892ff feat(FN-3396): bundle Cursor CLI as a plugin provider with dashboard auth w
Merges FN-3396's full Cursor CLI provider integration (Steps 1–4): defines a CLI-backed provider contract, adds the `fusion-plugin-cursor-runtime` plugin package with process management and runtime probes, wires dashboard auth flows and UI (ProviderCard, onboarding modal, settings), and bundles the

Fusion-Task-Id: FN-3396
2026-05-07 04:17:52 -07:00
Fusion
2eba5a007c feat(FN-3577): add native shell guide and bridge contract documentation
Adds a native shell integration guide (FN-3577) with fusionShell bridge contract documentation, wired into the docs navigation, plus a regression test; also hardens the dependency graph's task filtering (FN-3085) to include in-review tasks and handle orphan edges, with corresponding test coverage ac

Fusion-Task-Id: FN-3577
2026-05-07 03:59:43 -07:00
Fusion
80ee9c25fc feat(FN-3625): test TaskCard drag override and graph drag opt-out wiring
Adds test coverage for TaskCard drag override behavior and DependencyGraph drag opt-out wiring, with a minor README clarification in the graph plugin.

Fusion-Task-Id: FN-3625
2026-05-07 03:28:43 -07:00
Fusion
16d3f18d8d feat(FN-3426): add plugin AI security scan gate and GraphTaskNode wrapper t
Adds a plugin AI security scan gate that enforces security scanning before plugin installation, including new `plugin-security-scan.ts` infrastructure, CLI integration (`fn plugin install`), plugin loader hooks, and a changeset. Implements branch filter persistence across sessions in the dashboard (

Fusion-Task-Id: FN-3426
2026-05-07 02:49:35 -07:00
Fusion
5299745fc4 feat(FN-3077): enforce plugin AI security scan gate across install flows
- Add core plugin AI security scan module and schema support for scan toggle/state metadata
- Enforce scan checks during CLI and dashboard plugin install flows, with preserved API error status on scan failures
- Expose plugin scan toggle and rescan actions in dashboard/plugin manager with route and UI coverage
- Update plugin authoring and CLI/dashboard docs, plus add changeset for published CLI package

Fusion-Task-Id: FN-3077
2026-05-07 02:15:14 -07:00
Fusion
744f429447 feat(FN-3425): add board branch filter with no-branch semantics and respons
Restructures the dependency graph plugin into a modular architecture with separate edges, filters, layout, types, and interaction hooks, adding comprehensive tests for the new modules. Implements a board branch filter with "no-branch" semantics and responsive layout refinement, while removing legacy

Fusion-Task-Id: FN-3425
2026-05-07 01:53:48 -07:00
Fusion
10b7b3014f feat(FN-3632): remove quick-entry branch handling from dashboard and docs
Removes the `QuickEntryBox` component and its styles as part of FN-3632 cleanup, with its tests refactored accordingly. Also updates the test-changed script and fixes an isolated test home cleanup ordering issue.

Fusion-Task-Id: FN-3632
2026-05-07 01:30:34 -07:00
Fusion
cd8763a225 feat(FN-3631): replicate task creation across mesh nodes and fix modal scrolling
- Add mesh task replication plumbing in core store/types with node-aware task creation metadata
- Expose dashboard and mesh API route coverage for replicated task creation and sync behavior
- Restore independent scrolling in Git Manager changes list and prevent Scripts modal scroll regressions
- Expand tests across core, dashboard routes, API, and CLI extension insights for the new behavior

Fusion-Task-Id: FN-3631
2026-05-07 00:52:05 -07:00
Fusion
d1490d2972 feat(FN-3450): add mesh task create replication across nodes
Implements distributed mesh task creation by adding replicated create primitives to the core store, wiring new API routes (`register-mesh-routes.ts`) that replicate task creation across clustered nodes while preserving remote-targeting metadata, and updating the dashboard's task creation flow accord

Fusion-Task-Id: FN-3450
2026-05-07 00:05:34 -07:00
Fusion
1a0124c5da feat(FN-3080): document graph navigation canonicalization in plugin authori
Adds documentation for graph navigation canonicalization (FN-3080) covering plugin authoring and dashboard usage, along with a changeset for the `@runfusion/fusion` package release.

Fusion-Task-Id: FN-3080
2026-05-06 22:59:51 -07:00
gsxdsm
ecb5f60152 chore(release): v0.23.0
Version bump via changesets.
2026-05-06 22:47:53 -07:00
gsxdsm
6294993dd8 fix(dashboard): block iOS visualViewport pan while chat keyboard is up
Previous textarea-only touchmove listener didn't catch swipes that
started elsewhere (header, composer padding) — those still panned the
iOS visualViewport over the locked document, sliding the composer up.

Replaces it with a document-level non-passive touchmove listener that
fires while keyboardOpen on mobile and preventDefaults all gestures
EXCEPT when the target is inside .chat-messages (the one container
where pan-y should still work). Stops both header-swipe and composer-
swipe from panning the page, while leaving messages-list scroll
intact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:44:16 -07:00
gsxdsm
12b1ace95f fix(dashboard): use non-passive touchmove listener on textarea
React's onTouchMove handler is registered as a passive listener by
default, so the previous JSX-handler preventDefault() was silently a
no-op — drags on the composer still scrolled the input box up.

Attaches the listener imperatively via addEventListener with
{ passive: false } so preventDefault actually cancels the drag. Tap
(touchstart + touchend without touchmove between) is still unaffected,
so first-tap focus continues to work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:39:35 -07:00
gsxdsm
6815dd15c2 Reapply "fix(dashboard): block composer drag-pan via onTouchMove preventDefault"
This reverts commit 3478604fac.
2026-05-06 22:37:24 -07:00
gsxdsm
3478604fac Revert "fix(dashboard): block composer drag-pan via onTouchMove preventDefault"
This reverts commit 2bc7aa0151.
2026-05-06 22:36:04 -07:00
gsxdsm
c9bbd7d43e fix(dashboard): parse Codex reset_at as epoch ms or seconds
Codex returns weekly window reset_at in milliseconds in some cases,
which was being multiplied by 1000 and producing nonsensical reset
countdowns and pace calculations. Route through _parseResetTimestamp
so both formats work, and add a regression test.

Also tightens comments in useMobileKeyboard / ChatView around why
visualViewport scroll events skip offsetTop updates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:17:35 -07:00
Fusion
f8abef2858 feat(FN-3626): migrate plugin storage to project-scoped storage
Migrated the dependency-graph plugin's storage layer to use the project's scoped storage API (`projectStorage`) and added canonical storage-key assertions. The ChatView.tsx utility reference was updated to match the new storage path.

Fusion-Task-Id: FN-3626
2026-05-06 22:17:35 -07:00
Fusion
1de4844369 feat(FN-3575): rebuild plugin system with catalog, settings, and CLI comman
Restores plugin management features across the CLI and dashboard, including a new `plugin available/settings` commands and a refactored PluginManager component that groups built-in plugins (agent-browser, fusion) separately from custom ones, with updated documentation on the plugin authoring guide.

Fusion-Task-Id: FN-3575
2026-05-06 22:17:35 -07:00
Fusion
4ef927c42e feat(FN-3629): refine branch chip visibility in task cards
Refined branch chip visibility logic in TaskCard (suppressing the chip when the current branch is the default) and added test coverage for those suppression cases, with corresponding documentation updates. Also added chat layout regression tests and fixed a composer drag-pan issue on mobile touch de

Fusion-Task-Id: FN-3629
2026-05-06 22:17:35 -07:00
Fusion
ad60886794 fix(FN-3624): harden mobile chat keyboard layout behavior
- Update ChatView keyboard spacer styling to keep viewport layout stable on mobile
- Adjust ChatView viewport handling logic to better align chat body with keyboard transitions
- Add ChatView regression tests covering mobile layout and keyboard interaction scenarios
- Add useMobileKeyboard hook tests to lock keyboard metric behavior and prevent regressions

Fusion-Task-Id: FN-3624
2026-05-06 21:55:22 -07:00
gsxdsm
2bc7aa0151 fix(dashboard): block composer drag-pan via onTouchMove preventDefault
touch-action: manipulation is needed on the textarea so iOS registers
first-tap focus reliably, but it also allows pan-y — which let the
user drag the input box up off-screen with the keyboard up.
Cancelling touchmove blocks the drag without affecting tap (a tap
fires touchstart + touchend with no touchmove in between), so the
composer stays locked AND first-tap focus works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 21:51:40 -07:00
Fusion
5caaabcdba feat(FN-3424): add unassigned branch filter options to dashboard header
Adds unassigned branch filter options to the dashboard header, allowing users to filter tasks by unassigned status. Updates the Header component with new filter controls and includes corresponding tests for the App and Header components.

Fusion-Task-Id: FN-3424
2026-05-06 21:47:53 -07:00
gsxdsm
2ed722ecbd fix(dashboard): allow textarea taps + resync iOS keyboard on page restore
Two fixes for residual mobile chat issues:

1) Textarea touch-action: none was preventing iOS from registering a
   clean tap-to-focus, causing the keyboard to flash up via the
   programmatic focus() in onTouchStart and then auto-dismiss because
   iOS never saw the gesture complete. Switching to manipulation
   allows tap while still blocking pan/zoom — the composer stays
   anchored thanks to overscroll-behavior: contain on its container.

2) On switch-away-and-back the visualViewport metrics could get
   stuck in a half-state (composer pushed up, or blank pane covering
   it). Adding a visibilitychange / pageshow handler on ChatView that
   force-blurs and re-focuses the active textarea makes iOS resync
   the keyboard / vv metrics cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 21:44:39 -07:00
gsxdsm
8ec6c1086f Revert "fix(dashboard): lazy-init useMobileKeyboard so remount has no stale render"
This reverts commit 3f5d01f4d4.
2026-05-06 21:41:16 -07:00