Skip to main content
Contracts are the one layer that’s human-owned, not auto-maintained. They declare which definition is authoritative and what a compiled answer must satisfy. Governance decisions canonic surfaces but never makes for you. For the exhaustive field-by-field reference across all four contract file types, see the contract schema.

Canonical metric bindings

A binding (contracts/metrics/<metric>.yaml) resolves a logical metric name to exactly one owning definition:
Ambiguity rule: if a requested name matches zero or more than one active binding, the compiler doesn’t guess. It returns a structured AMBIGUOUS/UNRESOLVED error listing candidates, so the caller can refuse-and-ask instead of picking wrong.

Beyond single: composable metrics

Not every metric is one measure on one table. The binding’s kind selects a compilation strategy for metrics built from parts: Because ratio/weighted_avg components reference other metric names, each component keeps its own guardrails and provenance. A numerator’s guardrails fire automatically wherever it’s used. Every kind also accepts an optional population_filter, applied before aggregation on every leaf, for metrics that are only defined over a restricted population (e.g. excluding test accounts from active_customers). See the compiler for how each strategy actually compiles to SQL.

Guardrails

A guardrail declares a rule the compiler must enforce:
severity: error (the default) blocks the query, but severity: warn lets it through with a warnings[] entry instead. mandatory_filter has no “block” outcome to gate this way: its predicate is always injected regardless of severity, and severity: warn there only adds the warnings[] entry on top.

Trust score

Every compiled answer carries a trust tier: caution < provisional < trusted. It is a category with reasons, not a numeric score. It reports confidence in the context behind an answer (provenance, assertion coverage, finality, freshness), never a claim that the number itself is factually correct. Scoring is worst-signal-dominates. The tier starts at trusted and drops to the lowest tier forced by any active signal, with reasons listing only the signals tied at that worst tier. A min_trust guardrail enforces a floor on the served tier for a given context:
canonic audit includes a trust-tier worklist ranking every canonical metric worst-tier-first. See canonic audit.

Finality

Some metrics are served by two physical realizations along a freshness axis, a batch table that’s final, and a real-time table that’s provisional:
The compiler selects the right source per time window and tags every result row final or provisional. board_only_final pairs with a restrict_source guardrail so a board_reporting context sees only the final source.

Assertions

An assertion (contracts/assertions/<id>.yaml) is a trusted query → expected-result check:
canonic assert runs every assertion through the compiler and gates on the result: the CI integration that turns “>90% accuracy” from aspirational into measured. canonic query --harness runs matching assertions inline against a single query.

The contract ↔ compiler seam

The compiler never reads contract files directly. It asks a single resolver:
The resolver is the only authority on “what is canonical / what must be obeyed”. The compiler trusts its results and never reimplements canonicality logic. Results are deterministic and stably ordered, so identical queries compile to identical SQL every time.