"""Merge approval must pin the current PR head SHA (#471). Formal APPROVED reviews that predate the live PR head must not satisfy ``gitea_merge_pr`` eligibility. 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, ) -> 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. 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() approved_entries = [ entry for entry in (latest_by_reviewer or {}).values() if (entry.get("verdict") or "").upper() == "APPROVED" and not entry.get("dismissed") ] 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 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, }