DiffTriage - Pro PR Risk Gating for AI-Generated Code
difftriage is an open-source Python library for production-grade pull request risk analysis.
It scores change risk across blast radius, behavior change, test impact, schema/security sensitivity, AI uncertainty, and observability gaps. It then enforces configurable merge policy decisions: pass, review_required, block, and override_required_review.
Why DiffTriage
Teams shipping more AI-assisted code often face:
- more regressions in core paths,
- slower reviews,
- weak signal-to-noise in large diffs.
DiffTriage provides a deterministic, explainable risk gate with rule-level scoring so teams can move fast without blind merges.
Key Features
- Multi-factor risk model (9 weighted dimensions)
- Explainable scoring with per-rule contributions
- Policy decisions:
pass/review_required/block/override_required_review - Confidence bands near threshold boundaries
- False-positive controls for docs/tests-only changes
- Override governance with audit-friendly policy flags
- CI-friendly CLI with multiple output modes
- GitHub + PyPI release workflows (trusted publishing ready)
Installation
pip install difftriage
Requires Python 3.10+.
Quick Start
difftriage score \
--files-changed 12 \
--lines-added 420 \
--lines-deleted 130 \
--changed-path src/auth/service.py \
--changed-path db/migrations/001.sql \
--dependencies-changed \
--output text
Score directly from git diff
score-git collects diff stats from your repository and then scores the PR using the same risk model.
# Compare main..HEAD (explicit range)
difftriage score-git --range main..HEAD --output text
# Compare last commit (default base/head: HEAD~1..HEAD)
difftriage score-git --output json
# Staged-only changes (CI-friendly for pre-commit hooks)
difftriage score-git --staged --output markdown --exit-mode decision
Notes:
- Renames/copies are detected by default (
--rename-detection). Scoring uses the new path for risk rules. - Binary diffs (
--numstatshows-) are converted into heuristic churn using--treat-binary-as-lines(default250).
Example result:
- risk score + level
- decision + confidence
- top risk drivers
- rule scores
CLI Usage
Output formats:
--output text(default)--output json--output markdown
Exit semantics:
--exit-mode threshold:0pass2fail
--exit-mode decision:0pass3review required2block
Examples:
# JSON for automation
difftriage score --files-changed 8 --lines-added 140 --lines-deleted 35 --changed-path src/payments.py --output json
# Markdown for PR comments
difftriage score --files-changed 8 --lines-added 140 --lines-deleted 35 --changed-path src/payments.py --output markdown --exit-mode decision
Risk Model
Default weighted dimensions:
blast_radius(0.20)behavior_change(0.18)test_impact(0.16)complexity(0.12)dependency_config(0.10)data_schema(0.08)security_privacy(0.08)ai_uncertainty(0.05)observability_gap(0.03)
Scoring levels:
0-24: low25-49: medium50-74: high75-100: critical
Configuration
Create .difftriage.yml in repo root:
threshold: 50
review_threshold: 50
block_threshold: 75
enable_confidence_bands: true
weights:
blast_radius: 0.20
behavior_change: 0.18
test_impact: 0.16
complexity: 0.12
dependency_config: 0.10
data_schema: 0.08
security_privacy: 0.08
ai_uncertainty: 0.05
observability_gap: 0.03
rules:
risky_path_patterns: ["auth", "billing", "migrations", ".github/workflows", "infra", "config", "permissions", "token"]
schema_patterns: ["migrations", "schema", "models", "ddl"]
security_patterns: ["auth", "token", "permission", "secret", "privacy"]
observability_patterns: ["log", "metrics", "trace"]
safe_path_patterns: ["docs/", ".md", "tests/"]
policy:
docs_tests_only_max_score: 18
safe_change_max_score: 30
security_block_score: 70
schema_block_score: 78
schema_review_score: 45
dependency_review_score: 55
missing_tests_review_score: 45
override:
require_reason_min_length: 12
allow_score_override: true
allow_schema_override: true
allow_dependency_override: true
allow_security_override: true
CI Integration
DiffTriage is designed for CI gates:
difftriage score ... --output json --exit-mode decision
Recommended policy:
- treat
review_requiredas protected-branch reviewer gate, - treat
blockas merge stop, - allow audited overrides only for approved emergency paths.
Release and Publishing
This repo includes:
.github/workflows/ci.ymlfor tests + build checks.github/workflows/release.ymlfor tag-based PyPI publishing
Publish flow:
- Push tag
vX.Y.Z - Build artifacts
- Publish with
pypa/gh-action-pypi-publishvia GitHub OIDC
Local Validation
pip install -e . pytest build twine
pytest -q
python -m build
twine check dist/*
Contributing
Issues and pull requests are welcome.
License
MIT - see LICENSE.
Metadata
Release files for difftriage 0.2.7
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 | Actions |
|---|---|---|---|---|
| difftriage-0.2.7.tar.gz | 15.9 kB | Without provenance | Details for difftriage-0.2.7.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| difftriage-0.2.7-py3-none-any.whl | Python 3 | none | any | Details for difftriage-0.2.7-py3-none-any.whl |
Total release size: 30.6 kB
Release files / difftriage-0.2.7.tar.gz
| Download URL | difftriage-0.2.7.tar.gz |
|---|---|
| Size | 15.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fd99cb8fcc74f95ea7399e20c45ce19bb6b40e19fb2e93b0d978accf9624551f
|
|
BLAKE2b-256 checksum How to use checksums |
5fb2e4eaf92c9fbe8a3f26ef6bc57128e396974ab648963a09a7d4c4ae7c6a13
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Release files / difftriage-0.2.7-py3-none-any.whl
| Download URL | difftriage-0.2.7-py3-none-any.whl |
|---|---|
| Size | 14.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
170ad2ddcdc9993a15b3d7da534c29155d7b3442f7e8ce9d0991ee9a668003c5
|
|
BLAKE2b-256 checksum How to use checksums |
65587e7d47e933eff9103780da4480e147cc9d54fbda862d4d29b044ad05688f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Security for difftriage 0.2.7
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.