fix(gsd): preserve experimental preferences in merges (#3847)

This commit is contained in:
mastertyko 2026-04-13 14:07:54 +02:00 committed by GitHub
parent b13c980ecc
commit daef91f7b8
2 changed files with 56 additions and 0 deletions

View file

@ -389,6 +389,9 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
github: (base.github || override.github)
? { ...(base.github ?? {}), ...(override.github ?? {}) } as import("../github-sync/types.js").GitHubSyncConfig
: undefined,
experimental: (base.experimental || override.experimental)
? { ...(base.experimental ?? {}), ...(override.experimental ?? {}) }
: undefined,
service_tier: override.service_tier ?? base.service_tier,
forensics_dedup: override.forensics_dedup ?? base.forensics_dedup,
show_token_cost: override.show_token_cost ?? base.show_token_cost,

View file

@ -10,10 +10,14 @@
import test from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
validatePreferences,
applyModeDefaults,
getIsolationMode,
loadEffectiveGSDPreferences,
parsePreferencesMarkdown,
_resetParseWarningFlag,
} from "../preferences.ts";
@ -501,6 +505,55 @@ test("experimental.rtk parses correctly from preferences markdown", () => {
assert.equal(prefs!.experimental?.rtk, true);
});
test("loadEffectiveGSDPreferences preserves experimental prefs across global+project merge", () => {
const originalCwd = process.cwd();
const originalGsdHome = process.env.GSD_HOME;
const tempProject = mkdtempSync(join(tmpdir(), "gsd-prefs-project-"));
const tempGsdHome = mkdtempSync(join(tmpdir(), "gsd-prefs-home-"));
try {
mkdirSync(join(tempProject, ".gsd"), { recursive: true });
writeFileSync(
join(tempGsdHome, "preferences.md"),
[
"---",
"version: 1",
"experimental:",
" rtk: true",
"---",
].join("\n"),
"utf-8",
);
writeFileSync(
join(tempProject, ".gsd", "PREFERENCES.md"),
[
"---",
"version: 1",
"git:",
" isolation: none",
"---",
].join("\n"),
"utf-8",
);
process.env.GSD_HOME = tempGsdHome;
process.chdir(tempProject);
const loaded = loadEffectiveGSDPreferences();
assert.notEqual(loaded, null);
assert.equal(loaded!.preferences.experimental?.rtk, true);
assert.equal(loaded!.preferences.git?.isolation, "none");
} finally {
process.chdir(originalCwd);
if (originalGsdHome === undefined) delete process.env.GSD_HOME;
else process.env.GSD_HOME = originalGsdHome;
rmSync(tempProject, { recursive: true, force: true });
rmSync(tempGsdHome, { recursive: true, force: true });
}
});
test("experimental.rtk defaults to off in new project preferences", () => {
// No experimental key → feature is disabled
const content = "---\nversion: 1\n---\n";