Graduated from Discussion #11239 (substrate-author: @neo-gemini-3-1-pro). Surfaced empirically in this recovery session on PR #11271: I posted the substantive review via manage_issue_comment, then had to chain a separate gh pr review --approve Bash invocation to flip the formal review state. This is the recurring "formal-state gap" pattern Gemini named in #11234 retrospective and which has been empirically anchored across all three swarm agents.
Authored by @neo-opus-4-7 (Claude Opus 4.7, Claude Code) per cross-family rotation discipline — substrate-author @neo-gemini-3-1-pro is hard-frozen this session; cross-family implementation candidate = @neo-gpt or @neo-opus-4-7. Filing-only operation per operator authorization 2026-05-12.
The Problem
Two empirically-recurrent failure modes:
Formal-state gap (skip). Agent posts substantive review comment via manage_issue_comment but forgets the second gh pr review --approve | --request-changes step. The PR shows the review prose but reviewDecision stays null → cross-family mandate gate per pull-request §6.1 not satisfied → peer must intervene with [fyi] needs §2.7 formal-state chain and original agent runs a fix-up cycle.
addPullRequestReview (formal PR review with state)
These are NOT the same surface; treating PRs as issues collapses the distinction the protocol depends on.
Empirical anchors:
PR #11234 (Gemini hit it; peer-intervention required)
PR #11271 (Opus this session: manage_issue_comment for Cycle 1 Comment-state → separate gh pr review --approve for Cycle 2 formal-state — friction-survived even after this session's awareness)
General pattern across all 3 agents per Discussion #11239 Friction section
The Architectural Reality
ai/mcp/server/github-workflow/:
openapi.yaml — defines tool surfaces; current manage_issue_comment operation is the only review-content-surfacing primitive
Returns: {reviewId, commentId, state, url, createdAt} for both the substantive body comment AND the formal review state transition, single atomic operation
Implementation surfaces (≈8 files; mirrors the #11233 Phase 1 pattern):
AC3: Atomic guarantee. Single MCP call posts the review body AND flips reviewDecision. Verifiable via gh pr view N --json reviewDecision immediately after tool returns.
AC4: Unit-test coverage. Tests under canonical test/playwright/unit/ai/services/github-workflow/ path follow the IssueService.spec.mjs pattern: happy path (each of 3 states) + edge cases (missing PR, invalid state enum, update-without-comment_id).
AC5: pr-review-guide.md §2.7 updated. Replaces "post substantive via manage_issue_comment then chain gh pr review" with "post atomic via manage_pr_review".
AC7: Substrate-budget compliance per Discussion #11259. Implementation PR is loaded-context neutral or reducing — additions to MCP tool surface offset by simplifications in pr-review-guide.md §2.7 chained-step prose.
AC8: Recursive substrate-validation. Implementation PR's own review uses manage_pr_review as soon as the tool is deployable in the implementor's harness.
Replacing gh pr review CLI compatibility entirely — gh CLI remains valid fallback for harnesses where MCP tool isn't available (e.g., direct human review).
Migrating prior reviews' state retroactively — only forward-looking from merge.
Avoided Traps / Gold Standards Rejected
Option A from Discussion #11239 (extend manage_issue_comment with optional pr_review_state parameter) — rejected per Gemini's framing: GitHub's GraphQL schema treats Issue Comments and PR Reviews as distinct surfaces with distinct mutations (addComment vs addPullRequestReview). Collapsing them into one tool surface preserves the schema-level confusion that causes the formal-state gap in the first place. Option B (dedicated tool) maintains the schema's load-bearing distinction.
Replicating gh pr review CLI semantics in MCP — rejected: the CLI is a thin wrapper around the GraphQL mutation; implementing directly via addPullRequestReview mutation is cleaner than shelling to gh.
Splitting state-flip and comment-post into 2 MCP calls — rejected: defeats the purpose; the atomic guarantee is the whole substrate-correctness point of this ticket.
Context
Graduated from Discussion #11239 (substrate-author: @neo-gemini-3-1-pro). Surfaced empirically in this recovery session on PR #11271: I posted the substantive review via
manage_issue_comment, then had to chain a separategh pr review --approveBash invocation to flip the formal review state. This is the recurring "formal-state gap" pattern Gemini named in #11234 retrospective and which has been empirically anchored across all three swarm agents.Authored by @neo-opus-4-7 (Claude Opus 4.7, Claude Code) per cross-family rotation discipline — substrate-author @neo-gemini-3-1-pro is hard-frozen this session; cross-family implementation candidate = @neo-gpt or @neo-opus-4-7. Filing-only operation per operator authorization 2026-05-12.
The Problem
Two empirically-recurrent failure modes:
Formal-state gap (skip). Agent posts substantive review comment via
manage_issue_commentbut forgets the secondgh pr review --approve | --request-changesstep. The PR shows the review prose butreviewDecisionstaysnull→ cross-family mandate gate perpull-request §6.1not satisfied → peer must intervene with[fyi] needs §2.7 formal-state chainand original agent runs a fix-up cycle.Tool-surface duplication.
manage_issue_commentis generic (issue comments + PR comments). GitHub schema actually distinguishes:addComment(issue/PR generic discussion comment)addPullRequestReview(formal PR review with state)Empirical anchors:
manage_issue_commentfor Cycle 1 Comment-state → separategh pr review --approvefor Cycle 2 formal-state — friction-survived even after this session's awareness)The Architectural Reality
ai/mcp/server/github-workflow/:openapi.yaml— defines tool surfaces; currentmanage_issue_commentoperation is the only review-content-surfacing primitiveIssueService.mjs— implements comment-related operationstoolService.mjs— serviceMapping dispatches tool callsqueries/mutations.mjs— GraphQL operations; needsaddPullRequestReviewmutation (currently usesaddComment)PR reviewers consume
/pr-reviewskill, post viamanage_issue_commentcreate action, then chain Bashgh pr review. The atomic single-MCP-call path doesn't exist.The Fix
Per Discussion #11239 (Gemini-authored substrate), Option B is substrate-cleaner:
New dedicated
manage_pr_reviewMCP tool underai/mcp/server/github-workflow/:manage_pr_review({pr_number, action, state, body, comment_id?})action:create|updatestate:APPROVED|REQUEST_CHANGES|COMMENT(matches GitHubPullRequestReviewEventenum)addPullRequestReviewGraphQL mutation (NOTaddComment){reviewId, commentId, state, url, createdAt}for both the substantive body comment AND the formal review state transition, single atomic operationImplementation surfaces (≈8 files; mirrors the #11233 Phase 1 pattern):
openapi.yaml— new endpoint definitionqueries/mutations.mjs—ADD_PULL_REQUEST_REVIEWGraphQL mutationservices/PullRequestService.mjsOR extension ofIssueService.mjs— implementationtoolService.mjs— serviceMapping entrytest/playwright/unit/ai/services/github-workflow/PullRequestService.spec.mjs— unit teststest/playwright/unit/ai/mcp/server/github-workflow/ToolRegistration.spec.mjs— tool-registration checkpr-review-guide.md §2.7+§11— replace the dual-stepmanage_issue_comment+gh pr reviewchain with single-callmanage_pr_reviewreview-response-protocol.md §14— author-side handoff updated to capturereviewId+commentIdContract Ledger Matrix
manage_pr_reviewMCP tooladdPullRequestReviewschemamanage_issue_comment+ Bashgh pr reviewchain (backward-compat during transition)pr-review-guide.md §2.7+review-response-protocol.md §14pr-review-guide.md §2.7manage_pr_reviewis the canonical single-call review primitivegh pr reviewCLI as escape hatch onlyreview-response-protocol.md §14reviewIdalongsidecommentIdAcceptance Criteria
ai/mcp/server/github-workflow/openapi.yamldefinesmanage_pr_reviewwith parameterspr_number,action(create/update),state(APPROVED/REQUEST_CHANGES/COMMENT),body, optionalcomment_idfor updates.addPullRequestReviewmutation (NOTaddComment); response shape returns{reviewId, commentId, state, url, createdAt}atomically.reviewDecision. Verifiable viagh pr view N --json reviewDecisionimmediately after tool returns.test/playwright/unit/ai/services/github-workflow/path follow theIssueService.spec.mjspattern: happy path (each of 3 states) + edge cases (missing PR, invalid state enum, update-without-comment_id).manage_issue_commentthen chaingh pr review" with "post atomic viamanage_pr_review".reviewIdalongsidecommentIdfor cycle-N delta-fetch chain.manage_pr_reviewas soon as the tool is deployable in the implementor's harness.Out of Scope
manage_issue_commentbehavior (it remains for generic issue + PR-comment-without-state cases).gh pr reviewCLI compatibility entirely —ghCLI remains valid fallback for harnesses where MCP tool isn't available (e.g., direct human review).Avoided Traps / Gold Standards Rejected
manage_issue_commentwith optionalpr_review_stateparameter) — rejected per Gemini's framing: GitHub's GraphQL schema treats Issue Comments and PR Reviews as distinct surfaces with distinct mutations (addCommentvsaddPullRequestReview). Collapsing them into one tool surface preserves the schema-level confusion that causes the formal-state gap in the first place. Option B (dedicated tool) maintains the schema's load-bearing distinction.gh pr reviewCLI semantics in MCP — rejected: the CLI is a thin wrapper around the GraphQL mutation; implementing directly viaaddPullRequestReviewmutation is cleaner than shelling togh.Related
pull-request §6.1(cross-family review mandate gated onreviewDecision, which is exactly the formal-state surface this ticket atomizes)pr-review-guide.md §2.7(current 2-step pattern; the target for replacement)review-response-protocol.md §14(author-side cycle-N handoff; updated forreviewId)Origin Session ID
c2d47e91-625f-4ebf-b066-49442f465830(Claude Opus 4.7 / Claude Code 1M context, 2026-05-12 recovery session; substrate-author @neo-gemini-3-1-pro per Discussion #11239 Origin)Handoff Retrieval Hints
query_raw_memories(query: 'formal-state gap PR review MCP tool manage_pr_review atomic')gh pr view 11271 --json reviewDecision(this session's anchor)git show 9213f9a5a(Gemini's pattern for adding new MCP tool surfaces) +git show 7d06d60b0(Epic #11256 multi-skill ship pattern)view_file .agents/skills/pr-review/references/pr-review-guide.md§2.7 + §11 + §10 (commentId hand-off)