feat(telegram): expose alert learning writeback refs
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 56s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
AI 技術雷達監控 / ai-technology-watch (push) Successful in 45s
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 56s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
AI 技術雷達監控 / ai-technology-watch (push) Successful in 45s
This commit is contained in:
@@ -1378,6 +1378,23 @@ async def list_ai_alert_card_delivery_readback(
|
||||
'0'
|
||||
) <> '0'
|
||||
) AS runtime_write_gate_open_count,
|
||||
COUNT(*) FILTER (
|
||||
WHERE COALESCE(
|
||||
m.source_envelope #>>
|
||||
'{{ai_automation_alert_card,delivery_receipt_readback_required}}',
|
||||
''
|
||||
) = 'true'
|
||||
AND COALESCE(
|
||||
m.source_envelope #>>
|
||||
'{{ai_automation_alert_card,event_type}}',
|
||||
''
|
||||
) <> ''
|
||||
AND COALESCE(
|
||||
m.source_envelope #>>
|
||||
'{{ai_automation_alert_card,lane}}',
|
||||
''
|
||||
) <> ''
|
||||
) AS learning_writeback_ready_total,
|
||||
MAX(m.sent_at) AS latest_sent_at,
|
||||
MAX(m.queued_at) AS latest_queued_at
|
||||
FROM awooop_outbound_message m
|
||||
@@ -1464,6 +1481,10 @@ def _ai_alert_card_delivery_summary_from_row(
|
||||
runtime_write_gate_open_count = _safe_int(
|
||||
row.get("runtime_write_gate_open_count")
|
||||
)
|
||||
learning_writeback_ready_total = _safe_int(
|
||||
row.get("learning_writeback_ready_total")
|
||||
)
|
||||
learning_writeback_missing_total = max(total - learning_writeback_ready_total, 0)
|
||||
status_value = "no_delivery_receipt" if total == 0 else "observed"
|
||||
if failed_total > 0:
|
||||
status_value = "delivery_failure_observed"
|
||||
@@ -1486,6 +1507,18 @@ def _ai_alert_card_delivery_summary_from_row(
|
||||
),
|
||||
"runtime_write_gate_open_count": runtime_write_gate_open_count,
|
||||
"runtime_write_allowed": runtime_write_gate_open_count > 0,
|
||||
"learning_writeback_ready_total": learning_writeback_ready_total,
|
||||
"learning_writeback_missing_total": learning_writeback_missing_total,
|
||||
"km_writeback_ref_ready_total": learning_writeback_ready_total,
|
||||
"playbook_writeback_ref_ready_total": learning_writeback_ready_total,
|
||||
"rag_chunk_ref_ready_total": learning_writeback_ready_total,
|
||||
"mcp_evidence_ref_ready_total": learning_writeback_ready_total,
|
||||
"post_verifier_ref_ready_total": learning_writeback_ready_total,
|
||||
"learning_writeback_next_action": (
|
||||
"none"
|
||||
if total > 0 and learning_writeback_missing_total == 0
|
||||
else "ensure_ai_alert_cards_include_event_type_lane_and_delivery_receipt"
|
||||
),
|
||||
"latest_sent_at": row.get("latest_sent_at"),
|
||||
"latest_queued_at": row.get("latest_queued_at"),
|
||||
"production_write_count": 0,
|
||||
@@ -1502,6 +1535,13 @@ def _ai_alert_card_delivery_item(row: Mapping[str, Any]) -> dict[str, Any]:
|
||||
alert_card.get("runtime_write_gate_count")
|
||||
)
|
||||
event_at = row.get("sent_at") or row.get("queued_at")
|
||||
learning_writeback_refs = _ai_alert_card_learning_writeback_refs(
|
||||
alert_card=alert_card,
|
||||
source_refs=source_refs,
|
||||
message_id=row.get("message_id"),
|
||||
run_id=run_id,
|
||||
project_id=project_id,
|
||||
)
|
||||
return {
|
||||
"message_id": row.get("message_id"),
|
||||
"run_id": run_id,
|
||||
@@ -1527,6 +1567,11 @@ def _ai_alert_card_delivery_item(row: Mapping[str, Any]) -> dict[str, Any]:
|
||||
"delivery_receipt_readback_required": bool(
|
||||
alert_card.get("delivery_receipt_readback_required")
|
||||
),
|
||||
"learning_writeback_ready": (
|
||||
learning_writeback_refs["status"] == "ready"
|
||||
),
|
||||
"learning_writeback_status": learning_writeback_refs["status"],
|
||||
"learning_writeback_refs": learning_writeback_refs,
|
||||
"source_refs": source_refs,
|
||||
"run_state": row.get("run_state"),
|
||||
"agent_id": row.get("agent_id"),
|
||||
@@ -1539,6 +1584,77 @@ def _ai_alert_card_delivery_item(row: Mapping[str, Any]) -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
def _slug_ref(value: Any, fallback: str) -> str:
|
||||
slug = re.sub(r"[^a-z0-9_.:-]+", "-", str(value or "").strip().lower())
|
||||
slug = slug.strip("-")
|
||||
return slug or fallback
|
||||
|
||||
|
||||
def _ai_alert_card_learning_writeback_refs(
|
||||
*,
|
||||
alert_card: Mapping[str, Any],
|
||||
source_refs: Mapping[str, Any],
|
||||
message_id: Any,
|
||||
run_id: Any,
|
||||
project_id: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Build deterministic KM / PlayBook / RAG / MCP refs for one alert receipt."""
|
||||
event_type = str(alert_card.get("event_type") or "")
|
||||
lane = str(alert_card.get("lane") or "")
|
||||
target = str(alert_card.get("target") or "")
|
||||
delivery_required = bool(alert_card.get("delivery_receipt_readback_required"))
|
||||
event_slug = _slug_ref(event_type, "unknown-event")
|
||||
lane_slug = _slug_ref(lane, "unknown-lane")
|
||||
target_slug = _slug_ref(target, "unknown-target")
|
||||
message_ref = _slug_ref(message_id, "unknown-message")
|
||||
run_ref = _slug_ref(run_id, "unknown-run")
|
||||
missing = [
|
||||
key
|
||||
for key, value in (
|
||||
("event_type", event_type),
|
||||
("lane", lane),
|
||||
("delivery_receipt_readback_required", delivery_required),
|
||||
)
|
||||
if value in ("", False, None)
|
||||
]
|
||||
status = "ready" if not missing else "missing_required_alert_card_metadata"
|
||||
|
||||
fingerprints = source_refs.get("fingerprints") if isinstance(source_refs, Mapping) else []
|
||||
alert_ids = source_refs.get("alert_ids") if isinstance(source_refs, Mapping) else []
|
||||
return {
|
||||
"schema_version": "ai_alert_card_learning_writeback_refs_v1",
|
||||
"status": status,
|
||||
"work_item_id": "CIR-P0-TG-001",
|
||||
"receipt_source": "awooop_outbound_message",
|
||||
"receipt_id": str(message_id or ""),
|
||||
"run_id": str(run_id or ""),
|
||||
"project_id": project_id,
|
||||
"km_entry_ref": f"km://{project_id}/telegram-ai-alert-card/{event_slug}",
|
||||
"playbook_candidate_ref": (
|
||||
f"playbook://{project_id}/telegram-ai-alert-card/{lane_slug}/{target_slug}"
|
||||
),
|
||||
"rag_chunk_ref": (
|
||||
f"rag://{project_id}/telegram-ai-alert-card/{event_slug}/{message_ref}"
|
||||
),
|
||||
"mcp_evidence_ref": (
|
||||
f"mcp://{project_id}/awooop_outbound_message/{message_ref}"
|
||||
),
|
||||
"post_verifier_ref": (
|
||||
f"verifier://{project_id}/telegram-alert-delivery-receipt/{run_ref}"
|
||||
),
|
||||
"source_fingerprints": fingerprints if isinstance(fingerprints, list) else [],
|
||||
"alert_ids": alert_ids if isinstance(alert_ids, list) else [],
|
||||
"missing_required_fields": missing,
|
||||
"production_write_performed": False,
|
||||
"runtime_send_performed": False,
|
||||
"next_action": (
|
||||
"none"
|
||||
if status == "ready"
|
||||
else "ensure_ai_alert_cards_include_event_type_lane_and_delivery_receipt"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def _fetch_callback_reply_audit_summary(
|
||||
db: Any,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user