Skip to content
Back to blog
Engineering

Catching cross-PR contract breaks before they merge

ZAR Team3 min read

Here is a failure mode that branch isolation hides from you. Two open PRs, each correct on its own, that break when both land.

PR A changes a function signature. PR B, opened from an older point, still calls the old shape. Each branch builds. Each branch's tests pass. Neither diff looks wrong in review. Then both merge, and main is broken.

This is a cross-PR contract break, and ZAR can flag it.

Why CI does not catch this

CI runs each PR against its own branch. It does not run PR B's code against PR A's changes, because those changes do not exist on PR B's branch yet.

# PR A: the contract changes
-def charge(amount):
+def charge(amount, currency):
# PR B, opened earlier, never rebased:
charge(total)   # still the one-argument shape

Both pass. The conflict only exists in the union of the two branches, which nothing builds until they are both on main. That union is exactly the blind spot.

What ZAR looks at

ZAR already analyzes diffs plus best-effort AST and symbol changes to keep docs accurate. The same symbol awareness lets it reason across pull requests.

When a PR changes a function or endpoint signature, ZAR can check whether another open PR still uses the old shape:

  • A documented or referenced symbol changes its parameters, return, or name in one PR.
  • Another open PR continues to call, import, or reference the previous shape.
  • That mismatch would only surface after both merge, so no per-branch check sees it.

It is the contract that breaks, not the syntax. A merge conflict is when the same lines change. A contract break is when different lines disagree about a shared interface, which is far quieter.

How it surfaces

ZAR raises this as an advisory Check Run on the PR. It points at the symbol that changed and the other PR that still depends on the old form.

This follows the same principles as the rest of ZAR:

  • Advisory, not a hard wall. The signal lands where you review, as a check, with context.
  • PR-native. You see it in GitHub, next to the change that caused it.
  • Conservative. It points at a concrete symbol mismatch, not a vague warning.

We are deliberately not putting a number on this. Contract-break detection is a capability, framed as one. It catches a real and specific class of break. It is not a guarantee that every cross-PR interaction is safe, and we will not claim an accuracy figure we have not earned.

Why it matters for parallel work

The more PRs you keep open at once, the more this bites. Long-lived branches, several people editing the same module, an interface that everyone depends on. The cost of a contract break is paid on main, by whoever pulls next, usually with a stack trace and no obvious cause.

Moving that signal to review time means the author who changed the contract sees, in their own PR, that someone else is still on the old shape. They can coordinate before the merge instead of debugging a red main after it.