Skip to main content

PR risk gate for AI-generated code: diff scoring, test impact checks, and merge policy enforcement.

Project description

difftriage Banner

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.

PyPI version Python License: MIT


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 (--numstat shows -) are converted into heuristic churn using --treat-binary-as-lines (default 250).

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:
    • 0 pass
    • 2 fail
  • --exit-mode decision:
    • 0 pass
    • 3 review required
    • 2 block

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: low
  • 25-49: medium
  • 50-74: high
  • 75-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_required as protected-branch reviewer gate,
  • treat block as merge stop,
  • allow audited overrides only for approved emergency paths.

Release and Publishing

This repo includes:

  • .github/workflows/ci.yml for tests + build checks
  • .github/workflows/release.yml for tag-based PyPI publishing

Publish flow:

  1. Push tag vX.Y.Z
  2. Build artifacts
  3. Publish with pypa/gh-action-pypi-publish via 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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

difftriage-0.2.6.tar.gz (14.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

difftriage-0.2.6-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

File details

Details for the file difftriage-0.2.6.tar.gz.

File metadata

  • Download URL: difftriage-0.2.6.tar.gz
  • Upload date:
  • Size: 14.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for difftriage-0.2.6.tar.gz
Algorithm Hash digest
SHA256 dbb38b7a4d84ca0414f01caa554e8985a8b0e4bdcf5b71e7faeb597be5e8e1a1
MD5 81a2f6405abd82850153ccfee22c6fc6
BLAKE2b-256 0d298bb4167620e673fa3083bc565d393126f4836debc54070d10d1e2051ca37

See more details on using hashes here.

File details

Details for the file difftriage-0.2.6-py3-none-any.whl.

File metadata

  • Download URL: difftriage-0.2.6-py3-none-any.whl
  • Upload date:
  • Size: 13.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for difftriage-0.2.6-py3-none-any.whl
Algorithm Hash digest
SHA256 c0089beb478bcfd5540845c4a2ed39332d62151020d83e1ca50871081aaace2b
MD5 a34a7c54e71ca8a5a0c2fe62b92ae758
BLAKE2b-256 0187fabe462f92b611aef374162e3e65034beccbf271198ae3af32e76576496d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page