Signals

Every signal is a pure, deterministic function over the change surface and the repository’s git history. No model, no network. Each contributes a risk in 0...1, carries a documented weight, and emits a human-readable detail. The per-file score is the weight-normalized blend; see architecture.md for how the blend and aggregation work.

The weights

The prior weights sum to 1.0. They live in RiskEngine.Weights and are overridable per field via .augur.toml [weights] (see configuration.md).

SignalWeightWhat it catches
sensitivity0.2024Touches secrets, auth, crypto, payments, migrations, infra, CI, or dependency manifests.
test-gap0.1656Code changed with no test in the changeset, or, with coverage, the uncovered fraction of changed lines.
churn0.1380Hot files that change constantly are fragile.
coupling0.1196A file’s usual co-change partner is absent from the change.
diff-shape0.1104Large single-file edits are harder to review.
ownership0.0920Bus-factor (single author) or diffuse ownership (many authors).
incident0.0920The file’s own history of reverts / hotfixes (calibrated).
codeowners0.0800A changed file with no declared CODEOWNERS owner.

Why these exact decimals? The codeowners signal (added in spec v7) claimed a weight of 0.08. To keep the blend summing to 1.0 without changing the relative importance of the seven original signals, each of them was scaled by 1 − 0.08 = 0.92. So sensitivity went from 0.22 to 0.22 × 0.92 = 0.2024, and so on. The ratios between the original seven are unchanged.

Signal reference

sensitivity

Matches the changed path against a configurable ruleset (SensitivityRuleset). The highest-severity matching category sets the risk. Built-in categories, by descending severity:

CategoryRiskExample fragments
secrets1.0.env, secret, credential, .pem
auth0.9auth, login, session, token, oauth
crypto0.85crypto, encrypt, signing, keychain
payments0.85payment, billing, stripe, checkout
migration0.8migration, schema, /sql/
infra0.7dockerfile, terraform, k8s, helm
ci0.6.github/workflows, .gitlab-ci, circleci
dependencies0.55package.json, cargo.toml, go.mod

Tune: add rules via .augur.toml [[rules]] (merged onto defaults), or set [sensitivity] replace_defaults = true to use only your rules.

test-gap

Without coverage, a coarse heuristic: did the changeset touch any test file?

  • test file → 0; binary asset → 0.1; a sibling test in the changeset → 0.15; code with no test → 0.7.

With a --coverage report it becomes precise for non-test code files: risk = 1 − covered/instrumented over the change’s instrumented added lines; a code file entirely absent from the report scores 0.7. See coverage.md.

Tune: supply a coverage report to sharpen it; raise [weights] test_gap if test discipline matters most to you.

churn

risk = min(1, recent_commits_touching_file / 40). Files that change constantly are statistically fragile.

Tune: the divisor is fixed; adjust importance via [weights] churn.

coupling

If a file’s strongest historical co-change partner (seen together ≥ 4 times) is absent from the current change, that’s a broken co-change pattern → 0.6. Otherwise 0.

Tune: [weights] coupling.

diff-shape

risk = min(1, lines_touched / 400) (binary files: 0.2). Large single-file edits are harder to review well.

Tune: [weights] diff_shape.

ownership

A U-shaped curve on distinct historical authors:

AuthorsRiskWhy
00.3new / untracked file
10.35single author (bus-factor)
2–40.1healthy
5+0.6diffuse ownership

This is the git-history ownership signal, distinct from codeowners (which is about declared review routing).

Tune: [weights] ownership.

incident

0.8 if the file appears in commits whose subjects look like reverts / hotfixes / fix follow-ups, multiplied by the calibration confidence. On a history-free repo this contributes 0; in a repo with deep history and real incidents it sharpens. The detail reports the calibration factor.

Tune: [weights] incident. Run augur calibrate to back it with history.

codeowners

Flags review-routing gaps using the repo’s CODEOWNERS file. Behavior:

  • No CODEOWNERS file0 (neutral). Repos without one are never penalized.
  • Changed file with no declared owner0.6, detail no CODEOWNERS owner.
  • Owned file0, detail owned by @team, @user.

augur auto-discovers CODEOWNERS at .github/CODEOWNERS, CODEOWNERS, or docs/CODEOWNERS (GitHub precedence; first found wins). Matching follows GitHub semantics (last matching pattern wins) and reuses the same GlobPattern engine as path exclusions. Disable with --no-codeowners.

# .github/CODEOWNERS
*            @platform        # catch-all
/src/        @backend-team    # overrides the catch-all for src/
/src/auth/   @security        # overrides again for src/auth/
*.md         @docs-team

Tune: [weights] codeowners. Set it to 0 to disable the signal’s contribution entirely while keeping the rest of the blend (or just pass --no-codeowners).