fix(config): add resolve_model_ids to VALID_CONFIG_KEYS; accept workflow._auto_chain_active via RUNTIME_STATE_KEYS

Fixes #3162

`resolve_model_ids` is a documented top-level config key (CONFIGURATION.md)
read by core.cjs and session-runner.ts, but was missing from the CJS and SDK
VALID_CONFIG_KEYS allowlists — causing config-set to reject it with
"Unknown config key".

`workflow._auto_chain_active` is internal runtime state intentionally excluded
from VALID_CONFIG_KEYS by #2530, but plan-phase, execute-phase, discuss-phase,
transition, and new-project workflows all write it via `config-set`. Without
a valid write path these calls emit spurious errors (silenced with `|| true`
but noisy in logs). A new RUNTIME_STATE_KEYS set in config-schema.cjs holds
keys that isValidConfigKey() accepts without exposing them as user-settable
options — preserving the #2530 intent while fixing the runtime error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-05-06 14:56:34 -04:00
parent 94f835af40
commit 96ce608ee6
3 changed files with 34 additions and 3 deletions

View File

@@ -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 };

View File

@@ -71,6 +71,8 @@ export const VALID_CONFIG_KEYS: ReadonlySet<string> = 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',
]);
/**

View File

@@ -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)', () => {