3c05025b

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

A rule that sees every package at once, and the build that feeds it

Stacked on the package PR. Adds TestGenValidSpecPerGenValid from testing.md,
which is the flagship: for every GenValid instance, a genValidSpec call in the
matching gen package's test suite. An obligation made and an obligation met are
different facts, found in different packages, so the check between them is a
left join and a null check.

That rule needs two things nothing before it did.

It needs the compiler. A GenValid instance a splice produced appears in no
source, and a genValidSpec call a splice produced appears in no source either,
so each unmet obligation is put to the artifacts before it is reported. Reading
them is its own package, because the ghc library and ghc-lib-parser both expose
modules under GHC. and one component cannot import both. The artifacts are not
optional: given any .hie directories, every module read must have both a .hie
and a .hi or the run fails naming the module, because a tree missing one module
is indistinguishable at the point of use from no tree at all.

It needs to see every package at once, which is what the process boundary is
for. Facts cross it; source does not. A package is read once into a SQLite
store and the project layer answers from those stores alone, so the Nix side is
one derivation per package plus one for the repository, and changing one
package rebuilds three derivations rather than all of them. That the two paths
agree is a property in the suite, per project rule, so a fact a project rule
reads out of memory and extraction never serialises fails the tests rather than
the build.

With it come the Nix builders a consuming flake calls, the end to end tests
over them, and the plan documents, which describe this architecture and so are
only true once it exists.

The corpus gains a row for HsNoCustomShowRead: 22 on nix-ci, 2 on sydtest, 1 on
centjes, each checked by hand and recorded in plan/context.md. nix-ci's 22 are
all Show written to hide a secret, which is the exception haskell-style.md
names, so they are suppressions to write rather than instances to change.