Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion scripts/ci/pr_review_merge_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@
}
REST_MERGEABLE_STATES = set(REST_MERGEABLE_STATE_MAP.values())
REST_MERGEABLE_STATE_WORKERS = 10
DETERMINISTIC_APPROVAL_MARKERS = (
"deterministic current-head evidence",
"deterministic fallback approval",
"did not emit a usable current-head control block",
)


@dataclass
Expand Down Expand Up @@ -955,14 +960,25 @@ def is_opencode_review(review: dict[str, Any]) -> bool:
return review_author_login(review) in {"opencode-agent", "opencode-agent[bot]"}


def is_deterministic_fallback_approval(review: dict[str, Any]) -> bool:
"""Return whether an old fail-open approval body is not review evidence."""
if (review.get("state") or "").upper() != "APPROVED":
return False
body = (review.get("body") or "").lower()
return any(marker in body for marker in DETERMINISTIC_APPROVAL_MARKERS)


def current_head_review_state(pr: dict[str, Any], state: str) -> bool:
"""Return whether OpenCode's latest current-head review has the target state."""
target_state = state.upper()
for review in reversed((pr.get("reviews") or {}).get("nodes") or []):
if not is_opencode_review(review):
continue
if not review_matches_current_head(review, pr):
continue
return (review.get("state") or "").upper() == state
if target_state == "APPROVED" and is_deterministic_fallback_approval(review):
return False
return (review.get("state") or "").upper() == target_state
return False


Expand Down
22 changes: 22 additions & 0 deletions tests/test_pr_review_merge_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,28 @@ def test_review_state_and_failed_checks():
},
)
assert sched.has_current_head_approval(body_sha_match)
deterministic_fallback = make_pr(
headRefOid=exact_head,
reviews={
"nodes": [
{
**opencode_review("APPROVED", exact_head),
"body": (
"OpenCode model attempts did not emit a usable current-head "
"control block, so the approval gate used deterministic "
"current-head evidence instead of model prose."
),
}
]
},
)
assert sched.is_deterministic_fallback_approval(
deterministic_fallback["reviews"]["nodes"][0]
)
assert not sched.is_deterministic_fallback_approval(
opencode_review("CHANGES_REQUESTED", exact_head)
)
assert not sched.has_current_head_approval(deterministic_fallback)
stale_review = make_pr(
reviews={
"nodes": [
Expand Down
Loading