Keep project edit protection on when the settings file is unreadable

This commit is contained in:
Cursor Agent
2026-10-19 19:16:07 +00:00
parent c55e502450
commit 073c19c669
2 changed files with 30 additions and 1 deletions
@@ -6,6 +6,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import {
GlobalSettingsSchema,
isAgentPluginDisabledGlobally,
isKeepChangesInProjectEnabledGlobally,
isModelToolEnabledGlobally,
readCompactionModeGlobally,
readCompactionStrategyGlobally,
@@ -19,6 +20,7 @@ import {
setDisabledAgentPlugin,
setDisabledPlugin,
setDisabledTools,
setKeepChangesInProjectGlobally,
setModelToolEnabledGlobally,
setPlanActModeGlobally,
setTelemetryOptOutGlobally,
@@ -216,6 +218,24 @@ describe("global-settings", () => {
}
});
it("keeps project edit protection on when the settings file is unreadable", async () => {
const root = await mkdtemp(join(tmpdir(), "core-global-settings-"));
try {
const settingsPath = join(root, "global-settings.json");
process.env.CLINE_GLOBAL_SETTINGS_PATH = settingsPath;
setKeepChangesInProjectGlobally(true);
expect(isKeepChangesInProjectEnabledGlobally()).toBe(true);
await writeFile(settingsPath, "{torn write");
expect(isKeepChangesInProjectEnabledGlobally()).toBe(true);
setKeepChangesInProjectGlobally(false);
expect(isKeepChangesInProjectEnabledGlobally()).toBe(false);
} finally {
await rm(root, { recursive: true, force: true });
}
});
it("records telemetry opt-out once when the setting changes to true", async () => {
const root = await mkdtemp(join(tmpdir(), "core-global-settings-"));
try {
@@ -343,9 +343,18 @@ export function setToolAutoApproveGlobally(toolAutoApprove: boolean): void {
* project, and file edits outside the project are refused.
*/
export function isKeepChangesInProjectEnabledGlobally(): boolean {
return readGlobalSettings().keepChangesInProject === true;
const cached = getCachedSettings();
// A torn or corrupt read (e.g. another app mid-write) falls back to
// defaults; keep the last value actually read so protection does not
// silently switch off.
if (!cached.loadFailed) {
lastReadKeepChangesInProject = cached.value.keepChangesInProject === true;
}
return lastReadKeepChangesInProject;
}
let lastReadKeepChangesInProject = false;
export function setKeepChangesInProjectGlobally(
keepChangesInProject: boolean,
): void {