KognitaKognita.

Blog

How to Know a PR Is Actually Merged Before You Close the Sprint

9 min read

The sprint closes looking like a success. Velocity is up. Eighteen tickets are in "Done." The sprint review goes smoothly. Two weeks later, someone asks why the new export feature is not in the product. Engineering checks Jira: the ticket has been Done since day eight. What they do not check — and what the sprint board cannot show — is whether the PR ever merged.

It did not. The PR is still open. CI has been failing on it for nine days. Nobody noticed because the ticket was already marked Done, so nobody was watching it.

Engineers mark Done at PR open, not at PR merge

This is not a discipline problem. It is a workflow norm that has drifted into a systematic tracking gap. When an engineer pushes a PR, their work on that ticket is genuinely finished — from their perspective. The implementation is done. The code is correct. They are ready to move on. Moving the ticket to Done is a natural expression of that state, not a misrepresentation.

The problem is that "PR open" and "code merged" are two very different facts for a sprint. A PR that is open but not merged has not delivered anything. It has not changed the product. It has not satisfied the acceptance criteria in any observable way. It is work that exists in a waiting state, dependent on review and CI and merge — none of which are under the engineer's direct control once the PR is submitted.

The gap between an engineer's definition of Done and the sprint's definition
What "Done" means to an engineer versus what it means to the sprint:

  Engineer's definition of Done:
  -> Code is written and working locally
  -> A PR is open and the engineer is satisfied with the implementation
  -> The ticket is off their plate — they have moved to the next task

  Sprint's definition of Done (or what it should be):
  -> Code is merged to main
  -> CI has passed on the merged code
  -> The change is deployed to the environment defined in the sprint goal
  -> Acceptance criteria in the ticket are verifiably satisfied

  The gap: engineers routinely move tickets to "Done" at PR open,
  not at PR merge. The sprint board shows completion. The codebase
  does not reflect it. Velocity looks good. Nothing shipped.

Most engineering teams do not have a formal policy distinguishing PR-open Done from merged Done. The definition of done may say "code reviewed and merged" on paper, but in practice, tickets move to Done when the engineer is finished working — which is at PR open. The sprint board reflects this convention. It also obscures the gap completely.

How unmerged PRs survive a sprint close

The mechanics of how this happens are worth tracing because they make clear why it is so hard to catch without explicit tooling. Once a ticket moves to Done, it disappears from the active focus of the sprint board. Nobody is watching it. Nobody is checking it in standup because it is Done. The engineer has moved on. The reviewer may or may not have gotten to the PR. CI may have passed or failed. None of that surfaces anywhere.

How three unmerged PRs survive a ten-day sprint without being caught
How three unmerged PRs survive a sprint close undetected:

  Day 8: Engineer A opens PR for ticket PROJ-301.
  -> Moves ticket to "Done."
  -> CI is failing — flaky test, engineer will fix later.
  -> Later never comes before sprint close.

  Day 9: Engineer B opens PR for ticket PROJ-318.
  -> Moves ticket to "Done."
  -> Reviewer requests changes.
  -> Engineer B is pulled into an incident. Never returns to address comments.

  Day 10 (sprint close): Sprint review shows 18 tickets Done.
  -> PROJ-301: PR open, CI failing. Not merged.
  -> PROJ-318: PR open, changes requested. Not merged.
  -> PROJ-329: PR open, no reviewer assigned. Opened 3 days ago.
  -> All three are counted in velocity. None are in main.

  Post-sprint: Product asks "where is the new export feature?"
  Engineering: "It shipped — the ticket is done."
  Reality: The PR has been open for 9 days with a failing CI check.

The failure mode is structural. The sprint board has no field that connects "ticket status = Done" to "PR merged = true." Those two facts live in different systems — Jira and GitHub — and neither system queries the other. A scrum master closing the sprint has no practical way to check the alignment without either GitHub access or an engineer to look it up for every Done ticket.

This is the same underlying problem as sprint blockers that never surface in standup — the relevant state is in the system, not in anyone's head, and there is no mechanism to surface it without explicitly querying the system.

What the scrum master needs at sprint close

The question a scrum master needs to answer before closing a sprint is not "are all the tickets Done?" That question is trivially answered by looking at the board. The question is: "For every ticket marked Done, is there merged code behind it?" That question requires cross-referencing Jira ticket state with GitHub PR state — a join that does not exist natively in either tool.

A secondary question follows: "For any ticket where the PR is not merged, what is the state of the PR and what would it take to merge before sprint close?" Sometimes the answer is a ten-minute fix. Sometimes the answer is that the work carries into the next sprint. The scrum master cannot make that decision without knowing which situation they are in — and they cannot know which situation they are in without seeing the PR state.

This gap between Jira state and git state is the same gap that produces the misalignment in what "got shipped" actually means at sprint review. The sprint board reports what people moved. The codebase reflects what actually merged.

How Kognita catches the gap before sprint close

Kognita's Jira MCP integration reads both Jira ticket state and the git and PR state linked to it. A scrum master can ask a plain-language question — no GitHub access required, no understanding of branch names or merge commits — and get a factual answer about which Done tickets have merged code behind them and which do not.

A sprint close PR audit using Kognita + Jira MCP
Sprint close audit using Kognita + Jira MCP:

  "Which tickets marked Done this sprint have no merged PR linked?"
  -> PROJ-301: PR #912 open since Day 8, CI failing on 2 checks
  -> PROJ-318: PR #928 open since Day 9, 3 unresolved review comments
  -> PROJ-329: PR #941 open since Day 7, no reviewer assigned

  "Are any of these tickets dependencies for next sprint's work?"
  -> PROJ-301 is a dependency for 4 tickets in Sprint 12 backlog
  -> PROJ-329 is required for the Q2 milestone demo

  "What would it take to get each of these merged before sprint close?"
  -> PROJ-301: CI fix needed — test failure is in the payments module
  -> PROJ-318: Engineer B needs to address 3 reviewer comments
  -> PROJ-329: Reviewer needs to be assigned and must complete review

  "Which of these can realistically merge in the next 4 hours?"
  -> PROJ-318 comments are minor style feedback — addressable quickly
  -> PROJ-329 reviewer assignment is the only blocker
  -> PROJ-301 CI fix requires a code change — likely carries to next sprint

The audit surfaces not just which tickets are misaligned but what it would take to fix each one before the sprint closes. Some PRs are one reviewer assignment away from merging. Some require a CI fix that will take hours. Some carry into the next sprint regardless. The scrum master can make informed decisions about each one — defer, escalate, or accept the carry-over — rather than discovering the gap two weeks later when a stakeholder asks where the feature is.

The compounding cost of phantom Done tickets

A single sprint with three unmerged PRs counted as Done is an annoyance. A pattern of this across sprints is a forecasting problem. Velocity becomes unreliable because it counts work that did not actually ship. Sprint planning estimates become wrong because the hidden carry-over from previous sprints consumes capacity that the team did not account for. Retrospectives focus on the wrong sprint because the gap shows up as underperformance in the next sprint rather than as incomplete work in the sprint where it originated.

How phantom Done tickets compound into a velocity distortion problem
How phantom Done tickets distort velocity over time:

  Sprint 10: Velocity reported as 44 points
  -> Actual merged code: 36 points
  -> 8 points of "Done" tickets had open, unmerged PRs
  -> Those 8 points carry silently into Sprint 11's starting state

  Sprint 11: Team starts with hidden debt
  -> 3 PRs from Sprint 10 still need to merge
  -> Engineers return to stale branches, resolve drift, fix CI
  -> Visible Sprint 11 work slows — the team "underperforms"
  -> Retrospective focuses on Sprint 11 execution, not Sprint 10 accounting

  The compounding effect:
  -> Each sprint with phantom Done tickets inflates the next sprint's
     invisible workload
  -> Velocity averages become unreliable for forecasting
  -> The pattern is invisible unless someone tracks Jira state
     against actual git merge history

The compounding effect is subtle enough that many teams never connect it to the root cause. They see sprint-over-sprint velocity variation and attribute it to scope changes, estimation error, or team capacity. The actual cause — a systematic gap between Jira state and merge state — is invisible unless someone specifically looks for it.

Running a sprint close audit before closing each sprint, rather than after, catches the tickets that are close enough to merge and surfaces the ones that need to carry over with accurate accounting. The sprint's velocity reflects what actually shipped. The next sprint starts with an accurate backlog rather than hidden debt from PRs that never merged.

Final take

Engineers marking tickets Done at PR open is not a process violation — it is a convention that emerged from how software development actually works. The fix is not stricter enforcement of definition-of-done policies. The fix is giving the scrum master the ability to see the gap directly, before the sprint closes, when there is still time to act.

A sprint that closes with eighteen Done tickets and three unmerged PRs did not deliver what the velocity number suggests. The team will absorb that gap in the next sprint, invisibly, and the retrospective will ask the wrong questions about why things slowed down.

Closing a sprint without verifying merged PR state is not closing the sprint — it is deferring the accounting. The gap shows up eventually. It is cheaper to find it before sprint close than after.