"""Merge approval must pin the current PR head SHA (#471 / #695). Formal APPROVED reviews that predate the live PR head must not satisfy ``gitea_merge_pr`` eligibility. Contaminated / quarantined approvals (#695) must not authorize merge either. Pure assessment helpers are isolated here for hermetic unit tests apart from MCP HTTP calls. """ from __future__ import annotations def assess_merge_approval_head( *, current_head_sha: str | None, latest_by_reviewer: dict, quarantined_review_ids: set | None = None, ) -> dict: """Return whether a visible approval applies to the live PR head. Args: current_head_sha: Current PR head commit SHA. latest_by_reviewer: Map of reviewer login → review entry dicts with ``verdict``, ``dismissed``, and ``reviewed_head_sha`` keys. Optional ``review_id`` / ``id`` used for quarantine checks (#695). quarantined_review_ids: Optional set of review IDs that must not count toward merge authorization (#695). Returns: dict with ``approval_at_current_head``, ``latest_approved_head_sha``, and ``stale_approval_block_reason`` (set when merge must fail closed). """ current = (current_head_sha or "").strip() blocked_ids = {int(x) for x in (quarantined_review_ids or set()) if x is not None} def _rid(entry: dict): raw = entry.get("review_id", entry.get("id")) try: return int(raw) if raw is not None else None except (TypeError, ValueError): return None approved_entries = [] quarantined_at_head = [] for entry in (latest_by_reviewer or {}).values(): if (entry.get("verdict") or "").upper() != "APPROVED": continue if entry.get("dismissed"): continue rid = _rid(entry) head = (entry.get("reviewed_head_sha") or "").strip() if rid is not None and rid in blocked_ids: if current and head == current: quarantined_at_head.append(entry) continue if entry.get("quarantined"): if current and head == current: quarantined_at_head.append(entry) continue approved_entries.append(entry) at_current = any( (entry.get("reviewed_head_sha") or "").strip() == current for entry in approved_entries if current ) latest_approved = None if approved_entries: latest_entry = sorted( approved_entries, key=lambda entry: ( entry.get("submitted_at") or "", entry.get("reviewed_head_sha") or "", ), )[-1] latest_approved = (latest_entry.get("reviewed_head_sha") or "").strip() or None reason = None if quarantined_at_head and not at_current: reason = ( "contaminated/quarantined approval at current head is void for " "merge authorization (#695); required next action: fresh native " "MCP re-review after controller quarantine evidence is recorded" ) elif approved_entries and not at_current: reason = ( f"stale approval: approved SHA '{latest_approved}' does not match " f"current live PR head SHA '{current or '(unknown)'}' (fail closed); " "required next action: re-review PR at current head before merge" ) return { "approval_at_current_head": at_current, "latest_approved_head_sha": latest_approved, "stale_approval_block_reason": reason, "quarantined_approvals_at_current_head": len(quarantined_at_head), }