Context
During the #13584 merge-gate discussion on 2026-06-20, the live PR state exposed a merge-readiness false positive:
gh pr view 13584 returned reviewDecision=APPROVED, mergeStateStatus=CLEAN, and all checks green.
- The same live response still contained
reviewRequests: [neo-opus-grace].
- A second peer (
neo-opus-ada) had sent an A2A approval, but had not posted a formal GitHub review state.
Tobi's operator judgment was the stricter and substrate-correct rule: if an author assigns two reviewers, the merge is blocked until both requested reviewers approve, request changes, explicitly step out, or are unrequested. A flattened GitHub reviewDecision=APPROVED is not enough when an explicit reviewer request remains active.
Live latest-open sweep: checked the latest 20 open issues at 2026-06-20T03:25Z; no equivalent reviewer-request merge-gate ticket found. Closest adjacent tickets were unrelated Agent OS stability lanes (#13586, #13575, #13498, #13496, #13480). A2A in-flight sweep: checked latest 30 all-status messages at 2026-06-20T03:25Z; no overlapping [lane-claim] / [lane-intent] for this reviewer-contract gap found. Knowledge Base sweep surfaced adjacent cross-family review mandate and manage_pr_reviewers invitation-layer substrate, but no rule tying outstanding reviewRequests to merge-readiness.
Release classification: post-release / Agent OS process hardening. This is merge-gate correctness, but the immediate #13584 case is handled by targeted A2A to Grace; the general rule can land boardless unless the operator explicitly promotes it.
The Problem
Neo's PR lifecycle has multiple review signals:
reviewDecision tells whether GitHub has enough formal review state to consider the PR approved.
reviewRequests tells who the author/operator explicitly asked to review.
- A2A review messages provide useful peer signal, but they do not clear GitHub's requested-reviewer contract unless paired with a formal PR review or an explicit step-out / unrequest action.
Today an agent can honestly report "approved + clean" from reviewDecision=APPROVED while a requested reviewer is still outstanding. That is exactly the class of stale merge-ready signal the review process is supposed to prevent: the human merge gate sees a green surface, but the author-declared reviewer contract is not fully disposed.
The Architectural Reality
Relevant substrate already exists:
.agents/skills/pr-review/references/pr-review-guide.md requires live PR-state freshness before relaying review or merge-eligibility claims, and warns to relay the review body's verdict rather than flattened enums.
.agents/skills/post-review-pickup/references/post-review-pickup-workflow.md requires live PR state before lane-state declarations that name PR status.
ai/services/github-workflow/PullRequestService.mjs and ai/mcp/server/github-workflow/openapi.yaml expose manage_pr_reviewers as the invitation layer for GitHub reviewer requests.
reviewDecision remains necessary for formal approval, but it is not sufficient when reviewRequests is non-empty.
The missing rule is the merge-readiness contract:
A PR with outstanding requested reviewers is not strict-merge-ready, even if reviewDecision=APPROVED, unless each outstanding request is explicitly disposed by approval, request-changes, comment-step-out, or author/operator unrequest.
The Fix
Add a narrow merge-readiness guard wherever agents report or lint "eligible for human merge":
- Fetch
reviewRequests alongside reviewDecision, mergeStateStatus, checks, and head SHA in PR-state freshness checks.
- Treat non-empty
reviewRequests as a merge-gate blocker unless the body explicitly documents a disposal path:
- requested reviewer posted formal
APPROVED;
- requested reviewer posted formal
CHANGES_REQUESTED;
- requested reviewer posted a visible "stepping out / no review needed from me" comment;
- author/operator removed the review request via
manage_pr_reviewers(action: 'remove').
- Update review / PR / post-review-pickup guidance so agents do not claim strict merge-ready from
reviewDecision=APPROVED alone.
- If a mechanical lint exists for review or PR-body merge-ready language, extend it to catch the false-positive pattern when
reviewRequests is non-empty.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| PR merge-readiness claim |
GitHub PR reviewDecision, reviewRequests, checks, and head SHA |
Require reviewDecision=APPROVED, green checks, and empty/disposed reviewRequests before claiming strict merge-ready |
If requests remain, state "approved/clean, but strict gate waits on requested reviewer(s)" |
pr-review / pull-request / post-review-pickup guidance |
#13584 live state: reviewDecision=APPROVED plus reviewRequests=[neo-opus-grace] |
| Reviewer invitation lifecycle |
manage_pr_reviewers and GitHub requested-reviewers API |
Outstanding requested reviewers are explicit author/operator contract, not advisory noise |
Author/operator may remove stale requests explicitly |
GitHub Workflow MCP docs / PR workflow docs |
manage_pr_reviewers is already documented as invitation layer |
| A2A review signal |
Memory Core A2A messages |
A2A approval can inform author response, but does not clear a GitHub requested-reviewer slot by itself |
Ask the peer to post formal review or step-out, or remove request |
A2A handoff guidance |
#13584 Ada A2A approval did not remove Grace's outstanding GitHub request |
Decision Record impact
none. This clarifies merge-readiness process semantics using existing GitHub review primitives; it does not change human-only merge authority.
Acceptance Criteria
Out of Scope
- Changing GitHub branch protection.
- Requiring more than one reviewer when only one reviewer was requested.
- Treating all A2A review signals as invalid; A2A remains useful context, but formal requested-reviewer slots need explicit disposition.
- Any agent execution of
gh pr merge; human-only merge authority remains unchanged.
Avoided Traps
- Do not collapse "cross-family approval exists" into "every requested reviewer has dispositioned".
- Do not rely on GitHub's flattened
reviewDecision as the only merge-gate signal.
- Do not silently ignore stale reviewer requests; either remove them explicitly or report them as the remaining strict gate.
Related
Related: #13584
Related: #10214
Related: #11273
Origin Session ID
Origin Session ID: current @neo-gpt Codex Desktop session, 2026-06-20.
Handoff Retrieval Hints
query_raw_memories: 13584 reviewDecision APPROVED reviewRequests neo-opus-grace strict merge gate
query_raw_memories: requested reviewers block merge readiness flattened reviewDecision approved
- Exact PR-state anchor: #13584 at
6f755137595cca6770836428e5f86c3c7b2222fd returned reviewDecision=APPROVED and reviewRequests=[neo-opus-grace].
Context
During the #13584 merge-gate discussion on 2026-06-20, the live PR state exposed a merge-readiness false positive:
gh pr view 13584returnedreviewDecision=APPROVED,mergeStateStatus=CLEAN, and all checks green.reviewRequests: [neo-opus-grace].neo-opus-ada) had sent an A2A approval, but had not posted a formal GitHub review state.Tobi's operator judgment was the stricter and substrate-correct rule: if an author assigns two reviewers, the merge is blocked until both requested reviewers approve, request changes, explicitly step out, or are unrequested. A flattened GitHub
reviewDecision=APPROVEDis not enough when an explicit reviewer request remains active.Live latest-open sweep: checked the latest 20 open issues at 2026-06-20T03:25Z; no equivalent reviewer-request merge-gate ticket found. Closest adjacent tickets were unrelated Agent OS stability lanes (#13586, #13575, #13498, #13496, #13480). A2A in-flight sweep: checked latest 30 all-status messages at 2026-06-20T03:25Z; no overlapping
[lane-claim]/[lane-intent]for this reviewer-contract gap found. Knowledge Base sweep surfaced adjacent cross-family review mandate andmanage_pr_reviewersinvitation-layer substrate, but no rule tying outstandingreviewRequeststo merge-readiness.Release classification: post-release / Agent OS process hardening. This is merge-gate correctness, but the immediate #13584 case is handled by targeted A2A to Grace; the general rule can land boardless unless the operator explicitly promotes it.
The Problem
Neo's PR lifecycle has multiple review signals:
reviewDecisiontells whether GitHub has enough formal review state to consider the PR approved.reviewRequeststells who the author/operator explicitly asked to review.Today an agent can honestly report "approved + clean" from
reviewDecision=APPROVEDwhile a requested reviewer is still outstanding. That is exactly the class of stale merge-ready signal the review process is supposed to prevent: the human merge gate sees a green surface, but the author-declared reviewer contract is not fully disposed.The Architectural Reality
Relevant substrate already exists:
.agents/skills/pr-review/references/pr-review-guide.mdrequires live PR-state freshness before relaying review or merge-eligibility claims, and warns to relay the review body's verdict rather than flattened enums..agents/skills/post-review-pickup/references/post-review-pickup-workflow.mdrequires live PR state before lane-state declarations that name PR status.ai/services/github-workflow/PullRequestService.mjsandai/mcp/server/github-workflow/openapi.yamlexposemanage_pr_reviewersas the invitation layer for GitHub reviewer requests.reviewDecisionremains necessary for formal approval, but it is not sufficient whenreviewRequestsis non-empty.The missing rule is the merge-readiness contract:
The Fix
Add a narrow merge-readiness guard wherever agents report or lint "eligible for human merge":
reviewRequestsalongsidereviewDecision,mergeStateStatus, checks, and head SHA in PR-state freshness checks.reviewRequestsas a merge-gate blocker unless the body explicitly documents a disposal path:APPROVED;CHANGES_REQUESTED;manage_pr_reviewers(action: 'remove').reviewDecision=APPROVEDalone.reviewRequestsis non-empty.Contract Ledger Matrix
reviewDecision,reviewRequests, checks, and head SHAreviewDecision=APPROVED, green checks, and empty/disposedreviewRequestsbefore claiming strict merge-readypr-review/pull-request/post-review-pickupguidancereviewDecision=APPROVEDplusreviewRequests=[neo-opus-grace]manage_pr_reviewersand GitHub requested-reviewers APImanage_pr_reviewersis already documented as invitation layerDecision Record impact
none. This clarifies merge-readiness process semantics using existing GitHub review primitives; it does not change human-only merge authority.
Acceptance Criteria
reviewRequests.reviewDecision=APPROVEDfrom strict readiness whenreviewRequestsis non-empty.reviewRequests.reviewDecision=APPROVED, green checks, and one outstanding requested reviewer.Out of Scope
gh pr merge; human-only merge authority remains unchanged.Avoided Traps
reviewDecisionas the only merge-gate signal.Related
Related: #13584 Related: #10214 Related: #11273
Origin Session ID
Origin Session ID: current @neo-gpt Codex Desktop session, 2026-06-20.
Handoff Retrieval Hints
query_raw_memories:13584 reviewDecision APPROVED reviewRequests neo-opus-grace strict merge gatequery_raw_memories:requested reviewers block merge readiness flattened reviewDecision approved6f755137595cca6770836428e5f86c3c7b2222fdreturnedreviewDecision=APPROVEDandreviewRequests=[neo-opus-grace].