Suppress a finding, and turn a rule off Stacked on #5. Review that first; this diff is against it. Adds `CommentBareTodo` from `comments.md`, and with it the two things that make a checker adoptable at all: a way to say no to a finding, and a way to turn a rule off. 110 files, 3,359 lines. 226 tests. ## The keystone **A suppression that answers for nothing is an error.** That is what makes on-by-default with unlimited local escapes safe, and it is why there is no config file of exceptions that nobody reads. All of these fail the run in their own right: - one that has outlived the finding it was written for - one that answers for more than one finding at once - one naming a rule nothing answers to, or a rule this repository turned off - one with no reason - one written where it cannot attach to anything - one in a file no cabal component claims, which is watched by nobody **A suppression the report offers must be one the parser accepts.** The report tells you what to write and where. If the next run then rejected it, the tool would have lied. ## Which rules run `hopinion.yaml` at the repository root, not a flag, and there is no flag anywhere. The development loop and CI read the same file, so they cannot disagree about which rules they ran. Every way of getting that file wrong is refused rather than ignored, because each one reads as a rule turned off and behaves as a rule still running: an unknown key, a name that is not a rule id, a rule nothing answers to, a document that is not a mapping. ## What this rests on The comment attachment pass, computed here in an explicit pass over spans rather than taken from where exact-print annotations put a comment. That placement answers "where must this be reprinted", not "what is this about", and the two differ exactly where it would matter. The most consequential decision in it: **a blank line between a comment and the code below means the comment is not attached to that code.** ## Still not here One level, no fact store, nothing reads what the compiler wrote down. Neither rule needs any of it. weeder removed `readChoicesFrom` on the way in, because the flag it exists for belongs to a command that does not exist yet. ## Review loop ``` nix flake check nix develop --command cabal test hopinion-test --test-options="--ai-executor" ```