Commit Graph

4 Commits

Author SHA1 Message Date
bf2dc4ece7 refactor(validation): rename framework to match the validation idiom
The validation module already implemented the composable-rule idiom under
its own names (Check/Issue/SubjectContext) and a value-type Validator with
duplicated traversal machinery per layer. Renamed the core types to the
canonical names (Validation/ValidationError/ValidationErrorCollection/
ValidationContext/BuiltinValidation/AnyValidation), converted Validator to
a reference-type class with the two-tier default-rule split, and genericized
it over both Subject and Document via a new Traversable protocol so the
model and tagged layers share one walk engine instead of two copies. Wired
the JSON-representability rule set into the same shape and closed the two
missing pieces (unwrap combinator, JSON coverage/config-pin tests).
2026-07-12 18:10:00 +02:00
8f87a1ecd0 test(validation): extend the finding-coverage law to both layers
The finding-coverage meta-test governed only the model validator's default
checks. Bring the tagged validator's defaults under the same law, and make
the law precise as either layer grows past one check.

Each check now runs in isolation, in a validator holding only it, built from
the check's own AnyCheck. A fixture therefore cannot lean on a sibling check
to fail, which the previous model test (running the whole default validator)
would have allowed once a second model check shipped. Set-equality asserts
the fixtures cover exactly each layer's default checks.

The tagged set ships failing and near-miss fixtures for both built-in checks:
duplicate versus one-character-apart keys, and a built-in tag on the wrong
node kind versus a supported, kind-consistent one. A planted orphan fixture
was confirmed to fail both the set-equality and the isolation tests, then
removed. 405 tests pass.
2026-06-28 17:10:03 +02:00
d195dd3fa1 refactor(validation): retire the legacy Rule for one check type
A Rule was exactly a Check<Model.Value, Model.Value>: it fired on every
node, switched on the value itself, and carried the root. It was therefore a
second copy of the one check machinery, the duplication the validation idiom
exists to prevent (principle 10), now also resolved for the tagged layer.

Remove Rule and its Context. The model validator holds only checks; its
default is the type-directed BuiltinCheck.mappingKeysAreUnique; validating
takes a Check. Custom whole-tree rules become Check<Model.Value, Model.Value>
with the former context.root now context.document.

Behaviour is byte-identical: the mapping-key builtin reports the same issues
at the same paths in the same DFS order, so the public validate/collect/blank
surface is unchanged. All 399 tests pass; the coverage gate reconciles to 60
public types.
2026-06-28 16:43:31 +02:00
f901a3f04c test(validation): make finding coverage a tested law
Add the meta-test the validation idiom mandates: every rule in the default
validator ships a failing fixture and a near-miss (just-valid) fixture, kept
in a registry keyed by rule description. One meta-test asserts the registry
covers exactly the default rule set, naming any default rule without
fixtures or any orphaned fixture; another exercises each rule in isolation,
failing its failing fixture and passing its near miss so nothing proves a
rule quiet on valid input by accident.

A planted orphan fixture was confirmed to fail the set-equality meta-test
before being removed. Adding a default rule without its fixtures now fails a
test before the change is deliberate.
2026-06-28 10:17:48 +02:00