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:
|
else:
|
||||||
lines.append("此事件: <code>no_related_owner_review</code>")
|
lines.append("此事件: <code>no_related_owner_review</code>")
|
||||||
lines.append("下一步: <code>review_awooop_completion_queue</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
|
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(
|
async def _fetch_km_stale_completion_summary_for_incident(
|
||||||
*,
|
*,
|
||||||
incident_id: str,
|
incident_id: str,
|
||||||
@@ -508,11 +578,33 @@ async def _fetch_km_stale_completion_summary_for_incident(
|
|||||||
for item in queue.items
|
for item in queue.items
|
||||||
if item.related_incident_id == incident_id
|
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 {
|
return {
|
||||||
"schema_version": "km_stale_owner_review_completion_telegram_summary_v1",
|
"schema_version": "km_stale_owner_review_completion_telegram_summary_v1",
|
||||||
"status": "ok",
|
"status": status_value,
|
||||||
"project_id": project_id or "awoooi",
|
"project_id": project_id or "awoooi",
|
||||||
"incident_id": incident_id,
|
"incident_id": incident_id,
|
||||||
|
"missing_reason": reason,
|
||||||
"total": queue.total,
|
"total": queue.total,
|
||||||
"returned": queue.returned,
|
"returned": queue.returned,
|
||||||
"pending_count": queue.pending_count,
|
"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,
|
"batch_writes_allowed": queue.batch_writes_allowed,
|
||||||
"manual_review_required": queue.manual_review_required,
|
"manual_review_required": queue.manual_review_required,
|
||||||
"items": items[:5],
|
"items": items[:5],
|
||||||
|
"triage": triage,
|
||||||
|
"work_item": work_item,
|
||||||
}
|
}
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.debug(
|
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
|
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:
|
def test_awooop_runs_url_for_incident_uses_public_incident_filter() -> None:
|
||||||
"""Telegram URL button 必須導到公開 AwoooP Run list,並帶 incident filter。"""
|
"""Telegram URL button 必須導到公開 AwoooP Run list,並帶 incident filter。"""
|
||||||
url = telegram_gateway_module._awooop_runs_url_for_incident("INC-20260514-F85F21")
|
url = telegram_gateway_module._awooop_runs_url_for_incident("INC-20260514-F85F21")
|
||||||
|
|||||||
Reference in New Issue
Block a user