fix: coerce show_reasoning and guard_agent_created config bools

Widens #16528 to two sibling sites that had the same quoted-boolean
bug: a YAML string "false" (or "0", "no", "off") silently evaluated
truthy under bool() / if-check.

- gateway/run.py _load_show_reasoning: is_truthy_value wrap
- tools/skill_manager_tool.py _guard_agent_created_enabled: is_truthy_value wrap
- regression tests for both
This commit is contained in:
Teknium 2026-04-30 20:39:29 -07:00
parent bb706c3f38
commit 27ec74c68a
4 changed files with 70 additions and 3 deletions

View file

@ -407,3 +407,44 @@ class TestReasoningCommand:
assert result["final_response"] == "ok"
assert _CapturingAgent.last_init is not None
assert "homeassistant" in set(_CapturingAgent.last_init["enabled_toolsets"])
class TestLoadShowReasoningCoercion:
"""Regression: display.show_reasoning must be coerced, not bool()'d."""
def _load_with_config(self, tmp_path, monkeypatch, yaml_body: str) -> bool:
hermes_home = tmp_path / "hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(yaml_body, encoding="utf-8")
monkeypatch.setattr(gateway_run, "_hermes_home", hermes_home)
return gateway_run.GatewayRunner._load_show_reasoning()
def test_quoted_false_is_false(self, tmp_path, monkeypatch):
assert self._load_with_config(
tmp_path, monkeypatch,
'display:\n show_reasoning: "false"\n',
) is False
def test_quoted_off_is_false(self, tmp_path, monkeypatch):
assert self._load_with_config(
tmp_path, monkeypatch,
'display:\n show_reasoning: "off"\n',
) is False
def test_quoted_true_is_true(self, tmp_path, monkeypatch):
assert self._load_with_config(
tmp_path, monkeypatch,
'display:\n show_reasoning: "true"\n',
) is True
def test_bare_true_is_true(self, tmp_path, monkeypatch):
assert self._load_with_config(
tmp_path, monkeypatch,
'display:\n show_reasoning: true\n',
) is True
def test_missing_is_false(self, tmp_path, monkeypatch):
assert self._load_with_config(
tmp_path, monkeypatch,
'display: {}\n',
) is False

View file

@ -567,6 +567,26 @@ class TestSecurityScanGate:
with patch("hermes_cli.config.load_config", side_effect=RuntimeError("boom")):
assert _guard_agent_created_enabled() is False
def test_guard_flag_quoted_false_stays_disabled(self):
"""Quoted 'false' from YAML edits must not enable the guard."""
from tools.skill_manager_tool import _guard_agent_created_enabled
for quoted in ("false", "False", "0", "no", "off"):
with patch("hermes_cli.config.load_config",
return_value={"skills": {"guard_agent_created": quoted}}):
assert _guard_agent_created_enabled() is False, \
f"guard_agent_created={quoted!r} must coerce to False"
def test_guard_flag_quoted_true_enables(self):
"""Quoted truthy strings must enable the guard."""
from tools.skill_manager_tool import _guard_agent_created_enabled
for quoted in ("true", "True", "1", "yes", "on"):
with patch("hermes_cli.config.load_config",
return_value={"skills": {"guard_agent_created": quoted}}):
assert _guard_agent_created_enabled() is True, \
f"guard_agent_created={quoted!r} must coerce to True"
# ---------------------------------------------------------------------------
# External skills directories (skills.external_dirs) — mutations in place