fix(preferences): deduplicate unrecognized format warning on repeated loads (#2375)

parsePreferencesMarkdown emitted a console.warn every time preferences
were loaded with an unrecognized format, spamming stderr on each call
to loadEffectiveGSDPreferences. Gate the warning behind a warn-once
flag so it prints at most once per process.

Fixes #2373

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tom Boucher 2026-03-25 00:06:37 -04:00 committed by GitHub
parent e0b3bad2a5
commit d21db9f398
2 changed files with 38 additions and 1 deletions

View file

@ -196,6 +196,13 @@ function loadPreferencesFile(path: string, scope: "global" | "project"): LoadedG
};
}
let _warnedUnrecognizedFormat = false;
/** @internal Reset the warn-once flag — exported for testing only. */
export function _resetParseWarningFlag(): void {
_warnedUnrecognizedFormat = false;
}
/** @internal Exported for testing only */
export function parsePreferencesMarkdown(content: string): GSDPreferences | null {
// Use indexOf instead of [\s\S]*? regex to avoid backtracking (#468)
@ -214,7 +221,10 @@ export function parsePreferencesMarkdown(content: string): GSDPreferences | null
return parseHeadingListFormat(content);
}
console.warn("[parsePreferencesMarkdown] preferences.md exists but uses an unrecognized format — skipping.");
if (!_warnedUnrecognizedFormat) {
_warnedUnrecognizedFormat = true;
console.warn("[parsePreferencesMarkdown] preferences.md exists but uses an unrecognized format — skipping.");
}
return null;
}

View file

@ -15,6 +15,7 @@ import {
applyModeDefaults,
getIsolationMode,
parsePreferencesMarkdown,
_resetParseWarningFlag,
} from "../preferences.ts";
import type { GSDPreferences, GSDModelConfigV2, GSDPhaseModelConfig } from "../preferences.ts";
@ -352,3 +353,29 @@ test("handles empty models config", () => {
assert.notEqual(prefs, null);
assert.equal(prefs!.models, undefined);
});
// ── Warn-once for unrecognized format (#2373) ────────────────────────────────
test("unrecognized format warning is emitted at most once (#2373)", () => {
const warnings: string[] = [];
const origWarn = console.warn;
console.warn = (...args: unknown[]) => warnings.push(args.join(" "));
try {
// Reset internal warned flag so the test starts clean
_resetParseWarningFlag();
const unrecognized = "This is just plain text with no frontmatter or headings.";
// Call multiple times — simulates repeated preference loads
parsePreferencesMarkdown(unrecognized);
parsePreferencesMarkdown(unrecognized);
parsePreferencesMarkdown(unrecognized);
const relevant = warnings.filter(w => w.includes("unrecognized format"));
assert.equal(relevant.length, 1, `expected exactly 1 warning, got ${relevant.length}: ${JSON.stringify(relevant)}`);
} finally {
console.warn = origWarn;
// Reset so other tests aren't affected by the flag state
_resetParseWarningFlag();
}
});