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.