aedee4b8231bf050c3240a00ab6645ede5d87ee9
33 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d4d13e2fa5 |
FN-9111: Add global Quick Add Enter-save preference
Add an operator-level setting that controls whether plain Enter saves a Quick Add task while preserving Cmd/Ctrl+Enter submission. - add the global quickAddSubmitOnEnter setting, defaults, settings UI, and app context - update Quick Add keyboard handling with multiline and duplicate/in-flight safeguards - add focused settings and keyboard regression coverage, localization, documentation, and a release changeset Files changed: .changeset/fn-9111-quick-add-enter.md | 7 ++ docs/dashboard-guide.md | 2 + docs/settings-reference.md | 1 + .../core/src/__tests__/settings-defaults.test.ts | 10 ++ packages/core/src/config/settings-schema.ts | 5 + packages/core/src/types/settings/settings-scope.ts | 5 + packages/dashboard/app/App.tsx | 4 + .../dashboard/app/components/QuickEntryBox.tsx | 24 ++++- .../QuickEntryBox.submit-on-enter.test.tsx | 118 +++++++++++++++++++++ .../__tests__/SettingsModal.general.test.tsx | 18 ++++ .../app/components/settings/save-split.ts | 1 + .../sections/GlobalGeneralSection.search.ts | 9 ++ .../settings/sections/GlobalGeneralSection.tsx | 10 ++ .../settings-default-descriptions.test.tsx | 1 + .../__tests__/useQuickAddSubmitOnEnter.test.tsx | 24 +++++ packages/dashboard/app/hooks/useAppSettings.ts | 4 + .../app/hooks/useQuickAddSubmitOnEnter.ts | 21 ++++ packages/i18n/locales/en/app.json | 2 + packages/i18n/locales/es/app.json | 4 +- packages/i18n/locales/fr/app.json | 4 +- packages/i18n/locales/ko/app.json | 4 +- packages/i18n/locales/pt-BR/app.json | 4 +- packages/i18n/locales/zh-CN/app.json | 4 +- packages/i18n/locales/zh-TW/app.json | 4 +- packages/i18n/src/resources.d.ts | 4 +- 25 files changed, 284 insertions(+), 10 deletions(-) Fusion-Task-Id: FN-9111 Fusion-Task-Lineage: 246153a8-5127-48df-838c-d9b60920cd91 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
6ae9299576 |
FN-8953: defer terminal wedge alerts during recovery
Hold terminal wedge alerts until their recovery window has elapsed. - Persist and settle pending wedge notifications across restarts. - Clear pending alerts on task progress and reconcile expired holds during self-healing. - Expose the settle window in notification settings with coverage for store and notification flows. Files changed: .changeset/fn-8953-wedge-settle-window.md | 7 + AGENTS.md | 1 + docs/architecture.md | 3 +- docs/settings-reference.md | 1 + .../core/src/__tests__/store-wedge-pending.test.ts | 56 +++++ packages/core/src/config/settings-schema.ts | 1 + packages/core/src/store.ts | 46 ++++ packages/core/src/types/settings/settings-scope.ts | 2 + packages/core/src/types/task/task-core.ts | 15 ++ .../app/components/settings/save-split.ts | 1 + .../sections/NotificationsSection.search.ts | 9 + .../settings/sections/NotificationsSection.tsx | 15 ++ .../settings-default-descriptions.test.tsx | 1 + ...self-healing-pending-wedge-notification.test.ts | 148 ++++++++++++ .../__tests__/notification-service.test.ts | 7 +- .../__tests__/task-wedge-notification.test.ts | 258 ++++++++++++++++++++- .../src/notification/notification-service.ts | 260 +++++++++++++++++++++ packages/engine/src/self-healing.ts | 38 +++ packages/i18n/locales/en/app.json | 2 + 19 files changed, 850 insertions(+), 21 deletions(-) Fusion-Task-Id: FN-8953 Fusion-Task-Lineage: fd5b5827-c69d-409f-86d5-01ff23405ee3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2bb8537352 |
FN-8616: make agent tool-output limits configurable
Expose the shared agent tool-output budget as a scoped operator setting with an explicit no-limit option. - Resolve global and project output caps with a safe finite default and zero sentinel. - Propagate configured budgets through PI and plugin runtime tool wrappers. - Add settings controls, localized labels, documentation, and regression coverage. Files changed: .changeset/fn-8616-tool-output-budget-setting.md | 7 ++++ docs/agents.md | 4 +- docs/settings-reference.md | 1 + .../core/src/__tests__/tool-output-budget.test.ts | 23 ++++++++--- packages/core/src/index.gate.ts | 2 + packages/core/src/index.ts | 2 + packages/core/src/settings-schema.ts | 12 ++++++ packages/core/src/tool-output-budget.ts | 31 +++++++++++++-- packages/core/src/types/settings-scope.ts | 8 ++++ .../app/components/settings/save-split.ts | 1 + .../sections/GlobalGeneralSection.search.ts | 20 ++++++++++ .../settings/sections/GlobalGeneralSection.tsx | 26 ++++++++++++ ...lobalGeneralSection.tool-output-budget.test.tsx | 46 ++++++++++++++++++++++ .../settings-default-descriptions.test.tsx | 1 + .../src/__tests__/agent-session-helpers.test.ts | 20 ++++++++++ .../src/__tests__/runtime-resolution.test.ts | 15 +++++++ .../__tests__/tool-output-budget-wrapper.test.ts | 45 ++++++++++++++++----- packages/engine/src/agent-runtime.ts | 2 + packages/engine/src/agent-session-helpers.ts | 18 +++++++-- packages/engine/src/pi.ts | 29 ++++++++++---- packages/engine/src/runtime-resolution.ts | 10 ++++- packages/i18n/locales/en/app.json | 4 ++ packages/i18n/locales/es/app.json | 6 ++- packages/i18n/locales/fr/app.json | 6 ++- packages/i18n/locales/ko/app.json | 6 ++- packages/i18n/locales/zh-CN/app.json | 6 ++- packages/i18n/locales/zh-TW/app.json | 6 ++- packages/i18n/src/resources.d.ts | 4 ++ 28 files changed, 323 insertions(+), 38 deletions(-) Fusion-Task-Id: FN-8616 Fusion-Task-Lineage: 3ca99a61-d6ae-48ff-98d2-f14a153aa2b7 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
99b80ad748 |
feat(dashboard): add opt-in auto-update and harden restart supervision
Add the `autoUpdateAndRestart` global setting (default off, Settings -> General next to Release channel). When enabled, the dashboard host installs available updates on the selected channel by itself and requests the supervised in-place restart. Supervised hosts only: without a parent to respawn, installing would leave a running process whose code no longer matches its own install. Fix two ways the restart affordance could silently do nothing: - The supervisor now stamps FUSION_SUPERVISOR_PID and supervision is only counted when that pid is the real parent. FUSION_RESTART_SUPERVISED is inherited by every process Fusion spawns, so `fn dashboard` launched from an agent terminal skipped its own supervisor while still advertising restart support -- a restart request then killed it for good. - Settings and the update banner probe /system/info on mount and treat capability as advisory: the button always issues the request and shows the server's actual refusal instead of sitting disabled after a failed probe. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
da1e445d6b |
FN-8310: add public-roadmap report deduplication
Add public-roadmap issues as a configurable, reviewable deduplication source for in-app reports. - Resolve roadmap settings across project, global, and tracking-repository fallbacks - Search and endorse matching open roadmap issues before filing duplicate reports - Expose and index roadmap controls with localized default descriptions Files changed: .changeset/fn-8310-public-roadmap-dedupe.md | 7 ++ docs/dashboard-guide.md | 2 +- docs/settings-reference.md | 4 +- .../core/src/__tests__/settings-parity.test.ts | 14 +++- packages/core/src/settings-schema.ts | 7 +- packages/core/src/types.ts | 13 +++- packages/dashboard/app/api/report.ts | 2 +- packages/dashboard/app/components/ReportModal.tsx | 18 ++--- .../dashboard/app/components/SettingsModal.tsx | 15 +++- .../app/components/__tests__/ReportModal.test.tsx | 12 ++-- .../__tests__/SettingsModal.general.test.tsx | 6 +- .../settings/__tests__/section-keys.test.ts | 5 +- .../app/components/settings/save-split.ts | 14 ++-- .../app/components/settings/section-keys.ts | 5 ++ .../settings/sections/GeneralSection.search.ts | 34 ++++++--- .../settings/sections/GeneralSection.tsx | 29 ++++++-- .../sections/SourceControlGlobalSection.search.ts | 27 +++++++ .../sections/SourceControlGlobalSection.tsx | 55 ++++++++++---- .../settings-default-descriptions.test.tsx | 4 +- .../src/__tests__/report-pipeline.test.ts | 73 ++++++++++++------- .../dashboard/src/__tests__/report-routes.test.ts | 23 +++--- packages/dashboard/src/report-pipeline.ts | 84 ++++++++++++++-------- .../dashboard/src/routes/register-report-routes.ts | 9 +-- packages/i18n/locales/en/app.json | 17 ++++- packages/i18n/locales/es/app.json | 17 ++++- packages/i18n/locales/fr/app.json | 17 ++++- packages/i18n/locales/ko/app.json | 17 ++++- packages/i18n/locales/zh-CN/app.json | 16 ++++- packages/i18n/locales/zh-TW/app.json | 16 ++++- 29 files changed, 409 insertions(+), 153 deletions(-) Fusion-Task-Id: FN-8310 Fusion-Task-Lineage: 0efa8d76-e849-4256-bdcd-e9d6dd612e41 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2302fb8a3d |
feat: add beta/stable release tracks with switchable update channel (#2345)
## Summary Fusion can now ship on two release tracks. Betas are cut from `main` as `vX.Y.Z-beta.N` (npm dist-tag `beta`, GitHub prerelease), stable releases are promoted to a long-lived `release` branch and published to `latest`, and users pick their track with the new `updateChannel` global setting — via **Settings → General → Release channel** or `fn update --channel <stable|beta>`. Previously everything was single-track: every publish landed on `latest` and every update surface could only see it. | | beta | stable | |---|---|---| | Cut from | `main` | `release` branch | | Version | `X.Y.Z-beta.N` (changesets pre-mode) | `X.Y.Z` | | npm dist-tag | `beta` | `latest` | | GitHub Release | prerelease | latest | | Homebrew tap / X draft | skipped | bumped / printed | ## How releasing works now `pnpm release` prompts for the channel and **defaults to beta**, so day-to-day releases are betas; stable is always an explicit choice. Choosing stable from `main` triggers assisted promotion: the script proposes the newest beta tag reachable from HEAD, verifies `release` fast-forwards to it, then runs the whole stable release inside a temporary git worktree on `release` — the primary checkout never leaves `main`. Changesets pre-mode preserves changeset files across betas, so the promoted stable release aggregates every changeset since the last stable into one clean changelog entry. ## Design decisions - **Every publish path names an explicit `--tag`.** A beta accidentally landing on `latest` is the one unrecoverable failure of a dual-track scheme, so nothing relies on npm's implicit default (`release.mjs`, `version.yml`). - **Beta channel resolves to semver-max of `latest` and `beta`**, so beta users are offered each promoted stable once it overtakes their prerelease. Switching beta → stable never downgrades; `fn update --channel stable --force` is the explicit escape hatch. - **One comparator instead of three.** CLI, dashboard, and desktop each had their own `isRemoteNewer` that ignored prerelease identifiers — `0.73.0-beta.2`, `-beta.3`, and `0.73.0` all compared equal, which breaks the moment any beta exists. They now share full SemVer-precedence helpers (`compareVersions`, `resolveUpdateTargetVersion`) from `@fusion/core`. - **Installs pin exact versions** (`@runfusion/fusion@0.73.0-beta.2`), never a dist-tag, so an install can't silently land on the wrong track. - **Desktop channels via electron-updater manifests.** Beta tags build desktop artifacts with `publish.channel=beta` (emitting `beta*.yml`); the app sets `channel`/`allowPrerelease` from the shared setting, re-read on every manual check. - **Update caches are channel-stamped** — a cache written for one channel is never served to the other, so switching tracks takes effect on the next check instead of after TTL. ## Test plan - New unit coverage: SemVer precedence + channel resolution in `@fusion/core` (30), channel behavior of the dashboard update check (28, incl. 9 new) and `fn update` (16, incl. 8 new: persist `--channel`, no-downgrade, `--force`, cache channel mismatch). - `pnpm verify:fast` green (scoped typecheck, builds, CLI build, boot smoke); desktop + settings-section suites green. - `release.mjs` dry-run matrix exercised by hand: channel prompt (default/override/invalid), branch preflights per channel, assisted-promotion target selection, fast-forward guard against a diverged `release` branch, and bootstrap when no `release` branch exists. - Not exercised live: an end-to-end publish (needs TTY authorization + real npm publish). First real run is the first `pnpm release --channel beta`. --- [](https://github.com/EveryInc/compound-engineering-plugin)  <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added beta and stable release channels across CLI, dashboard, and desktop updates. * Users can select a channel via Settings or `fn update --channel <stable|beta>` (stored as a global default). * Desktop beta releases now generate beta update manifests and publish as prereleases. * **Documentation** * Expanded release-track, settings, and CLI references to explain channel semantics and workflows. * **Bug Fixes** * Updates now pin the resolved version per channel, improve version comparison, and prevent unintended cross-channel downgrades unless `--force` is used. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d593d87686 |
feat(FN-8064): make proactive task chat optional
Fusion-Task-Id: FN-8064 |
||
|
|
2c17fa70ab | feat(postgres): make embedded connection cap configurable | ||
|
|
fd036665ae |
FN-8123: add agent clarification notifications
Add agent clarification notices with ntfy delivery and mailbox support. - Add configurable clarification ntfy topics and notification settings - Route agent clarification requests to ntfy and the planning mailbox - Update planning dialogs, translations, documentation, and regression tests Files changed: .changeset/fn-8123-agent-clarification.md | 7 + docs/dashboard-guide.md | 6 + docs/settings-reference.md | 1 + .../core/src/__tests__/global-settings.test.ts | 11 + packages/core/src/settings-schema.ts | 2 + packages/core/src/types.ts | 6 + .../app/__tests__/settings-save-split.test.ts | 13 ++ packages/dashboard/app/api/legacy.ts | 3 +- .../dashboard/app/components/PlanningModeModal.tsx | 29 ++- .../dashboard/app/components/SettingsModal.tsx | 1 + .../__tests__/PlanningModeModal.initial.test.tsx | 17 +- .../app/components/settings/save-split.ts | 1 + .../settings/sections/NotificationsSection.tsx | 11 + .../src/__tests__/routes-planning.test.ts | 7 +- packages/dashboard/src/planning.ts | 228 ++++++++++++++++----- .../src/routes/register-planning-subtask-routes.ts | 59 +++++- packages/i18n/locales/en/app.json | 4 + packages/i18n/src/resources.d.ts | 4 + 18 files changed, 346 insertions(+), 64 deletions(-) Fusion-Task-Id: FN-8123 Fusion-Task-Lineage: cf397749-01c6-44d6-8d12-8ce7f5627c29 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c6be0b158b |
FN-8129: centralize database backup settings
Move database backup policy and scheduling to shared global configuration. - Split project memory backups from cluster-wide database backup settings. - Migrate legacy backup values and routines safely into central global storage. - Schedule and dispatch one shared PostgreSQL backup routine across project engines. Files changed: .changeset/fn-8129-backup-settings-scope-split.md | 7 + docs/dashboard-guide.md | 2 + docs/settings-reference.md | 10 +- packages/cli/src/commands/backup.ts | 3 +- .../__tests__/backup-settings-migration.test.ts | 50 ++++++ .../src/__tests__/backup-settings-scope.test.ts | 27 +++ packages/core/src/backup-settings-migration.ts | 188 +++++++++++++++++++++ packages/core/src/backup.ts | 77 +++++---- packages/core/src/global-routine-store.ts | 104 ++++++++++++ packages/core/src/index.gate.ts | 6 +- packages/core/src/index.ts | 6 +- .../core/src/postgres/migrations/0000_initial.sql | 19 +++ .../postgres/migrations/0015_global_routines.sql | 19 +++ packages/core/src/postgres/schema-applier.ts | 19 ++- packages/core/src/postgres/schema/central.ts | 21 ++- packages/core/src/postgres/startup-factory.ts | 11 ++ packages/core/src/settings-schema.ts | 14 +- packages/core/src/types.ts | 31 +++- .../dashboard/app/components/SettingsModal.tsx | 10 +- .../settings/__tests__/section-keys.test.ts | 1 + .../app/components/settings/save-split.ts | 2 + .../search/__tests__/settings-search-index.test.ts | 1 + .../settings/search/entries.ts | 2 + .../app/components/settings/section-keys.ts | 4 - .../settings/sections/BackupsSection.search.ts | 40 ----- .../settings/sections/BackupsSection.tsx | 112 +----------- .../sections/DatabaseBackupsSection.search.ts | 51 ++++++ .../settings/sections/DatabaseBackupsSection.tsx | 142 ++++++++++++++++ .../settings-default-descriptions.test.tsx | 1 + packages/dashboard/src/routes.ts | 12 +- .../src/routes/register-settings-memory-routes.ts | 41 ++--- .../engine/src/__tests__/routine-scheduler.test.ts | 55 +++++- packages/engine/src/cron-runner.ts | 4 +- packages/engine/src/routine-runner.ts | 67 +++++--- packages/engine/src/routine-scheduler.ts | 35 +++- 35 files changed, 929 insertions(+), 265 deletions(-) Fusion-Task-Id: FN-8129 Fusion-Task-Lineage: af17f39a-7f1c-40ff-8a4a-cd63895cd532 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f63818a6e9 |
FN-8072: add critical-action confirmation skip setting
Add a global operator preference that bypasses centralized critical-action confirmation dialogs. - Add a global-only skipConfirmationDialogs setting and Settings toggle - Return primary/default confirmation results without rendering dialogs when enabled - Route task reset actions through the centralized confirmation seam and add coverage - Document the setting and add a minor changeset Files changed: .changeset/fn-8072-skip-confirmation-dialogs.md | 7 +++++ docs/settings-reference.md | 1 + .../core/src/__tests__/settings-defaults.test.ts | 12 ++++++++- packages/core/src/settings-schema.ts | 5 ++++ packages/core/src/types.ts | 5 ++++ packages/dashboard/app/App.tsx | 11 ++++---- packages/dashboard/app/components/ListView.tsx | 20 +++++++++++---- packages/dashboard/app/components/TaskCard.tsx | 22 +++++++++++----- .../dashboard/app/components/TaskDetailModal.tsx | 26 +++++++++++-------- .../app/components/__tests__/ListView.test.tsx | 13 ++++++++++ .../__tests__/SettingsModal.general.test.tsx | 19 ++++++++++++++ .../app/components/__tests__/TaskCard.test.tsx | 17 ++++++++++++ .../components/__tests__/TaskDetailModal.test.tsx | 25 ++++++++++++++++++ .../app/components/settings/save-split.ts | 1 + .../sections/GlobalGeneralSection.search.ts | 10 ++++++++ .../settings/sections/GlobalGeneralSection.tsx | 10 ++++++++ .../settings-default-descriptions.test.tsx | 1 + .../app/hooks/__tests__/useConfirm.test.ts | 30 ++++++++++++++++++++++ packages/dashboard/app/hooks/useAppSettings.ts | 4 +++ packages/dashboard/app/hooks/useConfirm.ts | 21 ++++++++++++++- packages/i18n/locales/en/app.json | 4 ++- 21 files changed, 235 insertions(+), 29 deletions(-) Fusion-Task-Id: FN-8072 Fusion-Task-Lineage: bab4b8f2-5996-4161-8733-8e03bb6a7024 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
5b4ec4c08f |
FN-8042: add merger fallback model lane
Add configurable project fallback models for AI merger retries. - Resolve complete project merger fallback pairs before the shared global fallback. - Expose merger fallback model and thinking controls in Project Models with reset-aware persistence. - Apply the fallback lane across merger, review, PR-response, and recovery sessions with tests and documentation. Files changed: .changeset/fn-8042-merger-fallback-model.md | 7 +++ docs/settings-reference.md | 4 +- .../core/src/__tests__/model-resolution.test.ts | 24 ++++++++++ .../core/src/__tests__/settings-parity.test.ts | 3 ++ packages/core/src/index.gate.ts | 1 + packages/core/src/index.ts | 1 + packages/core/src/model-resolution.ts | 22 +++++++++ packages/core/src/settings-schema.ts | 4 ++ packages/core/src/types.ts | 13 ++++++ .../app/__tests__/settings-save-split.test.ts | 41 +++++++++++++++++ .../app/__tests__/settings-sections.test.tsx | 36 +++++++++++++++ .../app/components/settings/save-split.ts | 7 +-- .../settings/sections/ProjectModelsSection.tsx | 53 +++++++++++++++++++++- .../settings-default-descriptions.test.tsx | 3 ++ .../src/__tests__/agent-session-helpers.test.ts | 1 + .../__tests__/mcp-pr-response-forwarding.test.ts | 1 + packages/engine/src/agent-session-helpers.ts | 10 +++- packages/engine/src/merger-ai.ts | 17 +++++-- packages/engine/src/merger.ts | 43 +++++++++++++----- packages/engine/src/pr-response-run-ops.ts | 11 +++-- 20 files changed, 276 insertions(+), 26 deletions(-) Fusion-Task-Id: FN-8042 Fusion-Task-Lineage: 31762a72-461e-438c-a12d-2816580283fd Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
55745af80f |
Settings: one type scale, every setting searchable, nav grouped by topic (#2158)
Settings had three compounding problems: you couldn't find a setting, and once you found it, it didn't look like its neighbour. ## Organization — the nav was grouped by the wrong thing It was grouped by **scope** (Global / Runtimes / Project). Scope is an *attribute* of a setting, not a category — nobody opens Settings thinking "I need a project-authority setting." That single choice split five concepts across two groups, including **two nav entries both labelled "MCP Servers"**, distinguishable only by a small icon. Now grouped by topic, with paired sections adjacent and stating their own scope:  ``` PREFERENCES Appearance · Keyboard Shortcuts · Notifications · General · Global PROJECT General · Project · Commands & Scripts · Worktrees · Merge AI & MODELS Models · Global · Models · Project · CLI Agents · Agents & Permissions · Prompts · Memory AUTOMATION Scheduling & Capacity · Scheduled Evals INTEGRATIONS Authentication · MCP Servers · Global · MCP Servers · Project · Plugins · Runtimes · Secrets INFRASTRUCTURE Node Sync · Node Routing · Remote Access · Backups ADVANCED Experimental Features ``` ## Search — it now finds settings, not just sections Search matched only hand-written `searchableText` keyword arrays per nav entry, and those demonstrably rotted: Project Models accumulated 20 keywords across **two separate fixes** (FN-7907, then title-summarization on 2026-07-14) because operators searched "summarize" and got nothing. Every setting is now indexed from **its real label and help text** — 123 settings across 18 sections, zero curated keywords. The same query that was patched twice by hand:  Two of those four hits match on *help text*, which a keyword index structurally cannot do. Picking a result jumps to the exact control, **opens its collapsed disclosure**, and highlights it:  **This can't rot again.** `settings-search-index.test.ts` extracts every `descriptor={{ key }}` from section sources and fails the build if one isn't indexed. "All settings are searchable" is an enforced invariant, not a promise. ## Consistency — one type scale A text field's label and a toggle's label in the same section were styled **three different ways**: `.form-group label` (12px/600/uppercase/muted), a `.settings-content` override narrowing it to 0.72rem, and `.checkbox-label` (13px/500/sentence-case) whose every declaration carried `!important` purely to out-specify the other two. | | Before | After | |---|---|---| | Sections on shared primitives | 1 | **18** | | Indexed searchable settings | 0 | **123** | | `form-group` in settings | 226 | **98** | | `checkbox-label` in settings | 79 | **40** |         **Global `.form-group` is untouched** — 35 non-settings files style forms with it, so settings migrate *off* it rather than restyle it underneath the rest of the dashboard. ### A real latent bug this surfaced `--font-size-sm` and `--font-size-md` were named by **12 declarations** across AgentDetailView, DockTaskList, SetupWizardModal, and ModelOnboardingModal — but **defined nowhere**. Those rules silently no-op'd and inherited. The command-center token guard is the only thing that catches this class of omission and it doesn't cover those files. The scale is now complete (`2xs · xs · sm · base · md · lg`); `md` is 1.125rem to hold current rendering, since unstyled `h3` already inherits the 1.17em UA default. ## What deliberately did *not* migrate Some rows stay bespoke **on purpose**, not from incompleteness: - **Password fields** (`ntfyAccessToken`, `githubAuthToken`, `gitlabAuthToken`) — `SettingsTextRow` hardcodes `type="text"`, so migrating would have **rendered stored tokens unmasked**. - **Help text with embedded `<code>`/links** — `descriptor.help` is a single string; flattening would drop markup or reword copy. - **`<details>` progressive disclosure** in Merge — a descriptor's help renders unconditionally, so migrating ~10 rows would delete the disclosure and produce a wall of prose. - **Dynamic flag lists** (Experimental) and bespoke editors/CRUD (Prompts, Agents & Permissions, Plugins, KeyboardShortcuts' capture widget) — no settings field name and no i18n key to anchor honestly. ## Data-model ambiguities surfaced (not papered over) These need a human call and are **not** fixed here: - **Five keys are declared in BOTH `DEFAULT_GLOBAL_SETTINGS` and `DEFAULT_PROJECT_SETTINGS`**: `worktrunk`, `testMode`, `gitlabEnabled`, `gitlabAuthToken`, `gitlabAuthTokenType`. No scope badge can be stamped honestly, so those rows are left bespoke. - **`globalMaxConcurrent` lives in the *project* blob** despite its name, its dedicated global endpoint, and the "Global" header it renders under. Its badge is omitted rather than assert a contradiction. - **Two settings were editable from two screens**: `gitlabEnabled` (General + Merge) and `githubTrackingDefaultRepo` (General + Global General). Both are ambiguous-scope and custom widgets, so deduplication is left as follow-up. ## Follow-ups from review **`SettingsTextRow` gained `type`, so the token rows could migrate.** It hardcoded `type="text"`, which is why every secret-bearing row (ntfy access token, GitHub/GitLab tokens, the Cloudflare tunnel token) stayed hand-rolled — migrating would have rendered stored secrets in plain text. `password` rows now default to `autocomplete="off"` so a browser never offers to save an API token, and masking is pinned by tests: a regression there would not throw and would not look wrong in review, the field would simply render the token. That also made them findable. Searching "token" previously matched nothing useful; it now returns 9 settings including *Access token* and *Tunnel token*: **Jump-to-field now reveals collapsed disclosures.** Rows inside a closed `<details>` are in the DOM but invisible, so the jump scrolled to and highlighted a control the operator could not see. The settings most worth searching for are exactly the ones behind "Advanced". **The scope banner is gone.** It claimed one scope for a whole section, which was false wherever a section mixed them — Appearance is a "global" nav entry whose task-presentation toggles are all project-scoped. Per-row badges already say this accurately, so the banner and its dead CSS are removed. **Scheduling is split by scope.** `globalMaxConcurrent` moved to its own `Scheduling · Global` section instead of sitting above the project settings behind an in-section subheading. One section held two authority levels, so "does this affect my other projects?" depended on which subheading you had scrolled past — and a search result landing mid-section shows no subheading at all.  **Text-entry padding is now genuinely uniform.** Settings shipped two input treatments: `.input`/`.select` (6px 10px at 13px) and the global `.form-group input` rule (8px 12px at 14px). Padding depended on whether an ancestor happened to be a `.form-group`, and because `.form-group input` (0,1,1) out-specifies `.input` (0,1,0), naming the standard class on a nested control did nothing. Measured in-browser after the fix: **51 controls across four sections, one appearance, zero outliers.** The same specificity trap was silently re-imposing the uppercase/muted label treatment on migrated rows nested in a `.form-group`; fixed as an invariant rather than per-row, since sections legitimately keep `.form-group` around bespoke content. ## Reconciling with #2147 (please review this call) PR #2147 landed while this branch was open and deliberately moved the two import auto-translate controls **off** `SettingsToggleRow` onto `checkbox-label`, pinning that markup with a test written to survive *"a refactor back onto the primitive"*. Its objection was that the primitive rendered a right-aligned toggle switch clashing with the section's native checkboxes — two idioms in one section. Both halves of that objection are now gone: the primitive renders a native checkbox **before** its label, and every checkbox in that section — including the neighbour the test asserts parity against — renders through it. The idiom split is resolved by migrating all of them rather than de-migrating these two, so the markup assertions now track the primitive. **Every behavioural contract from #2147 is kept and still pinned**, and one was a real bug on this branch: switching auto-translate off wrote `false` where it must write `undefined`, leaving an explicit opt-out in the settings blob instead of staying unset. #2147's curated translate keywords are preserved for the genuine vocabulary gaps ("localize", "localization", "foreign language issues") that appear in no copy. FN-8016's rewritten `taskPopupsBoardListOnly` copy (default now enabled) is adopted into the migrated row and its search entry. Worth noting: #2147's own FNXC says the translate controls were *"effectively unfindable"* because *"settings search only matches curated terms plus advertised i18n keys"* — 25 keywords hand-added days ago. That is precisely the rot this PR's derived index removes. ## Source Control — the duplicate had a cause GitLab settings were split across **three** sections (General: enable + URLs; Merge: auth token + type; Global General: all five at global scope) and GitHub across two. That split is *why* `gitlabEnabled` ended up writable from both General and Merge — two enable toggles for one key, last-save-wins. A `Source Control · Global` / `· Project` pair now owns all 17 keys, adjacent under Integrations, with **one** GitLab disclosure and **one** enable toggle:  Key ownership moved with them in `section-keys.ts` / `save-split.ts`, so every key has exactly one owner (`section-keys.test.ts` enforces disjointness). **A latent bug surfaced by the move:** nine sites outside the registries hardcode `"global-general"`/`"general"` and silently gate **scope routing** — four in `save-split.ts`, five in `SettingsModal.tsx`. Left stale, global GitLab edits would have been written as project overrides. Also verified against the schema: **all five `gitlab*` keys AND `githubTrackingDefaultRepo`** are declared in both defaults (more than the four originally identified), so those rows carry no scope badge rather than assert a scope the data model can't support. ## Help moved behind a "?" beside every label Rendering every description inline turned dense sections into walls of prose — median help is ~100 chars, some past 400. That pressure is what made Merge invent its own "More details" disclosure, so one section showed two idioms. Measured across sections, Merge's help was **not** unusually long (median 103 vs Appearance's 168, which rendered inline), so the disclosure wasn't earning its keep. The copy is deferred **visually, not removed**: the bubble is always rendered and only fades in, so it stays in the accessibility tree for `aria-describedby`, stays findable with in-page find, and **the search index keeps matching on help text**. Errors are never deferred — a validation message you must hunt for is one you won't see. Only ~24 of 136 `<small>` blocks were actually row help. The rest stay inline on purpose and aren't help: validation errors, live status, empty-state explanations, per-option descriptions inside a multi-select, and copy explaining *why* a control is disabled. `children: ReactNode` (not a string) is what let the `<code>`-bearing and link-bearing rows migrate without rewording your copy — a string API is precisely why they were hand-rolled before. ### Mobile, verified on a 390px viewport  Driving a real phone-sized viewport caught two bugs that neither jsdom nor code review did: - **Bubble rendered off-screen.** The label line reads "Name [scope] ?", so the "?" sits well right of centre; anchored to the trigger, the bubble spanned x=338→658 against a 390px screen — 268px unreachable. `max-width` clamps width but can't help when the *anchor* is near the edge. It now anchors to the row (`inset-inline: 0`): re-measured at x=20→370 inside 390. An earlier comment claimed this behaviour; only the comment existed. - **Two bubbles open at once.** Outside-`pointerdown` dismissal misses a path: `click` fires with **no pointer event** when Enter/Space activates a focused trigger, so a keyboard user opening a second tip left the first open underneath. Tips now broadcast on open and close each other; the regression test asserts the bare-click path specifically. Also verified on touch: tapping outside dismisses, and opening a second tip closes the first — no stranded bubbles. **Checkbox wrapping.** On a 390px viewport a long label ("Keep task popups on the view where they were opened") stranded its checkbox alone on line 1, with the text on lines 2-3 and the badge on line 4. The head was a flex row and the label was a flex ITEM, so once it no longer fit beside the checkbox the whole label wrapped rather than its text. Label + badge + tip now form one group that absorbs the wrapping, leaving the checkbox as the only sibling item; continuation lines align under the first word. Audited every checkbox and radio on all 31 screens at 390px afterwards: **101 controls, all on the first line of their label text.** (The audit's first pass flagged 41 — all false positives from measuring `<label>` elements whose text is a bare text node, i.e. the label box included the checkbox. Re-measuring the text nodes themselves via Range cleared them.) ### Every row, including the ones that stayed bespoke Merge was the last holdout — 18 `<details>` "More details" disclosures plus 4 inline blocks, an idiom it invented and no other section used. All 22 now use the same "?":  Project Models likewise rendered lane help as prose while the global lanes next door already used the tip; its help now hangs on the existing lane label row beside the Override/Inherited badge (the badge is live state and stays visible; the fallback chain behind it is what you open deliberately). **Audited all 31 screens programmatically** (label treatments, control padding, row overflow, leftover banners, horizontal scroll): - **one label treatment on every screen**, one control treatment, zero overflowing rows, zero banners, no horizontal scroll - the copy still rendered inline is deliberately not row help: validation errors, live status, block descriptions, per-option text inside multi-selects, and copy explaining *why* a control is disabled **Known gap:** the three plugin runtime screens (Hermes / OpenClaw / Paperclip) still render inline help. They delegate to `HermesRuntimeCard` / `OpenClawRuntimeCard` / `PaperclipRuntimeCard` — separate card components outside the settings tree — and their copy *is* genuine row help ("Leave blank to resolve hermes from your PATH"). They are advanced-only and were left out of this pass rather than swept in at the end without review. ## Padding and label consistency (measured, not eyeballed) Two idioms were still visible on one screen — Merge rendered "PLAN APPROVAL MODE" in caps directly above "Auto-merge conflict retries" in sentence case. Rows that deliberately stay bespoke inherited the global `.form-group label` treatment. | | Before | After | |---|---|---| | Label treatments | uppercase/muted/11.5px **and** sentence/14px | **70 labels, one treatment** | | Control padding | `6px 10px` **and** `8px 12px` | **81 controls, one treatment** | | Row gaps | 12 / 16 / 20 by adjacency | **0** — every row owns its space | The cause was a specificity trap: `.form-group input` (0,1,1) out-specifies `.input` (0,1,0), so naming the standard class on a nested control did nothing. Fixed settings-scoped; the global `.form-group` is untouched (35 non-settings files depend on it, where uppercase is that context's convention). ## Advanced settings toggle — verified Confirmed in-browser after the regroup: **OFF → 15 sections / 5 groups; ON → 31 sections / 7 groups**, `data-show-advanced` flips, preference persists. The now-empty **Infrastructure and Advanced group headers are correctly hidden** when off — the case the regroup could have broken, since those groups contain only advanced sections. ## Pre-existing failures found (verified NOT caused by this PR) Each verified by running the identical file on the parent commit and diffing the **failure sets**, not just the counts: | Failure | Verified | |---|---| | `SettingsModal.scheduling-merge.test.tsx` — 55 failures | identical set before/after | | `SettingsModal.remote-notifications.test.tsx` — 16 failures | identical set before/after | | `settings-default-descriptions.test.tsx` — `sqliteMigrationNotice`, `postgresMigrationInboxMessageSentAt` | fails on clean tree | | i18n `parity.test.ts` — 12 violations (`settings.general.autoTranslate*`, `taskDetail.plan.*`) | 12 before, 12 after | **This PR adds zero new failures.** Fixed along the way: a stale `AppearanceSection` assertion testing copy FN-7945 deliberately rewrote (failing silently), the ungrammatical "1 matching sections", and `“` rendering literally on screen. ## Verification - `tsc --noEmit -p tsconfig.app.json` → **0 errors** (note: the default `tsconfig.json` only covers `src/` and does **not** typecheck `app/`) - `pnpm test:gate` → **63 passed** - Settings surface → 68 failures, every one a verified subset of the pre-existing baseline, diffed by failure SET not count (this branch incidentally fixes 4) - `pnpm test:gate` 63/63 · lint clean across 83 changed files · `tsc -p tsconfig.app.json` 0 errors - Rebased onto `main`: conflicts with #2147 and FN-8016 resolved - Driven in a real browser at 1440px and 390px: search, jump-to-field, help tips, advanced toggle, and every migrated section - Driven in a real browser: search, jump-to-field, highlight, and every migrated section 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Settings search now indexes individual settings controls, ranks matches, and navigates directly to the exact row with a temporary highlight. * **UI Improvements** * Migrated settings sections to shared row primitives (toggle/select/number/text/textarea) for consistent spacing and touch-friendly controls. * Updated typography to a complete tokenized type scale; added the “?” help tip and tokenized row highlight/error styling. * Navigation and search labels now show clear Global vs Project scope. * **Bug Fixes** * Improved search accuracy using label/help/keywords and fixed settings search counts/pluralization and MCP scope labels. * **Tests** * Added/updated checks to ensure the settings search index stays consistent with rendered rows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0863c0fb58 |
feat(dashboard): auto-translate foreign-language GitHub issues on import (#2141)
## Why The Import Tasks panel routinely lists issues in languages the operator cannot read. Translation already shipped in #2128, but deliberately **opt-in and preview-only** — its header comment read *"Translation is opt-in (never automatic) so import provenance stays faithful until the operator asks."* This reverses that decision **behind a default-off setting**, so operators who never opt in keep byte-faithful import provenance. The superseded comment is kept and annotated rather than deleted, so the reason the rule changed stays in the code. ### The structural gap #2128 left `POST /github/issues/import` accepts only `{owner, repo, issueNumber}` and **re-fetches the issue server-side**. A translation held in React state could never reach the created task, and the in-memory cache died with the modal. That is why the cache here is server-side rather than in the hook — it's what makes "imported issues carry the translated version" actually true. ## What operators get Auto-translate is **off by default**. When enabled: - The **50 most recent OPEN** foreign-language issues translate on panel load — **list titles**, not just the preview, so the list reads in your language before you click anything. - Translations show **by default**, with a toggle back to the original (hover a translated list title to see the original). - Translations **persist until the issue closes**, so re-opening the panel neither waits nor re-bills. - **Both single and batch import** carry the translation, so the created task reads like the preview you approved. - A **target language** setting (unset = follow the dashboard language) and a dedicated **model lane**, so you can pin a cheap/fast model without dragging the summarization lane onto it. ## Notable decisions | Decision | Why | |---|---| | Detect **before** the model | An issue already in the target language is never sent. Without this, an English repo with the setting on would bill every issue to return its input unchanged. | | Detection moved to `@fusion/core` | The panel and the server must not disagree about which issues are foreign; two copies of a heuristic drift. | | Own rate-limit budget | Translation shared a 10/hour budget with refine/goal-draft. Fanning out per-issue would fail partway **and** starve refine for the hour. | | Cache keyed on a **source hash** | An edited issue misses the cache and re-translates instead of serving stale prose. | | Import is **cache-read only** | A miss imports the original. Import must never block on, or fail because of, translation. | | `project_id` leads the cache PK + full RLS contract | All projects share one flat `project` schema. `verification_cache`'s PK predates that discipline; this table does not copy that mistake. | ## Verification - ✅ `pnpm lint`, `@fusion/core` + `@fusion/dashboard` typecheck - ✅ `pnpm verify:fast` — build + scoped typecheck + real boot smoke (`/api/health`) - ✅ `pnpm test:gate` — 479 tests - ✅ 19 new tests covering the billing invariants (off/closed/same-language ⇒ **no model call**), cache hit/miss-on-edit, the 50 cap, and per-item fail-soft - ✅ `schema-applier` real-Postgres suite (46 tests) exercises migration `0010` and its isolation invariant **Pre-existing failures NOT touched** (confirmed red on `HEAD` before this branch): `AppearanceSection`'s task-popup test, and two PG-cutover keys (`sqliteMigrationNotice`, `postgresMigrationInboxMessageSentAt`) missing description mappings. I left the latter rather than guess an allowlist entry that could mask a real coverage gap. ## Reviewer notes - Short Latin-script prose (a one-line Spanish title) rates only *medium* confidence and won't auto-translate — the existing heuristic is deliberately conservative so English issues are never billed. CJK detects regardless of length. The threshold is the knob if you'd rather bias toward translating. - The RLS/isolation contract in migration `0010` is the part most worth a careful look. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7261083781 |
fix(dashboard): isolate MCP settings scopes (#2116)
## Summary - bind Global and Project MCP editors to their raw values from `/api/settings/scopes` - keep edits isolated in the owning scope instead of mutating the merged project-effective form - persist changed MCP scopes independently of which Settings section is visible when Save is pressed - add unit and SettingsModal regressions for opposite scope values and edit → navigate → save ## Root cause `SettingsModal` passed the merged project-effective `form.mcpServers` to both MCP sections. A project override could therefore appear as the Global MCP value. Saving the apparent global change could then be dropped as a no-op when compared with the actual global-scoped value. The first fix still tied save routing to the active section. The follow-up carries both raw scoped MCP values through `splitSettingsSave`, where changed-only comparisons persist each owning scope even after navigation. ## Testing - `pnpm exec vitest run --project dashboard-app app/__tests__/settings-save-split.test.ts` (32 passed on PR branch) - `pnpm exec vitest run --project dashboard-app-quality-settings app/components/__tests__/SettingsModal.general.test.tsx` (84 passed) - `pnpm run typecheck` - `pnpm exec eslint app/components/SettingsModal.tsx app/components/settings/save-split.ts app/__tests__/settings-save-split.test.ts app/components/__tests__/SettingsModal.general.test.tsx` - `pnpm run build` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed MCP settings so global and project configurations remain correctly separated. * Prevented inherited global settings from appearing as project overrides. * Preserved MCP edits when navigating between Settings sections. * Ensured unchanged settings are not unnecessarily saved. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d4001ab0ee |
feat: make merger AI model configurable under Global and Project Models
Add a dedicated merger model lane (project + global provider/model/thinking) so merge-agent sessions no longer share only the default model, without inheriting executor/planner/reviewer lanes. |
||
|
|
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> |
||
|
|
f992e6aefa |
FN-7553: add dedicated keyboard shortcuts settings section
Adds a standalone Keyboard Shortcuts settings section with an easier-to-use capture input and support for more shortcut actions. - Introduce a new KeyboardShortcutsSection with a dedicated ShortcutCaptureInput component for recording key combos - Split keyboard-shortcut settings out of the general settings section into their own settings tab - Extend the shortcut schema/types and useDashboardKeyboardShortcuts hook to support additional actions - Update settings save-split, section-keys, and defaults/parity tests to cover the new section - Update dashboard docs and add a changeset for the new settings section Files changed: .changeset/fn-7553-keyboard-shortcuts-section.md | 7 + docs/dashboard-guide.md | 22 ++- packages/core/src/__tests__/global-settings.test.ts | 9 +- packages/core/src/__tests__/settings-defaults.test.ts | 4 + packages/core/src/__tests__/settings-parity.test.ts | 2 +- packages/core/src/settings-schema.ts | 6 +- packages/core/src/types.ts | 12 ++ packages/dashboard/app/App.tsx | 26 +++- packages/dashboard/app/__tests__/App.keyboard-shortcuts.test.tsx | 47 ++++++- packages/dashboard/app/components/SettingsModal.css | 56 ++++++-- packages/dashboard/app/components/SettingsModal.tsx | 30 +++- packages/dashboard/app/components/__tests__/SettingsModal.general.test.tsx | 63 --------- packages/dashboard/app/components/__tests__/SettingsModal.keyboardShortcuts.test.tsx | 156 +++++++++++++++++++++ packages/dashboard/app/components/settings/__tests__/section-keys.test.ts | 1 + packages/dashboard/app/components/settings/save-split.ts | 6 +- packages/dashboard/app/components/settings/sections/GlobalGeneralSection.tsx | 38 ----- packages/dashboard/app/components/settings/sections/KeyboardShortcutsSection.tsx | 78 +++++++++++ packages/dashboard/app/components/settings/sections/ShortcutCaptureInput.tsx | 118 ++++++++++++++++ packages/dashboard/app/components/settings/sections/__tests__/KeyboardShortcutsSection.test.tsx | 113 +++++++++++++++ packages/dashboard/app/hooks/__tests__/useDashboardKeyboardShortcuts.test.tsx | 73 +++++++++- packages/dashboard/app/hooks/useDashboardKeyboardShortcuts.ts | 38 ++++- packages/dashboard/app/utils/__tests__/keyboardShortcuts.test.ts | 37 ++++- packages/dashboard/app/utils/keyboardShortcuts.ts | 54 ++++++- 23 files changed, 854 insertions(+), 142 deletions(-) Fusion-Task-Id: FN-7553 Fusion-Task-Lineage: 51c1ad69-fbd3-45ce-8d2d-45d9962d7b76 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ec9ac61c19 |
FN-7535: fix global GitLab settings not persisting on save
Fixes splitSettingsSave so the five global GitLab keys are diffed only against the scoped global initial values, not the project-merged effective values, so a real global edit is no longer dropped when it happens to match a project override. - Add GLOBAL_GITLAB_SCOPED_ONLY_KEYS (gitlabEnabled, gitlabInstanceUrl, gitlabApiBaseUrl, gitlabAuthToken, gitlabAuthTokenType) that never fall back to merged initialValues when computing the save diff - Update splitSettingsSave to treat these keys as scoped-global-only, treating a missing scoped-global initial as undefined rather than falling back to the merged value - Add regression tests in settings-save-split.test.ts covering the scoped-vs-merged diff behavior - Add regression tests in SettingsModal.general.test.tsx covering the save flow end-to-end - Add changeset fn-7535-global-gitlab-setting-save.md (patch, fix) Files changed: .changeset/fn-7535-global-gitlab-setting-save.md | 7 +++ .../app/__tests__/settings-save-split.test.ts | 62 ++++++++++++++++++++++ .../__tests__/SettingsModal.general.test.tsx | 36 +++++++++++++ .../app/components/settings/save-split.ts | 26 ++++++++- 4 files changed, 129 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7535 Fusion-Task-Lineage: f9cd212e-a691-4cd9-8946-48c59537d583 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
87a700cd4d |
FN-7506: add scoped settings reset actions
Add a Settings footer reset flow for scoped menu and project-wide defaults. - Add Reset Settings dialog actions for the active settings menu and all project settings. - Track section-owned settings keys in a shared scope-aware registry and reuse it for save/reset validation. - Cover modal/mobile reset behavior, registry invariants, docs, i18n strings, and a release changeset. Files changed: .changeset/fn-7506-settings-reset.md | 7 + docs/dashboard-guide.md | 12 + .../dashboard/app/components/SettingsModal.css | 33 +++ .../dashboard/app/components/SettingsModal.tsx | 215 +++++++++++++++++- .../__tests__/SettingsModal.general.test.tsx | 145 ++++++++++++ .../components/__tests__/settings-mobile.test.tsx | 37 +++- .../settings/__tests__/section-keys.test.ts | 171 ++++++++++++++ .../app/components/settings/save-split.ts | 9 +- .../app/components/settings/section-keys.ts | 246 +++++++++++++++++++++ packages/i18n/locales/en/app.json | 11 + packages/i18n/locales/zh-CN/app.json | 11 + 11 files changed, 886 insertions(+), 11 deletions(-) Fusion-Task-Id: FN-7506 Fusion-Task-Lineage: a627e820-fe3b-42c5-adf2-97469bbe7a3b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2f23d2260d |
FN-7494: add configurable dashboard shortcuts
Add configurable dashboard keyboard shortcuts for opening Quick Chat and Terminal. - Add global settings defaults, schemas, persistence, and Settings UI controls for dashboard shortcuts. - Register safe document-level shortcut handling with editable-target guards and Escape popup dismissal. - Normalize shortcut strings, detect disabled/conflicting bindings, and document operator behavior. - Cover shortcut parsing, dashboard listener behavior, and settings persistence with tests. Files changed: .changeset/fn-7494-keyboard-shortcuts.md | 7 + docs/dashboard-guide.md | 14 ++ .../core/src/__tests__/global-settings.test.ts | 20 +++ .../core/src/__tests__/settings-defaults.test.ts | 10 ++ .../core/src/__tests__/settings-parity.test.ts | 10 ++ packages/core/src/__tests__/store-settings.test.ts | 10 ++ packages/core/src/settings-schema.ts | 8 + packages/core/src/types.ts | 12 ++ packages/dashboard/app/App.tsx | 52 ++++++ .../dashboard/app/components/SettingsModal.css | 21 +++ .../dashboard/app/components/SettingsModal.tsx | 11 ++ .../__tests__/SettingsModal.general.test.tsx | 63 ++++++++ .../app/components/settings/save-split.ts | 1 + .../settings/sections/GlobalGeneralSection.tsx | 38 +++++ .../useDashboardKeyboardShortcuts.test.tsx | 101 ++++++++++++ packages/dashboard/app/hooks/useAppSettings.ts | 8 +- .../app/hooks/useDashboardKeyboardShortcuts.ts | 66 ++++++++ .../app/utils/__tests__/keyboardShortcuts.test.ts | 76 +++++++++ packages/dashboard/app/utils/keyboardShortcuts.ts | 175 +++++++++++++++++++++ 19 files changed, 702 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7494 Fusion-Task-Lineage: 30445f4d-c0c5-4657-bd79-fc2acaf3c37d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
f9733341b5 |
FN-7453: add GitLab enablement controls
Add a settings-controlled GitLab enablement path while preserving saved GitLab configuration. - Add project and global GitLab enable settings with collapsible Settings UI for URL and token controls. - Gate GitLab auth, import loading, and import actions when GitLab integration is disabled. - Preserve global GitLab values separately during global settings saves and document the new behavior. - Cover enablement resolution, settings save behavior, disabled import UI, and GitLab route/auth gating with tests. Files changed: .changeset/fn-7453-gitlab-enable-disclosure.md | 7 ++ docs/dashboard-guide.md | 7 ++ docs/gitlab-parity-inventory.md | 1 + docs/settings-reference.md | 4 ++ docs/task-management.md | 6 +- packages/core/src/__tests__/gitlab-config.test.ts | 17 ++++- .../core/src/__tests__/settings-parity.test.ts | 18 +++-- packages/core/src/gitlab-config.ts | 15 ++++- packages/core/src/index.ts | 2 +- packages/core/src/settings-schema.ts | 2 + packages/core/src/types.ts | 5 ++ .../app/__tests__/settings-save-split.test.ts | 20 +++--- .../dashboard/app/components/GitHubImportModal.tsx | 43 +++++++++--- .../dashboard/app/components/SettingsModal.css | 77 +++++++++++++++++++++ .../dashboard/app/components/SettingsModal.tsx | 34 ++++++++- .../__tests__/GitHubImportModal.test.tsx | 19 ++++++ .../__tests__/SettingsModal.general.test.tsx | 78 ++++++++++++++++++++++ .../SettingsModal.scheduling-merge.test.tsx | 7 +- .../app/components/settings/save-split.ts | 5 +- .../settings/sections/GeneralSection.tsx | 36 ++++++---- .../settings/sections/GlobalGeneralSection.tsx | 71 ++++++++++++-------- .../components/settings/sections/MergeSection.tsx | 44 +++++++----- .../dashboard/src/__tests__/gitlab-auth.test.ts | 20 ++++++ .../dashboard/src/__tests__/routes-gitlab.test.ts | 11 +++ packages/dashboard/src/gitlab-auth.ts | 11 ++- 25 files changed, 458 insertions(+), 102 deletions(-) Fusion-Task-Id: FN-7453 Fusion-Task-Lineage: 81fbd39d-675f-49d6-8d13-b7fcb4d25658 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
fafe4c9d9f |
FN-7423: add GitLab access token settings
Add GitLab access-token configuration and auth resolution for future HTTP API integrations. - Add personal, project, and group GitLab token settings at project and global scope. - Resolve configured tokens with GITLAB_TOKEN fallback and PRIVATE-TOKEN metadata without requiring glab. - Document required GitLab scopes and update parity handoff notes. - Cover settings save splitting, parity, modal rendering, and auth resolution with tests. Files changed: .changeset/fn-7423-gitlab-access-tokens.md | 7 ++ docs/gitlab-parity-inventory.md | 10 +- docs/settings-reference.md | 6 +- docs/task-management.md | 2 +- .../core/src/__tests__/settings-parity.test.ts | 28 +++-- packages/core/src/index.ts | 2 +- packages/core/src/settings-schema.ts | 4 + packages/core/src/types.ts | 17 ++- .../app/__tests__/settings-save-split.test.ts | 69 ++++++++++++ .../dashboard/app/components/SettingsModal.tsx | 2 + .../SettingsModal.scheduling-merge.test.tsx | 57 ++++++++++ .../app/components/settings/save-split.ts | 6 +- .../settings/sections/GlobalGeneralSection.tsx | 18 ++- .../components/settings/sections/MergeSection.tsx | 22 ++++ .../dashboard/src/__tests__/gitlab-auth.test.ts | 99 +++++++++++++++++ packages/dashboard/src/gitlab-auth.ts | 123 +++++++++++++++++++++ 16 files changed, 449 insertions(+), 23 deletions(-) Fusion-Task-Id: FN-7423 Fusion-Task-Lineage: f14ae52b-b730-44b0-8bad-54945c61d009 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
573876603f |
FN-7422: add GitLab URL configuration
Add typed GitLab instance and API URL settings for GitLab.com and self-managed instances. - Add core GitLab URL defaults, validation, normalization, and project/global inheritance. - Expose project and global GitLab instance/API URL fields in settings with save-split handling. - Cover configuration resolution, settings parity, and settings UI save behavior with tests. - Document the new settings and add a changeset for the published CLI package. Files changed: .changeset/fn-7422-gitlab-configuration.md | 7 ++ docs/settings-reference.md | 6 +- docs/task-management.md | 2 +- packages/core/src/__tests__/gitlab-config.test.ts | 74 +++++++++++++++++++ .../core/src/__tests__/settings-parity.test.ts | 22 +++++- packages/core/src/gitlab-config.ts | 79 +++++++++++++++++++++ packages/core/src/index.ts | 4 +- packages/core/src/settings-schema.ts | 4 ++ packages/core/src/types.ts | 20 ++++++ .../app/__tests__/settings-save-split.test.ts | 53 ++++++++++++++ .../dashboard/app/components/SettingsModal.tsx | 20 ++++++ .../__tests__/SettingsModal.general.test.tsx | 82 ++++++++++++++++++++++ .../app/components/settings/save-split.ts | 6 ++ .../settings/sections/GeneralSection.tsx | 15 ++++ .../settings/sections/GlobalGeneralSection.tsx | 14 ++++ 15 files changed, 402 insertions(+), 6 deletions(-) Fusion-Task-Id: FN-7422 Fusion-Task-Lineage: 0110b4b6-71b0-4a62-afaf-61af65ebef03 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
519f158400 |
FN-7345: Persist remote access settings saves
Remote Access settings now save from the main Settings dialog without requiring tunnel startup. - Map flattened Remote Access form fields into the canonical global remoteAccess payload during section saves. - Preserve provider, token, and lifecycle branches while saving Tailscale accept-routes and remember-running options. - Cover the UI save flow, split helper, API route contract, docs, and release note. Files changed: .changeset/fn-7345-remote-settings-windows.md | 7 + docs/dashboard-guide.md | 1 + .../app/__tests__/settings-save-split.test.ts | 56 ++++++++ .../SettingsModal.remote-notifications.test.tsx | 144 +++++++++++++++++++++ .../app/components/settings/save-split.ts | 103 +++++++++++++++ .../src/__tests__/routes-remote-access.test.ts | 54 ++++++++ 6 files changed, 365 insertions(+) Fusion-Task-Id: FN-7345 Fusion-Task-Lineage: 9d1eb7f7-7e13-4070-af7d-eb6c6a41fe44 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ebb805d253 |
FN-7261: add global modal dismissal setting
Add a global dashboard preference that keeps modal backdrop dismissal off by default while allowing operators to opt in. - Add dismissModalsOnOutsideClick to global settings defaults, schema, docs, and save handling. - Provide the modal dismissal preference through App and gate shared overlay mouse/touch dismissal on it. - Expose the preference in Global General settings and update modal dismissal tests. - Add a changeset for the published CLI package. Files changed: .changeset/fn-7261-global-modal-outside-dismiss.md | 7 ++++ docs/settings-reference.md | 1 + .../core/src/__tests__/settings-defaults.test.ts | 9 +++++ packages/core/src/settings-schema.ts | 5 +++ packages/core/src/types.ts | 5 +++ packages/dashboard/app/App.tsx | 16 +++++---- .../app/components/AgentErrorDetailsModal.tsx | 4 ++- .../__tests__/AgentErrorDetailsModal.test.tsx | 28 +++++++++++++++- .../__tests__/SettingsModal.general.test.tsx | 23 ++++++++++++- .../app/components/settings/save-split.ts | 1 + .../settings/sections/GlobalGeneralSection.tsx | 5 +++ .../app/hooks/__tests__/useOverlayDismiss.test.tsx | 38 ++++++++++++++++++---- packages/dashboard/app/hooks/useAppSettings.ts | 5 +++ packages/dashboard/app/hooks/useOverlayDismiss.ts | 36 +++++++++++++++++--- 14 files changed, 163 insertions(+), 20 deletions(-) Fusion-Task-Id: FN-7261 Fusion-Task-Lineage: 4fd5195f-c759-46b4-b567-0d5a9d5b92e3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
301f25da06 |
FN-7025: add MCP server management settings UI
Adds dashboard controls for managing MCP server configuration across global and project scopes. - Add global and project MCP settings sections with server cards, validation, inheritance status, and import/export controls. - Wire MCP settings into split-save behavior, browser-safe core exports, localization, and dashboard documentation. - Cover MCP settings interactions and save routing with dashboard tests. Files changed: .changeset/fn-7025-mcp-dashboard-ui.md | 7 + docs/dashboard-guide.md | 14 + packages/core/src/types.ts | 4 + .../app/__tests__/settings-save-split.test.ts | 25 + .../dashboard/app/components/SettingsModal.tsx | 25 + .../__tests__/SettingsModal.mcp.test.tsx | 228 +++++++++ .../app/components/settings/save-split.ts | 5 + .../settings/sections/GlobalMcpSection.tsx | 26 ++ .../settings/sections/McpServersCard.css | 177 +++++++ .../settings/sections/McpServersCard.tsx | 515 +++++++++++++++++++++ .../settings/sections/ProjectMcpSection.tsx | 27 ++ packages/i18n/locales/en/app.json | 10 +- packages/i18n/locales/es/app.json | 10 +- packages/i18n/locales/fr/app.json | 10 +- packages/i18n/locales/ko/app.json | 10 +- packages/i18n/locales/zh-CN/app.json | 10 +- packages/i18n/locales/zh-TW/app.json | 10 +- 17 files changed, 1107 insertions(+), 6 deletions(-) Fusion-Task-Id: FN-7025 Fusion-Task-Lineage: e4e59431-c819-464b-a04b-e470ac51c460 |
||
|
|
192a2f2e94 | fix(FN-6951): preserve settings saves and inline file changes | ||
|
|
1bb8cea9f9 |
Address PR review feedback (#1666)
- mission-execution-loop: preserve judge "blocked" verdict (don't downgrade to fail), clear validation timeout, backfill omitted linked assertions, notify autopilot "blocked" on exhausted retry budget
- mission-verification: pass selected sandbox backend explicitly to fix concurrent global-override race (fail-closed isolation); distinguish infra outcomes (timeout/abort) from real test failures so they stay inconclusive
- mission-store: validate run-to-feature ownership before fix-feature dedup/creation
- settings-sync routes: persist pulled global settings via store; qualify workflow field keys with workflowId
- useNodeSettingsSync: drop redundant ?? {} guard (backend always emits diff.workflowSettings)
- driver(agent-browser): map only Playwright TimeoutError to "absent" in observe(); other faults -> inconclusive
- vitest.config: remove redundant engine-core exclude (quarantine lives in engine-default)
- tests: tighten timeout verdict assertion to inconclusive; remove duplicate schema-version assertions
- save-split: document why customProviders is excluded (persisted via dedicated provider routes)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
d963a756c3 |
FN-6205: skip custom providers in settings save split
Prevent the settings save split from serializing custom provider definitions through the global or project patch paths. - skip `customProviders` when building global settings patches - skip `customProviders` when building project settings patches - add a regression test that keeps custom providers out of both serialized patches Files changed: .../app/__tests__/settings-save-split.test.ts | 24 ++++++++++++++++++++++ .../app/components/settings/save-split.ts | 4 ++++ 2 files changed, 28 insertions(+) Fusion-Task-Id: FN-6205 Fusion-Task-Lineage: 84c3f42b-c621-44ff-b977-ecd3a6729e04 |
||
|
|
e623340e71 |
FN-5994: restore project summarization model settings
Keep summarization and PR metadata model selection on project settings while leaving workflow lanes on the workflow. - restore the project summarization model lane in Project Models and replace per-phase workflow lanes with a workflow-settings redirect stub - remove moved workflow model keys from project settings defaults/save paths and update settings docs/tests for the restored project lane behavior - make PR metadata generation resolve its model from the title summarizer settings lane instead of task planning settings Files changed: docs/settings-reference.md | 4 +- .../core/src/__tests__/settings-migration.test.ts | 18 +- .../core/src/__tests__/settings-parity.test.ts | 17 +- packages/core/src/__tests__/store-settings.test.ts | 54 ++-- .../core/src/__tests__/task-creation-hook.test.ts | 10 +- packages/core/src/builtin-workflow-settings.ts | 24 -- packages/core/src/settings-schema.ts | 13 +- .../components/__tests__/SettingsModal.test.tsx | 11 +- .../app/components/settings/save-split.ts | 11 +- .../settings/sections/ProjectModelsSection.tsx | 330 +++------------------ .../src/__tests__/pr-metadata-generator.test.ts | 25 +- packages/dashboard/src/pr-metadata-generator.ts | 4 +- 12 files changed, 140 insertions(+), 381 deletions(-) Fusion-Task-Id: FN-5994 Fusion-Task-Lineage: f7f6f1ff-5d06-4d16-b46d-644eb219e7c1 |
||
|
|
6c9a81a05f | fix(review): apply autofix feedback | ||
|
|
8c9702e909 | refactor(dashboard): extract SettingsModal Account/Global/Runtimes sections into shared-primitive components with pure save-split helper |