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.