canonic query
Resolve, compile, and execute a semantic query read-only.
--metrics/--dimensions/--filter/--via/--limit and -f are mutually exclusive: pick one way to build the query per invocation, since passing both is a usage error. The flags build the identical SemanticQuery a JSON file would deserialize: {"metrics": [...], "dimensions": [...], "filters": [...], "via": [...], "limit": null}. Use -f once a query grows more filters or joins than is comfortable inline. Without --harness, any matching assertions are informational only and never block. With --json, the output matches the MCP query tool’s payload byte-for-byte.
If a
--dimensions name exists on more than one join-reachable source, the query fails with ambiguous and a candidates list of alias.dimension values to qualify with. See Resolving ambiguous. If a metric’s join path to a dimension’s source is itself ambiguous (more than one route through declared joins), the query instead fails with ambiguous_join_path and a candidates list of alias sequences: pass one as --via (e.g. --via dim_customer,dim_sales_rep) to select that path.canonic sql
Execute a read-only SQL string on a named connection, the escape hatch for when no metric/dimension covers the question.
Non-
SELECT statements are rejected with READ_ONLY_VIOLATION (exit 11). Raw SQL bypasses the compiler entirely, so under an active tenancy policy canonic sql is additionally gated by the run_sql gate: refused with TENANT_FORBIDDEN (exit 24) unless the caller’s role allows run_sql and the target connection attests rls_enforced: true.
canonic assert
Run the accuracy harness over all loaded assertions and gate on the result. This is the CI integration that turns “>90% accuracy” from aspirational into measured.
Every executable assertion in
contracts/assertions/ is compiled, executed read-only, and compared to its expected value within tolerance. The harness reports accuracy = passed / total and prints any diverging checks. The --min-accuracy gate always applies to the canon accuracy, never the baseline.
With --baseline, the same assertions are also compiled against a resolver that only knows the raw physical schema: no curated bindings, aliases, or guardrails, so a metric name reachable only through an alias or composite binding fails to resolve. The gap between the two accuracy numbers (lift) is a measured, reproducible number for how much canon’s curated context is worth, rather than an asserted one.