Skip to main content

mergeproof

mergeproof

Proof before merge. Pull requests earn their merge with evidence, not claims.

CI PyPI Python GitHub Marketplace License: MIT

mergeproof gates pull requests on evidence. A policy file in the repository says what a change must prove before it merges: tests for the modules it touched, a green integration job, before/after links from a live environment, a human who opened them. CI enforces it and reports on the PR. Coding agents read the same file, through AGENTS.md or an MCP server, so what they are told is what CI checks.

One policy file drives CI, coding agents and reviewers

Why

Agentic development makes outcomes cheap to claim and expensive to verify. "Added tests, checked on staging" costs nothing to type. A checkbox is self-attestation. What holds up is an artifact someone else can open: a changed test file, a trace id that resolves, a screenshot pair, a sign-off bound to the exact commit. mergeproof checks those, verifies them at their source when it can, and keeps the last word with a person who is not the author.

Quickstart

1. Install and write a policy

pip install mergeproof        # or: uv tool install mergeproof
mergeproof init               # writes mergeproof.yaml
# mergeproof.yaml
version: 1
rules:
  - id: source-needs-tests
    description: Source changes ship with tests for the touched module.
    when:
      paths: ["src/**/*.py"]
    require:
      - check: tests.changed
        with: { map: { "src/{pkg}/{name}.py": "tests/**/test_{name}*.py" } }
      - check: ci.job_passed
        with: { name: "^unit", regex: true }

  - id: fix-needs-live-evidence
    description: Bug fixes show the behaviour before and after on staging.
    when:
      title: "^fix"
    require:
      - check: evidence.field
        with: { key: environment, equals: staging }
      - check: evidence.links
        with: { min_pairs: 1 }
      - check: review.human_verified

2. Add the workflow (full version in examples/github-workflow.yml)

# .github/workflows/mergeproof.yml
on:
  pull_request:
    types: [opened, synchronize, reopened, edited, labeled, unlabeled]
  issue_comment: { types: [created, edited] }
  check_suite:   { types: [completed] }
jobs:
  gate:
    name: 🛡️ mergeproof
    if: github.event_name != 'issue_comment' || github.event.issue.pull_request
    runs-on: ubuntu-latest
    permissions: { contents: read, pull-requests: write, statuses: write, checks: write }
    steps:
      - uses: actions/checkout@v4
        with: { ref: ${{ github.event.repository.default_branch }} }
      - uses: Aryamanz29/mergeproof@v0
        env:
          MERGEPROOF_PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}

3. Require the mergeproof status in a ruleset on your default branch. That single required check stands for everything the policy asks for, CI jobs included. See docs/github.md.

What a pull request sees

The mergeproof comment on a pull request

One comment updated in place, a mergeproof commit status in the merge box, and a Check Run whose annotations land on the files concerned. Contributors put evidence in the PR description as a fenced block that agents can write and machines can read:

```evidence
environment: staging
links:
  - what: search with an empty query
    before: https://langfuse.example.com/project/p1/traces/trace-before
    after:  https://langfuse.example.com/project/p1/traces/trace-after
```

mergeproof explain tells anyone, human or agent, what the current diff still has to prove:

# What this change must prove (fail)

## source-needs-tests [block]
Triggered by `src/api/search.py`.

- ❌ unit tests touched: Each changed source file needs a changed test file.
  - src/api/search.py: expected a changed test matching tests/**/test_search*.py
- ⏳ CI check run matching `^unit` is green on the head commit.
  - now: only visible in GitHub mode

## Evidence block to add to the PR description

```evidence
environment: staging
links:
- what: <what was exercised>
  before: https://<host>/<path-to-run>
  after: https://<host>/<path-to-run>
```

Built-in checks

check proves
tests.changed changed source files come with changed tests, mapped by {capture} globs
files.changed the change touches, or avoids, certain paths
evidence.field a key in the evidence block exists and has an acceptable value
evidence.links before/after link pairs, optionally verified at their source
ci.job_passed a named check run on the head commit succeeded
review.human_verified a non-author human posted /verified <sha>; a new push invalidates it
agent.verdict an allowed automated reviewer posted a head-bound verdict block
pr.labels, pr.body labels present or absent; description sections, regex, length
shell a command from the policy exits 0

Parameters for each: mergeproof checks, or docs/policy.md. Anything vendor-specific is a plugin: docs/plugins.md.

For coding agents

mergeproof agent-prompt >> AGENTS.md     # the rules, rendered from the policy
mergeproof mcp                           # the same over MCP: explain, check, evidence_block, ...

Agents learn what to prove and check their own work before opening the PR. They cannot approve anything: human verification is the one requirement no token of theirs can satisfy. Details, the MCP tool table and tracing: docs/agents.md.

Documentation

docs/policy.md Rules, when matchers, severity, the evidence block, every check and its parameters
docs/github.md Workflow, action inputs, rulesets, the three report channels, posting as your own App, JUnit and reviewdog output
docs/agents.md AGENTS.md generation, the MCP server, OpenTelemetry export
docs/cli.md Every command, the JSON plumbing, output formats, exit codes
docs/plugins.md Writing checks and verifiers, packaging them
examples/ Three example projects with scenario fixtures the test suite runs, and a Langfuse verifier plugin
CONTRIBUTING.md Development setup, conventions, how releases happen

Run without installing

uvx --from 'mergeproof[mcp]' mergeproof explain
docker run --rm -v "$PWD":/repo ghcr.io/aryamanz29/mergeproof check --local

Images: ghcr.io/aryamanz29/mergeproof tagged X.Y.Z, X.Y, X, latest per release, edge for main.

How it compares

Danger runs rules written in JavaScript and comments on the PR. policy-bot enforces approval policies from GitHub-native data. Checklist actions fail on unticked boxes. Hosted evidence gates evaluate your artifacts on their servers. mergeproof is declarative, has a notion of evidence that can be verified at its source, explains itself to agents, and runs entirely in your CI.

License

MIT. Contributions welcome; see CONTRIBUTING.md.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mergeproof-0.3.0.tar.gz (110.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mergeproof-0.3.0-py3-none-any.whl (50.6 kB view details)

Uploaded Python 3

File details

Details for the file mergeproof-0.3.0.tar.gz.

File metadata

  • Download URL: mergeproof-0.3.0.tar.gz
  • Upload date:
  • Size: 110.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mergeproof-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3a3bb8ba19aafc62a46ef10c7ed344bdaf60095e0b0d7046f3867a016924c3c8
MD5 e916efd21709747d99fc38bd1ed5ec91
BLAKE2b-256 1f7ed9d89ad2ca9839349d997a42bb5cc3f92adfb77022f8fd06798c3f03d6dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for mergeproof-0.3.0.tar.gz:

Publisher: release.yml on Aryamanz29/mergeproof

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mergeproof-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: mergeproof-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 50.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mergeproof-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d98187154ca43d662a45b3d49615297c9b0c8080285b3c448d6dfdfe2059b472
MD5 5280c0ef6905d663518303577c637bf2
BLAKE2b-256 eff4c4e9a1a9ed6c8058d7fa16eff2a6c470d5344a9ab686c1de634f9da98f59

See more details on using hashes here.

Provenance

The following attestation bundles were made for mergeproof-0.3.0-py3-none-any.whl:

Publisher: release.yml on Aryamanz29/mergeproof

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

This release

0.3.0 This release

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page