The distribution a report's verdict was collapsed from (#247).
data.risk is the worst of a repository's metrics. That makes two very
different repositories read identically:
one functional contributor, active this month -> "critical"
one functional contributor, silent two years -> "critical"The first is a bus-factor bet on a project someone is working on. The second
is an abandoned dependency. max/1 is the operation that loses the
difference, and it loses it after every threshold has already been applied,
so no amount of retuning reaches it.
Nor does a level above critical: the scale saturates exactly where
compounding matters most, and a fifth level would break every consumer of the
enum -- scripts/canary.sh, scripts/library-isolation.sh, the SARIF
mapping, and any customer gate.
So the verdict is left alone and the distribution reported beside it. No
weights, no 0-100 score, no normalisation: a weighted score needs weights,
and deciding whether bus factor outranks currency is a judgement there is no
evidence for. Counts need none, and they are enough to order 200 critical
dependencies by how much is wrong with each.
Summary
Functions
Builds the profile from a results map.
A sort key for "what should I look at first", higher being worse.
Functions
Builds the profile from a results map.
Works on atom-keyed results as the analyzer holds them and string-keyed ones
as they come back from JSON, because it matches on the values -- the risk
words themselves -- rather than on which keys are supposed to carry them.
That also means a field whose value is not a risk level is skipped rather
than counted: agentic_classification reads "human", "mixed" or "agent",
and is not a verdict about risk.
Metric names in elevated are returned as strings and sorted, so the field
is stable between two reports of the same repository.
@spec rank(map()) :: non_neg_integer()
A sort key for "what should I look at first", higher being worse.
A customer whose tree comes back half critical cannot act on the verdict:
measured across a 99-repository npm sample, 54% were critical and not one
was low. The word stops discriminating at that density, which is what this
orders through -- a repository with three critical metrics outranks one with
a single critical metric, though both read critical.
Lexicographic on the counts: criticals first, then highs, then mediums. The base is 100 rather than 10 because a report can carry more than nine metrics and a carry would silently make three highs outrank one critical.
Comparable within a report, not across them: it says which of these is worse, not how bad any of them is. A report with fewer metrics computed scores lower for that reason alone, so it is a ranking and never a score.