diff --git a/get-shit-done/bin/lib/config-schema.cjs b/get-shit-done/bin/lib/config-schema.cjs index 2fec078c0..bba9d44b0 100644 --- a/get-shit-done/bin/lib/config-schema.cjs +++ b/get-shit-done/bin/lib/config-schema.cjs @@ -69,6 +69,18 @@ const VALID_CONFIG_KEYS = new Set([ 'claude_md_assembly.mode', // #2517 — runtime-aware model profiles 'runtime', + // #3162 — documented top-level key: controls model ID resolution for non-Claude runtimes + 'resolve_model_ids', +]); + +/** + * Internal runtime-state keys — accepted by config-set (workflows write them) but not + * exposed as user-settable options. Excluded from VALID_CONFIG_KEYS so they stay out of + * the public docs-parity check and the "Valid keys:" error message. + * See: #3162 (workflow._auto_chain_active written by plan/execute/discuss workflows) + */ +const RUNTIME_STATE_KEYS = new Set([ + 'workflow._auto_chain_active', ]); /** @@ -98,11 +110,12 @@ const DYNAMIC_KEY_PATTERNS = [ ]; /** - * Returns true if keyPath is a valid config key (exact or dynamic pattern). + * Returns true if keyPath is a valid config key (exact, dynamic pattern, or runtime state). */ function isValidConfigKey(keyPath) { if (VALID_CONFIG_KEYS.has(keyPath)) return true; + if (RUNTIME_STATE_KEYS.has(keyPath)) return true; return DYNAMIC_KEY_PATTERNS.some((p) => p.test(keyPath)); } -module.exports = { VALID_CONFIG_KEYS, DYNAMIC_KEY_PATTERNS, isValidConfigKey }; +module.exports = { VALID_CONFIG_KEYS, RUNTIME_STATE_KEYS, DYNAMIC_KEY_PATTERNS, isValidConfigKey }; diff --git a/sdk/src/query/config-schema.ts b/sdk/src/query/config-schema.ts index 0029efa6a..d1b245f17 100644 --- a/sdk/src/query/config-schema.ts +++ b/sdk/src/query/config-schema.ts @@ -71,6 +71,8 @@ export const VALID_CONFIG_KEYS: ReadonlySet = new Set([ 'claude_md_assembly.mode', // #2517 — runtime-aware model profiles 'runtime', + // #3162 — documented top-level key: controls model ID resolution for non-Claude runtimes + 'resolve_model_ids', ]); /** diff --git a/tests/bug-2530-valid-config-keys.test.cjs b/tests/bug-2530-valid-config-keys.test.cjs index 78e5c3ad1..257a94358 100644 --- a/tests/bug-2530-valid-config-keys.test.cjs +++ b/tests/bug-2530-valid-config-keys.test.cjs @@ -7,6 +7,8 @@ * #2532 — workflow.ui_review is used in autonomous.md but missing from VALID_CONFIG_KEYS * #2533 — workflow.max_discuss_passes is used in discuss-phase.md but missing from VALID_CONFIG_KEYS * #2535 — sub_repos and plan_checker legacy keys need CONFIG_KEY_SUGGESTIONS migration hints + * #3162 — resolve_model_ids missing from VALID_CONFIG_KEYS; workflow._auto_chain_active must be + * accepted by isValidConfigKey (written by workflows) without being user-visible */ const { describe, test } = require('node:test'); @@ -14,7 +16,7 @@ const assert = require('node:assert/strict'); const path = require('node:path'); const { createTempProject, cleanup, runGsdTools } = require('./helpers.cjs'); -const { VALID_CONFIG_KEYS } = require('../get-shit-done/bin/lib/config-schema.cjs'); +const { VALID_CONFIG_KEYS, isValidConfigKey } = require('../get-shit-done/bin/lib/config-schema.cjs'); describe('VALID_CONFIG_KEYS correctness', () => { test('#2530: workflow._auto_chain_active must not be in VALID_CONFIG_KEYS (internal state)', () => { @@ -44,6 +46,20 @@ describe('VALID_CONFIG_KEYS correctness', () => { 'workflow.max_discuss_passes is read in discuss-phase.md via gsd-sdk query config-get' ); }); + + test('#3162: resolve_model_ids must be in VALID_CONFIG_KEYS (documented user-facing key)', () => { + assert.ok( + VALID_CONFIG_KEYS.has('resolve_model_ids'), + 'resolve_model_ids is documented in CONFIGURATION.md and read by core.cjs/session-runner.ts' + ); + }); + + test('#3162: workflow._auto_chain_active must be accepted by isValidConfigKey (written by workflows)', () => { + assert.ok( + isValidConfigKey('workflow._auto_chain_active'), + 'workflow._auto_chain_active is written by plan-phase, execute-phase, discuss-phase, transition workflows via config-set' + ); + }); }); describe('CONFIG_KEY_SUGGESTIONS migration hints (#2535)', () => {