diff --git a/hermes_cli/moa_config.py b/hermes_cli/moa_config.py index 389765a2d2..17ed12c6a4 100644 --- a/hermes_cli/moa_config.py +++ b/hermes_cli/moa_config.py @@ -29,7 +29,7 @@ def _coerce_number(value: Any, cast, default=None, *, positive: bool = False): """Coerce ``value`` with ``cast`` (float/int); ``default`` when unset/blank/invalid. ``int`` also accepts float-looking strings ("3.0"). With ``positive`` the result must be > 0 - (and finite for floats) or ``default`` is returned.""" + or ``default`` is returned. Non-finite floats always fall back to ``default``.""" if value is None or value == "": return default try: @@ -41,7 +41,7 @@ def _coerce_number(value: Any, cast, default=None, *, positive: bool = False): number = int(float(value)) except (TypeError, ValueError, OverflowError): return default - if positive and (number <= 0 or (cast is float and not math.isfinite(number))): + if (cast is float and not math.isfinite(number)) or (positive and number <= 0): return default return number diff --git a/tests/hermes_cli/test_moa_numeric_config.py b/tests/hermes_cli/test_moa_numeric_config.py index a32d227307..3a71bf8a93 100644 --- a/tests/hermes_cli/test_moa_numeric_config.py +++ b/tests/hermes_cli/test_moa_numeric_config.py @@ -1,5 +1,6 @@ """Malformed numeric MoA settings must degrade to defaults, not break the CLI or JSON.""" +import json import os from pathlib import Path import subprocess @@ -33,3 +34,23 @@ def test_moa_list_tolerates_nonfinite_fanout(tmp_path, fanout): normalized = normalize_moa_config({"fanout": fanout}) assert normalized["fanout"] == normalize_moa_config({})["fanout"] + +@pytest.mark.parametrize("temperature", [float("nan"), float("inf"), float("-inf"), "NaN", "inf", "-inf"]) +def test_nonfinite_temperatures_do_not_escape_into_json(temperature): + raw = { + "reference_temperature": temperature, + "aggregator_temperature": temperature, + } + normalized = normalize_moa_config(raw) + assert normalized["reference_temperature"] is None + assert normalized["aggregator_temperature"] is None + json.dumps(normalized, allow_nan=False) + + finite = normalize_moa_config({ + "reference_temperature": 0, + "aggregator_temperature": "0.75", + "fanout": {"mode": "every_n", "n": "3.0"}, + }) + assert finite["reference_temperature"] == 0 + assert finite["aggregator_temperature"] == 0.75 + assert finite["fanout"] == "every_n:3"