fix(config): warn on unrecognized keys in config.json instead of silent drop (#1542)

* fix(config): warn on unrecognized keys in config.json instead of silent drop (#1535)

loadConfig() silently ignores any config.json keys not in its known
set, leaving users confused when their settings have no effect. Add a
stderr warning listing unrecognized top-level keys so the problem
surfaces immediately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(config): derive known keys from VALID_CONFIG_KEYS instead of hardcoded set

Address review feedback: replace hardcoded KNOWN_CONFIG_KEYS with
programmatic derivation from config-set's VALID_CONFIG_KEYS (single
source of truth). New config keys added to config-set are automatically
recognized by loadConfig without a separate update. Add sync test
verifying all VALID_CONFIG_KEYS entries pass without warning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tibsfox
2026-04-04 04:11:00 -07:00
committed by GitHub
parent bd6a13186b
commit 12a4545124
3 changed files with 78 additions and 0 deletions

View File

@@ -126,6 +126,61 @@ describe('loadConfig', () => {
const config = loadConfig(tmpDir);
assert.strictEqual(config.commit_docs, false);
});
test('warns on unknown config keys to stderr (#1535)', () => {
writeConfig({ model_profile: 'quality', active_project: 'my-project', custom_flag: true });
const origWrite = process.stderr.write;
let stderrOutput = '';
process.stderr.write = (chunk) => { stderrOutput += chunk; };
try {
const config = loadConfig(tmpDir);
// Known key still loads correctly
assert.strictEqual(config.model_profile, 'quality');
// Warning emitted for unknown keys
assert.ok(stderrOutput.includes('active_project'), 'should warn about active_project');
assert.ok(stderrOutput.includes('custom_flag'), 'should warn about custom_flag');
assert.ok(stderrOutput.includes('ignored'), 'should mention keys will be ignored');
} finally {
process.stderr.write = origWrite;
}
});
test('known config keys are derived from VALID_CONFIG_KEYS (not hardcoded)', () => {
// Verify that loadConfig's unknown-key check uses config-set's VALID_CONFIG_KEYS
// as its source of truth. If a new key is added to config-set, it should
// automatically be recognized by loadConfig without a separate update.
const { VALID_CONFIG_KEYS } = require('../get-shit-done/bin/lib/config.cjs');
// Every top-level key from VALID_CONFIG_KEYS should be recognized
const topLevelKeys = [...VALID_CONFIG_KEYS].map(k => k.split('.')[0]);
for (const key of topLevelKeys) {
writeConfig({ [key]: 'test-value' });
const origWrite = process.stderr.write;
let stderrOutput = '';
process.stderr.write = (chunk) => { stderrOutput += chunk; };
try {
loadConfig(tmpDir);
assert.ok(
!stderrOutput.includes(key),
`VALID_CONFIG_KEYS key "${key}" should not trigger unknown-key warning`
);
} finally {
process.stderr.write = origWrite;
}
}
});
test('does not warn when all config keys are known', () => {
writeConfig({ model_profile: 'balanced', workflow: { research: false }, git: { branching_strategy: 'per-phase' } });
const origWrite = process.stderr.write;
let stderrOutput = '';
process.stderr.write = (chunk) => { stderrOutput += chunk; };
try {
loadConfig(tmpDir);
assert.strictEqual(stderrOutput, '', 'should not emit any warnings for valid config');
} finally {
process.stderr.write = origWrite;
}
});
});
// ─── loadConfig commit_docs gitignore auto-detection (#1250) ──────────────────