ADR-0002: Validation is capability-gated; nothing a payload asks for is silently dropped¶
- Status: accepted
- Date: 2026-07-13 (recorded 2026-10-24 from the initial design)
Context¶
The same canonical payload is sent to frameworks of very different expressiveness. A translator that quietly leaves out what a framework cannot represent produces models that look equivalent and are not: a cost minimised without a constraint the user wrote, a node without the demand the user placed there. Such differences are invisible in a successful solve and surface only as a wrong number.
Decision¶
Every target declares a capability profile (Capabilities()), a sparse
map from feature keys to true. The registry's generic gates reject a
payload that uses a feature the selected target does not claim, before any
target-specific code runs. Each target adds its own gates (ValidateJob)
for everything its emitter cannot render faithfully, and must do one of two
things with such a property: reject it with an error that names the
property and the target, or warn that it is approximated or dropped. A
property is never accepted and then ignored.
The claims are enforced in both directions: a capability-coverage test fails the build if a claimed feature has no runnable scenario behind it, and the frozen validation matrix fails the build if a verdict changes unnoticed.
Consequences¶
POST /validateis a real contract:200means the model the solver sees is the model the user wrote (up to the listed warnings);422names the first offending property.- Adding a feature means a schema field, a feature key, a scenario and the
gates — more ceremony than an ad-hoc
if, but every cell of the capability matrix stays provable. - Partial support is expressed as a gate on the shape, not as a silent fallback: Calliope 0.6 accepts single-term constraints and rejects multi-term ones with a pointer to the 0.7 target.
- The cost is friction for users who want "best effort": there is no mode
that ignores unsupported properties, by design. A warning-only policy for
a documented set of informational fields (
build_year,metadata) is the one concession.