Definitions and Runtime

A schema declaration is an immutable description. Runtime state is the changing experience of one person filling out or submitting a form.

The four contracts

ContractCreated byContainsDoes not contain
Source declarationYour TypeScriptCollections, fields, validation metadata, input intent, and optional layoutVisitor values or errors
databaseSchemacreateSchema() or the orchestratorNormalized database objects plus toJSONSchema() and checksum()UI layout
uiFormTreeThe orchestratorRender collections, steps, conditions, repeaters, and branchesCurrent values, errors, or submission state
Published FormSchemaBusinessDash dashboard/APIA Live form contract consumed by forms.schema(), <BdForm>, and createFormController()Your local orchestration tree

In 0.9.50 there is no adapter from uiFormTree to the published FormSchema expected by createFormController(). Do not pass one contract where the other is required.

One declaration, isolated outputs

const definition = createFormSchemaOrchestrator([projects])

export default definition.databaseSchema
export const projectFormTree = definition.uiFormTree

The default export is deliberately narrow: the CLI can see the database artifact but cannot accidentally upload layout or application state.

Your renderer reads uiFormTree as a definition and keeps live state separately:

type ProjectFormState = {
  values: Record<string, unknown>
  touched: Set<string>
  dirty: Set<string>
  errors: Record<string, string>
  activeBranch?: string
  currentStep: number
  submitting: boolean
}

Source, draft, and Live

The CLI compiles local source and compares it with the promoted Live data model. sync-data-model proposes a draft; it does not silently promote it.

local TypeScript → compiled artifact → migration plan → draft → human promotion → Live

This separation lets CI produce deterministic proposals while a person remains the gate for exposure changes and destructive migrations.

Next: Validation and Form State.