feat(api): 新增 SRE 戰情室 digest preview
All checks were successful
Code Review / ai-code-review (push) Successful in 19s
CD Pipeline / tests (push) Successful in 1m43s
CD Pipeline / build-and-deploy (push) Successful in 7m20s
CD Pipeline / post-deploy-checks (push) Successful in 3m8s

This commit is contained in:
Your Name
2026-06-18 20:18:28 +08:00
parent f8c290be63
commit 7e03b9231b
4 changed files with 166 additions and 0 deletions

View File

@@ -375,6 +375,54 @@ class ReportGenerationService:
]
return "\n".join(lines)
def format_sre_digest_preview(
self,
source_health: dict[str, Any] | None,
*,
generated_at: datetime | None = None,
) -> str:
"""Format an AwoooI SRE war-room no-send digest preview."""
now = generated_at or now_taipei()
source_health = source_health or {}
rollups = source_health.get("rollups") or {}
ok_count = int(rollups.get("source_ok_count") or 0)
total_count = int(rollups.get("source_count") or 0)
gap_count = int(rollups.get("source_gap_count") or 0)
confidence = int(rollups.get("confidence_percent") or 0)
preview_count = int(rollups.get("no_send_preview_count") or 0)
work_items = source_health.get("work_items") or []
gap_ids = [
str(item.get("work_item_id"))
for item in work_items
if item.get("work_item_id")
][:5]
gap_text = ", ".join(gap_ids) if gap_ids else ""
lines = [
"<b>🛡️ AwoooI SRE 戰情室 digest no-send preview</b>",
f"<b>{now.strftime('%Y-%m-%d %H:%M')}</b> 台北時間",
"",
"<b>📡 資料源健康</b>",
f" 來源: <code>{ok_count}/{total_count}</code> | 缺口: {gap_count} | 信心: <b>{confidence}%</b>",
f" 工作項: {html.escape(gap_text)}",
"",
"<b>🗓️ 日 / 週 / 月報狀態</b>",
f" no-send preview: {preview_count}",
" live Telegram send: 0",
" Gateway queue write: 0",
]
lines.extend(self._format_report_source_health_block(source_health))
lines += [
"",
"<b>🧭 下一步</b>",
" 1. 補齊 report-source-gap 專屬 PlayBook 與 Verifier readback。",
" 2. Owner review 後才允許 SRE digest 實發批准包。",
" 3. 任何中低風險自動處理仍需 rollback / post-check / audit receipt。",
"",
"<i>只讀草案:不發 Telegram、不寫 Gateway queue、不改排程、不啟動 runtime gate。</i>",
]
return "\n".join(lines)
def format_daily_report(
self,
kpi: DailyKpi,