fix(config): treat empty-dict DEFAULT_CONFIG sections as open containers in the typo gate

compression.model_thresholds.<model>, terminal.docker_env.<VAR>, lsp.servers.<lang>.*,
auxiliary.<task>.extra_body.<k> and similar free-form mappings are declared as {} in
DEFAULT_CONFIG; the fail-closed gate walked into the empty dict, found the user-chosen key
missing and refused the write. An empty dict now accepts the rest of the path, like a scalar
leaf or a platforms container does. Populated sections keep the did-you-mean refusal.
This commit is contained in:
teknium1
2026-09-15 15:01:34 -07:00
committed by Teknium
parent 33b6c4c650
commit c1115a7166
2 changed files with 23 additions and 4 deletions
+6 -4
View File
@@ -3298,13 +3298,15 @@ def _validate_config_key(key: str) -> tuple[bool, Optional[str]]:
if top in _OPEN_SUBKEY_TOP_LEVEL_KEYS:
return True, None
# Walk DEFAULT_CONFIG: a nested ``platforms`` container or a scalar leaf hit before the path is
# consumed both accept (the latter matches set_config_value's leaf->dict replacement); an
# unknown sub-key fails with a same-level "did you mean" suggestion.
# Walk DEFAULT_CONFIG: a nested ``platforms`` container, a scalar leaf, or an EMPTY dict hit
# before the path is consumed all accept. An empty dict is a free-form mapping section
# (``compression.model_thresholds.<model>``, ``terminal.docker_env.<VAR>``,
# ``lsp.servers.<lang>``): its keys are user-chosen, so nothing under it can be a typo. An
# unknown sub-key of a populated section fails with a same-level "did you mean" suggestion.
node: Any = DEFAULT_CONFIG.get(top)
consumed = [top]
for seg in segments[1:]:
if seg in _PLATFORM_CONTAINER_KEYS or not isinstance(node, dict):
if seg in _PLATFORM_CONTAINER_KEYS or not isinstance(node, dict) or not node:
return True, None
if seg not in node:
sibling = _suggest_closest_key(seg, set(node.keys()))
+17
View File
@@ -1941,3 +1941,20 @@ def test_gateway_multiplex_keys_are_recognized_config_keys():
known, suggestion = _validate_config_key("gateway.auto_migrate")
assert known is False
assert suggestion == "gateway.auto_multiplex_migration"
def test_empty_dict_default_sections_are_open_containers():
"""``compression.model_thresholds.<model>`` / ``terminal.docker_env.<VAR>`` are free-form
mappings declared as ``{}`` in DEFAULT_CONFIG: their user-chosen keys must not be refused as
typos, while a real typo under a populated sibling section still gets a suggestion."""
from hermes_cli.config import _validate_config_key
from hermes_cli.config_defaults import DEFAULT_CONFIG
assert DEFAULT_CONFIG["compression"]["model_thresholds"] == {}
assert DEFAULT_CONFIG["terminal"]["docker_env"] == {}
assert _validate_config_key("compression.model_thresholds.gpt-5") == (True, None)
assert _validate_config_key("terminal.docker_env.FOO") == (True, None)
assert _validate_config_key("lsp.servers.python.command") == (True, None)
assert _validate_config_key("auxiliary.vision.extra_body.reasoning") == (True, None)
known, suggestion = _validate_config_key("compression.model_threshold.gpt-5")
assert known is False
assert suggestion == "compression.model_thresholds"