diff --git a/hermes_cli/kanban_diagnostics.py b/hermes_cli/kanban_diagnostics.py index 8acd6dd932..bed5a6ebcc 100644 --- a/hermes_cli/kanban_diagnostics.py +++ b/hermes_cli/kanban_diagnostics.py @@ -41,6 +41,15 @@ import time SEVERITY_ORDER = ("warning", "error", "critical") +def severity_at_or_above(severity: Optional[str], threshold: Optional[str]) -> bool: + """Return True when ``severity`` meets or exceeds ``threshold``.""" + if threshold is None: + return True + if severity not in SEVERITY_ORDER or threshold not in SEVERITY_ORDER: + return False + return SEVERITY_ORDER.index(severity) >= SEVERITY_ORDER.index(threshold) + + @dataclass class DiagnosticAction: """A single recovery action attached to a diagnostic. diff --git a/plugins/kanban/dashboard/plugin_api.py b/plugins/kanban/dashboard/plugin_api.py index f13755dfb7..44bb33960c 100644 --- a/plugins/kanban/dashboard/plugin_api.py +++ b/plugins/kanban/dashboard/plugin_api.py @@ -49,6 +49,7 @@ from fastapi import APIRouter, HTTPException, Query, WebSocket, WebSocketDisconn from pydantic import BaseModel, Field from hermes_cli import kanban_db +from hermes_cli import kanban_diagnostics as kd log = logging.getLogger(__name__) @@ -1001,7 +1002,7 @@ def list_diagnostics( if severity: filtered: dict[str, list[dict]] = {} for tid, dl in diags_by_task.items(): - keep = [d for d in dl if d.get("severity") == severity] + keep = [d for d in dl if kd.severity_at_or_above(d.get("severity"), severity)] if keep: filtered[tid] = keep diags_by_task = filtered diff --git a/tests/hermes_cli/test_kanban_diagnostics.py b/tests/hermes_cli/test_kanban_diagnostics.py index 6329825ce1..2de4933dc6 100644 --- a/tests/hermes_cli/test_kanban_diagnostics.py +++ b/tests/hermes_cli/test_kanban_diagnostics.py @@ -737,3 +737,14 @@ def test_config_from_runtime_config_carries_aux_and_model(): def test_config_from_runtime_config_handles_empty_input(): assert kd.config_from_runtime_config(None) == {} assert kd.config_from_runtime_config({}) == {} + + +def test_severity_at_or_above_uses_threshold_semantics(): + assert kd.severity_at_or_above("warning", "warning") is True + assert kd.severity_at_or_above("error", "warning") is True + assert kd.severity_at_or_above("critical", "warning") is True + assert kd.severity_at_or_above("critical", "error") is True + assert kd.severity_at_or_above("warning", "error") is False + assert kd.severity_at_or_above("error", "critical") is False + assert kd.severity_at_or_above("mystery", "warning") is False + assert kd.severity_at_or_above("warning", None) is True