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 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 that rulesets can require, and file annotations on the job for anything that points at a file. 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.6.0.tar.gz (110.5 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.6.0-py3-none-any.whl (49.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for mergeproof-0.6.0.tar.gz
Algorithm Hash digest
SHA256 0444e0ac48c6c0a7ddd65783596a6dffcdd4c28472529f8766f41627c4731248
MD5 63787478dbaf76c68ba4e2b62af780fc
BLAKE2b-256 4d272d77cb0c09902bbe4a17698ce6bf45909793929317feccd788bb75fd6ef0

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: mergeproof-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 49.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.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 79292860a9e1018eaeae1ba7a2a2e73e9beba0e1b5ef49a7947cd13db6440082
MD5 969289a34fad66c3683085e1f445c4b1
BLAKE2b-256 d6607b15970dde1cfff1ac741d30558a0f2689dc437e4e479cc0bc37d3019c51

See more details on using hashes here.

Provenance

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

This release

0.6.0 This release

2 files

0.5.0

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