Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

maxgfr/feelc

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

feelc

CI Release License Go Playground

An AI-native business-rules engine (DMN/FEEL) compiled to Go: an LLM writes and explains the rules, and the engine proves and runs them — 100% deterministic, reproducible and auditable (no LLM in the core). In the spirit of IBM ODM/ILOG, reimagined for the age of LLMs: author by chatting with your own model, visualize the decision graph, prove completeness & consistency, and ship a single CGO-free binary or try it in your browser via WebAssembly.

Try the playground — the real engine, compiled to WebAssembly, runs entirely in your browser (no backend). Or read the docs.

Quick start

One CGO-free static binary, no runtime dependencies:

git clone https://github.com/maxgfr/feelc && cd feelc
go build -o feelc ./cmd/feelc          # Go 1.23+ (or: docker build -t feelc .)

cat > tax.rules <<'RULES'
input income : number >= 0
decision band : string {
  needs: income
  hit: first
  >= 50000 => "high"
  >= 20000 => "medium"
  default  => "low"
}
RULES

./feelc verify --rules tax.rules                                  # proves it's complete & conflict-free
./feelc run    --rules tax.rules --decision band --input '{"income":30000}'   # → "medium"
./feelc serve  --ui                                              # or author it by chatting with your LLM

verify is the point: before you ever run a rule, the engine proves every input is covered and no two rules conflict — with a concrete counterexample when they don't. Then serve --ui lets an LLM draft the next rule while the engine keeps proving it.

Why

Classic rule engines pit business readability against reliable execution. feelc reconciles the two:

  • AI writes, the engine executes. Rules are written in a readable .rules DSL (DMN paradigm: a graph of decisions, each a decision table, expressions in FEEL). An LLM can generate it natively. The Go compiler transforms it into typed, checked IR, executed by a small deterministic VM.
  • Formal verification. feelc verify proves completeness (no uncovered case), the absence of conflicts, and detects dead rules / redundancies — with concrete counterexamples.
  • Hot-reload. Rules are data: you update them on the fly, without recompiling the binary.
  • Auditable. Each decision is replayable (model hash + explanation trace citing the source).
  • Scales to projects. A workspace of many .rules modules links into one deterministic model; editing a single module re-compiles and re-verifies only that module (incremental, O(1) in project size), so AI authoring stays fast across hundreds of modules.

What makes it AI-native

The LLM lives only at the authoring boundary; the engine (compile, verify, VM, explain) is pure, deterministic Go that never calls a model. That separation is the point — it makes AI authoring safe:

  • Bring your own LLM. Author by chatting with your own provider/model/key (Anthropic or any OpenAI-compatible endpoint); the key stays in your browser. No key ⇒ AI endpoints return 501 and the engine still works fully.
  • MCP server (feelc mcp). Expose verify/run/explain/required/check/graph/model as Model Context Protocol tools over stdio, so any agent (Claude Code, Cursor, …) can author rules and have the deterministic engine decide outcomes — the verification moat as an agent tool.
  • Verify → repair → converge. The ingest endpoint (POST /v1/ingest) drafts a model, runs verify / check, feeds the deterministic blockers (with counterexample witnesses) back to the LLM, and repeats until clean — the engine, never the model, decides when it's done.
  • Traceability from the compiled model. @source mappings and explanation traces are read from the compiled IR, never from LLM prose, so every decision cites its real origin.
  • Project-aware editing at scale. Edit one module with full cross-module context via deterministic lexical retrieval (no embeddings) — see Project mode.

How it compares

Most rule engines make you hand-write rules and then trust them. feelc's bet is the opposite: the AI writes the rules (plain text you review like code) and the engine proves them before they ship.

feelc Drools Camunda DMN GoRules / ZEN json-rules-engine
AI authoring native — drafts and repairs against the engine
Rule format plain-text .rules, git-diffable DRL text DMN 1.x XML JSON model JSON conditions
Formal verification in-engine: completeness · conflicts · subsumption (+ SMT) table analysis¹ table analysis¹
Types & numbers typed · exact decimal (money-safe) typed (JVM) FEEL · decimal dynamic untyped JS
Deploy one static binary / ~16 MB Docker, no LLM at runtime JVM JVM / BPM platform Go/Rust lib npm lib
Try in browser WASM playground modeler demo playground

¹ In fairness, Camunda (dmn-js verify table), Trisotech and Drools/DMN do offer decision-table gap/overlap analysis — as modeling-tool features. feelc's is built into the compiler (adds subsumption

  • counterexamples + optional SMT) and ships in a single portable binary / WASM.

Rough by nature — each tool has strengths feelc doesn't (Drools' Rete/CEP, Camunda's BPM suite, GoRules' polished visual editor). What's unique to feelc is the combination: text rules an AI drafts, a deterministic engine that proves them, and a decision graph you can actually read — in a single binary. Measured details: comparison & gaps · conformance (DMN TCK + 6 engines) · benchmarks · embed in your app.

feelc decision-requirements graph — modules colour-coded, cross-module dependency dashed, verification findings overlaid

The built-in decision graph (feelc serve --ui or feelc graph): inputs and decisions across modules, colour-coded per module, with the cross-module dependency dashed and verification findings overlaid. Pan, zoom and click any node to inspect its type, hit policy, source line and findings.

Commands

feelc run     --rules m.rules --decision <name> --input '{…}' [--json]  # evaluate a decision
feelc compile --rules m.rules [-o m.ir.bin]                             # compile to canonical IR
feelc verify  --rules m.rules [--json]                                  # formal check (gaps/conflicts)
feelc explain --rules m.rules --decision <name> --input '{…}' [--json]  # justification trace
feelc check   --rules m.rules --claims claims.json [--json]             # NL↔rule semantic gate
feelc fmt     --rules m.rules [-w] [--check]                            # canonical pretty-printer
feelc import  --in model.dmn  [-o m.rules]                              # import DMN XML
feelc export  --rules m.rules [-o model.dmn]                            # export to DMN XML
feelc tck     --suite <dir>   [--json] [--min <pct>]                    # DMN TCK conformance
feelc graph   --rules m.rules [--format mermaid|dot|json]               # decision graph (DRG) + findings
feelc inputs  --rules m.rules --decision <name>                         # inputs a decision needs (question-flow)
feelc docs    --rules m.rules [-o DOC.md]                               # Markdown reference + Mermaid graph
feelc serve   --rules m.rules [--addr :8080] [--watch] [--strict] [--ui] # HTTP service + hot-reload (+ AI UI)
feelc serve   --project <dir>  [--addr :8080] [--watch] [--strict] [--ui] [--allow-edit] # multi-module PROJECT
feelc version                                                          # print the build version

The CLI flags, exit codes and the full HTTP route table are in the CLI reference and HTTP API reference.

Project mode

For more than a single file, a project is a directory of .rules modules plus an optional feelc.project.json manifest. The modules are namespaced (module__decision) and linked into one deterministic model the engine runs unchanged — a single hash, one verification pass, one decision graph. Modules reference each other through a manifest uses binding (a local input wired to other.decision); cross-module cycles and dangling refs are rejected at load. The web UI (--ui) gains a module navigator, a project health dashboard, and a cross-module graph; adding --allow-edit (off by default — the editing surface is unauthenticated, so keep it on a trusted/loopback host) enables a per-module editor with server-side Save + create/delete, persisted to the mounted directory under a golden rule: an invalid edit is rejected and the live project is kept. See the project-mode guide (also on the docs site), sample-project/, and ADR 0015. Ships as a Docker service:

docker build -t feelc .
docker run --rm -p 8080:8080 -v "$PWD/sample-project:/work" feelc   # open http://localhost:8080/

Status

Core operational: language → compiler → IR → deterministic VM (exact decimal), 7 DMN hit policies, formal verification (completeness/conflicts/dead rules with counterexamples), HTTP service + hot-reload, semantic gate (check), DMN XML import. Verified reference models live under examples/. Optional SMT (Z3) backend (-tags smt, ADR 0007) discharges non-geometric Op=Prog residuals — completeness and conflict proofs over if/then/else, floor/ceiling/round, cross-column cells (honest not-verifiable when z3 is absent).

Modelling reach: decision-graph visualization (feelc graph

  • the UI, ADR 0009), rule metadata & law/source traceability (@title/@doc/@question/@source, ADR 0010), an interactive question-flow / simulator (ADR-backed feelc inputs + the UI form), progressive brackets (bracket:, ADR 0011), physical units & money with compile-time dimensional analysis (ADR 0012), applicability (non-applicable values, ADR 0013), and date / duration types with sound whole-day arithmetic (ADR 0014). Deferred: multi-arg built-ins (ADR 0004 §3) and out-of-subset temporal forms (times of day, date-times, year-month durations). Generate docs with feelc docs (Markdown + Mermaid graph), or scaffold a cited repo reference with the external ultradoc skill.

AI writes the rules (two paths)

Per the thesis — AI authors, the engine executes — there are two interchangeable authoring paths. The LLM only drafts .rules; every result you see comes from the deterministic engine (see ADR 0008).

The red→green ingest loop: the LLM drafts, the engine verifies each round, blockers drive the next repair until it converges

The engine, not the LLM, decides when authoring is done: it drafts, verifies, and feeds the deterministic blockers (with counterexamples) back for repair until the model is provably complete and consistent (POST /v1/ingest, or the skill's red→green loop).

1. In-browser chat UI (bring-your-own LLM). feelc serve --ui serves a zero-dependency embedded UI: chat to describe your rules, the assistant drafts the model, and one click runs verify / run on the deterministic engine. It also renders the decision graph, builds a simulator form that asks only the inputs a decision needs, narrates a result in plain English ("Explain"), and generates test cases that are then checked deterministically. Configure your own provider/model/API key in ⚙ settings (Anthropic or any OpenAI-compatible endpoint). The key stays in your browser and transits only your local server; it is never stored or logged. With no key (request or ANTHROPIC_API_KEY env), AI endpoints return 501 and the engine still works.

feelc serve --ui            # then open http://localhost:8080/ (no --rules needed)

2. Claude Code + the bundled skill. A portable skill (Claude Code, Codex, Cursor…) lives in skills/feelc-rules/: it guides an agent through the interview → DSL → verifyrun → iterate flow, using feelc as a deterministic oracle. See skills/feelc-rules/SKILL.md. Install it any of three ways:

npx skills add maxgfr/feelc        # 1. skills.sh — drops the skill into .claude/skills/feelc-rules
# 2. as a Claude Code plugin (skill + MCP server), from inside Claude Code:
#      /plugin marketplace add maxgfr/feelc   then   /plugin install feelc@feelc
feelc mcp install                  # 3. wire the MCP server into ./.mcp.json (or --target claude-desktop)

Or run the skill's wrapper directly (it locates the feelc binary itself):

node skills/feelc-rules/scripts/feelc-skill.mjs verify --rules examples/credit/credit.rules --json

Example

model "credit" {
  rounding: half_even
}

input credit_score  : number in [300..850]
input annual_income : number >= 0
input monthly_debt  : number >= 0
input age           : number in [0..120]

decision dti : number = monthly_debt / (annual_income / 12)

decision eligibility : Eligibility {
  needs: credit_score, dti, age
  hit: first
  #  credit_score | dti     | age   => eligible | reason
     < 580        | -       | -     => false    | "insufficient score"
     -            | > 0.43  | -     => false    | "debt too high"
     -            | -       | < 18  => false    | "minor"
     [580..680)   | <= 0.43 | >= 18 => true     | "approved with conditions"
     >= 680       | <= 0.43 | >= 18 => true     | "approved"
     default      |         |       => false    | "not covered"
}

Contributing

Build & test instructions, the architecture map, and the append-only decision-record lifecycle are in CONTRIBUTING. Browse the decision records to see why feelc is built the way it is.

License

Apache-2.0. See LICENSE.

About

An AI-native DMN/FEEL business-rules engine compiled to Go: an LLM writes the rules, the engine proves (completeness/conflicts, SMT) and runs them 100% deterministically — auditable, hot-reloadable, with an in-browser WASM playground.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.