semantics/<connection-id>/<name>.yaml and are what canonic ingest drafts from your live schema.
Shape of a semantic source
type uses a normalized internal type set (string, int, decimal, float, bool, date, timestamp, json) that the compiler’s dialect adapter maps to each connector’s native types; never hard-coded per source.
Additivity
Every measure declares whether it can be safely re-aggregated:additive: plainsum/count(*)/min/max. Safe to re-aggregate at any coarser grain, and safe across a join fanout once deduplicated to the measure’s own grain.semi_additive: additive over every dimension except one (typically time): balances, inventory snapshots, headcount.non_additive: cannot be derived from a partial sum: distinct counts, ratios, percentiles.
additivity flag on the measure is what lets the compiler’s fanout analysis decide, per query, whether it’s safe to just sum; see the compiler for how each class actually compiles.
Where semantic sources come from
You rarely hand-write these.canonic ingest introspects each connection’s live schema (or a dbt manifest, for definition connectors) and drafts semantic sources deterministically: typed columns and a grain candidate from the primary key are mechanical, no LLM involved. An LLM only helps with the fuzzy parts; naming a measure, proposing a grain when no primary key is declared; and every LLM-drafted proposal is labelled and reviewed like any other diff (see Ingestion & reconciliation).
meta.provenance records how a semantic source was born: board_approved and human_curated facts are never overwritten by new evidence; only inferred facts can be revised automatically, and even then only through a reviewable diff.