Reach and spread drive the tier; ambiguity is surfaced as a confidence
caveat elsewhere rather than inflating the score, so the headline stays
trustworthy. affected counts downstream files (excludes the target);
packages is the number of distinct packages they span.
Normalize the separators in a path label to /. Labels are built from
Path::display(), which uses \ on Windows, while every grouping rule in
this module and the reports splits on / — without this, on Windows every
file collapses into package . and the package count degrades to 1.
Map a repo-relative path to the package that owns it: the longest matching
workspace root, falling back to the top-level directory. workspaces is
expected to be sorted longest-root-first. Both the path and the workspace
roots are separator-normalized defensively, so Windows-style labels still
group correctly.