feat(telegram): show callback owner review triage
This commit is contained in:
@@ -479,9 +479,79 @@ def _format_km_stale_completion_lines(summary: dict[str, object] | None) -> list
|
||||
else:
|
||||
lines.append("此事件: <code>no_related_owner_review</code>")
|
||||
lines.append("下一步: <code>review_awooop_completion_queue</code>")
|
||||
triage = _km_stale_completion_triage(summary)
|
||||
if triage:
|
||||
support = triage.get("supporting_agents")
|
||||
support_text = (
|
||||
" / ".join(str(item) for item in support[:3])
|
||||
if isinstance(support, list)
|
||||
else "--"
|
||||
)
|
||||
lines += [
|
||||
(
|
||||
"流程: "
|
||||
f"<code>{html.escape(str(triage.get('flow_stage') or '--'))}</code>"
|
||||
" / 匹配 "
|
||||
f"<code>{html.escape(str(triage.get('matching_strategy') or '--'))}</code>"
|
||||
),
|
||||
(
|
||||
"主責: "
|
||||
f"<code>{html.escape(str(triage.get('ai_lead_agent') or '--'))}</code>"
|
||||
" / 協作 "
|
||||
f"<code>{html.escape(support_text)}</code>"
|
||||
),
|
||||
(
|
||||
"自動化: "
|
||||
f"<code>{html.escape(str(triage.get('automation_state') or '--'))}</code>"
|
||||
" / safe-auto "
|
||||
f"<code>{html.escape(_bool_code(triage.get('safe_to_auto_repair')))}</code>"
|
||||
),
|
||||
(
|
||||
"卡點: "
|
||||
f"<code>{html.escape(str(triage.get('blocking_reason') or '--'))}</code>"
|
||||
),
|
||||
]
|
||||
return lines
|
||||
|
||||
|
||||
def _km_stale_completion_triage(
|
||||
summary: dict[str, object],
|
||||
) -> dict[str, object] | None:
|
||||
triage = summary.get("triage")
|
||||
if isinstance(triage, dict):
|
||||
return triage
|
||||
work_item = summary.get("work_item")
|
||||
if isinstance(work_item, dict) and isinstance(work_item.get("triage"), dict):
|
||||
return work_item["triage"]
|
||||
return None
|
||||
|
||||
|
||||
def _build_km_stale_callback_owner_review_triage(
|
||||
*,
|
||||
reason: str,
|
||||
) -> dict[str, object]:
|
||||
return {
|
||||
"schema_version": "km_stale_callback_owner_review_triage_v1",
|
||||
"flow_stage": "callback_observed_owner_review_link_missing",
|
||||
"ai_lead_agent": "Hermes",
|
||||
"supporting_agents": ["OpenClaw", "ElephantAlpha"],
|
||||
"automation_state": "manual_owner_review_required",
|
||||
"safe_to_auto_repair": False,
|
||||
"blocking_reason": reason,
|
||||
"matching_strategy": "related_incident_id_exact_match",
|
||||
"already_done": [
|
||||
"callback_reply_persisted",
|
||||
"completion_queue_checked",
|
||||
"telegram_detail_history_rendered",
|
||||
],
|
||||
"next_actions": [
|
||||
"review_awooop_callback_work_item",
|
||||
"queue_matching_km_stale_candidate",
|
||||
"complete_owner_review_after_owner_approval",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
async def _fetch_km_stale_completion_summary_for_incident(
|
||||
*,
|
||||
incident_id: str,
|
||||
@@ -508,11 +578,33 @@ async def _fetch_km_stale_completion_summary_for_incident(
|
||||
for item in queue.items
|
||||
if item.related_incident_id == incident_id
|
||||
]
|
||||
status_value = "matched_owner_review" if items else "no_related_owner_review"
|
||||
reason = None if items else "no_matching_completion_item"
|
||||
triage = (
|
||||
None
|
||||
if items
|
||||
else _build_km_stale_callback_owner_review_triage(reason=reason)
|
||||
)
|
||||
work_item = None
|
||||
if triage:
|
||||
work_item = {
|
||||
"schema_version": "km_stale_callback_owner_review_work_item_v1",
|
||||
"kind": "km_stale_callback_owner_review",
|
||||
"status": "open",
|
||||
"incident_id": incident_id,
|
||||
"reason": reason,
|
||||
"next_step": "review_or_queue_km_owner_review",
|
||||
"triage": triage,
|
||||
"writes_on_read": False,
|
||||
"manual_review_required": True,
|
||||
"batch_writes_allowed": False,
|
||||
}
|
||||
return {
|
||||
"schema_version": "km_stale_owner_review_completion_telegram_summary_v1",
|
||||
"status": "ok",
|
||||
"status": status_value,
|
||||
"project_id": project_id or "awoooi",
|
||||
"incident_id": incident_id,
|
||||
"missing_reason": reason,
|
||||
"total": queue.total,
|
||||
"returned": queue.returned,
|
||||
"pending_count": queue.pending_count,
|
||||
@@ -524,6 +616,8 @@ async def _fetch_km_stale_completion_summary_for_incident(
|
||||
"batch_writes_allowed": queue.batch_writes_allowed,
|
||||
"manual_review_required": queue.manual_review_required,
|
||||
"items": items[:5],
|
||||
"triage": triage,
|
||||
"work_item": work_item,
|
||||
}
|
||||
except Exception as exc:
|
||||
logger.debug(
|
||||
|
||||
@@ -206,6 +206,46 @@ def test_km_stale_completion_lines_show_owner_review_queue_state() -> None:
|
||||
assert "preview_stale_km_review_completion" in joined
|
||||
|
||||
|
||||
def test_km_stale_completion_lines_show_callback_triage_state() -> None:
|
||||
"""詳情/歷史要顯示 callback owner-review 缺口的流程、主責與卡點。"""
|
||||
lines = telegram_gateway_module._format_km_stale_completion_lines({
|
||||
"schema_version": "km_stale_owner_review_completion_telegram_summary_v1",
|
||||
"status": "no_related_owner_review",
|
||||
"incident_id": "INC-20260524-16109D",
|
||||
"ready_count": 10,
|
||||
"blocked_count": 0,
|
||||
"completed_count": 1,
|
||||
"failed_count": 0,
|
||||
"writes_on_read": False,
|
||||
"batch_writes_allowed": False,
|
||||
"items": [],
|
||||
"work_item": {
|
||||
"schema_version": "km_stale_callback_owner_review_work_item_v1",
|
||||
"status": "open",
|
||||
"triage": {
|
||||
"schema_version": "km_stale_callback_owner_review_triage_v1",
|
||||
"flow_stage": "callback_observed_owner_review_link_missing",
|
||||
"ai_lead_agent": "Hermes",
|
||||
"supporting_agents": ["OpenClaw", "ElephantAlpha"],
|
||||
"automation_state": "manual_owner_review_required",
|
||||
"safe_to_auto_repair": False,
|
||||
"blocking_reason": "no_matching_completion_item",
|
||||
"matching_strategy": "related_incident_id_exact_match",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
joined = "\n".join(lines)
|
||||
assert "no_related_owner_review" in joined
|
||||
assert "callback_observed_owner_review_link_missing" in joined
|
||||
assert "related_incident_id_exact_match" in joined
|
||||
assert "Hermes" in joined
|
||||
assert "OpenClaw / ElephantAlpha" in joined
|
||||
assert "manual_owner_review_required" in joined
|
||||
assert "safe-auto <code>no</code>" in joined
|
||||
assert "no_matching_completion_item" in joined
|
||||
|
||||
|
||||
def test_awooop_runs_url_for_incident_uses_public_incident_filter() -> None:
|
||||
"""Telegram URL button 必須導到公開 AwoooP Run list,並帶 incident filter。"""
|
||||
url = telegram_gateway_module._awooop_runs_url_for_incident("INC-20260514-F85F21")
|
||||
|
||||
Reference in New Issue
Block a user