Dosi Semantic Authoring
Author the active Dosi semantic model as strict OSI core YAML. Use this skill for native document authoring rules; use the active adapter specification and native validation as the exact document and DATUS-extension contract. The node prompt owns target selection, result-set strategy, mutation order, validation, and synchronization.
Model reusable semantics
- Keep one
semantic_model per file and stable snake_case names. Preserve unrelated content; an upsert replaces the complete same-named object.
- Bind a dataset to a qualified physical table or a complete reusable SELECT. Declare every referenced physical column as a field with the active OSI dialect.
- Mark time fields with
dimension: {is_time: true}. Keep other fields available as dimensions.
- Use source DDL as the only evidence for new key declarations. For a physical table, transcribe its declared physical primary key into
primary_key and its declared unique constraints or whole-table unique indexes on plain columns into unique_keys. Preserve each complete composite key and its declared column order. Partial or expression indexes do not establish a whole-table key on their named columns. ClickHouse PRIMARY KEY/ORDER BY and StarRocks/Doris DUPLICATE KEY are sort keys, not uniqueness declarations.
- Do not execute data queries to discover or verify keys, including full-table NULL/duplicate checks. Samples, approximate distinct counts, column names, SQL JOINs, and stated grain are not substitutes for DDL key declarations.
- If the DDL is unavailable or declares no usable key, leave the key undeclared and continue modeling fields, datasets, and independent metrics. Do not block the whole request or ask to scan the table to fill the gap. For a query-backed dataset, retain a DDL-declared source key only when the query provably preserves it; a one-to-many join can repeat it. Otherwise leave the key undeclared without scanning the source or query result.
- Give a field a
label when its column name is not what a reader would call it.
- Give a dataset
ai_context.instructions when its grain or intended use does not follow from the description, and give a field ai_context.synonyms when users ask for it by a name the column does not carry. Leave both out otherwise: restating the description dilutes what a reader can act on.
- Define model-level relationships with aligned
from_columns and to_columns; bind the target columns to one complete DDL-declared key that holds at the target dataset's grain. If no such key is available, omit the new relationship and any metrics that cannot be faithfully modeled without it, explain the omission, and continue with the remaining assets. Do not invent a key to make a relationship or metric compile.
Choose DATUS metric capabilities
Put Dosi-only metadata in the owning object's DATUS custom_extensions entry. Encode data as one JSON-object string and stamp it with the runtime <datus_extension_version>. The injected active DATUS extension specification is authoritative for supported carriers, keys, exact shapes, enums, constraints, and examples; never invent a field from this conceptual guide.
Prefer a plain base metric when one aggregate or arithmetic expression completely represents the business meaning.
Use a derived filter metric when the business concept narrows one reusable base metric. Use a derived compose metric only when the result combines two or more reusable metrics. Author and validate every referenced base metric first; do not inline its calculation again or create a one-input passthrough.
Use a structured window metric for period comparison, rolling, cumulative, ranking, distribution, or framed statistical calculations. Keep the underlying OSI expression as the plain aggregate described by the active contract.
Use a parameterized metric only when different callers must supply a bounded runtime business input to the same reusable definition. Stable policy belongs in the metric itself. Declare each parameter's type, default, and allowed values or bounds according to the active contract.
Use explicit measure metadata only when the metric needs a stable engine-facing measure identity or behavior that cannot be inferred from its OSI expression.
Combine capabilities only when the active contract explicitly permits their keys and dependencies on the same carrier. If the requested capability is absent from that contract, report it as unsupported by the installed engine instead of approximating it in YAML.
Use time_dimension to resolve the business time when inference is ambiguous; qualify metric-level references when field names collide.
Use time_granularity for the field's stored grain and join_type for left or inner relationship behavior.
Use metric dataset to attribute an otherwise unbound aggregate such as COUNT(*).
Give each business metric a description, ai_context.instructions, and a three-level subject_path.
- name: revenue
description: Total order revenue
ai_context: {instructions: Use order_date as business time.}
expression: {dialects: [{dialect: <osi_dialect>, expression: SUM(orders.amount)}]}
custom_extensions:
- vendor_name: DATUS
data: '{"v":"<datus_extension_version>","time_dimension":"orders.order_date","subject_path":["sales","revenue","total"],"unit":"USD"}'
Author base and window metrics
Express a base metric with its natural aggregate, ratio, or arithmetic expression. Put a durable metric condition inside its aggregate with CASE WHEN.
Express each window result as a standalone metric whose OSI expression is one plain aggregate. Put the derivation in one structured window object.
Choose the window family from the intended calculation and use the exact form advertised by the active contract.
Derive time, query grain, ordering, partition, and frame from the requested analytic meaning. Treat query grain as a runtime argument.
Reuse a window metric only when its base aggregate, time axis, calculation, ordering, partition, and frame all match.
Preserve meaningful window nulls for missing comparison buckets or incomplete required frames.
Validate the final model with the native Dosi parser/compiler after the last mutation.
For a parameterized metric, inspect its param_schema in list_metrics, then verify query behavior with query_metrics(params={...}, dry_run=True). Exercise the default and meaningful enum/boundary or list-valued cases; never invent undeclared parameter names. Native validation proves the definition compiles, while this optional query check proves a user-requested binding shape.
1---2name: dosi-semantic-authoring3description: Dosi native OSI dataset, relationship, and metric authoring guidance4---56# Dosi Semantic Authoring78Author the active Dosi semantic model as strict OSI core YAML. Use this skill for native document authoring rules; use the active adapter specification and native validation as the exact document and DATUS-extension contract. The node prompt owns target selection, result-set strategy, mutation order, validation, and synchronization.910## Model reusable semantics1112- Keep one `semantic_model` per file and stable `snake_case` names. Preserve unrelated content; an upsert replaces the complete same-named object.13- Bind a dataset to a qualified physical table or a complete reusable SELECT. Declare every referenced physical column as a field with the active OSI dialect.14- Mark time fields with `dimension: {is_time: true}`. Keep other fields available as dimensions.15- Use source DDL as the only evidence for new key declarations. For a physical table, transcribe its declared physical primary key into `primary_key` and its declared unique constraints or whole-table unique indexes on plain columns into `unique_keys`. Preserve each complete composite key and its declared column order. Partial or expression indexes do not establish a whole-table key on their named columns. ClickHouse `PRIMARY KEY`/`ORDER BY` and StarRocks/Doris `DUPLICATE KEY` are sort keys, not uniqueness declarations.16- Do not execute data queries to discover or verify keys, including full-table NULL/duplicate checks. Samples, approximate distinct counts, column names, SQL JOINs, and stated grain are not substitutes for DDL key declarations.17- If the DDL is unavailable or declares no usable key, leave the key undeclared and continue modeling fields, datasets, and independent metrics. Do not block the whole request or ask to scan the table to fill the gap. For a query-backed dataset, retain a DDL-declared source key only when the query provably preserves it; a one-to-many join can repeat it. Otherwise leave the key undeclared without scanning the source or query result.18- Give a field a `label` when its column name is not what a reader would call it.19- Give a dataset `ai_context.instructions` when its grain or intended use does not follow from the description, and give a field `ai_context.synonyms` when users ask for it by a name the column does not carry. Leave both out otherwise: restating the description dilutes what a reader can act on.20- Define model-level relationships with aligned `from_columns` and `to_columns`; bind the target columns to one complete DDL-declared key that holds at the target dataset's grain. If no such key is available, omit the new relationship and any metrics that cannot be faithfully modeled without it, explain the omission, and continue with the remaining assets. Do not invent a key to make a relationship or metric compile.2122## Choose DATUS metric capabilities2324Put Dosi-only metadata in the owning object's DATUS `custom_extensions` entry. Encode `data` as one JSON-object string and stamp it with the runtime `<datus_extension_version>`. The injected active DATUS extension specification is authoritative for supported carriers, keys, exact shapes, enums, constraints, and examples; never invent a field from this conceptual guide.2526- Prefer a plain base metric when one aggregate or arithmetic expression completely represents the business meaning.27- Use a derived filter metric when the business concept narrows one reusable base metric. Use a derived compose metric only when the result combines two or more reusable metrics. Author and validate every referenced base metric first; do not inline its calculation again or create a one-input passthrough.28- Use a structured window metric for period comparison, rolling, cumulative, ranking, distribution, or framed statistical calculations. Keep the underlying OSI expression as the plain aggregate described by the active contract.29- Use a parameterized metric only when different callers must supply a bounded runtime business input to the same reusable definition. Stable policy belongs in the metric itself. Declare each parameter's type, default, and allowed values or bounds according to the active contract.30- Use explicit measure metadata only when the metric needs a stable engine-facing measure identity or behavior that cannot be inferred from its OSI expression.31- Combine capabilities only when the active contract explicitly permits their keys and dependencies on the same carrier. If the requested capability is absent from that contract, report it as unsupported by the installed engine instead of approximating it in YAML.3233- Use `time_dimension` to resolve the business time when inference is ambiguous; qualify metric-level references when field names collide.34- Use `time_granularity` for the field's stored grain and `join_type` for `left` or `inner` relationship behavior.35- Use metric `dataset` to attribute an otherwise unbound aggregate such as `COUNT(*)`.36- Give each business metric a description, `ai_context.instructions`, and a three-level `subject_path`.3738```yaml39- name: revenue40 description: Total order revenue41 ai_context: {instructions: Use order_date as business time.}42 expression: {dialects: [{dialect: <osi_dialect>, expression: SUM(orders.amount)}]}43 custom_extensions:44 - vendor_name: DATUS45 data: '{"v":"<datus_extension_version>","time_dimension":"orders.order_date","subject_path":["sales","revenue","total"],"unit":"USD"}'46```4748## Author base and window metrics4950- Express a base metric with its natural aggregate, ratio, or arithmetic expression. Put a durable metric condition inside its aggregate with `CASE WHEN`.51- Express each window result as a standalone metric whose OSI expression is one plain aggregate. Put the derivation in one structured `window` object.52- Choose the window family from the intended calculation and use the exact form advertised by the active contract.5354- Derive time, query grain, ordering, partition, and frame from the requested analytic meaning. Treat query grain as a runtime argument.55- Reuse a window metric only when its base aggregate, time axis, calculation, ordering, partition, and frame all match.56- Preserve meaningful window nulls for missing comparison buckets or incomplete required frames.5758Validate the final model with the native Dosi parser/compiler after the last mutation.5960For a parameterized metric, inspect its `param_schema` in `list_metrics`, then verify query behavior with `query_metrics(params={...}, dry_run=True)`. Exercise the default and meaningful enum/boundary or list-valued cases; never invent undeclared parameter names. Native validation proves the definition compiles, while this optional query check proves a user-requested binding shape.