"""AwoooP inbound channel event dossier service.

T15c: converts redacted inbound source envelopes into an Operator Console DTO.
The service is read-only and does not mutate incident, run, approval, or
automation state.
"""

from __future__ import annotations

import re
from typing import Any, Literal
from uuid import UUID

import structlog
from fastapi import HTTPException, status
from sqlalchemy import text

from src.db.base import get_db_context

logger = structlog.get_logger(__name__)

_MAX_DOSSIER_EVENTS = 50
_MAX_COVERAGE_EVENTS = 200
_MAX_RECURRENCE_EVENTS = 300
_MAX_REPAIR_INCIDENTS = 200
_SOURCE_CORRELATION_REVIEW_PROVIDERS = {"sentry", "signoz"}
_SOURCE_CORRELATION_REVIEW_EXCLUDED_STAGES = {"heartbeat"}
_SOURCE_CORRELATION_WORK_ITEM_ID_MAX = 180
_SOURCE_CORRELATION_DECISION_SCHEMA_VERSION = (
    "awooop_source_correlation_review_decision_v1"
)
_SOURCE_CORRELATION_APPLY_SCHEMA_VERSION = "awooop_source_correlation_apply_v1"
_SOURCE_CORRELATION_APPLY_STAGE = "source_correlation_linked"
_SOURCE_CORRELATION_REVIEW_ACTOR = "awooop_source_correlation_review_service"
_SOURCE_CORRELATION_APPLY_ACTOR = "awooop_source_correlation_apply_service"
_INCIDENT_ID_RE = re.compile(r"\bINC-\d{8}-[A-Z0-9]{4,}\b")
RecurrenceWorkItemMode = Literal["auto", "ticket", "reverify", "approval_review", "observe"]
RecurrenceWorkItemHandoffKind = Literal["ticket_proposal", "manual_review"]
SourceCorrelationReviewDecision = Literal[
    "accepted",
    "rejected",
    "needs_more_evidence",
]


class RecurrenceWorkItemNotFoundError(LookupError):
    """Requested recurrence work item is not in the current read model."""


def _as_dict(value: Any) -> dict[str, Any]:
    return value if isinstance(value, dict) else {}


def _json_safe(value: Any) -> Any:
    if isinstance(value, dict):
        return {str(key): _json_safe(item) for key, item in value.items()}
    if isinstance(value, list | tuple | set):
        return [_json_safe(item) for item in value]
    if value is None or isinstance(value, str | int | float | bool):
        return value
    return str(value)


def _compact_ref_count(source_refs: dict[str, Any]) -> int:
    total = 0
    for value in source_refs.values():
        if isinstance(value, list):
            total += len(value)
        elif value:
            total += 1
    return total


def _ref_count(source_refs: dict[str, Any], key: str) -> int:
    value = source_refs.get(key)
    if isinstance(value, list):
        return len(value)
    return 1 if value else 0


def _source_correlation_ref_total(group: dict[str, Any]) -> int:
    return int(group.get("sentry_ref_total") or 0) + int(
        group.get("signoz_ref_total") or 0
    )


def _needs_source_correlation_review(
    group: dict[str, Any],
    latest_incident_id: str | None,
) -> bool:
    if latest_incident_id:
        return False
    provider = str(group.get("provider") or "").lower()
    stage = str(group.get("latest_stage") or "").lower()
    if provider not in _SOURCE_CORRELATION_REVIEW_PROVIDERS:
        return False
    if stage in _SOURCE_CORRELATION_REVIEW_EXCLUDED_STAGES:
        return False
    return _source_correlation_ref_total(group) > 0


def _source_correlation_work_item_id(group: dict[str, Any]) -> str:
    source_id = str(
        group.get("latest_provider_event_id") or group.get("recurrence_key") or "unknown"
    ).strip()
    return f"source-evidence:{source_id}"[:_SOURCE_CORRELATION_WORK_ITEM_ID_MAX]


def _source_correlation_review_outcome(decision: str) -> dict[str, str]:
    if decision == "accepted":
        return {
            "status": "source_correlation_accepted",
            "next_step": "verify_source_match_in_status_chain",
            "reason": "provider_native_evidence_accepted",
            "review_status": "accepted",
        }
    if decision == "rejected":
        return {
            "status": "source_correlation_rejected",
            "next_step": "monitor_for_new_provider_evidence",
            "reason": "provider_native_evidence_rejected",
            "review_status": "rejected",
        }
    return {
        "status": "source_correlation_review",
        "next_step": "collect_more_source_evidence",
        "reason": "provider_native_evidence_needs_more_evidence",
        "review_status": "needs_more_evidence",
    }


def _normalize_source_review_decision(row: dict[str, Any]) -> dict[str, Any] | None:
    context = _as_dict(row.get("context"))
    if context.get("schema_version") != _SOURCE_CORRELATION_DECISION_SCHEMA_VERSION:
        return None
    work_item_id = str(context.get("work_item_id") or "").strip()
    decision = str(context.get("decision") or "").strip()
    if not work_item_id or decision not in {
        "accepted",
        "rejected",
        "needs_more_evidence",
    }:
        return None

    return {
        "schema_version": _SOURCE_CORRELATION_DECISION_SCHEMA_VERSION,
        "review_id": row.get("id"),
        "work_item_id": work_item_id,
        "decision": decision,
        "review_status": context.get("review_status") or decision,
        "target_incident_id": context.get("target_incident_id"),
        "reviewer_id": context.get("reviewer_id"),
        "operator_note": context.get("operator_note"),
        "latest_provider_event_id": context.get("latest_provider_event_id"),
        "latest_stage": context.get("latest_stage"),
        "recorded_at": row.get("created_at"),
        "history": context.get("history") or {},
    }


def _normalize_source_apply(row: dict[str, Any]) -> dict[str, Any] | None:
    context = _as_dict(row.get("context"))
    if context.get("schema_version") != _SOURCE_CORRELATION_APPLY_SCHEMA_VERSION:
        return None
    work_item_id = str(context.get("work_item_id") or "").strip()
    target_incident_id = str(context.get("target_incident_id") or "").strip()
    if not work_item_id or not target_incident_id:
        return None

    history = _as_dict(context.get("history"))
    return {
        "schema_version": _SOURCE_CORRELATION_APPLY_SCHEMA_VERSION,
        "apply_id": row.get("id"),
        "work_item_id": work_item_id,
        "apply_status": context.get("apply_status") or "applied",
        "target_incident_id": target_incident_id,
        "review_id": context.get("review_id"),
        "reviewer_id": context.get("reviewer_id"),
        "operator_note": context.get("operator_note"),
        "latest_provider_event_id": context.get("latest_provider_event_id"),
        "source_event_provider_event_id": context.get(
            "source_event_provider_event_id"
        ),
        "source_event_id": history.get("source_event_id"),
        "timeline_event_id": history.get("timeline_event_id"),
        "recorded_at": row.get("created_at"),
        "history": history,
    }


def _provider_raw_event_id(provider_event_id: Any) -> str:
    parts = str(provider_event_id or "").split(":", 2)
    if len(parts) == 3 and parts[2].strip():
        return parts[2].strip()
    return str(provider_event_id or "unknown").strip() or "unknown"


def _append_unique(values: list[str], candidate: Any) -> None:
    text_value = str(candidate or "").strip()
    if text_value and text_value not in values:
        values.append(text_value)


def _append_incident_ids_from_text(values: list[str], text_value: Any) -> None:
    if not text_value:
        return
    for incident_id in _INCIDENT_ID_RE.findall(str(text_value)):
        _append_unique(values, incident_id)


def _append_incident_ids_from_refs(
    values: list[str], source_refs: dict[str, Any]
) -> None:
    incident_ids = source_refs.get("incident_ids")
    if isinstance(incident_ids, list):
        for incident_id in incident_ids:
            _append_unique(values, incident_id)
    else:
        _append_unique(values, incident_ids)


def _event_incident_ids(event: dict[str, Any]) -> list[str]:
    incident_ids: list[str] = []
    _append_incident_ids_from_refs(incident_ids, _as_dict(event.get("source_refs")))
    _append_incident_ids_from_text(incident_ids, event.get("content_preview"))
    _append_incident_ids_from_text(incident_ids, event.get("content_redacted"))
    _append_incident_ids_from_text(incident_ids, event.get("provider_event_id"))
    return incident_ids


def _recurrence_key(event: dict[str, Any]) -> str:
    fingerprint = str(event.get("fingerprint") or "").strip()
    if fingerprint:
        return f"fingerprint:{fingerprint}"

    provider = str(event.get("provider") or event.get("channel_type") or "unknown")
    alertname = str(event.get("alertname") or "").strip()
    namespace = str(event.get("namespace") or "").strip()
    target = str(event.get("target_resource") or "").strip()
    if alertname or namespace or target:
        return f"alert:{provider}:{alertname}:{namespace}:{target}"

    return f"event:{provider}:{event.get('provider_event_id')}"


def build_dossier_recurrence(
    rows: list[dict[str, Any]],
    *,
    project_id: str,
    limit: int,
    repair_summaries_by_incident: dict[str, dict[str, Any]] | None = None,
    source_review_decisions_by_work_item: dict[str, dict[str, Any]] | None = None,
    source_applies_by_work_item: dict[str, dict[str, Any]] | None = None,
) -> dict[str, Any]:
    """Group recent source events into recurrence buckets with linked run state."""
    groups: dict[str, dict[str, Any]] = {}
    repair_summaries = repair_summaries_by_incident or {}
    source_review_decisions = source_review_decisions_by_work_item or {}
    source_applies = source_applies_by_work_item or {}

    for row in rows:
        event = build_dossier_event(row)
        key = _recurrence_key(event)
        source_ref_count = int(event.get("source_ref_count") or 0)
        source_refs = _as_dict(event.get("source_refs"))
        incident_ids = _event_incident_ids(event)
        run_id = row.get("run_id")
        run_state = row.get("run_state")
        received_at = event.get("received_at")

        group = groups.setdefault(
            key,
            {
                "recurrence_key": key,
                "provider": event.get("provider"),
                "alertname": event.get("alertname"),
                "severity": event.get("severity"),
                "namespace": event.get("namespace"),
                "target_resource": event.get("target_resource"),
                "fingerprint": event.get("fingerprint"),
                "latest_stage": event.get("stage"),
                "latest_event_id": event.get("event_id"),
                "latest_provider_event_id": event.get("provider_event_id"),
                "latest_content_preview": event.get("content_preview"),
                "latest_run_id": run_id,
                "latest_run_state": run_state,
                "latest_agent_id": row.get("run_agent_id"),
                "latest_incident_id": incident_ids[0] if incident_ids else None,
                "incident_ids": [],
                "occurrence_total": 0,
                "duplicate_total": 0,
                "linked_run_total": 0,
                "source_ref_total": 0,
                "missing_source_refs_total": 0,
                "sentry_ref_total": 0,
                "signoz_ref_total": 0,
                "alert_ref_total": 0,
                "stage_counts": {},
                "run_state_counts": {},
                "first_received_at": received_at,
                "latest_received_at": received_at,
                "_run_ids": set(),
                "_source_correlation_work_item_ids": [],
            },
        )

        group["occurrence_total"] += 1
        group["source_ref_total"] += source_ref_count
        if source_ref_count <= 0:
            group["missing_source_refs_total"] += 1
        if event.get("is_duplicate"):
            group["duplicate_total"] += 1

        stage = str(event.get("stage") or "received")
        stage_counts = group["stage_counts"]
        stage_counts[stage] = int(stage_counts.get(stage, 0)) + 1
        if (
            str(event.get("provider") or "").lower()
            in _SOURCE_CORRELATION_REVIEW_PROVIDERS
            and stage.lower() not in _SOURCE_CORRELATION_REVIEW_EXCLUDED_STAGES
            and source_ref_count > 0
            and not incident_ids
        ):
            _append_unique(
                group["_source_correlation_work_item_ids"],
                _source_correlation_work_item_id({
                    "latest_provider_event_id": event.get("provider_event_id"),
                    "recurrence_key": key,
                }),
            )

        for incident_id in incident_ids:
            _append_unique(group["incident_ids"], incident_id)

        group["sentry_ref_total"] += _ref_count(source_refs, "sentry_issue_ids")
        group["signoz_ref_total"] += _ref_count(source_refs, "signoz_alerts")
        group["alert_ref_total"] += _ref_count(source_refs, "alert_ids")

        if run_id:
            group["_run_ids"].add(str(run_id))
            if group.get("latest_run_id") is None:
                group["latest_run_id"] = run_id
                group["latest_run_state"] = run_state
                group["latest_agent_id"] = row.get("run_agent_id")
        if run_state:
            state_counts = group["run_state_counts"]
            state_counts[str(run_state)] = int(state_counts.get(str(run_state), 0)) + 1

        if received_at and (
            group.get("first_received_at") is None
            or str(received_at) < str(group.get("first_received_at"))
        ):
            group["first_received_at"] = received_at
        if received_at and (
            group.get("latest_received_at") is None
            or str(received_at) > str(group.get("latest_received_at"))
        ):
            group["latest_received_at"] = received_at
            group["latest_event_id"] = event.get("event_id")
            group["latest_provider_event_id"] = event.get("provider_event_id")
            group["latest_content_preview"] = event.get("content_preview")
            group["latest_stage"] = event.get("stage")
            group["latest_incident_id"] = (
                incident_ids[0] if incident_ids else group.get("latest_incident_id")
            )

    items = []
    linked_run_total = 0
    for group in groups.values():
        run_ids = group.pop("_run_ids")
        group["linked_run_total"] = len(run_ids)
        _attach_work_item_summary(
            group,
            repair_summaries,
            source_review_decisions,
            source_applies,
        )
        linked_run_total += len(run_ids)
        items.append(group)

    items.sort(key=lambda item: str(item.get("latest_received_at") or ""), reverse=True)
    items.sort(key=lambda item: int(item.get("occurrence_total") or 0), reverse=True)
    latest_received_at = max(
        (
            item.get("latest_received_at")
            for item in items
            if item.get("latest_received_at")
        ),
        default=None,
    )

    return {
        "project_id": project_id,
        "limit": limit,
        "summary": {
            "source_event_total": len(rows),
            "recurrence_group_total": len(items),
            "recurrent_group_total": sum(
                1 for item in items if int(item.get("occurrence_total") or 0) > 1
            ),
            "duplicate_event_total": sum(
                int(item.get("duplicate_total") or 0) for item in items
            ),
            "linked_run_total": linked_run_total,
            "unlinked_event_total": sum(1 for row in rows if not row.get("run_id")),
            "auto_repair_linked_total": sum(
                1
                for item in items
                if _as_dict(item.get("repair_summary")).get("latest_auto_repair_id")
            ),
            "verified_repair_group_total": sum(
                1
                for item in items
                if _as_dict(item.get("repair_summary")).get("status")
                == "auto_repair_verified"
            ),
            "open_work_item_group_total": sum(
                1
                for item in items
                if _as_dict(item.get("work_item")).get("status") == "open"
            ),
            "manual_gate_group_total": sum(
                1
                for item in items
                if _as_dict(item.get("repair_summary")).get("status") == "manual_gate"
            ),
            "automation_gap_group_total": sum(
                1
                for item in items
                if _as_dict(item.get("repair_summary")).get("status")
                == "run_completed_no_repair"
            ),
            "failed_repair_group_total": sum(
                1
                for item in items
                if _as_dict(item.get("repair_summary")).get("status")
                == "auto_repair_failed"
            ),
            "source_correlation_review_group_total": sum(
                1
                for item in items
                if _as_dict(item.get("repair_summary")).get("status")
                == "source_correlation_review"
            ),
            "source_correlation_decision_recorded_group_total": sum(
                1 for item in items if item.get("source_correlation_review")
            ),
            "source_correlation_applied_group_total": sum(
                1 for item in items if item.get("source_correlation_apply")
            ),
            "latest_received_at": latest_received_at,
        },
        "items": items,
    }


def _repair_status(
    *,
    incident_id: str | None,
    latest_run_state: str | None,
    repair_summary: dict[str, Any] | None,
) -> str:
    if not incident_id:
        return "no_incident_link"
    if repair_summary:
        latest_success = repair_summary.get("latest_success")
        verification = str(
            repair_summary.get("latest_verification_result") or ""
        ).lower()
        if latest_success is True and verification == "success":
            return "auto_repair_verified"
        if latest_success is True:
            return "auto_repair_succeeded_unverified"
        if latest_success is False:
            return "auto_repair_failed"
        return "auto_repair_recorded"
    if latest_run_state == "waiting_approval":
        return "manual_gate"
    if latest_run_state in {"pending", "running", "waiting_tool"}:
        return "investigating"
    if latest_run_state == "completed":
        return "run_completed_no_repair"
    return "no_repair_record"


def _work_item_status(repair_status: str) -> str:
    if repair_status == "no_incident_link":
        return "none"
    if repair_status in {
        "auto_repair_verified",
        "source_correlation_accepted",
        "source_correlation_rejected",
    }:
        return "closed"
    return "open"


def _work_item_kind(repair_status: str, auto_repair_id: Any) -> str:
    if repair_status in {
        "source_correlation_review",
        "source_correlation_accepted",
        "source_correlation_rejected",
    }:
        return "source_correlation_review"
    if auto_repair_id:
        return "verification"
    if repair_status == "run_completed_no_repair":
        return "automation_gap"
    if repair_status == "manual_gate":
        return "approval_followup"
    if repair_status == "investigating":
        return "investigation"
    return "incident_followup"


def _work_item_next_step(repair_status: str) -> str:
    return {
        "source_correlation_review": "review_provider_source_match",
        "source_correlation_accepted": "verify_source_match_in_status_chain",
        "source_correlation_rejected": "monitor_for_new_provider_evidence",
        "source_correlation_applied": "verify_source_link_in_status_chain",
        "auto_repair_succeeded_unverified": "run_post_verification",
        "auto_repair_failed": "triage_failed_repair",
        "auto_repair_recorded": "review_repair_record",
        "manual_gate": "review_approval",
        "investigating": "wait_for_run_completion",
        "run_completed_no_repair": "create_repair_ticket",
        "no_repair_record": "triage_missing_repair_record",
    }.get(repair_status, "none")


def _work_item_reason(repair_status: str) -> str:
    return {
        "source_correlation_review": "provider_native_evidence_unlinked",
        "source_correlation_accepted": "provider_native_evidence_accepted",
        "source_correlation_rejected": "provider_native_evidence_rejected",
        "source_correlation_applied": "provider_native_evidence_link_applied",
        "auto_repair_succeeded_unverified": "auto_repair_missing_verification",
        "auto_repair_failed": "auto_repair_failed",
        "auto_repair_recorded": "auto_repair_record_needs_review",
        "manual_gate": "approval_required",
        "investigating": "run_still_investigating",
        "run_completed_no_repair": "completed_run_without_auto_repair",
        "no_repair_record": "incident_without_repair_record",
    }.get(repair_status, "none")


def _attach_work_item_summary(
    group: dict[str, Any],
    repair_summaries_by_incident: dict[str, dict[str, Any]],
    source_review_decisions_by_work_item: dict[str, dict[str, Any]],
    source_applies_by_work_item: dict[str, dict[str, Any]],
) -> None:
    incident_ids = [
        str(incident_id) for incident_id in group.get("incident_ids", []) if incident_id
    ]
    latest_incident_id = str(group.get("latest_incident_id") or "") or (
        incident_ids[0] if incident_ids else None
    )
    repair_summary = (
        repair_summaries_by_incident.get(latest_incident_id)
        if latest_incident_id
        else None
    )
    status_value = _repair_status(
        incident_id=latest_incident_id,
        latest_run_state=group.get("latest_run_state"),
        repair_summary=repair_summary,
    )
    if _needs_source_correlation_review(group, latest_incident_id):
        status_value = "source_correlation_review"

    if repair_summary:
        repair_payload = dict(repair_summary)
        repair_payload["status"] = status_value
    else:
        repair_payload = {
            "schema_version": "awooop_recurrence_repair_summary_v1",
            "status": status_value,
            "incident_id": latest_incident_id,
            "latest_auto_repair_id": None,
            "latest_verification_result": None,
            "auto_repair_total": 0,
            "success_total": 0,
            "failed_total": 0,
        }

    work_status = _work_item_status(status_value)
    auto_repair_id = repair_payload.get("latest_auto_repair_id")
    work_item_id = None
    if latest_incident_id and work_status != "none":
        work_item_id = (
            f"verification:{latest_incident_id}:{auto_repair_id}"
            if auto_repair_id
            else f"incident:{latest_incident_id}"
        )
    elif status_value == "source_correlation_review" and work_status != "none":
        work_item_id = _source_correlation_work_item_id(group)

    source_work_item_ids = [
        str(candidate)
        for candidate in group.pop("_source_correlation_work_item_ids", [])
        if candidate
    ]
    candidate_work_item_ids = [
        candidate
        for candidate in [work_item_id, *source_work_item_ids]
        if candidate
    ]
    source_review_decision = next(
        (
            source_review_decisions_by_work_item[candidate]
            for candidate in candidate_work_item_ids
            if candidate in source_review_decisions_by_work_item
        ),
        None,
    )
    source_apply = next(
        (
            source_applies_by_work_item[candidate]
            for candidate in candidate_work_item_ids
            if candidate in source_applies_by_work_item
        ),
        None,
    )
    matched_incident_id = None
    work_item_next_step = _work_item_next_step(status_value)
    work_item_reason = _work_item_reason(status_value)
    if source_review_decision:
        outcome = _source_correlation_review_outcome(
            str(source_review_decision.get("decision") or "")
        )
        status_value = outcome["status"]
        repair_payload["status"] = status_value
        work_status = _work_item_status(status_value)
        matched_incident_id = source_review_decision.get("target_incident_id")
        work_item_next_step = outcome["next_step"]
        work_item_reason = outcome["reason"]
        group["source_correlation_review"] = source_review_decision
    if source_apply:
        matched_incident_id = source_apply.get("target_incident_id")
        group["source_correlation_apply"] = source_apply
        if status_value in {
            "source_correlation_review",
            "source_correlation_accepted",
        }:
            work_item_next_step = "verify_source_link_in_status_chain"
            work_item_reason = "provider_native_evidence_link_applied"

    group["latest_incident_id"] = latest_incident_id
    group["repair_summary"] = repair_payload
    group["work_item"] = {
        "schema_version": "awooop_recurrence_work_item_link_v1",
        "work_item_id": work_item_id,
        "incident_id": latest_incident_id,
        "matched_incident_id": matched_incident_id,
        "auto_repair_id": auto_repair_id,
        "status": work_status,
        "kind": _work_item_kind(status_value, auto_repair_id),
        "next_step": work_item_next_step,
        "reason": work_item_reason,
        "needs_human": work_status == "open",
    }


def _recurrence_work_item_target(item: dict[str, Any]) -> dict[str, Any]:
    return {
        "recurrence_key": item.get("recurrence_key"),
        "provider": item.get("provider"),
        "alertname": item.get("alertname"),
        "severity": item.get("severity"),
        "namespace": item.get("namespace"),
        "target_resource": item.get("target_resource"),
        "fingerprint": item.get("fingerprint"),
        "latest_stage": item.get("latest_stage"),
        "latest_event_id": item.get("latest_event_id"),
        "latest_provider_event_id": item.get("latest_provider_event_id"),
        "latest_run_id": item.get("latest_run_id"),
        "latest_run_state": item.get("latest_run_state"),
        "latest_agent_id": item.get("latest_agent_id"),
        "latest_incident_id": item.get("latest_incident_id"),
        "matched_incident_id": _as_dict(item.get("work_item")).get(
            "matched_incident_id"
        ),
    }


def _selected_recurrence_mode(
    work_item: dict[str, Any],
    requested_mode: RecurrenceWorkItemMode,
) -> str:
    if requested_mode != "auto":
        return requested_mode

    next_step = str(work_item.get("next_step") or "")
    if next_step == "create_repair_ticket":
        return "ticket"
    if next_step in {
        "run_post_verification",
        "triage_failed_repair",
        "review_repair_record",
        "triage_missing_repair_record",
    }:
        return "reverify"
    if next_step == "review_approval":
        return "approval_review"
    return "observe"


def _recurrence_work_item_checks(
    item: dict[str, Any],
    work_item: dict[str, Any],
) -> list[dict[str, Any]]:
    repair_summary = _as_dict(item.get("repair_summary"))
    source_ref_total = int(item.get("source_ref_total") or 0)
    is_source_review = work_item.get("kind") == "source_correlation_review"
    evidence_linked = bool(item.get("latest_provider_event_id")) and source_ref_total > 0
    incident_or_source_linked = bool(work_item.get("incident_id")) or (
        is_source_review and evidence_linked
    )
    return [
        {
            "name": "work_item_open",
            "passed": work_item.get("status") == "open",
            "detail": str(work_item.get("status") or "unknown"),
        },
        {
            "name": "incident_or_source_evidence_linked",
            "passed": incident_or_source_linked,
            "detail": str(
                work_item.get("incident_id")
                or item.get("latest_provider_event_id")
                or "missing incident_id/source evidence"
            ),
        },
        {
            "name": "known_next_step",
            "passed": str(work_item.get("next_step") or "none") != "none",
            "detail": str(work_item.get("next_step") or "none"),
        },
        {
            "name": "source_refs_present",
            "passed": source_ref_total > 0,
            "detail": str(source_ref_total),
        },
        {
            "name": "no_destructive_writes",
            "passed": True,
            "detail": "preview_and_dry_run_only",
        },
        {
            "name": "repair_status_visible",
            "passed": bool(repair_summary.get("status")),
            "detail": str(repair_summary.get("status") or "unknown"),
        },
    ]


def _recurrence_plan(
    item: dict[str, Any],
    work_item: dict[str, Any],
    mode: str,
) -> dict[str, Any]:
    route_by_mode = {
        "ticket": {
            "step": "prepare_repair_ticket_preview",
            "flywheel_node": "work_item_to_ticket",
            "agent_id": "awooop_recurrence_coordinator",
        },
        "reverify": {
            "step": "collect_read_model_and_prepare_reverification",
            "flywheel_node": "verify",
            "agent_id": "post_execution_verifier",
        },
        "approval_review": {
            "step": "route_to_approval_review",
            "flywheel_node": "approval",
            "agent_id": "awooop_approval_coordinator",
        },
        "observe": {
            "step": "observe_until_run_or_repair_state_changes",
            "flywheel_node": "observe",
            "agent_id": "awooop_recurrence_coordinator",
        },
    }
    route = route_by_mode.get(mode, route_by_mode["observe"])
    return {
        **route,
        "required_scope": "read",
        "writes": [],
        "target_action": work_item.get("next_step"),
        "reason": work_item.get("reason"),
        "target": _recurrence_work_item_target(item),
    }


def _ticket_preview(item: dict[str, Any], work_item: dict[str, Any]) -> dict[str, Any]:
    alertname = str(item.get("alertname") or item.get("provider") or "recurrence")
    incident_id = str(work_item.get("incident_id") or item.get("latest_incident_id") or "")
    kind = str(work_item.get("kind") or "recurrence")
    if kind == "source_correlation_review":
        title = f"[AwoooP] Source evidence review: {alertname}"
        labels = ["awooop", "source-correlation", "review", str(item.get("provider") or "source")]
        body_lines = [
            f"Provider event: {item.get('latest_provider_event_id') or '--'}",
            f"Stage: {item.get('latest_stage') or '--'}",
            f"Provider: {item.get('provider') or '--'}",
            f"Alert: {alertname}",
            f"Namespace/Target: {item.get('namespace') or '--'} / {item.get('target_resource') or '--'}",
            f"Source refs: {item.get('source_ref_total') or 0}",
            f"Sentry refs: {item.get('sentry_ref_total') or 0}",
            f"SignOz refs: {item.get('signoz_ref_total') or 0}",
            f"Next step: {work_item.get('next_step') or '--'}",
            "Writes: none in preview/dry-run; source matching requires a later explicit review/apply path.",
        ]
    else:
        title = f"[AwoooP] {alertname} recurrence work item: {incident_id or 'unlinked'}"
        labels = ["awooop", "recurrence", kind]
        body_lines = [
            f"Incident: {incident_id or '--'}",
            f"Alert: {alertname}",
            f"Namespace/Target: {item.get('namespace') or '--'} / {item.get('target_resource') or '--'}",
            f"Occurrences: {item.get('occurrence_total') or 0}",
            f"Duplicates: {item.get('duplicate_total') or 0}",
            f"Latest run: {item.get('latest_run_id') or '--'} ({item.get('latest_run_state') or '--'})",
            f"Repair status: {_as_dict(item.get('repair_summary')).get('status') or '--'}",
            f"Next step: {work_item.get('next_step') or '--'}",
            "Writes: none in preview/dry-run; ticket creation requires a later explicit apply path.",
        ]
    return {
        "would_create": False,
        "title": title[:180],
        "labels": labels,
        "body_preview": "\n".join(body_lines)[:1000],
    }


def _recurrence_current_state_summary(
    item: dict[str, Any],
    work_item: dict[str, Any],
) -> dict[str, Any]:
    repair_summary = _as_dict(item.get("repair_summary"))
    return {
        "work_item_status": work_item.get("status"),
        "work_item_kind": work_item.get("kind"),
        "work_item_next_step": work_item.get("next_step"),
        "work_item_reason": work_item.get("reason"),
        "occurrence_total": int(item.get("occurrence_total") or 0),
        "duplicate_total": int(item.get("duplicate_total") or 0),
        "linked_run_total": int(item.get("linked_run_total") or 0),
        "run_state_counts": item.get("run_state_counts") or {},
        "stage_counts": item.get("stage_counts") or {},
        "latest_stage": item.get("latest_stage"),
        "latest_provider_event_id": item.get("latest_provider_event_id"),
        "latest_run_state": item.get("latest_run_state"),
        "latest_run_id": item.get("latest_run_id"),
        "matched_incident_id": work_item.get("matched_incident_id"),
        "source_correlation_review": item.get("source_correlation_review"),
        "source_correlation_apply": item.get("source_correlation_apply"),
        "repair_status": repair_summary.get("status"),
        "latest_auto_repair_id": repair_summary.get("latest_auto_repair_id"),
        "latest_verification_result": repair_summary.get("latest_verification_result"),
        "auto_repair_total": int(repair_summary.get("auto_repair_total") or 0),
        "source_ref_total": int(item.get("source_ref_total") or 0),
        "sentry_ref_total": int(item.get("sentry_ref_total") or 0),
        "signoz_ref_total": int(item.get("signoz_ref_total") or 0),
        "alert_ref_total": int(item.get("alert_ref_total") or 0),
    }


def _verification_result_preview(mode: str, allowed: bool) -> str:
    if not allowed:
        return "blocked"
    return {
        "ticket": "ticket_preview_ready",
        "reverify": "reverify_preview_ready",
        "approval_review": "approval_review_required",
        "observe": "observe_only",
    }.get(mode, "observe_only")


def _find_recurrence_work_item(
    recurrence: dict[str, Any],
    work_item_id: str,
) -> tuple[dict[str, Any], dict[str, Any]]:
    for item in recurrence.get("items") or []:
        work_item = _as_dict(item.get("work_item"))
        if work_item.get("work_item_id") == work_item_id:
            return item, work_item
    raise RecurrenceWorkItemNotFoundError(work_item_id)


def build_recurrence_work_item_preview(
    recurrence: dict[str, Any],
    *,
    work_item_id: str,
    mode: RecurrenceWorkItemMode = "auto",
) -> dict[str, Any]:
    """Build a read-only plan for a recurrence work item."""

    item, work_item = _find_recurrence_work_item(recurrence, work_item_id)
    selected_mode = _selected_recurrence_mode(work_item, mode)
    checks = _recurrence_work_item_checks(item, work_item)
    allowed = all(check["passed"] for check in checks)

    return {
        "schema_version": "awooop_recurrence_work_item_preview_v1",
        "source": "channel_event_dossier.recurrence",
        "project_id": recurrence.get("project_id"),
        "work_item_id": work_item.get("work_item_id"),
        "incident_id": work_item.get("incident_id"),
        "auto_repair_id": work_item.get("auto_repair_id"),
        "mode": selected_mode,
        "requested_mode": mode,
        "allowed": allowed,
        "safety_level": "read_only",
        "writes_incident_state": False,
        "writes_auto_repair_result": False,
        "writes_ticket": False,
        "checks": checks,
        "plan": _recurrence_plan(item, work_item, selected_mode),
    }


def build_recurrence_work_item_dry_run(
    recurrence: dict[str, Any],
    *,
    work_item_id: str,
    mode: RecurrenceWorkItemMode = "auto",
) -> dict[str, Any]:
    """Build a read-only dry-run result for a recurrence work item."""

    item, work_item = _find_recurrence_work_item(recurrence, work_item_id)
    selected_mode = _selected_recurrence_mode(work_item, mode)
    checks = _recurrence_work_item_checks(item, work_item)
    allowed = all(check["passed"] for check in checks)
    payload = {
        "schema_version": "awooop_recurrence_work_item_dry_run_v1",
        "source": "channel_event_dossier.recurrence",
        "project_id": recurrence.get("project_id"),
        "work_item_id": work_item.get("work_item_id"),
        "incident_id": work_item.get("incident_id"),
        "auto_repair_id": work_item.get("auto_repair_id"),
        "mode": selected_mode,
        "requested_mode": mode,
        "allowed": allowed,
        "executed": allowed,
        "safety_level": "read_only",
        "writes_incident_state": False,
        "writes_auto_repair_result": False,
        "writes_ticket": False,
        "checks": checks,
        "verification_result_preview": _verification_result_preview(
            selected_mode,
            allowed,
        ),
        "current_state_summary": _recurrence_current_state_summary(item, work_item),
        "ticket_preview": _ticket_preview(item, work_item),
        "plan": _recurrence_plan(item, work_item, selected_mode),
        "read_model_route": {
            "agent_id": "awooop_recurrence_coordinator",
            "tool_name": "channel_event_dossier.recurrence",
            "required_scope": "read",
            "is_shadow": True,
            "flywheel_node": "work_item",
        },
        "next_step": work_item.get("next_step"),
    }
    if not allowed:
        payload["executed"] = False
    return payload


def _recurrence_handoff_next_step(
    handoff_kind: RecurrenceWorkItemHandoffKind,
    allowed: bool,
) -> str:
    if not allowed:
        return "fix_preflight_checks"
    if handoff_kind == "manual_review":
        return "operator_manual_review"
    return "operator_review_ticket_preview"


def build_recurrence_work_item_handoff(
    recurrence: dict[str, Any],
    *,
    work_item_id: str,
    mode: RecurrenceWorkItemMode = "auto",
    handoff_kind: RecurrenceWorkItemHandoffKind = "ticket_proposal",
) -> dict[str, Any]:
    """Build a record-only handoff proposal for a recurrence work item."""

    payload = build_recurrence_work_item_dry_run(
        recurrence,
        work_item_id=work_item_id,
        mode=mode,
    )
    allowed = bool(payload.get("allowed"))
    plan = _as_dict(payload.get("plan"))
    read_model_route = _as_dict(payload.get("read_model_route"))
    payload.update(
        {
            "schema_version": "awooop_recurrence_work_item_handoff_v1",
            "handoff_kind": handoff_kind,
            "handoff_status": "ready_to_record" if allowed else "blocked",
            "handoff_owner": "operator",
            "safety_level": "handoff_record_only",
            "writes_incident_state": False,
            "writes_auto_repair_result": False,
            "writes_ticket": False,
            "creates_external_ticket": False,
            "plan": {
                **plan,
                "step": "record_recurrence_work_item_handoff",
                "flywheel_node": "handoff",
                "required_scope": "record_history",
                "writes": ["timeline_events", "alert_operation_log"],
            },
            "read_model_route": {
                **read_model_route,
                "required_scope": "record_history",
                "is_shadow": False,
                "flywheel_node": "handoff",
            },
            "next_step": _recurrence_handoff_next_step(handoff_kind, allowed),
        }
    )
    return payload


def _recurrence_history_context(payload: dict[str, Any]) -> dict[str, Any]:
    return {
        "schema_version": "awooop_recurrence_work_item_dry_run_history_v1",
        "source": payload.get("source"),
        "project_id": payload.get("project_id"),
        "work_item_id": payload.get("work_item_id"),
        "incident_id": payload.get("incident_id"),
        "auto_repair_id": payload.get("auto_repair_id"),
        "mode": payload.get("mode"),
        "requested_mode": payload.get("requested_mode"),
        "allowed": payload.get("allowed"),
        "executed": payload.get("executed"),
        "safety_level": payload.get("safety_level"),
        "writes_incident_state": payload.get("writes_incident_state"),
        "writes_auto_repair_result": payload.get("writes_auto_repair_result"),
        "writes_ticket": payload.get("writes_ticket"),
        "verification_result_preview": payload.get("verification_result_preview"),
        "current_state_summary": payload.get("current_state_summary"),
        "ticket_preview": payload.get("ticket_preview"),
        "read_model_route": payload.get("read_model_route"),
        "checks": payload.get("checks"),
        "next_step": payload.get("next_step"),
    }


def _recurrence_handoff_context(payload: dict[str, Any]) -> dict[str, Any]:
    return {
        "schema_version": "awooop_recurrence_work_item_handoff_history_v1",
        "source": payload.get("source"),
        "project_id": payload.get("project_id"),
        "work_item_id": payload.get("work_item_id"),
        "incident_id": payload.get("incident_id"),
        "auto_repair_id": payload.get("auto_repair_id"),
        "mode": payload.get("mode"),
        "requested_mode": payload.get("requested_mode"),
        "handoff_kind": payload.get("handoff_kind"),
        "handoff_status": payload.get("handoff_status"),
        "handoff_owner": payload.get("handoff_owner"),
        "allowed": payload.get("allowed"),
        "executed": payload.get("executed"),
        "safety_level": payload.get("safety_level"),
        "writes_incident_state": payload.get("writes_incident_state"),
        "writes_auto_repair_result": payload.get("writes_auto_repair_result"),
        "writes_ticket": payload.get("writes_ticket"),
        "creates_external_ticket": payload.get("creates_external_ticket"),
        "verification_result_preview": payload.get("verification_result_preview"),
        "current_state_summary": payload.get("current_state_summary"),
        "ticket_preview": payload.get("ticket_preview"),
        "read_model_route": payload.get("read_model_route"),
        "checks": payload.get("checks"),
        "next_step": payload.get("next_step"),
    }


def _is_source_correlation_review_payload(payload: dict[str, Any]) -> bool:
    state = _as_dict(payload.get("current_state_summary"))
    return (
        state.get("work_item_kind") == "source_correlation_review"
        or payload.get("next_step") == "review_provider_source_match"
    )


async def _record_recurrence_work_item_dry_run_history(
    payload: dict[str, Any],
) -> dict[str, Any]:
    incident_id = str(payload.get("incident_id") or "")
    source_review = _is_source_correlation_review_payload(payload)
    if not incident_id and not source_review:
        return {"recorded": False, "reason": "missing_incident_id"}

    history: dict[str, Any] = {
        "recorded": False,
        "alert_operation_id": None,
        "timeline_event_id": None,
    }
    context = _recurrence_history_context(payload)
    allowed = bool(payload.get("allowed"))

    try:
        from src.repositories.alert_operation_log_repository import (
            get_alert_operation_log_repository,
        )

        record = await get_alert_operation_log_repository().append(
            "PRE_FLIGHT_PASSED" if allowed else "PRE_FLIGHT_FAILED",
            incident_id=incident_id or None,
            auto_repair_id=str(payload.get("auto_repair_id") or "") or None,
            actor="awooop_recurrence_work_item_service",
            action_detail=f"recurrence_work_item_dry_run:{payload.get('mode')}"[:200],
            success=allowed,
            context=_json_safe(context),
        )
        if record is not None:
            history["alert_operation_id"] = getattr(record, "id", None)
    except Exception as exc:
        logger.warning(
            "awooop_recurrence_work_item_alert_operation_history_failed",
            incident_id=incident_id,
            error=str(exc),
        )

    if incident_id:
        try:
            from src.services.approval_db import get_timeline_service

            event = await get_timeline_service().add_event(
                event_type="verifier",
                status="success" if allowed else "warning",
                title="AwoooP recurrence work item dry-run",
                description=_recurrence_history_description(context),
                actor="awooop_recurrence_work_item_service",
                actor_role=str(payload.get("mode") or "dry_run"),
                incident_id=incident_id,
            )
            if event:
                history["timeline_event_id"] = event.get("id")
        except Exception as exc:
            logger.warning(
                "awooop_recurrence_work_item_timeline_history_failed",
                incident_id=incident_id,
                error=str(exc),
            )
    else:
        history["timeline_reason"] = "source_review_not_incident_scoped"

    history["recorded"] = bool(
        history.get("alert_operation_id") or history.get("timeline_event_id")
    )
    if not history["recorded"]:
        history["reason"] = "history_sink_unavailable"
    return history


async def _record_recurrence_work_item_handoff_history(
    payload: dict[str, Any],
) -> dict[str, Any]:
    incident_id = str(payload.get("incident_id") or "")
    source_review = _is_source_correlation_review_payload(payload)
    if not incident_id and not source_review:
        return {"recorded": False, "reason": "missing_incident_id"}

    history: dict[str, Any] = {
        "recorded": False,
        "alert_operation_id": None,
        "timeline_event_id": None,
    }
    context = _recurrence_handoff_context(payload)
    allowed = bool(payload.get("allowed"))

    try:
        from src.repositories.alert_operation_log_repository import (
            get_alert_operation_log_repository,
        )

        record = await get_alert_operation_log_repository().append(
            "ESCALATED",
            incident_id=incident_id or None,
            auto_repair_id=str(payload.get("auto_repair_id") or "") or None,
            actor="awooop_recurrence_work_item_service",
            action_detail=(
                f"recurrence_work_item_handoff:{payload.get('handoff_kind')}"
            )[:200],
            success=allowed,
            context=_json_safe(context),
        )
        if record is not None:
            history["alert_operation_id"] = getattr(record, "id", None)
    except Exception as exc:
        logger.warning(
            "awooop_recurrence_work_item_handoff_alert_operation_history_failed",
            incident_id=incident_id,
            error=str(exc),
        )

    if incident_id:
        try:
            from src.services.approval_db import get_timeline_service

            event = await get_timeline_service().add_event(
                event_type="human",
                status="warning" if allowed else "error",
                title="AwoooP recurrence work item handoff",
                description=_recurrence_handoff_history_description(context),
                actor="awooop_recurrence_work_item_service",
                actor_role=str(payload.get("handoff_kind") or "handoff"),
                incident_id=incident_id,
            )
            if event:
                history["timeline_event_id"] = event.get("id")
        except Exception as exc:
            logger.warning(
                "awooop_recurrence_work_item_handoff_timeline_history_failed",
                incident_id=incident_id,
                error=str(exc),
            )
    else:
        history["timeline_reason"] = "source_review_not_incident_scoped"

    history["recorded"] = bool(
        history.get("alert_operation_id") or history.get("timeline_event_id")
    )
    if not history["recorded"]:
        history["reason"] = "history_sink_unavailable"
    return history


def _recurrence_history_description(context: dict[str, Any]) -> str:
    state = context.get("current_state_summary") or {}
    route = context.get("read_model_route") or {}
    return (
        f"mode={context.get('mode')} "
        f"preview={context.get('verification_result_preview')} "
        f"occurrences={state.get('occurrence_total')} "
        f"repair_status={state.get('repair_status')} "
        f"route={route.get('agent_id')}/{route.get('tool_name')} "
        f"writes_incident={context.get('writes_incident_state')} "
        f"writes_auto_repair={context.get('writes_auto_repair_result')} "
        f"writes_ticket={context.get('writes_ticket')}"
    )[:500]


def _recurrence_handoff_history_description(context: dict[str, Any]) -> str:
    state = context.get("current_state_summary") or {}
    route = context.get("read_model_route") or {}
    return (
        f"handoff={context.get('handoff_kind')} "
        f"status={context.get('handoff_status')} "
        f"mode={context.get('mode')} "
        f"occurrences={state.get('occurrence_total')} "
        f"repair_status={state.get('repair_status')} "
        f"route={route.get('agent_id')}/{route.get('tool_name')} "
        f"external_ticket={context.get('creates_external_ticket')} "
        f"writes_incident={context.get('writes_incident_state')} "
        f"writes_auto_repair={context.get('writes_auto_repair_result')} "
        f"writes_ticket={context.get('writes_ticket')}"
    )[:500]


def _source_correlation_review_checks(
    item: dict[str, Any],
    work_item: dict[str, Any],
    *,
    decision: str,
    target_incident_id: str | None,
) -> list[dict[str, Any]]:
    source_ref_total = int(item.get("source_ref_total") or 0)
    is_source_review = work_item.get("kind") == "source_correlation_review"
    checks = [
        {
            "name": "source_review_work_item",
            "passed": is_source_review,
            "detail": str(work_item.get("kind") or "unknown"),
        },
        {
            "name": "known_decision",
            "passed": decision
            in {"accepted", "rejected", "needs_more_evidence"},
            "detail": decision or "unknown",
        },
        {
            "name": "source_refs_present",
            "passed": source_ref_total > 0,
            "detail": str(source_ref_total),
        },
        {
            "name": "provider_event_present",
            "passed": bool(item.get("latest_provider_event_id")),
            "detail": str(item.get("latest_provider_event_id") or "missing"),
        },
        {
            "name": "review_record_only",
            "passed": True,
            "detail": "alert_operation_log_only",
        },
    ]
    if decision == "accepted":
        checks.append(
            {
                "name": "target_incident_required",
                "passed": bool(
                    target_incident_id and _INCIDENT_ID_RE.search(target_incident_id)
                ),
                "detail": target_incident_id or "missing target_incident_id",
            }
        )
    return checks


def _source_correlation_review_context(payload: dict[str, Any]) -> dict[str, Any]:
    return {
        "schema_version": _SOURCE_CORRELATION_DECISION_SCHEMA_VERSION,
        "source": payload.get("source"),
        "project_id": payload.get("project_id"),
        "work_item_id": payload.get("work_item_id"),
        "decision": payload.get("decision"),
        "review_status": payload.get("review_status"),
        "target_incident_id": payload.get("target_incident_id"),
        "reviewer_id": payload.get("reviewer_id"),
        "operator_note": payload.get("operator_note"),
        "latest_provider_event_id": payload.get("latest_provider_event_id"),
        "latest_stage": payload.get("latest_stage"),
        "provider": payload.get("provider"),
        "alertname": payload.get("alertname"),
        "namespace": payload.get("namespace"),
        "target_resource": payload.get("target_resource"),
        "safety_level": payload.get("safety_level"),
        "writes_incident_state": payload.get("writes_incident_state"),
        "writes_source_event": payload.get("writes_source_event"),
        "writes_auto_repair_result": payload.get("writes_auto_repair_result"),
        "writes_ticket": payload.get("writes_ticket"),
        "creates_external_ticket": payload.get("creates_external_ticket"),
        "checks": payload.get("checks"),
        "current_state_summary": payload.get("current_state_summary"),
        "plan": payload.get("plan"),
        "read_model_route": payload.get("read_model_route"),
        "next_step": payload.get("next_step"),
        "history": payload.get("history"),
    }


def _source_correlation_review_description(context: dict[str, Any]) -> str:
    return (
        f"decision={context.get('decision')} "
        f"work_item={context.get('work_item_id')} "
        f"provider_event={context.get('latest_provider_event_id')} "
        f"target_incident={context.get('target_incident_id') or '--'} "
        f"writes_incident={context.get('writes_incident_state')} "
        f"writes_source_event={context.get('writes_source_event')}"
    )[:500]


def build_source_correlation_review_decision(
    recurrence: dict[str, Any],
    *,
    work_item_id: str,
    decision: SourceCorrelationReviewDecision,
    target_incident_id: str | None = None,
    reviewer_id: str = "operator_console",
    operator_note: str | None = None,
) -> dict[str, Any]:
    """Build a record-only source-correlation review decision payload."""

    item, work_item = _find_recurrence_work_item(recurrence, work_item_id)
    safe_decision = str(decision)
    target_id = str(target_incident_id or "").strip() or None
    checks = _source_correlation_review_checks(
        item,
        work_item,
        decision=safe_decision,
        target_incident_id=target_id,
    )
    allowed = all(check["passed"] for check in checks)
    outcome = _source_correlation_review_outcome(safe_decision)
    writes_timeline = bool(target_id and safe_decision == "accepted")

    payload = {
        "schema_version": _SOURCE_CORRELATION_DECISION_SCHEMA_VERSION,
        "source": "channel_event_dossier.recurrence",
        "project_id": recurrence.get("project_id"),
        "work_item_id": work_item.get("work_item_id"),
        "incident_id": work_item.get("incident_id"),
        "target_incident_id": target_id,
        "decision": safe_decision,
        "review_status": outcome["review_status"],
        "reviewer_id": str(reviewer_id or "operator_console")[:100],
        "operator_note": str(operator_note or "").strip()[:500] or None,
        "allowed": allowed,
        "executed": allowed,
        "safety_level": "source_review_record_only",
        "writes_incident_state": False,
        "writes_source_event": False,
        "writes_auto_repair_result": False,
        "writes_ticket": False,
        "creates_external_ticket": False,
        "latest_provider_event_id": item.get("latest_provider_event_id"),
        "latest_stage": item.get("latest_stage"),
        "provider": item.get("provider"),
        "alertname": item.get("alertname"),
        "namespace": item.get("namespace"),
        "target_resource": item.get("target_resource"),
        "checks": checks,
        "current_state_summary": _recurrence_current_state_summary(item, work_item),
        "plan": {
            "step": "record_source_correlation_review_decision",
            "flywheel_node": "source_correlation_review",
            "agent_id": "awooop_source_correlation_reviewer",
            "required_scope": "record_history",
            "writes": ["alert_operation_log", *(["timeline_events"] if writes_timeline else [])],
            "target_action": outcome["next_step"],
            "reason": outcome["reason"],
            "target": _recurrence_work_item_target(item),
        },
        "read_model_route": {
            "agent_id": "awooop_source_correlation_reviewer",
            "tool_name": "channel_event_dossier.recurrence",
            "required_scope": "record_history",
            "is_shadow": False,
            "flywheel_node": "source_correlation_review",
        },
        "next_step": outcome["next_step"] if allowed else "fix_preflight_checks",
    }
    if not allowed:
        payload["executed"] = False
    return payload


async def _record_source_correlation_review_decision_history(
    payload: dict[str, Any],
) -> dict[str, Any]:
    if not payload.get("allowed"):
        return {"recorded": False, "reason": "preflight_failed"}

    incident_id = str(payload.get("target_incident_id") or "") or None
    history: dict[str, Any] = {
        "recorded": False,
        "alert_operation_id": None,
        "timeline_event_id": None,
    }
    context = _source_correlation_review_context(payload)

    try:
        from src.repositories.alert_operation_log_repository import (
            get_alert_operation_log_repository,
        )

        record = await get_alert_operation_log_repository().append(
            "USER_ACTION",
            incident_id=incident_id,
            actor=_SOURCE_CORRELATION_REVIEW_ACTOR,
            action_detail=f"source_correlation_review:{payload.get('decision')}"[:200],
            success=True,
            context=_json_safe(context),
        )
        if record is not None:
            history["alert_operation_id"] = getattr(record, "id", None)
    except Exception as exc:
        logger.warning(
            "awooop_source_correlation_review_alert_operation_failed",
            work_item_id=payload.get("work_item_id"),
            error=str(exc),
        )

    if incident_id and payload.get("decision") == "accepted":
        try:
            from src.services.approval_db import get_timeline_service

            event = await get_timeline_service().add_event(
                event_type="human",
                status="success",
                title="AwoooP source correlation review",
                description=_source_correlation_review_description(context),
                actor=_SOURCE_CORRELATION_REVIEW_ACTOR,
                actor_role="source_correlation_review",
                incident_id=incident_id,
            )
            if event:
                history["timeline_event_id"] = event.get("id")
        except Exception as exc:
            logger.warning(
                "awooop_source_correlation_review_timeline_failed",
                incident_id=incident_id,
                work_item_id=payload.get("work_item_id"),
                error=str(exc),
            )
    else:
        history["timeline_reason"] = "review_not_incident_timeline_scoped"

    history["recorded"] = bool(
        history.get("alert_operation_id") or history.get("timeline_event_id")
    )
    if not history["recorded"]:
        history["reason"] = "history_sink_unavailable"
    return history


def _source_correlation_apply_checks(
    item: dict[str, Any],
    work_item: dict[str, Any],
    source_review: dict[str, Any],
    *,
    target_incident_id: str | None,
) -> list[dict[str, Any]]:
    provider = str(item.get("provider") or "").lower()
    source_ref_total = int(item.get("source_ref_total") or 0)
    return [
        {
            "name": "source_review_work_item",
            "passed": work_item.get("kind") == "source_correlation_review",
            "detail": str(work_item.get("kind") or "unknown"),
        },
        {
            "name": "accepted_review_recorded",
            "passed": source_review.get("decision") == "accepted",
            "detail": str(source_review.get("decision") or "missing"),
        },
        {
            "name": "target_incident_present",
            "passed": bool(target_incident_id),
            "detail": target_incident_id or "missing target_incident_id",
        },
        {
            "name": "provider_supported",
            "passed": provider in _SOURCE_CORRELATION_REVIEW_PROVIDERS,
            "detail": provider or "unknown",
        },
        {
            "name": "source_refs_present",
            "passed": source_ref_total > 0,
            "detail": str(source_ref_total),
        },
        {
            "name": "provider_event_present",
            "passed": bool(item.get("latest_provider_event_id")),
            "detail": str(item.get("latest_provider_event_id") or "missing"),
        },
        {
            "name": "append_only_source_link",
            "passed": True,
            "detail": "awooop_conversation_event_append_only",
        },
    ]


def _source_correlation_apply_context(payload: dict[str, Any]) -> dict[str, Any]:
    return {
        "schema_version": _SOURCE_CORRELATION_APPLY_SCHEMA_VERSION,
        "source": payload.get("source"),
        "project_id": payload.get("project_id"),
        "work_item_id": payload.get("work_item_id"),
        "review_id": payload.get("review_id"),
        "apply_status": payload.get("apply_status"),
        "target_incident_id": payload.get("target_incident_id"),
        "reviewer_id": payload.get("reviewer_id"),
        "operator_note": payload.get("operator_note"),
        "latest_provider_event_id": payload.get("latest_provider_event_id"),
        "source_event_provider_event_id": payload.get(
            "source_event_provider_event_id"
        ),
        "source_event_stage": payload.get("source_event_stage"),
        "provider": payload.get("provider"),
        "alertname": payload.get("alertname"),
        "namespace": payload.get("namespace"),
        "target_resource": payload.get("target_resource"),
        "safety_level": payload.get("safety_level"),
        "writes_incident_state": payload.get("writes_incident_state"),
        "writes_source_event": payload.get("writes_source_event"),
        "writes_auto_repair_result": payload.get("writes_auto_repair_result"),
        "writes_ticket": payload.get("writes_ticket"),
        "creates_external_ticket": payload.get("creates_external_ticket"),
        "checks": payload.get("checks"),
        "current_state_summary": payload.get("current_state_summary"),
        "plan": payload.get("plan"),
        "read_model_route": payload.get("read_model_route"),
        "next_step": payload.get("next_step"),
        "history": payload.get("history"),
    }


def _source_correlation_apply_description(context: dict[str, Any]) -> str:
    return (
        f"work_item={context.get('work_item_id')} "
        f"provider_event={context.get('latest_provider_event_id')} "
        f"source_event={context.get('source_event_provider_event_id')} "
        f"target_incident={context.get('target_incident_id')} "
        f"writes_source_event={context.get('writes_source_event')} "
        f"writes_incident={context.get('writes_incident_state')}"
    )[:500]


def build_source_correlation_apply(
    recurrence: dict[str, Any],
    *,
    work_item_id: str,
    reviewer_id: str = "operator_console",
    operator_note: str | None = None,
) -> dict[str, Any]:
    """Build an append-only source link apply payload for an accepted review."""

    item, work_item = _find_recurrence_work_item(recurrence, work_item_id)
    source_review = _as_dict(item.get("source_correlation_review"))
    target_id = (
        str(
            source_review.get("target_incident_id")
            or work_item.get("matched_incident_id")
            or ""
        ).strip()
        or None
    )
    checks = _source_correlation_apply_checks(
        item,
        work_item,
        source_review,
        target_incident_id=target_id,
    )
    allowed = all(check["passed"] for check in checks)
    raw_event_id = _provider_raw_event_id(item.get("latest_provider_event_id"))
    provider = str(item.get("provider") or "external").strip().lower() or "external"
    source_event_provider_event_id = (
        f"{provider}:{_SOURCE_CORRELATION_APPLY_STAGE}:{raw_event_id[:96]}"
    )

    payload = {
        "schema_version": _SOURCE_CORRELATION_APPLY_SCHEMA_VERSION,
        "source": "channel_event_dossier.recurrence",
        "project_id": recurrence.get("project_id"),
        "work_item_id": work_item.get("work_item_id"),
        "review_id": source_review.get("review_id"),
        "target_incident_id": target_id,
        "reviewer_id": str(reviewer_id or "operator_console")[:100],
        "operator_note": str(operator_note or "").strip()[:500] or None,
        "allowed": allowed,
        "executed": allowed,
        "apply_status": "ready_to_apply" if allowed else "blocked",
        "safety_level": "source_review_append_only_apply",
        "writes_incident_state": False,
        "writes_source_event": allowed,
        "writes_auto_repair_result": False,
        "writes_ticket": False,
        "creates_external_ticket": False,
        "latest_provider_event_id": item.get("latest_provider_event_id"),
        "source_event_provider_event_id": source_event_provider_event_id,
        "source_event_stage": _SOURCE_CORRELATION_APPLY_STAGE,
        "raw_event_id": raw_event_id,
        "provider": provider,
        "alertname": item.get("alertname"),
        "severity": item.get("severity"),
        "namespace": item.get("namespace"),
        "target_resource": item.get("target_resource"),
        "fingerprint": item.get("fingerprint"),
        "checks": checks,
        "current_state_summary": _recurrence_current_state_summary(item, work_item),
        "plan": {
            "step": "append_source_correlation_link_event",
            "flywheel_node": "source_correlation_apply",
            "agent_id": "awooop_source_correlation_reviewer",
            "required_scope": "append_source_link",
            "writes": (
                ["awooop_conversation_event", "timeline_events", "alert_operation_log"]
                if allowed
                else []
            ),
            "target_action": "verify_source_link_in_status_chain",
            "reason": (
                "provider_native_evidence_link_applied"
                if allowed
                else "source_correlation_apply_preflight_failed"
            ),
            "target": _recurrence_work_item_target(item),
        },
        "read_model_route": {
            "agent_id": "awooop_source_correlation_reviewer",
            "tool_name": "channel_event_dossier.recurrence",
            "required_scope": "append_source_link",
            "is_shadow": False,
            "flywheel_node": "source_correlation_apply",
        },
        "next_step": (
            "verify_source_link_in_status_chain"
            if allowed
            else "fix_preflight_checks"
        ),
    }
    if not allowed:
        payload["executed"] = False
    return payload


async def _record_source_correlation_apply_history(
    payload: dict[str, Any],
) -> dict[str, Any]:
    if not payload.get("allowed"):
        return {"recorded": False, "reason": "preflight_failed"}

    history: dict[str, Any] = {
        "recorded": False,
        "source_event_id": None,
        "alert_operation_id": None,
        "timeline_event_id": None,
    }
    incident_id = str(payload.get("target_incident_id") or "")

    try:
        from src.services.channel_hub import record_external_alert_event

        event_id = await record_external_alert_event(
            project_id=str(payload.get("project_id") or "awoooi"),
            provider=str(payload.get("provider") or "external"),
            event_id=str(payload.get("raw_event_id") or payload.get("work_item_id")),
            stage=_SOURCE_CORRELATION_APPLY_STAGE,
            title=str(payload.get("alertname") or "Source correlation link"),
            severity=str(payload.get("severity") or "info"),
            namespace=payload.get("namespace"),
            target_resource=payload.get("target_resource"),
            fingerprint=payload.get("fingerprint"),
            incident_id=incident_id,
            source_url=None,
            labels={
                "awooop_source_correlation": "applied",
                "work_item_id": payload.get("work_item_id"),
            },
            annotations={
                "review_id": payload.get("review_id") or "",
                "original_provider_event_id": payload.get("latest_provider_event_id")
                or "",
            },
            payload={
                "schema_version": _SOURCE_CORRELATION_APPLY_SCHEMA_VERSION,
                "work_item_id": payload.get("work_item_id"),
                "review_id": payload.get("review_id"),
                "target_incident_id": incident_id,
            },
            is_duplicate=False,
        )
        if event_id:
            history["source_event_id"] = str(event_id)
    except Exception as exc:
        logger.warning(
            "awooop_source_correlation_apply_source_event_failed",
            work_item_id=payload.get("work_item_id"),
            incident_id=incident_id,
            error=str(exc),
        )

    context = _source_correlation_apply_context({**payload, "history": history})
    try:
        from src.services.approval_db import get_timeline_service

        event = await get_timeline_service().add_event(
            event_type="human",
            status="success" if history.get("source_event_id") else "warning",
            title="AwoooP source correlation apply",
            description=_source_correlation_apply_description(context),
            actor=_SOURCE_CORRELATION_APPLY_ACTOR,
            actor_role="source_correlation_apply",
            incident_id=incident_id,
        )
        if event:
            history["timeline_event_id"] = event.get("id")
    except Exception as exc:
        logger.warning(
            "awooop_source_correlation_apply_timeline_failed",
            incident_id=incident_id,
            work_item_id=payload.get("work_item_id"),
            error=str(exc),
        )

    try:
        from src.repositories.alert_operation_log_repository import (
            get_alert_operation_log_repository,
        )

        final_context = _source_correlation_apply_context({
            **payload,
            "apply_status": "applied" if history.get("source_event_id") else "partial",
            "history": history,
        })
        record = await get_alert_operation_log_repository().append(
            "USER_ACTION",
            incident_id=incident_id,
            actor=_SOURCE_CORRELATION_APPLY_ACTOR,
            action_detail="source_correlation_apply:append_source_link",
            success=bool(history.get("source_event_id")),
            context=_json_safe(final_context),
        )
        if record is not None:
            history["alert_operation_id"] = getattr(record, "id", None)
    except Exception as exc:
        logger.warning(
            "awooop_source_correlation_apply_alert_operation_failed",
            work_item_id=payload.get("work_item_id"),
            error=str(exc),
        )

    history["recorded"] = bool(
        history.get("source_event_id")
        or history.get("alert_operation_id")
        or history.get("timeline_event_id")
    )
    if not history["recorded"]:
        history["reason"] = "history_sink_unavailable"
    return history


def build_dossier_coverage(
    rows: list[dict[str, Any]],
    *,
    project_id: str,
    limit: int,
) -> dict[str, Any]:
    """Summarize recent inbound source envelopes for console coverage checks."""
    events = [build_dossier_event(row) for row in rows]
    provider_map: dict[str, dict[str, Any]] = {}
    source_envelope_total = 0
    with_source_refs_total = 0
    sentry_ref_total = 0
    signoz_ref_total = 0
    alert_ref_total = 0

    for row, event in zip(rows, events, strict=False):
        envelope = _as_dict(row.get("source_envelope"))
        if envelope:
            source_envelope_total += 1

        source_refs = _as_dict(event.get("source_refs"))
        source_ref_count = int(event.get("source_ref_count") or 0)
        if source_ref_count > 0:
            with_source_refs_total += 1

        provider = str(event.get("provider") or row.get("channel_type") or "unknown")
        provider_item = provider_map.setdefault(
            provider,
            {
                "provider": provider,
                "total": 0,
                "duplicate_total": 0,
                "redacted_total": 0,
                "source_ref_total": 0,
                "missing_source_refs_total": 0,
                "sentry_ref_total": 0,
                "signoz_ref_total": 0,
                "alert_ref_total": 0,
                "latest_received_at": None,
            },
        )
        provider_item["total"] += 1
        provider_item["source_ref_total"] += source_ref_count
        if event.get("is_duplicate"):
            provider_item["duplicate_total"] += 1
        if event.get("has_redacted_content"):
            provider_item["redacted_total"] += 1
        if source_ref_count <= 0:
            provider_item["missing_source_refs_total"] += 1

        event_sentry_refs = _ref_count(source_refs, "sentry_issue_ids")
        event_signoz_refs = _ref_count(source_refs, "signoz_alerts")
        event_alert_refs = _ref_count(source_refs, "alert_ids")
        sentry_ref_total += event_sentry_refs
        signoz_ref_total += event_signoz_refs
        alert_ref_total += event_alert_refs
        provider_item["sentry_ref_total"] += event_sentry_refs
        provider_item["signoz_ref_total"] += event_signoz_refs
        provider_item["alert_ref_total"] += event_alert_refs
        provider_item["latest_received_at"] = provider_item[
            "latest_received_at"
        ] or event.get("received_at")

    duplicate_total = sum(1 for event in events if event.get("is_duplicate"))
    redacted_total = sum(1 for event in events if event.get("has_redacted_content"))
    source_ref_total = sum(int(event.get("source_ref_count") or 0) for event in events)
    missing_source_refs_total = len(events) - with_source_refs_total
    missing_source_envelope_total = len(events) - source_envelope_total

    return {
        "project_id": project_id,
        "limit": limit,
        "summary": {
            "source_count": len(events),
            "source_envelope_total": source_envelope_total,
            "missing_source_envelope_total": missing_source_envelope_total,
            "with_source_refs_total": with_source_refs_total,
            "missing_source_refs_total": missing_source_refs_total,
            "duplicate_total": duplicate_total,
            "redacted_total": redacted_total,
            "source_ref_total": source_ref_total,
            "sentry_ref_total": sentry_ref_total,
            "signoz_ref_total": signoz_ref_total,
            "alert_ref_total": alert_ref_total,
            "latest_received_at": events[0].get("received_at") if events else None,
        },
        "providers": sorted(
            provider_map.values(),
            key=lambda item: (
                -int(item.get("total") or 0),
                str(item.get("provider") or ""),
            ),
        ),
    }


def build_dossier_event(row: dict[str, Any]) -> dict[str, Any]:
    """Normalize a DB row into the front-end event dossier shape."""
    envelope = _as_dict(row.get("source_envelope"))
    source_refs = _as_dict(envelope.get("source_refs"))
    log_correlation = _as_dict(envelope.get("log_correlation"))
    content_redacted = row.get("content_redacted")
    content_preview = row.get("content_preview")

    return {
        "event_id": row.get("event_id"),
        "project_id": row.get("project_id"),
        "channel_type": row.get("channel_type"),
        "provider": envelope.get("provider") or row.get("channel_type"),
        "stage": envelope.get("stage") or "received",
        "provider_event_id": row.get("provider_event_id"),
        "content_preview": content_preview,
        "content_redacted": content_redacted,
        "has_redacted_content": bool(content_redacted),
        "redaction_version": row.get("redaction_version"),
        "source_url": envelope.get("source_url"),
        "content_sha256": envelope.get("content_sha256") or row.get("content_hash"),
        "content_length": envelope.get("content_length"),
        "source_refs": source_refs,
        "source_ref_count": _compact_ref_count(source_refs),
        "log_correlation": log_correlation,
        "alertname": log_correlation.get("alertname"),
        "severity": log_correlation.get("severity"),
        "namespace": log_correlation.get("namespace"),
        "target_resource": log_correlation.get("target_resource"),
        "fingerprint": log_correlation.get("fingerprint"),
        "is_duplicate": row.get("is_duplicate"),
        "provider_ts": row.get("provider_ts"),
        "received_at": row.get("received_at"),
    }


def _collect_incident_ids_from_rows(rows: list[dict[str, Any]]) -> list[str]:
    incident_ids: list[str] = []
    for row in rows:
        event = build_dossier_event(row)
        for incident_id in _event_incident_ids(event):
            _append_unique(incident_ids, incident_id)
    return incident_ids


async def _fetch_auto_repair_summaries_by_incident(
    db: Any,
    incident_ids: list[str],
) -> dict[str, dict[str, Any]]:
    """Fetch latest auto-repair and verifier evidence for recurrence groups."""
    visible_incident_ids = incident_ids[:_MAX_REPAIR_INCIDENTS]
    if not visible_incident_ids:
        return {}

    placeholders: list[str] = []
    params: dict[str, Any] = {}
    for index, incident_id in enumerate(visible_incident_ids):
        key = f"incident_id_{index}"
        placeholders.append(f":{key}")
        params[key] = incident_id

    result = await db.execute(
        text(
            f"""
            WITH ranked AS (
                SELECT
                    are.id AS latest_auto_repair_id,
                    are.incident_id,
                    are.playbook_id AS latest_playbook_id,
                    are.playbook_name AS latest_playbook_name,
                    are.success AS latest_success,
                    left(coalesce(are.error_message, ''), 240) AS latest_error_message_preview,
                    are.triggered_by AS latest_triggered_by,
                    are.risk_level AS latest_risk_level,
                    are.execution_time_ms AS latest_execution_time_ms,
                    are.created_at AS latest_auto_repair_at,
                    latest_evidence.verification_result AS latest_verification_result,
                    latest_evidence.collected_at AS latest_verification_at,
                    COUNT(*) OVER (PARTITION BY are.incident_id) AS auto_repair_total,
                    COUNT(*) FILTER (WHERE are.success IS TRUE)
                        OVER (PARTITION BY are.incident_id) AS success_total,
                    COUNT(*) FILTER (WHERE are.success IS FALSE)
                        OVER (PARTITION BY are.incident_id) AS failed_total,
                    ROW_NUMBER() OVER (
                        PARTITION BY are.incident_id
                        ORDER BY are.created_at DESC
                    ) AS rn
                FROM auto_repair_executions are
                LEFT JOIN LATERAL (
                    SELECT
                        ev.verification_result,
                        ev.collected_at
                    FROM incident_evidence ev
                    WHERE ev.incident_id = are.incident_id
                      AND ev.verification_result IS NOT NULL
                    ORDER BY ev.collected_at DESC
                    LIMIT 1
                ) latest_evidence ON TRUE
                WHERE are.incident_id IN ({", ".join(placeholders)})
            )
            SELECT
                latest_auto_repair_id,
                incident_id,
                latest_playbook_id,
                latest_playbook_name,
                latest_success,
                latest_error_message_preview,
                latest_triggered_by,
                latest_risk_level,
                latest_execution_time_ms,
                latest_auto_repair_at,
                latest_verification_result,
                latest_verification_at,
                auto_repair_total,
                success_total,
                failed_total
            FROM ranked
            WHERE rn = 1
        """
        ),
        params,
    )

    summaries: dict[str, dict[str, Any]] = {}
    for row in result.mappings().all():
        item = dict(row)
        incident_id = str(item.get("incident_id") or "")
        if not incident_id:
            continue
        item["schema_version"] = "awooop_recurrence_repair_summary_v1"
        summaries[incident_id] = item
    return summaries


async def _fetch_source_review_decisions_by_work_item(
    db: Any,
    *,
    project_id: str,
    limit: int,
) -> dict[str, dict[str, Any]]:
    """Fetch latest source-correlation review decisions from event-sourced audit."""

    result = await db.execute(
        text("""
            SELECT DISTINCT ON (context->>'work_item_id')
                id,
                incident_id,
                actor,
                action_detail,
                success,
                context,
                created_at
            FROM alert_operation_log
            WHERE actor = :actor
              AND context->>'schema_version' = :schema_version
              AND COALESCE(context->>'project_id', :project_id) = :project_id
            ORDER BY context->>'work_item_id', created_at DESC
            LIMIT :limit
        """),
        {
            "actor": _SOURCE_CORRELATION_REVIEW_ACTOR,
            "schema_version": _SOURCE_CORRELATION_DECISION_SCHEMA_VERSION,
            "project_id": project_id,
            "limit": max(1, min(limit, _MAX_RECURRENCE_EVENTS)),
        },
    )

    decisions: dict[str, dict[str, Any]] = {}
    for row in result.mappings().all():
        item = _normalize_source_review_decision(dict(row))
        if not item:
            continue
        decisions[str(item["work_item_id"])] = item
    return decisions


async def _fetch_source_applies_by_work_item(
    db: Any,
    *,
    project_id: str,
    limit: int,
) -> dict[str, dict[str, Any]]:
    """Fetch latest source-correlation apply records from event-sourced audit."""

    result = await db.execute(
        text("""
            SELECT DISTINCT ON (context->>'work_item_id')
                id,
                incident_id,
                actor,
                action_detail,
                success,
                context,
                created_at
            FROM alert_operation_log
            WHERE actor = :actor
              AND context->>'schema_version' = :schema_version
              AND COALESCE(context->>'project_id', :project_id) = :project_id
            ORDER BY context->>'work_item_id', created_at DESC
            LIMIT :limit
        """),
        {
            "actor": _SOURCE_CORRELATION_APPLY_ACTOR,
            "schema_version": _SOURCE_CORRELATION_APPLY_SCHEMA_VERSION,
            "project_id": project_id,
            "limit": max(1, min(limit, _MAX_RECURRENCE_EVENTS)),
        },
    )

    applies: dict[str, dict[str, Any]] = {}
    for row in result.mappings().all():
        item = _normalize_source_apply(dict(row))
        if not item:
            continue
        applies[str(item["work_item_id"])] = item
    return applies


async def fetch_channel_event_dossier(
    *,
    project_id: str | None,
    run_id: UUID | None,
    provider_event_id: str | None,
    limit: int,
) -> dict[str, Any]:
    """Fetch redacted source envelopes for a run or provider event id."""
    if run_id is None and not provider_event_id:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
            detail="run_id or provider_event_id is required",
        )

    effective_project_id = project_id or "awoooi"
    safe_limit = max(1, min(limit, _MAX_DOSSIER_EVENTS))
    where_clauses = ["project_id = :project_id"]
    params: dict[str, Any] = {
        "project_id": effective_project_id,
        "limit": safe_limit,
    }
    if run_id is not None:
        where_clauses.append("run_id = CAST(:run_id AS uuid)")
        params["run_id"] = str(run_id)
    if provider_event_id:
        where_clauses.append("provider_event_id = :provider_event_id")
        params["provider_event_id"] = provider_event_id

    async with get_db_context(effective_project_id) as db:
        result = await db.execute(
            text(
                f"""
                SELECT
                    event_id,
                    project_id,
                    channel_type,
                    provider_event_id,
                    content_hash,
                    content_preview,
                    content_redacted,
                    redaction_version,
                    source_envelope,
                    is_duplicate,
                    provider_ts,
                    received_at
                FROM awooop_conversation_event
                WHERE {" AND ".join(where_clauses)}
                ORDER BY received_at ASC
                LIMIT :limit
            """
            ),
            params,
        )
        rows = [dict(row) for row in result.mappings().all()]

    events = [build_dossier_event(row) for row in rows]
    duplicate_total = sum(1 for event in events if event.get("is_duplicate"))
    redacted_total = sum(1 for event in events if event.get("has_redacted_content"))

    return {
        "events": events,
        "total": len(events),
        "limit": safe_limit,
        "summary": {
            "source_count": len(events),
            "duplicate_total": duplicate_total,
            "redacted_total": redacted_total,
            "source_ref_total": sum(
                int(event.get("source_ref_count") or 0) for event in events
            ),
        },
    }


async def fetch_channel_event_dossier_coverage(
    *,
    project_id: str | None,
    provider: str | None,
    limit: int,
) -> dict[str, Any]:
    """Fetch a read-only coverage summary for recent inbound channel events."""
    effective_project_id = project_id or "awoooi"
    safe_limit = max(1, min(limit, _MAX_COVERAGE_EVENTS))
    where_clauses = ["project_id = :project_id"]
    params: dict[str, Any] = {
        "project_id": effective_project_id,
        "limit": safe_limit,
    }
    if provider:
        where_clauses.append(
            "COALESCE(NULLIF(source_envelope->>'provider', ''), "
            "split_part(provider_event_id, ':', 1), channel_type) = :provider"
        )
        params["provider"] = provider

    async with get_db_context(effective_project_id) as db:
        result = await db.execute(
            text(
                f"""
                SELECT
                    event_id,
                    project_id,
                    channel_type,
                    provider_event_id,
                    content_hash,
                    content_preview,
                    content_redacted,
                    redaction_version,
                    source_envelope,
                    is_duplicate,
                    provider_ts,
                    received_at
                FROM awooop_conversation_event
                WHERE {" AND ".join(where_clauses)}
                ORDER BY received_at DESC
                LIMIT :limit
            """
            ),
            params,
        )
        rows = [dict(row) for row in result.mappings().all()]

    return build_dossier_coverage(
        rows,
        project_id=effective_project_id,
        limit=safe_limit,
    )


async def fetch_channel_event_dossier_recurrence(
    *,
    project_id: str | None,
    provider: str | None,
    limit: int,
) -> dict[str, Any]:
    """Fetch recurrence groups and linked run state for recent source events."""
    effective_project_id = project_id or "awoooi"
    safe_limit = max(1, min(limit, _MAX_RECURRENCE_EVENTS))
    where_clauses = ["e.project_id = :project_id"]
    params: dict[str, Any] = {
        "project_id": effective_project_id,
        "limit": safe_limit,
    }
    if provider:
        where_clauses.append(
            "COALESCE(NULLIF(e.source_envelope->>'provider', ''), "
            "split_part(e.provider_event_id, ':', 1), e.channel_type) = :provider"
        )
        params["provider"] = provider

    async with get_db_context(effective_project_id) as db:
        result = await db.execute(
            text(
                f"""
                SELECT
                    e.event_id,
                    e.project_id,
                    e.channel_type,
                    e.provider_event_id,
                    e.content_hash,
                    e.content_preview,
                    e.content_redacted,
                    e.redaction_version,
                    e.source_envelope,
                    e.is_duplicate,
                    e.provider_ts,
                    e.received_at,
                    e.run_id,
                    r.state AS run_state,
                    r.agent_id AS run_agent_id
                FROM awooop_conversation_event e
                LEFT JOIN awooop_run_state r
                  ON r.project_id = e.project_id
                 AND r.run_id = e.run_id
                WHERE {" AND ".join(where_clauses)}
                ORDER BY e.received_at DESC
                LIMIT :limit
            """
            ),
            params,
        )
        rows = [dict(row) for row in result.mappings().all()]
        repair_summaries = await _fetch_auto_repair_summaries_by_incident(
            db,
            _collect_incident_ids_from_rows(rows),
        )
        source_review_decisions = await _fetch_source_review_decisions_by_work_item(
            db,
            project_id=effective_project_id,
            limit=safe_limit,
        )
        source_applies = await _fetch_source_applies_by_work_item(
            db,
            project_id=effective_project_id,
            limit=safe_limit,
        )

    return build_dossier_recurrence(
        rows,
        project_id=effective_project_id,
        limit=safe_limit,
        repair_summaries_by_incident=repair_summaries,
        source_review_decisions_by_work_item=source_review_decisions,
        source_applies_by_work_item=source_applies,
    )


async def fetch_recurrence_work_item_preview(
    *,
    project_id: str | None,
    work_item_id: str,
    mode: RecurrenceWorkItemMode = "auto",
    provider: str | None = None,
    limit: int = _MAX_RECURRENCE_EVENTS,
) -> dict[str, Any]:
    """Fetch a read-only preview for a recurrence work item."""

    recurrence = await fetch_channel_event_dossier_recurrence(
        project_id=project_id,
        provider=provider,
        limit=limit,
    )
    return build_recurrence_work_item_preview(
        recurrence,
        work_item_id=work_item_id,
        mode=mode,
    )


async def fetch_recurrence_work_item_dry_run(
    *,
    project_id: str | None,
    work_item_id: str,
    mode: RecurrenceWorkItemMode = "auto",
    provider: str | None = None,
    limit: int = _MAX_RECURRENCE_EVENTS,
) -> dict[str, Any]:
    """Fetch and record a safe read-only dry-run for a recurrence work item."""

    recurrence = await fetch_channel_event_dossier_recurrence(
        project_id=project_id,
        provider=provider,
        limit=limit,
    )
    payload = build_recurrence_work_item_dry_run(
        recurrence,
        work_item_id=work_item_id,
        mode=mode,
    )
    payload["history"] = await _record_recurrence_work_item_dry_run_history(payload)
    return payload


async def fetch_recurrence_work_item_handoff(
    *,
    project_id: str | None,
    work_item_id: str,
    mode: RecurrenceWorkItemMode = "auto",
    handoff_kind: RecurrenceWorkItemHandoffKind = "ticket_proposal",
    provider: str | None = None,
    limit: int = _MAX_RECURRENCE_EVENTS,
) -> dict[str, Any]:
    """Fetch and record a safe handoff proposal for a recurrence work item."""

    recurrence = await fetch_channel_event_dossier_recurrence(
        project_id=project_id,
        provider=provider,
        limit=limit,
    )
    payload = build_recurrence_work_item_handoff(
        recurrence,
        work_item_id=work_item_id,
        mode=mode,
        handoff_kind=handoff_kind,
    )
    payload["history"] = await _record_recurrence_work_item_handoff_history(payload)
    if payload["history"].get("recorded"):
        payload["handoff_status"] = "recorded"
    elif payload.get("allowed"):
        payload["handoff_status"] = "record_failed"
    return payload


async def fetch_source_correlation_review_decision(
    *,
    project_id: str | None,
    work_item_id: str,
    decision: SourceCorrelationReviewDecision,
    target_incident_id: str | None = None,
    reviewer_id: str = "operator_console",
    operator_note: str | None = None,
    provider: str | None = None,
    limit: int = _MAX_RECURRENCE_EVENTS,
) -> dict[str, Any]:
    """Fetch recurrence state and record an explicit source review decision."""

    recurrence = await fetch_channel_event_dossier_recurrence(
        project_id=project_id,
        provider=provider,
        limit=limit,
    )
    payload = build_source_correlation_review_decision(
        recurrence,
        work_item_id=work_item_id,
        decision=decision,
        target_incident_id=target_incident_id,
        reviewer_id=reviewer_id,
        operator_note=operator_note,
    )
    payload["history"] = await _record_source_correlation_review_decision_history(
        payload
    )
    if payload["history"].get("recorded"):
        payload["review_record_status"] = "recorded"
    elif payload.get("allowed"):
        payload["review_record_status"] = "record_failed"
    else:
        payload["review_record_status"] = "blocked"
    return payload


async def fetch_source_correlation_apply(
    *,
    project_id: str | None,
    work_item_id: str,
    reviewer_id: str = "operator_console",
    operator_note: str | None = None,
    provider: str | None = None,
    limit: int = _MAX_RECURRENCE_EVENTS,
) -> dict[str, Any]:
    """Fetch recurrence state and append an accepted source review link event."""

    recurrence = await fetch_channel_event_dossier_recurrence(
        project_id=project_id,
        provider=provider,
        limit=limit,
    )
    payload = build_source_correlation_apply(
        recurrence,
        work_item_id=work_item_id,
        reviewer_id=reviewer_id,
        operator_note=operator_note,
    )
    payload["history"] = await _record_source_correlation_apply_history(payload)
    if payload["history"].get("source_event_id"):
        payload["apply_status"] = "applied"
    elif payload["history"].get("recorded") and payload.get("allowed"):
        payload["apply_status"] = "partial"
    elif payload.get("allowed"):
        payload["apply_status"] = "record_failed"
    else:
        payload["apply_status"] = "blocked"
    return payload
