aa42355d

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

Producing a report always succeeds; only judging one fails

Four exit codes said what kind of complaint a run had, which meant a checker
failed by failing, which meant its report went with the derivation. Now every
command either produces a report or judges one. package and project write
report.json and report.txt to --report-out and succeed whatever is in them, and
one small judge derivation reads them and fails. The report survives either
way, which is the point. check and module still decide for themselves, because
a person running one wants the shell to know the answer.

That leaves two exit codes, and which kind of complaint it was is in the report
rather than in a number.

RunReport splits into Complaints and RunStats. A clean run is now
'runReportComplaints report == mempty' rather than four field assertions and a
blanking helper the tests had to carry, and it is stronger: nothing checked
over-broad suppressions before. Reports get codecs, generators and jsonSpecs,
because a report crosses a process boundary the same way facts do.

runStatsRulesRun is a Set. It was a list built once per module per rule and
nub'ed at render time to print one integer, which on nix-ci meant about 800
entries for the number 3.

The over-broad pair becomes an OverBroad record, so neither end can be read for
the other.

A --source that maps nothing is a complaint now. It used to mean a report with
no code under it and nobody the wiser, which is the same silent degradation the
fact-file check exists to prevent, one flag over. There is an end to end check
for it.

Writing the report text goes through explicit UTF-8 rather than a text handle:
a Nix build runs under the C locale, and this is the second time that has bitten
a box-drawing character. This time the new shape caught it, because the report
derivation failed loudly instead of a judgement passing quietly.