Query catalog
A named query is a parameterized telemetry analysis. The catalog has two halves:
- Built-in queries under the
telemetry.*namespace, shipped withexd-client. They back the cannedexd telemetry summary/srm/rules/ … subcommands. - User-defined queries declared as TOML files in the manifest repository (
queries/<name>.toml). Deferred indefinitely — see the banner below.
The query catalog is the analogue of flags/ and segments/ in the manifest tree.
Built-in queries
The telemetry.* namespace is reserved for built-in queries shipped with exd-client. The initial set:
| Name | Purpose | Parameters |
|---|---|---|
telemetry.summary | Eval counts and variant distribution per flag. | flag (optional), since (required), compare_to (optional duration) |
telemetry.srm | Sample-ratio mismatch check via chi-square test. | flag (required), since (required), expected (optional map<string,float>) |
telemetry.rules | Rule-fire frequency for a flag. | flag (required), since (required) |
telemetry.user | All evaluations for a single unit_id_hash. | id (required), since (optional) |
telemetry.coverage | Flags evaluated zero times in the window. | since (required), namespace (optional) |
telemetry.dead-flags | Flags only ever returning the default value. | since (required), namespace (optional) |
telemetry.version-skew | Eval counts grouped by manifest_version. | flag (optional), since (required) |
telemetry.contexts | Context-attribute presence and value distribution. | flag (required), since (required) |
telemetry.simulate | Evaluate a candidate manifest against historical context. | manifest_path (required), since (required), flag (optional) |
Each built-in query has a stable parameter list and a stable output schema. The capabilities manifest is the authoritative machine-readable record of these surfaces; exd telemetry capabilities --format json is the agent discovery point.
The CLI surface for each built-in lives at reference/cli/exd/telemetry/ (summary.md, srm.md, …). The CLI pages cover use cases; this page covers the catalog shape.
User-defined queries
Deferred indefinitely. The user-defined query catalog at
queries/<name>.tomlis not landed in Phase 1. The shape below describes what the surface would look like if reintroduced; today, noqueries/directory is recognized bymanifest/01-directory-layout.mdor by the linter walk. TheQ001–Q010range stays reserved against future reintroduction.
When reintroduced, queries would be version-controlled, lint-validated, and reviewed alongside flags.
Repository layout
manifest-repo/
namespace.toml
flags/
checkout-redesign.toml
segments/
internal-employees.toml
queries/
experiment-health.toml
rule-coverage.toml
flag-summary.toml
thresholds.toml
The queries/ directory is OPTIONAL. A flag namespace with no queries/ directory uses only built-in queries. A queries/thresholds.toml file, if present, configures detection thresholds applied to built-in and user-defined queries — see thresholds.
Query file schema
# queries/experiment-health.toml
name = "experiment-health"
version = 1
description = "End-to-end health check for an experiment flag."
[parameters]
flag = { type = "string", required = true }
since = { type = "duration", required = true }
expected_split = { type = "map<string,float>", required = false }
[[checks]]
id = "exposure-volume"
query = "telemetry.summary"
inputs = { flag = "${flag}", since = "${since}" }
[[checks]]
id = "srm"
query = "telemetry.srm"
inputs = { flag = "${flag}", since = "${since}", expected = "${expected_split}" }
on_diagnostic = ["T001", "T002"]
[[checks]]
id = "rule-coverage"
query = "telemetry.rules"
inputs = { flag = "${flag}", since = "${since}" }
on_diagnostic = ["T005"]
[[checks]]
id = "manifest-skew"
query = "telemetry.version-skew"
inputs = { flag = "${flag}", since = "${since}" }
on_diagnostic = ["T004"]
Top-level fields
| Field | Required | Type | Description |
|---|---|---|---|
name | yes | query_name | Stable, repo-unique identifier. MUST equal the filename stem. |
version | yes | integer ≥ 1 | Semantic version. Cited in provenance. |
description | no | string | Free-form. |
parameters | yes | table | Schema for the query's inputs. Empty table permitted. |
checks | yes | array of tables | Ordered list of built-in or user-defined queries to run. Non-empty. |
[parameters.<name>] fields
| Field | Required | Type | Description |
|---|---|---|---|
type | yes | string | One of string, int, float, bool, duration, timestamp, map<string,float>, map<string,string>, array<string>. |
required | no | bool | Defaults to false. |
default | no | matching type | Default value applied when the parameter is absent. Mutually exclusive with required = true. |
description | no | string | Free-form. |
duration values are parsed as Go-style durations: 5m, 1h30m, 7d. timestamp values are RFC 3339 strings.
[[checks]] fields
| Field | Required | Type | Description |
|---|---|---|---|
id | yes | slug | Unique within this query. Names the check in JSON output. |
query | yes | query_name | The built-in or user-defined query to invoke. |
inputs | yes | inline table | Mapping from the called query's parameter names to expressions. ${name} substitutes a parameter from this query. Literals are accepted. |
on_diagnostic | no | array of T-codes | Diagnostics this check is expected to surface. Used for documentation and capability metadata; does not gate execution. |
A check MUST NOT reference a parameter that does not exist on this query. A check MUST NOT pass a parameter that does not exist on the called query.
Query lint diagnostics
Deferred indefinitely with the user-defined query catalog. The range below is reserved against future use; no implementation tracks it today.
| Code | Severity | Triggers when |
|---|---|---|
Q001 | error | A [[checks]] block references a query name (built-in or user-defined) that does not resolve. |
Q002 | error | A parameter type in [parameters.<name>] is not one of the recognized types. |
Q003 | error | A [[checks]].inputs entry references a parameter ${name} that is not declared in this query's [parameters]. |
Q004 | error | An on_diagnostic entry references a T-code not defined in diagnostics. |
Q005 | error | The name field does not equal the filename stem. |
Q006 | error | Two queries share a name. |
Q007 | error | A [[checks]] block passes a parameter not declared on the called query, or omits a required parameter. |
Q008 | error | The name field does not match the query_name pattern. |
Q009 | warning | A query has zero [[checks]]. |
Q010 | warning | A query parameter is declared but never referenced by any [[checks]] entry. |
Composition rules
Composition of [[checks]] would be exactly one level deep at schema version 1. A user-defined query MAY reference any built-in telemetry.* query and any other user-defined query, but the called query MUST NOT itself contain [[checks]] referring to further user-defined queries.
This restriction prevents accidental composition cycles and keeps query execution analyzable.
Versioning
Each query carries an integer version. A change that adds a new [[checks]] block, alters thresholds, or modifies parameter shapes MUST bump version. The version is included in the provenance block so agent-produced findings can be quoted reproducibly.
Server-side validation
The exd-server upload endpoint runs the same lint pipeline that operates locally, including Q-codes. A push containing an invalid query file is rejected with manifest_lint_failed (HTTP 422), preserving the manifest reference's "no second validation layer" invariant.
See also
reference/cli/exd/telemetry/— per-built-in CLI reference with use cases.reference/cli/exd/telemetry/run— invoke a built-in query by its fully qualifiedtelemetry.<name>.- capabilities — the agent-discoverable manifest of what each query supports.
- diagnostics — the
T-codevocabulary every query may emit. - thresholds — knobs that gate when a diagnostic fires.
- provenance — the JSON envelope every query result is wrapped in.