Skip to content

Commit 1479544

Browse files
authored
feat(radar): add persistent_red, note and red_streak from SO radar (#31)
- RadarSummary: add persistent_red field (top-level count) - RadarSource: add note (str|null) and red_streak (int) fields - parse_radar_summary(): extract new fields from JSON - triage._build_radar_dict(): include persistent_red, note, red_streak in output - render session_bootstrap: show persistent RED warning + per-source note and streak - test_signals.test_parse_radar_summary: cover new fields
1 parent f34b3b0 commit 1479544

4 files changed

Lines changed: 30 additions & 3 deletions

File tree

src/agent_context_builder/render.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,15 @@ def render_session_bootstrap(self) -> str:
7979
f"GREEN {radar.green} · YELLOW {radar.yellow} · RED {radar.red} "
8080
f"(probe: {radar.probe_date})"
8181
)
82+
if radar.persistent_red:
83+
lines.append(f" ⚠ **{radar.persistent_red} persistent RED**")
8284
if radar.unhealthy:
8385
for s in radar.unhealthy:
8486
di = f" — ↳ {', '.join(s.datasets_in_use)}" if s.datasets_in_use else ""
87+
streak = f" (streak {s.red_streak})" if s.red_streak else ""
88+
note = f" — {s.note}" if s.note else ""
8589
lines.append(
86-
f" · **{s.id}** {s.status} [{s.http_code}]{di}"
90+
f" · **{s.id}** {s.status} [{s.http_code}]{note}{streak}{di}"
8791
)
8892
else:
8993
lines.append("**Radar**: unavailable")

src/agent_context_builder/signals.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ class RadarSource:
298298
http_code: str
299299
last_check: str
300300
datasets_in_use: list[str] = field(default_factory=list)
301+
note: str | None = None
302+
red_streak: int = 0
301303

302304

303305
@dataclass
@@ -310,6 +312,7 @@ class RadarSummary:
310312
green: int
311313
yellow: int
312314
red: int
315+
persistent_red: int = 0
313316
sources: list[RadarSource] = field(default_factory=list)
314317

315318
@property
@@ -333,6 +336,8 @@ def parse_radar_summary(raw: str) -> RadarSummary:
333336
http_code=s.get("http_code", "-"),
334337
last_check=s.get("last_check", ""),
335338
datasets_in_use=s.get("datasets_in_use") or [],
339+
note=s.get("note"),
340+
red_streak=s.get("red_streak", 0),
336341
)
337342
for s in data.get("sources", [])
338343
]
@@ -344,6 +349,7 @@ def parse_radar_summary(raw: str) -> RadarSummary:
344349
green=counts.get("GREEN", 0),
345350
yellow=counts.get("YELLOW", 0),
346351
red=counts.get("RED", 0),
352+
persistent_red=data.get("persistent_red", 0),
347353
sources=sources,
348354
)
349355

src/agent_context_builder/triage.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,16 @@ def _build_radar_dict(fetcher: SourceObservatoryFetcher) -> dict[str, Any]:
101101
"green": radar.green,
102102
"yellow": radar.yellow,
103103
"red": radar.red,
104+
"persistent_red": radar.persistent_red,
104105
"unhealthy": [
105-
{"id": s.id, "status": s.status, "protocol": s.protocol, "http_code": s.http_code}
106+
{
107+
"id": s.id,
108+
"status": s.status,
109+
"protocol": s.protocol,
110+
"http_code": s.http_code,
111+
"note": s.note,
112+
"red_streak": s.red_streak,
113+
}
106114
for s in radar.unhealthy
107115
],
108116
}

tests/test_signals.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,18 @@ def test_parse_radar_summary():
294294
"probe_date": "2026-04-19",
295295
"sources_total": 3,
296296
"status_counts": {"GREEN": 2, "YELLOW": 1, "RED": 0},
297+
"persistent_red": 1,
297298
"sources": [
298299
{"id": "inps", "status": "GREEN", "protocol": "ckan",
299300
"observation_mode": "catalog-watch", "http_code": "200",
300301
"last_check": "2026-04-19", "datasets_in_use": ["ds1"]},
301302
{"id": "anac", "status": "YELLOW", "protocol": "ckan",
302303
"observation_mode": "radar-only", "http_code": "200",
303304
"last_check": "2026-04-19", "datasets_in_use": []},
305+
{"id": "dati_salute", "status": "RED", "protocol": "html",
306+
"observation_mode": "radar-only", "http_code": "-",
307+
"last_check": "2026-04-19", "datasets_in_use": [],
308+
"note": "SSL verify failed", "red_streak": 2},
304309
{"id": "istat", "status": "GREEN", "protocol": "sdmx",
305310
"observation_mode": "catalog-watch", "http_code": "200",
306311
"last_check": "2026-04-19", "datasets_in_use": []},
@@ -311,8 +316,12 @@ def test_parse_radar_summary():
311316
assert summary.green == 2
312317
assert summary.yellow == 1
313318
assert summary.red == 0
314-
assert len(summary.unhealthy) == 1
319+
assert summary.persistent_red == 1
320+
assert len(summary.unhealthy) == 2
315321
assert summary.unhealthy[0].id == "anac"
322+
assert summary.unhealthy[1].id == "dati_salute"
323+
assert summary.unhealthy[1].note == "SSL verify failed"
324+
assert summary.unhealthy[1].red_streak == 2
316325

317326

318327
def test_parse_di_clean_catalog_basic():

0 commit comments

Comments
 (0)