feat(governance): surface verification coverage
This commit is contained in:
@@ -4,7 +4,10 @@ from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from src.services.adr100_slo_status_service import Adr100SloStatusService
|
||||
from src.services.adr100_slo_status_service import (
|
||||
Adr100SloStatusService,
|
||||
_build_verification_coverage_payload,
|
||||
)
|
||||
|
||||
|
||||
class _FakePrometheusResponse:
|
||||
@@ -39,6 +42,31 @@ class _FakePrometheusClient:
|
||||
})
|
||||
|
||||
|
||||
async def _low_volume_coverage(self): # noqa: ANN001
|
||||
return {
|
||||
"schema_version": "adr100_verification_coverage_v1",
|
||||
"source": "postgresql",
|
||||
"window": "24h",
|
||||
"status": "skipped_low_volume",
|
||||
"reason": "no_auto_repair_executions_24h",
|
||||
"evaluable": False,
|
||||
"total_auto": 0,
|
||||
"successful_auto": 0,
|
||||
"verified_auto": 0,
|
||||
"verified_success": 0,
|
||||
"verified_non_success": 0,
|
||||
"unverified_auto": 0,
|
||||
"coverage_rate": None,
|
||||
"verification_success_rate": None,
|
||||
"last_auto_at": None,
|
||||
"last_verified_auto_at": None,
|
||||
"last_verification_evidence_at": None,
|
||||
"latest_auto_age_seconds": None,
|
||||
"last_verified_auto_age_seconds": None,
|
||||
"recent_unverified": [],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_report_marks_ratio_slos_low_volume(monkeypatch):
|
||||
values = {
|
||||
@@ -52,6 +80,11 @@ async def test_fetch_report_marks_ratio_slos_low_volume(monkeypatch):
|
||||
"httpx.AsyncClient",
|
||||
lambda *args, **kwargs: _FakePrometheusClient(values),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
Adr100SloStatusService,
|
||||
"_fetch_verification_coverage",
|
||||
_low_volume_coverage,
|
||||
)
|
||||
|
||||
report = await Adr100SloStatusService().fetch_report()
|
||||
|
||||
@@ -79,6 +112,11 @@ async def test_fetch_report_classifies_hard_red_line_violation(monkeypatch):
|
||||
"httpx.AsyncClient",
|
||||
lambda *args, **kwargs: _FakePrometheusClient(values),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
Adr100SloStatusService,
|
||||
"_fetch_verification_coverage",
|
||||
_low_volume_coverage,
|
||||
)
|
||||
|
||||
report = await Adr100SloStatusService().fetch_report()
|
||||
|
||||
@@ -87,3 +125,53 @@ async def test_fetch_report_classifies_hard_red_line_violation(monkeypatch):
|
||||
assert by_name["autonomy_rate"]["sample_count"] == 6
|
||||
assert by_name["km_growth_rate"]["status"] == "violated"
|
||||
assert report["overall_status"] == "violated"
|
||||
|
||||
|
||||
def test_verification_coverage_payload_flags_backlog():
|
||||
payload = _build_verification_coverage_payload(
|
||||
{
|
||||
"total_auto": 7,
|
||||
"successful_auto": 6,
|
||||
"verified_auto": 5,
|
||||
"verified_success": 4,
|
||||
"verified_non_success": 1,
|
||||
"unverified_auto": 2,
|
||||
"last_auto_at": None,
|
||||
"last_verified_auto_at": None,
|
||||
"last_verification_evidence_at": None,
|
||||
"latest_auto_age_seconds": 90,
|
||||
"last_verified_auto_age_seconds": 120,
|
||||
},
|
||||
[
|
||||
{
|
||||
"id": "are-1",
|
||||
"incident_id": "INC-1",
|
||||
"success": True,
|
||||
"created_at": None,
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
assert payload["status"] == "warning"
|
||||
assert payload["reason"] == "verification_backlog_present"
|
||||
assert payload["coverage_rate"] == pytest.approx(5 / 7)
|
||||
assert payload["verification_success_rate"] == pytest.approx(4 / 5)
|
||||
assert payload["recent_unverified"][0]["incident_id"] == "INC-1"
|
||||
|
||||
|
||||
def test_verification_coverage_payload_skips_when_no_auto_repair():
|
||||
payload = _build_verification_coverage_payload(
|
||||
{
|
||||
"total_auto": 0,
|
||||
"successful_auto": 0,
|
||||
"verified_auto": 0,
|
||||
"verified_success": 0,
|
||||
"verified_non_success": 0,
|
||||
"unverified_auto": 0,
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
assert payload["status"] == "skipped_low_volume"
|
||||
assert payload["reason"] == "no_auto_repair_executions_24h"
|
||||
assert payload["evaluable"] is False
|
||||
|
||||
Reference in New Issue
Block a user