diff --git a/.changeset/fn-7451-workflow-settings-save-race.md b/.changeset/fn-7451-workflow-settings-save-race.md
new file mode 100644
index 0000000000..2f546a0a8f
--- /dev/null
+++ b/.changeset/fn-7451-workflow-settings-save-race.md
@@ -0,0 +1,7 @@
+---
+"@runfusion/fusion": patch
+---
+
+summary: Preserve workflow setting edits made while a values save is still in flight.
+category: fix
+dev: WorkflowSettingsPanel and Project Models workflow lane saves now clear only snapshot-matching pending keys.
diff --git a/packages/dashboard/app/__tests__/settings-sections.test.tsx b/packages/dashboard/app/__tests__/settings-sections.test.tsx
index 6bc0f14891..215c8f685b 100644
--- a/packages/dashboard/app/__tests__/settings-sections.test.tsx
+++ b/packages/dashboard/app/__tests__/settings-sections.test.tsx
@@ -9,8 +9,8 @@
* component-test conventions in settings-primitives.test.tsx.
*/
import { useState } from "react";
-import { describe, it, expect, vi, afterEach } from "vitest";
-import { render, screen, fireEvent, cleanup } from "@testing-library/react";
+import { describe, it, expect, vi, afterEach, beforeEach } from "vitest";
+import { render, screen, fireEvent, cleanup, waitFor, act } from "@testing-library/react";
import * as jestDomMatchers from "@testing-library/jest-dom/matchers";
import { AppearanceSection } from "../components/settings/sections/AppearanceSection";
@@ -23,7 +23,8 @@ import { PromptsSection } from "../components/settings/sections/PromptsSection";
import { SecretsSection } from "../components/settings/sections/SecretsSection";
import { WorktreesSection } from "../components/settings/sections/WorktreesSection";
import type { SettingsFormState } from "../components/settings/sections/context";
-import { fetchWorkflow, fetchWorkflowSettingValues } from "../api";
+import { fetchWorkflow, fetchWorkflowSettingValues, updateWorkflowSettingValues } from "../api";
+import type { WorkflowSettingValuesPayload } from "../api";
vi.mock("../components/AgentPromptsManager", () => ({
AgentPromptsManager: () =>
,
@@ -41,17 +42,32 @@ vi.mock("../api", async (importOriginal) => {
fetchProjectDefaultWorkflow: vi.fn(async () => ({ workflowId: null })),
setProjectDefaultWorkflow: vi.fn(async () => ({ workflowId: null })),
fetchGlobalSettings: vi.fn(async () => ({})),
+ updateWorkflowSettingValues: vi.fn(async () => ({ stored: {}, effective: {}, orphaned: [] })),
};
});
vi.mock("../components/CustomModelDropdown", () => ({
- CustomModelDropdown: ({ id, label, menuWidth = "trigger" }: { id?: string; label: string; menuWidth?: "trigger" | "readable" }) => (
-