Commit dddd31b
committed
schema: make the negative harness targeted, and drop the overlaid gate
The harness asserted only that *something* objected to each broken
fixture. That is weak exactly where it matters: a fixture that rewrites
a file another layer reads makes that layer object by construction, so a
case could go on passing after the rule it exists to test was deleted.
Cases 13-43 are the whole set in that position — each rewrites
goal-file.json, which the family layer reads — and the lint carried a
special case standing that layer down for them, with a documented
asymmetry: an overlaid BASELINE was not stood down, so a schema negative
written against goal-file-baseline.json would have been masked the same
way 13-43 would have been.
Every fail() now carries a required keyword-only rule class, and every
fixture declares the class that must catch it in examples/broken/
README.md's "Caught by" column, read back at run time. A case passes
only if that class fired. The gate is deleted: family noise on a schema
case is noise the assertion ignores, in both directions.
The column is now load-bearing, so its drift is also caught: a fixture
with no row, a row naming no fixture, a duplicate row, and a cell naming
no class this lint can emit are all findings. Under `family` the
parenthetical is part of the class — hash, apply and ceremony are three
rules and a case must name the right one. Under `schema` it stays prose
the lint cannot produce, so it is documentation and is unchecked.
Also restores the exactly-one-finding property for the family cases,
which the previous commit cost them: holding both approval records to
the diff left each case's un-overlaid reject record disagreeing with
that case's own diff. Cases 49, 51, 52, 53 and 54 gain a reject-record
overlay asserting the DERIVED ceremony class and the case diff's own
hashes — never the deliberate error the accept overlay exists to make,
which is why 52 and 53's mirrors correctly say `privileged`.
Verified by mutation, not by the lint staying green:
- a case declaring the wrong class -> red;
- deleting goal-file.schema.json's schema_version const -> case 13 red
with "declares 'schema', but the finding(s) came from ['family
(apply)', 'family (hash)']", which is the exact failure the gate
existed to prevent, now caught without it;
- the same deletion against a negative written as a broken BASELINE ->
red, closing the gate's asymmetry;
- a fixture with no row, and a row with no fixture -> red;
- all 57 cases fire their declared class; all nine family cases fire
exactly one finding.
schema-lint: OK (8 schemas, 52 negative fixtures, 5 byte-class fixtures).
xref_lint unchanged (same 3 pre-existing unrelated findings).1 parent eeef627 commit dddd31b
7 files changed
Lines changed: 395 additions & 103 deletions
File tree
- bin
- examples/broken
- 49-baseline-hash-mismatch
- 51-non-empty-migration
- 52-ordinary-over-privileged-hunk
- 53-coverage-retreat-ordinary-class
- 54-no-op-hunk
0 commit comments