# Current boundaries

A custom bounded expression language. No arbitrary code execution, loops, user functions or external I/O. Runtime types are always checked at evaluation. A full static type inference is not included; the opt-in `check` operation validates expressions and rule sets against an optional caller-supplied schema (`boolean`, `number`, `string`, `null`, `array`, `object` per dotted fact path), reports only what the evaluator would reject, and defers unknown fact paths to runtime. All matching rule outputs are evaluated even in first mode, and first selects the highest-priority match; equal priority uses rule ID order. Unique produces conflict and null decision on multiple matches, with the conflicting rule IDs reported in `conflict_ids`. Facts are caller supplied. Traces can include fact values, so redact sensitive facts before storing reports.
New in 0.3.0: `serialize`, `roundtrip`, `aggregate`, `infer`, `analyze` and `explain` operations; a stable E-code prefix on every input error; JSONL streaming selected only by a `.jsonl` file path (stdin stays single-request); aggregation groups order semantically (null, false, true, numbers ascending, strings character-wise, arrays/objects canonically); array literals are not part of the expression language. The core string compare on this toolchain is not byte-lexicographic, so deterministic ordering uses an explicit comparator.
New in 0.4.0: quantifier functions (count_matches, any_match, all_match), the pick projection, the ast JSON interchange, bundle manifests with migration resolution, the optimizer and precompiled programs moved past their 0.3.0 preview status, and the smoke pass plus verification ladder scripts. Count_matches requires numeric elements and a listed operator; pick reports missing paths instead of dropping them; the AST parse direction rejects unknown kinds, operators and functions with coded errors.
New in 0.5.0: the `lint` governance gate (analysis plus types plus bundle integrity in one report, all sections always run), `fmt` canonical rule-set formatting (changed-only selection, formatting-gate semantics), `export_schema` (JSON Schema draft 2020-12, inference fallback), and `migrate` (pending-step application to a run_program-ready artifact). Lint reuses check and analyze verbatim so gates can never disagree; export keeps arrays and objects structural without element schemas.
New in 0.6.0: `validate` (fact records against engine schemas with required paths), `conflicts` (sound relation classification restricted to the conjunction-of-ranges fragment; conditions outside it are marked unanalyzed rather than guessed), and `stats` (self-description from compiled trees, paths counted once per rule). Subsumption naming is standard: X subsumes Y when X is the more general condition.
New in 0.6.1: `plan_waves` (deployment scheduling from the dependency graph, one component per wave) and the `snapshot`/`compare` regression gate (FNV-1a fingerprints over decision, matched IDs and conflict flag; digests are self-implemented so all four backends agree). Snapshots are opaque digests, not rule text: they detect change but do not explain it — read the full decide report for the why.
New in 0.7.0: `template` (placeholder rendering before compilation; substitution is textual, so a rendered template still passes through the standard compile pipeline with position-carrying errors), `score` (deterministic documented weights, not ML), and `explain_rules` (sentences derived from the canonical tree; complex nestings read as nested clauses, not prose).
New in 0.8.0: `merge` (ID-based with canonical-signature equality; conflicts are marked, never silently dropped), `matrix` (mode disagreement is computed per record, agreement means at most one match), and `audit` (full reasoning trail; records may contain fact values, so redact sensitive batches before storage).
- Audit rule-set digests and snapshot fingerprints are SHA-256 (64 hex characters) over canonical text; they changed format from the 0.x FNV-1a fingerprints at 1.0.0, so snapshots and recorded digests from earlier versions do not compare equal.
