Period
Everything except rule health is scoped to a period — last 7 / 30 / 90 days, selected in the bar under the title. Export as CSV downloads every finding from every repository’s latest scan, tagged with its repository.Net change
The four figures beside the title summarise the period:Where findings go
One cohort followed forward: the findings that were first detected inside the period, and how far each of them got. Five stages — detected, triaged, fix sent, resolved, verified. Every stage is a subset of the first, so a bar’s height is the share of that cohort which reached it. A finding detected before the period does not join the cohort even if it was decided inside it; counting it would make a later stage taller than an earlier one, which a funnel cannot be. Read the amber lines rather than the numbers. Dismissals and acceptances are legitimate exits; a finding that came back on a later scan is not, because it means the fix did not hold. Fix sent counts findings that had a fix pull request opened for them. It says opened, never open: the count is of PRs that were sent, whatever became of them afterwards. Verified counts findings where the fix merged and a later scan then confirmed it gone, in that order. A merge on its own only proves somebody believed the finding was fixed; the scan is what proves it. A finding that disappeared before its fix merged is not verified either — the merge cannot be the reason. This stage reads an em dash rather than a zero on deployments with nopull_request webhook configured. Nothing there ever records a merge, so a 0
would say “nothing was verified” when it means “verification is not wired up”.
See PR checks for the webhook setup.
Where the history comes from
The funnel readsfinding_events, an append-only log of transitions written
alongside every state change. The ledger it replaced could only hold a
finding’s current state, which is why the regression stage used to be stuck
at zero: a scan clears resolved_at the moment a finding reappears, so nothing
survived to record the round trip.
Organizations that existed before the log had their history reconstructed from
the ledger’s timestamps. The ledger keeps one date per finding, so a finding
that was dismissed, reopened and dismissed again reconstructs as a single
decision. Where any of a period’s transitions were reconstructed rather than
recorded, the page says so under the funnel and gives the date real history
starts. Counts that include them are a floor, not a total.
Where the time goes
Two bars split a finding’s life at the verdict: how long it waited for a decision, and how long it survived after getting one. The prose underneath reads the comparison — if fixes take longer than verdicts, adding triagers moves the small number and review latency is the real lever.Accepted-risk budget
How much risk you’re carrying deliberately: acceptances still open, rules muted org-wide, and how many come back within the next 14 days. Expiries lists the next few by date, naming the rule and the repository each was accepted in. An accepted risk is a promise to revisit, so it carries a date and the nightly sweep returns it to the queue untriaged when that date passes — see triage.Two things the panel calls out rather than averaging away. Acceptances recorded
before expiry dates were required carry no date at all: they never come
back on their own, and the panel counts them separately so they cannot hide
among the dated ones. And an acceptance with no written reason is
un-reviewable — nothing else records why it was made — so that count is
flagged too.Rule mutes are the other half of this panel and they behave differently:
a muted rule has no expiry at all. See rule settings.
Rule health
One row per rule that fired in the latest scans: how often it fired, how often someone marked it a false positive, how often it was accepted as risk, and the resulting false-positive rate. A high rate is a property of the rule, not of the people dismissing it — so a rule above 50% is called out for muting, and a rule that is already muted but still reaching the queue is called out too. Both link straight to rule settings. This table deliberately has no per-person column. Every number is about a rule, a repository or a queue — the moment a dashboard ranks humans, people stop writing honest dismissal reasons and the data stops being worth reading.What is not measured
How long a pull request sat in review, and who it was waiting on. Pipefort records when a fix PR is opened and what became of it when it closes — but not the shape of the review in between, so Waiting on review reads— rather
than an approximation that would be read as measured.
On a deployment with no pull_request webhook configured, the outcome is not
recorded either, and the funnel’s Verified stage reads — for the same
reason.