Commit Graph

32 Commits

Author SHA1 Message Date
gsxdsm
b2373431e4 FN-8752: move escalation model to project selector
Centralize executor escalation model selection with the project-scoped provider-aware model control.

- Move escalation provider and model fields from Scheduling to Project Models
- Persist and clear escalation model pairs atomically through the shared selector
- Update search metadata, localization, documentation, and mobile coverage

Files changed:
 docs/settings-reference.md                         |  6 +-
 .../__tests__/SettingsModal.mobileClose.test.tsx   | 29 +++++++
 .../__tests__/SettingsModal.models-auth.test.tsx   | 94 ++++++++++++++++++++++
 .../search/__tests__/settings-search-index.test.ts | 17 ++++
 .../app/components/settings/section-keys.ts        |  4 +-
 .../sections/ProjectModelsSection.search.ts        | 10 +++
 .../settings/sections/ProjectModelsSection.tsx     | 39 +++++++++
 .../settings/sections/SchedulingSection.search.ts  | 18 -----
 .../settings/sections/SchedulingSection.tsx        |  2 -
 .../settings-default-descriptions.test.tsx         |  4 +-
 packages/dashboard/src/shared/settings-sections.ts |  9 +++
 packages/i18n/locales/en/app.json                  |  4 +
 packages/i18n/src/resources.d.ts                   |  4 +
 13 files changed, 213 insertions(+), 27 deletions(-)

Fusion-Task-Id: FN-8752

Fusion-Task-Lineage: f0f430d7-7976-4b65-89c5-8eab3487d26a

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-02 23:12:56 -07:00
gsxdsm
0e8f6769ba FN-8666: add credential instance pickers
Add credential-instance selection across dashboard model configuration surfaces.

- Expose provider credential instances in custom model dropdowns and task, workflow, and settings forms.
- Persist per-role credential-instance overrides through dashboard APIs and effective model resolution.
- Document credential-instance precedence and cover dropdown/settings behavior, including task state synchronization.

Files changed:
 .changeset/fn-8666-credential-instance-picker.md   |   7 ++
 docs/settings-reference.md                         |   2 +
 docs/workflow-steps.md                             |   2 +-
 packages/dashboard/app/api.ts                      |   1 +
 packages/dashboard/app/api/models-usage.ts         |  27 ++++-
 packages/dashboard/app/api/tasks.ts                |   8 ++
 .../app/components/CustomModelDropdown.css         |  12 ++-
 .../app/components/CustomModelDropdown.tsx         |  71 ++++++++++++-
 .../dashboard/app/components/InlineCreateCard.tsx  |  23 +++-
 packages/dashboard/app/components/ListView.tsx     |  29 +++++-
 .../app/components/ModelSelectionModal.tsx         |  25 ++++-
 .../dashboard/app/components/ModelSelectorTab.tsx  |  29 +++++-
 packages/dashboard/app/components/NewTaskModal.tsx |  23 +++-
 .../dashboard/app/components/QuickEntryBox.tsx     |  28 +++++
 .../dashboard/app/components/SettingsModal.tsx     |   2 +
 .../dashboard/app/components/TaskDetailModal.tsx   |  32 +++++-
 packages/dashboard/app/components/TaskForm.tsx     |  18 ++++
 .../app/components/WorkflowNodeEditor.tsx          |  13 ++-
 .../app/components/WorkflowSettingsPanel.tsx       |  38 ++++++-
 ...ustomModelDropdown.credential-instance.test.tsx | 111 ++++++++++++++++++++
 .../__tests__/WorkflowSettingsPanel.test.tsx       |   9 +-
 .../app/components/effective-model-resolution.ts   |   8 +-
 .../settings/sections/GlobalModelsSection.tsx      |  31 +++++-
 .../settings/sections/ProjectModelsSection.tsx     | 116 ++++++++++++++++-----
 .../ProjectModelsSection.chatDefault.test.tsx      |  33 +++++-
 packages/dashboard/app/hooks/useFavorites.ts       |   6 +-
 packages/dashboard/app/hooks/useModelsCache.ts     |   5 +-
 .../src/routes/register-task-workflow-routes.ts    |  17 ++-
 28 files changed, 655 insertions(+), 71 deletions(-)

Fusion-Task-Id: FN-8666

Fusion-Task-Lineage: 6c3711b3-68b8-47a0-ac36-4b64846adf39

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-01 04:03:26 -07:00
gsxdsm
dc50425e98 docs: correct 104 future-dated FNXC timestamps across 61 files (#2680)
## What

The FNXC convention exists so a reader can place a note against the
change that motivated it. A stamp dated *after* the edit landed defeats
exactly that.

This is program-wide drift, not one author's slip — I contributed to it
in my own commits this week, which is how I noticed it.

## Measured, on this tree

**104 stamps across 61 files** dated later than the day they were
written, from one day ahead to **2026-10-19 (81 days)**:

| count | date | count | date | count | date |
|---|---|---|---|---|---|
| 50 | 2026-07-31 | 6 | 2026-08-05 | 3 | 2026-08-13 |
| 17 | 2026-08-01 | 1 | 2026-08-07 | 1 | 2026-08-19 |
| 7 | 2026-08-02 | 1 | 2026-08-12 | 2 | 2026-08-26 |
| 11 | 2026-08-03 | | | 3 | 2026-10-19 |

An earlier number I circulated was ~70. That came from a narrower
pathspec and was wrong; **104** is the measurement.

## How

Each stamp is rewritten to the date of the commit that introduced **that
line**, via per-line `git blame` — deliberately *not* stamped uniformly
with today's date. A uniform stamp swaps a wrong date for a different
wrong date and flattens the ordering that makes these comments
navigable; blame preserves it. Times of day are untouched, and a blame
date in the future is clamped rather than trusted.

## Why the verification is listed

A docs sweep across 61 files is precisely where a stray edit hides, so
the safety claims are mechanical rather than asserted:

- every changed line begins with a comment marker — **no code touched**;
- **no test asserts an FNXC date later than today**, so no `toContain`
assertion on embedded source text can be silently invalidated (several
such assertions do exist);
- CSS files, which carry several of those assertions, are outside the
pathspec.

## Verified

lint clean · merge gate green (487 + 158 + 10 + 71) · `census --strict`
exit 0 · tsc clean for core, engine, and dashboard
(`tsconfig.app.json`).

**No behavior change.** Comment text only.

## Not done here

A guard preventing recurrence. A check that rejects an FNXC stamp dated
after the commit would stop this returning, but it needs a decision
about where it runs (lint rule vs. gate) and it is a behavior change to
CI — it does not belong riding inside the sweep it would police.
2026-07-30 02:38:58 -07:00
gsxdsm
e514e134da fix: apply project model lanes across workflows (#2400)
## Summary

Project workflow model lanes now apply to tasks on every workflow
instead of only tasks using the active default workflow. Model selection
consistently resolves task-specific choice -> project workflow baseline
-> global lane -> selected-workflow value -> project/global default for
primary models, fallback models, and thinking levels.

The active default workflow remains the storage owner for backward
compatibility, while runtime resolution keeps its project baseline
distinct from lower-priority selected-workflow values. Non-model
workflow policies remain isolated to their selected workflow.

## Validation

- Core workflow/model resolution: 60 tests passed
- Engine effective settings and session resolution: 59 tests passed
- Reviewer: 85 tests passed
- Scheduler: 154 tests passed
- Heartbeat: 90 tests passed
- Settings UI: 67 tests passed
- Workspace lint and core/engine/dashboard typechecks passed
- `pnpm verify:fast` passed workspace builds, the published CLI build,
and real `/api/health` boot smoke

---

[![Compound
Engineering](https://img.shields.io/badge/Built_with-Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added **Project workflow model lanes** to establish a project baseline
for model selection and thinking levels across workflows.
* Updated model/fallback resolution to account for task overrides,
project baselines, global lanes, and selected-workflow values.
* **Bug Fixes**
* Improved effective settings merging so project baselines are applied
correctly (including scheduled/idle and heartbeat flows) while
preserving selected-workflow provenance.
* **Documentation**
* Refreshed settings and dashboard guidance for workflow lane
inheritance and resolution precedence.
* **Tests**
* Expanded unit test coverage for lane precedence, fallback detection,
and thinking-level behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-22 08:53:31 -07:00
gsxdsm
d4a87accb8 FN-8395: autosave settings changes
Settings edits now persist automatically with safe feedback and close handling.

- Debounce and serialize settings persistence, retaining newer edits through in-flight saves and unmounts.
- Remove the Settings Save action and unsaved-changes prompt while flushing pending section and workflow-lane updates.
- Update Settings documentation, release metadata, and regression coverage for auto-save behavior.

Files changed:
 .changeset/fn-8395-settings-autosave.md            |   7 +
 docs/dashboard-guide.md                            |  11 +-
 docs/settings-reference.md                         |   8 +-
 .../dashboard/app/components/SettingsModal.tsx     | 402 ++++++++++++++++-----
 .../__tests__/SettingsModal.general.test.tsx       | 154 ++++++--
 .../SettingsModal.keyboardShortcuts.test.tsx       |   7 +-
 .../__tests__/SettingsModal.models-auth.test.tsx   |  46 +--
 .../SettingsModal.remote-notifications.test.tsx    |  38 +-
 .../SettingsModal.scheduling-merge.test.tsx        |  58 ++-
 .../__tests__/SettingsModal.test-harness.tsx       |   9 +-
 .../__tests__/SettingsModalNodeRouting.test.tsx    |   2 -
 .../settings/sections/ProjectModelsSection.tsx     |  15 +-
 12 files changed, 548 insertions(+), 209 deletions(-)

Fusion-Task-Id: FN-8395

Fusion-Task-Lineage: 77f4c0d3-d0cc-4973-9831-c70eb2a2b49b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-19 22:16:11 -07:00
gsxdsm
5006e5543c FN-8169: group workflow fallback lanes with primary lanes
Keep fallback model lanes adjacent to their primary lanes throughout Settings.

- Interleave planning, execution, and validator fallback lanes after their respective primary lanes.
- Classify executor fallback settings in the Models group so the row remains visible.
- Add ordering coverage for project and workflow Settings surfaces.

Files changed:
 .changeset/fn-8169-group-fallback-lanes.md         |  7 ++++
 .../app/__tests__/settings-sections.test.tsx       | 47 ++++++++++++++++++++++
 .../app/components/WorkflowSettingsPanel.tsx       | 31 +++++++-------
 .../__tests__/WorkflowSettingsPanel.test.tsx       | 40 ++++++++++++++++++
 .../settings/sections/ProjectModelsSection.tsx     | 31 +++++++-------
 .../app/components/workflow-setting-display.ts     | 12 ++++++
 6 files changed, 140 insertions(+), 28 deletions(-)

Fusion-Task-Id: FN-8169

Fusion-Task-Lineage: 89402b95-1f42-46a7-8ad6-5182dc21f172

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-16 18:36:50 -07:00
gsxdsm
1a337df5e9 FN-8098: add executor model fallback
Add workflow-specific executor fallback configuration and bounded recovery.

- Add executor fallback provider, model, and thinking settings across core schemas and settings UI.
- Route executor, heartbeat, child, and workflow-step sessions through the executor fallback resolver.
- Retry the primary model after fallback failure before reporting terminal exhaustion.
Files changed:

 .changeset/fn-8098-model-fallback.md               |  7 +++
 docs/settings-reference.md                         |  7 ++-
 .../core/src/__tests__/model-resolution.test.ts    | 13 ++++
 .../core/src/__tests__/settings-parity.test.ts     |  5 ++
 packages/core/src/builtin-workflow-settings.ts     | 24 +++++++
 packages/core/src/index.gate.ts                    |  1 +
 packages/core/src/index.ts                         |  1 +
 packages/core/src/model-resolution.ts              | 21 +++++++
 packages/core/src/settings-schema.ts               |  3 +
 packages/core/src/types.ts                         | 11 ++++
 .../app/components/WorkflowSettingsPanel.tsx       |  8 +++
 .../settings/sections/ProjectModelsSection.tsx     | 10 ++-
 packages/engine/src/__tests__/pi.test.ts           | 14 ++++-
 packages/engine/src/agent-session-helpers.ts       |  7 ++-
 packages/engine/src/executor.ts                    | 48 +++++++-------
 packages/engine/src/pi.ts                          | 73 ++++++++--------------
 packages/engine/src/step-session-executor.ts       |  8 ++-
 17 files changed, 180 insertions(+), 81 deletions(-)

Fusion-Task-Id: FN-8098

Fusion-Task-Lineage: 61b3103b-357b-431a-8d58-411e7806b87b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-16 08:33:57 -07:00
gsxdsm
19ab7a9e93 FN-8068: add input-language task definitions
Add an opt-in setting that localizes planner-authored task-definition prose.

- Detect confident Spanish, French, Korean, and Chinese input before instructing triage localization.
- Expose and persist the project-level task-definition language toggle with translations and search support.
- Preserve English structural markers, code, and unsupported or uncertain input for deterministic parsing.

Files changed:
 .../fn-8068-task-definition-input-language.md      |  7 +++
 docs/settings-reference.md                         |  1 +
 packages/core/src/settings-schema.ts               |  7 +++
 packages/core/src/types.ts                         | 10 ++++
 .../app/__tests__/settings-sections.test.tsx       | 18 ++++++
 .../dashboard/app/components/SettingsModal.tsx     |  4 ++
 .../__tests__/SettingsModal.mobileClose.test.tsx   | 12 ++++
 .../__tests__/SettingsModal.models-auth.test.tsx   | 11 ++++
 .../app/components/settings/section-keys.ts        |  1 +
 .../sections/ProjectModelsSection.search.ts        | 10 ++++
 .../settings/sections/ProjectModelsSection.tsx     | 17 ++++++
 .../settings-default-descriptions.test.tsx         |  1 +
 packages/engine/src/__tests__/triage.test.ts       | 64 ++++++++++++++++++++++
 packages/engine/src/triage.ts                      | 29 +++++++++-
 packages/i18n/locales/en/app.json                  |  2 +
 packages/i18n/locales/es/app.json                  |  2 +
 packages/i18n/locales/fr/app.json                  |  2 +
 packages/i18n/locales/ko/app.json                  |  2 +
 packages/i18n/locales/zh-CN/app.json               |  2 +
 packages/i18n/locales/zh-TW/app.json               |  2 +
 packages/i18n/src/resources.d.ts                   |  2 +
 21 files changed, 205 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8068

Fusion-Task-Lineage: fe0102f5-68cb-443c-8512-2ffa5fe0e2f8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-16 05:18:30 -07:00
gsxdsm
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>
2026-07-16 04:29:17 -07:00
gsxdsm
4b7f0d2d0e fix(dashboard): theme every Settings checkbox and move all inline help behind ? icons
- One settings-scoped checkbox rule (accent, size, focus ring) so the Advanced-settings
  toggle, SettingsToggleRow, ntfy/webhook card headers, and MCP toggle stop falling
  back to the browser-default accent.
- Fix the empty/off-screen help bubble on mobile: .notification-provider-header and
  .settings-field-label-row are now positioned ancestors for SettingsHelpTip.
- Migrate every remaining inline <small> description across settings sections to the
  shared SettingsHelpTip "?" affordance (validation errors and live status stay inline).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 01:06:43 -07:00
gsxdsm
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:

![Topic-first settings
navigation](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/nav-topic-groups.png)

```
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:


![Search returns individual
settings](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/search-summarize.png)

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:

![Jump to
field](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/jump-highlight.png)


**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** |


![Appearance](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/appearance.png)

![Scheduling](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/scheduling.png)

![Backups](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/backups.png)

![Worktrees](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/worktrees.png)

![Memory](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/memory.png)

![Merge](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/merge.png)

![Notifications](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/notifications.png)
![General ·
Project](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/general.png)

**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.

![Scheduling ·
Project](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/scheduling.png)

**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:

![Source Control ·
Project](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/source-control.png)

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

![Help tip on
mobile](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/mobile-help-tip.png)

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 "?":


![Merge](https://raw.githubusercontent.com/Runfusion/Fusion/468f71dfa065be6f46e4fccfe09f18518fbf4e81/shots/merge.png)

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 `&ldquo;` 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>
2026-07-15 22:00:27 -07:00
gsxdsm
d9843f75bc FN-7983: colocate project summarization model with summarization settings
Move the Project Summarization model lane and title-summarizer fallback next to the AI title/commit summarization controls in Project Models.

- Extract shared project-lane renderer and keep default/merger/import-translate in the general Model Lanes list
- Render summarization + title-summarizer fallback inside the AI summarization section with the same models-available guard
- Add regression tests for colocation and empty-models guard
- Update settings reference docs and add a patch changeset

Files changed:
 .changeset/fn-7983-summarization-lane-colocation.md       |   7 ++
 docs/settings-reference.md                         |   6 +-
 .../app/__tests__/settings-sections.test.tsx       |  61 ++++++++++
 .../settings/sections/ProjectModelsSection.tsx     | 126 ++++++++++++---------
 4 files changed, 142 insertions(+), 58 deletions(-)

Fusion-Task-Id: FN-7983

Fusion-Task-Lineage: c473ba61-f003-401d-bc66-86f2078ba047

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-15 15:21:16 -07:00
gsxdsm
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>
2026-07-15 14:06:42 -07:00
gsxdsm
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.
2026-07-13 08:10:56 -07:00
gsxdsm
03bca1787b FN-7907: Add project chat default (model/agent) setting and New Chat default behavior
Adds a project-scoped Direct-chat default (model pair or durable agent) plus a New Chat behavior toggle (prompt vs. always-use-default), surfaced in Project Models settings using the standard model dropdown.

- Add ProjectSettings fields: chatNewSessionMode, chatDefaultKind, chatDefaultAgentId, chatDefaultModelProvider, chatDefaultModelId, chatDefaultThinkingLevel
- Extend settings-schema validation for the new chat default fields
- Add a "Chat" subsection to ProjectModelsSection with New Chat behavior selector, model/agent target toggle, and the standard CustomModelDropdown for model selection
- Update ChatView.tsx handleNewChat() flow to honor the configured default (prompt vs. immediate session creation)
- Add i18n strings across en/es/fr/ko/zh-CN/zh-TW locales and regenerate resources.d.ts
- Add changeset (@runfusion/fusion minor) and update docs/settings-reference.md and docs/dashboard-guide.md
- Add settings-parity, ChatView new-chat-default, and ProjectModelsSection chatDefault test coverage

Files changed:
 .changeset/fn-7907-chat-default.md                 |   7 +
 docs/dashboard-guide.md                            |   3 +-
 docs/settings-reference.md                         |   8 +
 packages/core/src/__tests__/settings-parity.test.ts     |  20 ++
 packages/core/src/settings-schema.ts               |   6 +
 packages/core/src/types.ts                         |  15 +
 packages/dashboard/app/components/ChatView.tsx     |  93 +++++-
 packages/dashboard/app/components/__tests__/ChatView.new-chat-default.test.tsx   | 357 +++++++++++++++++++++
 packages/dashboard/app/components/settings/sections/ProjectModelsSection.tsx     |  77 +++++
 packages/dashboard/app/components/settings/sections/__tests__/ProjectModelsSection.chatDefault.test.tsx |  193 +++++++++++
 packages/i18n/locales/en/app.json                  |  20 +-
 packages/i18n/locales/es/app.json                  |  20 +-
 packages/i18n/locales/fr/app.json                  |  20 +-
 packages/i18n/locales/ko/app.json                  |  20 +-
 packages/i18n/locales/zh-CN/app.json               |  20 +-
 packages/i18n/locales/zh-TW/app.json               |  20 +-
 packages/i18n/src/resources.d.ts                   |  18 ++
 17 files changed, 899 insertions(+), 18 deletions(-)

Fusion-Task-Id: FN-7907

Fusion-Task-Lineage: 86a81b9c-7e0c-4033-9e2a-6f7380810fe9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-12 20:54:10 -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
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
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
4baa4c43c5 FN-7505: show defaults in settings descriptions
Expose settings defaults directly in dashboard help text so operators can see baseline values while editing settings.

- Add default-value wording across global and project settings descriptions and locale strings.
- Document the dashboard/default-reference alignment and add a changeset for the published CLI package.
- Add coverage that every visible settings field includes its default in helper text and update existing assertions.

Files changed:
 .changeset/fn-7505-settings-default-descriptions.md       |   7 +
 docs/dashboard-guide.md                                    |   3 +
 docs/settings-reference.md                                 |   3 +
 .../__tests__/SettingsModal.general.test.tsx               |   2 +-
 .../settings/sections/AgentPermissionsSection.tsx          |   4 +-
 .../settings/sections/AppearanceSection.tsx                |   4 +-
 .../settings/sections/BackupsSection.tsx                   |  13 +-
 .../settings/sections/CommandsSection.tsx                  |   4 +-
 .../settings/sections/ExperimentalSection.tsx              |   2 +-
 .../settings/sections/GeneralSection.tsx                   |  26 +-
 .../settings/sections/GlobalGeneralSection.tsx             |  25 +-
 .../settings/sections/GlobalModelsSection.tsx              |  24 +-
 .../settings/sections/McpServersCard.tsx                   |   1 +
 .../components/settings/sections/MemorySection.tsx         |  12 +-
 .../components/settings/sections/MergeSection.tsx          |  37 +-
 .../settings/sections/ModelPricingSection.tsx              |   2 +-
 .../settings/sections/NodeRoutingSection.tsx               |   3 +-
 .../settings/sections/NodeSyncSection.tsx                  |   6 +-
 .../settings/sections/NotificationsSection.tsx             |  14 +-
 .../settings/sections/ProjectModelsSection.tsx             |  11 +-
 .../settings/sections/PromptsSection.tsx                   |   2 +-
 .../components/settings/sections/RemoteSection.tsx         |   7 +-
 .../settings/sections/ResearchGlobalSection.tsx            |  15 +-
 .../settings/sections/ResearchProjectSection.tsx           |  16 +-
 .../settings/sections/ScheduledEvalsSection.tsx            |   7 +-
 .../settings/sections/SchedulingSection.tsx                |  20 +-
 .../settings/sections/WorktreesSection.tsx                 |  14 +-
 .../sections/__tests__/AppearanceSection.test.tsx          |   4 +-
 .../MergeSection.legacy-automerge-cleanup.test.tsx         |   2 +-
 .../settings-default-descriptions.test.tsx                 | 573 +++++++++++++++++++++
 packages/i18n/locales/en/app.json                          | 261 ++++++----
 31 files changed, 914 insertions(+), 210 deletions(-)

Fusion-Task-Id: FN-7505

Fusion-Task-Lineage: 7688caf2-2a95-4401-8b27-9da4b46ecfcd

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-04 13:09:29 -07:00
gsxdsm
2050323d16 FN-7451: preserve workflow setting edits during saves
Workflow settings now keep newer pending edits when earlier save requests finish.\n\n- Snapshot pending workflow values before saving so the request cannot mutate under the save.\n- Clear only keys whose pending value still matches the completed request in Workflow Settings and Project Models.\n- Cover same-key, clear-to-default, and model-lane edits made while saves are in flight.\n- Add a patch changeset for the published Fusion package.\n\nFiles changed:\n .changeset/fn-7451-workflow-settings-save-race.md  |   7 ++\n .../app/__tests__/settings-sections.test.tsx       | 109 ++++++++++++++++++-\n .../app/components/WorkflowSettingsPanel.tsx       |  21 +++-\n .../__tests__/WorkflowSettingsPanel.test.tsx       | 121 ++++++++++++++++++++-\n .../settings/sections/ProjectModelsSection.tsx     |  25 ++++-\n 5 files changed, 272 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-7451

Fusion-Task-Lineage: 82f5e1cf-fabb-4fc6-936c-f42dcd9337ac

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-02 14:18:08 -07:00
gsxdsm
07aa1a0085 FN-7399: widen Project Models model menus
Make Project Models dropdown menus easier to scan without changing shared selector defaults.

- Add an opt-in readable menu width mode to the shared custom model dropdown.
- Apply the wider menu only to Project Models lane, workflow, and preset model selectors.
- Cover readable sizing, viewport clamping, and default trigger-width behavior with dashboard tests.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/wide-project-model-dropdowns.md         |   7 +
 .../app/__tests__/settings-sections.test.tsx       |  66 ++++++-
 .../app/components/CustomModelDropdown.tsx         |  17 +-
 .../__tests__/CustomModelDropdown.test.tsx         | 210 +++++++++++++++++++++
 .../settings/sections/ProjectModelsSection.tsx     |   8 +-
 5 files changed, 301 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7399

Fusion-Task-Lineage: 40aae990-37bc-4ed8-8e2a-7e78a543053b

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-01 15:39:34 -07:00
gsxdsm
9c207fd286 FN-7180: add configurable PR metadata prompts
Add project-scoped guidance fields for AI-generated Create PR metadata.

- Store PR title and description prompt guidance as project settings only.
- Surface editable guidance textareas in Project Models settings.
- Append trimmed guidance to the PR metadata system prompt without changing defaults for blank values.
- Document the settings and add release notes/tests for persistence, UI, and prompt generation.

Files changed:
 .changeset/fn-7180-pr-prompt-settings.md           |  7 ++
 docs/dashboard-guide.md                            |  1 +
 docs/settings-reference.md                         |  2 +
 .../core/src/__tests__/settings-defaults.test.ts   | 11 ++-
 packages/core/src/__tests__/store-settings.test.ts | 19 +++++
 packages/core/src/settings-schema.ts               |  2 +
 packages/core/src/types.ts                         | 12 ++++
 .../app/__tests__/settings-sections.test.tsx       | 54 ++++++++++++++
 .../dashboard/app/components/SettingsModal.tsx     |  4 ++
 .../settings/sections/ProjectModelsSection.tsx     | 12 ++++
 .../src/__tests__/pr-metadata-generator.test.ts    | 84 ++++++++++++++++++++++
 packages/dashboard/src/pr-metadata-generator.ts    | 23 ++++--
 12 files changed, 225 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-7180

Fusion-Task-Lineage: 9bdc42d5-ffd3-4208-b64a-96d142cc1dc8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-06-28 00:28:13 -07:00
gsxdsm
3b61ac3d23 fix: make loading spinners actually spin across the dashboard
Many loading states rendered bare "Loading…" text with no spinner
element, and a couple rendered an unstyled `loading-spinner` div with no
matching CSS (invisible). The global spin animation was never broken —
it rotates in Chromium and WebKit — so prior transform-box edits chased
a non-bug, validated only by a string-matching CSS test.

Add a shared <LoadingSpinner> (self-contained animated SVG, no
lucide-react import so it survives partial test mocks) and adopt it
across ~47 loading placeholders so every loading state shows a
consistent animated spinner. Includes a component test that asserts the
svg carries the animate-spin utility.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 03:53:43 -07:00
gsxdsm
eca96fbd0b FN-6771: localize settings section copy
Localize dashboard settings section text and restore i18n lint coverage for those files.

- Replace hardcoded settings section labels, help text, placeholders, and status copy with i18n lookups.
- Add settings translation keys across supported app and common locale catalogs and refresh generated resource types.
- Remove the settings sections from the i18n lint deferral list and document that coverage requirement.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fn-6771-localize-settings-sections.md   |   5 +
 docs/i18n-contributing.md                          |   3 +-
 i18next.config.ts                                  |  26 +-
 .../settings/sections/AgentPermissionsSection.tsx  |  55 +-
 .../settings/sections/AppearanceSection.tsx        |  91 +-
 .../settings/sections/AuthenticationSection.tsx    | 457 +++-------
 .../settings/sections/BackupsSection.tsx           | 229 ++---
 .../settings/sections/CommandsSection.tsx          |  49 +-
 .../settings/sections/ExperimentalSection.tsx      | 109 +--
 .../settings/sections/GeneralSection.tsx           | 487 ++++-------
 .../settings/sections/GlobalGeneralSection.tsx     | 183 +---
 .../settings/sections/GlobalModelsSection.tsx      | 525 ++++-------
 .../components/settings/sections/MemorySection.tsx | 458 +++-------
 .../components/settings/sections/MergeSection.tsx  | 863 ++++++------------
 .../settings/sections/NodeRoutingSection.tsx       | 108 +--
 .../settings/sections/NodeSyncSection.tsx          | 105 +--
 .../settings/sections/NotificationsSection.tsx     | 484 ++++------
 .../settings/sections/PluginsSection.tsx           | 105 +--
 .../settings/sections/ProjectModelsSection.tsx     | 971 ++++++++-------------
 .../components/settings/sections/RemoteSection.tsx | 560 +++++-------
 .../settings/sections/ResearchGlobalSection.tsx    | 314 ++-----
 .../settings/sections/ResearchProjectSection.tsx   | 226 ++---
 .../settings/sections/RuntimesSections.tsx         |  40 +-
 .../settings/sections/ScheduledEvalsSection.tsx    | 169 ++--
 .../settings/sections/SchedulingSection.tsx        | 381 ++------
 .../settings/sections/WorktreesSection.tsx         | 330 ++-----
 packages/i18n/locales/en/app.json                  | 698 ++++++++++++++-
 packages/i18n/locales/en/common.json               |   8 +
 packages/i18n/locales/es/app.json                  | 698 ++++++++++++++-
 packages/i18n/locales/es/common.json               |   8 +
 packages/i18n/locales/fr/app.json                  | 698 ++++++++++++++-
 packages/i18n/locales/fr/common.json               |   8 +
 packages/i18n/locales/ko/app.json                  | 698 ++++++++++++++-
 packages/i18n/locales/ko/common.json               |   8 +
 packages/i18n/locales/zh-CN/app.json               | 698 ++++++++++++++-
 packages/i18n/locales/zh-CN/common.json            |   8 +
 packages/i18n/locales/zh-TW/app.json               | 698 ++++++++++++++-
 packages/i18n/locales/zh-TW/common.json            |   8 +
 packages/i18n/src/resources.d.ts                   | 706 ++++++++++++++-
 39 files changed, 7178 insertions(+), 5097 deletions(-)

Fusion-Task-Id: FN-6771
Fusion-Task-Lineage: cdf9b36f-414e-4084-b661-b578a4c27314
2026-06-20 08:57:45 -07:00
gsxdsm
a89804ec5f FN-6508: expose fallback workflow model lanes
Expose declared fallback model lanes in project Settings while preserving workflow-scoped persistence.

- Load the default workflow definition before rendering Project Models lane controls.\n- Show fallback model dropdowns only when the workflow declares matching provider/model settings.\n- Persist and reset fallback lane edits through the Settings modal primary Save action.\n- Update settings documentation for default-workflow and global fallback model placement.

Files changed:\n docs/settings-reference.md                         |  40 +++---\n .../components/__tests__/SettingsModal.test.tsx    | 135 ++++++++++++++++++++-\n .../settings/sections/ProjectModelsSection.tsx     |  52 +++++++-\n 3 files changed, 204 insertions(+), 23 deletions(-)

Fusion-Task-Id: FN-6508

Fusion-Task-Lineage: 18dba2f9-658a-4b82-850f-3bbeb70341d3
2026-06-16 20:59:30 -07:00
gsxdsm
64d831576d FN-6225: persist workflow model lanes on Settings save
Persist default workflow model lane edits through the Settings modal's primary save path.

- Register a Project Models section save handler so workflow lane overrides flush before closing Settings.
- Surface typed workflow setting rejections without closing the modal or showing a success toast.
- Remove the separate workflow-model save button and update coverage/docs for the unified save behavior.

Files changed:
 docs/dashboard-guide.md                            |  2 +-
 docs/settings-reference.md                         | 17 +++++---
 .../dashboard/app/components/SettingsModal.tsx     | 11 ++++-
 .../components/__tests__/SettingsModal.test.tsx    | 50 ++++++++++++++++------
 .../settings/sections/ProjectModelsSection.tsx     | 42 ++++++++++--------
 .../app/components/settings/sections/context.ts    |  3 ++
 6 files changed, 83 insertions(+), 42 deletions(-)

Fusion-Task-Id: FN-6225

Fusion-Task-Lineage: 98338f85-c742-46c2-8bdf-f676a6f7e32e
2026-06-11 20:21:30 -07:00
gsxdsm
4ffd0a2dde FN-6030: fix workflow terminal notifications
Ensure merged workflow tasks still emit the expected terminal notifications.

- emit task:merged when PR-driven workflow merges move tasks to done
- send merged notifications for merge-backed done transitions and suppress duplicates
- add regression coverage, a published changeset, and reconcile overlapping docs/test updates

Files changed:
 .../fn-6030-workflow-terminal-notifications.md     |   5 +
 docs/storage.md                                    |   8 +-
 .../core/src/__tests__/builtin-workflows.test.ts   |   1 -
 .../__tests__/store-pr-merged-transition.test.ts   |  14 ++-
 .../src/__tests__/workflow-ir-resolver.test.ts     |   1 -
 packages/core/src/store.ts                         |  14 ++-
 .../settings/sections/ProjectModelsSection.tsx     |   3 +-
 .../engine/src/__tests__/merger-post-merge.test.ts |   9 +-
 .../src/__tests__/notification-service.test.ts     | 129 ++++++++++++++++++++-
 .../__tests__/workflow-graph-task-runner.test.ts   |  57 +++++++++
 .../src/notification/notification-service.ts       |  36 ++++--
 11 files changed, 257 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-6030

Fusion-Task-Lineage: a991f765-0986-4541-ab38-ff476cf88d16
2026-06-08 13:54:17 -07:00
gsxdsm
474b492b26 FN-6027: show and space default workflow model overrides
Expose default workflow model lane overrides directly in project settings.

- load and persist default workflow model lane overrides from the active project workflow
- add inline workflow lane status, reset, save, and advanced policy actions in project model settings
- add CSS contract and modal coverage for the workflow model action row spacing and placement

Files changed:
 .../dashboard/app/components/SettingsModal.css     |  20 ++
 .../components/__tests__/SettingsModal.test.tsx    |  20 +-
 .../SettingsModal.workflow-model-lane-css.test.ts  |  24 ++
 .../settings/sections/ProjectModelsSection.tsx     | 245 ++++++++++++++++++++-
 4 files changed, 298 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-6027

Fusion-Task-Lineage: 981a5f01-f4b7-467e-9e2f-4ac8e4ed40fb
2026-06-08 13:32:58 -07:00
gsxdsm
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
2026-06-08 13:32:58 -07:00
gsxdsm
7850b08a18 Address PR review feedback (#1502)
- Bump workflow model lane changeset to minor

- Clear pending workflow model edits after value reload failures

- Exclude Vite source module requests with query strings from API proxy
2026-06-07 22:56:35 -07:00
gsxdsm
61ae1bf706 feat(workflow-settings): simplify workflow model lanes 2026-06-07 22:07:47 -07:00
gsxdsm
1dbb7052ae refactor(dashboard): extract all remaining Project sections — SettingsModal is now a shell (7,883 → 2,905 lines) 2026-06-05 01:10:35 -07:00