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

Uploaded Python 3

File details

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

File metadata

  • Download URL: difftriage-0.2.7.tar.gz
  • Upload date:
  • Size: 15.9 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.7.tar.gz
Algorithm Hash digest
SHA256 fd99cb8fcc74f95ea7399e20c45ce19bb6b40e19fb2e93b0d978accf9624551f
MD5 606b1b0b436b79e54a7a0c8fd690c23e
BLAKE2b-256 5fb2e4eaf92c9fbe8a3f26ef6bc57128e396974ab648963a09a7d4c4ae7c6a13

See more details on using hashes here.

File details

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

File metadata

  • Download URL: difftriage-0.2.7-py3-none-any.whl
  • Upload date:
  • Size: 14.7 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.7-py3-none-any.whl
Algorithm Hash digest
SHA256 170ad2ddcdc9993a15b3d7da534c29155d7b3442f7e8ce9d0991ee9a668003c5
MD5 ca97d29dbd447099391cb03ffb8178d6
BLAKE2b-256 65587e7d47e933eff9103780da4480e147cc9d54fbda862d4d29b044ad05688f

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