Risk signals: what opendrs measures

This page lists every signal that goes into the opendrs risk score and how each one is computed, for anyone who wants to read a PR comment’s breakdown or tune the model.

Meta’s DRS features and their opendrs signals

Meta’s baseline is a logistic regression over about a dozen features, chosen from about 100 (paper). opendrs computes each one from git alone:

Meta DRS feature opendrs signal How it is computed
Log of added/deleted lines relative to file size size.churn, size.relative log1p of changed lines, and of changed lines over base file length; lockfiles, generated and vendored files excluded
Diff creates new files only size.new_files_only 1 when every changed file is new
Comment-only change (“has no risk”, §II-B) size.comment_only 1 when every added or deleted line is blank or a plain comment in the file’s own syntax (not a lone /* or */, not a directive such as //go:embed or // @ts-nocheck), with no renames or binary files
Log of number of files diffusion.files, diffusion.dirs log1p of changed files and of distinct top-level directories
Log of distinct authors of the changed files diffusion.authors log1p of distinct authors in the files’ history
Previous SEV in the file history.incident, history.prior_fixes a recorded incident or revert touched the exact file (or an explicit incidents.jsonl paths prefix); log1p of fix and revert commits in the lookback window
High-criticality service paths.critical changed file matches paths.critical globs
Total logical complexity complexity.touched log1p of branch keywords in the touched files (language-agnostic heuristic)
Language indicators lang.* one indicator per language family present
Author created the file expertise.owner_ratio share of changed files the author created or mostly wrote
Author’s landed diffs expertise.author_commits log1p of the author’s prior commits; negative weight
Test plan tests.missing 1 when source changed and no test lines were added; otherwise max(0, 1 − addedTestLines / (0.3 · sourceLines)) (a proxy). Deleted test lines never count
(not in Meta’s list) tests.deleted 1 when a test file is deleted (or renamed out of paths.tests), or 10 or more test lines more are deleted than added. Also a policy rule: such a PR always goes to a human
LLM risk model (iDiffLlama) llm.semantic max(0, logit(p) − logit(0.2)) from an optional prompted LLM judge: it can only raise risk
(RADAR’s LLM reviewer) llm.risk.* 1 when the judge puts any hunk in that risk category (logic_bug, security, performance, structural, complex); weights are never negative
(not in Meta’s list) blast.dependents, blast.public_surface transitive dependents of the changed files (depth 3) from the import graph; exported symbols changed in a file that has dependents
(not in Meta’s list) history.churn log1p of commits touching the files in the lookback window

Import-graph languages

The import graph uses regex-based extractors for TypeScript/JavaScript, Python, Go, Java/Kotlin, Rust and Ruby. Files in other languages get unknown blast-radius signals, which the policy treats as risk, not as zero. How the blast-radius signals are measured is explained in What is the blast radius of a pull request?.

LLM signals

The llm.semantic and llm.risk.* signals come from the optional LLM judge, which can only raise a score, never lower it. How it is configured, how it classifies hunks and how it can gate auto-approval are on LLM judge.

The signals are combined by a logistic model whose weights opendrs calibrate fits to your repository’s history; see Calibration and backtesting and the README.

Updated 24 Oct 2026 · Edit this page on GitHub