fix(gitea): classify alert receipt chain gaps

This commit is contained in:
ogt
2026-07-10 00:15:27 +08:00
parent c3dc16fb5b
commit 3f6c62dd03
2 changed files with 122 additions and 11 deletions

View File

@@ -60,11 +60,28 @@ def build_gitea_cicd_alert_receipt_chain_readback(
monitoring_gap_count = _int(coverage_summary.get("monitoring_live_receipt_gap_count"))
full_dr_gap_count = _int(full_server_backup_dr_receipts.get("active_gap_count"))
full_dr_gap_ids = _list(full_server_backup_dr_receipts.get("active_gap_ids"))
full_dr_restore_drill_only = (
full_dr_gap_ids == ["restore_drill_approval_gate"]
and _int(full_dr_summary.get("source_ready_component_count")) >= 6
and _int(full_dr_summary.get("receipt_required_component_count")) == 0
)
quiet_contract_count = len(_list(backup_rollups.get("suppressed_success_rule_ids")))
immediate_escalation_count = len(
_list(backup_rollups.get("immediate_escalation_rule_ids"))
)
notify_workflow_count = _int(workflow_rollups.get("workflows_with_notify_bridge"))
ai_context_source_ready = (
coverage_summary.get("source_contract_ready") is True
and _int(coverage_summary.get("alert_receipt_pipeline_ready_count")) > 0
)
ai_context_verified_ready = (
(
coverage_summary.get("ai_loop_context_ready") is True
and _int(coverage_summary.get("ai_loop_ai_agent_context_receipt_count")) > 0
)
or _int(coverage_summary.get("verified_ai_agent_context_receipt_count")) > 0
)
receipt_rows = [
{
@@ -95,17 +112,30 @@ def build_gitea_cicd_alert_receipt_chain_readback(
{
"chain_id": "gitea_full_server_dr_receipts",
"domain": "backup_dr",
"status": "action_required" if full_dr_gap_count else "verified_ready",
"receipt_state": "component_receipts_pending"
if full_dr_gap_count
else "component_receipts_ready",
"status": "verified_ready"
if not full_dr_gap_count
else "controlled_restore_drill_pending"
if full_dr_restore_drill_only
else "action_required",
"receipt_state": "component_receipts_ready"
if not full_dr_gap_count
else "source_contract_ready_restore_drill_pending"
if full_dr_restore_drill_only
else "component_receipts_pending",
"evidence_refs": ["GET /api/v1/agents/gitea-full-server-backup-dr-receipts"],
"next_action": "close full-server component receipt rows before DR complete",
"next_action": "run a controlled restore-drill verifier before DR complete"
if full_dr_restore_drill_only
else "close full-server component receipt rows before DR complete",
"metrics": {
"full_server_active_gap_count": full_dr_gap_count,
"full_server_active_gap_ids": full_dr_gap_ids,
"full_server_verified_ready_component_count": _int(
full_dr_summary.get("verified_ready_component_count")
),
"full_server_source_ready_component_count": _int(
full_dr_summary.get("source_ready_component_count")
),
"restore_drill_only_gap": full_dr_restore_drill_only,
},
},
{
@@ -132,14 +162,40 @@ def build_gitea_cicd_alert_receipt_chain_readback(
{
"chain_id": "ai_agent_context_receipts",
"domain": "ai_context",
"status": "source_ready"
if _int(coverage_summary.get("verified_ai_agent_context_receipt_count")) > 0
"status": "verified_ready"
if ai_context_verified_ready
else "source_ready"
if ai_context_source_ready
else "action_required",
"receipt_state": "ai_context_receipts_projected",
"receipt_state": "ai_context_receipts_verified"
if ai_context_verified_ready
else "source_backed_ai_context_pipeline_ready"
if ai_context_source_ready
else "ai_context_receipts_projected",
"evidence_refs": [
"GET /api/v1/agents/telegram-alert-monitoring-coverage-readback"
],
"next_action": "keep KM/RAG/MCP/PlayBook context receipts metadata-only",
"next_action": "keep KM/RAG/MCP/PlayBook context receipts metadata-only"
if ai_context_source_ready
else "write metadata-only KM/RAG/MCP/PlayBook context receipts",
"metrics": {
"source_contract_ready": coverage_summary.get("source_contract_ready")
is True,
"ai_loop_context_ready": coverage_summary.get("ai_loop_context_ready")
is True,
"ai_loop_context_source": str(
coverage_summary.get("ai_loop_context_source") or ""
),
"ai_loop_ai_agent_context_receipt_count": _int(
coverage_summary.get("ai_loop_ai_agent_context_receipt_count")
),
"verified_ai_agent_context_receipt_count": _int(
coverage_summary.get("verified_ai_agent_context_receipt_count")
),
"alert_receipt_pipeline_ready_count": _int(
coverage_summary.get("alert_receipt_pipeline_ready_count")
),
},
},
]
@@ -181,9 +237,20 @@ def build_gitea_cicd_alert_receipt_chain_readback(
"source_or_policy_ready_chain_count": sum(
1
for row in receipt_rows
if row["status"] in {"source_ready", "policy_ready", "verified_ready"}
if row["status"]
in {
"source_ready",
"policy_ready",
"verified_ready",
"controlled_restore_drill_pending",
}
),
"action_required_chain_count": len(active_gaps),
"controlled_restore_drill_pending_chain_count": sum(
1
for row in receipt_rows
if row["status"] == "controlled_restore_drill_pending"
),
"monitoring_live_receipt_gap_count": monitoring_gap_count,
"full_server_dr_active_gap_count": full_dr_gap_count,
"workflow_notify_bridge_count": notify_workflow_count,

View File

@@ -73,7 +73,51 @@ def test_gitea_cicd_alert_receipt_chain_readback_surfaces_receipt_gaps() -> None
assert by_id["backup_notification_policy"]["status"] == "policy_ready"
assert by_id["gitea_full_server_dr_receipts"]["status"] == "action_required"
assert by_id["telegram_monitoring_live_receipts"]["status"] == "action_required"
assert by_id["ai_agent_context_receipts"]["status"] == "source_ready"
assert by_id["ai_agent_context_receipts"]["status"] == "verified_ready"
def test_gitea_cicd_alert_receipt_chain_keeps_restore_drill_pending_separate() -> None:
full_dr = {
"schema_version": "gitea_full_server_backup_dr_receipts_v1",
"status": "gitea_full_server_backup_dr_receipts_gaps_present",
"active_gap_count": 1,
"active_gap_ids": ["restore_drill_approval_gate"],
"summary": {
"verified_ready_component_count": 3,
"source_ready_component_count": 6,
"receipt_required_component_count": 0,
},
}
telegram_coverage = {
**_telegram_coverage(),
"summary": {
**_telegram_coverage()["summary"],
"source_contract_ready": True,
"ai_loop_context_ready": False,
"ai_loop_ai_agent_context_receipt_count": 0,
},
}
payload = build_gitea_cicd_alert_receipt_chain_readback(
telegram_coverage=telegram_coverage,
backup_notification_policy=load_latest_backup_notification_policy(),
workflow_runner_health=load_latest_gitea_workflow_runner_health(),
full_server_backup_dr_receipts=full_dr,
generated_at="2026-07-10T00:21:00+08:00",
)
assert payload["summary"]["action_required_chain_count"] == 1
assert payload["summary"]["controlled_restore_drill_pending_chain_count"] == 1
assert payload["active_gap_ids"] == ["telegram_monitoring_live_receipts"]
by_id = {row["chain_id"]: row for row in payload["receipt_chain_rows"]}
assert by_id["gitea_full_server_dr_receipts"]["status"] == (
"controlled_restore_drill_pending"
)
assert by_id["gitea_full_server_dr_receipts"]["metrics"][
"restore_drill_only_gap"
] is True
assert by_id["ai_agent_context_receipts"]["status"] == "verified_ready"
@pytest.mark.asyncio