Did this pull request break the API?
A yes/no question the merge gate answers deterministically.
Delimit ran against the DigitalOcean public OpenAPI across the pull request that removed the App Platform tier endpoints (PR #893, commit ccd01a3, parent 9e32977). The answer is yes: two endpoints removed, classified breaking, semver major, gate failed.
- The pull request is public and the removal was intentional and correctly versioned on DigitalOcean's side. This is not a defect report and DigitalOcean is not a Delimit customer.
- We use the diff only to show what a merge gate returns when a pull request removes an endpoint.
- Reproducible byte-for-byte (command at the end).
The problem
"Did this PR break the API?" is the question every reviewer of a spec change is really asking, and it is a bad fit for human eyeballs. Removing an endpoint is one deleted block in a diff that may also add ten. When an AI assistant regenerates a spec from changed source models, an endpoint can disappear as a side effect nobody intended. If the review is a skim or a summary, the removal can pass.
The merge gate replaces the judgment call with a classification. Endpoint removal is unambiguously breaking, so the answer is not "looks fine to me" but a verdict with an exit code.
The setup
One CI job, running on every pull request that touches the spec. It diffs the proposed spec against the base branch, classifies each change, and fails on a breaking change.
# .github/workflows/api-merge-gate.yml
name: API merge gate
on: [pull_request]
jobs:
delimit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: delimit-ai/delimit-action@v1
with:
spec: specification/DigitalOcean-public.v2.yamlHeadline numbers
Endpoint removal is breaking under the default policy, not just the strict one, so the gate returns a hard fail (exit code 1) with no extra configuration. The DigitalOcean spec composes 666 external $ref files; the gate reads the path set from the document root and flags the two removed routes without needing every referenced file resolved.
What free Delimit detects
Two findings, both endpoint removals, both breaking. Each cites the change-type from the taxonomy and the exact path.
- breakingfinding F1change type: endpoint_removedsurface:
/v2/apps/tiersThe endpoint that listed App Platform tiers was removed outright. Any client that calls GET /v2/apps/tiers to enumerate available tiers now receives a 404. There is no request-shape signal for this; the call simply stops resolving.
- breakingfinding F2change type: endpoint_removedsurface:
/v2/apps/tiers/{slug}The companion endpoint that fetched a single tier by slug was removed in the same change. Code paths that look up a specific tier before creating or scaling an app lose their lookup. Two endpoints, both flagged breaking, both forcing a major bump.
Why a generic AI review misses it
A free-text "review this diff" can describe a removed endpoint, but it has no obligation to. It has no fixed definition of "breaking," no exit code, and no policy to enforce, so its answer varies with prompt, context window, and how much other change is competing for attention. "Did this PR break the API?" deserves the same answer every time.
The merge gate gives it one. Two specs in, a classified change list and a pass/fail out, identical on every run. A removed endpoint is always endpoint_removed, always breaking, always a major bump.
The migration guide the gate generates
Verbatim head of the generated migration output for this diff:
# Migration Guide: API (2.0 -> 2.0)
This release contains 2 breaking change(s).
Follow the steps below to update your integration.
### Step 1: Endpoint Removed
Change: Endpoint removed: /v2/apps/tiers/{slug}
Action: Update all clients to stop calling this endpoint.
If you control the consumers, search for references
and remove them. Consider using the new endpoint
(if applicable) as a replacement.
### Step 2: Endpoint Removed
Change: Endpoint removed: /v2/apps/tiers
Action: Update all clients to stop calling this endpoint.Both source specs advertise version 2.0, so the guide's header shows an unchanged string on a major-class change set. Surfacing that mismatch is the point of the gate.
Reproduce locally
# Install the CLI npm install -g delimit-cli # Clone the spec repo git clone https://github.com/digitalocean/openapi cd openapi # Extract the two versions across PR #893 git show ccd01a3^:specification/DigitalOcean-public.v2.yaml > /tmp/old.yaml git show ccd01a3:specification/DigitalOcean-public.v2.yaml > /tmp/new.yaml # Run the merge gate delimit lint /tmp/old.yaml /tmp/new.yaml
If your bytes differ from this report, raise it on the Delimit repo.
Free detects. Pro proves.
Free Delimit is the merge gate: it answers "did this PR break the API?" on every pull request and blocks the merge when the answer is yes. Install delimit-cli or add the delimit-ai/delimit-action to CI. Free for individual maintainers.
Pro turns that answer into a signed, replayable attestation you can hand to a reviewer, an auditor, or a downstream consumer as proof the pull request was checked and what was found, without their having to rerun the gate. Pro tier $10/month for teams.