Browse docs
Docs /signals/overview
The four signals

Signals overview

Izri computes four independent signals and aggregates them into a single izri/quality verdict. This page is the aggregation model in full: if you want to predict whether a given finding will block your merge, everything you need is here.

The four children

Check Question
izri/scope Does the diff match its stated intent?
izri/tests Did the relevant tests run and pass?
izri/hallucination Did those tests exercise the changed lines?
izri/visual Did the rendered UI change?

Each publishes as its own GitHub check alongside the izri/quality umbrella.

Two ways to fail

The umbrella aggregates the children through two independent mechanisms. Understanding which one fired is the whole diagnostic.

1. Hard rules — worst-of

One hard finding fails the umbrella regardless of every other signal. There is no averaging, no override, no threshold to clear. The list is deliberately short:

Hard rule Source Why it's absolute
pr_type_forbidden_category scope The diff changed a category the PR's declared type forbids.
change_uncovered hallucination No test exercised the diff at all. The silent-regression case.
analyzer error any An analyzer crashed. Signal-agnostic — triggered by the row's error status, not a finding category.

An analyzer crash being a hard rule is deliberate. A crashed analyzer produces no findings, and "no findings" must never be mistaken for "nothing wrong."

2. Soft signals — weighted composite

Everything else feeds a weighted average that must reach 70.

Signal Weight
Hallucination coverage 0.40
Test pass rate 0.36
Scope alignment 0.24
Visual diff 0.15

Hallucination carries the most weight on purpose: a partially covered diff should drag the composite down even when scope and tests look clean.

Absent signals redistribute, they don't penalize. Weights are proportionally renormalized across the signals that actually ran. A backend PR that skips izri/visual scores exactly as it would have if the visual signal didn't exist. Skipped is not zero.

Severities

Every finding carries info, warn, or error. Only error blocks by default.

Severity Effect
error Blocks. Hard rules are emitted at this level.
warn Contributes to the composite. Does not block on its own.
info Advisory. A "look here" pointer with no gating effect.

This is why sensitive_path doesn't fail your build — it is emitted at info. It flags that a diff touched something worth a human glance, which is not the same as saying the diff is wrong.

Full findings reference

Every category the analyzers emit, and what each one does:

Scope

Category Severity Meaning
pr_type_forbidden_category error Change in a category the declared PR type forbids. Hard rule.
pr_type_mismatch warn The diff doesn't look like what the PR type claims.
test_removal warn Tests were deleted.
scale_anomaly warn / info The diff is much larger or smaller than the stated intent implies.
structural_drift info Module boundaries shifted.
sensitive_path info A path your config marks sensitive was touched.

Hallucination

Category Severity Meaning
change_uncovered error No test exercised the changed lines. Hard rule.
change_partially_covered warn Some changed lines were exercised, some weren't.
low_overall_coverage warn Project coverage is low enough to weaken the signal.
file_not_instrumented info The coverage tool never saw the file. Could be a filter, could be a gap.

The three umbrella states

State Meaning
passing No hard rule fired, composite ≥ 70.
failing A hard rule fired, or composite < 70.
unknown Not enough signal — delta in flight, or every child skipped.

Treat unknown as "wait", never as "go".

Reading this with an agent? /docs/signals/overview.md serves the raw markdown.

Edit this page on GitHub →All docs