PR Verify
Deterministic trust for agent-authored PRs. Not another AI reviewer — verification, not opinion. Agents now write more code than seniors can review; this tells a senior exactly how deep to review, from observable facts: which lines an agent wrote, what could break, and whether policy gates pass.
Install
git clone <repo> && cd pr-verify
pip install . # provides the `pr-verify` console script
Or run without installing: python3 -m pr_verify from the repo root.
Quick start
cd your-repo
python3 -m pr_verify init # write an example .pr-verify.yaml
python3 -m pr_verify check --base main
What it reports
Provenance — every added line labeled agent/human via git blame +
commit-author analysis (configurable markers: claude, codex, cursor,
copilot, bot…). Per file: agent / mixed / human, with the detected
agent identities.
Blast radius — reverse dependency graph: for each changed file, the transitive set of in-repo dependents that could break. Python via AST; JS/TS/Go/Rust/Java/Ruby/PHP via heuristic fallback.
Policy gates — commands from .pr-verify.yaml (tests, typecheck,
lint), run with timeout, pass/fail captured. The config is read from the
base ref (never the worktree under review) and gates run without a
shell — ;, &&, $(), pipes and the rest are literal arguments, never
interpreted. A failing gate fails the verification (nonzero exit).
Risk score — deterministic 0–100 from six public factors:
| Factor | Max | What it measures |
|---|---|---|
| agent_share | 40 | % of added lines agent-authored |
| blast | 25 | log-scaled transitive dependents |
| sensitive | 20 | changed files under sensitive globs (auth, crypto, payments, migrations…); deleted files match like touched ones |
| gates | 10 | any policy gate failed |
| no_tests | 5 | source changed with no test changes |
| deletion | 50 | agent-attributed deletions: 45 if any deleted file is sensitive, else 10 for deleting tracked files at all, plus log-scaled points for the deleted files' dependents — pure-deletion PRs can trip the threshold too |
Bands: 0–29 low · 30–69 medium · 70–100 high. The formula is documented so teams can argue with it and tune it — a black-box score is just another opinion.
CI
python3 -m pr_verify check --base origin/main --format json --fail-on high
--fail-on high (default) exits 1 when score ≥ risk_threshold (70).
--fail-on any-risk / --fail-on never available. A GitHub Action is
included at .github/workflows/pr-verify.yml.
Example output
════════════════════════════════════════════════════════
PR VERIFY risk 57/100 (MEDIUM)
════════════════════════════════════════════════════════
provenance: 9/13 added lines agent-authored
agent app/auth.py (4/4 agent) [claude-bot]
mixed app/core.py (4/8 agent) [claude-bot]
agent app/views.py (1/1 agent) [claude-bot]
blast radius:
app/core.py: 1 downstream dependent(s)
direct: app/views.py
risk factors:
28 pts agent_share 9/13 added lines agent-authored (69%)
4 pts blast largest blast radius: 1 downstream dependent(s)
20 pts sensitive sensitive files touched: app/auth.py
0 pts gates no gates configured
5 pts no_tests source changed with no test changes
✓ score 57 < threshold 70
════════════════════════════════════════════════════════
Honest limits
- Provenance depends on commit authorship — squashed or rebased PRs lose
per-commit attribution (tune
agent_markersfor your workflow). Uncommitted working-tree changes are included incheck, but with no commit to blame they are counted as human-written, never agent-written. - Non-Python blast-radius extraction is heuristic.
- The risk formula is a starting point, not a verdict — tune the threshold per team.
Tests
55/55 pass: python3 -m unittest discover -s tests
Metadata
Release files for pr-verify 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pr_verify-0.1.0.tar.gz | 24.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pr_verify-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.7 kB
Release files / pr_verify-0.1.0.tar.gz
| Download URL | pr_verify-0.1.0.tar.gz |
|---|---|
| Size | 24.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
428c916c21981690bfa5eacd1699cc85d1cd29d40b47c637d9652a204f4eaece
|
|
BLAKE2b-256 checksum How to use checksums |
3c245807cec46a645d27d3fe51ba1761619af1aa0e33d340d609224e99ca6465
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / pr_verify-0.1.0-py3-none-any.whl
| Download URL | pr_verify-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d688c79956e817e8ee4c74eb80232c4a64d045abab4a8e68b2c053779f2dd140
|
|
BLAKE2b-256 checksum How to use checksums |
120d1516a7ad72bebff885c56c37730326e1bf510178fd06d955e7d6b0b9a312
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for pr-verify 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.