Decisions

The key engineering decisions behind feelc, one line each. Each links to its full Architecture Decision Record (the detailed context + consequences live in docs/adr/).

# Decision Why
0001 Reuse a vendored FEEL parser fork, not an in-house parser Chosen after a measured spike; less code to own, same coverage.
0002 Exact decimal arithmetic (apd), never floats Money/tax rules must be bit-for-bit exact and reproducible.
0003 Three-valued null/error semantics No silent coercion — out-of-scope inputs fail honestly.
0004 Record deferred features explicitly A deferral is documented, not hidden (temporal since lifted).
0005 Positioned, coded, JSON-serializable diagnostics The contract the authoring loop reads to fix sources.
0006 Canonical hashed binary IR, hardened against untrusted blobs The model hash is the identity; decoding must be safe.
0007 Optional Z3/SMT verification behind a build tag Proves the non-geometric cells geometry can't; honest fallback.
0008 LLM authors at the boundary, never in the core "AI writes, the engine executes" — deterministic, auditable.
0009 Render the decision-requirements graph See the model and its verification findings, not just run it.
0010 @title/@doc/@question/@source annotations Documentation + law/source traceability, hash-neutral.
0011 bracket: lowered to plain arithmetic Marginal-rate schedules with no special runtime op.
0012 Compile-time dimensional analysis Reject dimensionally-inconsistent arithmetic (units & money).
0013 Non-applicable values via a sentinel Eligibility gating with no VM special-case.
0014 Whole-day date & duration arithmetic Sound, exact calendar logic without time-of-day complexity.
0015 Multi-module projects linked into one model Manage many rules; one hash, one verification pass.
0016 English is canonical Error strings are a test contract; one shared vocabulary.
0017 Compile the real engine to WebAssembly Run it in the browser with zero setup, no second engine.
0018 Zero-dependency docs-site generator Publish docs + decisions without an SSG toolchain.
0019 Ship the engine as the feelc npm package Embed the real engine in any TS app (browser/Node/bundler/edge), no API.
0020 Deterministic extra built-ins: round(x,n), abs, trunc, modulo Close near-universal gaps vs other rule engines without weakening determinism/verification.
0021 DMN OUTPUT ORDER hit policy + PRIORITY/OUTPUT ORDER import fidelity Reach 7/7 DMN hit policies; close the 3 remaining DMN-TCK Level-2 failures.
0022 power(x, n) built-in (integer-exponent, exact) Close the last common arithmetic gap (interest/growth/area) without floats or an operator change.
0023 String predicates starts_with / ends_with / contains Code/policy routing as pure boolean predicates, without becoming a string-manipulation library.
0024 Batch-evaluate API (evaluateBatch) Amortize the JS↔WASM JSON boundary across N rows (measured 2.1–2.3× for bulk/reactive eval).
0025 Bounded quantifiers every/some of {…} satisfies ? Quantify over a fixed scalar tuple (verifiable) without a list type or unbounded iteration.
0026 MCP server (feelc mcp) Expose verify/run/explain/… as MCP tools so any agent can author + deterministically verify rules.
0027 Skill distribution (skills.sh / plugin / feelc mcp install) Make the skill one-liner-installable: skills/feelc-rules/ flat layout, a Claude Code plugin marketplace, and an idempotent MCP config installer.

ADRs are append-only: an accepted decision is never rewritten — a later change is a dated note on the same ADR or a new superseding one.