Skip to content

Contribution Workflow#

How a change travels from a branch to a review-ready pull request. The workflow puts an automated Copilot review before human review: the author iterates with Copilot on a draft pull request until it has no more feedback, then opens the pull request for people.

This is the operational "how" for a repository-delivery Task or Bug. The conventions it builds on live in the ways of working — Issue Lifecycle, PR Format, Branching and Merging, and Review Etiquette. Epic and PBI aggregates stay in planning and coordination rather than entering this branch-and-pull-request flow.

The flow#

flowchart TD
    A[Branch and implement] --> B[Open PR as draft]
    B --> C[Request Copilot review]
    C --> D{New comments?}
    D -- in scope --> E[Fix in this PR]
    D -- out of scope --> F[File an issue]
    E --> C
    F --> C
    D -- none --> G[Mark ready for review]
    G --> AM[Enable auto-merge]
    AM --> H[Human review]
    H --> M[Auto-merge lands it on approval + green checks]
  1. Branch and implement. Pull one ready, unblocked Task or Bug into work on a <type>/<issue>-<description> branch. Keep per-change implementation detail in that delivery issue and the pull request, not in the spec, design, or parent aggregate.
  2. Open the pull request as a draft. A draft attaches CI and keeps the change out of people's review queues while you iterate.
  3. Run the Copilot review loop (below) until Copilot reports a clean round — no changes requested and no new inline comments.
  4. Mark the pull request ready for review once it meets the Definition of Ready for Review.
  5. Enable auto-merge so the change lands automatically when human review approves and the required checks stay green. Human review takes over from there.

Why draft first#

  • Copilot is the first pass. It catches the obvious issues quickly, so the cheap feedback is spent before a person's time is (AI-First Development).
  • People review a self-reviewed change. By the time someone is asked, the pull request has already survived an automated pass and the author's responses — review starts from a higher baseline.
  • The draft is a safe workspace. Force-pushes, rewrites, and rapid iteration are fine while it is a draft; readiness is a deliberate signal.

The Copilot review loop#

Each round is the same: request a review, wait for Copilot, triage what it says, and repeat until it is clean. The waiting is deterministic, so it is scripted — .github/scripts/Wait-CopilotReview.ps1 explicitly requests a Copilot review and polls until Copilot submits one, then reports whether it left inline comments:

  • exit 0 — a clean round: Copilot requested no changes and left no new inline comments;
  • exit 2 — Copilot has feedback (a new inline comment or a changes-requested review);
  • exit 1 — no review arrived before the timeout.
# one round: request Copilot and wait for its verdict (-Verbose logs each step)
./.github/scripts/Wait-CopilotReview.ps1 -Repository MSXOrg/<repo> -PullRequest <n> -Verbose

Always request the review explicitly — never assume a ruleset or other automation will do it. The script checks whether Copilot is already processing a request (from the timeline) and requests one only if not; a review "requested automatically" on push or on marking ready is not guaranteed to fire. Run a round after each push; the loop ends on a clean round (exit 0). Copilot re-reviews the diff from scratch each round, so a genuine false positive can recur — do not change correct code to silence it; dismiss it with a reason and treat the loop as converged on substance.

Triage: fix in scope, file an issue for the rest#

For each piece of feedback, decide:

  • In scope — it concerns the change under review. Address it in this pull request and push; the next round re-checks it.
  • Out of scope — it points at a pre-existing gap or an adjacent improvement. Route a follow-up through the Issue Hierarchy and reference it; do not grow the pull request to cover it.
  • Not actionable — a false positive, or a matter of taste you disagree with. Reply with the reason and resolve the thread; a documented dismissal counts as handled (Review Etiquette).

Keeping out-of-scope work in its own issue is what stops a focused change from sprawling — the pull request stays reviewable, and the gap is recorded rather than lost.

Marking ready#

Mark the pull request ready for review only when it meets every item in the Definition of Ready for Review — that gate is the single checklist, and nothing in it is left open. Readiness is a deliberate signal that the change has passed the automated pass and is ready for people — see Review Etiquette for what a reviewer is accountable for.

Anyone who can verify that gate — a human contributor, or an agent acting on their behalf — may mark the pull request ready. The gate, not the actor, is what makes it ready.

Enable auto-merge#

Once the pull request is ready, enable auto-merge (squash). The change then lands automatically the moment human review approves and the required checks are green — no one has to watch the pull request to click merge. Auto-merge waits on all of the branch's protection requirements — required checks, required approvals, and anything else the ruleset enforces — so nothing lands early. See Branching and Merging for the approval identity that satisfies the gate.

Where this connects#