The SDK's config-set kept its own hand-maintained allowlist (28-key drift vs. get-shit-done/bin/lib/config-schema.cjs), so documented keys accepted by the CJS config-set — planning.sub_repos, workflow.code_review_command, workflow.security_*, review.models.*, model_profile_overrides.*, etc. — were rejected with "Unknown config key" when routed through the SDK. Changes: - New sdk/src/query/config-schema.ts mirrors the CJS schema exactly (exact-match keys + dynamic regex sources). - config-mutation.ts imports VALID_CONFIG_KEYS / DYNAMIC_KEY_PATTERNS from the shared module instead of rolling its own set and regex branches. - Drop hand-coded agent_skills.* / features.* regex branches — now schema-driven so claude_md_assembly.blocks.*, review.models.*, and model_profile_overrides.<runtime>.<tier> are also accepted. - Add tests/config-schema-sdk-parity.test.cjs (node:test) as the CI drift guard: asserts CJS VALID_CONFIG_KEYS set-equals the literal set parsed from config-schema.ts, and that every CJS dynamic pattern source has an identical counterpart in the SDK. Parallel to the CJS↔docs parity added in #2479. - Vitest #2653 specs iterate every CJS key through the SDK validator, spot-check each dynamic pattern, and lock in planning.sub_repos. - While here: add workflow.context_coverage_gate to the CJS schema (already in docs and SDK; CJS previously rejected it) and sync the missing curated typo-suggestions (review.model, sub_repos, plan_checker, workflow.review_command) into the SDK. Fixes #2653.
This commit is contained in:
@@ -86,6 +86,42 @@ describe('isValidConfigKey', () => {
|
||||
expect(r2.valid).toBe(false);
|
||||
expect(r2.suggestion).toBe('workflow.nyquist_validation');
|
||||
});
|
||||
|
||||
// #2653 — SDK/CJS config-schema drift regression.
|
||||
// Every key accepted by the CJS config-set must also be accepted by
|
||||
// the SDK config-set. We exercise every entry in the shared schema
|
||||
// so drift fails this test the moment it is introduced.
|
||||
it('#2653 — accepts every key in shared VALID_CONFIG_KEYS', async () => {
|
||||
const { isValidConfigKey } = await import('./config-mutation.js');
|
||||
const { VALID_CONFIG_KEYS } = await import('./config-schema.js');
|
||||
const rejected: string[] = [];
|
||||
for (const key of VALID_CONFIG_KEYS) {
|
||||
const { valid } = isValidConfigKey(key);
|
||||
if (!valid) rejected.push(key);
|
||||
}
|
||||
expect(rejected).toEqual([]);
|
||||
});
|
||||
|
||||
it('#2653 — accepts sample dynamic keys from every DYNAMIC_KEY_PATTERN', async () => {
|
||||
const { isValidConfigKey } = await import('./config-mutation.js');
|
||||
const samples = [
|
||||
'agent_skills.gsd-planner',
|
||||
'review.models.claude',
|
||||
'features.some_feature',
|
||||
'claude_md_assembly.blocks.intro',
|
||||
'model_profile_overrides.codex.opus',
|
||||
'model_profile_overrides.codex.sonnet',
|
||||
'model_profile_overrides.my-runtime.haiku',
|
||||
];
|
||||
for (const key of samples) {
|
||||
expect(isValidConfigKey(key).valid, `expected ${key} to be accepted`).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('#2653 — accepts planning.sub_repos (CJS/docs key, previously rejected by SDK)', async () => {
|
||||
const { isValidConfigKey } = await import('./config-mutation.js');
|
||||
expect(isValidConfigKey('planning.sub_repos').valid).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── parseConfigValue ──────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user