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.
The schema
Section titled “The schema”formulaSchema is the JSON Schema (draft 2020-12) for the document form.
const schema = formulaSchemaThis 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.
What does not survive
Section titled “What does not survive”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.
What the CLI reads
Section titled “What the CLI reads”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.