LearnNewsExamplesServices
Frontmatter
id17692
titlePublish mergeability as a review-admission status
stateClosed
labels
enhancementaitestingbuildmodel-experience
assigneesneo-gpt-emmy
createdAtAug 24, 2026, 11:21 AM
updatedAtAug 24, 2026, 3:43 PM
githubUrlhttps://github.com/neomjs/neo/issues/17692
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 24, 2026, 3:43 PM

Publish mergeability as a review-admission status

Closed Backlog/active-chunk-19 enhancementaitestingbuildmodel-experience
neo-gpt-emmy
neo-gpt-emmy commented on Aug 24, 2026, 11:21 AM

Context

On 2026-08-24, PR #17670 became conflicted after later dev merges while its head stayed unchanged. The first live recheck returned head 65aed8d3a2, mergeable=CONFLICTING, and mergeStateStatus=DIRTY; the author then rebased to dda802a337, which restored mergeable=MERGEABLE and let the remaining CI gate surface normally. Review work should have waited for that author repair.

The existing admission contract catches only head-scoped CI:

  • .agents/skills/pull-request/references/ci-green-review-routing.md runs gh pr checks before reviewer assignment.
  • .agents/skills/pr-review/audits/ci-security-audit.md holds reviewers on pending or red checks.
  • PullRequestService.managePrReviewers() currently enters the reviewer mutation without a live mergeability preflight.

GitHub's event contract creates a blind spot: ordinary pull_request workflows do not run while a PR has a merge conflict, whereas pull_request_target still runs. GitHub also documents mergeable: null as an asynchronous computation state that must be polled, not interpreted as either clean or conflicting.

Official constraints:

Live latest-open sweep: checked the newest 20 open issues immediately before creation on 2026-08-24; no equivalent ticket or recent A2A claim existed. Closed #11467 is the exact author-admission predecessor and explicitly excluded a mechanical status gate. Open #16136 is adjacent PR-state instrumentation, not this gate. Open #17171 owns required-context/ruleset policy, which this ticket does not change.

The Problem

CI is primarily a function of the PR head. Mergeability is a function of the PR head and the moving base. A merge into dev can therefore make an unchanged, previously green head conflicting without generating a new head-scoped CI result.

The current review-admission flow asks a human or agent to remember a second query after gh pr checks. That query is easy to skip, and an ordinary PR workflow cannot repair the omission because GitHub suppresses that workflow precisely in the state it needs to report.

The predicate must remain narrow:

  • confirmed mergeable === false is a merge conflict;
  • mergeable === null is unresolved and must not become success;
  • BEHIND, BLOCKED, and UNSTABLE can coexist with positive mergeability and are not conflicts;
  • review approval, required checks, base-update policy, and human merge authority remain separate gates.

The Architectural Reality

  • .github/workflows/ owns the repository-local controller that can react both to PR-head events and dev movement.
  • pull_request_target runs trusted default-branch workflow code even for conflicted PRs. It is admissible here only with no checkout or execution of PR code, no repository secrets, and least-privilege pull-requests: read plus statuses: write.
  • GitHub commit statuses attach a named result to the exact PR head SHA, so the existing gh pr checks admission instrument can see it.
  • ai/services/github-workflow/PullRequestService.mjs#managePrReviewers owns the active reviewer-invitation mutation and is the defense-in-depth gate for callers that bypass workflow prose.
  • test/playwright/unit/ai/buildScripts/util/WorkflowConcurrency.spec.mjs already establishes the pattern for parsing an actions/github-script block from YAML and executing it against mocked GitHub/runtime objects.
  • test/playwright/unit/ai/services/github-workflow/PullRequestServiceReviewers.spec.mjs owns reviewer-mutation preflight and no-mutation evidence.
  • The author and reviewer CI payloads are already conditionally loaded; a compact mergeability clause belongs there, with no SKILL.md router growth and no new skill.

The mandatory Agent OS structure-map command was attempted during creation and failed with Cannot create a string longer than 0x1fffffe8 characters. Direct sibling inspection established the existing-file placement above. No new .mjs file or directory role is introduced.

The Fix

  1. Add .github/workflows/review-admission-mergeability.yml with:
    • pull_request_target for opened, reopened, synchronize, and ready_for_review PRs targeting dev;
    • push on dev, which enumerates every open dev-target PR and is the load-bearing response to later base merges;
    • workflow_dispatch as a recovery path;
    • no checkout and no execution of PR-controlled code;
    • event-only discovery for active pull_request_target events; board discovery for merged-close, push: dev, trusted Data Sync completion, and recovery;
    • per-PR serialized evaluation, with a declared safe board cap.
  2. For each live PR coordinate:
    • leave a new head without the named status while GitHub computes, which is itself an admission hold;
    • GET the PR and poll a declared, bounded number of times while mergeable === null;
    • re-read head and base before publishing; restart on movement already observed, while the serialized successor/live tool gate corrects any post-read movement;
    • publish success / failure / error only when the named terminal state changes, avoiding append-only status exhaustion.
  3. Before manage_pr_reviewers(action: 'add') mutates:
    • perform the same bounded live mergeability read;
    • refuse confirmed conflict and unresolved exhaustion with distinct structured codes;
    • keep remove available without the preflight.
  4. Update the MCP description/schema for the new refusal envelopes.
  5. Fold one compact named-status clause into each existing author/reviewer CI payload. Missing, failing, or error status is an author-side hold; only success admits formal review routing. The controller activation PR substitutes a named live mergeability read.
  6. Execute the workflow script in a focused unit harness and extend the reviewer-service suite with no-mutation controls.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
review-admission/mergeability on PR head live GitHub PR mergeable plus exact head/base coordinates absent while computing; terminal success / failure / error only on state transition source unresolved after a known coordinate becomes error; target discovery failure is a loud workflow failure and the reviewer-tool live gate stays authoritative workflow comments + existing CI-routing payloads mocked workflow runtime + exact-head/status assertions
Controller triggers GitHub PR/base event model PR events evaluate one PR; ordinary dev pushes plus Data Sync Pipeline completion re-evaluate the board within the safe cap workflow_dispatch recovery; discovery/overflow failure refuses a partial matrix and reports best-effort invalidation failures workflow header event/target/concurrency matrix
manage_pr_reviewers(add) live PR read immediately before mutation only positive mergeability reaches reviewer POST conflict and unresolved exhaustion return distinct structured refusals OpenAPI tool description captured command order + no-mutation arms
manage_pr_reviewers(remove) requested-reviewer state remains available independent of mergeability existing verification envelopes existing tool description negative control proving no mergeability read
Author/reviewer admission prose #11467 contract + named status context existing gh pr checks gate requires the mergeability context to be successful missing/pending/red/error routes to author repair/retry two existing conditional payloads byte-bounded diff + trigger-path assertions

Decision Record impact

none — additive repository workflow, status context, and existing-tool preflight. No API break, merge-policy change, or new subsystem.

Unresolved Liveness

  • revalidationTrigger: open dev PR count approaches 32, observed board-trigger rate × worst-case reads approaches 800 requests/hour, an overflow invalidation reports any failure, GitHub returns the first status-limit/rate-limit refusal, or a new [skip ci] dev producer appears outside Data Sync. The live reviewer-tool preflight remains authoritative; any changed bound or mechanism goes into a new successor ticket.
  • Same-state terminal writes are skipped, so the append-only 1,000-status limit is consumed by state transitions rather than routine dev movement.

Acceptance Criteria

  • review-admission/mergeability is written to the live PR head SHA, never the base SHA.
  • A conflicting PR produces failure; a positive PR produces success; exhausted null or an unreadable source after a known coordinate produces error; absence while computing never reads as success.
  • pull_request_target covers opened/reopened/synchronize/ready-for-review events targeting dev, and the controller never checks out or executes PR code.
  • Within the declared safe board cap, merged-close, ordinary dev push, and trusted Data Sync completion re-evaluate open dev-target PRs, including [skip ci] sync commits; an unchanged formerly-green head can turn red after a base move.
  • The safe board cap is justified as a per-trigger burst bound (hourly safety still includes event rate); discovery/overflow failure refuses a partial matrix, reports invalidation failures, and leaves manage_pr_reviewers(add) as the live authority.
  • Head/base movement observed before publication restarts on the new coordinate; a post-read movement is corrected by the serialized successor and authoritative live reviewer-tool preflight.
  • Workflow permissions are limited to the reads and commit-status write actually required; no repository secret is consumed.
  • manage_pr_reviewers(action: 'add') performs no reviewer mutation for a confirmed conflict or unresolved mergeability, and returns distinct structured refusal codes.
  • manage_pr_reviewers(action: 'remove') performs no mergeability preflight and preserves current removal verification.
  • Positive mergeability remains admissible alongside BEHIND, BLOCKED, or UNSTABLE; those states are not reclassified as conflicts.
  • The author and reviewer CI payloads require the named status to be successful before actionable/formal review, with no new skill or router growth.
  • Workflow-runtime tests fail if pull_request_target is replaced by pull_request, if push: dev is removed, if the status targets the base SHA, or if unresolved mergeability becomes success.

Out of Scope

  • Making the status a required ruleset context or changing branch protection; #17171 owns that operator/settings decision.
  • Merge queues, auto-rebase, automatic conflict resolution, or requiring a merely BEHIND branch to update.
  • Approval freshness, cross-family approval, or the human-only merge gate.
  • Extending list_pull_requests; #16136 retains board-projection work.
  • A scheduled poller. Add one only if missed-event evidence appears.
  • Generalizing the repository-local workflow across the Neo organization in this first leaf; the reviewer-tool guard still applies to every repository target it accepts.

Avoided Traps

  • Ordinary pull_request CI: absent on the conflict state it must report.
  • Executing PR code under pull_request_target: turns a status helper into a privileged-code-execution surface.
  • Tool preflight only: correct but invisible in gh pr checks, and cannot proactively turn red when dev moves.
  • Branch protection or merge queue as review admission: governs merge, not when reviewer attention should be spent, and changes the human merge flow.
  • Schedule as the primary trigger: slower and noisier than the exact push: dev cause.
  • A new skill or MCP tool: additive capability belongs in the existing status and reviewer-invitation surfaces.

Substrate-accretion rationale: only compact clauses enter two already-conditional payloads. Retire the manual prose if a future organization-wide controller plus mechanically exclusive reviewer-invitation path makes the named context unavoidable without agent discipline.

Related

Origin Session ID: 0dc1379e-5329-4fba-80ca-f6466822f7c9

Retrieval Hint: review admission mergeability commit status pull_request_target dev push conflicted PR reviewer assignment

Authored by Emmy (GPT-5.6 Sol Ultra, Codex).

tobiu referenced in commit 4e6d8da - "feat(ai): publish review-admission mergeability (#17692) (#17696) on Aug 24, 2026, 3:43 PM
tobiu closed this issue on Aug 24, 2026, 3:43 PM