mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
fix(kanban): honor severity thresholds in diagnostics
Salvages #26431 by @LeonSGP43. Dashboard plugin_api list_diagnostics was using exact-match (severity == filter), so '--severity warning' hid 'error' and 'critical' diagnostics. Adds severity_at_or_above() helper to kanban_diagnostics and uses it in the dashboard endpoint (CLI already used SEVERITY_ORDER comparison correctly).
This commit is contained in:
parent
9f008bcd5c
commit
a94ddd8073
3 changed files with 22 additions and 1 deletions
|
|
@ -41,6 +41,15 @@ import time
|
||||||
SEVERITY_ORDER = ("warning", "error", "critical")
|
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
|
@dataclass
|
||||||
class DiagnosticAction:
|
class DiagnosticAction:
|
||||||
"""A single recovery action attached to a diagnostic.
|
"""A single recovery action attached to a diagnostic.
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ from fastapi import APIRouter, HTTPException, Query, WebSocket, WebSocketDisconn
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from hermes_cli import kanban_db
|
from hermes_cli import kanban_db
|
||||||
|
from hermes_cli import kanban_diagnostics as kd
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -1001,7 +1002,7 @@ def list_diagnostics(
|
||||||
if severity:
|
if severity:
|
||||||
filtered: dict[str, list[dict]] = {}
|
filtered: dict[str, list[dict]] = {}
|
||||||
for tid, dl in diags_by_task.items():
|
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:
|
if keep:
|
||||||
filtered[tid] = keep
|
filtered[tid] = keep
|
||||||
diags_by_task = filtered
|
diags_by_task = filtered
|
||||||
|
|
|
||||||
|
|
@ -737,3 +737,14 @@ def test_config_from_runtime_config_carries_aux_and_model():
|
||||||
def test_config_from_runtime_config_handles_empty_input():
|
def test_config_from_runtime_config_handles_empty_input():
|
||||||
assert kd.config_from_runtime_config(None) == {}
|
assert kd.config_from_runtime_config(None) == {}
|
||||||
assert kd.config_from_runtime_config({}) == {}
|
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue