Skip to content

Rules as data

Every formula built from matchers alone serializes.

const document = formulaToJSON(SEC_01.formula)
const back = parseFormula(document)

parseFormula runs the same combinators a TypeScript author calls, so a rule that arrived as JSON meets identical structural rules and reports identical errors, with paths rooted at the document. There is no second parser and no second set of constraints to drift.

formulaSchema is the JSON Schema (draft 2020-12) for the document form.

const schema = formulaSchema

This is what makes a rule-drafting UI possible, and what makes a structured-output model able to write a rule: constrain generation to the schema and the result is either a valid formula or a parse error with a path, never a plausible-looking tree that means something else.

A rule written with a custom predicate is code rather than data. formulaToJSON refuses it, an artifact manifest carries the printed form without the serialized one, and static analysis reports it as out of scope. All three are explicit rather than silent — the point is that a rule you cannot serialize is still a first-class rule, it just cannot pretend to be a document.

Either form. --rules takes a .ts/.js/.mjs/.cjs module exporting rules, or a .json document. A module gets the whole surface including custom predicates; JSON gets the serializable subset.