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, 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 check 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 and one mergeproof Check Run, requireable, 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 explain                       # what the current diff still has to prove

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. See 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 agent loop with the CLI, LLM reviewers
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 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.4.0.tar.gz (106.3 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.4.0-py3-none-any.whl (47.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for mergeproof-0.4.0.tar.gz
Algorithm Hash digest
SHA256 2e37f71d4b4f13260067914b411118b6d43bc09bc0e4b1b0f958220d8d457f6f
MD5 fe247591f6b91dce5774670b07a4f18d
BLAKE2b-256 72934a2a1e64bd49c02b46894ec05c7e30ac28645eeac4e0997a5f6cd18cacb8

See more details on using hashes here.

Provenance

The following attestation bundles were made for mergeproof-0.4.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.4.0-py3-none-any.whl.

File metadata

  • Download URL: mergeproof-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 47.5 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.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b69cda67193039ff82d4712fedc3dec1309020510ceb2c16febe7c6feb84651
MD5 db6f7ff2d8019deffb1fcb6cf8affb86
BLAKE2b-256 2d4c76926ad976f8f323794b984e5c81fd5c8731b78bac7c307c5f9084d832d0

See more details on using hashes here.

Provenance

The following attestation bundles were made for mergeproof-0.4.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

This release

0.4.0 This release

2 files

0.3.0

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