JSON Contract
Versioning
Section titled “Versioning”Rocky’s CLI output is the interface contract with orchestrators like Dagster. Every JSON output includes a top-level version field that tracks the engine’s release version; it’s set from env!("CARGO_PKG_VERSION") at compile time, so the field reports whichever Rocky binary is producing the output.
Examples throughout the reference docs show an illustrative version string like "version": "1.6.0"; the actual value reflects whichever Rocky binary produced the output, not a fixed release:
{ "version": "1.6.0", "command": "discover", ...}Stability Guarantees
Section titled “Stability Guarantees”Rocky follows the engine’s semver cadence:
- Patch (
1.6.x): bug fixes, no schema changes. - Minor (
1.x.0): new optional fields may be added. Existing fields are never removed or renamed within a minor series. - Major (
x.0.0): breaking changes to field names, types, or structure. Consumers should pin or branch their parsing logic on the major version.
Consumers should parse defensively: tolerate unknown fields, treat absent optional fields as null, and don’t assume the set of enum variants is closed.
Asset Key Format
Section titled “Asset Key Format”The asset_key field in materializations and check results follows a fixed format:
[source_type, ...component_values, table_name]Example: ["fivetran", "acme", "us_west", "shopify", "orders"]
In the CLI JSON, a multi-valued component (like a list of regions) emits one array element per value — the values are not joined:
["fivetran", "acme", "us_west", "us_central", "shopify", "orders"]This format is consumed by dagster-rocky to build Dagster AssetKey objects. The __ join of multi-value components into a single key segment (e.g. us_west__us_central) is applied by the dagster-rocky translator when it constructs the Dagster AssetKey, not by the CLI JSON contract.
Parsing
Section titled “Parsing”Use the parse_rocky_output() function in dagster-rocky to auto-detect the command type:
from dagster_rocky import parse_rocky_output
result = parse_rocky_output(json_str)# Returns: DiscoverOutput | RunOutput | PlanOutput | StateOutput | ...The command is detected from the "command" field in the JSON. Shape-based discrimination (e.g. column vs model lineage) covers the commands whose output shape is disambiguated by the presence of an argument.
Codegen Pipeline
Section titled “Codegen Pipeline”Rocky’s JSON output schemas are autogenerated from typed Rust structs. Every CLI command that emits --output json is backed by a struct in engine/crates/rocky-cli/src/output.rs (or commands/doctor.rs) that derives JsonSchema. The full pipeline:
- Edit the relevant
*Outputstruct inoutput.rs. - Run
just codegenfrom the monorepo root. - That exports the JSON schemas to
schemas/, regenerates Pydantic v2 models insdk/python/src/rocky_sdk/types_generated/(re-exported bydagster_rocky.types), and TypeScript interfaces ineditors/vscode/src/types/generated/. - Commit the schema and regenerated bindings together.
The codegen-drift CI workflow fails any PR where committed bindings don’t match just codegen output. The .git-hooks/pre-commit hook mirrors the same check locally; enable once with just install-hooks.
See the JSON Output reference for the per-command payload shapes.
Adding New Fields
Section titled “Adding New Fields”When adding fields to Rocky’s JSON output:
- Add the field as optional (nullable) in the relevant Rust
*Outputstruct. - Run
just codegento regenerate Pydantic models and TypeScript interfaces. - The new field ships with the next minor engine release; no separate schema version bump is needed.
- Document the new field in the JSON Output reference.