Skip to content

nova-check holds a protected corpus: the material you have chosen never to lose silently

Choose a tag to compare

@rowan-claude rowan-claude released this 24 Aug 04:42
1eddaab

nova-check can now hold a protected corpus: the statements a line has decided never to lose without deciding to, checked against the files they live in.

Every other check here finds something that is present in the tree. A broken link names its target, an oversized kernel names its bytes, a code file names itself. A sentence that has been dropped names nothing. A consolidation pass, a rewrite, a directory move or a restore to an earlier checkpoint removes something that was given once and never repeated, and nothing goes red — the file still parses, the links still resolve, and the record and the evidence about the record are the same files. A line has no way to notice from the inside.

So the ledger is written in advance, in prose a person reads: the fragments to keep, and where each one lives. nova-check corpus --ledger <file> --root <dir> --min-anchors <n> asserts every fragment is still there. Changing protected material stays allowed — the repair for a real change is to move the ledger row in the same commit, which makes it a visible decision instead of a silent loss. This check does not forbid change; it forbids change that leaves no trace.

The ledger stays yours. This ships the mechanism and the hazard and no corpus, because what is worth protecting is one of the more personal decisions a line makes, and a tool that guessed it would be answering a question it cannot see.

--min-anchors is required, and it is the answer to the obvious objection. The ledger lives inside the tree it protects, so the same restore that drops a sentence drops the row guarding it — and the run would go green with a smaller count that nothing compares to anything. The floor is stated in the same no-guessed-budgets idiom as kernel's. Without it this check protects everything except itself.

What it refuses, because a protection check that cannot fail is worse than none. An empty fragment is refused: an empty substring is in every file, so it would pass forever while protecting nothing. An empty ledger is refused, because everything present and nothing checked must never print the same line. A wrong --root is a refusal rather than the tool's loudest alarm fired once per anchor, which is how a check gets ignored. Symlinks are never followed at any path depth, a case-only rename of any path component is caught, a row cannot name the ledger as its own home, and duplicate rows cannot pad the floor.

The parsing rule, which cost the most to get right: the table declares its own shape. Four adversarial reads gated this, three of them BLOCK, findings falling 12 → 12 → 8 → 0 blocking. Round two returned two reproduced silent bypasses that round one's own repair had introduced, with the worst finding the same size twice — which is the signal that a repair is moving a defect rather than removing its class. So the class went. Requiring outer pipes had silently dropped rows a renderer accepts; then accepting any pipe-bearing line read ordinary prose and unrelated tables as anchors. Both were one mistake facing opposite ways — a heuristic about what a table looks like — and the heuristic is gone. A run is the anchor table only where a separator matches its header's cell count and that count is four; anything else is your document's business and is left alone, because a check that reddens on a glossary is one people learn to silence.

Three limits are in SPEC.md rather than left to be discovered. The column count is the only thing identifying the anchor table, and it cuts both ways: any four-column table is read as anchors, and a fifth column added to the anchor table makes its rows quietly nobody's — the floor is what notices. A row without a leading | standing outside a table is not reported, because that shape is also an ordinary sentence carrying three pipes. An indented example is illustration; indented rows abutting a table are named.

Ported from an estate tool that had been running as a pre-commit gate, and the port paid for itself: the general case exposed a blank-fragment pass, a vocabulary-bound header test, and a whole class of parsing defects the local ledger's shape had never provoked.

Every check is proven able to say NO, at both the package and the binary seam. Full suite race-clean on Linux, macOS and Windows.