Skip to content

ADR-0015 — Field curation layer + JSON Schema for editor DX

Update date : 2026-06-02 06:52

Status: accepted (amends ADR-0001) Date: 2026-06-02

Context

ADR-0001 mirrors snowflake.core exactly (zero manual mapping, auto-sync on SDK changes). But the SDK surface has warts that leak into the YAML — the main authoring pain point:

  • Stringly-typed booleansauto_resume is typed str, so auto_resume: true (YAML bool) is rejected; the user must write "true".
  • Bare-string enumswarehouse_size is str, so a typo (XSAMLL) is only caught at apply time, and the editor offers no autocomplete.
  • Display-form echoes — Snowflake returns X-Small for a declared XSMALL (and 2X-Large for XXLARGE), which a naive diff reads as a perpetual ALTER.

These were all found by running apply against a real account during the warehouse slice.

Decision

Two complementary, opt-in mechanisms — declared per resource, only for the warts (the other ~95% of fields stay auto-synced from the SDK):

  1. _field_overridesfield → (clean Pydantic type, caster back to SDK form). The clean type is used for the model field (so the YAML is idiomatic and the JSON Schema autocompletes it); the caster restores the SDK string in to_sdk_dict(). E.g. auto_resume: (bool, str→"true"), warehouse_size: (WarehouseSize, enum→value).
  2. _field_normalizersfield → comparison function for the diff engine, so display forms compare equal (warehouse_size via a size canonicaliser handling X-Small, 2X-Large, 4X-Large). The diff compares to_sdk_dict() — the exact payload Snowflake receives.

Enums are curated as soft enums — the field type is Enum | str (e.g. WarehouseSize | str). The editor autocompletes the known values, but an unknown/future value still passes and is validated by Snowflake at apply. This keeps forward-compatibility (a new Snowflake tier is never blocked by a stale enum) and avoids the vendor-lock-in trap, at the cost of catching typos at apply instead of authoring time. The JSON Schema is generated from the curated models (pinky-provider schemas) and wired to the YAML language server; for a soft enum it emits anyOf: [enum, string] → value autocomplete and no hard error on unknown values.

Consequences

  • YAML stays clean (auto_resume: true, warehouse_size: XSMALL) while the SDK gets its string forms.
  • The schema is generated, never hand-maintained → stays in sync with the SDK and the overrides.
  • Amends ADR-0001: "pure mirror" → "mirror + thin curation". The inverted-maintenance property holds — only warts are annotated; a new SDK field still appears for free; a new warehouse tier is one line.
  • Trade-off accepted: soft enums autocomplete without blocking, so typos pass model validation and surface at apply (Snowflake returns a clear error). Forward-compatibility and no lock-in are preferred over author-time typo rejection — a deliberate alignment with pinky's anti-lock-in thesis.