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.5.0.tar.gz (109.1 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.5.0-py3-none-any.whl (48.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for mergeproof-0.5.0.tar.gz
Algorithm Hash digest
SHA256 3650e35f1ce586260f7d833dcabf121f55d1182665aa14c0c8d780b2396ca9de
MD5 50140f059c0ef444de5f57296efe514d
BLAKE2b-256 243649870e535dddb21125f396801e0d10a6a0700c064d610bb3d74c1c85122f

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: mergeproof-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 48.1 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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2799ed9b036355719601baf356ffb4d920085e609aa45f83e18ddb8992faded2
MD5 7610ae53d79115e49a21db07b44aedeb
BLAKE2b-256 45ffe146f8910e2f4eb84130acfd5cb37b1b2328f3c57cdf31f4ef9ef8b7de29

See more details on using hashes here.

Provenance

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

This release

0.5.0 This release

2 files

0.4.0

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